mirror of https://github.com/xzeldon/htop.git
expand/collapse tree
This commit is contained in:
parent
bc4f7147cc
commit
9eb912149e
|
@ -79,6 +79,7 @@ typedef struct Process_ {
|
||||||
int indent;
|
int indent;
|
||||||
char state;
|
char state;
|
||||||
bool tag;
|
bool tag;
|
||||||
|
bool showChildren;
|
||||||
pid_t ppid;
|
pid_t ppid;
|
||||||
unsigned int pgrp;
|
unsigned int pgrp;
|
||||||
unsigned int session;
|
unsigned int session;
|
||||||
|
@ -331,9 +332,9 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel
|
||||||
n -= 4;
|
n -= 4;
|
||||||
}
|
}
|
||||||
if (this->pl->direction == 1)
|
if (this->pl->direction == 1)
|
||||||
snprintf(buf, n, " `- ");
|
snprintf(buf, n, " `%s ", this->showChildren ? "-" : "+" );
|
||||||
else
|
else
|
||||||
snprintf(buf, n, " ,- ");
|
snprintf(buf, n, " ,%s ", this->showChildren ? "-" : "+" );
|
||||||
RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
|
RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
|
||||||
Process_writeCommand(this, attr, baseattr, str);
|
Process_writeCommand(this, attr, baseattr, str);
|
||||||
return;
|
return;
|
||||||
|
@ -460,6 +461,7 @@ Process* Process_new(struct ProcessList_ *pl) {
|
||||||
this->pid = 0;
|
this->pid = 0;
|
||||||
this->pl = pl;
|
this->pl = pl;
|
||||||
this->tag = false;
|
this->tag = false;
|
||||||
|
this->showChildren = true;
|
||||||
this->updated = false;
|
this->updated = false;
|
||||||
this->utime = 0;
|
this->utime = 0;
|
||||||
this->stime = 0;
|
this->stime = 0;
|
||||||
|
|
|
@ -81,6 +81,7 @@ typedef struct Process_ {
|
||||||
int indent;
|
int indent;
|
||||||
char state;
|
char state;
|
||||||
bool tag;
|
bool tag;
|
||||||
|
bool showChildren;
|
||||||
pid_t ppid;
|
pid_t ppid;
|
||||||
unsigned int pgrp;
|
unsigned int pgrp;
|
||||||
unsigned int session;
|
unsigned int session;
|
||||||
|
|
|
@ -331,7 +331,7 @@ int ProcessList_size(ProcessList* this) {
|
||||||
return (Vector_size(this->processes));
|
return (Vector_size(this->processes));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int indent, int direction) {
|
static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int indent, int direction, bool show) {
|
||||||
Vector* children = Vector_new(PROCESS_CLASS, false, DEFAULT_SIZE, Process_compare);
|
Vector* children = Vector_new(PROCESS_CLASS, false, DEFAULT_SIZE, Process_compare);
|
||||||
|
|
||||||
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
||||||
|
@ -344,17 +344,21 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i
|
||||||
int size = Vector_size(children);
|
int size = Vector_size(children);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
Process* process = (Process*) (Vector_get(children, i));
|
Process* process = (Process*) (Vector_get(children, i));
|
||||||
int s = this->processes2->items;
|
if (show) {
|
||||||
if (direction == 1)
|
int s = this->processes2->items;
|
||||||
Vector_add(this->processes2, process);
|
if (direction == 1)
|
||||||
else
|
Vector_add(this->processes2, process);
|
||||||
Vector_insert(this->processes2, 0, process);
|
else
|
||||||
assert(this->processes2->items == s+1); (void)s;
|
Vector_insert(this->processes2, 0, process);
|
||||||
int nextIndent = indent;
|
assert(this->processes2->items == s+1); (void)s;
|
||||||
if (i < size - 1)
|
int nextIndent = indent;
|
||||||
nextIndent = indent | (1 << level);
|
if (i < size - 1)
|
||||||
ProcessList_buildTree(this, process->pid, level+1, nextIndent, direction);
|
nextIndent = indent | (1 << level);
|
||||||
process->indent = indent | (1 << level);
|
ProcessList_buildTree(this, process->pid, level+1, nextIndent, direction, process->showChildren);
|
||||||
|
process->indent = indent | (1 << level);
|
||||||
|
} else {
|
||||||
|
Hashtable_remove(this->processTable, process->pid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Vector_delete(children);
|
Vector_delete(children);
|
||||||
}
|
}
|
||||||
|
@ -382,13 +386,13 @@ void ProcessList_sort(ProcessList* this) {
|
||||||
init->indent = 0;
|
init->indent = 0;
|
||||||
Vector_add(this->processes2, init);
|
Vector_add(this->processes2, init);
|
||||||
// Recursively empty list
|
// Recursively empty list
|
||||||
ProcessList_buildTree(this, init->pid, 0, 0, direction);
|
ProcessList_buildTree(this, init->pid, 0, 0, direction, true);
|
||||||
// Add leftovers
|
// Add leftovers
|
||||||
while (Vector_size(this->processes)) {
|
while (Vector_size(this->processes)) {
|
||||||
Process* p = (Process*) (Vector_take(this->processes, 0));
|
Process* p = (Process*) (Vector_take(this->processes, 0));
|
||||||
p->indent = 0;
|
p->indent = 0;
|
||||||
Vector_add(this->processes2, p);
|
Vector_add(this->processes2, p);
|
||||||
ProcessList_buildTree(this, p->pid, 0, 0, direction);
|
ProcessList_buildTree(this, p->pid, 0, 0, direction, p->showChildren);
|
||||||
}
|
}
|
||||||
assert(Vector_size(this->processes2) == vsize); (void)vsize;
|
assert(Vector_size(this->processes2) == vsize); (void)vsize;
|
||||||
assert(Vector_size(this->processes) == 0);
|
assert(Vector_size(this->processes) == 0);
|
||||||
|
|
15
Vector.c
15
Vector.c
|
@ -20,8 +20,6 @@ in the source distribution for its full text.
|
||||||
#define DEFAULT_SIZE -1
|
#define DEFAULT_SIZE -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void(*Vector_procedure)(void*);
|
|
||||||
|
|
||||||
typedef struct Vector_ {
|
typedef struct Vector_ {
|
||||||
Object **array;
|
Object **array;
|
||||||
Object_Compare compare;
|
Object_Compare compare;
|
||||||
|
@ -255,16 +253,3 @@ inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
static void Vector_foreach(Vector* this, Vector_procedure f) {
|
|
||||||
int i;
|
|
||||||
assert(Vector_isConsistent(this));
|
|
||||||
|
|
||||||
for (i = 0; i < this->items; i++)
|
|
||||||
f(this->array[i]);
|
|
||||||
assert(Vector_isConsistent(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
6
Vector.h
6
Vector.h
|
@ -22,8 +22,6 @@ in the source distribution for its full text.
|
||||||
#define DEFAULT_SIZE -1
|
#define DEFAULT_SIZE -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void(*Vector_procedure)(void*);
|
|
||||||
|
|
||||||
typedef struct Vector_ {
|
typedef struct Vector_ {
|
||||||
Object **array;
|
Object **array;
|
||||||
Object_Compare compare;
|
Object_Compare compare;
|
||||||
|
@ -73,8 +71,4 @@ void Vector_add(Vector* this, void* data_);
|
||||||
|
|
||||||
extern int Vector_indexOf(Vector* this, void* search_, Object_Compare compare);
|
extern int Vector_indexOf(Vector* this, void* search_, Object_Compare compare);
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
19
htop.c
19
htop.c
|
@ -117,10 +117,10 @@ static void showHelp(ProcessList* pl) {
|
||||||
mvaddstr(11, 0, " F3 /: incremental name search H: hide/show user threads");
|
mvaddstr(11, 0, " F3 /: incremental name search H: hide/show user threads");
|
||||||
mvaddstr(12, 0, " K: hide/show kernel threads");
|
mvaddstr(12, 0, " K: hide/show kernel threads");
|
||||||
mvaddstr(13, 0, " Space: tag processes F: cursor follows process");
|
mvaddstr(13, 0, " Space: tag processes F: cursor follows process");
|
||||||
mvaddstr(14, 0, " U: untag all processes");
|
mvaddstr(14, 0, " U: untag all processes + -: expand/collapse tree");
|
||||||
mvaddstr(15, 0, " F9 k: kill process/tagged processes P: sort by CPU%");
|
mvaddstr(15, 0, " F9 k: kill process/tagged processes P: sort by CPU%");
|
||||||
mvaddstr(16, 0, " - ] F7: higher priority (root only) M: sort by MEM%");
|
mvaddstr(16, 0, " ] F7: higher priority (root only) M: sort by MEM%");
|
||||||
mvaddstr(17, 0, " + [ F8: lower priority (+ nice) T: sort by TIME");
|
mvaddstr(17, 0, " [ F8: lower priority (+ nice) T: sort by TIME");
|
||||||
#ifdef HAVE_PLPA
|
#ifdef HAVE_PLPA
|
||||||
if (pl->processorCount > 1)
|
if (pl->processorCount > 1)
|
||||||
mvaddstr(18, 0, " a: set CPU affinity F4 I: invert sort order");
|
mvaddstr(18, 0, " a: set CPU affinity F4 I: invert sort order");
|
||||||
|
@ -639,6 +639,16 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case '+':
|
||||||
|
case '=':
|
||||||
|
case '-':
|
||||||
|
{
|
||||||
|
Process* p = (Process*) Panel_getSelected(panel);
|
||||||
|
p->showChildren = !p->showChildren;
|
||||||
|
refreshTimeout = 0;
|
||||||
|
doRecalculate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case KEY_F(9):
|
case KEY_F(9):
|
||||||
case 'k':
|
case 'k':
|
||||||
{
|
{
|
||||||
|
@ -751,15 +761,12 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
case KEY_F(8):
|
case KEY_F(8):
|
||||||
case '[':
|
case '[':
|
||||||
case '=':
|
|
||||||
case '+':
|
|
||||||
{
|
{
|
||||||
doRefresh = changePriority(panel, 1);
|
doRefresh = changePriority(panel, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEY_F(7):
|
case KEY_F(7):
|
||||||
case ']':
|
case ']':
|
||||||
case '-':
|
|
||||||
{
|
{
|
||||||
doRefresh = changePriority(panel, -1);
|
doRefresh = changePriority(panel, -1);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue