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