From 2327260ee888146beab3da66507c7744334a6973 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Fri, 18 Dec 2020 11:03:31 -0300 Subject: [PATCH] Separate tree and list sort orders Implements the suggestion from https://github.com/htop-dev/htop/issues/399#issuecomment-747861013 Thanks to the refactors from 0bd5c8fb5da and 6393baa74e5, this was really easy and clean to do. It maintains the "Tree view always by PID" option in the Settings, which results in some specific behaviors such as "clicking on the column header to exit tree view" and "picking a new sort order to exit tree view", for the sake of the muscle memory of long time htop users. :) --- Action.c | 10 +++------- MainPanel.c | 9 +++++---- Process.c | 7 ++----- ProcessList.c | 6 ++++-- Settings.c | 23 ++++++++++++++++++++--- Settings.h | 14 ++++++++++++++ htop.c | 9 ++++++--- 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/Action.c b/Action.c index 3335a430..d7359be8 100644 --- a/Action.c +++ b/Action.c @@ -158,11 +158,7 @@ static bool collapseIntoParent(Panel* panel) { } Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) { - settings->sortKey = sortKey; - settings->direction = 1; - if (settings->treeViewAlwaysByPID) { - settings->treeView = false; - } + Settings_setSortKey(settings, sortKey); return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING; } @@ -174,7 +170,7 @@ static Htop_Reaction sortBy(State* st) { for (int i = 0; fields[i]; i++) { char* name = String_trim(Process_fields[fields[i]].name); Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i])); - if (fields[i] == st->settings->sortKey) + if (fields[i] == Settings_getActiveSortKey(st->settings)) Panel_setSelected(sortPanel, i); free(name); @@ -234,7 +230,7 @@ static Htop_Reaction actionToggleMergedCommand(State* st) { static Htop_Reaction actionToggleTreeView(State* st) { st->settings->treeView = !st->settings->treeView; if (st->settings->treeView) { - st->settings->direction = 1; + st->settings->treeDirection = 1; } ProcessList_expandTree(st->pl); diff --git a/MainPanel.c b/MainPanel.c index f2b71e68..815609f6 100644 --- a/MainPanel.c +++ b/MainPanel.c @@ -60,14 +60,15 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) { Settings* settings = this->state->settings; int hx = super->scrollH + x + 1; ProcessField field = ProcessList_keyAt(pl, hx); - if (field == settings->sortKey) { + if (settings->treeView && settings->treeViewAlwaysByPID) { + settings->treeView = false; + settings->direction = 1; + reaction |= Action_setSortKey(settings, field); + } else if (field == Settings_getActiveSortKey(settings)) { Settings_invertSortOrder(settings); } else { reaction |= Action_setSortKey(settings, field); } - if (settings->treeViewAlwaysByPID) { - settings->treeView = false; - } reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS; result = HANDLED; } else if (ch != ERR && this->inc->active) { diff --git a/Process.c b/Process.c index a65918f5..46082173 100644 --- a/Process.c +++ b/Process.c @@ -497,7 +497,7 @@ long Process_compare(const void* v1, const void* v2) { const Settings *settings = ((const Process*)v1)->settings; int r; - if (settings->direction == 1) { + if (Settings_getActiveDirection(settings) == 1) { p1 = (const Process*)v1; p2 = (const Process*)v2; } else { @@ -505,10 +505,7 @@ long Process_compare(const void* v1, const void* v2) { p1 = (const Process*)v2; } - ProcessField key = settings->sortKey; - if (settings->treeView && settings->treeViewAlwaysByPID) { - key = PID; - } + ProcessField key = Settings_getActiveSortKey(settings); switch (key) { case PERCENT_CPU: diff --git a/ProcessList.c b/ProcessList.c index 54b69184..02ce373f 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -85,6 +85,8 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) { const Settings* settings = this->settings; const ProcessField* fields = settings->fields; + ProcessField key = Settings_getActiveSortKey(settings); + for (int i = 0; fields[i]; i++) { const char* field = Process_fields[fields[i]].title; if (!field) { @@ -94,7 +96,7 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) { int color; if (settings->treeView && settings->treeViewAlwaysByPID) { color = CRT_colors[PANEL_HEADER_FOCUS]; - } else if (settings->sortKey == fields[i]) { + } else if (key == fields[i]) { color = CRT_colors[PANEL_SELECTION_FOCUS]; } else { color = CRT_colors[PANEL_HEADER_FOCUS]; @@ -355,7 +357,7 @@ static long ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) static void ProcessList_buildTree(ProcessList* this) { int node_counter = 1; int node_index = 0; - int direction = this->settings->direction; + int direction = Settings_getActiveDirection(this->settings); // Sort by PID Vector_quickSortCustomCompare(this->processes, ProcessList_treeProcessCompareByPID); diff --git a/Settings.c b/Settings.c index 3b629a87..9122955d 100644 --- a/Settings.c +++ b/Settings.c @@ -137,8 +137,13 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo } else if (String_eq(option[0], "sort_key")) { // This "+1" is for compatibility with the older enum format. this->sortKey = atoi(option[1]) + 1; + } else if (String_eq(option[0], "tree_sort_key")) { + // This "+1" is for compatibility with the older enum format. + this->treeSortKey = atoi(option[1]) + 1; } else if (String_eq(option[0], "sort_direction")) { this->direction = atoi(option[1]); + } else if (String_eq(option[0], "tree_sort_direction")) { + this->treeDirection = atoi(option[1]); } else if (String_eq(option[0], "tree_view")) { this->treeView = atoi(option[1]); } else if (String_eq(option[0], "tree_view_always_by_pid")) { @@ -275,6 +280,8 @@ bool Settings_write(Settings* this) { // This "-1" is for compatibility with the older enum format. fprintf(fd, "sort_key=%d\n", (int) this->sortKey - 1); fprintf(fd, "sort_direction=%d\n", (int) this->direction); + fprintf(fd, "tree_sort_key=%d\n", (int) this->treeSortKey - 1); + fprintf(fd, "tree_sort_direction=%d\n", (int) this->treeDirection); fprintf(fd, "hide_kernel_threads=%d\n", (int) this->hideKernelThreads); fprintf(fd, "hide_userland_threads=%d\n", (int) this->hideUserlandThreads); fprintf(fd, "shadow_other_users=%d\n", (int) this->shadowOtherUsers); @@ -319,7 +326,9 @@ Settings* Settings_new(int initialCpuCount) { Settings* this = xCalloc(1, sizeof(Settings)); this->sortKey = PERCENT_CPU; + this->treeSortKey = PID; this->direction = 1; + this->treeDirection = 1; this->shadowOtherUsers = false; this->showThreadNames = false; this->hideKernelThreads = false; @@ -430,9 +439,17 @@ Settings* Settings_new(int initialCpuCount) { } void Settings_invertSortOrder(Settings* this) { - if (this->direction == 1) { - this->direction = -1; - } else { + int* attr = (this->treeView) ? &(this->treeDirection) : &(this->direction); + *attr = (*attr == 1) ? -1 : 1; +} + +void Settings_setSortKey(Settings* this, ProcessField sortKey) { + if (this->treeViewAlwaysByPID || !this->treeView) { + this->sortKey = sortKey; this->direction = 1; + this->treeView = false; + } else { + this->treeSortKey = sortKey; + this->treeDirection = 1; } } diff --git a/Settings.h b/Settings.h index 41a60f59..35520638 100644 --- a/Settings.h +++ b/Settings.h @@ -33,7 +33,9 @@ typedef struct Settings_ { int delay; int direction; + int treeDirection; ProcessField sortKey; + ProcessField treeSortKey; bool countCPUsFromOne; bool detailedCPUTime; @@ -71,6 +73,16 @@ typedef struct Settings_ { #define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromOne ? (cpu)+1 : (cpu)) +static inline ProcessField Settings_getActiveSortKey(const Settings* this) { + return (this->treeView) + ? (this->treeViewAlwaysByPID ? PID : this->treeSortKey) + : this->sortKey; +} + +static inline int Settings_getActiveDirection(const Settings* this) { + return this->treeView ? this->treeDirection : this->direction; +} + void Settings_delete(Settings* this); bool Settings_write(Settings* this); @@ -79,4 +91,6 @@ Settings* Settings_new(int initialCpuCount); void Settings_invertSortOrder(Settings* this); +void Settings_setSortKey(Settings* this, ProcessField sortKey); + #endif diff --git a/htop.c b/htop.c index 23da0815..7d67a05a 100644 --- a/htop.c +++ b/htop.c @@ -298,9 +298,12 @@ int main(int argc, char** argv) { if (flags.highlightDelaySecs != -1) settings->highlightDelaySecs = flags.highlightDelaySecs; if (flags.sortKey > 0) { - settings->sortKey = flags.sortKey; - settings->treeView = false; - settings->direction = 1; + // -t -s means "tree sorted by key" + // -s means "list sorted by key" (previous existing behavior) + if (!flags.treeView) { + settings->treeView = false; + } + Settings_setSortKey(settings, flags.sortKey); } CRT_init(&(settings->delay), settings->colorScheme, flags.allowUnicode);