1 /* widget-factory: a collection of widgets, for easy theme testing
2 *
3 * Copyright (C) 2011 Canonical Ltd
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
19 */
20
21 #include "config.h"
22
23 #include <glib/gi18n.h>
24 #include <gtk/gtk.h>
25
26 static void
change_theme_state(GSimpleAction * action,GVariant * state,gpointer user_data)27 change_theme_state (GSimpleAction *action,
28 GVariant *state,
29 gpointer user_data)
30 {
31 GtkSettings *settings = gtk_settings_get_default ();
32
33 g_object_set (G_OBJECT (settings),
34 "gtk-application-prefer-dark-theme",
35 g_variant_get_boolean (state),
36 NULL);
37
38 g_simple_action_set_state (action, state);
39 }
40
41 static GtkWidget *page_stack;
42
43 static void
change_transition_state(GSimpleAction * action,GVariant * state,gpointer user_data)44 change_transition_state (GSimpleAction *action,
45 GVariant *state,
46 gpointer user_data)
47 {
48 GtkStackTransitionType transition;
49
50 if (g_variant_get_boolean (state))
51 transition = GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT;
52 else
53 transition = GTK_STACK_TRANSITION_TYPE_NONE;
54
55 gtk_stack_set_transition_type (GTK_STACK (page_stack), transition);
56
57 g_simple_action_set_state (action, state);
58 }
59
60 static gboolean
get_idle(gpointer data)61 get_idle (gpointer data)
62 {
63 GtkWidget *window = data;
64 GtkApplication *app = gtk_window_get_application (GTK_WINDOW (window));
65
66 gtk_widget_set_sensitive (window, TRUE);
67 gdk_window_set_cursor (gtk_widget_get_window (window), NULL);
68 g_application_unmark_busy (G_APPLICATION (app));
69
70 return G_SOURCE_REMOVE;
71 }
72
73 static void
get_busy(GSimpleAction * action,GVariant * parameter,gpointer user_data)74 get_busy (GSimpleAction *action,
75 GVariant *parameter,
76 gpointer user_data)
77 {
78 GtkWidget *window = user_data;
79 GdkCursor *cursor;
80 GtkApplication *app = gtk_window_get_application (GTK_WINDOW (window));
81
82 g_application_mark_busy (G_APPLICATION (app));
83 cursor = gdk_cursor_new_from_name (gtk_widget_get_display (window), "wait");
84 gdk_window_set_cursor (gtk_widget_get_window (window), cursor);
85 g_object_unref (cursor);
86 g_timeout_add (5000, get_idle, window);
87
88 gtk_widget_set_sensitive (window, FALSE);
89 }
90
91 static gint current_page = 0;
92 static gboolean
on_page(gint i)93 on_page (gint i)
94 {
95 return current_page == i;
96 }
97
98 static void
activate_search(GSimpleAction * action,GVariant * parameter,gpointer user_data)99 activate_search (GSimpleAction *action,
100 GVariant *parameter,
101 gpointer user_data)
102 {
103 GtkWidget *window = user_data;
104 GtkWidget *searchbar;
105
106 if (!on_page (2))
107 return;
108
109 searchbar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "searchbar"));
110 gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (searchbar), TRUE);
111 }
112
113 static void
activate_delete(GSimpleAction * action,GVariant * parameter,gpointer user_data)114 activate_delete (GSimpleAction *action,
115 GVariant *parameter,
116 gpointer user_data)
117 {
118 GtkWidget *window = user_data;
119 GtkWidget *infobar;
120
121 if (!on_page (2))
122 return;
123
124 infobar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "infobar"));
125 gtk_widget_show (infobar);
126 }
127
128 static void populate_flowbox (GtkWidget *flowbox);
129
130 static void
activate_background(GSimpleAction * action,GVariant * parameter,gpointer user_data)131 activate_background (GSimpleAction *action,
132 GVariant *parameter,
133 gpointer user_data)
134 {
135 GtkWidget *window = user_data;
136 GtkWidget *dialog;
137 GtkWidget *flowbox;
138
139 if (!on_page (2))
140 return;
141
142 dialog = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "selection_dialog"));
143 flowbox = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "selection_flowbox"));
144
145 gtk_widget_show (dialog);
146 populate_flowbox (flowbox);
147 }
148
149 static void
activate_open(GSimpleAction * action,GVariant * parameter,gpointer user_data)150 activate_open (GSimpleAction *action,
151 GVariant *parameter,
152 gpointer user_data)
153 {
154 GtkWidget *window = user_data;
155 GtkWidget *button;
156
157 if (!on_page (3))
158 return;
159
160 button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "open_menubutton"));
161 gtk_button_clicked (GTK_BUTTON (button));
162 }
163
164 static void
activate_record(GSimpleAction * action,GVariant * parameter,gpointer user_data)165 activate_record (GSimpleAction *action,
166 GVariant *parameter,
167 gpointer user_data)
168 {
169 GtkWidget *window = user_data;
170 GtkWidget *button;
171
172 if (!on_page (3))
173 return;
174
175 button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "record_button"));
176 gtk_button_clicked (GTK_BUTTON (button));
177 }
178
179 static void
activate_lock(GSimpleAction * action,GVariant * parameter,gpointer user_data)180 activate_lock (GSimpleAction *action,
181 GVariant *parameter,
182 gpointer user_data)
183 {
184 GtkWidget *window = user_data;
185 GtkWidget *button;
186
187 if (!on_page (3))
188 return;
189
190 button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "lockbutton"));
191 gtk_button_clicked (GTK_BUTTON (button));
192 }
193
194 static void
activate_about(GSimpleAction * action,GVariant * parameter,gpointer user_data)195 activate_about (GSimpleAction *action,
196 GVariant *parameter,
197 gpointer user_data)
198 {
199 GtkApplication *app = user_data;
200 const gchar *authors[] = {
201 "Andrea Cimitan",
202 "Cosimo Cecchi",
203 NULL
204 };
205 gchar *version;
206
207 version = g_strdup_printf ("%s\nRunning against GTK+ %d.%d.%d",
208 PACKAGE_VERSION,
209 gtk_get_major_version (),
210 gtk_get_minor_version (),
211 gtk_get_micro_version ());
212
213 gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
214 "program-name", "GTK Widget Factory",
215 "version", version,
216 "copyright", "© 1997—2019 The GTK Team",
217 "license-type", GTK_LICENSE_LGPL_2_1,
218 "website", "http://www.gtk.org",
219 "comments", "Program to demonstrate GTK themes and widgets",
220 "authors", authors,
221 "logo-icon-name", "gtk3-widget-factory",
222 "title", "About GTK Widget Factory",
223 NULL);
224
225 g_free (version);
226 }
227
228 static void
activate_quit(GSimpleAction * action,GVariant * parameter,gpointer user_data)229 activate_quit (GSimpleAction *action,
230 GVariant *parameter,
231 gpointer user_data)
232 {
233 GtkApplication *app = user_data;
234 GtkWidget *win;
235 GList *list, *next;
236
237 list = gtk_application_get_windows (app);
238 while (list)
239 {
240 win = list->data;
241 next = list->next;
242
243 gtk_widget_destroy (GTK_WIDGET (win));
244
245 list = next;
246 }
247 }
248
249 static void
activate_inspector(GSimpleAction * action,GVariant * parameter,gpointer user_data)250 activate_inspector (GSimpleAction *action,
251 GVariant *parameter,
252 gpointer user_data)
253 {
254 gtk_window_set_interactive_debugging (TRUE);
255 }
256
257 static void
spin_value_changed(GtkAdjustment * adjustment,GtkWidget * label)258 spin_value_changed (GtkAdjustment *adjustment, GtkWidget *label)
259 {
260 GtkWidget *w;
261 gint v;
262 gchar *text;
263
264 v = (int)gtk_adjustment_get_value (adjustment);
265
266 if ((v % 3) == 0)
267 {
268 text = g_strdup_printf ("%d is a multiple of 3", v);
269 gtk_label_set_label (GTK_LABEL (label), text);
270 g_free (text);
271 }
272
273 w = gtk_widget_get_ancestor (label, GTK_TYPE_REVEALER);
274 gtk_revealer_set_reveal_child (GTK_REVEALER (w), (v % 3) == 0);
275 }
276
277 static void
dismiss(GtkWidget * button)278 dismiss (GtkWidget *button)
279 {
280 GtkWidget *w;
281
282 w = gtk_widget_get_ancestor (button, GTK_TYPE_REVEALER);
283 gtk_revealer_set_reveal_child (GTK_REVEALER (w), FALSE);
284 }
285
286 static void
spin_value_reset(GtkWidget * button,GtkAdjustment * adjustment)287 spin_value_reset (GtkWidget *button, GtkAdjustment *adjustment)
288 {
289 gtk_adjustment_set_value (adjustment, 50.0);
290 dismiss (button);
291 }
292
293 static gint pulse_time = 250;
294 static gint pulse_entry_mode = 0;
295
296 static void
remove_pulse(gpointer pulse_id)297 remove_pulse (gpointer pulse_id)
298 {
299 g_source_remove (GPOINTER_TO_UINT (pulse_id));
300 }
301
302 static gboolean
pulse_it(GtkWidget * widget)303 pulse_it (GtkWidget *widget)
304 {
305 guint pulse_id;
306
307 if (GTK_IS_ENTRY (widget))
308 gtk_entry_progress_pulse (GTK_ENTRY (widget));
309 else
310 gtk_progress_bar_pulse (GTK_PROGRESS_BAR (widget));
311
312 pulse_id = g_timeout_add (pulse_time, (GSourceFunc)pulse_it, widget);
313 g_object_set_data_full (G_OBJECT (widget), "pulse_id", GUINT_TO_POINTER (pulse_id), remove_pulse);
314
315 return G_SOURCE_REMOVE;
316 }
317
318 static void
update_pulse_time(GtkAdjustment * adjustment,GtkWidget * widget)319 update_pulse_time (GtkAdjustment *adjustment, GtkWidget *widget)
320 {
321 gdouble value;
322 guint pulse_id;
323
324 value = gtk_adjustment_get_value (adjustment);
325
326 pulse_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "pulse_id"));
327
328 /* vary between 50 and 450 */
329 pulse_time = 50 + 4 * value;
330
331 if (value == 100)
332 {
333 g_object_set_data (G_OBJECT (widget), "pulse_id", NULL);
334 }
335 else if (value < 100)
336 {
337 if (pulse_id == 0 && (GTK_IS_PROGRESS_BAR (widget) || pulse_entry_mode % 3 == 2))
338 {
339 pulse_id = g_timeout_add (pulse_time, (GSourceFunc)pulse_it, widget);
340 g_object_set_data_full (G_OBJECT (widget), "pulse_id", GUINT_TO_POINTER (pulse_id), remove_pulse);
341 }
342 }
343 }
344
345 static void
on_entry_icon_release(GtkEntry * entry,GtkEntryIconPosition icon_pos,GdkEvent * event,gpointer user_data)346 on_entry_icon_release (GtkEntry *entry,
347 GtkEntryIconPosition icon_pos,
348 GdkEvent *event,
349 gpointer user_data)
350 {
351 if (icon_pos != GTK_ENTRY_ICON_SECONDARY)
352 return;
353
354 pulse_entry_mode++;
355
356 if (pulse_entry_mode % 3 == 0)
357 {
358 g_object_set_data (G_OBJECT (entry), "pulse_id", NULL);
359 gtk_entry_set_progress_fraction (entry, 0);
360 }
361 else if (pulse_entry_mode % 3 == 1)
362 gtk_entry_set_progress_fraction (entry, 0.25);
363 else if (pulse_entry_mode % 3 == 2)
364 {
365 if (pulse_time - 50 < 400)
366 {
367 gtk_entry_set_progress_pulse_step (entry, 0.1);
368 pulse_it (GTK_WIDGET (entry));
369 }
370 }
371 }
372
373 #define EPSILON (1e-10)
374
375 static gboolean
on_scale_button_query_tooltip(GtkWidget * button,gint x,gint y,gboolean keyboard_mode,GtkTooltip * tooltip,gpointer user_data)376 on_scale_button_query_tooltip (GtkWidget *button,
377 gint x,
378 gint y,
379 gboolean keyboard_mode,
380 GtkTooltip *tooltip,
381 gpointer user_data)
382 {
383 GtkScaleButton *scale_button = GTK_SCALE_BUTTON (button);
384 GtkAdjustment *adjustment;
385 gdouble val;
386 gchar *str;
387 AtkImage *image;
388
389 image = ATK_IMAGE (gtk_widget_get_accessible (button));
390
391 adjustment = gtk_scale_button_get_adjustment (scale_button);
392 val = gtk_scale_button_get_value (scale_button);
393
394 if (val < (gtk_adjustment_get_lower (adjustment) + EPSILON))
395 {
396 str = g_strdup (_("Muted"));
397 }
398 else if (val >= (gtk_adjustment_get_upper (adjustment) - EPSILON))
399 {
400 str = g_strdup (_("Full Volume"));
401 }
402 else
403 {
404 gint percent;
405
406 percent = (gint) (100. * val / (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_lower (adjustment)) + .5);
407
408 str = g_strdup_printf (C_("volume percentage", "%d %%"), percent);
409 }
410
411 gtk_tooltip_set_text (tooltip, str);
412 atk_image_set_image_description (image, str);
413 g_free (str);
414
415 return TRUE;
416 }
417
418 static void
on_scale_button_value_changed(GtkScaleButton * button,gdouble value,gpointer user_data)419 on_scale_button_value_changed (GtkScaleButton *button,
420 gdouble value,
421 gpointer user_data)
422 {
423 gtk_widget_trigger_tooltip_query (GTK_WIDGET (button));
424 }
425
426 static void
on_record_button_toggled(GtkToggleButton * button,gpointer user_data)427 on_record_button_toggled (GtkToggleButton *button,
428 gpointer user_data)
429 {
430 GtkStyleContext *context;
431
432 context = gtk_widget_get_style_context (GTK_WIDGET (button));
433 if (gtk_toggle_button_get_active (button))
434 gtk_style_context_remove_class (context, "destructive-action");
435 else
436 gtk_style_context_add_class (context, "destructive-action");
437 }
438
439 static void
on_page_combo_changed(GtkComboBox * combo,gpointer user_data)440 on_page_combo_changed (GtkComboBox *combo,
441 gpointer user_data)
442 {
443 GtkWidget *from;
444 GtkWidget *to;
445 GtkWidget *print;
446
447 from = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "range_from_spin"));
448 to = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "range_to_spin"));
449 print = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "print_button"));
450
451 switch (gtk_combo_box_get_active (combo))
452 {
453 case 0: /* Range */
454 gtk_widget_set_sensitive (from, TRUE);
455 gtk_widget_set_sensitive (to, TRUE);
456 gtk_widget_set_sensitive (print, TRUE);
457 break;
458 case 1: /* All */
459 gtk_widget_set_sensitive (from, FALSE);
460 gtk_widget_set_sensitive (to, FALSE);
461 gtk_spin_button_set_value (GTK_SPIN_BUTTON (from), 1);
462 gtk_spin_button_set_value (GTK_SPIN_BUTTON (to), 99);
463 gtk_widget_set_sensitive (print, TRUE);
464 break;
465 case 2: /* Current */
466 gtk_widget_set_sensitive (from, FALSE);
467 gtk_widget_set_sensitive (to, FALSE);
468 gtk_spin_button_set_value (GTK_SPIN_BUTTON (from), 7);
469 gtk_spin_button_set_value (GTK_SPIN_BUTTON (to), 7);
470 gtk_widget_set_sensitive (print, TRUE);
471 break;
472 case 4:
473 gtk_widget_set_sensitive (from, FALSE);
474 gtk_widget_set_sensitive (to, FALSE);
475 gtk_widget_set_sensitive (print, FALSE);
476 break;
477 default:;
478 }
479 }
480
481 static void
on_range_from_changed(GtkSpinButton * from)482 on_range_from_changed (GtkSpinButton *from)
483 {
484 GtkSpinButton *to;
485 gint v1, v2;
486
487 to = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (from), "range_to_spin"));
488
489 v1 = gtk_spin_button_get_value_as_int (from);
490 v2 = gtk_spin_button_get_value_as_int (to);
491
492 if (v1 > v2)
493 gtk_spin_button_set_value (to, v1);
494 }
495
496 static void
on_range_to_changed(GtkSpinButton * to)497 on_range_to_changed (GtkSpinButton *to)
498 {
499 GtkSpinButton *from;
500 gint v1, v2;
501
502 from = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (to), "range_from_spin"));
503
504 v1 = gtk_spin_button_get_value_as_int (from);
505 v2 = gtk_spin_button_get_value_as_int (to);
506
507 if (v1 > v2)
508 gtk_spin_button_set_value (from, v2);
509 }
510
511 static void
update_header(GtkListBoxRow * row,GtkListBoxRow * before,gpointer data)512 update_header (GtkListBoxRow *row,
513 GtkListBoxRow *before,
514 gpointer data)
515 {
516 if (before != NULL &&
517 gtk_list_box_row_get_header (row) == NULL)
518 {
519 GtkWidget *separator;
520
521 separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
522 gtk_widget_show (separator);
523 gtk_list_box_row_set_header (row, separator);
524 }
525 }
526
527 static void
info_bar_response(GtkWidget * infobar,gint response_id)528 info_bar_response (GtkWidget *infobar, gint response_id)
529 {
530 if (response_id == GTK_RESPONSE_CLOSE)
531 gtk_widget_hide (infobar);
532 }
533
534 static void
show_dialog(GtkWidget * button,GtkWidget * dialog)535 show_dialog (GtkWidget *button, GtkWidget *dialog)
536 {
537 gtk_widget_show (dialog);
538 }
539
540 static void
close_dialog(GtkWidget * dialog)541 close_dialog (GtkWidget *dialog)
542 {
543 gtk_widget_hide (dialog);
544 }
545
546 static void
set_needs_attention(GtkWidget * page,gboolean needs_attention)547 set_needs_attention (GtkWidget *page, gboolean needs_attention)
548 {
549 GtkWidget *stack;
550
551 stack = gtk_widget_get_parent (page);
552 gtk_container_child_set (GTK_CONTAINER (stack), page,
553 "needs-attention", needs_attention,
554 NULL);
555 }
556
557 static gboolean
demand_attention(gpointer stack)558 demand_attention (gpointer stack)
559 {
560 GtkWidget *page;
561
562 page = gtk_stack_get_child_by_name (GTK_STACK (stack), "page3");
563 set_needs_attention (page, TRUE);
564
565 return G_SOURCE_REMOVE;
566 }
567
568 static void
action_dialog_button_clicked(GtkButton * button,GtkWidget * page)569 action_dialog_button_clicked (GtkButton *button, GtkWidget *page)
570 {
571 g_timeout_add (1000, demand_attention, page);
572 }
573
574 static void
page_changed_cb(GtkWidget * stack,GParamSpec * pspec,gpointer data)575 page_changed_cb (GtkWidget *stack, GParamSpec *pspec, gpointer data)
576 {
577 const gchar *name;
578 GtkWidget *window;
579 GtkWidget *page;
580
581 if (gtk_widget_in_destruction (stack))
582 return;
583
584 name = gtk_stack_get_visible_child_name (GTK_STACK (stack));
585
586 window = gtk_widget_get_ancestor (stack, GTK_TYPE_APPLICATION_WINDOW);
587 g_object_set (gtk_application_window_get_help_overlay (GTK_APPLICATION_WINDOW (window)),
588 "view-name", name,
589 NULL);
590
591 if (g_str_equal (name, "page1"))
592 current_page = 1;
593 else if (g_str_equal (name, "page2"))
594 current_page = 2;
595 if (g_str_equal (name, "page3"))
596 {
597 current_page = 3;
598 page = gtk_stack_get_visible_child (GTK_STACK (stack));
599 set_needs_attention (GTK_WIDGET (page), FALSE);
600 }
601 }
602
603 static void
populate_model(GtkTreeStore * store)604 populate_model (GtkTreeStore *store)
605 {
606 GtkTreeIter iter, parent0, parent1, parent2, parent3;
607
608 gtk_tree_store_append (store, &iter, NULL);
609 gtk_tree_store_set (store, &iter,
610 0, "Charlemagne",
611 1, "742",
612 2, "814",
613 -1);
614 parent0 = iter;
615 gtk_tree_store_append (store, &iter, &parent0);
616 gtk_tree_store_set (store, &iter,
617 0, "Pepin the Short",
618 1, "714",
619 2, "768",
620 -1);
621 parent1 = iter;
622 gtk_tree_store_append (store, &iter, &parent1);
623 gtk_tree_store_set (store, &iter,
624 0, "Charles Martel",
625 1, "688",
626 2, "741",
627 -1);
628 parent2 = iter;
629 gtk_tree_store_append (store, &iter, &parent2);
630 gtk_tree_store_set (store, &iter,
631 0, "Pepin of Herstal",
632 1, "635",
633 2, "714",
634 -1);
635 parent3 = iter;
636 gtk_tree_store_append (store, &iter, &parent3);
637 gtk_tree_store_set (store, &iter,
638 0, "Ansegisel",
639 1, "602 or 610",
640 2, "murdered before 679",
641 -1);
642 gtk_tree_store_append (store, &iter, &parent3);
643 gtk_tree_store_set (store, &iter,
644 0, "Begga",
645 1, "615",
646 2, "693",
647 -1);
648 gtk_tree_store_append (store, &iter, &parent2);
649 gtk_tree_store_set (store, &iter,
650 0, "Alpaida",
651 -1);
652 gtk_tree_store_append (store, &iter, &parent1);
653 gtk_tree_store_set (store, &iter,
654 0, "Rotrude",
655 -1);
656 parent2 = iter;
657 gtk_tree_store_append (store, &iter, &parent2);
658 gtk_tree_store_set (store, &iter,
659 0, "Liévin de Trèves",
660 -1);
661 parent3 = iter;
662 gtk_tree_store_append (store, &iter, &parent3);
663 gtk_tree_store_set (store, &iter,
664 0, "Guérin",
665 -1);
666 gtk_tree_store_append (store, &iter, &parent3);
667 gtk_tree_store_set (store, &iter,
668 0, "Gunza",
669 -1);
670 gtk_tree_store_append (store, &iter, &parent2);
671 gtk_tree_store_set (store, &iter,
672 0, "Willigarde de Bavière",
673 -1);
674 gtk_tree_store_append (store, &iter, &parent0);
675 gtk_tree_store_set (store, &iter,
676 0, "Bertrada of Laon",
677 1, "710",
678 2, "783",
679 -1);
680 parent1 = iter;
681 gtk_tree_store_append (store, &iter, &parent1);
682 gtk_tree_store_set (store, &iter,
683 0, "Caribert of Laon",
684 2, "before 762",
685 -1);
686 parent2 = iter;
687 gtk_tree_store_append (store, &iter, &parent2);
688 gtk_tree_store_set (store, &iter,
689 0, "Unknown",
690 -1);
691 gtk_tree_store_append (store, &iter, &parent2);
692 gtk_tree_store_set (store, &iter,
693 0, "Bertrada of Prüm",
694 1, "ca. 670",
695 2, "after 721",
696 -1);
697 gtk_tree_store_append (store, &iter, &parent1);
698 gtk_tree_store_set (store, &iter,
699 0, "Gisele of Aquitaine",
700 -1);
701 gtk_tree_store_append (store, &iter, NULL);
702 gtk_tree_store_set (store, &iter, 3, TRUE, -1);
703 gtk_tree_store_append (store, &iter, NULL);
704 gtk_tree_store_set (store, &iter,
705 0, "Attila the Hun",
706 1, "ca. 390",
707 2, "453",
708 -1);
709 }
710
711 static gboolean
row_separator_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)712 row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
713 {
714 gboolean is_sep;
715
716 gtk_tree_model_get (model, iter, 3, &is_sep, -1);
717
718 return is_sep;
719 }
720
721 static void
update_title_header(GtkListBoxRow * row,GtkListBoxRow * before,gpointer data)722 update_title_header (GtkListBoxRow *row,
723 GtkListBoxRow *before,
724 gpointer data)
725 {
726 GtkWidget *header;
727 gchar *title;
728
729 header = gtk_list_box_row_get_header (row);
730 title = (gchar *)g_object_get_data (G_OBJECT (row), "title");
731 if (!header && title)
732 {
733 title = g_strdup_printf ("<b>%s</b>", title);
734
735 header = gtk_label_new (title);
736 gtk_label_set_use_markup (GTK_LABEL (header), TRUE);
737 gtk_widget_set_halign (header, GTK_ALIGN_START);
738 gtk_widget_set_margin_top (header, 12);
739 gtk_widget_set_margin_start (header, 6);
740 gtk_widget_set_margin_end (header, 6);
741 gtk_widget_set_margin_bottom (header, 6);
742 gtk_widget_show (header);
743
744 gtk_list_box_row_set_header (row, header);
745
746 g_free (title);
747 }
748 }
749
750 static void
overshot(GtkScrolledWindow * sw,GtkPositionType pos,GtkWidget * widget)751 overshot (GtkScrolledWindow *sw, GtkPositionType pos, GtkWidget *widget)
752 {
753 GtkWidget *box, *row, *label, *swatch;
754 GdkRGBA rgba;
755 const gchar *color;
756 gchar *text;
757 GtkWidget *silver;
758 GtkWidget *gold;
759
760 silver = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "Silver"));
761 gold = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "Gold"));
762
763 if (pos == GTK_POS_TOP)
764 {
765 if (silver)
766 {
767 gtk_container_remove (GTK_CONTAINER (widget), silver);
768 g_object_set_data (G_OBJECT (widget), "Silver", NULL);
769 }
770 if (gold)
771 {
772 gtk_container_remove (GTK_CONTAINER (widget), gold);
773 g_object_set_data (G_OBJECT (widget), "Gold", NULL);
774 }
775
776 return;
777 }
778
779
780 if (gold)
781 return;
782 else if (silver)
783 color = "Gold";
784 else
785 color = "Silver";
786
787 row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
788 text = g_strconcat ("<b>", color, "</b>", NULL);
789 label = gtk_label_new (text);
790 g_free (text);
791 g_object_set (label,
792 "use-markup", TRUE,
793 "halign", GTK_ALIGN_START,
794 "valign", GTK_ALIGN_CENTER,
795 "margin", 6,
796 "xalign", 0.0,
797 NULL);
798 gtk_box_pack_start (GTK_BOX (row), label, TRUE, TRUE, 0);
799 gdk_rgba_parse (&rgba, color);
800 swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
801 "rgba", &rgba,
802 "selectable", FALSE,
803 "halign", GTK_ALIGN_END,
804 "valign", GTK_ALIGN_CENTER,
805 "margin", 6,
806 "height-request", 24,
807 NULL);
808 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
809 gtk_container_add (GTK_CONTAINER (box), swatch);
810 gtk_box_pack_start (GTK_BOX (row), box, FALSE, FALSE, 0);
811 gtk_widget_show_all (row);
812 gtk_list_box_insert (GTK_LIST_BOX (widget), row, -1);
813 row = gtk_widget_get_parent (row);
814 gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
815 g_object_set_data (G_OBJECT (widget), color, row);
816 g_object_set_data (G_OBJECT (row), "color", (gpointer)color);
817 }
818
819 static void
rgba_changed(GtkColorChooser * chooser,GParamSpec * pspec,GtkListBox * box)820 rgba_changed (GtkColorChooser *chooser, GParamSpec *pspec, GtkListBox *box)
821 {
822 gtk_list_box_select_row (box, NULL);
823 }
824
825 static void
set_color(GtkListBox * box,GtkListBoxRow * row,GtkColorChooser * chooser)826 set_color (GtkListBox *box, GtkListBoxRow *row, GtkColorChooser *chooser)
827 {
828 const char *color;
829 GdkRGBA rgba;
830
831 if (!row)
832 return;
833
834 color = (const char *)g_object_get_data (G_OBJECT (row), "color");
835
836 if (!color)
837 return;
838
839 if (gdk_rgba_parse (&rgba, color))
840 {
841 g_signal_handlers_block_by_func (chooser, rgba_changed, box);
842 gtk_color_chooser_set_rgba (chooser, &rgba);
843 g_signal_handlers_unblock_by_func (chooser, rgba_changed, box);
844 }
845 }
846
847 static void
populate_colors(GtkWidget * widget,GtkWidget * chooser)848 populate_colors (GtkWidget *widget, GtkWidget *chooser)
849 {
850 struct { const gchar *name; const gchar *color; const gchar *title; } colors[] = {
851 { "2.5", "#C8828C", "Red" },
852 { "5", "#C98286", NULL },
853 { "7.5", "#C9827F", NULL },
854 { "10", "#C98376", NULL },
855 { "2.5", "#C8856D", "Red/Yellow" },
856 { "5", "#C58764", NULL },
857 { "7.5", "#C1895E", NULL },
858 { "10", "#BB8C56", NULL },
859 { "2.5", "#B58F4F", "Yellow" },
860 { "5", "#AD924B", NULL },
861 { "7.5", "#A79548", NULL },
862 { "10", "#A09749", NULL },
863 { "2.5", "#979A4E", "Yellow/Green" },
864 { "5", "#8D9C55", NULL },
865 { "7.5", "#7F9F62", NULL },
866 { "10", "#73A06E", NULL },
867 { "2.5", "#65A27C", "Green" },
868 { "5", "#5CA386", NULL },
869 { "7.5", "#57A38D", NULL },
870 { "10", "#52A394", NULL },
871 { "2.5", "#4EA39A", "Green/Blue" },
872 { "5", "#49A3A2", NULL },
873 { "7.5", "#46A2AA", NULL },
874 { "10", "#46A1B1", NULL },
875 { "2.5", "#49A0B8", "Blue" },
876 { "5", "#529EBD", NULL },
877 { "7.5", "#5D9CC1", NULL },
878 { "10", "#689AC3", NULL },
879 { "2.5", "#7597C5", "Blue/Purple" },
880 { "5", "#8095C6", NULL },
881 { "7.5", "#8D91C6", NULL },
882 { "10", "#988EC4", NULL },
883 { "2.5", "#A08CC1", "Purple" },
884 { "5", "#A88ABD", NULL },
885 { "7.5", "#B187B6", NULL },
886 { "10", "#B786B0", NULL },
887 { "2.5", "#BC84A9", "Purple/Red" },
888 { "5", "#C183A0", NULL },
889 { "7.5", "#C48299", NULL },
890 { "10", "#C68292", NULL }
891 };
892 gint i;
893 GtkWidget *row, *box, *label, *swatch;
894 GtkWidget *sw;
895 GdkRGBA rgba;
896
897 gtk_list_box_set_header_func (GTK_LIST_BOX (widget), update_title_header, NULL, NULL);
898
899 for (i = 0; i < G_N_ELEMENTS (colors); i++)
900 {
901 row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
902 label = gtk_label_new (colors[i].name);
903 g_object_set (label,
904 "halign", GTK_ALIGN_START,
905 "valign", GTK_ALIGN_CENTER,
906 "margin", 6,
907 "xalign", 0.0,
908 NULL);
909 gtk_box_pack_start (GTK_BOX (row), label, TRUE, TRUE, 0);
910 gdk_rgba_parse (&rgba, colors[i].color);
911 swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
912 "rgba", &rgba,
913 "selectable", FALSE,
914 "halign", GTK_ALIGN_END,
915 "valign", GTK_ALIGN_CENTER,
916 "margin", 6,
917 "height-request", 24,
918 NULL);
919 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
920 gtk_container_add (GTK_CONTAINER (box), swatch);
921 gtk_box_pack_start (GTK_BOX (row), box, FALSE, FALSE, 0);
922 gtk_widget_show_all (row);
923 gtk_list_box_insert (GTK_LIST_BOX (widget), row, -1);
924 row = gtk_widget_get_parent (row);
925 gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
926 g_object_set_data (G_OBJECT (row), "color", (gpointer)colors[i].color);
927 if (colors[i].title)
928 g_object_set_data (G_OBJECT (row), "title", (gpointer)colors[i].title);
929 }
930
931 g_signal_connect (widget, "row-selected", G_CALLBACK (set_color), chooser);
932
933 gtk_list_box_invalidate_headers (GTK_LIST_BOX (widget));
934
935 sw = gtk_widget_get_ancestor (widget, GTK_TYPE_SCROLLED_WINDOW);
936 g_signal_connect (sw, "edge-overshot", G_CALLBACK (overshot), widget);
937 }
938
939 typedef struct {
940 GtkWidget *flowbox;
941 gchar *filename;
942 } BackgroundData;
943
944 static void
background_loaded_cb(GObject * source,GAsyncResult * res,gpointer data)945 background_loaded_cb (GObject *source,
946 GAsyncResult *res,
947 gpointer data)
948 {
949 BackgroundData *bd = data;
950 GtkWidget *child;
951 GdkPixbuf *pixbuf;
952 GError *error = NULL;
953
954 pixbuf = gdk_pixbuf_new_from_stream_finish (res, &error);
955 if (error)
956 {
957 g_warning ("Error loading '%s': %s", bd->filename, error->message);
958 g_error_free (error);
959 return;
960 }
961
962 child = gtk_image_new_from_pixbuf (pixbuf);
963 gtk_widget_show (child);
964 gtk_flow_box_insert (GTK_FLOW_BOX (bd->flowbox), child, -1);
965 child = gtk_widget_get_parent (child);
966 g_object_set_data_full (G_OBJECT (child), "filename", bd->filename, g_free);
967 g_free (bd);
968 }
969
970 static void
populate_flowbox(GtkWidget * flowbox)971 populate_flowbox (GtkWidget *flowbox)
972 {
973 const gchar *location;
974 GDir *dir;
975 GError *error = NULL;
976 const gchar *name;
977 gchar *filename;
978 GFile *file;
979 GInputStream *stream;
980 BackgroundData *bd;
981 GdkPixbuf *pixbuf;
982 GtkWidget *child;
983
984 if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (flowbox), "populated")))
985 return;
986
987 g_object_set_data (G_OBJECT (flowbox), "populated", GUINT_TO_POINTER (1));
988
989 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 110, 70);
990 gdk_pixbuf_fill (pixbuf, 0xffffffff);
991 child = gtk_image_new_from_pixbuf (pixbuf);
992 gtk_widget_show (child);
993 gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), child, -1);
994
995 location = "/usr/share/backgrounds/gnome";
996 dir = g_dir_open (location, 0, &error);
997 if (error)
998 {
999 g_warning ("%s", error->message);
1000 g_error_free (error);
1001 return;
1002 }
1003
1004 while ((name = g_dir_read_name (dir)) != NULL)
1005 {
1006 filename = g_build_filename (location, name, NULL);
1007 file = g_file_new_for_path (filename);
1008 stream = G_INPUT_STREAM (g_file_read (file, NULL, &error));
1009 if (error)
1010 {
1011 g_warning ("%s", error->message);
1012 g_clear_error (&error);
1013 g_free (filename);
1014 }
1015 else
1016 {
1017 bd = g_new (BackgroundData, 1);
1018 bd->flowbox = flowbox;
1019 bd->filename = filename;
1020 gdk_pixbuf_new_from_stream_at_scale_async (stream, 110, 110, TRUE, NULL,
1021 background_loaded_cb, bd);
1022 }
1023
1024 g_object_unref (file);
1025 g_object_unref (stream);
1026 }
1027
1028 g_dir_close (dir);
1029 }
1030
1031 static void
row_activated(GtkListBox * box,GtkListBoxRow * row)1032 row_activated (GtkListBox *box, GtkListBoxRow *row)
1033 {
1034 GtkWidget *image;
1035 GtkWidget *dialog;
1036
1037 image = (GtkWidget *)g_object_get_data (G_OBJECT (row), "image");
1038 dialog = (GtkWidget *)g_object_get_data (G_OBJECT (row), "dialog");
1039
1040 if (image)
1041 {
1042 if (gtk_widget_get_opacity (image) > 0)
1043 gtk_widget_set_opacity (image, 0);
1044 else
1045 gtk_widget_set_opacity (image, 1);
1046 }
1047 else if (dialog)
1048 {
1049 gtk_window_present (GTK_WINDOW (dialog));
1050 }
1051 }
1052
1053 static void
set_accel(GtkApplication * app,GtkWidget * widget)1054 set_accel (GtkApplication *app, GtkWidget *widget)
1055 {
1056 GtkWidget *accel_label;
1057 const gchar *action;
1058 gchar **accels;
1059 guint key;
1060 GdkModifierType mods;
1061
1062 accel_label = gtk_bin_get_child (GTK_BIN (widget));
1063 g_assert (GTK_IS_ACCEL_LABEL (accel_label));
1064
1065 action = gtk_actionable_get_action_name (GTK_ACTIONABLE (widget));
1066 accels = gtk_application_get_accels_for_action (app, action);
1067
1068 gtk_accelerator_parse (accels[0], &key, &mods);
1069 gtk_accel_label_set_accel (GTK_ACCEL_LABEL (accel_label), key, mods);
1070
1071 g_strfreev (accels);
1072 }
1073
1074 typedef struct
1075 {
1076 GtkTextView tv;
1077 cairo_surface_t *surface;
1078 } MyTextView;
1079
1080 typedef GtkTextViewClass MyTextViewClass;
1081
G_DEFINE_TYPE(MyTextView,my_text_view,GTK_TYPE_TEXT_VIEW)1082 G_DEFINE_TYPE (MyTextView, my_text_view, GTK_TYPE_TEXT_VIEW)
1083
1084 static void
1085 my_text_view_init (MyTextView *tv)
1086 {
1087 }
1088
1089 static void
my_tv_draw_layer(GtkTextView * widget,GtkTextViewLayer layer,cairo_t * cr)1090 my_tv_draw_layer (GtkTextView *widget,
1091 GtkTextViewLayer layer,
1092 cairo_t *cr)
1093 {
1094 MyTextView *tv = (MyTextView *)widget;
1095
1096 if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT && tv->surface)
1097 {
1098 cairo_save (cr);
1099 cairo_set_source_surface (cr, tv->surface, 0.0, 0.0);
1100 cairo_paint_with_alpha (cr, 0.333);
1101 cairo_restore (cr);
1102 }
1103 }
1104
1105 static void
my_tv_finalize(GObject * object)1106 my_tv_finalize (GObject *object)
1107 {
1108 MyTextView *tv = (MyTextView *)object;
1109
1110 if (tv->surface)
1111 cairo_surface_destroy (tv->surface);
1112
1113 G_OBJECT_CLASS (my_text_view_parent_class)->finalize (object);
1114 }
1115
1116 static void
my_text_view_class_init(MyTextViewClass * class)1117 my_text_view_class_init (MyTextViewClass *class)
1118 {
1119 GtkTextViewClass *tv_class = GTK_TEXT_VIEW_CLASS (class);
1120 GObjectClass *o_class = G_OBJECT_CLASS (class);
1121
1122 o_class->finalize = my_tv_finalize;
1123 tv_class->draw_layer = my_tv_draw_layer;
1124 }
1125
1126 static void
my_text_view_set_background(MyTextView * tv,const gchar * filename)1127 my_text_view_set_background (MyTextView *tv, const gchar *filename)
1128 {
1129 GdkPixbuf *pixbuf;
1130 GError *error = NULL;
1131
1132 if (tv->surface)
1133 cairo_surface_destroy (tv->surface);
1134
1135 tv->surface = NULL;
1136
1137 if (filename == NULL)
1138 return;
1139
1140 pixbuf = gdk_pixbuf_new_from_file (filename, &error);
1141 if (error)
1142 {
1143 g_warning ("%s", error->message);
1144 g_error_free (error);
1145 return;
1146 }
1147
1148 tv->surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
1149
1150 g_object_unref (pixbuf);
1151
1152 gtk_widget_queue_draw (GTK_WIDGET (tv));
1153 }
1154
1155 static void
close_selection_dialog(GtkWidget * dialog,gint response,GtkWidget * tv)1156 close_selection_dialog (GtkWidget *dialog, gint response, GtkWidget *tv)
1157 {
1158 GtkWidget *box;
1159 GtkWidget *child;
1160 GList *children;
1161 const gchar *filename;
1162
1163 gtk_widget_hide (dialog);
1164
1165 if (response == GTK_RESPONSE_CANCEL)
1166 return;
1167
1168 box = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
1169 children = gtk_container_get_children (GTK_CONTAINER (box));
1170 box = children->data;
1171 g_list_free (children);
1172 g_assert (GTK_IS_FLOW_BOX (box));
1173 children = gtk_flow_box_get_selected_children (GTK_FLOW_BOX (box));
1174
1175 if (!children)
1176 return;
1177
1178 child = children->data;
1179 filename = (const gchar *)g_object_get_data (G_OBJECT (child), "filename");
1180
1181 g_list_free (children);
1182
1183 my_text_view_set_background ((MyTextView *)tv, filename);
1184 }
1185
1186 static void
toggle_selection_mode(GtkSwitch * sw,GParamSpec * pspec,GtkListBox * listbox)1187 toggle_selection_mode (GtkSwitch *sw,
1188 GParamSpec *pspec,
1189 GtkListBox *listbox)
1190 {
1191 if (gtk_switch_get_active (sw))
1192 gtk_list_box_set_selection_mode (listbox, GTK_SELECTION_SINGLE);
1193 else
1194 gtk_list_box_set_selection_mode (listbox, GTK_SELECTION_NONE);
1195
1196 gtk_list_box_set_activate_on_single_click (listbox, !gtk_switch_get_active (sw));
1197 }
1198
1199 static void
handle_insert(GtkWidget * button,GtkWidget * textview)1200 handle_insert (GtkWidget *button, GtkWidget *textview)
1201 {
1202 GtkTextBuffer *buffer;
1203 const gchar *id;
1204 const gchar *text;
1205
1206 id = gtk_buildable_get_name (GTK_BUILDABLE (button));
1207
1208 if (strcmp (id, "toolbutton1") == 0)
1209 text = "⌘";
1210 else if (strcmp (id, "toolbutton2") == 0)
1211 text = "⚽";
1212 else if (strcmp (id, "toolbutton3") == 0)
1213 text = "⤢";
1214 else if (strcmp (id, "toolbutton4") == 0)
1215 text = "☆";
1216 else
1217 text = "";
1218
1219 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
1220 gtk_text_buffer_insert_at_cursor (buffer, text, -1);
1221 }
1222
1223 static void
handle_cutcopypaste(GtkWidget * button,GtkWidget * textview)1224 handle_cutcopypaste (GtkWidget *button, GtkWidget *textview)
1225 {
1226 GtkTextBuffer *buffer;
1227 GtkClipboard *clipboard;
1228 const gchar *id;
1229
1230 clipboard = gtk_widget_get_clipboard (textview, GDK_SELECTION_CLIPBOARD);
1231 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
1232 id = gtk_buildable_get_name (GTK_BUILDABLE (button));
1233
1234 if (strcmp (id, "cutbutton") == 0)
1235 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1236 else if (strcmp (id, "copybutton") == 0)
1237 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1238 else if (strcmp (id, "pastebutton") == 0)
1239 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1240 else if (strcmp (id, "deletebutton") == 0)
1241 gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
1242 }
1243
1244 static void
clipboard_owner_change(GtkClipboard * clipboard,GdkEvent * event,GtkWidget * button)1245 clipboard_owner_change (GtkClipboard *clipboard, GdkEvent *event, GtkWidget *button)
1246 {
1247 const gchar *id;
1248 gboolean has_text;
1249
1250 id = gtk_buildable_get_name (GTK_BUILDABLE (button));
1251 has_text = gtk_clipboard_wait_is_text_available (clipboard);
1252
1253 if (strcmp (id, "pastebutton") == 0)
1254 gtk_widget_set_sensitive (button, has_text);
1255 }
1256
1257 static void
textbuffer_notify_selection(GObject * object,GParamSpec * pspec,GtkWidget * button)1258 textbuffer_notify_selection (GObject *object, GParamSpec *pspec, GtkWidget *button)
1259 {
1260 const gchar *id;
1261 gboolean has_selection;
1262
1263 id = gtk_buildable_get_name (GTK_BUILDABLE (button));
1264 has_selection = gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (object));
1265
1266 if (strcmp (id, "cutbutton") == 0 ||
1267 strcmp (id, "copybutton") == 0 ||
1268 strcmp (id, "deletebutton") == 0)
1269 gtk_widget_set_sensitive (button, has_selection);
1270 }
1271
1272 static gboolean
osd_frame_button_press(GtkWidget * frame,GdkEventButton * event,gpointer data)1273 osd_frame_button_press (GtkWidget *frame, GdkEventButton *event, gpointer data)
1274 {
1275 GtkWidget *osd;
1276 gboolean visible;
1277
1278 osd = g_object_get_data (G_OBJECT (frame), "osd");
1279 visible = gtk_widget_get_visible (osd);
1280 gtk_widget_set_visible (osd, !visible);
1281
1282 return GDK_EVENT_STOP;
1283 }
1284
1285 static gboolean
page_combo_separator_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)1286 page_combo_separator_func (GtkTreeModel *model,
1287 GtkTreeIter *iter,
1288 gpointer data)
1289 {
1290 gchar *text;
1291 gboolean res;
1292
1293 gtk_tree_model_get (model, iter, 0, &text, -1);
1294 res = g_strcmp0 (text, "-") == 0;
1295 g_free (text);
1296
1297 return res;
1298 }
1299
1300 static void
activate_item(GtkWidget * item,GtkTextView * tv)1301 activate_item (GtkWidget *item, GtkTextView *tv)
1302 {
1303 const gchar *tag;
1304 GtkTextIter start, end;
1305 gboolean active;
1306
1307 g_object_get (item, "active", &active, NULL);
1308 tag = (const gchar *)g_object_get_data (G_OBJECT (item), "tag");
1309 gtk_text_buffer_get_selection_bounds (gtk_text_view_get_buffer (tv), &start, &end);
1310 if (active)
1311 gtk_text_buffer_apply_tag_by_name (gtk_text_view_get_buffer (tv), tag, &start, &end);
1312 else
1313 gtk_text_buffer_remove_tag_by_name (gtk_text_view_get_buffer (tv), tag, &start, &end);
1314 }
1315
1316 static void
add_item(GtkTextView * tv,GtkWidget * popup,const gchar * text,const gchar * tag,gboolean set)1317 add_item (GtkTextView *tv,
1318 GtkWidget *popup,
1319 const gchar *text,
1320 const gchar *tag,
1321 gboolean set)
1322 {
1323 GtkWidget *item, *label;
1324
1325 if (GTK_IS_MENU (popup))
1326 {
1327 item = gtk_check_menu_item_new ();
1328 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), set);
1329 g_signal_connect (item, "toggled", G_CALLBACK (activate_item), tv);
1330 }
1331 else
1332 {
1333 item = gtk_check_button_new ();
1334 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item), set);
1335 gtk_widget_set_focus_on_click (item, FALSE);
1336 g_signal_connect (item, "clicked", G_CALLBACK (activate_item), tv);
1337 }
1338
1339 label = gtk_label_new ("");
1340 gtk_label_set_xalign (GTK_LABEL (label), 0);
1341 gtk_label_set_markup (GTK_LABEL (label), text);
1342 gtk_widget_show (label);
1343 gtk_container_add (GTK_CONTAINER (item), label);
1344 g_object_set_data (G_OBJECT (item), "tag", (gpointer)tag);
1345 gtk_widget_show (item);
1346 gtk_container_add (GTK_CONTAINER (popup), item);
1347 }
1348
1349 static void
populate_popup(GtkTextView * tv,GtkWidget * popup)1350 populate_popup (GtkTextView *tv,
1351 GtkWidget *popup)
1352 {
1353 gboolean has_selection;
1354 GtkWidget *item;
1355 GtkTextIter start, end, iter;
1356 GtkTextTagTable *tags;
1357 GtkTextTag *bold, *italic, *underline;
1358 gboolean all_bold, all_italic, all_underline;
1359
1360 has_selection = gtk_text_buffer_get_selection_bounds (gtk_text_view_get_buffer (tv), &start, &end);
1361
1362 if (!has_selection)
1363 return;
1364
1365 tags = gtk_text_buffer_get_tag_table (gtk_text_view_get_buffer (tv));
1366 bold = gtk_text_tag_table_lookup (tags, "bold");
1367 italic = gtk_text_tag_table_lookup (tags, "italic");
1368 underline = gtk_text_tag_table_lookup (tags, "underline");
1369 all_bold = TRUE;
1370 all_italic = TRUE;
1371 all_underline = TRUE;
1372 gtk_text_iter_assign (&iter, &start);
1373 while (!gtk_text_iter_equal (&iter, &end))
1374 {
1375 all_bold &= gtk_text_iter_has_tag (&iter, bold);
1376 all_italic &= gtk_text_iter_has_tag (&iter, italic);
1377 all_underline &= gtk_text_iter_has_tag (&iter, underline);
1378 gtk_text_iter_forward_char (&iter);
1379 }
1380
1381 if (GTK_IS_MENU (popup))
1382 {
1383 item = gtk_separator_menu_item_new ();
1384 gtk_widget_show (item);
1385 gtk_container_add (GTK_CONTAINER (popup), item);
1386 }
1387
1388 add_item (tv, popup, "<b>Bold</b>", "bold", all_bold);
1389 add_item (tv, popup, "<i>Italics</i>", "italic", all_italic);
1390 add_item (tv, popup, "<u>Underline</u>", "underline", all_underline);
1391 }
1392
1393 static void
open_popover_text_changed(GtkEntry * entry,GParamSpec * pspec,GtkWidget * button)1394 open_popover_text_changed (GtkEntry *entry, GParamSpec *pspec, GtkWidget *button)
1395 {
1396 const gchar *text;
1397
1398 text = gtk_entry_get_text (entry);
1399 gtk_widget_set_sensitive (button, strlen (text) > 0);
1400 }
1401
1402 static gboolean
show_page_again(gpointer data)1403 show_page_again (gpointer data)
1404 {
1405 gtk_widget_show (GTK_WIDGET (data));
1406 return G_SOURCE_REMOVE;
1407 }
1408
1409 static void
tab_close_cb(GtkWidget * page)1410 tab_close_cb (GtkWidget *page)
1411 {
1412 gtk_widget_hide (page);
1413 g_timeout_add (2500, show_page_again, page);
1414 }
1415
1416 typedef struct _GTestPermission GTestPermission;
1417 typedef struct _GTestPermissionClass GTestPermissionClass;
1418
1419 struct _GTestPermission
1420 {
1421 GPermission parent;
1422 };
1423
1424 struct _GTestPermissionClass
1425 {
1426 GPermissionClass parent_class;
1427 };
1428
G_DEFINE_TYPE(GTestPermission,g_test_permission,G_TYPE_PERMISSION)1429 G_DEFINE_TYPE (GTestPermission, g_test_permission, G_TYPE_PERMISSION)
1430
1431 static void
1432 g_test_permission_init (GTestPermission *test)
1433 {
1434 g_permission_impl_update (G_PERMISSION (test), TRUE, TRUE, TRUE);
1435 }
1436
1437 static gboolean
update_allowed(GPermission * permission,gboolean allowed)1438 update_allowed (GPermission *permission,
1439 gboolean allowed)
1440 {
1441 g_permission_impl_update (permission, allowed, TRUE, TRUE);
1442
1443 return TRUE;
1444 }
1445
1446 static gboolean
acquire(GPermission * permission,GCancellable * cancellable,GError ** error)1447 acquire (GPermission *permission,
1448 GCancellable *cancellable,
1449 GError **error)
1450 {
1451 return update_allowed (permission, TRUE);
1452 }
1453
1454 static void
acquire_async(GPermission * permission,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1455 acquire_async (GPermission *permission,
1456 GCancellable *cancellable,
1457 GAsyncReadyCallback callback,
1458 gpointer user_data)
1459 {
1460 GTask *task;
1461
1462 task = g_task_new ((GObject*)permission, NULL, callback, user_data);
1463 g_task_return_boolean (task, update_allowed (permission, TRUE));
1464 g_object_unref (task);
1465 }
1466
1467 gboolean
acquire_finish(GPermission * permission,GAsyncResult * res,GError ** error)1468 acquire_finish (GPermission *permission,
1469 GAsyncResult *res,
1470 GError **error)
1471 {
1472 return g_task_propagate_boolean (G_TASK (res), error);
1473 }
1474
1475 static gboolean
release(GPermission * permission,GCancellable * cancellable,GError ** error)1476 release (GPermission *permission,
1477 GCancellable *cancellable,
1478 GError **error)
1479 {
1480 return update_allowed (permission, FALSE);
1481 }
1482
1483 static void
release_async(GPermission * permission,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1484 release_async (GPermission *permission,
1485 GCancellable *cancellable,
1486 GAsyncReadyCallback callback,
1487 gpointer user_data)
1488 {
1489 GTask *task;
1490
1491 task = g_task_new ((GObject*)permission, NULL, callback, user_data);
1492 g_task_return_boolean (task, update_allowed (permission, FALSE));
1493 g_object_unref (task);
1494 }
1495
1496 gboolean
release_finish(GPermission * permission,GAsyncResult * result,GError ** error)1497 release_finish (GPermission *permission,
1498 GAsyncResult *result,
1499 GError **error)
1500 {
1501 return g_task_propagate_boolean (G_TASK (result), error);
1502 }
1503
1504 static void
g_test_permission_class_init(GTestPermissionClass * class)1505 g_test_permission_class_init (GTestPermissionClass *class)
1506 {
1507 GPermissionClass *permission_class = G_PERMISSION_CLASS (class);
1508
1509 permission_class->acquire = acquire;
1510 permission_class->acquire_async = acquire_async;
1511 permission_class->acquire_finish = acquire_finish;
1512
1513 permission_class->release = release;
1514 permission_class->release_async = release_async;
1515 permission_class->release_finish = release_finish;
1516 }
1517
1518 static int icon_sizes[5];
1519
1520 static void
register_icon_sizes(void)1521 register_icon_sizes (void)
1522 {
1523 static gboolean registered;
1524
1525 if (registered)
1526 return;
1527
1528 registered = TRUE;
1529
1530 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1531 icon_sizes[0] = gtk_icon_size_register ("a", 16, 16);
1532 icon_sizes[1] = gtk_icon_size_register ("b", 24, 24);
1533 icon_sizes[2] = gtk_icon_size_register ("c", 32, 32);
1534 icon_sizes[3] = gtk_icon_size_register ("d", 48, 48);
1535 icon_sizes[4] = gtk_icon_size_register ("e", 64, 64);
1536 G_GNUC_END_IGNORE_DEPRECATIONS
1537 }
1538
1539 static int
find_icon_size(GtkIconSize size)1540 find_icon_size (GtkIconSize size)
1541 {
1542 gint w, h, w2, h2;
1543 gint i;
1544
1545 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1546 gtk_icon_size_lookup (size, &w, &h);
1547 for (i = 0; i < G_N_ELEMENTS (icon_sizes); i++)
1548 {
1549 gtk_icon_size_lookup (icon_sizes[i], &w2, &h2);
1550 if (w == w2)
1551 return i;
1552 }
1553 G_GNUC_END_IGNORE_DEPRECATIONS
1554
1555 return 2;
1556 }
1557
1558 static void
update_buttons(GtkWidget * iv,int pos)1559 update_buttons (GtkWidget *iv, int pos)
1560 {
1561 GtkWidget *button;
1562
1563 button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "increase_button"));
1564 gtk_widget_set_sensitive (button, pos + 1 < G_N_ELEMENTS (icon_sizes));
1565 button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "decrease_button"));
1566 gtk_widget_set_sensitive (button, pos > 0);
1567 }
1568
1569 static void
increase_icon_size(GtkWidget * iv)1570 increase_icon_size (GtkWidget *iv)
1571 {
1572 GList *cells;
1573 GtkCellRendererPixbuf *cell;
1574 GtkIconSize size;
1575 int i;
1576
1577 cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv));
1578 cell = cells->data;
1579 g_list_free (cells);
1580
1581 g_object_get (cell, "stock-size", &size, NULL);
1582
1583 i = find_icon_size (size);
1584 i = CLAMP (i + 1, 0, G_N_ELEMENTS (icon_sizes) - 1);
1585 size = icon_sizes[i];
1586
1587 g_object_set (cell, "stock-size", size, NULL);
1588
1589 update_buttons (iv, i);
1590
1591 gtk_widget_queue_resize (iv);
1592 }
1593
1594 static void
decrease_icon_size(GtkWidget * iv)1595 decrease_icon_size (GtkWidget *iv)
1596 {
1597 GList *cells;
1598 GtkCellRendererPixbuf *cell;
1599 GtkIconSize size;
1600 int i;
1601
1602 cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv));
1603 cell = cells->data;
1604 g_list_free (cells);
1605
1606 g_object_get (cell, "stock-size", &size, NULL);
1607
1608 i = find_icon_size (size);
1609 i = CLAMP (i - 1, 0, G_N_ELEMENTS (icon_sizes) - 1);
1610 size = icon_sizes[i];
1611
1612 g_object_set (cell, "stock-size", size, NULL);
1613
1614 update_buttons (iv, i);
1615
1616 gtk_widget_queue_resize (iv);
1617 }
1618
1619 static void
reset_icon_size(GtkWidget * iv)1620 reset_icon_size (GtkWidget *iv)
1621 {
1622 GList *cells;
1623 GtkCellRendererPixbuf *cell;
1624
1625 cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv));
1626 cell = cells->data;
1627 g_list_free (cells);
1628
1629 g_object_set (cell, "stock-size", icon_sizes[2], NULL);
1630
1631 update_buttons (iv, 2);
1632
1633 gtk_widget_queue_resize (iv);
1634 }
1635
1636 static gchar *
scale_format_value_blank(GtkScale * scale,gdouble value)1637 scale_format_value_blank (GtkScale *scale, gdouble value)
1638 {
1639 return g_strdup (" ");
1640 }
1641
1642 static gchar *
scale_format_value(GtkScale * scale,gdouble value)1643 scale_format_value (GtkScale *scale, gdouble value)
1644 {
1645 return g_strdup_printf ("%0.*f", 1, value);
1646 }
1647
1648 static void
adjustment3_value_changed(GtkAdjustment * adj,GtkProgressBar * pbar)1649 adjustment3_value_changed (GtkAdjustment *adj, GtkProgressBar *pbar)
1650 {
1651 double fraction;
1652
1653 fraction = gtk_adjustment_get_value (adj) / (gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj));
1654
1655 gtk_progress_bar_set_fraction (pbar, fraction);
1656 }
1657
1658 static void
validate_more_details(GtkEntry * entry,GParamSpec * pspec,GtkEntry * details)1659 validate_more_details (GtkEntry *entry,
1660 GParamSpec *pspec,
1661 GtkEntry *details)
1662 {
1663 if (strlen (gtk_entry_get_text (entry)) > 0 &&
1664 strlen (gtk_entry_get_text (details)) == 0)
1665 {
1666 gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "Must have details first");
1667 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (entry)), "error");
1668 }
1669 else
1670 {
1671 gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "");
1672 gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (entry)), "error");
1673 }
1674 }
1675
1676 static gboolean
mode_switch_state_set(GtkSwitch * sw,gboolean state)1677 mode_switch_state_set (GtkSwitch *sw, gboolean state)
1678 {
1679 GtkWidget *dialog = gtk_widget_get_ancestor (GTK_WIDGET (sw), GTK_TYPE_DIALOG);
1680 GtkWidget *scale = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "level_scale"));
1681 GtkWidget *label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "error_label"));
1682
1683 if (!state ||
1684 (gtk_range_get_value (GTK_RANGE (scale)) > 50))
1685 {
1686 gtk_widget_hide (label);
1687 gtk_switch_set_state (sw, state);
1688 }
1689 else
1690 {
1691 gtk_widget_show (label);
1692 }
1693
1694 return TRUE;
1695 }
1696
1697 static void
level_scale_value_changed(GtkRange * range)1698 level_scale_value_changed (GtkRange *range)
1699 {
1700 GtkWidget *dialog = gtk_widget_get_ancestor (GTK_WIDGET (range), GTK_TYPE_DIALOG);
1701 GtkWidget *sw = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "mode_switch"));
1702 GtkWidget *label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "error_label"));
1703
1704 if (gtk_switch_get_active (GTK_SWITCH (sw)) &&
1705 !gtk_switch_get_state (GTK_SWITCH (sw)) &&
1706 (gtk_range_get_value (range) > 50))
1707 {
1708 gtk_widget_hide (label);
1709 gtk_switch_set_state (GTK_SWITCH (sw), TRUE);
1710 }
1711 else if (gtk_switch_get_state (GTK_SWITCH (sw)) &&
1712 (gtk_range_get_value (range) <= 50))
1713 {
1714 gtk_switch_set_state (GTK_SWITCH (sw), FALSE);
1715 }
1716 }
1717
1718 static void
activate(GApplication * app)1719 activate (GApplication *app)
1720 {
1721 GtkBuilder *builder;
1722 GtkWindow *window;
1723 GtkWidget *widget;
1724 GtkWidget *widget2;
1725 GtkWidget *widget3;
1726 GtkWidget *widget4;
1727 GtkWidget *stack;
1728 GtkWidget *dialog;
1729 GtkAdjustment *adj;
1730 GtkCssProvider *provider;
1731 static GActionEntry win_entries[] = {
1732 { "dark", NULL, NULL, "false", change_theme_state },
1733 { "transition", NULL, NULL, "false", change_transition_state },
1734 { "search", activate_search, NULL, NULL, NULL },
1735 { "delete", activate_delete, NULL, NULL, NULL },
1736 { "busy", get_busy, NULL, NULL, NULL },
1737 { "background", activate_background, NULL, NULL, NULL },
1738 { "open", activate_open, NULL, NULL, NULL },
1739 { "record", activate_record, NULL, NULL, NULL },
1740 { "lock", activate_lock, NULL, NULL, NULL },
1741 };
1742 struct {
1743 const gchar *action_and_target;
1744 const gchar *accelerators[2];
1745 } accels[] = {
1746 { "app.about", { "F1", NULL } },
1747 { "app.quit", { "<Primary>q", NULL } },
1748 { "win.dark", { "<Primary>d", NULL } },
1749 { "win.search", { "<Primary>s", NULL } },
1750 { "win.delete", { "Delete", NULL } },
1751 { "win.background", { "<Primary>b", NULL } },
1752 { "win.open", { "<Primary>o", NULL } },
1753 { "win.record", { "<Primary>r", NULL } },
1754 { "win.lock", { "<Primary>l", NULL } },
1755 };
1756 gint i;
1757 GPermission *permission;
1758 GAction *action;
1759
1760 g_type_ensure (my_text_view_get_type ());
1761 register_icon_sizes ();
1762
1763 provider = gtk_css_provider_new ();
1764 gtk_css_provider_load_from_resource (provider, "/org/gtk/WidgetFactory/widget-factory.css");
1765 gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
1766 GTK_STYLE_PROVIDER (provider),
1767 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1768 g_object_unref (provider);
1769
1770 builder = gtk_builder_new_from_resource ("/org/gtk/WidgetFactory/widget-factory.ui");
1771 gtk_builder_add_callback_symbol (builder, "on_entry_icon_release", (GCallback)on_entry_icon_release);
1772 gtk_builder_add_callback_symbol (builder, "on_scale_button_value_changed", (GCallback)on_scale_button_value_changed);
1773 gtk_builder_add_callback_symbol (builder, "on_scale_button_query_tooltip", (GCallback)on_scale_button_query_tooltip);
1774 gtk_builder_add_callback_symbol (builder, "on_record_button_toggled", (GCallback)on_record_button_toggled);
1775 gtk_builder_add_callback_symbol (builder, "on_page_combo_changed", (GCallback)on_page_combo_changed);
1776 gtk_builder_add_callback_symbol (builder, "on_range_from_changed", (GCallback)on_range_from_changed);
1777 gtk_builder_add_callback_symbol (builder, "on_range_to_changed", (GCallback)on_range_to_changed);
1778 gtk_builder_add_callback_symbol (builder, "osd_frame_button_press", (GCallback)osd_frame_button_press);
1779 gtk_builder_add_callback_symbol (builder, "tab_close_cb", (GCallback)tab_close_cb);
1780 gtk_builder_add_callback_symbol (builder, "increase_icon_size", (GCallback)increase_icon_size);
1781 gtk_builder_add_callback_symbol (builder, "decrease_icon_size", (GCallback)decrease_icon_size);
1782 gtk_builder_add_callback_symbol (builder, "reset_icon_size", (GCallback)reset_icon_size);
1783 gtk_builder_add_callback_symbol (builder, "scale_format_value", (GCallback)scale_format_value);
1784 gtk_builder_add_callback_symbol (builder, "scale_format_value_blank", (GCallback)scale_format_value_blank);
1785 gtk_builder_add_callback_symbol (builder, "validate_more_details", (GCallback)validate_more_details);
1786 gtk_builder_add_callback_symbol (builder, "mode_switch_state_set", (GCallback)mode_switch_state_set);
1787 gtk_builder_add_callback_symbol (builder, "level_scale_value_changed", (GCallback)level_scale_value_changed);
1788
1789 gtk_builder_connect_signals (builder, NULL);
1790
1791 window = (GtkWindow *)gtk_builder_get_object (builder, "window");
1792 gtk_application_add_window (GTK_APPLICATION (app), window);
1793 g_action_map_add_action_entries (G_ACTION_MAP (window),
1794 win_entries, G_N_ELEMENTS (win_entries),
1795 window);
1796
1797 for (i = 0; i < G_N_ELEMENTS (accels); i++)
1798 gtk_application_set_accels_for_action (GTK_APPLICATION (app), accels[i].action_and_target, accels[i].accelerators);
1799
1800 widget = (GtkWidget *)gtk_builder_get_object (builder, "statusbar");
1801 gtk_statusbar_push (GTK_STATUSBAR (widget), 0, "All systems are operating normally.");
1802 action = G_ACTION (g_property_action_new ("statusbar", widget, "visible"));
1803 g_action_map_add_action (G_ACTION_MAP (window), action);
1804 g_object_unref (G_OBJECT (action));
1805
1806 widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbar");
1807 action = G_ACTION (g_property_action_new ("toolbar", widget, "visible"));
1808 g_action_map_add_action (G_ACTION_MAP (window), action);
1809 g_object_unref (G_OBJECT (action));
1810
1811 adj = (GtkAdjustment *)gtk_builder_get_object (builder, "adjustment1");
1812
1813 widget = (GtkWidget *)gtk_builder_get_object (builder, "progressbar3");
1814 g_signal_connect (adj, "value-changed", G_CALLBACK (update_pulse_time), widget);
1815 update_pulse_time (adj, widget);
1816
1817 widget = (GtkWidget *)gtk_builder_get_object (builder, "entry1");
1818 g_signal_connect (adj, "value-changed", G_CALLBACK (update_pulse_time), widget);
1819 update_pulse_time (adj, widget);
1820
1821 widget = (GtkWidget *)gtk_builder_get_object (builder, "page2reset");
1822 adj = (GtkAdjustment *) gtk_builder_get_object (builder, "adjustment2");
1823 g_signal_connect (widget, "clicked", G_CALLBACK (spin_value_reset), adj);
1824
1825 widget = (GtkWidget *)gtk_builder_get_object (builder, "page2dismiss");
1826 g_signal_connect (widget, "clicked", G_CALLBACK (dismiss), NULL);
1827
1828 widget = (GtkWidget *)gtk_builder_get_object (builder, "page2note");
1829 adj = (GtkAdjustment *) gtk_builder_get_object (builder, "adjustment2");
1830 g_signal_connect (adj, "value-changed", G_CALLBACK (spin_value_changed), widget);
1831
1832 widget = (GtkWidget *)gtk_builder_get_object (builder, "listbox");
1833 gtk_list_box_set_header_func (GTK_LIST_BOX (widget), update_header, NULL, NULL);
1834 g_signal_connect (widget, "row-activated", G_CALLBACK (row_activated), NULL);
1835
1836 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow1switch");
1837 g_signal_connect (widget2, "notify::active", G_CALLBACK (toggle_selection_mode), widget);
1838
1839 widget = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow3");
1840 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow3image");
1841 g_object_set_data (G_OBJECT (widget), "image", widget2);
1842
1843 widget = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow4");
1844 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog");
1845 g_object_set_data (G_OBJECT (widget), "dialog", widget2);
1846
1847 widget = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow5button");
1848 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog");
1849 g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_window_present), widget2);
1850
1851 widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbar");
1852 g_object_set_data (G_OBJECT (window), "toolbar", widget);
1853
1854 widget = (GtkWidget *)gtk_builder_get_object (builder, "searchbar");
1855 g_object_set_data (G_OBJECT (window), "searchbar", widget);
1856
1857 widget = (GtkWidget *)gtk_builder_get_object (builder, "infobar");
1858 g_signal_connect (widget, "response", G_CALLBACK (info_bar_response), NULL);
1859 g_object_set_data (G_OBJECT (window), "infobar", widget);
1860
1861 dialog = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog");
1862 g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
1863 widget = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog_button");
1864 g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
1865
1866 dialog = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog");
1867 g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
1868 widget = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog_button");
1869 g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
1870
1871 widget = (GtkWidget *)gtk_builder_get_object (builder, "act_action_dialog");
1872 stack = (GtkWidget *)gtk_builder_get_object (builder, "toplevel_stack");
1873 g_signal_connect (widget, "clicked", G_CALLBACK (action_dialog_button_clicked), stack);
1874 g_signal_connect (stack, "notify::visible-child-name", G_CALLBACK (page_changed_cb), NULL);
1875 page_changed_cb (stack, NULL, NULL);
1876
1877 page_stack = stack;
1878
1879 dialog = (GtkWidget *)gtk_builder_get_object (builder, "preference_dialog");
1880 g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
1881 widget = (GtkWidget *)gtk_builder_get_object (builder, "preference_dialog_button");
1882 g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
1883 widget = (GtkWidget *)gtk_builder_get_object (builder, "circular_button");
1884 g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
1885
1886 widget = (GtkWidget *)gtk_builder_get_object (builder, "level_scale");
1887 g_object_set_data (G_OBJECT (dialog), "level_scale", widget);
1888 widget = (GtkWidget *)gtk_builder_get_object (builder, "mode_switch");
1889 g_object_set_data (G_OBJECT (dialog), "mode_switch", widget);
1890 widget = (GtkWidget *)gtk_builder_get_object (builder, "error_label");
1891 g_object_set_data (G_OBJECT (dialog), "error_label", widget);
1892
1893 dialog = (GtkWidget *)gtk_builder_get_object (builder, "selection_dialog");
1894 g_object_set_data (G_OBJECT (window), "selection_dialog", dialog);
1895 widget = (GtkWidget *)gtk_builder_get_object (builder, "text3");
1896 g_signal_connect (dialog, "response", G_CALLBACK (close_selection_dialog), widget);
1897 widget = (GtkWidget *)gtk_builder_get_object (builder, "selection_dialog_button");
1898 g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
1899
1900 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "selection_flowbox");
1901 g_object_set_data (G_OBJECT (window), "selection_flowbox", widget2);
1902 g_signal_connect_swapped (widget, "clicked", G_CALLBACK (populate_flowbox), widget2);
1903
1904 widget = (GtkWidget *)gtk_builder_get_object (builder, "charletree");
1905 populate_model ((GtkTreeStore *)gtk_tree_view_get_model (GTK_TREE_VIEW (widget)));
1906 gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (widget), row_separator_func, NULL, NULL);
1907 gtk_tree_view_expand_all (GTK_TREE_VIEW (widget));
1908
1909 widget = GTK_WIDGET (gtk_builder_get_object (builder, "munsell"));
1910 widget2 = GTK_WIDGET (gtk_builder_get_object (builder, "cchooser"));
1911
1912 populate_colors (widget, widget2);
1913 g_signal_connect (widget2, "notify::rgba", G_CALLBACK (rgba_changed), widget);
1914
1915 widget = (GtkWidget *)gtk_builder_get_object (builder, "page_combo");
1916 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (widget), page_combo_separator_func, NULL, NULL);
1917 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "range_from_spin");
1918 widget3 = (GtkWidget *)gtk_builder_get_object (builder, "range_to_spin");
1919 widget4 = (GtkWidget *)gtk_builder_get_object (builder, "print_button");
1920 g_object_set_data (G_OBJECT (widget), "range_from_spin", widget2);
1921 g_object_set_data (G_OBJECT (widget3), "range_from_spin", widget2);
1922 g_object_set_data (G_OBJECT (widget), "range_to_spin", widget3);
1923 g_object_set_data (G_OBJECT (widget2), "range_to_spin", widget3);
1924 g_object_set_data (G_OBJECT (widget), "print_button", widget4);
1925
1926 set_accel (GTK_APPLICATION (app), GTK_WIDGET (gtk_builder_get_object (builder, "quitmenuitem")));
1927 set_accel (GTK_APPLICATION (app), GTK_WIDGET (gtk_builder_get_object (builder, "deletemenuitem")));
1928 set_accel (GTK_APPLICATION (app), GTK_WIDGET (gtk_builder_get_object (builder, "searchmenuitem")));
1929 set_accel (GTK_APPLICATION (app), GTK_WIDGET (gtk_builder_get_object (builder, "darkmenuitem")));
1930 set_accel (GTK_APPLICATION (app), GTK_WIDGET (gtk_builder_get_object (builder, "aboutmenuitem")));
1931 set_accel (GTK_APPLICATION (app), GTK_WIDGET (gtk_builder_get_object (builder, "bgmenuitem")));
1932
1933 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "tooltextview");
1934
1935 widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton1");
1936 g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
1937 widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton2");
1938 g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
1939 widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton3");
1940 g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
1941 widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton4");
1942 g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
1943 widget = (GtkWidget *)gtk_builder_get_object (builder, "cutbutton");
1944 g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
1945 g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection",
1946 G_CALLBACK (textbuffer_notify_selection), widget);
1947 widget = (GtkWidget *)gtk_builder_get_object (builder, "copybutton");
1948 g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
1949 g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection",
1950 G_CALLBACK (textbuffer_notify_selection), widget);
1951 widget = (GtkWidget *)gtk_builder_get_object (builder, "deletebutton");
1952 g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
1953 g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection",
1954 G_CALLBACK (textbuffer_notify_selection), widget);
1955 widget = (GtkWidget *)gtk_builder_get_object (builder, "pastebutton");
1956 g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
1957 g_signal_connect_object (gtk_widget_get_clipboard (widget2, GDK_SELECTION_CLIPBOARD), "owner-change",
1958 G_CALLBACK (clipboard_owner_change), widget, 0);
1959
1960 widget = (GtkWidget *)gtk_builder_get_object (builder, "osd_frame");
1961 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "totem_like_osd");
1962 g_object_set_data (G_OBJECT (widget), "osd", widget2);
1963
1964 widget = (GtkWidget *)gtk_builder_get_object (builder, "textview1");
1965 g_signal_connect (widget, "populate-popup",
1966 G_CALLBACK (populate_popup), NULL);
1967
1968 widget = (GtkWidget *)gtk_builder_get_object (builder, "open_popover");
1969 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "open_popover_entry");
1970 widget3 = (GtkWidget *)gtk_builder_get_object (builder, "open_popover_button");
1971 gtk_popover_set_default_widget (GTK_POPOVER (widget), widget3);
1972 g_signal_connect (widget2, "notify::text", G_CALLBACK (open_popover_text_changed), widget3);
1973 g_signal_connect_swapped (widget3, "clicked", G_CALLBACK (gtk_widget_hide), widget);
1974 widget = (GtkWidget *)gtk_builder_get_object (builder, "open_menubutton");
1975 g_object_set_data (G_OBJECT (window), "open_menubutton", widget);
1976 widget = (GtkWidget *)gtk_builder_get_object (builder, "record_button");
1977 g_object_set_data (G_OBJECT (window), "record_button", widget);
1978
1979 widget = (GtkWidget *)gtk_builder_get_object (builder, "lockbox");
1980 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "lockbutton");
1981 g_object_set_data (G_OBJECT (window), "lockbutton", widget2);
1982 permission = g_object_new (g_test_permission_get_type (), NULL);
1983 g_object_bind_property (permission, "allowed",
1984 widget, "sensitive",
1985 G_BINDING_SYNC_CREATE);
1986 action = g_action_map_lookup_action (G_ACTION_MAP (window), "open");
1987 g_object_bind_property (permission, "allowed",
1988 action, "enabled",
1989 G_BINDING_SYNC_CREATE);
1990 action = g_action_map_lookup_action (G_ACTION_MAP (window), "record");
1991 g_object_bind_property (permission, "allowed",
1992 action, "enabled",
1993 G_BINDING_SYNC_CREATE);
1994 gtk_lock_button_set_permission (GTK_LOCK_BUTTON (widget2), permission);
1995 g_object_unref (permission);
1996
1997 widget = (GtkWidget *)gtk_builder_get_object (builder, "iconview1");
1998 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "increase_button");
1999 g_object_set_data (G_OBJECT (widget), "increase_button", widget2);
2000 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "decrease_button");
2001 g_object_set_data (G_OBJECT (widget), "decrease_button", widget2);
2002
2003 adj = (GtkAdjustment *)gtk_builder_get_object (builder, "adjustment3");
2004 widget = (GtkWidget *)gtk_builder_get_object (builder, "progressbar1");
2005 widget2 = (GtkWidget *)gtk_builder_get_object (builder, "progressbar2");
2006 g_signal_connect (adj, "value-changed", G_CALLBACK (adjustment3_value_changed), widget);
2007 g_signal_connect (adj, "value-changed", G_CALLBACK (adjustment3_value_changed), widget2);
2008
2009 gtk_widget_show_all (GTK_WIDGET (window));
2010
2011 g_object_unref (builder);
2012 }
2013
2014 static void
print_version(void)2015 print_version (void)
2016 {
2017 g_print ("gtk3-widget-factory %d.%d.%d\n",
2018 gtk_get_major_version (),
2019 gtk_get_minor_version (),
2020 gtk_get_micro_version ());
2021 }
2022
2023 static int
local_options(GApplication * app,GVariantDict * options,gpointer data)2024 local_options (GApplication *app,
2025 GVariantDict *options,
2026 gpointer data)
2027 {
2028 gboolean version = FALSE;
2029
2030 g_variant_dict_lookup (options, "version", "b", &version);
2031
2032 if (version)
2033 {
2034 print_version ();
2035 return 0;
2036 }
2037
2038 return -1;
2039 }
2040
2041 int
main(int argc,char * argv[])2042 main (int argc, char *argv[])
2043 {
2044 GtkApplication *app;
2045 GAction *action;
2046 static GActionEntry app_entries[] = {
2047 { "about", activate_about, NULL, NULL, NULL },
2048 { "quit", activate_quit, NULL, NULL, NULL },
2049 { "inspector", activate_inspector, NULL, NULL, NULL },
2050 { "main", NULL, "s", "'steak'", NULL },
2051 { "wine", NULL, NULL, "false", NULL },
2052 { "beer", NULL, NULL, "false", NULL },
2053 { "water", NULL, NULL, "true", NULL },
2054 { "dessert", NULL, "s", "'bars'", NULL },
2055 { "pay", NULL, "s", NULL, NULL }
2056 };
2057 gint status;
2058
2059 app = gtk_application_new ("org.gtk.WidgetFactory", G_APPLICATION_NON_UNIQUE);
2060
2061 g_action_map_add_action_entries (G_ACTION_MAP (app),
2062 app_entries, G_N_ELEMENTS (app_entries),
2063 app);
2064 action = g_action_map_lookup_action (G_ACTION_MAP (app), "wine");
2065 g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
2066
2067 g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
2068
2069 g_application_add_main_option (G_APPLICATION (app), "version", 0, 0, G_OPTION_ARG_NONE, "Show program version", NULL);
2070
2071 g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
2072 status = g_application_run (G_APPLICATION (app), argc, argv);
2073 g_object_unref (app);
2074
2075 return status;
2076 }
2077