source: trunk/third/gnome-system-monitor/src/proctable.c @ 18394

Revision 18394, 22.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18393, which included commits to RCS files with non-trunk default branches.
Line 
1/* Procman tree view and process updating
2 * Copyright (C) 2001 Kevin Vandersloot
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20#ifdef HAVE_CONFIG_H
21#  include <config.h>
22#endif
23
24#include <string.h>
25#include <glibtop.h>
26#include <glibtop/proclist.h>
27#include <glibtop/xmalloc.h>
28#include <glibtop/procstate.h>
29#include <glibtop/procmem.h>
30#include <glibtop/proctime.h>
31#include <glibtop/procuid.h>
32#include <glibtop/procargs.h>
33#include <glibtop/mem.h>
34#include <glibtop/swap.h>
35#include <glibtop/procmap.h>
36#include <sys/stat.h>
37#include <pwd.h>
38#include "procman.h"
39#include "proctable.h"
40#include "callbacks.h"
41#include "prettytable.h"
42#include "util.h"
43#include "infoview.h"
44#include "interface.h"
45#include "memmaps.h"
46#include "favorites.h"
47
48
49
50gint total_time = 0;
51gint total_time_last = 0;
52gint total_time_meter = 0;
53gint total_time_last_meter = 0;
54gint cpu_time_last = 0;
55gint cpu_time = 0;
56gfloat pcpu_last = 0.0;
57
58static gint
59sort_ints (GtkTreeModel *model, GtkTreeIter *itera, GtkTreeIter *iterb, gpointer data)
60{
61        ProcInfo *infoa = NULL, *infob = NULL;
62        gint col = GPOINTER_TO_INT (data);
63        gint a, b;
64       
65        gtk_tree_model_get (model, itera, COL_POINTER, &infoa, -1);
66        gtk_tree_model_get (model, iterb, COL_POINTER, &infob, -1);
67        g_return_val_if_fail (infoa, 0);
68        g_return_val_if_fail (infob, 0);               
69       
70        switch (col) {
71        case COL_MEM:
72                a = infoa->mem;
73                b = infob->mem;
74                break;
75        case COL_CPU:
76                a = infoa->cpu;
77                b = infob->cpu;
78                break;
79        case COL_PID:
80                a = infoa->pid;
81                b = infob->pid;
82                break;
83        case COL_NICE:
84                a = infoa->nice;
85                b = infob->nice;
86                break;
87        case COL_VMSIZE:
88                a = infoa->vmsize;
89                b = infob->vmsize;
90                break;
91        case COL_MEMRES:
92                a = infoa->memres;
93                b = infob->memres;
94                break;
95        case COL_MEMSHARED:
96                a = infoa->memshared;
97                b = infob->memshared;
98                break;
99        case COL_MEMRSS:
100                a = infoa->memrss;
101                b = infob->memrss;
102                break;
103        default:
104                return 0;
105                break;
106        }       
107       
108        if (a > b)
109                return -1;
110        else if (a < b)
111                return 1;
112        else
113                return 0;       
114}
115
116GtkWidget *
117proctable_new (ProcData *data)
118{
119        ProcData *procdata = data;
120        GtkWidget *proctree;
121        GtkWidget *scrolled = NULL;
122        GtkTreeStore *model;
123        GtkTreeSelection *selection;
124        GtkTreeViewColumn *column;
125        GtkCellRenderer *cell_renderer;
126        static gchar *title[] = {N_("Process Name"), N_("Arguments"),
127                                 N_("User"), N_("Status"),
128                                 N_("Memory"), N_("VM Size"), N_("Resident Memory"),
129                                 N_("Shared Memory"), N_("RSS Memory"),
130                                 /* xgettext:no-c-format */
131                                 N_("% CPU"),
132                                 N_("Nice"), N_("ID"), NULL, "POINTER"};
133        gint i;
134       
135        scrolled = gtk_scrolled_window_new (NULL, NULL);
136        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
137                                        GTK_POLICY_AUTOMATIC,
138                                        GTK_POLICY_AUTOMATIC);
139       
140        model = gtk_tree_store_new (NUM_COLUMNS,  G_TYPE_STRING,
141                                    G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
142                                    G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
143                                    G_TYPE_STRING, G_TYPE_STRING,
144                                    G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
145                                    GDK_TYPE_PIXBUF, G_TYPE_POINTER);               
146       
147        proctree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
148        gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (proctree), TRUE);
149        g_object_unref (G_OBJECT (model));
150       
151        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (proctree));
152        gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
153       
154        column = gtk_tree_view_column_new ();
155
156        cell_renderer = gtk_cell_renderer_pixbuf_new ();
157        gtk_tree_view_column_pack_start (column, cell_renderer, FALSE);
158        gtk_tree_view_column_set_attributes (column, cell_renderer,
159                                             "pixbuf", COL_PIXBUF,
160                                             NULL);
161               
162        cell_renderer = gtk_cell_renderer_text_new ();
163        gtk_tree_view_column_pack_start (column, cell_renderer, FALSE);
164        gtk_tree_view_column_set_attributes (column, cell_renderer,
165                                             "text", COL_NAME,
166                                             NULL);
167        gtk_tree_view_column_set_title (column, _(title[0]));
168        gtk_tree_view_column_set_sort_column_id (column, COL_NAME);
169        gtk_tree_view_column_set_resizable (column, TRUE);
170        gtk_tree_view_append_column (GTK_TREE_VIEW (proctree), column);
171        gtk_tree_view_set_expander_column (GTK_TREE_VIEW (proctree), column);
172       
173        for (i = 1; i < NUM_COLUMNS - 2; i++) {
174                cell_renderer = gtk_cell_renderer_text_new ();
175                column = gtk_tree_view_column_new_with_attributes (_(title[i]),
176                                                                   cell_renderer,
177                                                                   "text", i,
178                                                                   NULL);
179                gtk_tree_view_column_set_sort_column_id (column, i);
180                gtk_tree_view_column_set_resizable (column, TRUE);
181                gtk_tree_view_append_column (GTK_TREE_VIEW (proctree), column);
182        }
183       
184        gtk_container_add (GTK_CONTAINER (scrolled), proctree);
185       
186        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
187                                         COL_MEM,
188                                         sort_ints,
189                                         GINT_TO_POINTER (COL_MEM),
190                                         NULL);
191        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
192                                         COL_CPU,
193                                         sort_ints,
194                                         GINT_TO_POINTER (COL_CPU),
195                                         NULL);
196        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
197                                         COL_PID,
198                                         sort_ints,
199                                         GINT_TO_POINTER (COL_PID),
200                                         NULL);
201        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
202                                         COL_NICE,
203                                         sort_ints,
204                                         GINT_TO_POINTER (COL_NICE),
205                                         NULL);
206        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
207                                         COL_VMSIZE,
208                                         sort_ints,
209                                         GINT_TO_POINTER (COL_VMSIZE),
210                                         NULL);
211        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
212                                         COL_MEMRES,
213                                         sort_ints,
214                                         GINT_TO_POINTER (COL_MEMRES),
215                                         NULL);
216        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
217                                         COL_MEMSHARED,
218                                         sort_ints,
219                                         GINT_TO_POINTER (COL_MEMSHARED),
220                                         NULL);
221        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
222                                         COL_MEMRSS,
223                                         sort_ints,
224                                         GINT_TO_POINTER (COL_MEMRSS),
225                                         NULL);
226        procdata->tree = proctree;
227       
228        procman_get_tree_state (procdata->client, proctree, "/apps/procman/proctree");
229
230        g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (proctree))),
231                          "changed",
232                          G_CALLBACK (cb_row_selected), procdata);
233        g_signal_connect (G_OBJECT (proctree), "button_press_event",
234                          G_CALLBACK (cb_tree_button_pressed), procdata);
235        g_signal_connect (G_OBJECT (proctree), "key_press_event",
236                          G_CALLBACK (cb_tree_key_press), procdata);
237                         
238        return scrolled;
239
240}
241
242
243
244static void
245proctable_free_info (ProcInfo *info)
246{
247        if (!info)
248                return;
249        if (info->name)
250                g_free (info->name);
251        if (info->arguments)
252                g_free (info->arguments);
253        if (info->user)
254                g_free (info->user);
255        if (info->status)
256                g_free (info->status);
257        if (info->pixbuf)
258                g_object_unref (info->pixbuf);
259        g_free (info);
260}
261
262
263
264static void
265get_process_status (ProcInfo *info, char *state)
266{
267        if (info->status)
268                g_free (info->status);
269               
270        if (!g_strcasecmp (state, "r"))
271        {
272                info->status = g_strdup_printf (_("Running"));
273                info->running = TRUE;
274                return;
275        }
276        else if (!g_strcasecmp (state, "t"))
277        {
278                info->status = g_strdup_printf (_("Stopped"));
279                info->running = FALSE;
280        }
281        else
282        {
283                info->status = g_strdup_printf (_("Sleeping"));
284                info->running = FALSE;
285        }
286
287}
288
289static void
290get_process_name (ProcData *procdata, ProcInfo *info, gchar *cmd, gchar *args)
291{
292        gchar *command = NULL;
293        gint i, n = 0, len, newlen;
294        gboolean done = FALSE;
295                                                 
296        /* strip the absolute path from the arguments */       
297        if (args)
298        {
299                len = strlen (args);
300                i = len;
301                while (!done)
302                {
303                        /* no / in string */
304                        if (i == 0) {
305                                n = 0;
306                                done = TRUE;
307                        }
308                        if (args[i] == '/') {
309                                done = TRUE;
310                                n = i + 1;
311                        }
312                        i--;
313                }               
314                newlen = len - n;
315                command = g_new (gchar, newlen + 1);
316                for (i = 0; i < newlen; i++) {
317                        command[i] = args[i + n];
318                }
319                command[newlen] = '\0';
320        }
321       
322        if (command)
323                info->name = g_strdup (command);
324        else if (!command)
325                info->name = g_strdup (cmd);
326               
327        if (command)
328                g_free (command);
329
330}
331
332static ProcInfo *
333find_parent (ProcData *data, gint pid)
334{
335        GList *list = data->info;
336       
337       
338        /* ignore init as a parent process */
339        if (pid <= 1)
340                return NULL;
341
342        while (list)
343        {
344                ProcInfo *info = list->data;
345               
346                if (pid == info->pid)
347                        return info;
348                                               
349                list = g_list_next (list);
350        }
351        return NULL;
352}
353
354
355/* He he. Check to see if the process links to libX11. */
356static gboolean
357is_graphical (ProcInfo *info)
358{
359        glibtop_map_entry *memmaps;
360        glibtop_proc_map procmap;
361        char *string=NULL;
362        gint i;
363       
364        memmaps = glibtop_get_proc_map (&procmap, info->pid);
365       
366        for (i = 0; i < procmap.number; i++) {
367                if (memmaps [i].flags & (1 << GLIBTOP_MAP_ENTRY_FILENAME)) {
368                        string = strstr (memmaps[i].filename, "libX11");
369                        if (string) {
370                                glibtop_free (memmaps);
371                                return TRUE;
372                        }
373                }
374        }
375       
376        glibtop_free (memmaps);
377       
378        return FALSE;
379}
380
381
382void
383insert_info_to_tree (ProcInfo *info, ProcData *procdata)
384{
385        GtkTreeModel *model;
386        GtkTreeIter row;
387        gchar *name;
388        gchar *mem, *vmsize, *memres, *memshared, *memrss;
389       
390        /* Don't show process if it is not running */
391        if (procdata->config.whose_process == RUNNING_PROCESSES &&
392            (!info->running))
393                return;
394               
395        /* crazy hack to see if process links to libX11 */     
396        /*if (!is_graphical (info))
397                return;*/
398
399
400        /* Don't show processes that user has blacklisted */
401        if (is_process_blacklisted (procdata, info->name))
402        {       
403                info->is_blacklisted = TRUE;
404                return;
405        }
406        info->is_blacklisted = FALSE;
407       
408        /* Don't show threads */
409        if (!procdata->config.show_threads && info->is_thread)
410                return;
411        else if (info->is_thread)
412                name = g_strconcat (info->name, _(" (thread)"), NULL);
413        else
414                name = g_strdup (info->name);
415                       
416        model = gtk_tree_view_get_model (GTK_TREE_VIEW (procdata->tree));
417        if (info->has_parent && procdata->config.show_tree) {
418                GtkTreePath *parent_node = gtk_tree_model_get_path (model, &info->parent_node);
419               
420                gtk_tree_store_insert (GTK_TREE_STORE (model), &row, &info->parent_node, 0);
421                if (!gtk_tree_view_row_expanded (GTK_TREE_VIEW (procdata->tree), parent_node))     
422                        gtk_tree_view_expand_row (GTK_TREE_VIEW (procdata->tree),
423                                          parent_node,
424                                          FALSE);
425                                         
426                gtk_tree_path_free (parent_node);
427        }       
428        else
429                gtk_tree_store_insert (GTK_TREE_STORE (model), &row, NULL, 0);
430       
431        mem = get_size_string (info->mem);
432        vmsize = get_size_string (info->vmsize);
433        memres = get_size_string (info->memres);
434        memshared = get_size_string (info->memshared);
435        memrss = get_size_string (info->memrss);
436
437        /* COL_POINTER must be set first, because GtkTreeStore
438         * will call sort_ints as soon as we set the column
439         * that we're sorting on.
440         */
441       
442        gtk_tree_store_set (GTK_TREE_STORE (model), &row,
443                            COL_POINTER, info,
444                            COL_PIXBUF, info->pixbuf,
445                            COL_NAME, name,
446                            COL_ARGS, info->arguments,
447                            COL_USER, info->user,
448                            COL_STATUS, info->status,
449                            COL_MEM, mem,
450                            COL_VMSIZE, vmsize,
451                            COL_MEMRES, memres,
452                            COL_MEMSHARED, memshared,
453                            COL_MEMRSS, memrss,
454                            COL_CPU, info->cpu,
455                            COL_PID, info->pid,
456                            COL_NICE, info->nice,
457                            -1);
458        g_free (mem);
459        g_free (vmsize);
460        g_free (memres);
461        g_free (memshared);
462        g_free (memrss);
463        g_free (name);
464       
465        info->node = row;
466        info->visible = TRUE;
467}
468
469
470
471/* Kind of a hack. When a parent process is removed we remove all the info
472** pertaining to the child processes and then readd them later
473*/
474static void
475remove_children_from_tree (ProcData *procdata, GtkTreeModel *model,
476                           GtkTreeIter *parent)
477{
478        ProcInfo *child_info;
479       
480        do {
481                GtkTreeIter child;
482               
483                if (gtk_tree_model_iter_children (model, &child, parent))
484                        remove_children_from_tree (procdata, model, &child);
485               
486                gtk_tree_model_get (model, parent, COL_POINTER, &child_info, -1);
487                if (child_info) {
488                        if (procdata->selected_process == child_info)
489                                procdata->selected_process = NULL;
490                        procdata->info = g_list_remove (procdata->info, child_info);
491                        proctable_free_info (child_info);
492                }
493        } while (gtk_tree_model_iter_next (model, parent));
494               
495}
496
497void
498remove_info_from_tree (ProcInfo *info, ProcData *procdata)
499{
500        GtkTreeModel *model;
501        GtkTreeIter iter, child;
502        GtkTreePath *node;
503       
504        g_return_if_fail (info);
505       
506        if (!info->visible)
507                return;
508       
509        model = gtk_tree_view_get_model (GTK_TREE_VIEW (procdata->tree));
510        iter = info->node;
511       
512        /* remove all children from tree. They will be added again in refresh_list */
513        if (gtk_tree_model_iter_children (model, &child, &iter))
514                remove_children_from_tree (procdata, model, &child);
515       
516        if (procdata->selected_process == info)
517                procdata->selected_process = NULL;
518       
519        gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
520       
521        info->visible = FALSE; 
522               
523}
524
525static void
526update_info (ProcData *procdata, ProcInfo *info, gint pid)
527{
528        GtkTreeModel *model;
529        glibtop_proc_state procstate;
530        glibtop_proc_mem procmem;
531        glibtop_proc_uid procuid;
532        glibtop_proc_time proctime;
533        gchar *mem, *vmsize, *memres, *memshared, *memrss;
534        gint newcputime;
535        gint pcpu;
536       
537        glibtop_get_proc_state (&procstate, pid);
538        glibtop_get_proc_mem (&procmem, pid);
539        glibtop_get_proc_uid (&procuid, pid);
540        glibtop_get_proc_time (&proctime, pid);
541        newcputime = proctime.utime + proctime.stime;
542        model = gtk_tree_view_get_model (GTK_TREE_VIEW (procdata->tree));
543
544        info->mem = procmem.size;
545        info->vmsize = procmem.vsize;
546        info->memres = procmem.resident;
547        info->memshared = procmem.share;
548        info->memrss = procmem.rss;
549        if (total_time != 0)
550                pcpu = ( newcputime - info->cpu_time_last ) * 100 / total_time;
551        else
552                pcpu = 0;
553        info->cpu_time_last = newcputime;
554        info->cpu = pcpu;       
555        info->nice = procuid.nice;
556               
557        get_process_status (info, &procstate.state);
558
559        if (procdata->config.whose_process == RUNNING_PROCESSES)
560        {
561                /* process started running */
562                if (info->running && (!info->visible)) {
563                        insert_info_to_tree (info, procdata);
564                        return;
565                }
566                /* process was running but not anymore */
567                else if ((!info->running) && info->visible) {
568                        remove_info_from_tree (info, procdata);
569                        return;
570                }
571                else if (!info->running)
572                        return;
573        }
574       
575        if (info->visible) {
576                mem = get_size_string (info->mem);
577                vmsize = get_size_string (info->vmsize);
578                memres = get_size_string (info->memres);
579                memshared = get_size_string (info->memshared);
580                memrss = get_size_string (info->memrss);
581               
582                gtk_tree_store_set (GTK_TREE_STORE (model), &info->node,
583                                    COL_STATUS, info->status,
584                                    COL_MEM, mem,
585                                    COL_VMSIZE, vmsize,
586                                    COL_MEMRES, memres,
587                                    COL_MEMSHARED, memshared,
588                                    COL_MEMRSS, memrss,
589                                    COL_CPU, info->cpu,
590                                    COL_NICE, info->nice,
591                                   -1);
592                g_free (mem);
593                g_free (vmsize);
594                g_free (memres);
595                g_free (memshared);
596                g_free (memrss);
597        }
598               
599}
600
601static ProcInfo *
602get_info (ProcData *procdata, gint pid)
603{
604        ProcInfo *info = g_new0 (ProcInfo, 1);
605        ProcInfo *parentinfo = NULL;
606        glibtop_proc_state procstate;
607        glibtop_proc_time proctime;
608        glibtop_proc_mem procmem;
609        glibtop_proc_uid procuid;
610        glibtop_proc_args procargs;
611        struct passwd *pwd;
612        gchar *arguments;
613        gint newcputime, i;
614       
615       
616        glibtop_get_proc_state (&procstate, pid);
617        pwd = getpwuid (procstate.uid);
618        glibtop_get_proc_time (&proctime, pid);
619        glibtop_get_proc_mem (&procmem, pid);
620        glibtop_get_proc_uid (&procuid, pid);
621        glibtop_get_proc_time (&proctime, pid);
622        newcputime = proctime.utime + proctime.stime;
623
624        arguments = glibtop_get_proc_args (&procargs, pid, 0); 
625        get_process_name (procdata, info, procstate.cmd, arguments);
626        if (arguments)
627        {
628                for (i = 0; i < procargs.size; i++)
629                {
630                        if (!arguments[i])
631                                arguments[i] = ' ';
632                }
633                info->arguments = g_strdup (arguments);
634                glibtop_free (arguments);
635        }
636        else
637                info->arguments = g_strdup ("");
638       
639        if (pwd->pw_name)
640                info->user = g_strdup_printf ("%s", pwd->pw_name);
641        else
642                info->user = NULL;
643        info->mem = procmem.size;
644        info->vmsize = procmem.vsize;
645        info->memres = procmem.resident;
646        info->memshared = procmem.share;
647        info->memrss = procmem.rss;
648        info->cpu = 0;
649        info->pid = pid;
650        info->parent_pid = procuid.ppid;
651        info->cpu_time_last = newcputime;
652        info->nice = procuid.nice;
653        get_process_status (info, &procstate.state);
654       
655        info->pixbuf = pretty_table_get_icon (procdata->pretty_table, info->name, pid);
656       
657        parentinfo = find_parent (procdata, info->parent_pid);
658        if (parentinfo) {
659                /* Ha Ha - don't expand different threads - check to see if parent has
660                ** same name and same mem usage - I don't know if this is too smart though.
661                */
662
663                if (!g_strcasecmp (info->name, parentinfo->name) &&
664                    ( parentinfo->mem == info->mem))
665                {
666                        info->is_thread = TRUE;
667                }
668                else
669
670                        info->is_thread = FALSE;
671               
672                if (parentinfo->visible) {     
673                        info->parent_node = parentinfo->node;
674                        info->has_parent = TRUE;
675                }
676                else
677                        info->has_parent = FALSE;
678        }
679        else {
680                info->has_parent = FALSE;
681                info->is_thread = FALSE;
682        }
683       
684        info->visible = FALSE;
685       
686        return info;
687}
688
689ProcInfo *
690proctable_find_process (gint pid, gchar *name, ProcData *procdata)
691{
692
693        GList *list = procdata->info;
694       
695        while (list) {
696                ProcInfo *info = list->data;
697               
698                if (pid == info->pid)
699                        return info;
700               
701                if (name) {     
702                        if (g_strcasecmp (name, info->name) == 0)
703                                return info;
704                }
705               
706                list = g_list_next (list);
707        }
708
709        return NULL;
710}
711
712static void
713refresh_list (ProcData *data, unsigned *pid_list, gint n)
714{
715        ProcData *procdata = data;
716        GList *list = procdata->info;
717        gint i = 0;
718       
719        while (i < n)
720        {
721                ProcInfo *oldinfo;
722               
723                /* New process with higher pid than any previous one */
724                if (!list)
725                {
726                        ProcInfo *info;
727                       
728                        info = get_info (procdata, pid_list[i]);
729                        insert_info_to_tree (info, procdata);
730                        procdata->info = g_list_append (procdata->info, info);
731                       
732                        i++;
733                        continue;
734                }
735                else
736                        oldinfo = list->data;
737                /* new process */       
738                if (pid_list[i] < oldinfo->pid)
739                {
740                        ProcInfo *info;
741                       
742                        info = get_info (procdata, pid_list[i]);
743                        insert_info_to_tree (info, procdata);
744                        procdata->info = g_list_insert (procdata->info, info, i);
745                       
746                        i++;
747                }
748                /* existing process */
749                else if (pid_list[i] == oldinfo->pid)
750                {
751                        update_info (procdata, oldinfo, oldinfo->pid);
752                       
753                        list = g_list_next (list);
754                        i++;
755                }
756                /* process no longer exists */
757                else if (pid_list[i] > oldinfo->pid)
758                {               
759                        remove_info_from_tree (oldinfo, procdata);
760                        list = g_list_next (list);
761                        procdata->info = g_list_remove (procdata->info, oldinfo);
762                        proctable_free_info (oldinfo);
763                                                                                       
764                }
765        }
766       
767       
768        /* Get rid of any tasks at end of list that have ended */
769        while (list)
770        {
771                ProcInfo *oldinfo;
772                oldinfo = list->data;
773                remove_info_from_tree (oldinfo, procdata);
774                list = g_list_next (list);
775                procdata->info = g_list_remove (procdata->info, oldinfo);
776                proctable_free_info (oldinfo);
777        }
778       
779       
780
781}
782
783void
784proctable_update_list (ProcData *data)
785{
786        ProcData *procdata = data;
787        unsigned *pid_list;
788        glibtop_proclist proclist;
789        glibtop_cpu cpu;
790        gint which, arg;
791        gint n;
792       
793       
794        switch (procdata->config.whose_process) {
795        case ALL_PROCESSES:
796        case RUNNING_PROCESSES:
797        case FAVORITE_PROCESSES:
798                which = GLIBTOP_KERN_PROC_ALL;
799                arg = 0;
800                break;
801        default:
802                which = GLIBTOP_KERN_PROC_UID;
803                arg = getuid ();
804                break;
805        }
806       
807
808        pid_list = glibtop_get_proclist (&proclist, which, arg);
809        n = proclist.number;
810       
811        /* FIXME: total cpu time elapsed should be calculated on an individual basis here
812        ** should probably have a total_time_last gint in the ProcInfo structure */
813        glibtop_get_cpu (&cpu);
814        total_time = cpu.total - total_time_last;
815        total_time_last = cpu.total;
816       
817        refresh_list (procdata, pid_list, n);
818       
819        glibtop_free (pid_list);
820       
821}
822
823
824void
825proctable_update_all (ProcData *data)
826{
827        ProcData *procdata = data;
828       
829        proctable_update_list (procdata);
830       
831        if (procdata->config.show_more_info)
832                infoview_update (procdata);
833
834}
835
836void
837proctable_clear_tree (ProcData *data)
838{
839        ProcData *procdata = data;
840        GtkTreeModel *model;
841       
842        model = gtk_tree_view_get_model (GTK_TREE_VIEW (procdata->tree));
843       
844        gtk_tree_store_clear (GTK_TREE_STORE (model));
845       
846        proctable_free_table (procdata);
847       
848        update_sensitivity (procdata, FALSE);
849       
850
851}
852
853void           
854proctable_free_table (ProcData *procdata)
855{
856        GList *list = procdata->info;
857       
858        while (list)
859        {
860                ProcInfo *info = list->data;
861                proctable_free_info (info);
862                list = g_list_next (list);
863        }
864       
865        g_list_free (procdata->info);
866        procdata->info = NULL;
867       
868}
869
870void
871proctable_search_table (ProcData *procdata, gchar *string)
872{
873        GList *list = procdata->info;
874        GtkWidget *dialog;
875        GtkTreeModel *model;
876        gchar *error;
877        static gint increment = 0, index;
878        static gchar *last = NULL;
879       
880        if (!g_strcasecmp (string, ""))
881                return;
882       
883        model = gtk_tree_view_get_model (GTK_TREE_VIEW (procdata->tree));
884       
885        if (!last)
886                last = g_strdup (string);
887        else if (g_strcasecmp (string, last)) {
888                increment = 0;
889                g_free (last);
890                last = g_strdup (string);
891        }
892        else
893                increment ++;
894       
895        index = increment;
896       
897        while (list)
898        {
899                ProcInfo *info = list->data;
900                if (strstr (info->name, string) && info->visible)
901                {
902                        GtkTreePath *node = gtk_tree_model_get_path (model, &info->node);
903                       
904                        if (index == 0) {
905                                gtk_tree_view_set_cursor (GTK_TREE_VIEW (procdata->tree),
906                                                         node,
907                                                         NULL,
908                                                         FALSE);
909                                return;
910                        }
911                        else
912                                index --;
913                               
914                        gtk_tree_path_free (node);
915                }
916               
917                if (strstr (info->user, string) && info->visible)
918                {
919                        GtkTreePath *node = gtk_tree_model_get_path (model, &info->node);
920                       
921                        if (index == 0) {
922                                gtk_tree_view_set_cursor (GTK_TREE_VIEW (procdata->tree),
923                                                         node,
924                                                         NULL,
925                                                         FALSE);
926                                return;
927                        }
928                        else
929                                index --;
930                               
931                        gtk_tree_path_free (node);
932                }
933               
934                list = g_list_next (list);
935        }
936       
937        if (index == increment) {
938                error = g_strdup_printf (_("%s could not be found."), string);
939                dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
940                                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
941                                                 "%s", error, NULL);
942                gtk_dialog_run (GTK_DIALOG (dialog));
943                gtk_widget_destroy (dialog);
944                g_free (error);
945        }
946        else {
947                /* no more cases found. Start the search anew */
948                increment = -1;
949                proctable_search_table (procdata, string);
950                return;
951        }
952       
953        increment --;
954
955}
956
957       
Note: See TracBrowser for help on using the repository browser.