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