diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:45:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:45:20 +0000 |
commit | ae1c76ff830d146d41e88d6fba724c0a54bce868 (patch) | |
tree | 3c354bec95af07be35fc71a4b738268496f1a1c4 /shell/cc-window.c | |
parent | Initial commit. (diff) | |
download | gnome-control-center-ae1c76ff830d146d41e88d6fba724c0a54bce868.tar.xz gnome-control-center-ae1c76ff830d146d41e88d6fba724c0a54bce868.zip |
Adding upstream version 1:43.6.upstream/1%43.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'shell/cc-window.c')
-rw-r--r-- | shell/cc-window.c | 894 |
1 files changed, 894 insertions, 0 deletions
diff --git a/shell/cc-window.c b/shell/cc-window.c new file mode 100644 index 0000000..15d7124 --- /dev/null +++ b/shell/cc-window.c @@ -0,0 +1,894 @@ +/* + * Copyright (c) 2009, 2010 Intel, Inc. + * Copyright (c) 2010 Red Hat, Inc. + * Copyright (c) 2016 Endless, Inc. + * + * The Control Center is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The Control Center 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: Thomas Wood <thos@gnome.org> + */ + +#define G_LOG_DOMAIN "cc-window" + +#include <config.h> + +#include "cc-debug.h" +#include "cc-window.h" + +#include <glib/gi18n.h> +#include <gio/gio.h> +#include <gio/gdesktopappinfo.h> +#include <gtk/gtk.h> +#include <string.h> +#include <time.h> + +#include "cc-application.h" +#include "cc-panel-private.h" +#include "cc-shell.h" +#include "cc-shell-model.h" +#include "cc-panel-list.h" +#include "cc-panel-loader.h" +#include "cc-util.h" + +#define MOUSE_BACK_BUTTON 8 + +#define DEFAULT_WINDOW_ICON_NAME "gnome-control-center" + +struct _CcWindow +{ + AdwApplicationWindow parent; + + GtkMessageDialog *development_warning_dialog; + AdwHeaderBar *header; + AdwLeaflet *main_leaflet; + CcPanelList *panel_list; + GtkButton *previous_button; + GtkSearchBar *search_bar; + GtkToggleButton *search_button; + GtkSearchEntry *search_entry; + GtkBox *sidebar_box; + AdwWindowTitle *sidebar_title_widget; + GtkStack *stack; + + GtkWidget *old_panel; + GtkWidget *current_panel; + char *current_panel_id; + GQueue *previous_panels; + + GtkWidget *custom_titlebar; + + CcShellModel *store; + + CcPanel *active_panel; + GSettings *settings; + + gboolean folded; + + CcPanelListView previous_list_view; +}; + +static void cc_shell_iface_init (CcShellInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (CcWindow, cc_window, ADW_TYPE_APPLICATION_WINDOW, + G_IMPLEMENT_INTERFACE (CC_TYPE_SHELL, cc_shell_iface_init)) + +enum +{ + PROP_0, + PROP_ACTIVE_PANEL, + PROP_MODEL, + PROP_FOLDED, +}; + +/* Auxiliary methods */ +static void +load_window_state (CcWindow *self) +{ + gint current_width = -1; + gint current_height = -1; + gboolean maximized = FALSE; + + g_settings_get (self->settings, + "window-state", + "(iib)", + ¤t_width, + ¤t_height, + &maximized); + + if (current_width != -1 && current_height != -1) + gtk_window_set_default_size (GTK_WINDOW (self), current_width, current_height); + if (maximized) + gtk_window_maximize (GTK_WINDOW (self)); +} + +static gboolean +in_flatpak_sandbox (void) +{ + return g_strcmp0 (PROFILE, "development") == 0; +} + +static void +on_sidebar_activated_cb (CcWindow *self) +{ + adw_leaflet_navigate (self->main_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD); +} + +static gboolean +activate_panel (CcWindow *self, + const gchar *id, + GVariant *parameters, + const gchar *name, + GIcon *gicon, + CcPanelVisibility visibility) +{ + g_autoptr(GTimer) timer = NULL; + GtkWidget *sidebar_widget; + gdouble ellapsed_time; + + CC_ENTRY; + + if (!id) + CC_RETURN (FALSE); + + if (visibility == CC_PANEL_HIDDEN) + CC_RETURN (FALSE); + + timer = g_timer_new (); + + g_settings_set_string (self->settings, "last-panel", id); + + /* Begin the profile */ + g_timer_start (timer); + + if (self->current_panel) + g_signal_handlers_disconnect_by_data (self->current_panel, self); + self->current_panel = GTK_WIDGET (cc_panel_loader_load_by_name (CC_SHELL (self), id, name, parameters)); + cc_panel_set_folded (CC_PANEL (self->current_panel), adw_leaflet_get_folded (self->main_leaflet)); + cc_shell_set_active_panel (CC_SHELL (self), CC_PANEL (self->current_panel)); + + gtk_stack_add_named (self->stack, self->current_panel, id); + + /* switch to the new panel */ + gtk_stack_set_visible_child_name (self->stack, id); + + sidebar_widget = cc_panel_get_sidebar_widget (CC_PANEL (self->current_panel)); + cc_panel_list_add_sidebar_widget (self->panel_list, sidebar_widget); + /* Ensure we show the panel when the leaflet is folded and a sidebar widget's + * row is activated. + */ + g_signal_connect_object (self->current_panel, "sidebar-activated", G_CALLBACK (on_sidebar_activated_cb), self, G_CONNECT_SWAPPED); + + /* Finish profiling */ + g_timer_stop (timer); + + ellapsed_time = g_timer_elapsed (timer, NULL); + + g_debug ("Time to open panel '%s': %lfs", name, ellapsed_time); + + CC_RETURN (TRUE); +} + +static void +add_current_panel_to_history (CcWindow *self, + const char *start_id) +{ + g_return_if_fail (start_id != NULL); + + if (!self->current_panel_id || g_strcmp0 (self->current_panel_id, start_id) == 0) + return; + + g_queue_push_head (self->previous_panels, g_strdup (self->current_panel_id)); + g_debug ("Added '%s' to the previous panels", self->current_panel_id); +} + +static gboolean +find_iter_for_panel_id (CcWindow *self, + const gchar *panel_id, + GtkTreeIter *out_iter) +{ + GtkTreeIter iter; + gboolean valid; + + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->store), &iter); + + while (valid) + { + g_autofree gchar *id = NULL; + + gtk_tree_model_get (GTK_TREE_MODEL (self->store), + &iter, + COL_ID, &id, + -1); + + if (g_strcmp0 (id, panel_id) == 0) + break; + + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->store), &iter); + } + + g_assert (out_iter != NULL); + *out_iter = iter; + + return valid; +} + +static void +update_list_title (CcWindow *self) +{ + CcPanelListView view; + GtkTreeIter iter; + g_autofree gchar *title = NULL; + + CC_ENTRY; + + view = cc_panel_list_get_view (self->panel_list); + title = NULL; + + switch (view) + { + case CC_PANEL_LIST_PRIVACY: + title = g_strdup (_("Privacy")); + break; + + case CC_PANEL_LIST_MAIN: + title = g_strdup (_("Settings")); + break; + + case CC_PANEL_LIST_WIDGET: + find_iter_for_panel_id (self, self->current_panel_id, &iter); + gtk_tree_model_get (GTK_TREE_MODEL (self->store), + &iter, + COL_NAME, &title, + -1); + break; + + case CC_PANEL_LIST_SEARCH: + title = NULL; + break; + } + + if (title) + adw_window_title_set_title (self->sidebar_title_widget, title); + + CC_EXIT; +} + +static void +on_row_changed_cb (CcWindow *self, + GtkTreePath *path, + GtkTreeIter *iter, + GtkTreeModel *model) +{ + g_autofree gchar *id = NULL; + CcPanelVisibility visibility; + + gtk_tree_model_get (model, iter, + COL_ID, &id, + COL_VISIBILITY, &visibility, + -1); + + cc_panel_list_set_panel_visibility (self->panel_list, id, visibility); +} + +static void +setup_model (CcWindow *self) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean valid; + + /* CcApplication must have a valid model at this point */ + g_assert (self->store != NULL); + + model = GTK_TREE_MODEL (self->store); + + cc_panel_loader_fill_model (self->store); + + /* Create a row for each panel */ + valid = gtk_tree_model_get_iter_first (model, &iter); + + while (valid) + { + CcPanelCategory category; + g_autoptr(GIcon) icon = NULL; + g_autofree gchar *name = NULL; + g_autofree gchar *description = NULL; + g_autofree gchar *id = NULL; + g_auto(GStrv) keywords = NULL; + CcPanelVisibility visibility; + gboolean has_sidebar; + const gchar *icon_name = NULL; + + gtk_tree_model_get (model, &iter, + COL_CATEGORY, &category, + COL_DESCRIPTION, &description, + COL_GICON, &icon, + COL_ID, &id, + COL_NAME, &name, + COL_KEYWORDS, &keywords, + COL_VISIBILITY, &visibility, + COL_HAS_SIDEBAR, &has_sidebar, + -1); + + if (G_IS_THEMED_ICON (icon)) + icon_name = g_themed_icon_get_names (G_THEMED_ICON (icon))[0]; + + cc_panel_list_add_panel (self->panel_list, + category, + id, + name, + description, + keywords, + icon_name, + visibility, + has_sidebar); + + valid = gtk_tree_model_iter_next (model, &iter); + } + + /* React to visibility changes */ + g_signal_connect_object (model, "row-changed", G_CALLBACK (on_row_changed_cb), self, G_CONNECT_SWAPPED); +} + +static void +update_headerbar_buttons (CcWindow *self) +{ + gboolean is_main_view; + + CC_ENTRY; + + is_main_view = cc_panel_list_get_view (self->panel_list) == CC_PANEL_LIST_MAIN; + + gtk_widget_set_visible (GTK_WIDGET (self->previous_button), !is_main_view); + gtk_widget_set_visible (GTK_WIDGET (self->search_button), is_main_view); + gtk_search_bar_set_key_capture_widget (self->search_bar, is_main_view ? GTK_WIDGET (self) : NULL); + + update_list_title (self); + + CC_EXIT; +} + +static gboolean +set_active_panel_from_id (CcWindow *self, + const gchar *start_id, + GVariant *parameters, + gboolean add_to_history, + gboolean force_moving_to_the_panel, + GError **error) +{ + g_autoptr(GIcon) gicon = NULL; + g_autofree gchar *name = NULL; + CcPanelVisibility visibility; + GtkTreeIter iter; + CcPanelListView view; + gboolean activated; + gboolean found; + + CC_ENTRY; + + view = cc_panel_list_get_view (self->panel_list); + + /* When loading the same panel again, just set its parameters */ + if (g_strcmp0 (self->current_panel_id, start_id) == 0) + { + g_object_set (G_OBJECT (self->current_panel), "parameters", parameters, NULL); + if (force_moving_to_the_panel || self->previous_list_view == view) + adw_leaflet_navigate (self->main_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD); + self->previous_list_view = view; + CC_RETURN (TRUE); + } + + found = find_iter_for_panel_id (self, start_id, &iter); + if (!found) + { + g_warning ("Could not find settings panel \"%s\"", start_id); + CC_RETURN (TRUE); + } + + if (self->old_panel) + gtk_stack_remove (self->stack, g_steal_pointer (&self->old_panel)); + + /* old_panel will be removed by the on_stack_transition_running_changed_cb + * callback - or, if panels changed before the transition ended, by the code + * just above. + */ + self->old_panel = self->current_panel; + if (self->old_panel) + cc_panel_deactivate (CC_PANEL (self->old_panel)); + + gtk_tree_model_get (GTK_TREE_MODEL (self->store), + &iter, + COL_NAME, &name, + COL_GICON, &gicon, + COL_VISIBILITY, &visibility, + -1); + + /* Activate the panel */ + activated = activate_panel (self, start_id, parameters, name, gicon, visibility); + + /* Failed to activate the panel for some reason, let's keep the old + * panel around instead */ + if (!activated) + { + g_debug ("Failed to activate panel"); + CC_RETURN (TRUE); + } + + if (add_to_history) + add_current_panel_to_history (self, start_id); + + if (force_moving_to_the_panel) + adw_leaflet_navigate (self->main_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD); + + g_free (self->current_panel_id); + self->current_panel_id = g_strdup (start_id); + + CC_TRACE_MSG ("Current panel id: %s", start_id); + + cc_panel_list_set_active_panel (self->panel_list, start_id); + + update_headerbar_buttons (self); + + CC_RETURN (TRUE); +} + +static void +set_active_panel (CcWindow *self, + CcPanel *panel) +{ + g_return_if_fail (CC_IS_SHELL (self)); + g_return_if_fail (panel == NULL || CC_IS_PANEL (panel)); + + if (panel != self->active_panel) + { + /* remove the old panel */ + g_clear_object (&self->active_panel); + + /* set the new panel */ + if (panel) + self->active_panel = g_object_ref (panel); + + g_object_notify (G_OBJECT (self), "active-panel"); + } +} + +static void +switch_to_previous_panel (CcWindow *self) +{ + g_autofree gchar *previous_panel_id = NULL; + + CC_ENTRY; + + if (g_queue_get_length (self->previous_panels) == 0) + CC_RETURN (); + + previous_panel_id = g_queue_pop_head (self->previous_panels); + + g_debug ("Going to previous panel (%s)", previous_panel_id); + + set_active_panel_from_id (self, previous_panel_id, NULL, FALSE, FALSE, NULL); + + CC_EXIT; +} + +/* Callbacks */ + +static void +navigate_action_cb (GtkWidget *widget, + const gchar *action_name, + GVariant *parameter) +{ + CcWindow *self = CC_WINDOW (widget); + + adw_leaflet_navigate (self->main_leaflet, g_variant_get_int32 (parameter)); +} + +static void +on_main_leaflet_folded_changed_cb (CcWindow *self) +{ + GtkSelectionMode selection_mode; + gboolean folded; + + g_assert (CC_IS_WINDOW (self)); + + folded = adw_leaflet_get_folded (self->main_leaflet); + + selection_mode = folded ? GTK_SELECTION_NONE : GTK_SELECTION_SINGLE; + cc_panel_list_set_selection_mode (self->panel_list, selection_mode); + + cc_panel_set_folded (CC_PANEL (self->current_panel), folded); +} + +static void +show_panel_cb (CcWindow *self, + const gchar *panel_id) +{ + if (!panel_id) + return; + + set_active_panel_from_id (self, panel_id, NULL, TRUE, FALSE, NULL); +} + +static void +search_entry_activate_cb (CcWindow *self) +{ + gboolean changed; + + changed = cc_panel_list_activate (self->panel_list); + + gtk_search_bar_set_search_mode (self->search_bar, !changed); +} + +static void +previous_button_clicked_cb (CcWindow *self) +{ + g_debug ("Num previous panels? %d", g_queue_get_length (self->previous_panels)); + + /* When in search, simply unset the search mode */ + if (gtk_search_bar_get_search_mode (self->search_bar)) + gtk_search_bar_set_search_mode (self->search_bar, FALSE); + else + cc_panel_list_go_previous (self->panel_list); + + update_headerbar_buttons (self); +} + +static gboolean +go_back_shortcut_cb (GtkWidget *widget, + GVariant *args, + gpointer user_data) +{ + g_debug ("Going to previous panel"); + switch_to_previous_panel (CC_WINDOW (widget)); + + return GDK_EVENT_STOP; +} + +static gboolean +search_shortcut_cb (GtkWidget *widget, + GVariant *args, + gpointer user_data) +{ + CcPanelListView view; + CcWindow *self; + gboolean search; + + self = CC_WINDOW (widget); + view = cc_panel_list_get_view (self->panel_list); + + /* The search only happens when we're in the MAIN view */ + if (view != CC_PANEL_LIST_MAIN && view != CC_PANEL_LIST_SEARCH) + return GDK_EVENT_PROPAGATE; + + search = !gtk_search_bar_get_search_mode (self->search_bar); + gtk_search_bar_set_search_mode (self->search_bar, search); + if (search) + gtk_widget_grab_focus (GTK_WIDGET (self->search_entry)); + + return GDK_EVENT_STOP; +} + +static void +on_development_warning_dialog_responded_cb (CcWindow *self) +{ + g_debug ("Disabling development build warning dialog"); + g_settings_set_boolean (self->settings, "show-development-warning", FALSE); + + gtk_widget_hide (GTK_WIDGET (self->development_warning_dialog)); +} + +static void +on_stack_transition_running_changed_cb (GtkStack *stack, + GParamSpec *pspec, + CcWindow *self) +{ + gboolean transition_running; + + CC_ENTRY; + + transition_running = gtk_stack_get_transition_running (stack); + + if (!transition_running && self->old_panel) + gtk_stack_remove (self->stack, g_steal_pointer (&self->old_panel)); + + CC_EXIT; +} + +/* CcShell implementation */ +static gboolean +cc_window_set_active_panel_from_id (CcShell *shell, + const gchar *start_id, + GVariant *parameters, + GError **error) +{ + return set_active_panel_from_id (CC_WINDOW (shell), start_id, parameters, TRUE, TRUE, error); +} + +static GtkWidget * +cc_window_get_toplevel (CcShell *self) +{ + return GTK_WIDGET (self); +} + +static void +cc_shell_iface_init (CcShellInterface *iface) +{ + iface->set_active_panel_from_id = cc_window_set_active_panel_from_id; + iface->get_toplevel = cc_window_get_toplevel; +} + +/* GtkWidget overrides */ +static void +cc_window_map (GtkWidget *widget) +{ + CcWindow *self = (CcWindow *) widget; + + GTK_WIDGET_CLASS (cc_window_parent_class)->map (widget); + + /* Show a warning for Flatpak builds */ + if (in_flatpak_sandbox () && g_settings_get_boolean (self->settings, "show-development-warning")) + gtk_window_present (GTK_WINDOW (self->development_warning_dialog)); +} + +static void +cc_window_unmap (GtkWidget *widget) +{ + CcWindow *self = CC_WINDOW (widget); + gboolean maximized; + gint height; + gint width; + + maximized = gtk_window_is_maximized (GTK_WINDOW (self)); + gtk_window_get_default_size (GTK_WINDOW (self), &width, &height); + + g_settings_set (self->settings, + "window-state", + "(iib)", + width, + height, + maximized); + + GTK_WIDGET_CLASS (cc_window_parent_class)->unmap (widget); +} + +/* GObject Implementation */ +static void +cc_window_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + CcWindow *self = CC_WINDOW (object); + + switch (property_id) + { + case PROP_ACTIVE_PANEL: + g_value_set_object (value, self->active_panel); + break; + + case PROP_MODEL: + g_value_set_object (value, self->store); + break; + + case PROP_FOLDED: + g_value_set_boolean (value, self->folded); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +cc_window_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + CcWindow *self = CC_WINDOW (object); + + switch (property_id) + { + case PROP_ACTIVE_PANEL: + set_active_panel (self, g_value_get_object (value)); + break; + + case PROP_MODEL: + g_assert (self->store == NULL); + self->store = g_value_dup_object (value); + break; + + case PROP_FOLDED: + self->folded = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +cc_window_constructed (GObject *object) +{ + CcWindow *self = CC_WINDOW (object); + g_autofree char *id = NULL; + + load_window_state (self); + + /* Add the panels */ + setup_model (self); + + /* After everything is loaded, select the last used panel, if any, + * or the first visible panel */ + id = g_settings_get_string (self->settings, "last-panel"); + if (id != NULL && cc_shell_model_has_panel (self->store, id)) + cc_panel_list_set_active_panel (self->panel_list, id); + else + cc_panel_list_activate (self->panel_list); + + g_signal_connect_swapped (self->panel_list, + "notify::view", + G_CALLBACK (update_headerbar_buttons), + self); + + update_headerbar_buttons (self); + adw_leaflet_set_visible_child (self->main_leaflet, + GTK_WIDGET (self->sidebar_box)); + + G_OBJECT_CLASS (cc_window_parent_class)->constructed (object); +} + +static void +cc_window_dispose (GObject *object) +{ + CcWindow *self = CC_WINDOW (object); + + g_clear_pointer (&self->current_panel_id, g_free); + g_clear_object (&self->store); + g_clear_object (&self->active_panel); + + G_OBJECT_CLASS (cc_window_parent_class)->dispose (object); +} + +static void +cc_window_finalize (GObject *object) +{ + CcWindow *self = CC_WINDOW (object); + + if (self->previous_panels) + { + g_queue_free_full (self->previous_panels, g_free); + self->previous_panels = NULL; + } + + g_clear_object (&self->settings); + + G_OBJECT_CLASS (cc_window_parent_class)->finalize (object); +} + +static void +cc_window_class_init (CcWindowClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = cc_window_get_property; + object_class->set_property = cc_window_set_property; + object_class->constructed = cc_window_constructed; + object_class->dispose = cc_window_dispose; + object_class->finalize = cc_window_finalize; + + widget_class->map = cc_window_map; + widget_class->unmap = cc_window_unmap; + + g_object_class_override_property (object_class, PROP_ACTIVE_PANEL, "active-panel"); + + g_object_class_install_property (object_class, + PROP_MODEL, + g_param_spec_object ("model", + "Model", + "The CcShellModel of this application", + CC_TYPE_SHELL_MODEL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_FOLDED, + g_param_spec_boolean ("folded", + "Folded", + "Whether the window is foled", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/gtk/cc-window.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcWindow, development_warning_dialog); + gtk_widget_class_bind_template_child (widget_class, CcWindow, header); + gtk_widget_class_bind_template_child (widget_class, CcWindow, main_leaflet); + gtk_widget_class_bind_template_child (widget_class, CcWindow, panel_list); + gtk_widget_class_bind_template_child (widget_class, CcWindow, previous_button); + gtk_widget_class_bind_template_child (widget_class, CcWindow, search_bar); + gtk_widget_class_bind_template_child (widget_class, CcWindow, search_button); + gtk_widget_class_bind_template_child (widget_class, CcWindow, search_entry); + gtk_widget_class_bind_template_child (widget_class, CcWindow, sidebar_box); + gtk_widget_class_bind_template_child (widget_class, CcWindow, sidebar_title_widget); + gtk_widget_class_bind_template_child (widget_class, CcWindow, stack); + + gtk_widget_class_bind_template_callback (widget_class, on_main_leaflet_folded_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, on_development_warning_dialog_responded_cb); + gtk_widget_class_bind_template_callback (widget_class, on_stack_transition_running_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, previous_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, search_entry_activate_cb); + gtk_widget_class_bind_template_callback (widget_class, show_panel_cb); + gtk_widget_class_bind_template_callback (widget_class, update_list_title); + + gtk_widget_class_add_binding (widget_class, GDK_KEY_Left, GDK_ALT_MASK, go_back_shortcut_cb, NULL); + gtk_widget_class_add_binding (widget_class, GDK_KEY_s, GDK_CONTROL_MASK, search_shortcut_cb, NULL); + gtk_widget_class_add_binding (widget_class, GDK_KEY_S, GDK_CONTROL_MASK, search_shortcut_cb, NULL); + gtk_widget_class_add_binding (widget_class, GDK_KEY_f, GDK_CONTROL_MASK, search_shortcut_cb, NULL); + gtk_widget_class_add_binding (widget_class, GDK_KEY_F, GDK_CONTROL_MASK, search_shortcut_cb, NULL); + gtk_widget_class_add_binding_action (widget_class, GDK_KEY_q, GDK_CONTROL_MASK, "window.close", NULL); + gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Q, GDK_CONTROL_MASK, "window.close", NULL); + gtk_widget_class_add_binding_action (widget_class, GDK_KEY_w, GDK_CONTROL_MASK, "window.close", NULL); + gtk_widget_class_add_binding_action (widget_class, GDK_KEY_W, GDK_CONTROL_MASK, "window.close", NULL); + + gtk_widget_class_install_action (widget_class, "window.navigate", "i", navigate_action_cb); + + g_type_ensure (CC_TYPE_PANEL_LIST); +} + +static void +cc_window_init (CcWindow *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); + + self->settings = g_settings_new ("org.gnome.Settings"); + self->previous_panels = g_queue_new (); + self->previous_list_view = cc_panel_list_get_view (self->panel_list); + + g_object_bind_property (self->main_leaflet, + "folded", + self, + "folded", + G_BINDING_SYNC_CREATE); + + /* Add a custom CSS class on development builds */ + if (in_flatpak_sandbox ()) + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "devel"); +} + +CcWindow * +cc_window_new (GtkApplication *application, + CcShellModel *model) +{ + g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL); + + return g_object_new (CC_TYPE_WINDOW, + "application", application, + "resizable", TRUE, + "title", _("Settings"), + "icon-name", DEFAULT_WINDOW_ICON_NAME, + "show-menubar", FALSE, + "model", model, + NULL); +} + +void +cc_window_set_search_item (CcWindow *center, + const char *search) +{ + gtk_search_bar_set_search_mode (center->search_bar, TRUE); + gtk_editable_set_text (GTK_EDITABLE (center->search_entry), search); + gtk_editable_set_position (GTK_EDITABLE (center->search_entry), -1); +} |