summaryrefslogtreecommitdiff
path: root/plugins/spell
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/spell')
-rwxr-xr-xplugins/spell/Makefile.am13
-rw-r--r--plugins/spell/org.mate.pluma.plugins.spell.gschema.xml.in14
-rwxr-xr-xplugins/spell/pluma-spell-plugin.c306
-rwxr-xr-xplugins/spell/pluma-spell-plugin.h2
-rw-r--r--plugins/spell/pluma-spell-setup-dialog.ui161
5 files changed, 480 insertions, 16 deletions
diff --git a/plugins/spell/Makefile.am b/plugins/spell/Makefile.am
index 7c08bf99..001b25ae 100755
--- a/plugins/spell/Makefile.am
+++ b/plugins/spell/Makefile.am
@@ -35,7 +35,7 @@ libspell_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libspell_la_LIBADD = $(PLUMA_LIBS) $(ENCHANT_LIBS)
uidir = $(PLUMA_PLUGINS_DATA_DIR)/spell
-ui_DATA = spell-checker.ui languages-dialog.ui
+ui_DATA = spell-checker.ui languages-dialog.ui pluma-spell-setup-dialog.ui
pluma-spell-marshal.h: pluma-spell-marshal.list $(GLIB_GENMARSHAL)
$(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=pluma_marshal > $@
@@ -50,12 +50,19 @@ plugin_in_files = spell.pluma-plugin.desktop.in
plugin_DATA = $(plugin_in_files:.pluma-plugin.desktop.in=.pluma-plugin)
+@INTLTOOL_XML_NOMERGE_RULE@
+spell_gschema_in = org.mate.pluma.plugins.spell.gschema.xml.in
+gsettings_SCHEMAS = $(spell_gschema_in:.xml.in=.xml)
+@GSETTINGS_RULES@
+
+
EXTRA_DIST = \
$(ui_DATA) \
$(plugin_in_files) \
- pluma-spell-marshal.list
+ pluma-spell-marshal.list \
+ $(spell_gschema_in)
-CLEANFILES = $(BUILT_SOURCES) $(plugin_DATA)
+CLEANFILES = $(BUILT_SOURCES) $(plugin_DATA) $(gsettings_SCHEMAS)
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
diff --git a/plugins/spell/org.mate.pluma.plugins.spell.gschema.xml.in b/plugins/spell/org.mate.pluma.plugins.spell.gschema.xml.in
new file mode 100644
index 00000000..d78d58fa
--- /dev/null
+++ b/plugins/spell/org.mate.pluma.plugins.spell.gschema.xml.in
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist gettext-domain="@GETTEXT_PACKAGE@">
+ <enum id="org.mate.pluma.plugins.spell.AutocheckType">
+ <value value="0" nick="never"/>
+ <value value="1" nick="document"/>
+ <value value="2" nick="always"/>
+ </enum>
+ <schema path="/org/mate/pluma/plugins/spell/" id="org.mate.pluma.plugins.spell">
+ <key name="autocheck-type" enum="org.mate.pluma.plugins.spell.AutocheckType">
+ <default>'document'</default>
+ <summary>Autocheck Type</summary>
+ </key>
+ </schema>
+</schemalist>
diff --git a/plugins/spell/pluma-spell-plugin.c b/plugins/spell/pluma-spell-plugin.c
index 6018621c..b3079bcc 100755
--- a/plugins/spell/pluma-spell-plugin.c
+++ b/plugins/spell/pluma-spell-plugin.c
@@ -33,8 +33,10 @@
#include <gmodule.h>
#include <pluma/pluma-debug.h>
+#include <pluma/pluma-help.h>
#include <pluma/pluma-prefs-manager.h>
#include <pluma/pluma-statusbar.h>
+#include <pluma/pluma-utils.h>
#include "pluma-spell-checker.h"
#include "pluma-spell-checker-dialog.h"
@@ -51,6 +53,10 @@
PLUMA_TYPE_SPELL_PLUGIN, \
PlumaSpellPluginPrivate))
+/* GSettings keys */
+#define SPELL_SCHEMA "org.mate.pluma.plugins.spell"
+#define AUTOCHECK_TYPE_KEY "autocheck-type"
+
PLUMA_PLUGIN_REGISTER_TYPE(PlumaSpellPlugin, pluma_spell_plugin)
typedef struct
@@ -60,6 +66,7 @@ typedef struct
guint message_cid;
gulong tab_added_id;
gulong tab_removed_id;
+ PlumaSpellPlugin *plugin;
} WindowData;
typedef struct
@@ -68,6 +75,11 @@ typedef struct
PlumaWindow *window;
} ActionData;
+struct _PlumaSpellPluginPrivate
+{
+ GSettings *settings;
+};
+
static void spell_cb (GtkAction *action, ActionData *action_data);
static void set_language_cb (GtkAction *action, ActionData *action_data);
static void auto_spell_cb (GtkAction *action, PlumaWindow *window);
@@ -104,6 +116,26 @@ static const GtkToggleActionEntry toggle_action_entries[] =
}
};
+typedef struct _SpellConfigureDialog SpellConfigureDialog;
+
+struct _SpellConfigureDialog
+{
+ GtkWidget *dialog;
+
+ GtkWidget *never;
+ GtkWidget *always;
+ GtkWidget *document;
+
+ PlumaSpellPlugin *plugin;
+};
+
+typedef enum
+{
+ AUTOCHECK_NEVER = 0,
+ AUTOCHECK_DOCUMENT,
+ AUTOCHECK_ALWAYS
+} PlumaSpellPluginAutocheckType;
+
typedef struct _CheckRange CheckRange;
struct _CheckRange
@@ -124,13 +156,21 @@ static void
pluma_spell_plugin_init (PlumaSpellPlugin *plugin)
{
pluma_debug_message (DEBUG_PLUGINS, "PlumaSpellPlugin initializing");
+
+ plugin->priv = PLUMA_SPELL_PLUGIN_GET_PRIVATE (plugin);
+
+ plugin->priv->settings = g_settings_new (SPELL_SCHEMA);
}
static void
pluma_spell_plugin_finalize (GObject *object)
{
+ PlumaSpellPlugin *plugin = PLUMA_SPELL_PLUGIN (object);
+
pluma_debug_message (DEBUG_PLUGINS, "PlumaSpellPlugin finalizing");
+ g_object_unref (G_OBJECT (plugin->priv->settings));
+
G_OBJECT_CLASS (pluma_spell_plugin_parent_class)->finalize (object);
}
@@ -174,6 +214,32 @@ set_language_from_metadata (PlumaSpellChecker *spell,
}
}
+static PlumaSpellPluginAutocheckType
+get_autocheck_type (PlumaSpellPlugin *plugin)
+{
+ PlumaSpellPluginAutocheckType autocheck_type;
+
+ autocheck_type = g_settings_get_enum (plugin->priv->settings,
+ AUTOCHECK_TYPE_KEY);
+
+ return autocheck_type;
+}
+
+static void
+set_autocheck_type (PlumaSpellPlugin *plugin,
+ PlumaSpellPluginAutocheckType autocheck_type)
+{
+ if (!g_settings_is_writable (plugin->priv->settings,
+ AUTOCHECK_TYPE_KEY))
+ {
+ return;
+ }
+
+ g_settings_set_enum (plugin->priv->settings,
+ AUTOCHECK_TYPE_KEY,
+ autocheck_type);
+}
+
static PlumaSpellChecker *
get_spell_checker_from_document (PlumaDocument *doc)
{
@@ -667,6 +733,156 @@ language_dialog_response (GtkDialog *dlg,
gtk_widget_destroy (GTK_WIDGET (dlg));
}
+static SpellConfigureDialog *
+get_configure_dialog (PlumaSpellPlugin *plugin)
+{
+ SpellConfigureDialog *dialog = NULL;
+ gchar *data_dir;
+ gchar *ui_file;
+ GtkWidget *content;
+ PlumaSpellPluginAutocheckType autocheck_type;
+ GtkWidget *error_widget;
+ gboolean ret;
+ gchar *root_objects[] = {
+ "spell_dialog_content",
+ NULL
+ };
+
+ pluma_debug (DEBUG_PLUGINS);
+
+ GtkWidget *dlg = gtk_dialog_new_with_buttons (_("Configure Spell Checker plugin..."),
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK,
+ GTK_STOCK_HELP,
+ GTK_RESPONSE_HELP,
+ NULL);
+
+ g_return_val_if_fail (dlg != NULL, NULL);
+
+ dialog = g_new0 (SpellConfigureDialog, 1);
+ dialog->dialog = dlg;
+
+
+ /* HIG defaults */
+ gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog->dialog)), 5);
+ gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog))),
+ 2); /* 2 * 5 + 2 = 12 */
+ gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dialog->dialog))),
+ 5);
+ gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dialog->dialog))), 6);
+
+ data_dir = pluma_plugin_get_data_dir (PLUMA_PLUGIN (plugin));
+ ui_file = g_build_filename (data_dir, "pluma-spell-setup-dialog.ui", NULL);
+ ret = pluma_utils_get_ui_objects (ui_file,
+ root_objects,
+ &error_widget,
+ "spell_dialog_content", &content,
+ "autocheck_never", &dialog->never,
+ "autocheck_document", &dialog->document,
+ "autocheck_always", &dialog->always,
+ NULL);
+
+ g_free (data_dir);
+ g_free (ui_file);
+
+ if (!ret)
+ {
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog))),
+ error_widget, TRUE, TRUE, 0);
+
+ gtk_container_set_border_width (GTK_CONTAINER (error_widget), 5);
+
+ gtk_widget_show (error_widget);
+
+ return dialog;
+ }
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE);
+
+ autocheck_type = get_autocheck_type (plugin);
+
+ if (autocheck_type == AUTOCHECK_ALWAYS)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->always), TRUE);
+ }
+ else if (autocheck_type == AUTOCHECK_DOCUMENT)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->document), TRUE);
+ }
+ else
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->never), TRUE);
+ }
+
+ gtk_window_set_default_size (GTK_WIDGET (content), 15, 120);
+
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog))),
+ content, FALSE, FALSE, 0);
+ g_object_unref (content);
+ gtk_container_set_border_width (GTK_CONTAINER (content), 5);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog->dialog),
+ GTK_RESPONSE_OK);
+
+ return dialog;
+}
+
+static void
+ok_button_pressed (SpellConfigureDialog *dialog)
+{
+ pluma_debug (DEBUG_PLUGINS);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->always)))
+ {
+ set_autocheck_type (dialog->plugin, AUTOCHECK_ALWAYS);
+ }
+ else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->document)))
+ {
+ set_autocheck_type (dialog->plugin, AUTOCHECK_DOCUMENT);
+ }
+ else
+ {
+ set_autocheck_type (dialog->plugin, AUTOCHECK_NEVER);
+ }
+}
+
+static void
+configure_dialog_response_cb (GtkWidget *widget,
+ gint response,
+ SpellConfigureDialog *dialog)
+{
+ switch (response)
+ {
+ case GTK_RESPONSE_HELP:
+ {
+ pluma_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_HELP");
+
+ pluma_help_display (GTK_WINDOW (widget),
+ NULL,
+ "pluma-spell-checker-plugin");
+ break;
+ }
+ case GTK_RESPONSE_OK:
+ {
+ pluma_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_OK");
+
+ ok_button_pressed (dialog);
+
+ gtk_widget_destroy (dialog->dialog);
+ break;
+ }
+ case GTK_RESPONSE_CANCEL:
+ {
+ pluma_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_CANCEL");
+ gtk_widget_destroy (dialog->dialog);
+ }
+ }
+}
+
static void
set_language_cb (GtkAction *action,
ActionData *action_data)
@@ -843,6 +1059,7 @@ auto_spell_cb (GtkAction *action,
PlumaDocument *doc;
gboolean active;
+ WindowData *data;
pluma_debug (DEBUG_PLUGINS);
@@ -854,9 +1071,16 @@ auto_spell_cb (GtkAction *action,
if (doc == NULL)
return;
- pluma_document_set_metadata (doc,
+ data = g_object_get_data (G_OBJECT (window),
+ WINDOW_DATA_KEY);
+
+ if (get_autocheck_type(data->plugin) == AUTOCHECK_DOCUMENT)
+ {
+
+ pluma_document_set_metadata (doc,
PLUMA_METADATA_ATTRIBUTE_SPELL_ENABLED,
active ? "1" : NULL, NULL);
+ }
set_auto_spell (window, doc, active);
}
@@ -931,11 +1155,34 @@ set_auto_spell_from_metadata (PlumaWindow *window,
GtkActionGroup *action_group)
{
gboolean active = FALSE;
- gchar *active_str;
+ gchar *active_str = NULL;
PlumaDocument *active_doc;
+ PlumaSpellPluginAutocheckType autocheck_type;
+ WindowData *data;
+
+ data = g_object_get_data (G_OBJECT (window),
+ WINDOW_DATA_KEY);
+
+ autocheck_type = get_autocheck_type(data->plugin);
- active_str = pluma_document_get_metadata (doc,
+ switch (autocheck_type)
+ {
+ case AUTOCHECK_ALWAYS:
+ {
+ active = TRUE;
+ break;
+ }
+ case AUTOCHECK_DOCUMENT:
+ {
+ active_str = pluma_document_get_metadata (doc,
PLUMA_METADATA_ATTRIBUTE_SPELL_ENABLED);
+ break;
+ }
+ case AUTOCHECK_NEVER:
+ default:
+ active = FALSE;
+ break;
+ }
if (active_str)
{
@@ -997,6 +1244,7 @@ on_document_saved (PlumaDocument *doc,
PlumaAutomaticSpellChecker *autospell;
PlumaSpellChecker *spell;
const gchar *key;
+ WindowData *data;
if (error != NULL)
{
@@ -1016,12 +1264,26 @@ on_document_saved (PlumaDocument *doc,
key = NULL;
}
- pluma_document_set_metadata (doc,
- PLUMA_METADATA_ATTRIBUTE_SPELL_ENABLED,
- autospell != NULL ? "1" : NULL,
- PLUMA_METADATA_ATTRIBUTE_SPELL_LANGUAGE,
- key,
- NULL);
+ data = g_object_get_data (G_OBJECT (window),
+ WINDOW_DATA_KEY);
+
+ if (get_autocheck_type(data->plugin) == AUTOCHECK_DOCUMENT)
+ {
+
+ pluma_document_set_metadata (doc,
+ PLUMA_METADATA_ATTRIBUTE_SPELL_ENABLED,
+ autospell != NULL ? "1" : NULL,
+ PLUMA_METADATA_ATTRIBUTE_SPELL_LANGUAGE,
+ key,
+ NULL);
+ }
+ else
+ {
+ pluma_document_set_metadata (doc,
+ PLUMA_METADATA_ATTRIBUTE_SPELL_LANGUAGE,
+ key,
+ NULL);
+ }
}
static void
@@ -1030,10 +1292,8 @@ tab_added_cb (PlumaWindow *window,
gpointer useless)
{
PlumaDocument *doc;
- PlumaView *view;
doc = pluma_tab_get_document (tab);
- view = pluma_tab_get_view (tab);
g_signal_connect (doc, "loaded",
G_CALLBACK (on_document_loaded),
@@ -1050,10 +1310,8 @@ tab_removed_cb (PlumaWindow *window,
gpointer useless)
{
PlumaDocument *doc;
- PlumaView *view;
doc = pluma_tab_get_document (tab);
- view = pluma_tab_get_view (tab);
g_signal_handlers_disconnect_by_func (doc, on_document_loaded, window);
g_signal_handlers_disconnect_by_func (doc, on_document_saved, window);
@@ -1071,6 +1329,7 @@ impl_activate (PlumaPlugin *plugin,
pluma_debug (DEBUG_PLUGINS);
data = g_slice_new (WindowData);
+ data->plugin = PLUMA_SPELL_PLUGIN (plugin);
action_data = g_slice_new (ActionData);
action_data->plugin = plugin;
action_data->window = window;
@@ -1191,6 +1450,23 @@ impl_update_ui (PlumaPlugin *plugin,
update_ui_real (window, data);
}
+static GtkWidget *
+impl_create_configure_dialog (PlumaPlugin *plugin)
+{
+ SpellConfigureDialog *dialog;
+
+ dialog = get_configure_dialog(PLUMA_SPELL_PLUGIN (plugin));
+
+ dialog->plugin = PLUMA_SPELL_PLUGIN (plugin);
+
+ g_signal_connect (dialog->dialog,
+ "response",
+ G_CALLBACK (configure_dialog_response_cb),
+ dialog);
+
+ return GTK_WIDGET (dialog->dialog);
+}
+
static void
pluma_spell_plugin_class_init (PlumaSpellPluginClass *klass)
{
@@ -1203,9 +1479,13 @@ pluma_spell_plugin_class_init (PlumaSpellPluginClass *klass)
plugin_class->deactivate = impl_deactivate;
plugin_class->update_ui = impl_update_ui;
+ plugin_class->create_configure_dialog = impl_create_configure_dialog;
+
if (spell_checker_id == 0)
spell_checker_id = g_quark_from_string ("PlumaSpellCheckerID");
if (check_range_id == 0)
check_range_id = g_quark_from_string ("CheckRangeID");
+
+ g_type_class_add_private (object_class, sizeof (PlumaSpellPluginPrivate));
}
diff --git a/plugins/spell/pluma-spell-plugin.h b/plugins/spell/pluma-spell-plugin.h
index e78a924e..d2c06252 100755
--- a/plugins/spell/pluma-spell-plugin.h
+++ b/plugins/spell/pluma-spell-plugin.h
@@ -50,6 +50,8 @@ typedef struct _PlumaSpellPlugin PlumaSpellPlugin;
struct _PlumaSpellPlugin
{
PlumaPlugin parent_instance;
+
+ PlumaSpellPluginPrivate *priv;
};
/*
diff --git a/plugins/spell/pluma-spell-setup-dialog.ui b/plugins/spell/pluma-spell-setup-dialog.ui
new file mode 100644
index 00000000..abc878d4
--- /dev/null
+++ b/plugins/spell/pluma-spell-setup-dialog.ui
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--*- mode: xml -*-->
+<interface>
+ <object class="GtkDialog" id="spell_dialog">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">_Configure Spell Checker plugin...</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">normal</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">8</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button3">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button4">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </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">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="spell_dialog_content">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Autocheck spelling on document load...</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="autocheck_never">
+ <property name="label" translatable="yes">_Never autocheck</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="autocheck_document">
+ <property name="label" translatable="yes">_Remember autocheck by document</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">autocheck_never</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="autocheck_always">
+ <property name="label" translatable="yes">_Always autocheck</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">autocheck_never</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">button1</action-widget>
+ <action-widget response="0">button3</action-widget>
+ <action-widget response="0">button4</action-widget>
+ </action-widgets>
+ </object>
+</interface>