GnuCash 2.4.99
gnc-plugin.c
Go to the documentation of this file.
00001 /*
00002  * gnc-plugin.c --
00003  *
00004  * Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
00005  * Copyright (C) 2003,2005 David Hampton <hampton@employees.org>
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, contact:
00019  *
00020  * Free Software Foundation           Voice:  +1-617-542-5942
00021  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
00022  * Boston, MA  02110-1301,  USA       gnu@gnu.org
00023  */
00024 
00035 #include "config.h"
00036 
00037 #include <gtk/gtk.h>
00038 #include <glib/gi18n.h>
00039 
00040 #include "gnc-plugin.h"
00041 #include "gnc-engine.h"
00042 #include "gnc-gconf-utils.h"
00043 #include "gnc-gnome-utils.h"
00044 #include "gnc-gobject-utils.h"
00045 
00047 static QofLogModule log_module = GNC_MOD_GUI;
00049 static gpointer parent_class = NULL;
00050 
00051 static void gnc_plugin_class_init (GncPluginClass *klass);
00052 static void gnc_plugin_init       (GncPlugin *plugin_page,
00053                                    GncPluginClass *klass);
00054 static void gnc_plugin_finalize   (GObject *object);
00055 
00056 
00059 typedef struct GncPluginPrivate
00060 {
00061     gpointer dummy;
00062 } GncPluginPrivate;
00063 
00064 #define GNC_PLUGIN_GET_PRIVATE(o)  \
00065    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN, GncPluginPrivate))
00066 
00067 
00070 GType
00071 gnc_plugin_get_type (void)
00072 {
00073     static GType gnc_plugin_type = 0;
00074 
00075     if (gnc_plugin_type == 0)
00076     {
00077         static const GTypeInfo our_info =
00078         {
00079             sizeof (GncPluginClass),
00080             NULL,               /* base_init */
00081             NULL,               /* base_finalize */
00082             (GClassInitFunc) gnc_plugin_class_init,
00083             NULL,               /* class_finalize */
00084             NULL,               /* class_data */
00085             sizeof (GncPlugin),
00086             0,          /* n_preallocs */
00087             (GInstanceInitFunc) gnc_plugin_init,
00088         };
00089 
00090         gnc_plugin_type = g_type_register_static (G_TYPE_OBJECT,
00091                           GNC_PLUGIN_NAME,
00092                           &our_info, 0);
00093     }
00094 
00095     return gnc_plugin_type;
00096 }
00097 
00098 
00106 static void
00107 gnc_plugin_class_init (GncPluginClass *klass)
00108 {
00109     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
00110 
00111     parent_class = g_type_class_peek_parent (klass);
00112     gobject_class->finalize = gnc_plugin_finalize;
00113 
00114     g_type_class_add_private(klass, sizeof(GncPluginPrivate));
00115 }
00116 
00117 
00126 static void
00127 gnc_plugin_init (GncPlugin *plugin_page, GncPluginClass *klass)
00128 {
00129     gnc_gobject_tracking_remember(G_OBJECT(plugin_page), \
00130                                   G_OBJECT_CLASS(klass));
00131 }
00132 
00133 
00141 static void
00142 gnc_plugin_finalize (GObject *object)
00143 {
00144     GncPlugin *plugin;
00145     GncPluginPrivate *priv;
00146 
00147     g_return_if_fail (GNC_IS_PLUGIN (object));
00148 
00149     plugin = GNC_PLUGIN (object);
00150     priv = GNC_PLUGIN_GET_PRIVATE (plugin);
00151 
00152     gnc_gobject_tracking_forget(object);
00153     G_OBJECT_CLASS (parent_class)->finalize (object);
00154 }
00155 
00156 
00163 void
00164 gnc_plugin_add_to_window (GncPlugin *plugin,
00165                           GncMainWindow *window,
00166                           GQuark type)
00167 {
00168     GncPluginClass *class;
00169     GtkActionGroup *action_group;
00170 
00171     g_return_if_fail (GNC_IS_PLUGIN (plugin));
00172     class = GNC_PLUGIN_GET_CLASS (plugin);
00173     ENTER (": plugin %s(%p), window %p", gnc_plugin_get_name(plugin),
00174            plugin, window);
00175 
00176     /*
00177      * Update window with additional UI items
00178      */
00179     if (class->actions_name)
00180     {
00181         DEBUG ("%s: %d actions to merge with gui from %s",
00182                class->actions_name, (class->n_actions + class->n_toggle_actions), class->ui_filename);
00183         gnc_main_window_merge_actions (window, class->actions_name,
00184                                        class->actions, class->n_actions,
00185                                        class->toggle_actions, class->n_toggle_actions,
00186                                        class->ui_filename, plugin);
00187 
00188 
00189         if (class->important_actions)
00190         {
00191             action_group =
00192                 gnc_main_window_get_action_group(window, class->actions_name);
00193             gnc_plugin_set_important_actions(action_group,
00194                                              class->important_actions);
00195         }
00196     }
00197 
00198     /*
00199      * Setup gconf notifications if requested
00200      */
00201     if (class->gconf_section && class->gconf_notifications)
00202     {
00203         DEBUG ("Requesting notification for section %s", class->gconf_section);
00204         gnc_gconf_add_notification(G_OBJECT(window), class->gconf_section,
00205                                    class->gconf_notifications, GNC_PLUGIN_NAME);
00206     }
00207 
00208     /*
00209      * Do plugin specific actions.
00210      */
00211     if (GNC_PLUGIN_GET_CLASS (plugin)->add_to_window)
00212     {
00213         DEBUG ("Calling child class function %p", GNC_PLUGIN_GET_CLASS (plugin)->add_to_window);
00214         GNC_PLUGIN_GET_CLASS (plugin)->add_to_window (plugin, window, type);
00215     }
00216     LEAVE ("");
00217 }
00218 
00219 
00220 /*  Remove the specified plugin from the specified window.  This
00221  *  function will call the plugin to perform any plugin specific
00222  *  actions, remove any gconf notifications that were set up for the
00223  *  page, and remove the page's user interface from the window.
00224  *
00225  *  See gnc-plugin.h for documentation on the function arguments. */
00226 void
00227 gnc_plugin_remove_from_window (GncPlugin *plugin,
00228                                GncMainWindow *window,
00229                                GQuark type)
00230 {
00231     GncPluginClass *class;
00232 
00233     g_return_if_fail (GNC_IS_PLUGIN (plugin));
00234     class = GNC_PLUGIN_GET_CLASS (plugin);
00235     ENTER (": plugin %s(%p), window %p", gnc_plugin_get_name(plugin),
00236            plugin, window);
00237 
00238     /*
00239      * Do plugin specific actions.
00240      */
00241     if (GNC_PLUGIN_GET_CLASS (plugin)->remove_from_window)
00242     {
00243         DEBUG ("Calling child class function %p",
00244                GNC_PLUGIN_GET_CLASS (plugin)->remove_from_window);
00245         GNC_PLUGIN_GET_CLASS (plugin)->remove_from_window (plugin, window, type);
00246     }
00247 
00248     /*
00249      * Remove any gconf notifications
00250      */
00251     if (class->gconf_section && class->gconf_notifications)
00252     {
00253         DEBUG ("Remove notification for section %s", class->gconf_section);
00254         gnc_gconf_remove_notification (G_OBJECT(window), class->gconf_section,
00255                                        GNC_PLUGIN_NAME);
00256     }
00257 
00258     /*
00259      * Update window to remove UI items
00260      */
00261     if (class->actions_name)
00262     {
00263         DEBUG ("%s: %d actions to unmerge",
00264                class->actions_name, (class->n_actions + class->n_toggle_actions));
00265         gnc_main_window_unmerge_actions (window, class->actions_name);
00266     }
00267     LEAVE ("");
00268 }
00269 
00270 
00273 const gchar *
00274 gnc_plugin_get_name (GncPlugin *plugin)
00275 {
00276     g_return_val_if_fail (GNC_IS_PLUGIN (plugin), NULL);
00277     return (GNC_PLUGIN_GET_CLASS(plugin)->plugin_name);
00278 }
00279 
00280 
00281 /************************************************************
00282  *                    Utility Functions                     *
00283  ************************************************************/
00284 
00285 
00290 void
00291 gnc_plugin_init_short_names (GtkActionGroup *action_group,
00292                              action_toolbar_labels *toolbar_labels)
00293 {
00294     GtkAction *action;
00295     GValue value = { 0, };
00296     gint i;
00297 
00298     g_value_init (&value, G_TYPE_STRING);
00299 
00300     for (i = 0; toolbar_labels[i].action_name; i++)
00301     {
00302         /* Add a couple of short labels for the toolbar */
00303         action = gtk_action_group_get_action (action_group,
00304                                               toolbar_labels[i].action_name);
00305         g_value_set_static_string (&value, gettext(toolbar_labels[i].label));
00306         g_object_set_property (G_OBJECT(action), "short_label", &value);
00307     }
00308 }
00309 
00310 
00316 void
00317 gnc_plugin_set_important_actions (GtkActionGroup *action_group,
00318                                   const gchar **name)
00319 {
00320     GtkAction *action;
00321     gint i;
00322 
00323     for (i = 0; name[i]; i++)
00324     {
00325         action = gtk_action_group_get_action (action_group, name[i]);
00326         g_object_set (G_OBJECT(action), "is_important", TRUE, NULL);
00327     }
00328 
00329     /* If this trips, you've got too many "important" actions.  That
00330      * can't *all* be that important, can they? */
00331     g_assert(i <= 3);
00332 }
00333 
00334 
00335 /*  Update a property of existing UI actions.  This function can
00336  *  modify actions making them visible, invisible, sensitive, or
00337  *  insensitive.
00338  *
00339  *  See gnc-plugin.h for documentation on the function arguments. */
00340 void
00341 gnc_plugin_update_actions (GtkActionGroup *action_group,
00342                            const gchar **action_names,
00343                            const gchar *property_name,
00344                            gboolean value)
00345 {
00346     GtkAction    *action;
00347     GValue        gvalue = { 0 };
00348     gint          i;
00349 
00350     g_value_init (&gvalue, G_TYPE_BOOLEAN);
00351     g_value_set_boolean (&gvalue, value);
00352 
00353     for (i = 0; action_names[i]; i++)
00354     {
00355         action = gtk_action_group_get_action (action_group, action_names[i]);
00356         if (action)
00357         {
00358             g_object_set_property (G_OBJECT(action), property_name, &gvalue);
00359         }
00360         else
00361         {
00362             g_warning("No such action with name '%s' in action group %s (size %d)",
00363                       action_names[i], gtk_action_group_get_name(action_group),
00364                       g_list_length(gtk_action_group_list_actions(action_group)));
00365         }
00366     }
00367 }
00368 
00369 
00373 gint
00374 gnc_plugin_add_actions (GtkUIManager *ui_merge,
00375                         GtkActionGroup *action_group,
00376                         const gchar *filename)
00377 {
00378     GError *error = NULL;
00379     gchar *pathname;
00380     gint merge_id;
00381 
00382     g_return_val_if_fail (ui_merge, 0);
00383     g_return_val_if_fail (action_group, 0);
00384     g_return_val_if_fail (filename, 0);
00385 
00386     ENTER("ui_merge %p, action_group %p, filename %s",
00387           ui_merge, action_group, filename);
00388     gtk_ui_manager_insert_action_group (ui_merge, action_group, 0);
00389 
00390     pathname = gnc_gnome_locate_ui_file (filename);
00391     if (pathname == NULL)
00392     {
00393         LEAVE("fail");
00394         return 0;
00395     }
00396 
00397     merge_id = gtk_ui_manager_add_ui_from_file (ui_merge, pathname, &error);
00398     DEBUG("merge_id is %d", merge_id);
00399 
00400     g_assert(merge_id || error);
00401     if (merge_id)
00402     {
00403         gtk_ui_manager_ensure_update (ui_merge);
00404     }
00405     else
00406     {
00407         g_critical("Failed to load ui file.\n  Filename %s\n  Error %s",
00408                    filename, error->message);
00409         g_error_free(error);
00410     }
00411 
00412     g_free(pathname);
00413     LEAVE(" ");
00414     return merge_id;
00415 }
00416 
00417 #if 0
00418 static void
00419 gnc_plugin_base_init (gpointer klass)
00420 {
00421     static gboolean initialized = FALSE;
00422 
00423     if (!initialized)
00424     {
00425         initialized = TRUE;
00426 
00427         signals[MERGE_ACTIONS] = g_signal_new ("merge-actions",
00428                                                G_OBJECT_CLASS_TYPE (klass),
00429                                                G_SIGNAL_RUN_FIRST,
00430                                                G_STRUCT_OFFSET (GncPluginClass, merge_actions),
00431                                                NULL, NULL,
00432                                                g_cclosure_marshal_VOID__POINTER,
00433                                                G_TYPE_NONE,
00434                                                1,
00435                                                GTK_TYPE_MENU_MERGE);
00436         signals[UNMERGE_ACTIONS] = g_signal_new ("unmerge-actions",
00437                                    G_OBJECT_CLASS_TYPE (klass),
00438                                    G_SIGNAL_RUN_FIRST,
00439                                    G_STRUCT_OFFSET (GncPluginClass, unmerge_actions),
00440                                    NULL, NULL,
00441                                    g_cclosure_marshal_VOID__POINTER,
00442                                    G_TYPE_NONE,
00443                                    1,
00444                                    GTK_TYPE_MENU_MERGE);
00445     }
00446 }
00447 #endif
00448 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines