1 /* GKrellM
2 | Copyright (C) 1999-2019 Bill Wilson
3 |
4 | Author: Bill Wilson billw@gkrellm.net
5 | Latest versions might be found at: http://gkrellm.net
6 |
7 |
8 | GKrellM is free software: you can redistribute it and/or modify it
9 | under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | GKrellM is distributed in the hope that it will be useful, but WITHOUT
14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 | License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with this program. If not, see http://www.gnu.org/licenses/
20 |
21 |
22 | Additional permission under GNU GPL version 3 section 7
23 |
24 | If you modify this program, or any covered work, by linking or
25 | combining it with the OpenSSL project's OpenSSL library (or a
26 | modified version of that library), containing parts covered by
27 | the terms of the OpenSSL or SSLeay licenses, you are granted
28 | additional permission to convey the resulting work.
29 | Corresponding Source for a non-source form of such a combination
30 | shall include the source code for the parts of OpenSSL used as well
31 | as that of the covered work.
32 */
33
34 #include "gkrellm.h"
35 #include "gkrellm-private.h"
36 #include "gkrellm-sysdeps.h"
37
38
39 #define DISK_ASSIGN_BY_DEVICE 0
40 #define DISK_ASSIGN_NTH 1
41 #define DISK_ASSIGN_BY_NAME 2
42
43 #define DISK_CONFIG_KEYWORD "disk"
44
45 #define MIN_GRID_RES 10
46 #define MAX_GRID_RES 100000000
47 #define DEFAULT_GRID_RES 2000
48
49 typedef struct
50 {
51 gchar *name,
52 *default_label, /* Possibly translated name */
53 *label;
54 GtkWidget *vbox;
55 GtkWidget *enable_button;
56 GkrellmChart *chart;
57 GkrellmChartdata *read_cd,
58 *write_cd;
59 GkrellmChartconfig *chart_config;
60 GkrellmAlert *alert;
61 GtkWidget *alert_config_read_button,
62 *alert_config_write_button;
63 gboolean alert_uses_read,
64 alert_uses_write,
65 new_text_format;
66
67 GkrellmDecal *temp_decal;
68 gint save_label_position;
69
70 gint enabled;
71 gint major,
72 minor,
73 subdisk,
74 order;
75 gint new_disk;
76 gint extra_info;
77 GkrellmLauncher launch;
78 GtkWidget *launch_entry,
79 *tooltip_entry;
80 GtkWidget *launch_table;
81
82 guint64 rb,
83 wb;
84 }
85 DiskMon;
86
87
88 static void cb_alert_config(GkrellmAlert *ap, DiskMon *disk);
89 static void cb_alert_config_create(GkrellmAlert *ap, GtkWidget *vbox,
90 DiskMon *disk);
91
92
93 static GkrellmMonitor *mon_disk;
94
95 static gint n_disks;
96 static GList *disk_mon_list;
97
98
99 static DiskMon *composite_disk;
100 static gint ascent;
101 static gint style_id;
102 static gint assign_method;
103 static gboolean sys_handles_composite_reset;
104 static gboolean units_are_blocks;
105
106 static void (*read_disk_data)();
107 static gchar *(*name_from_device)();
108 static gint (*order_from_name)();
109
110
111
112 DiskMon *
lookup_disk_by_device(gint major,gint minor)113 lookup_disk_by_device(gint major, gint minor)
114 {
115 DiskMon *disk;
116 GList *list;
117
118 for (list = disk_mon_list->next; list; list = list->next)
119 {
120 disk = (DiskMon * ) list->data;
121 if (disk->major == major && disk->minor == minor)
122 return disk;
123 }
124 return NULL;
125 }
126
127 static DiskMon *
lookup_disk_by_name(const gchar * name)128 lookup_disk_by_name(const gchar *name)
129 {
130 DiskMon *disk;
131 GList *list;
132
133 for (list = disk_mon_list; list; list = list->next)
134 {
135 disk = (DiskMon * ) list->data;
136 if (!strcmp(name, disk->name))
137 return disk;
138
139 /* Pre 2.1.15 config compatibility where translated "Disk" was
140 | written into the config. XXX remove this eventually.
141 */
142 if ( (disk == composite_disk || assign_method == DISK_ASSIGN_NTH)
143 && !strcmp(name, disk->default_label))
144 return disk;
145 }
146 return NULL;
147 }
148
149 static DiskMon *
disk_new(const gchar * name,const gchar * label)150 disk_new(const gchar *name, const gchar *label)
151 {
152 DiskMon *disk;
153
154 disk = g_new0(DiskMon, 1);
155 disk->name = g_strdup(name);
156 disk->default_label = g_strdup(label);
157 disk->label = g_strdup(label);
158 disk->launch.command = g_strdup("");
159 disk->launch.tooltip_comment = g_strdup("");
160 disk->alert_uses_read = disk->alert_uses_write = TRUE;
161 disk->extra_info = TRUE;
162 return disk;
163 }
164
165 static DiskMon *
add_disk(const gchar * name,const gchar * label,gint major,gint minor,gint order)166 add_disk(const gchar *name, const gchar *label, gint major, gint minor, gint order)
167 {
168 DiskMon *disk;
169 GList *list;
170 gint i;
171
172 if (lookup_disk_by_name(name))
173 return NULL;
174 disk = disk_new(name, label);
175
176 disk->major = major;
177 disk->minor = minor;
178 disk->order = order;
179 disk->subdisk = -1;
180 if (order >= 0)
181 {
182 ++disk->order; /* Skip the composite disk */
183 for (i = 1, list = disk_mon_list->next; list; list = list->next, ++i)
184 if (disk->order < ((DiskMon *) list->data)->order)
185 break;
186 disk_mon_list = g_list_insert(disk_mon_list, disk, i);
187 }
188 else
189 disk_mon_list = g_list_append(disk_mon_list, disk);
190 ++n_disks;
191 return disk;
192 }
193
194 static DiskMon *
add_subdisk(const gchar * subdisk_name,const gchar * disk_name,gint subdisk)195 add_subdisk(const gchar *subdisk_name, const gchar *disk_name, gint subdisk)
196 {
197 DiskMon *disk, *sdisk;
198 GList *list = NULL;
199
200 for (list = disk_mon_list->next; list; list = list->next)
201 {
202 disk = (DiskMon * ) list->data;
203 if (!strcmp(disk_name, disk->name))
204 break;
205 }
206 if (!list)
207 return NULL;
208 sdisk = disk_new(subdisk_name, subdisk_name);
209 sdisk->order = disk->order;
210 sdisk->subdisk = subdisk;
211 for (list = list->next; list; list = list->next)
212 {
213 disk = (DiskMon * ) list->data;
214 if (disk->subdisk == -1 || disk->subdisk > subdisk)
215 break;
216 }
217 disk_mon_list = g_list_insert_before(disk_mon_list, list, sdisk);
218 ++n_disks;
219 return sdisk;
220 }
221
222 static void
disk_assign_data(DiskMon * disk,guint64 rb,guint64 wb,gboolean virtual)223 disk_assign_data(DiskMon *disk, guint64 rb, guint64 wb, gboolean virtual)
224 {
225 if (!disk)
226 return;
227 disk->rb = rb;
228 disk->wb = wb;
229
230 /* Add data to composite disk if this is not a subdisk (partition) and
231 | not a virtual disk (eg /dev/mdX software RAID multi-disk).
232 */
233 if (disk->subdisk == -1 && !virtual)
234 {
235 composite_disk->rb += rb;
236 composite_disk->wb += wb;
237 }
238 }
239
240 static gboolean
setup_disk_interface(void)241 setup_disk_interface(void)
242 {
243 if (!read_disk_data && !_GK.client_mode && gkrellm_sys_disk_init())
244 {
245 read_disk_data = gkrellm_sys_disk_read_data;
246 name_from_device = gkrellm_sys_disk_name_from_device;
247 order_from_name = gkrellm_sys_disk_order_from_name;
248 }
249 /* Get a read in so I'll know the assign_method before config is loaded.
250 */
251 if (read_disk_data)
252 (*read_disk_data)();
253 return read_disk_data ? TRUE : FALSE;
254 }
255
256 /* ------------- Disk monitor to system dependent interface ------------- */
257 void
gkrellm_disk_client_divert(void (* read_func)(),gchar * (* name_from_device_func)(),gint (* order_from_name_func)())258 gkrellm_disk_client_divert(void (*read_func)(),
259 gchar *(*name_from_device_func)(), gint (*order_from_name_func)())
260 {
261 read_disk_data = read_func;
262 name_from_device = name_from_device_func;
263 order_from_name = order_from_name_func;
264 }
265
266 void
gkrellm_disk_reset_composite(void)267 gkrellm_disk_reset_composite(void)
268 {
269 composite_disk->rb = 0;
270 composite_disk->wb = 0;
271 sys_handles_composite_reset = TRUE;
272 }
273
274 void
gkrellm_disk_units_are_blocks(void)275 gkrellm_disk_units_are_blocks(void)
276 {
277 units_are_blocks = TRUE;
278 }
279
280 void
gkrellm_disk_add_by_name(const gchar * name,const gchar * label)281 gkrellm_disk_add_by_name(const gchar *name, const gchar *label)
282 {
283 gint order = -1;
284
285 assign_method = DISK_ASSIGN_BY_NAME;
286 if (NULL == name) // Cannot add disk without a name
287 return;
288 if (order_from_name) // get optional order from sysdep-code
289 order = (*order_from_name)(name);
290 if (NULL != label) // label is optional and might be NULL
291 add_disk(name, label, 0, 0, order);
292 else
293 add_disk(name, name, 0, 0, order);
294 }
295
296 void
gkrellm_disk_assign_data_by_device(gint device_number,gint unit_number,guint64 rb,guint64 wb,gboolean virtual)297 gkrellm_disk_assign_data_by_device(gint device_number, gint unit_number,
298 guint64 rb, guint64 wb, gboolean virtual)
299 {
300 DiskMon *disk;
301 gchar *name;
302 gint order = -1;
303
304 assign_method = DISK_ASSIGN_BY_DEVICE;
305 disk = lookup_disk_by_device(device_number, unit_number);
306 if (!disk && name_from_device)
307 {
308 name = (*name_from_device)(device_number, unit_number, &order);
309 if (name)
310 disk = add_disk(name, name, device_number, unit_number, order);
311 }
312 disk_assign_data(disk, rb, wb, virtual);
313 }
314
315 void
gkrellm_disk_assign_data_nth(gint n,guint64 rb,guint64 wb,gboolean virtual)316 gkrellm_disk_assign_data_nth(gint n, guint64 rb, guint64 wb, gboolean virtual)
317 {
318 DiskMon *disk;
319 gchar name[32], label[32];
320
321 assign_method = DISK_ASSIGN_NTH;
322 if (n < n_disks)
323 disk = (DiskMon *) g_list_nth_data(disk_mon_list, n + 1);
324 else
325 {
326 snprintf(name, sizeof(name), "%s%c", "Disk", 'A' + n);
327 snprintf(label, sizeof(label), "%s%c", _("Disk"), 'A' + n);
328 disk = add_disk(name, label, 0, 0, n);
329 }
330 disk_assign_data(disk, rb, wb, virtual);
331 }
332
333 void
gkrellm_disk_assign_data_by_name(gchar * name,guint64 rb,guint64 wb,gboolean virtual)334 gkrellm_disk_assign_data_by_name(gchar *name, guint64 rb, guint64 wb,
335 gboolean virtual)
336 {
337 DiskMon *disk;
338 gint order = -1;
339
340 assign_method = DISK_ASSIGN_BY_NAME;
341 if (!name)
342 return;
343 disk = lookup_disk_by_name(name);
344 if (!disk)
345 {
346 if (order_from_name)
347 order = (*order_from_name)(name);
348 disk = add_disk(name, name, 0, 0, order);
349 }
350 disk_assign_data(disk, rb, wb, virtual);
351 }
352
353 void
gkrellm_disk_subdisk_assign_data_by_name(gchar * subdisk_name,gchar * disk_name,guint64 rb,guint64 wb)354 gkrellm_disk_subdisk_assign_data_by_name(gchar *subdisk_name, gchar *disk_name,
355 guint64 rb, guint64 wb)
356 {
357 DiskMon *disk;
358 gchar *s, *endptr;
359 gint subdisk;
360
361 assign_method = DISK_ASSIGN_BY_NAME;
362 if (!subdisk_name || !disk_name)
363 return;
364 disk = lookup_disk_by_name(subdisk_name);
365 if (!disk)
366 {
367 /* A subdisk name is expected to be the disk_name with a number string
368 | appended. Eg. "hda1" is a subdisk_name of disk_name "hda"
369 */
370 s = subdisk_name + strlen(disk_name);
371 if (*s == 'p') /* except mmcblkN SD disks have "pN" partition numbers */
372 ++s;
373 subdisk = strtol(s, &endptr, 0);
374 if (!*s || *endptr)
375 return;
376 disk = add_subdisk(subdisk_name, disk_name, subdisk);
377 }
378 disk_assign_data(disk, rb, wb, FALSE);
379 }
380
381
382 /* ----------- End of Disk monitor to system dependent interface ---------- */
383
384
385 static GkrellmSizeAbbrev disk_blocks_abbrev[] =
386 {
387 { KB_SIZE(1), 1, "%.0f" },
388 { KB_SIZE(20), KB_SIZE(1), "%.1fK" },
389 { MB_SIZE(1), KB_SIZE(1), "%.0fK" },
390 { MB_SIZE(20), MB_SIZE(1), "%.1fM" },
391 { MB_SIZE(50), MB_SIZE(1), "%.0fM" }
392 };
393
394
395 static gchar *text_format,
396 *text_format_locale;
397
398 static void
format_disk_data(DiskMon * disk,gchar * src_string,gchar * buf,gint size)399 format_disk_data(DiskMon *disk, gchar *src_string, gchar *buf, gint size)
400 {
401 GkrellmChart *cp;
402 gchar c, *s;
403 size_t tbl_size;
404 gint len, r_blocks, w_blocks, blocks;
405
406 if (!buf || size < 1)
407 return;
408 --size;
409 *buf = '\0';
410 if (!src_string)
411 return;
412 cp = disk->chart;
413 r_blocks = gkrellm_get_current_chartdata(disk->read_cd);
414 w_blocks = gkrellm_get_current_chartdata(disk->write_cd);
415 tbl_size = sizeof(disk_blocks_abbrev) / sizeof(GkrellmSizeAbbrev);
416 for (s = src_string; *s != '\0' && size > 0; ++s)
417 {
418 len = 1;
419 if (*s == '$' && *(s + 1) != '\0')
420 {
421 blocks = -1;
422 if ((c = *(s + 1)) == 'T')
423 blocks = r_blocks + w_blocks;
424 else if (c == 'M')
425 blocks = gkrellm_get_chart_scalemax(cp);
426 else if (c == 'r')
427 blocks = r_blocks;
428 else if (c == 'w')
429 blocks = w_blocks;
430 else if (c == 'L')
431 len = snprintf(buf, size, "%s", disk->name);
432 else if (c == 'H')
433 len = snprintf(buf, size, "%s", gkrellm_sys_get_host_name());
434 else
435 {
436 *buf = *s;
437 if (size > 1)
438 {
439 *(buf + 1) = *(s + 1);
440 ++len;
441 }
442 }
443 if (blocks >= 0)
444 len = gkrellm_format_size_abbrev(buf, size, (gfloat) blocks,
445 &disk_blocks_abbrev[0], tbl_size);
446 ++s;
447 }
448 else
449 *buf = *s;
450 size -= len;
451 buf += len;
452 }
453 *buf = '\0';
454 }
455
456 static void
draw_disk_extra(DiskMon * disk)457 draw_disk_extra(DiskMon *disk)
458 {
459 gchar buf[128];
460
461 if (!disk->chart || !disk->extra_info)
462 return;
463 format_disk_data(disk, text_format_locale, buf, sizeof(buf));
464 if (!disk->new_text_format)
465 gkrellm_chart_reuse_text_format(disk->chart);
466 disk->new_text_format = FALSE;
467 gkrellm_draw_chart_text(disk->chart, style_id, buf);
468 }
469
470 static void
cb_command_process(GkrellmAlert * alert,gchar * src,gchar * dst,gint len,DiskMon * disk)471 cb_command_process(GkrellmAlert *alert, gchar *src, gchar *dst, gint len,
472 DiskMon *disk)
473 {
474 if (disk->chart)
475 format_disk_data(disk, src, dst, len);
476 }
477
478 static void
draw_disk_chart(DiskMon * disk)479 draw_disk_chart(DiskMon *disk)
480 {
481 gkrellm_draw_chartdata(disk->chart);
482 draw_disk_extra(disk);
483 gkrellm_draw_chart_to_screen(disk->chart);
484 }
485
486 static void
cb_disk_temp_alert_trigger(GkrellmAlert * alert,DiskMon * disk)487 cb_disk_temp_alert_trigger(GkrellmAlert *alert, DiskMon *disk)
488 {
489 GkrellmAlertdecal *ad;
490 GkrellmDecal *d;
491
492 if (alert && disk && disk->chart)
493 {
494 ad = &alert->ad;
495 d = disk->temp_decal;
496 if (d)
497 {
498 ad->x = d->x - 1;
499 ad->y = d->y - 1;
500 ad->w = d->w + 2;
501 ad->h = d->h + 2;
502 gkrellm_render_default_alert_decal(alert);
503 }
504 alert->panel = disk->chart->panel;
505 }
506 }
507
508 gboolean
gkrellm_disk_temperature_display(gpointer sr,gchar * id_name,gfloat t,gchar units)509 gkrellm_disk_temperature_display(gpointer sr, gchar *id_name, gfloat t,
510 gchar units)
511 {
512 GList *list;
513 DiskMon *disk;
514 GkrellmPanel *p;
515 GkrellmDecal *decal;
516 gchar *disk_name;
517 gint len;
518 gboolean display_done = FALSE, display_possible = FALSE;
519
520 if ((disk_name = strrchr(id_name, '/')) != NULL)
521 ++disk_name;
522 else
523 disk_name = id_name;
524
525 len = strlen(disk_name);
526 for (list = disk_mon_list; list; list = list->next)
527 {
528 disk = (DiskMon *) list->data;
529 if ( strncmp(disk->name, disk_name, len)
530 || (disk->name[len] != '\0' && !isdigit((unsigned char)disk->name[len]))
531 )
532 continue;
533 if (!disk->enabled || !disk->chart || !disk->chart->panel->decal_list)
534 {
535 display_possible |= disk->enabled; /* Not created or rebuilding */
536 continue;
537 }
538 decal = disk->temp_decal;
539 p = disk->chart->panel;
540 if (display_done)
541 {
542 if (gkrellm_is_decal_visible(decal))
543 {
544 gkrellm_make_decal_invisible(p, decal);
545 p->label->position = disk->save_label_position;
546 gkrellm_draw_panel_label(p);
547 gkrellm_draw_panel_layers(p);
548 }
549 continue;
550 }
551 if (!gkrellm_is_decal_visible(decal))
552 {
553 gkrellm_make_decal_visible(p, decal);
554 disk->save_label_position = p->label->position;
555 if (p->label->position >= 0)
556 {
557 p->label->position = 0;
558 gkrellm_draw_panel_label(p);
559 }
560 gkrellm_sensor_alert_connect(sr, cb_disk_temp_alert_trigger, disk);
561 }
562 gkrellm_sensor_draw_temperature_decal(p, decal, t, units);
563 gkrellm_draw_panel_layers(p);
564 display_done = TRUE;
565 }
566 return (display_possible || display_done);
567 }
568
569 void
gkrellm_disk_temperature_remove(gchar * id_name)570 gkrellm_disk_temperature_remove(gchar *id_name)
571 {
572 GList *list;
573 DiskMon *disk;
574 GkrellmPanel *p;
575 GkrellmDecal *decal;
576 gchar *disk_name;
577 gint len;
578
579 if ((disk_name = strrchr(id_name, '/')) != NULL)
580 ++disk_name;
581 else
582 disk_name = id_name;
583
584 len = strlen(disk_name);
585 for (list = disk_mon_list; list; list = list->next)
586 {
587 disk = (DiskMon *) list->data;
588 if (!disk->chart)
589 continue;
590 if ( strncmp(disk->name, disk_name, len)
591 || (disk->name[len] != '\0' && !isdigit((unsigned char)disk->name[len]))
592 )
593 continue;
594 p = disk->chart->panel;
595 decal = disk->temp_decal;
596 if (gkrellm_is_decal_visible(decal))
597 {
598 gkrellm_make_decal_invisible(p, decal);
599 p->label->position = disk->save_label_position;
600 gkrellm_draw_panel_label(p);
601 gkrellm_draw_panel_layers(p);
602 }
603 }
604 }
605
606
607 static void
update_disk(void)608 update_disk(void)
609 {
610 GList *list;
611 DiskMon *disk;
612 GkrellmChart *cp;
613 gint bytes;
614
615 if (!sys_handles_composite_reset)
616 {
617 composite_disk->rb = 0;
618 composite_disk->wb = 0;
619 }
620 (*read_disk_data)();
621 if (n_disks == 0)
622 return;
623
624 for (list = disk_mon_list; list; list = list->next)
625 {
626 disk = (DiskMon *) list->data;
627 if ((cp = disk->chart) == NULL) /* or disk->enabled FALSE */
628 continue;
629 if (GK.second_tick)
630 {
631 gkrellm_store_chartdata(cp, 0,
632 (gulong) disk->wb, (gulong) disk->rb);
633 if (disk->alert)
634 {
635 bytes = 0;
636 if (disk->alert_uses_read)
637 bytes += gkrellm_get_current_chartdata(disk->read_cd);
638 if (disk->alert_uses_write)
639 bytes += gkrellm_get_current_chartdata(disk->write_cd);
640 gkrellm_check_alert(disk->alert, bytes);
641 }
642 gkrellm_panel_label_on_top_of_decals(cp->panel,
643 gkrellm_alert_decal_visible(disk->alert));
644 draw_disk_chart(disk);
645 }
646 gkrellm_update_krell(cp->panel, KRELL(cp->panel),
647 (gulong) (disk->wb + disk->rb));
648 gkrellm_draw_panel_layers(cp->panel);
649 }
650 }
651
652
653 static gint
disk_expose_event(GtkWidget * widget,GdkEventExpose * ev)654 disk_expose_event(GtkWidget *widget, GdkEventExpose *ev)
655 {
656 GList *list;
657 GkrellmChart *cp;
658 GdkPixmap *pixmap = NULL;
659
660 for (list = disk_mon_list; list; list = list->next)
661 {
662 if ((cp = ((DiskMon *) list->data)->chart) == NULL)
663 continue;
664 if (widget == cp->drawing_area)
665 pixmap = cp->pixmap;
666 else if (widget == cp->panel->drawing_area)
667 pixmap = cp->panel->pixmap;
668 if (pixmap)
669 {
670 gdk_draw_drawable(widget->window, gkrellm_draw_GC(1), pixmap,
671 ev->area.x, ev->area.y, ev->area.x, ev->area.y,
672 ev->area.width, ev->area.height);
673 break;
674 }
675 }
676 return FALSE;
677 }
678
679 static gint
cb_disk_extra(GtkWidget * widget,GdkEventButton * ev)680 cb_disk_extra(GtkWidget *widget, GdkEventButton *ev)
681 {
682 GList *list;
683 DiskMon *disk;
684
685 for (list = disk_mon_list; list; list = list->next)
686 {
687 disk = (DiskMon *) list->data;
688 if (!disk->enabled || widget != disk->chart->drawing_area)
689 continue;
690 if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS)
691 {
692 disk->extra_info = !disk->extra_info;
693 draw_disk_chart(disk);
694 gkrellm_config_modified();
695 }
696 else if ( ev->button == 3
697 || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)
698 )
699 gkrellm_chartconfig_window_create(disk->chart);
700 break;
701 }
702 return FALSE;
703 }
704
705 static void
setup_disk_scaling(GkrellmChartconfig * cf,GkrellmChart * cp)706 setup_disk_scaling(GkrellmChartconfig *cf, GkrellmChart *cp)
707 {
708 gint grids, res;
709
710 grids = gkrellm_get_chartconfig_fixed_grids(cf);
711 if (!grids)
712 grids = FULL_SCALE_GRIDS;
713 res = gkrellm_get_chartconfig_grid_resolution(cf);
714
715 KRELL(cp->panel)->full_scale = res * grids / gkrellm_update_HZ();
716 }
717
718 /* Destroy everything in a DiskMon structure except for the vbox which
719 | is preserved so disk ordering will be maintained. Compare this to
720 | destroying an InetMon where really everything is destroyed including
721 | the InetMon structure. Here the DiskMon structure is not destroyed.
722 */
723 static void
destroy_disk_monitor(DiskMon * disk)724 destroy_disk_monitor(DiskMon *disk)
725 {
726 if (disk->launch_table)
727 gtk_widget_destroy(disk->launch_table);
728 disk->launch_table = NULL;
729 if (disk->launch.button)
730 gkrellm_destroy_button(disk->launch.button);
731 disk->launch.button = NULL;
732 gkrellm_dup_string(&disk->launch.command, "");
733 gkrellm_dup_string(&disk->launch.tooltip_comment, "");
734 gkrellm_chart_destroy(disk->chart);
735 disk->chart = NULL;
736 disk->enabled = FALSE;
737 }
738
739 static gint
cb_panel_press(GtkWidget * widget,GdkEventButton * ev)740 cb_panel_press(GtkWidget *widget, GdkEventButton *ev)
741 {
742 if (ev->button == 3)
743 gkrellm_open_config_window(mon_disk);
744 return FALSE;
745 }
746
747 static void
create_disk_monitor(DiskMon * disk,gint first_create)748 create_disk_monitor(DiskMon *disk, gint first_create)
749 {
750 GkrellmChart *cp;
751 GkrellmPanel *p;
752 GkrellmDecal *d;
753 GkrellmStyle *style;
754 GkrellmTextstyle *ts;
755 GkrellmMargin *m;
756
757 if (first_create)
758 {
759 disk->chart = gkrellm_chart_new0();
760 disk->chart->panel = gkrellm_panel_new0();
761 }
762 cp = disk->chart;
763 p = cp->panel;
764
765 style = gkrellm_panel_style(style_id);
766 gkrellm_create_krell(p, gkrellm_krell_panel_piximage(style_id), style);
767
768 gkrellm_chart_create(disk->vbox, mon_disk, cp, &disk->chart_config);
769 disk->write_cd = gkrellm_add_default_chartdata(cp, _("Write bytes"));
770 disk->read_cd = gkrellm_add_default_chartdata(cp, _("Read bytes"));
771 gkrellm_set_draw_chart_function(cp, draw_disk_chart, disk);
772
773 gkrellm_chartconfig_fixed_grids_connect(cp->config,
774 setup_disk_scaling, cp);
775 gkrellm_chartconfig_grid_resolution_connect(cp->config,
776 setup_disk_scaling, cp);
777 gkrellm_chartconfig_grid_resolution_adjustment(cp->config, TRUE,
778 0, (gfloat) MIN_GRID_RES, (gfloat) MAX_GRID_RES, 0, 0, 0, 0);
779 gkrellm_chartconfig_grid_resolution_label(cp->config,
780 units_are_blocks ?
781 _("Disk I/O blocks per sec") : _("Disk I/O bytes per sec"));
782 if (gkrellm_get_chartconfig_grid_resolution(cp->config) < MIN_GRID_RES)
783 gkrellm_set_chartconfig_grid_resolution(cp->config, DEFAULT_GRID_RES);
784 gkrellm_alloc_chartdata(cp);
785
786 setup_disk_scaling(cp->config, cp);
787
788 ts = gkrellm_panel_alt_textstyle(style_id);
789 disk->temp_decal = gkrellm_create_decal_text(p, "188.8F",
790 ts, style, -1, -1, 0);
791 gkrellm_make_decal_invisible(p, disk->temp_decal);
792
793 gkrellm_panel_configure(p, disk->label, style);
794 gkrellm_panel_create(disk->vbox, mon_disk, p);
795 disk->enabled = TRUE;
796 disk->new_text_format = TRUE;
797
798 /* Position the temp decal to right edge and vertically align it
799 | wrt the label.
800 */
801 d = disk->temp_decal;
802 m = gkrellm_get_style_margins(style);
803 gkrellm_move_decal(p, d,
804 gkrellm_chart_width() - m->right - d->w,
805 m->top + (p->label->height - d->h + 1) / 2);
806
807 if (first_create)
808 {
809 g_signal_connect(G_OBJECT(cp->drawing_area), "expose_event",
810 G_CALLBACK(disk_expose_event), NULL);
811 g_signal_connect(G_OBJECT (p->drawing_area), "expose_event",
812 G_CALLBACK(disk_expose_event), NULL);
813
814 g_signal_connect(G_OBJECT(cp->drawing_area), "button_press_event",
815 G_CALLBACK(cb_disk_extra), NULL);
816 g_signal_connect(G_OBJECT(p->drawing_area), "button_press_event",
817 G_CALLBACK(cb_panel_press), NULL);
818 }
819 else
820 draw_disk_chart(disk);
821
822 gkrellm_configure_tooltip(p, &disk->launch);
823 if (*(disk->launch.command) != '\0')
824 disk->launch.button = gkrellm_put_label_in_panel_button(p,
825 gkrellm_launch_button_cb, &disk->launch, disk->launch.pad);
826 }
827
828
829 static GtkWidget *disk_vbox;
830
831 static void
create_disk(GtkWidget * vbox,gint first_create)832 create_disk(GtkWidget *vbox, gint first_create)
833 {
834 GList *list;
835 DiskMon *disk;
836 gboolean any = FALSE;
837
838 ascent = 0;
839 disk_vbox = vbox;
840 for (list = disk_mon_list; list; list = list->next)
841 {
842 disk = (DiskMon *) list->data;
843 if (first_create)
844 {
845 disk->vbox = gtk_vbox_new(FALSE, 0);
846 gtk_box_pack_start(GTK_BOX(vbox), disk->vbox, FALSE, FALSE, 0);
847 gtk_widget_show(disk->vbox);
848 }
849 gkrellm_setup_launcher(NULL, &disk->launch, CHART_PANEL_TYPE, 4);
850 if (disk->enabled)
851 {
852 create_disk_monitor(disk, first_create);
853 any = TRUE;
854 }
855 }
856 if (any)
857 gkrellm_spacers_show(mon_disk);
858 else
859 gkrellm_spacers_hide(mon_disk);
860 }
861
862 /* Kernel 2.4 will not show a disk until it has I/O, and some systems
863 | may dynamically add a drive.
864 */
865 static void
check_for_new_disks(void)866 check_for_new_disks(void)
867 {
868 GList *list;
869 DiskMon *disk;
870
871 for (list = disk_mon_list; list; list = list->next)
872 {
873 disk = (DiskMon *) list->data;
874 if (disk->vbox == NULL)
875 {
876 disk->vbox = gtk_vbox_new(FALSE, 0);
877 gtk_box_pack_start(GTK_BOX(disk_vbox), disk->vbox, FALSE, FALSE,0);
878 gtk_widget_show(disk->vbox);
879 gkrellm_setup_launcher(NULL, &disk->launch, CHART_PANEL_TYPE, 4);
880 }
881 }
882 }
883
884 static void
cb_alert_trigger(GkrellmAlert * alert,DiskMon * disk)885 cb_alert_trigger(GkrellmAlert *alert, DiskMon *disk)
886 {
887 /* Full panel alert, default decal.
888 */
889 alert->panel = disk->chart->panel;
890 }
891
892
893 static void
create_alert(DiskMon * disk)894 create_alert(DiskMon *disk)
895 {
896 disk->alert = gkrellm_alert_create(NULL, disk->name,
897 _("Bytes per second"),
898 TRUE, FALSE, TRUE,
899 1e9, 1000, 1000, 10000, 0);
900 gkrellm_alert_delay_config(disk->alert, 1, 60 * 180, 0);
901
902 gkrellm_alert_trigger_connect(disk->alert, cb_alert_trigger, disk);
903 gkrellm_alert_config_connect(disk->alert, cb_alert_config, disk);
904 gkrellm_alert_config_create_connect(disk->alert,
905 cb_alert_config_create, disk);
906 gkrellm_alert_command_process_connect(disk->alert,
907 cb_command_process, disk);
908 }
909
910 static gboolean
any_enabled_subdisks(GList * dlist)911 any_enabled_subdisks(GList *dlist)
912 {
913 GList *list;
914 DiskMon *disk;
915
916 for (list = dlist; list; list = list->next)
917 {
918 disk = (DiskMon *) list->data;
919 if (disk->subdisk == -1)
920 break;
921 if (disk->enabled)
922 return TRUE;
923 }
924 return FALSE;
925 }
926
927 static void
save_disk_config(FILE * f)928 save_disk_config(FILE *f)
929 {
930 GList *list;
931 DiskMon *disk;
932 gboolean have_enabled_subdisks;
933
934 if (n_disks == 0)
935 return;
936 fprintf(f, "%s assign_method %d\n", DISK_CONFIG_KEYWORD, assign_method);
937 for (list = disk_mon_list; list; list = list->next)
938 {
939 disk = (DiskMon *) list->data;
940
941 /* To deal with possible disk hardware/partition changes at next load
942 | of the config, record if any subdisks are enabled to determine if
943 | a disk saved into the config here should be artificially created
944 | should it not be present at next gkrellm startup.
945 */
946 have_enabled_subdisks = (disk->subdisk == -1) ?
947 any_enabled_subdisks(list->next) : FALSE;
948
949 fprintf(f, "%s device %s %d %d %d %d %d %d %d %s\n",
950 DISK_CONFIG_KEYWORD,
951 disk->name, disk->major, disk->minor, disk->order,
952 disk->enabled, disk->extra_info, disk->subdisk,
953 have_enabled_subdisks, disk->label);
954 if (*(disk->launch.command) != '\0')
955 fprintf(f, "%s launch %s %s\n", DISK_CONFIG_KEYWORD,
956 disk->name, disk->launch.command);
957 if (*(disk->launch.tooltip_comment) != '\0')
958 fprintf(f, "%s tooltip_comment %s %s\n", DISK_CONFIG_KEYWORD,
959 disk->name, disk->launch.tooltip_comment);
960 gkrellm_save_chartconfig(f, disk->chart_config,
961 DISK_CONFIG_KEYWORD, disk->name);
962 if (disk->alert && disk->enabled)
963 {
964 gkrellm_save_alertconfig(f, disk->alert,
965 DISK_CONFIG_KEYWORD, disk->name);
966 fprintf(f, "%s extra_alert_config %s %d %d\n", DISK_CONFIG_KEYWORD,
967 disk->name,
968 disk->alert_uses_read, disk->alert_uses_write);
969 }
970 }
971 fprintf(f, "%s text_format %s\n", DISK_CONFIG_KEYWORD, text_format);
972 }
973
974 static void
load_disk_config(gchar * arg)975 load_disk_config(gchar *arg)
976 {
977 DiskMon *disk = NULL;
978 gchar config[32], item[CFG_BUFSIZE],
979 name[CFG_BUFSIZE], item1[CFG_BUFSIZE], disk_label[64];
980 gint major, minor, enabled, extra, order, subdisk = -1;
981 gint n;
982 gboolean enabled_subdisks = TRUE;
983 static gchar *parent;
984 static gint config_assign_method;
985
986 n = sscanf(arg, "%31s %[^\n]", config, item);
987 if (n == 2)
988 {
989 if (!strcmp(config, "text_format"))
990 gkrellm_locale_dup_string(&text_format, item, &text_format_locale);
991 else if (!strcmp(config, "assign_method"))
992 sscanf(item, "%d", &config_assign_method);
993 else if (sscanf(item, "%s %[^\n]", name, item1) == 2)
994 disk = lookup_disk_by_name(name);
995
996 if (!strcmp(config, "device"))
997 {
998 /* Disk config can be invalid (different disk naming scheme)
999 | if user changes kernel version.
1000 */
1001 if ( config_assign_method == assign_method
1002 && (n = sscanf(item1, "%d %d %d %d %d %d %d %63[^\n]",
1003 &major, &minor, &order,
1004 &enabled, &extra,
1005 &subdisk, &enabled_subdisks, disk_label)) >= 5
1006 )
1007 {
1008 /* A disk in the config may not have been found in the above
1009 | lookup because of removable drives or hardware/partition
1010 | changes since last gkrellm run.
1011 | Also Linux <= 2.4 may be getting disk stats from /proc/stat
1012 | where disks won't appear until they have I/O.
1013 | So, artificially create these not present disks if they
1014 | were previously enabled.
1015 */
1016 if (subdisk == -1)
1017 gkrellm_dup_string(&parent, name);
1018 if ( !disk && subdisk == -1
1019 && (enabled || enabled_subdisks)
1020 )
1021 disk = add_disk(name, name, major, minor, order - 1);
1022 else if (!disk && subdisk >= 0 && enabled)
1023 disk = add_subdisk(name, parent, subdisk);
1024 if (disk)
1025 {
1026 disk->enabled = enabled;
1027 disk->extra_info = extra;
1028 if (n >= 8)
1029 gkrellm_dup_string(&disk->label, disk_label);
1030 }
1031 }
1032 return;
1033 }
1034 if (!disk)
1035 return;
1036 if (!strcmp(config, GKRELLM_CHARTCONFIG_KEYWORD))
1037 gkrellm_load_chartconfig(&disk->chart_config, item1, 2);
1038 else if (!strcmp(config, GKRELLM_ALERTCONFIG_KEYWORD))
1039 {
1040 if (!disk->alert)
1041 create_alert(disk);
1042 gkrellm_load_alertconfig(&disk->alert, item1);
1043 }
1044 else if (!strcmp(config, "extra_alert_config"))
1045 sscanf(item1, "%d %d",
1046 &disk->alert_uses_read, &disk->alert_uses_write);
1047 else if (!strcmp(config, "launch"))
1048 disk->launch.command = g_strdup(item1);
1049 else if (!strcmp(config, "tooltip_comment"))
1050 disk->launch.tooltip_comment = g_strdup(item1);
1051 }
1052 }
1053
1054
1055 /* -------------------------------------------------------------------- */
1056
1057 enum
1058 {
1059 NAME_COLUMN,
1060 ENABLE_COLUMN,
1061 LABEL_COLUMN,
1062 DISK_COLUMN,
1063 VISIBLE_COLUMN,
1064 IMAGE_COLUMN,
1065 N_COLUMNS
1066 };
1067
1068 static GtkTreeModel *disk_model;
1069 static GtkTreeView *treeview;
1070
1071 static GtkTreeRowReference *row_reference;
1072 static GtkTreeSelection *selection;
1073
1074 static GtkWidget *launch_vbox,
1075 *text_format_combo_box;
1076
1077 static GtkWidget *alert_button;
1078
1079
1080
1081 static GtkTreeModel *
create_model(void)1082 create_model(void)
1083 {
1084 GtkTreeStore *tree;
1085 GtkTreeIter iter, citer;
1086 GList *list, *clist;
1087 DiskMon *disk;
1088
1089 tree = gtk_tree_store_new(N_COLUMNS,
1090 G_TYPE_STRING,
1091 G_TYPE_BOOLEAN,
1092 G_TYPE_STRING,
1093 G_TYPE_POINTER,
1094 G_TYPE_BOOLEAN,
1095 GDK_TYPE_PIXBUF);
1096 for (list = disk_mon_list; list; )
1097 {
1098 disk = (DiskMon *) list->data;
1099 gtk_tree_store_append(tree, &iter, NULL);
1100 if (list == disk_mon_list)
1101 gtk_tree_store_set(tree, &iter,
1102 NAME_COLUMN, _("Composite chart"),
1103 ENABLE_COLUMN, disk->enabled,
1104 LABEL_COLUMN, disk->label,
1105 DISK_COLUMN, disk,
1106 VISIBLE_COLUMN, TRUE,
1107 -1);
1108 else
1109 {
1110 gtk_tree_store_set(tree, &iter,
1111 NAME_COLUMN, disk->default_label,
1112 ENABLE_COLUMN, disk->enabled,
1113 LABEL_COLUMN, disk->label,
1114 DISK_COLUMN, disk,
1115 VISIBLE_COLUMN, TRUE,
1116 -1);
1117 if (disk->alert)
1118 gtk_tree_store_set(tree, &iter,
1119 IMAGE_COLUMN, gkrellm_alert_pixbuf(), -1);
1120 }
1121 for (clist = list->next; clist; clist = clist->next)
1122 {
1123 disk = (DiskMon *) clist->data;
1124 if (disk->subdisk == -1)
1125 break;
1126 gtk_tree_store_append(tree, &citer, &iter);
1127 gtk_tree_store_set(tree, &citer,
1128 NAME_COLUMN, disk->default_label,
1129 ENABLE_COLUMN, disk->enabled,
1130 LABEL_COLUMN, disk->label,
1131 DISK_COLUMN, disk,
1132 VISIBLE_COLUMN, TRUE,
1133 -1);
1134 if (disk->alert)
1135 gtk_tree_store_set(tree, &citer,
1136 IMAGE_COLUMN, gkrellm_alert_pixbuf(), -1);
1137 }
1138 list = clist;
1139 }
1140
1141 return GTK_TREE_MODEL(tree);
1142 }
1143
1144 static void
cb_launch_entry(GtkWidget * widget,DiskMon * disk)1145 cb_launch_entry(GtkWidget *widget, DiskMon *disk)
1146 {
1147 if (disk->enabled)
1148 gkrellm_apply_launcher(&disk->launch_entry, &disk->tooltip_entry,
1149 disk->chart->panel, &disk->launch, gkrellm_launch_button_cb);
1150 }
1151
1152 static void
add_launch_entry(GtkWidget * vbox,DiskMon * disk)1153 add_launch_entry(GtkWidget *vbox, DiskMon *disk)
1154 {
1155 disk->launch_table = gkrellm_gtk_launcher_table_new(vbox, 1);
1156 gkrellm_gtk_config_launcher(disk->launch_table, 0, &disk->launch_entry,
1157 &disk->tooltip_entry, disk->default_label,
1158 &disk->launch);
1159 g_signal_connect(G_OBJECT(disk->launch_entry), "changed",
1160 G_CALLBACK(cb_launch_entry), disk);
1161 g_signal_connect(G_OBJECT(disk->tooltip_entry), "changed",
1162 G_CALLBACK(cb_launch_entry), disk);
1163 gtk_widget_show_all(disk->launch_table);
1164 }
1165
1166 static void
change_row_reference(GtkTreeModel * model,GtkTreePath * path)1167 change_row_reference(GtkTreeModel *model, GtkTreePath *path)
1168 {
1169 gtk_tree_row_reference_free(row_reference);
1170 if (model && path)
1171 row_reference = gtk_tree_row_reference_new(model, path);
1172 else
1173 row_reference = NULL;
1174 }
1175
1176 static void
cb_alert_config(GkrellmAlert * ap,DiskMon * disk)1177 cb_alert_config(GkrellmAlert *ap, DiskMon *disk)
1178 {
1179 GtkTreeModel *model;
1180 GtkTreeIter iter, citer;
1181 DiskMon *disk_test;
1182 GdkPixbuf *pixbuf;
1183 gboolean valid;
1184
1185 disk->alert_uses_read =
1186 GTK_TOGGLE_BUTTON(disk->alert_config_read_button)->active;
1187 disk->alert_uses_write =
1188 GTK_TOGGLE_BUTTON(disk->alert_config_write_button)->active;
1189 if (!gkrellm_config_window_shown())
1190 return;
1191 model = gtk_tree_view_get_model(treeview);
1192 pixbuf = ap->activated ? gkrellm_alert_pixbuf() : NULL;
1193 valid = gtk_tree_model_get_iter_first(model, &iter);
1194 while (valid)
1195 {
1196 gtk_tree_model_get(model, &iter, DISK_COLUMN, &disk_test, -1);
1197 if (disk == disk_test)
1198 {
1199 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1200 IMAGE_COLUMN, pixbuf, -1);
1201 return;
1202 }
1203 if (gtk_tree_model_iter_children(model, &citer, &iter))
1204 do
1205 {
1206 gtk_tree_model_get(model, &citer, DISK_COLUMN, &disk_test, -1);
1207 if (disk == disk_test)
1208 {
1209 gtk_tree_store_set(GTK_TREE_STORE(model), &citer,
1210 IMAGE_COLUMN, pixbuf, -1);
1211 return;
1212 }
1213 }
1214 while (gtk_tree_model_iter_next(model, &citer));
1215
1216 valid = gtk_tree_model_iter_next(model, &iter);
1217 }
1218 }
1219
1220 static void
cb_alert_config_button(GtkWidget * button,DiskMon * disk)1221 cb_alert_config_button(GtkWidget *button, DiskMon *disk)
1222 {
1223 gboolean read, write;
1224
1225 read = GTK_TOGGLE_BUTTON(disk->alert_config_read_button)->active;
1226 write = GTK_TOGGLE_BUTTON(disk->alert_config_write_button)->active;
1227 if (!read && !write)
1228 {
1229 gtk_toggle_button_set_active(
1230 GTK_TOGGLE_BUTTON(disk->alert_config_read_button), TRUE);
1231 gtk_toggle_button_set_active(
1232 GTK_TOGGLE_BUTTON(disk->alert_config_write_button), TRUE);
1233 }
1234 }
1235
1236 static void
cb_alert_config_create(GkrellmAlert * ap,GtkWidget * vbox,DiskMon * disk)1237 cb_alert_config_create(GkrellmAlert *ap, GtkWidget *vbox, DiskMon *disk)
1238 {
1239 gkrellm_gtk_check_button_connected(vbox, &disk->alert_config_read_button,
1240 disk->alert_uses_read, FALSE, FALSE, 2,
1241 cb_alert_config_button, disk, _("Read bytes"));
1242 gkrellm_gtk_check_button_connected(vbox, &disk->alert_config_write_button,
1243 disk->alert_uses_write, FALSE, FALSE, 2,
1244 cb_alert_config_button, disk, _("Write bytes"));
1245 }
1246
1247 static void
cb_set_alert(GtkWidget * button,gpointer data)1248 cb_set_alert(GtkWidget *button, gpointer data)
1249 {
1250 GtkTreeModel *model;
1251 GtkTreePath *path;
1252 GtkTreeIter iter;
1253 DiskMon *disk;
1254
1255 if (!row_reference)
1256 return;
1257 model = gtk_tree_view_get_model(treeview);
1258 path = gtk_tree_row_reference_get_path(row_reference);
1259 gtk_tree_model_get_iter(model, &iter, path);
1260 gtk_tree_model_get(model, &iter, DISK_COLUMN, &disk, -1);
1261
1262 if (!disk->alert)
1263 create_alert(disk);
1264 gkrellm_alert_config_window(&disk->alert);
1265 }
1266
1267 static void
label_edited_cb(GtkCellRendererText * cell,gchar * path_string,gchar * new_label,gpointer data)1268 label_edited_cb(GtkCellRendererText *cell, gchar *path_string,
1269 gchar *new_label, gpointer data)
1270 {
1271 GtkTreeModel *model;
1272 GtkTreeIter iter;
1273 GtkTreePath *path;
1274 DiskMon *disk;
1275
1276 model = disk_model;
1277 path = gtk_tree_path_new_from_string(path_string);
1278 gtk_tree_model_get_iter(model, &iter, path);
1279 gtk_tree_path_free(path);
1280
1281 gtk_tree_model_get(model, &iter,
1282 DISK_COLUMN, &disk,
1283 -1);
1284 if (!*new_label)
1285 new_label = disk->default_label;
1286 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1287 LABEL_COLUMN, new_label, -1);
1288
1289 if (strcmp(new_label, disk->label))
1290 {
1291 gkrellm_dup_string(&disk->label, new_label);
1292 gkrellm_panel_configure(disk->chart->panel, disk->label,
1293 gkrellm_panel_style(style_id));
1294 gkrellm_panel_create(disk->vbox, mon_disk, disk->chart->panel);
1295 }
1296 #if 0
1297 if (gkrellm_locale_dup_string(&s->name, new_label, &s->name_locale))
1298 {
1299 gkrellm_sensors_rebuild(s->type == SENSOR_TEMPERATURE,
1300 s->type == SENSOR_FAN, s->type == SENSOR_VOLTAGE);
1301 if (s->alert)
1302 {
1303 g_free(s->alert->name);
1304 s->alert->name = g_strdup(s->name);
1305 // gkrellm_reset_alert(s->alert);
1306 }
1307 }
1308 #endif
1309 }
1310
1311 static void
cb_tree_selection_changed(GtkTreeSelection * selection,gpointer data)1312 cb_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
1313 {
1314 GtkTreeIter iter;
1315 GtkTreeModel *model;
1316 GtkTreePath *path;
1317 DiskMon *disk;
1318 gint *indices, depth;
1319
1320 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1321 {
1322 gtk_widget_set_sensitive(alert_button, FALSE);
1323 return;
1324 }
1325 path = gtk_tree_model_get_path(model, &iter);
1326 indices = gtk_tree_path_get_indices(path);
1327 depth = gtk_tree_path_get_depth(path);
1328 // g_debug("selection: indices=[%d,%d]:%d, path=%s\n",
1329 // indices[0], indices[1], gtk_tree_path_get_depth(path),
1330 // gtk_tree_path_to_string(path));
1331 change_row_reference(model, path);
1332
1333 gtk_tree_model_get(model, &iter,
1334 DISK_COLUMN, &disk, -1);
1335
1336 if (!disk->enabled || (depth == 1 && indices[0] == 0))
1337 gtk_widget_set_sensitive(alert_button, FALSE);
1338 else
1339 gtk_widget_set_sensitive(alert_button, TRUE);
1340 gtk_tree_path_free(path);
1341 }
1342
1343 static void
cb_enable(GtkCellRendererText * cell,gchar * path_string,gpointer data)1344 cb_enable(GtkCellRendererText *cell, gchar *path_string, gpointer data)
1345 {
1346 GtkTreeModel *model;
1347 GtkTreeIter iter;
1348 GtkTreePath *path;
1349 GList *list;
1350 DiskMon *disk;
1351 gboolean enabled;
1352
1353 model = GTK_TREE_MODEL(data);
1354 path = gtk_tree_path_new_from_string(path_string);
1355 gtk_tree_model_get_iter(model, &iter, path);
1356 gtk_tree_path_free(path);
1357
1358 gtk_tree_model_get(model, &iter,
1359 ENABLE_COLUMN, &enabled,
1360 DISK_COLUMN, &disk,
1361 -1);
1362 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1363 ENABLE_COLUMN, !enabled,
1364 -1);
1365 if (enabled)
1366 {
1367 destroy_disk_monitor(disk);
1368 gtk_widget_set_sensitive(alert_button, FALSE);
1369 }
1370 else
1371 {
1372 create_disk_monitor(disk, TRUE);
1373 add_launch_entry(launch_vbox, disk);
1374 gtk_widget_set_sensitive(alert_button, TRUE);
1375 }
1376 disk->enabled = !enabled;
1377 enabled = FALSE;
1378 for (list = disk_mon_list; list; list = list->next)
1379 if (((DiskMon *) list->data)->enabled)
1380 enabled = TRUE;
1381 if (enabled)
1382 gkrellm_spacers_show(mon_disk);
1383 else
1384 gkrellm_spacers_hide(mon_disk);
1385 }
1386
1387 static void
cb_text_format(GtkWidget * widget,gpointer data)1388 cb_text_format(GtkWidget *widget, gpointer data)
1389 {
1390 GList *list;
1391 DiskMon *disk;
1392 gchar *s;
1393 GtkWidget *entry;
1394
1395 entry = gtk_bin_get_child(GTK_BIN(text_format_combo_box));
1396 s = gkrellm_gtk_entry_get_text(&entry);
1397 gkrellm_locale_dup_string(&text_format, s, &text_format_locale);
1398 for (list = disk_mon_list; list; list = list->next)
1399 {
1400 disk = (DiskMon *) list->data;
1401 disk->new_text_format = TRUE;
1402 draw_disk_chart(disk);
1403 }
1404 }
1405
1406
1407 #define DEFAULT_TEXT_FORMAT "$T"
1408
1409 static gchar *disk_info_text[] =
1410 {
1411 N_("<h>Chart Labels\n"),
1412 N_("Substitution variables for the format string for chart labels:\n"),
1413 N_("\t$L the Disk label\n"),
1414 N_("\t$M maximum chart value\n"),
1415 N_("\t$T total read bytes + write bytes\n"),
1416 N_("\t$r read bytes\n"),
1417 N_("\t$w write bytes\n"),
1418 "\n",
1419 N_("Substitution variables may be used in alert commands.\n")
1420 };
1421
1422 static void
create_disk_tab(GtkWidget * tab_vbox)1423 create_disk_tab(GtkWidget *tab_vbox)
1424 {
1425 GtkWidget *tabs;
1426 GtkWidget *vbox, *vbox1, *hbox;
1427 GtkWidget *text;
1428 GtkWidget *scrolled;
1429 GtkTreeModel *model;
1430 GtkCellRenderer *renderer;
1431 GList *list;
1432 DiskMon *disk;
1433 gint i;
1434
1435 check_for_new_disks();
1436 if (n_disks == 0)
1437 return;
1438
1439 tabs = gtk_notebook_new();
1440 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
1441 gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
1442
1443 /* -- Options tab */
1444 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Options"));
1445
1446 scrolled = gtk_scrolled_window_new(NULL, NULL);
1447 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1448 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1449 gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0);
1450
1451 model = create_model();
1452 disk_model = model;
1453
1454 treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
1455 gtk_tree_view_set_rules_hint(treeview, TRUE);
1456
1457 renderer = gtk_cell_renderer_toggle_new();
1458 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Enable"),
1459 renderer,
1460 "active", ENABLE_COLUMN,
1461 NULL);
1462 g_signal_connect(G_OBJECT(renderer), "toggled",
1463 G_CALLBACK(cb_enable), model);
1464
1465 renderer = gtk_cell_renderer_text_new();
1466 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Disk"),
1467 renderer,
1468 "text", NAME_COLUMN,
1469 NULL);
1470 renderer = gtk_cell_renderer_text_new();
1471 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Label"),
1472 renderer,
1473 "text", LABEL_COLUMN,
1474 "editable", TRUE,
1475 "visible", VISIBLE_COLUMN,
1476 NULL);
1477 g_signal_connect(G_OBJECT(renderer), "edited",
1478 G_CALLBACK(label_edited_cb), NULL);
1479
1480 renderer = gtk_cell_renderer_pixbuf_new();
1481 gtk_tree_view_insert_column_with_attributes(treeview, -1, "",
1482 renderer,
1483 "pixbuf", IMAGE_COLUMN,
1484 NULL);
1485
1486 gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
1487 g_object_unref(G_OBJECT(model));
1488 selection = gtk_tree_view_get_selection(treeview);
1489 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
1490 g_signal_connect(G_OBJECT(selection), "changed",
1491 G_CALLBACK(cb_tree_selection_changed), NULL);
1492
1493 hbox = gtk_hbox_new(FALSE, 0);
1494 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
1495 gkrellm_gtk_alert_button(hbox, &alert_button, FALSE, FALSE, 4, FALSE,
1496 cb_set_alert, NULL);
1497 gtk_widget_set_sensitive(alert_button, FALSE);
1498
1499 /* -- Setup tab */
1500 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Setup"));
1501
1502 vbox1 = gkrellm_gtk_category_vbox(vbox,
1503 _("Format String for Chart Labels"),
1504 4, 0, TRUE);
1505 text_format_combo_box = gtk_combo_box_entry_new_text();
1506 gtk_box_pack_start(GTK_BOX(vbox1), text_format_combo_box, FALSE, FALSE, 0);
1507 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
1508 text_format);
1509 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
1510 DEFAULT_TEXT_FORMAT);
1511 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
1512 "\\c\\f$M\\n$T");
1513 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
1514 "\\c\\f$M\\b$T");
1515 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
1516 _("\\f\\ww\\r\\f$M\\D2\\f\\ar\\. $r\\D1\\f\\aw\\. $w"));
1517 gtk_combo_box_set_active(GTK_COMBO_BOX(text_format_combo_box), 0);
1518 g_signal_connect(G_OBJECT(GTK_COMBO_BOX(text_format_combo_box)), "changed",
1519 G_CALLBACK(cb_text_format), NULL);
1520
1521 vbox1 = gkrellm_gtk_category_vbox(vbox,
1522 _("Launch Commands"),
1523 4, 0, TRUE);
1524 launch_vbox = gkrellm_gtk_scrolled_vbox(vbox1, NULL,
1525 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1526 gtk_widget_show(launch_vbox);
1527 gtk_widget_realize(launch_vbox);
1528 for (i = 0, list = disk_mon_list; list; list = list->next, ++i)
1529 {
1530 disk = (DiskMon *) list->data;
1531 if (disk->enabled)
1532 add_launch_entry(launch_vbox, disk);
1533 }
1534
1535 /* --Info tab */
1536 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Info"));
1537 text = gkrellm_gtk_scrolled_text_view(vbox, NULL,
1538 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1539 for (i = 0; i < sizeof(disk_info_text)/sizeof(gchar *); ++i)
1540 gkrellm_gtk_text_view_append(text, _(disk_info_text[i]));
1541 }
1542
1543 static GkrellmMonitor monitor_disk =
1544 {
1545 N_("Disk"), /* Name, for config tab. */
1546 MON_DISK, /* Id, 0 if a plugin */
1547 create_disk, /* The create function */
1548 update_disk, /* The update function */
1549 create_disk_tab, /* The config tab create function */
1550 NULL, /* Instant apply */
1551
1552 save_disk_config, /* Save user conifg */
1553 load_disk_config, /* Load user config */
1554 DISK_CONFIG_KEYWORD, /* config keyword */
1555
1556 NULL, /* Undef 2 */
1557 NULL, /* Undef 1 */
1558 NULL, /* Undef 0 */
1559
1560 0, /* insert_before_id - place plugin before this mon */
1561
1562 NULL, /* Handle if a plugin, filled in by GKrellM */
1563 NULL /* path if a plugin, filled in by GKrellM */
1564 };
1565
1566 GkrellmMonitor *
gkrellm_init_disk_monitor(void)1567 gkrellm_init_disk_monitor(void)
1568 {
1569 DiskMon *disk;
1570
1571 monitor_disk.name = _(monitor_disk.name);
1572
1573 disk = disk_new("Disk", _("Disk"));
1574 disk_mon_list = g_list_append(disk_mon_list, disk);
1575
1576 composite_disk = disk;
1577 gkrellm_locale_dup_string(&text_format, DEFAULT_TEXT_FORMAT,
1578 &text_format_locale);
1579 mon_disk = &monitor_disk;
1580
1581 if (setup_disk_interface())
1582 {
1583 if (n_disks > 0)
1584 composite_disk->enabled = TRUE;
1585 style_id = gkrellm_add_chart_style(&monitor_disk, DISK_STYLE_NAME);
1586 return &monitor_disk;
1587 }
1588 return NULL;
1589 }
1590