[gtranslator: 2/5] New lang button widget
- From: Daniel Garcia Moreno <danigm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtranslator: 2/5] New lang button widget
- Date: Fri, 26 Oct 2018 17:08:22 +0000 (UTC)
commit e8a0e79989ce6fe7284ba609b3d8668d6c473991
Author: Daniel GarcĂa Moreno <danigm wadobo com>
Date: Thu Oct 25 14:59:29 2018 +0200
New lang button widget
See #16
src/gtr-lang-button.c | 209 ++++++++++++++++++++++++++++++++++++++++++
src/gtr-lang-button.h | 35 +++++++
src/gtr-lang-button.ui | 74 +++++++++++++++
src/gtr-languages-fetcher.c | 96 +++++++------------
src/gtr-languages-fetcher.ui | 10 +-
src/gtranslator.gresource.xml | 1 +
src/meson.build | 3 +-
7 files changed, 354 insertions(+), 74 deletions(-)
---
diff --git a/src/gtr-lang-button.c b/src/gtr-lang-button.c
new file mode 100644
index 00000000..918c3441
--- /dev/null
+++ b/src/gtr-lang-button.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2018 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-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;
+};
+
+enum
+{
+ CHANGED,
+ 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);
+
+ 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)
+{
+ GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (GTR_LANG_BUTTON (object));
+
+ g_clear_pointer (&priv->lang_name, g_free);
+
+ G_OBJECT_CLASS (gtr_lang_button_parent_class)->finalize (object);
+}
+
+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));
+
+ 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);
+}
+
+GtrLangButton*
+gtr_lang_button_new () {
+ GtrLangButton *self = g_object_new (GTR_TYPE_LANG_BUTTON, NULL);
+ return self;
+}
+
+const gchar *
+gtr_lang_button_get_lang (GtrLangButton *self)
+{
+ GtrLangButtonPrivate *priv = gtr_lang_button_get_instance_private (self);
+ return priv->lang_name;
+}
+
+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);
+}
+
diff --git a/src/gtr-lang-button.h b/src/gtr-lang-button.h
new file mode 100644
index 00000000..cacd69fe
--- /dev/null
+++ b/src/gtr-lang-button.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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_LANG_BUTTON (gtr_lang_button_get_type())
+
+G_DECLARE_FINAL_TYPE (GtrLangButton, gtr_lang_button, GTR, LANG_BUTTON, GtkMenuButton)
+
+GtrLangButton* gtr_lang_button_new ();
+const gchar * gtr_lang_button_get_lang (GtrLangButton *self);
+void gtr_lang_button_set_lang (GtrLangButton *self,
+ const gchar *name);
+
+G_END_DECLS
+
diff --git a/src/gtr-lang-button.ui b/src/gtr-lang-button.ui
new file mode 100644
index 00000000..fe5c693b
--- /dev/null
+++ b/src/gtr-lang-button.ui
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <object class="GtkPopover" id="popup">
+ <property name="can_focus">False</property>
+ <property name="position">right</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">6</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkEntry" id="lang">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="height_request">200</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkListBox" id="lang_list">
+ <property name="name">lang_list</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <template class="GtrLangButton" parent="GtkMenuButton">
+ <property name="label" translatable="yes">Choose Language</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="popover">popup</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Choose Language</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/gtr-languages-fetcher.c b/src/gtr-languages-fetcher.c
index 9f49435b..4068bce8 100644
--- a/src/gtr-languages-fetcher.c
+++ b/src/gtr-languages-fetcher.c
@@ -22,6 +22,7 @@
#include "gtr-languages-fetcher.h"
#include "gtr-language.h"
#include "gtr-utils.h"
+#include "gtr-lang-button.h"
#include <string.h>
typedef struct
@@ -34,7 +35,6 @@ typedef struct
GtkWidget *plural_forms;
GtkWidget *advanced;
- GtkListStore *language_store;
GtkListStore *code_store;
} GtrLanguagesFetcherPrivate;
@@ -78,22 +78,6 @@ gtr_languages_fetcher_class_init (GtrLanguagesFetcherClass *klass)
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 gint
compare_languages_code (gconstpointer a,
gconstpointer b)
@@ -120,20 +104,6 @@ append_from_languages (GtrLanguagesFetcher *fetcher)
plurals = g_hash_table_new (g_str_hash, g_int_equal);
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;
- GtkTreeIter iter1;
-
- gtk_list_store_append (priv->language_store, &iter1);
- gtk_list_store_set (priv->language_store, &iter1,
- 0, gtr_language_get_name (lang),
- 1, lang,
- -1);
- }
-
languages = g_slist_sort ((GSList *)languages, compare_languages_code);
for (l = languages; l != NULL; l = g_slist_next (l))
@@ -211,7 +181,7 @@ fill_from_language_code_entry (GtrLanguagesFetcher *fetcher,
fill_encoding_and_charset (fetcher);
- entry_text = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->language))));
+ entry_text = gtr_lang_button_get_lang (GTR_LANG_BUTTON (priv->language));
if (*entry_text == '\0')
{
@@ -220,7 +190,7 @@ fill_from_language_code_entry (GtrLanguagesFetcher *fetcher,
name = gtr_language_get_name (lang);
if (name != NULL && *name != '\0')
- gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->language))), name);
+ gtr_lang_button_set_lang (GTR_LANG_BUTTON (priv->language), name);
}
entry_text = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->plural_forms))));
@@ -240,18 +210,15 @@ typedef void (* fill_method) (GtrLanguagesFetcher *fetcher, GtrLanguage *lang);
static void
fill_boxes (GtrLanguagesFetcher *fetcher,
- GtkEntry *entry,
+ const gchar *text,
GtkTreeModel *store,
fill_method fill)
{
- const gchar *text;
gchar *entry_row;
GtkTreeIter iter;
GtrLanguage *lang;
gboolean found = FALSE;
- text = gtk_entry_get_text (entry);
-
if (text == NULL || *text == '\0' ||
!gtk_tree_model_get_iter_first (store, &iter))
return;
@@ -284,30 +251,35 @@ fill_boxes (GtrLanguagesFetcher *fetcher,
}
static void
-on_language_activate (GtkEntry *entry,
+on_language_activate (GtrLangButton *btn,
GtrLanguagesFetcher *fetcher)
{
GtrLanguagesFetcherPrivate *priv = gtr_languages_fetcher_get_instance_private (fetcher);
- fill_boxes (fetcher, entry, GTK_TREE_MODEL (priv->language_store),
- fill_from_language_entry);
-}
-
-static gboolean
-on_language_focus_out_event (GtkEntry *entry,
- GdkEvent *event,
- GtrLanguagesFetcher *fetcher)
-{
- on_language_activate (entry, fetcher);
+ const gchar *text = gtr_lang_button_get_lang (GTR_LANG_BUTTON (priv->language));
+ GtrLanguage *lang;
+ const GSList *l;
+ const GSList *languages = gtr_language_get_languages ();
- return FALSE;
+ for (l = languages; l != NULL; l = g_slist_next (l))
+ {
+ lang = (GtrLanguage*)l->data;
+ const gchar *langname = gtr_language_get_name (lang);
+ if (text != NULL && strcmp (langname, text) == 0)
+ {
+ fill_from_language_entry (fetcher, lang);
+ break;
+ }
+ }
}
static void
-on_language_code_activate (GtkEntry *entry,
+on_language_code_activate (GtkEntry *entry,
GtrLanguagesFetcher *fetcher)
{
GtrLanguagesFetcherPrivate *priv = gtr_languages_fetcher_get_instance_private (fetcher);
- fill_boxes (fetcher, entry, GTK_TREE_MODEL (priv->code_store),
+ const gchar *text = gtk_entry_get_text (entry);
+
+ fill_boxes (fetcher, text, GTK_TREE_MODEL (priv->code_store),
fill_from_language_code_entry);
}
@@ -346,9 +318,7 @@ on_lang_changed (GtkWidget *widget,
GtrLanguagesFetcher *fetcher)
{
GtrLanguagesFetcherPrivate *priv = gtr_languages_fetcher_get_instance_private (fetcher);
- GtkWidget *entry = gtk_bin_get_child (GTK_BIN (priv->language));
-
- on_language_activate (GTK_ENTRY (entry), fetcher);
+ on_language_activate (GTR_LANG_BUTTON (priv->language), fetcher);
g_signal_emit (fetcher, signals[CHANGED], 0, NULL);
}
@@ -359,7 +329,6 @@ gtr_languages_fetcher_init (GtrLanguagesFetcher *fetcher)
GtkBuilder *builder;
gchar *root_objects[] = {
"main_box",
- "language_store",
"code_store",
NULL
};
@@ -368,9 +337,12 @@ gtr_languages_fetcher_init (GtrLanguagesFetcher *fetcher)
gtk_orientable_set_orientation (GTK_ORIENTABLE (fetcher),
GTK_ORIENTATION_VERTICAL);
+ g_type_ensure (gtr_lang_button_get_type ());
+
builder = gtk_builder_new ();
gtk_builder_add_objects_from_resource (builder, "/org/gnome/translator/gtr-languages-fetcher.ui",
root_objects, NULL);
+
content = GTK_WIDGET (gtk_builder_get_object (builder, "main_box"));
g_object_ref (content);
priv->language = GTK_WIDGET (gtk_builder_get_object (builder, "language"));
@@ -379,8 +351,8 @@ gtr_languages_fetcher_init (GtrLanguagesFetcher *fetcher)
priv->encoding = GTK_WIDGET (gtk_builder_get_object (builder, "encoding"));
priv->plural_forms = GTK_WIDGET (gtk_builder_get_object (builder, "plural_forms"));
priv->advanced = GTK_WIDGET (gtk_builder_get_object (builder, "advanced_check"));
- priv->language_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "language_store"));
priv->code_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "code_store"));
+
g_object_unref (builder);
gtk_box_pack_start (GTK_BOX (fetcher), content, FALSE, FALSE, 0);
@@ -388,14 +360,10 @@ gtr_languages_fetcher_init (GtrLanguagesFetcher *fetcher)
/* add items to comboboxes */
append_from_languages (fetcher);
- g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->language)),
- "activate",
+ g_signal_connect (G_OBJECT (priv->language),
+ "clicked",
G_CALLBACK (on_language_activate),
fetcher);
- g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->language)),
- "focus-out-event",
- G_CALLBACK (on_language_focus_out_event),
- fetcher);
g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->language_code)),
"activate",
G_CALLBACK (on_language_code_activate),
@@ -439,7 +407,7 @@ gtr_languages_fetcher_get_language_name (GtrLanguagesFetcher *fetcher)
GtrLanguagesFetcherPrivate *priv = gtr_languages_fetcher_get_instance_private (fetcher);
g_return_val_if_fail (GTR_IS_LANGUAGES_FETCHER (fetcher), NULL);
- return gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->language))));
+ return gtr_lang_button_get_lang (GTR_LANG_BUTTON (priv->language));
}
void
@@ -450,7 +418,7 @@ gtr_languages_fetcher_set_language_name (GtrLanguagesFetcher *fetcher,
g_return_if_fail (GTR_IS_LANGUAGES_FETCHER (fetcher));
g_return_if_fail (name != NULL);
- gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->language))), name);
+ gtr_lang_button_set_lang (GTR_LANG_BUTTON (priv->language), name);
}
const gchar *
diff --git a/src/gtr-languages-fetcher.ui b/src/gtr-languages-fetcher.ui
index 80c9064c..f3d074cb 100644
--- a/src/gtr-languages-fetcher.ui
+++ b/src/gtr-languages-fetcher.ui
@@ -185,18 +185,10 @@
</packing>
</child>
<child>
- <object class="GtkComboBox" id="language">
+ <object class="GtrLangButton" id="language">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
- <property name="model">language_store</property>
- <property name="has_entry">True</property>
- <property name="entry_text_column">0</property>
- <child internal-child="entry">
- <object class="GtkEntry">
- <property name="can_focus">True</property>
- </object>
- </child>
</object>
<packing>
<property name="left_attach">1</property>
diff --git a/src/gtranslator.gresource.xml b/src/gtranslator.gresource.xml
index bf790226..b67c3071 100644
--- a/src/gtranslator.gresource.xml
+++ b/src/gtranslator.gresource.xml
@@ -17,6 +17,7 @@
<file preprocess="xml-stripblanks">gtr-tab.ui</file>
<file preprocess="xml-stripblanks">gtr-window.ui</file>
<file preprocess="xml-stripblanks">gtr-projects.ui</file>
+ <file preprocess="xml-stripblanks">gtr-lang-button.ui</file>
<file preprocess="xml-stripblanks">help-overlay.ui</file>
</gresource>
</gresources>
diff --git a/src/meson.build b/src/meson.build
index 88bff489..7274aa66 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -62,6 +62,7 @@ sources = files(
'gtr-utils.c',
'gtr-view.c',
'gtr-projects.c',
+ 'gtr-lang-button.c',
'gtr-progress.c',
'gtr-window.c',
)
@@ -146,4 +147,4 @@ executable(
dependencies: gtr_deps,
objects: libgtranslator.extract_all_objects(),
install: true,
-)
+)
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]