2020-07-09 14:54:20 -07:00
|
|
|
/* cc-keyboard-shortcut-dialog.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Intel, Inc
|
|
|
|
* Copyright (C) 2016 Endless, Inc
|
|
|
|
* Copyright (C) 2020 System76, Inc.
|
2022-11-24 12:42:14 +05:30
|
|
|
* Copyright (C) 2022 Purism SPC
|
2020-07-09 14:54:20 -07:00
|
|
|
*
|
|
|
|
* 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>
|
2022-11-24 12:42:14 +05:30
|
|
|
* Mohammed Sadiq <sadiq@sadiqpk.org>
|
2020-07-09 14:54:20 -07:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
|
|
|
|
2021-03-03 08:27:17 +01:00
|
|
|
#include <config.h>
|
2020-07-09 14:54:20 -07:00
|
|
|
#include <glib/gi18n.h>
|
2021-10-31 17:40:27 -03:00
|
|
|
#include <adwaita.h>
|
2020-07-09 14:54:20 -07:00
|
|
|
|
|
|
|
#include "cc-keyboard-shortcut-dialog.h"
|
|
|
|
#include "cc-keyboard-item.h"
|
|
|
|
#include "cc-keyboard-manager.h"
|
|
|
|
#include "cc-keyboard-shortcut-editor.h"
|
2022-11-24 12:42:14 +05:30
|
|
|
#include "cc-keyboard-shortcut-group.h"
|
2020-07-09 14:54:20 -07:00
|
|
|
#include "cc-keyboard-shortcut-row.h"
|
|
|
|
#include "cc-list-row.h"
|
|
|
|
#include "cc-util.h"
|
|
|
|
#include "keyboard-shortcuts.h"
|
|
|
|
|
|
|
|
struct _CcKeyboardShortcutDialog
|
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
AdwWindow parent_instance;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-06-02 23:48:59 -04:00
|
|
|
AdwNavigationView *navigation_view;
|
|
|
|
AdwNavigationPage *main_page;
|
2022-11-24 12:42:14 +05:30
|
|
|
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;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-06-02 23:48:59 -04:00
|
|
|
AdwNavigationPage *subview_page;
|
2022-12-22 17:13:15 +05:30
|
|
|
GtkStack *subview_stack;
|
2022-11-24 12:42:14 +05:30
|
|
|
GtkStack *shortcut_list_stack;
|
|
|
|
AdwStatusPage *empty_custom_shortcut_page;
|
|
|
|
GtkSizeGroup *accelerator_size_group;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* A GListStore of sections containing a GListStore of CcKeyboardItem */
|
|
|
|
GListStore *sections;
|
|
|
|
GListStore *visible_section;
|
|
|
|
GtkFlattenListModel *filtered_shortcuts;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
CcKeyboardManager *manager;
|
|
|
|
GtkWidget *shortcut_editor;
|
|
|
|
GStrv search_terms;
|
|
|
|
};
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
G_DEFINE_TYPE (CcKeyboardShortcutDialog, cc_keyboard_shortcut_dialog, ADW_TYPE_WINDOW)
|
2020-07-09 14:54:20 -07:00
|
|
|
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
static GListStore *
|
|
|
|
keyboard_shortcut_get_section_store (CcKeyboardShortcutDialog *self,
|
|
|
|
const char *section_id,
|
|
|
|
const char *section_title)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
g_autoptr(GListStore) section = NULL;
|
|
|
|
GtkWidget *group;
|
|
|
|
guint n_items;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
|
|
|
g_assert (section_id && *section_id);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->sections));
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
for (guint i = 0; i < n_items; i++)
|
|
|
|
{
|
|
|
|
g_autoptr(GObject) item = NULL;
|
|
|
|
const char *item_section_id;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
item = g_list_model_get_item (G_LIST_MODEL (self->sections), i);
|
|
|
|
item_section_id = g_object_get_data (item, "id");
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
if (g_str_equal (item_section_id, section_id))
|
|
|
|
return G_LIST_STORE (item);
|
|
|
|
}
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* 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;
|
|
|
|
}
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-11-24 12:42:14 +05:30
|
|
|
shortcut_removed_cb (CcKeyboardShortcutDialog *self,
|
|
|
|
CcKeyboardItem *item)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
GListStore *section;
|
|
|
|
guint position;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
section = g_object_get_data (G_OBJECT (item), "section");
|
|
|
|
g_return_if_fail (section);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
if (g_list_store_find (section, item, &position))
|
|
|
|
g_list_store_remove (section, position);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
2022-11-24 12:42:14 +05:30
|
|
|
|
2020-07-09 14:54:20 -07:00
|
|
|
static void
|
2022-11-24 12:42:14 +05:30
|
|
|
shortuct_custom_items_changed (CcKeyboardShortcutDialog *self)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
GListStore *section;
|
2023-05-28 14:45:10 -03:00
|
|
|
GtkWidget *page;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
section = keyboard_shortcut_get_section_store (self, "custom", "Custom Shortcuts");
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
if (self->visible_section == section)
|
|
|
|
{
|
|
|
|
guint n_items;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (section));
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
if (n_items)
|
|
|
|
page = GTK_WIDGET (self->shortcut_list_stack);
|
|
|
|
else
|
|
|
|
page = GTK_WIDGET (self->empty_custom_shortcut_page);
|
|
|
|
}
|
2023-05-28 14:45:10 -03:00
|
|
|
else
|
|
|
|
page = GTK_WIDGET (self->shortcut_list_stack);
|
|
|
|
|
|
|
|
gtk_stack_set_visible_child (self->subview_stack, page);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
static int
|
|
|
|
compare_sections_title (gconstpointer a,
|
|
|
|
gconstpointer b,
|
|
|
|
gpointer user_data)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
GObject *obj_a, *obj_b;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
const char *title_a, *title_b, *id_a, *id_b;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
obj_a = G_OBJECT (a);
|
|
|
|
obj_b = G_OBJECT (b);
|
2021-10-31 17:40:27 -03:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
id_a = g_object_get_data (obj_a, "id");
|
|
|
|
id_b = g_object_get_data (obj_b, "id");
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* 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);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-11-24 12:42:14 +05:30
|
|
|
shortcut_search_result_changed_cb (CcKeyboardShortcutDialog *self)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
GListModel *model;
|
|
|
|
GtkWidget *page;
|
|
|
|
guint n_items;
|
2021-10-31 17:40:27 -03:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* If a section is already shown, it is handled in search change callback */
|
|
|
|
if (self->visible_section)
|
|
|
|
return;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
model = G_LIST_MODEL (self->filtered_shortcuts);
|
|
|
|
n_items = g_list_model_get_n_items (model);
|
2021-10-31 17:40:27 -03:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* All items have loaded, now sort the groups and add them to the page */
|
2020-07-09 14:54:20 -07:00
|
|
|
static void
|
2022-11-24 12:42:14 +05:30
|
|
|
shortcuts_loaded_cb (CcKeyboardShortcutDialog *self)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
g_autoptr(GPtrArray) filtered_items = NULL;
|
|
|
|
g_autoptr(GPtrArray) widgets = NULL;
|
|
|
|
GListStore *filtered_lists;
|
|
|
|
GListStore *custom_store;
|
|
|
|
guint n_items;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* 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);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_signal_connect_object (custom_store, "items-changed",
|
|
|
|
G_CALLBACK (shortuct_custom_items_changed),
|
|
|
|
self, G_CONNECT_SWAPPED);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_list_store_sort (self->sections, compare_sections_title, NULL);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
for (guint i = 0; i < n_items; i++)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* Populate search results page */
|
|
|
|
for (guint i = 0; i < widgets->len; i++)
|
|
|
|
adw_preferences_page_add (self->search_result_page, widgets->pdata[i]);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* 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));
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_signal_connect_object (self->filtered_shortcuts, "items-changed",
|
|
|
|
G_CALLBACK (shortcut_search_result_changed_cb),
|
|
|
|
self, G_CONNECT_SWAPPED);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
static GtkWidget *
|
|
|
|
shortcut_dialog_row_new (gpointer item,
|
|
|
|
gpointer user_data)
|
2020-11-15 14:39:32 -08:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
GtkWidget *row, *group;
|
|
|
|
const char *title;
|
2020-11-15 14:39:32 -08:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
group = g_object_get_data (item, "search-group");
|
|
|
|
title = g_object_get_data (item, "title");
|
|
|
|
row = g_object_new (CC_TYPE_LIST_ROW, NULL);
|
2020-11-15 14:39:32 -08:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
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));
|
2020-11-15 14:39:32 -08:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_object_bind_property (group, "modified-text",
|
|
|
|
row, "secondary-label",
|
|
|
|
G_BINDING_SYNC_CREATE);
|
2020-11-15 14:39:32 -08:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
return row;
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-11-24 12:42:14 +05:30
|
|
|
add_custom_shortcut_clicked_cb (CcKeyboardShortcutDialog *self)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
|
|
|
CcKeyboardShortcutEditor *editor;
|
|
|
|
|
|
|
|
editor = CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor);
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
cc_keyboard_shortcut_editor_set_mode (editor, CC_SHORTCUT_EDITOR_CREATE);
|
|
|
|
cc_keyboard_shortcut_editor_set_item (editor, NULL);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-01-17 01:09:34 +02:00
|
|
|
gtk_widget_set_visible (self->shortcut_editor, TRUE);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
2021-10-31 17:40:27 -03:00
|
|
|
static void
|
2023-05-31 10:06:07 +12:00
|
|
|
on_reset_all_dialog_response_cb (CcKeyboardShortcutDialog *self,
|
2023-05-30 15:40:02 -03:00
|
|
|
gchar *response,
|
2023-05-31 10:06:07 +12:00
|
|
|
AdwMessageDialog *dialog)
|
2021-10-31 17:40:27 -03:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
guint n_items, j_items;
|
|
|
|
|
2023-03-22 23:02:55 +05:30
|
|
|
gtk_window_destroy (GTK_WINDOW (dialog));
|
2023-05-30 15:40:02 -03:00
|
|
|
|
|
|
|
if (g_strcmp0 (response, "cancel") == 0)
|
2022-11-24 12:42:14 +05:30
|
|
|
return;
|
2021-10-31 17:40:27 -03:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
n_items = g_list_model_get_n_items (G_LIST_MODEL (self->sections));
|
|
|
|
|
|
|
|
for (guint i = 0; i < n_items; i++)
|
2021-10-31 17:40:27 -03:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2021-10-31 17:40:27 -03:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
for (guint j = 0; j < j_items; j++)
|
2021-10-31 17:40:27 -03:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2021-10-31 17:40:27 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-09 14:54:20 -07:00
|
|
|
static void
|
|
|
|
reset_all_clicked_cb (CcKeyboardShortcutDialog *self)
|
|
|
|
{
|
2023-05-30 15:40:02 -03:00
|
|
|
GtkWidget *dialog;
|
|
|
|
|
|
|
|
dialog = adw_message_dialog_new (GTK_WINDOW (self),
|
|
|
|
_("Reset All Shortcuts?"),
|
|
|
|
NULL);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-05-30 15:40:02 -03:00
|
|
|
adw_message_dialog_format_body (ADW_MESSAGE_DIALOG (dialog),
|
2023-11-20 20:39:38 -03:00
|
|
|
_("All changes to keyboard shortcuts will be lost."));
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-05-30 15:40:02 -03:00
|
|
|
adw_message_dialog_add_responses (ADW_MESSAGE_DIALOG (dialog),
|
2023-11-20 23:20:52 -03:00
|
|
|
"cancel", _("_Cancel"),
|
|
|
|
"reset_all", _("_Reset All"),
|
2023-05-30 15:40:02 -03:00
|
|
|
NULL);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-05-30 15:40:02 -03:00
|
|
|
adw_message_dialog_set_response_appearance (ADW_MESSAGE_DIALOG (dialog),
|
|
|
|
"reset_all",
|
|
|
|
ADW_RESPONSE_DESTRUCTIVE);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-05-30 15:40:02 -03:00
|
|
|
adw_message_dialog_set_default_response (ADW_MESSAGE_DIALOG (dialog),
|
|
|
|
"cancel");
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-05-30 15:40:02 -03:00
|
|
|
adw_message_dialog_set_close_response (ADW_MESSAGE_DIALOG (dialog),
|
|
|
|
"cancel");
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-05-31 10:06:07 +12:00
|
|
|
g_signal_connect_swapped (dialog,
|
|
|
|
"response",
|
|
|
|
G_CALLBACK (on_reset_all_dialog_response_cb),
|
|
|
|
self);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2021-10-31 17:40:27 -03:00
|
|
|
gtk_window_present (GTK_WINDOW (dialog));
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-06-02 23:48:59 -04:00
|
|
|
shortcut_dialog_visible_page_changed_cb (CcKeyboardShortcutDialog *self)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2023-06-02 23:48:59 -04:00
|
|
|
gpointer visible_page;
|
2022-12-07 10:46:39 +05:30
|
|
|
gboolean is_main_view;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-06-02 23:48:59 -04:00
|
|
|
visible_page = adw_navigation_view_get_visible_page (self->navigation_view);
|
|
|
|
is_main_view = visible_page == self->main_page;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-12-07 10:46:39 +05:30
|
|
|
if (is_main_view)
|
2022-12-07 10:53:00 +05:30
|
|
|
{
|
|
|
|
gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
|
|
|
|
gtk_widget_grab_focus (GTK_WIDGET (self->search_entry));
|
|
|
|
|
|
|
|
self->visible_section = NULL;
|
|
|
|
}
|
2022-12-22 20:31:01 +05:30
|
|
|
else if (self->visible_section)
|
|
|
|
{
|
|
|
|
const char *title;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-12-22 20:31:01 +05:30
|
|
|
title = g_object_get_data (G_OBJECT (self->visible_section), "title");
|
2023-06-02 23:48:59 -04:00
|
|
|
adw_navigation_page_set_title (self->subview_page, _(title) ?: "");
|
2022-12-22 20:31:01 +05:30
|
|
|
}
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
static void
|
|
|
|
shortcut_search_entry_changed_cb (CcKeyboardShortcutDialog *self)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
g_autofree char *search = NULL;
|
|
|
|
const char *search_text;
|
|
|
|
guint n_items;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
2022-12-07 12:27:15 +05:30
|
|
|
|
|
|
|
/* Don't update search if we are in a subview */
|
|
|
|
if (self->visible_section)
|
|
|
|
return;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_clear_pointer (&self->search_terms, g_strfreev);
|
|
|
|
if (search && *search && *search != ' ')
|
|
|
|
self->search_terms = g_strsplit (search, " ", -1);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
/* "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);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
for (guint i = 0; i < n_items; i++)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
g_autoptr(GObject) item = NULL;
|
|
|
|
CcKeyboardShortcutGroup *group;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
item = g_list_model_get_item (G_LIST_MODEL (self->sections), i);
|
|
|
|
group = g_object_get_data (item, "search-group");
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
cc_keyboard_shortcut_group_set_filter (group, self->search_terms);
|
2021-02-06 20:24:37 +05:30
|
|
|
}
|
2022-11-24 12:42:14 +05:30
|
|
|
|
|
|
|
shortcut_search_result_changed_cb (self);
|
2021-02-06 20:24:37 +05:30
|
|
|
}
|
|
|
|
|
2023-10-19 19:30:42 +02:00
|
|
|
static void
|
|
|
|
shortcut_search_entry_stopped_cb (CcKeyboardShortcutDialog *self)
|
|
|
|
{
|
|
|
|
const char *search_text;
|
|
|
|
search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_entry));
|
|
|
|
|
|
|
|
if (search_text && g_strcmp0 (search_text, "") != 0)
|
|
|
|
gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
|
|
|
|
else
|
|
|
|
gtk_window_close (GTK_WINDOW (self));
|
|
|
|
}
|
|
|
|
|
2020-07-09 14:54:20 -07:00
|
|
|
static void
|
2022-11-24 12:42:14 +05:30
|
|
|
shortcut_section_row_activated_cb (CcKeyboardShortcutDialog *self,
|
|
|
|
GtkListBoxRow *row)
|
2020-07-09 14:54:20 -07:00
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
GListStore *section;
|
|
|
|
GtkWidget *page;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
g_assert (CC_IS_KEYBOARD_SHORTCUT_DIALOG (self));
|
|
|
|
g_assert (GTK_IS_LIST_BOX_ROW (row));
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
section = g_object_get_data (G_OBJECT (row), "section");
|
|
|
|
self->visible_section = section;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
page = g_object_get_data (G_OBJECT (section), "page");
|
|
|
|
gtk_stack_set_visible_child (self->shortcut_list_stack, page);
|
2023-06-02 23:48:59 -04:00
|
|
|
adw_navigation_view_push (self->navigation_view, self->subview_page);
|
2022-11-24 12:42:14 +05:30
|
|
|
shortuct_custom_items_changed (self);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2021-01-11 09:06:56 -08:00
|
|
|
static void
|
|
|
|
cc_keyboard_shortcut_dialog_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
CcKeyboardShortcutDialog *self = CC_KEYBOARD_SHORTCUT_DIALOG (object);
|
|
|
|
|
|
|
|
g_clear_object (&self->manager);
|
2022-11-24 12:42:14 +05:30
|
|
|
g_clear_object (&self->sections);
|
|
|
|
g_clear_pointer (&self->search_terms, g_strfreev);
|
|
|
|
g_clear_object (&self->sections);
|
|
|
|
g_clear_object (&self->filtered_shortcuts);
|
2021-10-31 17:40:27 -03:00
|
|
|
g_clear_pointer ((GtkWindow**)&self->shortcut_editor, gtk_window_destroy);
|
2022-11-24 12:42:14 +05:30
|
|
|
|
|
|
|
G_OBJECT_CLASS (cc_keyboard_shortcut_dialog_parent_class)->finalize (object);
|
2021-01-11 09:06:56 -08:00
|
|
|
}
|
|
|
|
|
2020-07-09 14:54:20 -07:00
|
|
|
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;
|
2021-01-11 09:06:56 -08:00
|
|
|
object_class->finalize = cc_keyboard_shortcut_dialog_finalize;
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-05-24 14:44:57 +02:00
|
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL);
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
gtk_widget_class_set_template_from_resource (widget_class,
|
|
|
|
"/org/gnome/control-center/"
|
|
|
|
"keyboard/cc-keyboard-shortcut-dialog.ui");
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2023-06-02 23:48:59 -04:00
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, navigation_view);
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, main_page);
|
2021-10-31 17:40:27 -03:00
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, reset_all_button);
|
2020-07-09 14:54:20 -07:00
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, search_entry);
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
|
|
|
|
2023-06-02 23:48:59 -04:00
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, subview_page);
|
2022-12-22 17:13:15 +05:30
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, subview_stack);
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, add_custom_shortcut_clicked_cb);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, reset_all_clicked_cb);
|
2023-06-02 23:48:59 -04:00
|
|
|
gtk_widget_class_bind_template_callback (widget_class, shortcut_dialog_visible_page_changed_cb);
|
2022-11-24 12:42:14 +05:30
|
|
|
gtk_widget_class_bind_template_callback (widget_class, shortcut_search_entry_changed_cb);
|
2023-10-19 19:30:42 +02:00
|
|
|
gtk_widget_class_bind_template_callback (widget_class, shortcut_search_entry_stopped_cb);
|
2022-11-24 12:42:14 +05:30
|
|
|
gtk_widget_class_bind_template_callback (widget_class, shortcut_section_row_activated_cb);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cc_keyboard_shortcut_dialog_init (CcKeyboardShortcutDialog *self)
|
|
|
|
{
|
2023-10-24 16:02:29 -03:00
|
|
|
GtkWindow *toplevel;
|
|
|
|
|
2020-07-09 14:54:20 -07:00
|
|
|
gtk_widget_init_template (GTK_WIDGET (self));
|
2021-10-31 17:40:27 -03:00
|
|
|
gtk_search_entry_set_key_capture_widget (self->search_entry, GTK_WIDGET (self));
|
2023-06-02 23:48:59 -04:00
|
|
|
shortcut_dialog_visible_page_changed_cb (self);
|
2021-10-31 17:40:27 -03:00
|
|
|
|
2020-07-09 14:54:20 -07:00
|
|
|
self->manager = cc_keyboard_manager_new ();
|
|
|
|
|
2023-10-24 16:02:29 -03:00
|
|
|
toplevel = GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self)));
|
|
|
|
self->shortcut_editor = cc_keyboard_shortcut_editor_new (toplevel, self->manager);
|
2023-06-02 23:48:59 -04:00
|
|
|
shortcut_dialog_visible_page_changed_cb (self);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
self->sections = g_list_store_new (G_TYPE_LIST_STORE);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
|
|
|
g_signal_connect_object (self->manager,
|
|
|
|
"shortcut-added",
|
2022-11-24 12:42:14 +05:30
|
|
|
G_CALLBACK (shortcut_added_cb),
|
|
|
|
self, G_CONNECT_SWAPPED);
|
2020-07-09 14:54:20 -07:00
|
|
|
g_signal_connect_object (self->manager,
|
|
|
|
"shortcut-removed",
|
2022-11-24 12:42:14 +05:30
|
|
|
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);
|
2020-07-09 14:54:20 -07:00
|
|
|
|
|
|
|
cc_keyboard_manager_load_shortcuts (self->manager);
|
|
|
|
|
2022-11-24 12:42:14 +05:30
|
|
|
gtk_list_box_bind_model (self->section_list_box,
|
|
|
|
G_LIST_MODEL (self->sections),
|
|
|
|
shortcut_dialog_row_new,
|
|
|
|
self, NULL);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
GtkWidget*
|
|
|
|
cc_keyboard_shortcut_dialog_new (void)
|
|
|
|
{
|
2022-11-24 12:42:14 +05:30
|
|
|
return g_object_new (CC_TYPE_KEYBOARD_SHORTCUT_DIALOG, NULL);
|
2020-07-09 14:54:20 -07:00
|
|
|
}
|