Commit e8a0e799 authored by Daniel García Moreno's avatar Daniel García Moreno

New lang button widget

See #16
parent b4ec2629
/*
* 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);
}
/*
* 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
<?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>
......@@ -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 *
......
......@@ -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>
......
......@@ -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>
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment