forked from AuroraMiddleware/gtk
2a24b8c653
These are all on GtkBox or enumerating children.
2253 lines
70 KiB
C
2253 lines
70 KiB
C
/* widget-factory: a collection of widgets, for easy theme testing
|
||
*
|
||
* Copyright (C) 2011 Canonical Ltd
|
||
*
|
||
* This library is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU Lesser General Public
|
||
* License as published by the Free Software Foundation; either
|
||
* version 2 of the License, or (at your option) any later version.
|
||
*
|
||
* This library is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
* Lesser General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||
*
|
||
* Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
|
||
*/
|
||
|
||
#include "config.h"
|
||
|
||
#include <stdlib.h>
|
||
|
||
#include <glib/gi18n.h>
|
||
#include <gtk/gtk.h>
|
||
|
||
static void
|
||
change_dark_state (GSimpleAction *action,
|
||
GVariant *state,
|
||
gpointer user_data)
|
||
{
|
||
GtkSettings *settings = gtk_settings_get_default ();
|
||
|
||
g_object_set (G_OBJECT (settings),
|
||
"gtk-application-prefer-dark-theme",
|
||
g_variant_get_boolean (state),
|
||
NULL);
|
||
|
||
g_simple_action_set_state (action, state);
|
||
}
|
||
|
||
static void
|
||
change_theme_state (GSimpleAction *action,
|
||
GVariant *state,
|
||
gpointer user_data)
|
||
{
|
||
GtkSettings *settings = gtk_settings_get_default ();
|
||
const char *s;
|
||
const char *theme;
|
||
gboolean prefer_dark = FALSE;
|
||
|
||
g_simple_action_set_state (action, state);
|
||
|
||
s = g_variant_get_string (state, NULL);
|
||
|
||
if (strcmp (s, "adwaita") == 0)
|
||
{
|
||
theme = "Adwaita";
|
||
prefer_dark = FALSE;
|
||
}
|
||
else if (strcmp (s, "adwaita-dark") == 0)
|
||
{
|
||
theme = "Adwaita";
|
||
prefer_dark = TRUE;
|
||
}
|
||
else if (strcmp (s, "highcontrast") == 0)
|
||
{
|
||
theme = "HighContrast";
|
||
prefer_dark = FALSE;
|
||
}
|
||
else if (strcmp (s, "highcontrast-inverse") == 0)
|
||
{
|
||
theme = "HighContrastInverse";
|
||
prefer_dark = FALSE;
|
||
}
|
||
else if (strcmp (s, "current") == 0)
|
||
{
|
||
gtk_settings_reset_property (settings, "gtk-theme-name");
|
||
gtk_settings_reset_property (settings, "gtk-application-prefer-dark-theme");
|
||
return;
|
||
}
|
||
else
|
||
return;
|
||
|
||
g_object_set (G_OBJECT (settings),
|
||
"gtk-theme-name", theme,
|
||
"gtk-application-prefer-dark-theme", prefer_dark,
|
||
NULL);
|
||
}
|
||
|
||
static GtkWidget *page_stack;
|
||
|
||
static void
|
||
change_transition_state (GSimpleAction *action,
|
||
GVariant *state,
|
||
gpointer user_data)
|
||
{
|
||
GtkStackTransitionType transition;
|
||
|
||
if (g_variant_get_boolean (state))
|
||
transition = GTK_STACK_TRANSITION_TYPE_CROSSFADE;
|
||
else
|
||
transition = GTK_STACK_TRANSITION_TYPE_NONE;
|
||
|
||
gtk_stack_set_transition_type (GTK_STACK (page_stack), transition);
|
||
|
||
g_simple_action_set_state (action, state);
|
||
}
|
||
|
||
static gboolean
|
||
get_idle (gpointer data)
|
||
{
|
||
GtkWidget *window = data;
|
||
GtkApplication *app = gtk_window_get_application (GTK_WINDOW (window));
|
||
|
||
gtk_widget_set_sensitive (window, TRUE);
|
||
gdk_surface_set_cursor (gtk_native_get_surface (GTK_NATIVE (window)), NULL);
|
||
g_application_unmark_busy (G_APPLICATION (app));
|
||
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
|
||
static void
|
||
get_busy (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *window = user_data;
|
||
GdkCursor *cursor;
|
||
GtkApplication *app = gtk_window_get_application (GTK_WINDOW (window));
|
||
|
||
g_application_mark_busy (G_APPLICATION (app));
|
||
cursor = gdk_cursor_new_from_name ("wait", NULL);
|
||
gdk_surface_set_cursor (gtk_native_get_surface (GTK_NATIVE (window)), cursor);
|
||
g_object_unref (cursor);
|
||
g_timeout_add (5000, get_idle, window);
|
||
|
||
gtk_widget_set_sensitive (window, FALSE);
|
||
}
|
||
|
||
static gint current_page = 0;
|
||
static gboolean
|
||
on_page (gint i)
|
||
{
|
||
return current_page == i;
|
||
}
|
||
|
||
static void
|
||
activate_search (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *window = user_data;
|
||
GtkWidget *searchbar;
|
||
|
||
if (!on_page (2))
|
||
return;
|
||
|
||
searchbar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "searchbar"));
|
||
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (searchbar), TRUE);
|
||
}
|
||
|
||
static void
|
||
activate_delete (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *window = user_data;
|
||
GtkWidget *infobar;
|
||
|
||
g_print ("Activate action delete\n");
|
||
|
||
if (!on_page (2))
|
||
return;
|
||
|
||
infobar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "infobar"));
|
||
gtk_widget_show (infobar);
|
||
}
|
||
|
||
static void populate_flowbox (GtkWidget *flowbox);
|
||
|
||
static void
|
||
activate_background (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *window = user_data;
|
||
GtkWidget *dialog;
|
||
GtkWidget *flowbox;
|
||
|
||
if (!on_page (2))
|
||
return;
|
||
|
||
dialog = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "selection_dialog"));
|
||
flowbox = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "selection_flowbox"));
|
||
|
||
gtk_widget_show (dialog);
|
||
populate_flowbox (flowbox);
|
||
}
|
||
|
||
static void
|
||
activate_open (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *window = user_data;
|
||
GtkWidget *button;
|
||
|
||
if (!on_page (3))
|
||
return;
|
||
|
||
button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "open_menubutton"));
|
||
g_signal_emit_by_name (button, "clicked");
|
||
}
|
||
|
||
static void
|
||
activate_record (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *window = user_data;
|
||
GtkWidget *button;
|
||
|
||
if (!on_page (3))
|
||
return;
|
||
|
||
button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "record_button"));
|
||
g_signal_emit_by_name (button, "clicked");
|
||
}
|
||
|
||
static void
|
||
activate_lock (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *window = user_data;
|
||
GtkWidget *button;
|
||
|
||
if (!on_page (3))
|
||
return;
|
||
|
||
button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "lockbutton"));
|
||
g_signal_emit_by_name (button, "clicked");
|
||
}
|
||
|
||
static void
|
||
activate_about (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkApplication *app = user_data;
|
||
const gchar *authors[] = {
|
||
"Andrea Cimitan",
|
||
"Cosimo Cecchi",
|
||
NULL
|
||
};
|
||
gchar *version;
|
||
GString *s;
|
||
|
||
s = g_string_new ("");
|
||
|
||
g_string_append (s, "System libraries\n");
|
||
g_string_append_printf (s, "\tGLib\t%d.%d.%d\n",
|
||
glib_major_version,
|
||
glib_minor_version,
|
||
glib_micro_version);
|
||
g_string_append_printf (s, "\tPango\t%s\n",
|
||
pango_version_string ());
|
||
g_string_append_printf (s, "\tGTK\t%d.%d.%d\n",
|
||
gtk_get_major_version (),
|
||
gtk_get_minor_version (),
|
||
gtk_get_micro_version ());
|
||
g_string_append_printf (s, "\nA link can apppear here: <http://www.gtk.org>");
|
||
|
||
version = g_strdup_printf ("%s\nRunning against GTK %d.%d.%d",
|
||
PACKAGE_VERSION,
|
||
gtk_get_major_version (),
|
||
gtk_get_minor_version (),
|
||
gtk_get_micro_version ());
|
||
|
||
gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
|
||
"program-name", "GTK Widget Factory",
|
||
"version", version,
|
||
"copyright", "© 1997—2020 The GTK Team",
|
||
"license-type", GTK_LICENSE_LGPL_2_1,
|
||
"website", "http://www.gtk.org",
|
||
"comments", "Program to demonstrate GTK themes and widgets",
|
||
"authors", authors,
|
||
"logo-icon-name", "org.gtk.WidgetFactory4",
|
||
"title", "About GTK Widget Factory",
|
||
"system-information", s->str,
|
||
NULL);
|
||
|
||
g_string_free (s, TRUE);
|
||
g_free (version);
|
||
}
|
||
|
||
static void
|
||
activate_quit (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkApplication *app = user_data;
|
||
GtkWidget *win;
|
||
GList *list, *next;
|
||
|
||
list = gtk_application_get_windows (app);
|
||
while (list)
|
||
{
|
||
win = list->data;
|
||
next = list->next;
|
||
|
||
gtk_window_destroy (GTK_WINDOW (win));
|
||
|
||
list = next;
|
||
}
|
||
}
|
||
|
||
static void
|
||
activate_inspector (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
gtk_window_set_interactive_debugging (TRUE);
|
||
}
|
||
|
||
static void
|
||
print_operation_done (GtkPrintOperation *op,
|
||
GtkPrintOperationResult res,
|
||
gpointer data)
|
||
{
|
||
GError *error = NULL;
|
||
|
||
switch (res)
|
||
{
|
||
case GTK_PRINT_OPERATION_RESULT_ERROR:
|
||
gtk_print_operation_get_error (op, &error);
|
||
g_print ("Printing failed: %s\n", error->message);
|
||
g_clear_error (&error);
|
||
break;
|
||
case GTK_PRINT_OPERATION_RESULT_APPLY:
|
||
break;
|
||
case GTK_PRINT_OPERATION_RESULT_CANCEL:
|
||
g_print ("Printing was canceled\n");
|
||
break;
|
||
case GTK_PRINT_OPERATION_RESULT_IN_PROGRESS:
|
||
return;
|
||
default:
|
||
g_assert_not_reached ();
|
||
break;
|
||
}
|
||
|
||
g_object_unref (op);
|
||
}
|
||
|
||
static void
|
||
print_operation_begin (GtkPrintOperation *op,
|
||
GtkPrintContext *context,
|
||
gpointer data)
|
||
{
|
||
gtk_print_operation_set_n_pages (op, 1);
|
||
}
|
||
|
||
static void
|
||
print_operation_page (GtkPrintOperation *op,
|
||
GtkPrintContext *context,
|
||
int page,
|
||
gpointer data)
|
||
{
|
||
cairo_t *cr;
|
||
double width;
|
||
double aspect_ratio;
|
||
GdkSnapshot *snapshot;
|
||
GdkPaintable *paintable;
|
||
GskRenderNode *node;
|
||
|
||
g_print ("Save the trees!\n");
|
||
|
||
cr = gtk_print_context_get_cairo_context (context);
|
||
width = gtk_print_context_get_width (context);
|
||
|
||
snapshot = gtk_snapshot_new ();
|
||
paintable = gtk_widget_paintable_new (GTK_WIDGET (data));
|
||
aspect_ratio = gdk_paintable_get_intrinsic_aspect_ratio (paintable);
|
||
gdk_paintable_snapshot (paintable, snapshot, width, width / aspect_ratio);
|
||
node = gtk_snapshot_free_to_node (snapshot);
|
||
|
||
gsk_render_node_draw (node, cr);
|
||
|
||
gsk_render_node_unref (node);
|
||
|
||
g_object_unref (paintable);
|
||
}
|
||
|
||
static void
|
||
activate_print (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GtkWindow *window = GTK_WINDOW (user_data);
|
||
GtkPrintOperation *op;
|
||
GtkPrintOperationResult res;
|
||
|
||
op = gtk_print_operation_new ();
|
||
gtk_print_operation_set_allow_async (op, TRUE);
|
||
g_signal_connect (op, "begin-print", G_CALLBACK (print_operation_begin), NULL);
|
||
g_signal_connect (op, "draw-page", G_CALLBACK (print_operation_page), window);
|
||
g_signal_connect (op, "done", G_CALLBACK (print_operation_done), NULL);
|
||
|
||
res = gtk_print_operation_run (op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, window, NULL);
|
||
|
||
if (res == GTK_PRINT_OPERATION_RESULT_IN_PROGRESS)
|
||
return;
|
||
|
||
print_operation_done (op, res, NULL);
|
||
}
|
||
|
||
static void
|
||
spin_value_changed (GtkAdjustment *adjustment, GtkWidget *label)
|
||
{
|
||
GtkWidget *w;
|
||
gint v;
|
||
gchar *text;
|
||
|
||
v = (int)gtk_adjustment_get_value (adjustment);
|
||
|
||
if ((v % 3) == 0)
|
||
{
|
||
text = g_strdup_printf ("%d is a multiple of 3", v);
|
||
gtk_label_set_label (GTK_LABEL (label), text);
|
||
g_free (text);
|
||
}
|
||
|
||
w = gtk_widget_get_ancestor (label, GTK_TYPE_REVEALER);
|
||
gtk_revealer_set_reveal_child (GTK_REVEALER (w), (v % 3) == 0);
|
||
}
|
||
|
||
static void
|
||
dismiss (GtkWidget *button)
|
||
{
|
||
GtkWidget *w;
|
||
|
||
w = gtk_widget_get_ancestor (button, GTK_TYPE_REVEALER);
|
||
gtk_revealer_set_reveal_child (GTK_REVEALER (w), FALSE);
|
||
}
|
||
|
||
static void
|
||
spin_value_reset (GtkWidget *button, GtkAdjustment *adjustment)
|
||
{
|
||
gtk_adjustment_set_value (adjustment, 50.0);
|
||
dismiss (button);
|
||
}
|
||
|
||
static gint pulse_time = 250;
|
||
static gint pulse_entry_mode = 0;
|
||
|
||
static void
|
||
remove_pulse (gpointer pulse_id)
|
||
{
|
||
g_source_remove (GPOINTER_TO_UINT (pulse_id));
|
||
}
|
||
|
||
static gboolean
|
||
pulse_it (GtkWidget *widget)
|
||
{
|
||
guint pulse_id;
|
||
|
||
if (GTK_IS_ENTRY (widget))
|
||
gtk_entry_progress_pulse (GTK_ENTRY (widget));
|
||
else
|
||
gtk_progress_bar_pulse (GTK_PROGRESS_BAR (widget));
|
||
|
||
pulse_id = g_timeout_add (pulse_time, (GSourceFunc)pulse_it, widget);
|
||
g_object_set_data_full (G_OBJECT (widget), "pulse_id", GUINT_TO_POINTER (pulse_id), remove_pulse);
|
||
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
|
||
static void
|
||
update_pulse_time (GtkAdjustment *adjustment, GtkWidget *widget)
|
||
{
|
||
gdouble value;
|
||
guint pulse_id;
|
||
|
||
value = gtk_adjustment_get_value (adjustment);
|
||
|
||
pulse_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "pulse_id"));
|
||
|
||
/* vary between 50 and 450 */
|
||
pulse_time = 50 + 4 * value;
|
||
|
||
if (value == 100)
|
||
{
|
||
g_object_set_data (G_OBJECT (widget), "pulse_id", NULL);
|
||
}
|
||
else if (value < 100)
|
||
{
|
||
if (pulse_id == 0 && (GTK_IS_PROGRESS_BAR (widget) || pulse_entry_mode % 3 == 2))
|
||
{
|
||
pulse_id = g_timeout_add (pulse_time, (GSourceFunc)pulse_it, widget);
|
||
g_object_set_data_full (G_OBJECT (widget), "pulse_id", GUINT_TO_POINTER (pulse_id), remove_pulse);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void
|
||
on_entry_icon_release (GtkEntry *entry,
|
||
GtkEntryIconPosition icon_pos,
|
||
gpointer user_data)
|
||
{
|
||
if (icon_pos != GTK_ENTRY_ICON_SECONDARY)
|
||
return;
|
||
|
||
pulse_entry_mode++;
|
||
|
||
if (pulse_entry_mode % 3 == 0)
|
||
{
|
||
g_object_set_data (G_OBJECT (entry), "pulse_id", NULL);
|
||
gtk_entry_set_progress_fraction (entry, 0);
|
||
}
|
||
else if (pulse_entry_mode % 3 == 1)
|
||
gtk_entry_set_progress_fraction (entry, 0.25);
|
||
else if (pulse_entry_mode % 3 == 2)
|
||
{
|
||
if (pulse_time - 50 < 400)
|
||
{
|
||
gtk_entry_set_progress_pulse_step (entry, 0.1);
|
||
pulse_it (GTK_WIDGET (entry));
|
||
}
|
||
}
|
||
}
|
||
|
||
#define EPSILON (1e-10)
|
||
|
||
static void
|
||
on_scale_button_value_changed (GtkScaleButton *button,
|
||
gdouble value,
|
||
gpointer user_data)
|
||
{
|
||
GtkAdjustment *adjustment;
|
||
gdouble val;
|
||
gchar *str;
|
||
|
||
adjustment = gtk_scale_button_get_adjustment (button);
|
||
val = gtk_scale_button_get_value (button);
|
||
|
||
if (val < (gtk_adjustment_get_lower (adjustment) + EPSILON))
|
||
{
|
||
str = g_strdup (_("Muted"));
|
||
}
|
||
else if (val >= (gtk_adjustment_get_upper (adjustment) - EPSILON))
|
||
{
|
||
str = g_strdup (_("Full Volume"));
|
||
}
|
||
else
|
||
{
|
||
gint percent;
|
||
|
||
percent = (gint) (100. * val / (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_lower (adjustment)) + .5);
|
||
|
||
str = g_strdup_printf (C_("volume percentage", "%d %%"), percent);
|
||
}
|
||
|
||
gtk_widget_set_tooltip_text (GTK_WIDGET (button), str);
|
||
atk_object_set_description (gtk_widget_get_accessible (GTK_WIDGET (button)), str);
|
||
|
||
g_free (str);
|
||
}
|
||
|
||
static void
|
||
on_record_button_toggled (GtkToggleButton *button,
|
||
gpointer user_data)
|
||
{
|
||
|
||
if (gtk_toggle_button_get_active (button))
|
||
gtk_widget_remove_css_class (GTK_WIDGET (button), "destructive-action");
|
||
else
|
||
gtk_widget_add_css_class (GTK_WIDGET (button), "destructive-action");
|
||
}
|
||
|
||
static void
|
||
on_page_combo_changed (GtkComboBox *combo,
|
||
gpointer user_data)
|
||
{
|
||
GtkWidget *from;
|
||
GtkWidget *to;
|
||
GtkWidget *print;
|
||
|
||
from = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "range_from_spin"));
|
||
to = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "range_to_spin"));
|
||
print = GTK_WIDGET (g_object_get_data (G_OBJECT (combo), "print_button"));
|
||
|
||
switch (gtk_combo_box_get_active (combo))
|
||
{
|
||
case 0: /* Range */
|
||
gtk_widget_set_sensitive (from, TRUE);
|
||
gtk_widget_set_sensitive (to, TRUE);
|
||
gtk_widget_set_sensitive (print, TRUE);
|
||
break;
|
||
case 1: /* All */
|
||
gtk_widget_set_sensitive (from, FALSE);
|
||
gtk_widget_set_sensitive (to, FALSE);
|
||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (from), 1);
|
||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (to), 99);
|
||
gtk_widget_set_sensitive (print, TRUE);
|
||
break;
|
||
case 2: /* Current */
|
||
gtk_widget_set_sensitive (from, FALSE);
|
||
gtk_widget_set_sensitive (to, FALSE);
|
||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (from), 7);
|
||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (to), 7);
|
||
gtk_widget_set_sensitive (print, TRUE);
|
||
break;
|
||
case 4:
|
||
gtk_widget_set_sensitive (from, FALSE);
|
||
gtk_widget_set_sensitive (to, FALSE);
|
||
gtk_widget_set_sensitive (print, FALSE);
|
||
break;
|
||
default:;
|
||
}
|
||
}
|
||
|
||
static void
|
||
on_range_from_changed (GtkSpinButton *from)
|
||
{
|
||
GtkSpinButton *to;
|
||
gint v1, v2;
|
||
|
||
to = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (from), "range_to_spin"));
|
||
|
||
v1 = gtk_spin_button_get_value_as_int (from);
|
||
v2 = gtk_spin_button_get_value_as_int (to);
|
||
|
||
if (v1 > v2)
|
||
gtk_spin_button_set_value (to, v1);
|
||
}
|
||
|
||
static void
|
||
on_range_to_changed (GtkSpinButton *to)
|
||
{
|
||
GtkSpinButton *from;
|
||
gint v1, v2;
|
||
|
||
from = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (to), "range_from_spin"));
|
||
|
||
v1 = gtk_spin_button_get_value_as_int (from);
|
||
v2 = gtk_spin_button_get_value_as_int (to);
|
||
|
||
if (v1 > v2)
|
||
gtk_spin_button_set_value (from, v2);
|
||
}
|
||
|
||
static void
|
||
info_bar_response (GtkWidget *infobar, gint response_id)
|
||
{
|
||
if (response_id == GTK_RESPONSE_CLOSE)
|
||
gtk_widget_hide (infobar);
|
||
}
|
||
|
||
static void
|
||
show_dialog (GtkWidget *button, GtkWidget *dialog)
|
||
{
|
||
gtk_widget_show (dialog);
|
||
}
|
||
|
||
static void
|
||
close_dialog (GtkWidget *dialog)
|
||
{
|
||
gtk_widget_hide (dialog);
|
||
}
|
||
|
||
static void
|
||
set_needs_attention (GtkWidget *page, gboolean needs_attention)
|
||
{
|
||
GtkWidget *stack;
|
||
|
||
stack = gtk_widget_get_parent (page);
|
||
g_object_set (gtk_stack_get_page (GTK_STACK (stack), page),
|
||
"needs-attention", needs_attention,
|
||
NULL);
|
||
}
|
||
|
||
static gboolean
|
||
demand_attention (gpointer stack)
|
||
{
|
||
GtkWidget *page;
|
||
|
||
page = gtk_stack_get_child_by_name (GTK_STACK (stack), "page3");
|
||
set_needs_attention (page, TRUE);
|
||
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
|
||
static void
|
||
action_dialog_button_clicked (GtkButton *button, GtkWidget *page)
|
||
{
|
||
g_timeout_add (1000, demand_attention, page);
|
||
}
|
||
|
||
static void
|
||
page_changed_cb (GtkWidget *stack, GParamSpec *pspec, gpointer data)
|
||
{
|
||
const gchar *name;
|
||
GtkWidget *window;
|
||
GtkWidget *page;
|
||
|
||
if (gtk_widget_in_destruction (stack))
|
||
return;
|
||
|
||
name = gtk_stack_get_visible_child_name (GTK_STACK (stack));
|
||
|
||
window = gtk_widget_get_ancestor (stack, GTK_TYPE_APPLICATION_WINDOW);
|
||
g_object_set (gtk_application_window_get_help_overlay (GTK_APPLICATION_WINDOW (window)),
|
||
"view-name", name,
|
||
NULL);
|
||
|
||
if (g_str_equal (name, "page1"))
|
||
current_page = 1;
|
||
else if (g_str_equal (name, "page2"))
|
||
current_page = 2;
|
||
if (g_str_equal (name, "page3"))
|
||
{
|
||
current_page = 3;
|
||
page = gtk_stack_get_visible_child (GTK_STACK (stack));
|
||
set_needs_attention (GTK_WIDGET (page), FALSE);
|
||
}
|
||
}
|
||
|
||
static void
|
||
populate_model (GtkTreeStore *store)
|
||
{
|
||
GtkTreeIter iter, parent0, parent1, parent2, parent3;
|
||
|
||
gtk_tree_store_append (store, &iter, NULL);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Charlemagne",
|
||
1, "742",
|
||
2, "814",
|
||
-1);
|
||
parent0 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent0);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Pepin the Short",
|
||
1, "714",
|
||
2, "768",
|
||
-1);
|
||
parent1 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent1);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Charles Martel",
|
||
1, "688",
|
||
2, "741",
|
||
-1);
|
||
parent2 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent2);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Pepin of Herstal",
|
||
1, "635",
|
||
2, "714",
|
||
-1);
|
||
parent3 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent3);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Ansegisel",
|
||
1, "602 or 610",
|
||
2, "murdered before 679",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent3);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Begga",
|
||
1, "615",
|
||
2, "693",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent2);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Alpaida",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent1);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Rotrude",
|
||
-1);
|
||
parent2 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent2);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Liévin de Trèves",
|
||
-1);
|
||
parent3 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent3);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Guérin",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent3);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Gunza",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent2);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Willigarde de Bavière",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent0);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Bertrada of Laon",
|
||
1, "710",
|
||
2, "783",
|
||
-1);
|
||
parent1 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent1);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Caribert of Laon",
|
||
2, "before 762",
|
||
-1);
|
||
parent2 = iter;
|
||
gtk_tree_store_append (store, &iter, &parent2);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Unknown",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent2);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Bertrada of Prüm",
|
||
1, "ca. 670",
|
||
2, "after 721",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, &parent1);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Gisele of Aquitaine",
|
||
-1);
|
||
gtk_tree_store_append (store, &iter, NULL);
|
||
gtk_tree_store_set (store, &iter, 3, TRUE, -1);
|
||
gtk_tree_store_append (store, &iter, NULL);
|
||
gtk_tree_store_set (store, &iter,
|
||
0, "Attila the Hun",
|
||
1, "ca. 390",
|
||
2, "453",
|
||
-1);
|
||
}
|
||
|
||
static gboolean
|
||
row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
|
||
{
|
||
gboolean is_sep;
|
||
|
||
gtk_tree_model_get (model, iter, 3, &is_sep, -1);
|
||
|
||
return is_sep;
|
||
}
|
||
|
||
static void
|
||
update_title_header (GtkListBoxRow *row,
|
||
GtkListBoxRow *before,
|
||
gpointer data)
|
||
{
|
||
GtkWidget *header;
|
||
gchar *title;
|
||
|
||
header = gtk_list_box_row_get_header (row);
|
||
title = (gchar *)g_object_get_data (G_OBJECT (row), "title");
|
||
if (!header && title)
|
||
{
|
||
title = g_strdup_printf ("<b>%s</b>", title);
|
||
|
||
header = gtk_label_new (title);
|
||
gtk_label_set_use_markup (GTK_LABEL (header), TRUE);
|
||
gtk_widget_set_halign (header, GTK_ALIGN_START);
|
||
gtk_widget_set_margin_top (header, 12);
|
||
gtk_widget_set_margin_start (header, 6);
|
||
gtk_widget_set_margin_end (header, 6);
|
||
gtk_widget_set_margin_bottom (header, 6);
|
||
gtk_widget_show (header);
|
||
|
||
gtk_list_box_row_set_header (row, header);
|
||
|
||
g_free (title);
|
||
}
|
||
}
|
||
|
||
static void
|
||
overshot (GtkScrolledWindow *sw, GtkPositionType pos, GtkWidget *widget)
|
||
{
|
||
GtkWidget *box, *row, *label, *swatch;
|
||
GdkRGBA rgba;
|
||
const gchar *color;
|
||
gchar *text;
|
||
GtkWidget *silver;
|
||
GtkWidget *gold;
|
||
|
||
silver = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "Silver"));
|
||
gold = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "Gold"));
|
||
|
||
if (pos == GTK_POS_TOP)
|
||
{
|
||
if (silver)
|
||
{
|
||
gtk_list_box_remove (GTK_LIST_BOX (widget), silver);
|
||
g_object_set_data (G_OBJECT (widget), "Silver", NULL);
|
||
}
|
||
if (gold)
|
||
{
|
||
gtk_list_box_remove (GTK_LIST_BOX (widget), gold);
|
||
g_object_set_data (G_OBJECT (widget), "Gold", NULL);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
if (gold)
|
||
return;
|
||
else if (silver)
|
||
color = "Gold";
|
||
else
|
||
color = "Silver";
|
||
|
||
row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
|
||
text = g_strconcat ("<b>", color, "</b>", NULL);
|
||
label = gtk_label_new (text);
|
||
g_free (text);
|
||
g_object_set (label,
|
||
"use-markup", TRUE,
|
||
"halign", GTK_ALIGN_START,
|
||
"valign", GTK_ALIGN_CENTER,
|
||
"hexpand", TRUE,
|
||
"margin-start", 6,
|
||
"margin-end", 6,
|
||
"margin-top", 6,
|
||
"margin-bottom", 6,
|
||
"xalign", 0.0,
|
||
NULL);
|
||
gtk_box_append (GTK_BOX (row), label);
|
||
gdk_rgba_parse (&rgba, color);
|
||
swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
|
||
"rgba", &rgba,
|
||
"can-focus", FALSE,
|
||
"selectable", FALSE,
|
||
"halign", GTK_ALIGN_END,
|
||
"valign", GTK_ALIGN_CENTER,
|
||
"margin-start", 6,
|
||
"margin-end", 6,
|
||
"margin-top", 6,
|
||
"margin-bottom", 6,
|
||
"height-request", 24,
|
||
NULL);
|
||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||
gtk_box_append (GTK_BOX (box), swatch);
|
||
gtk_box_append (GTK_BOX (row), box);
|
||
gtk_list_box_insert (GTK_LIST_BOX (widget), row, -1);
|
||
row = gtk_widget_get_parent (row);
|
||
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
|
||
g_object_set_data (G_OBJECT (widget), color, row);
|
||
g_object_set_data (G_OBJECT (row), "color", (gpointer)color);
|
||
}
|
||
|
||
static void
|
||
rgba_changed (GtkColorChooser *chooser, GParamSpec *pspec, GtkListBox *box)
|
||
{
|
||
gtk_list_box_select_row (box, NULL);
|
||
}
|
||
|
||
static void
|
||
set_color (GtkListBox *box, GtkListBoxRow *row, GtkColorChooser *chooser)
|
||
{
|
||
const char *color;
|
||
GdkRGBA rgba;
|
||
|
||
if (!row)
|
||
return;
|
||
|
||
color = (const char *)g_object_get_data (G_OBJECT (row), "color");
|
||
|
||
if (!color)
|
||
return;
|
||
|
||
if (gdk_rgba_parse (&rgba, color))
|
||
{
|
||
g_signal_handlers_block_by_func (chooser, rgba_changed, box);
|
||
gtk_color_chooser_set_rgba (chooser, &rgba);
|
||
g_signal_handlers_unblock_by_func (chooser, rgba_changed, box);
|
||
}
|
||
}
|
||
|
||
static void
|
||
populate_colors (GtkWidget *widget, GtkWidget *chooser)
|
||
{
|
||
struct { const gchar *name; const gchar *color; const gchar *title; } colors[] = {
|
||
{ "2.5", "#C8828C", "Red" },
|
||
{ "5", "#C98286", NULL },
|
||
{ "7.5", "#C9827F", NULL },
|
||
{ "10", "#C98376", NULL },
|
||
{ "2.5", "#C8856D", "Red/Yellow" },
|
||
{ "5", "#C58764", NULL },
|
||
{ "7.5", "#C1895E", NULL },
|
||
{ "10", "#BB8C56", NULL },
|
||
{ "2.5", "#B58F4F", "Yellow" },
|
||
{ "5", "#AD924B", NULL },
|
||
{ "7.5", "#A79548", NULL },
|
||
{ "10", "#A09749", NULL },
|
||
{ "2.5", "#979A4E", "Yellow/Green" },
|
||
{ "5", "#8D9C55", NULL },
|
||
{ "7.5", "#7F9F62", NULL },
|
||
{ "10", "#73A06E", NULL },
|
||
{ "2.5", "#65A27C", "Green" },
|
||
{ "5", "#5CA386", NULL },
|
||
{ "7.5", "#57A38D", NULL },
|
||
{ "10", "#52A394", NULL },
|
||
{ "2.5", "#4EA39A", "Green/Blue" },
|
||
{ "5", "#49A3A2", NULL },
|
||
{ "7.5", "#46A2AA", NULL },
|
||
{ "10", "#46A1B1", NULL },
|
||
{ "2.5", "#49A0B8", "Blue" },
|
||
{ "5", "#529EBD", NULL },
|
||
{ "7.5", "#5D9CC1", NULL },
|
||
{ "10", "#689AC3", NULL },
|
||
{ "2.5", "#7597C5", "Blue/Purple" },
|
||
{ "5", "#8095C6", NULL },
|
||
{ "7.5", "#8D91C6", NULL },
|
||
{ "10", "#988EC4", NULL },
|
||
{ "2.5", "#A08CC1", "Purple" },
|
||
{ "5", "#A88ABD", NULL },
|
||
{ "7.5", "#B187B6", NULL },
|
||
{ "10", "#B786B0", NULL },
|
||
{ "2.5", "#BC84A9", "Purple/Red" },
|
||
{ "5", "#C183A0", NULL },
|
||
{ "7.5", "#C48299", NULL },
|
||
{ "10", "#C68292", NULL }
|
||
};
|
||
gint i;
|
||
GtkWidget *row, *box, *label, *swatch;
|
||
GtkWidget *sw;
|
||
GdkRGBA rgba;
|
||
|
||
gtk_list_box_set_header_func (GTK_LIST_BOX (widget), update_title_header, NULL, NULL);
|
||
|
||
for (i = 0; i < G_N_ELEMENTS (colors); i++)
|
||
{
|
||
row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
|
||
label = gtk_label_new (colors[i].name);
|
||
g_object_set (label,
|
||
"halign", GTK_ALIGN_START,
|
||
"valign", GTK_ALIGN_CENTER,
|
||
"margin-start", 6,
|
||
"margin-end", 6,
|
||
"margin-top", 6,
|
||
"margin-bottom", 6,
|
||
"hexpand", TRUE,
|
||
"xalign", 0.0,
|
||
NULL);
|
||
gtk_box_append (GTK_BOX (row), label);
|
||
gdk_rgba_parse (&rgba, colors[i].color);
|
||
swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
|
||
"rgba", &rgba,
|
||
"selectable", FALSE,
|
||
"can-focus", FALSE,
|
||
"halign", GTK_ALIGN_END,
|
||
"valign", GTK_ALIGN_CENTER,
|
||
"margin-start", 6,
|
||
"margin-end", 6,
|
||
"margin-top", 6,
|
||
"margin-bottom", 6,
|
||
"height-request", 24,
|
||
NULL);
|
||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||
gtk_box_append (GTK_BOX (box), swatch);
|
||
gtk_box_append (GTK_BOX (row), box);
|
||
gtk_list_box_insert (GTK_LIST_BOX (widget), row, -1);
|
||
row = gtk_widget_get_parent (row);
|
||
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
|
||
g_object_set_data (G_OBJECT (row), "color", (gpointer)colors[i].color);
|
||
if (colors[i].title)
|
||
g_object_set_data (G_OBJECT (row), "title", (gpointer)colors[i].title);
|
||
}
|
||
|
||
g_signal_connect (widget, "row-selected", G_CALLBACK (set_color), chooser);
|
||
|
||
gtk_list_box_invalidate_headers (GTK_LIST_BOX (widget));
|
||
|
||
sw = gtk_widget_get_ancestor (widget, GTK_TYPE_SCROLLED_WINDOW);
|
||
g_signal_connect (sw, "edge-overshot", G_CALLBACK (overshot), widget);
|
||
}
|
||
|
||
typedef struct {
|
||
GtkWidget *flowbox;
|
||
gchar *filename;
|
||
} BackgroundData;
|
||
|
||
static void
|
||
background_loaded_cb (GObject *source,
|
||
GAsyncResult *res,
|
||
gpointer data)
|
||
{
|
||
BackgroundData *bd = data;
|
||
GtkWidget *child;
|
||
GdkPixbuf *pixbuf;
|
||
GError *error = NULL;
|
||
|
||
pixbuf = gdk_pixbuf_new_from_stream_finish (res, &error);
|
||
if (error)
|
||
{
|
||
g_warning ("Error loading '%s': %s", bd->filename, error->message);
|
||
g_error_free (error);
|
||
return;
|
||
}
|
||
|
||
child = gtk_picture_new_for_pixbuf (pixbuf);
|
||
gtk_widget_set_size_request (child, 110, 70);
|
||
gtk_flow_box_insert (GTK_FLOW_BOX (bd->flowbox), child, -1);
|
||
child = gtk_widget_get_parent (child);
|
||
g_object_set_data_full (G_OBJECT (child), "filename", bd->filename, g_free);
|
||
g_free (bd);
|
||
}
|
||
|
||
static void
|
||
populate_flowbox (GtkWidget *flowbox)
|
||
{
|
||
const gchar *location;
|
||
GDir *dir;
|
||
GError *error = NULL;
|
||
const gchar *name;
|
||
gchar *filename;
|
||
GFile *file;
|
||
GInputStream *stream;
|
||
BackgroundData *bd;
|
||
GdkPixbuf *pixbuf;
|
||
GtkWidget *child;
|
||
|
||
if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (flowbox), "populated")))
|
||
return;
|
||
|
||
g_object_set_data (G_OBJECT (flowbox), "populated", GUINT_TO_POINTER (1));
|
||
|
||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 110, 70);
|
||
gdk_pixbuf_fill (pixbuf, 0xffffffff);
|
||
child = gtk_picture_new_for_pixbuf (pixbuf);
|
||
gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), child, -1);
|
||
|
||
location = "/usr/share/backgrounds/gnome";
|
||
dir = g_dir_open (location, 0, &error);
|
||
if (error)
|
||
{
|
||
g_warning ("%s", error->message);
|
||
g_error_free (error);
|
||
return;
|
||
}
|
||
|
||
while ((name = g_dir_read_name (dir)) != NULL)
|
||
{
|
||
if (g_str_has_suffix (name, ".xml"))
|
||
continue;
|
||
|
||
filename = g_build_filename (location, name, NULL);
|
||
file = g_file_new_for_path (filename);
|
||
stream = G_INPUT_STREAM (g_file_read (file, NULL, &error));
|
||
if (error)
|
||
{
|
||
g_warning ("%s", error->message);
|
||
g_clear_error (&error);
|
||
g_free (filename);
|
||
}
|
||
else
|
||
{
|
||
bd = g_new (BackgroundData, 1);
|
||
bd->flowbox = flowbox;
|
||
bd->filename = filename;
|
||
gdk_pixbuf_new_from_stream_at_scale_async (stream, 110, 110, TRUE, NULL,
|
||
background_loaded_cb, bd);
|
||
}
|
||
|
||
g_object_unref (file);
|
||
g_object_unref (stream);
|
||
}
|
||
|
||
g_dir_close (dir);
|
||
}
|
||
|
||
static void
|
||
row_activated (GtkListBox *box, GtkListBoxRow *row)
|
||
{
|
||
GtkWidget *image;
|
||
GtkWidget *dialog;
|
||
|
||
image = (GtkWidget *)g_object_get_data (G_OBJECT (row), "image");
|
||
dialog = (GtkWidget *)g_object_get_data (G_OBJECT (row), "dialog");
|
||
|
||
if (image)
|
||
{
|
||
if (gtk_widget_get_opacity (image) > 0)
|
||
gtk_widget_set_opacity (image, 0);
|
||
else
|
||
gtk_widget_set_opacity (image, 1);
|
||
}
|
||
else if (dialog)
|
||
{
|
||
gtk_window_present (GTK_WINDOW (dialog));
|
||
}
|
||
}
|
||
|
||
typedef struct
|
||
{
|
||
GtkTextView tv;
|
||
GdkTexture *texture;
|
||
} MyTextView;
|
||
|
||
typedef GtkTextViewClass MyTextViewClass;
|
||
|
||
static GType my_text_view_get_type (void);
|
||
G_DEFINE_TYPE (MyTextView, my_text_view, GTK_TYPE_TEXT_VIEW)
|
||
|
||
static void
|
||
my_text_view_init (MyTextView *tv)
|
||
{
|
||
}
|
||
|
||
static void
|
||
my_tv_snapshot_layer (GtkTextView *widget,
|
||
GtkTextViewLayer layer,
|
||
GtkSnapshot *snapshot)
|
||
{
|
||
MyTextView *tv = (MyTextView *)widget;
|
||
|
||
if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT && tv->texture)
|
||
{
|
||
gtk_snapshot_push_opacity (snapshot, 0.333);
|
||
gtk_snapshot_append_texture (snapshot,
|
||
tv->texture,
|
||
&GRAPHENE_RECT_INIT(
|
||
0, 0,
|
||
gdk_texture_get_width (tv->texture),
|
||
gdk_texture_get_height (tv->texture)
|
||
));
|
||
gtk_snapshot_pop (snapshot);
|
||
}
|
||
}
|
||
|
||
static void
|
||
my_tv_finalize (GObject *object)
|
||
{
|
||
MyTextView *tv = (MyTextView *)object;
|
||
|
||
g_clear_object (&tv->texture);
|
||
|
||
G_OBJECT_CLASS (my_text_view_parent_class)->finalize (object);
|
||
}
|
||
|
||
static void
|
||
my_text_view_class_init (MyTextViewClass *class)
|
||
{
|
||
GtkTextViewClass *tv_class = GTK_TEXT_VIEW_CLASS (class);
|
||
GObjectClass *o_class = G_OBJECT_CLASS (class);
|
||
|
||
o_class->finalize = my_tv_finalize;
|
||
tv_class->snapshot_layer = my_tv_snapshot_layer;
|
||
}
|
||
|
||
static void
|
||
my_text_view_set_background (MyTextView *tv, const gchar *filename)
|
||
{
|
||
GError *error = NULL;
|
||
GFile *file;
|
||
|
||
g_clear_object (&tv->texture);
|
||
|
||
if (filename == NULL)
|
||
return;
|
||
|
||
file = g_file_new_for_path (filename);
|
||
tv->texture = gdk_texture_new_from_file (file, &error);
|
||
g_object_unref (file);
|
||
|
||
if (error)
|
||
{
|
||
g_warning ("%s", error->message);
|
||
g_error_free (error);
|
||
return;
|
||
}
|
||
|
||
gtk_widget_queue_draw (GTK_WIDGET (tv));
|
||
}
|
||
|
||
static void
|
||
close_selection_dialog (GtkWidget *dialog, gint response, GtkWidget *tv)
|
||
{
|
||
GtkWidget *box;
|
||
GtkWidget *child;
|
||
GList *children;
|
||
const gchar *filename;
|
||
|
||
gtk_widget_hide (dialog);
|
||
|
||
if (response == GTK_RESPONSE_CANCEL)
|
||
return;
|
||
|
||
box = gtk_widget_get_first_child (gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
|
||
g_assert (GTK_IS_FLOW_BOX (box));
|
||
children = gtk_flow_box_get_selected_children (GTK_FLOW_BOX (box));
|
||
|
||
if (!children)
|
||
return;
|
||
|
||
child = children->data;
|
||
filename = (const gchar *)g_object_get_data (G_OBJECT (child), "filename");
|
||
|
||
g_list_free (children);
|
||
|
||
my_text_view_set_background ((MyTextView *)tv, filename);
|
||
}
|
||
|
||
static void
|
||
toggle_selection_mode (GtkSwitch *sw,
|
||
GParamSpec *pspec,
|
||
GtkListBox *listbox)
|
||
{
|
||
if (gtk_switch_get_active (sw))
|
||
gtk_list_box_set_selection_mode (listbox, GTK_SELECTION_SINGLE);
|
||
else
|
||
gtk_list_box_set_selection_mode (listbox, GTK_SELECTION_NONE);
|
||
|
||
gtk_list_box_set_activate_on_single_click (listbox, !gtk_switch_get_active (sw));
|
||
}
|
||
|
||
static void
|
||
handle_insert (GtkWidget *button, GtkWidget *textview)
|
||
{
|
||
GtkTextBuffer *buffer;
|
||
const gchar *id;
|
||
const gchar *text;
|
||
|
||
id = gtk_buildable_get_name (GTK_BUILDABLE (button));
|
||
|
||
if (strcmp (id, "toolbutton1") == 0)
|
||
text = "⌘";
|
||
else if (strcmp (id, "toolbutton2") == 0)
|
||
text = "⚽";
|
||
else if (strcmp (id, "toolbutton3") == 0)
|
||
text = "⤢";
|
||
else if (strcmp (id, "toolbutton4") == 0)
|
||
text = "☆";
|
||
else
|
||
text = "";
|
||
|
||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
|
||
gtk_text_buffer_insert_at_cursor (buffer, text, -1);
|
||
}
|
||
|
||
static void
|
||
handle_cutcopypaste (GtkWidget *button, GtkWidget *textview)
|
||
{
|
||
GtkTextBuffer *buffer;
|
||
GdkClipboard *clipboard;
|
||
const gchar *id;
|
||
|
||
clipboard = gtk_widget_get_clipboard (textview);
|
||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
|
||
id = gtk_buildable_get_name (GTK_BUILDABLE (button));
|
||
|
||
if (strcmp (id, "cutbutton") == 0)
|
||
gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
|
||
else if (strcmp (id, "copybutton") == 0)
|
||
gtk_text_buffer_copy_clipboard (buffer, clipboard);
|
||
else if (strcmp (id, "pastebutton") == 0)
|
||
gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
|
||
else if (strcmp (id, "deletebutton") == 0)
|
||
gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
|
||
}
|
||
|
||
static void
|
||
clipboard_formats_notify (GdkClipboard *clipboard, GdkEvent *event, GtkWidget *button)
|
||
{
|
||
const gchar *id;
|
||
gboolean has_text;
|
||
|
||
id = gtk_buildable_get_name (GTK_BUILDABLE (button));
|
||
has_text = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GTK_TYPE_TEXT_BUFFER);
|
||
|
||
if (strcmp (id, "pastebutton") == 0)
|
||
gtk_widget_set_sensitive (button, has_text);
|
||
}
|
||
|
||
static void
|
||
textbuffer_notify_selection (GObject *object, GParamSpec *pspec, GtkWidget *button)
|
||
{
|
||
const gchar *id;
|
||
gboolean has_selection;
|
||
|
||
id = gtk_buildable_get_name (GTK_BUILDABLE (button));
|
||
has_selection = gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (object));
|
||
|
||
if (strcmp (id, "cutbutton") == 0 ||
|
||
strcmp (id, "copybutton") == 0 ||
|
||
strcmp (id, "deletebutton") == 0)
|
||
gtk_widget_set_sensitive (button, has_selection);
|
||
}
|
||
|
||
static gboolean
|
||
osd_frame_pressed (GtkGestureClick *gesture,
|
||
int press,
|
||
double x,
|
||
double y,
|
||
gpointer data)
|
||
{
|
||
GtkWidget *frame = data;
|
||
GtkWidget *osd;
|
||
gboolean visible;
|
||
|
||
osd = g_object_get_data (G_OBJECT (frame), "osd");
|
||
visible = gtk_widget_get_visible (osd);
|
||
gtk_widget_set_visible (osd, !visible);
|
||
|
||
return GDK_EVENT_STOP;
|
||
}
|
||
|
||
static gboolean
|
||
page_combo_separator_func (GtkTreeModel *model,
|
||
GtkTreeIter *iter,
|
||
gpointer data)
|
||
{
|
||
gchar *text;
|
||
gboolean res;
|
||
|
||
gtk_tree_model_get (model, iter, 0, &text, -1);
|
||
res = g_strcmp0 (text, "-") == 0;
|
||
g_free (text);
|
||
|
||
return res;
|
||
}
|
||
|
||
static void
|
||
toggle_format (GSimpleAction *action,
|
||
GVariant *value,
|
||
gpointer user_data)
|
||
{
|
||
GtkTextView *text_view = user_data;
|
||
GtkTextIter start, end;
|
||
const char *name;
|
||
|
||
name = g_action_get_name (G_ACTION (action));
|
||
|
||
g_simple_action_set_state (action, value);
|
||
|
||
gtk_text_buffer_get_selection_bounds (gtk_text_view_get_buffer (text_view), &start, &end);
|
||
if (g_variant_get_boolean (value))
|
||
gtk_text_buffer_apply_tag_by_name (gtk_text_view_get_buffer (text_view), name, &start, &end);
|
||
else
|
||
gtk_text_buffer_remove_tag_by_name (gtk_text_view_get_buffer (text_view), name, &start, &end);
|
||
}
|
||
|
||
static GActionGroup *actions;
|
||
|
||
static void
|
||
text_changed (GtkTextBuffer *buffer)
|
||
{
|
||
GAction *bold;
|
||
GAction *italic;
|
||
GAction *underline;
|
||
GtkTextIter iter;
|
||
GtkTextTagTable *tags;
|
||
GtkTextTag *bold_tag, *italic_tag, *underline_tag;
|
||
gboolean all_bold, all_italic, all_underline;
|
||
GtkTextIter start, end;
|
||
gboolean has_selection;
|
||
|
||
bold = g_action_map_lookup_action (G_ACTION_MAP (actions), "bold");
|
||
italic = g_action_map_lookup_action (G_ACTION_MAP (actions), "italic");
|
||
underline = g_action_map_lookup_action (G_ACTION_MAP (actions), "underline");
|
||
|
||
has_selection = gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (bold), has_selection);
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (italic), has_selection);
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (underline), has_selection);
|
||
if (!has_selection)
|
||
return;
|
||
|
||
tags = gtk_text_buffer_get_tag_table (buffer);
|
||
bold_tag = gtk_text_tag_table_lookup (tags, "bold");
|
||
italic_tag = gtk_text_tag_table_lookup (tags, "italic");
|
||
underline_tag = gtk_text_tag_table_lookup (tags, "underline");
|
||
all_bold = TRUE;
|
||
all_italic = TRUE;
|
||
all_underline = TRUE;
|
||
gtk_text_iter_assign (&iter, &start);
|
||
while (!gtk_text_iter_equal (&iter, &end))
|
||
{
|
||
all_bold &= gtk_text_iter_has_tag (&iter, bold_tag);
|
||
all_italic &= gtk_text_iter_has_tag (&iter, italic_tag);
|
||
all_underline &= gtk_text_iter_has_tag (&iter, underline_tag);
|
||
gtk_text_iter_forward_char (&iter);
|
||
}
|
||
|
||
g_simple_action_set_state (G_SIMPLE_ACTION (bold), g_variant_new_boolean (all_bold));
|
||
g_simple_action_set_state (G_SIMPLE_ACTION (italic), g_variant_new_boolean (all_italic));
|
||
g_simple_action_set_state (G_SIMPLE_ACTION (underline), g_variant_new_boolean (all_underline));
|
||
}
|
||
|
||
static void
|
||
text_view_add_to_context_menu (GtkTextView *text_view)
|
||
{
|
||
GMenu *menu;
|
||
GActionEntry entries[] = {
|
||
{ "bold", NULL, NULL, "false", toggle_format },
|
||
{ "italic", NULL, NULL, "false", toggle_format },
|
||
{ "underline", NULL, NULL, "false", toggle_format },
|
||
};
|
||
GMenuItem *item;
|
||
GAction *action;
|
||
|
||
actions = G_ACTION_GROUP (g_simple_action_group_new ());
|
||
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), text_view);
|
||
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "bold");
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "italic");
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "underline");
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
|
||
|
||
gtk_widget_insert_action_group (GTK_WIDGET (text_view), "format", G_ACTION_GROUP (actions));
|
||
|
||
menu = g_menu_new ();
|
||
item = g_menu_item_new (_("Bold"), "format.bold");
|
||
g_menu_item_set_attribute (item, "touch-icon", "s", "format-text-bold-symbolic");
|
||
g_menu_append_item (G_MENU (menu), item);
|
||
g_object_unref (item);
|
||
item = g_menu_item_new (_("Italics"), "format.italic");
|
||
g_menu_item_set_attribute (item, "touch-icon", "s", "format-text-italic-symbolic");
|
||
g_menu_append_item (G_MENU (menu), item);
|
||
g_object_unref (item);
|
||
item = g_menu_item_new (_("Underline"), "format.underline");
|
||
g_menu_item_set_attribute (item, "touch-icon", "s", "format-text-underline-symbolic");
|
||
g_menu_append_item (G_MENU (menu), item);
|
||
g_object_unref (item);
|
||
|
||
gtk_text_view_set_extra_menu (text_view, G_MENU_MODEL (menu));
|
||
g_object_unref (menu);
|
||
|
||
g_signal_connect (gtk_text_view_get_buffer (text_view), "changed", G_CALLBACK (text_changed), NULL);
|
||
g_signal_connect (gtk_text_view_get_buffer (text_view), "mark-set", G_CALLBACK (text_changed), NULL);
|
||
}
|
||
|
||
static void
|
||
open_popover_text_changed (GtkEntry *entry, GParamSpec *pspec, GtkWidget *button)
|
||
{
|
||
const gchar *text;
|
||
|
||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||
gtk_widget_set_sensitive (button, strlen (text) > 0);
|
||
}
|
||
|
||
static gboolean
|
||
show_page_again (gpointer data)
|
||
{
|
||
gtk_widget_show (GTK_WIDGET (data));
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
|
||
static void
|
||
tab_close_cb (GtkWidget *page)
|
||
{
|
||
gtk_widget_hide (page);
|
||
g_timeout_add (2500, show_page_again, page);
|
||
}
|
||
|
||
typedef struct _GTestPermission GTestPermission;
|
||
typedef struct _GTestPermissionClass GTestPermissionClass;
|
||
|
||
struct _GTestPermission
|
||
{
|
||
GPermission parent;
|
||
};
|
||
|
||
struct _GTestPermissionClass
|
||
{
|
||
GPermissionClass parent_class;
|
||
};
|
||
|
||
static GType g_test_permission_get_type (void);
|
||
G_DEFINE_TYPE (GTestPermission, g_test_permission, G_TYPE_PERMISSION)
|
||
|
||
static void
|
||
g_test_permission_init (GTestPermission *test)
|
||
{
|
||
g_permission_impl_update (G_PERMISSION (test), TRUE, TRUE, TRUE);
|
||
}
|
||
|
||
static gboolean
|
||
update_allowed (GPermission *permission,
|
||
gboolean allowed)
|
||
{
|
||
g_permission_impl_update (permission, allowed, TRUE, TRUE);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
acquire (GPermission *permission,
|
||
GCancellable *cancellable,
|
||
GError **error)
|
||
{
|
||
return update_allowed (permission, TRUE);
|
||
}
|
||
|
||
static void
|
||
acquire_async (GPermission *permission,
|
||
GCancellable *cancellable,
|
||
GAsyncReadyCallback callback,
|
||
gpointer user_data)
|
||
{
|
||
GTask *task;
|
||
|
||
task = g_task_new ((GObject*)permission, NULL, callback, user_data);
|
||
g_task_return_boolean (task, update_allowed (permission, TRUE));
|
||
g_object_unref (task);
|
||
}
|
||
|
||
static gboolean
|
||
acquire_finish (GPermission *permission,
|
||
GAsyncResult *res,
|
||
GError **error)
|
||
{
|
||
return g_task_propagate_boolean (G_TASK (res), error);
|
||
}
|
||
|
||
static gboolean
|
||
release (GPermission *permission,
|
||
GCancellable *cancellable,
|
||
GError **error)
|
||
{
|
||
return update_allowed (permission, FALSE);
|
||
}
|
||
|
||
static void
|
||
release_async (GPermission *permission,
|
||
GCancellable *cancellable,
|
||
GAsyncReadyCallback callback,
|
||
gpointer user_data)
|
||
{
|
||
GTask *task;
|
||
|
||
task = g_task_new ((GObject*)permission, NULL, callback, user_data);
|
||
g_task_return_boolean (task, update_allowed (permission, FALSE));
|
||
g_object_unref (task);
|
||
}
|
||
|
||
static gboolean
|
||
release_finish (GPermission *permission,
|
||
GAsyncResult *result,
|
||
GError **error)
|
||
{
|
||
return g_task_propagate_boolean (G_TASK (result), error);
|
||
}
|
||
|
||
static void
|
||
g_test_permission_class_init (GTestPermissionClass *class)
|
||
{
|
||
GPermissionClass *permission_class = G_PERMISSION_CLASS (class);
|
||
|
||
permission_class->acquire = acquire;
|
||
permission_class->acquire_async = acquire_async;
|
||
permission_class->acquire_finish = acquire_finish;
|
||
|
||
permission_class->release = release;
|
||
permission_class->release_async = release_async;
|
||
permission_class->release_finish = release_finish;
|
||
}
|
||
|
||
static void
|
||
update_buttons (GtkWidget *iv, GtkIconSize size)
|
||
{
|
||
GtkWidget *button;
|
||
|
||
button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "increase_button"));
|
||
gtk_widget_set_sensitive (button, size != GTK_ICON_SIZE_LARGE);
|
||
button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "decrease_button"));
|
||
gtk_widget_set_sensitive (button, size != GTK_ICON_SIZE_NORMAL);
|
||
button = GTK_WIDGET (g_object_get_data (G_OBJECT (iv), "reset_button"));
|
||
gtk_widget_set_sensitive (button, size != GTK_ICON_SIZE_INHERIT);
|
||
}
|
||
|
||
static void
|
||
increase_icon_size (GtkWidget *iv)
|
||
{
|
||
GList *cells;
|
||
GtkCellRendererPixbuf *cell;
|
||
|
||
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv));
|
||
cell = cells->data;
|
||
g_list_free (cells);
|
||
|
||
g_object_set (cell, "icon-size", GTK_ICON_SIZE_LARGE, NULL);
|
||
|
||
update_buttons (iv, GTK_ICON_SIZE_LARGE);
|
||
|
||
gtk_widget_queue_resize (iv);
|
||
}
|
||
|
||
static void
|
||
decrease_icon_size (GtkWidget *iv)
|
||
{
|
||
GList *cells;
|
||
GtkCellRendererPixbuf *cell;
|
||
|
||
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv));
|
||
cell = cells->data;
|
||
g_list_free (cells);
|
||
|
||
g_object_set (cell, "icon-size", GTK_ICON_SIZE_NORMAL, NULL);
|
||
|
||
update_buttons (iv, GTK_ICON_SIZE_NORMAL);
|
||
|
||
gtk_widget_queue_resize (iv);
|
||
}
|
||
|
||
static void
|
||
reset_icon_size (GtkWidget *iv)
|
||
{
|
||
GList *cells;
|
||
GtkCellRendererPixbuf *cell;
|
||
|
||
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (iv));
|
||
cell = cells->data;
|
||
g_list_free (cells);
|
||
|
||
g_object_set (cell, "icon-size", GTK_ICON_SIZE_INHERIT, NULL);
|
||
|
||
update_buttons (iv, GTK_ICON_SIZE_INHERIT);
|
||
|
||
gtk_widget_queue_resize (iv);
|
||
}
|
||
|
||
static char *
|
||
scale_format_value_blank (GtkScale *scale, double value, gpointer user_data)
|
||
{
|
||
return g_strdup (" ");
|
||
}
|
||
|
||
static char *
|
||
scale_format_value (GtkScale *scale, double value, gpointer user_data)
|
||
{
|
||
return g_strdup_printf ("%0.*f", 1, value);
|
||
}
|
||
|
||
static void
|
||
adjustment3_value_changed (GtkAdjustment *adj, GtkProgressBar *pbar)
|
||
{
|
||
double fraction;
|
||
|
||
fraction = gtk_adjustment_get_value (adj) / (gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj));
|
||
|
||
gtk_progress_bar_set_fraction (pbar, fraction);
|
||
}
|
||
|
||
static void
|
||
clicked_cb (GtkGesture *gesture,
|
||
int n_press,
|
||
double x,
|
||
double y,
|
||
GtkPopover *popover)
|
||
{
|
||
GdkRectangle rect;
|
||
|
||
rect.x = x;
|
||
rect.y = y;
|
||
rect.width = 1;
|
||
rect.height = 1;
|
||
gtk_popover_set_pointing_to (popover, &rect);
|
||
gtk_popover_popup (popover);
|
||
}
|
||
|
||
static void
|
||
set_up_context_popover (GtkWidget *widget,
|
||
GMenuModel *model)
|
||
{
|
||
GtkWidget *popover = gtk_popover_menu_new_from_model (model);
|
||
GtkGesture *gesture;
|
||
|
||
gtk_widget_set_parent (popover, widget);
|
||
gtk_popover_set_has_arrow (GTK_POPOVER (popover), FALSE);
|
||
gesture = gtk_gesture_click_new ();
|
||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
|
||
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked_cb), popover);
|
||
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
|
||
}
|
||
|
||
static void
|
||
activate (GApplication *app)
|
||
{
|
||
GtkBuilder *builder;
|
||
GtkBuilderScope *scope;
|
||
GtkWindow *window;
|
||
GtkWidget *widget;
|
||
GtkWidget *widget2;
|
||
GtkWidget *widget3;
|
||
GtkWidget *widget4;
|
||
GtkWidget *stack;
|
||
GtkWidget *dialog;
|
||
GtkAdjustment *adj;
|
||
GtkCssProvider *provider;
|
||
GMenuModel *model;
|
||
static GActionEntry win_entries[] = {
|
||
{ "dark", NULL, NULL, "false", change_dark_state },
|
||
{ "theme", NULL, "s", "'current'", change_theme_state },
|
||
{ "transition", NULL, NULL, "true", change_transition_state },
|
||
{ "search", activate_search, NULL, NULL, NULL },
|
||
{ "delete", activate_delete, NULL, NULL, NULL },
|
||
{ "busy", get_busy, NULL, NULL, NULL },
|
||
{ "background", activate_background, NULL, NULL, NULL },
|
||
{ "open", activate_open, NULL, NULL, NULL },
|
||
{ "record", activate_record, NULL, NULL, NULL },
|
||
{ "lock", activate_lock, NULL, NULL, NULL },
|
||
{ "print", activate_print, NULL, NULL, NULL },
|
||
};
|
||
struct {
|
||
const gchar *action_and_target;
|
||
const gchar *accelerators[2];
|
||
} accels[] = {
|
||
{ "app.about", { "F1", NULL } },
|
||
{ "app.quit", { "<Control>q", NULL } },
|
||
{ "app.open-in", { "<Control>n", NULL } },
|
||
{ "win.dark", { "<Control>d", NULL } },
|
||
{ "win.search", { "<Control>s", NULL } },
|
||
{ "win.background", { "<Control>b", NULL } },
|
||
{ "win.open", { "<Control>o", NULL } },
|
||
{ "win.record", { "<Control>r", NULL } },
|
||
{ "win.lock", { "<Control>l", NULL } },
|
||
};
|
||
struct {
|
||
const gchar *action_and_target;
|
||
const gchar *accelerators[2];
|
||
} late_accels[] = {
|
||
{ "app.cut", { "<Control>x", NULL } },
|
||
{ "app.copy", { "<Control>c", NULL } },
|
||
{ "app.paste", { "<Control>v", NULL } },
|
||
{ "win.delete", { "Delete", NULL } },
|
||
};
|
||
gint i;
|
||
GPermission *permission;
|
||
GAction *action;
|
||
GError *error = NULL;
|
||
GtkEventController *controller;
|
||
|
||
g_type_ensure (my_text_view_get_type ());
|
||
|
||
provider = gtk_css_provider_new ();
|
||
gtk_css_provider_load_from_resource (provider, "/org/gtk/WidgetFactory4/widget-factory.css");
|
||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||
GTK_STYLE_PROVIDER (provider),
|
||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||
g_object_unref (provider);
|
||
|
||
builder = gtk_builder_new ();
|
||
scope = gtk_builder_cscope_new ();
|
||
gtk_builder_cscope_add_callback_symbols (GTK_BUILDER_CSCOPE (scope),
|
||
"on_entry_icon_release", (GCallback)on_entry_icon_release,
|
||
"on_scale_button_value_changed", (GCallback)on_scale_button_value_changed,
|
||
"on_record_button_toggled", (GCallback)on_record_button_toggled,
|
||
"on_page_combo_changed", (GCallback)on_page_combo_changed,
|
||
"on_range_from_changed", (GCallback)on_range_from_changed,
|
||
"on_range_to_changed", (GCallback)on_range_to_changed,
|
||
"tab_close_cb", (GCallback)tab_close_cb,
|
||
"increase_icon_size", (GCallback)increase_icon_size,
|
||
"decrease_icon_size", (GCallback)decrease_icon_size,
|
||
"reset_icon_size", (GCallback)reset_icon_size,
|
||
"osd_frame_pressed", (GCallback)osd_frame_pressed,
|
||
NULL);
|
||
gtk_builder_set_scope (builder, scope);
|
||
g_object_unref (scope);
|
||
if (!gtk_builder_add_from_resource (builder, "/org/gtk/WidgetFactory4/widget-factory.ui", &error))
|
||
{
|
||
g_critical ("%s", error->message);
|
||
g_clear_error (&error);
|
||
}
|
||
|
||
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
|
||
gtk_application_add_window (GTK_APPLICATION (app), window);
|
||
g_action_map_add_action_entries (G_ACTION_MAP (window),
|
||
win_entries, G_N_ELEMENTS (win_entries),
|
||
window);
|
||
|
||
controller = gtk_shortcut_controller_new ();
|
||
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_BUBBLE);
|
||
|
||
for (i = 0; i < G_N_ELEMENTS (late_accels); i++)
|
||
{
|
||
guint key;
|
||
GdkModifierType mods;
|
||
GtkShortcutTrigger *trigger;
|
||
GtkShortcutAction *ac;
|
||
|
||
gtk_accelerator_parse (late_accels[i].accelerators[0], &key, &mods);
|
||
trigger = gtk_keyval_trigger_new (key, mods);
|
||
ac = gtk_named_action_new (late_accels[i].action_and_target);
|
||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||
gtk_shortcut_new (trigger, ac));
|
||
}
|
||
gtk_widget_add_controller (GTK_WIDGET (window), controller);
|
||
|
||
for (i = 0; i < G_N_ELEMENTS (accels); i++)
|
||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), accels[i].action_and_target, accels[i].accelerators);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "statusbar");
|
||
gtk_statusbar_push (GTK_STATUSBAR (widget), 0, "All systems are operating normally.");
|
||
action = G_ACTION (g_property_action_new ("statusbar", widget, "visible"));
|
||
g_action_map_add_action (G_ACTION_MAP (window), action);
|
||
g_object_unref (G_OBJECT (action));
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbar");
|
||
action = G_ACTION (g_property_action_new ("toolbar", widget, "visible"));
|
||
g_action_map_add_action (G_ACTION_MAP (window), action);
|
||
g_object_unref (G_OBJECT (action));
|
||
|
||
adj = (GtkAdjustment *)gtk_builder_get_object (builder, "adjustment1");
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "progressbar3");
|
||
g_signal_connect (adj, "value-changed", G_CALLBACK (update_pulse_time), widget);
|
||
update_pulse_time (adj, widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "entry1");
|
||
g_signal_connect (adj, "value-changed", G_CALLBACK (update_pulse_time), widget);
|
||
update_pulse_time (adj, widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "page2reset");
|
||
adj = (GtkAdjustment *) gtk_builder_get_object (builder, "adjustment2");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (spin_value_reset), adj);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "page2dismiss");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (dismiss), NULL);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "page2note");
|
||
adj = (GtkAdjustment *) gtk_builder_get_object (builder, "adjustment2");
|
||
g_signal_connect (adj, "value-changed", G_CALLBACK (spin_value_changed), widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "listbox");
|
||
g_signal_connect (widget, "row-activated", G_CALLBACK (row_activated), NULL);
|
||
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow1switch");
|
||
g_signal_connect (widget2, "notify::active", G_CALLBACK (toggle_selection_mode), widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow3");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow3image");
|
||
g_object_set_data (G_OBJECT (widget), "image", widget2);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow4");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog");
|
||
g_object_set_data (G_OBJECT (widget), "dialog", widget2);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "listboxrow5button");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog");
|
||
g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_window_present), widget2);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbar");
|
||
g_object_set_data (G_OBJECT (window), "toolbar", widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "searchbar");
|
||
g_object_set_data (G_OBJECT (window), "searchbar", widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "infobar");
|
||
g_signal_connect (widget, "response", G_CALLBACK (info_bar_response), NULL);
|
||
g_object_set_data (G_OBJECT (window), "infobar", widget);
|
||
|
||
dialog = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog");
|
||
g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog_button");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
||
|
||
dialog = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog");
|
||
g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog_button");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "act_action_dialog");
|
||
stack = (GtkWidget *)gtk_builder_get_object (builder, "toplevel_stack");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (action_dialog_button_clicked), stack);
|
||
g_signal_connect (stack, "notify::visible-child-name", G_CALLBACK (page_changed_cb), NULL);
|
||
page_changed_cb (stack, NULL, NULL);
|
||
|
||
page_stack = stack;
|
||
|
||
dialog = (GtkWidget *)gtk_builder_get_object (builder, "preference_dialog");
|
||
g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "preference_dialog_button");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "circular_button");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
||
|
||
dialog = (GtkWidget *)gtk_builder_get_object (builder, "selection_dialog");
|
||
g_object_set_data (G_OBJECT (window), "selection_dialog", dialog);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "text3");
|
||
g_signal_connect (dialog, "response", G_CALLBACK (close_selection_dialog), widget);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "selection_dialog_button");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
||
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "selection_flowbox");
|
||
g_object_set_data (G_OBJECT (window), "selection_flowbox", widget2);
|
||
g_signal_connect_swapped (widget, "clicked", G_CALLBACK (populate_flowbox), widget2);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "charletree");
|
||
populate_model ((GtkTreeStore *)gtk_tree_view_get_model (GTK_TREE_VIEW (widget)));
|
||
gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (widget), row_separator_func, NULL, NULL);
|
||
gtk_tree_view_expand_all (GTK_TREE_VIEW (widget));
|
||
|
||
widget = GTK_WIDGET (gtk_builder_get_object (builder, "munsell"));
|
||
widget2 = GTK_WIDGET (gtk_builder_get_object (builder, "cchooser"));
|
||
|
||
populate_colors (widget, widget2);
|
||
g_signal_connect (widget2, "notify::rgba", G_CALLBACK (rgba_changed), widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "page_combo");
|
||
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (widget), page_combo_separator_func, NULL, NULL);
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "range_from_spin");
|
||
widget3 = (GtkWidget *)gtk_builder_get_object (builder, "range_to_spin");
|
||
widget4 = (GtkWidget *)gtk_builder_get_object (builder, "print_button");
|
||
g_object_set_data (G_OBJECT (widget), "range_from_spin", widget2);
|
||
g_object_set_data (G_OBJECT (widget3), "range_from_spin", widget2);
|
||
g_object_set_data (G_OBJECT (widget), "range_to_spin", widget3);
|
||
g_object_set_data (G_OBJECT (widget2), "range_to_spin", widget3);
|
||
g_object_set_data (G_OBJECT (widget), "print_button", widget4);
|
||
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "tooltextview");
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton1");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton2");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton3");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbutton4");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_insert), widget2);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "cutbutton");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
|
||
g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection",
|
||
G_CALLBACK (textbuffer_notify_selection), widget);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "copybutton");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
|
||
g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection",
|
||
G_CALLBACK (textbuffer_notify_selection), widget);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "deletebutton");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
|
||
g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget2)), "notify::has-selection",
|
||
G_CALLBACK (textbuffer_notify_selection), widget);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "pastebutton");
|
||
g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
|
||
g_signal_connect_object (gtk_widget_get_clipboard (widget2), "notify::formats",
|
||
G_CALLBACK (clipboard_formats_notify), widget, 0);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "osd_frame");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "totem_like_osd");
|
||
g_object_set_data (G_OBJECT (widget), "osd", widget2);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "textview1");
|
||
text_view_add_to_context_menu (GTK_TEXT_VIEW (widget));
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "open_popover");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "open_popover_entry");
|
||
widget3 = (GtkWidget *)gtk_builder_get_object (builder, "open_popover_button");
|
||
gtk_popover_set_default_widget (GTK_POPOVER (widget), widget3);
|
||
g_signal_connect (widget2, "notify::text", G_CALLBACK (open_popover_text_changed), widget3);
|
||
g_signal_connect_swapped (widget3, "clicked", G_CALLBACK (gtk_widget_hide), widget);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "open_menubutton");
|
||
g_object_set_data (G_OBJECT (window), "open_menubutton", widget);
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "record_button");
|
||
g_object_set_data (G_OBJECT (window), "record_button", widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "lockbox");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "lockbutton");
|
||
g_object_set_data (G_OBJECT (window), "lockbutton", widget2);
|
||
permission = g_object_new (g_test_permission_get_type (), NULL);
|
||
g_object_bind_property (permission, "allowed",
|
||
widget, "sensitive",
|
||
G_BINDING_SYNC_CREATE);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (window), "open");
|
||
g_object_bind_property (permission, "allowed",
|
||
action, "enabled",
|
||
G_BINDING_SYNC_CREATE);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (window), "record");
|
||
g_object_bind_property (permission, "allowed",
|
||
action, "enabled",
|
||
G_BINDING_SYNC_CREATE);
|
||
gtk_lock_button_set_permission (GTK_LOCK_BUTTON (widget2), permission);
|
||
g_object_unref (permission);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "iconview1");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "increase_button");
|
||
g_object_set_data (G_OBJECT (widget), "increase_button", widget2);
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "decrease_button");
|
||
g_object_set_data (G_OBJECT (widget), "decrease_button", widget2);
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "reset_button");
|
||
g_object_set_data (G_OBJECT (widget), "reset_button", widget2);
|
||
reset_icon_size (widget);
|
||
|
||
adj = (GtkAdjustment *)gtk_builder_get_object (builder, "adjustment3");
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "progressbar1");
|
||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "progressbar2");
|
||
g_signal_connect (adj, "value-changed", G_CALLBACK (adjustment3_value_changed), widget);
|
||
g_signal_connect (adj, "value-changed", G_CALLBACK (adjustment3_value_changed), widget2);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "extra_info_entry");
|
||
g_timeout_add (100, (GSourceFunc)pulse_it, widget);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "scale3");
|
||
gtk_scale_set_format_value_func (GTK_SCALE (widget), scale_format_value, NULL, NULL);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "scale4");
|
||
gtk_scale_set_format_value_func (GTK_SCALE (widget), scale_format_value_blank, NULL, NULL);
|
||
|
||
widget = (GtkWidget *)gtk_builder_get_object (builder, "box_for_context");
|
||
model = (GMenuModel *)gtk_builder_get_object (builder, "new_style_context_menu_model");
|
||
set_up_context_popover (widget, model);
|
||
|
||
gtk_widget_show (GTK_WIDGET (window));
|
||
|
||
g_object_unref (builder);
|
||
}
|
||
|
||
static void
|
||
print_version (void)
|
||
{
|
||
g_print ("gtk4-widget-factory %d.%d.%d\n",
|
||
gtk_get_major_version (),
|
||
gtk_get_minor_version (),
|
||
gtk_get_micro_version ());
|
||
}
|
||
|
||
static int
|
||
local_options (GApplication *app,
|
||
GVariantDict *options,
|
||
gpointer data)
|
||
{
|
||
gboolean version = FALSE;
|
||
|
||
g_variant_dict_lookup (options, "version", "b", &version);
|
||
|
||
if (version)
|
||
{
|
||
print_version ();
|
||
return 0;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
static void
|
||
activate_action (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
g_print ("Activate action %s\n", g_action_get_name (G_ACTION (action)));
|
||
}
|
||
|
||
static void
|
||
select_action (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
g_print ("Select action %s value %s\n",
|
||
g_action_get_name (G_ACTION (action)),
|
||
g_variant_get_string (parameter, NULL));
|
||
|
||
g_simple_action_set_state (action, parameter);
|
||
}
|
||
|
||
static void
|
||
toggle_action (GSimpleAction *action,
|
||
GVariant *parameter,
|
||
gpointer user_data)
|
||
{
|
||
GVariant *state = g_action_get_state (G_ACTION (action));
|
||
|
||
g_print ("Toggle action %s to %s\n",
|
||
g_action_get_name (G_ACTION (action)),
|
||
g_variant_get_boolean (state) ? "false" : "true");
|
||
|
||
g_simple_action_set_state (action,
|
||
g_variant_new_boolean (!g_variant_get_boolean (state)));
|
||
}
|
||
|
||
static gboolean
|
||
quit_timeout (gpointer data)
|
||
{
|
||
exit (0);
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
|
||
int
|
||
main (int argc, char *argv[])
|
||
{
|
||
GtkApplication *app;
|
||
GAction *action;
|
||
static GActionEntry app_entries[] = {
|
||
{ "about", activate_about, NULL, NULL, NULL },
|
||
{ "quit", activate_quit, NULL, NULL, NULL },
|
||
{ "inspector", activate_inspector, NULL, NULL, NULL },
|
||
{ "main", NULL, "s", "'steak'", NULL },
|
||
{ "wine", NULL, NULL, "false", NULL },
|
||
{ "beer", NULL, NULL, "false", NULL },
|
||
{ "water", NULL, NULL, "true", NULL },
|
||
{ "dessert", NULL, "s", "'bars'", NULL },
|
||
{ "pay", NULL, "s", NULL, NULL },
|
||
{ "share", activate_action, NULL, NULL, NULL },
|
||
{ "labels", activate_action, NULL, NULL, NULL },
|
||
{ "new", activate_action, NULL, NULL, NULL },
|
||
{ "open", activate_action, NULL, NULL, NULL },
|
||
{ "open-in", activate_action, NULL, NULL, NULL },
|
||
{ "open-tab", activate_action, NULL, NULL, NULL },
|
||
{ "open-window", activate_action, NULL, NULL, NULL },
|
||
{ "save", activate_action, NULL, NULL, NULL },
|
||
{ "save-as", activate_action, NULL, NULL, NULL },
|
||
{ "cut", activate_action, NULL, NULL, NULL },
|
||
{ "copy", activate_action, NULL, NULL, NULL },
|
||
{ "paste", activate_action, NULL, NULL, NULL },
|
||
{ "pin", toggle_action, NULL, "true", NULL },
|
||
{ "size", select_action, "s", "'medium'", NULL },
|
||
{ "berk", toggle_action, NULL, "true", NULL },
|
||
{ "broni", toggle_action, NULL, "true", NULL },
|
||
{ "drutt", toggle_action, NULL, "true", NULL },
|
||
{ "upstairs", toggle_action, NULL, "true", NULL },
|
||
{ "option-a", activate_action, NULL, NULL, NULL },
|
||
{ "option-b", activate_action, NULL, NULL, NULL },
|
||
{ "option-c", activate_action, NULL, NULL, NULL },
|
||
{ "option-d", activate_action, NULL, NULL, NULL },
|
||
{ "check-on", NULL, NULL, "true", NULL },
|
||
{ "check-off", NULL, NULL, "false", NULL },
|
||
{ "radio-x", NULL, "s", "'x'", NULL },
|
||
{ "check-on-disabled", NULL, NULL, "true", NULL },
|
||
{ "check-off-disabled", NULL, NULL, "false", NULL },
|
||
{ "radio-x-disabled", NULL, "s", "'x'", NULL },
|
||
};
|
||
gint status;
|
||
|
||
app = gtk_application_new ("org.gtk.WidgetFactory4", G_APPLICATION_NON_UNIQUE);
|
||
|
||
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||
app_entries, G_N_ELEMENTS (app_entries),
|
||
app);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (app), "wine");
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (app), "check-on-disabled");
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (app), "check-off-disabled");
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
|
||
action = g_action_map_lookup_action (G_ACTION_MAP (app), "radio-x-disabled");
|
||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
|
||
|
||
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
|
||
|
||
g_application_add_main_option (G_APPLICATION (app), "version", 0, 0, G_OPTION_ARG_NONE, "Show program version", NULL);
|
||
|
||
if (g_getenv ("GTK_DEBUG_AUTO_QUIT"))
|
||
g_timeout_add (500, quit_timeout, NULL);
|
||
|
||
g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
|
||
status = g_application_run (G_APPLICATION (app), argc, argv);
|
||
g_object_unref (app);
|
||
|
||
return status;
|
||
}
|