diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-03-05 05:31:17 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-03-14 09:53:17 +0800 |
commit | c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e (patch) | |
tree | bd2d411c98752931ef573e268f04af930aa04e6a | |
parent | d7494c8f160b12e1199b06dcafdc8ff01b24b796 (diff) | |
download | gsoc2013-evolution-c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e.tar gsoc2013-evolution-c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e.tar.gz gsoc2013-evolution-c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e.tar.bz2 gsoc2013-evolution-c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e.tar.lz gsoc2013-evolution-c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e.tar.xz gsoc2013-evolution-c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e.tar.zst gsoc2013-evolution-c2685d9a6395fd6efb6b7cc2be28414c7fef2b5e.zip |
Forgot to commit the new source files...
-rw-r--r-- | e-util/e-ui-manager.c | 333 | ||||
-rw-r--r-- | e-util/e-ui-manager.h | 83 |
2 files changed, 416 insertions, 0 deletions
diff --git a/e-util/e-ui-manager.c b/e-util/e-ui-manager.c new file mode 100644 index 0000000000..c6a73042f0 --- /dev/null +++ b/e-util/e-ui-manager.c @@ -0,0 +1,333 @@ +/* + * e-ui-manager.c + * + * This program 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) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#include "e-ui-manager.h" + +#include <string.h> + +#define E_UI_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_UI_MANAGER, EUIManagerPrivate)) + +/* + * --- NOTE TO SELF --- + * + * While creating this class I was tempted to add an "id" property which + * EPluginUI could extract from a given EUIManager instead of having the + * public EPluginUI functions take a separate "id" argument. Seemed like + * a nice cleanup until I remembered that an EUIManager instance can have + * multiple IDs ("aliases"), as in the case of EShellWindow's UI manager. + * So the UI Manager ID and the instance still need to be kept separate. + * + * Mentioning it here in case I forget why I didn't go through with it. + */ + +struct _EUIManagerPrivate { + guint express_mode : 1; +}; + +enum { + PROP_0, + PROP_EXPRESS_MODE +}; + +static gpointer parent_class; + +static void +ui_manager_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_EXPRESS_MODE: + e_ui_manager_set_express_mode ( + E_UI_MANAGER (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +ui_manager_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_EXPRESS_MODE: + g_value_set_boolean ( + value, e_ui_manager_get_express_mode ( + E_UI_MANAGER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static gchar * +ui_manager_filter_ui (EUIManager *ui_manager, + const gchar *ui_definition) +{ + gchar **lines; + gchar *filtered; + gboolean express_mode; + gboolean in_conditional = FALSE; + gboolean include = TRUE; + gint ii; + + express_mode = e_ui_manager_get_express_mode (ui_manager); + + /* + * Very simple line based pre-processing based on comments: + * <!-- if [!]EXPRESS -->\n ... \n<!-- endif -->\n + */ + + lines = g_strsplit (ui_definition, "\n", -1); + + for (ii = 0; lines[ii] != NULL; ii++) { + gchar *cp; + + if ((cp = strstr (lines[ii], "<!-- if "))) { + gboolean not_express = lines[ii][8] == '!'; + include = express_mode ^ not_express; + lines[ii][0] = '\0'; + in_conditional = TRUE; + } else if ((cp = strstr (lines[ii], "<!-- endif"))) { + lines[ii][0] = '\0'; + include = TRUE; + in_conditional = FALSE; + } + if (!include) + lines[ii][0] = '\0'; + } + + filtered = g_strjoinv ("\n", lines); + + g_strfreev (lines); + + return filtered; +} + +static void +ui_manager_class_init (EUIManagerClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EUIManagerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = ui_manager_set_property; + object_class->get_property = ui_manager_get_property; + + class->filter_ui = ui_manager_filter_ui; + + g_object_class_install_property ( + object_class, + PROP_EXPRESS_MODE, + g_param_spec_boolean ( + "express-mode", + "Express Mode", + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); +} + +static void +ui_manager_init (EUIManager *ui_manager) +{ + ui_manager->priv = E_UI_MANAGER_GET_PRIVATE (ui_manager); +} + +GType +e_ui_manager_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EUIManagerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ui_manager_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EUIManager), + 0, /* n_preallocs */ + (GInstanceInitFunc) ui_manager_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_UI_MANAGER, "EUIManager", &type_info, 0); + } + + return type; +} + +/** + * e_ui_manager_new: + * + * Returns a new #EUIManager instance. + * + * Returns: a new #EUIManager instance + **/ +GtkUIManager * +e_ui_manager_new (void) +{ + return g_object_new (E_TYPE_UI_MANAGER, NULL); +} + +/** + * e_ui_manager_get_express_mode: + * @ui_manager: an #EUIManager + * + * Returns the "express mode" flag in @ui_manager. + * + * Returns: %TRUE if @ui_manager is set to express mode + **/ +gboolean +e_ui_manager_get_express_mode (EUIManager *ui_manager) +{ + g_return_val_if_fail (E_IS_UI_MANAGER (ui_manager), FALSE); + + return ui_manager->priv->express_mode; +} + +/** + * e_ui_manager_set_express_mode: + * @ui_manager: an #EUIManager + * @express_mode: express mode flag + * + * Sets the "express mode" flag in @ui_manager, which influences how + * UI definitions are loaded. + **/ +void +e_ui_manager_set_express_mode (EUIManager *ui_manager, + gboolean express_mode) +{ + g_return_if_fail (E_IS_UI_MANAGER (ui_manager)); + + ui_manager->priv->express_mode = express_mode; + + g_object_notify (G_OBJECT (ui_manager), "express-mode"); +} + +/** + * e_ui_manager_add_ui_from_file: + * @ui_manager: an #EUIManager + * @basename: basename of the UI definition file + * + * Loads a UI definition into @ui_manager from Evolution's UI directory. + * If the EUIManager:express-mode property is %TRUE, a simplified version + * of the UI may be presented. + * + * Failure here is fatal, since the application can't function without + * its core UI definitions. + * + * Returns: The merge ID for the merged UI. The merge ID can be used to + * unmerge the UI with gtk_ui_manager_remove_ui(). + **/ +guint +e_ui_manager_add_ui_from_file (EUIManager *ui_manager, + const gchar *basename) +{ + EUIManagerClass *class; + gchar *filename; + gchar *contents; + guint merge_id = 0; + GError *error = NULL; + + g_return_val_if_fail (E_IS_UI_MANAGER (ui_manager), 0); + g_return_val_if_fail (basename != NULL, 0); + + class = E_UI_MANAGER_GET_CLASS (ui_manager); + g_return_val_if_fail (class->filter_ui != NULL, 0); + + filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL); + + if (g_file_get_contents (filename, &contents, NULL, &error)) { + gchar *filtered; + + /* We could call e_ui_manager_add_ui_from_string() here, + * but if an error occurs we'd like to include the file + * name in the error message. */ + + filtered = class->filter_ui (ui_manager, contents); + + merge_id = gtk_ui_manager_add_ui_from_string ( + GTK_UI_MANAGER (ui_manager), filtered, -1, &error); + + g_free (filtered); + g_free (contents); + } + + g_free (filename); + + if (error != NULL) { + g_error ("%s: %s", basename, error->message); + g_assert_not_reached (); + } + + return merge_id; +} + +/** + * e_ui_manager_add_ui_from_string: + * @ui_manager: an #EUIManager + * @ui_definition: the UI XML in NULL terminated string form + * @error: return location for a #GError, or %NULL + * + * Loads the given UI definition into @ui_manager. If the + * EUIManager:express-mode property is %TRUE, a simplified version of + * the UI may be presented. + * + * Failure here is <i>not</i> fatal, since the function is primarily + * used to load UI definitions for plugins, which we can get by without. + * + * Returns: The merge ID for the merged UI. The merge ID can be used to + * unmerge the UI with gtk_ui_manager_remove_ui(). + **/ +guint +e_ui_manager_add_ui_from_string (EUIManager *ui_manager, + const gchar *ui_definition, + GError **error) +{ + EUIManagerClass *class; + gchar *filtered; + guint merge_id; + + g_return_val_if_fail (E_IS_UI_MANAGER (ui_manager), 0); + g_return_val_if_fail (ui_definition != NULL, 0); + + class = E_UI_MANAGER_GET_CLASS (ui_manager); + g_return_val_if_fail (class->filter_ui != NULL, 0); + + filtered = class->filter_ui (ui_manager, ui_definition); + + merge_id = gtk_ui_manager_add_ui_from_string ( + GTK_UI_MANAGER (ui_manager), filtered, -1, error); + + g_free (filtered); + + return merge_id; +} diff --git a/e-util/e-ui-manager.h b/e-util/e-ui-manager.h new file mode 100644 index 0000000000..f0dc02c2cc --- /dev/null +++ b/e-util/e-ui-manager.h @@ -0,0 +1,83 @@ +/* + * e-ui-manager.h + * + * This program 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) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +/** + * SECTION: e-ui-manager + * @short_description: construct menus and toolbars from a UI definition + * @include: e-util/e-ui-manager.h + * + * This is a #GtkUIManager with support for Evolution's "express" mode, + * which influences the parsing of UI definitions. + **/ + +#ifndef E_UI_MANAGER_H +#define E_UI_MANAGER_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_UI_MANAGER \ + (e_ui_manager_get_type ()) +#define E_UI_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_UI_MANAGER, EUIManager)) +#define E_UI_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_UI_MANAGER, EUIManagerClass)) +#define E_IS_UI_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_UI_MANAGER)) +#define E_IS_UI_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_UI_MANAGER)) +#define E_UI_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_UI_MANAGER, EUIManagerClass)) + +G_BEGIN_DECLS + +typedef struct _EUIManager EUIManager; +typedef struct _EUIManagerClass EUIManagerClass; +typedef struct _EUIManagerPrivate EUIManagerPrivate; + +struct _EUIManager { + GtkUIManager parent; + EUIManagerPrivate *priv; +}; + +struct _EUIManagerClass { + GtkUIManagerClass parent_class; + + gchar * (*filter_ui) (EUIManager *ui_manager, + const gchar *ui_definition); +}; + +GType e_ui_manager_get_type (void); +GtkUIManager * e_ui_manager_new (void); +gboolean e_ui_manager_get_express_mode (EUIManager *ui_manager); +void e_ui_manager_set_express_mode (EUIManager *ui_manager, + gboolean express_mode); +guint e_ui_manager_add_ui_from_file (EUIManager *ui_manager, + const gchar *basename); +guint e_ui_manager_add_ui_from_string (EUIManager *ui_manager, + const gchar *ui_definition, + GError **error); + +G_END_DECLS + +#endif /* E_UI_MANAGER_H */ |