Clicking on the 'Custom Shortcuts' row when there are no custom shortcuts causes the 'Add Custom Shortcuts' dialog to be shown for all subsequent sessions. This is because the first stack defined was 'Add Custom Shortcuts', it would always be visible, as it was no longer defined which stack was going to be shown. Fixes (https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/2479)
594 lines
21 KiB
C
594 lines
21 KiB
C
/* cc-keyboard-shortcut-dialog.c
|
|
*
|
|
* Copyright (C) 2010 Intel, Inc
|
|
* Copyright (C) 2016 Endless, Inc
|
|
* Copyright (C) 2020 System76, Inc.
|
|
* Copyright (C) 2022 Purism SPC
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Thomas Wood <thomas.wood@intel.com>
|
|
* Georges Basile Stavracas Neto <gbsneto@gnome.org>
|
|
* Ian Douglas Scott <idscott@system76.com>
|
|
* Mohammed Sadiq <sadiq@sadiqpk.org>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <glib/gi18n.h>
|
|
#include <adwaita.h>
|
|
|
|
#include "cc-keyboard-shortcut-dialog.h"
|
|
#include "cc-keyboard-item.h"
|
|
#include "cc-keyboard-manager.h"
|
|
#include "cc-keyboard-shortcut-editor.h"
|
|
#include "cc-keyboard-shortcut-group.h"
|
|
#include "cc-keyboard-shortcut-row.h"
|
|
#include "cc-list-row.h"
|
|
#include "cc-util.h"
|
|
#include "keyboard-shortcuts.h"
|
|
|
|
struct _CcKeyboardShortcutDialog
|
|
{
|
|
AdwWindow parent_instance;
|
|
|
|
AdwLeaflet *leaflet;
|
|
GtkBox *main_box;
|
|
GtkButton *reset_all_button;
|
|
GtkSearchEntry *search_entry;
|
|
GtkStack *section_stack;
|
|
AdwPreferencesPage *section_list_page;
|
|
GtkListBox *section_list_box;
|
|
AdwPreferencesPage *search_result_page;
|
|
AdwStatusPage *empty_results_page;
|
|
|
|
GtkBox *subview_box;
|
|
AdwWindowTitle *subview_title;
|
|
GtkButton *back_button;
|
|
GtkStack *subview_stack;
|
|
GtkStack *shortcut_list_stack;
|
|
AdwStatusPage *empty_custom_shortcut_page;
|
|
GtkSizeGroup *accelerator_size_group;
|
|
|
|
/* A GListStore of sections containing a GListStore of CcKeyboardItem */
|
|
GListStore *sections;
|
|
GListStore *visible_section;
|
|
GtkFlattenListModel *filtered_shortcuts;
|
|
|
|
CcKeyboardManager *manager;
|
|
GtkWidget *shortcut_editor;
|
|
GStrv search_terms;
|
|
};
|
|
|
|
G_DEFINE_TYPE (CcKeyboardShortcutDialog, cc_keyboard_shortcut_dialog, ADW_TYPE_WINDOW)
|
|
|
|
|
|
static GListStore *
|
|
keyboard_shortcut_get_section_store (CcKeyboardShortcutDialog *self,
|
|
const char *section_id,
|
|
const char *section_title)
|
|
{
|
|
g_autoptr(GListStore) section = NULL;
|
|
GtkWidget *group;
|
|
guint n_items;
|
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
|
g_assert (section_id && *section_id);
|
|
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->sections));
|
|
|
|
for (guint i = 0; i < n_items; i++)
|
|
{
|
|
g_autoptr(GObject) item = NULL;
|
|
const char *item_section_id;
|
|
|
|
item = g_list_model_get_item (G_LIST_MODEL (self->sections), i);
|
|
item_section_id = g_object_get_data (item, "id");
|
|
|
|
if (g_str_equal (item_section_id, section_id))
|
|
return G_LIST_STORE (item);
|
|
}
|
|
|
|
/* Found no matching section, so create one */
|
|
section = g_list_store_new (CC_TYPE_KEYBOARD_ITEM);
|
|
g_object_set_data_full (G_OBJECT (section), "id", g_strdup (section_id), g_free);
|
|
g_object_set_data_full (G_OBJECT (section), "title", g_strdup (section_title), g_free);
|
|
|
|
/* This group shall be shown in the search results page */
|
|
group = cc_keyboard_shortcut_group_new (G_LIST_MODEL (section),
|
|
section_id, section_title,
|
|
self->manager,
|
|
CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor),
|
|
self->accelerator_size_group);
|
|
g_object_set_data (G_OBJECT (section), "search-group", group);
|
|
|
|
/* This group shall be shown when a section title row is activated */
|
|
group = cc_keyboard_shortcut_group_new (G_LIST_MODEL (section),
|
|
section_id, NULL,
|
|
self->manager,
|
|
CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor),
|
|
self->accelerator_size_group);
|
|
g_object_set_data (G_OBJECT (section), "group", group);
|
|
|
|
g_list_store_append (self->sections, section);
|
|
|
|
return section;
|
|
}
|
|
|
|
static void
|
|
shortcut_added_cb (CcKeyboardShortcutDialog *self,
|
|
CcKeyboardItem *item,
|
|
const char *section_id,
|
|
const char *section_title)
|
|
{
|
|
GListStore *section;
|
|
|
|
section = keyboard_shortcut_get_section_store (self, section_id, section_title);
|
|
g_object_set_data (G_OBJECT (item), "section", section);
|
|
g_list_store_append (section, item);
|
|
}
|
|
|
|
static void
|
|
shortcut_removed_cb (CcKeyboardShortcutDialog *self,
|
|
CcKeyboardItem *item)
|
|
{
|
|
GListStore *section;
|
|
guint position;
|
|
|
|
section = g_object_get_data (G_OBJECT (item), "section");
|
|
g_return_if_fail (section);
|
|
|
|
if (g_list_store_find (section, item, &position))
|
|
g_list_store_remove (section, position);
|
|
}
|
|
|
|
static void
|
|
shortuct_custom_items_changed (CcKeyboardShortcutDialog *self)
|
|
{
|
|
GListStore *section;
|
|
GtkWidget *page;
|
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
|
|
|
section = keyboard_shortcut_get_section_store (self, "custom", "Custom Shortcuts");
|
|
|
|
if (self->visible_section == section)
|
|
{
|
|
guint n_items;
|
|
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (section));
|
|
|
|
if (n_items)
|
|
page = GTK_WIDGET (self->shortcut_list_stack);
|
|
else
|
|
page = GTK_WIDGET (self->empty_custom_shortcut_page);
|
|
}
|
|
else
|
|
page = GTK_WIDGET (self->shortcut_list_stack);
|
|
|
|
gtk_stack_set_visible_child (self->subview_stack, page);
|
|
}
|
|
|
|
static int
|
|
compare_sections_title (gconstpointer a,
|
|
gconstpointer b,
|
|
gpointer user_data)
|
|
{
|
|
GObject *obj_a, *obj_b;
|
|
|
|
const char *title_a, *title_b, *id_a, *id_b;
|
|
|
|
obj_a = G_OBJECT (a);
|
|
obj_b = G_OBJECT (b);
|
|
|
|
id_a = g_object_get_data (obj_a, "id");
|
|
id_b = g_object_get_data (obj_b, "id");
|
|
|
|
/* Always place custom row as the last item */
|
|
if (g_str_equal (id_a, "custom"))
|
|
return 1;
|
|
|
|
if (g_str_equal (id_b, "custom"))
|
|
return -1;
|
|
|
|
title_a = _(g_object_get_data (obj_a, "title"));
|
|
title_b = _(g_object_get_data (obj_b, "title"));
|
|
|
|
return g_strcmp0 (title_a, title_b);
|
|
}
|
|
|
|
static void
|
|
shortcut_search_result_changed_cb (CcKeyboardShortcutDialog *self)
|
|
{
|
|
GListModel *model;
|
|
GtkWidget *page;
|
|
guint n_items;
|
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
|
|
|
/* If a section is already shown, it is handled in search change callback */
|
|
if (self->visible_section)
|
|
return;
|
|
|
|
model = G_LIST_MODEL (self->filtered_shortcuts);
|
|
n_items = g_list_model_get_n_items (model);
|
|
|
|
if (n_items == 0)
|
|
page = GTK_WIDGET (self->empty_results_page);
|
|
else if (self->search_terms)
|
|
page = GTK_WIDGET (self->search_result_page);
|
|
else
|
|
page = GTK_WIDGET (self->section_list_page);
|
|
|
|
gtk_stack_set_visible_child (self->section_stack, page);
|
|
}
|
|
|
|
/* All items have loaded, now sort the groups and add them to the page */
|
|
static void
|
|
shortcuts_loaded_cb (CcKeyboardShortcutDialog *self)
|
|
{
|
|
g_autoptr(GPtrArray) filtered_items = NULL;
|
|
g_autoptr(GPtrArray) widgets = NULL;
|
|
GListStore *filtered_lists;
|
|
GListStore *custom_store;
|
|
guint n_items;
|
|
|
|
/* Ensure that custom shorcuts section exists */
|
|
custom_store = keyboard_shortcut_get_section_store (self, "custom", "Custom Shortcuts");
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->sections));
|
|
widgets = g_ptr_array_new ();
|
|
filtered_items = g_ptr_array_new ();
|
|
filtered_lists = g_list_store_new (G_TYPE_LIST_MODEL);
|
|
|
|
g_signal_connect_object (custom_store, "items-changed",
|
|
G_CALLBACK (shortuct_custom_items_changed),
|
|
self, G_CONNECT_SWAPPED);
|
|
|
|
g_list_store_sort (self->sections, compare_sections_title, NULL);
|
|
|
|
for (guint i = 0; i < n_items; i++)
|
|
{
|
|
g_autoptr(GObject) item = NULL;
|
|
CcKeyboardShortcutGroup *group;
|
|
GListModel *model;
|
|
GtkWidget *page;
|
|
|
|
item = g_list_model_get_item (G_LIST_MODEL (self->sections), i);
|
|
group = g_object_get_data (item, "search-group");
|
|
g_ptr_array_add (widgets, group);
|
|
|
|
model = cc_keyboard_shortcut_group_get_model (group);
|
|
g_ptr_array_add (filtered_items, model);
|
|
|
|
/* Populate shortcut section page */
|
|
group = g_object_get_data (item, "group");
|
|
page = adw_preferences_page_new ();
|
|
g_object_set_data (item, "page", page);
|
|
adw_preferences_page_add (ADW_PREFERENCES_PAGE (page), ADW_PREFERENCES_GROUP (group));
|
|
gtk_stack_add_child (self->shortcut_list_stack, page);
|
|
}
|
|
|
|
/* Populate search results page */
|
|
for (guint i = 0; i < widgets->len; i++)
|
|
adw_preferences_page_add (self->search_result_page, widgets->pdata[i]);
|
|
|
|
/* Keep track of search results so as to update empty state */
|
|
g_list_store_splice (filtered_lists, 0, 0, filtered_items->pdata, filtered_items->len);
|
|
self->filtered_shortcuts = gtk_flatten_list_model_new (G_LIST_MODEL (filtered_lists));
|
|
|
|
g_signal_connect_object (self->filtered_shortcuts, "items-changed",
|
|
G_CALLBACK (shortcut_search_result_changed_cb),
|
|
self, G_CONNECT_SWAPPED);
|
|
}
|
|
|
|
static GtkWidget *
|
|
shortcut_dialog_row_new (gpointer item,
|
|
gpointer user_data)
|
|
{
|
|
GtkWidget *row, *group;
|
|
const char *title;
|
|
|
|
group = g_object_get_data (item, "search-group");
|
|
title = g_object_get_data (item, "title");
|
|
row = g_object_new (CC_TYPE_LIST_ROW, NULL);
|
|
|
|
g_object_set_data (G_OBJECT (row), "section", item);
|
|
cc_list_row_set_show_arrow (CC_LIST_ROW (row), TRUE);
|
|
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE);
|
|
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), _(title));
|
|
|
|
g_object_bind_property (group, "modified-text",
|
|
row, "secondary-label",
|
|
G_BINDING_SYNC_CREATE);
|
|
|
|
return row;
|
|
}
|
|
|
|
static void
|
|
add_custom_shortcut_clicked_cb (CcKeyboardShortcutDialog *self)
|
|
{
|
|
CcKeyboardShortcutEditor *editor;
|
|
|
|
editor = CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor);
|
|
|
|
cc_keyboard_shortcut_editor_set_mode (editor, CC_SHORTCUT_EDITOR_CREATE);
|
|
cc_keyboard_shortcut_editor_set_item (editor, NULL);
|
|
|
|
gtk_widget_set_visible (self->shortcut_editor, TRUE);
|
|
}
|
|
|
|
static void
|
|
back_button_clicked_cb (CcKeyboardShortcutDialog *self)
|
|
{
|
|
adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_BACK);
|
|
}
|
|
|
|
static void
|
|
on_reset_all_dialog_response_cb (GtkDialog *dialog,
|
|
gint response,
|
|
CcKeyboardShortcutDialog *self)
|
|
{
|
|
guint n_items, j_items;
|
|
|
|
gtk_window_destroy (GTK_WINDOW (dialog));
|
|
if (response != GTK_RESPONSE_ACCEPT)
|
|
return;
|
|
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->sections));
|
|
|
|
for (guint i = 0; i < n_items; i++)
|
|
{
|
|
g_autoptr(GListModel) section = NULL;
|
|
|
|
section = g_list_model_get_item (G_LIST_MODEL (self->sections), i);
|
|
j_items = g_list_model_get_n_items (section);
|
|
|
|
for (guint j = 0; j < j_items; j++)
|
|
{
|
|
g_autoptr(CcKeyboardItem) item = NULL;
|
|
|
|
item = g_list_model_get_item (section, j);
|
|
|
|
/* Don't reset custom shortcuts */
|
|
if (cc_keyboard_item_get_item_type (item) == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH)
|
|
return;
|
|
|
|
/* cc_keyboard_manager_reset_shortcut() already resets conflicting shortcuts,
|
|
* so no other check is needed here. */
|
|
cc_keyboard_manager_reset_shortcut (self->manager, item);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
reset_all_clicked_cb (CcKeyboardShortcutDialog *self)
|
|
{
|
|
GtkWidget *dialog, *button;
|
|
|
|
dialog = gtk_message_dialog_new (GTK_WINDOW (self),
|
|
GTK_DIALOG_MODAL | GTK_DIALOG_USE_HEADER_BAR | GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
GTK_MESSAGE_WARNING,
|
|
GTK_BUTTONS_NONE,
|
|
_("Reset All Shortcuts?"));
|
|
|
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
|
_("Resetting the shortcuts may affect your custom shortcuts. "
|
|
"This cannot be undone."));
|
|
|
|
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
|
_("Cancel"), GTK_RESPONSE_CANCEL,
|
|
_("Reset All"), GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
|
|
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
|
|
|
|
/* Make the "Reset All" button destructive */
|
|
button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
|
gtk_widget_add_css_class (button, "destructive-action");
|
|
|
|
g_signal_connect (dialog, "response", G_CALLBACK (on_reset_all_dialog_response_cb), self);
|
|
|
|
gtk_window_present (GTK_WINDOW (dialog));
|
|
}
|
|
|
|
static void
|
|
shortcut_dialog_visible_child_changed_cb (CcKeyboardShortcutDialog *self)
|
|
{
|
|
gpointer visible_child;
|
|
gboolean is_main_view;
|
|
|
|
visible_child = adw_leaflet_get_visible_child (self->leaflet);
|
|
is_main_view = visible_child == self->main_box;
|
|
|
|
if (is_main_view)
|
|
{
|
|
gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
|
|
gtk_widget_grab_focus (GTK_WIDGET (self->search_entry));
|
|
|
|
self->visible_section = NULL;
|
|
}
|
|
else if (self->visible_section)
|
|
{
|
|
const char *title;
|
|
|
|
title = g_object_get_data (G_OBJECT (self->visible_section), "title");
|
|
adw_window_title_set_title (self->subview_title, _(title) ?: "");
|
|
}
|
|
}
|
|
|
|
static void
|
|
shortcut_search_entry_changed_cb (CcKeyboardShortcutDialog *self)
|
|
{
|
|
g_autofree char *search = NULL;
|
|
const char *search_text;
|
|
guint n_items;
|
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
|
|
|
/* Don't update search if we are in a subview */
|
|
if (self->visible_section)
|
|
return;
|
|
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->sections));
|
|
search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_entry));
|
|
search = cc_util_normalize_casefold_and_unaccent (search_text);
|
|
|
|
g_clear_pointer (&self->search_terms, g_strfreev);
|
|
if (search && *search && *search != ' ')
|
|
self->search_terms = g_strsplit (search, " ", -1);
|
|
|
|
/* "Reset all..." button should be sensitive only if the search is not active */
|
|
gtk_widget_set_sensitive (GTK_WIDGET (self->reset_all_button), !self->search_terms);
|
|
|
|
for (guint i = 0; i < n_items; i++)
|
|
{
|
|
g_autoptr(GObject) item = NULL;
|
|
CcKeyboardShortcutGroup *group;
|
|
|
|
item = g_list_model_get_item (G_LIST_MODEL (self->sections), i);
|
|
group = g_object_get_data (item, "search-group");
|
|
|
|
cc_keyboard_shortcut_group_set_filter (group, self->search_terms);
|
|
}
|
|
|
|
shortcut_search_result_changed_cb (self);
|
|
}
|
|
|
|
static void
|
|
shortcut_section_row_activated_cb (CcKeyboardShortcutDialog *self,
|
|
GtkListBoxRow *row)
|
|
{
|
|
GListStore *section;
|
|
GtkWidget *page;
|
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
|
g_assert (GTK_IS_LIST_BOX_ROW (row));
|
|
|
|
section = g_object_get_data (G_OBJECT (row), "section");
|
|
self->visible_section = section;
|
|
|
|
page = g_object_get_data (G_OBJECT (section), "page");
|
|
gtk_stack_set_visible_child (self->shortcut_list_stack, page);
|
|
adw_leaflet_set_visible_child (self->leaflet, GTK_WIDGET (self->subview_box));
|
|
shortuct_custom_items_changed (self);
|
|
}
|
|
|
|
static void
|
|
cc_keyboard_shortcut_dialog_constructed (GObject *object)
|
|
{
|
|
CcKeyboardShortcutDialog *self = CC_KEYBOARD_SHORTCUT_DIALOG (object);
|
|
|
|
G_OBJECT_CLASS (cc_keyboard_shortcut_dialog_parent_class)->constructed (object);
|
|
|
|
/* Setup the dialog's transient parent */
|
|
gtk_window_set_transient_for (GTK_WINDOW (self->shortcut_editor), GTK_WINDOW (self));
|
|
}
|
|
|
|
static void
|
|
cc_keyboard_shortcut_dialog_finalize (GObject *object)
|
|
{
|
|
CcKeyboardShortcutDialog *self = CC_KEYBOARD_SHORTCUT_DIALOG (object);
|
|
|
|
g_clear_object (&self->manager);
|
|
g_clear_object (&self->sections);
|
|
g_clear_pointer (&self->search_terms, g_strfreev);
|
|
g_clear_object (&self->sections);
|
|
g_clear_object (&self->filtered_shortcuts);
|
|
g_clear_pointer ((GtkWindow**)&self->shortcut_editor, gtk_window_destroy);
|
|
|
|
G_OBJECT_CLASS (cc_keyboard_shortcut_dialog_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
cc_keyboard_shortcut_dialog_class_init (CcKeyboardShortcutDialogClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
|
|
object_class->constructed = cc_keyboard_shortcut_dialog_constructed;
|
|
object_class->finalize = cc_keyboard_shortcut_dialog_finalize;
|
|
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL);
|
|
|
|
gtk_widget_class_set_template_from_resource (widget_class,
|
|
"/org/gnome/control-center/"
|
|
"keyboard/cc-keyboard-shortcut-dialog.ui");
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, leaflet);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, main_box);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, reset_all_button);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, search_entry);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, section_stack);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, section_list_page);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, section_list_box);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, search_result_page);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, empty_results_page);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, subview_box);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, subview_title);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, back_button);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, subview_stack);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, shortcut_list_stack);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, empty_custom_shortcut_page);
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, accelerator_size_group);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, add_custom_shortcut_clicked_cb);
|
|
gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb);
|
|
gtk_widget_class_bind_template_callback (widget_class, reset_all_clicked_cb);
|
|
gtk_widget_class_bind_template_callback (widget_class, shortcut_dialog_visible_child_changed_cb);
|
|
gtk_widget_class_bind_template_callback (widget_class, shortcut_search_entry_changed_cb);
|
|
gtk_widget_class_bind_template_callback (widget_class, shortcut_section_row_activated_cb);
|
|
}
|
|
|
|
static void
|
|
cc_keyboard_shortcut_dialog_init (CcKeyboardShortcutDialog *self)
|
|
{
|
|
gtk_widget_init_template (GTK_WIDGET (self));
|
|
gtk_search_entry_set_key_capture_widget (self->search_entry, GTK_WIDGET (self));
|
|
shortcut_dialog_visible_child_changed_cb (self);
|
|
|
|
self->manager = cc_keyboard_manager_new ();
|
|
|
|
self->shortcut_editor = cc_keyboard_shortcut_editor_new (self->manager);
|
|
shortcut_dialog_visible_child_changed_cb (self);
|
|
|
|
self->sections = g_list_store_new (G_TYPE_LIST_STORE);
|
|
|
|
g_signal_connect_object (self->manager,
|
|
"shortcut-added",
|
|
G_CALLBACK (shortcut_added_cb),
|
|
self, G_CONNECT_SWAPPED);
|
|
g_signal_connect_object (self->manager,
|
|
"shortcut-removed",
|
|
G_CALLBACK (shortcut_removed_cb),
|
|
self, G_CONNECT_SWAPPED);
|
|
g_signal_connect_object (self->manager,
|
|
"shortcuts-loaded",
|
|
G_CALLBACK (shortcuts_loaded_cb),
|
|
self, G_CONNECT_SWAPPED);
|
|
|
|
cc_keyboard_manager_load_shortcuts (self->manager);
|
|
|
|
gtk_list_box_bind_model (self->section_list_box,
|
|
G_LIST_MODEL (self->sections),
|
|
shortcut_dialog_row_new,
|
|
self, NULL);
|
|
}
|
|
|
|
GtkWidget*
|
|
cc_keyboard_shortcut_dialog_new (void)
|
|
{
|
|
return g_object_new (CC_TYPE_KEYBOARD_SHORTCUT_DIALOG, NULL);
|
|
}
|