Compare commits
15 Commits
44.alpha
...
wip/input-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d47beb4561 | ||
|
|
ad2a238420 | ||
|
|
776cf56a7e | ||
|
|
ce92413af2 | ||
|
|
816a551cae | ||
|
|
e21d9313ea | ||
|
|
1d6f62e026 | ||
|
|
2c09c8e0ff | ||
|
|
5e7dc53d9b | ||
|
|
3e7c33f2e1 | ||
|
|
67302794ae | ||
|
|
ff8d5e9660 | ||
|
|
38ea325a36 | ||
|
|
d894c6d3dd | ||
|
|
2b953a694c |
11
configure.ac
11
configure.ac
@@ -112,9 +112,9 @@ PKG_CHECK_MODULES(POWER_PANEL, $COMMON_MODULES upower-glib >= 0.9.1
|
||||
PKG_CHECK_MODULES(COLOR_PANEL, $COMMON_MODULES colord >= 0.1.8)
|
||||
PKG_CHECK_MODULES(PRINTERS_PANEL, $COMMON_MODULES
|
||||
polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION)
|
||||
PKG_CHECK_MODULES(REGION_PANEL, $COMMON_MODULES libgnomekbd >= 2.91.91
|
||||
PKG_CHECK_MODULES(REGION_PANEL, $COMMON_MODULES
|
||||
polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION
|
||||
libxklavier >= 5.1 libgnomekbdui >= 2.91.91)
|
||||
xkbfile)
|
||||
PKG_CHECK_MODULES(SCREEN_PANEL, $COMMON_MODULES)
|
||||
PKG_CHECK_MODULES(SOUND_PANEL, $COMMON_MODULES libxml-2.0
|
||||
libcanberra-gtk3 >= $CANBERRA_REQUIRED_VERSION
|
||||
@@ -135,6 +135,13 @@ PKG_CHECK_MODULES(WACOM_PANEL, $COMMON_MODULES
|
||||
GDESKTOP_PREFIX=`$PKG_CONFIG --variable prefix gsettings-desktop-schemas`
|
||||
AC_SUBST(GDESKTOP_PREFIX)
|
||||
|
||||
AC_ARG_WITH(xkb-config-root,
|
||||
AS_HELP_STRING([--with-xkb-config-root=<paths>],
|
||||
[Set default XKB config root (default: ${datadir}/X11/xkb)]),
|
||||
[XKBCONFIGROOT="$withval"],
|
||||
[XKBCONFIGROOT=${datadir}/X11/xkb])
|
||||
AC_SUBST([XKBCONFIGROOT])
|
||||
|
||||
# Check for NetworkManager ~0.9
|
||||
PKG_CHECK_MODULES(NETWORK_MANAGER, NetworkManager >= $NETWORK_MANAGER_REQUIRED_VERSION
|
||||
libnm-glib >= $NETWORK_MANAGER_REQUIRED_VERSION
|
||||
|
||||
12
panels/keyboard/01-input-sources.xml.in
Normal file
12
panels/keyboard/01-input-sources.xml.in
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<KeyListEntries group="system"
|
||||
schema="org.gnome.desktop.input-sources.keybindings"
|
||||
_name="Input Sources">
|
||||
|
||||
<KeyListEntry name="switch-previous"
|
||||
_description="Switch to previous source"/>
|
||||
|
||||
<KeyListEntry name="switch-next"
|
||||
_description="Switch to next source"/>
|
||||
|
||||
</KeyListEntries>
|
||||
@@ -33,7 +33,13 @@ desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
|
||||
xmldir = $(pkgdatadir)/keybindings
|
||||
xml_in_files = 00-multimedia.xml.in 01-launchers.xml.in 01-screenshot.xml.in 01-system.xml.in 50-accessibility.xml.in
|
||||
xml_in_files = \
|
||||
00-multimedia.xml.in \
|
||||
01-input-sources.xml.in \
|
||||
01-launchers.xml.in \
|
||||
01-screenshot.xml.in \
|
||||
01-system.xml.in \
|
||||
50-accessibility.xml.in
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
pkgconfigdir = $(datadir)/pkgconfig
|
||||
|
||||
@@ -47,19 +47,85 @@ cc_keyboard_panel_get_property (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ARGV
|
||||
};
|
||||
|
||||
enum {
|
||||
TYPING_PAGE,
|
||||
SHORTCUTS_PAGE
|
||||
};
|
||||
|
||||
static void
|
||||
cc_keyboard_panel_set_page (CcKeyboardPanel *panel,
|
||||
const gchar *page)
|
||||
{
|
||||
GtkWidget *notebook;
|
||||
gint page_num;
|
||||
|
||||
if (g_strcmp0 (page, "typing") == 0)
|
||||
page_num = TYPING_PAGE;
|
||||
else
|
||||
page_num = SHORTCUTS_PAGE;
|
||||
|
||||
notebook = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "keyboard_notebook"));
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), page_num);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cc_keyboard_panel_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcKeyboardPanel *panel = CC_KEYBOARD_PANEL (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ARGV: {
|
||||
gchar **args;
|
||||
|
||||
args = g_value_get_boxed (value);
|
||||
|
||||
if (args && args[0]) {
|
||||
cc_keyboard_panel_set_page (panel, args[0]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static GObject *
|
||||
cc_keyboard_panel_constructor (GType gtype,
|
||||
guint n_properties,
|
||||
GObjectConstructParam *properties)
|
||||
{
|
||||
GObject *obj;
|
||||
CcKeyboardPanel *self;
|
||||
CcKeyboardPanelPrivate *priv;
|
||||
GtkWidget *widget;
|
||||
|
||||
obj = G_OBJECT_CLASS (cc_keyboard_panel_parent_class)->constructor (gtype, n_properties, properties);
|
||||
|
||||
self = CC_KEYBOARD_PANEL (obj);
|
||||
priv = self->priv;
|
||||
|
||||
keyboard_general_init (CC_PANEL (self), priv->builder);
|
||||
keyboard_shortcuts_init (CC_PANEL (self), priv->builder);
|
||||
|
||||
widget = (GtkWidget *) gtk_builder_get_object (priv->builder,
|
||||
"keyboard_notebook");
|
||||
|
||||
gtk_widget_reparent (widget, (GtkWidget *) self);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_keyboard_panel_dispose (GObject *object)
|
||||
{
|
||||
@@ -72,49 +138,14 @@ cc_keyboard_panel_dispose (GObject *object)
|
||||
static void
|
||||
cc_keyboard_panel_finalize (GObject *object)
|
||||
{
|
||||
CcKeyboardPanel *panel = CC_KEYBOARD_PANEL (object);
|
||||
|
||||
if (panel->priv->builder)
|
||||
g_object_unref (panel->priv->builder);
|
||||
|
||||
G_OBJECT_CLASS (cc_keyboard_panel_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
cc_keyboard_panel_constructor (GType gtype,
|
||||
guint n_properties,
|
||||
GObjectConstructParam *properties)
|
||||
{
|
||||
GObject *obj;
|
||||
CcKeyboardPanel *self;
|
||||
CcKeyboardPanelPrivate *priv;
|
||||
GError *error = NULL;
|
||||
GtkWidget *widget;
|
||||
|
||||
const gchar *uifile = GNOMECC_UI_DIR "/gnome-keyboard-panel.ui";
|
||||
|
||||
obj = G_OBJECT_CLASS (cc_keyboard_panel_parent_class)->constructor (gtype, n_properties, properties);
|
||||
|
||||
self = CC_KEYBOARD_PANEL (obj);
|
||||
priv = self->priv = KEYBOARD_PANEL_PRIVATE (self);
|
||||
|
||||
priv->builder = gtk_builder_new ();
|
||||
|
||||
if (gtk_builder_add_from_file (priv->builder, uifile, &error) == 0)
|
||||
{
|
||||
g_warning ("Could not load UI: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
g_object_unref (priv->builder);
|
||||
priv->builder = NULL;
|
||||
return obj;
|
||||
}
|
||||
|
||||
keyboard_general_init (CC_PANEL (self), priv->builder);
|
||||
keyboard_shortcuts_init (CC_PANEL (self), priv->builder);
|
||||
|
||||
widget = (GtkWidget *) gtk_builder_get_object (priv->builder,
|
||||
"keyboard_notebook");
|
||||
|
||||
gtk_widget_reparent (widget, (GtkWidget *) self);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass)
|
||||
{
|
||||
@@ -127,6 +158,8 @@ cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass)
|
||||
object_class->set_property = cc_keyboard_panel_set_property;
|
||||
object_class->dispose = cc_keyboard_panel_dispose;
|
||||
object_class->finalize = cc_keyboard_panel_finalize;
|
||||
|
||||
g_object_class_override_property (object_class, PROP_ARGV, "argv");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -137,6 +170,21 @@ cc_keyboard_panel_class_finalize (CcKeyboardPanelClass *klass)
|
||||
static void
|
||||
cc_keyboard_panel_init (CcKeyboardPanel *self)
|
||||
{
|
||||
const gchar *uifile = GNOMECC_UI_DIR "/gnome-keyboard-panel.ui";
|
||||
CcKeyboardPanelPrivate *priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv = self->priv = KEYBOARD_PANEL_PRIVATE (self);
|
||||
|
||||
priv->builder = gtk_builder_new ();
|
||||
|
||||
if (gtk_builder_add_from_file (priv->builder, uifile, &error) == 0)
|
||||
{
|
||||
g_warning ("Could not load UI: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
g_object_unref (priv->builder);
|
||||
priv->builder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
# This is used in PANEL_CFLAGS
|
||||
cappletname = region
|
||||
|
||||
XKBCONFIGROOT=@XKBCONFIGROOT@
|
||||
|
||||
INCLUDES = \
|
||||
$(PANEL_CFLAGS) \
|
||||
$(REGION_PANEL_CFLAGS) \
|
||||
-DGNOMELOCALEDIR="\"$(datadir)/locale\"" \
|
||||
-DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \
|
||||
-DGNOMECC_UI_DIR="\"$(uidir)\"" \
|
||||
-DDFLT_XKB_CONFIG_ROOT=\"$(XKBCONFIGROOT)\" \
|
||||
-I$(srcdir)/../common/ \
|
||||
$(NULL)
|
||||
|
||||
@@ -23,12 +26,10 @@ libregion_la_SOURCES = \
|
||||
gnome-region-panel-lang.h \
|
||||
gnome-region-panel-system.c \
|
||||
gnome-region-panel-system.h \
|
||||
gnome-region-panel-xkb.c \
|
||||
gnome-region-panel-xkblt.c \
|
||||
gnome-region-panel-xkbltadd.c \
|
||||
gnome-region-panel-xkbot.c \
|
||||
gnome-region-panel-xkbpv.c \
|
||||
gnome-region-panel-xkb.h
|
||||
gnome-region-panel-input.c \
|
||||
gnome-region-panel-input.h \
|
||||
xkb-rules-db.c \
|
||||
xkb-rules-db.h
|
||||
|
||||
libregion_la_LIBADD = $(PANEL_LIBS) $(REGION_PANEL_LIBS) $(builddir)/../common/liblanguage.la
|
||||
|
||||
@@ -39,8 +40,7 @@ libregion_la_LDFLAGS = $(PANEL_LDFLAGS)
|
||||
uidir = $(pkgdatadir)/ui
|
||||
ui_DATA = \
|
||||
gnome-region-panel.ui \
|
||||
gnome-region-panel-layout-chooser.ui \
|
||||
gnome-region-panel-options-dialog.ui
|
||||
gnome-region-panel-input-chooser.ui
|
||||
|
||||
desktopdir = $(datadir)/applications
|
||||
Desktop_in_files = gnome-region-panel.desktop.in
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "cc-region-panel.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gnome-region-panel-xkb.h"
|
||||
#include "gnome-region-panel-input.h"
|
||||
#include "gnome-region-panel-lang.h"
|
||||
#include "gnome-region-panel-formats.h"
|
||||
#include "gnome-region-panel-system.h"
|
||||
@@ -151,7 +151,7 @@ cc_region_panel_init (CcRegionPanel * self)
|
||||
|
||||
gtk_widget_reparent (prefs_widget, GTK_WIDGET (self));
|
||||
|
||||
setup_xkb_tabs (priv->builder);
|
||||
setup_input_tabs (priv->builder, self);
|
||||
setup_language (priv->builder);
|
||||
setup_formats (priv->builder);
|
||||
setup_system (priv->builder);
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.16"/>
|
||||
<object class="GtkListStore" id="layout_list_model">
|
||||
<object class="GtkListStore" id="input_source_model">
|
||||
<columns>
|
||||
<!-- column-name sort_order -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name visible -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name xkb_id -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name country_desc -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name language_desc -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkTreeModelFilter" id="filtered_layout_list_model">
|
||||
<property name="child_model">layout_list_model</property>
|
||||
<object class="GtkTreeModelFilter" id="filtered_input_source_model">
|
||||
<property name="child_model">input_source_model</property>
|
||||
</object>
|
||||
<object class="GtkDialog" id="xkb_layout_chooser">
|
||||
<object class="GtkDialog" id="input_source_chooser">
|
||||
<property name="visible">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Choose a Layout</property>
|
||||
<property name="title" translatable="yes">Choose an input source</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
@@ -38,22 +31,7 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="btnPreview">
|
||||
<property name="label" translatable="yes">Preview</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
<property name="secondary">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="btnCancel">
|
||||
<object class="GtkButton" id="cancel-button">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
@@ -70,7 +48,7 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="btnOk">
|
||||
<object class="GtkButton" id="ok-button">
|
||||
<property name="label">gtk-add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
@@ -121,15 +99,12 @@
|
||||
<property name="min_content_width">450</property>
|
||||
<property name="min_content_height">250</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="xkb_filtered_layouts_list">
|
||||
<object class="GtkTreeView" id="filtered_input_source_list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="model">filtered_layout_list_model</property>
|
||||
<property name="model">filtered_input_source_model</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="search_column">0</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -147,7 +122,7 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="xkb_layout_filter">
|
||||
<object class="GtkEntry" id="input_source_filter">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
@@ -172,9 +147,8 @@
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="1">btnPreview</action-widget>
|
||||
<action-widget response="-5">btnOk</action-widget>
|
||||
<action-widget response="-6">btnCancel</action-widget>
|
||||
<action-widget response="-5">ok-button</action-widget>
|
||||
<action-widget response="-6">cancel-button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
764
panels/region/gnome-region-panel-input.c
Normal file
764
panels/region/gnome-region-panel-input.c
Normal file
@@ -0,0 +1,764 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* Written by: Matthias Clasen <mclasen@redhat.com>
|
||||
*
|
||||
* 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, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "xkb-rules-db.h"
|
||||
#include "gnome-region-panel-input.h"
|
||||
|
||||
#define WID(s) GTK_WIDGET(gtk_builder_get_object (builder, s))
|
||||
|
||||
/* TODO
|
||||
*
|
||||
* - There is a large overlap between xkb and m17n:kbd -
|
||||
* we need to somehow decide and filter out
|
||||
* cases to consider:
|
||||
* Amharic: xkb:layout:et vs m17n:am:sera - probably keep both
|
||||
* Arabic: xkb:layout:ara vs m17n:ar:kbd - probably not
|
||||
*
|
||||
* - Straighten out the naming. It needs to be either
|
||||
* "Language" or "Language (Method)" when the same
|
||||
* language occurs more than once. Need to decide what
|
||||
* to do about xkb and m17n
|
||||
*
|
||||
* - Implement system-wide settings
|
||||
*
|
||||
* - Debug hotkeys, they don't act right
|
||||
*
|
||||
* - Allow changing shortcuts ?
|
||||
*/
|
||||
|
||||
typedef struct _InputSource InputSource;
|
||||
struct _InputSource
|
||||
{
|
||||
const gchar *name;
|
||||
const gchar *short_name;
|
||||
const gchar *xkb_layout;
|
||||
const gchar *xkb_variant;
|
||||
const gchar *ibus_engine;
|
||||
};
|
||||
|
||||
static const InputSource ibus_sources[] = {
|
||||
{ "Chinese (Bopomofo)", "般", "us", "", "bopomofo" },
|
||||
{ "Chinese (Pinyin)", "拼", "us", "", "pinyin" },
|
||||
{ "Japanese (Anthy)", "あ", "jp", "", "anthy" },
|
||||
{ "Korean (Hangul)", "한", "us", "", "hangul" },
|
||||
};
|
||||
|
||||
#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
|
||||
|
||||
#define KEY_CURRENT_IS "current"
|
||||
#define KEY_INPUT_SOURCES "sources"
|
||||
|
||||
static GSettings *is_settings = NULL;
|
||||
|
||||
static GtkWidget *input_chooser_new (GtkBuilder *builder);
|
||||
static gboolean input_chooser_get_selected (GtkWidget *chooser,
|
||||
GtkTreeModel **model,
|
||||
GtkTreeIter *iter);
|
||||
|
||||
static gboolean
|
||||
add_source_to_table (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
GHashTable *hash = data;
|
||||
gchar *name;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &name, -1);
|
||||
g_hash_table_add (hash, name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
populate_model (GtkListStore *store,
|
||||
GtkListStore *active_sources)
|
||||
{
|
||||
GHashTable *active_sources_table;
|
||||
GtkTreeIter iter;
|
||||
GSList *all_sources, *tmp;
|
||||
gint i;
|
||||
|
||||
active_sources_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (active_sources),
|
||||
add_source_to_table,
|
||||
active_sources_table);
|
||||
|
||||
all_sources = xkb_rules_db_get_all_layout_names ();
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (ibus_sources); ++i)
|
||||
all_sources = g_slist_prepend (all_sources, (gpointer)ibus_sources[i].name);
|
||||
|
||||
for (tmp = all_sources; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (g_hash_table_contains (active_sources_table, tmp->data))
|
||||
continue;
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
0, tmp->data,
|
||||
-1);
|
||||
}
|
||||
|
||||
g_slist_free (all_sources);
|
||||
g_hash_table_destroy (active_sources_table);
|
||||
}
|
||||
|
||||
static void
|
||||
populate_with_active_sources (GtkListStore *store)
|
||||
{
|
||||
GVariant *sources;
|
||||
GVariantIter iter;
|
||||
const gchar *name;
|
||||
GtkTreeIter tree_iter;
|
||||
|
||||
sources = g_settings_get_value (is_settings, KEY_INPUT_SOURCES);
|
||||
|
||||
g_variant_iter_init (&iter, sources);
|
||||
while (g_variant_iter_next (&iter, "(&s&s&s&s&s)", &name, NULL, NULL, NULL, NULL))
|
||||
{
|
||||
gtk_list_store_append (store, &tree_iter);
|
||||
gtk_list_store_set (store, &tree_iter,
|
||||
0, name,
|
||||
-1);
|
||||
}
|
||||
|
||||
g_variant_unref (sources);
|
||||
}
|
||||
|
||||
static void
|
||||
update_configuration (GtkTreeModel *model)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gchar *name;
|
||||
const gchar *short_name = "";
|
||||
const gchar *xkb_layout = "";
|
||||
const gchar *xkb_variant = "";
|
||||
const gchar *ibus_engine = "";
|
||||
GVariantBuilder builder;
|
||||
gint i;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssss)"));
|
||||
|
||||
gtk_tree_model_get_iter_first (model, &iter);
|
||||
do {
|
||||
gtk_tree_model_get (model, &iter,
|
||||
0, &name,
|
||||
-1);
|
||||
|
||||
if (xkb_rules_db_get_layout_info (name, &short_name, &xkb_layout, &xkb_variant))
|
||||
ibus_engine = "";
|
||||
else
|
||||
for (i = 0; i < G_N_ELEMENTS (ibus_sources); ++i)
|
||||
if (strcmp (name, ibus_sources[i].name) == 0)
|
||||
{
|
||||
short_name = ibus_sources[i].short_name;
|
||||
xkb_layout = ibus_sources[i].xkb_layout;
|
||||
xkb_variant = ibus_sources[i].xkb_variant;
|
||||
ibus_engine = ibus_sources[i].ibus_engine;
|
||||
break;
|
||||
}
|
||||
|
||||
g_variant_builder_add (&builder, "(sssss)", name, short_name, xkb_layout, xkb_variant, ibus_engine);
|
||||
g_free (name);
|
||||
} while (gtk_tree_model_iter_next (model, &iter));
|
||||
|
||||
g_settings_set_value (is_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
|
||||
}
|
||||
|
||||
/* List handling {{{1 */
|
||||
|
||||
static gboolean
|
||||
get_selected_iter (GtkBuilder *builder,
|
||||
GtkTreeModel **model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("active_input_sources")));
|
||||
|
||||
return gtk_tree_selection_get_selected (selection, model, iter);
|
||||
}
|
||||
|
||||
static gint
|
||||
find_selected_layout_idx (GtkBuilder *builder)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
GtkTreePath *path;
|
||||
gint idx;
|
||||
|
||||
if (!get_selected_iter (builder, &model, &iter))
|
||||
return -1;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &iter);
|
||||
if (path == NULL)
|
||||
return -1;
|
||||
|
||||
idx = gtk_tree_path_get_indices (path)[0];
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void
|
||||
update_button_sensitivity (GtkBuilder *builder)
|
||||
{
|
||||
GtkWidget *remove_button;
|
||||
GtkWidget *up_button;
|
||||
GtkWidget *down_button;
|
||||
GtkWidget *show_button;
|
||||
GtkTreeView *tv;
|
||||
gint n_active;
|
||||
gint index;
|
||||
|
||||
remove_button = WID("input_source_remove");
|
||||
show_button = WID("input_source_show");
|
||||
up_button = WID("input_source_move_up");
|
||||
down_button = WID("input_source_move_down");
|
||||
|
||||
tv = GTK_TREE_VIEW (WID ("active_input_sources"));
|
||||
|
||||
n_active = gtk_tree_model_iter_n_children (gtk_tree_view_get_model (tv), NULL);
|
||||
index = find_selected_layout_idx (builder);
|
||||
|
||||
gtk_widget_set_sensitive (remove_button, index >= 0 && n_active > 1);
|
||||
gtk_widget_set_sensitive (show_button, index >= 0);
|
||||
gtk_widget_set_sensitive (up_button, index > 0);
|
||||
gtk_widget_set_sensitive (down_button, index >= 0 && index < n_active - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
set_selected_path (GtkBuilder *builder,
|
||||
GtkTreePath *path)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("active_input_sources")));
|
||||
|
||||
gtk_tree_selection_select_path (selection, path);
|
||||
}
|
||||
|
||||
static void
|
||||
chooser_response (GtkWidget *chooser, gint response_id, gpointer data)
|
||||
{
|
||||
GtkBuilder *builder = data;
|
||||
|
||||
if (response_id == GTK_RESPONSE_OK)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (input_chooser_get_selected (chooser, &model, &iter))
|
||||
{
|
||||
GtkTreeView *my_tv;
|
||||
GtkListStore *my_model;
|
||||
GtkTreeIter my_iter;
|
||||
gchar *name;
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
0, &name,
|
||||
-1);
|
||||
|
||||
my_tv = GTK_TREE_VIEW (WID ("active_input_sources"));
|
||||
my_model = GTK_LIST_STORE (gtk_tree_view_get_model (my_tv));
|
||||
|
||||
gtk_list_store_append (my_model, &my_iter);
|
||||
|
||||
gtk_list_store_set (my_model, &my_iter,
|
||||
0, name,
|
||||
-1);
|
||||
g_free (name);
|
||||
|
||||
gtk_tree_selection_select_iter (gtk_tree_view_get_selection (my_tv), &my_iter);
|
||||
|
||||
update_button_sensitivity (builder);
|
||||
update_configuration (GTK_TREE_MODEL (my_model));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("nothing selected, nothing added");
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (chooser));
|
||||
}
|
||||
|
||||
static void
|
||||
add_input (GtkButton *button, gpointer data)
|
||||
{
|
||||
GtkBuilder *builder = data;
|
||||
GtkWidget *chooser;
|
||||
|
||||
g_debug ("add an input source");
|
||||
|
||||
chooser = input_chooser_new (builder);
|
||||
g_signal_connect (chooser, "response",
|
||||
G_CALLBACK (chooser_response), builder);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_selected_input (GtkButton *button, gpointer data)
|
||||
{
|
||||
GtkBuilder *builder = data;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
|
||||
g_debug ("remove selected input source");
|
||||
|
||||
if (get_selected_iter (builder, &model, &iter) == FALSE)
|
||||
return;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &iter);
|
||||
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
|
||||
|
||||
if (!gtk_tree_model_get_iter (model, &iter, path))
|
||||
gtk_tree_path_prev (path);
|
||||
|
||||
set_selected_path (builder, path);
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
update_button_sensitivity (builder);
|
||||
update_configuration (model);
|
||||
}
|
||||
|
||||
static void
|
||||
move_selected_input_up (GtkButton *button, gpointer data)
|
||||
{
|
||||
GtkBuilder *builder = data;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter, prev;
|
||||
GtkTreePath *path;
|
||||
|
||||
g_debug ("move selected input source up");
|
||||
|
||||
if (!get_selected_iter (builder, &model, &iter))
|
||||
return;
|
||||
|
||||
prev = iter;
|
||||
if (!gtk_tree_model_iter_previous (model, &prev))
|
||||
return;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &prev);
|
||||
|
||||
gtk_list_store_swap (GTK_LIST_STORE (model), &iter, &prev);
|
||||
set_selected_path (builder, path);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
update_button_sensitivity (builder);
|
||||
update_configuration (model);
|
||||
}
|
||||
|
||||
static void
|
||||
move_selected_input_down (GtkButton *button, gpointer data)
|
||||
{
|
||||
GtkBuilder *builder = data;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter, next;
|
||||
GtkTreePath *path;
|
||||
|
||||
g_debug ("move selected input source down");
|
||||
|
||||
if (!get_selected_iter (builder, &model, &iter))
|
||||
return;
|
||||
|
||||
next = iter;
|
||||
if (!gtk_tree_model_iter_next (model, &next))
|
||||
return;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &next);
|
||||
gtk_list_store_swap (GTK_LIST_STORE (model), &iter, &next);
|
||||
set_selected_path (builder, path);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
update_button_sensitivity (builder);
|
||||
update_configuration (model);
|
||||
}
|
||||
|
||||
static void
|
||||
show_selected_layout (GtkButton *button, gpointer data)
|
||||
{
|
||||
GtkBuilder *builder = data;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gchar *name;
|
||||
gchar *kbd_viewer_args;
|
||||
const gchar *xkb_layout = "";
|
||||
const gchar *xkb_variant = "";
|
||||
gint i;
|
||||
|
||||
g_debug ("show selected layout");
|
||||
|
||||
if (!get_selected_iter (builder, &model, &iter))
|
||||
return;
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
0, &name,
|
||||
-1);
|
||||
|
||||
if (!xkb_rules_db_get_layout_info (name, NULL, &xkb_layout, &xkb_variant))
|
||||
for (i = 0; i < G_N_ELEMENTS (ibus_sources); ++i)
|
||||
if (strcmp (name, ibus_sources[i].name) == 0)
|
||||
{
|
||||
xkb_layout = ibus_sources[i].xkb_layout;
|
||||
xkb_variant = ibus_sources[i].xkb_variant;
|
||||
break;
|
||||
}
|
||||
|
||||
if (xkb_variant[0])
|
||||
kbd_viewer_args = g_strdup_printf ("gkbd-keyboard-display -l \"%s\t%s\"",
|
||||
xkb_layout, xkb_variant);
|
||||
else
|
||||
kbd_viewer_args = g_strdup_printf ("gkbd-keyboard-display -l %s",
|
||||
xkb_layout);
|
||||
|
||||
g_spawn_command_line_async (kbd_viewer_args, NULL);
|
||||
|
||||
g_free (kbd_viewer_args);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
/* Main setup {{{1 */
|
||||
|
||||
static gboolean
|
||||
go_to_shortcuts (GtkLinkButton *button,
|
||||
CcRegionPanel *panel)
|
||||
{
|
||||
CcShell *shell;
|
||||
const gchar *argv[] = { "shortcuts", NULL };
|
||||
GError *error = NULL;
|
||||
|
||||
shell = cc_panel_get_shell (CC_PANEL (panel));
|
||||
if (!cc_shell_set_active_panel_from_id (shell, "keyboard", argv, &error))
|
||||
{
|
||||
g_warning ("Failed to activate Keyboard panel: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
setup_input_tabs (GtkBuilder *builder,
|
||||
CcRegionPanel *panel)
|
||||
{
|
||||
GtkWidget *treeview;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkCellRenderer *cell;
|
||||
GtkListStore *store;
|
||||
GtkTreeSelection *selection;
|
||||
gchar *previous = NULL;
|
||||
gchar *next = NULL;
|
||||
GtkWidget *label;
|
||||
|
||||
is_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
|
||||
|
||||
/* set up the list of active inputs */
|
||||
treeview = WID("active_input_sources");
|
||||
column = gtk_tree_view_column_new ();
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, cell, TRUE);
|
||||
gtk_tree_view_column_add_attribute (column, cell, "text", 0);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
store = gtk_list_store_new (1, G_TYPE_STRING);
|
||||
|
||||
populate_with_active_sources (store);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
|
||||
g_signal_connect_swapped (selection, "changed",
|
||||
G_CALLBACK (update_button_sensitivity), builder);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
|
||||
|
||||
/* set up the buttons */
|
||||
g_signal_connect (WID("input_source_add"), "clicked",
|
||||
G_CALLBACK (add_input), builder);
|
||||
g_signal_connect (WID("input_source_remove"), "clicked",
|
||||
G_CALLBACK (remove_selected_input), builder);
|
||||
g_signal_connect (WID("input_source_move_up"), "clicked",
|
||||
G_CALLBACK (move_selected_input_up), builder);
|
||||
g_signal_connect (WID("input_source_move_down"), "clicked",
|
||||
G_CALLBACK (move_selected_input_down), builder);
|
||||
g_signal_connect (WID("input_source_show"), "clicked",
|
||||
G_CALLBACK (show_selected_layout), builder);
|
||||
|
||||
/* use an em dash is no shortcut */
|
||||
if (!previous)
|
||||
previous = g_strdup ("\342\200\224");
|
||||
if (!next)
|
||||
next = g_strdup ("\342\200\224");
|
||||
|
||||
label = WID("prev-source-shortcut-label");
|
||||
gtk_label_set_label (GTK_LABEL (label), previous);
|
||||
label = WID("next-source-shortcut-label");
|
||||
gtk_label_set_label (GTK_LABEL (label), next);
|
||||
|
||||
g_free (previous);
|
||||
g_free (next);
|
||||
|
||||
g_signal_connect (WID("jump-to-shortcuts"), "activate-link",
|
||||
G_CALLBACK (go_to_shortcuts), panel);
|
||||
}
|
||||
|
||||
/* Chooser dialog {{{1 */
|
||||
|
||||
static void
|
||||
filter_clear (GtkEntry *entry,
|
||||
GtkEntryIconPosition icon_pos,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_entry_set_text (entry, "");
|
||||
}
|
||||
|
||||
static gchar **search_pattern_list;
|
||||
|
||||
static void
|
||||
filter_changed (GtkBuilder *builder)
|
||||
{
|
||||
GtkTreeModelFilter *filtered_model;
|
||||
GtkTreeView *tree_view;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeIter selected_iter;
|
||||
GtkWidget *filter_entry;
|
||||
const gchar *pattern;
|
||||
gchar *upattern;
|
||||
|
||||
filter_entry = WID ("input_source_filter");
|
||||
pattern = gtk_entry_get_text (GTK_ENTRY (filter_entry));
|
||||
upattern = g_utf8_strup (pattern, -1);
|
||||
if (!g_strcmp0 (pattern, ""))
|
||||
g_object_set (G_OBJECT (filter_entry),
|
||||
"secondary-icon-name", "edit-find-symbolic",
|
||||
"secondary-icon-activatable", FALSE,
|
||||
"secondary-icon-sensitive", FALSE,
|
||||
NULL);
|
||||
else
|
||||
g_object_set (G_OBJECT (filter_entry),
|
||||
"secondary-icon-name", "edit-clear-symbolic",
|
||||
"secondary-icon-activatable", TRUE,
|
||||
"secondary-icon-sensitive", TRUE,
|
||||
NULL);
|
||||
|
||||
if (search_pattern_list != NULL)
|
||||
g_strfreev (search_pattern_list);
|
||||
|
||||
search_pattern_list = g_strsplit (upattern, " ", -1);
|
||||
g_free (upattern);
|
||||
|
||||
filtered_model =
|
||||
GTK_TREE_MODEL_FILTER (gtk_builder_get_object (builder, "filtered_input_source_model"));
|
||||
gtk_tree_model_filter_refilter (filtered_model);
|
||||
|
||||
tree_view = GTK_TREE_VIEW (WID ("filtered_input_source_list"));
|
||||
selection = gtk_tree_view_get_selection (tree_view);
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, &selected_iter))
|
||||
{
|
||||
GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (filtered_model),
|
||||
&selected_iter);
|
||||
gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered_model), &iter))
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
selection_changed (GtkTreeSelection *selection,
|
||||
GtkBuilder *builder)
|
||||
{
|
||||
gtk_widget_set_sensitive (WID ("ok-button"),
|
||||
gtk_tree_selection_get_selected (selection, NULL, NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
row_activated (GtkTreeView *tree_view,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column,
|
||||
GtkBuilder *builder)
|
||||
{
|
||||
GtkWidget *add_button;
|
||||
GtkWidget *dialog;
|
||||
|
||||
add_button = WID ("ok-button");
|
||||
dialog = WID ("input_source_chooser");
|
||||
if (gtk_widget_is_sensitive (add_button))
|
||||
gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
entry_activated (GtkBuilder *builder,
|
||||
gpointer data)
|
||||
{
|
||||
row_activated (NULL, NULL, NULL, builder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_func (GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
gchar *name = NULL;
|
||||
gchar **pattern;
|
||||
gboolean rv = TRUE;
|
||||
|
||||
if (search_pattern_list == NULL || search_pattern_list[0] == NULL)
|
||||
return TRUE;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
0, &name,
|
||||
-1);
|
||||
|
||||
pattern = search_pattern_list;
|
||||
do {
|
||||
gboolean is_pattern_found = FALSE;
|
||||
gchar *udesc = g_utf8_strup (name, -1);
|
||||
if (udesc != NULL && g_strstr_len (udesc, -1, *pattern))
|
||||
{
|
||||
is_pattern_found = TRUE;
|
||||
}
|
||||
g_free (udesc);
|
||||
|
||||
if (!is_pattern_found)
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (*++pattern != NULL);
|
||||
|
||||
g_free (name);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
input_chooser_new (GtkBuilder *main_builder)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *chooser;
|
||||
GtkWidget *filtered_list;
|
||||
GtkWidget *filter_entry;
|
||||
GtkTreeViewColumn *visible_column;
|
||||
GtkTreeSelection *selection;
|
||||
GtkListStore *model;
|
||||
GtkTreeModelFilter *filtered_model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_add_from_file (builder,
|
||||
GNOMECC_UI_DIR "/gnome-region-panel-input-chooser.ui",
|
||||
NULL);
|
||||
chooser = WID ("input_source_chooser");
|
||||
g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
|
||||
|
||||
filtered_list = WID ("filtered_input_source_list");
|
||||
filter_entry = WID ("input_source_filter");
|
||||
|
||||
g_object_set_data (G_OBJECT (chooser),
|
||||
"filtered_input_source_list", filtered_list);
|
||||
visible_column =
|
||||
gtk_tree_view_column_new_with_attributes ("Input Sources",
|
||||
gtk_cell_renderer_text_new (),
|
||||
"text", 0,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (chooser),
|
||||
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gtk_builder_get_object (main_builder, "region_notebook")))));
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (filtered_list),
|
||||
visible_column);
|
||||
/* We handle searching ourselves, thank you. */
|
||||
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (filtered_list), FALSE);
|
||||
gtk_tree_view_set_search_column (GTK_TREE_VIEW (filtered_list), -1);
|
||||
|
||||
g_signal_connect_swapped (G_OBJECT (filter_entry), "activate",
|
||||
G_CALLBACK (entry_activated), builder);
|
||||
g_signal_connect_swapped (G_OBJECT (filter_entry), "notify::text",
|
||||
G_CALLBACK (filter_changed), builder);
|
||||
g_signal_connect (G_OBJECT (filter_entry), "icon-release",
|
||||
G_CALLBACK (filter_clear), NULL);
|
||||
|
||||
filtered_model =
|
||||
GTK_TREE_MODEL_FILTER (gtk_builder_get_object (builder, "filtered_input_source_model"));
|
||||
model =
|
||||
GTK_LIST_STORE (gtk_builder_get_object (builder, "input_source_model"));
|
||||
|
||||
populate_model (model,
|
||||
GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_builder_get_object (main_builder,
|
||||
"active_input_sources")))));
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
|
||||
0, GTK_SORT_ASCENDING);
|
||||
|
||||
gtk_tree_model_filter_set_visible_func (filtered_model,
|
||||
filter_func,
|
||||
NULL, NULL);
|
||||
|
||||
selection =
|
||||
gtk_tree_view_get_selection (GTK_TREE_VIEW (filtered_list));
|
||||
|
||||
g_signal_connect (G_OBJECT (selection), "changed",
|
||||
G_CALLBACK (selection_changed), builder);
|
||||
|
||||
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered_model), &iter))
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
|
||||
g_signal_connect (G_OBJECT (filtered_list), "row-activated",
|
||||
G_CALLBACK (row_activated), builder);
|
||||
|
||||
gtk_widget_grab_focus (filter_entry);
|
||||
|
||||
gtk_widget_show (chooser);
|
||||
|
||||
return chooser;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
input_chooser_get_selected (GtkWidget *dialog,
|
||||
GtkTreeModel **model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
GtkWidget *tv;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
tv = g_object_get_data (G_OBJECT (dialog), "filtered_input_source_list");
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
|
||||
|
||||
return gtk_tree_selection_get_selected (selection, model, iter);
|
||||
}
|
||||
/* Epilogue {{{1 */
|
||||
/* vim: set foldmethod=marker: */
|
||||
36
panels/region/gnome-region-panel-input.h
Normal file
36
panels/region/gnome-region-panel-input.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* gnome-region-panel-input.h
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* Written by Matthias Clasen
|
||||
*
|
||||
* 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, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GNOME_KEYBOARD_PROPERTY_INPUT_H
|
||||
#define __GNOME_KEYBOARD_PROPERTY_INPUT_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "cc-region-panel.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void setup_input_tabs (GtkBuilder *builder,
|
||||
CcRegionPanel *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GNOME_KEYBOARD_PROPERTY_INPUT_H */
|
||||
@@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.16"/>
|
||||
<object class="GtkDialog" id="xkb_options_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Keyboard Layout Options</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="default_width">550</property>
|
||||
<property name="default_height">400</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog_vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="options_scroll">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<child>
|
||||
<object class="GtkViewport" id="viewport1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="options_vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="dialog-action_area4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button2">
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-7">button2</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -29,13 +29,13 @@
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <libgnomekbd/gkbd-keyboard-config.h>
|
||||
#include "cc-common-language.h"
|
||||
#include "gdm-languages.h"
|
||||
#include "gnome-region-panel-system.h"
|
||||
#include "gnome-region-panel-xkb.h"
|
||||
|
||||
static GSettings *locale_settings, *xkb_settings;
|
||||
#define WID(s) GTK_WIDGET(gtk_builder_get_object (dialog, s))
|
||||
|
||||
static GSettings *locale_settings;
|
||||
static GDBusProxy *localed_proxy;
|
||||
static GPermission *localed_permission;
|
||||
|
||||
@@ -130,64 +130,6 @@ system_update_language (GtkBuilder *dialog, const gchar *language)
|
||||
update_copy_button (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_settings_changed (GSettings *settings,
|
||||
const gchar *key,
|
||||
GtkBuilder *dialog)
|
||||
{
|
||||
guint i;
|
||||
GString *disp, *list, *variants;
|
||||
GtkWidget *label;
|
||||
gchar **layouts;
|
||||
|
||||
layouts = g_settings_get_strv (settings, "layouts");
|
||||
if (layouts == NULL)
|
||||
return;
|
||||
|
||||
label = WID ("user_input_source");
|
||||
disp = g_string_new ("");
|
||||
list = g_string_new ("");
|
||||
variants = g_string_new ("");
|
||||
|
||||
for (i = 0; layouts[i]; i++) {
|
||||
gchar *utf_visible;
|
||||
char **split;
|
||||
gchar *layout, *variant;
|
||||
|
||||
utf_visible = xkb_layout_description_utf8 (layouts[i]);
|
||||
if (disp->str[0] != '\0')
|
||||
g_string_append (disp, ", ");
|
||||
g_string_append (disp, utf_visible ? utf_visible : layouts[i]);
|
||||
g_free (utf_visible);
|
||||
|
||||
split = g_strsplit_set (layouts[i], " \t", 2);
|
||||
|
||||
if (split == NULL || split[0] == NULL)
|
||||
continue;
|
||||
|
||||
layout = split[0];
|
||||
variant = split[1];
|
||||
|
||||
if (list->str[0] != '\0')
|
||||
g_string_append (list, ",");
|
||||
g_string_append (list, layout);
|
||||
|
||||
if (variants->str[0] != '\0')
|
||||
g_string_append (variants, ",");
|
||||
g_string_append (variants, variant ? variant : "");
|
||||
|
||||
g_strfreev (split);
|
||||
}
|
||||
g_strfreev (layouts);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (label), "input_source", g_string_free (list, FALSE), g_free);
|
||||
g_object_set_data_full (G_OBJECT (label), "input_variants", g_string_free (variants, FALSE), g_free);
|
||||
gtk_label_set_text (GTK_LABEL (label), disp->str);
|
||||
g_string_free (disp, TRUE);
|
||||
|
||||
update_copy_button (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
update_property (GDBusProxy *proxy,
|
||||
const char *property)
|
||||
@@ -287,6 +229,7 @@ on_localed_properties_changed (GDBusProxy *proxy,
|
||||
g_variant_unref (v);
|
||||
}
|
||||
|
||||
#if 0
|
||||
label = WID ("system_input_source");
|
||||
v = g_dbus_proxy_get_cached_property (proxy, "X11Layout");
|
||||
if (v) {
|
||||
@@ -313,6 +256,7 @@ on_localed_properties_changed (GDBusProxy *proxy,
|
||||
g_string_free (disp, TRUE);
|
||||
|
||||
g_variant_unref (v);
|
||||
#endif
|
||||
|
||||
update_copy_button (dialog);
|
||||
}
|
||||
@@ -468,11 +412,6 @@ setup_system (GtkBuilder *dialog)
|
||||
G_CALLBACK (locale_settings_changed), dialog);
|
||||
g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_object_unref, locale_settings);
|
||||
|
||||
xkb_settings = g_settings_new (GKBD_KEYBOARD_SCHEMA);
|
||||
g_signal_connect (xkb_settings, "changed::layouts",
|
||||
G_CALLBACK (xkb_settings_changed), dialog);
|
||||
g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_object_unref, xkb_settings);
|
||||
|
||||
/* Display user settings */
|
||||
language = cc_common_language_get_current_language ();
|
||||
system_update_language (dialog, language);
|
||||
@@ -480,8 +419,6 @@ setup_system (GtkBuilder *dialog)
|
||||
|
||||
locale_settings_changed (locale_settings, "region", dialog);
|
||||
|
||||
xkb_settings_changed (xkb_settings, "layouts", dialog);
|
||||
|
||||
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
|
||||
g_dbus_proxy_new (bus,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
/* gnome-region-panel-xkb.c
|
||||
* Copyright (C) 2003-2007 Sergey V. Udaltsov
|
||||
*
|
||||
* Written by: Sergey V. Udaltsov <svu@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 2, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gnome-region-panel-xkb.h"
|
||||
|
||||
#include <libgnomekbd/gkbd-desktop-config.h>
|
||||
|
||||
XklEngine *engine;
|
||||
XklConfigRegistry *config_registry;
|
||||
|
||||
GkbdKeyboardConfig initial_config;
|
||||
GkbdDesktopConfig desktop_config;
|
||||
|
||||
GSettings *xkb_keyboard_settings;
|
||||
GSettings *xkb_desktop_settings;
|
||||
|
||||
char *
|
||||
xci_desc_to_utf8 (const XklConfigItem * ci)
|
||||
{
|
||||
gchar *dd = g_strdup (ci->description);
|
||||
gchar *sd = g_strstrip (dd);
|
||||
gchar *rv = g_strdup (sd[0] == 0 ? ci->name : sd);
|
||||
g_free (dd);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_xkb_tabs (GtkBuilder * dialog,
|
||||
GObject *where_the_object_wa)
|
||||
{
|
||||
gkbd_desktop_config_term (&desktop_config);
|
||||
gkbd_keyboard_config_term (&initial_config);
|
||||
g_object_unref (G_OBJECT (config_registry));
|
||||
config_registry = NULL;
|
||||
/* Don't unref it here, or we'll crash if open the panel again */
|
||||
engine = NULL;
|
||||
g_object_unref (G_OBJECT (xkb_keyboard_settings));
|
||||
g_object_unref (G_OBJECT (xkb_desktop_settings));
|
||||
xkb_keyboard_settings = NULL;
|
||||
xkb_desktop_settings = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_to_defaults (GtkWidget * button, GtkBuilder * dialog)
|
||||
{
|
||||
GkbdKeyboardConfig empty_kbd_config;
|
||||
|
||||
gkbd_keyboard_config_init (&empty_kbd_config, engine);
|
||||
gkbd_keyboard_config_save (&empty_kbd_config);
|
||||
gkbd_keyboard_config_term (&empty_kbd_config);
|
||||
|
||||
g_settings_reset (xkb_desktop_settings,
|
||||
GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP);
|
||||
|
||||
/* all the rest is g-s-d's business */
|
||||
}
|
||||
|
||||
static void
|
||||
chk_new_windows_inherit_layout_toggled (GtkWidget *
|
||||
chk_new_windows_inherit_layout,
|
||||
GtkBuilder * dialog)
|
||||
{
|
||||
xkb_save_default_group (gtk_toggle_button_get_active
|
||||
(GTK_TOGGLE_BUTTON
|
||||
(chk_new_windows_inherit_layout)) ? -1 :
|
||||
0);
|
||||
}
|
||||
|
||||
void
|
||||
setup_xkb_tabs (GtkBuilder * dialog)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkStyleContext *context;
|
||||
GtkWidget *chk_new_windows_inherit_layout;
|
||||
|
||||
chk_new_windows_inherit_layout = WID ("chk_new_windows_inherit_layout");
|
||||
|
||||
xkb_desktop_settings = g_settings_new (GKBD_DESKTOP_SCHEMA);
|
||||
xkb_keyboard_settings = g_settings_new (GKBD_KEYBOARD_SCHEMA);
|
||||
|
||||
engine =
|
||||
xkl_engine_get_instance (GDK_DISPLAY_XDISPLAY
|
||||
(gdk_display_get_default ()));
|
||||
config_registry = xkl_config_registry_get_instance (engine);
|
||||
|
||||
gkbd_desktop_config_init (&desktop_config, engine);
|
||||
gkbd_desktop_config_load (&desktop_config);
|
||||
|
||||
xkl_config_registry_load (config_registry,
|
||||
desktop_config.load_extra_items);
|
||||
|
||||
gkbd_keyboard_config_init (&initial_config, engine);
|
||||
gkbd_keyboard_config_load_from_x_initial (&initial_config, NULL);
|
||||
|
||||
/* Set initial state */
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("chk_separate_group_per_window")),
|
||||
g_settings_get_boolean (xkb_desktop_settings,
|
||||
GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chk_new_windows_inherit_layout),
|
||||
xkb_get_default_group () < 0);
|
||||
|
||||
g_settings_bind (xkb_desktop_settings,
|
||||
GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
|
||||
WID ("chk_separate_group_per_window"), "active",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
g_settings_bind (xkb_desktop_settings,
|
||||
GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
|
||||
WID ("chk_new_windows_inherit_layout"), "sensitive",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
g_settings_bind (xkb_desktop_settings,
|
||||
GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
|
||||
WID ("chk_new_windows_default_layout"), "sensitive",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
xkb_layouts_prepare_selected_tree (dialog);
|
||||
xkb_layouts_fill_selected_tree (dialog);
|
||||
|
||||
xkb_layouts_register_buttons_handlers (dialog);
|
||||
g_signal_connect (G_OBJECT (WID ("xkb_reset_to_defaults")),
|
||||
"clicked", G_CALLBACK (reset_to_defaults),
|
||||
dialog);
|
||||
|
||||
g_signal_connect (G_OBJECT (chk_new_windows_inherit_layout),
|
||||
"toggled",
|
||||
G_CALLBACK
|
||||
(chk_new_windows_inherit_layout_toggled),
|
||||
dialog);
|
||||
|
||||
g_signal_connect_swapped (G_OBJECT (WID ("xkb_layout_options")),
|
||||
"clicked",
|
||||
G_CALLBACK (xkb_options_popup_dialog),
|
||||
dialog);
|
||||
|
||||
xkb_layouts_register_conf_listener (dialog);
|
||||
xkb_options_register_conf_listener (dialog);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (WID ("region_notebook")),
|
||||
(GWeakNotify) cleanup_xkb_tabs, dialog);
|
||||
|
||||
enable_disable_restoring (dialog);
|
||||
|
||||
/* Setup junction between toolbar and treeview */
|
||||
widget = WID ("xkb_layouts_swindow");
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
|
||||
widget = WID ("layouts-toolbar");
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
|
||||
}
|
||||
|
||||
void
|
||||
enable_disable_restoring (GtkBuilder * dialog)
|
||||
{
|
||||
GkbdKeyboardConfig gswic;
|
||||
gboolean enable;
|
||||
|
||||
gkbd_keyboard_config_init (&gswic, engine);
|
||||
gkbd_keyboard_config_load (&gswic, NULL);
|
||||
|
||||
enable = !gkbd_keyboard_config_equals (&gswic, &initial_config);
|
||||
|
||||
gkbd_keyboard_config_term (&gswic);
|
||||
gtk_widget_set_sensitive (WID ("xkb_reset_to_defaults"), enable);
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/* gnome-region-panel-xkb.h
|
||||
* Copyright (C) 2003-2007 Sergey V Udaltsov
|
||||
*
|
||||
* Written by Sergey V. Udaltsov <svu@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 2, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GNOME_KEYBOARD_PROPERTY_XKB_H
|
||||
#define __GNOME_KEYBOARD_PROPERTY_XKB_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libgnomekbd/gkbd-keyboard-config.h"
|
||||
#include "libgnomekbd/gkbd-util.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define CWID(s) GTK_WIDGET (gtk_builder_get_object (chooser_dialog, s))
|
||||
#define WID(s) GTK_WIDGET (gtk_builder_get_object (dialog, s))
|
||||
extern XklEngine *engine;
|
||||
extern XklConfigRegistry *config_registry;
|
||||
extern GSettings *xkb_keyboard_settings;
|
||||
extern GSettings *xkb_desktop_settings;
|
||||
extern GkbdKeyboardConfig initial_config;
|
||||
|
||||
extern void setup_xkb_tabs (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_layouts_fill_selected_tree (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_layouts_register_buttons_handlers (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_layouts_register_conf_listener (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_options_register_conf_listener (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_layouts_prepare_selected_tree (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_options_load_options (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_options_popup_dialog (GtkBuilder * dialog);
|
||||
|
||||
extern char *xci_desc_to_utf8 (const XklConfigItem * ci);
|
||||
|
||||
extern gchar *xkb_layout_description_utf8 (const gchar * visible);
|
||||
|
||||
extern void enable_disable_restoring (GtkBuilder * dialog);
|
||||
|
||||
extern void preview_toggled (GtkBuilder * dialog, GtkWidget * button);
|
||||
|
||||
extern GtkWidget *xkb_layout_choose (GtkBuilder * dialog);
|
||||
|
||||
extern void xkb_layout_chooser_response (GtkDialog *dialog, gint response_id);
|
||||
|
||||
extern gchar **xkb_layouts_get_selected_list (void);
|
||||
|
||||
extern gchar **xkb_options_get_selected_list (void);
|
||||
|
||||
#define xkb_layouts_set_selected_list(list) \
|
||||
g_settings_set_strv (xkb_keyboard_settings, \
|
||||
GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS, \
|
||||
(const gchar *const*)(list))
|
||||
|
||||
#define xkb_options_set_selected_list(list) \
|
||||
g_settings_set_strv (xkb_keyboard_settings, \
|
||||
GKBD_KEYBOARD_CONFIG_KEY_OPTIONS, \
|
||||
(const gchar *const*)(list))
|
||||
|
||||
extern GtkWidget *xkb_layout_preview_create_widget (GtkBuilder *
|
||||
chooser_dialog);
|
||||
|
||||
extern void xkb_layout_preview_update (GtkBuilder * chooser_dialog);
|
||||
|
||||
extern void xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw,
|
||||
const gchar * id);
|
||||
|
||||
extern gchar *xkb_layout_chooser_get_selected_id (GtkDialog *dialog);
|
||||
|
||||
extern void xkb_save_default_group (gint group_no);
|
||||
|
||||
extern gint xkb_get_default_group (void);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GNOME_KEYBOARD_PROPERTY_XKB_H */
|
||||
@@ -1,470 +0,0 @@
|
||||
/* gnome-region-panel-xkblt.c
|
||||
* Copyright (C) 2003-2007 Sergey V. Udaltsov
|
||||
*
|
||||
* Written by: Sergey V. Udaltsov <svu@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 2, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <libgnomekbd/gkbd-desktop-config.h>
|
||||
#include <libgnomekbd/gkbd-keyboard-drawing.h>
|
||||
|
||||
#include "gnome-region-panel-xkb.h"
|
||||
|
||||
enum {
|
||||
SEL_LAYOUT_TREE_COL_DESCRIPTION,
|
||||
SEL_LAYOUT_TREE_COL_ID,
|
||||
SEL_LAYOUT_TREE_COL_ENABLED,
|
||||
SEL_LAYOUT_N_COLS
|
||||
};
|
||||
|
||||
static int idx2select = -1;
|
||||
static int max_selected_layouts = -1;
|
||||
|
||||
static GtkCellRenderer *text_renderer;
|
||||
|
||||
static gboolean disable_buttons_sensibility_update = FALSE;
|
||||
|
||||
static gboolean
|
||||
get_selected_iter (GtkBuilder *dialog,
|
||||
GtkTreeModel **model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("xkb_layouts_selected")));
|
||||
|
||||
return gtk_tree_selection_get_selected (selection, model, iter);
|
||||
}
|
||||
|
||||
static void
|
||||
set_selected_path (GtkBuilder *dialog,
|
||||
GtkTreePath *path)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("xkb_layouts_selected")));
|
||||
|
||||
gtk_tree_selection_select_path (selection, path);
|
||||
}
|
||||
|
||||
static gint
|
||||
find_selected_layout_idx (GtkBuilder *dialog)
|
||||
{
|
||||
GtkTreeIter selected_iter;
|
||||
GtkTreeModel *model;
|
||||
GtkTreePath *path;
|
||||
gint *indices;
|
||||
gint rv;
|
||||
|
||||
if (!get_selected_iter (dialog, &model, &selected_iter))
|
||||
return -1;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &selected_iter);
|
||||
if (path == NULL)
|
||||
return -1;
|
||||
|
||||
indices = gtk_tree_path_get_indices (path);
|
||||
rv = indices[0];
|
||||
gtk_tree_path_free (path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
gchar **
|
||||
xkb_layouts_get_selected_list (void)
|
||||
{
|
||||
gchar **retval;
|
||||
|
||||
retval = g_settings_get_strv (xkb_keyboard_settings,
|
||||
GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS);
|
||||
if (retval == NULL || retval[0] == NULL) {
|
||||
g_strfreev (retval);
|
||||
retval = g_strdupv (initial_config.layouts_variants);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
gint
|
||||
xkb_get_default_group ()
|
||||
{
|
||||
return g_settings_get_int (xkb_desktop_settings,
|
||||
GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
void
|
||||
xkb_save_default_group (gint default_group)
|
||||
{
|
||||
g_settings_set_int (xkb_desktop_settings,
|
||||
GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP,
|
||||
default_group);
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_layouts_enable_disable_buttons (GtkBuilder * dialog)
|
||||
{
|
||||
GtkWidget *add_layout_btn = WID ("xkb_layouts_add");
|
||||
GtkWidget *show_layout_btn = WID ("xkb_layouts_show");
|
||||
GtkWidget *del_layout_btn = WID ("xkb_layouts_remove");
|
||||
GtkWidget *selected_layouts_tree = WID ("xkb_layouts_selected");
|
||||
GtkWidget *move_up_layout_btn = WID ("xkb_layouts_move_up");
|
||||
GtkWidget *move_down_layout_btn = WID ("xkb_layouts_move_down");
|
||||
|
||||
GtkTreeSelection *s_selection =
|
||||
gtk_tree_view_get_selection (GTK_TREE_VIEW
|
||||
(selected_layouts_tree));
|
||||
const int n_selected_selected_layouts =
|
||||
gtk_tree_selection_count_selected_rows (s_selection);
|
||||
GtkTreeModel *selected_layouts_model = gtk_tree_view_get_model
|
||||
(GTK_TREE_VIEW (selected_layouts_tree));
|
||||
const int n_selected_layouts =
|
||||
gtk_tree_model_iter_n_children (selected_layouts_model,
|
||||
NULL);
|
||||
gint sidx = find_selected_layout_idx (dialog);
|
||||
|
||||
if (disable_buttons_sensibility_update)
|
||||
return;
|
||||
|
||||
gtk_widget_set_sensitive (add_layout_btn,
|
||||
(n_selected_layouts <
|
||||
max_selected_layouts
|
||||
|| max_selected_layouts == 0));
|
||||
gtk_widget_set_sensitive (del_layout_btn, (n_selected_layouts > 1)
|
||||
&& (n_selected_selected_layouts > 0));
|
||||
gtk_widget_set_sensitive (show_layout_btn,
|
||||
(n_selected_selected_layouts > 0));
|
||||
gtk_widget_set_sensitive (move_up_layout_btn, sidx > 0);
|
||||
gtk_widget_set_sensitive (move_down_layout_btn, sidx >= 0
|
||||
&& sidx < (n_selected_layouts - 1));
|
||||
}
|
||||
|
||||
static void
|
||||
update_layouts_list (GtkTreeModel *model,
|
||||
GtkBuilder *dialog)
|
||||
{
|
||||
gboolean cont;
|
||||
GtkTreeIter iter;
|
||||
GPtrArray *array;
|
||||
|
||||
array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
|
||||
cont = gtk_tree_model_get_iter_first (model, &iter);
|
||||
while (cont) {
|
||||
char *id;
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
SEL_LAYOUT_TREE_COL_ID, &id,
|
||||
-1);
|
||||
g_ptr_array_add (array, id);
|
||||
cont = gtk_tree_model_iter_next (model, &iter);
|
||||
}
|
||||
g_ptr_array_add (array, NULL);
|
||||
xkb_layouts_set_selected_list (array->pdata);
|
||||
g_ptr_array_free (array, TRUE);
|
||||
|
||||
xkb_layouts_enable_disable_buttons (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_layouts_drag_end (GtkWidget *widget,
|
||||
GdkDragContext *drag_context,
|
||||
gpointer user_data)
|
||||
{
|
||||
update_layouts_list (gtk_tree_view_get_model (GTK_TREE_VIEW (widget)),
|
||||
GTK_BUILDER (user_data));
|
||||
}
|
||||
|
||||
void
|
||||
xkb_layouts_prepare_selected_tree (GtkBuilder * dialog)
|
||||
{
|
||||
GtkListStore *list_store;
|
||||
GtkWidget *tree_view = WID ("xkb_layouts_selected");
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeViewColumn *desc_column;
|
||||
|
||||
list_store = gtk_list_store_new (SEL_LAYOUT_N_COLS,
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
|
||||
|
||||
text_renderer = GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
|
||||
|
||||
desc_column =
|
||||
gtk_tree_view_column_new_with_attributes (_("Layout"),
|
||||
text_renderer,
|
||||
"text",
|
||||
SEL_LAYOUT_TREE_COL_DESCRIPTION,
|
||||
"sensitive",
|
||||
SEL_LAYOUT_TREE_COL_ENABLED,
|
||||
NULL);
|
||||
selection =
|
||||
gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view),
|
||||
GTK_TREE_MODEL (list_store));
|
||||
|
||||
gtk_tree_view_column_set_sizing (desc_column,
|
||||
GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
||||
gtk_tree_view_column_set_resizable (desc_column, TRUE);
|
||||
gtk_tree_view_column_set_expand (desc_column, TRUE);
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
|
||||
desc_column);
|
||||
|
||||
g_signal_connect_swapped (G_OBJECT (selection), "changed",
|
||||
G_CALLBACK
|
||||
(xkb_layouts_enable_disable_buttons),
|
||||
dialog);
|
||||
max_selected_layouts = xkl_engine_get_max_num_groups (engine);
|
||||
|
||||
/* Setting up DnD */
|
||||
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (tree_view), TRUE);
|
||||
g_signal_connect (G_OBJECT (tree_view), "drag-end",
|
||||
G_CALLBACK (xkb_layouts_drag_end), dialog);
|
||||
}
|
||||
|
||||
gchar *
|
||||
xkb_layout_description_utf8 (const gchar * visible)
|
||||
{
|
||||
char *l, *sl, *v, *sv;
|
||||
if (gkbd_keyboard_config_get_descriptions
|
||||
(config_registry, visible, &sl, &l, &sv, &v))
|
||||
visible =
|
||||
gkbd_keyboard_config_format_full_description (l, v);
|
||||
return g_strstrip (g_strdup (visible));
|
||||
}
|
||||
|
||||
void
|
||||
xkb_layouts_fill_selected_tree (GtkBuilder * dialog)
|
||||
{
|
||||
gchar **layouts = xkb_layouts_get_selected_list ();
|
||||
guint i;
|
||||
GtkListStore *list_store =
|
||||
GTK_LIST_STORE (gtk_tree_view_get_model
|
||||
(GTK_TREE_VIEW
|
||||
(WID ("xkb_layouts_selected"))));
|
||||
|
||||
/* temporarily disable the buttons' status update */
|
||||
disable_buttons_sensibility_update = TRUE;
|
||||
|
||||
gtk_list_store_clear (list_store);
|
||||
|
||||
for (i = 0; layouts != NULL && layouts[i] != NULL; i++) {
|
||||
char *cur_layout = layouts[i];
|
||||
gchar *utf_visible =
|
||||
xkb_layout_description_utf8 (cur_layout);
|
||||
|
||||
gtk_list_store_insert_with_values (list_store, NULL, G_MAXINT,
|
||||
SEL_LAYOUT_TREE_COL_DESCRIPTION,
|
||||
utf_visible,
|
||||
SEL_LAYOUT_TREE_COL_ID,
|
||||
cur_layout,
|
||||
SEL_LAYOUT_TREE_COL_ENABLED,
|
||||
i < max_selected_layouts, -1);
|
||||
g_free (utf_visible);
|
||||
}
|
||||
|
||||
g_strfreev (layouts);
|
||||
|
||||
/* enable the buttons' status update */
|
||||
disable_buttons_sensibility_update = FALSE;
|
||||
|
||||
if (idx2select != -1) {
|
||||
GtkTreeSelection *selection =
|
||||
gtk_tree_view_get_selection ((GTK_TREE_VIEW
|
||||
(WID
|
||||
("xkb_layouts_selected"))));
|
||||
GtkTreePath *path =
|
||||
gtk_tree_path_new_from_indices (idx2select, -1);
|
||||
gtk_tree_selection_select_path (selection, path);
|
||||
gtk_tree_path_free (path);
|
||||
idx2select = -1;
|
||||
} else {
|
||||
/* if there is nothing to select - just enable/disable the buttons,
|
||||
otherwise it would be done by the selection change */
|
||||
xkb_layouts_enable_disable_buttons (dialog);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_default_switcher_if_necessary ()
|
||||
{
|
||||
gchar **layouts_list = xkb_layouts_get_selected_list();
|
||||
gchar **options_list = xkb_options_get_selected_list ();
|
||||
gboolean was_appended;
|
||||
|
||||
options_list =
|
||||
gkbd_keyboard_config_add_default_switch_option_if_necessary
|
||||
(layouts_list, options_list, &was_appended);
|
||||
if (was_appended)
|
||||
xkb_options_set_selected_list (options_list);
|
||||
g_strfreev (options_list);
|
||||
}
|
||||
|
||||
static void
|
||||
chooser_response (GtkDialog *chooser,
|
||||
int response_id,
|
||||
GtkBuilder *dialog)
|
||||
{
|
||||
if (response_id == GTK_RESPONSE_OK) {
|
||||
char *id, *name;
|
||||
GtkListStore *list_store;
|
||||
|
||||
list_store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (WID ("xkb_layouts_selected"))));
|
||||
id = xkb_layout_chooser_get_selected_id (chooser);
|
||||
name = xkb_layout_description_utf8 (id);
|
||||
gtk_list_store_insert_with_values (list_store, NULL, G_MAXINT,
|
||||
SEL_LAYOUT_TREE_COL_DESCRIPTION, name,
|
||||
SEL_LAYOUT_TREE_COL_ID, id,
|
||||
SEL_LAYOUT_TREE_COL_ENABLED, TRUE,
|
||||
-1);
|
||||
g_free (name);
|
||||
add_default_switcher_if_necessary ();
|
||||
update_layouts_list (GTK_TREE_MODEL (list_store), dialog);
|
||||
}
|
||||
|
||||
xkb_layout_chooser_response (chooser, response_id);
|
||||
}
|
||||
|
||||
static void
|
||||
add_selected_layout (GtkWidget * button, GtkBuilder * dialog)
|
||||
{
|
||||
GtkWidget *chooser;
|
||||
|
||||
chooser = xkb_layout_choose (dialog);
|
||||
g_signal_connect (G_OBJECT (chooser), "response",
|
||||
G_CALLBACK (chooser_response), dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
show_selected_layout (GtkWidget * button, GtkBuilder * dialog)
|
||||
{
|
||||
gint idx = find_selected_layout_idx (dialog);
|
||||
|
||||
if (idx != -1) {
|
||||
GtkWidget *parent = WID ("region_notebook");
|
||||
GtkWidget *popup = gkbd_keyboard_drawing_dialog_new ();
|
||||
gkbd_keyboard_drawing_dialog_set_group (popup,
|
||||
config_registry,
|
||||
idx);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (popup),
|
||||
GTK_WINDOW
|
||||
(gtk_widget_get_toplevel
|
||||
(parent)));
|
||||
gtk_widget_show_all (popup);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_selected_layout (GtkWidget * button, GtkBuilder * dialog)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (get_selected_iter (dialog, &model, &iter) == FALSE)
|
||||
return;
|
||||
|
||||
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
|
||||
update_layouts_list (model, dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
move_up_selected_layout (GtkWidget * button, GtkBuilder * dialog)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter, prev;
|
||||
GtkTreePath *path;
|
||||
|
||||
if (get_selected_iter (dialog, &model, &iter) == FALSE)
|
||||
return;
|
||||
|
||||
prev = iter;
|
||||
if (!gtk_tree_model_iter_previous (model, &prev))
|
||||
return;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &prev);
|
||||
|
||||
gtk_list_store_swap (GTK_LIST_STORE (model), &iter, &prev);
|
||||
|
||||
update_layouts_list (model, dialog);
|
||||
|
||||
set_selected_path (dialog, path);
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
move_down_selected_layout (GtkWidget * button, GtkBuilder * dialog)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter, next;
|
||||
GtkTreePath *path;
|
||||
|
||||
if (get_selected_iter (dialog, &model, &iter) == FALSE)
|
||||
return;
|
||||
|
||||
next = iter;
|
||||
if (!gtk_tree_model_iter_next (model, &next))
|
||||
return;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &next);
|
||||
|
||||
gtk_list_store_swap (GTK_LIST_STORE (model), &iter, &next);
|
||||
|
||||
update_layouts_list (model, dialog);
|
||||
|
||||
set_selected_path (dialog, path);
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
void
|
||||
xkb_layouts_register_buttons_handlers (GtkBuilder * dialog)
|
||||
{
|
||||
g_signal_connect (G_OBJECT (WID ("xkb_layouts_add")), "clicked",
|
||||
G_CALLBACK (add_selected_layout), dialog);
|
||||
g_signal_connect (G_OBJECT (WID ("xkb_layouts_show")), "clicked",
|
||||
G_CALLBACK (show_selected_layout), dialog);
|
||||
g_signal_connect (G_OBJECT (WID ("xkb_layouts_remove")), "clicked",
|
||||
G_CALLBACK (remove_selected_layout), dialog);
|
||||
g_signal_connect (G_OBJECT (WID ("xkb_layouts_move_up")),
|
||||
"clicked", G_CALLBACK (move_up_selected_layout),
|
||||
dialog);
|
||||
g_signal_connect (G_OBJECT (WID ("xkb_layouts_move_down")),
|
||||
"clicked",
|
||||
G_CALLBACK (move_down_selected_layout), dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_layouts_update_list (GSettings * settings,
|
||||
gchar * key, GtkBuilder * dialog)
|
||||
{
|
||||
if (strcmp (key, GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS) == 0) {
|
||||
xkb_layouts_fill_selected_tree (dialog);
|
||||
enable_disable_restoring (dialog);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xkb_layouts_register_conf_listener (GtkBuilder * dialog)
|
||||
{
|
||||
g_signal_connect (xkb_keyboard_settings, "changed",
|
||||
G_CALLBACK (xkb_layouts_update_list), dialog);
|
||||
}
|
||||
@@ -1,495 +0,0 @@
|
||||
/* gnome-region-panel-xkbltadd.c
|
||||
* Copyright (C) 2007 Sergey V. Udaltsov
|
||||
*
|
||||
* Written by: Sergey V. Udaltsov <svu@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 2, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <libgnomekbd/gkbd-keyboard-drawing.h>
|
||||
#include <libgnomekbd/gkbd-util.h>
|
||||
|
||||
#include "gnome-region-panel-xkb.h"
|
||||
|
||||
enum {
|
||||
COMBO_BOX_MODEL_COL_SORT,
|
||||
COMBO_BOX_MODEL_COL_VISIBLE,
|
||||
COMBO_BOX_MODEL_COL_XKB_ID,
|
||||
COMBO_BOX_MODEL_COL_COUNTRY_DESC,
|
||||
COMBO_BOX_MODEL_COL_LANGUAGE_DESC
|
||||
};
|
||||
|
||||
static gchar **search_pattern_list = NULL;
|
||||
|
||||
static GtkWidget *preview_dialog = NULL;
|
||||
|
||||
static GRegex *left_bracket_regex = NULL;
|
||||
|
||||
#define RESPONSE_PREVIEW 1
|
||||
|
||||
static void
|
||||
xkb_preview_destroy_callback (GtkWidget * widget)
|
||||
{
|
||||
preview_dialog = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xkb_layout_chooser_selection_dupe (GtkDialog * dialog)
|
||||
{
|
||||
gchar *selected_id =
|
||||
(gchar *) xkb_layout_chooser_get_selected_id (dialog);
|
||||
gchar **layouts_list, **pl;
|
||||
gboolean rv = FALSE;
|
||||
if (selected_id == NULL)
|
||||
return rv;
|
||||
layouts_list = pl = xkb_layouts_get_selected_list ();
|
||||
while (pl && *pl) {
|
||||
if (!g_ascii_strcasecmp (*pl++, selected_id)) {
|
||||
rv = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_strfreev (layouts_list);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
xkb_layout_chooser_response (GtkDialog * dialog, gint response)
|
||||
{
|
||||
switch (response)
|
||||
case GTK_RESPONSE_OK:{
|
||||
/* Handled by the main code */
|
||||
break;
|
||||
case RESPONSE_PREVIEW:{
|
||||
gchar *selected_id = (gchar *)
|
||||
xkb_layout_chooser_get_selected_id
|
||||
(dialog);
|
||||
|
||||
if (selected_id != NULL) {
|
||||
if (preview_dialog == NULL) {
|
||||
preview_dialog =
|
||||
gkbd_keyboard_drawing_dialog_new
|
||||
();
|
||||
g_signal_connect (G_OBJECT
|
||||
(preview_dialog),
|
||||
"destroy",
|
||||
G_CALLBACK
|
||||
(xkb_preview_destroy_callback),
|
||||
NULL);
|
||||
/* Put into the separate group to avoid conflict
|
||||
with modal parent */
|
||||
gtk_window_group_add_window
|
||||
(gtk_window_group_new
|
||||
(),
|
||||
GTK_WINDOW
|
||||
(preview_dialog));
|
||||
};
|
||||
gkbd_keyboard_drawing_dialog_set_layout
|
||||
(preview_dialog,
|
||||
config_registry, selected_id);
|
||||
|
||||
gtk_widget_show_all
|
||||
(preview_dialog);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (preview_dialog != NULL) {
|
||||
gtk_widget_destroy (preview_dialog);
|
||||
}
|
||||
if (search_pattern_list != NULL) {
|
||||
g_strfreev (search_pattern_list);
|
||||
search_pattern_list = NULL;
|
||||
}
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
}
|
||||
|
||||
static gchar *
|
||||
xkl_create_description_from_list (const XklConfigItem * item,
|
||||
const XklConfigItem * subitem,
|
||||
const gchar * prop_name,
|
||||
const gchar *
|
||||
(*desc_getter) (const gchar * code))
|
||||
{
|
||||
gchar *rv = NULL, *code = NULL;
|
||||
gchar **list = NULL;
|
||||
const gchar *desc;
|
||||
|
||||
if (subitem != NULL)
|
||||
list =
|
||||
(gchar
|
||||
**) (g_object_get_data (G_OBJECT (subitem),
|
||||
prop_name));
|
||||
if (list == NULL || *list == 0)
|
||||
list =
|
||||
(gchar
|
||||
**) (g_object_get_data (G_OBJECT (item), prop_name));
|
||||
|
||||
/* First try the parent id as such */
|
||||
desc = desc_getter (item->name);
|
||||
if (desc != NULL) {
|
||||
rv = g_utf8_strup (desc, -1);
|
||||
} else {
|
||||
code = g_utf8_strup (item->name, -1);
|
||||
desc = desc_getter (code);
|
||||
if (desc != NULL) {
|
||||
rv = g_utf8_strup (desc, -1);
|
||||
}
|
||||
g_free (code);
|
||||
}
|
||||
|
||||
if (list == NULL || *list == 0)
|
||||
return rv;
|
||||
|
||||
while (*list != 0) {
|
||||
code = *list++;
|
||||
desc = desc_getter (code);
|
||||
if (desc != NULL) {
|
||||
gchar *udesc = g_utf8_strup (desc, -1);
|
||||
if (rv == NULL) {
|
||||
rv = udesc;
|
||||
} else {
|
||||
gchar *orv = rv;
|
||||
rv = g_strdup_printf ("%s %s", rv, udesc);
|
||||
g_free (orv);
|
||||
g_free (udesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
xkl_layout_add_to_list (XklConfigRegistry * config,
|
||||
const XklConfigItem * item,
|
||||
const XklConfigItem * subitem,
|
||||
GtkBuilder * chooser_dialog)
|
||||
{
|
||||
GtkListStore *list_store =
|
||||
GTK_LIST_STORE (gtk_builder_get_object (chooser_dialog,
|
||||
"layout_list_model"));
|
||||
GtkTreeIter iter;
|
||||
|
||||
gchar *utf_variant_name =
|
||||
subitem ?
|
||||
xkb_layout_description_utf8 (gkbd_keyboard_config_merge_items
|
||||
(item->name,
|
||||
subitem->name)) :
|
||||
xci_desc_to_utf8 (item);
|
||||
|
||||
const gchar *xkb_id =
|
||||
subitem ? gkbd_keyboard_config_merge_items (item->name,
|
||||
subitem->name) :
|
||||
item->name;
|
||||
|
||||
gchar *country_desc =
|
||||
xkl_create_description_from_list (item, subitem,
|
||||
XCI_PROP_COUNTRY_LIST,
|
||||
xkl_get_country_name);
|
||||
gchar *language_desc =
|
||||
xkl_create_description_from_list (item, subitem,
|
||||
XCI_PROP_LANGUAGE_LIST,
|
||||
xkl_get_language_name);
|
||||
|
||||
gchar *tmp = utf_variant_name;
|
||||
utf_variant_name =
|
||||
g_regex_replace_literal (left_bracket_regex, tmp, -1, 0,
|
||||
"<", 0, NULL);
|
||||
g_free (tmp);
|
||||
|
||||
if (subitem
|
||||
&& g_object_get_data (G_OBJECT (subitem),
|
||||
XCI_PROP_EXTRA_ITEM)) {
|
||||
gchar *buf =
|
||||
g_strdup_printf ("<i>%s</i>", utf_variant_name);
|
||||
gtk_list_store_insert_with_values (list_store, &iter, -1,
|
||||
COMBO_BOX_MODEL_COL_SORT,
|
||||
utf_variant_name,
|
||||
COMBO_BOX_MODEL_COL_VISIBLE,
|
||||
buf,
|
||||
COMBO_BOX_MODEL_COL_XKB_ID,
|
||||
xkb_id,
|
||||
COMBO_BOX_MODEL_COL_COUNTRY_DESC,
|
||||
country_desc,
|
||||
COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
|
||||
language_desc, -1);
|
||||
g_free (buf);
|
||||
} else
|
||||
gtk_list_store_insert_with_values (list_store, &iter,
|
||||
-1,
|
||||
COMBO_BOX_MODEL_COL_SORT,
|
||||
utf_variant_name,
|
||||
COMBO_BOX_MODEL_COL_VISIBLE,
|
||||
utf_variant_name,
|
||||
COMBO_BOX_MODEL_COL_XKB_ID,
|
||||
xkb_id,
|
||||
COMBO_BOX_MODEL_COL_COUNTRY_DESC,
|
||||
country_desc,
|
||||
COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
|
||||
language_desc, -1);
|
||||
g_free (utf_variant_name);
|
||||
g_free (country_desc);
|
||||
g_free (language_desc);
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_layout_filter_clear (GtkEntry * entry,
|
||||
GtkEntryIconPosition icon_pos,
|
||||
GdkEvent * event, gpointer user_data)
|
||||
{
|
||||
gtk_entry_set_text (entry, "");
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_layout_filter_changed (GtkBuilder * chooser_dialog)
|
||||
{
|
||||
GtkTreeModelFilter *filtered_model =
|
||||
GTK_TREE_MODEL_FILTER (gtk_builder_get_object (chooser_dialog,
|
||||
"filtered_layout_list_model"));
|
||||
GtkWidget *xkb_layout_filter = CWID ("xkb_layout_filter");
|
||||
const gchar *pattern =
|
||||
gtk_entry_get_text (GTK_ENTRY (xkb_layout_filter));
|
||||
gchar *upattern = g_utf8_strup (pattern, -1);
|
||||
|
||||
if (!g_strcmp0 (pattern, "")) {
|
||||
g_object_set (G_OBJECT (xkb_layout_filter),
|
||||
"secondary-icon-name", "edit-find-symbolic",
|
||||
"secondary-icon-activatable", FALSE,
|
||||
"secondary-icon-sensitive", FALSE, NULL);
|
||||
} else {
|
||||
g_object_set (G_OBJECT (xkb_layout_filter),
|
||||
"secondary-icon-name", "edit-clear-symbolic",
|
||||
"secondary-icon-activatable", TRUE,
|
||||
"secondary-icon-sensitive", TRUE, NULL);
|
||||
}
|
||||
|
||||
if (search_pattern_list != NULL)
|
||||
g_strfreev (search_pattern_list);
|
||||
|
||||
search_pattern_list = g_strsplit (upattern, " ", -1);
|
||||
g_free (upattern);
|
||||
|
||||
gtk_tree_model_filter_refilter (filtered_model);
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_layout_chooser_selection_changed (GtkTreeSelection * selection,
|
||||
GtkBuilder * chooser_dialog)
|
||||
{
|
||||
GList *selected_layouts =
|
||||
gtk_tree_selection_get_selected_rows (selection, NULL);
|
||||
GtkWidget *add_button = CWID ("btnOk");
|
||||
GtkWidget *preview_button = CWID ("btnPreview");
|
||||
gboolean anything_selected = g_list_length (selected_layouts) == 1;
|
||||
gboolean dupe =
|
||||
xkb_layout_chooser_selection_dupe (GTK_DIALOG
|
||||
(CWID
|
||||
("xkb_layout_chooser")));
|
||||
|
||||
gtk_widget_set_sensitive (add_button, anything_selected && !dupe);
|
||||
gtk_widget_set_sensitive (preview_button, anything_selected);
|
||||
}
|
||||
|
||||
static void
|
||||
xkb_layout_chooser_row_activated (GtkTreeView * tree_view,
|
||||
GtkTreePath * path,
|
||||
GtkTreeViewColumn * column,
|
||||
GtkBuilder * chooser_dialog)
|
||||
{
|
||||
GtkWidget *add_button = CWID ("btnOk");
|
||||
GtkWidget *dialog = CWID ("xkb_layout_chooser");
|
||||
|
||||
if (gtk_widget_is_sensitive (add_button))
|
||||
gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xkb_filter_layouts (GtkTreeModel * model,
|
||||
GtkTreeIter * iter, gpointer data)
|
||||
{
|
||||
gchar *desc = NULL, *country_desc = NULL, *language_desc =
|
||||
NULL, **pattern;
|
||||
gboolean rv = TRUE;
|
||||
|
||||
if (search_pattern_list == NULL || search_pattern_list[0] == NULL)
|
||||
return TRUE;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
COMBO_BOX_MODEL_COL_SORT, &desc,
|
||||
COMBO_BOX_MODEL_COL_COUNTRY_DESC,
|
||||
&country_desc,
|
||||
COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
|
||||
&language_desc, -1);
|
||||
|
||||
pattern = search_pattern_list;
|
||||
do {
|
||||
gboolean is_pattern_found = FALSE;
|
||||
gchar *udesc = g_utf8_strup (desc, -1);
|
||||
if (udesc != NULL && g_strstr_len (udesc, -1, *pattern)) {
|
||||
is_pattern_found = TRUE;
|
||||
} else if (country_desc != NULL
|
||||
&& g_strstr_len (country_desc, -1, *pattern)) {
|
||||
is_pattern_found = TRUE;
|
||||
} else if (language_desc != NULL
|
||||
&& g_strstr_len (language_desc, -1, *pattern)) {
|
||||
is_pattern_found = TRUE;
|
||||
}
|
||||
g_free (udesc);
|
||||
|
||||
if (!is_pattern_found) {
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (*++pattern != NULL);
|
||||
|
||||
g_free (desc);
|
||||
g_free (country_desc);
|
||||
g_free (language_desc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
xkb_layout_choose (GtkBuilder * dialog)
|
||||
{
|
||||
GtkBuilder *chooser_dialog = gtk_builder_new ();
|
||||
GtkWidget *chooser, *xkb_filtered_layouts_list, *xkb_layout_filter;
|
||||
GtkTreeViewColumn *visible_column;
|
||||
GtkTreeSelection *selection;
|
||||
GtkListStore *model;
|
||||
GtkTreeModelFilter *filtered_model;
|
||||
|
||||
gtk_builder_add_from_file (chooser_dialog, GNOMECC_UI_DIR
|
||||
"/gnome-region-panel-layout-chooser.ui",
|
||||
NULL);
|
||||
chooser = CWID ("xkb_layout_chooser");
|
||||
xkb_filtered_layouts_list = CWID ("xkb_filtered_layouts_list");
|
||||
xkb_layout_filter = CWID ("xkb_layout_filter");
|
||||
|
||||
g_object_set_data (G_OBJECT (chooser), "xkb_filtered_layouts_list",
|
||||
xkb_filtered_layouts_list);
|
||||
visible_column =
|
||||
gtk_tree_view_column_new_with_attributes ("Layout",
|
||||
gtk_cell_renderer_text_new
|
||||
(), "markup",
|
||||
COMBO_BOX_MODEL_COL_VISIBLE,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (chooser),
|
||||
GTK_WINDOW
|
||||
(gtk_widget_get_toplevel
|
||||
(WID ("region_notebook"))));
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW
|
||||
(xkb_filtered_layouts_list),
|
||||
visible_column);
|
||||
g_signal_connect_swapped (G_OBJECT (xkb_layout_filter),
|
||||
"notify::text",
|
||||
G_CALLBACK
|
||||
(xkb_layout_filter_changed),
|
||||
chooser_dialog);
|
||||
|
||||
g_signal_connect (G_OBJECT (xkb_layout_filter), "icon-release",
|
||||
G_CALLBACK (xkb_layout_filter_clear), NULL);
|
||||
|
||||
selection =
|
||||
gtk_tree_view_get_selection (GTK_TREE_VIEW
|
||||
(xkb_filtered_layouts_list));
|
||||
|
||||
g_signal_connect (G_OBJECT (selection),
|
||||
"changed",
|
||||
G_CALLBACK
|
||||
(xkb_layout_chooser_selection_changed),
|
||||
chooser_dialog);
|
||||
|
||||
xkb_layout_chooser_selection_changed (selection, chooser_dialog);
|
||||
|
||||
g_signal_connect (G_OBJECT (xkb_filtered_layouts_list),
|
||||
"row-activated",
|
||||
G_CALLBACK (xkb_layout_chooser_row_activated),
|
||||
chooser_dialog);
|
||||
|
||||
filtered_model =
|
||||
GTK_TREE_MODEL_FILTER (gtk_builder_get_object
|
||||
(chooser_dialog,
|
||||
"filtered_layout_list_model"));
|
||||
model =
|
||||
GTK_LIST_STORE (gtk_builder_get_object
|
||||
(chooser_dialog, "layout_list_model"));
|
||||
|
||||
left_bracket_regex = g_regex_new ("<", 0, 0, NULL);
|
||||
|
||||
xkl_config_registry_search_by_pattern (config_registry,
|
||||
NULL,
|
||||
(TwoConfigItemsProcessFunc)
|
||||
(xkl_layout_add_to_list),
|
||||
chooser_dialog);
|
||||
|
||||
g_regex_unref (left_bracket_regex);
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
|
||||
COMBO_BOX_MODEL_COL_SORT,
|
||||
GTK_SORT_ASCENDING);
|
||||
|
||||
gtk_tree_model_filter_set_visible_func (filtered_model,
|
||||
xkb_filter_layouts,
|
||||
NULL, NULL);
|
||||
|
||||
gtk_widget_grab_focus (xkb_layout_filter);
|
||||
|
||||
gtk_widget_show (chooser);
|
||||
|
||||
return chooser;
|
||||
}
|
||||
|
||||
gchar *
|
||||
xkb_layout_chooser_get_selected_id (GtkDialog * dialog)
|
||||
{
|
||||
GtkTreeModel *filtered_list_model;
|
||||
GtkWidget *xkb_filtered_layouts_list =
|
||||
g_object_get_data (G_OBJECT (dialog),
|
||||
"xkb_filtered_layouts_list");
|
||||
GtkTreeIter viter;
|
||||
gchar *v_id;
|
||||
GtkTreeSelection *selection =
|
||||
gtk_tree_view_get_selection (GTK_TREE_VIEW
|
||||
(xkb_filtered_layouts_list));
|
||||
GList *selected_layouts =
|
||||
gtk_tree_selection_get_selected_rows (selection,
|
||||
&filtered_list_model);
|
||||
|
||||
if (g_list_length (selected_layouts) != 1)
|
||||
return NULL;
|
||||
|
||||
gtk_tree_model_get_iter (filtered_list_model,
|
||||
&viter,
|
||||
(GtkTreePath *) (selected_layouts->data));
|
||||
g_list_foreach (selected_layouts,
|
||||
(GFunc) gtk_tree_path_free, NULL);
|
||||
g_list_free (selected_layouts);
|
||||
|
||||
gtk_tree_model_get (filtered_list_model, &viter,
|
||||
COMBO_BOX_MODEL_COL_XKB_ID, &v_id, -1);
|
||||
|
||||
return v_id;
|
||||
}
|
||||
@@ -1,515 +0,0 @@
|
||||
/* gnome-region-panel-xkbot.c
|
||||
* Copyright (C) 2003-2007 Sergey V. Udaltsov
|
||||
*
|
||||
* Written by: Sergey V. Udaltsov <svu@gnome.org>
|
||||
* John Spray <spray_john@users.sourceforge.net>
|
||||
*
|
||||
* 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, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gnome-region-panel-xkb.h"
|
||||
|
||||
static GtkBuilder *chooser_dialog = NULL;
|
||||
static const char *current1st_level_id = NULL;
|
||||
static GSList *option_checks_list = NULL;
|
||||
static GtkWidget *current_none_radio = NULL;
|
||||
static GtkWidget *current_expander = NULL;
|
||||
static gboolean current_multi_select = FALSE;
|
||||
static GSList *current_radio_group = NULL;
|
||||
|
||||
#define OPTION_ID_PROP "optionID"
|
||||
#define SELCOUNTER_PROP "selectionCounter"
|
||||
#define GCONFSTATE_PROP "gconfState"
|
||||
#define EXPANDERS_PROP "expandersList"
|
||||
|
||||
gchar **
|
||||
xkb_options_get_selected_list (void)
|
||||
{
|
||||
gchar **retval;
|
||||
|
||||
retval =
|
||||
g_settings_get_strv (xkb_keyboard_settings,
|
||||
GKBD_KEYBOARD_CONFIG_KEY_OPTIONS);
|
||||
if (retval == NULL) {
|
||||
retval = g_strdupv (initial_config.options);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Returns the selection counter of the expander (static current_expander) */
|
||||
static int
|
||||
xkb_options_expander_selcounter_get (void)
|
||||
{
|
||||
return
|
||||
GPOINTER_TO_INT (g_object_get_data
|
||||
(G_OBJECT (current_expander),
|
||||
SELCOUNTER_PROP));
|
||||
}
|
||||
|
||||
/* Increments the selection counter in the expander (static current_expander)
|
||||
using the value (can be 0)*/
|
||||
static void
|
||||
xkb_options_expander_selcounter_add (int value)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (current_expander), SELCOUNTER_PROP,
|
||||
GINT_TO_POINTER
|
||||
(xkb_options_expander_selcounter_get ()
|
||||
+ value));
|
||||
}
|
||||
|
||||
/* Resets the seletion counter in the expander (static current_expander) */
|
||||
static void
|
||||
xkb_options_expander_selcounter_reset (void)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (current_expander), SELCOUNTER_PROP,
|
||||
GINT_TO_POINTER (0));
|
||||
}
|
||||
|
||||
/* Formats the expander (static current_expander), based on the selection counter */
|
||||
static void
|
||||
xkb_options_expander_highlight (void)
|
||||
{
|
||||
char *utf_group_name =
|
||||
g_object_get_data (G_OBJECT (current_expander),
|
||||
"utfGroupName");
|
||||
int counter = xkb_options_expander_selcounter_get ();
|
||||
if (utf_group_name != NULL) {
|
||||
gchar *titlemarkup =
|
||||
g_strconcat (counter >
|
||||
0 ? "<span weight=\"bold\">" : "<span>",
|
||||
utf_group_name, "</span>", NULL);
|
||||
gtk_expander_set_label (GTK_EXPANDER (current_expander),
|
||||
titlemarkup);
|
||||
g_free (titlemarkup);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add optionname from the backend's selection list if it's not
|
||||
already in there. */
|
||||
static void
|
||||
xkb_options_select (gchar * optionname)
|
||||
{
|
||||
gboolean already_selected = FALSE;
|
||||
gchar **options_list;
|
||||
guint i;
|
||||
|
||||
options_list = xkb_options_get_selected_list ();
|
||||
for (i = 0; options_list != NULL && options_list[i] != NULL; i++) {
|
||||
gchar *option = options_list[i];
|
||||
if (!strcmp (option, optionname)) {
|
||||
already_selected = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!already_selected) {
|
||||
options_list =
|
||||
gkbd_strv_append (options_list, g_strdup (optionname));
|
||||
xkb_options_set_selected_list (options_list);
|
||||
}
|
||||
|
||||
g_strfreev (options_list);
|
||||
}
|
||||
|
||||
/* Remove all occurences of optionname from the backend's selection list */
|
||||
static void
|
||||
xkb_options_deselect (gchar * optionname)
|
||||
{
|
||||
gchar **options_list = xkb_options_get_selected_list ();
|
||||
if (options_list != NULL) {
|
||||
gchar **option = options_list;
|
||||
while (*option != NULL) {
|
||||
gchar *id = *option;
|
||||
if (!strcmp (id, optionname)) {
|
||||
gkbd_strv_behead (option);
|
||||
} else
|
||||
option++;
|
||||
}
|
||||
xkb_options_set_selected_list (options_list);
|
||||
}
|
||||
g_strfreev (options_list);
|
||||
}
|
||||
|
||||
/* Return true if optionname describes a string already in the backend's
|
||||
list of selected options */
|
||||
static gboolean
|
||||
xkb_options_is_selected (gchar * optionname)
|
||||
{
|
||||
gboolean retval = FALSE;
|
||||
gchar **options_list = xkb_options_get_selected_list ();
|
||||
if (options_list != NULL) {
|
||||
gchar **option = options_list;
|
||||
while (*option != NULL) {
|
||||
if (!strcmp (*option, optionname)) {
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
option++;
|
||||
}
|
||||
}
|
||||
g_strfreev (options_list);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Make sure selected options stay visible when navigating with the keyboard */
|
||||
static gboolean
|
||||
option_focused_cb (GtkWidget * widget, GdkEventFocus * event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkScrolledWindow *win = GTK_SCROLLED_WINDOW (data);
|
||||
GtkAllocation alloc;
|
||||
GtkAdjustment *adj;
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
adj = gtk_scrolled_window_get_vadjustment (win);
|
||||
gtk_adjustment_clamp_page (adj, alloc.y, alloc.y + alloc.height);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Update xkb backend to reflect the new UI state */
|
||||
static void
|
||||
option_toggled_cb (GtkWidget * checkbutton, gpointer data)
|
||||
{
|
||||
gpointer optionID =
|
||||
g_object_get_data (G_OBJECT (checkbutton), OPTION_ID_PROP);
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton)))
|
||||
xkb_options_select (optionID);
|
||||
else
|
||||
xkb_options_deselect (optionID);
|
||||
}
|
||||
|
||||
/* Add a check_button or radio_button to control a particular option
|
||||
This function makes particular use of the current... variables at
|
||||
the top of this file. */
|
||||
static void
|
||||
xkb_options_add_option (XklConfigRegistry * config_registry,
|
||||
XklConfigItem * config_item, GtkBuilder * dialog)
|
||||
{
|
||||
GtkWidget *option_check;
|
||||
gchar *utf_option_name = xci_desc_to_utf8 (config_item);
|
||||
/* Copy this out because we'll load it into the widget with set_data */
|
||||
gchar *full_option_name =
|
||||
g_strdup (gkbd_keyboard_config_merge_items
|
||||
(current1st_level_id, config_item->name));
|
||||
gboolean initial_state;
|
||||
|
||||
if (current_multi_select)
|
||||
option_check =
|
||||
gtk_check_button_new_with_label (utf_option_name);
|
||||
else {
|
||||
if (current_radio_group == NULL) {
|
||||
/* The first radio in a group is to be "Default", meaning none of
|
||||
the below options are to be included in the selected list.
|
||||
This is a HIG-compliant alternative to allowing no
|
||||
selection in the group. */
|
||||
option_check =
|
||||
gtk_radio_button_new_with_label
|
||||
(current_radio_group, _("Default"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
|
||||
(option_check),
|
||||
TRUE);
|
||||
/* Make option name underscore -
|
||||
to enforce its first position in the list */
|
||||
g_object_set_data_full (G_OBJECT (option_check),
|
||||
"utfOptionName",
|
||||
g_strdup (" "), g_free);
|
||||
option_checks_list =
|
||||
g_slist_append (option_checks_list,
|
||||
option_check);
|
||||
current_radio_group =
|
||||
gtk_radio_button_get_group (GTK_RADIO_BUTTON
|
||||
(option_check));
|
||||
current_none_radio = option_check;
|
||||
|
||||
g_signal_connect (option_check, "focus-in-event",
|
||||
G_CALLBACK (option_focused_cb),
|
||||
WID ("options_scroll"));
|
||||
}
|
||||
option_check =
|
||||
gtk_radio_button_new_with_label (current_radio_group,
|
||||
utf_option_name);
|
||||
current_radio_group =
|
||||
gtk_radio_button_get_group (GTK_RADIO_BUTTON
|
||||
(option_check));
|
||||
g_object_set_data (G_OBJECT (option_check), "NoneRadio",
|
||||
current_none_radio);
|
||||
}
|
||||
|
||||
initial_state = xkb_options_is_selected (full_option_name);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (option_check),
|
||||
initial_state);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (option_check), OPTION_ID_PROP,
|
||||
full_option_name, g_free);
|
||||
g_object_set_data_full (G_OBJECT (option_check), "utfOptionName",
|
||||
utf_option_name, g_free);
|
||||
|
||||
g_signal_connect (option_check, "toggled",
|
||||
G_CALLBACK (option_toggled_cb), NULL);
|
||||
|
||||
option_checks_list =
|
||||
g_slist_append (option_checks_list, option_check);
|
||||
|
||||
g_signal_connect (option_check, "focus-in-event",
|
||||
G_CALLBACK (option_focused_cb),
|
||||
WID ("options_scroll"));
|
||||
|
||||
xkb_options_expander_selcounter_add (initial_state);
|
||||
g_object_set_data (G_OBJECT (option_check), GCONFSTATE_PROP,
|
||||
GINT_TO_POINTER (initial_state));
|
||||
}
|
||||
|
||||
static gint
|
||||
xkb_option_checks_compare (GtkWidget * chk1, GtkWidget * chk2)
|
||||
{
|
||||
const gchar *t1 =
|
||||
g_object_get_data (G_OBJECT (chk1), "utfOptionName");
|
||||
const gchar *t2 =
|
||||
g_object_get_data (G_OBJECT (chk2), "utfOptionName");
|
||||
return g_utf8_collate (t1, t2);
|
||||
}
|
||||
|
||||
/* Add a group of options: create title and layout widgets and then
|
||||
add widgets for all the options in the group. */
|
||||
static void
|
||||
xkb_options_add_group (XklConfigRegistry * config_registry,
|
||||
XklConfigItem * config_item, GtkBuilder * dialog)
|
||||
{
|
||||
GtkWidget *align, *vbox, *option_check;
|
||||
gboolean allow_multiple_selection =
|
||||
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (config_item),
|
||||
XCI_PROP_ALLOW_MULTIPLE_SELECTION));
|
||||
|
||||
GSList *expanders_list =
|
||||
g_object_get_data (G_OBJECT (dialog), EXPANDERS_PROP);
|
||||
|
||||
gchar *utf_group_name = xci_desc_to_utf8 (config_item);
|
||||
gchar *titlemarkup =
|
||||
g_strconcat ("<span>", utf_group_name, "</span>", NULL);
|
||||
|
||||
current_expander = gtk_expander_new (titlemarkup);
|
||||
gtk_expander_set_use_markup (GTK_EXPANDER (current_expander),
|
||||
TRUE);
|
||||
g_object_set_data_full (G_OBJECT (current_expander),
|
||||
"utfGroupName", utf_group_name, g_free);
|
||||
g_object_set_data_full (G_OBJECT (current_expander), "groupId",
|
||||
g_strdup (config_item->name), g_free);
|
||||
|
||||
g_free (titlemarkup);
|
||||
align = gtk_alignment_new (0, 0, 1, 1);
|
||||
gtk_alignment_set_padding (GTK_ALIGNMENT (align), 6, 12, 12, 0);
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_box_set_homogeneous (GTK_BOX (vbox), TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (align), vbox);
|
||||
gtk_container_add (GTK_CONTAINER (current_expander), align);
|
||||
|
||||
current_multi_select = (gboolean) allow_multiple_selection;
|
||||
current_radio_group = NULL;
|
||||
current1st_level_id = config_item->name;
|
||||
|
||||
option_checks_list = NULL;
|
||||
|
||||
xkl_config_registry_foreach_option (config_registry,
|
||||
config_item->name,
|
||||
(ConfigItemProcessFunc)
|
||||
xkb_options_add_option,
|
||||
dialog);
|
||||
/* sort it */
|
||||
option_checks_list =
|
||||
g_slist_sort (option_checks_list,
|
||||
(GCompareFunc) xkb_option_checks_compare);
|
||||
while (option_checks_list) {
|
||||
option_check = GTK_WIDGET (option_checks_list->data);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), option_check, TRUE,
|
||||
TRUE, 0);
|
||||
option_checks_list = option_checks_list->next;
|
||||
}
|
||||
/* free it */
|
||||
g_slist_free (option_checks_list);
|
||||
option_checks_list = NULL;
|
||||
|
||||
xkb_options_expander_highlight ();
|
||||
|
||||
expanders_list = g_slist_append (expanders_list, current_expander);
|
||||
g_object_set_data (G_OBJECT (dialog), EXPANDERS_PROP,
|
||||
expanders_list);
|
||||
|
||||
g_signal_connect (current_expander, "focus-in-event",
|
||||
G_CALLBACK (option_focused_cb),
|
||||
WID ("options_scroll"));
|
||||
}
|
||||
|
||||
static gint
|
||||
xkb_options_expanders_compare (GtkWidget * expander1,
|
||||
GtkWidget * expander2)
|
||||
{
|
||||
const gchar *t1 =
|
||||
g_object_get_data (G_OBJECT (expander1), "utfGroupName");
|
||||
const gchar *t2 =
|
||||
g_object_get_data (G_OBJECT (expander2), "utfGroupName");
|
||||
return g_utf8_collate (t1, t2);
|
||||
}
|
||||
|
||||
/* Create widgets to represent the options made available by the backend */
|
||||
void
|
||||
xkb_options_load_options (GtkBuilder * dialog)
|
||||
{
|
||||
GtkWidget *opts_vbox = WID ("options_vbox");
|
||||
GtkWidget *dialog_vbox = WID ("dialog_vbox");
|
||||
GtkWidget *options_scroll = WID ("options_scroll");
|
||||
GtkWidget *expander;
|
||||
GSList *expanders_list;
|
||||
|
||||
current1st_level_id = NULL;
|
||||
current_none_radio = NULL;
|
||||
current_multi_select = FALSE;
|
||||
current_radio_group = NULL;
|
||||
|
||||
/* fill the list */
|
||||
xkl_config_registry_foreach_option_group (config_registry,
|
||||
(ConfigItemProcessFunc)
|
||||
xkb_options_add_group,
|
||||
dialog);
|
||||
/* sort it */
|
||||
expanders_list =
|
||||
g_object_get_data (G_OBJECT (dialog), EXPANDERS_PROP);
|
||||
expanders_list =
|
||||
g_slist_sort (expanders_list,
|
||||
(GCompareFunc) xkb_options_expanders_compare);
|
||||
g_object_set_data (G_OBJECT (dialog), EXPANDERS_PROP,
|
||||
expanders_list);
|
||||
while (expanders_list) {
|
||||
expander = GTK_WIDGET (expanders_list->data);
|
||||
gtk_box_pack_start (GTK_BOX (opts_vbox), expander, FALSE,
|
||||
FALSE, 0);
|
||||
expanders_list = expanders_list->next;
|
||||
}
|
||||
|
||||
/* Somewhere in gtk3 the top vbox in dialog is made non-expandable */
|
||||
gtk_box_set_child_packing (GTK_BOX (dialog_vbox), options_scroll,
|
||||
TRUE, TRUE, 0, GTK_PACK_START);
|
||||
gtk_widget_show_all (dialog_vbox);
|
||||
}
|
||||
|
||||
static void
|
||||
chooser_response_cb (GtkDialog * dialog, gint response, gpointer data)
|
||||
{
|
||||
switch (response) {
|
||||
case GTK_RESPONSE_DELETE_EVENT:
|
||||
case GTK_RESPONSE_CLOSE: {
|
||||
/* just cleanup */
|
||||
GSList *expanders_list =
|
||||
g_object_get_data (G_OBJECT (dialog),
|
||||
EXPANDERS_PROP);
|
||||
g_object_set_data (G_OBJECT (dialog),
|
||||
EXPANDERS_PROP, NULL);
|
||||
g_slist_free (expanders_list);
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
chooser_dialog = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create popup dialog */
|
||||
void
|
||||
xkb_options_popup_dialog (GtkBuilder * dialog)
|
||||
{
|
||||
GtkWidget *chooser;
|
||||
|
||||
chooser_dialog = gtk_builder_new ();
|
||||
gtk_builder_add_from_file (chooser_dialog, GNOMECC_UI_DIR
|
||||
"/gnome-region-panel-options-dialog.ui",
|
||||
NULL);
|
||||
|
||||
chooser = CWID ("xkb_options_dialog");
|
||||
gtk_window_set_transient_for (GTK_WINDOW (chooser),
|
||||
GTK_WINDOW (gtk_widget_get_toplevel (WID ("region_notebook"))));
|
||||
gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
|
||||
xkb_options_load_options (chooser_dialog);
|
||||
|
||||
g_signal_connect (chooser, "response",
|
||||
G_CALLBACK (chooser_response_cb), dialog);
|
||||
gtk_widget_show (chooser);
|
||||
}
|
||||
|
||||
/* Update selected option counters for a group-bound expander */
|
||||
static void
|
||||
xkb_options_update_option_counters (XklConfigRegistry * config_registry,
|
||||
XklConfigItem * config_item)
|
||||
{
|
||||
gchar *full_option_name =
|
||||
g_strdup (gkbd_keyboard_config_merge_items
|
||||
(current1st_level_id, config_item->name));
|
||||
gboolean current_state =
|
||||
xkb_options_is_selected (full_option_name);
|
||||
g_free (full_option_name);
|
||||
|
||||
xkb_options_expander_selcounter_add (current_state);
|
||||
}
|
||||
|
||||
/* Respond to a change in the xkb gconf settings */
|
||||
static void
|
||||
xkb_options_update (GSettings * settings, gchar * key, GtkBuilder * dialog)
|
||||
{
|
||||
if (!strcmp (key, GKBD_KEYBOARD_CONFIG_KEY_OPTIONS)) {
|
||||
/* Updating options is handled by gconf notifies for each widget
|
||||
This is here to avoid calling it N_OPTIONS times for each gconf
|
||||
change. */
|
||||
enable_disable_restoring (dialog);
|
||||
|
||||
if (chooser_dialog != NULL) {
|
||||
GSList *expanders_list =
|
||||
g_object_get_data (G_OBJECT (chooser_dialog),
|
||||
EXPANDERS_PROP);
|
||||
while (expanders_list) {
|
||||
current_expander =
|
||||
GTK_WIDGET (expanders_list->data);
|
||||
gchar *group_id =
|
||||
g_object_get_data (G_OBJECT
|
||||
(current_expander),
|
||||
"groupId");
|
||||
current1st_level_id = group_id;
|
||||
xkb_options_expander_selcounter_reset ();
|
||||
xkl_config_registry_foreach_option
|
||||
(config_registry, group_id,
|
||||
(ConfigItemProcessFunc)
|
||||
xkb_options_update_option_counters,
|
||||
current_expander);
|
||||
xkb_options_expander_highlight ();
|
||||
expanders_list = expanders_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xkb_options_register_conf_listener (GtkBuilder * dialog)
|
||||
{
|
||||
g_signal_connect (xkb_keyboard_settings, "changed",
|
||||
G_CALLBACK (xkb_options_update), dialog);
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/* gnome-region-panel-xkbpv.c
|
||||
* Copyright (C) 2003-2007 Sergey V. Udaltsov
|
||||
*
|
||||
* Written by: Sergey V. Udaltsov <svu@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 2, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libgnomekbd/gkbd-keyboard-drawing.h>
|
||||
|
||||
#include "gnome-region-panel-xkb.h"
|
||||
|
||||
#ifdef HAVE_X11_EXTENSIONS_XKB_H
|
||||
#include "X11/XKBlib.h"
|
||||
/**
|
||||
* BAD STYLE: Taken from xklavier_private_xkb.h
|
||||
* Any ideas on architectural improvements are WELCOME
|
||||
*/
|
||||
extern gboolean xkl_xkb_config_native_prepare (XklEngine * engine,
|
||||
const XklConfigRec * data,
|
||||
XkbComponentNamesPtr
|
||||
component_names);
|
||||
|
||||
extern void xkl_xkb_config_native_cleanup (XklEngine * engine,
|
||||
XkbComponentNamesPtr
|
||||
component_names);
|
||||
|
||||
/* */
|
||||
#endif
|
||||
|
||||
static GkbdKeyboardDrawingGroupLevel groupsLevels[] =
|
||||
{ {0, 1}, {0, 3}, {0, 0}, {0, 2} };
|
||||
static GkbdKeyboardDrawingGroupLevel *pGroupsLevels[] = {
|
||||
groupsLevels, groupsLevels + 1, groupsLevels + 2, groupsLevels + 3
|
||||
};
|
||||
|
||||
GtkWidget *
|
||||
xkb_layout_preview_create_widget (GtkBuilder * chooserDialog)
|
||||
{
|
||||
GtkWidget *kbdraw = gkbd_keyboard_drawing_new ();
|
||||
|
||||
gkbd_keyboard_drawing_set_groups_levels (GKBD_KEYBOARD_DRAWING
|
||||
(kbdraw), pGroupsLevels);
|
||||
return kbdraw;
|
||||
}
|
||||
|
||||
void
|
||||
xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw,
|
||||
const gchar * id)
|
||||
{
|
||||
#ifdef HAVE_X11_EXTENSIONS_XKB_H
|
||||
if (kbdraw != NULL) {
|
||||
if (id != NULL) {
|
||||
XklConfigRec *data;
|
||||
char **p, *layout, *variant;
|
||||
XkbComponentNamesRec component_names;
|
||||
|
||||
data = xkl_config_rec_new ();
|
||||
if (xkl_config_rec_get_from_server (data, engine)) {
|
||||
if ((p = data->layouts) != NULL)
|
||||
g_strfreev (data->layouts);
|
||||
|
||||
if ((p = data->variants) != NULL)
|
||||
g_strfreev (data->variants);
|
||||
|
||||
data->layouts = g_new0 (char *, 2);
|
||||
data->variants = g_new0 (char *, 2);
|
||||
if (gkbd_keyboard_config_split_items
|
||||
(id, &layout, &variant)
|
||||
&& variant != NULL) {
|
||||
data->layouts[0] =
|
||||
(layout ==
|
||||
NULL) ? NULL :
|
||||
g_strdup (layout);
|
||||
data->variants[0] =
|
||||
(variant ==
|
||||
NULL) ? NULL :
|
||||
g_strdup (variant);
|
||||
} else {
|
||||
data->layouts[0] =
|
||||
(id ==
|
||||
NULL) ? NULL : g_strdup (id);
|
||||
data->variants[0] = NULL;
|
||||
}
|
||||
|
||||
if (xkl_xkb_config_native_prepare
|
||||
(engine, data, &component_names)) {
|
||||
gkbd_keyboard_drawing_set_keyboard
|
||||
(GKBD_KEYBOARD_DRAWING
|
||||
(kbdraw), &component_names);
|
||||
|
||||
xkl_xkb_config_native_cleanup
|
||||
(engine, &component_names);
|
||||
}
|
||||
}
|
||||
g_object_unref (G_OBJECT (data));
|
||||
} else
|
||||
gkbd_keyboard_drawing_set_keyboard
|
||||
(GKBD_KEYBOARD_DRAWING (kbdraw), NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.22"/>
|
||||
<!-- interface-requires gtk+ 3.0 -->
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="lower">100</property>
|
||||
<property name="upper">2000</property>
|
||||
@@ -152,6 +152,55 @@
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="language-toolbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="toolbar_style">icons</property>
|
||||
<property name="show_arrow">False</property>
|
||||
<property name="icon_size">1</property>
|
||||
<style>
|
||||
<class name="inline-toolbar"/>
|
||||
</style>
|
||||
<style>
|
||||
<class name="inline-toolbar"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="language_add">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Add Language</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="language_remove">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="label" translatable="yes">Remove Language</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-remove-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox3">
|
||||
<property name="can_focus">False</property>
|
||||
@@ -159,6 +208,8 @@
|
||||
<object class="GtkLabel" id="label23">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="label" translatable="yes">Add Language</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
@@ -173,9 +224,6 @@
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="has_tooltip">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="relief">none</property>
|
||||
<property name="uri">http://glade.gnome.org</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@@ -190,52 +238,6 @@
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="language-toolbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="toolbar_style">icons</property>
|
||||
<property name="show_arrow">False</property>
|
||||
<property name="icon_size">1</property>
|
||||
<style>
|
||||
<class name="inline-toolbar"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="language_add">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
<property name="label" translatable="yes">Add Language</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="language_remove">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-remove-symbolic</property>
|
||||
<property name="label" translatable="yes">Remove Language</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
@@ -259,12 +261,12 @@
|
||||
<object class="GtkGrid" id="table1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="margin_bottom">12</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="margin_bottom">12</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
@@ -273,92 +275,92 @@
|
||||
<property name="label" translatable="yes">Select a region (change will be applied the next time you log in)</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="region-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="region-swindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="valign">fill</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="region_selector">
|
||||
<object class="GtkScrolledWindow" id="region-swindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="region-treeview-selection"/>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="region_selector">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="region-treeview-selection"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="region-toolbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="toolbar_style">icons</property>
|
||||
<property name="show_arrow">False</property>
|
||||
<property name="icon_size">1</property>
|
||||
<style>
|
||||
<class name="inline-toolbar"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="region_add">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
<property name="label" translatable="yes">Add Region</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="region_remove">
|
||||
<object class="GtkToolbar" id="region-toolbar">
|
||||
<property name="toolbar_style">icons</property>
|
||||
<property name="show_arrow">False</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-remove-symbolic</property>
|
||||
<property name="label" translatable="yes">Remove Region</property>
|
||||
<style>
|
||||
<class name="inline-toolbar"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="region_add">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="label" translatable="yes">Add Region</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="region_remove">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Remove Region</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-remove-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -616,8 +618,16 @@
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
@@ -635,36 +645,43 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox1">
|
||||
<object class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">10</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
<object class="GtkLabel" id="label24">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Select keyboards or other input sources</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox2">
|
||||
<object class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox7">
|
||||
<object class="GtkVBox" id="vbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="xkb_layouts_swindow">
|
||||
<object class="GtkScrolledWindow" id="input_sources_swindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="xkb_layouts_selected">
|
||||
<object class="GtkTreeView" id="active_input_sources">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -675,7 +692,7 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="layouts-toolbar">
|
||||
<object class="GtkToolbar" id="input-toolbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="toolbar_style">icons</property>
|
||||
@@ -685,75 +702,166 @@
|
||||
<class name="inline-toolbar"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="xkb_layouts_add">
|
||||
<object class="GtkToolItem" id="i_s_ar_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
<property name="label" translatable="yes">Add Layout</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="i_s_ar_box">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="input_source_add">
|
||||
<property name="visible">True</property>
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="i_s_a_a11y">
|
||||
<property name="accessible-name" translatable="yes">Add Input Source</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="i_s_a_image">
|
||||
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="input_source_remove">
|
||||
<property name="visible">True</property>
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="i_s_r_a11y">
|
||||
<property name="accessible-name" translatable="yes">Remove Input Source</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="i_s_r_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">list-remove-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkToolButton" id="xkb_layouts_remove">
|
||||
<object class="GtkSeparatorToolItem" id="sep1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">list-remove-symbolic</property>
|
||||
<property name="label" translatable="yes">Remove Layout</property>
|
||||
<property name="draw">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="expand">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkToolButton" id="xkb_layouts_move_up">
|
||||
<object class="GtkToolItem" id="i_s_ud_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">go-up-symbolic</property>
|
||||
<property name="label" translatable="yes">Move Up</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="i_s_ud_box">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="input_source_move_up">
|
||||
<property name="visible">True</property>
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="i_s_u_a11y">
|
||||
<property name="accessible-name" translatable="yes">Move Input Source Up</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="i_s_u_image">
|
||||
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">go-up-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="input_source_move_down">
|
||||
<property name="visible">True</property>
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="i_s_d_a11y">
|
||||
<property name="accessible-name" translatable="yes">Move Input Source Down</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="i_s_d_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">go-down-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkToolButton" id="xkb_layouts_move_down">
|
||||
<object class="GtkSeparatorToolItem" id="sep2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">go-down-symbolic</property>
|
||||
<property name="label" translatable="yes">Move Down</property>
|
||||
<property name="draw">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="expand">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkToolButton" id="xkb_layouts_show">
|
||||
<object class="GtkToolItem" id="i_s_sp_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">input-keyboard-symbolic</property>
|
||||
<property name="label" translatable="yes">Preview Layout</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="i_s_sp_box">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="input_source_settings">
|
||||
<property name="visible">True</property>
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="i_s_s_a11y">
|
||||
<property name="accessible-name" translatable="yes">Input Source Settings</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="i_s_s_image">
|
||||
|
||||
<property name="visible">True</property>
|
||||
<property name="icon_name">preferences-system-symbolic</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="pixel_size">16</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="input_source_show">
|
||||
<property name="visible">True</property>
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="i_s_p_a11y">
|
||||
<property name="accessible-name" translatable="yes">Show Keyboard Layout</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="i_s_p_image">
|
||||
|
||||
<property name="visible">True</property>
|
||||
<property name="icon_name">input-keyboard-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@@ -769,174 +877,111 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox33">
|
||||
<object class="GtkFrame" id="frame4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox34">
|
||||
<object class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="chk_same_group">
|
||||
<property name="label" translatable="yes">Use the same layout for all windows</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="chk_separate_group_per_window">
|
||||
<property name="label" translatable="yes">Allow different layouts for individual windows</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">chk_same_group</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment1">
|
||||
<object class="GtkGrid" id="shortcuts-grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="left_padding">12</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox4">
|
||||
<object class="GtkLabel" id="prev-source-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="chk_new_windows_default_layout">
|
||||
<property name="label" translatable="yes">New windows use the default layout</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="chk_new_windows_inherit_layout">
|
||||
<property name="label" translatable="yes">New windows use the previous window's layout</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">chk_new_windows_default_layout</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Switch to previous source</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="prev-source-shortcut-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label" translatable="yes">Ctrl+Alt+Space</property>
|
||||
<style><class name="dim-label"/></style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="next-source-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Switch to next source</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="next-source-shortcut-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label" translatable="yes">Ctrl+Alt+Shift+Space</property>
|
||||
<style><class name="dim-label"/></style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLinkButton" id="jump-to-shortcuts">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Shortcut Settings</property>
|
||||
<property name="halign">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="shortcuts-frame-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Shortcuts</property>
|
||||
<property name="use_markup">True</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHButtonBox" id="hbuttonbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="xkb_layout_options">
|
||||
<property name="label" translatable="yes">_Options...</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="has_tooltip">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">View and edit keyboard layout options</property>
|
||||
<property name="tooltip_text" translatable="yes">View and edit keyboard layout options</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="xkb_reset_to_defaults">
|
||||
<property name="label" translatable="yes">Reset to De_faults</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="has_tooltip">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">Replace the current keyboard layout settings with the
|
||||
default settings</property>
|
||||
<property name="tooltip_text" translatable="yes">Replace the current keyboard layout settings with the
|
||||
default settings</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
<property name="secondary">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -954,17 +999,17 @@ default settings</property>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label46">
|
||||
<object class="GtkLabel" id="label13">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Layouts</property>
|
||||
<property name="label" translatable="yes">Input Sources</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
@@ -985,7 +1030,7 @@ default settings</property>
|
||||
<property name="ypad">6</property>
|
||||
<property name="label" translatable="yes">The login screen, system accounts and new user accounts use the system-wide Region and Language settings. You may change the system settings to match yours.</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="width-chars">60</property>
|
||||
<property name="width_chars">60</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="right_attach">2</property>
|
||||
@@ -1003,10 +1048,10 @@ default settings</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table4">
|
||||
<property name="margin_top">12</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="column_spacing">3</property>
|
||||
@@ -1130,10 +1175,10 @@ default settings</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table5">
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="column_spacing">3</property>
|
||||
@@ -1254,10 +1299,10 @@ default settings</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="copy_settings_button">
|
||||
<property name="label" translatable="yes">Copy Settings...</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@@ -1275,7 +1320,7 @@ default settings</property>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
@@ -1285,7 +1330,7 @@ default settings</property>
|
||||
<property name="label" translatable="yes">System</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
<property name="position">4</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
Preface
|
||||
|
||||
This document describes the scenarios which have to be checked every time someone makes changes in the gnome keyboard handling modules, namely:
|
||||
|
||||
- libxklavier (project in freedesktop.org CVS)
|
||||
- libgswitchit (virtual module in gnome.org CVS)
|
||||
- gnome-settings-daemon (module in gnome-control-center, gnome.org CVS)
|
||||
- gnome-keyboard-properties (module in gnome-control-center, gnome.org CVS)
|
||||
- gnome-keyboard-indicator (module in gnome-applets, gnome.org CVS)
|
||||
|
||||
Changes in configuration
|
||||
|
||||
The tests should be performed under different configurations, controlled by several variables:
|
||||
|
||||
- "group per window" mode (GPW: on/off): visible in UI
|
||||
- "default group" (DG: switchited off - or some group selected): only in GConf
|
||||
- "keep indicators with the group" (IPW: on/off): only in GConf
|
||||
- "hidden groups" (HG: some list of groups, can be empty): only in GConf
|
||||
|
||||
Taking that parameters DG and IPW only make sense when GPW is on, there are 5 combinations possible for the first 3 parameters. Taking that DG and IPW do not interfere, it is reasonable to test 3 combinations:
|
||||
|
||||
- GPW: off
|
||||
- GPW: on, DG: off, IPW: off
|
||||
- GPW: on, DG: {some value}, IPW: on
|
||||
|
||||
It is necessary to perform each test with the empty and non-empty HG. If HG is not empty, every test should be performed with both "enabled" and "hidden" groups.
|
||||
|
||||
Test cases
|
||||
|
||||
1. Open a terminal window. Type in some characters. Change the group using some chosen keyboard combination (default LAlt-RAlt or any other from the list of available ones). Type in some characters - ensure the group was changed.
|
||||
|
||||
2. Same as #1 - but change the group by clicking on the indicator applet
|
||||
|
||||
3. Same as #1 - but choose the group from the applet's menu
|
||||
|
||||
4. Set the US group in one terminal window. Create new terminal window. Ensure the group matches the DG setting.
|
||||
|
||||
5. Switch between two terminal windows using Alt-Tab. Ensure the behaviour matches the GPW setting and IPW setting.
|
||||
|
||||
6. Same as #5, but switch using the panel WindowList applet.
|
||||
|
||||
7. Change the settings in g-k-p, ensure the applet picks the changes.
|
||||
529
panels/region/xkb-rules-db.c
Normal file
529
panels/region/xkb-rules-db.c
Normal file
@@ -0,0 +1,529 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* Written by: Rui Matos <rmatos@redhat.com>
|
||||
*
|
||||
* 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, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBrules.h>
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "xkb-rules-db.h"
|
||||
|
||||
#ifndef DFLT_XKB_CONFIG_ROOT
|
||||
#define DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb"
|
||||
#endif
|
||||
#ifndef DFLT_XKB_RULES_FILE
|
||||
#define DFLT_XKB_RULES_FILE "base"
|
||||
#endif
|
||||
#ifndef DFLT_XKB_LAYOUT
|
||||
#define DFLT_XKB_LAYOUT "us"
|
||||
#endif
|
||||
#ifndef DFLT_XKB_MODEL
|
||||
#define DFLT_XKB_MODEL "pc105"
|
||||
#endif
|
||||
|
||||
typedef struct _Layout Layout;
|
||||
struct _Layout
|
||||
{
|
||||
gchar *id;
|
||||
gchar *xkb_name;
|
||||
gchar *short_id;
|
||||
gboolean is_variant;
|
||||
const Layout *main_layout;
|
||||
};
|
||||
|
||||
static GHashTable *layouts_by_short_id = NULL;
|
||||
static GHashTable *layouts_by_iso639 = NULL;
|
||||
static GHashTable *layouts_table = NULL;
|
||||
static Layout *current_parser_layout = NULL;
|
||||
static Layout *current_parser_variant = NULL;
|
||||
static gchar **current_parser_text = NULL;
|
||||
static gchar *current_parser_iso639Id = NULL;
|
||||
|
||||
static void
|
||||
free_layout (gpointer data)
|
||||
{
|
||||
Layout *layout = data;
|
||||
|
||||
g_free (layout->id);
|
||||
g_free (layout->xkb_name);
|
||||
g_free (layout->short_id);
|
||||
g_free (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
get_xkb_values (gchar **rules,
|
||||
XkbRF_VarDefsRec *var_defs)
|
||||
{
|
||||
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
*rules = NULL;
|
||||
|
||||
/* Get it from the X property or fallback on defaults */
|
||||
if (!XkbRF_GetNamesProp (display, rules, var_defs) || !*rules) {
|
||||
*rules = strdup (DFLT_XKB_RULES_FILE);
|
||||
var_defs->model = strdup (DFLT_XKB_MODEL);
|
||||
var_defs->layout = strdup (DFLT_XKB_LAYOUT);
|
||||
var_defs->variant = NULL;
|
||||
var_defs->options = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_xkb_var_defs (XkbRF_VarDefsRec *p)
|
||||
{
|
||||
if (p->model)
|
||||
free (p->model);
|
||||
if (p->layout)
|
||||
free (p->layout);
|
||||
if (p->variant)
|
||||
free (p->variant);
|
||||
if (p->options)
|
||||
free (p->options);
|
||||
free (p);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_rules_file_path (void)
|
||||
{
|
||||
XkbRF_VarDefsRec *xkb_var_defs;
|
||||
gchar *rules_file;
|
||||
gchar *rules_path;
|
||||
|
||||
xkb_var_defs = calloc (1, sizeof (XkbRF_VarDefsRec));
|
||||
get_xkb_values (&rules_file, xkb_var_defs);
|
||||
|
||||
if (rules_file[0] == '/')
|
||||
rules_path = g_strdup_printf ("%s.xml", rules_file);
|
||||
else
|
||||
rules_path = g_strdup_printf ("%s/rules/%s.xml",
|
||||
DFLT_XKB_CONFIG_ROOT,
|
||||
rules_file);
|
||||
|
||||
free_xkb_var_defs (xkb_var_defs);
|
||||
free (rules_file);
|
||||
|
||||
return rules_path;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **attribute_names,
|
||||
const gchar **attribute_values,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
if (current_parser_text)
|
||||
{
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"Expected character data but got element '%s'", element_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp (element_name, "name") == 0)
|
||||
{
|
||||
if (current_parser_variant)
|
||||
current_parser_text = ¤t_parser_variant->xkb_name;
|
||||
else if (current_parser_layout)
|
||||
current_parser_text = ¤t_parser_layout->xkb_name;
|
||||
}
|
||||
else if (strcmp (element_name, "description") == 0)
|
||||
{
|
||||
if (current_parser_variant)
|
||||
current_parser_text = ¤t_parser_variant->id;
|
||||
else if (current_parser_layout)
|
||||
current_parser_text = ¤t_parser_layout->id;
|
||||
}
|
||||
else if (strcmp (element_name, "shortDescription") == 0)
|
||||
{
|
||||
if (current_parser_variant)
|
||||
current_parser_text = ¤t_parser_variant->short_id;
|
||||
else if (current_parser_layout)
|
||||
current_parser_text = ¤t_parser_layout->short_id;
|
||||
}
|
||||
else if (strcmp (element_name, "iso639Id") == 0)
|
||||
{
|
||||
current_parser_text = ¤t_parser_iso639Id;
|
||||
}
|
||||
else if (strcmp (element_name, "layout") == 0)
|
||||
{
|
||||
if (current_parser_layout)
|
||||
{
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"'layout' elements can't be nested");
|
||||
return;
|
||||
}
|
||||
|
||||
current_parser_layout = g_new0 (Layout, 1);
|
||||
}
|
||||
else if (strcmp (element_name, "variant") == 0)
|
||||
{
|
||||
if (current_parser_variant)
|
||||
{
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"'variant' elements can't be nested");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!current_parser_layout)
|
||||
{
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"'variant' elements must be inside 'layout' elements");
|
||||
return;
|
||||
}
|
||||
|
||||
current_parser_variant = g_new0 (Layout, 1);
|
||||
current_parser_variant->is_variant = TRUE;
|
||||
current_parser_variant->main_layout = current_parser_layout;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_replace (GHashTable *table,
|
||||
gchar *key,
|
||||
Layout *new_layout)
|
||||
{
|
||||
Layout *layout;
|
||||
gboolean exists;
|
||||
gboolean replace = TRUE;
|
||||
|
||||
exists = g_hash_table_lookup_extended (table, key, NULL, (gpointer *)&layout);
|
||||
if (exists)
|
||||
replace = strlen (new_layout->id) < strlen (layout->id);
|
||||
if (replace)
|
||||
g_hash_table_replace (table, key, new_layout);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
if (strcmp (element_name, "layout") == 0)
|
||||
{
|
||||
if (!current_parser_layout->id || !current_parser_layout->xkb_name)
|
||||
{
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"'layout' elements must enclose 'description' and 'name' elements");
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_parser_layout->short_id)
|
||||
maybe_replace (layouts_by_short_id,
|
||||
current_parser_layout->short_id, current_parser_layout);
|
||||
|
||||
g_hash_table_replace (layouts_table,
|
||||
current_parser_layout->id,
|
||||
current_parser_layout);
|
||||
current_parser_layout = NULL;
|
||||
}
|
||||
else if (strcmp (element_name, "variant") == 0)
|
||||
{
|
||||
if (!current_parser_variant->id || !current_parser_variant->xkb_name)
|
||||
{
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"'variant' elements must enclose 'description' and 'name' elements");
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_parser_variant->short_id)
|
||||
maybe_replace (layouts_by_short_id,
|
||||
current_parser_variant->short_id, current_parser_variant);
|
||||
|
||||
g_hash_table_replace (layouts_table,
|
||||
current_parser_variant->id,
|
||||
current_parser_variant);
|
||||
current_parser_variant = NULL;
|
||||
}
|
||||
else if (strcmp (element_name, "iso639Id") == 0)
|
||||
{
|
||||
if (!current_parser_iso639Id)
|
||||
{
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"'iso639Id' elements must enclose text");
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_parser_layout)
|
||||
maybe_replace (layouts_by_iso639,
|
||||
current_parser_iso639Id, current_parser_layout);
|
||||
else if (current_parser_variant)
|
||||
maybe_replace (layouts_by_iso639,
|
||||
current_parser_iso639Id, current_parser_variant);
|
||||
else
|
||||
g_free (current_parser_iso639Id);
|
||||
|
||||
current_parser_iso639Id = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_text (GMarkupParseContext *context,
|
||||
const gchar *text,
|
||||
gsize text_len,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
if (current_parser_text)
|
||||
{
|
||||
*current_parser_text = g_strndup (text, text_len);
|
||||
current_parser_text = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_error (GMarkupParseContext *context,
|
||||
GError *error,
|
||||
gpointer data)
|
||||
{
|
||||
free_layout (current_parser_layout);
|
||||
free_layout (current_parser_variant);
|
||||
g_free (current_parser_iso639Id);
|
||||
}
|
||||
|
||||
static const GMarkupParser markup_parser = {
|
||||
parse_start_element,
|
||||
parse_end_element,
|
||||
parse_text,
|
||||
NULL,
|
||||
parse_error
|
||||
};
|
||||
|
||||
static void
|
||||
parse_rules_file (void)
|
||||
{
|
||||
gchar *buffer;
|
||||
gsize length;
|
||||
GMarkupParseContext *context;
|
||||
GError *error = NULL;
|
||||
gchar *full_path = get_rules_file_path ();
|
||||
|
||||
g_file_get_contents (full_path, &buffer, &length, &error);
|
||||
g_free (full_path);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Failed to read XKB rules file: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
layouts_by_short_id = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
layouts_by_iso639 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
/* This is the "master" table so it assumes memory "ownership". */
|
||||
layouts_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_layout);
|
||||
|
||||
context = g_markup_parse_context_new (&markup_parser, 0, NULL, NULL);
|
||||
g_markup_parse_context_parse (context, buffer, length, &error);
|
||||
g_markup_parse_context_free (context);
|
||||
g_free (buffer);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Failed to parse XKB rules file: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_hash_table_destroy (layouts_by_short_id);
|
||||
g_hash_table_destroy (layouts_by_iso639);
|
||||
g_hash_table_destroy (layouts_table);
|
||||
layouts_table = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_rules_are_parsed (void)
|
||||
{
|
||||
if (!layouts_table)
|
||||
parse_rules_file ();
|
||||
|
||||
return !!layouts_table;
|
||||
}
|
||||
|
||||
static void
|
||||
add_name_to_list (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
GSList **list = data;
|
||||
|
||||
*list = g_slist_prepend (*list, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* xkb_rules_db_get_all_layout_names:
|
||||
*
|
||||
* Returns a list of all layout names we know about.
|
||||
*
|
||||
* Return value: (transfer container): the list of layout names. The
|
||||
* caller takes ownership of the #GSList but not of the strings
|
||||
* themselves, those are internally allocated and must not be
|
||||
* modified.
|
||||
*/
|
||||
GSList *
|
||||
xkb_rules_db_get_all_layout_names (void)
|
||||
{
|
||||
GSList *layout_names = NULL;
|
||||
|
||||
if (!ensure_rules_are_parsed ())
|
||||
return NULL;
|
||||
|
||||
g_hash_table_foreach (layouts_table, add_name_to_list, &layout_names);
|
||||
|
||||
return layout_names;
|
||||
}
|
||||
|
||||
/**
|
||||
* xkb_rules_db_get_layout_info:
|
||||
* @name: layout's name about which to retrieve the info
|
||||
* @short_name: (out) (allow-none) (transfer none): location to store
|
||||
* the layout's short name, or %NULL
|
||||
* @xkb_layout: (out) (allow-none) (transfer none): location to store
|
||||
* the layout's XKB name, or %NULL
|
||||
* @xkb_variant: (out) (allow-none) (transfer none): location to store
|
||||
* the layout's XKB variant, or %NULL
|
||||
*
|
||||
* Retrieves information about a layout. Some layouts don't provide a
|
||||
* short name (2 or 3 letters) or don't specify a XKB variant, in
|
||||
* those cases @short_name or @xkb_variant are empty strings, i.e. "".
|
||||
*
|
||||
* If the given layout doesn't exist the return value is %FALSE and
|
||||
* all the (out) parameters are set to %NULL.
|
||||
*
|
||||
* Return value: %TRUE if the layout exists or %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
xkb_rules_db_get_layout_info (const gchar *name,
|
||||
const gchar **short_name,
|
||||
const gchar **xkb_layout,
|
||||
const gchar **xkb_variant)
|
||||
{
|
||||
const Layout *layout;
|
||||
|
||||
if (short_name)
|
||||
*short_name = NULL;
|
||||
if (xkb_layout)
|
||||
*xkb_layout = NULL;
|
||||
if (xkb_variant)
|
||||
*xkb_variant = NULL;
|
||||
|
||||
if (!ensure_rules_are_parsed ())
|
||||
return FALSE;
|
||||
|
||||
if (!g_hash_table_lookup_extended (layouts_table, name, NULL, (gpointer *)&layout))
|
||||
return FALSE;
|
||||
|
||||
if (!layout->is_variant)
|
||||
{
|
||||
if (short_name)
|
||||
*short_name = layout->short_id ? layout->short_id : "";
|
||||
if (xkb_layout)
|
||||
*xkb_layout = layout->xkb_name;
|
||||
if (xkb_variant)
|
||||
*xkb_variant = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (short_name)
|
||||
*short_name = layout->short_id ? layout->short_id :
|
||||
layout->main_layout->short_id ? layout->main_layout->short_id : "";
|
||||
if (xkb_layout)
|
||||
*xkb_layout = layout->main_layout->xkb_name;
|
||||
if (xkb_variant)
|
||||
*xkb_variant = layout->xkb_name;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* xkb_rules_db_get_layout_info_for_language:
|
||||
* @language: an ISO 639 code
|
||||
* @name: (out) (allow-none) (transfer none): location to store the
|
||||
* layout's name, or %NULL
|
||||
* @short_name: (out) (allow-none) (transfer none): location to store
|
||||
* the layout's short name, or %NULL
|
||||
* @xkb_layout: (out) (allow-none) (transfer none): location to store
|
||||
* the layout's XKB name, or %NULL
|
||||
* @xkb_variant: (out) (allow-none) (transfer none): location to store
|
||||
* the layout's XKB variant, or %NULL
|
||||
*
|
||||
* Retrieves the layout that better fits @language. It also fetches
|
||||
* information about that layout like xkb_rules_db_get_layout_info().
|
||||
*
|
||||
* If the a layout can't be found the return value is %FALSE and all
|
||||
* the (out) parameters are set to %NULL.
|
||||
*
|
||||
* Return value: %TRUE if a layout exists or %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
xkb_rules_db_get_layout_info_for_language (const gchar *language,
|
||||
const gchar **name,
|
||||
const gchar **short_name,
|
||||
const gchar **xkb_layout,
|
||||
const gchar **xkb_variant)
|
||||
{
|
||||
const Layout *layout;
|
||||
|
||||
if (name)
|
||||
*name = NULL;
|
||||
if (short_name)
|
||||
*short_name = NULL;
|
||||
if (xkb_layout)
|
||||
*xkb_layout = NULL;
|
||||
if (xkb_variant)
|
||||
*xkb_variant = NULL;
|
||||
|
||||
if (!ensure_rules_are_parsed ())
|
||||
return FALSE;
|
||||
|
||||
if (!g_hash_table_lookup_extended (layouts_by_iso639, language, NULL, (gpointer *)&layout))
|
||||
if (!g_hash_table_lookup_extended (layouts_by_short_id, language, NULL, (gpointer *)&layout))
|
||||
return FALSE;
|
||||
|
||||
if (name)
|
||||
*name = layout->id;
|
||||
|
||||
if (!layout->is_variant)
|
||||
{
|
||||
if (short_name)
|
||||
*short_name = layout->short_id ? layout->short_id : "";
|
||||
if (xkb_layout)
|
||||
*xkb_layout = layout->xkb_name;
|
||||
if (xkb_variant)
|
||||
*xkb_variant = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (short_name)
|
||||
*short_name = layout->short_id ? layout->short_id :
|
||||
layout->main_layout->short_id ? layout->main_layout->short_id : "";
|
||||
if (xkb_layout)
|
||||
*xkb_layout = layout->main_layout->xkb_name;
|
||||
if (xkb_variant)
|
||||
*xkb_variant = layout->xkb_name;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
38
panels/region/xkb-rules-db.h
Normal file
38
panels/region/xkb-rules-db.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* Written by: Rui Matos <rmatos@redhat.com>
|
||||
*
|
||||
* 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, 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __XKB_RULES_DB_H__
|
||||
#define __XKB_RULES_DB_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
GSList *xkb_rules_db_get_all_layout_names (void);
|
||||
gboolean xkb_rules_db_get_layout_info (const gchar *name,
|
||||
const gchar **short_name,
|
||||
const gchar **xkb_layout,
|
||||
const gchar **xkb_variant);
|
||||
gboolean xkb_rules_db_get_layout_info_for_language (const gchar *language,
|
||||
const gchar **name,
|
||||
const gchar **short_name,
|
||||
const gchar **xkb_layout,
|
||||
const gchar **xkb_variant);
|
||||
|
||||
#endif /* __XKB_RULES_DB_H__ */
|
||||
Reference in New Issue
Block a user