[gtranslator] Add Generic filter selection widget



commit 127603005cca81f75ae087ff7d07ca1b233269fa
Author: Daniel GarcĂ­a Moreno <dani danigm net>
Date:   Sun May 19 11:43:36 2019 +0200

    Add Generic filter selection widget
    
    We've a custom widget for the language selection with a long text list
    and a filter text entry. We can use this widget in the DL selection
    because we're currenlty using comboboxes and we've a lot of options,
    it'll be easier if we reuse this widget.
    
    This patch generalizes the widget to be able to use there.

 src/gtr-dl-teams.c                                 |   2 -
 src/gtr-filter-selection.c                         | 206 +++++++++++++++++++++
 src/gtr-filter-selection.h                         |  50 +++++
 ...{gtr-lang-button.ui => gtr-filter-selection.ui} |  14 +-
 src/gtr-lang-button.c                              | 159 ++--------------
 src/gtr-lang-button.h                              |   3 +-
 src/gtranslator.gresource.xml                      |   2 +-
 src/meson.build                                    |   1 +
 8 files changed, 285 insertions(+), 152 deletions(-)
---
diff --git a/src/gtr-dl-teams.c b/src/gtr-dl-teams.c
index cc51e8f6..a508f640 100644
--- a/src/gtr-dl-teams.c
+++ b/src/gtr-dl-teams.c
@@ -49,8 +49,6 @@ typedef struct
 
   GtkListStore *teams_store;
   GtkListStore *modules_store;
-  GtkListStore *domains_store;
-  GtkListStore *branches_store;
 
   gchar *selected_team;
   gchar *selected_module;
diff --git a/src/gtr-filter-selection.c b/src/gtr-filter-selection.c
new file mode 100644
index 00000000..1e3affd0
--- /dev/null
+++ b/src/gtr-filter-selection.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2019  Daniel Garcia Moreno <danigm gnome org>
+ *
+ * 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 3 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/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gtr-filter-selection.h"
+
+typedef struct
+{
+  GtkWidget *entry;
+  GtkWidget *option_list;
+  GtkWidget *popup;
+  GSList *options;
+  // TODO: manage this as a property
+  char *option;
+
+} GtrFilterSelectionPrivate;
+
+enum
+{
+  CHANGED,
+  LAST_SIGNAL
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtrFilterSelection, gtr_filter_selection, GTK_TYPE_MENU_BUTTON)
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+change_option (GtkListBox         *box,
+               GtkListBoxRow      *row,
+               GtrFilterSelection *self)
+{
+  GtrFilterSelectionPrivate *priv = gtr_filter_selection_get_instance_private (self);
+  GtkWidget *label = gtk_bin_get_child (GTK_BIN (row));
+  gtr_filter_selection_set_option (self, gtk_label_get_text (GTK_LABEL (label)));
+
+  gtk_popover_popdown (GTK_POPOVER (priv->popup));
+}
+
+static void
+filter_option (GtkEditable        *entry,
+               GtrFilterSelection *self)
+{
+  GtrFilterSelectionPrivate *priv = gtr_filter_selection_get_instance_private (self);
+  const char *text = gtk_entry_get_text (GTK_ENTRY (entry));
+  g_autofree char *uptext = g_ascii_strup (text, -1);
+  const GSList *o;
+  GList *children;
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->option_list));
+  while (children)
+    {
+      GtkWidget *w = GTK_WIDGET (children->data);
+      gtk_container_remove (GTK_CONTAINER (priv->option_list), w);
+      children = g_list_next (children);
+    }
+
+  for (o = priv->options; o != NULL; o = g_slist_next (o))
+    {
+      GtkWidget *child;
+      const char *opt = (char *)o->data;
+      g_autofree char *upopt = g_ascii_strup (opt, -1);
+
+      if (g_strrstr (upopt, uptext) == NULL)
+        continue;
+
+      child = gtk_label_new (opt);
+      gtk_label_set_xalign (GTK_LABEL (child), 0.0);
+      gtk_container_add (GTK_CONTAINER (priv->option_list), child);
+    }
+  gtk_widget_show_all (priv->option_list);
+}
+
+static void
+gtr_filter_selection_finalize (GObject *object)
+{
+  GtrFilterSelectionPrivate *priv = gtr_filter_selection_get_instance_private (GTR_FILTER_SELECTION 
(object));
+  g_clear_pointer (&priv->option, g_free);
+  if (priv->options)
+    g_slist_free_full (priv->options, g_free);
+  G_OBJECT_CLASS (gtr_filter_selection_parent_class)->finalize (object);
+}
+
+static void
+gtr_filter_selection_class_init (GtrFilterSelectionClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gtr_filter_selection_finalize;
+
+  signals[CHANGED] =
+    g_signal_newv ("changed",
+                   G_OBJECT_CLASS_TYPE (object_class),
+                   G_SIGNAL_RUN_LAST,
+                   NULL, NULL, NULL, NULL,
+                   G_TYPE_NONE, 0, NULL);
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/translator/gtr-filter-selection.ui");
+
+  gtk_widget_class_bind_template_child_private (widget_class, GtrFilterSelection, entry);
+  gtk_widget_class_bind_template_child_private (widget_class, GtrFilterSelection, option_list);
+  gtk_widget_class_bind_template_child_private (widget_class, GtrFilterSelection, popup);
+}
+
+static void
+gtr_filter_selection_init (GtrFilterSelection *self)
+{
+  GtrFilterSelectionPrivate *priv = gtr_filter_selection_get_instance_private (self);
+  priv->option = NULL;
+  priv->options = NULL;
+  gtk_widget_init_template (GTK_WIDGET (self));
+  gtk_widget_show_all (priv->option_list);
+
+  g_signal_connect (priv->option_list,
+                    "row-activated",
+                    G_CALLBACK (change_option),
+                    self);
+
+  g_signal_connect (priv->entry,
+                    "changed",
+                    G_CALLBACK (filter_option),
+                    self);
+}
+
+GtrFilterSelection*
+gtr_filter_selection_new () {
+  GtrFilterSelection *self = g_object_new (GTR_TYPE_FILTER_SELECTION, NULL);
+  return self;
+}
+
+const char *
+gtr_filter_selection_get_option (GtrFilterSelection *self)
+{
+  GtrFilterSelectionPrivate *priv = gtr_filter_selection_get_instance_private (self);
+  return priv->option;
+}
+
+void
+gtr_filter_selection_set_option (GtrFilterSelection *self,
+                                 const char         *option)
+{
+  GtrFilterSelectionPrivate *priv = gtr_filter_selection_get_instance_private (self);
+  g_clear_pointer (&priv->option, g_free);
+  priv->option = g_strdup (option);
+  gtk_button_set_label (GTK_BUTTON (self), option);
+  g_signal_emit (self, signals[CHANGED], 0, NULL);
+}
+
+void
+gtr_filter_selection_set_options (GtrFilterSelection *self,
+                                  GSList *options)
+{
+  GtrFilterSelectionPrivate *priv = gtr_filter_selection_get_instance_private (self);
+  const GSList *o;
+  GList *children;
+
+  if (priv->options)
+    g_slist_free_full (priv->options, g_free);
+  priv->options = options;
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->option_list));
+  while (children)
+    {
+      GtkWidget *w = GTK_WIDGET (children->data);
+      gtk_container_remove (GTK_CONTAINER (priv->option_list), w);
+      children = g_list_next (children);
+    }
+
+  for (o = priv->options; o != NULL; o = g_slist_next (o))
+    {
+      const char *opt = (char *)o->data;
+      GtkWidget *child = gtk_label_new (opt);
+      gtk_label_set_xalign (GTK_LABEL (child), 0.0);
+      gtk_container_add (GTK_CONTAINER (priv->option_list), child);
+    }
+
+  gtk_widget_show_all (priv->option_list);
+}
+
+void
+gtr_filter_selection_set_text (GtrFilterSelection *selection,
+                               const char *text)
+{
+  gtk_button_set_label (GTK_BUTTON (selection), text);
+}
+
diff --git a/src/gtr-filter-selection.h b/src/gtr-filter-selection.h
new file mode 100644
index 00000000..5e94efa8
--- /dev/null
+++ b/src/gtr-filter-selection.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019  Daniel Garcia Moreno <danigm gnome org>
+ *
+ * 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 3 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>
+
+G_BEGIN_DECLS
+
+#define GTR_TYPE_FILTER_SELECTION (gtr_filter_selection_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GtrFilterSelection, gtr_filter_selection, GTR, FILTER_SELECTION, GtkMenuButton)
+
+struct _GtrFilterSelectionClass
+{
+  GtkMenuButtonClass parent_class;
+};
+
+GtrFilterSelection*  gtr_filter_selection_new             ();
+
+void
+gtr_filter_selection_set_text (GtrFilterSelection *selection,
+                               const char *text);
+
+void
+gtr_filter_selection_set_options (GtrFilterSelection *self,
+                                  GSList *options);
+const char *
+gtr_filter_selection_get_option (GtrFilterSelection *self);
+void
+gtr_filter_selection_set_option (GtrFilterSelection *self,
+                                 const char         *option);
+
+G_END_DECLS
+
diff --git a/src/gtr-lang-button.ui b/src/gtr-filter-selection.ui
similarity index 86%
rename from src/gtr-lang-button.ui
rename to src/gtr-filter-selection.ui
index bf0d9e42..1029f02a 100644
--- a/src/gtr-lang-button.ui
+++ b/src/gtr-filter-selection.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1 -->
+<!-- Generated with glade 3.22.0 -->
 <interface>
   <requires lib="gtk+" version="3.12"/>
   <object class="GtkPopover" id="popup">
@@ -16,7 +16,7 @@
         <property name="orientation">vertical</property>
         <property name="spacing">4</property>
         <child>
-          <object class="GtkEntry" id="lang">
+          <object class="GtkEntry" id="entry">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
           </object>
@@ -38,8 +38,8 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <child>
-                  <object class="GtkListBox" id="lang_list">
-                    <property name="name">lang_list</property>
+                  <object class="GtkListBox" id="option_list">
+                    <property name="name">option_list</property>
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="vexpand">True</property>
@@ -57,8 +57,8 @@
       </object>
     </child>
   </object>
-  <template class="GtrLangButton" parent="GtkMenuButton">
-    <property name="label" translatable="yes">Choose Language</property>
+  <template class="GtrFilterSelection" parent="GtkMenuButton">
+    <property name="label" translatable="no">Choose Option</property>
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="receives_default">False</property>
@@ -67,7 +67,7 @@
       <object class="GtkLabel">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="label" translatable="yes">Choose _Language</property>
+        <property name="label">Choose Option</property>
         <property name="use_underline">True</property>
       </object>
     </child>
diff --git a/src/gtr-lang-button.c b/src/gtr-lang-button.c
index 918c3441..a6550e56 100644
--- a/src/gtr-lang-button.c
+++ b/src/gtr-lang-button.c
@@ -20,21 +20,14 @@
 #include <config.h>
 #endif
 
+#include <glib/gi18n.h>
+
 #include "gtr-language.h"
 #include "gtr-lang-button.h"
 
-typedef struct
-{
-  GtkWidget *lang;
-  GtkWidget *lang_list;
-  GtkWidget *popup;
-  gchar *lang_name;
-
-} GtrLangButtonPrivate;
-
 struct _GtrLangButton
 {
-  GtkMenuButton parent_instance;
+  GtrFilterSelection parent_instance;
 };
 
 enum
@@ -43,144 +36,33 @@ enum
   LAST_SIGNAL
 };
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtrLangButton, gtr_lang_button, GTK_TYPE_MENU_BUTTON)
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static gint
-compare_languages_name (gconstpointer a,
-                        gconstpointer b)
-{
-  GtrLanguage *lang1, *lang2;
-  const gchar *name1, *name2;
-
-  lang1 = (GtrLanguage *) a;
-  lang2 = (GtrLanguage *) b;
-
-  name1 = gtr_language_get_name (lang1);
-  name2 = gtr_language_get_name (lang2);
-
-  return g_utf8_collate (name1, name2);
-}
-
-static void
-change_language (GtkListBox    *box,
-                 GtkListBoxRow *row,
-                 GtrLangButton *self)
-{
-  GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (self);
-  GtkWidget *label = gtk_bin_get_child (GTK_BIN (row));
-  gtr_lang_button_set_lang (self, gtk_label_get_text (GTK_LABEL (label)));
-
-  gtk_popover_popdown (GTK_POPOVER (priv->popup));
-}
-
-static void
-filter_language (GtkEditable   *entry,
-                 GtrLangButton *self)
-{
-  GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (self);
-  const gchar *text = gtk_entry_get_text (GTK_ENTRY (entry));
-  gchar *uptext = g_ascii_strup (text, -1);
-  const GSList *languages, *l;
-  GList *children;
-
-  languages = gtr_language_get_languages ();
-  languages = g_slist_sort ((GSList*)languages, compare_languages_name);
-
-  children = gtk_container_get_children (GTK_CONTAINER (priv->lang_list));
-  while (children)
-    {
-      GtkWidget *w = GTK_WIDGET (children->data);
-      gtk_container_remove (GTK_CONTAINER (priv->lang_list), w);
-      children = g_list_next (children);
-    }
-
-  for (l = languages; l != NULL; l = g_slist_next (l))
-    {
-      GtrLanguage *lang = (GtrLanguage *)l->data;
-      const gchar *langname = gtr_language_get_name (lang);
-      GtkWidget *child;
-      gchar *uplang = g_ascii_strup (langname, -1);
-
-      if (g_strrstr (uplang, uptext) == NULL) {
-        g_free (uplang);
-        continue;
-      }
-      g_free (uplang);
+G_DEFINE_TYPE (GtrLangButton, gtr_lang_button, GTR_TYPE_FILTER_SELECTION)
 
-      child = gtk_label_new (langname);
-      gtk_label_set_xalign (GTK_LABEL (child), 0.0);
-      gtk_container_add (GTK_CONTAINER (priv->lang_list), child);
-    }
-  gtk_widget_show_all (priv->lang_list);
-
-  g_free (uptext);
-}
-
-static void
-gtr_lang_button_finalize (GObject *object)
+static gpointer
+copy_lang (gconstpointer src,
+           gpointer      data)
 {
-  GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (GTR_LANG_BUTTON (object));
-
-  g_clear_pointer (&priv->lang_name, g_free);
+  GtrLanguage *lang = (GtrLanguage *)src;
+  const gchar *langname = gtr_language_get_name (lang);
 
-  G_OBJECT_CLASS (gtr_lang_button_parent_class)->finalize (object);
+  return g_strdup ((char *)langname);
 }
 
 static void
 gtr_lang_button_class_init (GtrLangButtonClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
-  object_class->finalize = gtr_lang_button_finalize;
-
-  signals[CHANGED] =
-    g_signal_newv ("changed",
-                   G_OBJECT_CLASS_TYPE (object_class),
-                   G_SIGNAL_RUN_LAST,
-                   NULL, NULL, NULL, NULL,
-                   G_TYPE_NONE, 0, NULL);
-
-  gtk_widget_class_set_template_from_resource (widget_class,
-                                               "/org/gnome/translator/gtr-lang-button.ui");
-
-  gtk_widget_class_bind_template_child_private (widget_class, GtrLangButton, lang);
-  gtk_widget_class_bind_template_child_private (widget_class, GtrLangButton, lang_list);
-  gtk_widget_class_bind_template_child_private (widget_class, GtrLangButton, popup);
 }
 
 static void
 gtr_lang_button_init (GtrLangButton *self)
 {
-  const GSList *languages, *l;
-  GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (self);
-  gtk_widget_init_template (GTK_WIDGET (self));
-
+  const GSList *languages;
+  GSList *langs;
   languages = gtr_language_get_languages ();
-  languages = g_slist_sort ((GSList*)languages, compare_languages_name);
-
-  for (l = languages; l != NULL; l = g_slist_next (l))
-    {
-      GtrLanguage *lang = (GtrLanguage *)l->data;
-      GtkWidget *child = gtk_label_new (gtr_language_get_name (lang));
-      gtk_label_set_xalign (GTK_LABEL (child), 0.0);
-      gtk_container_add (GTK_CONTAINER (priv->lang_list), child);
-    }
-
-  gtk_widget_show_all (priv->lang_list);
-  priv->lang_name = NULL;
-
-  g_signal_connect (priv->lang_list,
-                    "row-activated",
-                    G_CALLBACK (change_language),
-                    self);
-
-  g_signal_connect (priv->lang,
-                    "changed",
-                    G_CALLBACK (filter_language),
-                    self);
+  langs = g_slist_copy_deep ((GSList *)languages, copy_lang, NULL);
+  langs = g_slist_sort (langs, (GCompareFunc)g_utf8_collate);
+  gtr_filter_selection_set_options (GTR_FILTER_SELECTION (self), langs);
+  gtr_filter_selection_set_text (GTR_FILTER_SELECTION (self), _("Choose Language"));
 }
 
 GtrLangButton*
@@ -192,18 +74,13 @@ gtr_lang_button_new () {
 const gchar *
 gtr_lang_button_get_lang (GtrLangButton *self)
 {
-  GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (self);
-  return priv->lang_name;
+  return gtr_filter_selection_get_option (GTR_FILTER_SELECTION (self));
 }
 
 void
 gtr_lang_button_set_lang (GtrLangButton *self,
                           const gchar   *name)
 {
-  GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (self);
-  g_clear_pointer (&priv->lang_name, g_free);
-  priv->lang_name = g_strdup (name);
-  gtk_button_set_label (GTK_BUTTON (self), name);
-  g_signal_emit (self, signals[CHANGED], 0, NULL);
+  gtr_filter_selection_set_option (GTR_FILTER_SELECTION (self), name);
 }
 
diff --git a/src/gtr-lang-button.h b/src/gtr-lang-button.h
index cacd69fe..d6bea82d 100644
--- a/src/gtr-lang-button.h
+++ b/src/gtr-lang-button.h
@@ -19,12 +19,13 @@
 #pragma once
 
 #include <gtk/gtk.h>
+#include "gtr-filter-selection.h"
 
 G_BEGIN_DECLS
 
 #define GTR_TYPE_LANG_BUTTON (gtr_lang_button_get_type())
 
-G_DECLARE_FINAL_TYPE (GtrLangButton, gtr_lang_button, GTR, LANG_BUTTON, GtkMenuButton)
+G_DECLARE_FINAL_TYPE (GtrLangButton, gtr_lang_button, GTR, LANG_BUTTON, GtrFilterSelection)
 
 GtrLangButton*  gtr_lang_button_new       ();
 const gchar *   gtr_lang_button_get_lang  (GtrLangButton *self);
diff --git a/src/gtranslator.gresource.xml b/src/gtranslator.gresource.xml
index 23f4841e..04d6c0db 100644
--- a/src/gtranslator.gresource.xml
+++ b/src/gtranslator.gresource.xml
@@ -18,7 +18,7 @@
     <file preprocess="xml-stripblanks">gtr-window.ui</file>
     <file preprocess="xml-stripblanks">gtr-projects.ui</file>
     <file preprocess="xml-stripblanks">gtr-dl-teams.ui</file>
-    <file preprocess="xml-stripblanks">gtr-lang-button.ui</file>
+    <file preprocess="xml-stripblanks">gtr-filter-selection.ui</file>
     <file preprocess="xml-stripblanks">help-overlay.ui</file>
   </gresource>
 </gresources>
diff --git a/src/meson.build b/src/meson.build
index 088bb4e6..be64e2d0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -64,6 +64,7 @@ sources = files(
   'gtr-view.c',
   'gtr-projects.c',
   'gtr-dl-teams.c',
+  'gtr-filter-selection.c',
   'gtr-lang-button.c',
   'gtr-progress.c',
   'gtr-window.c',


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