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 DEFAULT_DATA_FORMAT (_("$t - $f free"))
40 #define ALT1_DATA_FORMAT (_("$t - $u used"))
41 #define ALT2_DATA_FORMAT (_("$t - $U"))
42
43
44 /* Values for force_fs_check */
45 #define FORCE_REDRAW 1
46 #define FORCE_UPDATE 2
47
48 #define FS_MOUNTING_ENABLED(fs) \
49 ((fs)->fstab_mounting || *((fs)->launch_umount.command))
50
51 typedef struct
52 {
53 gchar *directory;
54 gchar *device;
55 gchar *type;
56 gchar *options;
57 }
58 Mount;
59
60 typedef struct
61 {
62 gint idx;
63 GkrellmPanel *panel;
64 GkrellmDecalbutton *md_button,
65 *eject_button,
66 *drawer_button;
67 GkrellmDecal *mount_decal,
68 *eject_decal,
69 *label_decal,
70 *data_decal;
71 GkrellmKrell *krell;
72 gchar *label, /* Actual utf8 label */
73 *label_shadow; /* Shadow label for gdk_draw functions */
74 gboolean label_is_data,
75 restore_label,
76 mouse_entered;
77
78 Mount mount;
79 gboolean fstab_mounting;
80 GkrellmLauncher launch_mount,
81 launch_umount;
82
83 GkrellmAlert *alert;
84
85 gboolean secondary,
86 show_if_mounted,
87 is_mounted,
88 ejectable,
89 is_nfs_fs;
90 gchar *eject_device;
91 gint eject_pending;
92 gint x_eject_button_target;
93
94 GString *pipe_gstring; /* output of mount commands */
95
96 gulong krell_factor; /* avoid krell math overflow */
97
98 gboolean busy;
99 gint64 blocks,
100 bfree,
101 bavail,
102 bsize;
103 }
104 FSmon;
105
106 static void cb_alert_config(GkrellmAlert *ap, FSmon *fs);
107
108 static GkrellmMonitor
109 *mon_fs;
110
111 static GList *fs_mon_list,
112 *mounts_list;
113 static GList *fstab_list;
114
115 static gint uid;
116
117 void (*get_mounts_list)(),
118 (*get_fsusage)(),
119 (*get_fstab_list)();
120 gboolean (*get_fstab_modified)();
121
122
123 /* If ejecting is available via an ioctl() or if there is an eject command,
124 | set these up in gkrellm_sys_fs_init() by calling gkrellm_fs_setup_eject().
125 */
126 void (*eject_cdrom_func)(),
127 (*close_cdrom_func)();
128 static gchar *eject_cdrom_command,
129 *close_cdrom_command;
130 static gboolean cdrom_thread_busy; /* for the cdrom_funcs */
131
132
133 static GtkWidget
134 *fs_main_vbox,
135 *fs_secondary_vbox;
136
137 static gboolean fs_check_timeout = 2,
138 nfs_check_timeout = 16;
139 static gint check_tick;
140
141 static gint secondary_monitors_shown;
142
143 static gint n_fs_monitors;
144 static gint force_fs_check;
145 static FSmon *fs_in_motion;
146 static gint x_fs_motion;
147 static gint x_moved;
148 static gint x_eject_button_open,
149 x_eject_button_closed;
150
151 static gint x_scroll;
152 static gint data_decal_width;
153 static gint cdrom_auto_eject;
154 static gint binary_units;
155 static gboolean mounting_supported = TRUE,
156 ejecting_supported = FALSE;
157 static gboolean have_secondary_panels;
158 static gchar *data_format,
159 *data_format_locale;
160
161 static gint style_id;
162
163 static gchar *remote_fs_types[] =
164 {
165 "cifs",
166 "nfs",
167 "smbfs"
168 };
169
170
171 static gboolean
setup_fs_interface(void)172 setup_fs_interface(void)
173 {
174 #ifdef WIN32
175 uid = 0; /* nothing comparable available on windows */
176 #else
177 uid = getuid(); /* only real root is allowed to mount/umount always */
178 #endif
179 if (!get_fsusage && !_GK.client_mode && gkrellm_sys_fs_init())
180 {
181 get_fsusage = gkrellm_sys_fs_get_fsusage;
182 get_mounts_list = gkrellm_sys_fs_get_mounts_list;
183 get_fstab_list = gkrellm_sys_fs_get_fstab_list;
184 get_fstab_modified = gkrellm_sys_fs_fstab_modified;
185 }
186 return get_fsusage ? TRUE : FALSE;
187 }
188
189 void
gkrellm_fs_client_divert(void (* get_fsusage_func)(),void (* get_mounts_func)(),void (* get_fstab_func)(),gboolean (* fstab_modified_func)())190 gkrellm_fs_client_divert(void (*get_fsusage_func)(),
191 void (*get_mounts_func)(), void (*get_fstab_func)(),
192 gboolean (*fstab_modified_func)())
193 {
194 get_fsusage = get_fsusage_func;
195 get_mounts_list = get_mounts_func;
196 get_fstab_list = get_fstab_func;
197 get_fstab_modified = fstab_modified_func;
198 }
199
200 void
gkrellm_fs_setup_eject(gchar * eject_tray,gchar * close_tray,void (* eject_func)(),void (* close_func)())201 gkrellm_fs_setup_eject(gchar *eject_tray, gchar *close_tray,
202 void (*eject_func)(), void (*close_func)())
203 {
204 eject_cdrom_command = g_strdup(eject_tray);
205 close_cdrom_command = g_strdup(close_tray);
206 eject_cdrom_func = eject_func;
207 close_cdrom_func = close_func;
208 if (eject_cdrom_command || eject_cdrom_func)
209 ejecting_supported = TRUE;
210 }
211
212 void
gkrellm_fs_add_to_mounts_list(gchar * dir,gchar * dev,gchar * type)213 gkrellm_fs_add_to_mounts_list(gchar *dir, gchar *dev, gchar *type)
214 {
215 Mount *m;
216
217 m = g_new0(Mount, 1);
218 m->directory = g_strdup(dir);
219 m->device = g_strdup(dev);
220 m->type = g_strdup(type);
221 mounts_list = g_list_append(mounts_list, m);
222 }
223
224 void
gkrellm_fs_add_to_fstab_list(gchar * dir,gchar * dev,gchar * type,gchar * opt)225 gkrellm_fs_add_to_fstab_list(gchar *dir, gchar *dev, gchar *type, gchar *opt)
226 {
227 Mount *m;
228
229 m = g_new0(Mount, 1);
230 m->directory = g_strdup(dir);
231 m->device = g_strdup(dev);
232 m->type = g_strdup(type);
233 m->options = g_strdup(opt);
234 fstab_list = g_list_append(fstab_list, m);
235 }
236
237 void
gkrellm_fs_assign_fsusage_data(gpointer fspointer,gint64 blocks,gint64 bavail,gint64 bfree,gint64 bsize)238 gkrellm_fs_assign_fsusage_data(gpointer fspointer,
239 gint64 blocks, gint64 bavail, gint64 bfree, gint64 bsize)
240 {
241 FSmon *fs = (FSmon *) fspointer;
242
243 fs->blocks = blocks;
244 fs->bavail = bavail;
245 fs->bfree = bfree;
246 fs->bsize = bsize;
247 }
248
249 void
gkrellm_fs_mounting_unsupported(void)250 gkrellm_fs_mounting_unsupported(void)
251 {
252 mounting_supported = FALSE;
253 }
254
255 /* ======================================================================== */
256
257
258 static Mount *
in_fstab_list(gchar * s)259 in_fstab_list(gchar *s)
260 {
261 GList *list;
262 Mount *m;
263
264 for (list = fstab_list; list; list = list->next)
265 {
266 m = (Mount *)list->data;
267 if (strcmp(s, m->directory) == 0)
268 return m;
269 }
270 return NULL;
271 }
272
273 static void
refresh_mounts_list(void)274 refresh_mounts_list(void)
275 {
276 Mount *m;
277
278 while (mounts_list)
279 {
280 m = (Mount *) mounts_list->data;
281 g_free(m->directory);
282 g_free(m->device);
283 g_free(m->type);
284 g_free(mounts_list->data);
285 mounts_list = g_list_remove(mounts_list, mounts_list->data);
286 }
287 (*get_mounts_list)();
288 }
289
290 static void
refresh_fstab_list(void)291 refresh_fstab_list(void)
292 {
293 Mount *m;
294
295 while (fstab_list)
296 {
297 m = (Mount *) fstab_list->data;
298 g_free(m->device);
299 g_free(m->directory);
300 g_free(m->type);
301 g_free(m->options);
302 g_free(m);
303 fstab_list = g_list_remove(fstab_list, fstab_list->data);
304 }
305 (*get_fstab_list)();
306 }
307
308 static gint
fs_is_mounted(FSmon * fs)309 fs_is_mounted(FSmon *fs)
310 {
311 Mount *m_fs, *m_mounted;
312 GList *list;
313 gint i;
314
315 fs->is_mounted = FALSE;
316 m_fs = &fs->mount;
317 for (list = mounts_list; list; list = list->next)
318 {
319 m_mounted = (Mount *) list->data;
320 if (strcmp(m_fs->directory, m_mounted->directory))
321 continue;
322 fs->is_mounted = TRUE;
323 fs->is_nfs_fs = FALSE;
324 for (i = 0; i < (sizeof(remote_fs_types) / sizeof(gchar *)); ++i)
325 {
326 if (!strcmp(m_mounted->type, remote_fs_types[i]))
327 {
328 fs->is_nfs_fs = TRUE;
329 break;
330 }
331 }
332 }
333 return fs->is_mounted;
334 }
335
336 static GkrellmSizeAbbrev fs_decimal_abbrev[] =
337 {
338 { MB_SIZE(10), MB_SIZE(1), "%.2fM" },
339 { GB_SIZE(1), MB_SIZE(1), "%.0fM" },
340 { GB_SIZE(10), GB_SIZE(1), "%.2fG" },
341 { GB_SIZE(100), GB_SIZE(1), "%.1fG" },
342 { TB_SIZE(1), GB_SIZE(1), "%.0fG" },
343 { TB_SIZE(10), TB_SIZE(1), "%.2fT" },
344 { TB_SIZE(100), TB_SIZE(1), "%.1fT" }
345 };
346
347 static GkrellmSizeAbbrev fs_binary_abbrev[] =
348 {
349 { MiB_SIZE(10), MiB_SIZE(1), "%.2fM" },
350 { GiB_SIZE(1), MiB_SIZE(1), "%.0fM" },
351 { GiB_SIZE(10), GiB_SIZE(1), "%.2fG" },
352 { GiB_SIZE(100), GiB_SIZE(1), "%.1fG" },
353 { TiB_SIZE(1), GiB_SIZE(1), "%.0fG" },
354 { TiB_SIZE(10), TiB_SIZE(1), "%.2fT" },
355 { TiB_SIZE(100), TiB_SIZE(1), "%.1fT" }
356 };
357
358 static gint
format_fs_data(FSmon * fs,gchar * src_string,gchar * buf,gint size)359 format_fs_data(FSmon *fs, gchar *src_string, gchar *buf, gint size)
360 {
361 gint64 b, u, a;
362 gint len;
363 gchar *s;
364 gchar tbuf[32], ubuf[32], abuf[32];
365 gfloat bsize, val;
366 GkrellmSizeAbbrev *tbl;
367 size_t tbl_size;
368
369 if (!buf || size < 1)
370 return -1;
371 --size;
372 *buf = '\0';
373 if (!src_string)
374 return -1;
375
376 b = fs->blocks;
377 u = fs->blocks - fs->bfree;
378 a = fs->bavail; /* Can be negative on BSD */
379 bsize = (gfloat) fs->bsize;
380
381 tbl = binary_units ? &fs_binary_abbrev[0] : &fs_decimal_abbrev[0];
382 tbl_size = binary_units
383 ? (sizeof(fs_binary_abbrev) / sizeof(GkrellmSizeAbbrev))
384 : (sizeof(fs_decimal_abbrev) / sizeof(GkrellmSizeAbbrev));
385
386 gkrellm_format_size_abbrev(tbuf, sizeof(tbuf), (gfloat) b * bsize,
387 tbl, tbl_size);
388 gkrellm_format_size_abbrev(ubuf, sizeof(ubuf), (gfloat) u * bsize,
389 tbl, tbl_size);
390 gkrellm_format_size_abbrev(abuf, sizeof(abuf), (gfloat) a * bsize,
391 tbl, tbl_size);
392
393 for (s = src_string; *s != '\0' && size > 0; ++s)
394 {
395 len = 1;
396 if (*s == '$' && *(s + 1) != '\0')
397 {
398 switch(*(s + 1))
399 {
400 case 'D':
401 if (fs->mount.directory)
402 len = snprintf(buf, size, "%s", fs->mount.directory);
403 break;
404 case 'l':
405 case 'L':
406 len = snprintf(buf, size, "%s", fs->label_shadow);
407 break;
408 case 't':
409 len = snprintf(buf, size, "%s", tbuf);
410 break;
411 case 'u':
412 len = snprintf(buf, size, "%s", ubuf);
413 break;
414 case 'U':
415 if (u + a > 0)
416 val = 100.0 * (gfloat) u / (gfloat) (u + a);
417 else
418 val = 0;
419 len = snprintf(buf, size, "%.0f%%", val);
420 break;
421 case 'f':
422 len = snprintf(buf, size, "%s", abuf);
423 break;
424 case 'F':
425 if (u + a > 0)
426 val = 100.0 * (gfloat) a / (gfloat) (u + a);
427 else
428 val = 0;
429 len = snprintf(buf, size, "%.0f%%", val);
430 break;
431 case 'H':
432 len = snprintf(buf, size, "%s",
433 gkrellm_sys_get_host_name());
434 break;
435 default:
436 *buf = *s;
437 if (size > 1)
438 {
439 *(buf + 1) = *(s + 1);
440 ++len;
441 }
442 break;
443 }
444 ++s;
445 }
446 else
447 *buf = *s;
448 size -= len;
449 buf += len;
450 }
451 *buf = '\0';
452 return u + 1;
453 }
454
455 /* Draw the fs label or toggle the fs total blocks and blocks avail.
456 */
457 static gint
fs_draw_decal_text(FSmon * fs,gint value)458 fs_draw_decal_text(FSmon *fs, gint value)
459 {
460 GkrellmDecal *d;
461 GkrellmTextstyle ts_save;
462 gchar buf[128];
463 gint x_off, w = 0;
464
465 if (value == 0)
466 {
467 gkrellm_make_decal_invisible(fs->panel, fs->data_decal);
468 d = fs->label_decal;
469 gkrellm_make_decal_visible(fs->panel, d);
470 gkrellm_decal_text_set_offset(d, 0, 0);
471 gkrellm_draw_decal_markup(fs->panel, d, fs->label_shadow);
472 }
473 else if (!fs->busy)
474 {
475 gkrellm_make_decal_invisible(fs->panel, fs->label_decal);
476 d = fs->data_decal;
477 gkrellm_make_decal_visible(fs->panel, d);
478 ts_save = d->text_style;
479 d->text_style = *gkrellm_meter_alt_textstyle(style_id);
480
481 format_fs_data(fs, data_format_locale, buf, sizeof(buf));
482 gkrellm_decal_scroll_text_set_markup(fs->panel, d, buf);
483 gkrellm_decal_scroll_text_get_size(d, &w, NULL);
484 if (w > d->w)
485 x_off = d->w / 3 - x_scroll;
486 else
487 x_off = 0;
488 gkrellm_decal_text_set_offset(d, x_off, 0);
489
490 d->text_style = ts_save;
491 }
492 return w;
493 }
494
495 static void
cb_command_process(GkrellmAlert * alert,gchar * src,gchar * dst,gint len,FSmon * fs)496 cb_command_process(GkrellmAlert *alert, gchar *src, gchar *dst, gint len,
497 FSmon *fs)
498 {
499 format_fs_data(fs, src, dst, len);
500 }
501
502 static gpointer
close_cdrom_thread(void * device)503 close_cdrom_thread(void *device)
504 {
505 (*close_cdrom_func)((gchar *) device);
506 cdrom_thread_busy = FALSE;
507 return NULL;
508 }
509
510 static void
close_tray(FSmon * fs)511 close_tray(FSmon *fs)
512 {
513 GThread *gth;
514 Mount *m;
515 static gchar *close_target;
516 gchar buf[512];
517
518 close_target = fs->eject_device;
519 if (close_cdrom_command)
520 {
521 snprintf(buf, sizeof(buf), close_cdrom_command,
522 *close_target ? close_target : fs->mount.directory);
523 g_spawn_command_line_async(buf, NULL /* GError */);
524 }
525 else if (close_cdrom_func && !cdrom_thread_busy)
526 {
527 if (!*close_target && (m = in_fstab_list(fs->mount.directory)) != NULL)
528 close_target = m->device;
529 if (*close_target)
530 {
531 cdrom_thread_busy = TRUE;
532 gth = g_thread_new("close_cdrom",
533 close_cdrom_thread, close_target);
534 g_thread_unref(gth);
535 }
536 }
537 }
538
539 static gpointer
eject_cdrom_thread(void * device)540 eject_cdrom_thread(void *device)
541 {
542 (*eject_cdrom_func)((gchar *) device);
543 cdrom_thread_busy = FALSE;
544 return NULL;
545 }
546
547 static void
eject_tray(FSmon * fs)548 eject_tray(FSmon *fs)
549 {
550 GThread *gth;
551 Mount *m;
552 static gchar *eject_target;
553 gchar buf[512];
554
555 eject_target = fs->eject_device;
556 if (eject_cdrom_command)
557 {
558 snprintf(buf, sizeof(buf), eject_cdrom_command,
559 *eject_target ? eject_target : fs->mount.directory);
560 g_spawn_command_line_async(buf, NULL /* GError */);
561 }
562 else if (eject_cdrom_func && !cdrom_thread_busy)
563 {
564 if (!*eject_target && (m = in_fstab_list(fs->mount.directory)) != NULL)
565 eject_target = m->device;
566 if (*eject_target)
567 {
568 cdrom_thread_busy = TRUE;
569 gth = g_thread_new("eject_cdrom",
570 eject_cdrom_thread, eject_target);
571 g_thread_unref(gth);
572 }
573 }
574 }
575
576 static void
accumulate_pipe_gstring(FSmon * fs)577 accumulate_pipe_gstring(FSmon *fs)
578 {
579 gchar buf[512];
580 gint n;
581
582 n = fread(buf, 1, sizeof(buf) - 1, fs->launch_mount.pipe);
583 buf[n] = '\0';
584 if (n > 0)
585 {
586 if (fs->pipe_gstring)
587 g_string_append(fs->pipe_gstring, buf);
588 else
589 fs->pipe_gstring = g_string_new(buf);
590 }
591 if (feof(fs->launch_mount.pipe))
592 {
593 pclose(fs->launch_mount.pipe);
594 fs->launch_mount.pipe = NULL;
595 }
596 }
597
598 static void
pipe_command(FSmon * fs,gchar * command)599 pipe_command(FSmon *fs, gchar *command)
600 {
601 gchar buf[512];
602
603 if (fs->launch_mount.pipe) /* Still running? */
604 return;
605 snprintf(buf, sizeof(buf), "%s 2>&1", command);
606 if ((fs->launch_mount.pipe = popen(buf, "r")) == NULL)
607 return;
608 #ifndef WIN32
609 fcntl(fileno(fs->launch_mount.pipe), F_SETFL, O_NONBLOCK);
610 #endif
611 }
612
613 static void
mount_command(FSmon * fs)614 mount_command(FSmon *fs)
615 {
616 gchar cmd[CFG_BUFSIZE];
617
618 if (! FS_MOUNTING_ENABLED(fs))
619 return;
620 if (fs->is_mounted)
621 {
622 if (fs->fstab_mounting)
623 snprintf(cmd, sizeof(cmd), "umount '%s'", fs->mount.directory);
624 else
625 snprintf(cmd, sizeof(cmd), "%s", fs->launch_umount.command);
626 fs->label_is_data = FALSE;
627 fs_draw_decal_text(fs, 0);
628 pipe_command(fs, cmd);
629 if (cdrom_auto_eject)
630 fs->eject_pending = GK.timer_ticks + 5; /* at least 1/2 sec delay*/
631 }
632 else
633 {
634 if (fs->ejectable)
635 close_tray(fs);
636 if (fs->fstab_mounting)
637 snprintf(cmd, sizeof(cmd), "mount '%s'", fs->mount.directory);
638 else
639 snprintf(cmd, sizeof(cmd), "%s", fs->launch_mount.command);
640 fs->blocks = fs->bfree = fs->bavail = fs->bsize = 0;
641 pipe_command(fs, cmd);
642 }
643 force_fs_check = FORCE_REDRAW; /* An update triggers when pipe closes */
644 }
645
646 static void
hide_secondary_monitors(void)647 hide_secondary_monitors(void)
648 {
649 FSmon *fs;
650 GList *list;
651
652 if (!secondary_monitors_shown)
653 return;
654 secondary_monitors_shown = FALSE;
655 gkrellm_freeze_side_frame_packing();
656 for (list = fs_mon_list; list; list = list->next)
657 {
658 fs = (FSmon *) list->data;
659 if (fs->secondary && (!fs_is_mounted(fs) || !fs->show_if_mounted))
660 gkrellm_panel_hide(fs->panel);
661 }
662 gkrellm_thaw_side_frame_packing();
663 }
664
665 static void
show_secondary_monitors(void)666 show_secondary_monitors(void)
667 {
668 FSmon *fs;
669 GList *list;
670
671 if (secondary_monitors_shown)
672 return;
673 secondary_monitors_shown = TRUE;
674 gkrellm_freeze_side_frame_packing();
675 for (list = fs_mon_list; list; list = list->next)
676 {
677 fs = (FSmon *) list->data;
678 if (fs->secondary)
679 gkrellm_panel_show(fs->panel);
680 }
681 gkrellm_thaw_side_frame_packing();
682 }
683
684 static gpointer
get_fsusage_thread(void * data)685 get_fsusage_thread(void *data)
686 {
687 FSmon *fs = (FSmon *) data;
688
689 (*get_fsusage)(fs, fs->mount.directory);
690 fs->busy = FALSE;
691 return NULL;
692 }
693
694 static gboolean
animate_eject_button(FSmon * fs,gboolean force_close)695 animate_eject_button(FSmon *fs, gboolean force_close)
696 {
697 gint dx, target;
698
699 if (force_close)
700 target = x_eject_button_closed;
701 else
702 target = fs->x_eject_button_target;
703 dx = target - fs->eject_decal->x;
704 if (dx > 0)
705 gkrellm_move_decal(fs->panel, fs->eject_decal,
706 fs->eject_decal->x + 1 + dx / 4, fs->eject_decal->y);
707 else if (dx < 0)
708 gkrellm_move_decal(fs->panel, fs->eject_decal,
709 fs->eject_decal->x - 1 + dx / 4, fs->eject_decal->y);
710 if (fs->eject_decal->x < x_eject_button_closed)
711 gkrellm_show_button(fs->eject_button);
712 else
713 gkrellm_hide_button(fs->eject_button);
714 if (fs->eject_decal->x != target)
715 return TRUE;
716 return FALSE;
717 }
718
719 static void
fs_update(void)720 fs_update(void)
721 {
722 GThread *gth;
723 FSmon *fs;
724 GkrellmPanel *p;
725 GkrellmKrell *k;
726 GList *list;
727 gint64 used, avail;
728 gint full_scale, index, w_scroll, w;
729 gboolean fs_check, nfs_check, force_check, force_draw,
730 mounting_enabled;
731
732 if (!fs_mon_list)
733 return;
734
735 w = w_scroll = 0;
736 for (list = fs_mon_list; list; list = list->next)
737 {
738 fs = (FSmon *) list->data;
739 if (fs->label_is_data && !fs_in_motion)
740 {
741 w = fs_draw_decal_text(fs, 1);
742 if (w > w_scroll)
743 w_scroll = w;
744 gkrellm_draw_panel_layers(fs->panel);
745 }
746 }
747 if (!fs_in_motion)
748 {
749 if (w_scroll > data_decal_width)
750 x_scroll = (x_scroll + ((gkrellm_update_HZ() < 7) ? 2 : 1))
751 % (w_scroll - data_decal_width / 3);
752 else
753 x_scroll = 0;
754 }
755 if (GK.second_tick)
756 ++check_tick;
757 fs_check = (check_tick % fs_check_timeout) ? FALSE : TRUE;
758 if (_GK.client_mode)
759 nfs_check = fs_check;
760 else
761 nfs_check = (check_tick % nfs_check_timeout) ? FALSE : TRUE;
762
763 if (!force_fs_check && (!GK.second_tick || (!fs_check && !nfs_check)))
764 return;
765 //g_debug("fs update %d nfs %d force %d\n", fs_check, nfs_check, force_fs_check);
766
767 refresh_mounts_list();
768
769 force_check = force_draw = FALSE;
770
771 for (list = fs_mon_list; list; list = list->next)
772 {
773 fs = (FSmon *) list->data;
774 p = fs->panel;
775 k = fs->krell;
776 mounting_enabled = FS_MOUNTING_ENABLED(fs);
777 if (fs_is_mounted(fs))
778 {
779 if (mounting_enabled)
780 { /* Blink it while busy or pipe is open. */
781 if ( (fs->launch_mount.pipe || fs->busy)
782 && fs->md_button->cur_index == D_MISC_FS_MOUNTED
783 )
784 index = D_MISC_FS_UMOUNTED;
785 else
786 index = D_MISC_FS_MOUNTED;
787 gkrellm_set_decal_button_index(fs->md_button, index);
788 }
789 else
790 {
791 if (fs->busy && fs->md_button->cur_index == D_MISC_LED1)
792 index = D_MISC_LED0;
793 else
794 index = mounting_supported ? D_MISC_LED1 : D_MISC_BLANK;
795 gkrellm_set_decal_button_index(fs->md_button, index);
796 }
797 if ( force_fs_check == FORCE_UPDATE
798 || (fs_check && !fs->is_nfs_fs)
799 || (nfs_check && fs->is_nfs_fs)
800 )
801 {
802 if (!fs->is_nfs_fs || _GK.client_mode)
803 (*get_fsusage)(fs, fs->mount.directory);
804 else if (!fs->busy)
805 {
806 fs->busy = TRUE;
807 gth = g_thread_new("get_fsusage", get_fsusage_thread, fs);
808 g_thread_unref(gth);
809 }
810 if (fs->blocks > 2147483648LL)
811 fs->krell_factor = 1024 * 1024;
812 else if (fs->blocks > 2097152LL)
813 fs->krell_factor = 1024;
814 else
815 fs->krell_factor = 1;
816 }
817
818 avail = fs->bavail >= 0 ? fs->bavail : 0;
819 used = fs->blocks - fs->bfree;
820
821 full_scale = (gint) ((used + avail) / (gint64) fs->krell_factor);
822 used = used / (gint64) fs->krell_factor;
823
824 gkrellm_set_krell_full_scale(k, full_scale, 1);
825
826 if (!fs->busy)
827 {
828 if ( (fs_in_motion && fs->label_is_data && x_moved)
829 || fs->mouse_entered
830 )
831 gkrellm_update_krell(p, k, 0);
832 else
833 gkrellm_update_krell(p, k, (gulong) used);
834 if (full_scale > 0)
835 gkrellm_check_alert(fs->alert,
836 100.0 * (gfloat) used / (gfloat) full_scale);
837 }
838 else
839 force_draw = TRUE;
840
841 if (fs->secondary && fs->show_if_mounted)
842 gkrellm_panel_show(fs->panel);
843 if (fs->eject_decal)
844 force_draw |= animate_eject_button(fs, mounting_supported);
845 }
846 else /* not mounted */
847 {
848 gkrellm_reset_alert(fs->alert);
849 if (mounting_enabled)
850 { /* Blink it while pipe is open. */
851 if ( fs->launch_mount.pipe
852 && fs->md_button->cur_index == D_MISC_FS_UMOUNTED
853 )
854 index = D_MISC_FS_MOUNTED;
855 else
856 index = D_MISC_FS_UMOUNTED;
857 gkrellm_set_decal_button_index(fs->md_button, index);
858 }
859 else
860 gkrellm_set_decal_button_index(fs->md_button, D_MISC_LED0);
861 gkrellm_set_krell_full_scale(k, 100, 1); /* Arbitrary > 0 */
862 gkrellm_update_krell(p, k, 0);
863 if (!secondary_monitors_shown && fs->secondary)
864 gkrellm_panel_hide(fs->panel);
865 if (fs->eject_decal)
866 force_draw |= animate_eject_button(fs, FALSE);
867 }
868 gkrellm_set_button_sensitive(fs->md_button, mounting_enabled);
869 if (!fs->label_is_data && fs != fs_in_motion)
870 fs_draw_decal_text(fs, 0);
871
872 if (_GK.client_mode)
873 {
874 if (fs->blocks == 0)
875 gkrellm_remove_krell(p, k);
876 else
877 gkrellm_insert_krell(p, k, FALSE);
878 }
879
880 gkrellm_draw_panel_layers(p);
881
882 if ( fs->ejectable
883 && fs->eject_pending && fs->eject_pending < GK.timer_ticks
884 )
885 {
886 eject_tray(fs);
887 fs->eject_pending = 0;
888 }
889 if (fs->launch_mount.pipe)
890 {
891 accumulate_pipe_gstring(fs);
892 if (fs->launch_mount.pipe == NULL) /* Command is done */
893 {
894 if (fs->pipe_gstring)
895 {
896 gkrellm_message_dialog(_("GKrellM Mount Error"),
897 fs->pipe_gstring->str);
898 g_string_free(fs->pipe_gstring, 1);
899 fs->pipe_gstring = NULL;
900 }
901 force_check = TRUE;
902 }
903 else
904 force_draw = TRUE; /* Keep it going */
905 }
906 }
907 force_fs_check = force_check ? FORCE_UPDATE : force_draw;
908 }
909
910 static gint
fs_expose_event(GtkWidget * widget,GdkEventExpose * ev)911 fs_expose_event(GtkWidget *widget, GdkEventExpose *ev)
912 {
913 FSmon *fs;
914 GList *list;
915
916 for (list = fs_mon_list; list; list = list->next)
917 {
918 fs = (FSmon *) list->data;
919 if (widget == fs->panel->drawing_area)
920 {
921 gdk_draw_drawable(widget->window, gkrellm_draw_GC(1),
922 fs->panel->pixmap,
923 ev->area.x, ev->area.y, ev->area.x, ev->area.y,
924 ev->area.width, ev->area.height);
925 break;
926 }
927 }
928 return FALSE;
929 }
930
931 static gint
cb_panel_enter(GtkWidget * w,GdkEventButton * ev,FSmon * fs)932 cb_panel_enter(GtkWidget *w, GdkEventButton *ev, FSmon *fs)
933 {
934 if (fs->label_is_data)
935 {
936 fs->mouse_entered = TRUE;
937 force_fs_check = FORCE_REDRAW;
938 }
939 if (fs->ejectable)
940 {
941 fs->x_eject_button_target = x_eject_button_open;
942 force_fs_check = FORCE_REDRAW;
943 }
944 if (fs != fs_in_motion)
945 gkrellm_show_button(fs->drawer_button);
946 return FALSE;
947 }
948
949 static gint
cb_panel_leave(GtkWidget * w,GdkEventButton * ev,FSmon * fs)950 cb_panel_leave(GtkWidget *w, GdkEventButton *ev, FSmon *fs)
951 {
952 if (fs->mouse_entered)
953 force_fs_check = FORCE_REDRAW;
954 fs->mouse_entered = FALSE;
955 if (fs->ejectable)
956 {
957 fs->x_eject_button_target = x_eject_button_closed;
958 force_fs_check = FORCE_REDRAW;
959 }
960 return FALSE;
961 }
962
963
964 static void
cb_drawer_button(GkrellmDecalbutton * button,FSmon * fs)965 cb_drawer_button(GkrellmDecalbutton *button, FSmon *fs)
966 {
967 if (secondary_monitors_shown)
968 hide_secondary_monitors();
969 else
970 show_secondary_monitors();
971 }
972
973 static gint
cb_panel_scroll(GtkWidget * widget,GdkEventScroll * ev)974 cb_panel_scroll(GtkWidget *widget, GdkEventScroll *ev)
975 {
976 if (ev->direction == GDK_SCROLL_UP)
977 hide_secondary_monitors();
978 if (ev->direction == GDK_SCROLL_DOWN)
979 show_secondary_monitors();
980 return FALSE;
981 }
982
983 static gint
cb_panel_release(GtkWidget * widget,GdkEventButton * ev,FSmon * fs)984 cb_panel_release(GtkWidget *widget, GdkEventButton *ev, FSmon *fs)
985 {
986 if (ev->button == 3)
987 return TRUE;
988 if (fs_in_motion)
989 {
990 if (fs_in_motion->restore_label)
991 {
992 if (fs_in_motion->label_is_data)
993 gkrellm_config_modified();
994 fs_in_motion->label_is_data = FALSE;
995 fs_draw_decal_text(fs_in_motion, 0);
996 gkrellm_show_button(fs_in_motion->drawer_button);
997 gkrellm_draw_panel_layers(fs_in_motion->panel);
998 }
999 fs_in_motion->restore_label = TRUE;
1000 }
1001 force_fs_check = FORCE_REDRAW; /* Move krells back */
1002 fs_in_motion = NULL;
1003 x_moved = 0;
1004 return FALSE;
1005 }
1006
1007 static gint
cb_panel_press(GtkWidget * widget,GdkEventButton * ev,FSmon * fs)1008 cb_panel_press(GtkWidget *widget, GdkEventButton *ev, FSmon *fs)
1009 {
1010 GkrellmDecal *d;
1011
1012 d = fs->eject_decal ? fs->eject_decal : fs->mount_decal;
1013
1014 if (ev->button == 3 && ev->x < d->x)
1015 {
1016 gkrellm_open_config_window(mon_fs);
1017 return TRUE;
1018 }
1019 #if 0
1020 if ( ev->button == 1
1021 && ( (fs->drawer_button
1022 && gkrellm_in_decal(fs->drawer_button->decal, ev))
1023 || ev->x >= d->x
1024 )
1025 )
1026 return FALSE;
1027 #endif
1028
1029 if (!fs->label_is_data)
1030 {
1031 fs->label_is_data = TRUE;
1032 fs->restore_label = FALSE;
1033 fs->mouse_entered = TRUE;
1034 gkrellm_config_modified();
1035 }
1036 x_fs_motion = ev->x;
1037 fs_draw_decal_text(fs, 1);
1038 gkrellm_draw_panel_layers(fs->panel);
1039 fs_in_motion = fs;
1040 x_moved = 0;
1041 gkrellm_hide_button(fs->drawer_button);
1042 return TRUE;
1043 }
1044
1045 static gint
cb_panel_motion(GtkWidget * widget,GdkEventButton * ev)1046 cb_panel_motion(GtkWidget *widget, GdkEventButton *ev)
1047 {
1048 GdkModifierType state;
1049 GList *list;
1050 FSmon *fs;
1051 GkrellmDecal *d;
1052 gchar buf[128];
1053 gint w, x_delta = 0;
1054
1055 state = ev->state;
1056 if ( !fs_in_motion
1057 || !(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK))
1058 || !fs_in_motion->label_is_data
1059 )
1060 {
1061 fs_in_motion = NULL;
1062 return FALSE;
1063 }
1064
1065 d = fs_in_motion->data_decal;
1066 format_fs_data(fs_in_motion, data_format_locale, buf, sizeof(buf));
1067 gkrellm_decal_scroll_text_get_size(d, &w, NULL);
1068 if (w > d->w)
1069 {
1070 x_delta = ev->x - x_fs_motion;
1071 x_fs_motion = ev->x;
1072 d->x_off += x_delta;
1073 if (d->x_off < -w)
1074 d->x_off = -w;
1075 if (d->x_off > d->w)
1076 d->x_off = d->w;
1077 x_scroll = d->w / 3 - d->x_off;
1078 for (list = fs_mon_list; list; list = list->next)
1079 {
1080 fs = (FSmon *) list->data;
1081 if (fs->label_is_data)
1082 {
1083 fs_draw_decal_text(fs, 1);
1084 gkrellm_draw_panel_layers(fs->panel);
1085 }
1086 }
1087 if (x_moved > 0)
1088 fs_in_motion->restore_label = FALSE;
1089 }
1090 if (x_moved == 0)
1091 force_fs_check = FORCE_REDRAW; /* Move krells out of the way */
1092 x_moved += (x_delta > 0) ? x_delta : -x_delta;
1093 return FALSE;
1094 }
1095
1096 static void
cb_fs_mount_button(GkrellmDecalbutton * button)1097 cb_fs_mount_button(GkrellmDecalbutton *button)
1098 {
1099 if (button)
1100 mount_command((FSmon *) button->data);
1101 }
1102
1103 static void
cb_fs_eject_button(GkrellmDecalbutton * button,FSmon * fs)1104 cb_fs_eject_button(GkrellmDecalbutton *button, FSmon *fs)
1105 {
1106 if (button)
1107 eject_tray(fs);
1108 }
1109
1110 static void
cb_fs_close_tray(GkrellmDecalbutton * button,FSmon * fs)1111 cb_fs_close_tray(GkrellmDecalbutton *button, FSmon *fs)
1112 {
1113 if (button)
1114 close_tray(fs);
1115 }
1116
1117 static void
fs_monitor_create(GtkWidget * vbox,FSmon * fs,gint index,gint first_create)1118 fs_monitor_create(GtkWidget *vbox, FSmon *fs, gint index, gint first_create)
1119 {
1120 GkrellmStyle *style;
1121 GkrellmTextstyle *ts;
1122 GkrellmMargin *m;
1123 GkrellmPanel *p;
1124 gchar buf[256];
1125 gint h, label_x_position, label_y_off;
1126 gint h_data, h_label;
1127
1128 if (first_create)
1129 fs->panel = gkrellm_panel_new0();
1130 p = fs->panel;
1131 fs->idx = index;
1132 ++n_fs_monitors;
1133 fs->krell_factor = 1;
1134
1135 style = gkrellm_meter_style(style_id);
1136 ts = gkrellm_meter_textstyle(style_id);
1137 m = gkrellm_get_style_margins(style);
1138
1139 gkrellm_panel_label_get_position(style, &label_x_position, &label_y_off);
1140
1141 format_fs_data(fs, data_format_locale, buf, sizeof(buf));
1142 fs->data_decal = gkrellm_create_decal_text_markup(p, buf,
1143 ts, style, -1,
1144 (label_y_off > 0) ? label_y_off : -1,
1145 -1);
1146 gkrellm_decal_get_size(fs->data_decal, NULL, &h_data);
1147
1148 fs->label_decal = gkrellm_create_decal_text_markup(p, fs->label_shadow,
1149 ts, style, -1,
1150 (label_y_off > 0) ? label_y_off : -1,
1151 -1);
1152 gkrellm_decal_get_size(fs->label_decal, NULL, &h_label);
1153
1154 if (h_data > h_label)
1155 gkrellm_move_decal(p, fs->label_decal, fs->label_decal->x,
1156 fs->label_decal->y + (h_data - h_label + 1) / 2);
1157 else if (h_data < h_label)
1158 gkrellm_move_decal(p, fs->data_decal, fs->data_decal->x,
1159 fs->data_decal->y + (h_label - h_data + 1) / 2);
1160
1161 fs->mount_decal = gkrellm_create_decal_pixmap(p,
1162 gkrellm_decal_misc_pixmap(), gkrellm_decal_misc_mask(),
1163 N_MISC_DECALS, style, -1, -1);
1164 fs->mount_decal->x =
1165 gkrellm_chart_width() - fs->mount_decal->w - m->right;
1166
1167 if (fs->ejectable)
1168 {
1169 fs->eject_decal = gkrellm_create_decal_pixmap(p,
1170 gkrellm_decal_misc_pixmap(), gkrellm_decal_misc_mask(),
1171 N_MISC_DECALS, style, -1, -1);
1172 if (mounting_supported)
1173 {
1174 x_eject_button_closed = fs->mount_decal->x;
1175 x_eject_button_open = fs->mount_decal->x - fs->eject_decal->w + 1;
1176 }
1177 else
1178 {
1179 x_eject_button_closed = gkrellm_chart_width() - 2;
1180 x_eject_button_open = x_eject_button_closed - fs->eject_decal->w;
1181 }
1182 fs->x_eject_button_target = x_eject_button_closed;
1183 fs->eject_decal->x = x_eject_button_closed;
1184 }
1185
1186 /* Usable width to determine various scrolling parameters.
1187 */
1188 data_decal_width = fs->mount_decal->x - fs->data_decal->x;
1189
1190 fs->krell = gkrellm_create_krell(p,
1191 gkrellm_krell_meter_piximage(style_id), style);
1192 gkrellm_monotonic_krell_values(fs->krell, FALSE);
1193
1194 gkrellm_panel_configure(p, NULL, style);
1195 gkrellm_panel_create(vbox, mon_fs, p);
1196
1197 fs->md_button = gkrellm_make_decal_button(p, fs->mount_decal,
1198 cb_fs_mount_button, fs, D_MISC_FS_UMOUNTED, D_MISC_FS_PRESSED);
1199 if (index == 0 && have_secondary_panels)
1200 {
1201 if ((h = p->h / 2) > 7)
1202 h = 7;
1203 fs->drawer_button = gkrellm_make_scaled_button(p, NULL,
1204 cb_drawer_button, fs, TRUE, TRUE,
1205 0, 0, 0, /* NULL image => builtin depth & indices */
1206 (gkrellm_chart_width() - 20) / 2, 0,
1207 20, h);
1208 /* Make it appear under the label decal */
1209 gkrellm_remove_decal(p, fs->drawer_button->decal);
1210 gkrellm_insert_decal_nth(p, fs->drawer_button->decal, 0);
1211 }
1212 if (fs->eject_decal)
1213 {
1214 fs->eject_button = gkrellm_make_decal_button(p, fs->eject_decal,
1215 cb_fs_eject_button, fs, D_MISC_BUTTON_OUT, D_MISC_BUTTON_IN);
1216 gkrellm_hide_button(fs->eject_button);
1217 if (close_cdrom_command || close_cdrom_func)
1218 gkrellm_decal_button_right_connect(fs->eject_button,
1219 cb_fs_close_tray, fs);
1220 }
1221 if (first_create)
1222 {
1223 g_signal_connect(G_OBJECT(p->drawing_area), "expose_event",
1224 G_CALLBACK(fs_expose_event), NULL);
1225 g_signal_connect(G_OBJECT(p->drawing_area),"button_press_event",
1226 G_CALLBACK(cb_panel_press), fs);
1227 g_signal_connect(G_OBJECT(p->drawing_area),"button_release_event",
1228 G_CALLBACK(cb_panel_release), fs);
1229 g_signal_connect(G_OBJECT(p->drawing_area),"scroll_event",
1230 G_CALLBACK(cb_panel_scroll), fs);
1231 g_signal_connect(G_OBJECT(p->drawing_area),"motion_notify_event",
1232 G_CALLBACK(cb_panel_motion), NULL);
1233 g_signal_connect(G_OBJECT(p->drawing_area), "enter_notify_event",
1234 G_CALLBACK(cb_panel_enter), fs);
1235 g_signal_connect(G_OBJECT(p->drawing_area), "leave_notify_event",
1236 G_CALLBACK(cb_panel_leave), fs);
1237 if ( !secondary_monitors_shown && fs->secondary
1238 && (!fs_is_mounted(fs) || !fs->show_if_mounted))
1239 gkrellm_panel_hide(fs->panel);
1240 }
1241
1242 fs_draw_decal_text(fs, 0);
1243 force_fs_check = FORCE_UPDATE;
1244
1245 if (fs->launch_mount.command == NULL)
1246 fs->launch_mount.command = g_strdup("");
1247 if (fs->launch_umount.command == NULL)
1248 fs->launch_umount.command = g_strdup("");
1249 }
1250
1251 static void
free_fsmon_strings(FSmon * fs)1252 free_fsmon_strings(FSmon *fs)
1253 {
1254 g_free(fs->label);
1255 g_free(fs->label_shadow);
1256 g_free(fs->mount.directory);
1257 g_free(fs->eject_device);
1258 g_free(fs->launch_mount.command);
1259 g_free(fs->launch_umount.command);
1260 }
1261
1262 static void
destroy_fs_monitor(FSmon * fs)1263 destroy_fs_monitor(FSmon *fs)
1264 {
1265 gkrellm_reset_alert(fs->alert);
1266 free_fsmon_strings(fs);
1267 gkrellm_panel_destroy(fs->panel);
1268 g_free(fs);
1269 --n_fs_monitors;
1270 }
1271
1272 static void
fs_create(GtkWidget * vbox,gint first_create)1273 fs_create(GtkWidget *vbox, gint first_create)
1274 {
1275 GList *list;
1276 FSmon *fs;
1277 gint i;
1278
1279 if (fs_main_vbox == NULL)
1280 {
1281 fs_main_vbox = gtk_vbox_new(FALSE, 0);
1282 gtk_box_pack_start(GTK_BOX(vbox), fs_main_vbox, FALSE, FALSE, 0);
1283 gtk_widget_show(fs_main_vbox);
1284
1285 fs_secondary_vbox = gtk_vbox_new(FALSE, 0);
1286 gtk_box_pack_start(GTK_BOX(vbox), fs_secondary_vbox, FALSE, FALSE, 0);
1287 gtk_widget_show(fs_secondary_vbox);
1288 secondary_monitors_shown = FALSE;
1289 }
1290 n_fs_monitors = 0;
1291 for (i = 0, list = fs_mon_list; list; ++i, list = list->next)
1292 {
1293 fs = (FSmon *)list->data;
1294 fs_monitor_create(fs->secondary ? fs_secondary_vbox : fs_main_vbox,fs,
1295 i, first_create);
1296 }
1297 if (g_list_length(fs_mon_list) == 0)
1298 gkrellm_spacers_hide(mon_fs);
1299 }
1300
1301 #define FS_CONFIG_KEYWORD "fs"
1302
1303 static void
cb_alert_trigger(GkrellmAlert * alert,FSmon * fs)1304 cb_alert_trigger(GkrellmAlert *alert, FSmon *fs)
1305 {
1306 /* Full panel alert, default decal.
1307 */
1308 alert->panel = fs->panel;
1309 }
1310
1311 static void
create_alert(FSmon * fs)1312 create_alert(FSmon *fs)
1313 {
1314 fs->alert = gkrellm_alert_create(NULL, fs->label,
1315 _("Percent Usage"),
1316 TRUE, FALSE, TRUE,
1317 100, 10, 1, 10, 0);
1318 gkrellm_alert_trigger_connect(fs->alert, cb_alert_trigger, fs);
1319 gkrellm_alert_config_connect(fs->alert, cb_alert_config, fs);
1320 gkrellm_alert_command_process_connect(fs->alert, cb_command_process, fs);
1321 }
1322
1323 static void
fs_config_save(FILE * f)1324 fs_config_save(FILE *f)
1325 {
1326 GList *list;
1327 FSmon *fs;
1328 gchar quoted_label[64], quoted_dir[512];
1329
1330 for (list = fs_mon_list; list; list = list->next)
1331 {
1332 fs = (FSmon *) list->data;
1333 snprintf(quoted_label, sizeof(quoted_label), "\"%s\"", fs->label);
1334 snprintf(quoted_dir, sizeof(quoted_dir), "\"%s\"",fs->mount.directory);
1335 fprintf(f, "%s %s %s %d %d %d %d %d\n", FS_CONFIG_KEYWORD,
1336 quoted_label, quoted_dir,
1337 fs->fstab_mounting, fs->secondary,
1338 fs->show_if_mounted, fs->label_is_data, fs->ejectable);
1339 if (*(fs->launch_mount.command))
1340 fprintf(f, "%s mount_command %s\n", FS_CONFIG_KEYWORD,
1341 fs->launch_mount.command);
1342 if (*(fs->launch_umount.command))
1343 fprintf(f, "%s umount_command %s\n", FS_CONFIG_KEYWORD,
1344 fs->launch_umount.command);
1345 if (*(fs->eject_device))
1346 fprintf(f, "%s eject_device %s\n", FS_CONFIG_KEYWORD,
1347 fs->eject_device);
1348 if (fs->alert)
1349 gkrellm_save_alertconfig(f, fs->alert,
1350 FS_CONFIG_KEYWORD, quoted_label);
1351 }
1352 if (!_GK.client_mode)
1353 {
1354 fprintf(f, "%s fs_check_timeout %d\n", FS_CONFIG_KEYWORD,
1355 fs_check_timeout);
1356 fprintf(f, "%s nfs_check_timeout %d\n", FS_CONFIG_KEYWORD,
1357 nfs_check_timeout);
1358 fprintf(f, "%s auto_eject %d\n", FS_CONFIG_KEYWORD, cdrom_auto_eject);
1359 }
1360 fprintf(f, "%s binary_units %d\n", FS_CONFIG_KEYWORD, binary_units);
1361 fprintf(f, "%s data_format %s\n", FS_CONFIG_KEYWORD, data_format);
1362 }
1363
1364 static gboolean
fstab_user_permission(Mount * m)1365 fstab_user_permission(Mount *m)
1366 {
1367 struct stat my_stat;
1368
1369 stat(m->device, &my_stat);
1370 if ( strstr(m->options, "user")
1371 || (strstr(m->options, "owner") && my_stat.st_uid == uid)
1372 )
1373 return TRUE;
1374 return FALSE;
1375 }
1376
1377 static gint
fix_fstab_mountable_changed(FSmon * fs)1378 fix_fstab_mountable_changed(FSmon *fs)
1379 {
1380 Mount *m;
1381
1382 if (!mounting_supported)
1383 return FALSE;
1384 m = in_fstab_list(fs->mount.directory);
1385 if ( (!m || (!fstab_user_permission(m) && uid != 0))
1386 && fs->fstab_mounting
1387 )
1388 {
1389 fs->fstab_mounting = FALSE;
1390 return TRUE;
1391 }
1392 return FALSE;
1393 }
1394
1395 static FSmon *
lookup_fs(gchar * name)1396 lookup_fs(gchar *name)
1397 {
1398 GList *list;
1399 FSmon *fs;
1400
1401 if (!name)
1402 return NULL;
1403 for (list = fs_mon_list; list; list = list->next)
1404 {
1405 fs = (FSmon *) list->data;
1406 if (!strcmp(fs->label, name))
1407 return fs;
1408 }
1409 return NULL;
1410 }
1411
1412 static void
fs_config_load(gchar * arg)1413 fs_config_load(gchar *arg)
1414 {
1415 static FSmon *fs_prev;
1416 FSmon *fs;
1417 gchar *cut_label, *cut_dir;
1418 gchar config[32], item[CFG_BUFSIZE];
1419 gchar name[64], item1[CFG_BUFSIZE];
1420 gint n;
1421
1422 if ((n = sscanf(arg, "%31s %[^\n]", config, item)) != 2)
1423 return;
1424
1425 if (!strcmp(config, "fs_check_timeout"))
1426 {
1427 sscanf(item, "%d", &fs_check_timeout);
1428 if (fs_check_timeout < 2)
1429 fs_check_timeout = 2;
1430 }
1431 else if (!strcmp(config, "nfs_check_timeout"))
1432 {
1433 sscanf(item, "%d", &nfs_check_timeout);
1434 if (nfs_check_timeout < 5)
1435 nfs_check_timeout = 5;
1436 }
1437 else if (!strcmp(config, "auto_eject"))
1438 sscanf(item, "%d", &cdrom_auto_eject);
1439 else if (!strcmp(config, "binary_units"))
1440 sscanf(item, "%d", &binary_units);
1441 else if (!strcmp(config, "data_format"))
1442 gkrellm_locale_dup_string(&data_format, item, &data_format_locale);
1443 else if (fs_prev && !strcmp(config, "mount_command"))
1444 gkrellm_dup_string(&fs_prev->launch_mount.command, item);
1445 else if (fs_prev && !strcmp(config, "umount_command"))
1446 gkrellm_dup_string(&fs_prev->launch_umount.command, item);
1447 else if (fs_prev && !strcmp(config, "eject_device"))
1448 {
1449 if (fs_prev->ejectable)
1450 gkrellm_dup_string(&fs_prev->eject_device, item);
1451 }
1452 else if (!strcmp(config, GKRELLM_ALERTCONFIG_KEYWORD))
1453 {
1454 if ( sscanf(item, "\"%63[^\"]\" %[^\n]", name, item1) == 2
1455 && (fs = lookup_fs(name)) != NULL
1456 )
1457 {
1458 if (!fs->alert)
1459 create_alert(fs);
1460 gkrellm_load_alertconfig(&fs->alert, item1);
1461 }
1462 }
1463 else
1464 {
1465 if ( (cut_label = gkrellm_cut_quoted_string(arg, &arg)) != NULL
1466 && (cut_dir = gkrellm_cut_quoted_string(arg, &arg)) != NULL
1467 )
1468 {
1469 fs = g_new0(FSmon, 1);
1470 gkrellm_locale_dup_string(&fs->label, cut_label,&fs->label_shadow);
1471
1472 sscanf(arg, "%d %d %d %d %d", &fs->fstab_mounting,
1473 &fs->secondary, &fs->show_if_mounted,
1474 &fs->label_is_data, &fs->ejectable);
1475 if (fs->fstab_mounting > 1) /* pre 2.0.0 config fix */
1476 fs->fstab_mounting = FALSE;
1477 if (!ejecting_supported)
1478 fs->ejectable = FALSE;
1479 if (!mounting_supported)
1480 fs->fstab_mounting = fs->show_if_mounted = FALSE;
1481 if (fs->secondary)
1482 have_secondary_panels = TRUE;
1483 fs->mount.directory = g_strdup(cut_dir);
1484 fs->restore_label = fs->label_is_data;
1485
1486 fix_fstab_mountable_changed(fs);
1487 fs->krell_factor = 1;
1488 fs->launch_mount.command = g_strdup("");
1489 fs->launch_umount.command = g_strdup("");
1490 fs->eject_device = g_strdup("");
1491 fs_mon_list = g_list_append(fs_mon_list, fs);
1492 fs_prev = fs; /* XXX */
1493 }
1494 }
1495 }
1496
1497
1498 /* --------------------------------------------------------------------- */
1499
1500 enum
1501 {
1502 NAME_COLUMN,
1503 MOUNT_POINT_COLUMN,
1504 SHOW_COLUMN,
1505 FSTAB_COLUMN,
1506 MOUNT_COMMAND_COLUMN,
1507 UMOUNT_COMMAND_COLUMN,
1508 EJECTABLE_COLUMN,
1509 DEVICE_COLUMN,
1510 FSMON_COLUMN,
1511 ALERT_COLUMN,
1512 SHOW_DATA_COLUMN,
1513 VISIBLE_COLUMN,
1514 IMAGE_COLUMN,
1515 N_COLUMNS
1516 };
1517
1518 static GtkTreeView *treeview;
1519 static GtkTreeRowReference *row_reference;
1520 static GtkTreeSelection *selection;
1521
1522 static GtkWidget
1523 *label_entry,
1524 *dir_combo_box,
1525 *mount_entry,
1526 *umount_entry,
1527 *mounting_button,
1528 *ejectable_button,
1529 *device_entry,
1530 *secondary_button,
1531 *show_button,
1532 *delete_button,
1533 *new_apply_button;
1534
1535 static GtkWidget *alert_button;
1536
1537 static GtkWidget *data_format_combo_box;
1538
1539 static gboolean (*original_row_drop_possible)();
1540
1541
1542 static void
set_tree_store_model_data(GtkTreeStore * tree,GtkTreeIter * iter,FSmon * fs)1543 set_tree_store_model_data(GtkTreeStore *tree, GtkTreeIter *iter, FSmon *fs)
1544 {
1545 gtk_tree_store_set(tree, iter,
1546 NAME_COLUMN, fs->label,
1547 MOUNT_POINT_COLUMN, fs->mount.directory,
1548 SHOW_COLUMN, fs->show_if_mounted,
1549 FSTAB_COLUMN, fs->fstab_mounting,
1550 MOUNT_COMMAND_COLUMN, fs->launch_mount.command,
1551 UMOUNT_COMMAND_COLUMN, fs->launch_umount.command,
1552 EJECTABLE_COLUMN, fs->ejectable,
1553 DEVICE_COLUMN, fs->eject_device,
1554 FSMON_COLUMN, fs,
1555 ALERT_COLUMN, fs->alert,
1556 SHOW_DATA_COLUMN, fs->label_is_data,
1557 VISIBLE_COLUMN, TRUE,
1558 -1);
1559 if (fs->alert)
1560 gtk_tree_store_set(tree, iter,
1561 IMAGE_COLUMN, gkrellm_alert_pixbuf(),
1562 -1);
1563 }
1564
1565 static GtkTreeModel *
create_model(void)1566 create_model(void)
1567 {
1568 GtkTreeStore *tree;
1569 GtkTreeIter iter, citer;
1570 GList *list;
1571 FSmon *fs;
1572
1573 tree = gtk_tree_store_new(N_COLUMNS,
1574 G_TYPE_STRING, G_TYPE_STRING,
1575 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
1576 G_TYPE_STRING, G_TYPE_STRING,
1577 G_TYPE_BOOLEAN, G_TYPE_STRING,
1578 G_TYPE_POINTER, G_TYPE_POINTER,
1579 G_TYPE_BOOLEAN,
1580 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF);
1581
1582 gtk_tree_store_append(tree, &iter, NULL);
1583 gtk_tree_store_set(tree, &iter,
1584 NAME_COLUMN, _("Primary"),
1585 VISIBLE_COLUMN, FALSE,
1586 -1);
1587 for (list = fs_mon_list; list; list = list->next)
1588 {
1589 fs = (FSmon *) list->data;
1590 if (fs->secondary)
1591 continue;
1592 gtk_tree_store_append(tree, &citer, &iter);
1593 set_tree_store_model_data(tree, &citer, fs);
1594 }
1595
1596 gtk_tree_store_append(tree, &iter, NULL);
1597 gtk_tree_store_set(tree, &iter,
1598 NAME_COLUMN, _("Secondary"),
1599 VISIBLE_COLUMN, FALSE,
1600 -1);
1601 for (list = fs_mon_list; list; list = list->next)
1602 {
1603 fs = (FSmon *) list->data;
1604 if (!fs->secondary)
1605 continue;
1606 gtk_tree_store_append(tree, &citer, &iter);
1607 set_tree_store_model_data(tree, &citer, fs);
1608 }
1609 return GTK_TREE_MODEL(tree);
1610 }
1611
1612 static void
change_row_reference(GtkTreeModel * model,GtkTreePath * path)1613 change_row_reference(GtkTreeModel *model, GtkTreePath *path)
1614 {
1615 gtk_tree_row_reference_free(row_reference);
1616 if (model && path)
1617 row_reference = gtk_tree_row_reference_new(model, path);
1618 else
1619 row_reference = NULL;
1620 }
1621
1622 static void
cb_set_alert(GtkWidget * button,gpointer data)1623 cb_set_alert(GtkWidget *button, gpointer data)
1624 {
1625 GtkTreeModel *model;
1626 GtkTreePath *path;
1627 GtkTreeIter iter;
1628 FSmon *fs;
1629
1630 if (!row_reference)
1631 return;
1632 model = gtk_tree_view_get_model(treeview);
1633 path = gtk_tree_row_reference_get_path(row_reference);
1634 gtk_tree_model_get_iter(model, &iter, path);
1635 gtk_tree_model_get(model, &iter, FSMON_COLUMN, &fs, -1);
1636
1637 if (!fs->alert)
1638 create_alert(fs);
1639 gkrellm_alert_config_window(&fs->alert);
1640 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1641 ALERT_COLUMN, fs->alert, -1);
1642 }
1643
1644 static gboolean
get_child_iter(GtkTreeModel * model,gchar * parent_node,GtkTreeIter * citer)1645 get_child_iter(GtkTreeModel *model, gchar *parent_node, GtkTreeIter *citer)
1646 {
1647 GtkTreePath *path;
1648 GtkTreeIter iter;
1649
1650 path = gtk_tree_path_new_from_string(parent_node);
1651 gtk_tree_model_get_iter(model, &iter, path);
1652 gtk_tree_path_free(path);
1653 return gtk_tree_model_iter_children(model, citer, &iter);
1654 }
1655
1656 /* Callback for a created or destroyed alert. Find the sensor in the model
1657 | and set the IMAGE_COLUMN.
1658 */
1659 static void
cb_alert_config(GkrellmAlert * ap,FSmon * fs)1660 cb_alert_config(GkrellmAlert *ap, FSmon *fs)
1661 {
1662 GtkTreeModel *model;
1663 GtkTreeIter iter;
1664 FSmon *fs_test;
1665 GdkPixbuf *pixbuf;
1666 gchar node[2];
1667 gint i;
1668
1669 if (!gkrellm_config_window_shown())
1670 return;
1671 model = gtk_tree_view_get_model(treeview);
1672 pixbuf = ap->activated ? gkrellm_alert_pixbuf() : NULL;
1673 for (i = 0; i < 2; ++i)
1674 {
1675 node[0] = '0' + i; /* toplevel Primary or Secondary node */
1676 node[1] = '\0';
1677 if (get_child_iter(model, node, &iter))
1678 do
1679 {
1680 gtk_tree_model_get(model, &iter, FSMON_COLUMN, &fs_test, -1);
1681 if (fs != fs_test)
1682 continue;
1683 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1684 IMAGE_COLUMN, pixbuf, -1);
1685 return;
1686 }
1687 while (gtk_tree_model_iter_next(model, &iter));
1688 }
1689 }
1690
1691 /* Watch what is going into the directory combo entry, compare it to
1692 | fstab entries and accordingly set sensitivity of the mounting_button.
1693 */
1694 static void
cb_combo_changed(GtkComboBox * widget,gpointer user_data)1695 cb_combo_changed(GtkComboBox *widget, gpointer user_data)
1696 {
1697 Mount *m;
1698 gchar *s;
1699 GtkWidget *entry;
1700
1701 if (!mounting_supported || _GK.client_mode)
1702 return;
1703
1704 entry = gtk_bin_get_child(GTK_BIN(dir_combo_box));
1705 s = gkrellm_gtk_entry_get_text(&entry);
1706 m = in_fstab_list(s);
1707 if (m && (fstab_user_permission(m) || uid == 0))
1708 {
1709 gtk_widget_set_sensitive(mounting_button, TRUE);
1710 if (GTK_TOGGLE_BUTTON(mounting_button)->active)
1711 {
1712 gtk_entry_set_text(GTK_ENTRY(mount_entry), "");
1713 gtk_entry_set_text(GTK_ENTRY(umount_entry), "");
1714 gtk_widget_set_sensitive(mount_entry, FALSE);
1715 gtk_widget_set_sensitive(umount_entry, FALSE);
1716 }
1717 }
1718 else
1719 {
1720 if (GTK_TOGGLE_BUTTON(mounting_button)->active)
1721 gtk_toggle_button_set_active(
1722 GTK_TOGGLE_BUTTON(mounting_button), FALSE);
1723 else
1724 {
1725 gtk_widget_set_sensitive(mount_entry, TRUE);
1726 gtk_widget_set_sensitive(umount_entry, TRUE);
1727 }
1728 gtk_widget_set_sensitive(mounting_button, FALSE);
1729 }
1730 }
1731
1732 static void
cb_mount_button_clicked(GtkWidget * widget)1733 cb_mount_button_clicked(GtkWidget *widget)
1734 {
1735 if (!mounting_supported || _GK.client_mode)
1736 return;
1737 if (GTK_TOGGLE_BUTTON(mounting_button)->active)
1738 {
1739 gtk_entry_set_text(GTK_ENTRY(mount_entry), "");
1740 gtk_entry_set_text(GTK_ENTRY(umount_entry), "");
1741 gtk_widget_set_sensitive(mount_entry, FALSE);
1742 gtk_widget_set_sensitive(umount_entry, FALSE);
1743 if (device_entry)
1744 {
1745 gtk_entry_set_text(GTK_ENTRY(device_entry), "");
1746 gtk_widget_set_sensitive(device_entry, FALSE);
1747 }
1748 }
1749 else
1750 {
1751 gtk_widget_set_sensitive(mount_entry, TRUE);
1752 gtk_widget_set_sensitive(umount_entry, TRUE);
1753 if ( ejectable_button
1754 && GTK_TOGGLE_BUTTON(ejectable_button)->active
1755 )
1756 gtk_widget_set_sensitive(device_entry, TRUE);
1757 }
1758 }
1759
1760 static void
cb_ejectable_button_clicked(GtkWidget * widget)1761 cb_ejectable_button_clicked(GtkWidget *widget)
1762 {
1763 gboolean fstab_mounting;
1764
1765 if (!mounting_supported || _GK.client_mode)
1766 return;
1767 fstab_mounting = GTK_TOGGLE_BUTTON(mounting_button)->active;
1768 if (GTK_TOGGLE_BUTTON(ejectable_button)->active)
1769 {
1770 gtk_widget_set_sensitive(device_entry, !fstab_mounting);
1771 }
1772 else
1773 {
1774 gtk_entry_set_text(GTK_ENTRY(device_entry), "");
1775 gtk_widget_set_sensitive(device_entry, FALSE);
1776 }
1777 }
1778
1779 static void
cb_secondary_button_clicked(GtkWidget * widget)1780 cb_secondary_button_clicked(GtkWidget *widget)
1781 {
1782 if (!mounting_supported) /* Show button is in client mode */
1783 return;
1784 if (GTK_TOGGLE_BUTTON(secondary_button)->active)
1785 gtk_widget_set_sensitive(show_button, TRUE);
1786 else
1787 {
1788 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_button), FALSE);
1789 gtk_widget_set_sensitive(show_button, FALSE);
1790 }
1791 }
1792
1793 static void
reset_entries(gboolean level0)1794 reset_entries(gboolean level0)
1795 {
1796 gtk_entry_set_text(GTK_ENTRY(label_entry), "");
1797 gtk_combo_box_set_active(GTK_COMBO_BOX(dir_combo_box), -1);
1798 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(secondary_button), level0);
1799 if (mounting_button)
1800 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mounting_button),FALSE);
1801 if (show_button)
1802 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_button), FALSE);
1803 if (ejectable_button)
1804 {
1805 gtk_toggle_button_set_active(
1806 GTK_TOGGLE_BUTTON(ejectable_button), FALSE);
1807 if (device_entry)
1808 gtk_entry_set_text(GTK_ENTRY(device_entry), "");
1809 }
1810 if (mount_entry)
1811 {
1812 gtk_entry_set_text(GTK_ENTRY(mount_entry), "");
1813 gtk_entry_set_text(GTK_ENTRY(umount_entry), "");
1814 }
1815 change_row_reference(NULL, NULL);
1816 gtk_tree_selection_unselect_all(selection);
1817 }
1818
1819 static FSmon *
fs_new_from_model(GtkTreeModel * model,GtkTreeIter * iter)1820 fs_new_from_model(GtkTreeModel *model, GtkTreeIter *iter)
1821 {
1822 FSmon *fs;
1823 gchar *label;
1824
1825 fs = g_new0(FSmon, 1);
1826 gtk_tree_model_get(model, iter,
1827 NAME_COLUMN, &label,
1828 MOUNT_POINT_COLUMN, &fs->mount.directory,
1829 SHOW_COLUMN, &fs->show_if_mounted,
1830 FSTAB_COLUMN, &fs->fstab_mounting,
1831 MOUNT_COMMAND_COLUMN, &fs->launch_mount.command,
1832 UMOUNT_COMMAND_COLUMN, &fs->launch_umount.command,
1833 EJECTABLE_COLUMN, &fs->ejectable,
1834 DEVICE_COLUMN, &fs->eject_device,
1835 ALERT_COLUMN, &fs->alert,
1836 SHOW_DATA_COLUMN, &fs->label_is_data,
1837 -1);
1838 gkrellm_locale_dup_string(&fs->label, label, &fs->label_shadow);
1839 g_free(label);
1840 return fs;
1841 }
1842
1843 static void
cb_tree_selection_changed(GtkTreeSelection * selection,gpointer data)1844 cb_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
1845 {
1846 GtkTreeIter iter;
1847 GtkTreeModel *model;
1848 GtkTreePath *path;
1849 FSmon *fs;
1850 gint *indices, depth, secondary;
1851
1852 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1853 {
1854 reset_entries(FALSE);
1855 gtk_button_set_label(GTK_BUTTON(new_apply_button), GTK_STOCK_NEW);
1856 gtk_widget_set_sensitive(delete_button, FALSE);
1857 gtk_widget_set_sensitive(alert_button, FALSE);
1858 return;
1859 }
1860 path = gtk_tree_model_get_path(model, &iter);
1861 indices = gtk_tree_path_get_indices(path);
1862 secondary = indices[0];
1863 depth = gtk_tree_path_get_depth(path);
1864 // g_debug("selection: indices=[%d,%d]:%d, path=%s\n",
1865 // indices[0], indices[1], gtk_tree_path_get_depth(path),
1866 // gtk_tree_path_to_string(path));
1867 change_row_reference(model, path);
1868 gtk_tree_path_free(path);
1869
1870 if (depth == 1)
1871 {
1872 reset_entries(secondary);
1873 gtk_button_set_label(GTK_BUTTON(new_apply_button), GTK_STOCK_NEW);
1874 gtk_widget_set_sensitive(delete_button, FALSE);
1875 gtk_widget_set_sensitive(alert_button, FALSE);
1876 return;
1877 }
1878 gtk_button_set_label(GTK_BUTTON(new_apply_button), GTK_STOCK_APPLY);
1879 gtk_widget_set_sensitive(delete_button, TRUE);
1880 gtk_widget_set_sensitive(alert_button, TRUE);
1881
1882 fs = fs_new_from_model(model, &iter);
1883 if (!secondary)
1884 fs->show_if_mounted = FALSE; /* in case dragged secondary->primary*/
1885
1886 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(secondary_button),
1887 secondary);
1888 gtk_entry_set_text(GTK_ENTRY(label_entry), fs->label);
1889 gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(dir_combo_box))),
1890 fs->mount.directory);
1891 if (show_button)
1892 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_button),
1893 fs->show_if_mounted);
1894 if (mounting_button)
1895 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mounting_button),
1896 fs->fstab_mounting);
1897 if (ejectable_button)
1898 {
1899 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ejectable_button),
1900 fs->ejectable);
1901 if (device_entry)
1902 {
1903 gtk_entry_set_text(GTK_ENTRY(device_entry), fs->eject_device);
1904 if (!fs->ejectable)
1905 gtk_widget_set_sensitive(device_entry, FALSE);
1906 }
1907 }
1908 if (mount_entry)
1909 {
1910 gtk_entry_set_text(GTK_ENTRY(mount_entry), fs->launch_mount.command);
1911 gtk_entry_set_text(GTK_ENTRY(umount_entry), fs->launch_umount.command);
1912 }
1913 free_fsmon_strings(fs);
1914 g_free(fs);
1915 }
1916
1917 static void
sync_fs_panels(void)1918 sync_fs_panels(void)
1919 {
1920 GtkTreeModel *model;
1921 GtkTreePath *path;
1922 GtkTreeIter iter0, iter1, iter;
1923 GList *list;
1924 FSmon *fs;
1925
1926 model = gtk_tree_view_get_model(treeview);
1927
1928 path = gtk_tree_path_new_from_string("0");
1929 gtk_tree_model_get_iter(model, &iter0, path);
1930 gtk_tree_path_free(path);
1931
1932 path = gtk_tree_path_new_from_string("1");
1933 gtk_tree_model_get_iter(model, &iter1, path);
1934 gtk_tree_path_free(path);
1935
1936 if ( gtk_tree_model_iter_has_child(model, &iter1)
1937 && !gtk_tree_model_iter_has_child(model, &iter0)
1938 )
1939 {
1940 gkrellm_config_message_dialog(_("Entry Error"),
1941 N_("At least one primary fs monitor must exist to click on in order to show\n"
1942 "secondary ones.\n"));
1943 }
1944
1945 for (list = fs_mon_list; list; list = list->next)
1946 destroy_fs_monitor((FSmon *) list->data);
1947 g_list_free(fs_mon_list);
1948 fs_mon_list = NULL;
1949 n_fs_monitors = 0;
1950 have_secondary_panels = gtk_tree_model_iter_has_child(model, &iter1);
1951
1952 if (gtk_tree_model_iter_children(model, &iter, &iter0))
1953 {
1954 do
1955 {
1956 fs = fs_new_from_model(model, &iter);
1957 fs->secondary = FALSE;
1958 fs->show_if_mounted = FALSE;
1959 fs_mon_list = g_list_append(fs_mon_list, fs);
1960 fs_monitor_create(fs_main_vbox, fs, n_fs_monitors, TRUE);
1961 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1962 FSMON_COLUMN, fs, -1);
1963 gkrellm_alert_trigger_connect(fs->alert, cb_alert_trigger, fs);
1964 gkrellm_alert_config_connect(fs->alert, cb_alert_config, fs);
1965 }
1966 while (gtk_tree_model_iter_next(model, &iter));
1967 }
1968
1969 if (gtk_tree_model_iter_children(model, &iter, &iter1))
1970 {
1971 do
1972 {
1973 fs = fs_new_from_model(model, &iter);
1974 fs->secondary = TRUE;
1975 fs_mon_list = g_list_append(fs_mon_list, fs);
1976 fs_monitor_create(fs_secondary_vbox, fs, n_fs_monitors, TRUE);
1977 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1978 FSMON_COLUMN, fs, -1);
1979 gkrellm_alert_trigger_connect(fs->alert, cb_alert_trigger, fs);
1980 gkrellm_alert_config_connect(fs->alert, cb_alert_config, fs);
1981 }
1982 while (gtk_tree_model_iter_next(model, &iter));
1983 }
1984 else
1985 secondary_monitors_shown = FALSE;
1986
1987 force_fs_check = FORCE_UPDATE;
1988 if (g_list_length(fs_mon_list) > 0)
1989 gkrellm_spacers_show(mon_fs);
1990 else
1991 gkrellm_spacers_hide(mon_fs);
1992 }
1993
1994 static void
add_cb(GtkWidget * widget)1995 add_cb(GtkWidget *widget)
1996 {
1997 GtkTreeModel *model;
1998 GtkTreePath *path = NULL;
1999 GtkTreeIter iter, parent_iter;
2000 FSmon *fs;
2001 gchar *label;
2002 gint secondary, *indices;
2003 gboolean a, b, err = FALSE;
2004 GtkWidget *entry;
2005
2006 fs = g_new0(FSmon, 1);
2007 fs->launch_mount.command = g_strdup("");
2008 fs->launch_umount.command = g_strdup("");
2009 fs->eject_device = g_strdup("");
2010
2011 label = gkrellm_gtk_entry_get_text(&label_entry);
2012 gkrellm_locale_dup_string(&fs->label, label, &fs->label_shadow);
2013
2014 entry = gtk_bin_get_child(GTK_BIN(dir_combo_box));
2015 fs->mount.directory = g_strdup(gkrellm_gtk_entry_get_text(&entry));
2016
2017 if (show_button)
2018 fs->show_if_mounted = GTK_TOGGLE_BUTTON(show_button)->active;
2019 if (mounting_button)
2020 fs->fstab_mounting = GTK_TOGGLE_BUTTON(mounting_button)->active;
2021 if (mount_entry)
2022 {
2023 gkrellm_dup_string(&(fs->launch_mount.command),
2024 gkrellm_gtk_entry_get_text(&mount_entry));
2025 gkrellm_dup_string(&(fs->launch_umount.command),
2026 gkrellm_gtk_entry_get_text(&umount_entry));
2027 }
2028 if (ejectable_button)
2029 {
2030 fs->ejectable = GTK_TOGGLE_BUTTON(ejectable_button)->active;
2031 if (fs->ejectable && !fs->fstab_mounting && device_entry)
2032 gkrellm_dup_string(&(fs->eject_device),
2033 gkrellm_gtk_entry_get_text(&device_entry));
2034 }
2035 if (!*(fs->label) || !*(fs->mount.directory))
2036 {
2037 gkrellm_config_message_dialog(_("Entry Error"),
2038 #if !defined(WIN32)
2039 _("Both a label and a mount point must be entered."));
2040 #else
2041 "Both a label and a disk must be entered.");
2042 #endif
2043 err = TRUE;
2044 }
2045 a = (*(fs->launch_mount.command) != '\0');
2046 b = (*(fs->launch_umount.command) != '\0');
2047 if (mounting_supported && !_GK.client_mode && ((a && !b) || (!a && b)))
2048 {
2049 gkrellm_config_message_dialog(_("Entry Error"),
2050 _("Both mount and umount commands must be entered."));
2051 err = TRUE;
2052 }
2053 if ( mounting_supported && !_GK.client_mode
2054 && fs->ejectable && !fs->fstab_mounting && !*fs->eject_device
2055 )
2056 {
2057 gkrellm_config_message_dialog(_("Entry Error"),
2058 _("Missing ejectable device entry."));
2059 err = TRUE;
2060 }
2061 if (err)
2062 {
2063 free_fsmon_strings(fs);
2064 g_free(fs);
2065 return;
2066 }
2067
2068 model = gtk_tree_view_get_model(treeview);
2069 secondary = GTK_TOGGLE_BUTTON(secondary_button)->active;
2070 if (row_reference)
2071 {
2072 path = gtk_tree_row_reference_get_path(row_reference);
2073 gtk_tree_model_get_iter(model, &iter, path);
2074 indices = gtk_tree_path_get_indices(path);
2075
2076 /* Have a row ref, but if user changed secondary button, remove the
2077 | row ref node and set path NULL so iter will be set as function of
2078 | secondary. row_ref will be invalidated below.
2079 */
2080 if (indices[0] != secondary)
2081 {
2082 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
2083 path = NULL;
2084 }
2085 }
2086 if (!path)
2087 {
2088 gtk_tree_model_iter_nth_child(model, &parent_iter, NULL, secondary);
2089 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &parent_iter);
2090 }
2091 set_tree_store_model_data(GTK_TREE_STORE(model), &iter, fs);
2092 if (!path)
2093 {
2094 /* If appending (not editing existing node) leave cursor at root level
2095 | and clear the entries anticipating another new entry.
2096 */
2097 path = gtk_tree_path_new_from_string(secondary ? "1" : "0");
2098 gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
2099 gtk_tree_path_free(path);
2100 reset_entries(secondary);
2101 }
2102 free_fsmon_strings(fs);
2103 g_free(fs);
2104 sync_fs_panels();
2105 }
2106
2107 static void
cb_delete(GtkWidget * widget)2108 cb_delete(GtkWidget *widget)
2109 {
2110 GtkTreeModel *model;
2111 GtkTreePath *path;
2112 GtkTreeIter iter;
2113 FSmon *fs;
2114
2115 if (!row_reference)
2116 return;
2117 model = gtk_tree_view_get_model(treeview);
2118 path = gtk_tree_row_reference_get_path(row_reference);
2119 gtk_tree_model_get_iter(model, &iter, path);
2120
2121 gtk_tree_model_get(model, &iter, FSMON_COLUMN, &fs, -1);
2122 gkrellm_alert_destroy(&fs->alert);
2123
2124 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
2125 reset_entries(FALSE);
2126 sync_fs_panels();
2127 }
2128
2129 static void
cb_data_format(GtkWidget * widget,gpointer data)2130 cb_data_format(GtkWidget *widget, gpointer data)
2131 {
2132 GList *list;
2133 FSmon *fs;
2134 GkrellmDecal *d;
2135 gchar *s, buf[256];
2136 gint h_data, h_label;
2137 GtkWidget *entry;
2138
2139 entry = gtk_bin_get_child(GTK_BIN(data_format_combo_box));
2140 s = gkrellm_gtk_entry_get_text(&entry);
2141
2142 /* In case Pango markup tags, don't accept line unless valid markup.
2143 | Ie, markup like <span ...> xxx </span> or <b> xxx </b>
2144 */
2145
2146 if ( strchr(s, '<') != NULL
2147 && !pango_parse_markup(s, -1, 0, NULL, NULL, NULL, NULL)
2148 )
2149 return;
2150
2151 if (gkrellm_locale_dup_string(&data_format, s, &data_format_locale))
2152 {
2153 for (list = fs_mon_list; list; list = list->next)
2154 {
2155 fs = (FSmon *) list->data;
2156 fs->label_decal->value = -1; /* Force redraw */
2157
2158 d = fs->data_decal;
2159
2160 format_fs_data(fs, data_format_locale, buf, sizeof(buf));
2161 gkrellm_text_markup_extents(d->text_style.font, buf, strlen(buf),
2162 NULL, &h_data, NULL, NULL);
2163 h_data += d->text_style.effect;
2164 h_label = fs->label_decal->h;
2165
2166 /* Rebuild fs mon panels if new format string height extents
2167 | are wrong for current label/data decals.
2168 */
2169 if ( (d->h >= h_label && h_data != d->h)
2170 || (d->h < h_label && h_data >= h_label)
2171 )
2172 {
2173 sync_fs_panels();
2174 break;
2175 }
2176 if (d->h < h_label && h_data < h_label && d->h != h_data)
2177 gkrellm_move_decal(fs->panel, d, d->x,
2178 d->y + (d->h - h_data) / 2);
2179 }
2180 }
2181 }
2182
2183 static void
cb_auto_eject(GtkWidget * button,gpointer data)2184 cb_auto_eject(GtkWidget *button, gpointer data)
2185 {
2186 cdrom_auto_eject = GTK_TOGGLE_BUTTON(button)->active;
2187 }
2188
2189 static void
cb_binary_units(GtkWidget * button,gpointer data)2190 cb_binary_units(GtkWidget *button, gpointer data)
2191 {
2192 binary_units = GTK_TOGGLE_BUTTON(button)->active;
2193 }
2194
2195 static void
cb_check_interval(GtkWidget * widget,GtkSpinButton * spin)2196 cb_check_interval(GtkWidget *widget, GtkSpinButton *spin)
2197 {
2198 fs_check_timeout = gtk_spin_button_get_value_as_int(spin);
2199 }
2200
2201 static void
cb_nfs_check_interval(GtkWidget * widget,GtkSpinButton * spin)2202 cb_nfs_check_interval(GtkWidget *widget, GtkSpinButton *spin)
2203 {
2204 nfs_check_timeout = gtk_spin_button_get_value_as_int(spin);
2205 }
2206
2207 /* Allow destination drops only on depth 2 paths and don't allow drops from
2208 | source depths of 1 (top level nodes). Note: for some reason if I allow
2209 | drops on depth 3 nodes (destination is on top of a second level node) I
2210 | am not getting "drag_end" callbacks.
2211 */
2212 static gboolean
row_drop_possible(GtkTreeDragDest * drag_dest,GtkTreePath * path,GtkSelectionData * selection_data)2213 row_drop_possible(GtkTreeDragDest *drag_dest, GtkTreePath *path,
2214 GtkSelectionData *selection_data)
2215 {
2216 GtkTreePath *src_path;
2217
2218 if (!row_reference)
2219 return FALSE;
2220 src_path = gtk_tree_row_reference_get_path(row_reference);
2221
2222 if ( gtk_tree_path_get_depth(src_path) == 1
2223 || gtk_tree_path_get_depth(path) != 2
2224 )
2225 return FALSE;
2226
2227 return (*original_row_drop_possible)(drag_dest, path,
2228 selection_data);
2229 }
2230
2231 /* At each drag, divert the original Gtk row_drop_possible function to my
2232 | custom row_drop_possible so I can control tree structure. The original
2233 | row_drop_possible function must be restored at "drag_end" else other
2234 | monitors doing drag n' drop could get screwed.
2235 */
2236 static gboolean
cb_drag_begin(GtkWidget * widget,GdkDragContext * context,gpointer data)2237 cb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
2238 {
2239 GtkTreeModel *model;
2240 GtkTreeDragDestIface *dest_iface;
2241
2242 model = gtk_tree_view_get_model(treeview);
2243 dest_iface = GTK_TREE_DRAG_DEST_GET_IFACE(GTK_TREE_DRAG_DEST(model));
2244 if (!original_row_drop_possible)
2245 original_row_drop_possible = dest_iface->row_drop_possible;
2246 dest_iface->row_drop_possible = row_drop_possible;
2247 return FALSE;
2248 }
2249
2250 static gboolean
cb_drag_end(GtkWidget * widget,GdkDragContext * context,gpointer data)2251 cb_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
2252 {
2253 GtkTreeModel *model;
2254 GtkTreeDragDestIface *dest_iface;
2255
2256 model = gtk_tree_view_get_model(treeview);
2257 dest_iface = GTK_TREE_DRAG_DEST_GET_IFACE(GTK_TREE_DRAG_DEST(model));
2258 dest_iface->row_drop_possible = original_row_drop_possible;
2259
2260 reset_entries(FALSE);
2261 sync_fs_panels();
2262 return FALSE;
2263 }
2264
2265
2266 static void
create_fs_panels_page(GtkWidget * vbox)2267 create_fs_panels_page(GtkWidget *vbox)
2268 {
2269 GtkWidget *table;
2270 GtkWidget *hbox, *hbox1, *vbox1;
2271 GtkWidget *label;
2272 GtkWidget *scrolled;
2273 GtkTreeModel *model;
2274 GtkCellRenderer *renderer;
2275 GList *list;
2276
2277
2278 hbox = gtk_hbox_new(FALSE, 0);
2279 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2280 vbox1 = gkrellm_gtk_framed_vbox(hbox, NULL, 1, TRUE, 0, 2);
2281
2282 table = gtk_table_new(2, 2, FALSE);
2283 gtk_box_pack_start(GTK_BOX(vbox1), table, FALSE, FALSE, 0);
2284
2285 label = gtk_label_new(_("Label"));
2286 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
2287 GTK_SHRINK, GTK_SHRINK, 2, 1);
2288 label_entry = gtk_entry_new();
2289 // gtk_entry_set_max_length(GTK_ENTRY(label_entry), 16);
2290 gtk_widget_set_size_request(label_entry, 100, -1);
2291 gtk_table_attach_defaults(GTK_TABLE(table), label_entry, 1, 2, 0, 1);
2292
2293 #if !defined(WIN32)
2294 label = gtk_label_new(_("Mount Point"));
2295 #else
2296 label = gtk_label_new("Disk");
2297 #endif
2298 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
2299 GTK_SHRINK, GTK_SHRINK, 2, 1);
2300 dir_combo_box = gtk_combo_box_entry_new_text();
2301 gtk_table_attach_defaults(GTK_TABLE(table), dir_combo_box, 1, 2, 1, 2);
2302 for (list = fstab_list; list; list = list->next)
2303 {
2304 gtk_combo_box_append_text(GTK_COMBO_BOX(dir_combo_box),
2305 ((Mount *)list->data)->directory);
2306 }
2307 gtk_combo_box_set_active(GTK_COMBO_BOX(dir_combo_box), -1);
2308 g_signal_connect(G_OBJECT(GTK_COMBO_BOX(dir_combo_box)),
2309 "changed", G_CALLBACK(cb_combo_changed), NULL);
2310
2311 vbox1 = gtk_vbox_new(FALSE, 0);
2312 gtk_box_pack_start(GTK_BOX(hbox), vbox1, FALSE, FALSE, 0);
2313 hbox = gtk_hbox_new(FALSE, 0);
2314 gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
2315
2316 gkrellm_gtk_check_button_connected(hbox, &secondary_button, 0,
2317 TRUE, TRUE, 2, cb_secondary_button_clicked, NULL,
2318 _("Secondary"));
2319
2320
2321 if (mounting_supported)
2322 {
2323 gkrellm_gtk_check_button_connected(hbox, &show_button, 0,
2324 TRUE, TRUE, 2, NULL, NULL,
2325 _("Show if mounted"));
2326 gtk_widget_set_sensitive(show_button, FALSE);
2327 if (!_GK.client_mode)
2328 {
2329 gkrellm_gtk_check_button_connected(vbox1, &mounting_button, 0,
2330 FALSE, FALSE, 2, cb_mount_button_clicked, NULL,
2331 _("Enable /etc/fstab mounting"));
2332 gtk_widget_set_sensitive(mounting_button, FALSE);
2333 }
2334 }
2335
2336 hbox = gtk_hbox_new(FALSE, 0);
2337 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2338
2339 if (ejecting_supported && !_GK.client_mode)
2340 {
2341 vbox1 = gkrellm_gtk_framed_vbox(hbox, NULL, 1, FALSE, 0, 2);
2342
2343 gkrellm_gtk_check_button_connected(vbox1, &ejectable_button, 0,
2344 FALSE, FALSE, 0, cb_ejectable_button_clicked, NULL,
2345 _("Ejectable"));
2346
2347 if (mounting_supported)
2348 {
2349 hbox1 = gtk_hbox_new(FALSE, 0);
2350 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
2351 label = gtk_label_new(_("Device"));
2352 gtk_box_pack_start(GTK_BOX(hbox1), label, FALSE, FALSE, 2);
2353 device_entry = gtk_entry_new();
2354 gtk_entry_set_max_length(GTK_ENTRY(device_entry), 64);
2355 gtk_widget_set_size_request(device_entry, 100, -1);
2356 gtk_box_pack_start(GTK_BOX(hbox1), device_entry,
2357 FALSE, FALSE, 2);
2358 }
2359 }
2360
2361 if (mounting_supported && !_GK.client_mode)
2362 {
2363 vbox1 = gkrellm_gtk_framed_vbox(hbox, NULL, 1, TRUE, 0, 2);
2364 table = gkrellm_gtk_launcher_table_new(vbox1, 1); /* Won't have tooltip */
2365 gkrellm_gtk_config_launcher(table, 0, &mount_entry,
2366 NULL, _("mount"), NULL);
2367 gkrellm_gtk_config_launcher(table, 1, &umount_entry,
2368 NULL, _("umount"), NULL);
2369 }
2370 hbox = gtk_hbox_new(FALSE, 2);
2371 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
2372
2373 vbox1 = gtk_vbox_new(FALSE, 0);
2374 gtk_box_pack_end(GTK_BOX(hbox), vbox1, FALSE, FALSE, 5);
2375
2376 gkrellm_gtk_button_connected(vbox1, &new_apply_button, FALSE, FALSE, 4,
2377 add_cb, NULL, GTK_STOCK_NEW);
2378 GTK_WIDGET_SET_FLAGS(new_apply_button, GTK_CAN_DEFAULT);
2379 gtk_widget_grab_default(new_apply_button);
2380
2381 gkrellm_gtk_button_connected(vbox1, &delete_button, FALSE, FALSE, 4,
2382 cb_delete, NULL, GTK_STOCK_DELETE);
2383 gtk_widget_set_sensitive(delete_button, FALSE);
2384
2385 gkrellm_gtk_alert_button(vbox1, &alert_button, FALSE, FALSE, 4, FALSE,
2386 cb_set_alert, NULL);
2387 gtk_widget_set_sensitive(alert_button, FALSE);
2388
2389 scrolled = gtk_scrolled_window_new(NULL, NULL);
2390 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2391 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2392 gtk_box_pack_end(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0);
2393
2394 model = create_model();
2395
2396 treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
2397 g_object_unref(G_OBJECT(model));
2398 gtk_tree_view_set_rules_hint(treeview, TRUE);
2399 gtk_tree_view_set_reorderable(treeview, TRUE);
2400 g_signal_connect(G_OBJECT(treeview), "drag_begin",
2401 G_CALLBACK(cb_drag_begin), NULL);
2402 g_signal_connect(G_OBJECT(treeview), "drag_end",
2403 G_CALLBACK(cb_drag_end), NULL);
2404
2405 renderer = gtk_cell_renderer_text_new();
2406 // g_object_set(G_OBJECT(renderer), "xalign", 0.0, NULL);
2407 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Label"),
2408 renderer,
2409 "text", NAME_COLUMN, NULL);
2410 renderer = gtk_cell_renderer_text_new();
2411 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Mount Point"),
2412 renderer,
2413 "text", MOUNT_POINT_COLUMN,
2414 // "visible", VISIBLE_COLUMN,
2415 NULL);
2416
2417 renderer = gtk_cell_renderer_pixbuf_new();
2418 gtk_tree_view_insert_column_with_attributes(treeview, -1, "",
2419 renderer,
2420 "pixbuf", IMAGE_COLUMN,
2421 NULL);
2422
2423 gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
2424
2425 selection = gtk_tree_view_get_selection(treeview);
2426 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
2427 g_signal_connect(G_OBJECT(selection), "changed",
2428 G_CALLBACK(cb_tree_selection_changed), NULL);
2429 }
2430
2431
2432 static gchar *fs_info_text0[] =
2433 {
2434 N_("<h>Mounting\n"),
2435 N_("Enter file system mount points to monitor and enter a label to describe\n"
2436 "the mount point. The krell shows the ratio of blocks used to total blocks\n"
2437 "available. Mounting commands can be enabled for mount points in one\n"
2438 "of two ways:\n\n"),
2439
2440 N_("<b>\t1) Mounting using /etc/fstab: "),
2441
2442 N_("If a mount point is in your\n"
2443 "\t/etc/fstab and you have mount permission then mount and umount\n"
2444 "\tcommands can be enabled and executed for that mount point simply\n"
2445 "\tby checking the \"Enable /etc/fstab mounting\" option.\n"
2446 "\tMount table entries in /etc/fstab need the \"user\" or \"owner\" option\n"
2447 "\tset to grant this permission unless GKrellM is run as root.\n"
2448 "\tFor example, if you run GKrellM as a normal user and you want\n"
2449 "\tto be able to mount your floppy, your /etc/fstab could have\n"
2450 "\teither of:\n"),
2451
2452 N_("<i>\t\t/dev/fd0 /mnt/floppy ext2 user,noauto,rw,exec 0 0\n"),
2453 N_("\tor\n"),
2454 N_("<i>\t\t/dev/fd0 /mnt/floppy ext2 user,defaults 0 0\n\n"),
2455
2456 N_("<b>\t2) Mounting using custom commands: "),
2457 N_("If GKrellM is run as root or if\n"
2458 "\tyou have sudo permission to run the mount commands, then a custom\n"
2459 "\tmount command can be entered into the \"mount command\" entry\n"
2460 "\tbox. A umount command must also be entered if you choose this\n"
2461 "\tmethod. Example mount and umount entries using sudo:\n"),
2462
2463 N_("<i>\t\tsudo /bin/mount -t msdos /dev/fd0 /mnt/A\n"),
2464 N_("<i>\t\tsudo /bin/umount /mnt/A\n"),
2465
2466 N_("\tNotes: the mount point specified in a custom mount command\n"
2467 "\t(/mnt/A in this example) must be the same as entered in the\n"
2468 "\t\"Mount Point\" entry. You should have the NOPASSWD option set\n"
2469 "\tin /etc/sudoers if using sudo.\n\n"),
2470
2471 N_("<h>Primary and Secondary Monitors\n"), /* xgettext:no-c-format */
2472 N_("File system monitors can be created as primary (always visible)\n"
2473 "or secondary which can be hidden and then shown when they are of\n"
2474 "interest. For example, you might make primary file system monitors\n"
2475 "for root, home, or user so they will be always visible, but make\n"
2476 "secondary monitors for less frequently used mount points such as\n"
2477 "floppy, zip, backup partitions, foreign file system types, etc.\n"
2478 "Secondary FS monitors can also be configured to always be visible if they\n"
2479 "are mounted by checking the \"Show if mounted\" option. Using this\n"
2480 "feature you can show the secondary group, mount a file system, and have\n"
2481 "that FS monitor remain visible even when the secondary group is hidden.\n"
2482 "A standard cdrom mount will show as 100% full but a monitor for it\n"
2483 "could be created with mounting enabled just to have the\n"
2484 "mount/umount convenience.\n\n")
2485 };
2486
2487 static gchar *fs_info_text1[] =
2488 {
2489 N_("<h>Panel Labels\n"),
2490 N_("Substitution variables for the format string for file system panels:\n"),
2491 N_("\t$t total capacity\n"),
2492 N_("\t$u used space\n"),
2493 N_("\t$f free space\n"),
2494 N_("\t$U used %,\n"),
2495 N_("\t$F free %\n"),
2496 N_("\t$l the panel label\n"),
2497 #if !defined(WIN32)
2498 N_("\t$D the mount point\n"),
2499 #else
2500 N_("\t$D the disk\n"),
2501 #endif
2502 "\n",
2503 N_("Substitution variables may be used in alert commands.\n"),
2504 "\n",
2505 N_("<h>Mouse Button Actions:\n"),
2506 N_("<b>\tLeft "),
2507 N_("click on a panel to scroll a programmable display\n"),
2508 N_("\t\tof file system capacities (default is total and free space).\n"),
2509 N_("<b>\tWheel "),
2510 N_("Shows and hides the secondary file system monitors.\n")
2511 };
2512
2513 static void
fs_tab_create(GtkWidget * tab_vbox)2514 fs_tab_create(GtkWidget *tab_vbox)
2515 {
2516 GtkWidget *tabs;
2517 GtkWidget *vbox, *vbox1;
2518 GtkWidget *text;
2519 gint i;
2520
2521 row_reference = NULL;
2522 refresh_fstab_list();
2523
2524 tabs = gtk_notebook_new();
2525 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
2526 gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
2527
2528 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Panels"));
2529 create_fs_panels_page(vbox);
2530
2531 // vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Primary"));
2532 // fill_fs_tab(vbox, &primary_widgets);
2533
2534 // vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Secondary"));
2535 // fill_fs_tab(vbox, &secondary_widgets);
2536
2537 /* --Setup tab */
2538 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Setup"));
2539
2540 vbox1 = gkrellm_gtk_category_vbox(vbox,
2541 _("Options"),
2542 4, 0, TRUE);
2543 gkrellm_gtk_check_button_connected(vbox1, NULL,
2544 binary_units, FALSE, FALSE, 0,
2545 cb_binary_units, NULL,
2546 _("Use binary units (MiB, GiG) for reporting disk capacities."));
2547
2548 if (mounting_supported && ejecting_supported && !_GK.client_mode)
2549 gkrellm_gtk_check_button_connected(vbox1, NULL,
2550 cdrom_auto_eject, FALSE, FALSE, 0,
2551 cb_auto_eject, NULL,
2552 _("Auto eject when ejectable devices are unmounted"));
2553
2554 if (!_GK.client_mode)
2555 {
2556 vbox1 = gkrellm_gtk_framed_vbox_end(vbox, NULL, 4, FALSE, 0, 2);
2557 gkrellm_gtk_spin_button(vbox1, NULL,
2558 (gfloat) fs_check_timeout,
2559 2.0, 15.0, 1.0, 5.0, 0 /*digits*/, 0 /*width*/,
2560 cb_check_interval, NULL, FALSE,
2561 _("Seconds between data updates for local mounted file systems"));
2562 gkrellm_gtk_spin_button(vbox1, NULL,
2563 (gfloat) nfs_check_timeout,
2564 5.0, 60.0, 1.0, 5.0, 0, 0,
2565 cb_nfs_check_interval, NULL, FALSE,
2566 _("Seconds between data updates for remote mounted file systems"));
2567 }
2568
2569 vbox1 = gkrellm_gtk_category_vbox(vbox,
2570 _("Format String for Panel Labels"),
2571 4, 0, TRUE);
2572 data_format_combo_box = gtk_combo_box_entry_new_text();
2573 gtk_box_pack_start(GTK_BOX(vbox1), data_format_combo_box, FALSE, FALSE, 2);
2574 gtk_combo_box_append_text(GTK_COMBO_BOX(data_format_combo_box), data_format);
2575 gtk_combo_box_append_text(GTK_COMBO_BOX(data_format_combo_box), DEFAULT_DATA_FORMAT);
2576 gtk_combo_box_append_text(GTK_COMBO_BOX(data_format_combo_box), ALT1_DATA_FORMAT);
2577 gtk_combo_box_append_text(GTK_COMBO_BOX(data_format_combo_box), ALT2_DATA_FORMAT);
2578 gtk_combo_box_set_active(GTK_COMBO_BOX(data_format_combo_box), 0);
2579 g_signal_connect(G_OBJECT(GTK_COMBO_BOX(data_format_combo_box)), "changed",
2580 G_CALLBACK(cb_data_format), NULL);
2581
2582 /* --Info tab */
2583 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Info"));
2584 text = gkrellm_gtk_scrolled_text_view(vbox, NULL,
2585 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2586 if (mounting_supported && !_GK.client_mode)
2587 for (i = 0; i < sizeof(fs_info_text0)/sizeof(gchar *); ++i)
2588 gkrellm_gtk_text_view_append(text, _(fs_info_text0[i]));
2589 for (i = 0; i < sizeof(fs_info_text1)/sizeof(gchar *); ++i)
2590 gkrellm_gtk_text_view_append(text, _(fs_info_text1[i]));
2591 }
2592
2593
2594
2595 static GkrellmMonitor monitor_fs =
2596 {
2597 N_("File System"), /* Name, for config tab. */
2598 MON_FS, /* Id, 0 if a plugin */
2599 fs_create, /* The create function */
2600 fs_update, /* The update function */
2601 fs_tab_create, /* The config tab create function */
2602 NULL, /* Instant config */
2603
2604 fs_config_save, /* Save user conifg */
2605 fs_config_load, /* Load user config */
2606 FS_CONFIG_KEYWORD, /* config keyword */
2607
2608 NULL, /* Undef 2 */
2609 NULL, /* Undef 1 */
2610 NULL, /* Undef 0 */
2611
2612 0, /* insert_before_id - place plugin before this mon */
2613
2614 NULL, /* Handle if a plugin, filled in by GKrellM */
2615 NULL /* path if a plugin, filled in by GKrellM */
2616 };
2617
2618 GkrellmMonitor *
gkrellm_init_fs_monitor(void)2619 gkrellm_init_fs_monitor(void)
2620 {
2621 monitor_fs.name = _(monitor_fs.name);
2622 style_id = gkrellm_add_meter_style(&monitor_fs, FS_STYLE_NAME);
2623 gkrellm_locale_dup_string(&data_format, DEFAULT_DATA_FORMAT,
2624 &data_format_locale);
2625
2626 mon_fs = &monitor_fs;
2627 if (setup_fs_interface())
2628 {
2629 refresh_fstab_list();
2630 refresh_mounts_list();
2631 return &monitor_fs;
2632 }
2633 return NULL;
2634 }
2635