From dc02c803c20390c0cf71ac83a74c154c157df628 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 6 Aug 2020 15:50:34 -0700 Subject: [PATCH] keyboard: Move row code to CcKeyboardShortcutRow This adds a widget called `CcKeyboardShortcutRow`, sub-classing `GtkListBoxRow`, to handle a shortcut row. This makes the implementation a bit tidier, rather than handling it all in `CcKeyboardPanel`, and allows the widgets that compose the row to be laid out in xml. This is a prerequisite for moving the shortcuts to a new dialog. --- panels/keyboard/cc-keyboard-panel.c | 201 +++++--------------- panels/keyboard/cc-keyboard-shortcut-row.c | 139 ++++++++++++++ panels/keyboard/cc-keyboard-shortcut-row.h | 37 ++++ panels/keyboard/cc-keyboard-shortcut-row.ui | 59 ++++++ panels/keyboard/keyboard.gresource.xml | 1 + panels/keyboard/meson.build | 1 + 6 files changed, 280 insertions(+), 158 deletions(-) create mode 100644 panels/keyboard/cc-keyboard-shortcut-row.c create mode 100644 panels/keyboard/cc-keyboard-shortcut-row.h create mode 100644 panels/keyboard/cc-keyboard-shortcut-row.ui diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c index f4d8d7c2c..ac3d149d5 100644 --- a/panels/keyboard/cc-keyboard-panel.c +++ b/panels/keyboard/cc-keyboard-panel.c @@ -23,6 +23,7 @@ #include #include "cc-alt-chars-key-dialog.h" +#include "cc-keyboard-shortcut-row.h" #include "cc-keyboard-item.h" #include "cc-keyboard-manager.h" #include "cc-keyboard-option.h" @@ -124,46 +125,6 @@ row_data_free (RowData *data) g_free (data); } -static gboolean -transform_binding_to_accel (GBinding *binding, - const GValue *from_value, - GValue *to_value, - gpointer user_data) -{ - CcKeyboardItem *item; - CcKeyCombo combo; - gchar *accelerator; - - item = CC_KEYBOARD_ITEM (g_binding_get_source (binding)); - combo = cc_keyboard_item_get_primary_combo (item); - - /* Embolden the label when the shortcut is modified */ - if (!cc_keyboard_item_is_value_default (item)) - { - g_autofree gchar *tmp = NULL; - - tmp = convert_keysym_state_to_string (&combo); - - accelerator = g_strdup_printf ("%s", tmp); - } - else - { - accelerator = convert_keysym_state_to_string (&combo); - } - - g_value_take_string (to_value, accelerator); - - return TRUE; -} - -static void -shortcut_modified_changed_cb (CcKeyboardItem *item, - GParamSpec *pspec, - GtkWidget *button) -{ - gtk_widget_set_child_visible (button, !cc_keyboard_item_is_value_default (item)); -} - static void reset_all_shortcuts_cb (GtkWidget *widget, gpointer user_data) @@ -228,108 +189,22 @@ reset_all_clicked_cb (CcKeyboardPanel *self) gtk_widget_destroy (dialog); } -static void -reset_shortcut_cb (GtkWidget *reset_button, - CcKeyboardItem *item) -{ - CcKeyboardPanel *self; - - self = CC_KEYBOARD_PANEL (gtk_widget_get_ancestor (reset_button, CC_TYPE_KEYBOARD_PANEL)); - - cc_keyboard_manager_reset_shortcut (self->manager, item); -} - static void add_item (CcKeyboardPanel *self, CcKeyboardItem *item, const gchar *section_id, const gchar *section_title) { - GtkWidget *row, *box, *label, *reset_button; - - /* Horizontal box */ - box = g_object_new (GTK_TYPE_BOX, - "orientation", GTK_ORIENTATION_HORIZONTAL, - "spacing", 18, - "margin-start", 6, - "margin-end", 6, - "margin-bottom", 4, - "margin-top", 4, - NULL); - gtk_widget_show (box); - - /* Shortcut title */ - label = gtk_label_new (cc_keyboard_item_get_description (item)); - gtk_widget_show (label); - gtk_label_set_xalign (GTK_LABEL (label), 0.0); - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR); - gtk_widget_set_hexpand (label, TRUE); - - g_object_bind_property (item, - "description", - label, - "label", - G_BINDING_DEFAULT); - - gtk_container_add (GTK_CONTAINER (box), label); - - /* Shortcut accelerator */ - label = gtk_label_new (""); - gtk_widget_show (label); - gtk_label_set_xalign (GTK_LABEL (label), 0.0); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - - gtk_size_group_add_widget (self->accelerator_sizegroup, label); - - g_object_bind_property_full (item, - "key-combos", - label, - "label", - G_BINDING_SYNC_CREATE, - transform_binding_to_accel, - NULL, NULL, NULL); - - gtk_container_add (GTK_CONTAINER (box), label); - - gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label"); - - /* Reset shortcut button */ - reset_button = gtk_button_new_from_icon_name ("edit-clear-symbolic", GTK_ICON_SIZE_BUTTON); - gtk_widget_show (reset_button); - gtk_widget_set_valign (reset_button, GTK_ALIGN_CENTER); - - gtk_button_set_relief (GTK_BUTTON (reset_button), GTK_RELIEF_NONE); - gtk_widget_set_child_visible (reset_button, !cc_keyboard_item_is_value_default (item)); - - gtk_widget_set_tooltip_text (reset_button, _("Reset the shortcut to its default value")); - - gtk_container_add (GTK_CONTAINER (box), reset_button); - - gtk_style_context_add_class (gtk_widget_get_style_context (reset_button), "flat"); - gtk_style_context_add_class (gtk_widget_get_style_context (reset_button), "circular"); - gtk_style_context_add_class (gtk_widget_get_style_context (reset_button), "reset-shortcut-button"); - - g_signal_connect_object (item, - "notify::is-value-default", - G_CALLBACK (shortcut_modified_changed_cb), - reset_button, 0); - - g_signal_connect_object (reset_button, - "clicked", - G_CALLBACK (reset_shortcut_cb), - item, 0); - - /* The row */ - row = gtk_list_box_row_new (); - gtk_widget_show (row); - gtk_container_add (GTK_CONTAINER (row), box); + GtkWidget *row; + row = GTK_WIDGET(cc_keyboard_shortcut_row_new(item, + self->manager, + CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor), + self->accelerator_sizegroup)); g_object_set_data_full (G_OBJECT (row), "data", row_data_new (item, section_id, section_title), (GDestroyNotify) row_data_free); - gtk_container_add (GTK_CONTAINER (self->shortcuts_listbox), row); } @@ -417,43 +292,53 @@ static gboolean search_match_shortcut (CcKeyboardItem *item, const gchar *search) { - CcKeyCombo combo = cc_keyboard_item_get_primary_combo (item); GStrv shortcut_tokens, search_tokens; g_autofree gchar *normalized_accel = NULL; g_autofree gchar *accel = NULL; gboolean match; guint i; + GList *key_combos, *l; + CcKeyCombo *combo; - if (is_empty_binding (&combo)) - return FALSE; - - match = TRUE; - accel = convert_keysym_state_to_string (&combo); - normalized_accel = cc_util_normalize_casefold_and_unaccent (accel); - - shortcut_tokens = g_strsplit_set (normalized_accel, SHORTCUT_DELIMITERS, -1); - search_tokens = g_strsplit_set (search, SHORTCUT_DELIMITERS, -1); - - for (i = 0; search_tokens[i] != NULL; i++) + key_combos = cc_keyboard_item_get_key_combos (item); + for (l = key_combos; l != NULL; l = l->next) { - const gchar *token; + combo = l->data; - /* Strip leading and trailing whitespaces */ - token = g_strstrip (search_tokens[i]); - - if (g_utf8_strlen (token, -1) == 0) + if (is_empty_binding (combo)) continue; - match = match && strv_contains_prefix_or_match (shortcut_tokens, token); + match = TRUE; + accel = convert_keysym_state_to_string (combo); + normalized_accel = cc_util_normalize_casefold_and_unaccent (accel); - if (!match) - break; + shortcut_tokens = g_strsplit_set (normalized_accel, SHORTCUT_DELIMITERS, -1); + search_tokens = g_strsplit_set (search, SHORTCUT_DELIMITERS, -1); + + for (i = 0; search_tokens[i] != NULL; i++) + { + const gchar *token; + + /* Strip leading and trailing whitespaces */ + token = g_strstrip (search_tokens[i]); + + if (g_utf8_strlen (token, -1) == 0) + continue; + + match = match && strv_contains_prefix_or_match (shortcut_tokens, token); + + if (!match) + break; + } + + g_strfreev (shortcut_tokens); + g_strfreev (search_tokens); + + if (match) + return TRUE; } - g_strfreev (shortcut_tokens); - g_strfreev (search_tokens); - - return match; + return FALSE; } static gint @@ -803,6 +688,9 @@ cc_keyboard_panel_init (CcKeyboardPanel *self) /* Shortcut manager */ self->manager = cc_keyboard_manager_new (); + /* Shortcut editor dialog */ + self->shortcut_editor = cc_keyboard_shortcut_editor_new (self->manager); + /* Use a sizegroup to make the accelerator labels the same width */ self->accelerator_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); @@ -820,9 +708,6 @@ cc_keyboard_panel_init (CcKeyboardPanel *self) cc_keyboard_manager_load_shortcuts (self->manager); - /* Shortcut editor dialog */ - self->shortcut_editor = cc_keyboard_shortcut_editor_new (self->manager); - /* Setup the shortcuts shortcuts_listbox */ gtk_list_box_set_sort_func (GTK_LIST_BOX (self->shortcuts_listbox), sort_function, diff --git a/panels/keyboard/cc-keyboard-shortcut-row.c b/panels/keyboard/cc-keyboard-shortcut-row.c new file mode 100644 index 000000000..6bb91d3ca --- /dev/null +++ b/panels/keyboard/cc-keyboard-shortcut-row.c @@ -0,0 +1,139 @@ +/* cc-keyboard-shortcut-row.c + * + * Copyright (C) 2020 System76, Inc. + * + * 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 . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include "cc-keyboard-shortcut-row.h" +#include "keyboard-shortcuts.h" + +struct _CcKeyboardShortcutRow +{ + GtkListBoxRow parent_instance; + + GtkLabel *accelerator_label; + GtkLabel *description_label; + GtkButton *reset_button; + + CcKeyboardItem *item; + CcKeyboardManager *manager; + CcKeyboardShortcutEditor *shortcut_editor; +}; + +G_DEFINE_TYPE (CcKeyboardShortcutRow, cc_keyboard_shortcut_row, GTK_TYPE_LIST_BOX_ROW) + +static void +reset_shortcut_cb (CcKeyboardShortcutRow *self) +{ + cc_keyboard_manager_reset_shortcut (self->manager, self->item); +} + +static void +cc_keyboard_shortcut_row_class_init (CcKeyboardShortcutRowClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-keyboard-shortcut-row.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutRow, description_label); + gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutRow, accelerator_label); + gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutRow, reset_button); + + gtk_widget_class_bind_template_callback (widget_class, reset_shortcut_cb); +} + +static void +cc_keyboard_shortcut_row_init (CcKeyboardShortcutRow *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} + +static void +shortcut_modified_changed_cb (CcKeyboardShortcutRow *self) +{ + gtk_widget_set_child_visible (GTK_WIDGET (self->reset_button), + !cc_keyboard_item_is_value_default (self->item)); +} + +static gboolean +transform_binding_to_accel (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + CcKeyboardItem *item; + CcKeyCombo combo; + gchar *accelerator; + + item = CC_KEYBOARD_ITEM (g_binding_get_source (binding)); + combo = cc_keyboard_item_get_primary_combo (item); + + /* Embolden the label when the shortcut is modified */ + if (!cc_keyboard_item_is_value_default (item)) + { + g_autofree gchar *tmp = NULL; + + tmp = convert_keysym_state_to_string (&combo); + + accelerator = g_strdup_printf ("%s", tmp); + } + else + { + accelerator = convert_keysym_state_to_string (&combo); + } + + g_value_take_string (to_value, accelerator); + + return TRUE; +} + +CcKeyboardShortcutRow * +cc_keyboard_shortcut_row_new (CcKeyboardItem *item, + CcKeyboardManager *manager, + CcKeyboardShortcutEditor *shortcut_editor, + GtkSizeGroup *size_group) +{ + CcKeyboardShortcutRow *self; + + self = g_object_new (CC_TYPE_KEYBOARD_SHORTCUT_ROW, NULL); + self->item = item; + self->manager = manager; + self->shortcut_editor = shortcut_editor; + + gtk_label_set_text (self->description_label, cc_keyboard_item_get_description (item)); + + g_object_bind_property_full (item, + "key-combos", + self->accelerator_label, + "label", + G_BINDING_SYNC_CREATE, + transform_binding_to_accel, + NULL, NULL, NULL); + + gtk_widget_set_child_visible (GTK_WIDGET (self->reset_button), + !cc_keyboard_item_is_value_default (item)); + g_signal_connect_object (item, + "notify::key-combos", + G_CALLBACK (shortcut_modified_changed_cb), + self, G_CONNECT_SWAPPED); + + gtk_size_group_add_widget(size_group, + GTK_WIDGET (self->accelerator_label)); + + return self; +} diff --git a/panels/keyboard/cc-keyboard-shortcut-row.h b/panels/keyboard/cc-keyboard-shortcut-row.h new file mode 100644 index 000000000..d11143f73 --- /dev/null +++ b/panels/keyboard/cc-keyboard-shortcut-row.h @@ -0,0 +1,37 @@ +/* cc-keyboard-shortcut-row.h + * + * Copyright (C) 2020 System76, Inc. + * + * 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 . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include +#include "cc-keyboard-item.h" +#include "cc-keyboard-manager.h" +#include "cc-keyboard-shortcut-editor.h" + +G_BEGIN_DECLS + +#define CC_TYPE_KEYBOARD_SHORTCUT_ROW (cc_keyboard_shortcut_row_get_type()) + +G_DECLARE_FINAL_TYPE (CcKeyboardShortcutRow, cc_keyboard_shortcut_row, CC, KEYBOARD_SHORTCUT_ROW, GtkListBoxRow) + + +CcKeyboardShortcutRow *cc_keyboard_shortcut_row_new (CcKeyboardItem*, CcKeyboardManager*, CcKeyboardShortcutEditor*, GtkSizeGroup*); + +G_END_DECLS diff --git a/panels/keyboard/cc-keyboard-shortcut-row.ui b/panels/keyboard/cc-keyboard-shortcut-row.ui new file mode 100644 index 000000000..87a52d77a --- /dev/null +++ b/panels/keyboard/cc-keyboard-shortcut-row.ui @@ -0,0 +1,59 @@ + + + + + diff --git a/panels/keyboard/keyboard.gresource.xml b/panels/keyboard/keyboard.gresource.xml index 0283dae2a..7fe8bf8dc 100644 --- a/panels/keyboard/keyboard.gresource.xml +++ b/panels/keyboard/keyboard.gresource.xml @@ -3,6 +3,7 @@ enter-keyboard-shortcut.svg cc-alt-chars-key-dialog.ui + cc-keyboard-shortcut-row.ui cc-keyboard-panel.ui cc-keyboard-shortcut-editor.ui diff --git a/panels/keyboard/meson.build b/panels/keyboard/meson.build index 2f61ed071..63729f57c 100644 --- a/panels/keyboard/meson.build +++ b/panels/keyboard/meson.build @@ -57,6 +57,7 @@ endforeach sources = files( 'cc-alt-chars-key-dialog.c', + 'cc-keyboard-shortcut-row.c', 'cc-keyboard-panel.c', 'cc-keyboard-item.c', 'cc-keyboard-manager.c',