2
* Copyright (C) 2001 Kevin Vandersloot
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.
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.
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.
25
#include <glib/gi18n.h>
29
#include <bacon-message-connection.h>
30
#include <libgnomevfs/gnome-vfs.h>
31
#include <gconf/gconf-client.h>
33
#include <glibtop/close.h>
34
#include <glibtop/loadavg.h>
35
#include "load-graph.h"
37
#include "interface.h"
38
#include "proctable.h"
39
#include "prettytable.h"
40
#include "favorites.h"
41
#include "callbacks.h"
42
#include "smooth_refresh.h"
46
tree_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
48
ProcData *procdata = data;
49
GConfValue *value = gconf_entry_get_value (entry);
51
procdata->config.show_tree = gconf_value_get_bool (value);
52
proctable_clear_tree (procdata);
53
proctable_update_all (procdata);
58
view_as_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
60
ProcData *procdata = data;
61
GConfValue *value = gconf_entry_get_value (entry);
63
procdata->config.whose_process = gconf_value_get_int (value);
64
procdata->config.whose_process = CLAMP (procdata->config.whose_process, 0, 2);
65
proctable_clear_tree (procdata);
66
proctable_update_all (procdata);
71
warning_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
73
ProcData *procdata = data;
74
const gchar *key = gconf_entry_get_key (entry);
75
GConfValue *value = gconf_entry_get_value (entry);
77
if (g_str_equal (key, "/apps/procman/kill_dialog")) {
78
procdata->config.show_kill_warning = gconf_value_get_bool (value);
81
procdata->config.show_hide_message = gconf_value_get_bool (value);
86
timeouts_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
88
ProcData *procdata = data;
89
const gchar *key = gconf_entry_get_key (entry);
90
GConfValue *value = gconf_entry_get_value (entry);
92
if (g_str_equal (key, "/apps/procman/update_interval")) {
93
procdata->config.update_interval = gconf_value_get_int (value);
94
procdata->config.update_interval =
95
MAX (procdata->config.update_interval, 1000);
97
smooth_refresh_reset(procdata->smooth_refresh);
99
if(procdata->timeout) {
100
g_source_remove (procdata->timeout);
101
procdata->timeout = g_timeout_add (procdata->config.update_interval,
106
else if (g_str_equal (key, "/apps/procman/graph_update_interval")){
107
procdata->config.graph_update_interval = gconf_value_get_int (value);
108
procdata->config.graph_update_interval =
109
MAX (procdata->config.graph_update_interval,
111
load_graph_change_speed(procdata->cpu_graph,
112
procdata->config.graph_update_interval);
113
load_graph_change_speed(procdata->mem_graph,
114
procdata->config.graph_update_interval);
115
load_graph_change_speed(procdata->net_graph,
116
procdata->config.graph_update_interval);
118
else if (g_str_equal(key, "/apps/procman/disks_interval")) {
120
procdata->config.disks_update_interval = gconf_value_get_int (value);
121
procdata->config.disks_update_interval =
122
MAX (procdata->config.disks_update_interval, 1000);
124
if(procdata->disk_timeout) {
125
g_source_remove (procdata->disk_timeout);
126
procdata->disk_timeout = \
127
g_timeout_add (procdata->config.disks_update_interval,
133
g_assert_not_reached();
138
color_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
140
ProcData * const procdata = data;
141
const gchar *key = gconf_entry_get_key (entry);
142
GConfValue *value = gconf_entry_get_value (entry);
143
const gchar *color = gconf_value_get_string (value);
145
if (g_str_equal (key, "/apps/procman/bg_color")) {
146
gdk_color_parse (color, &procdata->config.bg_color);
147
load_graph_get_colors(procdata->cpu_graph)[0] = procdata->config.bg_color;
148
load_graph_get_colors(procdata->mem_graph)[0] = procdata->config.bg_color;
149
load_graph_get_colors(procdata->net_graph)[0] = procdata->config.bg_color;
151
else if (g_str_equal (key, "/apps/procman/frame_color")) {
152
gdk_color_parse (color, &procdata->config.frame_color);
153
load_graph_get_colors(procdata->cpu_graph)[1] = procdata->config.frame_color;
154
load_graph_get_colors(procdata->mem_graph)[1] = procdata->config.frame_color;
155
load_graph_get_colors(procdata->net_graph)[1] = procdata->config.frame_color;
157
else if (g_str_equal (key, "/apps/procman/cpu_color")) {
158
gdk_color_parse (color, &procdata->config.cpu_color[0]);
159
load_graph_get_colors(procdata->cpu_graph)[2] = procdata->config.cpu_color[0];
161
else if (g_str_has_prefix (key, "/apps/procman/cpu_color")) {
164
for (i=1;i<GLIBTOP_NCPU;i++) {
166
cpu_key = g_strdup_printf ("/apps/procman/cpu_color%d",i);
167
if (g_str_equal (key, cpu_key)) {
168
gdk_color_parse (color, &procdata->config.cpu_color[i]);
169
load_graph_get_colors(procdata->cpu_graph)[i+2] = procdata->config.cpu_color[i];
174
else if (g_str_equal (key, "/apps/procman/mem_color")) {
175
gdk_color_parse (color, &procdata->config.mem_color);
176
load_graph_get_colors(procdata->mem_graph)[2] = procdata->config.mem_color;
178
else if (g_str_equal (key, "/apps/procman/swap_color")) {
179
gdk_color_parse (color, &procdata->config.swap_color);
180
load_graph_get_colors(procdata->mem_graph)[3] = procdata->config.swap_color;
182
else if (g_str_equal (key, "/apps/procman/net_in_color")) {
183
gdk_color_parse (color, &procdata->config.net_in_color);
184
load_graph_get_colors(procdata->net_graph)[2] = procdata->config.net_in_color;
186
else if (g_str_equal (key, "/apps/procman/net_out_color")) {
187
gdk_color_parse (color, &procdata->config.net_out_color);
188
load_graph_get_colors(procdata->net_graph)[3] = procdata->config.net_out_color;
191
g_assert_not_reached();
198
show_all_fs_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
200
ProcData * const procdata = data;
201
GConfValue *value = gconf_entry_get_value (entry);
203
procdata->config.show_all_fs = gconf_value_get_bool (value);
205
cb_update_disks (data);
210
procman_data_new (GConfClient *client)
215
gint swidth, sheight;
219
pd = g_new0 (ProcData, 1);
223
pd->pids = g_hash_table_new(NULL, NULL);
224
pd->selected_process = NULL;
226
pd->blacklist = NULL;
227
pd->cpu_graph = NULL;
228
pd->mem_graph = NULL;
229
pd->net_graph = NULL;
230
pd->disk_timeout = 0;
232
/* username is usually 8 chars long
233
for caching, we create chunks of 128 chars */
234
pd->users = g_string_chunk_new(128);
235
/* push empty string */
236
g_string_chunk_insert_const(pd->users, "");
238
pd->config.width = gconf_client_get_int (client, "/apps/procman/width", NULL);
239
pd->config.height = gconf_client_get_int (client, "/apps/procman/height", NULL);
240
pd->config.show_tree = gconf_client_get_bool (client, "/apps/procman/show_tree", NULL);
241
gconf_client_notify_add (client, "/apps/procman/show_tree", tree_changed_cb,
243
pd->config.show_kill_warning = gconf_client_get_bool (client, "/apps/procman/kill_dialog",
245
gconf_client_notify_add (client, "/apps/procman/kill_dialog", warning_changed_cb,
247
pd->config.show_hide_message = gconf_client_get_bool (client, "/apps/procman/hide_message",
249
gconf_client_notify_add (client, "/apps/procman/hide_message", warning_changed_cb,
251
pd->config.update_interval = gconf_client_get_int (client, "/apps/procman/update_interval",
253
gconf_client_notify_add (client, "/apps/procman/update_interval", timeouts_changed_cb,
255
pd->config.graph_update_interval = gconf_client_get_int (client,
256
"/apps/procman/graph_update_interval",
258
gconf_client_notify_add (client, "/apps/procman/graph_update_interval", timeouts_changed_cb,
260
pd->config.disks_update_interval = gconf_client_get_int (client,
261
"/apps/procman/disks_interval",
263
gconf_client_notify_add (client, "/apps/procman/disks_interval", timeouts_changed_cb,
267
/* /apps/procman/show_all_fs */
268
pd->config.show_all_fs = gconf_client_get_bool (
269
client, "/apps/procman/show_all_fs",
271
gconf_client_notify_add
272
(client, "/apps/procman/show_all_fs",
273
show_all_fs_changed_cb, pd, NULL, NULL);
276
pd->config.whose_process = gconf_client_get_int (client, "/apps/procman/view_as", NULL);
277
gconf_client_notify_add (client, "/apps/procman/view_as", view_as_changed_cb,
279
pd->config.current_tab = gconf_client_get_int (client, "/apps/procman/current_tab", NULL);
281
color = gconf_client_get_string (client, "/apps/procman/bg_color", NULL);
283
color = g_strdup ("#000000");
284
gconf_client_notify_add (client, "/apps/procman/bg_color",
285
color_changed_cb, pd, NULL, NULL);
286
gdk_color_parse(color, &pd->config.bg_color);
289
color = gconf_client_get_string (client, "/apps/procman/frame_color", NULL);
291
color = g_strdup ("#231e89aa2805");
292
gconf_client_notify_add (client, "/apps/procman/frame_color",
293
color_changed_cb, pd, NULL, NULL);
294
gdk_color_parse(color, &pd->config.frame_color);
297
color = gconf_client_get_string (client, "/apps/procman/cpu_color", NULL);
299
color = g_strdup ("#000000a200ff");
300
gconf_client_notify_add (client, "/apps/procman/cpu_color",
301
color_changed_cb, pd, NULL, NULL);
302
gdk_color_parse(color, &pd->config.cpu_color[0]);
305
for (i=1;i<GLIBTOP_NCPU;i++) {
307
key = g_strdup_printf ("/apps/procman/cpu_color%d", i);
309
color = gconf_client_get_string (client, key, NULL);
311
color = g_strdup ("#f25915e815e8");
312
gconf_client_notify_add (client, key,
313
color_changed_cb, pd, NULL, NULL);
314
gdk_color_parse(color, &pd->config.cpu_color[i]);
318
color = gconf_client_get_string (client, "/apps/procman/mem_color", NULL);
320
color = g_strdup ("#000000ff0082");
321
gconf_client_notify_add (client, "/apps/procman/mem_color",
322
color_changed_cb, pd, NULL, NULL);
323
gdk_color_parse(color, &pd->config.mem_color);
327
color = gconf_client_get_string (client, "/apps/procman/swap_color", NULL);
329
color = g_strdup ("#00b6000000ff");
330
gconf_client_notify_add (client, "/apps/procman/swap_color",
331
color_changed_cb, pd, NULL, NULL);
332
gdk_color_parse(color, &pd->config.swap_color);
335
color = gconf_client_get_string (client, "/apps/procman/net_in_color", NULL);
337
color = g_strdup ("#000000f200f2");
338
gconf_client_notify_add (client, "/apps/procman/net_in_color",
339
color_changed_cb, pd, NULL, NULL);
340
gdk_color_parse(color, &pd->config.net_in_color);
343
color = gconf_client_get_string (client, "/apps/procman/net_out_color", NULL);
345
color = g_strdup ("#00f2000000c1");
346
gconf_client_notify_add (client, "/apps/procman/net_out_color",
347
color_changed_cb, pd, NULL, NULL);
348
gdk_color_parse(color, &pd->config.net_out_color);
351
get_blacklist (pd, client);
354
swidth = gdk_screen_width ();
355
sheight = gdk_screen_height ();
356
pd->config.width = CLAMP (pd->config.width, 50, swidth);
357
pd->config.height = CLAMP (pd->config.height, 50, sheight);
358
pd->config.update_interval = MAX (pd->config.update_interval, 1000);
359
pd->config.graph_update_interval = MAX (pd->config.graph_update_interval, 250);
360
pd->config.disks_update_interval = MAX (pd->config.disks_update_interval, 1000);
361
pd->config.whose_process = CLAMP (pd->config.whose_process, 0, 2);
362
pd->config.current_tab = CLAMP(pd->config.current_tab,
366
/* Determinie number of cpus since libgtop doesn't really tell you*/
367
pd->config.num_cpus = 0;
368
glibtop_get_cpu (&cpu);
369
pd->frequency = cpu.frequency;
371
while (i < GLIBTOP_NCPU && cpu.xcpu_total[i] != 0) {
372
pd->config.num_cpus ++;
375
if (pd->config.num_cpus == 0)
376
pd->config.num_cpus = 1;
378
pd->smooth_refresh = smooth_refresh_new(&pd->config.update_interval);
385
procman_free_data (ProcData *procdata)
388
proctable_free_table (procdata);
389
g_string_chunk_free(procdata->users);
390
g_hash_table_destroy(procdata->pids);
391
pretty_table_free (procdata->pretty_table);
392
smooth_refresh_destroy(procdata->smooth_refresh);
399
procman_get_tree_state (GConfClient *client, GtkWidget *tree, const gchar *prefix)
411
if (!gconf_client_dir_exists (client, prefix, NULL))
414
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
416
key = g_strdup_printf ("%s/sort_col", prefix);
417
sort_col = gconf_client_get_int (client, key, NULL);
420
key = g_strdup_printf ("%s/sort_order", prefix);
421
order = gconf_client_get_int (client, key, NULL);
425
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
429
columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree));
431
for(it = columns; it; it = it->next)
433
GtkTreeViewColumn *column;
434
GConfValue *value = NULL;
440
id = gtk_tree_view_column_get_sort_column_id (column);
442
key = g_strdup_printf ("%s/col_%d_width", prefix, id);
443
value = gconf_client_get (client, key, NULL);
447
width = gconf_value_get_int(value);
448
gconf_value_free (value);
450
key = g_strdup_printf ("%s/col_%d_visible", prefix, id);
451
visible = gconf_client_get_bool (client, key, NULL);
454
column = gtk_tree_view_get_column (GTK_TREE_VIEW (tree), id);
455
if(!column) continue;
456
gtk_tree_view_column_set_visible (column, visible);
458
/* ensure column is really visible */
459
width = MAX(width, 10);
460
gtk_tree_view_column_set_fixed_width(column, width);
465
if(g_str_has_suffix(prefix, "proctree") || g_str_has_suffix(prefix, "disktreenew"))
470
key = g_strdup_printf("%s/columns_order", prefix);
471
order = gconf_client_get_list(client, key, GCONF_VALUE_INT, NULL);
472
proctable_set_columns_order(GTK_TREE_VIEW(tree), order);
478
g_list_free(columns);
484
procman_save_tree_state (GConfClient *client, GtkWidget *tree, const gchar *prefix)
494
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
495
if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), &sort_col,
499
key = g_strdup_printf ("%s/sort_col", prefix);
500
gconf_client_set_int (client, key, sort_col, NULL);
503
key = g_strdup_printf ("%s/sort_order", prefix);
504
gconf_client_set_int (client, key, order, NULL);
508
columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree));
510
for(it = columns; it; it = it->next)
512
GtkTreeViewColumn *column;
519
id = gtk_tree_view_column_get_sort_column_id (column);
520
visible = gtk_tree_view_column_get_visible (column);
521
width = gtk_tree_view_column_get_width (column);
523
key = g_strdup_printf ("%s/col_%d_width", prefix, id);
524
gconf_client_set_int (client, key, width, NULL);
527
key = g_strdup_printf ("%s/col_%d_visible", prefix, id);
528
gconf_client_set_bool (client, key, visible, NULL);
532
if(g_str_has_suffix(prefix, "proctree") || g_str_has_suffix(prefix, "disktreenew"))
536
GError *error = NULL;
538
key = g_strdup_printf("%s/columns_order", prefix);
539
order = proctable_get_columns_order(GTK_TREE_VIEW(tree));
541
if(!gconf_client_set_list(client, key, GCONF_VALUE_INT, order, &error))
543
g_critical("Could not save GConf key '%s' : %s",
553
g_list_free(columns);
557
procman_save_config (ProcData *data)
559
GConfClient *client = data->client;
564
procman_save_tree_state (data->client, data->tree, "/apps/procman/proctree");
565
procman_save_tree_state (data->client, data->disk_list, "/apps/procman/disktreenew");
567
gdk_window_get_size (data->app->window, &width, &height);
568
data->config.width = width;
569
data->config.height = height;
571
gconf_client_set_int (client, "/apps/procman/width", data->config.width, NULL);
572
gconf_client_set_int (client, "/apps/procman/height", data->config.height, NULL);
573
gconf_client_set_int (client, "/apps/procman/current_tab", data->config.current_tab, NULL);
575
save_blacklist (data, client);
577
gconf_client_suggest_sync (client, NULL);
584
get_startup_timestamp ()
586
const gchar *startup_id_env;
587
gchar *startup_id = NULL;
591
/* we don't unset the env, since startup-notification
592
* may still need it */
593
startup_id_env = g_getenv ("DESKTOP_STARTUP_ID");
594
if (startup_id_env == NULL)
597
startup_id = g_strdup (startup_id_env);
599
time_str = g_strrstr (startup_id, "_TIME");
600
if (time_str == NULL)
603
/* Skip past the "_TIME" part */
606
retval = strtoul (time_str, NULL, 0);
616
cb_server (const gchar *msg, gpointer user_data)
622
window = gdk_get_default_root_window ();
624
procdata = *(ProcData**)user_data;
625
g_assert (procdata != NULL);
627
timestamp = strtoul(msg, NULL, 0);
631
/* fall back to rountripping to X */
632
timestamp = gdk_x11_get_server_time (window);
635
gdk_x11_window_set_user_time (window, timestamp);
637
gtk_window_present (GTK_WINDOW(procdata->app));
642
init_volume_monitor(ProcData *procdata)
644
GnomeVFSVolumeMonitor *mon;
645
mon = gnome_vfs_get_volume_monitor();
647
g_signal_connect(mon, "volume_mounted",
648
G_CALLBACK(cb_volume_mounted_or_unmounted), procdata);
650
g_signal_connect(mon, "volume_unmounted",
651
G_CALLBACK(cb_volume_mounted_or_unmounted), procdata);
656
main (int argc, char *argv[])
658
guint32 startup_timestamp;
659
GnomeProgram *procman;
662
BaconMessageConnection *conn;
664
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
665
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
666
textdomain (GETTEXT_PACKAGE);
668
startup_timestamp = get_startup_timestamp();
670
procman = gnome_program_init ("gnome-system-monitor", VERSION,
671
LIBGNOMEUI_MODULE, argc, argv,
672
GNOME_PARAM_APP_DATADIR,DATADIR, NULL);
674
conn = bacon_message_connection_new ("gnome-system-monitor");
675
if (!conn) g_error("Couldn't connect to gnome-system-monitor");
677
if (bacon_message_connection_get_is_server (conn))
679
bacon_message_connection_set_callback (conn, cb_server, &procdata);
685
timestamp = g_strdup_printf ("%" G_GUINT32_FORMAT, startup_timestamp);
687
bacon_message_connection_send (conn, timestamp);
689
gdk_notify_startup_complete ();
692
bacon_message_connection_free (conn);
697
gtk_window_set_default_icon_name ("utilities-system-monitor");
698
g_set_application_name(_("System Monitor"));
700
gconf_init (argc, argv, NULL);
702
client = gconf_client_get_default ();
703
gconf_client_add_dir(client, "/apps/procman", GCONF_CLIENT_PRELOAD_NONE, NULL);
708
procdata = procman_data_new (client);
709
procdata->client = client;
710
pretty_table_new (procdata);
712
create_main_window (procdata);
714
proctable_update_all (procdata);
716
init_volume_monitor (procdata);
718
g_assert(procdata->app);
720
gtk_widget_show(procdata->app);
724
procman_free_data (procdata);
727
gnome_vfs_shutdown ();