@@ -48,6 +48,8 @@ static void printVersionFlag() {
48
48
exit (0 );
49
49
}
50
50
51
+ static const char * defaultFunctions [] = {"Help " , "Setup " , "Search" , "Filter" , "Tree " , "SortBy" , "Nice -" , "Nice +" , "Kill " , "Quit " , NULL };
52
+
51
53
static void printHelpFlag () {
52
54
fputs ("htop " VERSION " - " COPYRIGHT "\n"
53
55
"Released under the GNU GPL.\n\n"
@@ -76,7 +78,7 @@ static struct { const char* key; const char* info; } helpLeft[] = {
76
78
{ .key = " H: " , .info = "hide/show user threads" },
77
79
{ .key = " K: " , .info = "hide/show kernel threads" },
78
80
{ .key = " F: " , .info = "cursor follows process" },
79
- { .key = " + -: " , .info = "expand/collapse tree" },
81
+ { .key = " F6 + -: " , .info = "expand/collapse tree" },
80
82
{ .key = " P M T: " , .info = "sort by CPU%, MEM% or TIME" },
81
83
{ .key = " I: " , .info = "invert sort order" },
82
84
{ .key = " F6 >: " , .info = "select sort column" },
@@ -268,10 +270,24 @@ static bool setUserOnly(const char* userName, bool* userOnly, uid_t* userId) {
268
270
return false;
269
271
}
270
272
271
- static inline void setSortKey (ProcessList * pl , ProcessField sortKey , Panel * panel , Settings * settings ) {
273
+ static void setTreeView (ProcessList * pl , FunctionBar * fuBar , bool mode ) {
274
+ if (mode ) {
275
+ FunctionBar_setLabel (fuBar , KEY_F (5 ), "Sorted" );
276
+ FunctionBar_setLabel (fuBar , KEY_F (6 ), "Collap" );
277
+ } else {
278
+ FunctionBar_setLabel (fuBar , KEY_F (5 ), "Tree " );
279
+ FunctionBar_setLabel (fuBar , KEY_F (6 ), "SortBy" );
280
+ }
281
+ if (mode != pl -> treeView ) {
282
+ FunctionBar_draw (fuBar , NULL );
283
+ }
284
+ pl -> treeView = mode ;
285
+ }
286
+
287
+ static inline void setSortKey (ProcessList * pl , FunctionBar * fuBar , ProcessField sortKey , Panel * panel , Settings * settings ) {
272
288
pl -> sortKey = sortKey ;
273
289
pl -> direction = 1 ;
274
- pl -> treeView = false;
290
+ setTreeView ( pl , fuBar , false) ;
275
291
settings -> changed = true;
276
292
ProcessList_printHeader (pl , Panel_getHeader (panel ));
277
293
}
@@ -294,6 +310,35 @@ static void tagAllChildren(Panel* panel, Process* parent) {
294
310
}
295
311
}
296
312
313
+ static bool expandCollapse (Panel * panel ) {
314
+ Process * p = (Process * ) Panel_getSelected (panel );
315
+ if (!p ) return false;
316
+ p -> showChildren = !p -> showChildren ;
317
+ return true;
318
+ }
319
+
320
+ void sortBy (Panel * panel , ProcessList * pl , Settings * settings , int headerHeight , FunctionBar * defaultBar , Header * header ) {
321
+ Panel * sortPanel = Panel_new (0 , 0 , 0 , 0 , true, Class (ListItem ));
322
+ Panel_setHeader (sortPanel , "Sort by" );
323
+ const char * fuFunctions [] = {"Sort " , "Cancel " , NULL };
324
+ ProcessField * fields = pl -> fields ;
325
+ for (int i = 0 ; fields [i ]; i ++ ) {
326
+ char * name = String_trim (Process_fieldNames [fields [i ]]);
327
+ Panel_add (sortPanel , (Object * ) ListItem_new (name , fields [i ]));
328
+ if (fields [i ] == pl -> sortKey )
329
+ Panel_setSelected (sortPanel , i );
330
+ free (name );
331
+ }
332
+ ListItem * field = (ListItem * ) pickFromVector (panel , sortPanel , 15 , headerHeight , fuFunctions , defaultBar , header );
333
+ if (field ) {
334
+ settings -> changed = true;
335
+ setSortKey (pl , defaultBar , field -> key , panel , settings );
336
+ } else {
337
+ ProcessList_printHeader (pl , Panel_getHeader (panel ));
338
+ }
339
+ Object_delete (sortPanel );
340
+ }
341
+
297
342
int main (int argc , char * * argv ) {
298
343
299
344
int delay = -1 ;
@@ -437,16 +482,15 @@ int main(int argc, char** argv) {
437
482
Panel * panel = Panel_new (0 , headerHeight , COLS , LINES - headerHeight - 2 , false, & Process_class );
438
483
ProcessList_setPanel (pl , panel );
439
484
485
+ FunctionBar * defaultBar = FunctionBar_new (defaultFunctions , NULL , NULL );
486
+ setTreeView (pl , defaultBar , pl -> treeView );
487
+
440
488
if (sortKey > 0 ) {
441
489
pl -> sortKey = sortKey ;
442
- pl -> treeView = false;
490
+ setTreeView ( pl , defaultBar , false) ;
443
491
pl -> direction = 1 ;
444
492
}
445
493
ProcessList_printHeader (pl , Panel_getHeader (panel ));
446
-
447
- const char * defaultFunctions [] = {"Help " , "Setup " , "Search" , "Filter" , "Tree " ,
448
- "SortBy" , "Nice -" , "Nice +" , "Kill " , "Quit " , NULL };
449
- FunctionBar * defaultBar = FunctionBar_new (defaultFunctions , NULL , NULL );
450
494
451
495
IncSet * inc = IncSet_new (defaultBar );
452
496
@@ -468,6 +512,8 @@ int main(int argc, char** argv) {
468
512
469
513
bool idle = false;
470
514
515
+ bool collapsed = false;
516
+
471
517
while (!quit ) {
472
518
gettimeofday (& tv , NULL );
473
519
newTime = ((double )tv .tv_sec * 10 ) + ((double )tv .tv_usec / 100000 );
@@ -490,9 +536,24 @@ int main(int argc, char** argv) {
490
536
idle = false;
491
537
}
492
538
doRefresh = true;
539
+
540
+ if (pl -> treeView ) {
541
+ Process * p = (Process * ) Panel_getSelected (panel );
542
+ if (p ) {
543
+ if (!p -> showChildren && !collapsed ) {
544
+ FunctionBar_setLabel (defaultBar , KEY_F (6 ), "Expand" );
545
+ FunctionBar_draw (defaultBar , NULL );
546
+ } else if (p -> showChildren && collapsed ) {
547
+ FunctionBar_setLabel (defaultBar , KEY_F (6 ), "Collap" );
548
+ FunctionBar_draw (defaultBar , NULL );
549
+ }
550
+ collapsed = !p -> showChildren ;
551
+ }
552
+ }
493
553
494
- if (!idle )
554
+ if (!idle ) {
495
555
Panel_draw (panel , true);
556
+ }
496
557
497
558
int prev = ch ;
498
559
if (inc -> active )
@@ -524,9 +585,9 @@ int main(int argc, char** argv) {
524
585
ProcessField field = ProcessList_keyAt (pl , x );
525
586
if (field == pl -> sortKey ) {
526
587
ProcessList_invertSortOrder (pl );
527
- pl -> treeView = false;
588
+ setTreeView ( pl , defaultBar , false) ;
528
589
} else {
529
- setSortKey (pl , field , panel , settings );
590
+ setSortKey (pl , defaultBar , field , panel , settings );
530
591
}
531
592
refreshTimeout = 0 ;
532
593
continue ;
@@ -580,13 +641,13 @@ int main(int argc, char** argv) {
580
641
case 'M' :
581
642
{
582
643
refreshTimeout = 0 ;
583
- setSortKey (pl , PERCENT_MEM , panel , settings );
644
+ setSortKey (pl , defaultBar , PERCENT_MEM , panel , settings );
584
645
break ;
585
646
}
586
647
case 'T' :
587
648
{
588
649
refreshTimeout = 0 ;
589
- setSortKey (pl , TIME , panel , settings );
650
+ setSortKey (pl , defaultBar , TIME , panel , settings );
590
651
break ;
591
652
}
592
653
case 'c' :
@@ -608,7 +669,7 @@ int main(int argc, char** argv) {
608
669
case 'P' :
609
670
{
610
671
refreshTimeout = 0 ;
611
- setSortKey (pl , PERCENT_CPU , panel , settings );
672
+ setSortKey (pl , defaultBar , PERCENT_CPU , panel , settings );
612
673
break ;
613
674
}
614
675
case KEY_F (1 ):
@@ -704,11 +765,10 @@ int main(int argc, char** argv) {
704
765
case '=' :
705
766
case '-' :
706
767
{
707
- Process * p = (Process * ) Panel_getSelected (panel );
708
- if (!p ) break ;
709
- p -> showChildren = !p -> showChildren ;
710
- refreshTimeout = 0 ;
711
- doRecalculate = true;
768
+ if (expandCollapse (panel )) {
769
+ doRecalculate = true;
770
+ refreshTimeout = 0 ;
771
+ }
712
772
break ;
713
773
}
714
774
case KEY_F (9 ):
@@ -764,31 +824,25 @@ int main(int argc, char** argv) {
764
824
break ;
765
825
case '<' :
766
826
case ',' :
767
- case KEY_F (18 ):
768
827
case '>' :
769
828
case '.' :
829
+ {
830
+ sortBy (panel , pl , settings , headerHeight , defaultBar , header );
831
+ refreshTimeout = 0 ;
832
+ break ;
833
+ }
834
+ case KEY_F (18 ):
770
835
case KEY_F (6 ):
771
836
{
772
- Panel * sortPanel = Panel_new (0 , 0 , 0 , 0 , true, Class (ListItem ));
773
- Panel_setHeader (sortPanel , "Sort by" );
774
- const char * fuFunctions [] = {"Sort " , "Cancel " , NULL };
775
- ProcessField * fields = pl -> fields ;
776
- for (int i = 0 ; fields [i ]; i ++ ) {
777
- char * name = String_trim (Process_fieldNames [fields [i ]]);
778
- Panel_add (sortPanel , (Object * ) ListItem_new (name , fields [i ]));
779
- if (fields [i ] == pl -> sortKey )
780
- Panel_setSelected (sortPanel , i );
781
- free (name );
782
- }
783
- ListItem * field = (ListItem * ) pickFromVector (panel , sortPanel , 15 , headerHeight , fuFunctions , defaultBar , header );
784
- if (field ) {
785
- settings -> changed = true;
786
- setSortKey (pl , field -> key , panel , settings );
837
+ if (pl -> treeView ) {
838
+ if (expandCollapse (panel )) {
839
+ doRecalculate = true;
840
+ refreshTimeout = 0 ;
841
+ }
787
842
} else {
788
- ProcessList_printHeader (pl , Panel_getHeader (panel ));
843
+ sortBy (panel , pl , settings , headerHeight , defaultBar , header );
844
+ refreshTimeout = 0 ;
789
845
}
790
- Object_delete (sortPanel );
791
- refreshTimeout = 0 ;
792
846
break ;
793
847
}
794
848
case 'i' :
@@ -842,7 +896,8 @@ int main(int argc, char** argv) {
842
896
case 't' :
843
897
case KEY_F (5 ):
844
898
refreshTimeout = 0 ;
845
- pl -> treeView = !pl -> treeView ;
899
+ collapsed = false;
900
+ setTreeView (pl , defaultBar , !pl -> treeView );
846
901
if (pl -> treeView ) pl -> direction = 1 ;
847
902
ProcessList_printHeader (pl , Panel_getHeader (panel ));
848
903
ProcessList_expandTree (pl );
0 commit comments