1 /* GKrellM
2 |  Copyright (C) 1999-2019 Bill Wilson
3 |
4 |  Author:  Bill Wilson    billw@gkrellm.net
5 |  Latest versions might be found at:  http://gkrellm.net
6 |
7 |
8 |  GKrellM is free software: you can redistribute it and/or modify it
9 |  under the terms of the GNU General Public License as published by
10 |  the Free Software Foundation, either version 3 of the License, or
11 |  (at your option) any later version.
12 |
13 |  GKrellM is distributed in the hope that it will be useful, but WITHOUT
14 |  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 |  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 |  License for more details.
17 |
18 |  You should have received a copy of the GNU General Public License
19 |  along with this program. If not, see http://www.gnu.org/licenses/
20 |
21 |
22 |  Additional permission under GNU GPL version 3 section 7
23 |
24 |  If you modify this program, or any covered work, by linking or
25 |  combining it with the OpenSSL project's OpenSSL library (or a
26 |  modified version of that library), containing parts covered by
27 |  the terms of the OpenSSL or SSLeay licenses, you are granted
28 |  additional permission to convey the resulting work.
29 |  Corresponding Source for a non-source form of such a combination
30 |  shall include the source code for the parts of OpenSSL used as well
31 |  as that of the covered work.
32 */
33 
34 #include "gkrellm.h"
35 #include "gkrellm-private.h"
36 
37 
38 GtkWidget		*config_window;
39 
40 
41 void
gkrellm_message_dialog(gchar * title,gchar * message)42 gkrellm_message_dialog(gchar *title, gchar *message)
43 	{
44 	GtkWidget	*top_win;
45 	GtkWidget	*dialog;
46 	GtkWidget	*scrolled;
47 	GtkWidget	*vbox, *vbox1;
48 	GtkWidget	*label;
49 	gchar		*s;
50 	gint		nlines;
51 
52 	if (!message)
53 		return;
54 	top_win = gkrellm_get_top_window();
55 	dialog = gtk_dialog_new_with_buttons(title ? title : "GKrellM",
56 				GTK_WINDOW(top_win),
57 				GTK_DIALOG_DESTROY_WITH_PARENT,
58 				GTK_STOCK_OK, GTK_RESPONSE_NONE,
59 				NULL);
60 	g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
61 				G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(dialog));
62 	gtk_window_set_wmclass(GTK_WINDOW(dialog),
63 				"Gkrellm_dialog", "Gkrellm");
64 
65 	vbox = gtk_vbox_new(FALSE, 0);
66 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
67 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
68 				FALSE, FALSE, 0);
69 
70 	label = gtk_label_new(message);
71 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
72 
73 	for (nlines = 0, s = message; *s; ++s)
74 		if (*s == '\n')
75 			++nlines;
76 	if (nlines > 20)
77 		{
78 		vbox1 = gkrellm_gtk_scrolled_vbox(vbox, &scrolled,
79 					GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
80 		gtk_widget_set_size_request(scrolled, -1, 300);
81 		gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, FALSE, 0);
82 		}
83 	else
84 		gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
85 
86 	gtk_widget_show_all(dialog);
87 	}
88 
89 void
gkrellm_config_message_dialog(gchar * title,gchar * message)90 gkrellm_config_message_dialog(gchar *title, gchar *message)
91 	{
92 	GtkWidget	*dialog;
93 	GtkWidget	*vbox;
94 	GtkWidget	*label;
95 
96 	if (!message || !config_window)
97 		return;
98 	dialog = gtk_dialog_new_with_buttons(title ? title : "GKrellM",
99 				GTK_WINDOW(config_window),
100 				GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
101 				GTK_STOCK_OK, GTK_RESPONSE_OK,
102 				NULL);
103 	gtk_window_set_wmclass(GTK_WINDOW(dialog),
104 				"Gkrellm_dialog", "Gkrellm");
105 	vbox = gtk_vbox_new(FALSE, 0);
106 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
107 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
108 				FALSE, FALSE, 0);
109 
110 	label = gtk_label_new(message);
111 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
112 
113 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
114 
115 	gtk_widget_show_all(vbox);
116 	gtk_dialog_run(GTK_DIALOG(dialog));
117 	gtk_widget_destroy(dialog);
118 	}
119 
120 #undef gkrellm_message_window
121 #undef gkrellm_config_message_window
122 
123 void
gkrellm_message_window(gchar * title,gchar * message,GtkWidget * widget)124 gkrellm_message_window(gchar *title, gchar *message, GtkWidget *widget)
125 	{
126 	gkrellm_message_dialog(title, message);
127 	}
128 
129 void
gkrellm_config_message_window(gchar * title,gchar * message,GtkWidget * widget)130 gkrellm_config_message_window(gchar *title, gchar *message, GtkWidget *widget)
131 	{
132 	gkrellm_config_message_dialog(title, message);
133 	}
134 
135 static void
text_view_append(GtkWidget * view,gchar * s)136 text_view_append(GtkWidget *view, gchar *s)
137 	{
138 	GtkTextIter		iter;
139 	GtkTextBuffer	*buffer;
140 
141 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
142 	gtk_text_buffer_get_end_iter(buffer, &iter);
143 //	gtk_text_iter_forward_to_end(&iter);
144 
145 	if (strncmp(s, "<b>", 3) == 0)
146 		gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
147 					s + 3, -1, "bold", NULL);
148 	else if (strncmp(s, "<i>", 3) == 0)
149 		gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
150 					s + 3, -1, "italic", NULL);
151 	else if (strncmp(s, "<h>", 3) == 0)
152 		gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
153 					s + 3, -1, "heading", NULL);
154 	else if (strncmp(s, "<c>", 3) == 0)
155 		gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
156 					s + 3, -1, "center", NULL);
157 	else if (strncmp(s, "<ul>", 4) == 0)
158 		gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
159 					s + 4, -1, "underline", NULL);
160 	else
161 		gtk_text_buffer_insert(buffer, &iter, s, -1);
162 	}
163 
164 void
gkrellm_gtk_text_view_append(GtkWidget * view,gchar * string)165 gkrellm_gtk_text_view_append(GtkWidget *view, gchar *string)
166 	{
167 	static gchar	*tag;
168 	gchar			*s;
169 
170 	s = string;
171 	if (   *s == '<'
172 		&& (   (*(s + 2) == '>' && !*(s + 3))
173 			|| (*(s + 3) == '>' && !*(s + 4))
174 		   )
175 	   )
176 		{
177 		tag = g_strdup(s);
178 		return;
179 		}
180 	if (tag)
181 		{
182 		s = g_strconcat(tag, string, NULL);
183 		text_view_append(view, s);
184 		g_free(s);
185 		g_free(tag);
186 		tag = NULL;
187 		}
188 	else
189 		text_view_append(view, string);
190 	}
191 
192 void
gkrellm_gtk_text_view_append_strings(GtkWidget * view,gchar ** string,gint n_strings)193 gkrellm_gtk_text_view_append_strings(GtkWidget *view, gchar **string,
194 			gint n_strings)
195 	{
196 	gchar	*tag = NULL;
197 	gchar	*s, *t;
198 	gint	i;
199 
200 	for (i = 0; i < n_strings; ++i)
201 		{
202 		s = string[i];
203 		if (   *s == '<'
204 			&& (   (*(s + 2) == '>' && !*(s + 3))
205 				|| (*(s + 3) == '>' && !*(s + 4))
206 			   )
207 		   )
208 			{
209 			tag = g_strdup(s);
210 			continue;
211 			}
212 #if defined(ENABLE_NLS)
213 		s = gettext(string[i]);
214 #else
215 		s = string[i];
216 #endif
217 		if (tag)
218 			{
219 			t = g_strconcat(tag, s, NULL);
220 			text_view_append(view, t);
221 			g_free(t);
222 			g_free(tag);
223 			tag = NULL;
224 			}
225 		else
226 			text_view_append(view, s);
227 		}
228 	}
229 
230 GtkWidget *
gkrellm_gtk_scrolled_text_view(GtkWidget * box,GtkWidget ** scr,GtkPolicyType h_policy,GtkPolicyType v_policy)231 gkrellm_gtk_scrolled_text_view(GtkWidget *box, GtkWidget **scr,
232 		GtkPolicyType h_policy, GtkPolicyType v_policy)
233 	{
234 	GtkWidget	*scrolled,
235 				*view;
236 	GtkTextBuffer *buffer;
237 
238 	scrolled = gtk_scrolled_window_new(NULL, NULL);
239 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
240 			h_policy, v_policy);
241 	gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0);
242 
243 	view = gtk_text_view_new();
244 	gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
245 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
246 	gtk_container_add(GTK_CONTAINER(scrolled), view);
247 	gtk_text_buffer_create_tag(buffer, "heading",
248 			"weight", PANGO_WEIGHT_BOLD,
249 			"size", 14 * PANGO_SCALE, NULL);
250 	gtk_text_buffer_create_tag(buffer, "italic",
251 			"style", PANGO_STYLE_ITALIC, NULL);
252 	gtk_text_buffer_create_tag (buffer, "bold",
253 			"weight", PANGO_WEIGHT_BOLD, NULL);
254 	gtk_text_buffer_create_tag (buffer, "center",
255 			"justification", GTK_JUSTIFY_CENTER, NULL);
256 	gtk_text_buffer_create_tag (buffer, "underline",
257 			"underline", PANGO_UNDERLINE_SINGLE, NULL);
258 	if (scr)
259 		*scr = scrolled;
260 	return view;
261 	}
262 
263 GtkTreeSelection *
gkrellm_gtk_scrolled_selection(GtkTreeView * treeview,GtkWidget * box,GtkSelectionMode s_mode,GtkPolicyType h_policy,GtkPolicyType v_policy,void (* func_cb)(),gpointer data)264 gkrellm_gtk_scrolled_selection(GtkTreeView *treeview, GtkWidget *box,
265 			GtkSelectionMode s_mode,
266 			GtkPolicyType h_policy, GtkPolicyType v_policy,
267 			void (*func_cb)(), gpointer data)
268 	{
269 	GtkTreeSelection	*selection;
270 	GtkWidget			*scrolled;
271 
272 	if (!box || !treeview)
273 		return NULL;
274 
275 	scrolled = gtk_scrolled_window_new(NULL, NULL);
276 	gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0);
277 	gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
278 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
279 				h_policy, v_policy);
280 	selection = gtk_tree_view_get_selection(treeview);
281 	gtk_tree_selection_set_mode(selection, s_mode);
282 	if (func_cb)
283 		g_signal_connect(G_OBJECT(selection), "changed",
284 					G_CALLBACK(func_cb), data);
285 	return selection;
286 	}
287 
288 void
gkrellm_launch_button_cb(GkrellmDecalbutton * button)289 gkrellm_launch_button_cb(GkrellmDecalbutton *button)
290 	{
291 	GkrellmLauncher    *launch;
292 
293 	launch = (GkrellmLauncher *) button->data;
294 	g_spawn_command_line_async(launch->command, NULL /* GError */);
295 	}
296 
297 void
gkrellm_remove_launcher(GkrellmLauncher * launch)298 gkrellm_remove_launcher(GkrellmLauncher *launch)
299 	{
300 	if (launch->button)
301 		gkrellm_destroy_button(launch->button);
302 	launch->button = NULL;
303 	}
304 
305 void
gkrellm_configure_tooltip(GkrellmPanel * p,GkrellmLauncher * launch)306 gkrellm_configure_tooltip(GkrellmPanel *p, GkrellmLauncher *launch)
307 	{
308 	launch->widget = p->drawing_area;
309 	if (*launch->tooltip_comment && *launch->command)
310         {
311             gtk_widget_set_tooltip_text(p->drawing_area,
312                                         launch->tooltip_comment);
313         }
314 	else
315             gtk_widget_set_tooltip_text(p->drawing_area,
316                                         NULL);
317 	}
318 
319 void
gkrellm_apply_launcher(GtkWidget ** launch_entry,GtkWidget ** tooltip_entry,GkrellmPanel * p,GkrellmLauncher * launch,void (* func)())320 gkrellm_apply_launcher(GtkWidget **launch_entry, GtkWidget **tooltip_entry,
321 			GkrellmPanel *p, GkrellmLauncher *launch, void (*func)())
322 	{
323 	gchar	*command, *tip_comment;
324 
325 	if (!launch_entry || !launch || !p)
326 		return;
327 	command = gkrellm_gtk_entry_get_text(launch_entry);
328 	tip_comment = tooltip_entry ?
329 						gkrellm_gtk_entry_get_text(tooltip_entry) : "";
330 	if (   launch->command && !strcmp(command, launch->command)
331 		&& launch->tooltip_comment
332 		&& !strcmp(tip_comment, launch->tooltip_comment)
333 	   )
334 		return;
335 	if (*command)
336 		{
337 		if (!launch->button)
338 			{
339 			if (launch->type == METER_LAUNCHER)
340 				launch->button = gkrellm_put_label_in_meter_button(p, func,
341 							launch, launch->pad);
342 			else if (launch->type == PANEL_LAUNCHER)
343 				launch->button = gkrellm_put_label_in_panel_button(p, func,
344 							launch, launch->pad);
345 			else if (launch->type == DECAL_LAUNCHER)
346 				launch->button = gkrellm_put_decal_in_meter_button(p,
347 							launch->decal,
348 							gkrellm_launch_button_cb, launch, &launch->margin);
349 			}
350 		gkrellm_dup_string(&launch->command, command);
351 		}
352 	else
353 		{
354 		if (launch->button)
355 			gkrellm_destroy_button(launch->button);
356 		launch->button = NULL;
357 		launch->pipe = NULL;		/* Close?? */
358 		gkrellm_dup_string(&launch->command, "");
359 		}
360 	gkrellm_dup_string(&launch->tooltip_comment, tip_comment);
361 	gkrellm_configure_tooltip(p, launch);
362 	}
363 
364 GtkWidget *
gkrellm_gtk_launcher_table_new(GtkWidget * vbox,gint n_launchers)365 gkrellm_gtk_launcher_table_new(GtkWidget *vbox, gint n_launchers)
366 	{
367 	GtkWidget	*table;
368 
369 	table = gtk_table_new(2 * n_launchers, 2, FALSE /*non-homogeneous*/);
370 	gtk_table_set_col_spacings(GTK_TABLE(table), 2);
371 	gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 2);
372 	return table;
373 	}
374 
375 void
gkrellm_gtk_config_launcher(GtkWidget * table,gint n,GtkWidget ** launch_entry,GtkWidget ** tooltip_entry,gchar * desc,GkrellmLauncher * launch)376 gkrellm_gtk_config_launcher(GtkWidget *table, gint n, GtkWidget **launch_entry,
377 			GtkWidget **tooltip_entry, gchar *desc, GkrellmLauncher *launch)
378 	{
379 	GtkWidget	*label, *hbox;
380 	gchar		buf[64];
381 	gint		row;
382 
383 	if (!table || !launch_entry)
384 		return;
385 	row = (tooltip_entry ? 2 : 1) * n;
386 	hbox = gtk_hbox_new(FALSE, 0);
387     /* Attach left right top bottom */
388     gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, row, row + 1,
389 				GTK_FILL, GTK_SHRINK, 0, 0);
390 
391 	snprintf(buf, sizeof(buf), _("%s command"), desc);
392     label = gtk_label_new(buf);
393 	gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
394 	gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 4);
395 
396 	*launch_entry = gtk_entry_new();
397 	gtk_entry_set_max_length(GTK_ENTRY(*launch_entry), 255);
398     gtk_table_attach_defaults(GTK_TABLE(table), *launch_entry,
399                 1, 2, row, row + 1);
400 	gtk_entry_set_text(GTK_ENTRY(*launch_entry),
401 					(launch && launch->command) ? launch->command : "");
402 
403 	if (tooltip_entry)
404 		{
405 		hbox = gtk_hbox_new(FALSE, 0);
406 	    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, row + 1, row + 2,
407 					GTK_FILL, GTK_SHRINK, 0, 0);
408 
409 	    label = gtk_label_new(_("comment"));
410 		gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
411 		gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 4);
412 		*tooltip_entry = gtk_entry_new();
413 		gtk_entry_set_max_length(GTK_ENTRY(*tooltip_entry), 255);
414 	    gtk_table_attach_defaults(GTK_TABLE(table), *tooltip_entry,
415 	                1, 2, row + 1, row + 2);
416 		gtk_entry_set_text(GTK_ENTRY(*tooltip_entry),
417 					(launch && launch->tooltip_comment)
418 					? launch->tooltip_comment : "");
419 		}
420 	}
421 
422   /* FIXME: this guy is called on panels at create events
423   |  when this situation has occurred:  the GKrellM rebuild has destroyed
424   |  the decal button list.  But existing launchers have not had their
425   |  button pointer set to NULL!  This could cause a problem with
426   |  code that tries to check for button pointers in the create routines.
427   */
428 void
gkrellm_setup_launcher(GkrellmPanel * p,GkrellmLauncher * launch,gint type,gint pad)429 gkrellm_setup_launcher(GkrellmPanel *p, GkrellmLauncher *launch,
430 			gint type, gint pad)
431 	{
432 	if (!launch)
433 		return;
434 	if (!launch->command)
435 		launch->command = g_strdup("");
436 	if (!launch->tooltip_comment)
437 		launch->tooltip_comment = g_strdup("");
438 	launch->type = type;
439 	launch->pad = pad;
440 	if (p)
441 		{
442 		gkrellm_configure_tooltip(p, launch);
443 		if (*(launch->command))
444 			launch->button = gkrellm_put_label_in_meter_button(p,
445 					gkrellm_launch_button_cb, launch, launch->pad);
446 		else
447 			launch->button = NULL;	/* In case dangling pointer, see above */
448 		}
449 	}
450 
451 void
gkrellm_setup_decal_launcher(GkrellmPanel * p,GkrellmLauncher * launch,GkrellmDecal * d)452 gkrellm_setup_decal_launcher(GkrellmPanel *p, GkrellmLauncher *launch,
453 			GkrellmDecal *d)
454 	{
455 	if (!launch)
456 		return;
457 	if (!launch->command)
458 		launch->command = g_strdup("");
459 	if (!launch->tooltip_comment)
460 		launch->tooltip_comment = g_strdup("");
461 	launch->type = DECAL_LAUNCHER;
462 	launch->pad = 0;
463 	launch->decal = d;
464 	if (p)
465 		{
466 		gkrellm_configure_tooltip(p, launch);
467 		if (*(launch->command))
468 			launch->button = gkrellm_put_decal_in_meter_button(p, d,
469 					gkrellm_launch_button_cb, launch, &launch->margin);
470 		else
471 			launch->button = NULL;	/* In case dangling pointer, see above */
472 		}
473 	}
474 
475 void
gkrellm_gtk_check_button(GtkWidget * box,GtkWidget ** button,gboolean active,gboolean expand,gint pad,gchar * string)476 gkrellm_gtk_check_button(GtkWidget *box, GtkWidget **button, gboolean active,
477 			gboolean expand, gint pad, gchar *string)
478 	{
479 	GtkWidget	*b;
480 
481 	if (!string)
482 		return;
483 	b = gtk_check_button_new_with_label(string);
484 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), active);
485 	if (box)
486 		gtk_box_pack_start(GTK_BOX(box), b, expand, FALSE, pad);
487 	if (button)
488 		*button = b;
489 	}
490 
491 void
gkrellm_gtk_check_button_connected(GtkWidget * box,GtkWidget ** button,gboolean active,gboolean expand,gboolean fill,gint pad,void (* cb_func)(),gpointer data,gchar * string)492 gkrellm_gtk_check_button_connected(GtkWidget *box, GtkWidget **button,
493 			gboolean active, gboolean expand, gboolean fill, gint pad,
494 			void (*cb_func)(), gpointer data, gchar *string)
495 	{
496 	GtkWidget	*b;
497 
498 	if (!string)
499 		return;
500 	b = gtk_check_button_new_with_label(string);
501 
502 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), active);
503 	if (box)
504 		{
505 		if (pad < 0)
506 			gtk_box_pack_end(GTK_BOX(box), b, expand, fill, -(pad + 1));
507 		else
508 			gtk_box_pack_start(GTK_BOX(box), b, expand, fill, pad);
509 		}
510 	if (cb_func)
511 		g_signal_connect(G_OBJECT(b), "toggled",
512 				G_CALLBACK(cb_func), data);
513 	if (button)
514 		*button = b;
515 	}
516 
517 void
gkrellm_gtk_button_connected(GtkWidget * box,GtkWidget ** button,gboolean expand,gboolean fill,gint pad,void (* cb_func)(),gpointer data,gchar * string)518 gkrellm_gtk_button_connected(GtkWidget *box, GtkWidget **button,
519 			gboolean expand, gboolean fill, gint pad,
520 			void (*cb_func)(), gpointer data, gchar *string)
521 	{
522 	GtkWidget	*b;
523 
524 	if (!string)
525 		return;
526 	if (!strncmp(string, "gtk-", 4))
527 		b = gtk_button_new_from_stock(string);
528 	else
529 		b = gtk_button_new_with_label(string);
530 	if (box)
531 		{
532 		if (pad < 0)
533 			gtk_box_pack_end(GTK_BOX(box), b, expand, fill, -(pad + 1));
534 		else
535 			gtk_box_pack_start(GTK_BOX(box), b, expand, fill, pad);
536 		}
537 	if (cb_func)
538 		g_signal_connect(G_OBJECT(b), "clicked",
539 				G_CALLBACK(cb_func), data);
540 	if (button)
541 		*button = b;
542 	}
543 
544 void
gkrellm_gtk_alert_button(GtkWidget * box,GtkWidget ** button,gboolean expand,gboolean fill,gint pad,gboolean pack_start,void (* cb_func)(),gpointer data)545 gkrellm_gtk_alert_button(GtkWidget *box, GtkWidget **button,
546 			gboolean expand, gboolean fill, gint pad, gboolean pack_start,
547 			void (*cb_func)(), gpointer data)
548 	{
549 	GtkWidget	*b, *hbox;
550 	GtkWidget	*image, *label;
551 
552 	hbox = gtk_hbox_new(FALSE, 0);
553 	gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
554 	image = gtk_image_new_from_pixbuf(gkrellm_alert_pixbuf());
555 	label = gtk_label_new(_("Alerts"));
556 	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 3);
557 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 3);
558 	b = gtk_button_new();
559 	if (button)
560 		*button = b;
561 	if (cb_func)
562 		g_signal_connect(G_OBJECT(b), "clicked", G_CALLBACK(cb_func), data);
563 	gtk_widget_show_all(hbox);
564 	gtk_container_add(GTK_CONTAINER(b), hbox);
565 	if (box)
566 		{
567 		if (pack_start)
568 			gtk_box_pack_start(GTK_BOX(box), b, expand, fill, pad);
569 		else
570 			gtk_box_pack_end(GTK_BOX(box), b, expand, fill, pad);
571 		}
572 	}
573 
574 void
gkrellm_gtk_spin_button(GtkWidget * box,GtkWidget ** spin_button,gfloat value,gfloat low,gfloat high,gfloat step0,gfloat step1,gint digits,gint width,void (* cb_func)(),gpointer data,gboolean right_align,gchar * string)575 gkrellm_gtk_spin_button(GtkWidget *box, GtkWidget **spin_button, gfloat value,
576 		gfloat low, gfloat high, gfloat step0, gfloat step1,
577 		gint digits, gint width,
578 		void (*cb_func)(), gpointer data, gboolean right_align, gchar *string)
579 	{
580 	GtkWidget		*hbox	= NULL,
581 					*label,
582 					*button;
583 	GtkSpinButton	*spin;
584 	GtkAdjustment	*adj;
585 
586 	if (string && box)
587 		{
588 	    hbox = gtk_hbox_new (FALSE, 0);
589     	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 2);
590 		box = hbox;
591 		}
592     adj = (GtkAdjustment *) gtk_adjustment_new (value,
593 								low, high, step0, step1, 0.0);
594     button = gtk_spin_button_new(adj, 0.5, digits);
595 	if (spin_button)
596 		*spin_button = button;
597 	if (width > 0)
598 		gtk_widget_set_size_request(button, width, -1);
599     spin = GTK_SPIN_BUTTON(button);
600     gtk_spin_button_set_numeric(spin, TRUE);
601 	if (!data)
602 		data = (gpointer) spin;
603 	if (cb_func)
604 		g_signal_connect(G_OBJECT(adj), "value_changed",
605 				G_CALLBACK(cb_func), data);
606 	if (box)
607 		{
608 		if (right_align && string)
609 			{
610 			label = gtk_label_new(string);
611 			gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
612 			gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 2);
613 			}
614 		gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 2);
615 		if (!right_align && string)
616 			{
617 			label = gtk_label_new(string);
618 			gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
619 			gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 2);
620 			}
621 		}
622 	}
623 
624 GtkWidget *
gkrellm_gtk_scrolled_vbox(GtkWidget * box,GtkWidget ** scr,GtkPolicyType h_policy,GtkPolicyType v_policy)625 gkrellm_gtk_scrolled_vbox(GtkWidget *box, GtkWidget **scr,
626 		GtkPolicyType h_policy, GtkPolicyType v_policy)
627 	{
628 	GtkWidget	*scrolled,
629 				*vbox;
630 
631 	scrolled = gtk_scrolled_window_new(NULL, NULL);
632 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
633 			h_policy, v_policy);
634 	gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0);
635 	vbox = gtk_vbox_new(FALSE, 2);
636 	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), vbox);
637 	if (scr)
638 		*scr = scrolled;
639 	return vbox;
640 	}
641 
642   /* frame_border_width - border around outside of frame.
643   |  vbox_pad - pad between widgets to be packed in returned vbox.
644   |  vbox_border_width - border between returned vbox and frame.
645   */
646 GtkWidget *
gkrellm_gtk_framed_vbox(GtkWidget * box,gchar * label,gint frame_border_width,gboolean frame_expand,gint vbox_pad,gint vbox_border_width)647 gkrellm_gtk_framed_vbox(GtkWidget *box, gchar *label, gint frame_border_width,
648 		gboolean frame_expand, gint vbox_pad, gint vbox_border_width)
649 	{
650 	GtkWidget	*frame, *lbl;
651 	GtkWidget	*vbox;
652 
653 	frame = gtk_frame_new(NULL);
654 /*	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE); */
655 	lbl = gtk_label_new(NULL);
656 	gtk_label_set_markup(GTK_LABEL(lbl), label);
657 	gtk_frame_set_label_widget(GTK_FRAME(frame), lbl);
658 
659 	gtk_container_set_border_width(GTK_CONTAINER(frame), frame_border_width);
660     gtk_box_pack_start(GTK_BOX(box), frame, frame_expand, frame_expand, 0);
661     vbox = gtk_vbox_new(FALSE, vbox_pad);
662     gtk_container_set_border_width(GTK_CONTAINER(vbox), vbox_border_width);
663     gtk_container_add(GTK_CONTAINER(frame), vbox);
664 	return vbox;
665 	}
666 
667 GtkWidget *
gkrellm_gtk_framed_vbox_end(GtkWidget * box,gchar * label,gint frame_border_width,gboolean frame_expand,gint vbox_pad,gint vbox_border_width)668 gkrellm_gtk_framed_vbox_end(GtkWidget *box, gchar *label,
669 		gint frame_border_width, gboolean frame_expand,
670 		gint vbox_pad, gint vbox_border_width)
671 	{
672 	GtkWidget	*frame;
673 	GtkWidget	*vbox;
674 
675 	frame = gtk_frame_new(label);
676 	gtk_container_set_border_width(GTK_CONTAINER(frame), frame_border_width);
677     gtk_box_pack_end(GTK_BOX(box), frame, frame_expand, frame_expand, 0);
678     vbox = gtk_vbox_new(FALSE, vbox_pad);
679     gtk_container_set_border_width(GTK_CONTAINER(vbox), vbox_border_width);
680     gtk_container_add(GTK_CONTAINER(frame), vbox);
681 	return vbox;
682 	}
683 
684 GtkWidget *
gkrellm_gtk_category_vbox(GtkWidget * box,gchar * category_header,gint header_pad,gint box_pad,gboolean pack_start)685 gkrellm_gtk_category_vbox(GtkWidget *box, gchar *category_header,
686 		gint header_pad, gint box_pad, gboolean pack_start)
687 	{
688 	GtkWidget	*vbox, *vbox1, *hbox, *label;
689 	gchar		*s;
690 
691 	vbox = gtk_vbox_new(TRUE, 0);
692 	gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
693 
694 	if (pack_start)
695 		gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0);
696 	else
697 		gtk_box_pack_end(GTK_BOX(box), vbox, TRUE, TRUE, 0);
698 
699 	if (category_header)
700 		{
701 		label = gtk_label_new(NULL);
702 		s = g_strconcat("<span weight=\"bold\">", category_header,
703 					"</span>",NULL);
704 		gtk_label_set_markup(GTK_LABEL(label), s);
705 		gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
706 		gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, header_pad);
707 		g_free(s);
708 		}
709 
710 	hbox = gtk_hbox_new(FALSE, 0);
711 	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
712 
713 	label = gtk_label_new("    ");
714 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
715 	vbox1 = gtk_vbox_new(FALSE, box_pad);
716 	gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
717 
718 	/* Add some bottom pad */
719 	label = gtk_label_new("");
720 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
721 
722 	return vbox1;
723 	}
724 
725 GtkWidget *
gkrellm_gtk_notebook_page(GtkWidget * tabs,char * name)726 gkrellm_gtk_notebook_page(GtkWidget *tabs, char *name)
727 	{
728 	GtkWidget	*label;
729 	GtkWidget	*vbox;
730 
731 	vbox = gtk_vbox_new(FALSE, 0);
732 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 0);
733 
734 	label = gtk_label_new(name);
735 	gtk_notebook_append_page(GTK_NOTEBOOK(tabs), vbox, label);
736 
737 	return vbox;
738 	}
739 
740 GtkWidget *
gkrellm_gtk_framed_notebook_page(GtkWidget * tabs,char * name)741 gkrellm_gtk_framed_notebook_page(GtkWidget *tabs, char *name)
742 	{
743 	GtkWidget	*vbox;
744 
745 	vbox = gkrellm_gtk_notebook_page(tabs, name);
746 	vbox = gkrellm_gtk_framed_vbox(vbox, NULL, 2, TRUE, 4, 4);
747 	return vbox;
748 	}
749 
750 static void
create_about_tab(GtkWidget * vbox)751 create_about_tab(GtkWidget *vbox)
752 	{
753 	GtkWidget	*label;
754 	gchar		*buf;
755 
756 	vbox = gkrellm_gtk_framed_vbox(vbox, NULL, 2, TRUE, 0, 0);
757 	label = gtk_label_new("");
758 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
759 
760 	buf = g_strdup_printf(_("GKrellM %d.%d.%d%s\nGNU Krell Monitors\n\n"
761 				"Copyright (c) %s by Bill Wilson\n"
762 				"billw@gkrellm.net\n"
763 				"http://gkrellm.net\n\n"
764 				"Released under the GNU General Public License"),
765 				GKRELLM_VERSION_MAJOR, GKRELLM_VERSION_MINOR,
766 				GKRELLM_VERSION_REV, GKRELLM_EXTRAVERSION,
767 				"1999-2019");
768 	label = gtk_label_new(buf);
769 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
770 	g_free(buf);
771 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
772 
773 	label = gtk_label_new("");
774 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
775 
776 #if defined(__APPLE__)
777 	buf = g_strdup_printf(_("Mac OS X code was contributed by:\n"
778 						"Ben Hines <bhines@alumni.ucsd.edu>\n"
779 						"and\n"
780 						"Hajimu UMEMOTO <ume@mahoroba.org>"));
781 	label = gtk_label_new(buf);
782 	g_free(buf);
783 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
784 #endif
785 #if defined(__FreeBSD__)
786 	buf = g_strdup_printf(
787 				_("FreeBSD system dependent code was contributed by:\n"
788 				"Hajimu UMEMOTO <ume@mahoroba.org>"));
789 	label = gtk_label_new(buf);
790 	g_free(buf);
791 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
792 #endif
793 #if defined(__DragonFly__)
794 	buf = g_strdup_printf(
795 				_("DragonFly system dependent code was contributed by:\n"
796 				"Joerg Sonnenberger <joerg@bec.de>"));
797 	label = gtk_label_new(buf);
798 	g_free(buf);
799 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
800 #endif
801 #if defined(__NetBSD__)
802 	buf = g_strdup_printf(
803 				_("NetBSD system dependent code was contributed by:\n"
804 				"Anthony Mallet <anthony.mallet@useless-ficus.net>"));
805 	label = gtk_label_new(buf);
806 	g_free(buf);
807 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
808 #endif
809 #if defined(__solaris__)
810 	buf = g_strdup_printf(
811 				_("Solaris system dependent code was contributed by:\n"
812 				"Daisuke Yabuki <dxy@acm.org>"));
813 	label = gtk_label_new(buf);
814 	g_free(buf);
815 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
816 #endif
817 #if defined(WIN32)
818 	buf = g_strdup_printf(
819 				_("Windows system dependent code was contributed by:\n"
820 				"Bill Nalen <bill@nalens.com>\n"
821 				"Stefan Gehn <stefan+gkrellm@srcbox.net>\n"));
822 	label = gtk_label_new(buf);
823 	g_free(buf);
824 	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
825 #endif // !WIN32
826 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
827 	}
828 
829 
830 /* ------------------General Settings---------------------------------*/
831 static GtkWidget
832 			*enable_hst_button,
833 			*hostname_short_button,
834 			*enable_sysname_button,
835 			*save_position_button;
836 
837 #if !defined(WIN32)
838 static GtkWidget
839 			*sticky_state_button,
840 			*dock_type_button,
841 			*decorated_button,
842 			*skip_taskbar_button,
843 			*skip_pager_button,
844 			*above_button,
845 			*below_button;
846 #endif // !WIN32
847 
848 GtkWidget	*track_gtk_button,
849 			*allow_multiple_button;
850 GtkWidget	*on_top_button;
851 
852 
853 
854 static void
cb_width_spin(GtkWidget * widget,GtkSpinButton * spin)855 cb_width_spin(GtkWidget *widget, GtkSpinButton *spin)
856 	{
857 	_GK.chart_width = gtk_spin_button_get_value_as_int(spin);
858 	gkrellm_build();
859 	}
860 
861 static void
cb_HZ_spin(GtkWidget * widget,GtkSpinButton * spin)862 cb_HZ_spin(GtkWidget *widget, GtkSpinButton *spin)
863 	{
864 	gint	n;
865 
866 	n = _GK.update_HZ;
867 	_GK.update_HZ = gtk_spin_button_get_value_as_int(spin);
868 	if (n != _GK.update_HZ)
869 		gkrellm_start_timer(_GK.update_HZ);
870 	}
871 
872 static void
cb_hostname_sysname(GtkWidget * widget,gpointer data)873 cb_hostname_sysname(GtkWidget *widget, gpointer data)
874 	{
875 	_GK.enable_hostname = GTK_TOGGLE_BUTTON(enable_hst_button)->active;
876 	if (hostname_short_button)
877 		_GK.hostname_short = GTK_TOGGLE_BUTTON(hostname_short_button)->active;
878 	_GK.enable_system_name = GTK_TOGGLE_BUTTON(enable_sysname_button)->active;
879 	gkrellm_apply_hostname_config();
880 	}
881 
882 static void
cb_general(void)883 cb_general(void)
884 	{
885 #if !defined(WIN32)
886 	gint		n;
887 	gboolean	new_state;
888 #endif
889 
890 	if (allow_multiple_button)
891 		_GK.allow_multiple_instances =
892 					GTK_TOGGLE_BUTTON(allow_multiple_button)->active;
893 	if (on_top_button)
894 		_GK.on_top = GTK_TOGGLE_BUTTON(on_top_button)->active;
895 
896 	_GK.save_position = GTK_TOGGLE_BUTTON(save_position_button)->active;
897 #if !defined(WIN32)
898 	if (sticky_state_button)
899 		{
900 		n = GTK_TOGGLE_BUTTON(sticky_state_button)->active;
901 		new_state = (n != _GK.sticky_state);
902 		_GK.sticky_state = n;
903 		if (new_state)
904 			{
905 			GtkWidget	*top_window = gkrellm_get_top_window();
906 
907 			if (_GK.sticky_state)
908 				gtk_window_stick(GTK_WINDOW(top_window));
909 			else
910 				gtk_window_unstick(GTK_WINDOW(top_window));
911 			}
912 		}
913 
914 	if (decorated_button)	/* restart for change to take effect */
915 		_GK.decorated = GTK_TOGGLE_BUTTON(decorated_button)->active;
916 
917 	if (skip_taskbar_button)
918 		{
919 		n = GTK_TOGGLE_BUTTON(skip_taskbar_button)->active;
920 		new_state = (n != _GK.state_skip_taskbar);
921 		_GK.state_skip_taskbar = n;
922 		if (new_state)
923 			gkrellm_winop_state_skip_taskbar(n);
924 		}
925 	if (skip_pager_button)
926 		{
927 		n = GTK_TOGGLE_BUTTON(skip_pager_button)->active;
928 		new_state = (n != _GK.state_skip_pager);
929 		_GK.state_skip_pager = n;
930 		if (new_state)
931 			gkrellm_winop_state_skip_pager(n);
932 		}
933 	if (above_button)
934 		{
935 		n = GTK_TOGGLE_BUTTON(above_button)->active;
936 		new_state = (n != _GK.state_above);
937 		_GK.state_above = n;
938 		if (new_state)
939 			{
940 			if (n && _GK.state_below)
941 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(below_button),
942 						FALSE);
943 			gkrellm_winop_state_above(n);
944 			}
945 		}
946 	if (below_button)
947 		{
948 		n = GTK_TOGGLE_BUTTON(below_button)->active;
949 		new_state = (n != _GK.state_below);
950 		_GK.state_below = n;
951 		if (new_state)
952 			{
953 			if (n && _GK.state_above)
954 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(above_button),
955 						FALSE);
956 			gkrellm_winop_state_below(n);
957 			}
958 		}
959 #endif // !WIN32
960 	}
961 
962 #ifndef WIN32
963 static void
cb_dock_type(GtkWidget * widget,gpointer data)964 cb_dock_type(GtkWidget *widget, gpointer data)
965 	{
966 	gboolean	sensitive;
967 
968 	_GK.dock_type = GTK_TOGGLE_BUTTON(dock_type_button)->active;
969 	sensitive = !_GK.dock_type;
970 	if (!sensitive)
971 		{
972 		gtk_toggle_button_set_active(
973 					GTK_TOGGLE_BUTTON(decorated_button), FALSE);
974 		gtk_toggle_button_set_active(
975 					GTK_TOGGLE_BUTTON(skip_taskbar_button), FALSE);
976 		gtk_toggle_button_set_active(
977 					GTK_TOGGLE_BUTTON(skip_pager_button), FALSE);
978 		}
979 	gtk_widget_set_sensitive(decorated_button, sensitive);
980 	gtk_widget_set_sensitive(skip_taskbar_button, sensitive);
981 	gtk_widget_set_sensitive(skip_pager_button, sensitive);
982 	}
983 #endif // WIN32
984 
985 static gchar	*general_info_text[]	=
986 {
987 N_("<h>Krells\n"),
988 N_("Krells are the horizontally moving indicators below each chart and\n"
989 "on meter style monitors.  Depending on the monitor, they show fast\n"
990 "response data rates, a percentage of some capacity, or something else.\n"),
991 "\n",
992 N_("<h>Charts\n"),
993 N_("The default for most charts is to automatically adjust the number of\n"
994 	"grid lines drawn and the resolution per grid so drawn data will be\n"
995 	"nicely visible.  You may change this to fixed grids of 1-5 and/or\n"
996 	"fixed grid resolutions in the chart config windows.  However,\n"
997 	"some combination of the auto scaling modes may give best results.\n"),
998 "\n",
999 N_("See the README or do a \"man gkrellm\" for more information.\n"),
1000 "\n",
1001 N_("<h>Chart Labels\n"),
1002 N_("Chart label format strings place text on charts using position codes:\n"),
1003 N_("\t\\t    top left\n"),
1004 N_("\t\\b    bottom left\n"),
1005 N_("\t\\n    next line\n"),
1006 N_("\t\\N    next line only if last string had visible characters\n"),
1007 N_("\t\\p    previous line\n"),
1008 N_("\t\\c    center the text\n"),
1009 N_("\t\\C    begin drawing text at the center\n"),
1010 N_("\t\\r    right justify\n"),
1011 N_("\t\\f    use alternate font for the next string\n"),
1012 N_("\t\\w    use the following string to define a field width\n"),
1013 N_("\t\\a    draw left justified in the defined field width\n"),
1014 N_("\t\\e    draw right justified in the defined field width\n"),
1015 N_("\t\\.     no-op.  Used to break a string into two strings.\n"),
1016 N_("\t\\D0   bottom of charts first data view (D2 for second data view ...)\n"),
1017 N_("\t\\D1   top of charts first data view (D3 for second data view ...)\n"),
1018 "\n",
1019 N_("\tText drawn on charts cannot use Pango markup and changing the color\n"),
1020 N_("\tused for a chart default or alternate font requires editing the theme.\n"),
1021 "\n",
1022 
1023 N_("<h>Panel Labels\n"),
1024 N_("\tMost panel labels can use Pango markup to customize the font or\n"
1025    "\ttext color.  If the Pango markup string requires quote characters some\n"
1026    "\tmonitors (eg Sensors) require using single quotes instead of double\n"
1027    "\tquotes.  For example, to set a big colored CPU label, use markup:\n"),
1028 	"\t    <span foreground='cyan'><big>CPU</big></span>\n",
1029 "\n",
1030 
1031 N_("<h>\nCommands\n"),
1032 N_("\tMany monitors can be configured to launch commands.  Just enter the\n"
1033    "\tcommand where you see a \"command\" entry and also a comment if you\n"
1034    "\twant a tooltip to appear for the command.  After a command is entered,\n"
1035    "\tfor a monitor, a button for launching it will become visible when you\n"
1036    "\tmove the mouse into the panel area of the monitor.\n\n"),
1037 N_("See the README or do a \"man gkrellm\" for more information.\n"),
1038 "\n",
1039 
1040 N_("<h>\nMouse Button Actions:\n"),
1041 N_("<b>\tLeft "),
1042 N_("clicking on charts will toggle a display of some extra info.\n"),
1043 N_("<b>\tRight "),
1044 N_("clicking on charts brings up a chart configuration window.\n"),
1045 N_("<b>\tRight "),
1046 N_("clicking on many panels opens its monitor configuration window.\n")
1047 };
1048 
1049 static void
create_general_tab(GtkWidget * tab_vbox)1050 create_general_tab(GtkWidget *tab_vbox)
1051 	{
1052 	GtkWidget		*tabs;
1053 	GtkWidget		*vbox, *vbox1;
1054 #if !defined(WIN32)
1055 	GtkWidget		*vbox2;
1056 #endif
1057 	GtkWidget		*hbox;
1058 	GtkWidget		*label, *text;
1059 	gint			i;
1060 
1061 	tabs = gtk_notebook_new();
1062 	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
1063 	gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
1064 
1065 /* --Options tab */
1066 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Options"));
1067 	vbox1 = gtk_vbox_new(FALSE, 0);
1068 	gtk_box_pack_start(GTK_BOX(vbox), vbox1, FALSE, FALSE, 0);
1069 	hbox = gtk_hbox_new (FALSE, 0);
1070 	gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
1071 
1072 	gkrellm_gtk_check_button_connected(hbox, &enable_hst_button,
1073 			_GK.enable_hostname, FALSE, FALSE, 0,
1074 			cb_hostname_sysname, NULL,
1075 			_("Hostname display"));
1076 
1077 	if (gkrellm_hostname_can_shorten())
1078 		gkrellm_gtk_check_button_connected(hbox, &hostname_short_button,
1079 				_GK.hostname_short, FALSE, FALSE, 10,
1080 				cb_hostname_sysname, NULL,
1081 				_("Short hostname"));
1082 
1083 	gkrellm_gtk_check_button_connected(vbox, &enable_sysname_button,
1084 			_GK.enable_system_name, FALSE, FALSE, 0,
1085 			cb_hostname_sysname, NULL,
1086 			_("System name display"));
1087 
1088 	gkrellm_gtk_check_button_connected(vbox, &save_position_button,
1089 			_GK.save_position, FALSE, FALSE, 6,
1090 			cb_general, NULL,
1091 		_("Remember screen location at exit and move to it at next startup"));
1092 
1093 #if !defined(WIN32)
1094 	gkrellm_gtk_check_button_connected(vbox, &allow_multiple_button,
1095 			_GK.allow_multiple_instances, FALSE, FALSE, 0,
1096 			cb_general, NULL,
1097 			_("Allow multiple instances"));
1098 #endif // !WIN32
1099 
1100 #if defined(WIN32)
1101 	gkrellm_gtk_check_button_connected(vbox, &on_top_button,
1102 			_GK.on_top, FALSE, FALSE, 0,
1103 			cb_general, NULL,
1104 _("Make gkrellm a topmost window (restart gkrellm for this to take effect)."));
1105 #endif // WIN32
1106 
1107 	if (_GK.client_mode)
1108 		{
1109 		hbox = gtk_hbox_new(FALSE, 0);
1110 		gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 6);
1111 		gkrellm_gtk_alert_button(hbox, NULL, FALSE, FALSE, 4, TRUE,
1112 					gkrellm_gkrellmd_disconnect_cb, NULL);
1113 		label = gtk_label_new(_("gkrellmd server disconnect"));
1114 		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 4);
1115 		}
1116 
1117 	vbox = gkrellm_gtk_framed_vbox_end(vbox, NULL, 4, FALSE, 0, 2);
1118 	gkrellm_gtk_spin_button(vbox, NULL, (gfloat) _GK.update_HZ,
1119 			1.0, 20.0, 1.0, 1.0, 0, 55,
1120 			cb_HZ_spin, NULL, FALSE,
1121 			_("Krell and LED updates per second."));
1122 
1123 	gkrellm_gtk_spin_button(vbox, NULL, (gfloat) _GK.chart_width,
1124 			(gfloat) CHART_WIDTH_MIN, (gfloat) CHART_WIDTH_MAX,
1125 			5.0, 10.0, 0, 55,
1126 			cb_width_spin, NULL, FALSE,
1127 			_("GKrellM width"));
1128 
1129 #if !defined(WIN32)
1130 /* --Window options tab */
1131 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Properties"));
1132 	gkrellm_gtk_check_button_connected(vbox, &sticky_state_button,
1133 			_GK.sticky_state, FALSE, FALSE, 0, cb_general, NULL,
1134 			_("Set sticky state"));
1135 	gkrellm_gtk_check_button_connected(vbox, &above_button,
1136 			_GK.state_above, FALSE, FALSE, 0, cb_general, NULL,
1137 			_("Set on top of other windows of the same type"));
1138 	gkrellm_gtk_check_button_connected(vbox, &below_button,
1139 			_GK.state_below, FALSE, FALSE, 0, cb_general, NULL,
1140 			_("Set below other windows of the same type"));
1141 
1142 	vbox1 = gkrellm_gtk_framed_vbox(vbox, NULL, 4, FALSE, 2, 0);
1143 	vbox2 = gkrellm_gtk_framed_vbox(vbox1, NULL, 0, FALSE, 0, 0);
1144 	gkrellm_gtk_check_button_connected(vbox2, &dock_type_button,
1145 			_GK.dock_type, FALSE, FALSE, 0,
1146 			cb_dock_type, NULL,
1147 			_("Set window type to be a dock or panel"));
1148 
1149 	vbox2 = gkrellm_gtk_framed_vbox(vbox1, NULL, 0, FALSE, 0, 0);
1150 	gkrellm_gtk_check_button_connected(vbox2, &decorated_button,
1151 			_GK.decorated, FALSE, FALSE, 0, cb_general, NULL,
1152 			_("Use window manager decorations"));
1153 
1154 	gkrellm_gtk_check_button_connected(vbox2, &skip_taskbar_button,
1155 			_GK.state_skip_taskbar, FALSE, FALSE, 0, cb_general, NULL,
1156 			_("Do not include on a taskbar"));
1157 
1158 	gkrellm_gtk_check_button_connected(vbox2, &skip_pager_button,
1159 			_GK.state_skip_pager, FALSE, FALSE, 0, cb_general, NULL,
1160 			_("Do not include on a pager"));
1161 
1162 	if (_GK.dock_type)
1163 		{
1164 		gtk_widget_set_sensitive(decorated_button, FALSE);
1165 		gtk_widget_set_sensitive(skip_taskbar_button, FALSE);
1166 		gtk_widget_set_sensitive(skip_pager_button, FALSE);
1167 		}
1168 
1169 	text = gtk_label_new(
1170 _("Some of these properties require a standards compliant window manager.\n"
1171   "You may have to restart gkrellm for them to take effect.\n"));
1172 	gtk_box_pack_end(GTK_BOX(vbox), text, FALSE, TRUE, 4);
1173 #endif // !WIN32
1174 
1175 /* --Info tab */
1176 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Info"));
1177 	text = gkrellm_gtk_scrolled_text_view(vbox, NULL,
1178 				GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1179 
1180 	for (i = 0; i < sizeof(general_info_text)/sizeof(gchar *); ++i)
1181 		gkrellm_gtk_text_view_append(text, _(general_info_text[i]));
1182 	}
1183 
1184 
1185 /* ------------------Themes Tab----------------------------------*/
1186 
1187 enum
1188 	{
1189 	THEME_COLUMN,
1190 	PATH_COLUMN,
1191 	N_THEME_COLUMNS
1192 	};
1193 
1194 typedef struct
1195 	{
1196 	gchar	*path;
1197 	gchar	*name;
1198 	}
1199 	Theme;
1200 
1201 static GtkTreeView      *theme_treeview;
1202 static GtkTreeSelection *theme_selection;
1203 
1204 static GList		*themes_list;
1205 static GList		*theme_position_in_list;
1206 
1207 static GtkWidget	*theme_alt_spin_button;
1208 static GtkWidget	*theme_alt_label;
1209 static GtkWidget	*theme_entry,
1210 					*author_label;
1211 
1212 static gboolean		theme_modified;
1213 
1214 
1215 typedef struct
1216 	{
1217 	GtkFontSelectionDialog	*fontseldlg;
1218 	GtkWidget				*entry;
1219 	GtkWidget				*browse_button;
1220 	gchar					*name;
1221 	gchar					*string;
1222 //	PangoFontDescription	*font_desc;
1223 	}
1224 	AltFontSelect;
1225 
1226 static AltFontSelect
1227 			large_font,
1228 			normal_font,
1229 			small_font;
1230 
1231 gchar *
gkrellm_get_large_font_string(void)1232 gkrellm_get_large_font_string(void)
1233 	{
1234 	return large_font.string;
1235 	}
1236 
1237 gchar *
gkrellm_get_normal_font_string(void)1238 gkrellm_get_normal_font_string(void)
1239 	{
1240 	return normal_font.string;
1241 	}
1242 
1243 gchar *
gkrellm_get_small_font_string(void)1244 gkrellm_get_small_font_string(void)
1245 	{
1246 	return small_font.string;
1247 	}
1248 
1249 static gboolean
get_font_entries(void)1250 get_font_entries(void)
1251 	{
1252 	gchar		*s;
1253 	gboolean	modified = FALSE;
1254 
1255 	s = (gchar *) gtk_entry_get_text(GTK_ENTRY(large_font.entry));
1256 	modified |= gkrellm_dup_string(&large_font.string, s);
1257 	s = (gchar *) gtk_entry_get_text(GTK_ENTRY(normal_font.entry));
1258 	modified |= gkrellm_dup_string(&normal_font.string, s);
1259 	s = (gchar *) gtk_entry_get_text(GTK_ENTRY(small_font.entry));
1260 	modified |= gkrellm_dup_string(&small_font.string, s);
1261 	return modified;
1262 	}
1263 
1264 static void
cb_font_dialog_ok(GtkWidget * w,AltFontSelect * afs)1265 cb_font_dialog_ok(GtkWidget *w, AltFontSelect *afs)
1266 	{
1267 	gchar	*fontname;
1268 
1269 	fontname = gtk_font_selection_dialog_get_font_name(afs->fontseldlg);
1270 	if (fontname)
1271 		gtk_entry_set_text(GTK_ENTRY(afs->entry), fontname);
1272 	gtk_widget_destroy(GTK_WIDGET(afs->fontseldlg));
1273 	theme_modified = TRUE;
1274 	get_font_entries();
1275 	gkrellm_build();
1276 	}
1277 
1278 static void
cb_font_dialog(GtkWidget * widget,AltFontSelect * afs)1279 cb_font_dialog(GtkWidget *widget, AltFontSelect *afs)
1280 	{
1281 	GtkWidget				*w;
1282 	GtkFontSelectionDialog	*fsd;
1283 
1284 	if (afs->fontseldlg)
1285 		return;
1286 	w = gtk_font_selection_dialog_new(_(afs->name));
1287 	gtk_window_set_wmclass(GTK_WINDOW(w),
1288 				"Gkrellm_dialog", "Gkrellm");
1289 	fsd = GTK_FONT_SELECTION_DIALOG(w);
1290 	afs->fontseldlg = fsd;
1291 	gtk_font_selection_dialog_set_font_name(fsd, afs->string);
1292 	g_signal_connect(G_OBJECT(fsd->ok_button), "clicked",
1293 			G_CALLBACK(cb_font_dialog_ok), afs);
1294 	g_signal_connect_swapped(G_OBJECT(fsd->cancel_button), "clicked",
1295 			G_CALLBACK(gtk_widget_destroy), fsd);
1296 	g_signal_connect(G_OBJECT(fsd), "destroy",
1297 			G_CALLBACK(gtk_widget_destroyed), &afs->fontseldlg);
1298 	gtk_widget_show(GTK_WIDGET(fsd));
1299 	}
1300 
1301 static gchar *
get_theme_author(gchar * path)1302 get_theme_author(gchar *path)
1303 	{
1304 	static gchar	buf[128];
1305 	FILE			*f;
1306 	gchar			*s, *q, *rcfile, line[128];
1307 
1308 	buf[0] = '\0';
1309 	if (!path || *path == '\0')
1310 		return buf;
1311 	rcfile = g_strdup_printf("%s/%s", path, GKRELLMRC);
1312 	f = g_fopen(rcfile, "r");
1313 	g_free(rcfile);
1314 	if (!f)
1315 		return buf;
1316 	while (fgets(line, sizeof(line), f))
1317 		{
1318 		if (   (s = strtok(line, " :=\t\n")) == NULL
1319 			|| strcmp(s, "author") != 0
1320 		   )
1321 			continue;
1322 		s = strtok(NULL, "\n");		/* Rest of line is Author string */
1323 		if (s)
1324 			{
1325 			while (   *s == ' ' || *s == '\t' || *s == '"' || *s == '='
1326 					|| *s == ':')
1327 				++s;
1328 			q = strchr(s, (int) '"');
1329 			if (q)
1330 				*q = '\0';
1331 			strcpy(buf, s);
1332 			break;
1333 			}
1334 		}
1335 	fclose(f);
1336 	return buf;
1337 	}
1338 
1339 static Theme *
find_theme_in_list(gchar * name)1340 find_theme_in_list(gchar *name)
1341 	{
1342 	GList	*list;
1343 	Theme	*theme;
1344 
1345 	if (!name || !*name)
1346 		return NULL;
1347 
1348 	for (list = themes_list ; list; list = list->next)
1349 		{
1350 		theme = (Theme *) list->data;
1351 		if (!strcmp(theme->name, name))
1352 			return theme;
1353 		}
1354 	return NULL;
1355 	}
1356 
1357 static void
add_themes_to_list(gchar * theme_dir,gboolean in_gkrellm2)1358 add_themes_to_list(gchar *theme_dir, gboolean in_gkrellm2)
1359 	{
1360 	GDir	*dir;
1361 	Theme	*theme;
1362 	gchar	*name;
1363 	gchar	*path;
1364 
1365 	if ((dir = g_dir_open(theme_dir, 0, NULL)) == NULL)
1366 		return;
1367 	while ((name = (gchar *) g_dir_read_name(dir)) != NULL)
1368 		{
1369 		if (find_theme_in_list(name))
1370 			continue;
1371 		if (in_gkrellm2)
1372 			path = g_build_filename(theme_dir, name, "gkrellm2", NULL);
1373 		else
1374 			path = g_build_filename(theme_dir, name, NULL);
1375 
1376 		if (g_file_test(path, G_FILE_TEST_IS_DIR))
1377 			{
1378 			theme = g_new0(Theme, 1);
1379 			theme->path = path;
1380 			theme->name = g_strdup(name);
1381 			themes_list = g_list_append(themes_list, theme);
1382 			}
1383 		else
1384 			g_free(path);
1385 		}
1386 	g_dir_close(dir);
1387 	}
1388 
1389 static void
find_theme_position_in_list(void)1390 find_theme_position_in_list(void)
1391 	{
1392 	GList	*list;
1393 	Theme	*theme;
1394 	gchar	*name;
1395 
1396 	name = *(_GK.theme_path) ? _GK.theme_path : "Default";
1397 	for (list = themes_list; list; list = list->next)
1398 		{
1399 		theme = (Theme *) list->data;
1400 		if (!strcmp(name, theme->path))
1401 			break;
1402 		}
1403 	theme_position_in_list = list ? list : themes_list;
1404 	}
1405 
1406 gint
theme_compare(Theme * th1,Theme * th2)1407 theme_compare(Theme *th1, Theme *th2)
1408 	{
1409 	return strcmp(th1->name, th2->name);
1410 	}
1411 
1412 void
gkrellm_make_themes_list(void)1413 gkrellm_make_themes_list(void)
1414 	{
1415 	GList	*list;
1416 	Theme	*theme;
1417 	gchar	*theme_dir;
1418 
1419 	for (list = themes_list; list; list = list->next)
1420 		{
1421 		theme = (Theme *) list->data;
1422 		g_free(theme->path);
1423 		g_free(theme->name);
1424 		}
1425 	gkrellm_free_glist_and_data(&themes_list);
1426 
1427 	theme = g_new0(Theme, 1);
1428 	theme->path = g_strdup("Default");
1429 	theme->name = g_strdup(theme->path);
1430 	themes_list = g_list_append(themes_list, theme);
1431 
1432 	theme_dir = g_build_filename(gkrellm_homedir(), GKRELLM_THEMES_DIR, NULL);
1433 	add_themes_to_list(theme_dir, FALSE);
1434 	g_free(theme_dir);
1435 
1436 	theme_dir = g_build_filename(gkrellm_homedir(), ".themes", NULL);
1437 	add_themes_to_list(theme_dir, TRUE);
1438 	g_free(theme_dir);
1439 
1440 	theme_dir = gtk_rc_get_theme_dir();
1441 	add_themes_to_list(theme_dir, TRUE);
1442 
1443 #if defined(WIN32)
1444 	gchar *install_path;
1445 	install_path = g_win32_get_package_installation_directory_of_module(NULL);
1446 	if (install_path != NULL)
1447 		{
1448 		theme_dir = g_build_filename(install_path, "share", "gkrellm2", "themes", NULL);
1449 		add_themes_to_list(theme_dir, FALSE);
1450 		g_free(theme_dir);
1451 		g_free(install_path);
1452 		}
1453 #endif
1454 
1455 #if defined(LOCAL_THEMES_DIR)
1456 	add_themes_to_list(LOCAL_THEMES_DIR, FALSE);
1457 #endif
1458 #if defined(SYSTEM_THEMES_DIR)
1459 	add_themes_to_list(SYSTEM_THEMES_DIR, FALSE);
1460 #endif
1461 
1462 	themes_list = g_list_sort(themes_list, (GCompareFunc) theme_compare);
1463 
1464 	if (_GK.command_line_theme)
1465 		{
1466 		theme = g_new0(Theme, 1);
1467 		theme->path = g_strdup(_GK.command_line_theme);
1468 		theme->name = g_strdup(theme->path);
1469 		themes_list = g_list_append(themes_list, theme);
1470 		}
1471 	find_theme_position_in_list();
1472 	}
1473 
1474 static GtkTreeModel *
theme_create_model(void)1475 theme_create_model(void)
1476 	{
1477 	GtkListStore	*store;
1478 	GtkTreeIter		iter;
1479 	GList			*list;
1480 	Theme			*theme;
1481 
1482 	gkrellm_make_themes_list();
1483 	store = gtk_list_store_new(N_THEME_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
1484 	for (list = themes_list; list; list = list->next)
1485 		{
1486 		theme = (Theme *) list->data;
1487 		gtk_list_store_append(store, &iter);
1488 		gtk_list_store_set(store, &iter,
1489 				THEME_COLUMN, theme->name,
1490 				PATH_COLUMN, theme->path,
1491 				-1);
1492 		}
1493 	return GTK_TREE_MODEL(store);
1494 	}
1495 
1496 static void
cb_theme_tree_selection_changed(GtkTreeSelection * selection,gpointer data)1497 cb_theme_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
1498 	{
1499 	GtkTreeIter		iter;
1500 	GtkTreeModel	*model;
1501 	gchar			*path;
1502 
1503 	if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1504 		return;
1505 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(theme_alt_spin_button), 0.0);
1506 	gtk_tree_model_get(model, &iter, PATH_COLUMN, &path, -1);
1507 	gtk_entry_set_text(GTK_ENTRY(theme_entry), path);
1508 	gtk_label_set_text(GTK_LABEL(author_label), get_theme_author(path));
1509 	if (gkrellm_dup_string(&_GK.theme_path, path))
1510 		{
1511 		find_theme_position_in_list();
1512 		theme_modified = TRUE;
1513 		gkrellm_build();
1514 		}
1515 	}
1516 
1517 static void
cb_theme_alternative_changed(GtkWidget * widget,GtkSpinButton * spin)1518 cb_theme_alternative_changed(GtkWidget *widget, GtkSpinButton *spin)
1519 	{
1520 	gint	i;
1521 
1522 	i = gtk_spin_button_get_value_as_int(spin);
1523 	if (i > _GK.theme_n_alternatives)
1524 		{
1525 		i = _GK.theme_n_alternatives;
1526 		gtk_spin_button_set_value(spin, (gfloat) i);
1527 		}
1528 	if (i != _GK.theme_alternative)
1529 		{
1530 		_GK.theme_alternative = i;
1531 		theme_modified = TRUE;
1532 		gkrellm_build();
1533 		}
1534 	}
1535 
1536 static void
cb_theme_scale_changed(GtkWidget * widget,GtkSpinButton * spin)1537 cb_theme_scale_changed(GtkWidget *widget, GtkSpinButton *spin)
1538 	{
1539 	gint	i;
1540 
1541 	i = gtk_spin_button_get_value_as_int(spin);
1542 	if (i != _GK.theme_scale)
1543 		{
1544 		_GK.theme_scale = i;
1545 		theme_modified = TRUE;
1546 		gkrellm_build();
1547 		}
1548 	}
1549 
1550 void
gkrellm_set_theme_alternatives_label(void)1551 gkrellm_set_theme_alternatives_label(void)
1552 	{
1553 	GtkSpinButton	*spin;
1554 	gchar			buf[64];
1555 
1556 	if (!config_window)
1557 		return;
1558 	spin = GTK_SPIN_BUTTON(theme_alt_spin_button);
1559 	gtk_spin_button_set_value(spin, (gfloat) _GK.theme_alternative);
1560 	snprintf(buf, sizeof(buf), _("%d total theme alternatives"),
1561 					_GK.theme_n_alternatives);
1562 	gtk_label_set_text(GTK_LABEL(theme_alt_label), buf);
1563 	}
1564 
1565 void
gkrellm_save_theme_config(void)1566 gkrellm_save_theme_config(void)
1567 	{
1568 	FILE	*f;
1569 	gchar	*path;
1570 
1571 	/* Assume gkrellm -t is for testing and don't save theme config changes.
1572 	|  Similarly for _GK.demo.
1573 	*/
1574 	if (!theme_modified || _GK.command_line_theme || _GK.demo || _GK.no_config)
1575 		return;
1576 
1577 	path = gkrellm_make_config_file_name(gkrellm_homedir(),
1578 					GKRELLM_THEME_CONFIG);
1579 
1580 	if ((f = g_fopen(path, "w")) != NULL)
1581 		{
1582 		fprintf(f, "%s\n", _GK.theme_path);
1583 		fprintf(f, "%d\n", _GK.theme_alternative);
1584 		fprintf(f, "%s\n", large_font.string);
1585 		fprintf(f, "%s\n", normal_font.string);
1586 		fprintf(f, "%s\n", small_font.string);
1587 		fprintf(f, "%d\n", _GK.theme_scale);
1588 		fclose(f);
1589 		}
1590 	g_free(path);
1591 	theme_modified = FALSE;
1592 	}
1593 
1594 void
gkrellm_load_theme_config(void)1595 gkrellm_load_theme_config(void)
1596 	{
1597 	FILE	*f;
1598 	gchar	*path, *s;
1599 	gchar	buf[1024];
1600 	gint	i;
1601 
1602 	/* Need to load the theme from ~/.gkrellm/theme_config only at startup
1603 	|  or if re-reading because of theme_event - these are only times
1604 	|  _GK.theme_path will be NULL.  Note: _GK.theme_path will not be NULL
1605 	|  at startup if there is a command line theme, so no theme scaling if
1606 	|  using command line theme.
1607 	*/
1608 	if (!_GK.theme_path)
1609 		{
1610 		path = gkrellm_make_config_file_name(gkrellm_homedir(),
1611 					GKRELLM_THEME_CONFIG);
1612 		f = g_fopen(path, "r");
1613 		g_free(path);
1614 		if (f && fgets(buf, sizeof(buf), f))
1615 			{
1616 			if ((s = strchr(buf, (gint) '\n')) != NULL)
1617 				*s = '\0';
1618 			gkrellm_debug(DEBUG_GUI, "gkrellm_load_theme_config: %s\n", buf);
1619 			s = buf;
1620 			if (s && *s != '#' && *s != '\0' && strcmp(s, "Default"))
1621 				{
1622 				if (*s == '/' || s[1] == ':')
1623 					_GK.theme_path = g_strdup(s);
1624 			  	else
1625 					_GK.theme_path = g_strdup_printf("%s/%s/%s",
1626 							gkrellm_homedir(), GKRELLM_THEMES_DIR, s);
1627 				}
1628 			for (i = 0; fgets(buf, sizeof(buf), f); ++i)
1629 				{
1630 				if ((s = strchr(buf, (gint) '\n')) != NULL)
1631 					*s = '\0';
1632 				gkrellm_debug(DEBUG_GUI, "gkrellm_load_theme_config: %s\n", buf);
1633 				if (i == 0)
1634 					sscanf(buf, "%d", &_GK.theme_alternative);
1635 				if (i == 1 && !strstr(buf, "*-*"))	/* XXX Trap out GdkFont */
1636 					gkrellm_dup_string(&large_font.string, buf);
1637 				if (i == 2 && !strstr(buf, "*-*"))
1638 					gkrellm_dup_string(&normal_font.string, buf);
1639 				if (i == 3 && !strstr(buf, "*-*"))
1640 					gkrellm_dup_string(&small_font.string, buf);
1641 				if (i == 4)
1642 					sscanf(buf, "%d", &_GK.theme_scale);
1643 				}
1644 			}
1645 		if (f)
1646 			fclose(f);
1647 		}
1648 	if (!_GK.theme_path || !g_file_test(_GK.theme_path, G_FILE_TEST_IS_DIR))
1649 		gkrellm_dup_string(&_GK.theme_path, "");
1650 	if (!large_font.string)
1651 		gkrellm_dup_string(&large_font.string, "Serif 11");
1652 	if (!normal_font.string)
1653 		gkrellm_dup_string(&normal_font.string, "Serif 9");
1654 	if (!small_font.string)
1655 		gkrellm_dup_string(&small_font.string, "Serif 8");
1656 	}
1657 
1658 
1659 void
gkrellm_read_theme_event(GtkSettings * settings)1660 gkrellm_read_theme_event(GtkSettings  *settings)
1661 	{
1662 	Theme	*theme;
1663 	gchar	*s, *theme_name = NULL;
1664 	gint	alt = 0;
1665 
1666 	if (settings)	/* called via "notify::gtk-theme-name" signal connect, */
1667 					/* so get the current gtk theme name and switch to it  */
1668 		{
1669 		g_object_get(_GK.gtk_settings, "gtk-theme-name", &theme_name, NULL);
1670 		if (theme_name)
1671 			gkrellm_debug(DEBUG_GUI, "notify::gtk-theme-name: %s\n", theme_name);
1672 
1673 		if (   gkrellm_dup_string(&_GK.gtk_theme_name, theme_name)
1674 			&& _GK.track_gtk_theme_name
1675 		   )
1676 			{
1677 			theme = find_theme_in_list(theme_name);
1678 			if (!theme)
1679 				{
1680 				theme_name = g_strdup(_GK.default_track_theme);
1681 				if ((s = strrchr(theme_name, ':')) != NULL)
1682 					{
1683 					*s++ = '\0';
1684 					alt = atoi(s);
1685 					}
1686 				theme = find_theme_in_list(theme_name);
1687 				g_free(theme_name);
1688 				}
1689 			if (   theme && theme->path
1690 				&& gkrellm_dup_string(&_GK.theme_path,
1691 							strcmp(theme->path, "Default") ? theme->path : "")
1692 			   )
1693 				{
1694 				_GK.theme_alternative = alt;
1695 				theme_modified = TRUE;
1696 				gkrellm_save_theme_config();
1697 				gkrellm_build();
1698 				}
1699 			}
1700 		}
1701 	else		/* Called from cb_client_event() because we were sent the    */
1702 				/* _GKRELLM_READ_THEME client event, so reread theme config. */
1703 		{
1704 		g_free(_GK.theme_path);
1705 		_GK.theme_path = NULL;	/* Forces reread of GKRELLM_THEME_CONFIG */
1706 		gkrellm_build();
1707 		}
1708 	}
1709 
1710 static void
cb_load_theme(GtkAction * action,GtkWidget * widget)1711 cb_load_theme(GtkAction *action, GtkWidget *widget)
1712 	{
1713 	GtkTreeIter		iter;
1714 	GtkTreeModel	*model;
1715 	GtkTreePath		*path;
1716 	Theme			*theme;
1717 	gint			row;
1718         const gchar *act = gtk_action_get_name(action);
1719 
1720 	++_GK.theme_reload_count;
1721 	if (_GK.no_config)
1722 		return;
1723 	if (!themes_list)
1724 		gkrellm_make_themes_list();
1725 	if (strcmp(act, "ThemeAltNextAction") == 0 || strcmp(act, "ThemeAltPrevAction") == 0)
1726 		{
1727 		_GK.theme_alternative += ((strcmp(act, "ThemeAltNextAction") == 0) ? 1 : -1);
1728 		if (_GK.theme_alternative > _GK.theme_n_alternatives)
1729 			{
1730 			_GK.theme_alternative = 0;
1731 			act = "ThemeNextAction";
1732 			}
1733 		if (_GK.theme_alternative < 0)
1734 			{
1735 			_GK.theme_alternative = 100;
1736 			act = "ThemePrevAction";
1737 			}
1738 		theme_modified = TRUE;
1739 		}
1740 
1741 	if (strcmp(act, "ThemeNextAction") == 0 || strcmp(act, "ThemePrevAction") == 0)
1742 		{
1743 		_GK.theme_alternative = 0;
1744 		if (strcmp(act, "ThemeNextAction") == 0)
1745 			{
1746 			theme_position_in_list = theme_position_in_list->next;
1747 			if (!theme_position_in_list)
1748 				theme_position_in_list = themes_list;
1749 			}
1750 		else
1751 			{
1752 			theme_position_in_list = theme_position_in_list->prev;
1753 			if (!theme_position_in_list)
1754 				theme_position_in_list = g_list_last(themes_list);
1755 			}
1756 		if (config_window)
1757 			{
1758 			row = g_list_position(themes_list, theme_position_in_list);
1759 			model = gtk_tree_view_get_model(theme_treeview);
1760 			gtk_tree_model_iter_nth_child(model, &iter, NULL, row);
1761 			path = gtk_tree_model_get_path(model, &iter);
1762 			gtk_tree_view_set_cursor(theme_treeview, path, NULL, FALSE);
1763 			return;		/* cb_theme_tree_selection_changed -> gkrellm_build()*/
1764 			}
1765 		theme = (Theme *) theme_position_in_list->data;
1766 		gkrellm_dup_string(&_GK.theme_path,
1767 					strcmp(theme->path, "Default") ? theme->path : "");
1768 		theme_modified = TRUE;
1769 		}
1770 	if (strcmp(act, "ThemeScaleUp") == 0 && _GK.theme_scale < 380)
1771 		{
1772 		_GK.theme_scale += 20;
1773 		theme_modified = TRUE;
1774 		}
1775 	else if (strcmp(act, "ThemeScaleDn") == 0 && _GK.theme_scale > 50)
1776 		{
1777 		_GK.theme_scale -= 20;
1778 		theme_modified = TRUE;
1779 		}
1780 	gkrellm_build();
1781 	}
1782 
1783 static void
destroy_font_dialogs(void)1784 destroy_font_dialogs(void)
1785 	{
1786 	if (large_font.fontseldlg)
1787 		gtk_widget_destroy(GTK_WIDGET(large_font.fontseldlg));
1788 	if (normal_font.fontseldlg)
1789 		gtk_widget_destroy(GTK_WIDGET(normal_font.fontseldlg));
1790 	if (small_font.fontseldlg)
1791 		gtk_widget_destroy(GTK_WIDGET(small_font.fontseldlg));
1792 	}
1793 
1794 static void
close_theme_config(gint from_close)1795 close_theme_config(gint from_close)
1796 	{
1797 	destroy_font_dialogs();
1798 	}
1799 
1800 static void
cb_font_entry_activate(GtkWidget * widget,gpointer * data)1801 cb_font_entry_activate(GtkWidget *widget, gpointer *data)
1802 	{
1803 	if (!get_font_entries())
1804 		return;
1805 	theme_modified = TRUE;
1806 	gkrellm_build();
1807 	}
1808 
1809 static void
cb_font_entry_changed(GtkWidget * widget,gpointer * data)1810 cb_font_entry_changed(GtkWidget *widget, gpointer *data)
1811 	{
1812 	theme_modified = TRUE;
1813 	}
1814 
1815 gfloat
gkrellm_get_theme_scale(void)1816 gkrellm_get_theme_scale(void)
1817 	{
1818 	return (gfloat) (_GK.theme_scale) / 100.0;
1819 	}
1820 
1821 #ifndef WIN32
1822 static void
cb_track_gtk(GtkToggleButton * button,GtkWidget * box)1823 cb_track_gtk(GtkToggleButton *button, GtkWidget *box)
1824 	{
1825 	_GK.track_gtk_theme_name = button->active;
1826 	gtk_widget_set_sensitive(box, _GK.track_gtk_theme_name);
1827 	}
1828 
1829 static void
cb_track_entry_changed(GtkWidget * widget,gpointer * data)1830 cb_track_entry_changed(GtkWidget *widget, gpointer *data)
1831 	{
1832 	gchar	*s;
1833 
1834 	s = gkrellm_gtk_entry_get_text(&widget);
1835 	gkrellm_dup_string(&_GK.default_track_theme, s);
1836 	gkrellm_config_modified();
1837 	}
1838 #endif // !WIN32
1839 
1840 static void
create_theme_tab(GtkWidget * tabs_vbox)1841 create_theme_tab(GtkWidget *tabs_vbox)
1842 	{
1843 	GtkWidget		*tabs;
1844 	GtkWidget		*vbox, *vbox1, *vbox2, *hbox;
1845 	GtkWidget		*label;
1846 #if !defined(WIN32)
1847 	GtkWidget		*entry;
1848 #endif // !WIN32
1849 	GtkWidget		*scrolled;
1850 	GtkTreeModel	*model;
1851 	GtkCellRenderer	*renderer;
1852 	gchar			*s;
1853 
1854 	tabs = gtk_notebook_new();
1855 	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
1856 	gtk_box_pack_start(GTK_BOX(tabs_vbox), tabs, TRUE, TRUE, 0);
1857 
1858 /* --Theme tab */
1859 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Theme"));
1860 
1861 	hbox = gtk_hbox_new (FALSE, 0);
1862 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1863 	label = gtk_label_new(_("Theme:"));
1864 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 3);
1865 	theme_entry = gtk_entry_new();
1866 	gtk_entry_set_max_length(GTK_ENTRY(theme_entry), 128);
1867 	if (_GK.theme_path)
1868 		gtk_entry_set_text(GTK_ENTRY(theme_entry), _GK.theme_path);
1869 	gtk_box_pack_start(GTK_BOX(hbox), theme_entry, TRUE, TRUE,0);
1870 
1871 	hbox = gtk_hbox_new (FALSE, 0);
1872 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1873 	label = gtk_label_new(_("Author:"));
1874 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 3);
1875 	author_label = gtk_label_new(get_theme_author(_GK.theme_path));
1876 	gtk_misc_set_alignment(GTK_MISC(author_label), 0, 0.5);
1877 	gtk_box_pack_start(GTK_BOX(hbox), author_label, TRUE, TRUE, 5);
1878 
1879 	vbox1 = gkrellm_gtk_framed_vbox(vbox, NULL, 4, TRUE, 0, 2);
1880 	scrolled = gtk_scrolled_window_new(NULL, NULL);
1881 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1882 			GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1883 	gtk_box_pack_start(GTK_BOX(vbox1), scrolled, TRUE, TRUE, 0);
1884 
1885 	model = theme_create_model();
1886 	theme_treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
1887 	g_object_unref(G_OBJECT(model));
1888 	gtk_tree_view_set_rules_hint(theme_treeview, TRUE);
1889 	renderer = gtk_cell_renderer_text_new();
1890 	gtk_tree_view_insert_column_with_attributes(theme_treeview, -1,
1891 				_("Theme"), renderer,
1892 				"text", THEME_COLUMN, NULL);
1893 	gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(theme_treeview));
1894 	theme_selection = gtk_tree_view_get_selection(theme_treeview);
1895 	gtk_tree_selection_set_mode(theme_selection, GTK_SELECTION_SINGLE);
1896 	g_signal_connect(G_OBJECT(theme_selection), "changed",
1897 				G_CALLBACK(cb_theme_tree_selection_changed), NULL);
1898 
1899 	hbox = gtk_hbox_new (FALSE, 0);
1900 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
1901 	gkrellm_gtk_spin_button(hbox, &theme_alt_spin_button,
1902 			(gfloat)_GK.theme_alternative, 0.0, 100.0, 1.0, 5.0, 0, 60,
1903 			cb_theme_alternative_changed, NULL, FALSE, NULL);
1904 	theme_alt_label = gtk_label_new("");
1905 	gtk_box_pack_start (GTK_BOX (hbox), theme_alt_label, TRUE, TRUE, 4);
1906 	gtk_misc_set_alignment(GTK_MISC(theme_alt_label), 0, 0.5);
1907 	gkrellm_set_theme_alternatives_label();
1908 
1909 
1910 /* -- Options tab */
1911 	vbox = gkrellm_gtk_notebook_page(tabs, _("Options"));
1912 	vbox = gkrellm_gtk_framed_vbox(vbox, NULL, 2, TRUE, 10, 4);
1913 
1914 #if !defined(WIN32)
1915 	vbox1 = gtk_vbox_new(FALSE, 0);
1916 	gkrellm_gtk_check_button_connected(vbox, &track_gtk_button,
1917 			_GK.track_gtk_theme_name, FALSE, FALSE, 0,
1918 			cb_track_gtk, vbox1,
1919 			_("Track Gtk theme changes for similarly named themes"));
1920 	gtk_widget_set_sensitive(vbox1, _GK.track_gtk_theme_name);
1921 	gtk_box_pack_start(GTK_BOX(vbox), vbox1, FALSE, FALSE, 0);
1922 
1923 	vbox1 = gkrellm_gtk_category_vbox(vbox1, NULL, 0, 0, TRUE);
1924 	hbox = gtk_hbox_new(FALSE, 0);
1925 	gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
1926 	label = gtk_label_new(_("Default"));
1927 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1928 	entry = gtk_entry_new();
1929 	gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
1930 	gtk_entry_set_text(GTK_ENTRY(entry), _GK.default_track_theme);
1931 	g_signal_connect(G_OBJECT(entry), "changed",
1932 				G_CALLBACK(cb_track_entry_changed), NULL);
1933 
1934 #endif // !WIN32
1935 
1936 	hbox = gtk_hbox_new (FALSE, 0);
1937 	gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
1938 	gkrellm_gtk_spin_button(hbox, NULL,
1939 			(gfloat)_GK.theme_scale, 40.0, 400.0, 10.0, 20.0, 0, 60,
1940 			cb_theme_scale_changed, NULL, FALSE, NULL);
1941 	label = gtk_label_new(_("Scale"));
1942 	gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 4);
1943 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1944 
1945 
1946 /* --Fonts tab */
1947 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Fonts"));
1948 	vbox1 = gkrellm_gtk_framed_vbox(vbox, NULL, 2, FALSE, 0, 2);
1949 
1950 	vbox2 = gkrellm_gtk_framed_vbox(vbox1, _("Large font"), 4, FALSE, 0, 3);
1951 	hbox = gtk_hbox_new(FALSE, 0);
1952 	gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);
1953 
1954 	large_font.entry = gtk_entry_new();
1955 	gtk_box_pack_start(GTK_BOX(hbox), large_font.entry, TRUE, TRUE, 0);
1956 	gtk_entry_set_text(GTK_ENTRY(large_font.entry), large_font.string);
1957 	g_signal_connect(G_OBJECT(large_font.entry), "changed",
1958 			G_CALLBACK(cb_font_entry_changed), NULL);
1959 	g_signal_connect(G_OBJECT(large_font.entry), "activate",
1960 			G_CALLBACK(cb_font_entry_activate), NULL);
1961 	gkrellm_gtk_button_connected(hbox, &large_font.browse_button, FALSE, FALSE,
1962 			0, cb_font_dialog, &large_font, _("Browse"));
1963 
1964 	vbox2 = gkrellm_gtk_framed_vbox(vbox1, _("Normal font"), 4, FALSE, 0, 3);
1965 	hbox = gtk_hbox_new(FALSE, 0);
1966 	gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);
1967 	normal_font.entry = gtk_entry_new();
1968 	gtk_box_pack_start(GTK_BOX(hbox), normal_font.entry, TRUE, TRUE, 0);
1969 	gtk_entry_set_text(GTK_ENTRY(normal_font.entry), normal_font.string);
1970 	g_signal_connect(G_OBJECT(normal_font.entry), "changed",
1971 			G_CALLBACK(cb_font_entry_changed), NULL);
1972 	g_signal_connect(G_OBJECT(normal_font.entry), "activate",
1973 			G_CALLBACK(cb_font_entry_activate), NULL);
1974 	gkrellm_gtk_button_connected(hbox, &normal_font.browse_button,
1975 			FALSE, FALSE, 0, cb_font_dialog, &normal_font,
1976 			_("Browse"));
1977 
1978 	vbox2 = gkrellm_gtk_framed_vbox(vbox1, _("Small font"), 4, FALSE, 0, 3);
1979 	hbox = gtk_hbox_new(FALSE, 0);
1980 	gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);
1981 	small_font.entry = gtk_entry_new();
1982 	gtk_box_pack_start(GTK_BOX(hbox), small_font.entry, TRUE, TRUE, 0);
1983 	gtk_entry_set_text(GTK_ENTRY(small_font.entry), small_font.string);
1984 	g_signal_connect(G_OBJECT(small_font.entry), "changed",
1985 			G_CALLBACK(cb_font_entry_changed), NULL);
1986 	g_signal_connect(G_OBJECT(small_font.entry), "activate",
1987 			G_CALLBACK(cb_font_entry_activate), NULL);
1988 	gkrellm_gtk_button_connected(hbox, &small_font.browse_button, FALSE, FALSE,
1989 			0, cb_font_dialog, &small_font, _("Browse"));
1990 
1991 	/* --Info tab*/
1992 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Info"));
1993 	s = g_strdup_printf(_("Untar your theme tar files in %s/%s"),
1994 						gkrellm_homedir(), GKRELLM_THEMES_DIR);
1995 	label = gtk_label_new(s);
1996 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
1997 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1998 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
1999 	g_free(s);
2000 
2001 	label = gtk_label_new(
2002 			_("Download themes from the GKrellM theme site at www.muhri.net"));
2003 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
2004 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
2005 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
2006 
2007 
2008 	}
2009 
2010 
2011 /* ================================================================ */
2012 /* A simple tree store model for selecting monitor configs.
2013 */
2014 enum
2015 	{
2016 	NAME_COLUMN,
2017 	MONITOR_COLUMN,
2018 	PAGE_COLUMN,
2019 	N_COLUMNS
2020 	};
2021 
2022 static GtkNotebook	*config_notebook;
2023 
2024 static gboolean		expand_builtins,
2025 					expand_plugins;
2026 
2027 static GtkTreeView	*treeview;
2028 static GtkTreeStore	*model;
2029 
2030 static GtkWidget	*apply_button,
2031 					*close_button;
2032 
2033 static GkrellmMonitor	*selected_monitor;
2034 
2035 static void
close_config(gpointer data)2036 close_config(gpointer data)
2037 	{
2038 	GtkTreePath	*path;
2039 	gint		from_close	= GPOINTER_TO_INT(data);
2040 
2041 	path = gtk_tree_path_new_from_string("1");
2042 	expand_builtins = gtk_tree_view_row_expanded(treeview, path);
2043 	gtk_tree_path_free(path);
2044 
2045 	path = gtk_tree_path_new_from_string("2");
2046 	expand_plugins = gtk_tree_view_row_expanded(treeview, path);
2047 	gtk_tree_path_free(path);
2048 
2049 	g_object_unref(G_OBJECT(model));
2050 	gtk_widget_destroy(config_window);
2051 	config_window = NULL;
2052 
2053 	gkrellm_plugins_config_close();
2054 	close_theme_config(from_close);
2055 	if (_GK.config_modified)
2056 		gkrellm_save_user_config();
2057 	gkrellm_save_theme_config();
2058 	}
2059 
2060 
2061 static void
apply_config(void)2062 apply_config(void)
2063 	{
2064 	GList	*list;
2065 	GkrellmMonitor	*mon;
2066 
2067 	gkrellm_freeze_side_frame_packing();
2068 	for (list = gkrellm_monitor_list; list; list = list->next)
2069 		{
2070 		mon = (GkrellmMonitor *) list->data;
2071 		if (   mon->apply_config && mon->privat->enabled
2072 			&& (mon->privat->config_created || !mon->create_config)
2073 		   )
2074 			{
2075 			gkrellm_record_state(APPLY_CONFIG, mon);
2076 			(*(mon->apply_config))();
2077 			gkrellm_record_state(INTERNAL, NULL);
2078 			}
2079 		}
2080 	gkrellm_thaw_side_frame_packing();
2081 	gkrellm_config_modified();
2082 	}
2083 
2084 static void
OK_config(void)2085 OK_config(void)
2086 	{
2087 	apply_config();
2088 	close_config(GINT_TO_POINTER(0));
2089 	}
2090 
2091 
2092 static GtkWidget *
create_config_page(GkrellmMonitor * mon,GtkTreeStore * tree,GtkTreeIter * iter,GtkNotebook * notebook)2093 create_config_page(GkrellmMonitor *mon, GtkTreeStore *tree, GtkTreeIter *iter,
2094 			GtkNotebook *notebook)
2095 	{
2096 	GtkWidget	*vbox;
2097 	gint		page;
2098 
2099 	vbox = gtk_vbox_new(FALSE, 0);
2100 	gtk_notebook_append_page(notebook, vbox, NULL);
2101 	page = g_list_length(notebook->children) - 1;
2102 
2103 	if (mon)
2104 		mon->privat->config_page = page;
2105 
2106 	gtk_tree_store_set(tree, iter,
2107 			MONITOR_COLUMN, mon,
2108 			PAGE_COLUMN, page,
2109 			-1);
2110 
2111 	gkrellm_debug(DEBUG_GUI, "create_config_page %d: %s\n", page,
2112 		mon ? mon->name : "--");
2113 
2114 	return vbox;
2115 	}
2116 
2117 static void
real_create_config(GkrellmMonitor * mon)2118 real_create_config(GkrellmMonitor *mon)
2119 	{
2120 	if (mon->privat->config_created || !mon->create_config)
2121 		return;
2122 
2123 	gkrellm_record_state(CREATE_CONFIG, mon);
2124 	(*(mon->create_config))(mon->privat->config_vbox);
2125 	gkrellm_record_state(INTERNAL, NULL);
2126 
2127 	gtk_widget_show_all(mon->privat->config_vbox);
2128 	mon->privat->config_created = TRUE;
2129 	}
2130 
2131 void
gkrellm_add_plugin_config_page(GkrellmMonitor * mon)2132 gkrellm_add_plugin_config_page(GkrellmMonitor *mon)
2133 	{
2134 	GtkTreeIter		iter, plugin_iter;
2135 	GtkTreePath		*path;
2136 
2137 	if (config_window && mon->create_config)
2138 		{
2139 		path = gtk_tree_path_new_from_string("2");
2140 		gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &plugin_iter, path);
2141 		gtk_tree_path_free(path);
2142 
2143 		gtk_tree_store_append(model, &iter, &plugin_iter);
2144 		gtk_tree_store_set(model, &iter, NAME_COLUMN, mon->name, -1);
2145 		mon->privat->config_vbox =
2146 					create_config_page(mon, model, &iter, config_notebook);
2147 		mon->privat->config_created = FALSE;
2148 
2149 		mon->privat->row_reference =
2150 			gtk_tree_row_reference_new(GTK_TREE_MODEL(model),
2151 					gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter));
2152 		}
2153 	else
2154 		mon->privat->config_page = -1;
2155 	}
2156 
2157 void
gkrellm_remove_plugin_config_page(GkrellmMonitor * mon)2158 gkrellm_remove_plugin_config_page(GkrellmMonitor *mon)
2159 	{
2160 	GtkTreePath		*path;
2161 	GtkTreeIter		iter;
2162 	GList			*list;
2163 	GkrellmMonitor	*tmon;
2164 
2165 	if (mon->privat->config_page > 0)
2166 		{
2167 		path = gtk_tree_row_reference_get_path(mon->privat->row_reference);
2168 		gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
2169 		gtk_tree_store_remove(model, &iter);
2170 
2171 		gtk_notebook_remove_page(config_notebook, mon->privat->config_page);
2172 
2173 		/* When a config_page is removed, any greater plugin config_page must
2174 		|  be decremented
2175 		*/
2176 		for (list = gkrellm_monitor_list; list; list = list->next)
2177 			{
2178 			tmon = (GkrellmMonitor *) list->data;
2179 			if (mon->privat->config_page >= tmon->privat->config_page)
2180 				continue;
2181 			tmon->privat->config_page -= 1;
2182 			gkrellm_debug(DEBUG_GUI, "config_page %d: %s\n",
2183 						tmon->privat->config_page,  tmon->name);
2184 			}
2185 		}
2186 	mon->privat->config_page = -1;
2187 	}
2188 
2189   /* If a config page uses instant apply, hide the APPLY/CLOSE buttons and
2190   |  assume the config will be modified.
2191   */
2192 static void
set_apply_mode(gboolean instant)2193 set_apply_mode(gboolean instant)
2194 	{
2195 	if (instant)
2196 		{
2197 		gtk_widget_hide(apply_button);
2198 		gtk_widget_hide(close_button);
2199 		gkrellm_config_modified();
2200 		}
2201 	else
2202 		{
2203 		gtk_widget_show(apply_button);
2204 		gtk_widget_show(close_button);
2205 		}
2206 	}
2207 
2208 static void
cb_tree_selection_changed(GtkTreeSelection * selection,gpointer data)2209 cb_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
2210 	{
2211 	GtkTreeIter		iter;
2212 	GtkTreeModel	*model;
2213 	gint			page;
2214 	gboolean		instant;
2215 
2216 	if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2217 		return;
2218 	if (selected_monitor && selected_monitor->apply_config)
2219 		{
2220 		gkrellm_record_state(APPLY_CONFIG, selected_monitor);
2221 		(*(selected_monitor->apply_config))();
2222 		gkrellm_record_state(INTERNAL, NULL);
2223 		}
2224 	gtk_tree_model_get(model, &iter,
2225 				MONITOR_COLUMN, &selected_monitor,
2226 				PAGE_COLUMN, &page,
2227 				-1);
2228 	if (selected_monitor && selected_monitor->privat)
2229 		{
2230 		page = selected_monitor->privat->config_page;
2231 		real_create_config(selected_monitor);
2232 		if (selected_monitor == gkrellm_get_sensors_mon())
2233 			{	/* Special case dependencies in the configs */
2234 			real_create_config(gkrellm_get_cpu_mon());
2235 			real_create_config(gkrellm_get_proc_mon());
2236 			}
2237 		instant = (   selected_monitor->apply_config == NULL
2238 				   || selected_monitor->privat->instant_apply);
2239 		}
2240 	else
2241 		instant = TRUE;
2242 
2243 	set_apply_mode(instant);
2244 
2245 	gtk_notebook_set_current_page(config_notebook, page);
2246 	gkrellm_debug(DEBUG_GUI, "tree_selection_changed %d: %s\n",
2247 					page, selected_monitor ? selected_monitor->name : "--");
2248 	}
2249 
2250   /* Monitors may want to present as instant apply monitors, but still need
2251   |  their apply function called when changing notebook pages or on OK button.
2252   */
2253 void
gkrellm_config_instant_apply(GkrellmMonitor * mon)2254 gkrellm_config_instant_apply(GkrellmMonitor *mon)
2255 	{
2256 	mon->privat->instant_apply = TRUE;
2257 	}
2258 
2259 gboolean
gkrellm_config_window_shown(void)2260 gkrellm_config_window_shown(void)
2261 	{
2262 	return config_window ? TRUE : FALSE;
2263 	}
2264 
2265 void
create_config_window(void)2266 create_config_window(void)
2267 	{
2268 	GtkWidget			*widget,
2269 						*vbox,
2270 						*main_vbox,
2271 						*config_hbox,
2272 						*hbox;
2273 	GtkWidget			*scrolled;
2274 	GtkWidget			*button;
2275 	GtkTreeIter			iter, citer;
2276 	GtkTreePath			*path;
2277 	GtkCellRenderer		*renderer;
2278 	GtkTreeViewColumn	*column;
2279 	GtkTreeSelection	*select;
2280 	GList				*list;
2281 	GkrellmMonitor		*mon;
2282 	gchar				*config_name, *window_title;
2283 
2284 	if (config_window)
2285 		{
2286 		gtk_window_present(GTK_WINDOW(config_window));
2287 		return;
2288 		}
2289 	selected_monitor = NULL;
2290 
2291 	config_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2292 	g_signal_connect(G_OBJECT(config_window), "delete_event",
2293 			G_CALLBACK(close_config), GINT_TO_POINTER(1));
2294 
2295 	config_name = gkrellm_make_config_file_name(NULL, "GKrellM");
2296 	window_title = g_strdup_printf("%s %s", config_name, _("Configuration"));
2297 	gtk_window_set_title(GTK_WINDOW(config_window), window_title);
2298 	g_free(config_name);
2299 	g_free(window_title);
2300 
2301 	gtk_window_set_wmclass(GTK_WINDOW(config_window),
2302 					"Gkrellm_conf", "Gkrellm");
2303 	gtk_container_set_border_width(GTK_CONTAINER(config_window), 2);
2304 
2305 	config_hbox = gtk_hbox_new(FALSE, 4);
2306 	gtk_container_add(GTK_CONTAINER(config_window), config_hbox);
2307 
2308 	scrolled = gtk_scrolled_window_new(NULL, NULL);
2309 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2310 			GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2311 	gtk_box_pack_start(GTK_BOX(config_hbox), scrolled, FALSE, FALSE, 0);
2312 
2313 	main_vbox = gtk_vbox_new(FALSE, 4);
2314 	gtk_box_pack_start(GTK_BOX(config_hbox), main_vbox, TRUE, TRUE, 0);
2315 
2316 	widget = gtk_notebook_new();
2317 	gtk_box_pack_start(GTK_BOX(main_vbox), widget, TRUE, TRUE, 0);
2318 	config_notebook = GTK_NOTEBOOK(widget);
2319 	gtk_notebook_set_show_tabs(config_notebook, FALSE);
2320 
2321 	model = gtk_tree_store_new(N_COLUMNS,
2322 				G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
2323 	gtk_tree_store_append(model, &iter, NULL);
2324 	gtk_tree_store_set(model, &iter, NAME_COLUMN, _("General"), -1);
2325 	vbox = create_config_page(NULL, model, &iter, config_notebook);
2326 	create_general_tab(vbox);
2327 
2328 	gtk_tree_store_append(model, &iter, NULL);
2329 	gtk_tree_store_set(model, &iter, NAME_COLUMN, _("Builtins"), -1);
2330 	vbox = create_config_page(NULL, model, &iter, config_notebook);
2331 
2332 	for (list = gkrellm_monitor_list; list; list = list->next)
2333 		{
2334 		mon = (GkrellmMonitor *) list->data;
2335 		if (MONITOR_ID(mon) == MON_PLUGIN || ! mon->create_config)
2336 			continue;
2337 
2338 		gtk_tree_store_append(model, &citer, &iter);
2339 		gtk_tree_store_set(model, &citer, NAME_COLUMN, mon->name, -1);
2340 		mon->privat->config_vbox =
2341 					create_config_page(mon, model, &citer, config_notebook);
2342 		mon->privat->config_created = FALSE;
2343 		mon->privat->row_reference =
2344 			gtk_tree_row_reference_new(GTK_TREE_MODEL(model),
2345 					gtk_tree_model_get_path(GTK_TREE_MODEL(model), &citer));
2346 		}
2347 
2348 	gtk_tree_store_append(model, &iter, NULL);
2349 	gtk_tree_store_set(model, &iter, NAME_COLUMN, _("Plugins"), -1);
2350 	vbox = create_config_page(NULL, model, &iter, config_notebook);
2351 	gkrellm_plugins_config_create(vbox);
2352 
2353 	gtk_tree_store_append(model, &iter, NULL);
2354 	gtk_tree_store_set(model, &iter, NAME_COLUMN, _("Themes"), -1);
2355 	vbox = create_config_page(NULL, model, &iter, config_notebook);
2356 	create_theme_tab(vbox);
2357 
2358 	gtk_tree_store_append(model, &iter, NULL);
2359 	gtk_tree_store_set(model, &iter, NAME_COLUMN, _("About"), -1);
2360 	vbox = create_config_page(NULL, model, &iter, config_notebook);
2361 	create_about_tab(vbox);
2362 
2363 	/* Add plugin notebook pages last since they may need special add/remove
2364 	|  actions as plugins are enabled/disabled.
2365 	*/
2366 	for (list = gkrellm_monitor_list; list; list = list->next)
2367 		{
2368 		mon = (GkrellmMonitor *) list->data;
2369 		if (   ! mon->create_config
2370 			|| ! mon->privat->enabled
2371 			|| MONITOR_ID(mon) != MON_PLUGIN
2372 		   )
2373 			continue;
2374 		gkrellm_add_plugin_config_page(mon);
2375 		}
2376 
2377 	/* Create the tree view and don't unref the model because need to modify
2378 	|  it when enabling plugins
2379 	*/
2380 	treeview =
2381 			GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)));
2382 
2383 	renderer = gtk_cell_renderer_text_new();
2384 	column = gtk_tree_view_column_new_with_attributes(_("Monitors"), renderer,
2385 					"text", NAME_COLUMN, NULL);
2386 	gtk_tree_view_append_column(treeview, column);
2387 	gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
2388 
2389 	select = gtk_tree_view_get_selection(treeview);
2390 	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
2391 	g_signal_connect(G_OBJECT(select), "changed",
2392 				G_CALLBACK(cb_tree_selection_changed), NULL);
2393 
2394 	if (expand_builtins)
2395 		{
2396 		path = gtk_tree_path_new_from_string("1");
2397 		gtk_tree_view_expand_row(treeview, path, TRUE);
2398 		gtk_tree_path_free(path);
2399 		}
2400 	if (expand_plugins)
2401 		{
2402 		path = gtk_tree_path_new_from_string("2");
2403 		gtk_tree_view_expand_row(treeview, path, TRUE);
2404 		gtk_tree_path_free(path);
2405 		}
2406 
2407 	hbox = gtk_hbutton_box_new();
2408 	gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2409 	gtk_box_set_spacing(GTK_BOX(hbox), 5);
2410 	gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0);
2411 
2412 	apply_button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
2413 	GTK_WIDGET_SET_FLAGS(apply_button, GTK_CAN_DEFAULT);
2414 	g_signal_connect(G_OBJECT(apply_button), "clicked",
2415 				G_CALLBACK(apply_config), NULL);
2416 	gtk_box_pack_start(GTK_BOX(hbox), apply_button, TRUE, TRUE, 0);
2417 
2418 	close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
2419 	GTK_WIDGET_SET_FLAGS(close_button, GTK_CAN_DEFAULT);
2420 	g_signal_connect(G_OBJECT(close_button), "clicked",
2421 				G_CALLBACK(close_config), GINT_TO_POINTER(1));
2422 	gtk_box_pack_start(GTK_BOX(hbox), close_button, TRUE, TRUE, 0);
2423 
2424 	button = gtk_button_new_from_stock(GTK_STOCK_OK);
2425 	GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
2426 	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(OK_config), NULL);
2427 	gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
2428 	gtk_widget_grab_default(button);
2429 
2430 	gtk_widget_show_all(config_window);
2431 	}
2432 
2433 void
gkrellm_open_config_window(GkrellmMonitor * mon)2434 gkrellm_open_config_window(GkrellmMonitor *mon)
2435 	{
2436 	GtkTreePath	*path;
2437 
2438 	if (!mon || !mon->create_config || _GK.no_config)
2439 		return;
2440 	create_config_window();
2441 	if (MONITOR_ID(mon) == MON_PLUGIN)
2442 		path = gtk_tree_path_new_from_string("2");
2443 	else
2444 		path = gtk_tree_path_new_from_string("1");
2445 
2446 	gtk_tree_view_expand_row(treeview, path, TRUE);
2447 	gtk_tree_path_free(path);
2448 
2449 	path = gtk_tree_row_reference_get_path(mon->privat->row_reference);
2450 	gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
2451 	}
2452 
2453 static const char *ui_items_no_config = "\
2454 <ui>\
2455   <popup>\
2456     <separator/>\
2457     <menuitem name=\"Quit\" action=\"QuitAction\"/>\
2458     <separator/>\
2459   </popup>\
2460 </ui>\
2461 ";
2462 
2463 static const char *ui_items = "\
2464 <ui>\
2465   <popup accelerators=\"true\">\
2466     <menuitem name=\"Configuration\" action=\"ConfigurationAction\"/>\
2467     <menu name=\"ThemeMenu\" action=\"ThemeMenuAction\">\
2468       <menuitem name=\"ThemeAltNext\" action=\"ThemeAltNextAction\"/>\
2469       <menuitem name=\"ThemeAltPrev\" action=\"ThemeAltPrevAction\"/>\
2470     </menu>\
2471     <separator/>\
2472     <menuitem name=\"Quit\" action=\"QuitAction\"/>\
2473   </popup>\
2474 </ui>\
2475 ";
2476 
2477 /*
2478 static const char *ui_items_debug = "\
2479   <popup>\
2480     <menuitem name=\"ThemeNext\" action=\"ThemeNextAction\"/>\
2481     <menuitem name=\"ThemePrev\" action=\"ThemePrevAction\"/>\
2482     <menuitem name=\"MenuPopup\" action=\"MenuPopupAction\"/>\
2483     <menuitem name=\"ReloadTheme\" action=\"ReloadThemeAction\"/>\
2484     <menuitem name=\"ScaleThemeUp\" action=\"ScaleThemeUpAction\"/>\
2485     <menuitem name=\"ScaleThemeDn\" action=\"ScaleThemeDnAction\"/>\
2486   </popup>\
2487 ";
2488 */
2489 
2490 static GtkActionEntry ui_entries[] =
2491 {
2492     { "QuitAction", NULL, N_("Quit"),
2493       NULL, NULL, G_CALLBACK(gtk_main_quit) },
2494     { "ConfigurationAction", NULL, N_("Configuration"),
2495       "F1", NULL, G_CALLBACK(create_config_window) },
2496     { "ThemeMenuAction", NULL, N_("Theme"),
2497       NULL, NULL, NULL },
2498     { "ThemeAltNextAction", NULL, N_("Next"),
2499       "<shift>Page_Up", NULL, G_CALLBACK(cb_load_theme) },
2500     { "ThemeAltPrevAction", NULL, N_("Prev"),
2501       "<shift>Page_Down", NULL, G_CALLBACK(cb_load_theme) },
2502     { "ThemeNextAction", NULL, N_("Theme next"),
2503       "<control>Page_Up", NULL, G_CALLBACK(cb_load_theme) },
2504     { "ThemePrevAction", NULL, N_("Theme prev"),
2505       "<control>Page_Down", NULL, G_CALLBACK(cb_load_theme) },
2506     { "MenuPopupAction", NULL, N_("Menu Popup"),
2507       "F2", NULL, G_CALLBACK(cb_load_theme) },
2508     { "ReloadThemeAction", NULL, N_("Reload Theme"),
2509       "F5", NULL, G_CALLBACK(cb_load_theme) },
2510     { "ScaleThemeUpAction", NULL, N_("Scale Theme Up"),
2511       "F6", NULL, G_CALLBACK(cb_load_theme) },
2512     { "ScaleThemeDnAction", NULL, N_("Scale Theme Dn"),
2513       "F7", NULL, G_CALLBACK(cb_load_theme) },
2514 };
2515 static guint n_ui_entries = G_N_ELEMENTS (ui_entries);
2516 
2517 GtkUIManager *
gkrellm_create_ui_manager_popup(void)2518 gkrellm_create_ui_manager_popup(void)
2519 	{
2520 	GtkWidget		*top_win;
2521         GtkUIManager *ui_manager;
2522         GtkActionGroup *action_group;
2523         GError *error;
2524 
2525 	top_win = gkrellm_get_top_window();
2526         action_group = gtk_action_group_new ("UiActions");
2527         gtk_action_group_add_actions (action_group, ui_entries, n_ui_entries, NULL);
2528         ui_manager = gtk_ui_manager_new ();
2529         gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
2530         error = NULL;
2531         if (_GK.no_config)
2532             gtk_ui_manager_add_ui_from_string (ui_manager, ui_items_no_config,
2533                                                strlen(ui_items_no_config), &error);
2534         else
2535             gtk_ui_manager_add_ui_from_string (ui_manager, ui_items,
2536                                                strlen(ui_items), &error);
2537         if (error)
2538         {
2539             g_message ("building menus failed: %s", error->message);
2540             g_error_free (error);
2541             return NULL;
2542         }
2543 	gtk_window_add_accel_group(GTK_WINDOW(top_win),
2544                                    gtk_ui_manager_get_accel_group (ui_manager));
2545 
2546 	return ui_manager;
2547 	}
2548 
2549