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 <stdlib.h> |
24 | |
25 | #include <glib/gi18n.h> |
26 | #include <gtk/gtk.h> |
27 | |
28 | #include "demo_conf.h" |
29 | |
30 | static void |
31 | change_dark_state (GSimpleAction *action, |
32 | GVariant *state, |
33 | gpointer user_data) |
34 | { |
35 | GtkSettings *settings = gtk_settings_get_default (); |
36 | |
37 | g_object_set (G_OBJECT (settings), |
38 | first_property_name: "gtk-application-prefer-dark-theme" , |
39 | g_variant_get_boolean (value: state), |
40 | NULL); |
41 | |
42 | g_simple_action_set_state (simple: action, value: state); |
43 | } |
44 | |
45 | static void |
46 | change_theme_state (GSimpleAction *action, |
47 | GVariant *state, |
48 | gpointer user_data) |
49 | { |
50 | GtkSettings *settings = gtk_settings_get_default (); |
51 | const char *s; |
52 | const char *theme; |
53 | |
54 | g_simple_action_set_state (simple: action, value: state); |
55 | |
56 | s = g_variant_get_string (value: state, NULL); |
57 | |
58 | if (strcmp (s1: s, s2: "default" ) == 0) |
59 | theme = "Default" ; |
60 | else if (strcmp (s1: s, s2: "dark" ) == 0) |
61 | theme = "Default-dark" ; |
62 | else if (strcmp (s1: s, s2: "hc" ) == 0) |
63 | theme = "Default-hc" ; |
64 | else if (strcmp (s1: s, s2: "hc-dark" ) == 0) |
65 | theme = "Default-hc-dark" ; |
66 | else if (strcmp (s1: s, s2: "current" ) == 0) |
67 | { |
68 | gtk_settings_reset_property (settings, name: "gtk-theme-name" ); |
69 | gtk_settings_reset_property (settings, name: "gtk-application-prefer-dark-theme" ); |
70 | return; |
71 | } |
72 | else |
73 | return; |
74 | |
75 | g_object_set (G_OBJECT (settings), |
76 | first_property_name: "gtk-theme-name" , theme, |
77 | "gtk-application-prefer-dark-theme" , FALSE, |
78 | NULL); |
79 | } |
80 | |
81 | static void |
82 | change_fullscreen (GSimpleAction *action, |
83 | GVariant *state, |
84 | gpointer user_data) |
85 | { |
86 | GtkWindow *window = user_data; |
87 | |
88 | if (g_variant_get_boolean (value: state)) |
89 | gtk_window_fullscreen (window); |
90 | else |
91 | gtk_window_unfullscreen (window); |
92 | |
93 | g_simple_action_set_state (simple: action, value: state); |
94 | } |
95 | |
96 | static GtkWidget *page_stack; |
97 | |
98 | static void |
99 | transition_speed_changed (GtkRange *range, |
100 | gpointer data) |
101 | { |
102 | double value; |
103 | |
104 | value = gtk_range_get_value (range); |
105 | gtk_stack_set_transition_duration (GTK_STACK (page_stack), duration: (int)value); |
106 | } |
107 | |
108 | static void |
109 | change_transition_state (GSimpleAction *action, |
110 | GVariant *state, |
111 | gpointer user_data) |
112 | { |
113 | GtkStackTransitionType transition; |
114 | |
115 | if (g_variant_get_boolean (value: state)) |
116 | transition = GTK_STACK_TRANSITION_TYPE_CROSSFADE; |
117 | else |
118 | transition = GTK_STACK_TRANSITION_TYPE_NONE; |
119 | |
120 | gtk_stack_set_transition_type (GTK_STACK (page_stack), transition); |
121 | |
122 | g_simple_action_set_state (simple: action, value: state); |
123 | } |
124 | |
125 | static gboolean |
126 | get_idle (gpointer data) |
127 | { |
128 | GtkWidget *window = data; |
129 | GtkApplication *app = gtk_window_get_application (GTK_WINDOW (window)); |
130 | |
131 | gtk_widget_set_sensitive (widget: window, TRUE); |
132 | gdk_surface_set_cursor (surface: gtk_native_get_surface (self: GTK_NATIVE (ptr: window)), NULL); |
133 | g_application_unmark_busy (G_APPLICATION (app)); |
134 | |
135 | return G_SOURCE_REMOVE; |
136 | } |
137 | |
138 | static void |
139 | get_busy (GSimpleAction *action, |
140 | GVariant *parameter, |
141 | gpointer user_data) |
142 | { |
143 | GtkWidget *window = user_data; |
144 | GdkCursor *cursor; |
145 | GtkApplication *app = gtk_window_get_application (GTK_WINDOW (window)); |
146 | |
147 | g_application_mark_busy (G_APPLICATION (app)); |
148 | cursor = gdk_cursor_new_from_name (name: "wait" , NULL); |
149 | gdk_surface_set_cursor (surface: gtk_native_get_surface (self: GTK_NATIVE (ptr: window)), cursor); |
150 | g_object_unref (object: cursor); |
151 | g_timeout_add (interval: 5000, function: get_idle, data: window); |
152 | |
153 | gtk_widget_set_sensitive (widget: window, FALSE); |
154 | } |
155 | |
156 | static int current_page = 0; |
157 | static gboolean |
158 | on_page (int i) |
159 | { |
160 | return current_page == i; |
161 | } |
162 | |
163 | static void |
164 | activate_search (GSimpleAction *action, |
165 | GVariant *parameter, |
166 | gpointer user_data) |
167 | { |
168 | GtkWidget *window = user_data; |
169 | GtkWidget *searchbar; |
170 | |
171 | if (!on_page (i: 2)) |
172 | return; |
173 | |
174 | searchbar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "searchbar" )); |
175 | gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (searchbar), TRUE); |
176 | } |
177 | |
178 | static void |
179 | activate_delete (GSimpleAction *action, |
180 | GVariant *parameter, |
181 | gpointer user_data) |
182 | { |
183 | GtkWidget *window = user_data; |
184 | GtkWidget *infobar; |
185 | |
186 | g_print (format: "Activate action delete\n" ); |
187 | |
188 | if (!on_page (i: 2)) |
189 | return; |
190 | |
191 | infobar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "infobar" )); |
192 | gtk_widget_show (widget: infobar); |
193 | } |
194 | |
195 | static void populate_flowbox (GtkWidget *flowbox); |
196 | |
197 | static void |
198 | activate_background (GSimpleAction *action, |
199 | GVariant *parameter, |
200 | gpointer user_data) |
201 | { |
202 | GtkWidget *window = user_data; |
203 | GtkWidget *dialog; |
204 | GtkWidget *flowbox; |
205 | |
206 | if (!on_page (i: 2)) |
207 | return; |
208 | |
209 | dialog = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "selection_dialog" )); |
210 | flowbox = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "selection_flowbox" )); |
211 | |
212 | gtk_widget_show (widget: dialog); |
213 | populate_flowbox (flowbox); |
214 | } |
215 | |
216 | static void |
217 | activate_open (GSimpleAction *action, |
218 | GVariant *parameter, |
219 | gpointer user_data) |
220 | { |
221 | GtkWidget *window = user_data; |
222 | GtkWidget *button; |
223 | |
224 | if (!on_page (i: 3)) |
225 | return; |
226 | |
227 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "open_menubutton" )); |
228 | g_signal_emit_by_name (instance: button, detailed_signal: "clicked" ); |
229 | } |
230 | |
231 | static void |
232 | activate_record (GSimpleAction *action, |
233 | GVariant *parameter, |
234 | gpointer user_data) |
235 | { |
236 | GtkWidget *window = user_data; |
237 | GtkWidget *button; |
238 | |
239 | if (!on_page (i: 3)) |
240 | return; |
241 | |
242 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "record_button" )); |
243 | g_signal_emit_by_name (instance: button, detailed_signal: "clicked" ); |
244 | } |
245 | |
246 | static void |
247 | activate_lock (GSimpleAction *action, |
248 | GVariant *parameter, |
249 | gpointer user_data) |
250 | { |
251 | GtkWidget *window = user_data; |
252 | GtkWidget *button; |
253 | |
254 | if (!on_page (i: 3)) |
255 | return; |
256 | |
257 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "lockbutton" )); |
258 | g_signal_emit_by_name (instance: button, detailed_signal: "clicked" ); |
259 | } |
260 | |
261 | static void |
262 | activate_about (GSimpleAction *action, |
263 | GVariant *parameter, |
264 | gpointer user_data) |
265 | { |
266 | GtkApplication *app = user_data; |
267 | GtkWindow *window; |
268 | GtkWidget *button; |
269 | const char *authors[] = { |
270 | "Andrea Cimitan" , |
271 | "Cosimo Cecchi" , |
272 | NULL |
273 | }; |
274 | const char *maintainers[] = { |
275 | "The GTK Team" , |
276 | NULL |
277 | }; |
278 | char *version; |
279 | char *os_name; |
280 | char *os_version; |
281 | GString *s; |
282 | GtkWidget *dialog; |
283 | |
284 | s = g_string_new (init: "" ); |
285 | |
286 | window = gtk_application_get_active_window (application: app); |
287 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "open_menubutton" )); |
288 | gtk_menu_button_popdown (GTK_MENU_BUTTON (button)); |
289 | |
290 | os_name = g_get_os_info (G_OS_INFO_KEY_NAME); |
291 | os_version = g_get_os_info (G_OS_INFO_KEY_VERSION_ID); |
292 | if (os_name && os_version) |
293 | g_string_append_printf (string: s, format: "OS\t%s %s\n\n" , os_name, os_version); |
294 | g_string_append (string: s, val: "System libraries\n" ); |
295 | g_string_append_printf (string: s, format: "\tGLib\t%d.%d.%d\n" , |
296 | glib_major_version, |
297 | glib_minor_version, |
298 | glib_micro_version); |
299 | g_string_append_printf (string: s, format: "\tPango\t%s\n" , |
300 | pango_version_string ()); |
301 | g_string_append_printf (string: s, format: "\tGTK \t%d.%d.%d\n" , |
302 | gtk_get_major_version (), |
303 | gtk_get_minor_version (), |
304 | gtk_get_micro_version ()); |
305 | g_string_append_printf (string: s, format: "\nA link can appear here: <http://www.gtk.org>" ); |
306 | |
307 | version = g_strdup_printf (format: "%s%s%s\nRunning against GTK %d.%d.%d" , |
308 | PACKAGE_VERSION, |
309 | g_strcmp0 (str1: PROFILE, str2: "devel" ) == 0 ? "-" : "" , |
310 | g_strcmp0 (str1: PROFILE, str2: "devel" ) == 0 ? VCS_TAG : "" , |
311 | gtk_get_major_version (), |
312 | gtk_get_minor_version (), |
313 | gtk_get_micro_version ()); |
314 | |
315 | dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG, |
316 | first_property_name: "transient-for" , gtk_application_get_active_window (application: app), |
317 | "modal" , TRUE, |
318 | "program-name" , g_strcmp0 (str1: PROFILE, str2: "devel" ) == 0 |
319 | ? "GTK Widget Factory (Development)" |
320 | : "GTK Widget Factory" , |
321 | "version" , version, |
322 | "copyright" , "© 1997—2021 The GTK Team" , |
323 | "license-type" , GTK_LICENSE_LGPL_2_1, |
324 | "website" , "http://www.gtk.org" , |
325 | "comments" , "Program to demonstrate GTK themes and widgets" , |
326 | "authors" , authors, |
327 | "logo-icon-name" , "org.gtk.WidgetFactory4" , |
328 | "title" , "About GTK Widget Factory" , |
329 | "system-information" , s->str, |
330 | NULL); |
331 | |
332 | gtk_about_dialog_add_credit_section (GTK_ABOUT_DIALOG (dialog), |
333 | _("Maintained by" ), people: maintainers); |
334 | |
335 | gtk_window_present (GTK_WINDOW (dialog)); |
336 | |
337 | g_string_free (string: s, TRUE); |
338 | g_free (mem: version); |
339 | g_free (mem: os_name); |
340 | g_free (mem: os_version); |
341 | } |
342 | |
343 | static void |
344 | activate_shortcuts_window (GSimpleAction *action, |
345 | GVariant *parameter, |
346 | gpointer user_data) |
347 | { |
348 | GtkApplication *app = user_data; |
349 | GtkWindow *window; |
350 | GtkWidget *button; |
351 | |
352 | window = gtk_application_get_active_window (application: app); |
353 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "open_menubutton" )); |
354 | gtk_menu_button_popdown (GTK_MENU_BUTTON (button)); |
355 | gtk_widget_activate_action (GTK_WIDGET (window), name: "win.show-help-overlay" , NULL); |
356 | } |
357 | |
358 | static void |
359 | activate_quit (GSimpleAction *action, |
360 | GVariant *parameter, |
361 | gpointer user_data) |
362 | { |
363 | GtkApplication *app = user_data; |
364 | GtkWidget *win; |
365 | GList *list, *next; |
366 | |
367 | list = gtk_application_get_windows (application: app); |
368 | while (list) |
369 | { |
370 | win = list->data; |
371 | next = list->next; |
372 | |
373 | gtk_window_destroy (GTK_WINDOW (win)); |
374 | |
375 | list = next; |
376 | } |
377 | } |
378 | |
379 | static void |
380 | activate_inspector (GSimpleAction *action, |
381 | GVariant *parameter, |
382 | gpointer user_data) |
383 | { |
384 | gtk_window_set_interactive_debugging (TRUE); |
385 | } |
386 | |
387 | static void |
388 | print_operation_done (GtkPrintOperation *op, |
389 | GtkPrintOperationResult res, |
390 | gpointer data) |
391 | { |
392 | GError *error = NULL; |
393 | |
394 | switch (res) |
395 | { |
396 | case GTK_PRINT_OPERATION_RESULT_ERROR: |
397 | gtk_print_operation_get_error (op, error: &error); |
398 | g_print (format: "Printing failed: %s\n" , error->message); |
399 | g_clear_error (err: &error); |
400 | break; |
401 | case GTK_PRINT_OPERATION_RESULT_APPLY: |
402 | break; |
403 | case GTK_PRINT_OPERATION_RESULT_CANCEL: |
404 | g_print (format: "Printing was canceled\n" ); |
405 | break; |
406 | case GTK_PRINT_OPERATION_RESULT_IN_PROGRESS: |
407 | return; |
408 | default: |
409 | g_assert_not_reached (); |
410 | break; |
411 | } |
412 | |
413 | g_object_unref (object: op); |
414 | } |
415 | |
416 | static void |
417 | print_operation_begin (GtkPrintOperation *op, |
418 | GtkPrintContext *context, |
419 | gpointer data) |
420 | { |
421 | gtk_print_operation_set_n_pages (op, n_pages: 1); |
422 | } |
423 | |
424 | static void |
425 | print_operation_page (GtkPrintOperation *op, |
426 | GtkPrintContext *context, |
427 | int page, |
428 | gpointer data) |
429 | { |
430 | cairo_t *cr; |
431 | double width; |
432 | double aspect_ratio; |
433 | GdkSnapshot *snapshot; |
434 | GdkPaintable *paintable; |
435 | GskRenderNode *node; |
436 | |
437 | g_print (format: "Save the trees!\n" ); |
438 | |
439 | cr = gtk_print_context_get_cairo_context (context); |
440 | width = gtk_print_context_get_width (context); |
441 | |
442 | snapshot = gtk_snapshot_new (); |
443 | paintable = gtk_widget_paintable_new (GTK_WIDGET (data)); |
444 | aspect_ratio = gdk_paintable_get_intrinsic_aspect_ratio (paintable); |
445 | gdk_paintable_snapshot (paintable, snapshot, width, height: width / aspect_ratio); |
446 | node = gtk_snapshot_free_to_node (snapshot); |
447 | |
448 | gsk_render_node_draw (node, cr); |
449 | |
450 | gsk_render_node_unref (node); |
451 | |
452 | g_object_unref (object: paintable); |
453 | } |
454 | |
455 | static void |
456 | activate_print (GSimpleAction *action, |
457 | GVariant *parameter, |
458 | gpointer user_data) |
459 | { |
460 | GtkWindow *window = GTK_WINDOW (user_data); |
461 | GtkPrintOperation *op; |
462 | GtkPrintOperationResult res; |
463 | |
464 | op = gtk_print_operation_new (); |
465 | gtk_print_operation_set_allow_async (op, TRUE); |
466 | g_signal_connect (op, "begin-print" , G_CALLBACK (print_operation_begin), NULL); |
467 | g_signal_connect (op, "draw-page" , G_CALLBACK (print_operation_page), window); |
468 | g_signal_connect (op, "done" , G_CALLBACK (print_operation_done), NULL); |
469 | |
470 | gtk_print_operation_set_embed_page_setup (op, TRUE); |
471 | |
472 | res = gtk_print_operation_run (op, action: GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, parent: window, NULL); |
473 | |
474 | if (res == GTK_PRINT_OPERATION_RESULT_IN_PROGRESS) |
475 | return; |
476 | |
477 | print_operation_done (op, res, NULL); |
478 | } |
479 | |
480 | static void |
481 | spin_value_changed (GtkAdjustment *adjustment, GtkWidget *label) |
482 | { |
483 | GtkWidget *w; |
484 | int v; |
485 | char *text; |
486 | |
487 | v = (int)gtk_adjustment_get_value (adjustment); |
488 | |
489 | if ((v % 3) == 0) |
490 | { |
491 | text = g_strdup_printf (format: "%d is a multiple of 3" , v); |
492 | gtk_label_set_label (GTK_LABEL (label), str: text); |
493 | g_free (mem: text); |
494 | } |
495 | |
496 | w = gtk_widget_get_ancestor (widget: label, GTK_TYPE_REVEALER); |
497 | gtk_revealer_set_reveal_child (GTK_REVEALER (w), reveal_child: (v % 3) == 0); |
498 | } |
499 | |
500 | static void |
501 | dismiss (GtkWidget *button) |
502 | { |
503 | GtkWidget *w; |
504 | |
505 | w = gtk_widget_get_ancestor (widget: button, GTK_TYPE_REVEALER); |
506 | gtk_revealer_set_reveal_child (GTK_REVEALER (w), FALSE); |
507 | } |
508 | |
509 | static void |
510 | spin_value_reset (GtkWidget *button, GtkAdjustment *adjustment) |
511 | { |
512 | gtk_adjustment_set_value (adjustment, value: 50.0); |
513 | dismiss (button); |
514 | } |
515 | |
516 | static int pulse_time = 250; |
517 | static int pulse_entry_mode = 0; |
518 | |
519 | static void |
520 | remove_pulse (gpointer pulse_id) |
521 | { |
522 | g_source_remove (GPOINTER_TO_UINT (pulse_id)); |
523 | } |
524 | |
525 | static gboolean |
526 | pulse_it (GtkWidget *widget) |
527 | { |
528 | guint pulse_id; |
529 | |
530 | if (GTK_IS_ENTRY (widget)) |
531 | gtk_entry_progress_pulse (GTK_ENTRY (widget)); |
532 | else |
533 | gtk_progress_bar_pulse (GTK_PROGRESS_BAR (widget)); |
534 | |
535 | pulse_id = g_timeout_add (interval: pulse_time, function: (GSourceFunc)pulse_it, data: widget); |
536 | g_object_set_data_full (G_OBJECT (widget), key: "pulse_id" , GUINT_TO_POINTER (pulse_id), destroy: remove_pulse); |
537 | |
538 | return G_SOURCE_REMOVE; |
539 | } |
540 | |
541 | static void |
542 | update_pulse_time (GtkAdjustment *adjustment, GtkWidget *widget) |
543 | { |
544 | double value; |
545 | guint pulse_id; |
546 | |
547 | value = gtk_adjustment_get_value (adjustment); |
548 | |
549 | pulse_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "pulse_id" )); |
550 | |
551 | /* vary between 50 and 450 */ |
552 | pulse_time = 50 + 4 * value; |
553 | |
554 | if (value == 100) |
555 | { |
556 | g_object_set_data (G_OBJECT (widget), key: "pulse_id" , NULL); |
557 | } |
558 | else if (value < 100) |
559 | { |
560 | if (pulse_id == 0 && (GTK_IS_PROGRESS_BAR (widget) || pulse_entry_mode % 3 == 2)) |
561 | { |
562 | pulse_id = g_timeout_add (interval: pulse_time, function: (GSourceFunc)pulse_it, data: widget); |
563 | g_object_set_data_full (G_OBJECT (widget), key: "pulse_id" , GUINT_TO_POINTER (pulse_id), destroy: remove_pulse); |
564 | } |
565 | } |
566 | } |
567 | |
568 | static void |
569 | on_entry_icon_release (GtkEntry *entry, |
570 | GtkEntryIconPosition icon_pos, |
571 | gpointer user_data) |
572 | { |
573 | if (icon_pos != GTK_ENTRY_ICON_SECONDARY) |
574 | return; |
575 | |
576 | pulse_entry_mode++; |
577 | |
578 | if (pulse_entry_mode % 3 == 0) |
579 | { |
580 | g_object_set_data (G_OBJECT (entry), key: "pulse_id" , NULL); |
581 | gtk_entry_set_progress_fraction (entry, fraction: 0); |
582 | } |
583 | else if (pulse_entry_mode % 3 == 1) |
584 | gtk_entry_set_progress_fraction (entry, fraction: 0.25); |
585 | else if (pulse_entry_mode % 3 == 2) |
586 | { |
587 | if (pulse_time - 50 < 400) |
588 | { |
589 | gtk_entry_set_progress_pulse_step (entry, fraction: 0.1); |
590 | pulse_it (GTK_WIDGET (entry)); |
591 | } |
592 | } |
593 | } |
594 | |
595 | #define EPSILON (1e-10) |
596 | |
597 | static void |
598 | on_scale_button_value_changed (GtkScaleButton *button, |
599 | double value, |
600 | gpointer user_data) |
601 | { |
602 | GtkAdjustment *adjustment; |
603 | double val; |
604 | char *str; |
605 | |
606 | adjustment = gtk_scale_button_get_adjustment (button); |
607 | val = gtk_scale_button_get_value (button); |
608 | |
609 | if (val < (gtk_adjustment_get_lower (adjustment) + EPSILON)) |
610 | { |
611 | str = g_strdup (_("Muted" )); |
612 | } |
613 | else if (val >= (gtk_adjustment_get_upper (adjustment) - EPSILON)) |
614 | { |
615 | str = g_strdup (_("Full Volume" )); |
616 | } |
617 | else |
618 | { |
619 | int percent; |
620 | |
621 | percent = (int) (100. * val / (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_lower (adjustment)) + .5); |
622 | |
623 | str = g_strdup_printf (C_("volume percentage" , "%d %%" ), percent); |
624 | } |
625 | |
626 | gtk_widget_set_tooltip_text (GTK_WIDGET (button), text: str); |
627 | |
628 | g_free (mem: str); |
629 | } |
630 | |
631 | static void |
632 | on_record_button_toggled (GtkToggleButton *button, |
633 | gpointer user_data) |
634 | { |
635 | |
636 | if (gtk_toggle_button_get_active (toggle_button: button)) |
637 | gtk_widget_remove_css_class (GTK_WIDGET (button), css_class: "destructive-action" ); |
638 | else |
639 | gtk_widget_add_css_class (GTK_WIDGET (button), css_class: "destructive-action" ); |
640 | } |
641 | |
642 | static void |
643 | on_page_combo_changed (GtkComboBox *combo, |
644 | gpointer user_data) |
645 | { |
646 | GtkWidget *from; |
647 | GtkWidget *to; |
648 | GtkWidget *print; |
649 | |
650 | from = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "range_from_spin" )); |
651 | to = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "range_to_spin" )); |
652 | print = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "print_button" )); |
653 | |
654 | switch (gtk_combo_box_get_active (combo_box: combo)) |
655 | { |
656 | case 0: /* Range */ |
657 | gtk_widget_set_sensitive (widget: from, TRUE); |
658 | gtk_widget_set_sensitive (widget: to, TRUE); |
659 | gtk_widget_set_sensitive (widget: print, TRUE); |
660 | break; |
661 | case 1: /* All */ |
662 | gtk_widget_set_sensitive (widget: from, FALSE); |
663 | gtk_widget_set_sensitive (widget: to, FALSE); |
664 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (from), value: 1); |
665 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (to), value: 99); |
666 | gtk_widget_set_sensitive (widget: print, TRUE); |
667 | break; |
668 | case 2: /* Current */ |
669 | gtk_widget_set_sensitive (widget: from, FALSE); |
670 | gtk_widget_set_sensitive (widget: to, FALSE); |
671 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (from), value: 7); |
672 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (to), value: 7); |
673 | gtk_widget_set_sensitive (widget: print, TRUE); |
674 | break; |
675 | case 4: |
676 | gtk_widget_set_sensitive (widget: from, FALSE); |
677 | gtk_widget_set_sensitive (widget: to, FALSE); |
678 | gtk_widget_set_sensitive (widget: print, FALSE); |
679 | break; |
680 | default:; |
681 | } |
682 | } |
683 | |
684 | static void |
685 | on_range_from_changed (GtkSpinButton *from) |
686 | { |
687 | GtkSpinButton *to; |
688 | int v1, v2; |
689 | |
690 | to = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (from), "range_to_spin" )); |
691 | |
692 | v1 = gtk_spin_button_get_value_as_int (spin_button: from); |
693 | v2 = gtk_spin_button_get_value_as_int (spin_button: to); |
694 | |
695 | if (v1 > v2) |
696 | gtk_spin_button_set_value (spin_button: to, value: v1); |
697 | } |
698 | |
699 | static void |
700 | on_range_to_changed (GtkSpinButton *to) |
701 | { |
702 | GtkSpinButton *from; |
703 | int v1, v2; |
704 | |
705 | from = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (to), "range_from_spin" )); |
706 | |
707 | v1 = gtk_spin_button_get_value_as_int (spin_button: from); |
708 | v2 = gtk_spin_button_get_value_as_int (spin_button: to); |
709 | |
710 | if (v1 > v2) |
711 | gtk_spin_button_set_value (spin_button: from, value: v2); |
712 | } |
713 | |
714 | static GdkContentProvider * |
715 | on_picture_drag_prepare (GtkDragSource *source, |
716 | double x, |
717 | double y, |
718 | gpointer unused) |
719 | { |
720 | GtkWidget *picture; |
721 | |
722 | picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source)); |
723 | |
724 | return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, gtk_picture_get_paintable (self: GTK_PICTURE (ptr: picture))); |
725 | } |
726 | |
727 | static gboolean |
728 | on_picture_drop (GtkDropTarget *dest, |
729 | const GValue *value, |
730 | double x, |
731 | double y, |
732 | gpointer unused) |
733 | { |
734 | GtkWidget *picture; |
735 | GdkPaintable *paintable; |
736 | |
737 | picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest)); |
738 | paintable = g_value_get_object (value); |
739 | |
740 | gtk_picture_set_paintable (self: GTK_PICTURE (ptr: picture), paintable); |
741 | |
742 | return TRUE; |
743 | } |
744 | |
745 | static void |
746 | info_bar_response (GtkWidget *infobar, int response_id) |
747 | { |
748 | if (response_id == GTK_RESPONSE_CLOSE) |
749 | gtk_widget_hide (widget: infobar); |
750 | } |
751 | |
752 | static void |
753 | show_dialog (GtkWidget *button, GtkWidget *dialog) |
754 | { |
755 | gtk_widget_show (widget: dialog); |
756 | } |
757 | |
758 | static void |
759 | close_dialog (GtkWidget *dialog) |
760 | { |
761 | gtk_widget_hide (widget: dialog); |
762 | } |
763 | |
764 | static void |
765 | set_needs_attention (GtkWidget *page, gboolean needs_attention) |
766 | { |
767 | GtkWidget *stack; |
768 | |
769 | stack = gtk_widget_get_parent (widget: page); |
770 | g_object_set (object: gtk_stack_get_page (GTK_STACK (stack), child: page), |
771 | first_property_name: "needs-attention" , needs_attention, |
772 | NULL); |
773 | } |
774 | |
775 | static gboolean |
776 | demand_attention (gpointer stack) |
777 | { |
778 | GtkWidget *page; |
779 | |
780 | page = gtk_stack_get_child_by_name (GTK_STACK (stack), name: "page3" ); |
781 | set_needs_attention (page, TRUE); |
782 | |
783 | return G_SOURCE_REMOVE; |
784 | } |
785 | |
786 | static void |
787 | action_dialog_button_clicked (GtkButton *button, GtkWidget *page) |
788 | { |
789 | g_timeout_add (interval: 1000, function: demand_attention, data: page); |
790 | } |
791 | |
792 | static void |
793 | page_changed_cb (GtkWidget *stack, GParamSpec *pspec, gpointer data) |
794 | { |
795 | const char *name; |
796 | GtkWidget *window; |
797 | GtkWidget *page; |
798 | |
799 | if (gtk_widget_in_destruction (widget: stack)) |
800 | return; |
801 | |
802 | name = gtk_stack_get_visible_child_name (GTK_STACK (stack)); |
803 | |
804 | window = gtk_widget_get_ancestor (widget: stack, GTK_TYPE_APPLICATION_WINDOW); |
805 | g_object_set (object: gtk_application_window_get_help_overlay (GTK_APPLICATION_WINDOW (window)), |
806 | first_property_name: "view-name" , name, |
807 | NULL); |
808 | |
809 | if (g_str_equal (v1: name, v2: "page1" )) |
810 | current_page = 1; |
811 | else if (g_str_equal (v1: name, v2: "page2" )) |
812 | current_page = 2; |
813 | if (g_str_equal (v1: name, v2: "page3" )) |
814 | { |
815 | current_page = 3; |
816 | page = gtk_stack_get_visible_child (GTK_STACK (stack)); |
817 | set_needs_attention (GTK_WIDGET (page), FALSE); |
818 | } |
819 | } |
820 | |
821 | static void |
822 | populate_model (GtkTreeStore *store) |
823 | { |
824 | GtkTreeIter iter, parent0, parent1, parent2, parent3; |
825 | |
826 | gtk_tree_store_append (tree_store: store, iter: &iter, NULL); |
827 | gtk_tree_store_set (tree_store: store, iter: &iter, |
828 | 0, "Charlemagne" , |
829 | 1, "742" , |
830 | 2, "814" , |
831 | -1); |
832 | parent0 = iter; |
833 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent0); |
834 | gtk_tree_store_set (tree_store: store, iter: &iter, |
835 | 0, "Pepin the Short" , |
836 | 1, "714" , |
837 | 2, "768" , |
838 | -1); |
839 | parent1 = iter; |
840 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent1); |
841 | gtk_tree_store_set (tree_store: store, iter: &iter, |
842 | 0, "Charles Martel" , |
843 | 1, "688" , |
844 | 2, "741" , |
845 | -1); |
846 | parent2 = iter; |
847 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent2); |
848 | gtk_tree_store_set (tree_store: store, iter: &iter, |
849 | 0, "Pepin of Herstal" , |
850 | 1, "635" , |
851 | 2, "714" , |
852 | -1); |
853 | parent3 = iter; |
854 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent3); |
855 | gtk_tree_store_set (tree_store: store, iter: &iter, |
856 | 0, "Ansegisel" , |
857 | 1, "602 or 610" , |
858 | 2, "murdered before 679" , |
859 | -1); |
860 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent3); |
861 | gtk_tree_store_set (tree_store: store, iter: &iter, |
862 | 0, "Begga" , |
863 | 1, "615" , |
864 | 2, "693" , |
865 | -1); |
866 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent2); |
867 | gtk_tree_store_set (tree_store: store, iter: &iter, |
868 | 0, "Alpaida" , |
869 | -1); |
870 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent1); |
871 | gtk_tree_store_set (tree_store: store, iter: &iter, |
872 | 0, "Rotrude" , |
873 | -1); |
874 | parent2 = iter; |
875 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent2); |
876 | gtk_tree_store_set (tree_store: store, iter: &iter, |
877 | 0, "Liévin de Trèves" , |
878 | -1); |
879 | parent3 = iter; |
880 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent3); |
881 | gtk_tree_store_set (tree_store: store, iter: &iter, |
882 | 0, "Guérin" , |
883 | -1); |
884 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent3); |
885 | gtk_tree_store_set (tree_store: store, iter: &iter, |
886 | 0, "Gunza" , |
887 | -1); |
888 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent2); |
889 | gtk_tree_store_set (tree_store: store, iter: &iter, |
890 | 0, "Willigarde de Bavière" , |
891 | -1); |
892 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent0); |
893 | gtk_tree_store_set (tree_store: store, iter: &iter, |
894 | 0, "Bertrada of Laon" , |
895 | 1, "710" , |
896 | 2, "783" , |
897 | -1); |
898 | parent1 = iter; |
899 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent1); |
900 | gtk_tree_store_set (tree_store: store, iter: &iter, |
901 | 0, "Caribert of Laon" , |
902 | 2, "before 762" , |
903 | -1); |
904 | parent2 = iter; |
905 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent2); |
906 | gtk_tree_store_set (tree_store: store, iter: &iter, |
907 | 0, "Unknown" , |
908 | -1); |
909 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent2); |
910 | gtk_tree_store_set (tree_store: store, iter: &iter, |
911 | 0, "Bertrada of Prüm" , |
912 | 1, "ca. 670" , |
913 | 2, "after 721" , |
914 | -1); |
915 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: &parent1); |
916 | gtk_tree_store_set (tree_store: store, iter: &iter, |
917 | 0, "Gisele of Aquitaine" , |
918 | -1); |
919 | gtk_tree_store_append (tree_store: store, iter: &iter, NULL); |
920 | gtk_tree_store_set (tree_store: store, iter: &iter, 3, TRUE, -1); |
921 | gtk_tree_store_append (tree_store: store, iter: &iter, NULL); |
922 | gtk_tree_store_set (tree_store: store, iter: &iter, |
923 | 0, "Attila the Hun" , |
924 | 1, "ca. 390" , |
925 | 2, "453" , |
926 | -1); |
927 | } |
928 | |
929 | static gboolean |
930 | row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) |
931 | { |
932 | gboolean is_sep; |
933 | |
934 | gtk_tree_model_get (tree_model: model, iter, 3, &is_sep, -1); |
935 | |
936 | return is_sep; |
937 | } |
938 | |
939 | static void |
940 | (GtkListBoxRow *row, |
941 | GtkListBoxRow *before, |
942 | gpointer data) |
943 | { |
944 | GtkWidget *; |
945 | char *title; |
946 | |
947 | header = gtk_list_box_row_get_header (row); |
948 | title = (char *)g_object_get_data (G_OBJECT (row), key: "title" ); |
949 | if (!header && title) |
950 | { |
951 | title = g_strdup_printf (format: "<b>%s</b>" , title); |
952 | |
953 | header = gtk_label_new (str: title); |
954 | gtk_label_set_use_markup (GTK_LABEL (header), TRUE); |
955 | gtk_widget_set_halign (widget: header, align: GTK_ALIGN_START); |
956 | gtk_widget_set_margin_top (widget: header, margin: 12); |
957 | gtk_widget_set_margin_start (widget: header, margin: 6); |
958 | gtk_widget_set_margin_end (widget: header, margin: 6); |
959 | gtk_widget_set_margin_bottom (widget: header, margin: 6); |
960 | gtk_widget_show (widget: header); |
961 | |
962 | gtk_list_box_row_set_header (row, header); |
963 | |
964 | g_free (mem: title); |
965 | } |
966 | } |
967 | |
968 | static void |
969 | overshot (GtkScrolledWindow *sw, GtkPositionType pos, GtkWidget *widget) |
970 | { |
971 | GtkWidget *box, *row, *label, *swatch; |
972 | GdkRGBA rgba; |
973 | const char *color; |
974 | char *text; |
975 | GtkWidget *silver; |
976 | GtkWidget *gold; |
977 | |
978 | silver = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "Silver" )); |
979 | gold = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "Gold" )); |
980 | |
981 | if (pos == GTK_POS_TOP) |
982 | { |
983 | if (silver) |
984 | { |
985 | gtk_list_box_remove (GTK_LIST_BOX (widget), child: silver); |
986 | g_object_set_data (G_OBJECT (widget), key: "Silver" , NULL); |
987 | } |
988 | if (gold) |
989 | { |
990 | gtk_list_box_remove (GTK_LIST_BOX (widget), child: gold); |
991 | g_object_set_data (G_OBJECT (widget), key: "Gold" , NULL); |
992 | } |
993 | |
994 | return; |
995 | } |
996 | |
997 | |
998 | if (gold) |
999 | return; |
1000 | else if (silver) |
1001 | color = "Gold" ; |
1002 | else |
1003 | color = "Silver" ; |
1004 | |
1005 | row = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 20); |
1006 | text = g_strconcat (string1: "<b>" , color, "</b>" , NULL); |
1007 | label = gtk_label_new (str: text); |
1008 | g_free (mem: text); |
1009 | g_object_set (object: label, |
1010 | first_property_name: "use-markup" , TRUE, |
1011 | "halign" , GTK_ALIGN_START, |
1012 | "valign" , GTK_ALIGN_CENTER, |
1013 | "hexpand" , TRUE, |
1014 | "margin-start" , 6, |
1015 | "margin-end" , 6, |
1016 | "margin-top" , 6, |
1017 | "margin-bottom" , 6, |
1018 | "xalign" , 0.0, |
1019 | NULL); |
1020 | gtk_box_append (GTK_BOX (row), child: label); |
1021 | gdk_rgba_parse (rgba: &rgba, spec: color); |
1022 | swatch = g_object_new (object_type: g_type_from_name (name: "GtkColorSwatch" ), |
1023 | first_property_name: "rgba" , &rgba, |
1024 | "can-focus" , FALSE, |
1025 | "selectable" , FALSE, |
1026 | "halign" , GTK_ALIGN_END, |
1027 | "valign" , GTK_ALIGN_CENTER, |
1028 | "margin-start" , 6, |
1029 | "margin-end" , 6, |
1030 | "margin-top" , 6, |
1031 | "margin-bottom" , 6, |
1032 | "height-request" , 24, |
1033 | NULL); |
1034 | box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0); |
1035 | gtk_box_append (GTK_BOX (box), child: swatch); |
1036 | gtk_box_append (GTK_BOX (row), child: box); |
1037 | gtk_list_box_insert (GTK_LIST_BOX (widget), child: row, position: -1); |
1038 | row = gtk_widget_get_parent (widget: row); |
1039 | gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); |
1040 | g_object_set_data (G_OBJECT (widget), key: color, data: row); |
1041 | g_object_set_data (G_OBJECT (row), key: "color" , data: (gpointer)color); |
1042 | } |
1043 | |
1044 | static void |
1045 | rgba_changed (GtkColorChooser *chooser, GParamSpec *pspec, GtkListBox *box) |
1046 | { |
1047 | gtk_list_box_select_row (box, NULL); |
1048 | } |
1049 | |
1050 | static void |
1051 | set_color (GtkListBox *box, GtkListBoxRow *row, GtkColorChooser *chooser) |
1052 | { |
1053 | const char *color; |
1054 | GdkRGBA rgba; |
1055 | |
1056 | if (!row) |
1057 | return; |
1058 | |
1059 | color = (const char *)g_object_get_data (G_OBJECT (row), key: "color" ); |
1060 | |
1061 | if (!color) |
1062 | return; |
1063 | |
1064 | if (gdk_rgba_parse (rgba: &rgba, spec: color)) |
1065 | { |
1066 | g_signal_handlers_block_by_func (chooser, rgba_changed, box); |
1067 | gtk_color_chooser_set_rgba (chooser, color: &rgba); |
1068 | g_signal_handlers_unblock_by_func (chooser, rgba_changed, box); |
1069 | } |
1070 | } |
1071 | |
1072 | static void |
1073 | populate_colors (GtkWidget *widget, GtkWidget *chooser) |
1074 | { |
1075 | struct { const char *name; const char *color; const char *title; } colors[] = { |
1076 | { "2.5" , "#C8828C" , "Red" }, |
1077 | { "5" , "#C98286" , NULL }, |
1078 | { "7.5" , "#C9827F" , NULL }, |
1079 | { "10" , "#C98376" , NULL }, |
1080 | { "2.5" , "#C8856D" , "Red/Yellow" }, |
1081 | { "5" , "#C58764" , NULL }, |
1082 | { "7.5" , "#C1895E" , NULL }, |
1083 | { "10" , "#BB8C56" , NULL }, |
1084 | { "2.5" , "#B58F4F" , "Yellow" }, |
1085 | { "5" , "#AD924B" , NULL }, |
1086 | { "7.5" , "#A79548" , NULL }, |
1087 | { "10" , "#A09749" , NULL }, |
1088 | { "2.5" , "#979A4E" , "Yellow/Green" }, |
1089 | { "5" , "#8D9C55" , NULL }, |
1090 | { "7.5" , "#7F9F62" , NULL }, |
1091 | { "10" , "#73A06E" , NULL }, |
1092 | { "2.5" , "#65A27C" , "Green" }, |
1093 | { "5" , "#5CA386" , NULL }, |
1094 | { "7.5" , "#57A38D" , NULL }, |
1095 | { "10" , "#52A394" , NULL }, |
1096 | { "2.5" , "#4EA39A" , "Green/Blue" }, |
1097 | { "5" , "#49A3A2" , NULL }, |
1098 | { "7.5" , "#46A2AA" , NULL }, |
1099 | { "10" , "#46A1B1" , NULL }, |
1100 | { "2.5" , "#49A0B8" , "Blue" }, |
1101 | { "5" , "#529EBD" , NULL }, |
1102 | { "7.5" , "#5D9CC1" , NULL }, |
1103 | { "10" , "#689AC3" , NULL }, |
1104 | { "2.5" , "#7597C5" , "Blue/Purple" }, |
1105 | { "5" , "#8095C6" , NULL }, |
1106 | { "7.5" , "#8D91C6" , NULL }, |
1107 | { "10" , "#988EC4" , NULL }, |
1108 | { "2.5" , "#A08CC1" , "Purple" }, |
1109 | { "5" , "#A88ABD" , NULL }, |
1110 | { "7.5" , "#B187B6" , NULL }, |
1111 | { "10" , "#B786B0" , NULL }, |
1112 | { "2.5" , "#BC84A9" , "Purple/Red" }, |
1113 | { "5" , "#C183A0" , NULL }, |
1114 | { "7.5" , "#C48299" , NULL }, |
1115 | { "10" , "#C68292" , NULL } |
1116 | }; |
1117 | int i; |
1118 | GtkWidget *row, *box, *label, *swatch; |
1119 | GtkWidget *sw; |
1120 | GdkRGBA rgba; |
1121 | |
1122 | gtk_list_box_set_header_func (GTK_LIST_BOX (widget), update_header: update_title_header, NULL, NULL); |
1123 | |
1124 | for (i = 0; i < G_N_ELEMENTS (colors); i++) |
1125 | { |
1126 | row = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 20); |
1127 | label = gtk_label_new (str: colors[i].name); |
1128 | g_object_set (object: label, |
1129 | first_property_name: "halign" , GTK_ALIGN_START, |
1130 | "valign" , GTK_ALIGN_CENTER, |
1131 | "margin-start" , 6, |
1132 | "margin-end" , 6, |
1133 | "margin-top" , 6, |
1134 | "margin-bottom" , 6, |
1135 | "hexpand" , TRUE, |
1136 | "xalign" , 0.0, |
1137 | NULL); |
1138 | gtk_box_append (GTK_BOX (row), child: label); |
1139 | gdk_rgba_parse (rgba: &rgba, spec: colors[i].color); |
1140 | swatch = g_object_new (object_type: g_type_from_name (name: "GtkColorSwatch" ), |
1141 | first_property_name: "rgba" , &rgba, |
1142 | "selectable" , FALSE, |
1143 | "can-focus" , FALSE, |
1144 | "halign" , GTK_ALIGN_END, |
1145 | "valign" , GTK_ALIGN_CENTER, |
1146 | "margin-start" , 6, |
1147 | "margin-end" , 6, |
1148 | "margin-top" , 6, |
1149 | "margin-bottom" , 6, |
1150 | "height-request" , 24, |
1151 | NULL); |
1152 | box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0); |
1153 | gtk_box_append (GTK_BOX (box), child: swatch); |
1154 | gtk_box_append (GTK_BOX (row), child: box); |
1155 | gtk_list_box_insert (GTK_LIST_BOX (widget), child: row, position: -1); |
1156 | row = gtk_widget_get_parent (widget: row); |
1157 | gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); |
1158 | g_object_set_data (G_OBJECT (row), key: "color" , data: (gpointer)colors[i].color); |
1159 | if (colors[i].title) |
1160 | g_object_set_data (G_OBJECT (row), key: "title" , data: (gpointer)colors[i].title); |
1161 | } |
1162 | |
1163 | g_signal_connect (widget, "row-selected" , G_CALLBACK (set_color), chooser); |
1164 | |
1165 | gtk_list_box_invalidate_headers (GTK_LIST_BOX (widget)); |
1166 | |
1167 | sw = gtk_widget_get_ancestor (widget, GTK_TYPE_SCROLLED_WINDOW); |
1168 | g_signal_connect (sw, "edge-overshot" , G_CALLBACK (overshot), widget); |
1169 | } |
1170 | |
1171 | typedef struct { |
1172 | GtkWidget *flowbox; |
1173 | char *filename; |
1174 | } BackgroundData; |
1175 | |
1176 | static void |
1177 | add_background (GtkWidget *flowbox, |
1178 | const char *filename, |
1179 | GdkPixbuf *pixbuf, |
1180 | gboolean is_resource) |
1181 | { |
1182 | GtkWidget *child; |
1183 | |
1184 | child = gtk_picture_new_for_pixbuf (pixbuf); |
1185 | gtk_widget_set_size_request (widget: child, width: 110, height: 70); |
1186 | gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), widget: child, position: -1); |
1187 | child = gtk_widget_get_parent (widget: child); |
1188 | g_object_set_data_full (G_OBJECT (child), key: "filename" , data: g_strdup (str: filename), destroy: g_free); |
1189 | if (is_resource) |
1190 | g_object_set_data (G_OBJECT (child), key: "is-resource" , GINT_TO_POINTER (1)); |
1191 | } |
1192 | |
1193 | static void |
1194 | background_loaded_cb (GObject *source, |
1195 | GAsyncResult *res, |
1196 | gpointer data) |
1197 | { |
1198 | BackgroundData *bd = data; |
1199 | GdkPixbuf *pixbuf; |
1200 | GError *error = NULL; |
1201 | |
1202 | pixbuf = gdk_pixbuf_new_from_stream_finish (async_result: res, error: &error); |
1203 | if (error) |
1204 | { |
1205 | g_warning ("Error loading '%s': %s" , bd->filename, error->message); |
1206 | g_error_free (error); |
1207 | return; |
1208 | } |
1209 | |
1210 | add_background (flowbox: bd->flowbox, filename: bd->filename, pixbuf, FALSE); |
1211 | |
1212 | g_free (mem: bd->filename); |
1213 | g_free (mem: bd); |
1214 | } |
1215 | |
1216 | static void |
1217 | populate_flowbox (GtkWidget *flowbox) |
1218 | { |
1219 | const char *location; |
1220 | GDir *dir; |
1221 | GError *error = NULL; |
1222 | const char *name; |
1223 | char *filename; |
1224 | GFile *file; |
1225 | GInputStream *stream; |
1226 | BackgroundData *bd; |
1227 | GdkPixbuf *pixbuf; |
1228 | GtkWidget *child; |
1229 | int i; |
1230 | const char *resources[] = { |
1231 | "sunset.jpg" , "portland-rose.jpg" , "beach.jpg" , "nyc.jpg" |
1232 | }; |
1233 | |
1234 | if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (flowbox), "populated" ))) |
1235 | return; |
1236 | |
1237 | g_object_set_data (G_OBJECT (flowbox), key: "populated" , GUINT_TO_POINTER (1)); |
1238 | |
1239 | pixbuf = gdk_pixbuf_new (colorspace: GDK_COLORSPACE_RGB, FALSE, bits_per_sample: 8, width: 110, height: 70); |
1240 | gdk_pixbuf_fill (pixbuf, pixel: 0xffffffff); |
1241 | child = gtk_picture_new_for_pixbuf (pixbuf); |
1242 | gtk_widget_add_css_class (widget: child, css_class: "frame" ); |
1243 | gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), widget: child, position: -1); |
1244 | |
1245 | for (i = 0; i < G_N_ELEMENTS (resources); i++) |
1246 | { |
1247 | filename = g_strconcat (string1: "/org/gtk/WidgetFactory4/" , resources[i], NULL); |
1248 | pixbuf = gdk_pixbuf_new_from_resource_at_scale (resource_path: filename, width: 110, height: 110, TRUE, NULL); |
1249 | add_background (flowbox, filename, pixbuf, TRUE); |
1250 | } |
1251 | |
1252 | location = "/usr/share/backgrounds/gnome" ; |
1253 | dir = g_dir_open (path: location, flags: 0, error: &error); |
1254 | if (error) |
1255 | { |
1256 | g_warning ("%s" , error->message); |
1257 | g_error_free (error); |
1258 | return; |
1259 | } |
1260 | |
1261 | while ((name = g_dir_read_name (dir)) != NULL) |
1262 | { |
1263 | if (g_str_has_suffix (str: name, suffix: ".xml" )) |
1264 | continue; |
1265 | |
1266 | filename = g_build_filename (first_element: location, name, NULL); |
1267 | file = g_file_new_for_path (path: filename); |
1268 | stream = G_INPUT_STREAM (g_file_read (file, NULL, &error)); |
1269 | if (error) |
1270 | { |
1271 | g_warning ("%s" , error->message); |
1272 | g_clear_error (err: &error); |
1273 | g_free (mem: filename); |
1274 | } |
1275 | else |
1276 | { |
1277 | bd = g_new (BackgroundData, 1); |
1278 | bd->flowbox = flowbox; |
1279 | bd->filename = filename; |
1280 | gdk_pixbuf_new_from_stream_at_scale_async (stream, width: 110, height: 110, TRUE, NULL, |
1281 | callback: background_loaded_cb, user_data: bd); |
1282 | } |
1283 | |
1284 | g_object_unref (object: file); |
1285 | g_object_unref (object: stream); |
1286 | } |
1287 | |
1288 | g_dir_close (dir); |
1289 | |
1290 | } |
1291 | |
1292 | static void |
1293 | row_activated (GtkListBox *box, GtkListBoxRow *row) |
1294 | { |
1295 | GtkWidget *image; |
1296 | GtkWidget *dialog; |
1297 | |
1298 | image = (GtkWidget *)g_object_get_data (G_OBJECT (row), key: "image" ); |
1299 | dialog = (GtkWidget *)g_object_get_data (G_OBJECT (row), key: "dialog" ); |
1300 | |
1301 | if (image) |
1302 | { |
1303 | if (gtk_widget_get_opacity (widget: image) > 0) |
1304 | gtk_widget_set_opacity (widget: image, opacity: 0); |
1305 | else |
1306 | gtk_widget_set_opacity (widget: image, opacity: 1); |
1307 | } |
1308 | else if (dialog) |
1309 | { |
1310 | gtk_window_present (GTK_WINDOW (dialog)); |
1311 | } |
1312 | } |
1313 | |
1314 | typedef struct |
1315 | { |
1316 | GtkTextView tv; |
1317 | GdkTexture *texture; |
1318 | GtkAdjustment *adjustment; |
1319 | } MyTextView; |
1320 | |
1321 | typedef GtkTextViewClass MyTextViewClass; |
1322 | |
1323 | static GType my_text_view_get_type (void); |
1324 | G_DEFINE_TYPE (MyTextView, my_text_view, GTK_TYPE_TEXT_VIEW) |
1325 | |
1326 | static void |
1327 | my_text_view_init (MyTextView *tv) |
1328 | { |
1329 | } |
1330 | |
1331 | static void |
1332 | my_tv_snapshot_layer (GtkTextView *widget, |
1333 | GtkTextViewLayer layer, |
1334 | GtkSnapshot *snapshot) |
1335 | { |
1336 | MyTextView *tv = (MyTextView *)widget; |
1337 | double opacity; |
1338 | double scale; |
1339 | |
1340 | opacity = gtk_adjustment_get_value (adjustment: tv->adjustment) / 100.0; |
1341 | |
1342 | if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT && tv->texture) |
1343 | { |
1344 | scale = gtk_widget_get_width (GTK_WIDGET (widget)) / (double)gdk_texture_get_width (texture: tv->texture); |
1345 | gtk_snapshot_push_opacity (snapshot, opacity); |
1346 | gtk_snapshot_scale (snapshot, factor_x: scale, factor_y: scale); |
1347 | gtk_snapshot_append_texture (snapshot, |
1348 | texture: tv->texture, |
1349 | bounds: &GRAPHENE_RECT_INIT( |
1350 | 0, 0, |
1351 | gdk_texture_get_width (tv->texture), |
1352 | gdk_texture_get_height (tv->texture) |
1353 | )); |
1354 | gtk_snapshot_scale (snapshot, factor_x: 1/scale, factor_y: 1/scale); |
1355 | gtk_snapshot_pop (snapshot); |
1356 | } |
1357 | } |
1358 | |
1359 | static void |
1360 | my_tv_finalize (GObject *object) |
1361 | { |
1362 | MyTextView *tv = (MyTextView *)object; |
1363 | |
1364 | g_clear_object (&tv->texture); |
1365 | |
1366 | G_OBJECT_CLASS (my_text_view_parent_class)->finalize (object); |
1367 | } |
1368 | |
1369 | static void |
1370 | my_text_view_class_init (MyTextViewClass *class) |
1371 | { |
1372 | GtkTextViewClass *tv_class = GTK_TEXT_VIEW_CLASS (class); |
1373 | GObjectClass *o_class = G_OBJECT_CLASS (class); |
1374 | |
1375 | o_class->finalize = my_tv_finalize; |
1376 | tv_class->snapshot_layer = my_tv_snapshot_layer; |
1377 | } |
1378 | |
1379 | static void |
1380 | my_text_view_set_background (MyTextView *tv, const char *filename, gboolean is_resource) |
1381 | { |
1382 | GError *error = NULL; |
1383 | GFile *file; |
1384 | |
1385 | g_clear_object (&tv->texture); |
1386 | |
1387 | if (filename == NULL) |
1388 | return; |
1389 | |
1390 | if (is_resource) |
1391 | tv->texture = gdk_texture_new_from_resource (resource_path: filename); |
1392 | else |
1393 | { |
1394 | file = g_file_new_for_path (path: filename); |
1395 | tv->texture = gdk_texture_new_from_file (file, error: &error); |
1396 | g_object_unref (object: file); |
1397 | } |
1398 | |
1399 | if (error) |
1400 | { |
1401 | g_warning ("%s" , error->message); |
1402 | g_error_free (error); |
1403 | return; |
1404 | } |
1405 | |
1406 | gtk_widget_queue_draw (GTK_WIDGET (tv)); |
1407 | } |
1408 | |
1409 | static void |
1410 | value_changed (GtkAdjustment *adjustment, MyTextView *tv) |
1411 | { |
1412 | gtk_widget_queue_draw (GTK_WIDGET (tv)); |
1413 | } |
1414 | |
1415 | static void |
1416 | my_text_view_set_adjustment (MyTextView *tv, GtkAdjustment *adjustment) |
1417 | { |
1418 | g_set_object (&tv->adjustment, adjustment); |
1419 | g_signal_connect (tv->adjustment, "value-changed" , G_CALLBACK (value_changed), tv); |
1420 | } |
1421 | |
1422 | static void |
1423 | close_selection_dialog (GtkWidget *dialog, int response, GtkWidget *tv) |
1424 | { |
1425 | GtkWidget *box; |
1426 | GtkWidget *child; |
1427 | GList *children; |
1428 | const char *filename; |
1429 | gboolean is_resource; |
1430 | |
1431 | gtk_widget_hide (widget: dialog); |
1432 | |
1433 | if (response == GTK_RESPONSE_CANCEL) |
1434 | return; |
1435 | |
1436 | box = gtk_widget_get_first_child (widget: gtk_dialog_get_content_area (GTK_DIALOG (dialog))); |
1437 | g_assert (GTK_IS_FLOW_BOX (box)); |
1438 | children = gtk_flow_box_get_selected_children (GTK_FLOW_BOX (box)); |
1439 | |
1440 | if (!children) |
1441 | return; |
1442 | |
1443 | child = children->data; |
1444 | filename = (const char *)g_object_get_data (G_OBJECT (child), key: "filename" ); |
1445 | is_resource = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), "is-resource" )); |
1446 | |
1447 | g_list_free (list: children); |
1448 | |
1449 | my_text_view_set_background (tv: (MyTextView *)tv, filename, is_resource); |
1450 | } |
1451 | |
1452 | static void |
1453 | toggle_selection_mode (GtkSwitch *sw, |
1454 | GParamSpec *pspec, |
1455 | GtkListBox *listbox) |
1456 | { |
1457 | if (gtk_switch_get_active (self: sw)) |
1458 | gtk_list_box_set_selection_mode (box: listbox, mode: GTK_SELECTION_SINGLE); |
1459 | else |
1460 | gtk_list_box_set_selection_mode (box: listbox, mode: GTK_SELECTION_NONE); |
1461 | |
1462 | gtk_list_box_set_activate_on_single_click (box: listbox, single: !gtk_switch_get_active (self: sw)); |
1463 | } |
1464 | |
1465 | static void |
1466 | handle_insert (GtkWidget *button, GtkWidget *textview) |
1467 | { |
1468 | GtkTextBuffer *buffer; |
1469 | const char *id; |
1470 | const char *text; |
1471 | |
1472 | id = gtk_buildable_get_buildable_id (GTK_BUILDABLE (button)); |
1473 | |
1474 | if (strcmp (s1: id, s2: "toolbutton1" ) == 0) |
1475 | text = "⌘" ; |
1476 | else if (strcmp (s1: id, s2: "toolbutton2" ) == 0) |
1477 | text = "âš½" ; |
1478 | else if (strcmp (s1: id, s2: "toolbutton3" ) == 0) |
1479 | text = "⤢" ; |
1480 | else if (strcmp (s1: id, s2: "toolbutton4" ) == 0) |
1481 | text = "☆" ; |
1482 | else |
1483 | text = "" ; |
1484 | |
1485 | buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)); |
1486 | gtk_text_buffer_insert_at_cursor (buffer, text, len: -1); |
1487 | } |
1488 | |
1489 | static void |
1490 | handle_cutcopypaste (GtkWidget *button, GtkWidget *textview) |
1491 | { |
1492 | GtkTextBuffer *buffer; |
1493 | GdkClipboard *clipboard; |
1494 | const char *id; |
1495 | |
1496 | clipboard = gtk_widget_get_clipboard (widget: textview); |
1497 | buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)); |
1498 | id = gtk_buildable_get_buildable_id (GTK_BUILDABLE (button)); |
1499 | |
1500 | if (strcmp (s1: id, s2: "cutbutton" ) == 0) |
1501 | gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE); |
1502 | else if (strcmp (s1: id, s2: "copybutton" ) == 0) |
1503 | gtk_text_buffer_copy_clipboard (buffer, clipboard); |
1504 | else if (strcmp (s1: id, s2: "pastebutton" ) == 0) |
1505 | gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE); |
1506 | else if (strcmp (s1: id, s2: "deletebutton" ) == 0) |
1507 | gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); |
1508 | } |
1509 | |
1510 | static void |
1511 | clipboard_formats_notify (GdkClipboard *clipboard, GdkEvent *event, GtkWidget *button) |
1512 | { |
1513 | const char *id; |
1514 | gboolean has_text; |
1515 | |
1516 | id = gtk_buildable_get_buildable_id (GTK_BUILDABLE (button)); |
1517 | has_text = gdk_content_formats_contain_gtype (formats: gdk_clipboard_get_formats (clipboard), GTK_TYPE_TEXT_BUFFER); |
1518 | |
1519 | if (strcmp (s1: id, s2: "pastebutton" ) == 0) |
1520 | gtk_widget_set_sensitive (widget: button, sensitive: has_text); |
1521 | } |
1522 | |
1523 | static void |
1524 | textbuffer_notify_selection (GObject *object, GParamSpec *pspec, GtkWidget *button) |
1525 | { |
1526 | const char *id; |
1527 | gboolean has_selection; |
1528 | |
1529 | id = gtk_buildable_get_buildable_id (GTK_BUILDABLE (button)); |
1530 | has_selection = gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (object)); |
1531 | |
1532 | if (strcmp (s1: id, s2: "cutbutton" ) == 0 || |
1533 | strcmp (s1: id, s2: "copybutton" ) == 0 || |
1534 | strcmp (s1: id, s2: "deletebutton" ) == 0) |
1535 | gtk_widget_set_sensitive (widget: button, sensitive: has_selection); |
1536 | } |
1537 | |
1538 | static gboolean |
1539 | osd_frame_pressed (GtkGestureClick *gesture, |
1540 | int press, |
1541 | double x, |
1542 | double y, |
1543 | gpointer data) |
1544 | { |
1545 | GtkWidget *frame = data; |
1546 | GtkWidget *osd; |
1547 | gboolean visible; |
1548 | |
1549 | osd = g_object_get_data (G_OBJECT (frame), key: "osd" ); |
1550 | visible = gtk_widget_get_visible (widget: osd); |
1551 | gtk_widget_set_visible (widget: osd, visible: !visible); |
1552 | |
1553 | return GDK_EVENT_STOP; |
1554 | } |
1555 | |
1556 | static gboolean |
1557 | page_combo_separator_func (GtkTreeModel *model, |
1558 | GtkTreeIter *iter, |
1559 | gpointer data) |
1560 | { |
1561 | char *text; |
1562 | gboolean res; |
1563 | |
1564 | gtk_tree_model_get (tree_model: model, iter, 0, &text, -1); |
1565 | res = g_strcmp0 (str1: text, str2: "-" ) == 0; |
1566 | g_free (mem: text); |
1567 | |
1568 | return res; |
1569 | } |
1570 | |
1571 | static void |
1572 | toggle_format (GSimpleAction *action, |
1573 | GVariant *value, |
1574 | gpointer user_data) |
1575 | { |
1576 | GtkTextView *text_view = user_data; |
1577 | GtkTextIter start, end; |
1578 | const char *name; |
1579 | |
1580 | name = g_action_get_name (G_ACTION (action)); |
1581 | |
1582 | g_simple_action_set_state (simple: action, value); |
1583 | |
1584 | gtk_text_buffer_get_selection_bounds (buffer: gtk_text_view_get_buffer (text_view), start: &start, end: &end); |
1585 | if (g_variant_get_boolean (value)) |
1586 | gtk_text_buffer_apply_tag_by_name (buffer: gtk_text_view_get_buffer (text_view), name, start: &start, end: &end); |
1587 | else |
1588 | gtk_text_buffer_remove_tag_by_name (buffer: gtk_text_view_get_buffer (text_view), name, start: &start, end: &end); |
1589 | } |
1590 | |
1591 | static GActionGroup *actions; |
1592 | |
1593 | static void |
1594 | text_changed (GtkTextBuffer *buffer) |
1595 | { |
1596 | GAction *bold; |
1597 | GAction *italic; |
1598 | GAction *underline; |
1599 | GtkTextIter iter; |
1600 | GtkTextTagTable *tags; |
1601 | GtkTextTag *bold_tag, *italic_tag, *underline_tag; |
1602 | gboolean all_bold, all_italic, all_underline; |
1603 | GtkTextIter start, end; |
1604 | gboolean has_selection; |
1605 | |
1606 | bold = g_action_map_lookup_action (G_ACTION_MAP (actions), action_name: "bold" ); |
1607 | italic = g_action_map_lookup_action (G_ACTION_MAP (actions), action_name: "italic" ); |
1608 | underline = g_action_map_lookup_action (G_ACTION_MAP (actions), action_name: "underline" ); |
1609 | |
1610 | has_selection = gtk_text_buffer_get_selection_bounds (buffer, start: &start, end: &end); |
1611 | g_simple_action_set_enabled (G_SIMPLE_ACTION (bold), enabled: has_selection); |
1612 | g_simple_action_set_enabled (G_SIMPLE_ACTION (italic), enabled: has_selection); |
1613 | g_simple_action_set_enabled (G_SIMPLE_ACTION (underline), enabled: has_selection); |
1614 | if (!has_selection) |
1615 | return; |
1616 | |
1617 | tags = gtk_text_buffer_get_tag_table (buffer); |
1618 | bold_tag = gtk_text_tag_table_lookup (table: tags, name: "bold" ); |
1619 | italic_tag = gtk_text_tag_table_lookup (table: tags, name: "italic" ); |
1620 | underline_tag = gtk_text_tag_table_lookup (table: tags, name: "underline" ); |
1621 | all_bold = TRUE; |
1622 | all_italic = TRUE; |
1623 | all_underline = TRUE; |
1624 | gtk_text_iter_assign (iter: &iter, other: &start); |
1625 | while (!gtk_text_iter_equal (lhs: &iter, rhs: &end)) |
1626 | { |
1627 | all_bold &= gtk_text_iter_has_tag (iter: &iter, tag: bold_tag); |
1628 | all_italic &= gtk_text_iter_has_tag (iter: &iter, tag: italic_tag); |
1629 | all_underline &= gtk_text_iter_has_tag (iter: &iter, tag: underline_tag); |
1630 | gtk_text_iter_forward_char (iter: &iter); |
1631 | } |
1632 | |
1633 | g_simple_action_set_state (G_SIMPLE_ACTION (bold), value: g_variant_new_boolean (value: all_bold)); |
1634 | g_simple_action_set_state (G_SIMPLE_ACTION (italic), value: g_variant_new_boolean (value: all_italic)); |
1635 | g_simple_action_set_state (G_SIMPLE_ACTION (underline), value: g_variant_new_boolean (value: all_underline)); |
1636 | } |
1637 | |
1638 | static void |
1639 | (GtkTextView *text_view) |
1640 | { |
1641 | GMenu *; |
1642 | GActionEntry entries[] = { |
1643 | { "bold" , NULL, NULL, "false" , toggle_format }, |
1644 | { "italic" , NULL, NULL, "false" , toggle_format }, |
1645 | { "underline" , NULL, NULL, "false" , toggle_format }, |
1646 | }; |
1647 | GMenuItem *item; |
1648 | GAction *action; |
1649 | |
1650 | actions = G_ACTION_GROUP (g_simple_action_group_new ()); |
1651 | g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), user_data: text_view); |
1652 | |
1653 | action = g_action_map_lookup_action (G_ACTION_MAP (actions), action_name: "bold" ); |
1654 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); |
1655 | action = g_action_map_lookup_action (G_ACTION_MAP (actions), action_name: "italic" ); |
1656 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); |
1657 | action = g_action_map_lookup_action (G_ACTION_MAP (actions), action_name: "underline" ); |
1658 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); |
1659 | |
1660 | gtk_widget_insert_action_group (GTK_WIDGET (text_view), name: "format" , G_ACTION_GROUP (actions)); |
1661 | |
1662 | menu = g_menu_new (); |
1663 | item = g_menu_item_new (_("Bold" ), detailed_action: "format.bold" ); |
1664 | g_menu_item_set_attribute (menu_item: item, attribute: "touch-icon" , format_string: "s" , "format-text-bold-symbolic" ); |
1665 | g_menu_append_item (G_MENU (menu), item); |
1666 | g_object_unref (object: item); |
1667 | item = g_menu_item_new (_("Italics" ), detailed_action: "format.italic" ); |
1668 | g_menu_item_set_attribute (menu_item: item, attribute: "touch-icon" , format_string: "s" , "format-text-italic-symbolic" ); |
1669 | g_menu_append_item (G_MENU (menu), item); |
1670 | g_object_unref (object: item); |
1671 | item = g_menu_item_new (_("Underline" ), detailed_action: "format.underline" ); |
1672 | g_menu_item_set_attribute (menu_item: item, attribute: "touch-icon" , format_string: "s" , "format-text-underline-symbolic" ); |
1673 | g_menu_append_item (G_MENU (menu), item); |
1674 | g_object_unref (object: item); |
1675 | |
1676 | gtk_text_view_set_extra_menu (text_view, G_MENU_MODEL (menu)); |
1677 | g_object_unref (object: menu); |
1678 | |
1679 | g_signal_connect (gtk_text_view_get_buffer (text_view), "changed" , G_CALLBACK (text_changed), NULL); |
1680 | g_signal_connect (gtk_text_view_get_buffer (text_view), "mark-set" , G_CALLBACK (text_changed), NULL); |
1681 | } |
1682 | |
1683 | static void |
1684 | open_popover_text_changed (GtkEntry *entry, GParamSpec *pspec, GtkWidget *button) |
1685 | { |
1686 | const char *text; |
1687 | |
1688 | text = gtk_editable_get_text (GTK_EDITABLE (entry)); |
1689 | gtk_widget_set_sensitive (widget: button, sensitive: strlen (s: text) > 0); |
1690 | } |
1691 | |
1692 | static gboolean |
1693 | show_page_again (gpointer data) |
1694 | { |
1695 | gtk_widget_show (GTK_WIDGET (data)); |
1696 | return G_SOURCE_REMOVE; |
1697 | } |
1698 | |
1699 | static void |
1700 | tab_close_cb (GtkWidget *page) |
1701 | { |
1702 | gtk_widget_hide (widget: page); |
1703 | g_timeout_add (interval: 2500, function: show_page_again, data: page); |
1704 | } |
1705 | |
1706 | typedef struct _GTestPermission GTestPermission; |
1707 | typedef struct _GTestPermissionClass GTestPermissionClass; |
1708 | |
1709 | struct _GTestPermission |
1710 | { |
1711 | GPermission parent; |
1712 | }; |
1713 | |
1714 | struct _GTestPermissionClass |
1715 | { |
1716 | GPermissionClass parent_class; |
1717 | }; |
1718 | |
1719 | static GType g_test_permission_get_type (void); |
1720 | G_DEFINE_TYPE (GTestPermission, g_test_permission, G_TYPE_PERMISSION) |
1721 | |
1722 | static void |
1723 | g_test_permission_init (GTestPermission *test) |
1724 | { |
1725 | g_permission_impl_update (G_PERMISSION (test), TRUE, TRUE, TRUE); |
1726 | } |
1727 | |
1728 | static gboolean |
1729 | update_allowed (GPermission *permission, |
1730 | gboolean allowed) |
1731 | { |
1732 | g_permission_impl_update (permission, allowed, TRUE, TRUE); |
1733 | |
1734 | return TRUE; |
1735 | } |
1736 | |
1737 | static gboolean |
1738 | acquire (GPermission *permission, |
1739 | GCancellable *cancellable, |
1740 | GError **error) |
1741 | { |
1742 | return update_allowed (permission, TRUE); |
1743 | } |
1744 | |
1745 | static void |
1746 | acquire_async (GPermission *permission, |
1747 | GCancellable *cancellable, |
1748 | GAsyncReadyCallback callback, |
1749 | gpointer user_data) |
1750 | { |
1751 | GTask *task; |
1752 | |
1753 | task = g_task_new (source_object: (GObject*)permission, NULL, callback, callback_data: user_data); |
1754 | g_task_return_boolean (task, result: update_allowed (permission, TRUE)); |
1755 | g_object_unref (object: task); |
1756 | } |
1757 | |
1758 | static gboolean |
1759 | acquire_finish (GPermission *permission, |
1760 | GAsyncResult *res, |
1761 | GError **error) |
1762 | { |
1763 | return g_task_propagate_boolean (G_TASK (res), error); |
1764 | } |
1765 | |
1766 | static gboolean |
1767 | release (GPermission *permission, |
1768 | GCancellable *cancellable, |
1769 | GError **error) |
1770 | { |
1771 | return update_allowed (permission, FALSE); |
1772 | } |
1773 | |
1774 | static void |
1775 | release_async (GPermission *permission, |
1776 | GCancellable *cancellable, |
1777 | GAsyncReadyCallback callback, |
1778 | gpointer user_data) |
1779 | { |
1780 | GTask *task; |
1781 | |
1782 | task = g_task_new (source_object: (GObject*)permission, NULL, callback, callback_data: user_data); |
1783 | g_task_return_boolean (task, result: update_allowed (permission, FALSE)); |
1784 | g_object_unref (object: task); |
1785 | } |
1786 | |
1787 | static gboolean |
1788 | release_finish (GPermission *permission, |
1789 | GAsyncResult *result, |
1790 | GError **error) |
1791 | { |
1792 | return g_task_propagate_boolean (G_TASK (result), error); |
1793 | } |
1794 | |
1795 | static void |
1796 | g_test_permission_class_init (GTestPermissionClass *class) |
1797 | { |
1798 | GPermissionClass *permission_class = G_PERMISSION_CLASS (class); |
1799 | |
1800 | permission_class->acquire = acquire; |
1801 | permission_class->acquire_async = acquire_async; |
1802 | permission_class->acquire_finish = acquire_finish; |
1803 | |
1804 | permission_class->release = release; |
1805 | permission_class->release_async = release_async; |
1806 | permission_class->release_finish = release_finish; |
1807 | } |
1808 | |
1809 | static void |
1810 | update_buttons (GtkWidget *iv, GtkIconSize size) |
1811 | { |
1812 | GtkWidget *button; |
1813 | |
1814 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "increase_button" )); |
1815 | gtk_widget_set_sensitive (widget: button, sensitive: size != GTK_ICON_SIZE_LARGE); |
1816 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "decrease_button" )); |
1817 | gtk_widget_set_sensitive (widget: button, sensitive: size != GTK_ICON_SIZE_NORMAL); |
1818 | button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "reset_button" )); |
1819 | gtk_widget_set_sensitive (widget: button, sensitive: size != GTK_ICON_SIZE_INHERIT); |
1820 | } |
1821 | |
1822 | static void |
1823 | increase_icon_size (GtkWidget *iv) |
1824 | { |
1825 | GList *cells; |
1826 | GtkCellRendererPixbuf *cell; |
1827 | |
1828 | cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv)); |
1829 | cell = cells->data; |
1830 | g_list_free (list: cells); |
1831 | |
1832 | g_object_set (object: cell, first_property_name: "icon-size" , GTK_ICON_SIZE_LARGE, NULL); |
1833 | |
1834 | update_buttons (iv, size: GTK_ICON_SIZE_LARGE); |
1835 | |
1836 | gtk_widget_queue_resize (widget: iv); |
1837 | } |
1838 | |
1839 | static void |
1840 | decrease_icon_size (GtkWidget *iv) |
1841 | { |
1842 | GList *cells; |
1843 | GtkCellRendererPixbuf *cell; |
1844 | |
1845 | cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv)); |
1846 | cell = cells->data; |
1847 | g_list_free (list: cells); |
1848 | |
1849 | g_object_set (object: cell, first_property_name: "icon-size" , GTK_ICON_SIZE_NORMAL, NULL); |
1850 | |
1851 | update_buttons (iv, size: GTK_ICON_SIZE_NORMAL); |
1852 | |
1853 | gtk_widget_queue_resize (widget: iv); |
1854 | } |
1855 | |
1856 | static void |
1857 | reset_icon_size (GtkWidget *iv) |
1858 | { |
1859 | GList *cells; |
1860 | GtkCellRendererPixbuf *cell; |
1861 | |
1862 | cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv)); |
1863 | cell = cells->data; |
1864 | g_list_free (list: cells); |
1865 | |
1866 | g_object_set (object: cell, first_property_name: "icon-size" , GTK_ICON_SIZE_INHERIT, NULL); |
1867 | |
1868 | update_buttons (iv, size: GTK_ICON_SIZE_INHERIT); |
1869 | |
1870 | gtk_widget_queue_resize (widget: iv); |
1871 | } |
1872 | |
1873 | static char * |
1874 | scale_format_value_blank (GtkScale *scale, double value, gpointer user_data) |
1875 | { |
1876 | return g_strdup (str: " " ); |
1877 | } |
1878 | |
1879 | static char * |
1880 | scale_format_value (GtkScale *scale, double value, gpointer user_data) |
1881 | { |
1882 | return g_strdup_printf (format: "%0.*f" , 1, value); |
1883 | } |
1884 | |
1885 | static void |
1886 | adjustment3_value_changed (GtkAdjustment *adj, GtkProgressBar *pbar) |
1887 | { |
1888 | double fraction; |
1889 | |
1890 | fraction = gtk_adjustment_get_value (adjustment: adj) / (gtk_adjustment_get_upper (adjustment: adj) - gtk_adjustment_get_lower (adjustment: adj)); |
1891 | |
1892 | gtk_progress_bar_set_fraction (pbar, fraction); |
1893 | } |
1894 | |
1895 | static void |
1896 | clicked_cb (GtkGesture *gesture, |
1897 | int n_press, |
1898 | double x, |
1899 | double y, |
1900 | GtkPopover *popover) |
1901 | { |
1902 | GdkRectangle rect; |
1903 | |
1904 | rect.x = x; |
1905 | rect.y = y; |
1906 | rect.width = 1; |
1907 | rect.height = 1; |
1908 | gtk_popover_set_pointing_to (popover, rect: &rect); |
1909 | gtk_popover_popup (popover); |
1910 | } |
1911 | |
1912 | static void |
1913 | set_up_context_popover (GtkWidget *widget, |
1914 | GMenuModel *model) |
1915 | { |
1916 | GtkWidget *popover = gtk_popover_menu_new_from_model (model); |
1917 | GtkGesture *gesture; |
1918 | |
1919 | gtk_widget_set_parent (widget: popover, parent: widget); |
1920 | gtk_popover_set_has_arrow (GTK_POPOVER (popover), FALSE); |
1921 | gesture = gtk_gesture_click_new (); |
1922 | gtk_event_controller_set_name (GTK_EVENT_CONTROLLER (gesture), name: "widget-factory-context-click" ); |
1923 | gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY); |
1924 | g_signal_connect (gesture, "pressed" , G_CALLBACK (clicked_cb), popover); |
1925 | gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture)); |
1926 | } |
1927 | |
1928 | static void |
1929 | age_entry_changed (GtkEntry *entry, |
1930 | GParamSpec *pspec, |
1931 | gpointer data) |
1932 | { |
1933 | const char *text; |
1934 | guint64 age; |
1935 | GError *error = NULL; |
1936 | |
1937 | text = gtk_editable_get_text (GTK_EDITABLE (entry)); |
1938 | |
1939 | if (strlen (s: text) > 0 && |
1940 | !g_ascii_string_to_unsigned (str: text, base: 10, min: 16, max: 666, out_num: &age, error: &error)) |
1941 | { |
1942 | gtk_widget_set_tooltip_text (GTK_WIDGET (entry), text: error->message); |
1943 | gtk_widget_add_css_class (GTK_WIDGET (entry), css_class: "error" ); |
1944 | g_error_free (error); |
1945 | } |
1946 | else |
1947 | { |
1948 | gtk_widget_set_tooltip_text (GTK_WIDGET (entry), text: "" ); |
1949 | gtk_widget_remove_css_class (GTK_WIDGET (entry), css_class: "error" ); |
1950 | } |
1951 | } |
1952 | |
1953 | static void |
1954 | validate_more_details (GtkEntry *entry, |
1955 | GParamSpec *pspec, |
1956 | GtkEntry *details) |
1957 | { |
1958 | if (strlen (s: gtk_editable_get_text (GTK_EDITABLE (entry))) > 0 && |
1959 | strlen (s: gtk_editable_get_text (GTK_EDITABLE (details))) == 0) |
1960 | { |
1961 | gtk_widget_set_tooltip_text (GTK_WIDGET (entry), text: "Must have details first" ); |
1962 | gtk_widget_add_css_class (GTK_WIDGET (entry), css_class: "error" ); |
1963 | } |
1964 | else |
1965 | { |
1966 | gtk_widget_set_tooltip_text (GTK_WIDGET (entry), text: "" ); |
1967 | gtk_widget_remove_css_class (GTK_WIDGET (entry), css_class: "error" ); |
1968 | } |
1969 | } |
1970 | |
1971 | static gboolean |
1972 | mode_switch_state_set (GtkSwitch *sw, gboolean state) |
1973 | { |
1974 | GtkWidget *dialog = gtk_widget_get_ancestor (GTK_WIDGET (sw), GTK_TYPE_DIALOG); |
1975 | GtkWidget *scale = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "level_scale" )); |
1976 | GtkWidget *label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "error_label" )); |
1977 | |
1978 | if (!state || |
1979 | (gtk_range_get_value (GTK_RANGE (scale)) > 50)) |
1980 | { |
1981 | gtk_widget_hide (widget: label); |
1982 | gtk_switch_set_state (self: sw, state); |
1983 | } |
1984 | else |
1985 | { |
1986 | gtk_widget_show (widget: label); |
1987 | } |
1988 | |
1989 | return TRUE; |
1990 | } |
1991 | |
1992 | static void |
1993 | level_scale_value_changed (GtkRange *range) |
1994 | { |
1995 | GtkWidget *dialog = gtk_widget_get_ancestor (GTK_WIDGET (range), GTK_TYPE_DIALOG); |
1996 | GtkWidget *sw = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "mode_switch" )); |
1997 | GtkWidget *label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "error_label" )); |
1998 | |
1999 | if (gtk_switch_get_active (GTK_SWITCH (sw)) && |
2000 | !gtk_switch_get_state (GTK_SWITCH (sw)) && |
2001 | (gtk_range_get_value (range) > 50)) |
2002 | { |
2003 | gtk_widget_hide (widget: label); |
2004 | gtk_switch_set_state (GTK_SWITCH (sw), TRUE); |
2005 | } |
2006 | else if (gtk_switch_get_state (GTK_SWITCH (sw)) && |
2007 | (gtk_range_get_value (range) <= 50)) |
2008 | { |
2009 | gtk_switch_set_state (GTK_SWITCH (sw), FALSE); |
2010 | } |
2011 | } |
2012 | |
2013 | static void |
2014 | activate (GApplication *app) |
2015 | { |
2016 | GtkBuilder *builder; |
2017 | GtkBuilderScope *scope; |
2018 | GtkWindow *window; |
2019 | GtkWidget *widget; |
2020 | GtkWidget *widget2; |
2021 | GtkWidget *widget3; |
2022 | GtkWidget *widget4; |
2023 | GtkWidget *stack; |
2024 | GtkWidget *dialog; |
2025 | GtkAdjustment *adj; |
2026 | GtkCssProvider *provider; |
2027 | GMenuModel *model; |
2028 | static GActionEntry win_entries[] = { |
2029 | { "dark" , NULL, NULL, "false" , change_dark_state }, |
2030 | { "theme" , NULL, "s" , "'current'" , change_theme_state }, |
2031 | { "transition" , NULL, NULL, "true" , change_transition_state }, |
2032 | { "search" , activate_search, NULL, NULL, NULL }, |
2033 | { "delete" , activate_delete, NULL, NULL, NULL }, |
2034 | { "busy" , get_busy, NULL, NULL, NULL }, |
2035 | { "fullscreen" , NULL, NULL, "false" , change_fullscreen }, |
2036 | { "background" , activate_background, NULL, NULL, NULL }, |
2037 | { "open" , activate_open, NULL, NULL, NULL }, |
2038 | { "record" , activate_record, NULL, NULL, NULL }, |
2039 | { "lock" , activate_lock, NULL, NULL, NULL }, |
2040 | { "print" , activate_print, NULL, NULL, NULL }, |
2041 | }; |
2042 | struct { |
2043 | const char *action_and_target; |
2044 | const char *accelerators[2]; |
2045 | } accels[] = { |
2046 | { "app.about" , { "F1" , NULL } }, |
2047 | { "app.shortcuts" , { "<Control>question" , NULL } }, |
2048 | { "app.quit" , { "<Control>q" , NULL } }, |
2049 | { "app.open-in" , { "<Control>n" , NULL } }, |
2050 | { "win.dark" , { "<Control>d" , NULL } }, |
2051 | { "win.search" , { "<Control>s" , NULL } }, |
2052 | { "win.background" , { "<Control>b" , NULL } }, |
2053 | { "win.open" , { "<Control>o" , NULL } }, |
2054 | { "win.record" , { "<Control>r" , NULL } }, |
2055 | { "win.lock" , { "<Control>l" , NULL } }, |
2056 | { "win.fullscreen" , { "F11" , NULL } }, |
2057 | }; |
2058 | struct { |
2059 | const char *action_and_target; |
2060 | const char *accelerators[2]; |
2061 | } late_accels[] = { |
2062 | { "app.cut" , { "<Control>x" , NULL } }, |
2063 | { "app.copy" , { "<Control>c" , NULL } }, |
2064 | { "app.paste" , { "<Control>v" , NULL } }, |
2065 | { "win.delete" , { "Delete" , NULL } }, |
2066 | }; |
2067 | int i; |
2068 | GPermission *permission; |
2069 | GAction *action; |
2070 | GError *error = NULL; |
2071 | GtkEventController *controller; |
2072 | |
2073 | g_type_ensure (type: my_text_view_get_type ()); |
2074 | |
2075 | provider = gtk_css_provider_new (); |
2076 | gtk_css_provider_load_from_resource (css_provider: provider, resource_path: "/org/gtk/WidgetFactory4/widget-factory.css" ); |
2077 | gtk_style_context_add_provider_for_display (display: gdk_display_get_default (), |
2078 | GTK_STYLE_PROVIDER (provider), |
2079 | GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); |
2080 | g_object_unref (object: provider); |
2081 | |
2082 | builder = gtk_builder_new (); |
2083 | scope = gtk_builder_cscope_new (); |
2084 | gtk_builder_cscope_add_callback_symbols (self: GTK_BUILDER_CSCOPE (ptr: scope), |
2085 | first_callback_name: "on_entry_icon_release" , first_callback_symbol: (GCallback)on_entry_icon_release, |
2086 | "on_scale_button_value_changed" , (GCallback)on_scale_button_value_changed, |
2087 | "on_record_button_toggled" , (GCallback)on_record_button_toggled, |
2088 | "on_page_combo_changed" , (GCallback)on_page_combo_changed, |
2089 | "on_range_from_changed" , (GCallback)on_range_from_changed, |
2090 | "on_range_to_changed" , (GCallback)on_range_to_changed, |
2091 | "on_picture_drag_prepare" , (GCallback)on_picture_drag_prepare, |
2092 | "on_picture_drop" , (GCallback)on_picture_drop, |
2093 | "tab_close_cb" , (GCallback)tab_close_cb, |
2094 | "increase_icon_size" , (GCallback)increase_icon_size, |
2095 | "decrease_icon_size" , (GCallback)decrease_icon_size, |
2096 | "reset_icon_size" , (GCallback)reset_icon_size, |
2097 | "osd_frame_pressed" , (GCallback)osd_frame_pressed, |
2098 | "age_entry_changed" , (GCallback)age_entry_changed, |
2099 | "validate_more_details" , (GCallback)validate_more_details, |
2100 | "mode_switch_state_set" , (GCallback)mode_switch_state_set, |
2101 | "level_scale_value_changed" , (GCallback)level_scale_value_changed, |
2102 | "transition_speed_changed" , (GCallback)transition_speed_changed, |
2103 | NULL); |
2104 | gtk_builder_set_scope (builder, scope); |
2105 | g_object_unref (object: scope); |
2106 | if (!gtk_builder_add_from_resource (builder, resource_path: "/org/gtk/WidgetFactory4/widget-factory.ui" , error: &error)) |
2107 | { |
2108 | g_critical ("%s" , error->message); |
2109 | g_clear_error (err: &error); |
2110 | } |
2111 | |
2112 | window = (GtkWindow *)gtk_builder_get_object (builder, name: "window" ); |
2113 | |
2114 | if (g_strcmp0 (str1: PROFILE, str2: "devel" ) == 0) |
2115 | gtk_widget_add_css_class (GTK_WIDGET (window), css_class: "devel" ); |
2116 | |
2117 | gtk_application_add_window (GTK_APPLICATION (app), window); |
2118 | g_action_map_add_action_entries (G_ACTION_MAP (window), |
2119 | entries: win_entries, G_N_ELEMENTS (win_entries), |
2120 | user_data: window); |
2121 | |
2122 | controller = gtk_shortcut_controller_new (); |
2123 | gtk_event_controller_set_propagation_phase (controller, phase: GTK_PHASE_BUBBLE); |
2124 | |
2125 | for (i = 0; i < G_N_ELEMENTS (late_accels); i++) |
2126 | { |
2127 | guint key; |
2128 | GdkModifierType mods; |
2129 | GtkShortcutTrigger *trigger; |
2130 | GtkShortcutAction *ac; |
2131 | |
2132 | gtk_accelerator_parse (accelerator: late_accels[i].accelerators[0], accelerator_key: &key, accelerator_mods: &mods); |
2133 | trigger = gtk_keyval_trigger_new (keyval: key, modifiers: mods); |
2134 | ac = gtk_named_action_new (name: late_accels[i].action_and_target); |
2135 | gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), |
2136 | shortcut: gtk_shortcut_new (trigger, action: ac)); |
2137 | } |
2138 | gtk_widget_add_controller (GTK_WIDGET (window), controller); |
2139 | |
2140 | for (i = 0; i < G_N_ELEMENTS (accels); i++) |
2141 | gtk_application_set_accels_for_action (GTK_APPLICATION (app), detailed_action_name: accels[i].action_and_target, accels: accels[i].accelerators); |
2142 | |
2143 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "statusbar" ); |
2144 | gtk_statusbar_push (GTK_STATUSBAR (widget), context_id: 0, text: "All systems are operating normally." ); |
2145 | action = G_ACTION (g_property_action_new ("statusbar" , widget, "visible" )); |
2146 | g_action_map_add_action (G_ACTION_MAP (window), action); |
2147 | g_object_unref (G_OBJECT (action)); |
2148 | |
2149 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "toolbar" ); |
2150 | action = G_ACTION (g_property_action_new ("toolbar" , widget, "visible" )); |
2151 | g_action_map_add_action (G_ACTION_MAP (window), action); |
2152 | g_object_unref (G_OBJECT (action)); |
2153 | |
2154 | adj = (GtkAdjustment *)gtk_builder_get_object (builder, name: "adjustment1" ); |
2155 | |
2156 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "progressbar3" ); |
2157 | g_signal_connect (adj, "value-changed" , G_CALLBACK (update_pulse_time), widget); |
2158 | update_pulse_time (adjustment: adj, widget); |
2159 | |
2160 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "entry1" ); |
2161 | g_signal_connect (adj, "value-changed" , G_CALLBACK (update_pulse_time), widget); |
2162 | update_pulse_time (adjustment: adj, widget); |
2163 | |
2164 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "page2reset" ); |
2165 | adj = (GtkAdjustment *) gtk_builder_get_object (builder, name: "adjustment2" ); |
2166 | g_signal_connect (widget, "clicked" , G_CALLBACK (spin_value_reset), adj); |
2167 | |
2168 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "page2dismiss" ); |
2169 | g_signal_connect (widget, "clicked" , G_CALLBACK (dismiss), NULL); |
2170 | |
2171 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "page2note" ); |
2172 | adj = (GtkAdjustment *) gtk_builder_get_object (builder, name: "adjustment2" ); |
2173 | g_signal_connect (adj, "value-changed" , G_CALLBACK (spin_value_changed), widget); |
2174 | |
2175 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "listbox" ); |
2176 | g_signal_connect (widget, "row-activated" , G_CALLBACK (row_activated), NULL); |
2177 | |
2178 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "listboxrow1switch" ); |
2179 | g_signal_connect (widget2, "notify::active" , G_CALLBACK (toggle_selection_mode), widget); |
2180 | |
2181 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "listboxrow3" ); |
2182 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "listboxrow3image" ); |
2183 | g_object_set_data (G_OBJECT (widget), key: "image" , data: widget2); |
2184 | |
2185 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "info_dialog" ); |
2186 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "listboxrow7" ); |
2187 | g_object_set_data (G_OBJECT (widget), key: "dialog" , data: widget2); |
2188 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "listboxrow8" ); |
2189 | g_object_set_data (G_OBJECT (widget), key: "dialog" , data: widget2); |
2190 | |
2191 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "listboxrow5button" ); |
2192 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "action_dialog" ); |
2193 | g_signal_connect_swapped (widget, "clicked" , G_CALLBACK (gtk_window_present), widget2); |
2194 | |
2195 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "toolbar" ); |
2196 | g_object_set_data (G_OBJECT (window), key: "toolbar" , data: widget); |
2197 | |
2198 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "searchbar" ); |
2199 | g_object_set_data (G_OBJECT (window), key: "searchbar" , data: widget); |
2200 | |
2201 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "infobar" ); |
2202 | g_signal_connect (widget, "response" , G_CALLBACK (info_bar_response), NULL); |
2203 | g_object_set_data (G_OBJECT (window), key: "infobar" , data: widget); |
2204 | |
2205 | dialog = (GtkWidget *)gtk_builder_get_object (builder, name: "info_dialog" ); |
2206 | g_signal_connect (dialog, "response" , G_CALLBACK (close_dialog), NULL); |
2207 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "info_dialog_button" ); |
2208 | g_signal_connect (widget, "clicked" , G_CALLBACK (show_dialog), dialog); |
2209 | |
2210 | dialog = (GtkWidget *)gtk_builder_get_object (builder, name: "action_dialog" ); |
2211 | g_signal_connect (dialog, "response" , G_CALLBACK (close_dialog), NULL); |
2212 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "action_dialog_button" ); |
2213 | g_signal_connect (widget, "clicked" , G_CALLBACK (show_dialog), dialog); |
2214 | |
2215 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "act_action_dialog" ); |
2216 | stack = (GtkWidget *)gtk_builder_get_object (builder, name: "toplevel_stack" ); |
2217 | g_signal_connect (widget, "clicked" , G_CALLBACK (action_dialog_button_clicked), stack); |
2218 | g_signal_connect (stack, "notify::visible-child-name" , G_CALLBACK (page_changed_cb), NULL); |
2219 | page_changed_cb (stack, NULL, NULL); |
2220 | |
2221 | page_stack = stack; |
2222 | |
2223 | dialog = (GtkWidget *)gtk_builder_get_object (builder, name: "preference_dialog" ); |
2224 | g_signal_connect (dialog, "response" , G_CALLBACK (close_dialog), NULL); |
2225 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "preference_dialog_button" ); |
2226 | g_signal_connect (widget, "clicked" , G_CALLBACK (show_dialog), dialog); |
2227 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "circular_button" ); |
2228 | g_signal_connect (widget, "clicked" , G_CALLBACK (show_dialog), dialog); |
2229 | |
2230 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "level_scale" ); |
2231 | g_object_set_data (G_OBJECT (dialog), key: "level_scale" , data: widget); |
2232 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "mode_switch" ); |
2233 | g_object_set_data (G_OBJECT (dialog), key: "mode_switch" , data: widget); |
2234 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "error_label" ); |
2235 | g_object_set_data (G_OBJECT (dialog), key: "error_label" , data: widget); |
2236 | |
2237 | dialog = (GtkWidget *)gtk_builder_get_object (builder, name: "selection_dialog" ); |
2238 | g_object_set_data (G_OBJECT (window), key: "selection_dialog" , data: dialog); |
2239 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "text3" ); |
2240 | g_signal_connect (dialog, "response" , G_CALLBACK (close_selection_dialog), widget); |
2241 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "opacity" ); |
2242 | my_text_view_set_adjustment (tv: (MyTextView *)widget, adjustment: gtk_range_get_adjustment (GTK_RANGE (widget2))); |
2243 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "selection_dialog_button" ); |
2244 | g_signal_connect (widget, "clicked" , G_CALLBACK (show_dialog), dialog); |
2245 | |
2246 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "selection_flowbox" ); |
2247 | g_object_set_data (G_OBJECT (window), key: "selection_flowbox" , data: widget2); |
2248 | g_signal_connect_swapped (widget, "clicked" , G_CALLBACK (populate_flowbox), widget2); |
2249 | |
2250 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "charletree" ); |
2251 | populate_model (store: (GtkTreeStore *)gtk_tree_view_get_model (GTK_TREE_VIEW (widget))); |
2252 | gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (widget), func: row_separator_func, NULL, NULL); |
2253 | gtk_tree_view_expand_all (GTK_TREE_VIEW (widget)); |
2254 | |
2255 | widget = GTK_WIDGET (gtk_builder_get_object (builder, "munsell" )); |
2256 | widget2 = GTK_WIDGET (gtk_builder_get_object (builder, "cchooser" )); |
2257 | |
2258 | populate_colors (widget, chooser: widget2); |
2259 | g_signal_connect (widget2, "notify::rgba" , G_CALLBACK (rgba_changed), widget); |
2260 | |
2261 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "page_combo" ); |
2262 | gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (widget), func: page_combo_separator_func, NULL, NULL); |
2263 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "range_from_spin" ); |
2264 | widget3 = (GtkWidget *)gtk_builder_get_object (builder, name: "range_to_spin" ); |
2265 | widget4 = (GtkWidget *)gtk_builder_get_object (builder, name: "print_button" ); |
2266 | g_object_set_data (G_OBJECT (widget), key: "range_from_spin" , data: widget2); |
2267 | g_object_set_data (G_OBJECT (widget3), key: "range_from_spin" , data: widget2); |
2268 | g_object_set_data (G_OBJECT (widget), key: "range_to_spin" , data: widget3); |
2269 | g_object_set_data (G_OBJECT (widget2), key: "range_to_spin" , data: widget3); |
2270 | g_object_set_data (G_OBJECT (widget), key: "print_button" , data: widget4); |
2271 | |
2272 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "tooltextview" ); |
2273 | |
2274 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "toolbutton1" ); |
2275 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_insert), widget2); |
2276 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "toolbutton2" ); |
2277 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_insert), widget2); |
2278 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "toolbutton3" ); |
2279 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_insert), widget2); |
2280 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "toolbutton4" ); |
2281 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_insert), widget2); |
2282 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "cutbutton" ); |
2283 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_cutcopypaste), widget2); |
2284 | g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection" , |
2285 | G_CALLBACK (textbuffer_notify_selection), widget); |
2286 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "copybutton" ); |
2287 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_cutcopypaste), widget2); |
2288 | g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection" , |
2289 | G_CALLBACK (textbuffer_notify_selection), widget); |
2290 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "deletebutton" ); |
2291 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_cutcopypaste), widget2); |
2292 | g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection" , |
2293 | G_CALLBACK (textbuffer_notify_selection), widget); |
2294 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "pastebutton" ); |
2295 | g_signal_connect (widget, "clicked" , G_CALLBACK (handle_cutcopypaste), widget2); |
2296 | g_signal_connect_object (instance: gtk_widget_get_clipboard (widget: widget2), detailed_signal: "notify::formats" , |
2297 | G_CALLBACK (clipboard_formats_notify), gobject: widget, connect_flags: 0); |
2298 | |
2299 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "osd_frame" ); |
2300 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "totem_like_osd" ); |
2301 | g_object_set_data (G_OBJECT (widget), key: "osd" , data: widget2); |
2302 | |
2303 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "textview1" ); |
2304 | text_view_add_to_context_menu (GTK_TEXT_VIEW (widget)); |
2305 | |
2306 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "open_popover" ); |
2307 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "open_popover_entry" ); |
2308 | widget3 = (GtkWidget *)gtk_builder_get_object (builder, name: "open_popover_button" ); |
2309 | gtk_popover_set_default_widget (GTK_POPOVER (widget), widget: widget3); |
2310 | g_signal_connect (widget2, "notify::text" , G_CALLBACK (open_popover_text_changed), widget3); |
2311 | g_signal_connect_swapped (widget3, "clicked" , G_CALLBACK (gtk_widget_hide), widget); |
2312 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "open_menubutton" ); |
2313 | g_object_set_data (G_OBJECT (window), key: "open_menubutton" , data: widget); |
2314 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "record_button" ); |
2315 | g_object_set_data (G_OBJECT (window), key: "record_button" , data: widget); |
2316 | |
2317 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "lockbox" ); |
2318 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "lockbutton" ); |
2319 | g_object_set_data (G_OBJECT (window), key: "lockbutton" , data: widget2); |
2320 | permission = g_object_new (object_type: g_test_permission_get_type (), NULL); |
2321 | g_object_bind_property (source: permission, source_property: "allowed" , |
2322 | target: widget, target_property: "sensitive" , |
2323 | flags: G_BINDING_SYNC_CREATE); |
2324 | action = g_action_map_lookup_action (G_ACTION_MAP (window), action_name: "open" ); |
2325 | g_object_bind_property (source: permission, source_property: "allowed" , |
2326 | target: action, target_property: "enabled" , |
2327 | flags: G_BINDING_SYNC_CREATE); |
2328 | action = g_action_map_lookup_action (G_ACTION_MAP (window), action_name: "record" ); |
2329 | g_object_bind_property (source: permission, source_property: "allowed" , |
2330 | target: action, target_property: "enabled" , |
2331 | flags: G_BINDING_SYNC_CREATE); |
2332 | gtk_lock_button_set_permission (GTK_LOCK_BUTTON (widget2), permission); |
2333 | g_object_unref (object: permission); |
2334 | |
2335 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "iconview1" ); |
2336 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "increase_button" ); |
2337 | g_object_set_data (G_OBJECT (widget), key: "increase_button" , data: widget2); |
2338 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "decrease_button" ); |
2339 | g_object_set_data (G_OBJECT (widget), key: "decrease_button" , data: widget2); |
2340 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "reset_button" ); |
2341 | g_object_set_data (G_OBJECT (widget), key: "reset_button" , data: widget2); |
2342 | reset_icon_size (iv: widget); |
2343 | |
2344 | adj = (GtkAdjustment *)gtk_builder_get_object (builder, name: "adjustment3" ); |
2345 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "progressbar1" ); |
2346 | widget2 = (GtkWidget *)gtk_builder_get_object (builder, name: "progressbar2" ); |
2347 | g_signal_connect (adj, "value-changed" , G_CALLBACK (adjustment3_value_changed), widget); |
2348 | g_signal_connect (adj, "value-changed" , G_CALLBACK (adjustment3_value_changed), widget2); |
2349 | |
2350 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "extra_info_entry" ); |
2351 | g_timeout_add (interval: 100, function: (GSourceFunc)pulse_it, data: widget); |
2352 | |
2353 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "scale3" ); |
2354 | gtk_scale_set_format_value_func (GTK_SCALE (widget), func: scale_format_value, NULL, NULL); |
2355 | |
2356 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "scale4" ); |
2357 | gtk_scale_set_format_value_func (GTK_SCALE (widget), func: scale_format_value_blank, NULL, NULL); |
2358 | |
2359 | widget = (GtkWidget *)gtk_builder_get_object (builder, name: "box_for_context" ); |
2360 | model = (GMenuModel *)gtk_builder_get_object (builder, name: "new_style_context_menu_model" ); |
2361 | set_up_context_popover (widget, model); |
2362 | |
2363 | gtk_window_present (window); |
2364 | |
2365 | g_object_unref (object: builder); |
2366 | } |
2367 | |
2368 | static void |
2369 | print_version (void) |
2370 | { |
2371 | g_print (format: "gtk4-widget-factory %s%s%s\n" , |
2372 | PACKAGE_VERSION, |
2373 | g_strcmp0 (str1: PROFILE, str2: "devel" ) == 0 ? "-" : "" , |
2374 | g_strcmp0 (str1: PROFILE, str2: "devel" ) == 0 ? VCS_TAG : "" ); |
2375 | } |
2376 | |
2377 | static int |
2378 | local_options (GApplication *app, |
2379 | GVariantDict *options, |
2380 | gpointer data) |
2381 | { |
2382 | gboolean version = FALSE; |
2383 | |
2384 | g_variant_dict_lookup (dict: options, key: "version" , format_string: "b" , &version); |
2385 | |
2386 | if (version) |
2387 | { |
2388 | print_version (); |
2389 | return 0; |
2390 | } |
2391 | |
2392 | return -1; |
2393 | } |
2394 | |
2395 | static void |
2396 | activate_action (GSimpleAction *action, |
2397 | GVariant *parameter, |
2398 | gpointer user_data) |
2399 | { |
2400 | g_print (format: "Activate action %s\n" , g_action_get_name (G_ACTION (action))); |
2401 | } |
2402 | |
2403 | static void |
2404 | select_action (GSimpleAction *action, |
2405 | GVariant *parameter, |
2406 | gpointer user_data) |
2407 | { |
2408 | g_print (format: "Select action %s value %s\n" , |
2409 | g_action_get_name (G_ACTION (action)), |
2410 | g_variant_get_string (value: parameter, NULL)); |
2411 | |
2412 | g_simple_action_set_state (simple: action, value: parameter); |
2413 | } |
2414 | |
2415 | static void |
2416 | toggle_action (GSimpleAction *action, |
2417 | GVariant *parameter, |
2418 | gpointer user_data) |
2419 | { |
2420 | GVariant *state = g_action_get_state (G_ACTION (action)); |
2421 | |
2422 | g_print (format: "Toggle action %s to %s\n" , |
2423 | g_action_get_name (G_ACTION (action)), |
2424 | g_variant_get_boolean (value: state) ? "false" : "true" ); |
2425 | |
2426 | g_simple_action_set_state (simple: action, |
2427 | value: g_variant_new_boolean (value: !g_variant_get_boolean (value: state))); |
2428 | } |
2429 | |
2430 | static gboolean |
2431 | quit_timeout (gpointer data) |
2432 | { |
2433 | exit (status: 0); |
2434 | return G_SOURCE_REMOVE; |
2435 | } |
2436 | |
2437 | int |
2438 | main (int argc, char *argv[]) |
2439 | { |
2440 | GtkApplication *app; |
2441 | GAction *action; |
2442 | static GActionEntry app_entries[] = { |
2443 | { "about" , activate_about, NULL, NULL, NULL }, |
2444 | { "shortcuts" , activate_shortcuts_window, NULL, NULL, NULL }, |
2445 | { "quit" , activate_quit, NULL, NULL, NULL }, |
2446 | { "inspector" , activate_inspector, NULL, NULL, NULL }, |
2447 | { "main" , NULL, "s" , "'steak'" , NULL }, |
2448 | { "wine" , NULL, NULL, "false" , NULL }, |
2449 | { "beer" , NULL, NULL, "false" , NULL }, |
2450 | { "water" , NULL, NULL, "true" , NULL }, |
2451 | { "dessert" , NULL, "s" , "'bars'" , NULL }, |
2452 | { "pay" , NULL, "s" , NULL, NULL }, |
2453 | { "share" , activate_action, NULL, NULL, NULL }, |
2454 | { "labels" , activate_action, NULL, NULL, NULL }, |
2455 | { "new" , activate_action, NULL, NULL, NULL }, |
2456 | { "open" , activate_action, NULL, NULL, NULL }, |
2457 | { "open-in" , activate_action, NULL, NULL, NULL }, |
2458 | { "open-tab" , activate_action, NULL, NULL, NULL }, |
2459 | { "open-window" , activate_action, NULL, NULL, NULL }, |
2460 | { "save" , activate_action, NULL, NULL, NULL }, |
2461 | { "save-as" , activate_action, NULL, NULL, NULL }, |
2462 | { "cut" , activate_action, NULL, NULL, NULL }, |
2463 | { "copy" , activate_action, NULL, NULL, NULL }, |
2464 | { "paste" , activate_action, NULL, NULL, NULL }, |
2465 | { "pin" , toggle_action, NULL, "true" , NULL }, |
2466 | { "size" , select_action, "s" , "'medium'" , NULL }, |
2467 | { "berk" , toggle_action, NULL, "true" , NULL }, |
2468 | { "broni" , toggle_action, NULL, "true" , NULL }, |
2469 | { "drutt" , toggle_action, NULL, "true" , NULL }, |
2470 | { "upstairs" , toggle_action, NULL, "true" , NULL }, |
2471 | { "option-a" , activate_action, NULL, NULL, NULL }, |
2472 | { "option-b" , activate_action, NULL, NULL, NULL }, |
2473 | { "option-c" , activate_action, NULL, NULL, NULL }, |
2474 | { "option-d" , activate_action, NULL, NULL, NULL }, |
2475 | { "check-on" , NULL, NULL, "true" , NULL }, |
2476 | { "check-off" , NULL, NULL, "false" , NULL }, |
2477 | { "radio-x" , NULL, "s" , "'x'" , NULL }, |
2478 | { "check-on-disabled" , NULL, NULL, "true" , NULL }, |
2479 | { "check-off-disabled" , NULL, NULL, "false" , NULL }, |
2480 | { "radio-x-disabled" , NULL, "s" , "'x'" , NULL }, |
2481 | }; |
2482 | int status; |
2483 | |
2484 | app = gtk_application_new (application_id: "org.gtk.WidgetFactory4" , flags: G_APPLICATION_NON_UNIQUE); |
2485 | |
2486 | g_action_map_add_action_entries (G_ACTION_MAP (app), |
2487 | entries: app_entries, G_N_ELEMENTS (app_entries), |
2488 | user_data: app); |
2489 | action = g_action_map_lookup_action (G_ACTION_MAP (app), action_name: "wine" ); |
2490 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); |
2491 | action = g_action_map_lookup_action (G_ACTION_MAP (app), action_name: "check-on-disabled" ); |
2492 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); |
2493 | action = g_action_map_lookup_action (G_ACTION_MAP (app), action_name: "check-off-disabled" ); |
2494 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); |
2495 | action = g_action_map_lookup_action (G_ACTION_MAP (app), action_name: "radio-x-disabled" ); |
2496 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); |
2497 | |
2498 | g_signal_connect (app, "activate" , G_CALLBACK (activate), NULL); |
2499 | |
2500 | g_application_add_main_option (G_APPLICATION (app), long_name: "version" , short_name: 0, flags: 0, arg: G_OPTION_ARG_NONE, description: "Show program version" , NULL); |
2501 | |
2502 | if (g_getenv (variable: "GTK_DEBUG_AUTO_QUIT" )) |
2503 | g_timeout_add (interval: 500, function: quit_timeout, NULL); |
2504 | |
2505 | g_signal_connect (app, "handle-local-options" , G_CALLBACK (local_options), NULL); |
2506 | status = g_application_run (G_APPLICATION (app), argc, argv); |
2507 | g_object_unref (object: app); |
2508 | |
2509 | return status; |
2510 | } |
2511 | |