UPS: apcupsd clean sources
[tomato.git] / release / src / router / apcupsd / src / gapcmon / gapcmon.c
blobdfc5d0bc83937407c5c4f62f23eb25b0d4955fb2
1 /* gapcmon.c serial-0088-0 *****************************************
3 GKT+ GUI with Notification Area (System Tray) support. Program for
4 monitoring the apcupsd.sourceforge.net package.
5 Copyright (C) 2006 James Scott, Jr. <skoona@users.sourceforge.net>
7 Command Line Syntax: gapcmon [--help]
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* ************************************************************************** *
25 * Program Structure
26 * ------------------------ -------------------------------------------------
27 * GtkWindow Main Control Program Thread ----
28 * EggTrayIcon Notification system tray icon for main app.
29 * * GtkNotebook Main Interface
30 * * GtkTreeView Monitors pg: list of active monitors and state
31 * - EggTrayIcon Notification system tray icon for monitors.
32 * - GtkWindow Monitor Information Window -
33 * TrayIcon and InfoWindow compose a monitor
34 * * PG-n GtkNotebook Active monitor notebook with four pages;
35 * summary chart, detailed, eventlog, statuslog pages.
36 * - nbPage HISTORY A lg_Graph histogram line chart of
37 * LINEV, LOADPCT, BCHARGE, CUMONBATT, TIMELEFT
38 * g_timeout_add Monitor g_timeout per monitor for data updates
39 * g_timeout_add Monitor g_timeout per graph 1:30 collection updates
40 * - nbPage DETAILS Grouped results from the status output.
41 * - nbPage EVENTS Current events log
42 * - nbPage STATUS Current status log, same as APCACCESS
43 * * GtkTreeView Preferences pg: For Main app, and Monitors
44 * * GtkVBox About pg: Program copyright info
45 * * GtkHBox Action info
46 * - GtkLabel Program Title line
47 * - GtkButton Program Close button
48 * * GtkStatusbar Status message line
50 * ------------------------ ---------------------------------------------------
51 * + GConfClient Tied to Preferences page
52 * Produces direct change on application state and
53 * operation by monitoring changes to config values
54 * ------------------------ ---------------------------------------------------
55 * + GThread Network Communication via socket io using GIOChannels
56 * Communication to interface gtkthread through
57 * a GAsyncQueue, with additional instance mutex
58 * - protect hash table from multi-thread access
59 * - protect GTK from multi-thread access
60 * gdk_thread_[enter|leave] around gtk calls in timer
61 * routines and threads - and gtk_main_loop.
62 * ------------------------ ---------------------------------------------------
63 * GCONF2 Info
64 * CURRENT KEYS ARE:
65 * key /schemas/apps/gapcmon/controller/keys
66 * /apps/gapcmon/monitor/x/monitor-keys
67 * Where x is the internal monitor number.
68 * max monitors=unlimted or sizeof guint
69 * Where key is the actual keyname like enabled, host_name, port_name, or
70 * refresh_interval, etc.
71 * ************************************************************************** *
74 #include <unistd.h> /* close() */
75 #include <sys/types.h> /* socket() */
76 #include <sys/socket.h> /* socket() */
77 #include <netinet/in.h> /* sockaddr_in */
78 #include <arpa/inet.h> /* ntohs() */
79 #include <netinet/in.h> /* sockaddr_in */
80 #include <netdb.h> /* gethostbyname() */
81 #include <errno.h>
82 #include <string.h> /* memset() */
83 #include <time.h>
84 #include <stdlib.h> /* malloc() */
86 #include <gconf/gconf-client.h>
87 #include <gtk/gtk.h>
88 #include "eggtrayicon.h"
89 #include "gapcmon.h"
91 static gboolean cb_monitor_dedicated_one_time_refresh(PGAPC_MONITOR pm);
92 static gboolean cb_monitor_automatic_refresh(PGAPC_MONITOR pm);
93 static gboolean cb_monitor_refresh_control(PGAPC_MONITOR pm);
94 static gboolean gapc_monitor_update_tooltip_msg(PGAPC_MONITOR pm);
95 static gint gapc_monitor_update(PGAPC_MONITOR pm);
97 static gdouble gapc_util_point_filter_set(PGAPC_SUMS sq, gdouble this_point);
98 static gdouble gapc_util_point_filter_reset(PGAPC_SUMS sq);
99 static void lg_graph_set_chart_title (PLGRAPH plg, gchar * pch_text);
100 static void lg_graph_set_y_label_text (PLGRAPH plg, gchar * pch_text);
101 static void lg_graph_set_x_label_text (PLGRAPH plg, gchar * pch_text);
103 static void lg_graph_set_chart_title_color (PLGRAPH plg, gchar * pch_color);
104 static void lg_graph_set_chart_scales_color (PLGRAPH plg, gchar * pch_color);
105 static void lg_graph_set_chart_window_fg_color (PLGRAPH plg, gchar * pch_color);
106 static void lg_graph_set_chart_window_bg_color (PLGRAPH plg, gchar * pch_color);
108 static PLGRAPH lg_graph_create (GtkWidget * box, gint width, gint height);
109 static void lg_graph_set_ranges (PLGRAPH plg,
110 gint xminor_by,
111 gint xmajor_by,
112 gint x_min,
113 gint x_max,
114 gint yminor_by, gint ymajor_by, gint y_min, gint y_max);
115 static void lg_graph_redraw (PLGRAPH plg);
117 static gint lg_graph_data_series_add (PLGRAPH plg, gchar * pch_legend_text,
118 gchar * pch_color_text);
119 static gboolean lg_graph_data_series_remove_all (PLGRAPH plg);
120 static gboolean lg_graph_data_series_add_value (PLGRAPH plg, gint i_series_number,
121 gdouble y_value);
122 static gint lg_graph_data_series_draw (PLGRAPH plg, PLG_SERIES psd);
125 * Private Interfaces */
126 static gint lg_graph_draw_tooltip (PLGRAPH plg);
127 static gint lg_graph_data_series_draw_all (PLGRAPH plg, gboolean redraw_control);
128 static void lg_graph_get_default_sizes (PLGRAPH plg, gint * width, gint * height);
129 static void lg_graph_draw_x_grid_labels (PLGRAPH plg);
130 static void lg_graph_draw_y_grid_labels (PLGRAPH plg);
131 static gint lg_graph_draw_grid_lines (PLGRAPH plg);
132 static gint lg_graph_draw_horizontal_text (PLGRAPH plg,
133 gchar * pch_text,
134 GdkRectangle * rect, gboolean redraw_control);
135 static gint lg_graph_draw_vertical_text (PLGRAPH plg,
136 gchar * pch_text,
137 GdkRectangle * rect, gboolean redraw_control);
138 static gint lg_graph_draw (PLGRAPH plg);
139 static gint lg_graph_configure_event_cb (GtkWidget * widget,
140 GdkEventConfigure * event, PLGRAPH plg);
141 static gint lg_graph_expose_event_cb (GtkWidget * widget, GdkEventExpose * event,
142 PLGRAPH plg);
143 static gboolean lg_graph_motion_notify_event_cb (GtkWidget * widget, GdkEventMotion * ev,
144 PLGRAPH plg);
145 static gboolean lg_graph_button_press_event_cb (GtkWidget * widget, GdkEventButton * ev,
146 PLGRAPH plg);
147 static gboolean cb_util_barchart_handle_exposed(GtkWidget * widget,
148 GdkEventExpose * event, gpointer data);
149 static gboolean cb_util_line_chart_refresh(PGAPC_HISTORY pg);
151 static gboolean cb_util_manage_iconify_event(GtkWidget *widget,
152 GdkEventWindowState *event,
153 gpointer gp);
154 static void gapc_util_text_view_append(GtkWidget * view, gchar * pch);
155 static void gapc_util_text_view_prepend(GtkWidget * view, gchar * pch);
156 static gboolean gapc_util_text_view_clear_buffer(GtkWidget * view);
157 static gboolean gapc_util_treeview_get_iter_from_monitor(GtkTreeModel * model,
158 GtkTreeIter * iter, gint i_value);
159 static gint gapc_util_update_hashtable(PGAPC_MONITOR pm, gchar * pch_unparsed);
160 static void cb_panel_systray_icon_destroy(GtkObject * object, gpointer gp);
161 static void cb_main_interface_button_quit(GtkWidget * button, PGAPC_CONFIG pcfg);
162 static void gapc_monitor_interface_destroy(PGAPC_CONFIG pcfg, gint i_monitor);
163 static GtkWidget *gapc_monitor_interface_create(PGAPC_CONFIG pcfg, gint i_monitor,
164 GtkTreeIter * iter);
165 static void cb_panel_monitor_list_activated(GtkTreeView * treeview,
166 GtkTreePath * arg1, GtkTreeViewColumn * arg2, PGAPC_CONFIG pcfg);
167 static gint gapc_panel_glossary_page(PGAPC_CONFIG pcfg, GtkWidget * notebook);
168 static gint gapc_panel_graph_property_page(PGAPC_CONFIG pcfg, GtkWidget * notebook);
171 * Common interface to the various versions of gethostbyname_r().
172 * Implemented in gethostname.c.
174 struct hostent * gethostname_re
175 (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen);
178 * Some small number of globals are required
180 static gboolean lg_graph_debug = FALSE;
183 /* ************************************************************************* */
186 * Draws one data series points to chart
187 * returns number of points processed
189 static gint lg_graph_data_series_draw (PLGRAPH plg, PLG_SERIES psd)
191 gint v_index = 0;
192 GdkPoint *point_pos = NULL;
194 g_return_val_if_fail (plg != NULL, -1);
195 g_return_val_if_fail (psd != NULL, -1);
196 g_return_val_if_fail (psd->point_pos != NULL, -1);
198 gdk_gc_set_rgb_fg_color (plg->series_gc, &psd->legend_color);
199 gdk_gc_set_line_attributes (plg->series_gc, 2,
200 GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
202 point_pos = psd->point_pos;
204 /* trap first and only point */
205 if (psd->i_point_count == 0)
207 return 0;
209 if (psd->i_point_count == 1)
211 point_pos[0].x = plg->plot_box.x;
212 point_pos[0].y =
213 (plg->plot_box.y + plg->plot_box.height) -
214 ((psd->lg_point_dvalue[0] *
215 (gdouble) ((gdouble) plg->plot_box.height /
216 (gdouble) plg->y_range.i_max_scale)));
218 gdk_draw_arc (plg->pixmap, plg->series_gc, TRUE,
219 point_pos[0].x - 1, point_pos[0].y - 2, 3, 3, 0, 360 * 64);
220 return 1;
223 for (v_index = 0; v_index < psd->i_point_count; v_index++)
225 point_pos[v_index].x = plg->plot_box.x + (v_index * plg->x_range.i_minor_inc);
226 point_pos[v_index].y = (plg->plot_box.y + plg->plot_box.height) -
227 ((psd->lg_point_dvalue[v_index] *
228 (gdouble) ((gdouble) plg->plot_box.height /
229 (gdouble) plg->y_range.i_max_scale)));
231 if ((v_index != 0) && (v_index < psd->i_point_count - 1))
233 gdk_draw_arc (plg->pixmap, plg->series_gc, TRUE,
234 point_pos[v_index].x - 1,
235 point_pos[v_index].y - 2, 3, 3, 0, 360 * 64);
236 gdk_draw_arc (plg->pixmap, plg->series_gc, FALSE,
237 point_pos[v_index].x - 1,
238 point_pos[v_index].y - 2, 3, 3, 0, 360 * 64);
242 gdk_draw_lines (plg->pixmap, plg->series_gc, point_pos, psd->i_point_count);
244 return v_index;
248 * Draws all data series points to chart
249 * returns number of series processed, or -1 if not drawable
251 static gint lg_graph_data_series_draw_all (PLGRAPH plg, gboolean redraw_control)
253 PLG_SERIES psd = NULL;
254 GList *data_sets = NULL;
255 gint v_index = 0;
257 g_return_val_if_fail (plg != NULL, -1);
259 if ( !(GTK_WIDGET_DRAWABLE (plg->drawing_area)) ) {
260 return -1;
263 data_sets = g_list_first (plg->lg_series);
264 while (data_sets)
266 psd = data_sets->data;
267 if (psd != NULL)
268 { /* found */
269 lg_graph_data_series_draw (plg, psd);
270 v_index++;
272 data_sets = g_list_next (data_sets);
275 if (lg_graph_debug)
277 g_print ("DrawAllDataSeries: series=%d\n", v_index);
280 return v_index;
284 * Add a single value to the requested data series
285 * auto indexes the value is max is reach (appends to the end)
287 static gboolean lg_graph_data_series_add_value (PLGRAPH plg, gint i_series_number,
288 gdouble y_value)
290 PLG_SERIES psd = NULL;
291 GList *data_sets = NULL;
292 gint v_index = 0, time_count = 0;
293 gboolean b_found = FALSE;
295 g_return_val_if_fail (plg != NULL, FALSE);
297 data_sets = g_list_first (plg->lg_series);
298 while (data_sets)
300 psd = data_sets->data;
301 if (psd->i_series_id == i_series_number)
302 { /* found */
303 b_found = TRUE;
304 break;
306 data_sets = g_list_next (data_sets);
309 if (!b_found)
311 g_message ("lg_graph_data_series_add_value(%d): Invalid data series number",
312 i_series_number);
313 return FALSE;
316 if (y_value >= plg->y_range.i_max_scale)
318 y_value = (gdouble) plg->y_range.i_max_scale * 0.98;
321 if (psd->i_point_count == psd->i_max_points + 1)
323 for (v_index = 0; v_index < psd->i_max_points; v_index++)
325 psd->lg_point_dvalue[v_index] = psd->lg_point_dvalue[v_index + 1];
327 psd->lg_point_dvalue[psd->i_max_points] = y_value;
329 else
331 psd->lg_point_dvalue[psd->i_point_count++] = y_value;
334 psd->d_max_value = MAX (y_value, psd->d_max_value);
335 psd->d_min_value = MIN (y_value, psd->d_min_value);
337 plg->i_points_available = MAX (plg->i_points_available, psd->i_point_count);
339 /* record current time with data points */
340 if (psd->i_series_id == plg->i_num_series - 1)
342 GList *gl_remove = NULL;
344 gl_remove = g_list_first (plg->lg_series_time);
346 time_count = g_list_length (plg->lg_series_time);
347 if (time_count == psd->i_max_points + 1)
349 plg->lg_series_time =
350 g_list_remove_all (plg->lg_series_time, gl_remove->data);
352 plg->lg_series_time =
353 g_list_append (plg->lg_series_time, GINT_TO_POINTER ((time_t) time (NULL)));
356 if (lg_graph_debug)
358 g_print
359 ("DataSeriesAddValue: series=%d, value=%3.1f, index=%d, count=%d, time_count=%d, max_pts=%d\n",
360 i_series_number, y_value, v_index, psd->i_point_count, time_count, psd->i_max_points);
363 return TRUE;
367 * A shutdown routine
368 * destroys all the data series and any assocaited dynamic data
370 static gboolean lg_graph_data_series_remove_all (PLGRAPH plg)
372 PLG_SERIES psd = NULL;
373 GList *data_sets = NULL;
374 gint i_count = 0;
376 g_return_val_if_fail (plg != NULL, FALSE);
378 data_sets = g_list_first (plg->lg_series);
379 while (data_sets)
381 psd = data_sets->data;
382 g_free (psd->lg_point_dvalue);
383 g_free (psd->point_pos);
384 g_free (psd);
385 data_sets = g_list_next (data_sets);
386 i_count++;
388 g_list_free (plg->lg_series);
389 g_list_free (plg->lg_series_time);
390 plg->lg_series = NULL;
391 plg->lg_series_time = NULL;
392 plg->i_num_series = 0;
393 plg->i_points_available = 0;
395 if (lg_graph_debug)
397 g_print ("DataSeriesRemoveAll: series total=%d\n", i_count);
400 return TRUE;
404 * allocates space for another data series
405 * returns the series number of this dataset
407 static gint lg_graph_data_series_add (PLGRAPH plg, gchar * pch_legend_text,
408 gchar * pch_color_text)
410 PLG_SERIES psd = NULL;
412 g_return_val_if_fail (plg != NULL, -1);
413 g_return_val_if_fail (pch_legend_text != NULL, -1);
414 g_return_val_if_fail (pch_color_text != NULL, -1);
416 psd = (PLG_SERIES) g_new0 (LG_SERIES, 1);
417 g_return_val_if_fail (psd != NULL, -1);
419 psd->lg_point_dvalue = (gdouble *) g_new0 (gdouble, (plg->x_range.i_max_scale + 4));
420 g_return_val_if_fail (psd->lg_point_dvalue != NULL, -1);
422 psd->point_pos = g_new0 (GdkPoint, (plg->x_range.i_max_scale + 4));
423 g_return_val_if_fail (psd->point_pos != NULL, -1);
425 g_snprintf (psd->ch_legend_text, sizeof (psd->ch_legend_text), "%s", pch_legend_text);
426 psd->i_max_points = plg->x_range.i_max_scale;
427 gdk_color_parse (pch_color_text, &psd->legend_color);
428 g_snprintf (psd->ch_legend_color, sizeof (psd->ch_legend_color), "%s",
429 pch_color_text);
430 psd->cb_id = CB_SERIES_ID;
432 plg->lg_series = g_list_append (plg->lg_series, psd);
433 psd->i_series_id = plg->i_num_series++;
435 if (lg_graph_debug)
437 g_print ("DataSeriesAdd: series=%d, max_pts=%d\n",
438 psd->i_series_id, psd->i_max_points);
441 return psd->i_series_id;
445 * Set the bottom x label text
447 static void lg_graph_set_x_label_text (PLGRAPH plg, gchar * pch_text)
449 g_return_if_fail (plg != NULL);
451 if (plg->x_label_text != NULL)
453 g_free (plg->x_label_text);
455 plg->x_label_text = g_strdup (pch_text);
457 static void lg_graph_set_y_label_text (PLGRAPH plg, gchar * pch_text)
459 g_return_if_fail (plg != NULL);
461 if (plg->y_label_text != NULL)
463 g_free (plg->y_label_text);
465 plg->y_label_text = g_strdup (pch_text);
467 static void lg_graph_set_chart_title (PLGRAPH plg, gchar * pch_text)
469 g_return_if_fail (plg != NULL);
471 if (plg->x_title_text != NULL)
473 g_free (plg->x_title_text);
475 plg->x_title_text = g_strdup (pch_text);
477 static void lg_graph_set_chart_window_bg_color (PLGRAPH plg, gchar * pch_color)
479 g_return_if_fail (plg != NULL);
480 g_snprintf (plg->ch_color_window_bg, sizeof (plg->ch_color_window_bg),
481 "%s", pch_color);
483 static void lg_graph_set_chart_window_fg_color (PLGRAPH plg, gchar * pch_color)
485 g_return_if_fail (plg != NULL);
486 g_snprintf (plg->ch_color_chart_bg, sizeof (plg->ch_color_chart_bg), "%s", pch_color);
488 static void lg_graph_set_chart_scales_color (PLGRAPH plg, gchar * pch_color)
490 g_return_if_fail (plg != NULL);
491 g_snprintf (plg->ch_color_scale_fg, sizeof (plg->ch_color_scale_fg), "%s", pch_color);
493 static void lg_graph_set_chart_title_color (PLGRAPH plg, gchar * pch_color)
495 g_return_if_fail (plg != NULL);
496 g_snprintf (plg->ch_color_title_fg, sizeof (plg->ch_color_title_fg), "%s", pch_color);
498 static void lg_graph_redraw (PLGRAPH plg)
500 GdkRectangle update_rect;
501 GdkRegion *region = NULL;
503 g_return_if_fail (plg != NULL);
505 update_rect.x = 0;
506 update_rect.y = 0;
507 update_rect.width = plg->drawing_area->allocation.width;
508 update_rect.height = plg->drawing_area->allocation.height;
510 /* --- And then draw it (calls expose event) --- */
511 region = gdk_region_rectangle (&update_rect);
512 gdk_window_invalidate_region (plg->drawing_area->window, region, FALSE);
513 gdk_region_destroy (region);
517 * Toggle the legend function on off
518 * "button-press-event"
520 static gboolean lg_graph_button_press_event_cb (GtkWidget * widget,
521 GdkEventButton * ev, PLGRAPH plg)
523 g_return_val_if_fail (plg != NULL, FALSE);
525 if ((ev->type & GDK_BUTTON_PRESS) && (ev->button == 1))
527 plg->b_tooltip_active = plg->b_tooltip_active ? FALSE : TRUE;
528 lg_graph_redraw (plg);
529 return TRUE;
531 if ((ev->type & GDK_BUTTON_PRESS) && (ev->button == 2) && plg->b_mouse_onoff)
533 lg_graph_debug = lg_graph_debug ? FALSE : TRUE;
534 return TRUE;
537 if ((ev->type & GDK_BUTTON_PRESS) && (ev->button == 3))
539 plg->b_mouse_onoff = plg->b_mouse_onoff ? FALSE : TRUE;
540 return TRUE;
543 return FALSE;
547 * Track the mouse pointer position
548 * "motion-notify-event"
550 static gboolean lg_graph_motion_notify_event_cb (GtkWidget * widget,
551 GdkEventMotion * ev, PLGRAPH plg)
553 GdkModifierType state;
554 gint x = 0, y = 0;
556 g_return_val_if_fail (plg != NULL, FALSE);
558 if (ev->is_hint)
560 gdk_window_get_pointer (ev->window, &x, &y, &state);
562 else
564 x = ev->x;
565 y = ev->y;
566 state = ev->state;
569 plg->mouse_pos.x = x;
570 plg->mouse_pos.y = y;
571 plg->mouse_state = state;
573 if ( lg_graph_draw_tooltip (plg) ) {
574 lg_graph_redraw (plg);
577 if (lg_graph_debug)
579 g_print ("mouse is at x=%d, y=%d, with a state of %d\n", x, y, state);
582 return FALSE;
586 * Draw the chart x scale legend
588 static void lg_graph_draw_x_grid_labels (PLGRAPH plg)
590 gchar ch_grid_label[GAPC_MAX_BUFFER];
591 gchar ch_work[GAPC_MAX_BUFFER];
592 PangoLayout *layout = NULL;
593 PangoTabArray *p_tabs = NULL;
594 gint x_adj = 0, x1_adj = 0, width = 0, height = 0, h_index = 0, x_scale = 0;
596 g_return_if_fail (plg != NULL);
598 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "<small>%d</small>",
599 plg->x_range.i_max_scale);
600 layout = gtk_widget_create_pango_layout (plg->drawing_area, ch_grid_label);
602 pango_layout_set_markup (layout, ch_grid_label, -1);
603 pango_layout_get_pixel_size (layout, &width, &height);
604 x_adj = width / 2;
605 x1_adj = width / 4;
607 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "<small>%s", "0");
608 for (h_index = plg->x_range.i_inc_major_scale_by;
609 h_index <= plg->x_range.i_max_scale;
610 h_index += plg->x_range.i_inc_major_scale_by)
612 g_strlcpy (ch_work, ch_grid_label, GAPC_MAX_BUFFER);
613 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "%s\t%d", ch_work, h_index);
614 if (h_index < 10)
616 x_scale++;
619 g_strlcpy (ch_work, ch_grid_label, GAPC_MAX_BUFFER);
620 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "%s</small>", ch_work);
622 pango_layout_set_markup (layout, ch_grid_label, -1);
624 if (lg_graph_debug)
626 g_print ("(%d:%d:%d)x_Labels=[%s]\n", x_adj, x1_adj, x_scale, ch_grid_label);
629 p_tabs = pango_tab_array_new (plg->x_range.i_num_major, TRUE);
630 for (h_index = 0; h_index <= plg->x_range.i_num_major; h_index++)
632 gint xbase = 0;
634 if (h_index > x_scale)
636 xbase = (h_index * plg->x_range.i_major_inc);
638 else
640 xbase = (h_index * plg->x_range.i_major_inc) + x1_adj;
642 if (h_index == 0)
644 xbase = plg->x_range.i_major_inc + x1_adj;
646 pango_tab_array_set_tab (p_tabs, h_index, PANGO_TAB_LEFT, xbase);
648 pango_layout_set_tabs (layout, p_tabs);
650 pango_layout_context_changed (layout);
652 gdk_draw_layout (plg->pixmap,
653 plg->scale_gc,
654 plg->plot_box.x - x_adj,
655 plg->plot_box.y + plg->plot_box.height, layout);
657 pango_tab_array_free (p_tabs);
658 g_object_unref (layout);
660 return;
664 * Draw the chart y scale legend
666 static void lg_graph_draw_y_grid_labels (PLGRAPH plg)
668 gchar ch_grid_label[GAPC_MAX_BUFFER];
669 gchar ch_work[GAPC_MAX_BUFFER];
670 PangoLayout *layout = NULL;
671 gint y_adj = 0, width = 0, height = 0, v_index = 0;
673 g_return_if_fail (plg != NULL);
675 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "<small>%d</small>",
676 plg->y_range.i_max_scale);
677 layout = gtk_widget_create_pango_layout (plg->drawing_area, ch_grid_label);
679 pango_layout_set_markup (layout, ch_grid_label, -1);
680 pango_layout_get_pixel_size (layout, &width, &height);
681 y_adj = height / 2;
683 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "<small>%d", plg->y_range.i_max_scale);
684 for (v_index =
685 plg->y_range.i_max_scale - plg->y_range.i_inc_major_scale_by;
686 v_index > 0; v_index -= plg->y_range.i_inc_major_scale_by)
688 g_strlcpy (ch_work, ch_grid_label, GAPC_MAX_BUFFER);
689 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "%s\n%d", ch_work, v_index);
691 g_strlcpy (ch_work, ch_grid_label, GAPC_MAX_BUFFER);
692 g_snprintf (ch_grid_label, GAPC_MAX_BUFFER, "%s</small>", ch_work);
694 pango_layout_set_spacing (layout,
695 ((plg->y_range.i_major_inc - height) * PANGO_SCALE));
696 pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
697 pango_layout_set_markup (layout, ch_grid_label, -1);
699 if (lg_graph_debug)
701 g_print ("(%d:%d)y_Labels=[%s]\n", y_adj, plg->y_range.i_major_inc,
702 ch_grid_label);
705 pango_layout_context_changed (layout);
707 gdk_draw_layout (plg->pixmap,
708 plg->scale_gc,
709 plg->plot_box.x - (width * 1.2), plg->plot_box.y - y_adj, layout);
711 g_object_unref (layout);
713 return;
717 * Draws the minor and major grid lines inside the current plot_area
718 * returns -1 on error, or TRUE;
720 static gint lg_graph_draw_grid_lines (PLGRAPH plg)
722 GtkWidget *drawing_area = NULL;
723 gint y_minor_inc = 0, y_pos = 0, y_index = 0;
724 gint y_major_inc = 0;
725 gint x_minor_inc = 0, x_pos = 0, x_index = 0;
726 gint x_major_inc = 0;
727 gint count_major = 0, count_minor = 0;
728 GdkSegment *seg_minor = NULL;
729 GdkSegment *seg_major = NULL;
731 g_return_val_if_fail (plg != NULL, -1);
732 g_return_val_if_fail (GTK_WIDGET_DRAWABLE (plg->drawing_area), -1);
734 drawing_area = plg->drawing_area;
736 count_major = plg->y_range.i_num_major;
737 count_minor = plg->y_range.i_num_minor;
738 y_minor_inc = plg->y_range.i_minor_inc;
739 y_major_inc = plg->y_range.i_major_inc;
741 if (lg_graph_debug)
743 g_print
744 ("count_major=%d, count_minor=%d, y_minor_inc=%d, y_major_inc=%d\n",
745 count_major, count_minor, y_minor_inc, y_major_inc);
748 seg_minor = g_new0 (GdkSegment, count_minor + 8);
749 seg_major = g_new0 (GdkSegment, count_major + 8);
750 x_pos = plg->plot_box.width;
751 y_pos = plg->plot_box.y;
752 for (y_index = 0; y_index < count_minor; y_index++)
754 seg_minor[y_index].x1 = plg->plot_box.x;
755 seg_minor[y_index].y1 = y_pos + (y_minor_inc * (y_index + 1));
756 seg_minor[y_index].x2 = plg->plot_box.x + x_pos - 2;
757 seg_minor[y_index].y2 = seg_minor[y_index].y1;
760 x_pos = plg->plot_box.width;
761 y_pos = plg->plot_box.y;
762 for (y_index = 0; y_index < count_major; y_index++)
764 seg_major[y_index].x1 = plg->plot_box.x;
765 seg_major[y_index].y1 = y_pos + (y_major_inc * (y_index + 1));
766 seg_major[y_index].x2 = plg->plot_box.x + x_pos - 2;
767 seg_major[y_index].y2 = seg_major[y_index].y1;
770 gdk_gc_set_line_attributes (plg->window_gc,
771 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
772 gdk_draw_segments (plg->pixmap, plg->window_gc, seg_minor, count_minor - 1);
774 gdk_gc_set_line_attributes (plg->window_gc,
775 2, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_BEVEL);
776 gdk_draw_segments (plg->pixmap, plg->window_gc, seg_major, count_major - 1);
778 g_free (seg_minor);
779 g_free (seg_major);
781 count_major = plg->x_range.i_num_major;
782 count_minor = plg->x_range.i_num_minor;
783 x_minor_inc = plg->x_range.i_minor_inc;
784 x_major_inc = plg->x_range.i_major_inc;
786 if (lg_graph_debug)
788 g_print
789 ("count_major=%d, count_minor=%d, x_minor_inc=%d, x_major_inc=%d\n",
790 count_major, count_minor, x_minor_inc, x_major_inc);
793 seg_minor = g_new0 (GdkSegment, count_minor + 8);
794 seg_major = g_new0 (GdkSegment, count_major + 8);
795 x_pos = plg->plot_box.x;
796 y_pos = plg->plot_box.height;
797 for (x_index = 0; x_index < count_minor; x_index++)
799 seg_minor[x_index].x1 = plg->plot_box.x + (x_minor_inc * (x_index + 1));
800 seg_minor[x_index].y1 = plg->plot_box.y + 2;
801 seg_minor[x_index].x2 = seg_minor[x_index].x1;
802 seg_minor[x_index].y2 = plg->plot_box.y + y_pos;
805 x_pos = plg->plot_box.x;
806 y_pos = plg->plot_box.height;
807 for (x_index = 0; x_index < count_major; x_index++)
809 seg_major[x_index].x1 = plg->plot_box.x + (x_major_inc * (x_index + 1));
810 seg_major[x_index].y1 = plg->plot_box.y + 2;
811 seg_major[x_index].x2 = seg_major[x_index].x1;
812 seg_major[x_index].y2 = plg->plot_box.y + y_pos;
815 gdk_gc_set_line_attributes (plg->window_gc,
816 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
817 gdk_draw_segments (plg->pixmap, plg->window_gc, seg_minor, count_minor - 1);
819 gdk_gc_set_line_attributes (plg->window_gc,
820 2, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_BEVEL);
821 gdk_draw_segments (plg->pixmap, plg->window_gc, seg_major, count_major - 1);
823 g_free (seg_minor);
824 g_free (seg_major);
826 return TRUE;
830 * Draws the tooltip legend message at top or bottom of chart
831 * returns the width of the text area, or -1 on error
832 * requires plg->b_tooltip_active to be TRUE, (toggled by mouse)
834 static gint lg_graph_draw_tooltip (PLGRAPH plg)
836 PangoLayout *layout = NULL;
837 gint x_pos = 0, y_pos = 0, width = 0, height = 0;
838 gint v_index = 0, x_adj = 0;
839 PLG_SERIES psd = NULL;
840 GList *data_sets = NULL;
841 GdkRegion *region = NULL;
842 gboolean b_found = FALSE;
844 g_return_val_if_fail (plg != NULL, -1);
845 g_return_val_if_fail (GTK_WIDGET_DRAWABLE (plg->drawing_area), -1);
847 if (!plg->b_tooltip_active)
849 return -1;
851 if (plg->i_points_available < 1) {
852 return -1;
856 * Create tooltip if needed */
857 region = gdk_region_rectangle (&plg->plot_box);
858 x_adj = (plg->x_range.i_minor_inc / plg->x_range.i_inc_minor_scale_by);
861 * see if ptr is at a x-range point */
862 if (!gdk_region_point_in (region, plg->mouse_pos.x, plg->mouse_pos.y))
864 gdk_region_destroy (region);
865 return -1;
867 gdk_region_destroy (region);
869 for (v_index = 0; v_index <= plg->x_range.i_max_scale; v_index++)
871 x_pos = plg->plot_box.x + (v_index * x_adj);
872 if ((plg->mouse_pos.x > (x_pos - (x_adj / 3))) &&
873 (plg->mouse_pos.x < (x_pos + (x_adj / 3))))
875 if (v_index < plg->i_points_available)
877 b_found = TRUE;
878 break;
884 * All we needed was x, so now post a tooltip */
885 if (b_found)
887 gchar ch_buffer[GAPC_MAX_BUFFER];
888 gchar ch_work[GAPC_MAX_BUFFER];
889 gchar ch_time_r[GAPC_MAX_TEXT];
890 gchar *pch_time = NULL;
891 time_t point_time;
893 point_time = (time_t) g_list_nth_data (plg->lg_series_time, v_index);
895 pch_time = ctime_r (&point_time, ch_time_r);
897 g_strdelimit (pch_time, "\n", ' ');
899 g_snprintf (ch_buffer, sizeof (ch_buffer),
900 "<small>{ <u>sample #%d @ %s</u>}\n", v_index, pch_time);
901 data_sets = g_list_first (plg->lg_series);
902 while (data_sets)
904 psd = data_sets->data;
905 if (psd != NULL)
906 { /* found */
907 g_snprintf (ch_work, sizeof (ch_work), "%s", ch_buffer);
908 g_snprintf (ch_buffer, sizeof (ch_buffer),
909 "%s{%3.0f%% <span foreground=\"%s\">%s</span>}",
910 ch_work,
911 psd->lg_point_dvalue[v_index],
912 psd->ch_legend_color, psd->ch_legend_text);
914 data_sets = g_list_next (data_sets);
917 g_snprintf (ch_work, sizeof (ch_work), "%s", ch_buffer);
918 g_snprintf (ch_buffer, sizeof (ch_buffer), "%s</small>", ch_work);
919 g_snprintf (plg->ch_tooltip_text, sizeof (plg->ch_tooltip_text), "%s",
920 ch_buffer);
923 if (!b_found)
925 return -1;
928 layout = gtk_widget_create_pango_layout (plg->drawing_area, plg->ch_tooltip_text);
929 pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
931 pango_layout_set_markup (layout, plg->ch_tooltip_text, -1);
933 pango_layout_get_pixel_size (layout, &width, &height);
935 x_pos = plg->x_tooltip.x + ((plg->x_tooltip.width - width) / 2);
936 y_pos = plg->x_tooltip.y + ((plg->x_tooltip.height - height) / 2);
938 gdk_draw_rectangle (plg->pixmap, plg->window_gc, /* box_gc, */
939 TRUE,
940 plg->x_tooltip.x,
941 plg->x_tooltip.y, plg->x_tooltip.width, plg->x_tooltip.height);
942 gdk_draw_rectangle (plg->pixmap, plg->box_gc,
943 FALSE,
944 plg->x_tooltip.x,
945 plg->x_tooltip.y, plg->x_tooltip.width, plg->x_tooltip.height);
947 gdk_draw_layout (plg->pixmap, plg->scale_gc, x_pos, y_pos, layout);
949 g_object_unref (layout);
951 if (lg_graph_debug)
953 g_print ("DrawToolTip: x=%d, y=%d Width=%d, Height=%d, Text=%s\n",
954 x_pos, y_pos, width, height, plg->ch_tooltip_text);
957 return width;
960 #if GTK_CHECK_VERSION(2,6,0)
962 * Draws a label text on the Y axis
963 * sets the width, height values of the input rectangle to the size of textbox
964 * returns the height of the text area, or -1 on error
966 static gint lg_graph_draw_vertical_text (PLGRAPH plg,
967 gchar * pch_text,
968 GdkRectangle * rect, gboolean redraw_control)
970 PangoRenderer *renderer = NULL;
971 PangoMatrix matrix = PANGO_MATRIX_INIT;
972 PangoContext *context = NULL;
973 PangoLayout *layout = NULL;
974 gint y_pos = 0;
976 g_return_val_if_fail (plg != NULL, -1);
977 g_return_val_if_fail (pch_text != NULL, -1);
978 g_return_val_if_fail (rect != NULL, -1);
979 g_return_val_if_fail (GTK_WIDGET_DRAWABLE (plg->drawing_area), -1);
981 if (rect->width && redraw_control)
983 gdk_draw_rectangle (plg->pixmap, plg->window_gc,
984 TRUE, rect->x, rect->y, rect->width, rect->height);
987 /* Get the default renderer for the screen, and set it up for drawing */
988 renderer = gdk_pango_renderer_get_default (gtk_widget_get_screen (plg->drawing_area));
989 gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), plg->pixmap);
990 gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), plg->title_gc);
992 context = gtk_widget_get_pango_context (plg->drawing_area);
994 layout = pango_layout_new (context);
995 pango_layout_set_markup (layout, pch_text, -1);
997 pango_matrix_rotate (&matrix, 90.0);
998 pango_context_set_matrix (context, &matrix);
1000 pango_layout_context_changed (layout);
1002 /* xy switched due to rotate func */
1003 pango_layout_get_pixel_size (layout, &rect->height, &rect->width);
1004 y_pos = rect->y + ((plg->plot_box.height - rect->height) / 2);
1006 gdk_draw_layout (plg->pixmap, plg->title_gc, rect->x, y_pos, layout);
1008 /* Clean up default renderer, since it is shared */
1009 gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), NULL);
1010 gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), NULL);
1011 pango_context_set_matrix (context, NULL);
1013 /* free the objects we created */
1014 g_object_unref (layout);
1016 if (lg_graph_debug)
1018 g_print ("Vertical Label: x=%d, y=%d Width=%d, Height=%d Text:%s\n",
1019 rect->x, rect->y, rect->width, rect->height, pch_text);
1022 if (redraw_control)
1024 GdkRegion *region = NULL;
1026 region = gdk_region_rectangle (rect);
1027 gdk_window_invalidate_region (plg->drawing_area->window, region, FALSE);
1028 gdk_region_destroy (region);
1031 return rect->height;
1033 #else
1034 static gint lg_graph_draw_vertical_text (PLGRAPH plg,
1035 gchar * pch_text,
1036 GdkRectangle * rect, gboolean redraw_control)
1038 PangoContext *context = NULL;
1039 PangoLayout *layout = NULL;
1040 gint y_pos = 0;
1041 GdkPixmap *norm_pixmap = NULL;
1042 gint width, height;
1043 gint rot_width, rot_height;
1044 GdkPixbuf *norm_pixbuf = NULL, *rot_pixbuf = NULL;
1045 guint32 *norm_pix, *rot_pix;
1046 gint i, j, k, l;
1048 g_return_val_if_fail (plg != NULL, -1);
1049 g_return_val_if_fail (pch_text != NULL, -1);
1050 g_return_val_if_fail (rect != NULL, -1);
1051 g_return_val_if_fail (GTK_WIDGET_DRAWABLE (plg->drawing_area), -1);
1054 context = gtk_widget_get_pango_context (plg->drawing_area);
1055 layout = pango_layout_new (context);
1056 pango_layout_set_markup (layout, pch_text, -1);
1057 pango_layout_get_pixel_size (layout, &width, &height);
1058 if (width <= 0 || height <= 0)
1060 return 0;
1063 /* Figure out the rotated width and height */
1064 rect->width = rot_width = height;
1065 rect->height = rot_height = width;
1067 norm_pixmap = gdk_pixmap_new (plg->drawing_area->window, width, height, -1);
1068 gdk_draw_rectangle (norm_pixmap, plg->window_gc, TRUE, 0, 0, width, height);
1069 gdk_draw_layout (norm_pixmap, plg->title_gc, 0, 0, layout);
1071 norm_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
1072 norm_pixbuf = gdk_pixbuf_get_from_drawable (norm_pixbuf, norm_pixmap, NULL,
1073 0, 0, 0, 0, width, height);
1075 /* Get the raw pixel pointer of client buffer */
1076 norm_pix = (guint32 *) gdk_pixbuf_get_pixels (norm_pixbuf);
1078 /* Allocate a new client buffer with rotated memory */
1079 rot_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, rot_width, rot_height);
1080 rot_pix = (guint32 *) gdk_pixbuf_get_pixels (rot_pixbuf);
1082 /* Actually rotate */
1083 k = 0;
1084 for (j = width - 1; j >= 0; j--)
1086 l = j;
1087 for (i = 0; i < height; i++, k++, l += width)
1089 rot_pix[k] = norm_pix[l];
1093 /* compute a centered position on chart */
1094 y_pos = rect->y + ((plg->plot_box.height - rect->height) / 2);
1096 /* Draw it to the chart */
1097 gdk_pixbuf_render_to_drawable ( rot_pixbuf,
1098 plg->pixmap,
1099 plg->title_gc,
1100 0, 0,
1101 rect->x -1, y_pos,
1102 rect->width, rect->height,
1103 GDK_RGB_DITHER_NONE, 0, 0);
1105 /* Free everything */
1106 g_object_unref (layout);
1107 g_object_unref (G_OBJECT (norm_pixmap));
1108 g_object_unref (G_OBJECT (norm_pixbuf));
1109 g_object_unref (G_OBJECT (rot_pixbuf));
1112 return rect->height;
1114 #endif
1117 * Draws a label text on the X axis
1118 * sets the width, height values of the input rectangle to the size of textbox
1119 * returns the width of the text area, or -1 on error
1120 * redraw_control = 1 causes an expose_event, 0 or != 1 does not
1122 static gint lg_graph_draw_horizontal_text (PLGRAPH plg,
1123 gchar * pch_text,
1124 GdkRectangle * rect, gboolean redraw_control)
1126 PangoLayout *layout = NULL;
1127 gint x_pos = 0;
1129 g_return_val_if_fail (plg != NULL, -1);
1130 g_return_val_if_fail (pch_text != NULL, -1);
1131 g_return_val_if_fail (rect != NULL, -1);
1132 g_return_val_if_fail (GTK_WIDGET_DRAWABLE (plg->drawing_area), -1);
1134 if (rect->width && redraw_control)
1136 gdk_draw_rectangle (plg->pixmap, plg->window_gc,
1137 TRUE, rect->x, rect->y, rect->width, rect->height);
1140 layout = gtk_widget_create_pango_layout (plg->drawing_area, pch_text);
1141 pango_layout_set_markup (layout, pch_text, -1);
1142 pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
1144 pango_layout_get_pixel_size (layout, &rect->width, &rect->height);
1145 x_pos = rect->x + ((plg->plot_box.width - rect->width) / 2);
1147 gdk_draw_layout (plg->pixmap, plg->title_gc, x_pos, rect->y, layout);
1149 g_object_unref (layout);
1151 if (lg_graph_debug)
1153 g_print ("Horizontal Label: x=%d, y=%d Width=%d, Height=%d Text:%s\n",
1154 x_pos, rect->y, rect->width, rect->height, pch_text);
1158 if (redraw_control)
1160 GdkRegion *region = NULL;
1162 region = gdk_region_rectangle (rect);
1163 gdk_window_invalidate_region (plg->drawing_area->window, region, FALSE);
1164 gdk_region_destroy (region);
1167 return rect->width;
1171 * Computes the size of 3 proportional charactor using default font
1173 static void lg_graph_get_default_sizes (PLGRAPH plg, gint * width, gint * height)
1175 PangoLayout *layout = NULL;
1177 g_return_if_fail (plg != NULL);
1179 layout = gtk_widget_create_pango_layout (plg->drawing_area, "1M5");
1181 pango_layout_set_markup (layout, "<big><b>M5</b></big>", -1);
1183 pango_layout_get_pixel_size (layout, width, height);
1185 g_object_unref (layout);
1187 if (lg_graph_debug)
1189 g_print ("Default Sizing(1M5): Width=%d, Height=%d\n", *width, *height);
1192 return;
1196 * Compute and set x-y ranges
1198 static void lg_graph_set_ranges (PLGRAPH plg,
1199 gint xminor_by,
1200 gint xmajor_by,
1201 gint x_min,
1202 gint x_max,
1203 gint yminor_by, gint ymajor_by, gint y_min, gint y_max)
1205 g_return_if_fail (plg != NULL);
1207 plg->x_range.i_inc_minor_scale_by = xminor_by; /* minimum scale value - ex: 0 */
1208 plg->x_range.i_inc_major_scale_by = xmajor_by; /* minimum scale value - ex: 0 */
1210 plg->x_range.i_min_scale = x_min; /* minimum scale value - ex: 0 */
1211 plg->x_range.i_max_scale = x_max; /* maximum scale value - ex: 100 */
1212 plg->x_range.i_num_minor = x_max / xminor_by; /* number of minor points */
1213 plg->x_range.i_num_major = x_max / xmajor_by; /* number of major points */
1215 plg->y_range.i_inc_minor_scale_by = yminor_by; /* minimum scale value - ex: 0 */
1216 plg->y_range.i_inc_major_scale_by = ymajor_by; /* minimum scale value - ex: 0 */
1218 plg->y_range.i_min_scale = y_min; /* minimum scale value - ex: 0 */
1219 plg->y_range.i_max_scale = y_max; /* maximum scale value - ex: 100 */
1220 plg->y_range.i_num_minor = y_max / yminor_by; /* number of minor points */
1221 plg->y_range.i_num_major = y_max / ymajor_by; /* number of major points */
1223 return;
1227 * Repaint
1229 * data - widget to repaint
1231 static gint lg_graph_draw (PLGRAPH plg)
1233 GtkWidget *drawing_area = NULL;
1235 g_return_val_if_fail (plg != NULL, TRUE);
1237 drawing_area = plg->drawing_area;
1239 if ( !(GTK_WIDGET_DRAWABLE (drawing_area)) ) {
1240 return TRUE;
1244 * Clear the whole area
1246 gdk_draw_rectangle (plg->pixmap, plg->window_gc,
1247 TRUE, 0, 0,
1248 plg->drawing_area->allocation.width,
1249 plg->drawing_area->allocation.height);
1252 * draw plot area
1254 gdk_draw_rectangle (plg->pixmap,
1255 plg->box_gc,
1256 TRUE,
1257 plg->plot_box.x,
1258 plg->plot_box.y, plg->plot_box.width, plg->plot_box.height);
1260 gdk_gc_set_line_attributes (plg->drawing_area->style->black_gc,
1261 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
1262 gdk_draw_rectangle (plg->pixmap,
1263 plg->drawing_area->style->black_gc,
1264 FALSE,
1265 plg->plot_box.x,
1266 plg->plot_box.y, plg->plot_box.width, plg->plot_box.height);
1268 if (lg_graph_debug)
1270 g_print
1271 ("Window: Width=%d, Height=%d, Plot Area x=%d y=%d width=%d, height=%d\n",
1272 drawing_area->allocation.width, drawing_area->allocation.height,
1273 plg->plot_box.x, plg->plot_box.y, plg->plot_box.width, plg->plot_box.height);
1277 * draw titles
1279 lg_graph_draw_horizontal_text (plg, plg->x_title_text, &plg->x_title, FALSE);
1281 lg_graph_draw_horizontal_text (plg, plg->x_label_text, &plg->x_label, FALSE);
1283 lg_graph_draw_vertical_text (plg, plg->y_label_text, &plg->y_label, FALSE);
1285 lg_graph_draw_grid_lines (plg);
1287 lg_graph_draw_x_grid_labels (plg);
1289 lg_graph_draw_y_grid_labels (plg);
1291 lg_graph_data_series_draw_all (plg, FALSE);
1293 lg_graph_draw_tooltip (plg);
1295 /* The entire pixmap is going to be copied
1296 * onto the window so the rect is configured
1297 * as the size of the window.
1299 lg_graph_redraw (plg);
1301 return (FALSE);
1305 * configure_event
1307 * Create a new backing pixmap of the appropriate size
1308 * Of course, this is called whenever the window is
1309 * resized. We have to free up things we allocated.
1311 static gint lg_graph_configure_event_cb (GtkWidget * widget,
1312 GdkEventConfigure * event, PLGRAPH plg)
1314 GdkRectangle clip_area;
1315 gint xfactor = 0, yfactor = 0;
1317 /* --- Free background if we created it --- */
1318 if (plg->pixmap)
1320 gdk_pixmap_unref (plg->pixmap);
1323 /* --- Create a new pixmap with new size --- */
1324 plg->pixmap = gdk_pixmap_new (widget->window,
1325 widget->allocation.width,
1326 widget->allocation.height, -1);
1328 gdk_draw_rectangle (plg->pixmap, plg->window_gc,
1329 TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
1331 plg->width = widget->allocation.width;
1332 plg->height = widget->allocation.height;
1334 clip_area.x = 0;
1335 clip_area.y = 0;
1336 clip_area.width = widget->allocation.width;
1337 clip_area.height = widget->allocation.height;
1339 xfactor = MAX (plg->x_range.i_num_minor, plg->x_range.i_num_major);
1340 yfactor = MAX (plg->y_range.i_num_minor, plg->y_range.i_num_major);
1342 lg_graph_get_default_sizes (plg, &plg->x_border, &plg->y_border);
1343 plg->x_border /= 4;
1344 plg->y_border /= 4;
1346 plg->x_label.x = plg->x_border * 6; /* define top-left corner of textbox */
1347 plg->x_label.y = plg->height - (plg->y_border * 4) + 2;
1349 plg->y_label.x = plg->x_border;
1350 plg->y_label.y = plg->y_border * 6;
1352 plg->x_title.x = plg->x_border * 6;
1353 plg->x_title.y = 1; /* /plg->y_border ; */
1355 plg->x_tooltip.x = plg->x_border;
1356 plg->x_tooltip.y = plg->y_border;
1357 plg->x_tooltip.width = plg->width - (plg->x_border * 2);
1358 plg->x_tooltip.height = plg->y_border * 7;
1360 plg->plot_box.x = plg->x_border * 6;
1361 plg->plot_box.y = plg->y_border * 6;
1362 plg->plot_box.width =
1363 ((gint) (plg->width - (plg->x_border * 10)) / xfactor) * xfactor;
1364 plg->plot_box.height =
1365 ((gint) (plg->height - (plg->y_border * 14)) / yfactor) * yfactor;
1367 /* reposition the box according to scale-able increments */
1368 plg->plot_box.x = (((gfloat) (plg->width - plg->plot_box.width) / 10.0) * 7) + 4;
1369 plg->plot_box.y = (((gfloat) (plg->height - plg->plot_box.height) / 10.0) * 5) + 4;
1370 plg->x_label.x = plg->x_title.x = plg->plot_box.x;
1371 plg->y_label.y = plg->plot_box.y;
1373 plg->y_range.i_minor_inc = plg->plot_box.height / plg->y_range.i_num_minor;
1374 plg->y_range.i_major_inc = plg->plot_box.height / plg->y_range.i_num_major;
1376 plg->x_range.i_minor_inc = plg->plot_box.width / plg->x_range.i_num_minor;
1377 plg->x_range.i_major_inc = plg->plot_box.width / plg->x_range.i_num_major;
1379 g_timeout_add (250, (GSourceFunc) lg_graph_draw, plg);
1381 return TRUE;
1385 * expose_event
1387 * When the window is exposed to the viewer or
1388 * the gdk_widget_draw routine is called, this
1389 * routine is called. Copies the background pixmap
1390 * to the window.
1392 static gint lg_graph_expose_event_cb (GtkWidget * widget, GdkEventExpose * event,
1393 PLGRAPH plg)
1396 g_return_val_if_fail (GDK_IS_DRAWABLE (widget->window), FALSE);
1398 /* --- Copy pixmap to the window --- */
1399 gdk_draw_pixmap (widget->window,
1400 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1401 plg->pixmap,
1402 event->area.x, event->area.y,
1403 event->area.x, event->area.y, event->area.width, event->area.height);
1405 return FALSE;
1408 static void cb_util_popup_menu_response_exit(GtkWidget * widget, gpointer gp)
1410 PGAPC_CONFIG pcfg = NULL;
1411 PGAPC_MONITOR pm = NULL;
1412 gchar *penabled = NULL;
1414 g_return_if_fail(gp != NULL);
1416 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
1417 /* this is a monitor struct (2) */
1418 pm = (PGAPC_MONITOR) gp;
1419 pm->b_run = FALSE;
1420 penabled = g_strdup_printf(GAPC_ENABLE_KEY, pm->cb_monitor_num);
1421 gconf_client_set_bool(pm->client, penabled, FALSE, NULL);
1422 g_free(penabled);
1423 } else {
1424 /* this is a config struct (1) */
1425 pcfg = (PGAPC_CONFIG) gp;
1426 gtk_widget_destroy(GTK_WIDGET(pcfg->window));
1429 return;
1431 static void cb_util_popup_menu_response_jumpto(GtkWidget * widget, gpointer gp)
1433 PGAPC_CONFIG pcfg = NULL;
1434 PGAPC_MONITOR pm = NULL;
1435 GtkWindow *window = NULL;
1437 g_return_if_fail(gp != NULL);
1439 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
1440 /* this is a monitor struct (2) */
1441 pm = (PGAPC_MONITOR) gp;
1442 window = GTK_WINDOW(pm->window);
1443 } else {
1444 /* this is a config struct (1) */
1445 pcfg = (PGAPC_CONFIG) gp;
1446 window = GTK_WINDOW(pcfg->window);
1449 if (window != NULL) {
1450 gtk_window_present(window);
1453 return;
1457 * Change the color values back to their original defaults
1459 static void cb_panel_property_color_reset (GtkButton *button, PGAPC_CONFIG pcfg)
1461 gchar *pstring = NULL;
1463 g_return_if_fail (pcfg != NULL);
1465 gdk_color_parse ("green", &pcfg->color_linev);
1466 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_linev, 1);
1467 if (pstring != NULL) {
1468 gconf_client_set_string(pcfg->client, GAPC_COLOR_LINEV_KEY, pstring, NULL);
1469 g_free (pstring);
1472 gdk_color_parse ("blue", &pcfg->color_loadpct);
1473 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_loadpct, 1);
1474 if (pstring != NULL) {
1475 gconf_client_set_string(pcfg->client, GAPC_COLOR_LOADPCT_KEY, pstring, NULL);
1476 g_free (pstring);
1479 gdk_color_parse ("red", &pcfg->color_timeleft);
1480 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_timeleft, 1);
1481 if (pstring != NULL) {
1482 gconf_client_set_string(pcfg->client, GAPC_COLOR_TIMELEFT_KEY, pstring, NULL);
1483 g_free (pstring);
1486 gdk_color_parse ("yellow", &pcfg->color_bcharge);
1487 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_bcharge, 1);
1488 if (pstring != NULL) {
1489 gconf_client_set_string(pcfg->client, GAPC_COLOR_BCHARGE_KEY, pstring, NULL);
1490 g_free (pstring);
1493 gdk_color_parse ("black", &pcfg->color_battv);
1494 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_battv, 1);
1495 if (pstring != NULL) {
1496 gconf_client_set_string(pcfg->client, GAPC_COLOR_BATTV_KEY, pstring, NULL);
1497 g_free (pstring);
1500 gdk_color_parse ("white", &pcfg->color_window);
1501 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_window, 1);
1502 if (pstring != NULL) {
1503 gconf_client_set_string(pcfg->client, GAPC_COLOR_WINDOW_KEY, pstring, NULL);
1504 g_free (pstring);
1507 gdk_color_parse ("light blue", &pcfg->color_chart);
1508 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_chart, 1);
1509 if (pstring != NULL) {
1510 gconf_client_set_string(pcfg->client, GAPC_COLOR_CHART_KEY, pstring, NULL);
1511 g_free (pstring);
1514 gdk_color_parse ("blue", &pcfg->color_title);
1515 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_title, 1);
1516 if (pstring != NULL) {
1517 gconf_client_set_string(pcfg->client, GAPC_COLOR_TITLE_KEY, pstring, NULL);
1518 g_free (pstring);
1521 return;
1524 * catch the color change signal and save its value into gconf
1526 static void cb_panel_property_color_change (GtkColorButton *widget, gchar *color_key)
1528 GConfClient *client = NULL;
1529 GdkColor color;
1530 gchar *pstring = NULL;
1532 g_return_if_fail(GTK_IS_COLOR_BUTTON(widget));
1533 g_return_if_fail(color_key != NULL);
1535 gtk_color_button_get_color (GTK_COLOR_BUTTON(widget), &color);
1536 pstring = gtk_color_selection_palette_to_string ( &color, 1);
1537 if (pstring == NULL) {
1538 return;
1541 client = (GConfClient *)g_object_get_data (G_OBJECT(widget), "gconf-client");
1542 if (client != NULL) {
1543 gconf_client_set_string (client, color_key, pstring, NULL);
1546 g_free (pstring);
1548 return;
1551 * Changes the Applets icon if needed
1552 * returns FALSE if OK
1553 * return TRUE is any error
1555 static gint gapc_util_change_icons(PGAPC_MONITOR pm)
1557 GdkPixbuf *pixbuf = NULL;
1558 GdkPixbuf *scaled = NULL;
1559 GtkOrientation orientation;
1560 gint size = 0;
1562 g_return_val_if_fail(pm != NULL, TRUE);
1564 if (pm->i_icon_index >= GAPC_N_ICONS) {
1565 pm->i_icon_index = GAPC_ICON_ONLINE;
1568 pixbuf = pm->my_icons[pm->i_icon_index];
1569 if (pixbuf) {
1570 if (pm->tray_image != NULL) {
1571 orientation = egg_tray_icon_get_orientation(EGG_TRAY_ICON(pm->tray_icon));
1572 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
1573 size = pm->i_icon_height;
1574 } else {
1575 size = pm->i_icon_width;
1577 if (size < 5) {
1578 size = 22;
1580 scaled = gdk_pixbuf_scale_simple(pixbuf, size, size, GDK_INTERP_BILINEAR);
1581 gtk_image_set_from_pixbuf(GTK_IMAGE(pm->tray_image), scaled);
1582 gtk_widget_show(pm->tray_image);
1583 gdk_pixbuf_unref(scaled);
1586 if (pm->window != NULL)
1587 gtk_window_set_icon(GTK_WINDOW(pm->window), pixbuf);
1590 return FALSE;
1594 * used to switch timers when d_refresh changes
1595 * b_timer_control True trigger the target timer to stop and have this one
1596 * restart it; so it can pickup the new interval;
1598 static gboolean cb_util_line_chart_refresh_control(PGAPC_MONITOR pm)
1600 GtkWidget *w = NULL;
1601 gchar *pch1 = NULL, *pch = NULL;
1603 g_return_val_if_fail(pm != NULL, FALSE);
1605 if ((!pm->b_run) || !(pm->cb_enabled))
1606 return FALSE; /* stop timers */
1608 pm->b_graph_control = FALSE;
1609 pm->phs.d_xinc = pm->d_graph * pm->d_refresh;
1611 pm->tid_graph_refresh =
1612 g_timeout_add((guint) (pm->phs.d_xinc * GAPC_REFRESH_FACTOR_1K ),
1613 (GSourceFunc) cb_util_line_chart_refresh, &pm->phs);
1615 pch = g_strdup_printf(
1616 "<i>sampled every %3.1f seconds</i>",
1617 pm->phs.d_xinc);
1618 lg_graph_set_x_label_text (pm->phs.plg, pch);
1620 g_free(pch);
1622 w = g_hash_table_lookup(pm->pht_Widgets, "StatusBar");
1624 if ((pm->tid_graph_refresh != 0) && (w != NULL)) {
1625 gtk_statusbar_pop(GTK_STATUSBAR(w), pm->i_info_context);
1626 pch1 = g_strdup_printf
1627 ("Graphing refresh cycle changed for host %s completed!...", pm->pch_host);
1628 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1629 g_free(pch1);
1633 return FALSE;
1637 * used to switch timers when d_refresh changes
1638 * b_timer_control True trigger the target timer to stop and have this one
1639 * restart it; so it can pickup the new interval;
1641 static gboolean cb_monitor_refresh_control(PGAPC_MONITOR pm)
1643 GtkWidget *w = NULL;
1644 gchar *pch1 = NULL;
1646 g_return_val_if_fail(pm != NULL, FALSE);
1648 if ((!pm->b_run) || !(pm->cb_enabled))
1649 return FALSE; /* stop timers */
1651 pm->b_timer_control = FALSE;
1653 pm->tid_automatic_refresh =
1654 g_timeout_add((guint) (pm->d_refresh * GAPC_REFRESH_FACTOR_1K),
1655 (GSourceFunc) cb_monitor_automatic_refresh, pm);
1657 w = g_hash_table_lookup(pm->pht_Widgets, "StatusBar");
1659 if ((pm->tid_automatic_refresh != 0) && (w != NULL)) {
1660 gtk_statusbar_pop(GTK_STATUSBAR(w), pm->i_info_context);
1661 pch1 = g_strdup_printf("Refresh Cycle Change for host %s Completed!...",
1662 pm->pch_host);
1663 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1664 g_free(pch1);
1667 return FALSE;
1671 * timer service routine for IPL refresh and refresh_button.
1672 * used to overcome the multi-threaded startup delay. very short
1674 static gboolean cb_monitor_dedicated_one_time_refresh(PGAPC_MONITOR pm)
1676 GtkWidget *w = NULL;
1677 gchar *pch1 = NULL;
1679 g_return_val_if_fail(pm != NULL, FALSE);
1681 if ((!pm->b_run) || !(pm->cb_enabled)) {
1682 return FALSE;
1685 if (!g_mutex_trylock(pm->gm_update)) {
1686 w = g_hash_table_lookup(pm->pht_Widgets, "StatusBar");
1687 if (w != NULL) {
1688 gtk_statusbar_pop(GTK_STATUSBAR(w), pm->i_info_context);
1689 pch1 = g_strdup_printf("Quick refresh for %s failed!"
1690 " Network thread is busy...", pm->pch_host);
1691 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1692 g_free(pch1);
1694 return TRUE; /* thread must be busy */
1697 gdk_threads_enter();
1699 w = g_hash_table_lookup(pm->pht_Widgets, "StatusBar");
1700 if (w != NULL) {
1701 gtk_statusbar_pop(GTK_STATUSBAR(w), pm->i_info_context);
1704 gapc_monitor_update_tooltip_msg(pm);
1706 if (!gapc_monitor_update(pm)) {
1707 if (w != NULL) {
1708 pch1 = g_strdup_printf("Refresh for %s failed! "
1709 "(retry enabled)... network busy!", pm->pch_host);
1710 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1711 g_free(pch1);
1713 if (pm->i_netbusy_counter++ % 10) { /* Fall thru and quit after ten trys */
1714 g_mutex_unlock(pm->gm_update);
1715 gdk_flush();
1716 gdk_threads_leave();
1717 return TRUE; /* try again */
1721 if (w != NULL) {
1722 pch1 = g_strdup_printf("One-Time Refresh for %s Completed...", pm->pch_host);
1723 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1724 g_free(pch1);
1727 g_mutex_unlock(pm->gm_update);
1728 gdk_flush();
1729 gdk_threads_leave();
1731 return FALSE; /* this will terminate the timer */
1735 * used to make a work request to network queue
1737 static gboolean cb_monitor_automatic_refresh(PGAPC_MONITOR pm)
1739 gchar *pch1 = NULL;
1740 GtkWidget *w = NULL;
1742 g_return_val_if_fail(pm != NULL, FALSE);
1744 if ((!pm->b_run) || !(pm->cb_enabled))
1745 return FALSE; /* stop timers */
1747 if (pm->b_timer_control) {
1748 g_timeout_add(100, (GSourceFunc) cb_monitor_refresh_control, pm);
1749 return FALSE;
1752 if (!g_mutex_trylock(pm->gm_update)) {
1753 w = g_hash_table_lookup(pm->pht_Widgets, "StatusBar");
1754 if (w != NULL) {
1755 gtk_statusbar_pop(GTK_STATUSBAR(w), pm->i_info_context);
1756 pch1 = g_strdup_printf("Automatic refresh for %s failed!"
1757 " Network thread is busy...", pm->pch_host);
1758 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1759 g_free(pch1);
1761 return TRUE; /* thread must be busy */
1764 gdk_threads_enter();
1766 w = g_hash_table_lookup(pm->pht_Widgets, "StatusBar");
1767 if (w != NULL) {
1768 gtk_statusbar_pop(GTK_STATUSBAR(w), pm->i_info_context);
1771 gapc_monitor_update_tooltip_msg(pm); /* false = OK */
1772 if (gapc_monitor_update(pm)) {
1773 if (w != NULL) {
1774 pch1 =
1775 g_strdup_printf("Automatic refresh for %s complete...", pm->pch_host);
1776 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1777 g_free(pch1);
1779 } else {
1780 if (w != NULL) {
1781 pch1 = g_strdup_printf("Automatic refresh for %s failed!"
1782 " Network thread is busy...", pm->pch_host);
1783 gtk_statusbar_push(GTK_STATUSBAR(w), pm->i_info_context, pch1);
1784 g_free(pch1);
1786 if (pm->i_netbusy_counter++ % 10) { /* fall thru every tenth time to queue a message */
1787 g_mutex_unlock(pm->gm_update);
1788 gdk_flush();
1789 gdk_threads_leave();
1791 return TRUE;
1796 * This is the work request to network queue */
1797 g_async_queue_push(pm->q_network, (gpointer) pm);
1799 g_mutex_unlock(pm->gm_update);
1800 gdk_flush();
1801 gdk_threads_leave();
1803 return TRUE;
1807 * Manage the state icon in the panel and the associated tooltip
1808 * Composes the expanded tooltip message
1810 static gboolean gapc_monitor_update_tooltip_msg(PGAPC_MONITOR pm)
1812 gchar *pchx = NULL, *pmsg = NULL, *ptitle = NULL, *pch5 = NULL, *pch5a =
1813 NULL, *pch5b = NULL;
1814 gchar *pch1 = NULL, *pch2 = NULL, *pch3 = NULL, *pch4 = NULL;
1815 gchar *pch6 = NULL, *pch7 = NULL, *pch8 = NULL, *pch9 = NULL;
1816 gchar *pchb = NULL, *pchc = NULL, *pchd = NULL, *pche = NULL;
1817 gchar *pcha = NULL, *pmview = NULL, *pch_watt = NULL;
1818 GtkWidget *w = NULL;
1819 gdouble d_value = 0.0, d_watt =0.0, d_loadpct = 0.0;
1820 gboolean b_flag = FALSE, b_valid = FALSE;
1821 gint i_series = 0;
1822 GtkTreeIter miter;
1823 GdkPixbuf *pixbuf;
1825 g_return_val_if_fail(pm != NULL, TRUE);
1827 if (pm->b_run != TRUE)
1828 return TRUE;
1830 w = g_hash_table_lookup(pm->pht_Widgets, "StatusBar");
1832 pm->i_icon_index = GAPC_ICON_ONLINE;
1834 pch1 = g_hash_table_lookup(pm->pht_Status, "UPSNAME");
1835 pch2 = g_hash_table_lookup(pm->pht_Status, "HOSTNAME");
1836 if (pch2 == NULL) {
1837 pch2 = pm->pch_host;
1839 if (pch2 == NULL) {
1840 pch2 = "unknown";
1842 pch3 = g_hash_table_lookup(pm->pht_Status, "STATUS");
1843 if (pch3 == NULL) {
1844 pch3 = "NISERR";
1846 pch4 = g_hash_table_lookup(pm->pht_Status, "NUMXFERS");
1847 pch5a = g_hash_table_lookup(pm->pht_Status, "TONBATT");
1848 if (pch5a == NULL) {
1849 pch5a = " ";
1851 pch5b = g_hash_table_lookup(pm->pht_Status, "CUMONBATT");
1852 if (pch5b == NULL) {
1853 pch5b = " ";
1855 pch5 = g_hash_table_lookup(pm->pht_Status, "XONBATT");
1856 if (pch5 == NULL) {
1857 pch5 = " ";
1859 pch6 = g_hash_table_lookup(pm->pht_Status, "LINEV");
1860 pch7 = g_hash_table_lookup(pm->pht_Status, "BCHARGE");
1861 if (pch7 == NULL) {
1862 pch7 = "n/a";
1864 pch8 = g_hash_table_lookup(pm->pht_Status, "LOADPCT");
1865 if ( pch8 != NULL ) {
1866 d_loadpct = g_strtod (pch8, NULL);
1867 d_loadpct /= 100.0;
1869 pch_watt = g_hash_table_lookup(pm->pht_Status, "NOMPOWER");
1870 if ( pch_watt != NULL ) {
1871 pm->i_watt = g_strtod (pch_watt, NULL);
1872 d_watt = d_loadpct * pm->i_watt;
1873 } else {
1874 d_watt = d_loadpct * pm->i_watt;
1877 pch9 = g_hash_table_lookup(pm->pht_Status, "TIMELEFT");
1878 pcha = g_hash_table_lookup(pm->pht_Status, "VERSION");
1879 pchb = g_hash_table_lookup(pm->pht_Status, "STARTTIME");
1880 pchc = g_hash_table_lookup(pm->pht_Status, "MODEL");
1881 pchd = g_hash_table_lookup(pm->pht_Status, "UPSMODE");
1882 pche = g_hash_table_lookup(pm->pht_Status, "CABLE");
1884 if (pm->b_data_available) {
1885 d_value = g_strtod(pch7, NULL);
1886 pchx = NULL;
1887 if (g_strrstr(pch3, "COMMLOST") != NULL) {
1888 pchx = " cable un-plugged...";
1889 pm->i_icon_index = GAPC_ICON_UNPLUGGED;
1890 b_flag = TRUE;
1891 } else if ((d_value < 99.0) && (g_strrstr(pch3, "LINE") != NULL)) {
1892 pchx = " and charging...";
1893 pch3 = "CHARGING";
1894 pm->i_icon_index = GAPC_ICON_CHARGING;
1895 } else if (g_strrstr(pch3, "BATT") != NULL) {
1896 pchx = " on battery...";
1897 pm->i_icon_index = GAPC_ICON_ONBATT;
1899 } else {
1900 b_flag = TRUE;
1901 pchx = " NIS network error...";
1902 pch3 = "NISERR";
1903 g_hash_table_replace(pm->pht_Status, g_strdup("STATUS"), g_strdup(pch3));
1904 pm->i_icon_index = GAPC_ICON_NETWORKERROR;
1905 for (i_series = 0; i_series < pm->phs.plg->i_num_series; i_series++) {
1906 gapc_util_point_filter_set(&(pm->phs.sq[i_series]), 0.0);
1910 if (b_flag) {
1911 ptitle = g_strdup_printf("<span foreground=\"red\" size=\"large\">"
1912 "%s@%s\nis %s%s" "</span>",
1913 (pch1 != NULL) ? pch1 : "unknown",
1914 (pch2 != NULL) ? pch2 : "unknown",
1915 (pch3 != NULL) ? pch3 : "n/a", (pchx != NULL) ? pchx : " ");
1916 } else {
1917 ptitle = g_strdup_printf("<span foreground=\"blue\" size=\"large\">"
1918 "%s@%s\nis %s%s" "</span>",
1919 (pch1 != NULL) ? pch1 : "unknown",
1920 (pch2 != NULL) ? pch2 : "unknown",
1921 (pch3 != NULL) ? pch3 : "n/a", (pchx != NULL) ? pchx : " ");
1924 pmsg = g_strdup_printf("%s@%s\nStatus: %s%s\n"
1925 "Refresh occurs every %3.1f seconds\n"
1926 "----------------------------------------------------------\n"
1927 "%s Outage[s]\n" "Last on %s\n" "%s Utility VAC\n"
1928 "%s Battery Charge\n"
1929 "%s UPS Load\n"
1930 "%3.0f of %d watts\n"
1931 "%s Remaining\n"
1932 "----------------------------------------------------------\n"
1933 "Build: %s\n" "Started: %s\n"
1934 "----------------------------------------------------------\n"
1935 "Model: %s\n" " Mode: %s\n" "Cable: %s",
1936 (pch1 != NULL) ? pch1 : "unknown",
1937 (pch2 != NULL) ? pch2 : "unknown",
1938 (pch3 != NULL) ? pch3 : "n/a",
1939 (pchx != NULL) ? pchx : " ",
1940 pm->d_refresh,
1941 (pch4 != NULL) ? pch4 : "n/a",
1942 (pch5 != NULL) ? pch5 : "n/a",
1943 (pch6 != NULL) ? pch6 : "n/a",
1944 (pch7 != NULL) ? pch7 : "n/a",
1945 (pch8 != NULL) ? pch8 : "n/a",
1946 d_watt, pm->i_watt,
1947 (pch9 != NULL) ? pch9 : "n/a",
1948 (pcha != NULL) ? pcha : "n/a",
1949 (pchb != NULL) ? pchb : "n/a",
1950 (pchc != NULL) ? pchc : "n/a",
1951 (pchd != NULL) ? pchd : "n/a", (pche != NULL) ? pche : "n/a");
1954 switch (pm->i_icon_index) {
1955 case GAPC_ICON_NETWORKERROR:
1956 pmview = g_strdup_printf("<span foreground=\"red\" size=\"large\">"
1957 "<b><i>%s@%s</i></b></span>\n"
1958 "NIS network connection not Responding!",
1959 (pch1 != NULL) ? pch1 : "unknown", (pch2 != NULL) ? pch2 : "unknown");
1960 break;
1961 case GAPC_ICON_UNPLUGGED:
1962 pmview = g_strdup_printf("<span foreground=\"red\" size=\"large\">"
1963 "<b><i>%s@%s</i></b></span>\n"
1964 "%s",
1965 (pch1 != NULL) ? pch1 : "unknown",
1966 (pch2 != NULL) ? pch2 : "unknown", (pchx != NULL) ? pchx : " un-plugged");
1967 break;
1968 case GAPC_ICON_CHARGING:
1969 pmview = g_strdup_printf("<span foreground=\"blue\">"
1970 "<b><i>%s@%s</i></b></span>\n"
1971 "%s Outage, Last on %s\n"
1972 "%s VAC, %s Charge\n"
1973 "%s Remaining, %s total on battery, %3.0f of %d watts",
1974 (pch1 != NULL) ? pch1 : "unknown",
1975 (pch2 != NULL) ? pch2 : "unknown",
1976 (pch4 != NULL) ? pch4 : "n/a",
1977 (pch5 != NULL) ? pch5 : "n/a",
1978 (pch6 != NULL) ? pch6 : "n/a",
1979 (pch7 != NULL) ? pch7 : "n/a",
1980 (pch9 != NULL) ? pch9 : "n/a",
1981 (pch5b != NULL) ? pch5b : "n/a",
1982 d_watt, pm->i_watt);
1983 break;
1984 case GAPC_ICON_ONBATT:
1985 pmview = g_strdup_printf("<span foreground=\"yellow\">"
1986 "<b><i>%s@%s</i></b></span>\n"
1987 "%s Outage, Last on %s\n"
1988 "%s Charge, %s total on battery\n"
1989 "%s Remaining, %s on battery, %3.0f of %d watts",
1990 (pch1 != NULL) ? pch1 : "unknown",
1991 (pch2 != NULL) ? pch2 : "unknown",
1992 (pch4 != NULL) ? pch4 : "n/a",
1993 (pch5 != NULL) ? pch5 : "n/a",
1994 (pch7 != NULL) ? pch7 : "n/a",
1995 (pch5b != NULL) ? pch5b : "n/a",
1996 (pch9 != NULL) ? pch9 : "n/a",
1997 (pch5a != NULL) ? pch5a : "n/a ",
1998 d_watt, pm->i_watt);
1999 break;
2000 case GAPC_ICON_ONLINE:
2001 case GAPC_ICON_DEFAULT:
2002 default:
2003 pmview = g_strdup_printf("<b><i>%s@%s</i></b>\n"
2004 "%s Outage, Last on %s\n"
2005 "%s VAC, %s Charge %s %3.0f of %d watts",
2006 (pch1 != NULL) ? pch1 : "unknown",
2007 (pch2 != NULL) ? pch2 : "unknown",
2008 (pch4 != NULL) ? pch4 : "n/a",
2009 (pch5 != NULL) ? pch5 : "n/a",
2010 (pch6 != NULL) ? pch6 : "n/a",
2011 (pch7 != NULL) ? pch7 : "n/a",
2012 (pchx != NULL) ? pchx : " ",
2013 d_watt, pm->i_watt);
2014 break;
2017 pixbuf = pm->my_icons[pm->i_icon_index];
2018 if (pm->i_old_icon_index != pm->i_icon_index) {
2019 b_flag = TRUE;
2020 } else {
2021 b_flag = FALSE;
2024 if ((pm->tooltips != NULL) && (pm->tray_icon != NULL)) {
2025 gtk_tooltips_set_tip(pm->tooltips, GTK_WIDGET(pm->tray_icon), pmsg, NULL);
2026 if (b_flag) {
2027 gapc_util_change_icons(pm);
2031 b_valid =
2032 gapc_util_treeview_get_iter_from_monitor(pm->monitor_model, &miter,
2033 pm->cb_monitor_num);
2034 if (b_valid) {
2035 if (b_flag) {
2036 gtk_list_store_set(GTK_LIST_STORE(pm->monitor_model), &miter,
2037 GAPC_MON_STATUS, pmview, GAPC_MON_UPSSTATE, pch3,
2038 GAPC_MON_ICON, pixbuf, -1);
2039 } else {
2040 gtk_list_store_set(GTK_LIST_STORE(pm->monitor_model), &miter,
2041 GAPC_MON_STATUS, pmview, GAPC_MON_UPSSTATE, pch3, -1);
2045 if ((w = g_hash_table_lookup(pm->pht_Widgets, "TitleStatus"))) {
2046 gtk_label_set_markup(GTK_LABEL(w), ptitle);
2047 lg_graph_set_chart_title (pm->phs.plg, ptitle);
2048 g_snprintf(pm->ch_title_info, GAPC_MAX_TEXT, "%s", ptitle);
2050 lg_graph_draw ( pm->phs.plg );
2053 g_free(pmsg);
2054 g_free(ptitle);
2056 /* g_free (pmview); */
2058 return b_flag;
2062 * main data updating routine.
2063 * -- collects and pushes data to all ui
2065 static gint gapc_monitor_update(PGAPC_MONITOR pm)
2067 gint i_x = 0;
2068 GtkWidget *win = NULL, *w = NULL;
2069 gchar *pch = NULL, *pch1 = NULL, *pch2 = NULL, *pch3 = NULL, *pch4 = NULL;
2070 gchar *pch_watt = NULL, *pch5 = NULL, *pch6 = NULL;
2071 gdouble dValue = 0.00, dScale = 0.0, dtmp = 0.0, dCharge = 0.0, d_loadpct = 0.0, d_watt = 0.0;
2072 gchar ch_buffer[GAPC_MAX_TEXT];
2073 PGAPC_BAR_H pbar = NULL;
2075 g_return_val_if_fail(pm != NULL, FALSE);
2077 if (pm->window == NULL) /* not created yet */
2078 return TRUE;
2080 if (pm->b_run == FALSE)
2081 return FALSE;
2083 if (pm->b_data_available == FALSE)
2084 return FALSE;
2086 w = g_hash_table_lookup(pm->pht_Widgets, "StatusPage");
2087 if (gapc_util_text_view_clear_buffer(GTK_WIDGET(w))) {
2088 return FALSE;
2090 for (i_x = 1; pm->pach_status[i_x] != NULL; i_x++) {
2091 gapc_util_text_view_append(GTK_WIDGET(w), pm->pach_status[i_x]);
2094 w = g_hash_table_lookup(pm->pht_Widgets, "EventsPage");
2095 gapc_util_text_view_clear_buffer(GTK_WIDGET(w));
2096 for (i_x = 0; pm->pach_events[i_x] != NULL; i_x++) {
2097 gapc_util_text_view_prepend(GTK_WIDGET(w), pm->pach_events[i_x]);
2101 * compute graphic points */
2102 pch = g_hash_table_lookup(pm->pht_Status, "LINEV");
2103 if (pch == NULL) {
2104 pch = "n/a";
2106 dValue = g_strtod(pch, NULL);
2107 dScale = (( dValue - 200 ) > 1) ? 230.0 : 120.0;
2108 dValue /= dScale;
2109 gapc_util_point_filter_set(&(pm->phs.sq[0]), dValue);
2110 pbar = g_hash_table_lookup(pm->pht_Status, "HBar1");
2111 pbar->d_value = dValue;
2112 g_snprintf(pbar->c_text, sizeof(pbar->c_text), "%s from Utility", pch);
2113 w = g_hash_table_lookup(pm->pht_Widgets, "HBar1-Widget");
2114 if (GTK_WIDGET_DRAWABLE(w))
2115 gdk_window_invalidate_rect(w->window, &pbar->rect, FALSE);
2117 pch = g_hash_table_lookup(pm->pht_Status, "BATTV");
2118 if (pch == NULL) {
2119 pch = "n/a";
2121 pch1 = g_hash_table_lookup(pm->pht_Status, "NOMBATTV");
2122 if (pch1 == NULL) {
2123 pch1 = "n/a";
2125 dValue = g_strtod(pch, NULL);
2126 dScale = g_strtod(pch1, NULL);
2127 if (dScale == 0.0)
2128 dScale = ((gint) (dValue - 20)) ? 24 : 12;
2129 dValue /= dScale;
2130 gapc_util_point_filter_set(&(pm->phs.sq[4]), dValue);
2131 pbar = g_hash_table_lookup(pm->pht_Status, "HBar2");
2132 pbar->d_value = (dValue > 1.0) ? 1.0 : dValue;
2133 g_snprintf(pbar->c_text, sizeof(pbar->c_text), "%s DC on Battery", pch);
2135 w = g_hash_table_lookup(pm->pht_Widgets, "HBar2-Widget");
2136 if (GTK_WIDGET_DRAWABLE(w))
2137 gdk_window_invalidate_rect(w->window, &pbar->rect, FALSE);
2139 pch = g_hash_table_lookup(pm->pht_Status, "BCHARGE");
2140 if (pch == NULL) {
2141 pch = "n/a";
2143 dCharge = dValue = g_strtod(pch, NULL);
2144 dValue /= 100.0;
2145 gapc_util_point_filter_set(&(pm->phs.sq[3]), dValue);
2146 pbar = g_hash_table_lookup(pm->pht_Status, "HBar3");
2147 pbar->d_value = dValue;
2148 g_snprintf(pbar->c_text, sizeof(pbar->c_text), "%s Battery Charge", pch);
2149 w = g_hash_table_lookup(pm->pht_Widgets, "HBar3-Widget");
2150 if (GTK_WIDGET_DRAWABLE(w))
2151 gdk_window_invalidate_rect(w->window, &pbar->rect, FALSE);
2153 pch = g_hash_table_lookup(pm->pht_Status, "LOADPCT");
2154 if (pch == NULL) {
2155 pch = "n/a";
2157 dValue = g_strtod(pch, NULL);
2158 d_loadpct = dtmp = dValue /= 100.0;
2159 gapc_util_point_filter_set(&(pm->phs.sq[1]), dValue);
2160 pbar = g_hash_table_lookup(pm->pht_Status, "HBar4");
2161 pbar->d_value = (dValue > 1.0) ? 1.0 : dValue;
2162 g_snprintf(pbar->c_text, sizeof(pbar->c_text), "%s", pch);
2164 w = g_hash_table_lookup(pm->pht_Widgets, "HBar4-Widget");
2165 if (GTK_WIDGET_DRAWABLE(w))
2166 gdk_window_invalidate_rect(w->window, &pbar->rect, FALSE);
2168 pch = g_hash_table_lookup(pm->pht_Status, "TIMELEFT");
2169 if (pch == NULL) {
2170 pch = "n/a";
2172 dValue = g_strtod(pch, NULL);
2173 dScale = dValue / (1 - dtmp);
2174 dValue /= dScale;
2175 gapc_util_point_filter_set(&(pm->phs.sq[2]), dValue);
2176 pbar = g_hash_table_lookup(pm->pht_Status, "HBar5");
2177 pbar->d_value = dValue;
2178 g_snprintf(pbar->c_text, sizeof(pbar->c_text), "%s Remaining", pch);
2179 w = g_hash_table_lookup(pm->pht_Widgets, "HBar5-Widget");
2180 if (GTK_WIDGET_DRAWABLE(w))
2181 gdk_window_invalidate_rect(w->window, &pbar->rect, FALSE);
2184 * information window update */
2185 win = g_hash_table_lookup(pm->pht_Widgets, "SoftwareInformation");
2186 pch = g_hash_table_lookup(pm->pht_Status, "VERSION");
2187 pch1 = g_hash_table_lookup(pm->pht_Status, "UPSNAME");
2188 pch2 = g_hash_table_lookup(pm->pht_Status, "CABLE");
2189 pch3 = g_hash_table_lookup(pm->pht_Status, "UPSMODE");
2190 pch4 = g_hash_table_lookup(pm->pht_Status, "STARTTIME");
2191 pch5 = g_hash_table_lookup(pm->pht_Status, "STATUS");
2192 g_snprintf(ch_buffer, sizeof(ch_buffer),
2193 "<span foreground=\"blue\">" "%s\n%s\n%s\n%s\n%s\n%s" "</span>",
2194 (pch != NULL) ? pch : "N/A", (pch1 != NULL) ? pch1 : "N/A",
2195 (pch2 != NULL) ? pch2 : "N/A", (pch3 != NULL) ? pch3 : "N/A",
2196 (pch4 != NULL) ? pch4 : "N/A", (pch5 != NULL) ? pch5 : "N/A");
2197 gtk_label_set_markup(GTK_LABEL(win), ch_buffer);
2199 win = g_hash_table_lookup(pm->pht_Widgets, "PerformanceSummary");
2200 pch = g_hash_table_lookup(pm->pht_Status, "SELFTEST");
2201 pch1 = g_hash_table_lookup(pm->pht_Status, "NUMXFERS");
2202 pch2 = g_hash_table_lookup(pm->pht_Status, "LASTXFER");
2203 pch3 = g_hash_table_lookup(pm->pht_Status, "XONBATT");
2204 pch4 = g_hash_table_lookup(pm->pht_Status, "XOFFBATT");
2205 pch5 = g_hash_table_lookup(pm->pht_Status, "TONBATT");
2206 pch6 = g_hash_table_lookup(pm->pht_Status, "CUMONBATT");
2207 g_snprintf(ch_buffer, sizeof(ch_buffer),
2208 "<span foreground=\"blue\">" "%s\n%s\n%s\n%s\n%s\n%s\n%s" "</span>",
2209 (pch != NULL) ? pch : "N/A", (pch1 != NULL) ? pch1 : "N/A",
2210 (pch2 != NULL) ? pch2 : "N/A", (pch3 != NULL) ? pch3 : "N/A",
2211 (pch4 != NULL) ? pch4 : "N/A", (pch5 != NULL) ? pch5 : "N/A",
2212 (pch6 != NULL) ? pch6 : "N/A");
2213 gtk_label_set_markup(GTK_LABEL(win), ch_buffer);
2215 win = g_hash_table_lookup(pm->pht_Widgets, "ProductInformation");
2216 pch = g_hash_table_lookup(pm->pht_Status, "MODEL");
2217 pch1 = g_hash_table_lookup(pm->pht_Status, "SERIALNO");
2218 pch2 = g_hash_table_lookup(pm->pht_Status, "MANDATE");
2219 pch3 = g_hash_table_lookup(pm->pht_Status, "FIRMWARE");
2220 pch4 = g_hash_table_lookup(pm->pht_Status, "BATTDATE");
2221 pch_watt = g_hash_table_lookup(pm->pht_Status, "NOMPOWER");
2222 if (pch_watt != NULL) {
2223 pm->i_watt = g_strtod (pch_watt, NULL);
2224 d_watt = d_loadpct * pm->i_watt;
2225 } else {
2226 d_watt = d_loadpct * pm->i_watt;
2228 g_snprintf(ch_buffer, sizeof(ch_buffer),
2229 "<span foreground=\"blue\">" "%s\n%s\n%s\n%s\n%s\n%3.0f of %d" "</span>",
2230 (pch != NULL) ? pch : "N/A", (pch1 != NULL) ? pch1 : "N/A",
2231 (pch2 != NULL) ? pch2 : "N/A", (pch3 != NULL) ? pch3 : "N/A",
2232 (pch4 != NULL) ? pch4 : "N/A", d_watt, pm->i_watt);
2233 gtk_label_set_markup(GTK_LABEL(win), ch_buffer);
2235 return TRUE;
2237 /* sknet_util_log_msg()
2238 * capture the current application related error values
2239 * output the composed str only if debug_flag is on
2241 static void sknet_util_log_msg (gchar * pch_func, gchar * pch_topic, gchar * pch_emsg)
2243 if (lg_graph_debug)
2245 g_print ("%s(%s) msg=%s\n", pch_func, pch_topic, pch_emsg);
2248 return;
2252 * Write nbytes to the network.
2253 * It may require several writes.
2255 static gint sknet_net_write_nbytes (GIOChannel * ioc, gchar * ptr, gsize nbytes)
2257 gssize nleft = 0;
2258 gsize nwritten = 0;
2259 GError *gerror = NULL;
2260 GIOStatus ios = 0;
2261 gboolean b_eof = TRUE;
2263 nleft = nbytes;
2267 b_eof = FALSE;
2268 ios = g_io_channel_write_chars (ioc, ptr, nleft, &nwritten, &gerror);
2269 switch (ios)
2271 case G_IO_STATUS_ERROR:
2272 sknet_util_log_msg ("sknet_net_write_nbytes", "G_IO_STATUS_ERROR", gerror->message);
2273 g_error_free (gerror);
2274 return -1;
2275 break;
2276 case G_IO_STATUS_AGAIN:
2277 sknet_util_log_msg ("sknet_net_write_nbytes", "G_IO_STATUS_AGAIN", "retry enabled");
2278 g_usleep (500000);
2279 break;
2280 case G_IO_STATUS_EOF:
2281 sknet_util_log_msg ("sknet_net_write_nbytes", "G_IO_STATUS_EOF", "ok");
2282 return 0;
2283 break;
2284 case G_IO_STATUS_NORMAL:
2285 break;
2286 default:
2287 sknet_util_log_msg ("sknet_net_write_nbytes", "unknown state", "aborted");
2288 b_eof = TRUE;
2289 return 0;
2290 break;
2292 nleft -= nwritten;
2293 ptr += nwritten;
2295 while ((nleft > 0) && (b_eof != TRUE));
2297 return (nbytes - nleft);
2301 * Send a message over the network. The send consists of
2302 * two network packets. The first is sends a short containing
2303 * the length of the data packet which follows.
2304 * Returns number of bytes sent
2305 * Returns -1 on error
2307 static gint sknet_net_send (GIOChannel * ioc, gchar * buff, gsize len)
2309 gint rc = 0;
2310 gshort pktsiz = 0;
2312 /* send short containing size of data packet */
2313 pktsiz = g_htons ((gshort) len);
2314 rc = sknet_net_write_nbytes (ioc, (gchar *) &pktsiz, sizeof (gshort));
2315 if (rc != sizeof (gshort))
2317 sknet_util_log_msg ("sknet_net_send", "send message size", "failed");
2318 return -1;
2321 /* send data packet */
2322 rc = sknet_net_write_nbytes (ioc, buff, len);
2323 if (rc != len)
2325 sknet_util_log_msg ("sknet_net_send", "send message buffer", "failed");
2326 return -1;
2329 return rc;
2333 * Read nbytes from the network.
2334 * It is possible that the total bytes requires several
2335 * read requests, which will happen automatically.
2336 * Returns: count of bytes read, or -1 for error
2338 static gint sknet_net_read_nbytes (GIOChannel * ioc, gchar * ptr, gsize nbytes)
2340 gsize nleft = 0;
2341 gsize nread = 0;
2342 GError *gerror = NULL;
2343 GIOStatus ios = 0;
2344 gboolean b_eof = FALSE;
2346 nleft = nbytes;
2350 b_eof = FALSE;
2351 ios = g_io_channel_read_chars (ioc, ptr, nleft, &nread, &gerror);
2352 switch (ios)
2354 case G_IO_STATUS_ERROR:
2355 sknet_util_log_msg ("sknet_net_read_nbytes", "G_IO_STATUS_ERROR", gerror->message);
2356 g_error_free (gerror);
2357 return -1;
2358 break;
2359 case G_IO_STATUS_AGAIN:
2360 sknet_util_log_msg ("sknet_net_read_nbytes", "G_IO_STATUS_AGAIN", "aborted");
2361 g_usleep (500000);
2362 break;
2363 case G_IO_STATUS_EOF:
2364 sknet_util_log_msg ("sknet_net_read_nbytes", "G_IO_STATUS_EOF", "ok");
2365 return 0;
2366 break;
2367 case G_IO_STATUS_NORMAL:
2368 break;
2369 default:
2370 sknet_util_log_msg ("sknet_net_read_nbytes", "unknown state", "aborted");
2371 b_eof = TRUE;
2372 return 0;
2373 break;
2375 nleft -= nread;
2376 ptr += nread;
2378 while ((nleft > 0) && (b_eof != TRUE));
2380 return (nbytes - nleft); /* return >= 0 */
2384 * Receive a message from the other end. Each message consists of
2385 * two packets. The first is a header that contains the size
2386 * of the data that follows in the second packet.
2387 * Returns number of bytes read
2388 * Returns 0 on end of file
2389 * Returns -1 on hard end of file (i.e. network connection close)
2390 * Returns -2 on error
2392 static gint sknet_net_recv (GIOChannel * ioc, gchar * buff, gsize maxlen)
2394 gint nbytes = 0;
2395 gshort pktsiz = 0;
2397 /* get data size -- in short */
2398 nbytes = sknet_net_read_nbytes (ioc, (gchar *) &pktsiz, sizeof (gshort));
2399 if (nbytes <= 0)
2401 sknet_util_log_msg ("sknet_net_recv", "read msg_len", "failed");
2402 return -1; /* assume hard EOF received */
2404 if (nbytes != sizeof (gshort))
2406 sknet_util_log_msg ("sknet_net_recv", "read short_len", "failed");
2407 return -2;
2410 pktsiz = g_ntohs (pktsiz); /* decode no. of bytes that follow */
2411 if (pktsiz > maxlen)
2413 sknet_util_log_msg ("sknet_net_recv", "msg_len gt buffer", "overflow");
2414 return -2;
2417 if (pktsiz == 0)
2419 sknet_util_log_msg ("sknet_net_recv", "Soft error", "End-of-File");
2420 return 0; /* soft EOF */
2423 /* now read the actual data */
2424 nbytes = sknet_net_read_nbytes (ioc, buff, pktsiz);
2425 if (nbytes <= 0)
2427 sknet_util_log_msg ("sknet_net_recv", "read message", "failed");
2428 return -2;
2430 if (nbytes != pktsiz)
2432 sknet_util_log_msg ("sknet_net_recv", "read incomplete", "length error");
2433 return -2;
2436 return (nbytes); /* return actual length of message */
2439 /* sknet_net_close()
2440 * Close the active or error'ed socket
2442 static void sknet_net_close (GIOChannel *ioc, gboolean b_flush)
2444 int sockfd =0;
2445 GError *gerror = NULL;
2446 GIOStatus ios = G_IO_STATUS_NORMAL;
2448 sockfd = g_io_channel_unix_get_fd (ioc);
2449 ios = g_io_channel_shutdown (ioc, b_flush, &gerror);
2450 if (gerror != NULL)
2452 sknet_util_log_msg ("sknet_channel_close", "error", gerror->message);
2453 g_error_free (gerror);
2455 if (ios != G_IO_STATUS_NORMAL) {
2456 g_message ("net_close: g_io_channel_shutdown(%d) failed with %d", sockfd, ios);
2459 g_io_channel_unref (ioc);
2462 return;
2466 * Open a TCP connection using GIOChannels to a host
2467 * Returns NULL on error, with err text in ch_error_message
2468 * Returns GIOChannel ptr otherwise
2469 * Affects: -psk->gip, which is a sockaddr_in address of partner host
2470 * this value is allocated and retained for the life of this program
2471 * -psk->b_network_control, if true causes the addr to be resolved again
2472 * or if false, it uses the current value - saving a dns hit/query
2474 static GIOChannel *sknet_net_open (PSKCOMM psk)
2476 GIOChannel *ioc = NULL;
2477 int sockfd;
2478 struct sockaddr_in *tcp_serv_addr = NULL;
2479 gint nrc = 0;
2481 g_return_val_if_fail (psk != NULL, NULL);
2484 * Allocate a new address struct if it does not exist
2486 if (psk->gip == NULL) {
2487 psk->b_network_control=TRUE;
2488 psk->gip = g_new0( struct sockaddr_in , 1);
2489 g_return_val_if_fail (psk->gip != NULL, NULL);
2490 tcp_serv_addr = (struct sockaddr_in *)psk->gip;
2491 } else {
2492 tcp_serv_addr = (struct sockaddr_in *)psk->gip;
2496 * Fill in the structure serv_addr with the address of
2497 * the server that we want to connect with.
2499 if ( psk->b_network_control ) {
2500 memset ((char *)tcp_serv_addr, 0, sizeof (struct sockaddr_in));
2501 tcp_serv_addr->sin_family = AF_INET;
2502 tcp_serv_addr->sin_port = g_htons (psk->i_port);
2504 nrc = inet_aton (psk->ch_ip_string, (struct in_addr *)&tcp_serv_addr->sin_addr.s_addr);
2505 if ( nrc == 0) /* inet_aton failed */
2507 struct hostent he, *phe;
2508 char *buff;
2509 size_t bufflen = 0;
2511 phe = gethostname_re(psk->ch_ip_string, &he, &buff, &bufflen);
2512 if (phe == NULL)
2514 free(buff);
2515 sknet_util_log_msg ("sknet_net_open", "gethostbyname() failed", "");
2516 g_snprintf(psk->ch_error_msg, sizeof(psk->ch_error_msg), "gethostbyname() failed");
2517 psk->ioc = NULL;
2518 return NULL;
2520 if (he.h_length != sizeof (struct in_addr) || he.h_addrtype != AF_INET)
2522 free(buff);
2523 sknet_util_log_msg ("sknet_net_open", "struct hostent", "argument error");
2524 g_snprintf(psk->ch_error_msg, sizeof(psk->ch_error_msg),"%s","argument error");
2525 psk->ioc = NULL;
2526 return NULL;
2529 tcp_serv_addr->sin_addr.s_addr = *(unsigned int *) he.h_addr;
2530 free(buff);
2531 } /* end if inet_addr */
2533 } /* end if b_network */
2536 /* Open a TCP socket */
2537 if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
2539 sknet_util_log_msg ("sknet_net_open", "socket() api failed",
2540 (gchar *) g_strerror (errno));
2541 g_snprintf(psk->ch_error_msg, sizeof(psk->ch_error_msg),"%s",
2542 (gchar *) g_strerror (errno));
2543 psk->ioc = NULL;
2544 return NULL;
2548 struct timeval tv;
2549 int rcx = 0;
2550 tv.tv_sec = 0;
2551 tv.tv_usec = 200000;
2553 rcx = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO | SO_SNDTIMEO,
2554 &tv, (socklen_t) sizeof(struct timeval));
2555 if (rcx == -1) {
2556 sknet_util_log_msg ("sknet_net_open", "setsockopt(200ms) failed!",
2557 (gchar *) g_strerror (errno));
2562 /* connect to server */
2563 if ((connect (sockfd, (struct sockaddr *) tcp_serv_addr, sizeof (struct sockaddr_in))) == -1)
2565 sknet_util_log_msg ("sknet_net_open", "connect() api failed",
2566 (gchar *) g_strerror (errno));
2567 g_snprintf(psk->ch_error_msg, sizeof(psk->ch_error_msg),"%s",
2568 (gchar *) g_strerror (errno));
2570 close (sockfd);
2571 psk->b_network_control = TRUE;
2572 psk->ioc = NULL;
2573 return NULL;
2576 psk->b_network_control = FALSE;
2578 ioc = g_io_channel_unix_new (sockfd);
2579 g_io_channel_set_encoding (ioc, NULL, NULL);
2580 g_io_channel_set_buffered (ioc, FALSE);
2582 psk->ioc = ioc;
2583 return ioc;
2586 /* sknet_net_client_init()
2587 * Create a control structure and set ip values
2588 * for an open call.
2589 * return NULL on error.
2591 static PSKCOMM sknet_net_client_init (gchar *pch_remote_ip, gint i_remote_port)
2593 PSKCOMM psk = NULL;
2595 psk = g_new0(SKNET_COMMS, 1);
2596 g_return_val_if_fail(psk != NULL, NULL);
2598 psk->gp_reserved = NULL;
2599 psk->cb_id = 0; /* initialize count of instances created */
2600 g_snprintf( psk->ch_ip_string, sizeof(psk->ch_ip_string), "%s", pch_remote_ip);
2601 psk->i_port = i_remote_port;
2602 psk->b_network_control = TRUE;
2604 g_snprintf (psk->ch_error_msg, sizeof (psk->ch_error_msg),
2605 "client init(client ready to connect to %s:%6d",
2606 psk->ch_ip_string, psk->i_port);
2607 sknet_util_log_msg ("sknet_net_client_init", psk->ch_error_msg, "Ready");
2609 return psk;
2613 * Close server socket if open and release internal storage
2615 static void sknet_net_shutdown (PSKCOMM psk)
2618 g_return_if_fail (psk != NULL);
2620 if (psk->gp_reserved != NULL) {
2621 ((PSKCOMM)psk->gp_reserved)->cb_id--; /* decrement count of instances created */
2622 } else { /* or close main socket */
2623 if (psk->fd_server)
2625 close (psk->fd_server);
2629 if (psk->gip != NULL) {
2630 g_free(psk->gip);
2633 g_free(psk);
2635 return;
2639 * performs a complete NIS transaction by sending cmd and
2640 * loading each result line into the pch array.
2641 * also, refreshes status key/value pairs in hastable.
2642 * return error = 0, or number of lines read from network
2644 static gint gapc_net_transaction_service(PGAPC_MONITOR pm, gchar * cp_cmd, gchar ** pch)
2646 gint n = 0, iflag = 0;
2647 GIOChannel *ioc = NULL;
2649 g_return_val_if_fail(pm, -1);
2650 g_return_val_if_fail(pm->psk, -1);
2651 g_return_val_if_fail(pm->pch_host, -1);
2654 ioc = sknet_net_open(pm->psk);
2655 if (ioc == NULL) {
2656 return 0;
2659 n = sknet_net_send( ioc, cp_cmd, g_utf8_strlen(cp_cmd, -1));
2660 if (n <= 0) {
2661 sknet_net_close( ioc, TRUE);
2662 return 0;
2665 /* clear current data */
2666 for (iflag = 0; iflag < GAPC_MAX_ARRAY; iflag++) {
2667 if (pch[iflag] != NULL) {
2668 g_free(pch[iflag]);
2670 pch[iflag] = NULL;
2673 iflag = 0;
2674 while (iflag < GAPC_MAX_ARRAY) {
2675 n = sknet_net_recv(ioc, pm->psk->ch_session_message, sizeof(pm->psk->ch_session_message));
2676 if (n < 1)
2677 break;
2679 pm->psk->ch_session_message[n] = 0;
2680 pch[iflag++] = g_strdup(pm->psk->ch_session_message);
2682 if (g_str_equal(cp_cmd, "status") && iflag > 1)
2683 gapc_util_update_hashtable(pm, pm->psk->ch_session_message);
2686 sknet_net_close(ioc, TRUE);
2688 return iflag; /* count of records received */
2692 * Worker thread for network communications.
2694 static gpointer *gapc_net_thread_qwork(PGAPC_MONITOR pm)
2696 gint rc = 0;
2697 GAsyncQueue *thread_queue = NULL;
2699 g_return_val_if_fail(pm != NULL, NULL);
2700 g_return_val_if_fail(pm->q_network != NULL, NULL);
2702 g_async_queue_ref(pm->q_network);
2703 thread_queue = pm->q_network;
2705 if (pm->psk == NULL) {
2706 pm->psk = sknet_net_client_init (pm->pch_host, pm->i_port);
2707 if (pm->psk == NULL) {
2708 g_async_queue_unref(thread_queue);
2709 g_thread_exit(GINT_TO_POINTER(0));
2713 while ((pm = (PGAPC_MONITOR) g_async_queue_pop(thread_queue))) {
2714 if (pm->b_thread_stop) {
2715 break;
2718 if (pm->b_run) {
2719 g_mutex_lock(pm->gm_update);
2720 if (!pm->b_run) { /* may have waited a while for lock */
2721 g_mutex_unlock(pm->gm_update);
2722 continue;
2725 if ((rc = gapc_net_transaction_service(pm, "status", pm->pach_status))) {
2726 gapc_net_transaction_service(pm, "events", pm->pach_events);
2728 g_mutex_unlock(pm->gm_update);
2730 if (rc > 0) {
2731 pm->b_data_available = TRUE;
2732 } else {
2733 pm->b_data_available = FALSE;
2735 } else {
2736 pm->b_data_available = FALSE;
2738 } /* end-while */
2740 if (pm->psk != NULL) {
2741 sknet_net_shutdown (pm->psk);
2742 pm->psk = NULL;
2745 g_async_queue_unref(thread_queue);
2747 g_thread_exit(GINT_TO_POINTER(1));
2749 return NULL;
2753 * return the answer and reset the internal controls to zero
2755 static gdouble gapc_util_point_filter_reset(PGAPC_SUMS sq)
2757 gdouble d_the_final_answer = 0.0;
2759 g_mutex_lock(sq->gm_graph);
2761 d_the_final_answer = sq->last_answer;
2763 sq->point_count = 0;
2765 sq->this_point = 0.0;
2766 sq->last_point = 0.0;
2768 sq->this_answer = 0.0;
2769 sq->last_answer = 0.0;
2771 sq->answer_summ = 0.0;
2772 sq->point_min = 0.0;
2773 sq->point_max = 0.0;
2775 g_mutex_unlock(sq->gm_graph);
2777 return (d_the_final_answer);
2781 * Compute the average of the given data point
2783 static gdouble gapc_util_point_filter_set(PGAPC_SUMS sq, gdouble this_point)
2785 g_mutex_lock(sq->gm_graph);
2787 sq->this_point = this_point;
2789 sq->this_point *= 100;
2790 sq->point_count++;
2792 /* some calc here */
2793 sq->answer_summ += sq->this_point ;
2794 sq->this_answer = sq->answer_summ / sq->point_count;
2796 sq->last_point = sq->this_point;
2797 sq->last_answer = sq->this_answer;
2799 if (sq->point_min > sq->this_point)
2800 sq->point_min = sq->this_point;
2801 if (sq->point_max < sq->this_point)
2802 sq->point_max = sq->this_point;
2804 g_mutex_unlock(sq->gm_graph);
2806 return (sq->this_answer);
2810 * Get a iter to the list_store record containing this monitor key.
2811 * Will search either list_store
2812 * - monitor col is the same in both models
2813 * Returns: TRUE and iter is found, FALSE and invalid iter if not found
2815 static gboolean gapc_util_treeview_get_iter_from_monitor(GtkTreeModel * model,
2816 GtkTreeIter * iter, gint i_value)
2818 gboolean valid = FALSE, b_result = FALSE;
2819 gint i_monitor;
2821 g_return_val_if_fail(model != NULL, FALSE);
2822 g_return_val_if_fail(iter != NULL, FALSE);
2824 valid = gtk_tree_model_get_iter_first(model, iter);
2825 while (valid) {
2826 gtk_tree_model_get(model, iter, GAPC_PREFS_MONITOR, &i_monitor, -1);
2828 if (i_monitor == i_value) {
2829 /* set sucess flag */
2830 b_result = TRUE;
2831 break;
2833 valid = gtk_tree_model_iter_next(model, iter);
2836 return b_result;
2840 * Add a preferences record to the gconf instance and prefs_model
2841 * returns FALSE on error
2842 * returns TRUE on sucess
2844 static gboolean gapc_panel_preferences_gconf_add_rec(PGAPC_CONFIG pcfg,
2845 gint i_monitor)
2847 GAPC_PKEYS pk;
2848 gchar *pkey = NULL;
2850 g_return_val_if_fail(pcfg != NULL, FALSE);
2851 g_return_val_if_fail(pcfg->client != NULL, FALSE);
2852 g_return_val_if_fail(pcfg->prefs_model != NULL, FALSE);
2854 pkey = GAPC_MID_GROUP_KEY;
2855 g_snprintf(pk.k_enabled, GAPC_MAX_TEXT, "%s/%d/%s", pkey, i_monitor, "enabled");
2856 g_snprintf(pk.k_use_systray, GAPC_MAX_TEXT, "%s/%d/%s", pkey, i_monitor,
2857 "use_systray");
2858 g_snprintf(pk.k_port_number, GAPC_MAX_TEXT, "%s/%d/%s", pkey, i_monitor,
2859 "port_number");
2860 g_snprintf(pk.k_network_interval, GAPC_MAX_TEXT, "%s/%d/%s", pkey, i_monitor,
2861 "network_interval");
2862 g_snprintf(pk.k_graph_interval, GAPC_MAX_TEXT, "%s/%d/%s", pkey, i_monitor,
2863 "graph_interval");
2864 g_snprintf(pk.k_host_name, GAPC_MAX_TEXT, "%s/%d/%s", pkey, i_monitor,
2865 "host_name");
2866 g_snprintf(pk.v_host_name, GAPC_MAX_TEXT, "%s", GAPC_HOST_DEFAULT);
2868 gconf_client_set_bool(pcfg->client, pk.k_enabled, FALSE, NULL);
2869 gconf_client_set_bool(pcfg->client, pk.k_use_systray, FALSE, NULL);
2870 gconf_client_set_int(pcfg->client, pk.k_port_number, GAPC_PORT_DEFAULT, NULL);
2871 gconf_client_set_float(pcfg->client, pk.k_network_interval, GAPC_REFRESH_DEFAULT,
2872 NULL);
2873 gconf_client_set_float(pcfg->client, pk.k_graph_interval,
2874 GAPC_LINEGRAPH_REFRESH_FACTOR, NULL);
2875 gconf_client_set_string(pcfg->client, pk.k_host_name, pk.v_host_name, NULL);
2877 return TRUE;
2881 * capture the current application related error values centrally
2883 static void gapc_util_log_app_msg(gchar * pch_func, gchar * pch_topic,
2884 gchar * pch_emsg)
2886 gchar *pch = NULL;
2888 g_return_if_fail(pch_func != NULL);
2890 pch = g_strdup_printf("%s(%s) emsg=%s", pch_func, pch_topic, pch_emsg);
2892 g_message(pch);
2894 g_free(pch);
2896 return;
2900 * parses received line of text into key/value pairs to be inserted
2901 * into the status hashtable.
2903 static gint gapc_util_update_hashtable(PGAPC_MONITOR pm, gchar * pch_unparsed)
2905 gchar *pch_in = NULL;
2906 gchar *pch = NULL;
2907 gchar *pch_end = NULL;
2908 gint ilen = 0;
2910 g_return_val_if_fail(pm != NULL, FALSE);
2911 g_return_val_if_fail(pch_unparsed != NULL, -1);
2913 /* unparsed contains - keystring : keyvalue nl */
2914 pch_in = g_strdup(pch_unparsed);
2915 pch_end = g_strrstr(pch_in, "\n");
2916 if (pch_end != NULL)
2917 *pch_end = 0;
2919 ilen = g_utf8_strlen(pch_in, -1);
2921 pch = g_strstr_len(pch_in, ilen, ":");
2922 *pch = 0;
2923 pch_in = g_strchomp(pch_in);
2924 pch++;
2925 pch = g_strstrip(pch);
2927 g_hash_table_replace(pm->pht_Status, g_strdup(pch_in), g_strdup(pch));
2929 g_free(pch_in);
2931 return ilen;
2935 * Implements a Horizontal Bar Chart...
2936 * - data value has a range of 0.0 to 1.0 for 0-100% display
2937 * - in chart text is limited to about 30 chars
2939 static gboolean cb_util_barchart_handle_exposed(GtkWidget * widget,
2940 GdkEventExpose * event, gpointer data)
2942 PGAPC_BAR_H pbar = data;
2943 gint i_percent = 0;
2944 PangoLayout *playout = NULL;
2946 g_return_val_if_fail(data, FALSE); /* error exit */
2948 pbar->rect.x = 0;
2949 pbar->rect.y = 0;
2950 pbar->rect.width = widget->allocation.width;
2951 pbar->rect.height = widget->allocation.height;
2953 /* scale up the less than zero data value */
2954 i_percent =
2955 (gint) ((gdouble) (widget->allocation.width / 100.0) *
2956 (gdouble) (pbar->d_value * 100.0));
2958 /* the frame of the chart */
2959 gtk_paint_box(widget->style, widget->window, GTK_WIDGET_STATE(widget),
2960 GTK_SHADOW_ETCHED_IN, &pbar->rect, widget, "gapc_hbar_frame", 0, 0,
2961 widget->allocation.width - 1, widget->allocation.height - 1);
2963 /* the scaled value */
2964 gtk_paint_box(widget->style, widget->window, GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
2965 &pbar->rect, widget, "gapc_hbar_value", 1, 1, i_percent,
2966 widget->allocation.height - 4);
2968 if (pbar->c_text[0]) {
2969 gint x = 0, y = 0;
2971 playout = gtk_widget_create_pango_layout(widget, pbar->c_text);
2972 pango_layout_set_markup(playout, pbar->c_text, -1);
2974 pango_layout_get_pixel_size(playout, &x, &y);
2975 x = (widget->allocation.width - x) / 2;
2976 y = (widget->allocation.height - y) / 2;
2978 gtk_paint_layout(widget->style, widget->window, GTK_STATE_NORMAL, TRUE,
2979 &pbar->rect, widget, "gapc_hbar_text",
2980 (pbar->b_center_text) ? x : 6, y, playout);
2982 g_object_unref(playout);
2985 return TRUE;
2989 * creates horizontal bar chart and allocates control data
2990 * requires cb_h_bar_chart_exposed() routine
2991 * return drawing area widget
2993 static GtkWidget *gapc_util_barchart_create(PGAPC_MONITOR pm, GtkWidget * vbox,
2994 gchar * pch_hbar_name, gdouble d_percent, gchar * pch_text)
2996 PGAPC_BAR_H pbar = NULL;
2997 GtkWidget *drawing_area = NULL;
2998 gchar *pch = NULL;
3000 g_return_val_if_fail(pm != NULL, NULL);
3002 pbar = g_new0(GAPC_BAR_H, 1);
3003 pbar->d_value = d_percent;
3004 pbar->b_center_text = FALSE;
3005 g_strlcpy(pbar->c_text, pch_text, sizeof(pbar->c_text));
3007 drawing_area = gtk_drawing_area_new(); /* manual bargraph */
3008 gtk_widget_set_size_request(drawing_area, 100, 20);
3009 g_signal_connect(G_OBJECT(drawing_area), "expose_event",
3010 G_CALLBACK(cb_util_barchart_handle_exposed), (gpointer) pbar);
3012 gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0);
3013 gtk_widget_show(drawing_area);
3014 g_hash_table_insert(pm->pht_Status, g_strdup(pch_hbar_name), pbar);
3015 pch = g_strdup_printf("%s-Widget", pch_hbar_name);
3016 g_hash_table_insert(pm->pht_Widgets, pch, drawing_area);
3018 return drawing_area;
3022 * Utility Routines for text views
3024 static gboolean gapc_util_text_view_clear_buffer(GtkWidget * view)
3026 GtkTextIter start, end;
3027 GtkTextBuffer *buffer = NULL;
3029 g_return_val_if_fail(view != NULL, TRUE);
3031 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
3032 gtk_text_buffer_get_bounds(buffer, &start, &end);
3033 gtk_text_buffer_delete(buffer, &start, &end);
3035 return FALSE;
3039 * Utility Routines for text views
3041 static void gapc_util_text_view_prepend(GtkWidget * view, gchar * pch)
3043 GtkTextIter iter;
3044 GtkTextBuffer *buffer;
3046 g_return_if_fail(view != NULL);
3047 g_return_if_fail(pch != NULL);
3049 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
3050 gtk_text_buffer_get_start_iter(buffer, &iter);
3051 gtk_text_buffer_insert(buffer, &iter, pch, -1);
3055 * Utility Routines for text views
3057 static void gapc_util_text_view_append(GtkWidget * view, gchar * pch)
3059 GtkTextIter iter;
3060 GtkTextBuffer *buffer;
3062 g_return_if_fail(view != NULL);
3063 g_return_if_fail(pch != NULL);
3065 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
3066 gtk_text_buffer_get_end_iter(buffer, &iter);
3067 gtk_text_buffer_insert(buffer, &iter, pch, -1);
3070 static gint gapc_panel_monitor_model_rec_add(PGAPC_CONFIG pcfg, PGAPC_MONITOR pm)
3072 GtkTreeIter iter;
3073 gchar *pch = NULL;
3075 g_return_val_if_fail(pcfg != NULL, -1);
3076 g_return_val_if_fail(pm != NULL, -1);
3077 g_return_val_if_fail(pcfg->monitor_model != NULL, -1);
3078 g_return_val_if_fail(pcfg->monitor_select != NULL, -1);
3080 gtk_list_store_append(GTK_LIST_STORE(pcfg->monitor_model), &iter);
3082 pch = g_hash_table_lookup(pm->pht_Status, "STATUS");
3083 if (pch == NULL) {
3084 pch = "Starting";
3087 gtk_list_store_set(GTK_LIST_STORE(pcfg->monitor_model), &iter, GAPC_MON_ICON,
3088 pm->my_icons[pm->i_icon_index], GAPC_MON_STATUS,
3089 pm->ch_title_info, GAPC_MON_MONITOR, pm->cb_monitor_num,
3090 GAPC_MON_POINTER, (gpointer) pm, GAPC_MON_UPSSTATE, g_strdup(pch), -1);
3092 gtk_tree_selection_select_iter(pcfg->monitor_select, &iter);
3094 return TRUE;
3097 static gint gapc_panel_preferences_model_rec_remove(PGAPC_CONFIG pcfg)
3099 GtkTreeIter iter, *piter = NULL;
3100 gboolean result = FALSE;
3101 gint i_monitor = 0;
3102 gchar ch[GAPC_MAX_TEXT];
3103 gchar chk[GAPC_MAX_TEXT];
3104 GError *gerror = NULL;
3106 g_return_val_if_fail(pcfg != NULL, -1);
3107 g_return_val_if_fail(pcfg->prefs_model != NULL, -1);
3109 if (gtk_tree_selection_get_selected(pcfg->prefs_select, NULL, &iter)) {
3110 piter = gtk_tree_iter_copy(&iter);
3111 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(pcfg->prefs_model), piter)) {
3112 gtk_tree_selection_select_iter(pcfg->prefs_select, piter);
3114 gtk_tree_iter_free(piter);
3115 gtk_tree_model_get(GTK_TREE_MODEL(pcfg->prefs_model), &iter,
3116 GAPC_PREFS_MONITOR, &i_monitor, -1);
3118 /* now remove the record from gconf */
3119 g_snprintf(ch, GAPC_MAX_TEXT, "%s/%d", GAPC_MID_GROUP_KEY, i_monitor);
3121 gconf_client_unset(pcfg->client, ch, &gerror);
3122 if (gerror != NULL) {
3123 gapc_util_log_app_msg("gapc_panel_preferences_model_rec_remove()",
3124 "gconf_client_unset(DIR) Failed", gerror->message);
3125 g_error_free(gerror);
3126 gerror = NULL;
3129 gconf_client_suggest_sync(pcfg->client, &gerror);
3130 if (gerror != NULL) {
3131 gapc_util_log_app_msg("gapc_panel_preferences_model_rec_remove()",
3132 "gconf_client_suggest_sync() Failed", gerror->message);
3133 g_error_free(gerror);
3134 gerror = NULL;
3137 g_snprintf(chk, GAPC_MAX_TEXT, "%s/%s", ch, "enabled");
3138 gconf_client_unset(pcfg->client, chk, NULL);
3140 g_snprintf(chk, GAPC_MAX_TEXT, "%s/%s", ch, "use_systray");
3141 gconf_client_unset(pcfg->client, chk, NULL);
3143 g_snprintf(chk, GAPC_MAX_TEXT, "%s/%s", ch, "skip_pagers");
3144 gconf_client_unset(pcfg->client, chk, NULL);
3146 g_snprintf(chk, GAPC_MAX_TEXT, "%s/%s", ch, "port_number");
3147 gconf_client_unset(pcfg->client, chk, NULL);
3149 g_snprintf(chk, GAPC_MAX_TEXT, "%s/%s", ch, "network_interval");
3150 gconf_client_unset(pcfg->client, chk, NULL);
3152 g_snprintf(chk, GAPC_MAX_TEXT, "%s/%s", ch, "graph_interval");
3153 gconf_client_unset(pcfg->client, chk, NULL);
3155 g_snprintf(chk, GAPC_MAX_TEXT, "%s/%s", ch, "host_name");
3156 gconf_client_unset(pcfg->client, chk, NULL);
3158 gconf_client_unset(pcfg->client, ch, &gerror); /* again to drop it in gconf */
3159 if (gerror != NULL) {
3160 gapc_util_log_app_msg("gapc_panel_preferences_model_rec_remove()",
3161 "gconf_client_unset(DIR) Failed", gerror->message);
3162 g_error_free(gerror);
3163 gerror = NULL;
3166 gconf_client_suggest_sync(pcfg->client, &gerror);
3167 if (gerror != NULL) {
3168 gapc_util_log_app_msg("gapc_panel_preferences_model_rec_remove()",
3169 "gconf_client_suggest_sync() Failed", gerror->message);
3170 g_error_free(gerror);
3171 gerror = NULL;
3176 return result;
3179 static gint gapc_panel_preferences_model_rec_add(PGAPC_CONFIG pcfg)
3181 g_return_val_if_fail(pcfg != NULL, -1);
3182 g_return_val_if_fail(pcfg->prefs_model != NULL, -1);
3183 g_return_val_if_fail(pcfg->prefs_select != NULL, -1);
3185 gapc_panel_preferences_gconf_add_rec(pcfg, ++pcfg->prefs_last_monitor);
3187 return TRUE;
3191 * EggTrayIcon Callbacks
3193 static void cb_panel_systray_icon_activated(GtkPlug * plug, gpointer gp)
3195 PGAPC_CONFIG pcfg = NULL;
3196 PGAPC_MONITOR pm = NULL;
3198 g_return_if_fail(plug != NULL);
3199 g_return_if_fail(gp != NULL);
3201 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
3202 /* this is a monitor struct (2) */
3203 pm = (PGAPC_MONITOR) gp;
3204 if (pm->window != NULL) {
3205 g_object_set(pm->window, "skip-pager-hint", TRUE, "skip-taskbar-hint",
3206 TRUE, NULL);
3209 } else {
3210 /* this is a config struct (1) */
3211 pcfg = (PGAPC_CONFIG) gp;
3212 if (pcfg->window != NULL) {
3213 g_object_set(pcfg->window, "skip-pager-hint", TRUE, "skip-taskbar-hint",
3214 TRUE, NULL);
3219 return;
3222 static gboolean cb_panel_systray_icon_configure(GtkWidget * widget,
3223 GdkEventConfigure * event, gpointer gp)
3225 PGAPC_CONFIG pcfg = NULL;
3226 PGAPC_MONITOR pm = NULL;
3228 gint *pi_icon_size = NULL;
3230 g_return_val_if_fail(gp != NULL, FALSE);
3231 g_return_val_if_fail(event != NULL, FALSE);
3233 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
3234 /* this is a monitor struct (2) */
3235 pm = (PGAPC_MONITOR) gp;
3236 pi_icon_size = &pm->i_icon_size;
3237 pm->i_icon_height = event->height;
3238 pm->i_icon_width = event->width;
3239 } else {
3240 /* this is a config struct (1) */
3241 pcfg = (PGAPC_CONFIG) gp;
3242 pi_icon_size = &pcfg->i_icon_size;
3243 pcfg->i_icon_height = event->height;
3244 pcfg->i_icon_width = event->width;
3247 *pi_icon_size = MIN(event->width, event->height);
3248 return FALSE;
3251 static gboolean cb_panel_systray_icon_handle_clicked(GtkWidget * widget,
3252 GdkEventButton * event, gpointer gp)
3254 PGAPC_CONFIG pcfg = NULL;
3255 PGAPC_MONITOR pm = NULL;
3256 GtkWidget *window = NULL;
3257 gboolean b_visible = FALSE;
3258 GtkWidget *menu = NULL;
3260 g_return_val_if_fail(gp != NULL, FALSE);
3261 g_return_val_if_fail(widget != NULL, FALSE);
3263 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
3264 /* this is a monitor struct (2) */
3265 pm = (PGAPC_MONITOR) gp;
3266 window = pm->window;
3267 b_visible = pm->b_visible;
3268 menu = pm->menu;
3269 } else {
3270 /* this is a config struct (1) */
3271 pcfg = (PGAPC_CONFIG) gp;
3272 window = pcfg->window;
3273 b_visible = pcfg->b_visible;
3274 menu = pcfg->menu;
3277 if (window == NULL) {
3278 return FALSE;
3281 if (event->type == GDK_BUTTON_PRESS) {
3282 switch (event->button) {
3283 case 1:
3284 if (b_visible) {
3285 gtk_widget_hide(GTK_WIDGET(window));
3286 } else {
3287 gtk_window_present(GTK_WINDOW(window));
3289 break;
3290 case 2:
3291 case 3:
3292 if (menu != NULL) {
3293 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button,
3294 event->time);
3296 break;
3297 default:
3298 return FALSE;
3301 return TRUE;
3304 return FALSE;
3307 static void cb_panel_systray_icon_destroy(GtkObject * object, gpointer gp)
3309 PGAPC_CONFIG pcfg = NULL;
3310 PGAPC_MONITOR pm = NULL;
3312 g_return_if_fail(gp != NULL);
3314 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
3315 /* this is a monitor struct (2) */
3316 pm = (PGAPC_MONITOR) gp;
3317 pm->tray_icon = NULL;
3318 pm->tray_image = NULL;
3320 if (pm->b_run && (pm->window != NULL)) {
3321 g_object_set(pm->window, "skip-pager-hint", FALSE, "skip-taskbar-hint",
3322 FALSE, NULL);
3323 gtk_window_present(GTK_WINDOW(pm->window));
3326 } else {
3327 /* this is a config struct (1) */
3328 pcfg = (PGAPC_CONFIG) gp;
3329 pcfg->tray_icon = NULL;
3330 pcfg->tray_image = NULL;
3332 if (pcfg->b_run && (pcfg->window != NULL)) {
3333 g_object_set(pcfg->window, "skip-pager-hint", FALSE, "skip-taskbar-hint",
3334 FALSE, NULL);
3335 gtk_window_present(GTK_WINDOW(pcfg->window));
3339 return;
3342 static gboolean gapc_panel_systray_icon_create(gpointer gp)
3344 PGAPC_CONFIG pcfg = NULL;
3345 PGAPC_MONITOR pm = NULL;
3347 EggTrayIcon **tray_icon = NULL;
3348 GtkWidget **tray_image = NULL;
3349 GdkPixbuf *pixbuf = NULL;
3350 GtkTooltips *tooltips = NULL;
3351 gchar *pch_title = NULL;
3353 g_return_val_if_fail(gp != NULL, FALSE);
3355 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
3356 /* this is a monitor struct (2) */
3357 pm = (PGAPC_MONITOR) gp;
3358 tray_icon = &pm->tray_icon;
3359 tray_image = &pm->tray_image;
3360 tooltips = pm->tooltips;
3361 pixbuf = pm->my_icons[GAPC_ICON_DEFAULT];
3363 if (!pm->cb_use_systray) {
3364 return FALSE;
3367 pch_title = pm->ch_title_info;
3368 } else {
3369 /* this is a config struct (1) */
3370 pcfg = (PGAPC_CONFIG) gp;
3371 tray_icon = &pcfg->tray_icon;
3372 tray_image = &pcfg->tray_image;
3373 tooltips = pcfg->tooltips;
3374 pixbuf = pcfg->my_icons[GAPC_ICON_DEFAULT];
3375 pch_title = GAPC_WINDOW_TITLE;
3377 if (!pcfg->b_use_systray) {
3378 return FALSE;
3382 g_return_val_if_fail(*tray_icon == NULL, FALSE);
3383 g_return_val_if_fail(*tray_image == NULL, FALSE);
3385 *tray_icon = egg_tray_icon_new(pch_title);
3386 g_return_val_if_fail(*tray_icon != NULL, FALSE);
3388 g_signal_connect(*tray_icon, "embedded",
3389 G_CALLBACK(cb_panel_systray_icon_activated), gp);
3390 g_signal_connect(*tray_icon, "destroy",
3391 G_CALLBACK(cb_panel_systray_icon_destroy), gp);
3392 g_signal_connect(*tray_icon, "configure-event",
3393 G_CALLBACK(cb_panel_systray_icon_configure), gp);
3394 g_signal_connect(*tray_icon, "button-press-event",
3395 G_CALLBACK(cb_panel_systray_icon_handle_clicked), gp);
3397 *tray_image = gtk_image_new_from_pixbuf(pixbuf);
3398 gtk_container_add(GTK_CONTAINER(*tray_icon), *tray_image);
3399 gtk_widget_show(*tray_image);
3401 gtk_widget_show_all(GTK_WIDGET(*tray_icon));
3403 if (tooltips != NULL) {
3404 gtk_tooltips_set_tip(tooltips, GTK_WIDGET(*tray_icon), pch_title, NULL);
3407 return TRUE;
3410 static gboolean gapc_panel_systray_icon_remove(gpointer gp)
3412 PGAPC_CONFIG pcfg = NULL;
3413 PGAPC_MONITOR pm = NULL;
3415 EggTrayIcon **tray_icon = NULL;
3416 GtkWidget **tray_image = NULL;
3418 g_return_val_if_fail(gp != NULL, FALSE);
3420 if (((PGAPC_MONITOR) gp)->cb_id == CB_MONITOR_ID) {
3421 /* this is a monitor struct (2) */
3422 pm = (PGAPC_MONITOR) gp;
3423 tray_icon = &pm->tray_icon;
3424 tray_image = &pm->tray_image;
3425 } else {
3426 /* this is a config struct (1) */
3427 pcfg = (PGAPC_CONFIG) gp;
3428 tray_icon = &pcfg->tray_icon;
3429 tray_image = &pcfg->tray_image;
3432 g_return_val_if_fail(*tray_icon != NULL, FALSE);
3433 g_return_val_if_fail(*tray_image != NULL, FALSE);
3435 gtk_widget_destroy(*tray_image);
3436 gtk_widget_destroy(GTK_WIDGET(*tray_icon));
3438 return TRUE;
3442 * Handle the prefs add record button action
3444 static void cb_panel_prefs_button_add_rec(GtkWidget * button, PGAPC_CONFIG pcfg)
3446 g_return_if_fail(pcfg != NULL);
3448 gapc_panel_preferences_model_rec_add(pcfg);
3450 return;
3454 * Handle the prefs remove record button action
3456 static void cb_panel_prefs_button_remove_rec(GtkWidget * button, PGAPC_CONFIG pcfg)
3458 g_return_if_fail(pcfg != NULL);
3460 gapc_panel_preferences_model_rec_remove(pcfg);
3462 return;
3466 * Handle the prefs use-systray checkbutton action
3468 static void cb_panel_prefs_button_use_systray(GtkWidget * button, PGAPC_CONFIG pcfg)
3470 gboolean b_value = FALSE;
3471 gchar *pch = NULL;
3473 g_return_if_fail(pcfg != NULL);
3475 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
3476 b_value = TRUE;
3477 } else {
3478 b_value = FALSE;
3481 pch = pcfg->pch_gkeys[GAPC_PREFS_SYSTRAY];
3482 gconf_client_set_bool(pcfg->client, pch, b_value, NULL);
3484 return;
3488 * Handled the toggle of a checkbox in the preferences dialog
3489 * Could be:
3490 * enabled - enabled this monitor to run
3491 * systray - include the notification tray icon
3492 * pagers - remove from task_list and pager_list
3494 static void cb_panel_prefs_handle_cell_toggled(GtkCellRendererToggle * cell,
3495 gchar * path_str, PGAPC_PREFS_COLUMN pcolumn)
3497 GtkTreeModel *model;
3498 GtkTreeIter iter;
3499 GtkTreePath *path = NULL;
3500 gboolean b_value;
3501 gint col_number = 0, i_monitor = 0;
3502 gchar *penabled = NULL;
3504 g_return_if_fail(pcolumn != NULL);
3505 g_return_if_fail(path_str != NULL);
3507 model = pcolumn->prefs_model;
3508 col_number = pcolumn->i_col_num;
3510 /* get toggled iter */
3511 path = gtk_tree_path_new_from_string(path_str);
3512 gtk_tree_model_get_iter(model, &iter, path);
3513 gtk_tree_path_free(path);
3515 /* get the column id they asked for -- hope its boolean */
3516 gtk_tree_model_get(model, &iter, col_number, &b_value, GAPC_PREFS_MONITOR,
3517 &i_monitor, -1);
3519 /* do something with the value */
3520 b_value ^= 1;
3522 switch (col_number) {
3523 case GAPC_PREFS_ENABLED:
3524 penabled = g_strdup_printf(GAPC_ENABLE_KEY, i_monitor);
3525 gconf_client_set_bool(pcolumn->client, penabled, b_value, NULL);
3526 g_free(penabled);
3527 break;
3528 case GAPC_PREFS_SYSTRAY:
3529 penabled = g_strdup_printf(GAPC_SYSTRAY_KEY, i_monitor);
3530 gconf_client_set_bool(pcolumn->client, penabled, b_value, NULL);
3531 g_free(penabled);
3532 break;
3533 default:
3534 g_message("Cell_Toggled:Unknown key for Value(%s)\n",
3535 b_value ? "True" : "False");
3536 break;
3539 return;
3543 * A callback routine that collect changes to the path row and save it directly
3544 * to the desired location, also passes it back to the treeview for display.
3545 * These data point use this routine.
3546 * - Host
3547 * - Port
3548 * - Graph refresh
3549 * - Network refresh
3550 * - Monitor - not a visible field
3551 * We update gconf here and gconf updates the
3552 * list_store in cb_panel_preference_gconf_changed()
3554 static void cb_panel_prefs_handle_cell_edited(GtkCellRendererText * cell,
3555 gchar * path_string, gchar * pch_new, PGAPC_PREFS_COLUMN pcolumn)
3557 GtkTreeModel *model;
3558 GtkTreeIter iter;
3559 GtkTreePath *path;
3560 gint col_number = 0, i_port = 0, i_monitor = 0, i_len = 0;
3561 gfloat f_refresh = 0.0, f_graph = 0.0;
3562 gchar ch[GAPC_MAX_TEXT], *pch = NULL;
3563 gboolean b_dupped = FALSE;
3565 g_return_if_fail(pcolumn != NULL);
3566 g_return_if_fail(pch_new != NULL);
3567 g_return_if_fail(path_string != NULL);
3569 model = pcolumn->prefs_model;
3570 col_number = pcolumn->i_col_num;
3572 i_len = g_snprintf(ch, GAPC_MAX_TEXT, "%s", pch_new);
3574 * get iter to record
3576 path = gtk_tree_path_new_from_string(path_string);
3577 gtk_tree_model_get_iter(model, &iter, path);
3578 gtk_tree_path_free(path);
3581 * get data from that row
3583 gtk_tree_model_get(model, &iter, GAPC_PREFS_MONITOR, &i_monitor, -1);
3585 switch (col_number) {
3586 case GAPC_PREFS_HOST:
3588 gchar *phost = g_strdup_printf(GAPC_HOST_KEY, i_monitor);
3590 if ((pch_new == NULL) || (i_len < 2)) {
3591 pch = g_strdup(GAPC_HOST_DEFAULT);
3592 } else {
3593 pch = pch_new;
3594 b_dupped = TRUE;
3596 gconf_client_set_string(pcolumn->client, phost, pch, NULL);
3597 g_free(phost);
3599 break;
3600 case GAPC_PREFS_PORT:
3602 gchar *pport = g_strdup_printf(GAPC_PORT_KEY, i_monitor);
3604 i_port = (gint) g_strtod(pch_new, NULL);
3606 if (i_port == 0) {
3607 i_port = GAPC_PORT_DEFAULT;
3608 pch = g_strdup_printf("%d", i_port);
3609 } else {
3610 pch = pch_new;
3611 b_dupped = TRUE;
3613 gconf_client_set_int(pcolumn->client, pport, i_port, NULL);
3614 g_free(pport);
3616 break;
3617 case GAPC_PREFS_WATT:
3619 gchar *pport = g_strdup_printf(GAPC_WATT_KEY, i_monitor);
3621 i_port = (gint) g_strtod(pch_new, NULL);
3623 if (i_port == 0) {
3624 i_port = GAPC_WATT_DEFAULT;
3625 pch = g_strdup_printf("%d", i_port);
3626 } else {
3627 pch = pch_new;
3628 b_dupped = TRUE;
3630 gconf_client_set_int(pcolumn->client, pport, i_port, NULL);
3631 g_free(pport);
3633 break;
3634 case GAPC_PREFS_REFRESH:
3636 gchar *prefresh = g_strdup_printf(GAPC_REFRESH_KEY, i_monitor);
3638 f_refresh = (gfloat) g_strtod(pch_new, NULL);
3640 if (f_refresh < GAPC_REFRESH_MIN_INCREMENT) {
3641 f_refresh = GAPC_REFRESH_DEFAULT;
3642 pch = g_strdup_printf("%3.1f", f_refresh);
3643 } else {
3644 pch = pch_new;
3645 b_dupped = TRUE;
3647 gconf_client_set_float(pcolumn->client, prefresh, f_refresh, NULL);
3648 g_free(prefresh);
3650 break;
3651 case GAPC_PREFS_GRAPH:
3653 gchar *prefresh = g_strdup_printf(GAPC_GRAPH_KEY, i_monitor);
3655 f_graph = (gfloat) g_strtod(pch_new, NULL);
3657 if (f_graph < GAPC_REFRESH_MIN_INCREMENT) {
3658 f_graph = GAPC_LINEGRAPH_REFRESH_FACTOR;
3659 pch = g_strdup_printf("%3.1f", f_graph);
3660 } else {
3661 pch = pch_new;
3662 b_dupped = TRUE;
3664 gconf_client_set_float(pcolumn->client, prefresh, f_graph, NULL);
3665 g_free(prefresh);
3667 break;
3668 default:
3669 g_message("Cell_Edited:Unknown key for Value(%s)\n", pch_new);
3670 g_object_set(cell, "text", pch_new, NULL);
3671 break;
3674 if ((pch != NULL) && !b_dupped) {
3675 g_free(pch);
3678 return;
3682 * Cell data function used to format floating point numbers
3683 * This gets called a thousand times...
3685 static void cb_panel_prefs_handle_float_format(GtkTreeViewColumn * col,
3686 GtkCellRenderer * renderer, GtkTreeModel * model, GtkTreeIter * iter, gpointer gp)
3688 gfloat d_value;
3689 gchar buf[32];
3690 guint colnum = 0;
3691 gchar *pch_format = NULL;
3693 g_return_if_fail(gp != NULL);
3695 colnum = GPOINTER_TO_UINT(gp);
3697 pch_format = (gchar *) g_object_get_data(G_OBJECT(col), "float_format");
3699 gtk_tree_model_get(model, iter, colnum, &d_value, -1);
3701 if (pch_format) {
3702 g_snprintf(buf, sizeof(buf), pch_format, d_value);
3703 } else {
3704 g_snprintf(buf, sizeof(buf), "%3.0f", d_value);
3707 g_object_set(renderer, "text", buf, NULL);
3709 return;
3712 /* This routine initializes a user-data structure for use by the renderers of
3713 * the preference treeview
3715 static PGAPC_PREFS_COLUMN gapc_panel_prefs_col_data_init(PGAPC_CONFIG pcfg,
3716 GAPC_PrefsType col_num)
3718 PGAPC_PREFS_COLUMN pcol = NULL;
3720 pcol = g_new0(GAPC_PREFS_COLUMN, 1);
3721 g_return_val_if_fail(pcol != NULL, NULL);
3723 pcol->cb_id = CB_COLUMN_ID;
3724 pcol->prefs_model = pcfg->prefs_model;
3725 pcol->i_col_num = col_num;
3726 pcol->client = pcfg->client;
3728 return pcol;
3732 * Gets the gconf instance preferences for all monitors
3733 * and loads the prefs_model.
3734 * returns FALSE on error
3735 * returns TRUE on sucess
3737 static gboolean gapc_panel_preferences_data_model_load(PGAPC_CONFIG pcfg)
3739 GError *gerror = NULL;
3740 GSList *monitors = NULL;
3741 GtkTreeIter iter;
3742 gboolean b_valid = FALSE;
3743 gboolean v_enabled;
3744 gboolean v_use_systray;
3745 gint v_port_number;
3746 gint v_watt_number;
3747 gfloat v_network_interval;
3748 gfloat v_graph_interval;
3749 gchar *v_host_name;
3751 gchar k_enabled[GAPC_MAX_TEXT];
3752 gchar k_use_systray[GAPC_MAX_TEXT];
3753 gchar k_port_number[GAPC_MAX_TEXT];
3754 gchar k_network_interval[GAPC_MAX_TEXT];
3755 gchar k_graph_interval[GAPC_MAX_TEXT];
3756 gchar k_host_name[GAPC_MAX_TEXT];
3757 gchar k_watt_number[GAPC_MAX_TEXT];
3759 g_return_val_if_fail(pcfg != NULL, FALSE);
3760 g_return_val_if_fail(pcfg->client != NULL, FALSE);
3761 g_return_val_if_fail(pcfg->prefs_model != NULL, FALSE);
3763 b_valid = gconf_client_dir_exists(pcfg->client, GAPC_MID_GROUP_KEY, &gerror);
3764 if (gerror != NULL) {
3765 gapc_util_log_app_msg("gapc_panel_preferences_data_model_load",
3766 "gconf_dir_exists() Failed", gerror->message);
3767 g_error_free(gerror);
3768 gerror = NULL;
3769 return FALSE;
3773 if (b_valid == FALSE) {
3774 gapc_util_log_app_msg("gapc_panel_preferences_data_model_load",
3775 "No monitors predefined.", "very first startup");
3776 return FALSE;
3779 monitors = gconf_client_all_dirs(pcfg->client, GAPC_MID_GROUP_KEY, &gerror);
3780 if (gerror != NULL) {
3781 gapc_util_log_app_msg("gapc_panel_preferences_data_model_load",
3782 "gconf_client_all_dirs() Failed", gerror->message);
3783 g_error_free(gerror);
3784 gerror = NULL;
3785 return FALSE;
3788 while (monitors) { /* should be the regular text key */
3789 gchar *pmon = NULL;
3790 gint i_monitor = 0;
3791 GtkWidget *widget = NULL;
3793 pmon = g_strrstr((gchar *) monitors->data, "/");
3794 if (pmon) {
3795 i_monitor = (gint) g_strtod(pmon + 1, NULL);
3796 pcfg->prefs_last_monitor = MAX(pcfg->prefs_last_monitor, i_monitor);
3797 } else {
3798 g_free(monitors->data);
3799 monitors = g_slist_next(monitors);
3800 continue;
3803 g_snprintf(k_enabled, GAPC_MAX_TEXT, "%s/%s", (gchar *) monitors->data,
3804 "enabled");
3805 g_snprintf(k_use_systray, GAPC_MAX_TEXT, "%s/%s", (gchar *) monitors->data,
3806 "use_systray");
3807 g_snprintf(k_port_number, GAPC_MAX_TEXT, "%s/%s", (gchar *) monitors->data,
3808 "port_number");
3809 g_snprintf(k_watt_number, GAPC_MAX_TEXT, "%s/%s", (gchar *) monitors->data,
3810 "ups_wattage");
3811 g_snprintf(k_network_interval, GAPC_MAX_TEXT, "%s/%s",
3812 (gchar *) monitors->data, "network_interval");
3813 g_snprintf(k_graph_interval, GAPC_MAX_TEXT, "%s/%s", (gchar *) monitors->data,
3814 "graph_interval");
3815 g_snprintf(k_host_name, GAPC_MAX_TEXT, "%s/%s", (gchar *) monitors->data,
3816 "host_name");
3818 v_enabled = gconf_client_get_bool(pcfg->client, k_enabled, NULL);
3819 v_use_systray = gconf_client_get_bool(pcfg->client, k_use_systray, NULL);
3820 v_port_number = gconf_client_get_int(pcfg->client, k_port_number, NULL);
3821 if (v_port_number == 0) {
3822 v_port_number = GAPC_PORT_DEFAULT;
3824 v_watt_number = gconf_client_get_int(pcfg->client, k_watt_number, NULL);
3825 if (v_watt_number == 0) {
3826 v_watt_number = GAPC_WATT_DEFAULT;
3828 v_network_interval =
3829 gconf_client_get_float(pcfg->client, k_network_interval, NULL);
3830 if (v_network_interval == 0.0) {
3831 v_network_interval = GAPC_REFRESH_DEFAULT;
3833 v_graph_interval =
3834 gconf_client_get_float(pcfg->client, k_graph_interval, NULL);
3835 if (v_graph_interval == 0.0) {
3836 v_graph_interval = GAPC_LINEGRAPH_REFRESH_FACTOR;
3838 v_host_name = gconf_client_get_string(pcfg->client, k_host_name, NULL);
3839 if (v_host_name == NULL) {
3840 v_host_name = g_strdup(GAPC_HOST_DEFAULT);
3843 gtk_list_store_append(GTK_LIST_STORE(pcfg->prefs_model), &iter);
3844 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
3845 GAPC_PREFS_MONITOR, i_monitor,
3846 GAPC_PREFS_SYSTRAY, v_use_systray,
3847 GAPC_PREFS_ENABLED, v_enabled,
3848 GAPC_PREFS_PORT, v_port_number,
3849 GAPC_PREFS_REFRESH, v_network_interval,
3850 GAPC_PREFS_GRAPH, v_graph_interval,
3851 GAPC_PREFS_HOST, v_host_name,
3852 GAPC_PREFS_WATT, v_watt_number,
3853 -1);
3855 /* Startup Processing */
3856 if (v_enabled) {
3857 widget = gapc_monitor_interface_create(pcfg, i_monitor, &iter);
3858 if ((widget != NULL) && !v_use_systray ) {
3859 gtk_window_present( GTK_WINDOW(widget));
3862 g_free(monitors->data);
3863 monitors = g_slist_next(monitors);
3865 g_slist_free(monitors);
3867 return TRUE;
3871 * Create a data model to hold the preferences for this program. We are
3872 * using the list store model to hold the all data. Then we create the
3873 * complete GtkTreeView and initialize the columns.
3874 * returns GtkTreeView or NULL
3876 static GtkWidget *gapc_panel_preferences_model_init(PGAPC_CONFIG pcfg)
3878 GtkWidget *treeview = NULL;
3879 GtkTreeModel *model = NULL;
3880 GtkTreeViewColumn *column = NULL;
3881 GtkCellRenderer *renderer_enabled = NULL, *renderer_systray = NULL,
3882 *renderer_port = NULL, *renderer_watt = NULL, *renderer_refresh = NULL,
3883 *renderer_graph = NULL, *renderer_host = NULL, *anyrndr = NULL;
3884 PGAPC_PREFS_COLUMN col_enabled = NULL, col_systray = NULL, col_port = NULL,
3885 col_refresh = NULL, col_graph = NULL, col_host = NULL, col_watt = NULL;
3887 g_return_val_if_fail(pcfg != NULL, NULL);
3889 /* Don't create it twice */
3890 if (pcfg->prefs_treeview != NULL)
3891 return GTK_WIDGET(pcfg->prefs_treeview);
3893 /* Create the model -- this column order and that of the enum must match */
3894 model = GTK_TREE_MODEL(gtk_list_store_new(GAPC_N_PREFS_COLUMNS,
3895 G_TYPE_INT, /* Monitor base-1 */
3896 G_TYPE_BOOLEAN, /* enabled */
3897 G_TYPE_BOOLEAN, /* systray icon */
3898 G_TYPE_INT, /* Port */
3899 G_TYPE_FLOAT, /* network Refresh */
3900 G_TYPE_FLOAT, /* graph Refresh */
3901 G_TYPE_STRING, /* Host */
3902 G_TYPE_INT /* Wattage */
3904 /* store it for later */
3905 pcfg->prefs_model = model;
3907 /* load the data model */
3908 gapc_panel_preferences_data_model_load(pcfg);
3910 /* create the display columns and treeview */
3911 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
3912 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(treeview));
3913 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
3914 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(treeview), FALSE);
3916 /* allocate control struct for viewable columns */
3917 col_enabled = gapc_panel_prefs_col_data_init(pcfg, GAPC_PREFS_ENABLED);
3918 col_systray = gapc_panel_prefs_col_data_init(pcfg, GAPC_PREFS_SYSTRAY);
3919 col_port = gapc_panel_prefs_col_data_init(pcfg, GAPC_PREFS_PORT);
3920 col_watt = gapc_panel_prefs_col_data_init(pcfg, GAPC_PREFS_WATT);
3921 col_refresh = gapc_panel_prefs_col_data_init(pcfg, GAPC_PREFS_REFRESH);
3922 col_graph = gapc_panel_prefs_col_data_init(pcfg, GAPC_PREFS_GRAPH);
3923 col_host = gapc_panel_prefs_col_data_init(pcfg, GAPC_PREFS_HOST);
3925 /* create display formatters where needed */
3926 renderer_enabled = gtk_cell_renderer_toggle_new();
3927 renderer_systray = gtk_cell_renderer_toggle_new();
3928 renderer_port = gtk_cell_renderer_text_new();
3929 renderer_watt = gtk_cell_renderer_text_new();
3930 renderer_refresh = gtk_cell_renderer_text_new();
3931 renderer_graph = gtk_cell_renderer_text_new();
3932 renderer_host = gtk_cell_renderer_text_new();
3933 anyrndr = gtk_cell_renderer_text_new();
3935 /* set renderers attributes */
3936 g_object_set(G_OBJECT(renderer_port), "xalign", 0.5, "editable", TRUE, NULL);
3937 g_object_set(G_OBJECT(renderer_watt), "xalign", 0.5, "editable", TRUE, NULL);
3938 g_object_set(G_OBJECT(renderer_graph), "xalign", 0.5, "editable", TRUE, NULL);
3939 g_object_set(G_OBJECT(renderer_refresh), "xalign", 0.5, "editable", TRUE, NULL);
3940 g_object_set(G_OBJECT(renderer_host), "editable", TRUE, NULL);
3943 /* prepare callbacks to correctly handle the columns
3944 * careful to use these only once per column --
3945 * using an auto g_free to release allocated storage
3947 gtk_signal_connect_full(GTK_OBJECT(renderer_enabled), "toggled",
3948 G_CALLBACK(cb_panel_prefs_handle_cell_toggled), NULL,
3949 col_enabled, g_free, FALSE, TRUE);
3950 gtk_signal_connect_full(GTK_OBJECT(renderer_systray), "toggled",
3951 G_CALLBACK(cb_panel_prefs_handle_cell_toggled), NULL,
3952 col_systray, g_free, FALSE, TRUE);
3953 gtk_signal_connect_full(GTK_OBJECT(renderer_port), "edited",
3954 G_CALLBACK(cb_panel_prefs_handle_cell_edited), NULL,
3955 col_port, g_free, FALSE, TRUE);
3956 gtk_signal_connect_full(GTK_OBJECT(renderer_watt), "edited",
3957 G_CALLBACK(cb_panel_prefs_handle_cell_edited), NULL,
3958 col_watt, g_free, FALSE, TRUE);
3959 gtk_signal_connect_full(GTK_OBJECT(renderer_refresh), "edited",
3960 G_CALLBACK(cb_panel_prefs_handle_cell_edited), NULL,
3961 col_refresh, g_free, FALSE, TRUE);
3962 gtk_signal_connect_full(GTK_OBJECT(renderer_graph), "edited",
3963 G_CALLBACK(cb_panel_prefs_handle_cell_edited), NULL,
3964 col_graph, g_free, FALSE, TRUE);
3965 gtk_signal_connect_full(GTK_OBJECT(renderer_host), "edited",
3966 G_CALLBACK(cb_panel_prefs_handle_cell_edited), NULL,
3967 col_host, g_free, FALSE, TRUE);
3969 /* Define the column order and attributes */
3970 column = gtk_tree_view_column_new_with_attributes("Enabled", renderer_enabled,
3971 "active", GAPC_PREFS_ENABLED, NULL);
3972 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
3974 column = gtk_tree_view_column_new_with_attributes("use\nTrayIcon",
3975 renderer_systray, "active", GAPC_PREFS_SYSTRAY, NULL);
3976 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
3978 column = gtk_tree_view_column_new_with_attributes("network\nRefresh",
3979 renderer_refresh, "text", GAPC_PREFS_REFRESH, NULL);
3980 g_object_set_data(G_OBJECT(column), "float_format", "%3.1f");
3981 gtk_tree_view_column_set_cell_data_func(column, renderer_refresh,
3982 cb_panel_prefs_handle_float_format,
3983 GUINT_TO_POINTER(GAPC_PREFS_REFRESH), NULL);
3984 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
3986 column = gtk_tree_view_column_new_with_attributes("Port", renderer_port, "text",
3987 GAPC_PREFS_PORT, NULL);
3988 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
3990 column = gtk_tree_view_column_new_with_attributes("graph\nRefresh",
3991 renderer_graph, "text", GAPC_PREFS_GRAPH, NULL);
3992 g_object_set_data(G_OBJECT(column), "float_format", "%3.0f");
3993 gtk_tree_view_column_set_cell_data_func(column, renderer_graph,
3994 cb_panel_prefs_handle_float_format, GUINT_TO_POINTER(GAPC_PREFS_GRAPH), NULL);
3995 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
3997 column = gtk_tree_view_column_new_with_attributes("Rated\nWattage", renderer_watt, "text",
3998 GAPC_PREFS_WATT, NULL);
3999 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
4001 column = gtk_tree_view_column_new_with_attributes("Host Name or IP Address",
4002 renderer_host, "text", GAPC_PREFS_HOST, NULL);
4003 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
4005 column = gtk_tree_view_column_new_with_attributes("Monitor", anyrndr,
4006 "text", GAPC_PREFS_MONITOR, NULL);
4007 gtk_tree_view_column_set_sort_column_id(column, GAPC_PREFS_MONITOR);
4008 gtk_tree_view_column_clicked(column);
4009 g_object_set(G_OBJECT(column), "visible", FALSE, NULL);
4010 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
4012 return treeview;
4016 * Create a data model to hold the current list of active monitors. We are
4017 * using the list store model to hold the active data. Then we create the
4018 * complete GtkTreeView and initialize the columns.
4019 * returns GtkTreeView or NULL
4021 static GtkWidget *gapc_panel_monitors_model_init(PGAPC_CONFIG pcfg)
4023 GtkWidget *treeview = NULL;
4024 GtkTreeModel *model = NULL;
4025 GtkCellRenderer *renderer_icon = NULL, *renderer_text = NULL,
4026 *renderer_state = NULL, *renderer_any = NULL;
4027 GtkTreeViewColumn *column = NULL;
4029 g_return_val_if_fail(pcfg != NULL, NULL);
4031 /* Don't create it twice */
4032 if (pcfg->monitor_treeview != NULL)
4033 return GTK_WIDGET(pcfg->monitor_treeview);
4035 /* Create the model -- this column order and that of the enum must match */
4036 model = GTK_TREE_MODEL(gtk_list_store_new(GAPC_N_MON_COLUMNS, G_TYPE_INT, /* Monitor Num */
4037 GDK_TYPE_PIXBUF, /* ICON */
4038 G_TYPE_STRING, /* Status Text */
4039 G_TYPE_POINTER, /* monitor ptr */
4040 G_TYPE_STRING /* State Text */
4042 /* store it for later */
4043 pcfg->monitor_model = model;
4045 /* create the display columns and treeview */
4046 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
4047 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
4048 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(treeview));
4049 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(treeview), FALSE);
4050 g_signal_connect(treeview, "row-activated",
4051 G_CALLBACK(cb_panel_monitor_list_activated), pcfg);
4053 renderer_icon = gtk_cell_renderer_pixbuf_new();
4054 renderer_text = gtk_cell_renderer_text_new();
4055 renderer_state = gtk_cell_renderer_text_new();
4056 renderer_any = gtk_cell_renderer_text_new();
4057 g_object_set(G_OBJECT(renderer_state), "xalign", 0.5, NULL);
4058 g_object_set(G_OBJECT(renderer_text), "xalign", 0.0, NULL);
4059 g_object_set(G_OBJECT(renderer_text), "yalign", 0.5, NULL);
4062 column = gtk_tree_view_column_new();
4064 gtk_tree_view_column_set_title(column, "Status");
4066 gtk_tree_view_column_pack_start(column, renderer_icon, TRUE);
4068 gtk_tree_view_column_add_attribute(column, renderer_icon, "pixbuf",
4069 GAPC_MON_ICON);
4071 gtk_tree_view_column_pack_end(column, renderer_state, FALSE);
4073 gtk_tree_view_column_add_attribute(column, renderer_state, "markup",
4074 GAPC_MON_UPSSTATE);
4076 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
4078 column = gtk_tree_view_column_new_with_attributes("Current summary ups info",
4079 renderer_text, "markup", GAPC_MON_STATUS, NULL);
4080 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
4082 column = gtk_tree_view_column_new_with_attributes("Monitor", renderer_any,
4083 "text", GAPC_MON_MONITOR, NULL);
4084 gtk_tree_view_column_set_sort_column_id(column, GAPC_MON_MONITOR);
4085 g_object_set(G_OBJECT(column), "visible", FALSE, NULL);
4086 gtk_tree_view_column_clicked(column);
4087 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
4090 return treeview;
4094 * Load ICONs and set default icon
4095 * return TRUE if ok, FALSE otherwise
4097 static gboolean gapc_util_load_icons(PGAPC_CONFIG pcfg)
4099 guint i_x = 0, x = 0;
4100 GError *gerror = NULL;
4101 GdkPixbuf *pixbuf = NULL;
4102 gboolean b_rc = TRUE;
4103 gchar pch_file[GAPC_MAX_ARRAY];
4104 gchar *pch_2 = "./";
4105 gchar *pch_3 = "../pixmaps/";
4106 gchar *pch_4 = NULL;
4107 gchar *pch_image_names[] = {
4108 "online.png",
4109 "onbatt.png",
4110 "charging.png",
4111 "apcupsd.png",
4112 "unplugged.png",
4113 "gapc_prefs.png",
4114 NULL
4117 g_return_val_if_fail(pcfg != NULL, FALSE);
4119 /* build system path for icons */
4120 pch_4 = g_strconcat (ICON_DIR, "/pixmaps/", NULL);
4122 i_x = 0;
4123 while (i_x == 0) {
4124 if (g_file_test(pch_image_names[0], G_FILE_TEST_EXISTS)) {
4125 i_x = 1;
4126 break;
4129 g_snprintf(pch_file, GAPC_MAX_ARRAY, "%s%s", pch_2, pch_image_names[0]);
4130 if (g_file_test(pch_file, G_FILE_TEST_EXISTS)) {
4131 i_x = 2;
4132 break;
4135 g_snprintf(pch_file, GAPC_MAX_ARRAY, "%s%s", pch_3, pch_image_names[0]);
4136 if (g_file_test(pch_file, G_FILE_TEST_EXISTS)) {
4137 i_x = 3;
4138 break;
4141 g_snprintf(pch_file, GAPC_MAX_ARRAY, "%s%s", pch_4, pch_image_names[0]);
4142 if (g_file_test(pch_file, G_FILE_TEST_EXISTS)) {
4143 i_x = 4;
4144 break;
4147 break;
4150 if (i_x == 0) {
4151 gapc_util_log_app_msg("gapc_util_load_icons", "Unable to find icons",
4152 "--load failed!");
4153 g_free (pch_4);
4154 return FALSE;
4157 for (x = 0; (pch_image_names[x] != NULL) && (x < GAPC_N_ICONS); x++) {
4158 switch (i_x) {
4159 case 1:
4160 g_snprintf(pch_file, GAPC_MAX_ARRAY, "%s", pch_image_names[x]);
4161 break;
4162 case 2:
4163 g_snprintf(pch_file, GAPC_MAX_ARRAY, "%s%s", pch_2, pch_image_names[x]);
4164 break;
4165 case 3:
4166 g_snprintf(pch_file, GAPC_MAX_ARRAY, "%s%s", pch_3, pch_image_names[x]);
4167 break;
4168 case 4:
4169 g_snprintf(pch_file, GAPC_MAX_ARRAY, "%s%s", pch_4, pch_image_names[x]);
4170 break;
4171 default:
4172 g_return_val_if_reached(FALSE);
4173 break;
4176 pixbuf = gdk_pixbuf_new_from_file(pch_file, &gerror);
4177 if (gerror != NULL) {
4178 gchar *pch = NULL;
4180 pch = g_strdup_printf("Get Icon=%s Failed", pch_file);
4181 gapc_util_log_app_msg("gapc_util_load_icons", pch, gerror->message);
4182 g_error_free(gerror);
4183 g_free(pch);
4184 gerror = NULL;
4185 b_rc = FALSE;
4186 pcfg->my_icons[x] = NULL;
4187 } else {
4188 pcfg->my_icons[x] =
4189 gdk_pixbuf_scale_simple(pixbuf, GAPC_ICON_SIZE, GAPC_ICON_SIZE,
4190 GDK_INTERP_BILINEAR);
4191 g_object_unref(pixbuf);
4195 g_free (pch_4);
4196 return b_rc;
4200 * Monitor List "row-activated"
4202 static void cb_panel_monitor_list_activated(GtkTreeView * treeview,
4203 GtkTreePath * arg1, GtkTreeViewColumn * arg2, PGAPC_CONFIG pcfg)
4205 PGAPC_MONITOR pm = NULL;
4206 GtkTreeIter iter;
4208 g_return_if_fail(pcfg != NULL);
4210 if (gtk_tree_model_get_iter(pcfg->monitor_model, &iter, arg1)) {
4211 gtk_tree_model_get(pcfg->monitor_model, &iter, GAPC_MON_POINTER, &pm, -1);
4213 if ((pm != NULL) && (pm->window != NULL)) {
4214 if (pm->b_visible) {
4215 gtk_widget_hide(GTK_WIDGET(pm->window));
4216 } else {
4217 gtk_window_present(GTK_WINDOW(pm->window));
4222 return;
4226 * Active monitor selection
4228 static void cb_panel_monitor_list_selection(GtkTreeSelection * selection,
4229 PGAPC_CONFIG pcfg)
4231 GtkTreeIter iter;
4232 GtkTreeModel *model;
4233 gint i_monitor = 0;
4235 g_return_if_fail(pcfg != NULL);
4237 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
4238 gtk_tree_model_get(model, &iter, GAPC_MON_MONITOR, &i_monitor, -1);
4240 pcfg->cb_last_monitor = i_monitor;
4243 return;
4247 * The Active Monitor Icon List for the information window
4248 * returns created notebook page number.
4250 static gint gapc_panel_monitor_list_page(PGAPC_CONFIG pcfg, GtkNotebook * notebook)
4252 GtkWidget *label = NULL, *frame = NULL, *vbox = NULL, *sw = NULL;
4253 GtkWidget *treeview = NULL;
4254 GtkTreeSelection *select = NULL;
4255 GtkTreeIter iter;
4257 gint i_page = 0;
4259 g_return_val_if_fail(pcfg != NULL, -1);
4260 g_return_val_if_fail(notebook != NULL, -1);
4262 /* Create notebook page */
4263 frame = gtk_frame_new(NULL);
4264 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
4265 label = gtk_label_new("Active Monitors");
4266 i_page = gtk_notebook_append_page(notebook, frame, label);
4267 gtk_widget_show(frame);
4269 label = gtk_label_new("<span foreground=\"blue\">"
4270 "<i>double-click a row to popup information window.</i>" "</span>");
4271 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
4272 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
4274 vbox = gtk_event_box_new();
4275 gtk_container_add(GTK_CONTAINER(frame), vbox);
4276 gtk_widget_show(vbox);
4277 frame = gtk_frame_new("");
4278 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
4279 gtk_frame_set_label_widget(GTK_FRAME(frame), label);
4280 gtk_frame_set_label_align(GTK_FRAME(frame), 0.5, 0.8);
4281 gtk_container_add(GTK_CONTAINER(vbox), frame);
4282 gtk_widget_show(frame);
4284 /* Create the container for the icon view */
4285 sw = gtk_scrolled_window_new(NULL, NULL);
4286 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
4287 GTK_SHADOW_ETCHED_IN);
4288 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER,
4289 GTK_POLICY_AUTOMATIC);
4290 gtk_container_add(GTK_CONTAINER(frame), sw);
4291 gtk_widget_show(sw);
4293 /* create the active monitor list in a treeview */
4294 treeview = gapc_panel_monitors_model_init(pcfg);
4295 pcfg->monitor_treeview = GTK_TREE_VIEW(treeview);
4296 gtk_container_add(GTK_CONTAINER(sw), treeview);
4297 gtk_widget_show(GTK_WIDGET(treeview));
4299 /* Setup the selection handler */
4300 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
4301 pcfg->monitor_select = select;
4302 gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
4303 g_signal_connect(G_OBJECT(select), "changed",
4304 G_CALLBACK(cb_panel_monitor_list_selection), pcfg);
4306 /* Selection the first record */
4307 if (gtk_tree_model_get_iter_first(pcfg->monitor_model, &iter)) {
4308 gtk_tree_selection_select_iter(select, &iter);
4311 return i_page;
4315 * The Preferences List for the information window
4316 * returns created notebook page number.
4318 static gint gapc_panel_preferences_page(PGAPC_CONFIG pcfg, GtkNotebook * notebook)
4320 GtkWidget *label = NULL, *frame = NULL, *vbox = NULL, *sw = NULL;
4321 GtkWidget *pbox = NULL, *box = NULL, *cbox = NULL;
4322 GtkWidget *treeview = NULL;
4323 GtkTreeSelection *select = NULL;
4324 GtkTreeIter iter;
4325 gint i_page = 0;
4327 g_return_val_if_fail(pcfg != NULL, -1);
4328 g_return_val_if_fail(notebook != NULL, -1);
4330 /* Create notebook page */
4331 frame = gtk_frame_new(NULL);
4332 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
4333 label = gtk_label_new("Preferences");
4334 i_page = gtk_notebook_append_page(notebook, frame, label);
4335 gtk_widget_show(frame);
4337 label = gtk_label_new("<span foreground=\"blue\">"
4338 "<i>double-click a columns value to change it.</i>" "</span>");
4339 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
4340 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
4342 box = gtk_event_box_new();
4343 gtk_container_add(GTK_CONTAINER(frame), box);
4344 gtk_widget_show(box);
4345 vbox = gtk_vbox_new(FALSE, 0);
4346 gtk_container_add(GTK_CONTAINER(box), vbox);
4347 gtk_widget_show(vbox);
4348 frame = gtk_frame_new("");
4349 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
4350 gtk_frame_set_label_widget(GTK_FRAME(frame), label);
4351 gtk_frame_set_label_align(GTK_FRAME(frame), 0.5, 0.8);
4352 gtk_container_add(GTK_CONTAINER(vbox), frame);
4353 gtk_widget_show(frame);
4354 pbox = gtk_vbox_new(FALSE, 0);
4355 gtk_container_add(GTK_CONTAINER(frame), pbox);
4356 gtk_widget_show(pbox);
4358 /* Create the container for the icon view */
4359 sw = gtk_scrolled_window_new(NULL, NULL);
4360 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
4361 GTK_SHADOW_ETCHED_IN);
4362 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER,
4363 GTK_POLICY_AUTOMATIC);
4364 gtk_container_add(GTK_CONTAINER(pbox), sw);
4365 gtk_widget_show(sw);
4367 /* create the preferences in a treeview */
4368 treeview = gapc_panel_preferences_model_init(pcfg);
4369 pcfg->prefs_treeview = GTK_TREE_VIEW(treeview);
4370 gtk_container_add(GTK_CONTAINER(sw), treeview);
4371 gtk_widget_show(GTK_WIDGET(treeview));
4373 /* Setup the selection handler */
4374 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
4375 pcfg->prefs_select = select;
4376 gtk_tree_selection_set_mode(select, GTK_SELECTION_BROWSE);
4378 /* Select the first record */
4379 if (gtk_tree_model_get_iter_first(pcfg->prefs_model, &iter)) {
4380 gtk_tree_selection_select_iter(select, &iter);
4383 /* add options for adding monitors */
4384 box = gtk_hbox_new(FALSE, 4);
4385 gtk_box_pack_start(GTK_BOX(pbox), box, FALSE, FALSE, 0);
4386 gtk_widget_show(box);
4388 cbox = gtk_button_new_from_stock(GTK_STOCK_ADD);
4389 g_signal_connect(cbox, "clicked", G_CALLBACK(cb_panel_prefs_button_add_rec),
4390 pcfg);
4391 gtk_tooltips_set_tip(pcfg->tooltips, GTK_WIDGET(cbox),
4392 "Adds a new monitor\ndefinition to the system.", NULL);
4393 gtk_box_pack_start(GTK_BOX(box), cbox, FALSE, FALSE, 2);
4394 gtk_widget_show(cbox);
4396 cbox = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
4397 g_signal_connect(cbox, "clicked", G_CALLBACK(cb_panel_prefs_button_remove_rec),
4398 pcfg);
4399 gtk_tooltips_set_tip(pcfg->tooltips, GTK_WIDGET(cbox),
4400 "Removes selected monitor\ndefinition from the system.", NULL);
4401 gtk_box_pack_start(GTK_BOX(box), cbox, FALSE, FALSE, 2);
4402 gtk_widget_show(cbox);
4404 /* add options for control panel */
4405 frame = gtk_frame_new("Control panel options");
4406 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
4407 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
4408 gtk_widget_show(frame);
4410 box = gtk_hbox_new(FALSE, 4);
4411 gtk_container_add(GTK_CONTAINER(frame), box);
4412 gtk_widget_show(box);
4414 cbox = gtk_check_button_new_with_mnemonic("Use _tray Icon");
4415 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbox), pcfg->b_use_systray);
4416 g_signal_connect(cbox, "toggled", G_CALLBACK(cb_panel_prefs_button_use_systray),
4417 pcfg);
4418 gtk_tooltips_set_tip(pcfg->tooltips, GTK_WIDGET(cbox),
4419 "Creates a notification area icon\nfor this control panel.", NULL);
4420 gtk_box_pack_start(GTK_BOX(box), cbox, FALSE, FALSE, 2);
4421 gtk_widget_show(cbox);
4422 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("UseTrayIcon"), cbox);
4424 return i_page;
4428 * The about page in the information window
4429 * returns created notebook page number.
4431 static gint gapc_panel_about_page(GtkNotebook * notebook, gchar * pch_pname,
4432 gchar * pch_pversion, GdkPixbuf * icon)
4434 GtkWidget *label = NULL, *frame = NULL, *vbox = NULL;
4435 GtkWidget *hbox = NULL, *image = NULL;
4436 gchar *about_text = NULL;
4437 gchar *about_msg = NULL;
4438 GdkPixbuf *scaled = NULL;
4439 gint i_page = 0;
4441 g_return_val_if_fail(notebook != NULL, -1);
4444 about_text =
4445 g_strdup_printf("<b><big>%s</big>\nVersion %s</b>\n", pch_pname, pch_pversion);
4447 about_msg =
4448 g_strdup_printf("<b>gui monitor for UPSs under the management"
4449 " of the APCUPSD.sourceforge.net package</b>\n"
4450 "<i>http://gapcmon.sourceforge.net/</i>\n\n"
4451 "Copyright \xC2\xA9 2006 James Scott, Jr.\n"
4452 "skoona@users.sourceforge.net\n\n"
4453 "Released under the GNU Public License\n"
4454 "%s comes with\nABSOLUTELY NO WARRANTY", pch_pname);
4456 /* Create About page */
4457 frame = gtk_frame_new(NULL);
4458 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
4459 label = gtk_label_new("About");
4460 i_page = gtk_notebook_append_page(notebook, frame, label);
4461 gtk_widget_show(frame);
4463 vbox = gtk_vbox_new(FALSE, 8);
4464 gtk_container_add(GTK_CONTAINER(frame), vbox);
4465 gtk_widget_show(vbox);
4467 hbox = gtk_hbox_new(FALSE, 0);
4468 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
4469 gtk_widget_show(hbox);
4471 image = gtk_image_new();
4472 gtk_misc_set_alignment((GtkMisc *) image, 1.0, 0.5);
4473 scaled = gdk_pixbuf_scale_simple(icon, 48, 48, GDK_INTERP_BILINEAR);
4474 gtk_image_set_from_pixbuf(GTK_IMAGE(image), scaled);
4475 gtk_box_pack_start(GTK_BOX(hbox), image, TRUE, TRUE, 0);
4476 gtk_widget_show(image);
4477 gdk_pixbuf_unref(scaled);
4479 label = gtk_label_new(about_text);
4480 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
4481 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
4482 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
4483 gtk_misc_set_alignment((GtkMisc *) label, 0.0, 0.7);
4484 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
4485 gtk_widget_show(label);
4487 label = gtk_label_new(about_msg);
4488 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
4489 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
4490 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
4491 gtk_misc_set_alignment((GtkMisc *) label, 0.5, 0.5);
4492 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
4493 gtk_widget_show(label);
4495 g_free(about_text);
4496 g_free(about_msg);
4498 return i_page;
4501 static void cb_monitor_interface_show(GtkWidget * widget, PGAPC_MONITOR pm)
4503 g_return_if_fail(pm != NULL);
4504 pm->b_visible = TRUE;
4505 lg_graph_draw ( pm->phs.plg );
4508 static void cb_monitor_interface_hide(GtkWidget * widget, PGAPC_MONITOR pm)
4510 g_return_if_fail(pm != NULL);
4511 pm->b_visible = FALSE;
4514 static gboolean cb_monitor_interface_delete_event(GtkWidget * widget,
4515 GdkEvent * event, PGAPC_MONITOR pm)
4517 g_return_val_if_fail(pm != NULL, FALSE);
4519 return gtk_widget_hide_on_delete(widget);
4523 * Handle the close button action from the information window
4526 static void cb_monitor_interface_button_close(GtkWidget * button, PGAPC_MONITOR pm)
4528 g_return_if_fail(pm != NULL);
4529 gtk_widget_hide(GTK_WIDGET(pm->window));
4530 return;
4535 * Handle the refresh button action from the information window
4537 static void cb_monitor_interface_button_refresh(GtkWidget * button, PGAPC_MONITOR pm)
4539 g_return_if_fail(pm != NULL);
4541 if ((!pm->b_run) || !(pm->cb_enabled) || (pm->window == NULL)) {
4542 return;
4545 g_async_queue_push(pm->q_network, pm);
4546 g_timeout_add(GAPC_REFRESH_FACTOR_ONE_TIME,
4547 (GSourceFunc) cb_monitor_dedicated_one_time_refresh, pm);
4549 return;
4552 static void cb_main_interface_show(GtkWidget * widget, PGAPC_CONFIG pcfg)
4554 g_return_if_fail(pcfg != NULL);
4555 pcfg->b_visible = TRUE;
4558 static void cb_main_interface_hide(GtkWidget * widget, PGAPC_CONFIG pcfg)
4560 g_return_if_fail(pcfg != NULL);
4561 pcfg->b_visible = FALSE;
4564 /* "window-state-event"
4565 * iconify/minimize verus hide needs this routine to manage visibility
4567 static gboolean cb_util_manage_iconify_event(GtkWidget *widget, GdkEventWindowState *event,
4568 gpointer gp)
4570 g_return_val_if_fail(gp != NULL, FALSE);
4572 /* iconified */
4573 if ((event->type == GDK_WINDOW_STATE) && (
4574 ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) ||
4575 ((event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) && (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN))
4577 if ( ((PGAPC_MONITOR)gp)->cb_id == CB_MONITOR_ID) {
4578 if ( event->window == GTK_WIDGET(((PGAPC_MONITOR)gp)->window)->window ) {
4579 ((PGAPC_MONITOR)gp)->b_visible = FALSE;
4581 } else {
4582 if ( event->window == GTK_WIDGET(((PGAPC_CONFIG)gp)->window)->window ) {
4583 ((PGAPC_CONFIG)gp)->b_visible = FALSE;
4587 return TRUE;
4590 /* un - iconified */
4591 if ((event->type == GDK_WINDOW_STATE) && (
4592 ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && !(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) ||
4593 ((event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) && !(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN)))
4595 if ( ((PGAPC_MONITOR)gp)->cb_id == CB_MONITOR_ID) {
4596 if ( event->window == GTK_WIDGET(((PGAPC_MONITOR)gp)->window)->window ) {
4597 ((PGAPC_MONITOR)gp)->b_visible = TRUE;
4599 } else {
4600 if ( event->window == GTK_WIDGET(((PGAPC_CONFIG)gp)->window)->window ) {
4601 ((PGAPC_CONFIG)gp)->b_visible = TRUE;
4605 return TRUE;
4608 return FALSE;
4611 static gboolean cb_main_interface_delete_event(GtkWidget * widget, GdkEvent * event,
4612 PGAPC_CONFIG pcfg)
4614 g_return_val_if_fail(pcfg != NULL, FALSE);
4615 cb_main_interface_button_quit(widget, pcfg);
4616 return FALSE;
4620 * Handle the quit button action from the information window
4622 static void cb_main_interface_button_quit(GtkWidget * button, PGAPC_CONFIG pcfg)
4624 GtkTreeIter iter;
4625 PGAPC_MONITOR pm = NULL;
4626 gboolean valid = FALSE;
4628 g_return_if_fail(pcfg != NULL);
4630 valid = gtk_tree_model_get_iter_first(pcfg->monitor_model, &iter);
4631 while (valid) {
4632 gtk_tree_model_get(pcfg->monitor_model, &iter, GAPC_MON_POINTER, &pm, -1);
4633 if ((pm != NULL) && (pm->window != NULL)) {
4634 pm->b_run = FALSE;
4635 gtk_widget_destroy(GTK_WIDGET(pm->window));
4636 pm->window = NULL;
4637 pm = NULL;
4639 valid = gtk_tree_model_iter_next(pcfg->monitor_model, &iter);
4642 gtk_widget_destroy(GTK_WIDGET(pcfg->window));
4643 return;
4647 * GConf2 routine
4648 * Handles changes to use_systray and skip_pager for the control panel.
4649 * Triggers for this routine should not be installed until after the
4650 * control panel has been created.
4652 static void cb_panel_controller_gconf_changed(GConfClient * client, guint cnxn_id,
4653 GConfEntry * entry, PGAPC_CONFIG pcfg)
4655 gboolean b_new_value = FALSE;
4656 GtkWidget *cbox = NULL;
4657 gchar const *pstring = NULL;
4658 GdkColor *pcolor = NULL;
4660 g_return_if_fail(pcfg != NULL);
4661 g_return_if_fail(entry != NULL);
4662 g_return_if_fail(entry->value != NULL);
4663 g_return_if_fail(pcfg->window != NULL);
4665 switch (entry->value->type) {
4666 case GCONF_VALUE_STRING:
4667 /* take action to propagate the value to all monitors */
4668 pstring = gconf_value_get_string(entry->value);
4669 if (pstring == NULL) {
4670 break;
4672 pcolor = NULL;
4673 if (g_str_equal(entry->key, GAPC_COLOR_LINEV_KEY)) {
4674 pcolor = &pcfg->color_linev;
4675 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-linev");
4677 if (g_str_equal(entry->key, GAPC_COLOR_LOADPCT_KEY)) {
4678 pcolor = &pcfg->color_loadpct;
4679 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-loadpct");
4681 if (g_str_equal(entry->key, GAPC_COLOR_TIMELEFT_KEY)) {
4682 pcolor = &pcfg->color_timeleft;
4683 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-timeleft");
4685 if (g_str_equal(entry->key, GAPC_COLOR_BCHARGE_KEY)) {
4686 pcolor = &pcfg->color_bcharge;
4687 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-bcharge");
4689 if (g_str_equal(entry->key, GAPC_COLOR_BATTV_KEY)) {
4690 pcolor = &pcfg->color_battv;
4691 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-battv");
4693 if (g_str_equal(entry->key, GAPC_COLOR_WINDOW_KEY)) {
4694 pcolor = &pcfg->color_window;
4695 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-window");
4697 if (g_str_equal(entry->key, GAPC_COLOR_CHART_KEY)) {
4698 pcolor = &pcfg->color_chart;
4699 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-chart");
4701 if (g_str_equal(entry->key, GAPC_COLOR_TITLE_KEY)) {
4702 pcolor = &pcfg->color_title;
4703 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "color-title");
4705 if ( pcolor ) {
4706 gdk_color_parse (pstring, pcolor);
4708 if ( cbox ) {
4709 gtk_color_button_set_color (GTK_COLOR_BUTTON(cbox), pcolor);
4711 break;
4712 case GCONF_VALUE_BOOL:
4713 b_new_value = gconf_value_get_bool(entry->value);
4714 if (g_str_equal(entry->key, pcfg->pch_gkeys[GAPC_PREFS_SYSTRAY])) {
4715 if (pcfg->b_use_systray == b_new_value) {
4716 break;
4719 pcfg->b_use_systray = b_new_value;
4720 if (b_new_value) {
4721 if (pcfg->tray_icon == NULL) {
4722 gapc_panel_systray_icon_create(pcfg);
4724 } else {
4725 if (pcfg->tray_icon != NULL) {
4726 gapc_panel_systray_icon_remove(pcfg);
4729 cbox = g_hash_table_lookup(pcfg->pht_Widgets, "UseTrayIcon");
4730 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbox), pcfg->b_use_systray);
4731 break;
4733 break;
4734 default:
4735 gapc_util_log_app_msg("cb_panel_controller_gconf_changed",
4736 "(UnKnown Data Type for key)", entry->key);
4739 return;
4743 * GConf2 routine
4744 * Handles changes to prefs_model, or the master list of monitors in the preferences page.
4745 * Triggers for this routine should not be installed until after the
4746 * control panel has been created.
4748 static void cb_panel_preferences_gconf_changed(GConfClient * client, guint cnxn_id,
4749 GConfEntry * entry, PGAPC_CONFIG pcfg)
4751 gchar *pch_value = NULL;
4752 gchar *pkey = NULL, **pkey_l = NULL;
4754 gboolean ov_b_tray = FALSE;
4755 gint ov_i_port = 0;
4756 gint ov_i_watt = 0;
4757 gfloat ov_f_graph = 0.0;
4758 gfloat ov_f_refresh = 0.0;
4759 gchar *ov_s_host = NULL;
4762 gint i_monitor = 0;
4763 gint i_value = 0, i_len = 0;
4764 gfloat f_value = 0.0;
4765 gchar *s_value = NULL, ch[GAPC_MAX_TEXT];
4766 gboolean b_value = FALSE, b_flag_dupped = FALSE;
4768 gboolean b_ls_valid = FALSE;
4769 gboolean b_v_valid = FALSE;
4770 gboolean b_k_valid = FALSE;
4771 gboolean b_k_is_dir = FALSE;
4772 gboolean b_m_valid = FALSE;
4773 gboolean b_m_enabled = FALSE, b_add = TRUE, b_active_valid = FALSE;
4774 GtkTreeIter iter;
4775 GtkTreeIter miter;
4776 PGAPC_MONITOR pm = NULL;
4778 g_return_if_fail(pcfg != NULL);
4779 g_return_if_fail(entry != NULL);
4780 g_return_if_fail(pcfg->window != NULL);
4782 /* Parse out monitor number and item.key */
4783 pkey_l = g_strsplit(entry->key, "/", -1);
4784 if (pkey_l[5] != NULL) {
4785 pkey = g_strdup(pkey_l[5]);
4786 b_k_valid = TRUE;
4787 } else {
4788 b_k_is_dir = TRUE;
4790 if (pkey_l[4] != NULL) {
4791 i_monitor = (gint) g_strtod(pkey_l[4], NULL);
4792 b_m_valid = TRUE;
4794 g_strfreev(pkey_l);
4796 gdk_threads_enter();
4798 /* Determine control bools */
4799 b_ls_valid =
4800 gapc_util_treeview_get_iter_from_monitor(pcfg->prefs_model, &iter, i_monitor);
4801 if (b_ls_valid) {
4802 gtk_tree_model_get(pcfg->prefs_model, &iter,
4803 GAPC_PREFS_ENABLED, &b_m_enabled,
4804 GAPC_PREFS_SYSTRAY, &ov_b_tray,
4805 GAPC_PREFS_PORT, &ov_i_port,
4806 GAPC_PREFS_WATT, &ov_i_watt,
4807 GAPC_PREFS_GRAPH, &ov_f_graph,
4808 GAPC_PREFS_REFRESH, &ov_f_refresh,
4809 GAPC_PREFS_HOST, &ov_s_host, -1);
4811 if (entry->value != NULL) {
4812 pch_value = (gchar *) gconf_value_to_string(entry->value);
4813 if (pch_value != NULL) {
4814 b_v_valid = TRUE;
4818 /* perform record.level operations */
4819 if (b_ls_valid && !b_k_valid && !b_v_valid) { /* delete null dir - no key val */
4820 if (b_m_enabled) {
4821 gapc_monitor_interface_destroy(pcfg, i_monitor);
4822 b_m_enabled = FALSE;
4824 gtk_list_store_remove(GTK_LIST_STORE(pcfg->prefs_model), &iter);
4825 b_ls_valid = FALSE;
4826 pcfg->cb_last_monitor_deleted = i_monitor;
4828 if (i_monitor == pcfg->cb_last_monitor_deleted) { /* override gconf_unset-kde issue */
4829 b_k_valid = FALSE;
4830 b_v_valid = FALSE;
4831 b_m_enabled = FALSE;
4833 if (!b_ls_valid && b_v_valid && b_k_valid) { /* add new rec if keys valid -nfound */
4834 gtk_list_store_append(GTK_LIST_STORE(pcfg->prefs_model), &iter);
4835 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4836 GAPC_PREFS_MONITOR, i_monitor,
4837 GAPC_PREFS_SYSTRAY, FALSE,
4838 GAPC_PREFS_ENABLED, FALSE,
4839 GAPC_PREFS_PORT, GAPC_PORT_DEFAULT,
4840 GAPC_PREFS_GRAPH, GAPC_LINEGRAPH_REFRESH_FACTOR,
4841 GAPC_PREFS_HOST, GAPC_HOST_DEFAULT,
4842 GAPC_PREFS_REFRESH, GAPC_REFRESH_DEFAULT,
4843 GAPC_PREFS_WATT, GAPC_WATT_DEFAULT,
4844 -1);
4846 b_ls_valid = TRUE;
4847 b_add = TRUE;
4848 b_m_enabled = FALSE;
4851 /* perform cell.level operations */
4852 if (b_ls_valid && b_v_valid && b_k_valid) {
4854 b_active_valid =
4855 gapc_util_treeview_get_iter_from_monitor(pcfg->monitor_model, &miter,
4856 i_monitor);
4857 if (b_active_valid) {
4858 gtk_tree_model_get(pcfg->monitor_model, &miter, GAPC_MON_POINTER, &pm, -1);
4859 } else {
4860 b_active_valid = FALSE;
4863 if ((pm == NULL) || (pm->window == NULL)) {
4864 b_active_valid = FALSE;
4867 if (g_str_equal(pkey, "enabled")) {
4868 b_value = gconf_value_get_bool(entry->value);
4869 if (b_value != b_m_enabled) {
4870 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4871 GAPC_PREFS_ENABLED, b_value, -1);
4873 if (b_value && !b_m_enabled && !b_active_valid) {
4874 gtk_widget_show_all(gapc_monitor_interface_create(pcfg, i_monitor,
4875 &iter));
4877 if (!b_value && b_m_enabled && b_active_valid) {
4878 gapc_monitor_interface_destroy(pcfg, i_monitor);
4881 if (g_str_equal(pkey, "use_systray")) {
4882 b_value = gconf_value_get_bool(entry->value);
4883 if (b_value != ov_b_tray) {
4884 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4885 GAPC_PREFS_SYSTRAY, b_value, -1);
4887 if ((b_m_enabled) && (b_active_valid)) {
4888 pm->cb_use_systray = b_value;
4889 if (b_value) {
4890 gapc_panel_systray_icon_create(pm);
4891 } else {
4892 gapc_panel_systray_icon_remove(pm);
4896 if (g_str_equal(pkey, "port_number")) {
4897 i_value = gconf_value_get_int(entry->value);
4898 if (i_value != ov_i_port) {
4899 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4900 GAPC_PREFS_PORT, i_value, -1);
4902 if ((b_m_enabled) && (b_active_valid)) {
4903 pm->i_port = i_value;
4904 pm->b_network_control = TRUE;
4905 if (pm->psk != NULL) {
4906 pm->psk->i_port = i_value;
4907 pm->psk->b_network_control = TRUE;
4911 if (g_str_equal(pkey, "ups_wattage")) {
4912 i_value = gconf_value_get_int(entry->value);
4913 if (i_value != ov_i_watt) {
4914 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4915 GAPC_PREFS_WATT, i_value, -1);
4917 if ( pm != NULL ) {
4918 pm->i_watt = i_value;
4921 if (g_str_equal(pkey, "network_interval")) {
4922 f_value = gconf_value_get_float(entry->value);
4923 if (f_value != ov_f_refresh) {
4924 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4925 GAPC_PREFS_REFRESH, f_value, -1);
4927 if ((b_m_enabled) && (b_active_valid)) {
4928 pm->d_refresh = f_value;
4929 pm->b_timer_control = TRUE;
4932 if (g_str_equal(pkey, "graph_interval")) {
4933 f_value = gconf_value_get_float(entry->value);
4934 if (f_value != ov_f_graph) {
4935 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4936 GAPC_PREFS_GRAPH, f_value, -1);
4938 if ((b_m_enabled) && (b_active_valid)) {
4939 pm->d_graph = f_value;
4940 pm->b_graph_control = TRUE;
4943 if (g_str_equal(pkey, "host_name")) {
4944 s_value = (gchar *) gconf_value_get_string(entry->value);
4945 i_len = g_snprintf(ch, GAPC_MAX_TEXT, "%s", s_value);
4946 if (i_len < 2) {
4947 s_value = g_strdup(GAPC_HOST_DEFAULT);
4948 b_flag_dupped = TRUE;
4950 if (!g_str_equal(s_value, ov_s_host)) {
4951 gtk_list_store_set(GTK_LIST_STORE(pcfg->prefs_model), &iter,
4952 GAPC_PREFS_HOST, s_value, -1);
4954 if ((b_m_enabled) && (b_active_valid)) {
4955 if (pm->pch_host != NULL) {
4956 g_free(pm->pch_host);
4958 pm->pch_host = g_strdup(s_value);
4959 pm->b_network_control = TRUE;
4960 if (pm->psk != NULL) {
4961 g_snprintf(pm->psk->ch_ip_string, sizeof(pm->psk->ch_ip_string), "%s", s_value);
4962 pm->psk->b_network_control = TRUE;
4965 if (b_flag_dupped) {
4966 g_free(s_value);
4967 b_flag_dupped = FALSE;
4969 if (ov_s_host) {
4970 g_free(ov_s_host);
4975 if (pkey != NULL) {
4976 g_free(pkey);
4978 if (pch_value != NULL) {
4979 g_free(pch_value);
4982 gdk_flush();
4983 gdk_threads_leave();
4985 return;
4989 * Clears the gconf directory watchers for the control panel
4990 * returns FALSE on error
4991 * returns TRUE on sucess
4993 static gboolean gapc_panel_gconf_destroy(PGAPC_CONFIG pcfg)
4995 g_return_val_if_fail(pcfg != NULL, FALSE);
4997 if (pcfg->i_group_id > 0) {
4998 gconf_client_remove_dir(pcfg->client, GAPC_MID_GROUP_KEY, NULL);
4999 gconf_client_remove_dir(pcfg->client, GAPC_CP_GROUP_KEY, NULL);
5000 gconf_client_notify_remove(pcfg->client, pcfg->i_group_id);
5001 gconf_client_notify_remove(pcfg->client, pcfg->i_prefs_id);
5003 g_object_unref(pcfg->client);
5005 g_free(pcfg->pch_gkeys[GAPC_PREFS_SYSTRAY]);
5007 pcfg->i_group_id = 0;
5008 pcfg->i_prefs_id = 0;
5009 pcfg->client = NULL;
5010 pcfg->pch_gkeys[GAPC_PREFS_SYSTRAY] = NULL;
5012 return TRUE;
5016 * Set the gconf directory watchers for the control panel
5017 * returns FALSE on error
5018 * returns TRUE on sucess
5020 static gboolean gapc_panel_gconf_watch(PGAPC_CONFIG pcfg)
5022 GError *gerror = NULL;
5024 g_return_val_if_fail(pcfg != NULL, FALSE);
5026 /* Have gconf call us if something does change */
5027 pcfg->i_group_id =
5028 gconf_client_notify_add(pcfg->client, GAPC_CP_GROUP_KEY,
5029 (GConfClientNotifyFunc)
5030 cb_panel_controller_gconf_changed, pcfg, NULL, &gerror);
5031 if (gerror != NULL) {
5032 gapc_util_log_app_msg("gapc_panel_gconf_watch",
5033 "gconf_client_notify_add(controller.group) Failed", gerror->message);
5034 g_error_free(gerror);
5035 pcfg->i_group_id = 0;
5036 gerror = NULL;
5037 return FALSE;
5040 pcfg->i_prefs_id =
5041 gconf_client_notify_add(pcfg->client, GAPC_MID_GROUP_KEY,
5042 (GConfClientNotifyFunc)
5043 cb_panel_preferences_gconf_changed, pcfg, NULL, &gerror);
5044 if (gerror != NULL) {
5045 gapc_util_log_app_msg("gapc_panel_gconf_watch",
5046 "gconf_client_notify_add(prefs.group) Failed", gerror->message);
5047 g_error_free(gerror);
5048 pcfg->i_group_id = 0;
5049 gerror = NULL;
5050 return FALSE;
5053 return TRUE;
5057 * Gets the gconf instance preferences for this program
5058 * and init the control panel values.
5059 * returns FALSE on error
5060 * returns TRUE on sucess
5062 static gboolean gapc_panel_gconf_init(PGAPC_CONFIG pcfg)
5064 GError *gerror = NULL;
5065 gchar *pstring = NULL;
5067 g_return_val_if_fail(pcfg != NULL, FALSE);
5069 /* prepare control panel keys */
5070 pcfg->pch_gkeys[GAPC_PREFS_SYSTRAY] = g_strdup(GAPC_CP_SYSTRAY_KEY);
5072 /* contact gconf2 */
5073 pcfg->client = gconf_client_get_default();
5074 g_return_val_if_fail(pcfg->client != NULL, FALSE);
5076 /* Have gconf watch for changes in this controller directory */
5077 gconf_client_add_dir(pcfg->client, GAPC_CP_GROUP_KEY,
5078 GCONF_CLIENT_PRELOAD_ONELEVEL, &gerror);
5079 if (gerror != NULL) {
5080 gapc_util_log_app_msg("gapc_panel_gconf_init", "gconf_client_add_dir() Failed",
5081 gerror->message);
5082 g_error_free(gerror);
5083 gerror = NULL;
5084 return FALSE;
5087 /* Have gconf watch for changes in this monitor directory */
5088 gconf_client_add_dir(pcfg->client, GAPC_MID_GROUP_KEY,
5089 GCONF_CLIENT_PRELOAD_ONELEVEL, &gerror);
5090 if (gerror != NULL) {
5091 gapc_util_log_app_msg("gapc_panel_gconf_init", "gconf_client_add_dir() Failed",
5092 gerror->message);
5093 g_error_free(gerror);
5094 gerror = NULL;
5095 return FALSE;
5098 /* Defaults are FALSE */
5099 pcfg->b_use_systray =
5100 gconf_client_get_bool(pcfg->client, pcfg->pch_gkeys[GAPC_PREFS_SYSTRAY], NULL);
5102 /* Load graph colors or set defaults */
5103 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_LINEV_KEY, NULL);
5104 if (pstring) {
5105 gdk_color_parse (pstring, &pcfg->color_linev);
5106 } else {
5107 gdk_color_parse ("green", &pcfg->color_linev);
5109 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_LOADPCT_KEY, NULL);
5110 if (pstring) {
5111 gdk_color_parse (pstring, &pcfg->color_loadpct);
5112 } else {
5113 gdk_color_parse ("blue", &pcfg->color_loadpct);
5115 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_TIMELEFT_KEY, NULL);
5116 if (pstring) {
5117 gdk_color_parse (pstring, &pcfg->color_timeleft);
5118 } else {
5119 gdk_color_parse ("red", &pcfg->color_timeleft);
5121 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_BCHARGE_KEY, NULL);
5122 if (pstring) {
5123 gdk_color_parse (pstring, &pcfg->color_bcharge);
5124 } else {
5125 gdk_color_parse ("yellow", &pcfg->color_bcharge);
5127 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_BATTV_KEY, NULL);
5128 if (pstring) {
5129 gdk_color_parse (pstring, &pcfg->color_battv);
5130 } else {
5131 gdk_color_parse ("black", &pcfg->color_battv);
5133 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_WINDOW_KEY, NULL);
5134 if (pstring) {
5135 gdk_color_parse (pstring, &pcfg->color_window);
5136 } else {
5137 gdk_color_parse ("white", &pcfg->color_window);
5139 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_CHART_KEY, NULL);
5140 if (pstring) {
5141 gdk_color_parse (pstring, &pcfg->color_chart);
5142 } else {
5143 gdk_color_parse ("light blue", &pcfg->color_chart);
5145 pstring = gconf_client_get_string(pcfg->client, GAPC_COLOR_TITLE_KEY, NULL);
5146 if (pstring) {
5147 gdk_color_parse (pstring, &pcfg->color_title);
5148 } else {
5149 gdk_color_parse ("blue", &pcfg->color_title);
5152 return TRUE;
5156 * Handle Object.Destroy Signal
5157 * have no choice be go away when destroyed
5159 static void cb_monitor_interface_destroy(GtkWidget * widget, PGAPC_MONITOR pm)
5161 PGAPC_CONFIG pcfg = (PGAPC_CONFIG)pm->gp;
5162 GtkWidget *sbar = NULL;
5163 gint h_index = 0;
5165 g_return_if_fail(pm != NULL);
5166 g_return_if_fail(pcfg != NULL);
5168 pm->b_run = FALSE;
5170 if (pm->tid_graph_refresh) {
5171 g_source_remove(pm->tid_graph_refresh);
5173 if (pm->tid_automatic_refresh) {
5174 g_source_remove(pm->tid_automatic_refresh);
5177 if (pm->tid_thread_qwork != NULL) {
5178 pm->b_thread_stop = TRUE;
5179 g_async_queue_push(pm->q_network, pm);
5180 g_thread_join(pm->tid_thread_qwork);
5183 g_mutex_free(pm->gm_update);
5184 g_async_queue_unref(pm->q_network);
5187 for (h_index = 0; h_index < GAPC_LINEGRAPH_MAX_SERIES; h_index++) {
5188 if (pm->phs.sq[h_index].gm_graph != NULL) {
5189 g_mutex_free(pm->phs.sq[h_index].gm_graph);
5193 if (pm->pht_Widgets != NULL) {
5194 g_hash_table_destroy(pm->pht_Widgets);
5195 g_hash_table_destroy(pm->pht_Status);
5196 pm->pht_Widgets = NULL;
5197 pm->pht_Status = NULL;
5200 for (h_index = 0; h_index < GAPC_MAX_ARRAY; h_index++) {
5201 if (pm->pach_events[h_index] != NULL) {
5202 g_free(pm->pach_events[h_index]);
5204 pm->pach_events[h_index] = NULL;
5205 if (pm->pach_status[h_index] != NULL) {
5206 g_free(pm->pach_status[h_index]);
5208 pm->pach_status[h_index] = NULL;
5211 if (pm->tray_icon != NULL) {
5212 gtk_widget_destroy(GTK_WIDGET(pm->tray_icon));
5213 pm->tray_icon = NULL;
5214 pm->tray_image = NULL;
5216 if (pm->menu != NULL) {
5217 gtk_widget_destroy(GTK_WIDGET(pm->menu));
5218 pm->menu = NULL;
5221 g_object_unref (pm->tooltips);
5223 lg_graph_data_series_remove_all ( pm->phs.plg );
5225 sbar = g_hash_table_lookup (pcfg->pht_Widgets, "StatusBar");
5226 if (sbar) {
5227 gchar *pch = NULL;
5229 gtk_statusbar_pop(GTK_STATUSBAR(sbar), pcfg->i_info_context);
5230 pch = g_strdup_printf
5231 ("Monitor for %s Destroyed!...", pm->pch_host );
5232 gtk_statusbar_push(GTK_STATUSBAR(sbar), pcfg->i_info_context, pch);
5233 g_free(pch);
5236 g_free(pm);
5237 return;
5240 static void cb_main_interface_destroy(GtkWidget * widget, PGAPC_CONFIG pcfg)
5242 gint x = 0;
5244 g_return_if_fail(pcfg != NULL);
5246 pcfg->b_run = FALSE;
5248 gapc_panel_gconf_destroy(pcfg);
5250 if (GTK_IS_TREE_VIEW(pcfg->prefs_treeview)) {
5251 gtk_widget_destroy(GTK_WIDGET(pcfg->prefs_treeview));
5252 pcfg->prefs_treeview = NULL;
5254 if (GTK_IS_TREE_VIEW(pcfg->monitor_treeview)) {
5255 gtk_widget_destroy(GTK_WIDGET(pcfg->monitor_treeview));
5256 pcfg->monitor_treeview = NULL;
5258 if (pcfg->prefs_model != NULL) {
5259 gtk_list_store_clear(GTK_LIST_STORE(pcfg->prefs_model));
5260 g_object_unref(G_OBJECT(pcfg->prefs_model));
5261 pcfg->prefs_model = NULL;
5263 if (pcfg->monitor_model != NULL) {
5264 gtk_list_store_clear(GTK_LIST_STORE(pcfg->monitor_model));
5265 g_object_unref(G_OBJECT(pcfg->monitor_model));
5266 pcfg->monitor_model = NULL;
5268 if (pcfg->pht_Widgets != NULL) {
5269 g_hash_table_destroy(pcfg->pht_Widgets);
5270 g_hash_table_destroy(pcfg->pht_Status);
5272 for (x = 0; x < GAPC_N_ICONS; x++) {
5273 g_object_unref(pcfg->my_icons[x]);
5276 g_object_unref (pcfg->tooltips);
5278 gtk_main_quit();
5279 return;
5283 * returns TRUE if helps was offered, else FALSE if input was all ok.
5285 static gint gapc_main_interface_parse_args(gint argc, gchar ** argv,
5286 PGAPC_CONFIG pcfg)
5288 gchar *pch = NULL;
5289 GString *gs_parm1 = NULL, *gs_parm2 = NULL;
5291 gs_parm1 = g_string_new(GAPC_CP_GROUP_KEY);
5292 gs_parm2 = g_string_new(GAPC_CP_GROUP_KEY);
5294 /* *********************************************************** *
5295 * Get user input
5296 * - default to known values
5297 * - check config file for saved values -- careful not to override cmdline
5299 while (--argc > 0) { /* ADJUST COUNTER HERE */
5300 g_string_assign(gs_parm1, argv[argc]);
5301 if (argv[argc + 1] != NULL) {
5302 g_string_assign(gs_parm2, argv[argc + 1]);
5305 pch = g_strstr_len(gs_parm1->str, 6, "-help");
5306 if (pch != NULL) {
5307 g_print("\nsyntax: gapcmon [--help]\n"
5308 "where: --help, this message, no command line options are available\n"
5309 "Skoona@Users.SourceForge.Net (GPL) 2006 \n\n");
5311 g_string_free(gs_parm1, TRUE);
5312 g_string_free(gs_parm2, TRUE);
5313 return TRUE; /* trigger exit */
5317 g_string_free(gs_parm1, TRUE);
5318 g_string_free(gs_parm2, TRUE);
5320 /* *********************************************************
5321 * Apply instance value
5324 return FALSE;
5328 * Create main interface with the following panels
5329 * - icon list
5330 * - preferences panel
5331 * - about panel
5333 static GtkWidget *gapc_main_interface_create(PGAPC_CONFIG pcfg)
5335 GtkWindow *window = NULL;
5336 GdkPixbuf *pixbuf = NULL;
5337 GtkWidget *sbar = NULL, *notebook = NULL, *menu = NULL, *menu_item = NULL;
5338 GtkWidget *label = NULL, *button = NULL;
5339 GtkWidget *bbox = NULL, *lbox = NULL, *nbox = NULL, *box = NULL;
5340 gint i_page = 0;
5342 g_return_val_if_fail(pcfg != NULL, NULL);
5344 /* Create hash table for easy access to system widgets */
5345 pcfg->pht_Status = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
5346 pcfg->pht_Widgets = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5347 pixbuf = pcfg->my_icons[GAPC_ICON_DEFAULT];
5348 pcfg->b_visible = FALSE;
5349 pcfg->tooltips = gtk_tooltips_new();
5350 g_object_ref (pcfg->tooltips);
5351 gtk_object_sink (GTK_OBJECT(pcfg->tooltips));
5352 pcfg->b_run = TRUE;
5353 pcfg->cb_last_monitor_deleted = -1;
5356 * Create the top level window for the notebook to be packed into.*/
5357 window = g_object_new(GTK_TYPE_WINDOW, "border-width", 0, "destroy-with-parent",
5358 TRUE, "icon", pixbuf, "resizable", TRUE, "title",
5359 GAPC_WINDOW_TITLE, "type", GTK_WINDOW_TOPLEVEL, "type-hint",
5360 GDK_WINDOW_TYPE_HINT_NORMAL, "window-position", GTK_WIN_POS_NONE, NULL);
5362 pcfg->window = GTK_WIDGET(window);
5363 g_signal_connect(window, "destroy", G_CALLBACK(cb_main_interface_destroy), pcfg);
5364 g_signal_connect(window, "delete-event",
5365 G_CALLBACK(cb_main_interface_delete_event), pcfg);
5366 g_signal_connect(window, "show", G_CALLBACK(cb_main_interface_show), pcfg);
5367 g_signal_connect(window, "hide", G_CALLBACK(cb_main_interface_hide), pcfg);
5368 g_signal_connect(window, "window-state-event",
5369 G_CALLBACK(cb_util_manage_iconify_event), pcfg);
5371 gapc_panel_systray_icon_create(pcfg);
5373 lbox = gtk_vbox_new(FALSE, 2);
5374 gtk_container_add(GTK_CONTAINER(window), lbox);
5375 gtk_widget_show(lbox);
5377 /* */
5379 /* Notebook Box */
5380 bbox = gtk_vbox_new(FALSE, 0);
5381 gtk_container_set_border_width(GTK_CONTAINER(bbox), 6);
5382 gtk_box_pack_start(GTK_BOX(lbox), bbox, TRUE, TRUE, 2);
5383 gtk_widget_show(bbox);
5384 nbox = gtk_hbox_new(TRUE, 0);
5385 gtk_box_pack_start(GTK_BOX(bbox), nbox, TRUE, TRUE, 0);
5386 gtk_widget_show(nbox);
5388 /* create the status bar */
5389 sbar = gtk_statusbar_new();
5390 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(sbar), FALSE);
5391 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("StatusBar"), sbar);
5392 gtk_box_pack_end(GTK_BOX(lbox), sbar, FALSE, TRUE, 0);
5393 gtk_widget_show(sbar);
5394 pcfg->i_info_context =
5395 gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar), "Informational");
5397 /* buttons Box */
5398 bbox = gtk_hbox_new(FALSE, 0);
5399 gtk_container_set_border_width(GTK_CONTAINER(bbox), 0);
5400 gtk_box_pack_end(GTK_BOX(lbox), bbox, FALSE, FALSE, 0);
5401 gtk_widget_show(bbox);
5402 box = gtk_hbutton_box_new();
5403 gtk_container_set_border_width(GTK_CONTAINER(box), 6);
5404 gtk_box_pack_end(GTK_BOX(bbox), box, FALSE, FALSE, 2);
5405 gtk_widget_show(box);
5407 /* Create the top-level notebook */
5408 notebook = gtk_notebook_new();
5409 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
5410 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
5411 gtk_notebook_set_homogeneous_tabs(GTK_NOTEBOOK(notebook), TRUE);
5412 gtk_box_pack_start(GTK_BOX(nbox), notebook, TRUE, TRUE, 0);
5413 gtk_widget_show(notebook);
5415 /* Create the main pages */
5416 gapc_panel_monitor_list_page(pcfg, GTK_NOTEBOOK(notebook));
5417 i_page = gapc_panel_preferences_page(pcfg, GTK_NOTEBOOK(notebook));
5418 gapc_panel_graph_property_page(pcfg, notebook);
5419 gapc_panel_glossary_page(pcfg, notebook);
5420 gapc_panel_about_page(GTK_NOTEBOOK(notebook), GAPC_WINDOW_TITLE, GAPC_VERSION,
5421 pixbuf);
5423 label = gtk_label_new("<big>" GAPC_GROUP_TITLE "</big>");
5424 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5425 gtk_label_set_line_wrap(GTK_LABEL(label), FALSE);
5426 gtk_box_pack_start(GTK_BOX(bbox), label, TRUE, TRUE, 0);
5427 gtk_widget_show(label);
5429 /* quit Control button */
5431 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
5432 g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_hide), GTK_WIDGET(window));
5433 gtk_box_pack_end(GTK_BOX(box), button, TRUE, TRUE, 0);
5434 gtk_widget_show(button);
5436 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
5437 gtk_widget_grab_default(button);
5440 button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
5441 g_signal_connect(button, "clicked", G_CALLBACK(cb_main_interface_button_quit),
5442 pcfg);
5443 gtk_box_pack_end(GTK_BOX(box), button, TRUE, TRUE, 0);
5444 gtk_widget_show(button);
5447 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), i_page);
5449 pcfg->menu = menu = gtk_menu_new();
5450 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_JUMP_TO, NULL);
5451 g_signal_connect(G_OBJECT(menu_item), "activate",
5452 G_CALLBACK(cb_util_popup_menu_response_jumpto), pcfg);
5453 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
5454 gtk_widget_show(menu_item);
5455 menu_item = gtk_separator_menu_item_new();
5456 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
5457 gtk_widget_show(menu_item);
5458 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
5459 g_signal_connect(G_OBJECT(menu_item), "activate",
5460 G_CALLBACK(cb_util_popup_menu_response_exit), pcfg);
5461 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
5462 gtk_widget_show(menu_item);
5463 gtk_widget_show(menu);
5465 gtk_widget_show_all(lbox);
5467 return GTK_WIDGET(window);
5471 * Creates a GtkGLGraph histogram linechart page
5473 static gint gapc_monitor_history_page(PGAPC_MONITOR pm, GtkWidget * notebook)
5475 PGAPC_HISTORY pphs = (PGAPC_HISTORY) & pm->phs;
5476 PGAPC_CONFIG pcfg = (PGAPC_CONFIG) pm->gp;
5477 PLGRAPH plg = NULL;
5478 gint i_page = 0, i_series = 0, h_index = 0;
5479 GtkWidget *label = NULL, *box = NULL;
5480 gchar *pch = NULL;
5481 gchar *pch_colors[6];
5482 gchar *pch_legend[] = { "LINEV", "LOADPCT", "TIMELEFT", "BCHARGE", "BATTV" };
5484 g_return_val_if_fail(pm != NULL, -1);
5487 * Prepare the environment */
5488 pphs->gp = (gpointer) pm;
5489 pphs->d_xinc = pm->d_refresh * pm->d_graph;
5490 lg_graph_debug = FALSE;
5492 for (h_index = 0; h_index < GAPC_LINEGRAPH_MAX_SERIES; h_index++) {
5493 if (pm->phs.sq[h_index].gm_graph != NULL) {
5494 g_mutex_free(pm->phs.sq[h_index].gm_graph);
5496 pm->phs.sq[h_index].gm_graph = g_mutex_new();
5499 /* get values from graph properties */
5500 pch_colors[0] = gtk_color_selection_palette_to_string ( &pcfg->color_linev, 1);
5501 pch_colors[1] = gtk_color_selection_palette_to_string ( &pcfg->color_loadpct, 1);
5502 pch_colors[2] = gtk_color_selection_palette_to_string ( &pcfg->color_timeleft, 1);
5503 pch_colors[3] = gtk_color_selection_palette_to_string ( &pcfg->color_bcharge, 1);
5504 pch_colors[4] = gtk_color_selection_palette_to_string ( &pcfg->color_battv, 1);
5505 pch_colors[5] = NULL;
5508 * Create notebook page page */
5509 box = gtk_vbox_new(FALSE, 0);
5510 g_object_set_data ( G_OBJECT(box), "pcfg-pointer", pm->gp);
5511 label = gtk_label_new("Historical Summary");
5512 i_page = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), box, label);
5513 gtk_widget_show(GTK_WIDGET(box));
5514 gtk_widget_show(label);
5517 * Create Chart surface */
5518 plg = pphs->plg = lg_graph_create ( box, 300, 200 );
5519 if (plg != NULL) {
5520 for (i_series = 0; i_series < GAPC_LINEGRAPH_MAX_SERIES; i_series++) {
5521 lg_graph_data_series_add (plg, pch_legend[i_series], pch_colors[i_series]);
5522 g_free (pch_colors[i_series]);
5525 pch = g_strdup_printf(
5526 "<i>sampled every %3.1f seconds</i>",
5527 pm->phs.d_xinc);
5528 lg_graph_set_x_label_text (plg, pch);
5529 g_free(pch);
5531 lg_graph_set_chart_title (plg, pm->ch_title_info);
5534 pm->tid_graph_refresh =
5535 gtk_timeout_add(((guint) (pphs->d_xinc * GAPC_REFRESH_FACTOR_1K )),
5536 (GSourceFunc) cb_util_line_chart_refresh, pphs);
5538 /* collect one right away */
5539 pphs->b_startup = TRUE;
5540 g_timeout_add((guint) (pm->d_refresh * GAPC_REFRESH_FACTOR_1K + 75),
5541 (GSourceFunc) cb_util_line_chart_refresh, pphs);
5543 return i_page;
5547 * Add a new data point until xrange is reached
5548 * then rotate back the y points and add new point to end
5549 * return TRUE is successful, FALSE other wise
5551 static gboolean cb_util_line_chart_refresh(PGAPC_HISTORY pg)
5553 gint h_index = 0;
5554 PLGRAPH plg = NULL;
5555 PGAPC_MONITOR pm = NULL;
5557 g_return_val_if_fail(pg != NULL, FALSE);
5559 pm = (PGAPC_MONITOR) pg->gp;
5560 plg = pg->plg;
5561 g_return_val_if_fail(plg != NULL, FALSE);
5562 g_return_val_if_fail(pm != NULL, FALSE);
5564 if (!pm->b_run) /* stop this timer */
5565 return FALSE;
5567 if (pm->b_graph_control) {
5568 g_timeout_add(100, (GSourceFunc) cb_util_line_chart_refresh_control, pm);
5569 return FALSE;
5573 gdk_threads_enter();
5575 for (h_index = 0; h_index < plg->i_num_series; h_index++) {
5576 lg_graph_data_series_add_value (plg, h_index,
5577 gapc_util_point_filter_reset(&(pg->sq[h_index])) );
5580 if (plg->i_points_available >= plg->x_range.i_max_scale ) {
5581 lg_graph_draw ( plg );
5582 } else {
5583 lg_graph_data_series_draw_all (plg, TRUE);
5584 lg_graph_redraw ( plg );
5587 gdk_flush();
5588 gdk_threads_leave();
5590 if (pg->b_startup) {
5591 pg->b_startup = FALSE;
5592 return FALSE;
5595 /* first data point collected */
5596 return TRUE;
5601 * Create and Initialize a Line Chart
5603 static PLGRAPH lg_graph_create (GtkWidget * box, gint width, gint height)
5605 PLGRAPH plg = NULL;
5606 PGAPC_CONFIG pcfg = NULL;
5607 GtkWidget *drawing_area = NULL;
5608 GdkColor color;
5609 PangoFontDescription *font_desc = NULL;
5610 gchar *pstring = NULL;
5612 pcfg = (PGAPC_CONFIG)g_object_get_data (G_OBJECT(box), "pcfg-pointer");
5613 g_return_val_if_fail (pcfg != NULL, NULL);
5615 plg = g_new0 (LGRAPH, 1);
5616 g_return_val_if_fail (plg != NULL, NULL);
5618 plg->cb_id = CB_GRAPH_ID;
5619 plg->x_range.cb_id = CB_RANGE_ID;
5620 plg->y_range.cb_id = CB_RANGE_ID;
5621 plg->b_tooltip_active = TRUE;
5623 * These must be set before the first drawing_area configure event
5625 lg_graph_set_chart_title (plg, "Waiting for Update");
5626 lg_graph_set_y_label_text (plg, "Precentage of 100% normal");
5627 lg_graph_set_x_label_text (plg, "Waiting for Update");
5629 g_snprintf (plg->ch_tooltip_text, sizeof (plg->ch_tooltip_text), "%s",
5630 "Waiting for Graphable Data...");
5632 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_title, 1);
5633 lg_graph_set_chart_title_color (plg, pstring);
5634 g_free (pstring);
5636 lg_graph_set_chart_scales_color (plg, "black");
5638 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_chart, 1);
5639 lg_graph_set_chart_window_fg_color (plg, pstring);
5640 g_free (pstring);
5642 pstring = gtk_color_selection_palette_to_string ( &pcfg->color_window, 1);
5643 lg_graph_set_chart_window_bg_color (plg, pstring);
5644 g_free (pstring);
5646 /* Xminor divisions, Xmajor divisions, Xbotton scale, Xtop scale, ...y */
5647 lg_graph_set_ranges (plg, 1, 2, 0, 40, 2, 10, 0, 110);
5649 drawing_area = plg->drawing_area = gtk_drawing_area_new ();
5650 gtk_widget_set_events (drawing_area,
5651 GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
5652 GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
5653 gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), width, height);
5654 gtk_box_pack_start (GTK_BOX (box), drawing_area, TRUE, TRUE, 0);
5656 font_desc = pango_font_description_from_string ("Monospace 10");
5657 gtk_widget_modify_font (drawing_area, font_desc);
5658 pango_font_description_free (font_desc);
5660 gtk_widget_realize (drawing_area);
5661 gtk_widget_show (drawing_area);
5663 plg->series_gc = gdk_gc_new (drawing_area->window);
5664 plg->window_gc = gdk_gc_new (drawing_area->window);
5665 plg->box_gc = gdk_gc_new (drawing_area->window);
5666 plg->scale_gc = gdk_gc_new (drawing_area->window);
5667 plg->title_gc = gdk_gc_new (drawing_area->window);
5669 gdk_gc_copy (plg->series_gc,
5670 drawing_area->style->fg_gc[GTK_WIDGET_STATE (drawing_area)]);
5671 gdk_gc_copy (plg->window_gc,
5672 drawing_area->style->bg_gc[GTK_WIDGET_STATE (drawing_area)]);
5673 gdk_gc_copy (plg->box_gc,
5674 drawing_area->style->fg_gc[GTK_WIDGET_STATE (drawing_area)]);
5675 gdk_gc_copy (plg->scale_gc,
5676 drawing_area->style->fg_gc[GTK_WIDGET_STATE (drawing_area)]);
5677 gdk_gc_copy (plg->title_gc,
5678 drawing_area->style->text_aa_gc[GTK_WIDGET_STATE (drawing_area)]);
5680 gdk_color_parse (plg->ch_color_window_bg, &color);
5681 gdk_gc_set_rgb_fg_color (plg->window_gc, &color);
5683 gdk_color_parse (plg->ch_color_chart_bg, &color);
5684 gdk_gc_set_rgb_fg_color (plg->box_gc, &color);
5686 gdk_color_parse (plg->ch_color_scale_fg, &color);
5687 gdk_gc_set_rgb_fg_color (plg->scale_gc, &color);
5689 gdk_color_parse (plg->ch_color_title_fg, &color);
5690 gdk_gc_set_rgb_fg_color (plg->title_gc, &color);
5692 /* --- Signals used to handle backing pixmap --- */
5693 gtk_signal_connect (GTK_OBJECT (drawing_area), "configure_event",
5694 (GtkSignalFunc) lg_graph_configure_event_cb, plg);
5695 gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
5696 (GtkSignalFunc) lg_graph_expose_event_cb, plg);
5697 gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
5698 (GtkSignalFunc) lg_graph_motion_notify_event_cb, plg);
5699 gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
5700 (GtkSignalFunc) lg_graph_button_press_event_cb, plg);
5702 return plg;
5707 * Detailed Information Notebook Page
5709 static gint gapc_monitor_information_page(PGAPC_MONITOR pm, GtkWidget * notebook)
5711 GtkWidget *frame, *label, *pbox, *lbox, *rbox, *gbox;
5712 GtkWidget *tbox, *tlbox, *trbox;
5713 gint i_page = 0;
5715 /* Create a Notebook Page */
5716 gbox = gtk_frame_new(NULL);
5717 gtk_container_set_border_width(GTK_CONTAINER(gbox), 4);
5718 gtk_frame_set_shadow_type(GTK_FRAME(gbox), GTK_SHADOW_NONE);
5719 label = gtk_label_new("Detailed Information");
5720 i_page = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), gbox, label);
5721 gtk_widget_show(gbox);
5723 tbox = gtk_hbox_new(FALSE, 4);
5724 gtk_container_add(GTK_CONTAINER(gbox), tbox);
5725 gtk_widget_show(tbox);
5728 * create basic frame */
5729 tlbox = gtk_vbox_new(TRUE, 2);
5730 gtk_box_pack_start(GTK_BOX(tbox), tlbox, TRUE, TRUE, 0);
5731 gtk_widget_show(tlbox);
5732 trbox = gtk_vbox_new(TRUE, 2);
5733 gtk_box_pack_end(GTK_BOX(tbox), trbox, TRUE, TRUE, 0);
5734 gtk_widget_show(trbox);
5736 frame = gtk_frame_new("<b><i>Performance Summary</i></b>");
5737 gtk_frame_set_label_align(GTK_FRAME(frame), 0.1, 0.8);
5738 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
5739 label = gtk_frame_get_label_widget(GTK_FRAME(frame));
5740 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5741 gtk_box_pack_start(GTK_BOX(tlbox), frame, TRUE, TRUE, 0);
5742 gtk_widget_show(frame);
5744 pbox = gtk_hbox_new(FALSE, 4);
5745 gtk_container_add(GTK_CONTAINER(frame), pbox);
5746 gtk_widget_show(pbox);
5747 lbox = gtk_vbox_new(FALSE, 0);
5748 gtk_box_pack_start(GTK_BOX(pbox), lbox, FALSE, TRUE, 0);
5749 gtk_widget_show(lbox);
5750 rbox = gtk_vbox_new(FALSE, 0);
5751 gtk_box_pack_end(GTK_BOX(pbox), rbox, TRUE, TRUE, 0);
5752 gtk_widget_show(rbox);
5754 label = gtk_label_new("Selftest running\n" "Number of transfers\n"
5755 "Reason last transfer\n" "Last transfer to battery\n"
5756 "Last transfer off battery\n" "Time on battery\n" "Cummulative on battery");
5757 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5758 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
5759 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5760 gtk_misc_set_alignment((GtkMisc *) label, 1.0, 0.5);
5761 gtk_box_pack_start(GTK_BOX(lbox), label, FALSE, FALSE, 0);
5762 gtk_widget_show(label);
5764 label = gtk_label_new("Waiting for refresh\n");
5765 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5766 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
5767 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5768 gtk_misc_set_alignment((GtkMisc *) label, 0.0, 0.0);
5769 gtk_box_pack_start(GTK_BOX(rbox), label, TRUE, TRUE, 0);
5770 g_hash_table_insert(pm->pht_Widgets, g_strdup("PerformanceSummary"), label);
5771 gtk_widget_show(label);
5773 frame = gtk_frame_new("<b><i>Software Information</i></b>");
5774 gtk_frame_set_label_align(GTK_FRAME(frame), 0.1, 0.8);
5775 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
5776 label = gtk_frame_get_label_widget(GTK_FRAME(frame));
5777 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5778 gtk_box_pack_end(GTK_BOX(tlbox), frame, TRUE, TRUE, 0);
5779 gtk_widget_show(frame);
5781 pbox = gtk_hbox_new(FALSE, 4);
5782 gtk_container_add(GTK_CONTAINER(frame), pbox);
5783 gtk_widget_show(pbox);
5784 lbox = gtk_vbox_new(FALSE, 0);
5785 gtk_box_pack_start(GTK_BOX(pbox), lbox, FALSE, FALSE, 0);
5786 gtk_widget_show(lbox);
5787 rbox = gtk_vbox_new(FALSE, 0);
5788 gtk_box_pack_end(GTK_BOX(pbox), rbox, TRUE, TRUE, 0);
5789 gtk_widget_show(rbox);
5791 label = gtk_label_new("APCUPSD version\n" "Monitored UPS name\n"
5792 "Cable Driver type\n" "Configuration mode\n" "Last started\n" "UPS State");
5793 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5794 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
5795 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5796 gtk_misc_set_alignment((GtkMisc *) label, 1.0, 0.5);
5797 gtk_box_pack_start(GTK_BOX(lbox), label, FALSE, FALSE, 0);
5798 gtk_widget_show(label);
5800 label = gtk_label_new("Waiting for refresh\n");
5801 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5802 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
5803 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5804 gtk_misc_set_alignment((GtkMisc *) label, 0.0, 0.0);
5805 gtk_box_pack_start(GTK_BOX(rbox), label, TRUE, TRUE, 0);
5806 g_hash_table_insert(pm->pht_Widgets, g_strdup("SoftwareInformation"), label);
5807 gtk_widget_show(label);
5809 frame = gtk_frame_new("<b><i>UPS Metrics</i></b>");
5810 gtk_frame_set_label_align(GTK_FRAME(frame), 0.1, 0.8);
5811 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
5812 label = gtk_frame_get_label_widget(GTK_FRAME(frame));
5813 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5814 gtk_box_pack_start(GTK_BOX(trbox), frame, TRUE, TRUE, 0);
5815 gtk_widget_show(frame);
5817 gbox = gtk_vbox_new(TRUE, 2);
5818 gtk_container_add(GTK_CONTAINER(frame), gbox);
5819 gtk_widget_show(gbox);
5821 gapc_util_barchart_create(pm, gbox, "HBar1", 10.8, "Waiting for refresh");
5822 gapc_util_barchart_create(pm, gbox, "HBar2", 40.8, "Waiting for refresh");
5823 gapc_util_barchart_create(pm, gbox, "HBar3", 0.8, "Waiting for refresh");
5824 gapc_util_barchart_create(pm, gbox, "HBar4", 40.8, "Waiting for refresh");
5825 gapc_util_barchart_create(pm, gbox, "HBar5", 10.8, "Waiting for refresh");
5827 frame = gtk_frame_new("<b><i>Product Information</i></b>");
5828 gtk_frame_set_label_align(GTK_FRAME(frame), 0.1, 0.8);
5829 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
5830 label = gtk_frame_get_label_widget(GTK_FRAME(frame));
5831 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5832 gtk_box_pack_end(GTK_BOX(trbox), frame, TRUE, TRUE, 0);
5833 gtk_widget_show(frame);
5835 pbox = gtk_hbox_new(FALSE, 4);
5836 gtk_container_add(GTK_CONTAINER(frame), pbox);
5837 gtk_widget_show(pbox);
5838 lbox = gtk_vbox_new(FALSE, 0);
5839 gtk_box_pack_start(GTK_BOX(pbox), lbox, FALSE, FALSE, 0);
5840 gtk_widget_show(lbox);
5841 rbox = gtk_vbox_new(FALSE, 0);
5842 gtk_box_pack_end(GTK_BOX(pbox), rbox, TRUE, TRUE, 0);
5843 gtk_widget_show(rbox);
5845 label = gtk_label_new("Device\n" "Serial\n" "Manf date\n" "Firmware\n"
5846 "Batt date\n" "Wattage");
5847 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5848 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
5849 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5850 gtk_misc_set_alignment((GtkMisc *) label, 1.0, 0.5);
5851 gtk_box_pack_start(GTK_BOX(lbox), label, FALSE, FALSE, 0);
5852 gtk_widget_show(label);
5854 label = gtk_label_new("Waiting for refresh\n");
5855 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5856 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
5857 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5858 gtk_misc_set_alignment((GtkMisc *) label, 0.0, 0.0);
5859 gtk_box_pack_start(GTK_BOX(rbox), label, TRUE, TRUE, 0);
5860 g_hash_table_insert(pm->pht_Widgets, g_strdup("ProductInformation"), label);
5861 gtk_widget_show(label);
5863 return i_page;
5867 * Events and Status Report Pages
5869 static gint gapc_monitor_text_report_page(PGAPC_MONITOR pm, GtkWidget * notebook,
5870 gchar * pchTitle, gchar * pchKey)
5872 PangoFontDescription *font_desc;
5873 GtkWidget *scrolled, *view, *label;
5874 gint i_page = 0;
5876 scrolled = gtk_scrolled_window_new(NULL, NULL);
5877 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
5878 GTK_SHADOW_ETCHED_IN);
5879 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
5880 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
5881 label = gtk_label_new(pchTitle);
5882 i_page = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
5883 gtk_widget_show(scrolled);
5885 view = gtk_text_view_new();
5886 gtk_container_add(GTK_CONTAINER(scrolled), view);
5887 gtk_widget_show(view);
5889 /* Change default font throughout the widget */
5890 font_desc = pango_font_description_from_string("Monospace 9");
5891 gtk_widget_modify_font(view, font_desc);
5892 pango_font_description_free(font_desc);
5894 gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
5895 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(view), 5);
5897 g_hash_table_insert(pm->pht_Widgets, g_strdup(pchKey), view);
5899 return i_page;
5902 static gint gapc_panel_glossary_page(PGAPC_CONFIG pcfg, GtkWidget * notebook)
5904 GtkWidget *scrolled, *label, *vbox;
5905 gint i_page = 0;
5906 gchar *ptext = GAPC_GLOSSARY;
5907 GdkColor color;
5909 gdk_color_parse("white", &color);
5911 vbox = gtk_vbox_new(FALSE, 0);
5912 label = gtk_label_new("Glossary");
5913 i_page = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
5914 gtk_widget_show(vbox);
5916 scrolled = gtk_scrolled_window_new(NULL, NULL);
5917 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
5918 GTK_SHADOW_ETCHED_IN);
5919 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
5920 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
5921 gtk_container_add(GTK_CONTAINER(vbox), scrolled);
5922 gtk_widget_show(GTK_WIDGET(scrolled));
5924 label = gtk_label_new(ptext);
5925 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5926 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_FILL);
5927 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5929 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), label);
5930 gtk_widget_show(label);
5932 gtk_widget_modify_bg(gtk_widget_get_parent(label), GTK_STATE_NORMAL, &color);
5934 return i_page;
5937 static gint gapc_panel_graph_property_page(PGAPC_CONFIG pcfg, GtkWidget * notebook)
5939 GtkWidget *s_frame, *w_frame, *label, *s_box, *w_box, *frame, *hbox, *pbox;
5940 GtkWidget *cb_linev, *cb_loadpct, *cb_timeleft, *cb_bcharge, *cb_battv;
5941 GtkWidget *cb_window, *cb_chart, *cb_text;
5942 GtkWidget *bbox, *b_undo;
5944 gint i_page = 0;
5946 frame = gtk_vbox_new(FALSE, 0);
5947 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
5948 label = gtk_label_new("Graph Properties");
5949 i_page = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
5950 gtk_widget_show(frame);
5953 * Prepare the top color choice area */
5954 hbox = gtk_hbox_new(FALSE, 2);
5955 gtk_container_add ( GTK_CONTAINER (frame), hbox );
5956 gtk_widget_show(hbox);
5959 * Prepare the bottom button/message area */
5960 bbox = gtk_hbox_new(FALSE, 0);
5961 gtk_box_pack_end ( GTK_BOX (frame), bbox, TRUE, TRUE, 2);
5962 gtk_widget_show(bbox);
5964 b_undo = gtk_button_new_from_stock (GTK_STOCK_UNDO);
5965 gtk_box_pack_start ( GTK_BOX (bbox), b_undo, FALSE, TRUE, 2);
5966 gtk_widget_show(b_undo);
5967 g_signal_connect (GTK_OBJECT(b_undo), "clicked",
5968 G_CALLBACK(cb_panel_property_color_reset), pcfg);
5970 label = gtk_label_new("These values will be used during the"
5971 " creation of a monitor. Disable and "
5972 "enable existing monitors to push values now.");
5973 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
5974 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
5975 gtk_box_pack_end ( GTK_BOX (bbox), label, TRUE, TRUE, 2);
5976 gtk_widget_show(label);
5979 * Prepare the top color choice area */
5980 s_frame = gtk_frame_new("Series Color");
5981 gtk_container_set_border_width(GTK_CONTAINER(s_frame), 4);
5982 gtk_frame_set_shadow_type(GTK_FRAME(s_frame), GTK_SHADOW_IN);
5983 gtk_box_pack_start(GTK_BOX(hbox), s_frame, TRUE, TRUE, 0);
5984 gtk_widget_show(s_frame);
5986 s_box = gtk_vbox_new(FALSE, 0);
5987 gtk_container_add ( GTK_CONTAINER (s_frame), s_box );
5988 gtk_widget_show(s_box);
5990 pbox = gtk_hbox_new(TRUE, 4);
5991 gtk_box_pack_start(GTK_BOX(s_box), pbox, FALSE, FALSE, 0);
5992 label = gtk_label_new("LINEV");
5993 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
5994 gtk_widget_show(label);
5997 cb_linev = gtk_color_button_new_with_color( &pcfg->color_linev);
5998 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_linev), "LINEV");
5999 gtk_box_pack_start(GTK_BOX(pbox), cb_linev, FALSE, FALSE, 0);
6000 gtk_widget_show(cb_linev);
6001 g_object_set_data (G_OBJECT(cb_linev), "gconf-client", pcfg->client );
6002 g_signal_connect ( GTK_OBJECT(cb_linev), "color-set",
6003 G_CALLBACK(cb_panel_property_color_change),
6004 GAPC_COLOR_LINEV_KEY);
6005 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-linev"), cb_linev);
6007 pbox = gtk_hbox_new(TRUE, 4);
6008 gtk_box_pack_start(GTK_BOX(s_box), pbox, FALSE, FALSE, 0);
6009 label = gtk_label_new("LOADPCT");
6010 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
6011 gtk_widget_show(label);
6013 cb_loadpct = gtk_color_button_new_with_color( &pcfg->color_loadpct);
6014 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_loadpct), "LOADPCT");
6015 gtk_box_pack_start(GTK_BOX(pbox), cb_loadpct, FALSE, FALSE, 0);
6016 gtk_widget_show(cb_loadpct);
6017 g_object_set_data (G_OBJECT(cb_loadpct), "gconf-client", pcfg->client );
6018 g_signal_connect ( GTK_OBJECT(cb_loadpct), "color-set",
6019 G_CALLBACK(cb_panel_property_color_change),
6020 GAPC_COLOR_LOADPCT_KEY);
6021 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-loadpct"), cb_loadpct);
6023 pbox = gtk_hbox_new(TRUE, 4);
6024 gtk_box_pack_start(GTK_BOX(s_box), pbox, FALSE, FALSE, 0);
6025 label = gtk_label_new("TIMELEFT");
6026 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
6027 gtk_widget_show(label);
6029 cb_timeleft = gtk_color_button_new_with_color( &pcfg->color_timeleft);
6030 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_timeleft), "TIMELEFT");
6031 gtk_box_pack_start(GTK_BOX(pbox), cb_timeleft, FALSE, FALSE, 0);
6032 gtk_widget_show(cb_timeleft);
6033 g_object_set_data (G_OBJECT(cb_timeleft), "gconf-client", pcfg->client );
6034 g_signal_connect ( GTK_OBJECT(cb_timeleft), "color-set",
6035 G_CALLBACK(cb_panel_property_color_change),
6036 GAPC_COLOR_TIMELEFT_KEY);
6037 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-timeleft"), cb_timeleft);
6039 pbox = gtk_hbox_new(TRUE, 4);
6040 gtk_box_pack_start(GTK_BOX(s_box), pbox, FALSE, FALSE, 0);
6041 label = gtk_label_new("BCHARGE");
6042 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
6043 gtk_widget_show(label);
6045 cb_bcharge = gtk_color_button_new_with_color( &pcfg->color_bcharge);
6046 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_bcharge), "BCHARGE");
6047 gtk_box_pack_start(GTK_BOX(pbox), cb_bcharge, FALSE, FALSE, 0);
6048 gtk_widget_show(cb_bcharge);
6049 g_object_set_data (G_OBJECT(cb_bcharge), "gconf-client", pcfg->client );
6050 g_signal_connect ( GTK_OBJECT(cb_bcharge), "color-set",
6051 G_CALLBACK(cb_panel_property_color_change),
6052 GAPC_COLOR_BCHARGE_KEY);
6053 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-bcharge"), cb_bcharge);
6055 pbox = gtk_hbox_new(TRUE, 4);
6056 gtk_box_pack_start(GTK_BOX(s_box), pbox, FALSE, FALSE, 0);
6057 label = gtk_label_new("BATTV");
6058 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
6059 gtk_widget_show(label);
6061 cb_battv = gtk_color_button_new_with_color( &pcfg->color_battv);
6062 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_battv), "BATTV");
6063 gtk_box_pack_start(GTK_BOX(pbox), cb_battv, FALSE, FALSE, 0);
6064 gtk_widget_show(cb_battv);
6065 g_object_set_data (G_OBJECT(cb_battv), "gconf-client", pcfg->client );
6066 g_signal_connect ( GTK_OBJECT(cb_battv), "color-set",
6067 G_CALLBACK(cb_panel_property_color_change),
6068 GAPC_COLOR_BATTV_KEY);
6069 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-battv"), cb_battv);
6071 w_frame = gtk_frame_new("Window Colors");
6072 gtk_container_set_border_width(GTK_CONTAINER(w_frame), 4);
6073 gtk_frame_set_shadow_type(GTK_FRAME(w_frame), GTK_SHADOW_IN);
6074 gtk_box_pack_start(GTK_BOX(hbox), w_frame, TRUE, TRUE, 0);
6075 gtk_widget_show(w_frame);
6077 w_box = gtk_vbox_new(FALSE, 0);
6078 gtk_container_add ( GTK_CONTAINER (w_frame), w_box );
6079 gtk_widget_show(w_box);
6081 pbox = gtk_hbox_new(TRUE, 4);
6082 gtk_box_pack_start(GTK_BOX(w_box), pbox, FALSE, FALSE, 0);
6083 label = gtk_label_new("Window Background");
6084 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
6085 gtk_widget_show(label);
6087 cb_window = gtk_color_button_new_with_color( &pcfg->color_window);
6088 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_window), "Window Background");
6089 gtk_box_pack_start(GTK_BOX(pbox), cb_window, FALSE, FALSE, 0);
6090 gtk_widget_show(cb_window);
6091 g_object_set_data (G_OBJECT(cb_window), "gconf-client", pcfg->client );
6092 g_signal_connect ( GTK_OBJECT(cb_window), "color-set",
6093 G_CALLBACK(cb_panel_property_color_change),
6094 GAPC_COLOR_WINDOW_KEY);
6095 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-window"), cb_window);
6097 pbox = gtk_hbox_new(TRUE, 4);
6098 gtk_box_pack_start(GTK_BOX(w_box), pbox, FALSE, FALSE, 0);
6099 label = gtk_label_new("Chart Background");
6100 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
6101 gtk_widget_show(label);
6103 cb_chart = gtk_color_button_new_with_color( &pcfg->color_chart);
6104 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_chart), "Chart Background");
6105 gtk_box_pack_start(GTK_BOX(pbox), cb_chart, FALSE, FALSE, 0);
6106 gtk_widget_show(cb_chart);
6107 g_object_set_data (G_OBJECT(cb_chart), "gconf-client", pcfg->client );
6108 g_signal_connect ( GTK_OBJECT(cb_chart), "color-set",
6109 G_CALLBACK(cb_panel_property_color_change),
6110 GAPC_COLOR_CHART_KEY);
6111 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-chart"), cb_chart);
6113 pbox = gtk_hbox_new(TRUE, 4);
6114 gtk_box_pack_start(GTK_BOX(w_box), pbox, FALSE, FALSE, 0);
6115 label = gtk_label_new("Title Texts");
6116 gtk_box_pack_start(GTK_BOX(pbox), label, FALSE, FALSE, 0);
6117 gtk_widget_show(label);
6119 cb_text = gtk_color_button_new_with_color( &pcfg->color_title);
6120 gtk_color_button_set_title (GTK_COLOR_BUTTON(cb_text), "Title Texts");
6121 gtk_box_pack_start(GTK_BOX(pbox), cb_text, FALSE, FALSE, 0);
6122 gtk_widget_show(cb_text);
6123 g_object_set_data (G_OBJECT(cb_text), "gconf-client", pcfg->client );
6124 g_signal_connect ( GTK_OBJECT(cb_text), "color-set",
6125 G_CALLBACK(cb_panel_property_color_change),
6126 GAPC_COLOR_TITLE_KEY);
6127 g_hash_table_insert(pcfg->pht_Widgets, g_strdup("color-title"), cb_text);
6129 return i_page;
6134 * Creates monitor interface with the normal panels
6136 static GtkWidget *gapc_monitor_interface_create(PGAPC_CONFIG pcfg, gint i_monitor,
6137 GtkTreeIter * iter)
6139 GtkWindow *window = NULL;
6140 GdkPixbuf *pixbuf = NULL;
6141 GtkWidget *sbar = NULL, *notebook = NULL, *menu = NULL, *menu_item = NULL;
6142 GtkWidget *label = NULL, *button = NULL;
6143 GtkWidget *bbox = NULL, *lbox = NULL, *nbox = NULL, *box = NULL;
6144 PGAPC_MONITOR pm = NULL;
6145 gint z_monitor = 0;
6147 g_return_val_if_fail(pcfg != NULL, NULL);
6149 pm = g_new0(GAPC_MONITOR, 1);
6150 g_return_val_if_fail(pm != NULL, NULL);
6151 pm->cb_id = CB_MONITOR_ID;
6152 pm->cb_monitor_num = i_monitor;
6153 pm->gp = (gpointer) pcfg;
6154 pm->phs.gp = (gpointer) pm;
6155 pm->phs.cb_id = CB_HISTORY_ID;
6156 pm->phs.sq[0].cb_id = CB_SUMM_ID;
6157 pm->phs.sq[1].cb_id = CB_SUMM_ID;
6158 pm->phs.sq[2].cb_id = CB_SUMM_ID;
6159 pm->phs.sq[3].cb_id = CB_SUMM_ID;
6160 pm->phs.sq[4].cb_id = CB_SUMM_ID;
6162 pm->my_icons = pcfg->my_icons;
6163 pm->pht_Status = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
6164 pm->pht_Widgets = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
6165 pm->phs.b_startup = TRUE;
6167 pm->cb_enabled = TRUE;
6168 pm->b_visible = FALSE;
6169 pm->b_run = TRUE;
6170 pm->i_icon_index = GAPC_ICON_DEFAULT;
6171 pm->i_old_icon_index = GAPC_ICON_ONLINE;
6172 pm->tray_icon = NULL;
6173 pm->tray_image = NULL;
6174 if (pm->pch_host != NULL) {
6175 g_free(pm->pch_host);
6177 gtk_tree_model_get(GTK_TREE_MODEL(pcfg->prefs_model), iter,
6178 GAPC_PREFS_SYSTRAY, &(pm->cb_use_systray),
6179 GAPC_PREFS_PORT, &(pm->i_port),
6180 GAPC_PREFS_WATT, &(pm->i_watt),
6181 GAPC_PREFS_GRAPH, &(pm->d_graph),
6182 GAPC_PREFS_HOST, &(pm->pch_host),
6183 GAPC_PREFS_REFRESH, &(pm->d_refresh),
6184 GAPC_PREFS_MONITOR, &z_monitor, -1);
6186 pixbuf = pm->my_icons[GAPC_ICON_DEFAULT];
6187 pm->tooltips = gtk_tooltips_new();
6188 g_object_ref (pm->tooltips);
6189 gtk_object_sink (GTK_OBJECT(pm->tooltips));
6190 pm->gm_update = g_mutex_new();
6191 pm->client = pcfg->client;
6192 pm->i_old_icon_index = GAPC_ICON_DEFAULT;
6193 pm->monitor_model = pcfg->monitor_model;
6194 g_snprintf(pm->ch_title_info, GAPC_MAX_TEXT, "%s {%s}", GAPC_WINDOW_TITLE,
6195 pm->pch_host);
6197 if (pm->d_refresh < GAPC_REFRESH_MIN_INCREMENT) {
6198 pm->d_refresh = GAPC_REFRESH_DEFAULT;
6200 if (pm->d_graph < GAPC_REFRESH_MIN_INCREMENT) {
6201 pm->d_graph = GAPC_LINEGRAPH_REFRESH_FACTOR;
6205 * Start the central network thread */
6206 pm->q_network = g_async_queue_new();
6207 g_return_val_if_fail(pm->q_network != NULL, NULL);
6209 pm->b_thread_stop = FALSE;
6210 pm->tid_thread_qwork =
6211 g_thread_create((GThreadFunc) gapc_net_thread_qwork, pm, TRUE, NULL);
6214 * Create the top level window for the notebook to be packed into.*/
6215 window = g_object_new(GTK_TYPE_WINDOW, "border-width", 0, "destroy-with-parent",
6216 TRUE, "icon", pixbuf, "resizable", TRUE, "title",
6217 pm->ch_title_info, "type", GTK_WINDOW_TOPLEVEL, "type-hint",
6218 GDK_WINDOW_TYPE_HINT_NORMAL, "window-position", GTK_WIN_POS_NONE, NULL);
6220 pm->window = GTK_WIDGET(window);
6221 g_signal_connect(window, "destroy", G_CALLBACK(cb_monitor_interface_destroy), pm);
6222 g_signal_connect(window, "delete-event",
6223 G_CALLBACK(cb_monitor_interface_delete_event), pm);
6224 g_signal_connect(window, "show", G_CALLBACK(cb_monitor_interface_show), pm);
6225 g_signal_connect(window, "hide", G_CALLBACK(cb_monitor_interface_hide), pm);
6226 g_signal_connect(window, "window-state-event",
6227 G_CALLBACK(cb_util_manage_iconify_event), pm);
6229 g_snprintf(pm->ch_title_info, GAPC_MAX_TEXT, "%s\n<b><i>{%s}</i></b>",
6230 GAPC_WINDOW_TITLE, pm->pch_host);
6232 lbox = gtk_vbox_new(FALSE, 2);
6233 gtk_container_add(GTK_CONTAINER(window), lbox);
6234 gtk_widget_show(lbox);
6236 /* */
6238 /* Notebook Box */
6239 bbox = gtk_vbox_new(FALSE, 0);
6240 gtk_container_set_border_width(GTK_CONTAINER(bbox), 6);
6241 gtk_box_pack_start(GTK_BOX(lbox), bbox, TRUE, TRUE, 2);
6242 gtk_widget_show(bbox);
6243 nbox = gtk_hbox_new(TRUE, 0);
6244 gtk_box_pack_start(GTK_BOX(bbox), nbox, TRUE, TRUE, 0);
6245 gtk_widget_show(nbox);
6247 /* create the status bar */
6248 sbar = gtk_statusbar_new();
6249 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(sbar), FALSE);
6250 g_hash_table_insert(pm->pht_Widgets, g_strdup("StatusBar"), sbar);
6251 gtk_box_pack_end(GTK_BOX(lbox), sbar, FALSE, TRUE, 0);
6252 gtk_widget_show(sbar);
6253 pm->i_info_context =
6254 gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar), "Informational");
6256 /* buttons Box */
6257 bbox = gtk_hbox_new(FALSE, 0);
6258 gtk_container_set_border_width(GTK_CONTAINER(bbox), 0);
6259 gtk_box_pack_end(GTK_BOX(lbox), bbox, FALSE, FALSE, 0);
6260 gtk_widget_show(bbox);
6261 box = gtk_hbutton_box_new();
6262 gtk_hbutton_box_set_layout_default(GTK_BUTTONBOX_SPREAD);
6263 gtk_container_set_border_width(GTK_CONTAINER(box), 4);
6264 gtk_box_pack_end(GTK_BOX(bbox), box, TRUE, TRUE, 0);
6265 gtk_widget_show(box);
6267 /* Create the top-level notebook */
6268 pm->notebook = notebook = gtk_notebook_new();
6269 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
6270 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
6271 gtk_notebook_set_homogeneous_tabs(GTK_NOTEBOOK(notebook), FALSE);
6272 gtk_box_pack_start(GTK_BOX(nbox), notebook, TRUE, TRUE, 0);
6273 gtk_widget_show(notebook);
6275 /* Create the main pages */
6276 gapc_monitor_history_page(pm, notebook);
6277 gapc_monitor_information_page(pm, notebook);
6278 gapc_monitor_text_report_page(pm, notebook, "Power Events", "EventsPage");
6279 gapc_monitor_text_report_page(pm, notebook, "Full UPS Status", "StatusPage");
6281 /* Create the main pages */
6283 label = gtk_label_new(pm->ch_title_info);
6284 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
6285 gtk_label_set_line_wrap(GTK_LABEL(label), FALSE);
6286 gtk_box_pack_start(GTK_BOX(bbox), label, TRUE, TRUE, 0);
6287 gtk_widget_show(label);
6288 g_hash_table_insert(pm->pht_Widgets, g_strdup("TitleStatus"), label);
6290 /* refresh Control button */
6291 button = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
6292 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
6293 g_signal_connect(button, "clicked",
6294 G_CALLBACK(cb_monitor_interface_button_refresh), pm);
6295 gtk_box_pack_end(GTK_BOX(box), button, TRUE, TRUE, 0);
6296 gtk_widget_show(button);
6297 gtk_widget_grab_default(button);
6300 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
6301 g_signal_connect(button, "clicked",
6302 G_CALLBACK(cb_monitor_interface_button_close), pm);
6303 gtk_box_pack_end(GTK_BOX(box), button, TRUE, TRUE, 0);
6304 gtk_widget_show(button);
6306 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
6308 gapc_panel_monitor_model_rec_add(pcfg, pm);
6310 gapc_panel_systray_icon_create(pm);
6312 g_async_queue_push(pm->q_network, (gpointer) pm);
6314 pm->tid_automatic_refresh =
6315 g_timeout_add((guint) (pm->d_refresh * GAPC_REFRESH_FACTOR_1K),
6316 (GSourceFunc) cb_monitor_automatic_refresh, pm);
6318 pm->menu = menu = gtk_menu_new();
6319 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_JUMP_TO, NULL);
6320 g_signal_connect(G_OBJECT(menu_item), "activate",
6321 G_CALLBACK(cb_util_popup_menu_response_jumpto), pm);
6322 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
6323 gtk_widget_show(menu_item);
6324 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
6325 g_signal_connect(G_OBJECT(menu_item), "activate",
6326 G_CALLBACK(cb_util_popup_menu_response_exit), pm);
6327 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
6328 gtk_widget_show(menu_item);
6329 gtk_widget_show(menu);
6331 sbar = g_hash_table_lookup (pcfg->pht_Widgets, "StatusBar");
6332 if (sbar) {
6333 gchar *pch = NULL;
6335 gtk_statusbar_pop(GTK_STATUSBAR(sbar), pcfg->i_info_context);
6336 pch = g_strdup_printf
6337 ("Monitor for %s Created!...", pm->pch_host);
6338 gtk_statusbar_push(GTK_STATUSBAR(sbar), pcfg->i_info_context, pch);
6339 g_free(pch);
6342 return GTK_WIDGET(window);
6346 * Creates monitor interface with the normal panels
6348 static void gapc_monitor_interface_destroy(PGAPC_CONFIG pcfg, gint i_monitor)
6350 GtkTreeIter iter;
6351 PGAPC_MONITOR pm = NULL;
6353 g_return_if_fail(pcfg != NULL);
6355 if (gapc_util_treeview_get_iter_from_monitor(pcfg->monitor_model, &iter,
6356 i_monitor)) {
6357 gtk_tree_model_get(pcfg->monitor_model, &iter, GAPC_MON_POINTER, &pm, -1);
6360 if ((pm == NULL) || (pm->window == NULL)) {
6361 return;
6364 if (!pm->cb_enabled) {
6365 return;
6368 pm->b_run = FALSE;
6370 gtk_list_store_remove(GTK_LIST_STORE(pcfg->monitor_model), &iter);
6372 if (pm->cb_use_systray) {
6373 gapc_panel_systray_icon_remove(pm);
6376 if (pm->menu != NULL) {
6377 gtk_widget_destroy(pm->menu);
6380 if (pm->window != NULL) {
6381 gtk_widget_destroy(pm->window);
6384 return;
6388 * Main entry point
6390 extern int main(int argc, char *argv[])
6392 PGAPC_CONFIG pcfg = NULL;
6393 GtkWidget *window = NULL;
6396 * Initialize GLib thread support, and GTK
6398 g_type_init();
6399 g_thread_init(NULL);
6401 gdk_threads_init();
6403 gtk_init(&argc, &argv);
6405 pcfg = g_new0(GAPC_CONFIG, 1);
6406 pcfg->cb_id = CB_CONTROL_ID;
6409 * Get the instance number for this execution */
6410 if (gapc_main_interface_parse_args(argc, argv, pcfg)) {
6411 return 1; /* exit if user only wanted help */
6414 gapc_util_load_icons(pcfg);
6416 gapc_panel_gconf_init(pcfg);
6418 window = gapc_main_interface_create(pcfg);
6419 if (!pcfg->b_use_systray) {
6420 pcfg->b_visible = TRUE;
6421 g_object_set(pcfg->window,
6422 "skip-pager-hint", FALSE,
6423 "skip-taskbar-hint", FALSE,
6424 NULL);
6425 gtk_window_present(GTK_WINDOW(pcfg->window));
6428 gapc_panel_gconf_watch(pcfg);
6431 * enter the GTK main loop
6433 gdk_threads_enter();
6434 gtk_main();
6435 gdk_flush();
6436 gdk_threads_leave();
6438 return (0);