1 /*
2  * Osmo - a handy personal organizer
3  *
4  * Copyright (C) 2007-2009 Tomasz Mąka <pasp@users.sourceforge.net>
5  *               2007-2009 Piotr Mąka <silloz@users.sourceforge.net>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #include "gui.h"
23 #include "i18n.h"
24 #include "options_prefs.h"
25 #include "stock_icons.h"
26 #include "utils.h"
27 #include "utils_gui.h"
28 /* ========================================================================= */
29 
30 GtkWidget *
utl_gui_create_label(const gchar * format,const gchar * name)31 utl_gui_create_label (const gchar *format, const gchar *name)
32 {
33 	gchar *str = g_strdup_printf (format, name);
34 	GtkWidget *label = gtk_label_new (str);
35 	gtk_widget_set_halign(label, GTK_ALIGN_START);
36 	g_free (str);
37 
38 	return label;
39 }
40 
41 /* ========================================================================= */
42 
43 GtkWidget *
utl_gui_create_window(const gchar * name,gint width,gint height,GUI * appGUI)44 utl_gui_create_window (const gchar *name, gint width, gint height, GUI *appGUI)
45 {
46 	GtkWidget *window;
47 
48 	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
49 	gtk_window_set_title (GTK_WINDOW (window), name);
50 	gtk_window_set_default_size (GTK_WINDOW (window), width, height);
51 	gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ON_PARENT);
52 	gtk_window_set_modal (GTK_WINDOW (window), TRUE);
53 	if (config.fullscreen == FALSE) {
54 		gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (appGUI->main_window));
55 	}
56 	gtk_container_set_border_width (GTK_CONTAINER (window), WINDOW_BORDER);
57 
58 	return window;
59 }
60 
61 /* ========================================================================= */
62 static GtkWidget *
pack_in_frame(GtkWidget * widget,const gchar * frame_name)63 pack_in_frame(GtkWidget *widget, const gchar *frame_name) {
64     GtkWidget *frame, *label;
65 
66     frame = gtk_frame_new(NULL);
67     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
68 
69     label = utl_gui_create_label("<b>%s</b>", frame_name);
70     gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
71     gtk_frame_set_label_widget(GTK_FRAME(frame), label);
72 
73     gtk_container_add(GTK_CONTAINER(frame), widget);
74     gtk_widget_set_margin_left(widget, ALIGNMENT_PADDING_LEFT);
75     gtk_widget_set_margin_right(widget, ALIGNMENT_PADDING_RIGHT);
76     gtk_widget_set_margin_top(widget, ALIGNMENT_PADDING_TOP);
77     gtk_widget_set_margin_bottom(widget, ALIGNMENT_PADDING_BOTTOM);
78 
79     return frame;
80 }
81 
82 /* ========================================================================= */
83 
84 GtkWidget *
utl_gui_create_vbox_in_frame(GtkWidget * container,const gchar * name)85 utl_gui_create_vbox_in_frame (GtkWidget *container, const gchar *name)
86 {
87 	GtkWidget *frame, *box;
88 
89 	box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
90 	frame = pack_in_frame(box, name);
91         gtk_box_pack_start (GTK_BOX (container), frame, FALSE, FALSE, 0);
92 
93 	return box;
94 }
95 
96 /* ========================================================================= */
97 
98 GtkWidget *
utl_gui_create_hbox_in_frame(GtkWidget * container,const gchar * name)99 utl_gui_create_hbox_in_frame (GtkWidget *container, const gchar *name)
100 {
101 	GtkWidget *frame, *box;
102 
103 	box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
104 	frame = pack_in_frame(box, name);
105         gtk_box_pack_start (GTK_BOX (container), frame, FALSE, FALSE, 0);
106 
107 	return box;
108 }
109 
110 /* ========================================================================= */
111 
112 GtkWidget *
utl_gui_create_icon_with_label(const gchar * icon_name,const gchar * label_str)113 utl_gui_create_icon_with_label (const gchar *icon_name, const gchar *label_str)
114 {
115 	GtkWidget *vbox_icon, *image, *label;
116 
117 	vbox_icon = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
118 
119 	image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
120 	gtk_box_pack_start (GTK_BOX (vbox_icon), image, TRUE, TRUE, 0);
121 
122 	label = gtk_label_new (label_str);
123 	gtk_box_pack_start (GTK_BOX (vbox_icon), label, FALSE, FALSE, 0);
124 	gtk_widget_show_all (vbox_icon);
125 
126 	return vbox_icon;
127 }
128 
129 /* ========================================================================= */
130 
131 GtkWidget *
utl_gui_insert_in_scrolled_window(GtkWidget * widget,GtkShadowType type)132 utl_gui_insert_in_scrolled_window (GtkWidget *widget, GtkShadowType type)
133 {
134 	GtkWidget *scrolledwindow, *viewport;
135 
136 	scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
137 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
138 	                                GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
139 
140 	viewport = gtk_viewport_new (NULL, NULL);
141 	gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), type);
142 	gtk_container_add (GTK_CONTAINER (scrolledwindow), viewport);
143 
144 	gtk_container_add (GTK_CONTAINER (viewport), widget);
145 
146 	return scrolledwindow;
147 }
148 
149 /* ========================================================================= */
150 
151 void
utl_gui_font_select_cb(GtkWidget * widget,gpointer user_data)152 utl_gui_font_select_cb (GtkWidget *widget, gpointer user_data)
153 {
154 	GtkWidget *font_selector;
155 	gchar *font_name;
156 	gint response;
157         GtkWindow *parent;
158 
159 	FONT_SEL *sel = (FONT_SEL *) user_data;
160 
161 	g_return_if_fail (sel->config != NULL);
162 
163         if (config.fullscreen) {
164             parent = NULL;
165         } else {
166             parent = GTK_WINDOW(sel->appGUI->main_window);
167         }
168 	font_selector = gtk_font_chooser_dialog_new (_("Select a font..."), parent);
169 	gtk_window_set_modal (GTK_WINDOW (font_selector), TRUE);
170 	gtk_window_set_position (GTK_WINDOW (font_selector), GTK_WIN_POS_MOUSE);
171 	gtk_font_chooser_set_font (GTK_FONT_CHOOSER (font_selector),
172 	                                         sel->config);
173 	gtk_widget_show (font_selector);
174 
175 	response = gtk_dialog_run (GTK_DIALOG (font_selector));
176 
177 	if (response == GTK_RESPONSE_OK) {
178 
179 		font_name = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (font_selector));
180 
181 		if (sel->save == TRUE)
182 			g_strlcpy (sel->config, font_name, MAXFONTNAME);
183 
184 		if (sel->entry != NULL)
185 			gtk_entry_set_text (GTK_ENTRY (sel->entry), font_name);
186 
187 		if (sel->font != NULL) {
188 
189 			pango_font_description_free (*sel->font);
190 			*sel->font = pango_font_description_from_string (font_name);
191 
192 			if (sel->widget != NULL)
193 				gtk_widget_override_font (GTK_WIDGET (sel->widget), *sel->font);
194 
195 		}
196 
197 		g_free (font_name);
198 
199 	}
200 
201 	gtk_widget_destroy (font_selector);
202 }
203 
204 /*------------------------------------------------------------------------------*/
205 
206 gint
utl_gui_get_sw_vscrollbar_width(GtkWidget * scrolled_window)207 utl_gui_get_sw_vscrollbar_width (GtkWidget *scrolled_window)
208 {
209 	GtkWidget *vscrollbar;
210 	GValue *value;
211 	gint width;
212 
213 	value = g_new0 (GValue, 1);
214 	value = g_value_init (value, G_TYPE_INT);
215 
216 	vscrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (scrolled_window));
217 	gtk_widget_style_get_property (vscrollbar, "slider-width", value);
218 	width = g_value_get_int (value);
219 
220 	g_value_unset (value);
221 	g_free (value);
222 
223 	return width;
224 }
225 
226 /*------------------------------------------------------------------------------*/
227 
228 gint
utl_gui_get_combobox_items(GtkComboBox * combo_box)229 utl_gui_get_combobox_items (GtkComboBox *combo_box) {
230     return gtk_tree_model_iter_n_children (gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)), NULL);
231 }
232 
233 /*------------------------------------------------------------------------------*/
234 
235 void
utl_gui_create_category_combobox(GtkComboBox * combo_box,GtkListStore * store,gboolean none)236 utl_gui_create_category_combobox (GtkComboBox *combo_box, GtkListStore *store, gboolean none) {
237 
238 GtkTreeIter iter;
239 gchar *category;
240 gint i, n;
241 gboolean has_next;
242 
243     n = utl_gui_get_combobox_items(combo_box);
244 
245     gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), -1);
246 
247     for (i = n-1; i >= 0; i--) {
248         gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (combo_box), i);
249     }
250 
251     if (none == TRUE) {
252         gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo_box), NULL, _("None"));
253     } else {
254         gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo_box), NULL, _("All items"));
255     }
256 
257     has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
258     while (has_next) {
259         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &category, -1);
260         gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo_box), NULL, category);
261         g_free(category);
262         has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
263     }
264 
265 }
266 
267 /*------------------------------------------------------------------------------*/
268 
269 gint
utl_gui_get_column_position(GtkTreeViewColumn * column,GtkTreeView * treeview,gint M,GUI * appGUI)270 utl_gui_get_column_position (GtkTreeViewColumn *column, GtkTreeView *treeview, gint M, GUI *appGUI) {
271 
272 gint i, n = -1;
273 
274 	for (i = 0; i < M; i++) {
275 		if (gtk_tree_view_get_column (GTK_TREE_VIEW(treeview), i) == column) n = i;
276 	}
277 
278 	return n;
279 }
280 
281 /*------------------------------------------------------------------------------*/
282 
283 gchar *
utl_gui_text_buffer_get_text_with_tags(GtkTextBuffer * buffer)284 utl_gui_text_buffer_get_text_with_tags (GtkTextBuffer *buffer) {
285 
286 GtkTextIter start, prev;
287 GSList *tags = NULL, *i;
288 gchar tag_char_utf8[7] = {0};
289 gchar *text = g_strdup (""), *oldtext = NULL, *tmp;
290 gboolean done = FALSE;
291 gunichar TAG_CHAR = TAG;      /* Unicode chars in the Private Use Area. */
292 
293     gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
294 
295     g_unichar_to_utf8 (TAG_CHAR, tag_char_utf8);
296 
297     prev = start;
298 
299     while (!done)
300     {
301         tmp = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (buffer), &prev, &start, TRUE);
302         oldtext = text;
303         text = g_strconcat (text, tmp, NULL);
304         g_free (oldtext);
305         g_free (tmp);
306 
307         tags = gtk_text_iter_get_toggled_tags (&start, TRUE);
308         for (i = tags; i; i = i->next)
309         {
310             gchar *name;
311             g_object_get (G_OBJECT (i->data), "name", &name, NULL);
312             if (!name) {
313                 continue;
314             }
315             oldtext = text;
316             text = g_strconcat (text, tag_char_utf8, name, tag_char_utf8, NULL);
317             g_free (oldtext);
318             g_free (name);
319         }
320         g_slist_free (tags);
321 
322         tags = gtk_text_iter_get_toggled_tags (&start, FALSE);
323         for (i = tags; i; i = i->next)
324         {
325             gchar *name;
326             g_object_get (G_OBJECT (i->data), "name", &name, NULL);
327             if (!name) {
328                 continue;
329             }
330             oldtext = text;
331             text = g_strconcat (text, tag_char_utf8, "/", name, tag_char_utf8, NULL);
332             g_free (oldtext);
333             g_free (name);
334         }
335         g_slist_free (tags);
336 
337         if (gtk_text_iter_is_end (&start))
338             done = TRUE;
339         prev = start;
340         gtk_text_iter_forward_to_tag_toggle (&start, NULL);
341     }
342 
343     return text;
344 }
345 
346 /*------------------------------------------------------------------------------*/
347 
348 void
utl_gui_text_buffer_set_text_with_tags(GtkTextBuffer * buffer,const gchar * text,gboolean clear)349 utl_gui_text_buffer_set_text_with_tags (GtkTextBuffer *buffer, const gchar *text, gboolean clear) {
350 
351 GtkTextIter start, end;
352 GList *tags = NULL;
353 gchar **tokens;
354 gint count;
355 gchar tag_char_utf8[7] = {0};
356 gunichar TAG_CHAR = TAG;      /* Unicode chars in the Private Use Area. */
357 
358     if (!text)
359         return;
360 
361     gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
362 
363 	if (clear == TRUE) {
364         gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &start, &end);
365 	    gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &start, &end);
366 	}
367     gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &start, &end);
368 
369     g_unichar_to_utf8 (TAG_CHAR, tag_char_utf8);
370 
371     tokens = g_strsplit (text, tag_char_utf8, 0);
372 
373     for (count = 0; tokens[count]; count++)
374     {
375         if (count % 2 == 0)
376         {
377             gint offset;
378             GList *j;
379 
380             offset = gtk_text_iter_get_offset (&end);
381             gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &end, tokens[count], -1);
382             gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &start, offset);
383 
384             for (j = tags; j; j = j->next)
385             {
386                 gtk_text_buffer_apply_tag_by_name (GTK_TEXT_BUFFER (buffer), j->data, &start, &end);
387             }
388         }
389         else
390         {
391             if (tokens[count][0] != '/')
392             {
393                 tags = g_list_prepend (tags, tokens[count]);
394             }
395             else
396             {
397                 GList *element = g_list_find_custom (tags, &(tokens[count][1]), (GCompareFunc) g_ascii_strcasecmp);
398 
399                 if (element)
400                 {
401                     tags = g_list_delete_link (tags, element);
402                 }
403             }
404         }
405     }
406 
407     gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
408 
409     g_strfreev (tokens);
410 }
411 
412 /*------------------------------------------------------------------------------*/
413 
414 void
utl_gui_text_buffer_toggle_tags(GtkTextBuffer * buffer,const gchar * tag_name)415 utl_gui_text_buffer_toggle_tags (GtkTextBuffer *buffer, const gchar *tag_name) {
416 
417 GtkTextTagTable *tag_table;
418 GtkTextTag *tag;
419 GtkTextIter start, end, titer;
420 gboolean itagged;
421 
422 	tag_table = gtk_text_buffer_get_tag_table (buffer);
423 	tag = gtk_text_tag_table_lookup (tag_table, tag_name);
424 
425 	g_return_if_fail (tag != NULL);
426 
427 	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
428 
429 	itagged = TRUE;
430 
431 	for (titer = start; !gtk_text_iter_equal (&titer, &end); gtk_text_iter_forward_char (&titer)) {
432 		if ((itagged = gtk_text_iter_has_tag (&titer, tag)) == FALSE) {
433 			break;
434 		}
435 	}
436 
437 	if (itagged) {
438 		gtk_text_buffer_remove_tag (buffer, tag, &start, &end);
439 	} else {
440 		gtk_text_buffer_apply_tag (buffer, tag, &start, &end);
441 	}
442 }
443 
444 /*------------------------------------------------------------------------------*/
445 
446 gchar *
utl_gui_text_strip_tags(gchar * text)447 utl_gui_text_strip_tags (gchar *text) {
448 
449 gchar *output = g_strdup(""), *oldoutput = NULL;
450 gchar tag_char_utf8[7] = {0};
451 GList *tags = NULL;
452 gchar **tokens;
453 gint count;
454 gunichar TAG_CHAR = TAG;      /* Unicode chars in the Private Use Area. */
455 
456 	g_return_val_if_fail (output != NULL, NULL);
457 
458     g_unichar_to_utf8 (TAG_CHAR, tag_char_utf8);
459 
460     tokens = g_strsplit (text, tag_char_utf8, 0);
461 
462     for (count = 0; tokens[count]; count++)
463     {
464         if (count % 2 == 0)
465         {
466 			oldoutput = output;
467 	        output = g_strconcat (output, tokens[count], NULL);
468             g_free (oldoutput);
469         }
470         else
471         {
472             if (tokens[count][0] != '/')
473             {
474                 tags = g_list_prepend (tags, tokens[count]);
475             }
476             else
477             {
478                 GList *element = g_list_find_custom (tags, &(tokens[count][1]), (GCompareFunc) g_ascii_strcasecmp);
479 
480                 if (element)
481                 {
482                     tags = g_list_delete_link (tags, element);
483                 }
484             }
485         }
486     }
487 
488     g_strfreev (tokens);
489 
490 	return output;
491 }
492 
493 /*------------------------------------------------------------------------------*/
494 
495 void
utl_gui_text_buffer_remove_all_tags(GtkTextBuffer * buffer)496 utl_gui_text_buffer_remove_all_tags (GtkTextBuffer *buffer) {
497 
498 GtkTextIter start, end;
499 
500 	gtk_text_buffer_get_bounds (buffer, &start, &end);
501 	gtk_text_buffer_remove_all_tags (buffer, &start, &end);
502 }
503 
504 /*------------------------------------------------------------------------------*/
505 
506 void
utl_gui_change_bg_widget_state(GtkWidget * widget,gchar * color_str,GUI * appGUI)507 utl_gui_change_bg_widget_state(GtkWidget *widget, gchar *color_str, GUI *appGUI) {
508 
509     GdkRGBA color;
510 
511     if (color_str != NULL) {
512 
513         gdk_rgba_parse(&color, color_str);
514 
515     } else {
516         gtk_style_context_get_background_color(gtk_widget_get_style_context(appGUI->main_window),
517         gtk_widget_get_state_flags(appGUI->main_window), &color);
518     }
519     gtk_widget_override_background_color(widget, GTK_STATE_FLAG_NORMAL, &color);
520 }
521 
522 /*------------------------------------------------------------------------------*/
523 
524 GdkPixbuf*
utl_gui_create_color_swatch(gchar * color)525 utl_gui_create_color_swatch (gchar *color) {
526 
527 gchar *swatch[] = {
528     "32 14 2 1", ".      c #FFFFFF", "-      c #000000",
529     "--------------------------------", "-..............................-", "-..............................-",
530     "-..............................-", "-..............................-", "-..............................-",
531     "-..............................-", "-..............................-", "-..............................-",
532     "-..............................-", "-..............................-", "-..............................-",
533     "-..............................-", "--------------------------------"
534 };
535 
536 gchar color_str[] = ".      c #000000";
537 
538     g_snprintf(color_str, strlen(color_str) + 1, ".      c %s", color);
539     swatch[1] = color_str;
540     return gdk_pixbuf_new_from_xpm_data ((gchar const **)swatch);
541 }
542 
543 /*------------------------------------------------------------------------------*/
544 
545 gint
utl_gui_create_dialog(gint dialog_type,gchar * message,GtkWindow * parent)546 utl_gui_create_dialog (gint dialog_type, gchar *message, GtkWindow *parent) {
547 
548 GtkWidget *info_dialog = NULL;
549 gint response = -1;
550 
551     switch (dialog_type) {
552 
553         case GTK_MESSAGE_QUESTION:
554             info_dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW(parent),
555                                                   GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
556                                                   GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, message, NULL);
557             gtk_window_set_title (GTK_WINDOW(info_dialog), _("Question"));
558             break;
559 
560         case GTK_MESSAGE_INFO:
561             info_dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW(parent),
562                                                   GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
563                                                   GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, message, NULL);
564             gtk_window_set_title (GTK_WINDOW(info_dialog), _("Information"));
565             break;
566 
567         case GTK_MESSAGE_ERROR:
568             info_dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW(parent),
569                                                   GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
570                                                   GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, message, NULL);
571             gtk_window_set_title (GTK_WINDOW(info_dialog), _("Error"));
572             break;
573 
574         case GTK_MESSAGE_WARNING:
575             info_dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW(parent),
576                                                   GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
577                                                   GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, message, NULL);
578             gtk_window_set_title (GTK_WINDOW(info_dialog), _("Warning"));
579             break;
580     };
581 
582     if (info_dialog != NULL) {
583         gtk_widget_show (info_dialog);
584         response = gtk_dialog_run(GTK_DIALOG(info_dialog));
585         gtk_widget_destroy (info_dialog);
586     }
587 
588     return response;
589 }
590 /*------------------------------------------------------------------------------*/
591 static void
show_hidden_cb(GtkToggleButton * togglebutton,gpointer user_data)592 show_hidden_cb(GtkToggleButton *togglebutton, gpointer user_data) {
593     GtkFileChooser *file_chooser = user_data;
594     gboolean checked = gtk_toggle_button_get_active(togglebutton);
595     gtk_file_chooser_set_show_hidden(file_chooser, checked);
596 }
597 
598 static void
utl_gui_file_chooser_add_show_hidden(GtkFileChooser * file_chooser)599 utl_gui_file_chooser_add_show_hidden(GtkFileChooser *file_chooser) {
600     GtkWidget *show_hidden = gtk_check_button_new_with_label(_("Show hidden files"));
601     g_signal_connect(G_OBJECT(show_hidden), "toggled", G_CALLBACK(show_hidden_cb), file_chooser);
602     gtk_widget_show(show_hidden);
603     gtk_file_chooser_set_extra_widget(file_chooser, show_hidden);
604 }
605 /*------------------------------------------------------------------------------*/
606 
607 GtkWidget *
utl_gui_create_save_file_dialog(const gchar * title,GtkWindow * parent)608 utl_gui_create_save_file_dialog(const gchar *title, GtkWindow *parent) {
609     GtkWidget *dialog = gtk_file_chooser_dialog_new(title,
610             parent,
611             GTK_FILE_CHOOSER_ACTION_SAVE,
612             _("_Cancel"), GTK_RESPONSE_CANCEL,
613             _("_Save"), GTK_RESPONSE_ACCEPT,
614             NULL);
615 
616     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
617     gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
618     gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
619     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
620     utl_gui_file_chooser_add_show_hidden(GTK_FILE_CHOOSER(dialog));
621     return dialog;
622 }
623 
624 /*------------------------------------------------------------------------------*/
625 
626 GtkWidget *
utl_gui_create_open_file_dialog(const gchar * title,GtkWindow * parent)627 utl_gui_create_open_file_dialog(const gchar *title, GtkWindow *parent) {
628     GtkWidget *dialog = gtk_file_chooser_dialog_new(title,
629             parent,
630             GTK_FILE_CHOOSER_ACTION_OPEN,
631             _("_Cancel"), GTK_RESPONSE_CANCEL,
632             _("_Open"), GTK_RESPONSE_ACCEPT,
633             NULL);
634 
635     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
636     gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
637     gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
638     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
639     utl_gui_file_chooser_add_show_hidden(GTK_FILE_CHOOSER(dialog));
640     return dialog;
641 }
642 /*------------------------------------------------------------------------------*/
643 void
utl_gui_update_command_status(GtkEditable * editable,GtkWidget * icon_widget,GUI * appGUI)644 utl_gui_update_command_status (GtkEditable *editable, GtkWidget *icon_widget, GUI *appGUI) {
645 
646 GdkPixbuf *image;
647 gchar *cmd;
648 gint i;
649 
650     cmd = gtk_editable_get_chars(editable, 0, -1);
651     if (cmd) {
652         for (i=0; i < strlen(cmd); i++) {
653             if (cmd[i] == ' ') cmd[i] = 0;
654         }
655 	    gtk_widget_show (icon_widget);
656 
657         if (utl_is_valid_command (cmd) == TRUE) {
658             image = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), OSMO_STOCK_LIST_VALID, 16, 0, NULL);
659         } else {
660             image = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), OSMO_STOCK_LIST_INVALID, 16, 0, NULL);
661         }
662 
663 	    gtk_image_set_from_pixbuf (GTK_IMAGE(icon_widget), image);
664 	    g_object_unref (image);
665         g_free (cmd);
666     } else {
667 	    gtk_widget_hide (icon_widget);
668     }
669 }
670 
671 /*------------------------------------------------------------------------------*/
672 
673 gint
utl_gui_check_overwrite_file(gchar * filename,GtkWidget * window,GUI * appGUI)674 utl_gui_check_overwrite_file (gchar *filename, GtkWidget *window, GUI *appGUI) {
675 
676 gint response;
677 
678     if (g_file_test(filename, G_FILE_TEST_IS_REGULAR) == TRUE) {
679 
680         response = utl_gui_create_dialog(GTK_MESSAGE_QUESTION,
681 										 _("Selected file exist! Overwrite?"), GTK_WINDOW(window));
682 
683         if (response == GTK_RESPONSE_NO || response == GTK_RESPONSE_DELETE_EVENT) {
684             return -1;
685         }
686     }
687 
688     return 0;
689 }
690 
691 /*------------------------------------------------------------------------------*/
692 
693 void
utl_gui_clear_text_buffer(GtkTextBuffer * buffer,GtkTextIter * iter)694 utl_gui_clear_text_buffer (GtkTextBuffer *buffer, GtkTextIter *iter)
695 {
696 	GtkTextIter iter_s, iter_e;
697 
698 	gtk_text_buffer_get_bounds (buffer, &iter_s, &iter_e);
699 	gtk_text_buffer_delete (buffer, &iter_s, &iter_e);
700 	if (iter != NULL)
701 		gtk_text_buffer_get_iter_at_offset (buffer, iter, 0);
702 }
703 
704 /*------------------------------------------------------------------------------*/
705 
706 gint
utl_gui_list_store_get_text_index(GtkListStore * store,gchar * text)707 utl_gui_list_store_get_text_index (GtkListStore *store, gchar *text) {
708     if (text != NULL) {
709         GtkTreeIter iter;
710         gint i = 0;
711         gboolean has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
712         while (has_next) {
713             gchar *value;
714             i++;
715             gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &value, -1);
716             if (value != NULL) {
717                 if (!strcmp(value, text)) {
718                     g_free(value);
719                     return i;
720                 }
721                 g_free(value);
722             }
723             has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
724         }
725     }
726     return 0;
727 }
728 
729 /*------------------------------------------------------------------------------*/
730 
731 void
utl_gui_sw_vscrollbar_move_position(GtkWidget * scrolled_window,gint direction)732 utl_gui_sw_vscrollbar_move_position (GtkWidget *scrolled_window, gint direction) {
733 
734 GtkAdjustment *adj;
735 gdouble value;
736 
737     adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW(scrolled_window));
738 value = gtk_adjustment_get_value(adj);
739     if (direction == SW_MOVE_UP) {
740 
741         if (value > 0.0) {
742             value -= gtk_adjustment_get_step_increment (adj);
743             gtk_adjustment_set_value(adj, value < 0.0 ? 0.0 : value);
744         }
745 
746     } else if (direction == SW_MOVE_DOWN) {
747 
748         if (value+gtk_adjustment_get_page_size(adj) < gtk_adjustment_get_upper(adj)) {
749             value += gtk_adjustment_get_step_increment (adj);
750             gtk_adjustment_set_value(adj, value);
751         }
752     }
753 }
754 
755 /*------------------------------------------------------------------------------*/
756 
757 GtkWidget*
utl_gui_icon_label_radio_button(gchar * label,const gchar * icon_name,GtkIconSize size)758 utl_gui_icon_label_radio_button (gchar *label, const gchar *icon_name, GtkIconSize size) {
759 
760 GtkWidget *button;
761 GtkWidget *hbox;
762 GtkWidget *image;
763 
764     button = g_object_new (GTK_TYPE_RADIO_BUTTON, "visible", TRUE, NULL);
765 
766     hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
767 
768     image = gtk_image_new_from_icon_name (icon_name, size);
769     if (image) {
770         gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
771     }
772 
773     if (label != NULL && label != (gchar *)-1) {
774         gtk_box_pack_start (GTK_BOX (hbox),
775         g_object_new (GTK_TYPE_LABEL, "label", label, "use_underline", TRUE, NULL), FALSE, TRUE, 0);
776     }
777 
778     gtk_container_add (GTK_CONTAINER (button), hbox);
779     gtk_widget_show_all (button);
780 
781     return button;
782 }
783 
784 /*------------------------------------------------------------------------------*/
785 
786 void
utl_gui_url_initialize(GUI * appGUI)787 utl_gui_url_initialize (GUI *appGUI) {
788     GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(appGUI->main_window));
789     GdkDisplay *display = gdk_window_get_display(window);
790 
791     appGUI->hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
792     appGUI->regular_cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
793 
794     appGUI->hovering_over_link = FALSE;
795     appGUI->gui_url_tag = NULL;
796 }
797 
798 /*------------------------------------------------------------------------------*/
799 
800 void
utl_gui_url_insert_link(GSList ** links_list,gint * link_index,GtkWidget * textview,GtkTextIter * iter,gchar * color,gchar * font,gchar * text,gboolean center,GUI * appGUI)801 utl_gui_url_insert_link (GSList **links_list, gint *link_index, GtkWidget *textview, GtkTextIter *iter,
802                          gchar *color, gchar *font, gchar *text, gboolean center, GUI *appGUI)
803 {
804 	GtkJustification justify = center ? GTK_JUSTIFY_CENTER : GTK_JUSTIFY_LEFT;
805 	PangoUnderline underline = config.disable_underline_links ? PANGO_UNDERLINE_NONE : PANGO_UNDERLINE_SINGLE;
806 
807 	appGUI->gui_url_tag = gtk_text_buffer_create_tag (gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)), NULL,
808 	                                                  "foreground", color,
809 	                                                  "font", font,
810 	                                                  "justification", justify,
811 	                                                  "underline", underline,
812 	                                                  NULL);
813 
814 	g_object_set_data (G_OBJECT (appGUI->gui_url_tag), "link", GINT_TO_POINTER (*link_index));
815 
816 	*links_list = g_slist_append (*links_list, g_strdup (text));
817 	gtk_text_buffer_insert_with_tags (gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)),
818 	                                  iter, text, -1, appGUI->gui_url_tag, NULL);
819 	(*link_index)++;
820 }
821 
822 /*------------------------------------------------------------------------------*/
823 
824 void
utl_gui_url_remove_links(GSList ** links_list,gint * link_index)825 utl_gui_url_remove_links (GSList **links_list, gint *link_index)
826 {
827 	if (link_index) *link_index = 1;
828 
829 	if (*links_list != NULL) {
830 		g_slist_foreach (*links_list, (GFunc) g_free, NULL);
831 		g_slist_free (*links_list);
832 		*links_list = NULL;
833 	}
834 }
835 
836 /*------------------------------------------------------------------------------*/
837 
838 void
utl_gui_url_set_cursor_if_appropriate(GtkTextView * textview,gint x,gint y,GUI * appGUI)839 utl_gui_url_set_cursor_if_appropriate (GtkTextView *textview, gint x, gint y, GUI *appGUI) {
840 
841 GSList *tags = NULL, *tagp = NULL;
842 /*GtkTextBuffer *buffer;*/
843 GtkTextIter iter;
844 gboolean hovering = FALSE;
845 GtkTextTag *tag;
846 int *slink;
847 
848 /*    buffer = gtk_text_view_get_buffer (textview);*/
849 
850     gtk_text_view_get_iter_at_location (textview, &iter, x, y);
851 
852     tags = gtk_text_iter_get_tags (&iter);
853 
854     for (tagp = tags;  tagp != NULL;  tagp = tagp->next) {
855         tag = tagp->data;
856         slink = g_object_get_data (G_OBJECT (tag), "link");
857 
858         if (slink != 0) {
859             hovering = TRUE;
860             break;
861         }
862     }
863 
864     if (hovering != appGUI->hovering_over_link) {
865         appGUI->hovering_over_link = hovering;
866 
867         if (appGUI->hovering_over_link) {
868             gdk_window_set_cursor (gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_TEXT), appGUI->hand_cursor);
869         } else {
870             gdk_window_set_cursor (gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_TEXT), appGUI->regular_cursor);
871         }
872     }
873 
874     if (tags) {
875         g_slist_free (tags);
876     }
877 }
878 
879 /*------------------------------------------------------------------------------*/
880 
881 gboolean
utl_gui_url_event_after(GtkWidget * textview,GdkEvent * ev,GSList ** links_list)882 utl_gui_url_event_after (GtkWidget *textview, GdkEvent *ev, GSList **links_list)
883 {
884 	GtkTextIter start, end, iter;
885 	GtkTextBuffer *buffer;
886 	GdkEventButton *event;
887 	gint x, y;
888 	GSList *tags = NULL, *tagp = NULL;
889 	GtkTextTag *tag;
890 	gchar *link;
891 	gint slink;
892 	gchar tmpbuf[BUFFER_SIZE];
893 
894 	if (ev->type != GDK_BUTTON_RELEASE)
895 		return FALSE;
896 
897 	event = (GdkEventButton *) ev;
898 	if (event->button != 1)
899 		return FALSE;
900 
901 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
902 	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
903 	if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
904 		return FALSE;
905 
906 	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (textview), GTK_TEXT_WINDOW_WIDGET,
907 	                                       event->x, event->y, &x, &y);
908 	gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (textview), &iter, x, y);
909 
910 	tags = gtk_text_iter_get_tags (&iter);
911 	for (tagp = tags; tagp != NULL; tagp = tagp->next) {
912 		tag = tagp->data;
913 		slink = (size_t) g_object_get_data (G_OBJECT (tag), "link");
914 
915 		if (slink != 0) {
916 			link = g_slist_nth_data (*links_list, slink-1);
917 			g_snprintf (tmpbuf, BUFFER_SIZE, "\"%s\"", link);
918 			utl_run_helper (tmpbuf, utl_get_link_type (link));
919 			break;
920 		}
921 	}
922 
923 	if (tags) g_slist_free (tags);
924 
925 	return FALSE;
926 }
927 
928 /*------------------------------------------------------------------------------*/
929 
930 gboolean
utl_gui_url_motion_notify_event(GtkWidget * textview,GdkEventMotion * event,gpointer data)931 utl_gui_url_motion_notify_event (GtkWidget *textview, GdkEventMotion *event, gpointer data) {
932 
933 gint x, y;
934 
935     GUI *appGUI = (GUI *)data;
936 
937     gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (textview), GTK_TEXT_WINDOW_WIDGET,
938                                            event->x, event->y, &x, &y);
939     utl_gui_url_set_cursor_if_appropriate (GTK_TEXT_VIEW (textview), x, y, appGUI);
940     return FALSE;
941 }
942 
943 /*------------------------------------------------------------------------------*/
944 
945 gboolean
utl_gui_url_visibility_notify_event(GtkWidget * textview,GdkEventVisibility * event,gpointer data)946 utl_gui_url_visibility_notify_event (GtkWidget *textview, GdkEventVisibility *event, gpointer data) {
947 
948 gint wx, wy, bx, by;
949 
950     GUI *appGUI = (GUI *)data;
951     GdkDeviceManager* device_manager = gdk_display_get_device_manager(gtk_widget_get_display(textview));
952 
953     gdk_window_get_device_position (gtk_widget_get_window(textview), gdk_device_manager_get_client_pointer(device_manager), &wx, &wy, NULL);
954     gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (textview), GTK_TEXT_WINDOW_WIDGET, wx, wy, &bx, &by);
955     utl_gui_url_set_cursor_if_appropriate (GTK_TEXT_VIEW (textview), bx, by, appGUI);
956     return FALSE;
957 }
958 
959 /*------------------------------------------------------------------------------*/
960 
961 void
utl_gui_url_setup(GSList ** links_list,gint * link_index,GtkWidget * textview,GUI * appGUI)962 utl_gui_url_setup (GSList **links_list, gint *link_index, GtkWidget *textview, GUI *appGUI) {
963 
964     utl_gui_url_remove_links (links_list, link_index);
965 
966     *link_index = 1;
967     appGUI->hovering_over_link = FALSE;
968     appGUI->gui_url_tag = NULL;
969 
970     g_signal_connect (textview, "event-after", G_CALLBACK (utl_gui_url_event_after), links_list);
971     g_signal_connect (textview, "motion-notify-event", G_CALLBACK (utl_gui_url_motion_notify_event), appGUI);
972     g_signal_connect (textview, "visibility-notify-event", G_CALLBACK (utl_gui_url_visibility_notify_event), appGUI);
973 
974 }
975 
976 /*------------------------------------------------------------------------------*/
977 
978 void
utl_gui_foreach_selected(GtkTreeSelection * selection,GtkTreeModel * model,GFunc foreach_function,gpointer user_data)979 utl_gui_foreach_selected(GtkTreeSelection *selection, GtkTreeModel *model, GFunc foreach_function, gpointer user_data) {
980     GList *selected_rows, *selected_refs, *l;
981 
982     selected_rows = gtk_tree_selection_get_selected_rows(selection, &model);
983     for (l = selected_rows, selected_refs = NULL; l; l = l->next) {
984         selected_refs = g_list_prepend(selected_refs, gtk_tree_row_reference_new(model, (GtkTreePath *) l->data));
985     }
986     g_list_foreach(selected_refs, foreach_function, user_data);
987 
988     utl_free_list(selected_rows, (GDestroyNotify) gtk_tree_path_free);
989     utl_free_list(selected_refs, (GDestroyNotify) gtk_tree_row_reference_free);
990 }
991 /*------------------------------------------------------------------------------*/
992 GtkTreeIter
utl_gui_get_first_selection_iter(GtkTreeSelection * selection,GtkTreeModel ** model)993 utl_gui_get_first_selection_iter(GtkTreeSelection *selection, GtkTreeModel **model) {
994     GtkTreeIter iter;
995     GList *selected_rows;
996 
997     selected_rows = gtk_tree_selection_get_selected_rows(selection, model);
998     gtk_tree_model_get_iter(*model, &iter, selected_rows->data);
999 
1000     utl_free_list(selected_rows, (GDestroyNotify) gtk_tree_path_free);
1001     return iter;
1002 }
1003 /*------------------------------------------------------------------------------*/
1004 void
utl_gui_convert_color_to_string(GdkRGBA * color,gchar * string)1005 utl_gui_convert_color_to_string (GdkRGBA *color, gchar *string) {
1006     g_snprintf (string, MAXCOLORNAME, "#%02X%02X%02X",
1007 	            (guint)(color->red * 255), (guint)(color->green * 255), (guint)(color->blue * 255));
1008 }
1009 /*------------------------------------------------------------------------------*/
1010 void
utl_gui_convert_color_alpha_to_string(GdkRGBA * color,gchar * string,gint * alpha)1011 utl_gui_convert_color_alpha_to_string   (GdkRGBA *color, gchar *string, gint *alpha) {
1012     utl_gui_convert_color_to_string(color, string);
1013     *alpha = color->alpha * 65536;
1014 }
1015 
1016 #ifdef HAVE_GSPELL
1017 
1018 /*------------------------------------------------------------------------------*/
1019 GspellTextView*
utl_gui_create_spell_check_textview(GtkTextView * textview,gboolean enable_by_default)1020 utl_gui_create_spell_check_textview(GtkTextView *textview, gboolean enable_by_default) {
1021     GspellTextView *gspell_view;
1022     GspellChecker *checker;
1023     GtkTextBuffer *gtk_buffer;
1024     GspellTextBuffer *gspell_buffer;
1025 
1026     checker = gspell_checker_new(NULL);
1027     if (config.override_locale_settings == TRUE) {
1028         const GspellLanguage * language = gspell_language_lookup(config.spell_lang);
1029         if (language) {
1030             gspell_checker_set_language(checker, language);
1031         }
1032     }
1033     gtk_buffer = gtk_text_view_get_buffer(textview);
1034     gspell_buffer = gspell_text_buffer_get_from_gtk_text_buffer(gtk_buffer);
1035     gspell_text_buffer_set_spell_checker(gspell_buffer, checker);
1036     g_object_unref(checker);
1037 
1038     gspell_view = gspell_text_view_get_from_gtk_text_view(textview);
1039     gspell_text_view_set_inline_spell_checking(gspell_view, enable_by_default);
1040     gspell_text_view_set_enable_language_menu(gspell_view, enable_by_default);
1041     return gspell_view;
1042 }
1043 void
utl_gui_set_enable_spell_check(GspellTextView * text,gboolean enable)1044 utl_gui_set_enable_spell_check(GspellTextView* text, gboolean enable) {
1045     gspell_text_view_set_inline_spell_checking(text, enable);
1046     gspell_text_view_set_enable_language_menu(text, enable);
1047 }
1048 #endif /* HAVE_GSPELL */
1049 /*------------------------------------------------------------------------------*/
1050 
1051