summaryrefslogtreecommitdiffstats
path: root/htop.c
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2014-04-09 18:02:50 -0300
committerHisham Muhammad <hisham@gobolinux.org>2014-04-09 18:02:50 -0300
commit19b438de1009047ee425d1f36207c20b9c80d43a (patch)
tree003a45252e211016edb8ec71518efb321fd5aced /htop.c
parentaf4c412ebf4ba96973fb6ea3e9ee8f59fe751769 (diff)
Improve discoverability of the expand/collapse feature.
It is now accessible via F6 when on tree view (as a bonus, it is now also reachable via the mouse). The function bar now dynamically changes to reflect the toggle nature of the tree-view mode (F5) and the F6 key serves as expand/collapse when on tree mode, and its previous behavior of bringing up the "Sort By" menu (which only made sense on non-tree mode). Users wishing to go to the "Sort By" menu straight from Tree View can still do so with the "<" and ">" keys (the top-compatible keys for sort selection).
Diffstat (limited to 'htop.c')
-rw-r--r--htop.c133
1 files changed, 94 insertions, 39 deletions
diff --git a/htop.c b/htop.c
index 48fc6fc7..94ff3a7c 100644
--- a/htop.c
+++ b/htop.c
@@ -48,6 +48,8 @@ static void printVersionFlag() {
exit(0);
}
+static const char* defaultFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL};
+
static void printHelpFlag() {
fputs("htop " VERSION " - " COPYRIGHT "\n"
"Released under the GNU GPL.\n\n"
@@ -76,7 +78,7 @@ static struct { const char* key; const char* info; } helpLeft[] = {
{ .key = " H: ", .info = "hide/show user threads" },
{ .key = " K: ", .info = "hide/show kernel threads" },
{ .key = " F: ", .info = "cursor follows process" },
- { .key = " + -: ", .info = "expand/collapse tree" },
+ { .key = " F6 + -: ", .info = "expand/collapse tree" },
{ .key = " P M T: ", .info = "sort by CPU%, MEM% or TIME" },
{ .key = " I: ", .info = "invert sort order" },
{ .key = " F6 >: ", .info = "select sort column" },
@@ -268,10 +270,24 @@ static bool setUserOnly(const char* userName, bool* userOnly, uid_t* userId) {
return false;
}
-static inline void setSortKey(ProcessList* pl, ProcessField sortKey, Panel* panel, Settings* settings) {
+static void setTreeView(ProcessList* pl, FunctionBar* fuBar, bool mode) {
+ if (mode) {
+ FunctionBar_setLabel(fuBar, KEY_F(5), "Sorted");
+ FunctionBar_setLabel(fuBar, KEY_F(6), "Collap");
+ } else {
+ FunctionBar_setLabel(fuBar, KEY_F(5), "Tree ");
+ FunctionBar_setLabel(fuBar, KEY_F(6), "SortBy");
+ }
+ if (mode != pl->treeView) {
+ FunctionBar_draw(fuBar, NULL);
+ }
+ pl->treeView = mode;
+}
+
+static inline void setSortKey(ProcessList* pl, FunctionBar* fuBar, ProcessField sortKey, Panel* panel, Settings* settings) {
pl->sortKey = sortKey;
pl->direction = 1;
- pl->treeView = false;
+ setTreeView(pl, fuBar, false);
settings->changed = true;
ProcessList_printHeader(pl, Panel_getHeader(panel));
}
@@ -294,6 +310,35 @@ static void tagAllChildren(Panel* panel, Process* parent) {
}
}
+static bool expandCollapse(Panel* panel) {
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (!p) return false;
+ p->showChildren = !p->showChildren;
+ return true;
+}
+
+void sortBy(Panel* panel, ProcessList* pl, Settings* settings, int headerHeight, FunctionBar* defaultBar, Header* header) {
+ Panel* sortPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem));
+ Panel_setHeader(sortPanel, "Sort by");
+ const char* fuFunctions[] = {"Sort ", "Cancel ", NULL};
+ ProcessField* fields = pl->fields;
+ for (int i = 0; fields[i]; i++) {
+ char* name = String_trim(Process_fieldNames[fields[i]]);
+ Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i]));
+ if (fields[i] == pl->sortKey)
+ Panel_setSelected(sortPanel, i);
+ free(name);
+ }
+ ListItem* field = (ListItem*) pickFromVector(panel, sortPanel, 15, headerHeight, fuFunctions, defaultBar, header);
+ if (field) {
+ settings->changed = true;
+ setSortKey(pl, defaultBar, field->key, panel, settings);
+ } else {
+ ProcessList_printHeader(pl, Panel_getHeader(panel));
+ }
+ Object_delete(sortPanel);
+}
+
int main(int argc, char** argv) {
int delay = -1;
@@ -437,16 +482,15 @@ int main(int argc, char** argv) {
Panel* panel = Panel_new(0, headerHeight, COLS, LINES - headerHeight - 2, false, &Process_class);
ProcessList_setPanel(pl, panel);
+ FunctionBar* defaultBar = FunctionBar_new(defaultFunctions, NULL, NULL);
+ setTreeView(pl, defaultBar, pl->treeView);
+
if (sortKey > 0) {
pl->sortKey = sortKey;
- pl->treeView = false;
+ setTreeView(pl, defaultBar, false);
pl->direction = 1;
}
ProcessList_printHeader(pl, Panel_getHeader(panel));
-
- const char* defaultFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ",
- "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL};
- FunctionBar* defaultBar = FunctionBar_new(defaultFunctions, NULL, NULL);
IncSet* inc = IncSet_new(defaultBar);
@@ -468,6 +512,8 @@ int main(int argc, char** argv) {
bool idle = false;
+ bool collapsed = false;
+
while (!quit) {
gettimeofday(&tv, NULL);
newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
@@ -490,9 +536,24 @@ int main(int argc, char** argv) {
idle = false;
}
doRefresh = true;
+
+ if (pl->treeView) {
+ Process* p = (Process*) Panel_getSelected(panel);
+ if (p) {
+ if (!p->showChildren && !collapsed) {
+ FunctionBar_setLabel(defaultBar, KEY_F(6), "Expand");
+ FunctionBar_draw(defaultBar, NULL);
+ } else if (p->showChildren && collapsed) {
+ FunctionBar_setLabel(defaultBar, KEY_F(6), "Collap");
+ FunctionBar_draw(defaultBar, NULL);
+ }
+ collapsed = !p->showChildren;
+ }
+ }
- if (!idle)
+ if (!idle) {
Panel_draw(panel, true);
+ }
int prev = ch;
if (inc->active)
@@ -524,9 +585,9 @@ int main(int argc, char** argv) {
ProcessField field = ProcessList_keyAt(pl, x);
if (field == pl->sortKey) {
ProcessList_invertSortOrder(pl);
- pl->treeView = false;
+ setTreeView(pl, defaultBar, false);
} else {
- setSortKey(pl, field, panel, settings);
+ setSortKey(pl, defaultBar, field, panel, settings);
}
refreshTimeout = 0;
continue;
@@ -580,13 +641,13 @@ int main(int argc, char** argv) {
case 'M':
{
refreshTimeout = 0;
- setSortKey(pl, PERCENT_MEM, panel, settings);
+ setSortKey(pl, defaultBar, PERCENT_MEM, panel, settings);
break;
}
case 'T':
{
refreshTimeout = 0;
- setSortKey(pl, TIME, panel, settings);
+ setSortKey(pl, defaultBar, TIME, panel, settings);
break;
}
case 'c':
@@ -608,7 +669,7 @@ int main(int argc, char** argv) {
case 'P':
{
refreshTimeout = 0;
- setSortKey(pl, PERCENT_CPU, panel, settings);
+ setSortKey(pl, defaultBar, PERCENT_CPU, panel, settings);
break;
}
case KEY_F(1):
@@ -704,11 +765,10 @@ int main(int argc, char** argv) {
case '=':
case '-':
{
- Process* p = (Process*) Panel_getSelected(panel);
- if (!p) break;
- p->showChildren = !p->showChildren;
- refreshTimeout = 0;
- doRecalculate = true;
+ if (expandCollapse(panel)) {
+ doRecalculate = true;
+ refreshTimeout = 0;
+ }
break;
}
case KEY_F(9):
@@ -764,31 +824,25 @@ int main(int argc, char** argv) {
break;
case '<':
case ',':
- case KEY_F(18):
case '>':
case '.':
+ {
+ sortBy(panel, pl, settings, headerHeight, defaultBar, header);
+ refreshTimeout = 0;
+ break;
+ }
+ case KEY_F(18):
case KEY_F(6):
{
- Panel* sortPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem));
- Panel_setHeader(sortPanel, "Sort by");
- const char* fuFunctions[] = {"Sort ", "Cancel ", NULL};
- ProcessField* fields = pl->fields;
- for (int i = 0; fields[i]; i++) {
- char* name = String_trim(Process_fieldNames[fields[i]]);
- Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i]));
- if (fields[i] == pl->sortKey)
- Panel_setSelected(sortPanel, i);
- free(name);
- }
- ListItem* field = (ListItem*) pickFromVector(panel, sortPanel, 15, headerHeight, fuFunctions, defaultBar, header);
- if (field) {
- settings->changed = true;
- setSortKey(pl, field->key, panel, settings);
+ if (pl->treeView) {
+ if (expandCollapse(panel)) {
+ doRecalculate = true;
+ refreshTimeout = 0;
+ }
} else {
- ProcessList_printHeader(pl, Panel_getHeader(panel));
+ sortBy(panel, pl, settings, headerHeight, defaultBar, header);
+ refreshTimeout = 0;
}
- Object_delete(sortPanel);
- refreshTimeout = 0;
break;
}
case 'i':
@@ -842,7 +896,8 @@ int main(int argc, char** argv) {
case 't':
case KEY_F(5):
refreshTimeout = 0;
- pl->treeView = !pl->treeView;
+ collapsed = false;
+ setTreeView(pl, defaultBar, !pl->treeView);
if (pl->treeView) pl->direction = 1;
ProcessList_printHeader(pl, Panel_getHeader(panel));
ProcessList_expandTree(pl);

© 2014-2024 Faster IT GmbH | imprint | privacy policy