[gnome-control-center] region: Make full widget for input rows



commit 66981da2751648eab0365ee4892738fdd0d10d04
Author: Robert Ancell <robert ancell canonical com>
Date:   Fri Jun 29 15:55:59 2018 +1200

    region: Make full widget for input rows
    
    The row widgets are not full GtkWidgets. This means they are harder
    to understand, use g_object_set_data which looses type safety and
    cause the one .c file to be overly large.
    
    Update this code to use a CcInputRow widget that uses GTK+ best
    practice.

 panels/region/cc-input-row.c       | 117 +++++++++++++++++++++++++++++++++
 panels/region/cc-input-row.h       |  44 +++++++++++++
 panels/region/cc-input-row.ui      |  32 +++++++++
 panels/region/cc-region-panel.c    | 129 +++++++++++++------------------------
 panels/region/meson.build          |   3 +-
 panels/region/region.gresource.xml |   1 +
 6 files changed, 239 insertions(+), 87 deletions(-)
---
diff --git a/panels/region/cc-input-row.c b/panels/region/cc-input-row.c
new file mode 100644
index 000000000..86b452dee
--- /dev/null
+++ b/panels/region/cc-input-row.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * 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/>.
+ */
+
+#include <config.h>
+#include "cc-input-row.h"
+
+struct _CcInputRow
+{
+  GtkListBoxRow    parent_instance;
+
+  gchar           *type;
+  gchar           *id;
+  GDesktopAppInfo *app_info;
+
+  GtkWidget       *name_label;
+  GtkWidget       *icon_image;
+};
+
+G_DEFINE_TYPE (CcInputRow, cc_input_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_input_row_dispose (GObject *object)
+{
+  CcInputRow *self = CC_INPUT_ROW (object);
+
+  g_clear_pointer (&self->type, g_free);
+  g_clear_pointer (&self->id, g_free);
+  g_clear_object (&self->app_info);
+
+  G_OBJECT_CLASS (cc_input_row_parent_class)->dispose (object);
+}
+
+void
+cc_input_row_class_init (CcInputRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = cc_input_row_dispose;
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/region/cc-input-row.ui");
+  gtk_widget_class_bind_template_child (widget_class, CcInputRow, name_label);
+  gtk_widget_class_bind_template_child (widget_class, CcInputRow, icon_image);
+}
+
+void
+cc_input_row_init (CcInputRow *row)
+{
+  gtk_widget_init_template (GTK_WIDGET (row));
+}
+
+CcInputRow *
+cc_input_row_new (const gchar     *type,
+                  const gchar     *id,
+                  GDesktopAppInfo *app_info)
+{
+  CcInputRow *row;
+
+  row = g_object_new (CC_TYPE_INPUT_ROW, NULL);
+  row->type = g_strdup (type);
+  row->id = g_strdup (id);
+  if (app_info != NULL)
+    row->app_info = g_object_ref (app_info);
+
+  return row;
+}
+
+const gchar *
+cc_input_row_get_input_type (CcInputRow *row)
+{
+  g_return_val_if_fail (CC_IS_INPUT_ROW (row), NULL);
+  return row->type;
+}
+
+const gchar *
+cc_input_row_get_id (CcInputRow *row)
+{
+  g_return_val_if_fail (CC_IS_INPUT_ROW (row), NULL);
+  return row->id;
+}
+
+GDesktopAppInfo *
+cc_input_row_get_app_info (CcInputRow *row)
+{
+  g_return_val_if_fail (CC_IS_INPUT_ROW (row), NULL);
+  return row->app_info;
+}
+
+void
+cc_input_row_set_label (CcInputRow  *row,
+                        const gchar *text)
+{
+  g_return_if_fail (CC_IS_INPUT_ROW (row));
+  gtk_label_set_text (GTK_LABEL (row->name_label), text);
+}
+
+void
+cc_input_row_set_is_input_method (CcInputRow  *row,
+                                  gboolean is_input_method)
+{
+  g_return_if_fail (CC_IS_INPUT_ROW (row));
+  gtk_widget_set_visible (row->icon_image, is_input_method);
+}
diff --git a/panels/region/cc-input-row.h b/panels/region/cc-input-row.h
new file mode 100644
index 000000000..dba8b6158
--- /dev/null
+++ b/panels/region/cc-input-row.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <gio/gdesktopappinfo.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INPUT_ROW (cc_input_row_get_type ())
+G_DECLARE_FINAL_TYPE (CcInputRow, cc_input_row, CC, INPUT_ROW, GtkListBoxRow)
+
+CcInputRow      *cc_input_row_new                 (const gchar     *type,
+                                                   const gchar     *id,
+                                                   GDesktopAppInfo *app_info);
+
+const gchar     *cc_input_row_get_input_type      (CcInputRow      *row);
+
+const gchar     *cc_input_row_get_id              (CcInputRow      *row);
+
+GDesktopAppInfo *cc_input_row_get_app_info        (CcInputRow      *row);
+
+void             cc_input_row_set_label           (CcInputRow      *row,
+                                                   const gchar     *text);
+
+void             cc_input_row_set_is_input_method (CcInputRow      *row,
+                                                   gboolean         is_input_method);
+
+G_END_DECLS
diff --git a/panels/region/cc-input-row.ui b/panels/region/cc-input-row.ui
new file mode 100644
index 000000000..ad8212b08
--- /dev/null
+++ b/panels/region/cc-input-row.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+
+  <template class="CcInputRow" parent="GtkListBoxRow">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="activatable">True</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="border-width">18</property>
+        <child>
+          <object class="GtkLabel" id="name_label">
+            <property name="visible">True</property>
+            <property name="xalign">0.0</property>
+            <property name="hexpand">True</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkImage" id="icon_image">
+            <property name="visible">True</property>
+            <property name="icon_name">system-run-symbolic</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/panels/region/cc-region-panel.c b/panels/region/cc-region-panel.c
index b20106d09..c733592e8 100644
--- a/panels/region/cc-region-panel.c
+++ b/panels/region/cc-region-panel.c
@@ -33,6 +33,7 @@
 #include "cc-format-chooser.h"
 #include "cc-input-chooser.h"
 #include "cc-input-options.h"
+#include "cc-input-row.h"
 
 #include "cc-common-language.h"
 
@@ -629,25 +630,19 @@ update_ibus_active_sources (CcRegionPanel *self)
 {
         g_autoptr(GList) rows = NULL;
         GList *l;
-        GtkWidget *row;
-        const gchar *type;
-        const gchar *id;
-        IBusEngineDesc *engine_desc;
-        GtkWidget *label;
 
         rows = gtk_container_get_children (GTK_CONTAINER (self->input_list));
         for (l = rows; l; l = l->next) {
-                row = l->data;
-                type = g_object_get_data (G_OBJECT (row), "type");
-                id = g_object_get_data (G_OBJECT (row), "id");
-                if (g_strcmp0 (type, INPUT_SOURCE_TYPE_IBUS) != 0)
+                CcInputRow *row = CC_INPUT_ROW (l->data);
+                IBusEngineDesc *engine_desc;
+
+                if (g_strcmp0 (cc_input_row_get_input_type (row), INPUT_SOURCE_TYPE_IBUS) != 0)
                         continue;
 
-                engine_desc = g_hash_table_lookup (self->ibus_engines, id);
+                engine_desc = g_hash_table_lookup (self->ibus_engines, cc_input_row_get_id (row));
                 if (engine_desc) {
                         g_autofree gchar *display_name = engine_get_display_name (engine_desc);
-                        label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "label"));
-                        gtk_label_set_text (GTK_LABEL (label), display_name);
+                        cc_input_row_set_label (row, display_name);
                 }
         }
 }
@@ -749,58 +744,28 @@ remove_no_input_row (GtkContainer *list)
                 return;
         if (l->next != NULL)
                 return;
-        if (g_strcmp0 (g_object_get_data (G_OBJECT (l->data), "type"), "none") == 0)
+        if (g_strcmp0 (cc_input_row_get_input_type (CC_INPUT_ROW (l->data)), "none") == 0)
                 gtk_container_remove (list, GTK_WIDGET (l->data));
 }
 
-static GtkWidget *
+static void
 add_input_row (CcRegionPanel   *self,
                const gchar     *type,
                const gchar     *id,
                const gchar     *name,
                GDesktopAppInfo *app_info)
 {
-        GtkWidget *row;
-        GtkWidget *box;
-        GtkWidget *label;
-        GtkWidget *image;
+        CcInputRow *row;
 
         remove_no_input_row (GTK_CONTAINER (self->input_list));
 
-        row = gtk_list_box_row_new ();
-        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-        gtk_container_add (GTK_CONTAINER (row), box);
-        label = gtk_label_new (name);
-        gtk_widget_set_halign (label, GTK_ALIGN_START);
-        gtk_widget_set_margin_start (label, 20);
-        gtk_widget_set_margin_end (label, 20);
-        gtk_widget_set_margin_top (label, 18);
-        gtk_widget_set_margin_bottom (label, 18);
-        gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
-
-        if (strcmp (type, INPUT_SOURCE_TYPE_IBUS) == 0) {
-                image = gtk_image_new_from_icon_name ("system-run-symbolic", GTK_ICON_SIZE_BUTTON);
-                gtk_widget_set_margin_start (image, 20);
-                gtk_widget_set_margin_end (image, 20);
-                gtk_widget_set_margin_top (image, 6);
-                gtk_widget_set_margin_bottom (image, 6);
-                gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
-                gtk_box_pack_start (GTK_BOX (box), image, FALSE, TRUE, 0);
-        }
-
-        gtk_widget_show_all (row);
-        gtk_container_add (GTK_CONTAINER (self->input_list), row);
-
-        g_object_set_data (G_OBJECT (row), "label", label);
-        g_object_set_data (G_OBJECT (row), "type", (gpointer)type);
-        g_object_set_data_full (G_OBJECT (row), "id", g_strdup (id), g_free);
-        if (app_info) {
-                g_object_set_data_full (G_OBJECT (row), "app-info", g_object_ref (app_info), g_object_unref);
-        }
+        row = cc_input_row_new (type, id, app_info);
+        gtk_widget_show (GTK_WIDGET (row));
+        cc_input_row_set_label (row, name);
+        cc_input_row_set_is_input_method (row, strcmp (type, INPUT_SOURCE_TYPE_IBUS) == 0);
+        gtk_container_add (GTK_CONTAINER (self->input_list), GTK_WIDGET (row));
 
         cc_list_box_adjust_scrolling (GTK_LIST_BOX (self->input_list));
-
-        return row;
 }
 
 static void
@@ -884,10 +849,8 @@ select_by_id (GtkWidget   *row,
               gpointer     data)
 {
         const gchar *id = data;
-        const gchar *row_id;
 
-        row_id = (const gchar *)g_object_get_data (G_OBJECT (row), "id");
-        if (g_strcmp0 (row_id, id) == 0)
+        if (g_strcmp0 (cc_input_row_get_id (CC_INPUT_ROW (row)), id) == 0)
                 gtk_list_box_select_row (GTK_LIST_BOX (gtk_widget_get_parent (row)), GTK_LIST_BOX_ROW (row));
 }
 
@@ -904,12 +867,12 @@ input_sources_changed (GSettings     *settings,
                        const gchar   *key,
                        CcRegionPanel *self)
 {
-        GtkListBoxRow *selected;
+        CcInputRow *selected;
         g_autofree gchar *id = NULL;
 
-        selected = gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list));
+        selected = CC_INPUT_ROW (gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list)));
         if (selected)
-                id = g_strdup (g_object_get_data (G_OBJECT (selected), "id"));
+                id = g_strdup (cc_input_row_get_id (selected));
         clear_input_sources (self);
         add_input_sources_from_settings (self);
         if (id)
@@ -920,14 +883,14 @@ input_sources_changed (GSettings     *settings,
 static void
 update_buttons (CcRegionPanel *self)
 {
-        GtkListBoxRow *selected;
+        CcInputRow *selected;
         g_autoptr(GList) children = NULL;
         guint n_rows;
 
         children = gtk_container_get_children (GTK_CONTAINER (self->input_list));
         n_rows = g_list_length (children);
 
-        selected = gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list));
+        selected = CC_INPUT_ROW (gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list)));
         if (selected == NULL) {
                 gtk_widget_set_visible (self->show_config, FALSE);
                 gtk_widget_set_sensitive (self->remove_input, FALSE);
@@ -936,14 +899,16 @@ update_buttons (CcRegionPanel *self)
                 gtk_widget_set_sensitive (self->move_down_input, FALSE);
         } else {
                 GDesktopAppInfo *app_info;
+                gint index;
 
-                app_info = (GDesktopAppInfo *)g_object_get_data (G_OBJECT (selected), "app-info");
+                app_info = cc_input_row_get_app_info (selected);
+                index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (selected));
 
                 gtk_widget_set_visible (self->show_config, app_info != NULL);
                 gtk_widget_set_sensitive (self->show_layout, TRUE);
                 gtk_widget_set_sensitive (self->remove_input, n_rows > 1);
-                gtk_widget_set_sensitive (self->move_up_input, gtk_list_box_row_get_index (selected) > 0);
-                gtk_widget_set_sensitive (self->move_down_input, gtk_list_box_row_get_index (selected) < 
n_rows - 1);
+                gtk_widget_set_sensitive (self->move_up_input, index > 0);
+                gtk_widget_set_sensitive (self->move_down_input, index < n_rows - 1);
         }
 
         gtk_widget_set_visible (self->options_button,
@@ -953,8 +918,6 @@ update_buttons (CcRegionPanel *self)
 static void
 set_input_settings (CcRegionPanel *self)
 {
-        const gchar *type;
-        const gchar *id;
         GVariantBuilder builder;
         g_autoptr(GList) list = NULL;
         GList *l;
@@ -962,9 +925,8 @@ set_input_settings (CcRegionPanel *self)
         g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
         list = gtk_container_get_children (GTK_CONTAINER (self->input_list));
         for (l = list; l; l = l->next) {
-                type = (const gchar *)g_object_get_data (G_OBJECT (l->data), "type");
-                id = (const gchar *)g_object_get_data (G_OBJECT (l->data), "id");
-                g_variant_builder_add (&builder, "(ss)", type, id);
+                CcInputRow *row = CC_INPUT_ROW (l->data);
+                g_variant_builder_add (&builder, "(ss)", cc_input_row_get_input_type (row), 
cc_input_row_get_id (row));
         }
 
         g_settings_set_value (self->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
@@ -994,7 +956,7 @@ input_source_already_added (CcRegionPanel *self,
 
         list = gtk_container_get_children (GTK_CONTAINER (self->input_list));
         for (l = list; l; l = l->next)
-                if (g_str_equal (id, (const gchar *) g_object_get_data (G_OBJECT (l->data), "id"))) {
+                if (g_str_equal (id, cc_input_row_get_id (CC_INPUT_ROW (l->data)))) {
                         return TRUE;
                 }
 
@@ -1201,26 +1163,24 @@ move_selected_input_down (CcRegionPanel *self)
 static void
 show_selected_settings (CcRegionPanel *self)
 {
-        GtkListBoxRow *selected;
+        CcInputRow *selected;
         g_autoptr(GdkAppLaunchContext) ctx = NULL;
         GDesktopAppInfo *app_info;
-        const gchar *id;
         g_autoptr(GError) error = NULL;
 
-        selected = gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list));
+        selected = CC_INPUT_ROW (gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list)));
         if (selected == NULL)
                 return;
 
-        app_info = (GDesktopAppInfo *)g_object_get_data (G_OBJECT (selected), "app-info");
+        app_info = cc_input_row_get_app_info (selected);
         if  (app_info == NULL)
                 return;
 
         ctx = gdk_display_get_app_launch_context (gdk_display_get_default ());
         gdk_app_launch_context_set_timestamp (ctx, gtk_get_current_event_time ());
 
-        id = (const gchar *)g_object_get_data (G_OBJECT (selected), "id");
         g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (ctx),
-                                     "IBUS_ENGINE_NAME", id);
+                                     "IBUS_ENGINE_NAME", cc_input_row_get_id (selected));
 
         if (!g_app_info_launch (G_APP_INFO (app_info), NULL, G_APP_LAUNCH_CONTEXT (ctx), &error))
                 g_warning ("Failed to launch input source setup: %s", error->message);
@@ -1229,20 +1189,18 @@ show_selected_settings (CcRegionPanel *self)
 static void
 show_selected_layout (CcRegionPanel *self)
 {
-        GtkListBoxRow *selected;
-        const gchar *type;
-        const gchar *id;
+        CcInputRow *selected;
+        const gchar *type, *id;
         const gchar *layout;
         const gchar *variant;
         g_autofree gchar *commandline = NULL;
 
-        selected = gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list));
+        selected = CC_INPUT_ROW (gtk_list_box_get_selected_row (GTK_LIST_BOX (self->input_list)));
         if (selected == NULL)
                 return;
 
-        type = (const gchar *)g_object_get_data (G_OBJECT (selected), "type");
-        id = (const gchar *)g_object_get_data (G_OBJECT (selected), "id");
-
+        type = cc_input_row_get_input_type (selected);
+        id = cc_input_row_get_id (selected);
         if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
                 gnome_xkb_info_get_layout_info (self->xkb_info,
                                                 id, NULL, NULL,
@@ -1475,22 +1433,21 @@ set_localed_input (CcRegionPanel *self)
 {
         g_autoptr(GString) layouts = NULL;
         g_autoptr(GString) variants = NULL;
-        const gchar *type, *id;
         g_autoptr(GList) list = NULL;
         GList *li;
-        const gchar *l, *v;
 
         layouts = g_string_new ("");
         variants = g_string_new ("");
 
         list = gtk_container_get_children (GTK_CONTAINER (self->input_list));
         for (li = list; li; li = li->next) {
-                type = (const gchar *)g_object_get_data (G_OBJECT (li->data), "type");
-                id = (const gchar *)g_object_get_data (G_OBJECT (li->data), "id");
-                if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
+                CcInputRow *row = CC_INPUT_ROW (li->data);
+                const gchar *l, *v;
+
+                if (g_str_equal (cc_input_row_get_input_type (row), INPUT_SOURCE_TYPE_IBUS))
                         continue;
 
-                if (gnome_xkb_info_get_layout_info (self->xkb_info, id, NULL, NULL, &l, &v)) {
+                if (gnome_xkb_info_get_layout_info (self->xkb_info, cc_input_row_get_id (row), NULL, NULL, 
&l, &v)) {
                         if (layouts->str[0]) {
                                 g_string_append_c (layouts, ',');
                                 g_string_append_c (variants, ',');
diff --git a/panels/region/meson.build b/panels/region/meson.build
index 5c0a6f5db..1ab0019d5 100644
--- a/panels/region/meson.build
+++ b/panels/region/meson.build
@@ -22,7 +22,8 @@ sources = files(
   'cc-format-chooser.c',
   'cc-ibus-utils.c',
   'cc-input-chooser.c',
-  'cc-input-options.c'
+  'cc-input-options.c',
+  'cc-input-row.c',
 )
 
 resource_data = files(
diff --git a/panels/region/region.gresource.xml b/panels/region/region.gresource.xml
index 73ce4c167..b896bd701 100644
--- a/panels/region/region.gresource.xml
+++ b/panels/region/region.gresource.xml
@@ -3,6 +3,7 @@
   <gresource prefix="/org/gnome/control-center/region">
     <file preprocess="xml-stripblanks">region.ui</file>
     <file preprocess="xml-stripblanks">cc-format-chooser.ui</file>
+    <file preprocess="xml-stripblanks">cc-input-row.ui</file>
     <file preprocess="xml-stripblanks">input-options.ui</file>
     <file preprocess="xml-stripblanks">input-chooser.ui</file>
   </gresource>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]