mirror of
https://github.com/aristocratos/btop.git
synced 2026-05-19 14:10:14 -04:00
feat(proc): add E hotkey to collapse/expand all tree nodes
Pressing E in tree mode collapses all processes if any parent is currently expanded, or expands all if everything is already collapsed. This gives a quick per-application resource summary without having to manually toggle each node. Implemented across all platforms (Linux, macOS, FreeBSD, OpenBSD, NetBSD).
This commit is contained in:
@@ -346,6 +346,11 @@ namespace Input {
|
||||
no_update = false;
|
||||
Config::set("update_following", true);
|
||||
}
|
||||
else if (key == "E" and Config::getB("proc_tree")) {
|
||||
atomic_wait(Runner::active);
|
||||
Proc::collapse_all = 1;
|
||||
no_update = false;
|
||||
}
|
||||
else if (is_in(key, "u")) {
|
||||
Config::flip("pause_proc_list");
|
||||
}
|
||||
|
||||
@@ -205,6 +205,7 @@ namespace Menu {
|
||||
{"c", "Toggle per-core cpu usage of processes."},
|
||||
{"r", "Reverse sorting order in processes box."},
|
||||
{"e", "Toggle processes tree view."},
|
||||
{"E", "Collapse/expand all processes in tree view."},
|
||||
{"%", "Toggles memory display mode in processes box."},
|
||||
{"Selected +, -", "Expand/collapse the selected process in tree view."},
|
||||
{"Selected t", "Terminate selected process with SIGTERM - 15."},
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace Proc {
|
||||
extern bool shown, redraw;
|
||||
extern int select_max;
|
||||
extern atomic<int> detailed_pid;
|
||||
extern int selected_pid, start, selected, collapse, expand, filter_found, selected_depth, toggle_children;
|
||||
extern int selected_pid, start, selected, collapse, expand, filter_found, selected_depth, toggle_children, collapse_all;
|
||||
extern int scroll_pos;
|
||||
extern string selected_name;
|
||||
extern atomic<bool> resized;
|
||||
|
||||
@@ -1007,7 +1007,7 @@ namespace Proc {
|
||||
fs::file_time_type passwd_time;
|
||||
|
||||
uint64_t cputimes;
|
||||
int collapse = -1, expand = -1, toggle_children = -1;
|
||||
int collapse = -1, expand = -1, toggle_children = -1, collapse_all = -1;
|
||||
uint64_t old_cputimes = 0;
|
||||
atomic<int> numpids = 0;
|
||||
int filter_found = 0;
|
||||
@@ -1301,6 +1301,21 @@ namespace Proc {
|
||||
}
|
||||
collapse = expand = -1;
|
||||
}
|
||||
|
||||
if (collapse_all != -1) {
|
||||
//? If any parent process is currently expanded, collapse all; otherwise expand all
|
||||
std::unordered_set<size_t> parent_pids;
|
||||
for (const auto& p : current_procs)
|
||||
parent_pids.insert(static_cast<size_t>(p.ppid));
|
||||
const bool do_collapse = rng::any_of(current_procs, [&parent_pids](const proc_info& p) {
|
||||
return parent_pids.contains(p.pid) and not p.collapsed;
|
||||
});
|
||||
for (auto& p : current_procs)
|
||||
p.collapsed = do_collapse;
|
||||
collapse_all = -1;
|
||||
if (Config::ints.at("proc_selected") > 0) locate_selection = true;
|
||||
}
|
||||
|
||||
if (should_filter or not filter.empty()) filter_found = 0;
|
||||
|
||||
vector<tree_proc> tree_procs;
|
||||
|
||||
@@ -2879,7 +2879,7 @@ namespace Proc {
|
||||
fs::file_time_type passwd_time;
|
||||
|
||||
uint64_t cputimes;
|
||||
int collapse = -1, expand = -1, toggle_children = -1;
|
||||
int collapse = -1, expand = -1, toggle_children = -1, collapse_all = -1;
|
||||
uint64_t old_cputimes{};
|
||||
atomic<int> numpids{};
|
||||
int filter_found{};
|
||||
@@ -3354,6 +3354,21 @@ namespace Proc {
|
||||
}
|
||||
collapse = expand = -1;
|
||||
}
|
||||
|
||||
if (collapse_all != -1) {
|
||||
//? If any parent process is currently expanded, collapse all; otherwise expand all
|
||||
std::unordered_set<size_t> parent_pids;
|
||||
for (const auto& p : current_procs)
|
||||
parent_pids.insert(static_cast<size_t>(p.ppid));
|
||||
const bool do_collapse = rng::any_of(current_procs, [&parent_pids](const proc_info& p) {
|
||||
return parent_pids.contains(p.pid) and not p.collapsed;
|
||||
});
|
||||
for (auto& p : current_procs)
|
||||
p.collapsed = do_collapse;
|
||||
collapse_all = -1;
|
||||
if (Config::ints.at("proc_selected") > 0) locate_selection = true;
|
||||
}
|
||||
|
||||
if (should_filter or not filter.empty()) filter_found = 0;
|
||||
|
||||
vector<tree_proc> tree_procs;
|
||||
|
||||
@@ -1100,7 +1100,7 @@ namespace Proc {
|
||||
fs::file_time_type passwd_time;
|
||||
|
||||
uint64_t cputimes;
|
||||
int collapse = -1, expand = -1, toggle_children = -1;
|
||||
int collapse = -1, expand = -1, toggle_children = -1, collapse_all = -1;
|
||||
uint64_t old_cputimes = 0;
|
||||
atomic<int> numpids = 0;
|
||||
int filter_found = 0;
|
||||
@@ -1362,6 +1362,21 @@ namespace Proc {
|
||||
}
|
||||
collapse = expand = -1;
|
||||
}
|
||||
|
||||
if (collapse_all != -1) {
|
||||
//? If any parent process is currently expanded, collapse all; otherwise expand all
|
||||
std::unordered_set<size_t> parent_pids;
|
||||
for (const auto& p : current_procs)
|
||||
parent_pids.insert(static_cast<size_t>(p.ppid));
|
||||
const bool do_collapse = rng::any_of(current_procs, [&parent_pids](const proc_info& p) {
|
||||
return parent_pids.contains(p.pid) and not p.collapsed;
|
||||
});
|
||||
for (auto& p : current_procs)
|
||||
p.collapsed = do_collapse;
|
||||
collapse_all = -1;
|
||||
if (Config::ints.at("proc_selected") > 0) locate_selection = true;
|
||||
}
|
||||
|
||||
if (should_filter or not filter.empty()) filter_found = 0;
|
||||
|
||||
vector<tree_proc> tree_procs;
|
||||
|
||||
@@ -991,7 +991,7 @@ namespace Proc {
|
||||
fs::file_time_type passwd_time;
|
||||
|
||||
uint64_t cputimes;
|
||||
int collapse = -1, expand = -1, toggle_children = -1;
|
||||
int collapse = -1, expand = -1, toggle_children = -1, collapse_all = -1;
|
||||
uint64_t old_cputimes = 0;
|
||||
atomic<int> numpids = 0;
|
||||
int filter_found = 0;
|
||||
@@ -1265,6 +1265,21 @@ namespace Proc {
|
||||
}
|
||||
collapse = expand = -1;
|
||||
}
|
||||
|
||||
if (collapse_all != -1) {
|
||||
//? If any parent process is currently expanded, collapse all; otherwise expand all
|
||||
std::unordered_set<size_t> parent_pids;
|
||||
for (const auto& p : current_procs)
|
||||
parent_pids.insert(static_cast<size_t>(p.ppid));
|
||||
const bool do_collapse = rng::any_of(current_procs, [&parent_pids](const proc_info& p) {
|
||||
return parent_pids.contains(p.pid) and not p.collapsed;
|
||||
});
|
||||
for (auto& p : current_procs)
|
||||
p.collapsed = do_collapse;
|
||||
collapse_all = -1;
|
||||
if (Config::ints.at("proc_selected") > 0) locate_selection = true;
|
||||
}
|
||||
|
||||
if (should_filter or not filter.empty()) filter_found = 0;
|
||||
|
||||
vector<tree_proc> tree_procs;
|
||||
|
||||
@@ -1590,7 +1590,7 @@ namespace Proc {
|
||||
fs::file_time_type passwd_time;
|
||||
|
||||
uint64_t cputimes;
|
||||
int collapse = -1, expand = -1, toggle_children = -1;
|
||||
int collapse = -1, expand = -1, toggle_children = -1, collapse_all = -1;
|
||||
uint64_t old_cputimes = 0;
|
||||
atomic<int> numpids = 0;
|
||||
int filter_found = 0;
|
||||
@@ -1922,6 +1922,21 @@ namespace Proc {
|
||||
}
|
||||
collapse = expand = -1;
|
||||
}
|
||||
|
||||
if (collapse_all != -1) {
|
||||
//? If any parent process is currently expanded, collapse all; otherwise expand all
|
||||
std::unordered_set<size_t> parent_pids;
|
||||
for (const auto& p : current_procs)
|
||||
parent_pids.insert(static_cast<size_t>(p.ppid));
|
||||
const bool do_collapse = rng::any_of(current_procs, [&parent_pids](const proc_info& p) {
|
||||
return parent_pids.contains(p.pid) and not p.collapsed;
|
||||
});
|
||||
for (auto& p : current_procs)
|
||||
p.collapsed = do_collapse;
|
||||
collapse_all = -1;
|
||||
if (Config::ints.at("proc_selected") > 0) locate_selection = true;
|
||||
}
|
||||
|
||||
if (should_filter or not filter.empty()) filter_found = 0;
|
||||
|
||||
vector<tree_proc> tree_procs;
|
||||
|
||||
Reference in New Issue
Block a user