summaryrefslogtreecommitdiff
path: root/capplet/matekbd-indicator-plugins-capplet.c
diff options
context:
space:
mode:
Diffstat (limited to 'capplet/matekbd-indicator-plugins-capplet.c')
-rw-r--r--capplet/matekbd-indicator-plugins-capplet.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/capplet/matekbd-indicator-plugins-capplet.c b/capplet/matekbd-indicator-plugins-capplet.c
new file mode 100644
index 0000000..cea33f7
--- /dev/null
+++ b/capplet/matekbd-indicator-plugins-capplet.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "matekbd-indicator-plugins-capplet.h"
+
+#include <string.h>
+#include <sys/stat.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+
+static MatekbdKeyboardConfig initialSysKbdConfig;
+static GMainLoop *loop;
+
+extern void
+CappletFillActivePluginList (MatekbdIndicatorPluginsCapplet * gipc)
+{
+ GtkWidget *activePlugins =
+ CappletGetUiWidget (gipc, "activePlugins");
+ GtkListStore *activePluginsModel =
+ GTK_LIST_STORE (gtk_tree_view_get_model
+ (GTK_TREE_VIEW (activePlugins)));
+ GSList *pluginPathNode = gipc->applet_cfg.enabled_plugins;
+ GHashTable *allPluginRecs = gipc->plugin_manager.all_plugin_recs;
+
+ gtk_list_store_clear (activePluginsModel);
+ if (allPluginRecs == NULL)
+ return;
+
+ while (pluginPathNode != NULL) {
+ GtkTreeIter iter;
+ const char *fullPath = (const char *) pluginPathNode->data;
+ const MatekbdIndicatorPlugin *plugin =
+ matekbd_indicator_plugin_manager_get_plugin (&gipc->
+ plugin_manager,
+ fullPath);
+ if (plugin != NULL) {
+ gtk_list_store_append (activePluginsModel, &iter);
+ gtk_list_store_set (activePluginsModel, &iter,
+ NAME_COLUMN, plugin->name,
+ FULLPATH_COLUMN, fullPath, -1);
+ }
+
+ pluginPathNode = g_slist_next (pluginPathNode);
+ }
+}
+
+static char *
+CappletGetSelectedActivePluginPath (MatekbdIndicatorPluginsCapplet * gipc)
+{
+ GtkTreeView *pluginsList =
+ GTK_TREE_VIEW (CappletGetUiWidget (gipc, "activePlugins"));
+ return CappletGetSelectedPluginPath (pluginsList, gipc);
+}
+
+char *
+CappletGetSelectedPluginPath (GtkTreeView * pluginsList,
+ MatekbdIndicatorPluginsCapplet * gipc)
+{
+ GtkTreeModel *model =
+ gtk_tree_view_get_model (GTK_TREE_VIEW (pluginsList));
+ GtkTreeSelection *selection =
+ gtk_tree_view_get_selection (GTK_TREE_VIEW (pluginsList));
+ GtkTreeIter selectedIter;
+
+ if (gtk_tree_selection_get_selected
+ (selection, NULL, &selectedIter)) {
+ char *fullPath = NULL;
+
+ gtk_tree_model_get (model, &selectedIter,
+ FULLPATH_COLUMN, &fullPath, -1);
+ return fullPath;
+ }
+ return NULL;
+}
+
+static void
+CappletActivePluginsSelectionChanged (GtkTreeSelection *
+ selection,
+ MatekbdIndicatorPluginsCapplet * gipc)
+{
+ GtkWidget *activePlugins =
+ CappletGetUiWidget (gipc, "activePlugins");
+ GtkTreeModel *model =
+ gtk_tree_view_get_model (GTK_TREE_VIEW (activePlugins));
+ GtkTreeIter selectedIter;
+ gboolean isAnythingSelected = FALSE;
+ gboolean isFirstSelected = FALSE;
+ gboolean isLastSelected = FALSE;
+ gboolean hasConfigurationUi = FALSE;
+ GtkWidget *btnRemove = CappletGetUiWidget (gipc, "btnRemove");
+ GtkWidget *btnUp = CappletGetUiWidget (gipc, "btnUp");
+ GtkWidget *btnDown = CappletGetUiWidget (gipc, "btnDown");
+ GtkWidget *btnProperties = CappletGetUiWidget (gipc, "btnProperties");
+ GtkWidget *lblDescription = CappletGetUiWidget (gipc, "lblDescription");
+
+ gtk_label_set_text (GTK_LABEL (lblDescription),
+ g_strconcat ("<small><i>",
+ _("No description."),
+ "</i></small>", NULL));
+ gtk_label_set_use_markup (GTK_LABEL (lblDescription), TRUE);
+
+ if (gtk_tree_selection_get_selected
+ (selection, NULL, &selectedIter)) {
+ int counter = gtk_tree_model_iter_n_children (model, NULL);
+ GtkTreePath *treePath =
+ gtk_tree_model_get_path (model, &selectedIter);
+ gint *indices = gtk_tree_path_get_indices (treePath);
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ const MatekbdIndicatorPlugin *plugin =
+ matekbd_indicator_plugin_manager_get_plugin (&gipc->
+ plugin_manager,
+ fullPath);
+
+ isAnythingSelected = TRUE;
+
+ isFirstSelected = indices[0] == 0;
+ isLastSelected = indices[0] == counter - 1;
+
+ if (plugin != NULL) {
+ hasConfigurationUi =
+ (plugin->configure_properties_callback !=
+ NULL);
+ gtk_label_set_text (GTK_LABEL (lblDescription),
+ g_strconcat ("<small><i>",
+ plugin->
+ description,
+ "</i></small>",
+ NULL));
+ gtk_label_set_use_markup (GTK_LABEL
+ (lblDescription), TRUE);
+ }
+ g_free (fullPath);
+
+ gtk_tree_path_free (treePath);
+ }
+ gtk_widget_set_sensitive (btnRemove, isAnythingSelected);
+ gtk_widget_set_sensitive (btnUp, isAnythingSelected
+ && !isFirstSelected);
+ gtk_widget_set_sensitive (btnDown, isAnythingSelected
+ && !isLastSelected);
+ gtk_widget_set_sensitive (btnProperties, isAnythingSelected
+ && hasConfigurationUi);
+}
+
+static void
+CappletPromotePlugin (GtkWidget * btnUp,
+ MatekbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL) {
+ matekbd_indicator_plugin_manager_promote_plugin (&gipc->
+ plugin_manager,
+ gipc->
+ applet_cfg.
+ enabled_plugins,
+ fullPath);
+ g_free (fullPath);
+ CappletFillActivePluginList (gipc);
+ matekbd_indicator_config_save_to_mateconf (&gipc->applet_cfg);
+ }
+}
+
+static void
+CappletDemotePlugin (GtkWidget * btnUp, MatekbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL) {
+ matekbd_indicator_plugin_manager_demote_plugin (&gipc->
+ plugin_manager,
+ gipc->
+ applet_cfg.
+ enabled_plugins,
+ fullPath);
+ g_free (fullPath);
+ CappletFillActivePluginList (gipc);
+ matekbd_indicator_config_save_to_mateconf (&gipc->applet_cfg);
+ }
+}
+
+static void
+CappletDisablePlugin (GtkWidget * btnRemove,
+ MatekbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL) {
+ matekbd_indicator_plugin_manager_disable_plugin (&gipc->
+ plugin_manager,
+ &gipc->
+ applet_cfg.
+ enabled_plugins,
+ fullPath);
+ g_free (fullPath);
+ CappletFillActivePluginList (gipc);
+ matekbd_indicator_config_save_to_mateconf (&gipc->applet_cfg);
+ }
+}
+
+static void
+CappletConfigurePlugin (GtkWidget * btnRemove,
+ MatekbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL) {
+ matekbd_indicator_plugin_manager_configure_plugin (&gipc->
+ plugin_manager,
+ &gipc->
+ plugin_container,
+ fullPath,
+ GTK_WINDOW
+ (gipc->
+ capplet));
+ g_free (fullPath);
+ }
+}
+
+static void
+CappletResponse (GtkDialog * dialog, gint response)
+{
+ if (response == GTK_RESPONSE_HELP) {
+ GError *error = NULL;
+ GdkAppLaunchContext *ctx = gdk_app_launch_context_new ();
+
+ g_app_info_launch_default_for_uri
+ ("ghelp:matekbd?gkb-indicator-applet-plugins",
+ G_APP_LAUNCH_CONTEXT (ctx), &error);
+
+ if (error) {
+ GtkWidget *d = NULL;
+
+ d = gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s", _
+ ("Unable to open help file"));
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (d), "%s", error->message);
+ g_signal_connect (d, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+ gtk_window_present (GTK_WINDOW (d));
+
+ g_error_free (error);
+ }
+
+ return;
+ }
+
+ g_main_loop_quit (loop);
+}
+
+static void
+CappletSetup (MatekbdIndicatorPluginsCapplet * gipc)
+{
+ GtkBuilder *builder;
+ GError *error = NULL;
+ GtkWidget *button;
+ GtkWidget *capplet;
+ GtkWidget *activePlugins;
+ GtkTreeModel *activePluginsModel;
+ GtkCellRenderer *renderer =
+ GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
+ GtkTreeViewColumn *column =
+ gtk_tree_view_column_new_with_attributes (NULL, renderer,
+ "text", 0,
+ NULL);
+ GtkTreeSelection *selection;
+ builder = gtk_builder_new ();
+
+ gtk_window_set_default_icon_name ("input-keyboard");
+
+ /* default domain! */
+ if (!gtk_builder_add_from_file (builder,
+ UIDIR "/matekbd-indicator-plugins.ui",
+ &error)) {
+ g_warning ("Could not load builder file: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+
+ gipc->capplet = capplet =
+ GTK_WIDGET (gtk_builder_get_object (builder, "matekbd_indicator_plugins"));
+
+ gtk_builder_connect_signals (builder, NULL);
+
+ g_object_set_data (G_OBJECT (capplet), "uiData", builder);
+ g_signal_connect_swapped (GTK_OBJECT (capplet),
+ "destroy", G_CALLBACK (g_object_unref),
+ builder);
+ g_signal_connect_swapped (G_OBJECT (capplet), "unrealize",
+ G_CALLBACK (g_main_loop_quit), loop);
+
+ g_signal_connect (GTK_OBJECT (capplet),
+ "response", G_CALLBACK (CappletResponse), NULL);
+
+ button = GTK_WIDGET (gtk_builder_get_object (builder, "btnUp"));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK
+ (CappletPromotePlugin), gipc);
+ button = GTK_WIDGET (gtk_builder_get_object (builder, "btnDown"));
+ g_signal_connect (button,
+ "clicked",
+ G_CALLBACK
+ (CappletDemotePlugin), gipc);
+ button = GTK_WIDGET (gtk_builder_get_object (builder, "btnAdd"));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK
+ (CappletEnablePlugin), gipc);
+ button = GTK_WIDGET (gtk_builder_get_object (builder, "btnRemove"));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK
+ (CappletDisablePlugin), gipc);
+ button = GTK_WIDGET (gtk_builder_get_object (builder, "btnProperties"));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK
+ (CappletConfigurePlugin), gipc);
+
+ activePlugins = CappletGetUiWidget (gipc, "activePlugins");
+ activePluginsModel =
+ GTK_TREE_MODEL (gtk_list_store_new
+ (2, G_TYPE_STRING, G_TYPE_STRING));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (activePlugins),
+ activePluginsModel);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (activePlugins),
+ column);
+ selection =
+ gtk_tree_view_get_selection (GTK_TREE_VIEW (activePlugins));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK
+ (CappletActivePluginsSelectionChanged), gipc);
+ CappletFillActivePluginList (gipc);
+ CappletActivePluginsSelectionChanged (selection, gipc);
+ gtk_widget_show_all (capplet);
+}
+
+int
+main (int argc, char **argv)
+{
+ MatekbdIndicatorPluginsCapplet gipc;
+
+ GError *mateconf_error = NULL;
+ MateConfClient *confClient;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+ memset (&gipc, 0, sizeof (gipc));
+ gtk_init_with_args (&argc, &argv, "matekbd", NULL, NULL, NULL);
+ if (!mateconf_init (argc, argv, &mateconf_error)) {
+ g_warning (_("Failed to init MateConf: %s\n"),
+ mateconf_error->message);
+ g_error_free (mateconf_error);
+ return 1;
+ }
+ mateconf_error = NULL;
+ /*MatekbdIndicatorInstallGlibLogAppender( ); */
+ gipc.engine = xkl_engine_get_instance (GDK_DISPLAY ());
+ gipc.config_registry =
+ xkl_config_registry_get_instance (gipc.engine);
+
+ confClient = mateconf_client_get_default ();
+ matekbd_indicator_plugin_container_init (&gipc.plugin_container,
+ confClient);
+ g_object_unref (confClient);
+
+ matekbd_keyboard_config_init (&gipc.kbd_cfg, confClient, gipc.engine);
+ matekbd_keyboard_config_init (&initialSysKbdConfig, confClient,
+ gipc.engine);
+
+ matekbd_indicator_config_init (&gipc.applet_cfg, confClient,
+ gipc.engine);
+
+ matekbd_indicator_plugin_manager_init (&gipc.plugin_manager);
+
+ matekbd_keyboard_config_load_from_x_initial (&initialSysKbdConfig,
+ NULL);
+ matekbd_keyboard_config_load_from_mateconf (&gipc.kbd_cfg,
+ &initialSysKbdConfig);
+
+ matekbd_indicator_config_load_from_mateconf (&gipc.applet_cfg);
+
+ loop = g_main_loop_new (NULL, TRUE);
+
+ CappletSetup (&gipc);
+
+ g_main_loop_run (loop);
+
+ matekbd_indicator_plugin_manager_term (&gipc.plugin_manager);
+
+ matekbd_indicator_config_term (&gipc.applet_cfg);
+
+ matekbd_keyboard_config_term (&gipc.kbd_cfg);
+ matekbd_keyboard_config_term (&initialSysKbdConfig);
+
+ matekbd_indicator_plugin_container_term (&gipc.plugin_container);
+ g_object_unref (G_OBJECT (gipc.config_registry));
+ g_object_unref (G_OBJECT (gipc.engine));
+ return 0;
+}
+
+/* functions just for plugins - otherwise ldd is not happy */
+void
+matekbd_indicator_plugin_container_reinit_ui (MatekbdIndicatorPluginContainer *
+ pc)
+{
+}
+
+gchar **matekbd_indicator_plugin_load_localized_group_names
+ (MatekbdIndicatorPluginContainer * pc) {
+ MatekbdDesktopConfig *config =
+ &((MatekbdIndicatorPluginsCapplet *) pc)->cfg;
+ XklConfigRegistry *config_registry =
+ ((MatekbdIndicatorPluginsCapplet *) pc)->config_registry;
+
+ int i;
+ const gchar **native_names =
+ xkl_engine_get_groups_names (config->engine);
+ guint total_groups = xkl_engine_get_num_groups (config->engine);
+ guint total_layouts;
+ gchar **rv = g_new0 (char *, total_groups + 1);
+ gchar **current_descr = rv;
+
+ if ((xkl_engine_get_features (config->engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED)
+ && config->layout_names_as_group_names) {
+ XklConfigRec *xkl_config = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server
+ (xkl_config, config->engine)) {
+ gchar **sgn = NULL;
+ gchar **fgn = NULL;
+ matekbd_desktop_config_load_group_descriptions
+ (config, config_registry,
+ (const gchar **) xkl_config->layouts,
+ (const gchar **) xkl_config->variants, &sgn,
+ &fgn);
+ g_strfreev (sgn);
+ rv = fgn;
+ }
+ g_object_unref (G_OBJECT (xkl_config));
+ /* Worst case - multiple layous - but SOME of them are multigrouped :(((
+ * We cannot do much - just add empty descriptions.
+ * The UI is going to be messy.
+ * Canadian layouts are famous for this sh.t. */
+ total_layouts = g_strv_length (rv);
+ if (total_layouts != total_groups) {
+ xkl_debug (0,
+ "The mismatch between "
+ "the number of groups: %d and number of layouts: %d\n",
+ total_groups, total_layouts);
+ current_descr = rv + total_layouts;
+ for (i = total_groups - total_layouts; --i >= 0;)
+ *current_descr++ = g_strdup ("");
+ }
+ }
+ total_layouts = g_strv_length (rv);
+ if (!total_layouts)
+ for (i = total_groups; --i >= 0;)
+ *current_descr++ = g_strdup (*native_names++);
+
+ return rv;
+}