You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnucash/gnucash/gnome-utils/gnc-plugin-page.c

1095 lines
32 KiB

/*
* gnc-plugin_page.c --
*
* Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
* Copyright (C) 2003,2005 David Hampton <hampton@employees.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 of
* the License, 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, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/** @addtogroup ContentPlugins
@{ */
/** @addtogroup ContentPluginBase Common object and functions
@{ */
/** @file gnc-plugin-page.c
@brief Functions for adding plugins to a GnuCash window.
@author Copyright (C) 2003 Jan Arne Petersen
@author Copyright (C) 2003,2005 David Hampton <hampton@employees.org>
*/
#include <config.h>
#include <gtk/gtk.h>
#include "gnc-engine.h"
#include "gnc-plugin.h"
#include "gnc-plugin-page.h"
#include "gnc-gobject-utils.h"
/** The debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
/** A pointer to the parent class of a plugin page. */
static gpointer parent_class = NULL;
static void gnc_plugin_page_class_init (GncPluginPageClass *klass);
static void gnc_plugin_page_init (GncPluginPage *plugin_page,
void *data);
static void gnc_plugin_page_finalize (GObject *object);
static void gnc_plugin_page_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gnc_plugin_page_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gnc_plugin_page_default_focus (GncPluginPage *plugin_page,
gboolean on_current_page);
enum
{
INSERTED,
REMOVED,
SELECTED,
UNSELECTED,
LAST_SIGNAL
};
enum
{
PROP_0,
PROP_PAGE_NAME,
PROP_PAGE_COLOR,
PROP_BOOK,
PROP_STATUSBAR_TEXT,
PROP_USE_NEW_WINDOW,
PROP_UI_DESCRIPTION,
};
static guint signals[LAST_SIGNAL] = { 0 };
/** The instance private data for a content plugin. */
typedef struct _GncPluginPagePrivate
{
/** The group of all actions provided by this plugin. */
char *ui_description;
GtkBuilder *builder; //FIXMEb added
GSimpleActionGroup *simple_action_group; //FIXMEb added
const gchar *simple_action_group_name; //FIXMEb added
const gchar *menu_qualifier; //FIXMEb added
GList *books;
gboolean use_new_window;
gchar *page_name;
gchar *page_long_name;
gchar *page_color;
gchar *uri;
gchar *statusbar_text;
gulong page_changed_id;
guint focus_source_id;
} GncPluginPagePrivate;
GNC_DEFINE_TYPE_WITH_CODE(GncPluginPage, gnc_plugin_page, G_TYPE_OBJECT,
G_ADD_PRIVATE(GncPluginPage))
#define GNC_PLUGIN_PAGE_GET_PRIVATE(o) \
((GncPluginPagePrivate*)gnc_plugin_page_get_instance_private((GncPluginPage*)o))
/* Create the display widget that corresponds to this plugin. This
* function will be called by the main/embedded window manipulation
* code to create a widget that they can display. The returned
* widget should encompass all information that goes with this page,
* including scroll bars, a summary bar, etc. */
GtkWidget *
gnc_plugin_page_create_widget (GncPluginPage *plugin_page)
{
GncPluginPageClass *klass;
GtkWidget *widget;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page), NULL);
klass = GNC_PLUGIN_PAGE_GET_CLASS(plugin_page);
g_return_val_if_fail (klass != NULL, NULL);
g_return_val_if_fail (klass->create_widget != NULL, NULL);
widget = klass->create_widget (plugin_page);
/*
* If there is a destroy function, add a ref so that the
* widgets will exists when the destroy function is called.
* Otherwise it will be destroyed when it is removed from the
* main notebook for the window.
*/
if (klass->destroy_widget)
g_object_ref (widget);
return widget;
}
/* Destroy the display widget that corresponds to this plugin. This
* function will be called by the main/embedded window manipulation
* code when a page is closed. */
void
gnc_plugin_page_destroy_widget (GncPluginPage *plugin_page)
{
GncPluginPageClass *klass;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page));
klass = GNC_PLUGIN_PAGE_GET_CLASS(plugin_page);
g_return_if_fail (klass != NULL);
g_return_if_fail (klass->destroy_widget != NULL);
klass->destroy_widget (plugin_page);
}
/* Show/hide the summarybar associated with this page. */
void
gnc_plugin_page_show_summarybar (GncPluginPage *page,
gboolean visible)
{
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
if (!page->summarybar)
return;
if (visible)
gtk_widget_show (page->summarybar);
else
gtk_widget_hide (page->summarybar);
}
/* Call the plugin specific function that will save the state of a
* content page to a disk. That function must save enough
* information about the page that it can be recreated next time the
* user starts gnucash. */
void
gnc_plugin_page_save_page (GncPluginPage *page,
GKeyFile *key_file,
const gchar *group_name)
{
GncPluginPageClass *klass;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
g_return_if_fail (key_file != NULL);
g_return_if_fail (group_name != NULL);
ENTER(" ");
klass = GNC_PLUGIN_PAGE_GET_CLASS(page);
g_return_if_fail (klass != NULL);
g_return_if_fail (klass->save_page != NULL);
klass->save_page (page, key_file, group_name);
LEAVE(" ");
}
/* This function looks up a specific plugin type by name, and then
* calls a plugin specific function to create a new page and restore
* its content to a previous state. */
GncPluginPage *
gnc_plugin_page_recreate_page(GtkWidget *window,
const gchar *page_type,
GKeyFile *key_file,
const gchar *page_group)
{
GncPluginPageClass *klass;
GncPluginPage *page = NULL;
GType type;
ENTER("type %s, keyfile %p, group %s", page_type, key_file, page_group);
type = g_type_from_name (page_type);
if (type == 0)
{
LEAVE("Cannot find type named %s", page_type);
return NULL;
}
klass = g_type_class_ref (type);
if (klass == NULL)
{
const gchar *type_name = g_type_name (type);
LEAVE("Cannot create class %s(%s)", page_type, type_name ? type_name : "invalid type");
return NULL;
}
if (!klass->recreate_page)
{
LEAVE("Class %shas no recreate function.", page_type);
g_type_class_unref (klass);
return NULL;
}
page = (klass->recreate_page)(window, key_file, page_group);
g_type_class_unref (klass);
LEAVE(" ");
return page;
}
void
gnc_plugin_page_merge_actions (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
GError *error = NULL;
gchar *resource;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (!priv->builder)
priv->builder = gtk_builder_new ();
resource = g_strconcat ("/org/gnucash/", priv->ui_description, NULL);
gtk_builder_set_translation_domain (priv->builder, PROJECT_NAME);
gtk_builder_add_from_resource (priv->builder, resource, &error);
if (error)
{
g_critical ("Failed to load ui resource %s, Error %s", resource, error->message);
g_error_free (error);
}
g_free (resource);
}
GAction *
gnc_plugin_page_get_action (GncPluginPage *page, const gchar *name)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
g_return_val_if_fail (name != NULL, NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (!priv->simple_action_group)
return NULL;
return g_action_map_lookup_action (G_ACTION_MAP(priv->simple_action_group), name);
}
/* Retrieve the textual name of a plugin. */
const gchar *
gnc_plugin_page_get_plugin_name (GncPluginPage *plugin_page)
{
GncPluginPageClass *klass;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page), NULL);
klass = GNC_PLUGIN_PAGE_GET_CLASS(plugin_page);
g_return_val_if_fail (klass != NULL, NULL);
return (klass->plugin_name);
}
/* Signals */
void
gnc_plugin_page_inserted (GncPluginPage *plugin_page)
{
g_return_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page));
g_signal_emit (G_OBJECT(plugin_page), signals[INSERTED], 0);
}
void
gnc_plugin_page_removed (GncPluginPage *plugin_page)
{
g_return_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page));
g_signal_emit (G_OBJECT(plugin_page), signals[REMOVED], 0);
}
void
gnc_plugin_page_selected (GncPluginPage *plugin_page)
{
g_return_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page));
g_signal_emit (G_OBJECT(plugin_page), signals[SELECTED], 0);
}
void
gnc_plugin_page_unselected (GncPluginPage *plugin_page)
{
g_return_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page));
g_signal_emit (G_OBJECT(plugin_page), signals[UNSELECTED], 0);
}
/** Initialize the class for a new generic plugin page. This will set
* up any function pointers that override functions in the parent
* class, set up all properties and signals, and also configure the
* private data storage for this widget.
*
* @param klass The new class structure created by the object system.
*/
static void
gnc_plugin_page_class_init (GncPluginPageClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = gnc_plugin_page_finalize;
gobject_class->set_property = gnc_plugin_page_set_property;
gobject_class->get_property = gnc_plugin_page_get_property;
klass->tab_icon = NULL;
klass->plugin_name = NULL;
klass->focus_page = gnc_plugin_page_default_focus;
g_object_class_install_property
(gobject_class,
PROP_PAGE_NAME,
g_param_spec_string ("page-name",
"Page Name",
"The name of this page. This value is "
"used to generate the notebook tab and "
"menu items, and also the window title "
"when this page is visible.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_PAGE_COLOR,
g_param_spec_string ("page-color",
"Page Color",
"The color of this page. This value is "
"used to generate the notebook tab color "
"when this page is visible.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_STATUSBAR_TEXT,
g_param_spec_string ("statusbar-text",
"Statusbar Text",
"The text to be displayed in the statusbar "
"at the bottom of the window when this page "
"is visible.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_USE_NEW_WINDOW,
g_param_spec_boolean ("use-new-window",
"Use New Window",
"When TRUE a new top level window will be "
"created to hold this page.",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_UI_DESCRIPTION,
g_param_spec_string ("ui-description",
"UI Description File",
"The filename containing the XML data that "
"describes this pages menus and toolbars.",
NULL,
G_PARAM_READWRITE));
signals[INSERTED] = g_signal_new ("inserted",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GncPluginPageClass, inserted),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
signals[REMOVED] = g_signal_new ("removed",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GncPluginPageClass, removed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
signals[SELECTED] = g_signal_new ("selected",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GncPluginPageClass, selected),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
signals[UNSELECTED] = g_signal_new ("unselected",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GncPluginPageClass, unselected),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
/** Initialize a new instance of a gnucash content plugin. This
* function initializes the object private storage space, and adds
* the object to the tracking system.
*
* @param page The new object instance created by the object system.
*
* @param klass A pointer to the class data structure for this
* object. */
static void
gnc_plugin_page_init (GncPluginPage *page, void *data)
{
GncPluginPagePrivate *priv;
GncPluginPageClass *klass = (GncPluginPageClass*)data;
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
priv->page_name = NULL;
priv->page_color = NULL;
priv->page_changed_id = 0;
priv->focus_source_id = 0;
priv->menu_qualifier = NULL;
page->window = NULL;
page->summarybar = NULL;
gnc_gobject_tracking_remember (G_OBJECT(page),
G_OBJECT_CLASS(klass));
}
/** Finalize the gnucash plugin object. This function is called from
* the G_Object level to complete the destruction of the object. It
* should release any memory not previously released by the destroy
* function (i.e. the private data structure), then chain up to the
* parent's destroy function.
*
* @param object The object being destroyed. */
static void
gnc_plugin_page_finalize (GObject *object)
{
GncPluginPagePrivate *priv;
GncPluginPage *page;
page = GNC_PLUGIN_PAGE(object);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (priv->ui_description)
g_free (priv->ui_description);
if (priv->page_name)
g_free (priv->page_name);
if (priv->page_long_name)
g_free (priv->page_long_name);
if (priv->page_color)
g_free (priv->page_color);
if (priv->statusbar_text)
g_free (priv->statusbar_text);
if (priv->books)
{
g_list_free (priv->books);
priv->books = NULL;
}
page->window = NULL; // Don't need to free it.
gnc_gobject_tracking_forget (object);
G_OBJECT_CLASS(parent_class)->finalize (object);
}
/************************************************************/
/* g_object other functions */
/************************************************************/
/** Retrieve a property specific to this GncPluginPage object. This is
* nothing more than a dispatch function for routines that can be
* called directly. It has the nice feature of allowing a single
* function call to retrieve multiple properties.
*
* @param object The object whose property should be retrieved.
*
* @param prop_id The numeric identifier of the property. This
* should be a PROP_XXX constant as specified at the beginning of
* this file.
*
* @param value A pointer to where this property value should be
* stored.
*
* @param pspec A pointer to the meta data that described the property
* being retrieved. */
/* Note that g_value_set_object() refs the object, as does
* g_object_get(). But g_object_get() only unrefs once when it disgorges
* the object, leaving an unbalanced ref, which leaks. So instead of
* using g_value_set_object(), use g_value_take_object() which doesn't
* ref the object when used in get_property().
*/
static void
gnc_plugin_page_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GncPluginPage *page;
GncPluginPagePrivate *priv;
g_return_if_fail(GNC_IS_PLUGIN_PAGE(object));
page = GNC_PLUGIN_PAGE(object);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
switch (prop_id)
{
case PROP_PAGE_NAME:
g_value_set_string (value, priv->page_name);
break;
case PROP_PAGE_COLOR:
g_value_set_string (value, priv->page_color);
break;
case PROP_STATUSBAR_TEXT:
g_value_set_string (value, priv->statusbar_text);
break;
case PROP_USE_NEW_WINDOW:
g_value_set_boolean (value, priv->use_new_window);
break;
case PROP_UI_DESCRIPTION:
g_value_set_string (value, priv->ui_description);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/** Set a property specific to this GncPluginPage object. This is
* nothing more than a dispatch function for routines that can be
* called directly. It has the nice feature of allowing a new view
* to be created with a varargs list specifying the properties,
* instead of having to explicitly call each property function.
*
* @param object The object whose property should be set.
*
* @param prop_id The numeric identifier of the property. This
* should be a PROP_XXX constant as specified at the beginning of
* this file.
*
* @param value A pointer to then new value for this property value.
*
* @param pspec A pointer to the meta data that described the property
* being retrieved. */
static void
gnc_plugin_page_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GncPluginPage *page;
g_return_if_fail(GNC_IS_PLUGIN_PAGE(object));
page = GNC_PLUGIN_PAGE(object);
switch (prop_id)
{
case PROP_PAGE_NAME:
gnc_plugin_page_set_page_name (page, g_value_get_string (value));
break;
case PROP_PAGE_COLOR:
gnc_plugin_page_set_page_color (page, g_value_get_string (value));
break;
case PROP_STATUSBAR_TEXT:
gnc_plugin_page_set_statusbar_text (page, g_value_get_string (value));
break;
case PROP_USE_NEW_WINDOW:
gnc_plugin_page_set_use_new_window (page, g_value_get_boolean (value));
break;
case PROP_UI_DESCRIPTION:
gnc_plugin_page_set_ui_description (page, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/************************************************************/
/* */
/************************************************************/
/* Add a book reference to the specified page. */
void
gnc_plugin_page_add_book (GncPluginPage *page, QofBook *book)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
g_return_if_fail (book != NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
priv->books = g_list_append (priv->books, book);
}
/* Query a page to see if it has a reference to a given book. */
gboolean
gnc_plugin_page_has_book (GncPluginPage *page, QofBook *book)
{
GncPluginPagePrivate *priv;
GList *item;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), FALSE);
g_return_val_if_fail (book != NULL, FALSE);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
for (item = priv->books; item; item = g_list_next (item))
{
if (item->data == book)
{
return TRUE;
}
}
return FALSE;
}
/* Query a page to see if it has a reference to any book. */
gboolean
gnc_plugin_page_has_books (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), FALSE);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return (priv->books != NULL);
}
/* Retrieve a pointer to the GncMainWindow (GtkWindow) containing
* this page. */
GtkWidget *
gnc_plugin_page_get_window (GncPluginPage *page)
{
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
return page->window;
}
/* Retrieve the name of this page. This is the string used in the
* window title, and in the notebook tab and page selection menus. */
const gchar *
gnc_plugin_page_get_page_name (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->page_name;
}
/* Set the name of this page. This is the string used in the window
* title, and in the notebook tab and page selection menus. */
void
gnc_plugin_page_set_page_name (GncPluginPage *page, const gchar *name)
{
GncPluginPagePrivate *priv;
GncPluginPageClass *klass;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (priv->page_name)
g_free (priv->page_name);
priv->page_name = g_strdup (name);
/* Perform page specific actions */
klass = GNC_PLUGIN_PAGE_GET_CLASS (page);
if (klass->page_name_changed)
{
klass->page_name_changed(page, name);
}
}
/* Retrieve the long name of this page. This is the string used in
* the tooltip that is attached to the page name in the notebook
* tab. */
const gchar *
gnc_plugin_page_get_page_long_name (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->page_long_name;
}
/* Set the long name of this page. This is the string used in the
* tooltip that is attached to the page name in the notebook tab. */
void
gnc_plugin_page_set_page_long_name (GncPluginPage *page, const gchar *name)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (priv->page_long_name)
g_free (priv->page_long_name);
priv->page_long_name = g_strdup (name);
}
/* Get the color of this page. This is the string used in the notebook tab. */
const gchar *
gnc_plugin_page_get_page_color (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->page_color;
}
/* Set the color of this page. This is the string used in the notebook tab. */
void
gnc_plugin_page_set_page_color (GncPluginPage *page, const gchar *color)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (priv->page_color)
g_free (priv->page_color);
if (color)
priv->page_color = g_strdup (color);
}
static void
gnc_plugin_page_focus_idle_destroy (GncPluginPage *plugin_page)
{
GncPluginPagePrivate *priv = GNC_PLUGIN_PAGE_GET_PRIVATE(plugin_page);
priv->focus_source_id = 0;
}
static void
gnc_plugin_page_default_focus (GncPluginPage *plugin_page,
gboolean on_current_page)
{
GncPluginPagePrivate *priv;
if (!on_current_page)
return;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(plugin_page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(plugin_page);
if (G_LIKELY(GNC_PLUGIN_PAGE_GET_CLASS(plugin_page)->focus_page_function))
{
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus
if (priv->focus_source_id > 0)
g_source_remove (priv->focus_source_id);
priv->focus_source_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc)(GNC_PLUGIN_PAGE_GET_CLASS(plugin_page)->focus_page_function),
GNC_PLUGIN_PAGE(plugin_page),
(GDestroyNotify)gnc_plugin_page_focus_idle_destroy);
}
}
/* this is the callback for the plugin "page_changed" signal */
static void
gnc_plugin_page_main_window_changed (GtkWindow *window,
GObject *object,
gpointer user_data)
{
GncPluginPage *current_plugin_page = GNC_PLUGIN_PAGE(object);
GncPluginPage *plugin_page = GNC_PLUGIN_PAGE(user_data);
GncPluginPagePrivate *priv;
gboolean on_current_page = FALSE;
// Continue if current_plugin_page is valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE(current_plugin_page))
return;
// Continue only if the plugin_page is valid
if (!plugin_page || !GNC_IS_PLUGIN_PAGE(plugin_page))
return;
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(plugin_page);
if (current_plugin_page == plugin_page)
on_current_page = TRUE;
(GNC_PLUGIN_PAGE_GET_CLASS(plugin_page)->focus_page)(plugin_page, on_current_page);
}
/* this is the callback for the plugin "inserted" signal which will setup
* the callback for the "page_changed" signal and save a pointer to the
* page focus function. */
void
gnc_plugin_page_inserted_cb (GncPluginPage *page, gpointer user_data)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
priv->page_changed_id = g_signal_connect (G_OBJECT(page->window), "page_changed",
G_CALLBACK(gnc_plugin_page_main_window_changed),
page);
// on initial load try and set the page focus
(GNC_PLUGIN_PAGE_GET_CLASS(page)->focus_page)(page, TRUE);
}
/* disconnect the page_changed callback */
void
gnc_plugin_page_disconnect_page_changed (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (priv->page_changed_id > 0)
{
g_signal_handler_disconnect (G_OBJECT(page->window), priv->page_changed_id);
priv->page_changed_id = 0;
}
}
/* Retrieve the statusbar text associated with this page. */
const gchar *
gnc_plugin_page_get_statusbar_text (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->statusbar_text;
}
/* Set the statusbar text associated with this page. */
void
gnc_plugin_page_set_statusbar_text (GncPluginPage *page, const gchar *message)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (priv->statusbar_text)
g_free (priv->statusbar_text);
priv->statusbar_text = g_strdup (message);
}
/* Retrieve the "use new window" setting associated with this page. */
gboolean
gnc_plugin_page_get_use_new_window (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), FALSE);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->use_new_window;
}
/* Set the "use new window" setting associated with this page. If
* this setting is TRUE, the page will be installed into a new
* window. Otherwise the page will be installed into an existing
* window. */
void
gnc_plugin_page_set_use_new_window (GncPluginPage *page, gboolean use_new)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
priv->use_new_window = use_new;
}
/* Retrieve the name of the XML UI file associated with this page. */
const gchar *
gnc_plugin_page_get_ui_description (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), FALSE);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->ui_description;
}
/* Set an alternate UI for the specified page. This alternate ui
* may only use actions specified in the source for the page. */
void
gnc_plugin_page_set_ui_description (GncPluginPage *page,
const char *ui_filename)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
if (priv->ui_description)
g_free (priv->ui_description);
priv->ui_description = g_strdup (ui_filename);
}
/* Retrieve the GtkBuilder object associated with this page. */
GtkBuilder *
gnc_plugin_page_get_builder (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->builder;
}
/* Retrieve the menu qualifier associated with this page. */
const gchar *
gnc_plugin_page_get_menu_qualifier (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->menu_qualifier;
}
void
gnc_plugin_page_set_menu_qualifier (GncPluginPage *page,
const char *menu_qualifier)
{
GncPluginPagePrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_PAGE(page));
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
priv->menu_qualifier = menu_qualifier;
}
GSimpleActionGroup *
gnc_plugin_page_get_action_group (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->simple_action_group;
}
GSimpleActionGroup *
gnc_plugin_page_create_action_group (GncPluginPage *page, const gchar *group_name)
{
GncPluginPagePrivate *priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
priv->simple_action_group = g_simple_action_group_new ();
priv->simple_action_group_name = group_name;
return priv->simple_action_group;
}
const gchar *
gnc_plugin_page_get_simple_action_group_name (GncPluginPage *page)
{
GncPluginPagePrivate *priv;
g_return_val_if_fail (GNC_IS_PLUGIN_PAGE(page), NULL);
priv = GNC_PLUGIN_PAGE_GET_PRIVATE(page);
return priv->simple_action_group_name;
}
gboolean
gnc_plugin_page_finish_pending (GncPluginPage *page)
{
if (!page)
return TRUE;
if (!GNC_IS_PLUGIN_PAGE(page))
return TRUE;
if (!GNC_PLUGIN_PAGE_GET_CLASS(page)->finish_pending)
return TRUE;
return (GNC_PLUGIN_PAGE_GET_CLASS(page)->finish_pending)(page);
}
/** @} */
/** @} */