mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Add code to save window state into a Glib Key-Value file. This code
is distributed between the gnc-main-window code and all of the plugin pages. It subsumes the existing state file code, and will call that code upon file open if it cannot find a key-value state file. This code is also where the creation of the initial account tree page occurs when no state file is found. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@11905 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
24
ChangeLog
24
ChangeLog
@@ -1,5 +1,29 @@
|
||||
2005-11-11 David Hampton <hampton@employees.org>
|
||||
|
||||
* src/app-utils/file-utils.[ch]:
|
||||
* src/app-utils/guile-util.[ch]:
|
||||
* src/business/business-gnome/gnc-plugin-business.c:
|
||||
* src/business/business-gnome/gnc-plugin-page-invoice.h:
|
||||
* src/gnome-utils/gnc-main-window.c:
|
||||
* src/gnome-utils/gnc-plugin-page.[ch]:
|
||||
* src/gnome-utils/ui/gnc-main-window-ui.xml:
|
||||
* src/gnome/gnc-plugin-account-tree.[ch]:
|
||||
* src/gnome/gnc-plugin-budget.c:
|
||||
* src/gnome/gnc-plugin-page-account-tree.[ch]:
|
||||
* src/gnome/gnc-plugin-page-budget.h:
|
||||
* src/gnome/gnc-plugin-page-register.c:
|
||||
* src/gnome/gnc-plugin-register.c:
|
||||
* src/gnome/gw-gnc-spec.scm:
|
||||
* src/report/report-gnome/gnc-plugin-page-report.[ch]:
|
||||
* src/report/report-gnome/window-report.c:
|
||||
* src/scm/main-window.scm: Add code to save window state into a
|
||||
Glib Key-Value file. This code is distributed between the
|
||||
gnc-main-window code and all of the plugin pages. It subsumes the
|
||||
existing state file code, and will call that code upon file open
|
||||
if it cannot find a key-value state file. This code is also where
|
||||
the creation of the initial account tree page occurs when no state
|
||||
file is found.
|
||||
|
||||
* lib/glib26/gkeyfile.c:
|
||||
* lib/glib26/gutils26.c: Fix a couple of gcc4 warnings.
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "file-utils.h"
|
||||
#include "messages.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-gkeyfile-utils.h"
|
||||
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
static QofLogModule log_module = GNC_MOD_GUILE;
|
||||
@@ -166,4 +167,73 @@ gnc_getline (gchar **line, FILE *file)
|
||||
}
|
||||
|
||||
|
||||
/* Find the state file that corresponds to this URL and guid. The
|
||||
* URL is used to compute the base name of the file (which will be in
|
||||
* ~/.gnucash/books) and the guid is used to differentiate when the
|
||||
* user has multiple data files with the same name. */
|
||||
GKeyFile *
|
||||
gnc_find_state_file (const gchar *url,
|
||||
const gchar *guid,
|
||||
gchar **filename_p)
|
||||
{
|
||||
gchar *basename, *original = NULL, *filename, *tmp, *file_guid;
|
||||
GKeyFile *key_file = NULL;
|
||||
GError *error = NULL;
|
||||
gint i;
|
||||
|
||||
ENTER("url %s, guid %s", url, guid);
|
||||
tmp = index(url, ':');
|
||||
if (tmp)
|
||||
url = tmp + 1;
|
||||
|
||||
basename = g_path_get_basename(url);
|
||||
DEBUG("Basename %s", basename);
|
||||
original = g_build_filename(g_get_home_dir(), ".gnucash",
|
||||
"books", basename, NULL);
|
||||
g_free(basename);
|
||||
DEBUG("Original %s", original);
|
||||
|
||||
i = 1;
|
||||
while (1) {
|
||||
if (i == 1)
|
||||
filename = g_strdup(original);
|
||||
else
|
||||
filename = g_strdup_printf("%s_%d", original, i);
|
||||
DEBUG("Trying %s", filename);
|
||||
key_file = gnc_key_file_load_from_file(filename, FALSE);
|
||||
DEBUG("Result %p", key_file);
|
||||
|
||||
if (!key_file) {
|
||||
DEBUG("No key file by that name");
|
||||
break;
|
||||
}
|
||||
|
||||
file_guid = g_key_file_get_string(key_file,
|
||||
STATE_FILE_TOP, STATE_FILE_BOOK_GUID,
|
||||
&error);
|
||||
DEBUG("File GUID is %s", file_guid);
|
||||
if (strcmp(guid, file_guid) == 0) {
|
||||
DEBUG("Matched !!!");
|
||||
g_free(file_guid);
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG("Clean up this pass");
|
||||
g_free(file_guid);
|
||||
g_key_file_free(key_file);
|
||||
g_free(filename);
|
||||
i++;
|
||||
}
|
||||
|
||||
DEBUG("Clean up");
|
||||
g_free(original);
|
||||
if (filename_p)
|
||||
*filename_p = filename;
|
||||
else
|
||||
g_free(filename);
|
||||
LEAVE("key_file %p, filename %s", key_file,
|
||||
filename_p ? *filename_p : "(none)");
|
||||
return key_file;
|
||||
}
|
||||
|
||||
/* ----------------------- END OF FILE --------------------- */
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#define GNC_FILE_UTILS_H
|
||||
|
||||
#include <stdio.h> /* for FILE* */
|
||||
#ifndef HAVE_GLIB26
|
||||
#include "gkeyfile.h"
|
||||
#endif
|
||||
|
||||
char * gncFindFile (const char * filename);
|
||||
|
||||
@@ -59,4 +62,24 @@ int gncReadFile (const char * file, char ** data);
|
||||
gint64 gnc_getline (gchar **line, FILE *file);
|
||||
|
||||
|
||||
/* Definitions shared by file-utils.c and gnc-main-window.c */
|
||||
#define STATE_FILE_TOP "Top"
|
||||
#define STATE_FILE_BOOK_GUID "Book Guid"
|
||||
|
||||
/** Find the state file that corresponds to this URL and guid. The
|
||||
* URL is used to compute the base name of the file (which will be in
|
||||
* ~/.gnucash/books) and the guid is used to differentiate when the
|
||||
* user has multiple data files with the same name.
|
||||
*
|
||||
* @param url The usrl of the data file being used.
|
||||
*
|
||||
* @param guid The guid of the book associated with this data file.
|
||||
*
|
||||
* @param next_filename Return the next available file name if the
|
||||
* data file cannot be found.
|
||||
*
|
||||
* @return The name of the data file that was located.
|
||||
*/
|
||||
GKeyFile *gnc_find_state_file (const gchar *url, const gchar *guid, gchar **filename);
|
||||
|
||||
#endif /* GNC_FILE_UTILS_H */
|
||||
|
||||
@@ -1152,3 +1152,27 @@ gnc_get_credit_string(GNCAccountType account_type)
|
||||
return g_strdup(string);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Clean up a scheme options string for use in a key/value file.
|
||||
* This function removes all full line comments, removes all blank
|
||||
* lines, and removes all leading/trailing white space. */
|
||||
gchar *gnc_guile_strip_comments (const gchar *raw_text)
|
||||
{
|
||||
gchar *text, **splits;
|
||||
gint i, j;
|
||||
|
||||
splits = g_strsplit(raw_text, "\n", -1);
|
||||
for (i = j = 0; splits[i]; i++) {
|
||||
if ((splits[i][0] == ';') || (splits[i][0] == '\0')) {
|
||||
g_free(splits[i]);
|
||||
continue;
|
||||
}
|
||||
splits[j++] = g_strstrip(splits[i]);
|
||||
}
|
||||
splits[j] = NULL;
|
||||
|
||||
text = g_strjoinv(" ", splits);
|
||||
g_strfreev(splits);
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -95,4 +95,13 @@ int gnc_trans_scm_get_num_splits(SCM trans_scm);
|
||||
char * gnc_get_debit_string(GNCAccountType account_type);
|
||||
char * gnc_get_credit_string(GNCAccountType account_type);
|
||||
|
||||
/** Clean up a scheme options string for use in a key/value file.
|
||||
* This function removes all full line comments, removes all blank
|
||||
* lines, and removes all leading/trailing white space.
|
||||
*
|
||||
* @note: This function does not correctly handle comments that occur
|
||||
* at the end of a line. Fortunately there aren't any such
|
||||
* comments. */
|
||||
gchar *gnc_guile_strip_comments (const gchar *text);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "dialog-tax-table.h"
|
||||
#include "dialog-vendor.h"
|
||||
#include "gnc-plugin-business.h"
|
||||
#include "gnc-plugin-page-invoice.h"
|
||||
#include "gncOwner.h"
|
||||
#include "messages.h"
|
||||
#include "gnc-ui-util.h"
|
||||
@@ -303,6 +304,10 @@ gnc_plugin_business_new (void)
|
||||
{
|
||||
GncPluginBusiness *plugin;
|
||||
|
||||
/* Reference the invoice page plugin to ensure it exists in
|
||||
* the gtk type system. */
|
||||
GNC_TYPE_PLUGIN_PAGE_INVOICE;
|
||||
|
||||
plugin = g_object_new (GNC_TYPE_PLUGIN_BUSINESS,
|
||||
NULL);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ G_BEGIN_DECLS
|
||||
#define GNC_IS_PLUGIN_PAGE_INVOICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_INVOICE))
|
||||
#define GNC_PLUGIN_PAGE_INVOICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_INVOICE, GncPluginPageInvoiceClass))
|
||||
|
||||
#define GNC_PLUGIN_PAGE_INVOICE_NAME "gnc-plugin-page-invoice"
|
||||
#define GNC_PLUGIN_PAGE_INVOICE_NAME "GncPluginPageInvoice"
|
||||
|
||||
/* typedefs & structures */
|
||||
typedef struct {
|
||||
|
||||
@@ -17,6 +17,7 @@ AM_CFLAGS = \
|
||||
-I${top_srcdir}/src/network-utils \
|
||||
-I${top_srcdir}/src/app-utils \
|
||||
-I${top_srcdir}/src \
|
||||
-I${top_srcdir}/lib/glib26 \
|
||||
${LIBGUPPI_CFLAGS} \
|
||||
${GLIB_CFLAGS} \
|
||||
${GLADE_CFLAGS} \
|
||||
@@ -40,10 +41,11 @@ AM_CFLAGS = \
|
||||
-I${top_srcdir}/src/backend/file \
|
||||
-I${top_srcdir}/src/network-utils \
|
||||
-I${top_srcdir}/src/app-utils \
|
||||
-I${top_srcdir}/src \
|
||||
-I${top_srcdir}/lib/goffice \
|
||||
-I${top_srcdir}/lib/goffice/split \
|
||||
-I${top_srcdir}/lib/glib26 \
|
||||
-I${top_srcdir}/lib \
|
||||
-I${top_srcdir}/src \
|
||||
${LIBGUPPI_CFLAGS} \
|
||||
${GNOME_CFLAGS} \
|
||||
${GTKHTML_CFLAGS} \
|
||||
@@ -205,6 +207,7 @@ libgncmod_gnome_utils_la_LIBADD = \
|
||||
${top_builddir}/src/calculation/libgncmod-calculation.la \
|
||||
${top_builddir}/src/network-utils/libgncmod-network-utils.la \
|
||||
${top_builddir}/src/app-utils/libgncmod-app-utils.la \
|
||||
${top_builddir}/lib/glib26/libgncglib.la \
|
||||
${LIBGUPPI_LIBS} \
|
||||
${GNOME_LIBS} \
|
||||
${GNOME_PRINT_LIBS} \
|
||||
@@ -228,6 +231,7 @@ libgncmod_gnome_utils_la_LIBADD = \
|
||||
${top_builddir}/src/network-utils/libgncmod-network-utils.la \
|
||||
${top_builddir}/src/app-utils/libgncmod-app-utils.la \
|
||||
${top_builddir}/lib/goffice/libgoffice.la \
|
||||
${top_builddir}/lib/glib26/libgncglib.la \
|
||||
${LIBGUPPI_LIBS} \
|
||||
${GNOME_LIBS} \
|
||||
${GNOME_PRINT_LIBS} \
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkpixbuf.h>
|
||||
#include <gtk/gtk.h>
|
||||
#ifndef HAVE_GLIB26
|
||||
#include "gkeyfile.h"
|
||||
#endif
|
||||
|
||||
#include "gnc-plugin.h"
|
||||
#include "gnc-plugin-manager.h"
|
||||
@@ -46,12 +48,15 @@
|
||||
#include "dialog-reset-warnings.h"
|
||||
#include "dialog-transfer.h"
|
||||
#include "dialog-utils.h"
|
||||
#include "file-utils.h"
|
||||
#include "gnc-component-manager.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-file.h"
|
||||
#include "gnc-gkeyfile-utils.h"
|
||||
#include "gnc-gnome-utils.h"
|
||||
#include "gnc-gobject-utils.h"
|
||||
#include "gnc-gui-query.h"
|
||||
#include "gnc-hooks.h"
|
||||
#include "gnc-session.h"
|
||||
#include "gnc-ui.h"
|
||||
#include "gnc-version.h"
|
||||
@@ -60,6 +65,7 @@
|
||||
#include "gnc-gconf-utils.h"
|
||||
// +JSLED
|
||||
#include "gnc-html.h"
|
||||
#include <g-wrap-wct.h>
|
||||
|
||||
enum {
|
||||
PAGE_ADDED,
|
||||
@@ -89,6 +95,8 @@ static void gnc_main_window_destroy (GtkObject *object);
|
||||
static void gnc_main_window_setup_window (GncMainWindow *window);
|
||||
static void gnc_window_main_window_init (GncWindowIface *iface);
|
||||
|
||||
static void main_window_update_page_name (GncMainWindow *window, GncPluginPage *page, const gchar *name_in);
|
||||
|
||||
/* Callbacks */
|
||||
static void gnc_main_window_add_widget (GtkUIManager *merge, GtkWidget *widget, GncMainWindow *window);
|
||||
static void gnc_main_window_switch_page (GtkNotebook *notebook, GtkNotebookPage *notebook_page, gint pos, GncMainWindow *window);
|
||||
@@ -105,6 +113,7 @@ static void gnc_main_window_cmd_view_toolbar (GtkAction *action, GncMainWindow *
|
||||
static void gnc_main_window_cmd_view_summary (GtkAction *action, GncMainWindow *window);
|
||||
static void gnc_main_window_cmd_view_statusbar (GtkAction *action, GncMainWindow *window);
|
||||
static void gnc_main_window_cmd_actions_reset_warnings (GtkAction *action, GncMainWindow *window);
|
||||
static void gnc_main_window_cmd_actions_rename_page (GtkAction *action, GncMainWindow *window);
|
||||
static void gnc_main_window_cmd_window_new (GtkAction *action, GncMainWindow *window);
|
||||
static void gnc_main_window_cmd_window_move_page (GtkAction *action, GncMainWindow *window);
|
||||
static void gnc_main_window_cmd_window_raise (GtkAction *action, GtkRadioAction *current, GncMainWindow *window);
|
||||
@@ -117,6 +126,7 @@ static void gnc_main_window_cmd_test( GtkAction *action, GncMainWindow *window )
|
||||
static void do_popup_menu(GncPluginPage *page, GdkEventButton *event);
|
||||
static gboolean gnc_main_window_popup_menu_cb (GtkWidget *widget, GncPluginPage *page);
|
||||
|
||||
static GtkAction *gnc_main_window_find_action (GncMainWindow *window, const gchar *name);
|
||||
|
||||
typedef struct GncMainWindowPrivate
|
||||
{
|
||||
@@ -200,6 +210,9 @@ static GtkActionEntry gnc_menu_actions [] =
|
||||
{ "ActionsForgetWarningsAction", NULL, N_("_Reset Warnings..."), NULL,
|
||||
N_("Reset the state of all warning message so they will be shown again."),
|
||||
G_CALLBACK (gnc_main_window_cmd_actions_reset_warnings) },
|
||||
{ "ActionsRenamePageAction", NULL, N_("Rename Page"), NULL,
|
||||
N_("Rename this page."),
|
||||
G_CALLBACK (gnc_main_window_cmd_actions_rename_page) },
|
||||
|
||||
/* Windows menu */
|
||||
|
||||
@@ -298,18 +311,477 @@ static GQuark window_type = 0;
|
||||
/************************************************************
|
||||
* *
|
||||
************************************************************/
|
||||
#define WINDOW_COUNT "Window Count"
|
||||
#define WINDOW_STRING "Window %d"
|
||||
#define WINDOW_GEOMETRY "Window Geometry"
|
||||
#define WINDOW_POSITION "Window Position"
|
||||
#define WINDOW_FIRSTPAGE "First Page"
|
||||
#define WINDOW_PAGECOUNT "Page Count"
|
||||
#define PAGE_TYPE "Page Type"
|
||||
#define PAGE_NAME "Page Name"
|
||||
#define PAGE_STRING "Page %d"
|
||||
|
||||
typedef struct {
|
||||
GKeyFile *key_file;
|
||||
const gchar *group_name;
|
||||
gint window_num;
|
||||
gint page_num;
|
||||
gint page_offset;
|
||||
} GncMainWindowSaveData;
|
||||
|
||||
|
||||
/** Restore a single page to a window. This function calls a page
|
||||
* specific function to create the actual page. It then handles all
|
||||
* the common tasks such as insuring the page is installed into a
|
||||
* window, updating the page name, and anything else that might be
|
||||
* common to all pages.
|
||||
*
|
||||
* @param window The GncMainWindow where the new page will be
|
||||
* installed.
|
||||
*
|
||||
* @param data A data structure containing state about the
|
||||
* window/page restoration process. */
|
||||
static void
|
||||
gnc_main_window_save_window (GncMainWindow *window, gpointer session)
|
||||
gnc_main_window_restore_page (GncMainWindow *window, GncMainWindowSaveData *data)
|
||||
{
|
||||
DEBUG("window %p", window);
|
||||
GncMainWindowPrivate *priv;
|
||||
GncPluginPage *page;
|
||||
gchar *page_group, *page_type = NULL, *name = NULL;
|
||||
const gchar *class_type;
|
||||
GError *error = NULL;
|
||||
|
||||
ENTER("window %p, data %p (key file %p, window %d, page start %d, page num %d)",
|
||||
window, data, data->key_file, data->window_num, data->page_offset, data->page_num);
|
||||
|
||||
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
|
||||
page_group = g_strdup_printf(PAGE_STRING, data->page_offset + data->page_num);
|
||||
page_type = g_key_file_get_string(data->key_file, page_group,
|
||||
PAGE_TYPE, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
page_group, PAGE_TYPE, error->message);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* See if the page already exists. */
|
||||
page = g_list_nth_data(priv->installed_pages, data->page_num);
|
||||
if (page) {
|
||||
class_type = GNC_PLUGIN_PAGE_GET_CLASS(page)->plugin_name;
|
||||
if (strcmp(page_type, class_type) != 0) {
|
||||
g_warning("error: page types don't match: state %s, existing page %s",
|
||||
page_type, class_type);
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
/* create and install the page */
|
||||
page = gnc_plugin_page_recreate_page(GTK_WIDGET(window), page_type,
|
||||
data->key_file, page_group);
|
||||
if (page) {
|
||||
/* Does the page still need to be installed into the window? */
|
||||
if (page->window == NULL) {
|
||||
gnc_main_window_open_page(window, page);
|
||||
}
|
||||
|
||||
/* Restore the page name */
|
||||
name = g_key_file_get_string(data->key_file, page_group,
|
||||
PAGE_NAME, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
page_group, PAGE_NAME, error->message);
|
||||
/* Fall through and still show the page. */
|
||||
} else {
|
||||
DEBUG("updating page name for %p to %s.", page, name);
|
||||
main_window_update_page_name(window, page, name);
|
||||
g_free(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LEAVE("ok");
|
||||
cleanup:
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
if (page_type)
|
||||
g_free(page_type);
|
||||
g_free(page_group);
|
||||
}
|
||||
|
||||
|
||||
/** Restore all the pages in a given window. This function restores
|
||||
* all the window specific attributes, then calls a helper function
|
||||
* to restore all the pages that are contained in the window.
|
||||
*
|
||||
* @param window The GncMainWindow whose pages should be restored.
|
||||
*
|
||||
* @param data A data structure containing state about the
|
||||
* window/page restoration process. */
|
||||
static void
|
||||
gnc_main_window_shutdown (gpointer session, gpointer user_data)
|
||||
gnc_main_window_restore_window (GncMainWindow *window, GncMainWindowSaveData *data)
|
||||
{
|
||||
DEBUG("session %p (%s)", session, qof_session_get_url (session));
|
||||
g_list_foreach (active_windows, (GFunc)gnc_main_window_save_window, session);
|
||||
GncMainWindowPrivate *priv;
|
||||
gint *pos, *geom;
|
||||
gsize length;
|
||||
gchar *window_group;
|
||||
gint page_start, page_count, i;
|
||||
GError *error = NULL;
|
||||
|
||||
/* Setup */
|
||||
ENTER("window %p, data %p (key file %p, window %d)",
|
||||
window, data, data->key_file, data->window_num);
|
||||
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
|
||||
window_group = g_strdup_printf(WINDOW_STRING, data->window_num + 1);
|
||||
|
||||
/* Save the window coordinates, etc. */
|
||||
pos = g_key_file_get_integer_list(data->key_file, window_group,
|
||||
WINDOW_POSITION, &length, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
window_group, WINDOW_POSITION, error->message);
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
} else if (length != 2) {
|
||||
g_warning("invalid number of values for group %s key %s",
|
||||
window_group, WINDOW_POSITION);
|
||||
} else {
|
||||
gtk_window_move(GTK_WINDOW(window), pos[0], pos[1]);
|
||||
DEBUG("window (%p) position %dx%d", window, pos[0], pos[1]);
|
||||
}
|
||||
|
||||
geom = g_key_file_get_integer_list(data->key_file, window_group,
|
||||
WINDOW_GEOMETRY, &length, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
window_group, WINDOW_GEOMETRY, error->message);
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
} else if (length != 2) {
|
||||
g_warning("invalid number of values for group %s key %s",
|
||||
window_group, WINDOW_GEOMETRY);
|
||||
} else {
|
||||
gtk_window_resize(GTK_WINDOW(window), geom[0], geom[1]);
|
||||
DEBUG("window (%p) size %dx%d", window, geom[0], geom[1]);
|
||||
}
|
||||
|
||||
/* Get this window's notebook info */
|
||||
page_start = g_key_file_get_integer(data->key_file,
|
||||
window_group, WINDOW_FIRSTPAGE, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
window_group, WINDOW_FIRSTPAGE, error->message);
|
||||
goto cleanup;
|
||||
}
|
||||
page_count = g_key_file_get_integer(data->key_file,
|
||||
window_group, WINDOW_PAGECOUNT, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
window_group, WINDOW_PAGECOUNT, error->message);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < page_count; i++) {
|
||||
data->page_offset = page_start;
|
||||
data->page_num = i;
|
||||
gnc_main_window_restore_page(window, data);
|
||||
}
|
||||
|
||||
LEAVE("window %p", window);
|
||||
cleanup:
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
g_free(window_group);
|
||||
}
|
||||
|
||||
|
||||
/** Restore all windows. This function finds the "new" state file
|
||||
* associated with a specific book guid. It then iterates through
|
||||
* this state information, calling a helper function to recreate
|
||||
* each open window.
|
||||
*
|
||||
* If the "new" state file cannot be found, this function will open
|
||||
* an account tree window and then attempt to invoke the old gnucash
|
||||
* 1.x state routines. This provides a fluid transition for users
|
||||
* from the old to the new state systems.
|
||||
*
|
||||
* @note The name of the state file is based on the name of the data
|
||||
* file, not the path name of the data file. If there are multiple
|
||||
* data files with the same name, the state files will be suffixed
|
||||
* with a number. E.G. test_account, test_account_2, test_account_3,
|
||||
* etc.
|
||||
*
|
||||
* @param session A pointer to the current session.
|
||||
*
|
||||
* @param unused An unused pointer. */
|
||||
static void
|
||||
gnc_main_window_restore_all_state (gpointer session, gpointer unused)
|
||||
{
|
||||
GncMainWindow *window;
|
||||
GncMainWindowSaveData data;
|
||||
QofBook *book;
|
||||
const gchar *url, *guid_string;
|
||||
gchar *file_guid, *filename = NULL;
|
||||
const GUID *guid;
|
||||
gint i, window_count;
|
||||
GError *error = NULL;
|
||||
|
||||
url = qof_session_get_url(session);
|
||||
ENTER("session %p (%s)", session, url);
|
||||
if (!url) {
|
||||
LEAVE("no url, nothing to do");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the book GUID */
|
||||
book = qof_session_get_book(session);
|
||||
guid = qof_entity_get_guid(QOF_ENTITY(book));
|
||||
guid_string = guid_to_string(guid);
|
||||
|
||||
data.key_file = gnc_find_state_file(url, guid_string, &filename);
|
||||
if (filename)
|
||||
g_free(filename);
|
||||
if (!data.key_file) {
|
||||
GtkAction *action;
|
||||
|
||||
/* The default state should be to have an Account Tree page open
|
||||
* in the window. */
|
||||
DEBUG("no saved state file");
|
||||
window = g_list_nth_data(active_windows, 0);
|
||||
action = gnc_main_window_find_action(window, "FileNewAccountTreeAction");
|
||||
gtk_action_activate(action);
|
||||
|
||||
#if (GNUCASH_MAJOR_VERSION < 2) || ((GNUCASH_MAJOR_VERSION == 2) && (GNUCASH_MINOR_VERSION == 0))
|
||||
/* See if there's an old style state file to be found */
|
||||
scm_call_1(scm_c_eval_string("gnc:main-window-book-open-handler"),
|
||||
(session ?
|
||||
gw_wcp_assimilate_ptr (session, scm_c_eval_string("<gnc:Session*>")) :
|
||||
SCM_BOOL_F));
|
||||
#endif
|
||||
|
||||
LEAVE("old");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Debugging: dump a copy to stdout and the trace log */
|
||||
{
|
||||
gchar *file_data;
|
||||
gint file_length;
|
||||
file_data = g_key_file_to_data(data.key_file, &file_length, NULL);
|
||||
DEBUG("=== File Data Read===\n%s\n=== File End ===\n", file_data);
|
||||
g_free(file_data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* validate top level info */
|
||||
file_guid = g_key_file_get_string(data.key_file,
|
||||
STATE_FILE_TOP, STATE_FILE_BOOK_GUID,
|
||||
&error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
STATE_FILE_TOP, STATE_FILE_BOOK_GUID, error->message);
|
||||
LEAVE("can't read guid");
|
||||
goto cleanup;
|
||||
}
|
||||
if (!file_guid || strcmp(guid_string, file_guid)) {
|
||||
g_warning("guid mismatch: book guid %s, state file guid %s",
|
||||
guid_string, file_guid);
|
||||
LEAVE("guid values do not match");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
window_count =
|
||||
g_key_file_get_integer(data.key_file, STATE_FILE_TOP, WINDOW_COUNT, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
STATE_FILE_TOP, WINDOW_COUNT, error->message);
|
||||
LEAVE("can't read count");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Restore all state information on the open windows. Window
|
||||
numbers in state file are 1-based. GList indices are 0-based. */
|
||||
for (i = 0; i < window_count; i++) {
|
||||
data.window_num = i;
|
||||
window = g_list_nth_data(active_windows, i);
|
||||
if (window == NULL) {
|
||||
DEBUG("Window %d doesn't exist. Creating new window.", i);
|
||||
DEBUG("active_windows %p.", active_windows);
|
||||
if (active_windows)
|
||||
DEBUG("first window %p.", active_windows->data);
|
||||
window = gnc_main_window_new();
|
||||
}
|
||||
gnc_main_window_restore_window(window, &data);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
LEAVE("ok");
|
||||
cleanup:
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
if (file_guid)
|
||||
g_free(file_guid);
|
||||
g_key_file_free(data.key_file);
|
||||
}
|
||||
|
||||
|
||||
/** Save the state of a single page to a disk. This function handles
|
||||
* all the common tasks such as saving the page type and name, and
|
||||
* anything else that might be common to all pages. It then calls a
|
||||
* page specific function to save the actual page.
|
||||
*
|
||||
* @param page The GncPluginPage whose state should be saved.
|
||||
*
|
||||
* @param data A data structure containing state about the
|
||||
* window/page saving process. */
|
||||
static void
|
||||
gnc_main_window_save_page (GncPluginPage *page, GncMainWindowSaveData *data)
|
||||
{
|
||||
gchar *page_group;
|
||||
|
||||
ENTER("page %p, data %p (key file %p, window %d, page %d)",
|
||||
page, data, data->key_file, data->window_num, data->page_num);
|
||||
page_group = g_strdup_printf(PAGE_STRING, data->page_num++);
|
||||
g_key_file_set_string(data->key_file, page_group, PAGE_TYPE,
|
||||
GNC_PLUGIN_PAGE_GET_CLASS(page)->plugin_name);
|
||||
|
||||
g_key_file_set_string(data->key_file, page_group, PAGE_NAME,
|
||||
gnc_plugin_page_get_page_name(page));
|
||||
|
||||
gnc_plugin_page_save_page(page, data->key_file, page_group);
|
||||
g_free(page_group);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
|
||||
/** Saves all the pages in a single window to a disk. This function
|
||||
* saves all the window specific attributes, then calls a helper
|
||||
* function to save all the pages that are contained in the window.
|
||||
*
|
||||
* @param window The GncMainWindow whose pages should be saved.
|
||||
*
|
||||
* @param data A data structure containing state about the
|
||||
* window/page saving process. */
|
||||
static void
|
||||
gnc_main_window_save_window (GncMainWindow *window, GncMainWindowSaveData *data)
|
||||
{
|
||||
GncMainWindowPrivate *priv;
|
||||
gint num_pages, coords[4];
|
||||
gchar *window_group;
|
||||
|
||||
/* Setup */
|
||||
ENTER("window %p, data %p (key file %p, window %d)",
|
||||
window, data, data->key_file, data->window_num);
|
||||
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
|
||||
window_group = g_strdup_printf(WINDOW_STRING, data->window_num++);
|
||||
|
||||
/* Save the window coordinates, etc. */
|
||||
gtk_window_get_position(GTK_WINDOW(window), &coords[0], &coords[1]);
|
||||
gtk_window_get_size(GTK_WINDOW(window), &coords[2], &coords[3]);
|
||||
g_key_file_set_integer_list(data->key_file, window_group,
|
||||
WINDOW_POSITION, &coords[0], 2);
|
||||
g_key_file_set_integer_list(data->key_file, window_group,
|
||||
WINDOW_GEOMETRY, &coords[2], 2);
|
||||
DEBUG("window (%p) position %dx%d, size %dx%d", window, coords[0], coords[1],
|
||||
coords[2], coords[3]);
|
||||
|
||||
/* Save this window's notebook info */
|
||||
num_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook));
|
||||
g_key_file_set_integer(data->key_file, window_group,
|
||||
WINDOW_PAGECOUNT, num_pages);
|
||||
g_key_file_set_integer(data->key_file, window_group,
|
||||
WINDOW_FIRSTPAGE, data->page_num);
|
||||
|
||||
/* Save individual pages in this window */
|
||||
g_list_foreach(priv->installed_pages, (GFunc)gnc_main_window_save_page, data);
|
||||
|
||||
g_free(window_group);
|
||||
LEAVE("window %p", window);
|
||||
}
|
||||
|
||||
|
||||
/** Save the state of all windows to disk. This function finds the
|
||||
* name of the "new" state file associated with a specific book guid.
|
||||
* It saves some top level data, then iterates through the list of
|
||||
* open windows calling a helper function to save each window.
|
||||
*
|
||||
* @note The name of the state file is based on the name of the data
|
||||
* file, not the path name of the data file. If there are multiple
|
||||
* data files with the same name, the state files will be suffixed
|
||||
* with a number. E.G. test_account, test_account_2, test_account_3,
|
||||
* etc.
|
||||
*
|
||||
* @param page The GncPluginPage whose state should be saved.
|
||||
*
|
||||
* @param data A data structure containing state about the
|
||||
* window/page saving process. */
|
||||
static void
|
||||
gnc_main_window_save_all_state (gpointer session, gpointer user_data)
|
||||
{
|
||||
GncMainWindowSaveData data;
|
||||
QofBook *book;
|
||||
const char *url, *guid_string;
|
||||
gchar *filename;
|
||||
const GUID *guid;
|
||||
GError *error = NULL;
|
||||
|
||||
url = qof_session_get_url(session);
|
||||
ENTER("session %p (%s)", session, url);
|
||||
if (!url) {
|
||||
LEAVE("no url, nothing to do");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the book GUID */
|
||||
book = qof_session_get_book(session);
|
||||
guid = qof_entity_get_guid(QOF_ENTITY(book));
|
||||
guid_string = guid_to_string(guid);
|
||||
|
||||
/* Find the filename to use. This returns the data from the
|
||||
* file so its possible that we could reuse the data and
|
||||
* maintain comments that were added to the data file, but
|
||||
* that's not something we currently do. For now the existing
|
||||
* data is dumped and completely regenerated.*/
|
||||
data.key_file = gnc_find_state_file(url, guid_string, &filename);
|
||||
if (data.key_file)
|
||||
g_key_file_free(data.key_file);
|
||||
|
||||
/* Set up the iterator data structures */
|
||||
data.key_file = g_key_file_new();
|
||||
data.window_num = 1;
|
||||
data.page_num = 1;
|
||||
|
||||
/* Store top level info in the data structure */
|
||||
g_key_file_set_string(data.key_file,
|
||||
STATE_FILE_TOP, STATE_FILE_BOOK_GUID,
|
||||
guid_string);
|
||||
g_key_file_set_integer(data.key_file,
|
||||
STATE_FILE_TOP, WINDOW_COUNT,
|
||||
g_list_length(active_windows));
|
||||
|
||||
/* Dump all state information on the open windows */
|
||||
g_list_foreach(active_windows, (GFunc)gnc_main_window_save_window, &data);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Debugging: dump a copy to the trace log */
|
||||
{
|
||||
gchar *file_data;
|
||||
gint file_length;
|
||||
file_data = g_key_file_to_data(data.key_file, &file_length, NULL);
|
||||
DEBUG("=== File Data Written===\n%s\n=== File End ===\n", file_data);
|
||||
g_free(file_data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write it all out to disk */
|
||||
gnc_key_file_save_to_file(filename, data.key_file, &error);
|
||||
if (error) {
|
||||
g_critical(_("Error: Failure saving state file.\n %s"), error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
g_free(filename);
|
||||
|
||||
/* Clean up */
|
||||
g_key_file_free(data.key_file);
|
||||
LEAVE("");
|
||||
}
|
||||
|
||||
|
||||
@@ -873,6 +1345,127 @@ gnc_main_window_update_tabs (GConfEntry *entry, gpointer user_data)
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
* Tab Label Implementation *
|
||||
************************************************************/
|
||||
static gboolean
|
||||
main_window_find_tab_items (GncMainWindow *window,
|
||||
GncPluginPage *page,
|
||||
GtkWidget **label_p,
|
||||
GtkWidget **entry_p)
|
||||
{
|
||||
GncMainWindowPrivate *priv;
|
||||
GtkWidget *tab_hbox, *widget;
|
||||
GList *children, *tmp;
|
||||
|
||||
ENTER("window %p, page %p, label_p %p, entry_p %p",
|
||||
window, page, label_p, entry_p);
|
||||
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
|
||||
*label_p = *entry_p = NULL;
|
||||
tab_hbox = gtk_notebook_get_tab_label(GTK_NOTEBOOK(priv->notebook),
|
||||
page->notebook_page);
|
||||
children = gtk_container_get_children(GTK_CONTAINER(tab_hbox));
|
||||
for (tmp = children; tmp; tmp = g_list_next(tmp)) {
|
||||
widget = tmp->data;
|
||||
if (GTK_IS_LABEL(widget)) {
|
||||
*label_p = widget;
|
||||
} else if (GTK_IS_ENTRY(widget)) {
|
||||
*entry_p = widget;
|
||||
}
|
||||
}
|
||||
g_list_free(children);
|
||||
|
||||
LEAVE("label %p, entry %p", *label_p, *entry_p);
|
||||
return (*label_p && *entry_p);
|
||||
}
|
||||
|
||||
static void
|
||||
main_window_update_page_name (GncMainWindow *window,
|
||||
GncPluginPage *page,
|
||||
const gchar *name_in)
|
||||
{
|
||||
GncMainWindowPrivate *priv;
|
||||
GtkWidget *label, *entry;
|
||||
gchar *name;
|
||||
|
||||
ENTER(" ");
|
||||
|
||||
if ((name_in == NULL) || (*name_in == '\0')) {
|
||||
LEAVE("no string");
|
||||
return;
|
||||
}
|
||||
name = g_strstrip(g_strdup(name_in));
|
||||
if (*name == '\0') {
|
||||
g_free(name);
|
||||
LEAVE("empty string");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update the plugin */
|
||||
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
|
||||
gnc_plugin_page_set_page_name(page, name);
|
||||
|
||||
/* Update the notebook tab */
|
||||
main_window_find_tab_items(window, page, &label, &entry);
|
||||
gtk_label_set_text(GTK_LABEL(label), name);
|
||||
|
||||
/* Update the notebook menu */
|
||||
label = gtk_notebook_get_menu_label (GTK_NOTEBOOK(priv->notebook),
|
||||
page->notebook_page);
|
||||
gtk_label_set_text(GTK_LABEL(label), name);
|
||||
|
||||
/* Force an update of the window title */
|
||||
gnc_main_window_update_title(window);
|
||||
g_free(name);
|
||||
LEAVE("done");
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_main_window_tab_entry_activate (GtkWidget *entry,
|
||||
GncPluginPage *page)
|
||||
{
|
||||
GtkWidget *label, *entry2;
|
||||
|
||||
g_return_if_fail(GTK_IS_ENTRY(entry));
|
||||
g_return_if_fail(GNC_IS_PLUGIN_PAGE(page));
|
||||
|
||||
ENTER("");
|
||||
if (!main_window_find_tab_items(GNC_MAIN_WINDOW(page->window),
|
||||
page, &label, &entry2)) {
|
||||
LEAVE("can't find required widgets");
|
||||
return;
|
||||
}
|
||||
|
||||
main_window_update_page_name(GNC_MAIN_WINDOW(page->window), page,
|
||||
gtk_entry_get_text(GTK_ENTRY(entry)));
|
||||
|
||||
gtk_widget_hide(entry);
|
||||
gtk_widget_show(label);
|
||||
LEAVE("");
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gnc_main_window_tab_entry_editing_done (GtkWidget *entry,
|
||||
GncPluginPage *page)
|
||||
{
|
||||
ENTER("");
|
||||
gnc_main_window_tab_entry_activate(entry, page);
|
||||
LEAVE("");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnc_main_window_tab_entry_focus_out_event (GtkWidget *entry,
|
||||
GdkEvent *event,
|
||||
GncPluginPage *page)
|
||||
{
|
||||
ENTER("");
|
||||
gnc_main_window_tab_entry_activate(entry, page);
|
||||
LEAVE("");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Widget Implementation *
|
||||
************************************************************/
|
||||
@@ -982,7 +1575,10 @@ gnc_main_window_class_init (GncMainWindowClass *klass)
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_OBJECT);
|
||||
|
||||
qof_session_add_close_hook(gnc_main_window_shutdown, NULL);
|
||||
gnc_hook_add_dangler(HOOK_BOOK_OPENED,
|
||||
gnc_main_window_restore_all_state, NULL);
|
||||
gnc_hook_add_dangler(HOOK_BOOK_CLOSED,
|
||||
gnc_main_window_save_all_state, NULL);
|
||||
|
||||
gnc_gconf_general_register_cb (KEY_SHOW_CLOSE_BUTTON,
|
||||
gnc_main_window_update_tabs,
|
||||
@@ -1249,7 +1845,7 @@ gnc_main_window_open_page (GncMainWindow *window,
|
||||
{
|
||||
GncMainWindowPrivate *priv;
|
||||
GtkWidget *tab_hbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *label, *entry;
|
||||
const gchar *icon;
|
||||
GtkWidget *image;
|
||||
gboolean immutable = FALSE;
|
||||
@@ -1304,6 +1900,18 @@ gnc_main_window_open_page (GncMainWindow *window,
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (tab_hbox), label, TRUE, TRUE, 0);
|
||||
|
||||
entry = gtk_entry_new();
|
||||
gtk_widget_hide (entry);
|
||||
gtk_box_pack_start (GTK_BOX (tab_hbox), entry, TRUE, TRUE, 0);
|
||||
g_signal_connect(G_OBJECT(entry), "activate",
|
||||
G_CALLBACK(gnc_main_window_tab_entry_activate), page);
|
||||
g_signal_connect(G_OBJECT(entry), "focus-out-event",
|
||||
G_CALLBACK(gnc_main_window_tab_entry_focus_out_event),
|
||||
page);
|
||||
g_signal_connect(G_OBJECT(entry), "editing-done",
|
||||
G_CALLBACK(gnc_main_window_tab_entry_editing_done),
|
||||
page);
|
||||
|
||||
/* Add close button - Not for immutable pages */
|
||||
if (!immutable) {
|
||||
GtkWidget *close_image, *close_button;
|
||||
@@ -1525,6 +2133,22 @@ gnc_main_window_actions_updated (GncMainWindow *window)
|
||||
}
|
||||
|
||||
|
||||
static GtkAction *
|
||||
gnc_main_window_find_action (GncMainWindow *window, const gchar *name)
|
||||
{
|
||||
GtkAction *action = NULL;
|
||||
const GList *groups, *tmp;
|
||||
|
||||
groups = gtk_ui_manager_get_action_groups(window->ui_merge);
|
||||
for (tmp = groups; tmp; tmp = g_list_next(tmp)) {
|
||||
action = gtk_action_group_get_action(GTK_ACTION_GROUP(tmp->data), name);
|
||||
if (action)
|
||||
break;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
/* Retrieve a specific set of user interface actions from a window.
|
||||
* This function can be used to get an group of action to be
|
||||
* manipulated when the front page of a window has changed.
|
||||
@@ -1556,9 +2180,11 @@ gnc_main_window_add_plugin (gpointer plugin,
|
||||
g_return_if_fail (GNC_IS_MAIN_WINDOW (window));
|
||||
g_return_if_fail (GNC_IS_PLUGIN (plugin));
|
||||
|
||||
ENTER(" ");
|
||||
gnc_plugin_add_to_window (GNC_PLUGIN (plugin),
|
||||
GNC_MAIN_WINDOW (window),
|
||||
window_type);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1613,6 +2239,8 @@ gnc_main_window_setup_window (GncMainWindow *window)
|
||||
gchar *filename;
|
||||
SCM debugging;
|
||||
|
||||
ENTER(" ");
|
||||
|
||||
/* Catch window manager delete signal */
|
||||
g_signal_connect (G_OBJECT (window), "delete-event",
|
||||
G_CALLBACK (gnc_main_window_delete_event), window);
|
||||
@@ -1721,8 +2349,10 @@ gnc_main_window_setup_window (GncMainWindow *window)
|
||||
g_signal_connect (G_OBJECT (manager), "plugin-removed",
|
||||
G_CALLBACK (gnc_main_window_plugin_removed), window);
|
||||
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
static void
|
||||
gnc_main_window_add_widget (GtkUIManager *merge,
|
||||
GtkWidget *widget,
|
||||
@@ -1914,6 +2544,43 @@ gnc_main_window_cmd_actions_reset_warnings (GtkAction *action, GncMainWindow *wi
|
||||
gnc_reset_warnings_dialog(GTK_WIDGET(window));
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_main_window_cmd_actions_rename_page (GtkAction *action, GncMainWindow *window)
|
||||
{
|
||||
GncMainWindowPrivate *priv;
|
||||
GncPluginPage *page;
|
||||
GtkWidget *tab_hbox, *widget, *label = NULL, *entry = NULL;
|
||||
GList *children, *tmp;
|
||||
|
||||
ENTER(" ");
|
||||
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
|
||||
page = priv->current_page;
|
||||
tab_hbox = gtk_notebook_get_tab_label(GTK_NOTEBOOK(priv->notebook),
|
||||
page->notebook_page);
|
||||
children = gtk_container_get_children(GTK_CONTAINER(tab_hbox));
|
||||
for (tmp = children; tmp; tmp = g_list_next(tmp)) {
|
||||
widget = tmp->data;
|
||||
if (GTK_IS_LABEL(widget)) {
|
||||
label = widget;
|
||||
} else if (GTK_IS_ENTRY(widget)) {
|
||||
entry = widget;
|
||||
}
|
||||
}
|
||||
g_list_free(children);
|
||||
|
||||
if (!label || !entry) {
|
||||
LEAVE("Missing label or entry.");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_entry_set_text(GTK_ENTRY(entry), gtk_label_get_text(GTK_LABEL(label)));
|
||||
gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
|
||||
gtk_widget_hide(label);
|
||||
gtk_widget_show(entry);
|
||||
gtk_widget_grab_focus(entry);
|
||||
LEAVE("opened for editing");
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_main_window_cmd_view_toolbar (GtkAction *action, GncMainWindow *window)
|
||||
{
|
||||
|
||||
@@ -35,10 +35,15 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "gnc-plugin.h"
|
||||
#include "gnc-plugin-page.h"
|
||||
#include "gnc-gobject-utils.h"
|
||||
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
static QofLogModule log_module = GNC_MOD_GUI;
|
||||
|
||||
static gpointer parent_class = NULL;
|
||||
|
||||
static void gnc_plugin_page_class_init (GncPluginPageClass *klass);
|
||||
@@ -180,6 +185,84 @@ gnc_plugin_page_show_summarybar (GncPluginPage *page,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Call a plugin specific function to save enough information about
|
||||
* this page that it can be recreated next time the user starts
|
||||
* gnucash.
|
||||
*
|
||||
* @param page The page to save.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be written.
|
||||
*
|
||||
* @param group_name The group name to use when saving data. */
|
||||
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 and then calls its
|
||||
* function to create a new page.
|
||||
*
|
||||
* @param window The window where this page should be installed.
|
||||
*
|
||||
* @param page_type The name of the page type to create.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be read.
|
||||
*
|
||||
* @param group_name The group name to use when restoring data. */
|
||||
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) {
|
||||
LEAVE("Cannot create class %s(%ld)", page_type, 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,
|
||||
GtkUIManager *ui_merge)
|
||||
@@ -601,6 +684,7 @@ 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));
|
||||
|
||||
@@ -608,6 +692,12 @@ gnc_plugin_page_set_page_name (GncPluginPage *page, const gchar *name)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
const gchar *
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#ifndef __GNC_PLUGIN_PAGE_H
|
||||
#define __GNC_PLUGIN_PAGE_H
|
||||
|
||||
#include <glib.h>
|
||||
#include "guid.h"
|
||||
#include "qofbook.h"
|
||||
|
||||
@@ -50,6 +51,12 @@ G_BEGIN_DECLS
|
||||
#define GNC_PLUGIN_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_PLUGIN_PAGE, GncPluginPageClass))
|
||||
|
||||
/* typedefs & structures */
|
||||
#ifndef HAVE_GLIB26
|
||||
#ifndef __G_KEY_FILE_H__
|
||||
typedef struct _GKeyFile GKeyFile;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct GncPluginPage {
|
||||
GObject gobject; /**< The parent object data. */
|
||||
|
||||
@@ -84,7 +91,47 @@ typedef struct {
|
||||
/* Virtual Table */
|
||||
GtkWidget *(* create_widget) (GncPluginPage *plugin_page);
|
||||
void (* destroy_widget) (GncPluginPage *plugin_page);
|
||||
|
||||
/** Save enough information about this page so that it can be
|
||||
* recreated next time the user starts gnucash.
|
||||
*
|
||||
* @param page The page to save.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be written.
|
||||
*
|
||||
* @param group_name The group name to use when writing data.
|
||||
* The name is specific to this page instance. */
|
||||
void (* save_page) (GncPluginPage *page, GKeyFile *file, const gchar *group);
|
||||
|
||||
/** Create a new page based on the information saved during a
|
||||
* previous instantiation of gnucash. This function may or
|
||||
* may not install the new page in the window as it sees fit.
|
||||
* Generally the function will install the page int the
|
||||
* window in order to manipulate the menu items that are
|
||||
* created at install time.
|
||||
*
|
||||
* @param window The window where this new page will be
|
||||
* installed.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be retrieved.
|
||||
*
|
||||
* @param group_name The group name to use when retrieving
|
||||
* data. The name is specific to this page instance.
|
||||
*
|
||||
* @return A pointer to the new page. */
|
||||
GncPluginPage * (* recreate_page) (GtkWidget *window, GKeyFile *file, const gchar *group);
|
||||
|
||||
void (* window_changed) (GncPluginPage *plugin_page, GtkWidget *window);
|
||||
|
||||
/** This function vector allows page specific actions to occur
|
||||
* when the page name is changed.
|
||||
*
|
||||
* @param page The page to update.
|
||||
*
|
||||
* @param name The new name for this page. */
|
||||
void (* page_name_changed) (GncPluginPage *plugin_page, const gchar *name);
|
||||
} GncPluginPageClass;
|
||||
|
||||
/* function prototypes */
|
||||
@@ -101,6 +148,14 @@ void gnc_plugin_page_destroy_widget (GncPluginPage *plugin_pag
|
||||
*/
|
||||
void gnc_plugin_page_show_summarybar (GncPluginPage *page, gboolean visible);
|
||||
|
||||
void gnc_plugin_page_save_page (GncPluginPage *page,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name);
|
||||
GncPluginPage * gnc_plugin_page_recreate_page (GtkWidget *window,
|
||||
const gchar *page_type,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name);
|
||||
|
||||
void gnc_plugin_page_merge_actions (GncPluginPage *plugin_page,
|
||||
GtkUIManager *merge);
|
||||
void gnc_plugin_page_unmerge_actions (GncPluginPage *plugin_page,
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
<menu name="ScrubMenu" action="ScrubMenuAction"/>
|
||||
<separator name="ActionSepE"/>
|
||||
<menuitem name="ActionsForgetWarnings" action="ActionsForgetWarningsAction"/>
|
||||
<menuitem name="ActionsRenamePage" action="ActionsRenamePageAction"/>
|
||||
</menu>
|
||||
|
||||
<placeholder name="AdditionalMenusPlaceholder"/>
|
||||
@@ -139,6 +140,7 @@
|
||||
<popup name="MainPopup" action="FakeToplevel">
|
||||
<separator name="PopupSep1"/>
|
||||
<placeholder name="PopupPlaceholder1"/>
|
||||
<menuitem name="ActionsRenamePage" action="ActionsRenamePageAction"/>
|
||||
<separator name="PopupSep2"/>
|
||||
<placeholder name="PopupPlaceholder2"/>
|
||||
<separator name="PopupSep3"/>
|
||||
|
||||
@@ -12,6 +12,7 @@ libgncgnome_la_LIBADD = \
|
||||
${top_builddir}/src/report/report-gnome/libgncmod-report-gnome.la \
|
||||
${top_builddir}/src/register/ledger-core/libgncmod-ledger-core.la \
|
||||
${top_builddir}/src/gnome-search/libgncmod-gnome-search.la \
|
||||
${top_builddir}/lib/glib26/libgncglib.la \
|
||||
${GUILE_LIBS} ${GNOME_LIBS} ${GLIB_LIBS} ${QOF_LIBS}
|
||||
|
||||
libgw_gnc_la_SOURCES = gw-gnc.c
|
||||
@@ -142,6 +143,7 @@ AM_CFLAGS = \
|
||||
-I${top_srcdir}/src/register/register-gnome \
|
||||
-I${top_srcdir}/src/report/report-system \
|
||||
-I${top_srcdir}/src/report/report-gnome \
|
||||
-I${top_srcdir}/lib/glib26 \
|
||||
${GUILE_INCS} \
|
||||
${G_WRAP_COMPILE_ARGS} \
|
||||
${GNOME_CFLAGS} \
|
||||
|
||||
@@ -94,6 +94,10 @@ gnc_plugin_account_tree_new (void)
|
||||
{
|
||||
GncPluginAccountTree *plugin;
|
||||
|
||||
/* Reference the account tree page plugin to ensure it exists
|
||||
* in the gtk type system. */
|
||||
GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE;
|
||||
|
||||
plugin = g_object_new (GNC_TYPE_PLUGIN_ACCOUNT_TREE,
|
||||
NULL);
|
||||
|
||||
@@ -170,20 +174,11 @@ gnc_plugin_account_tree_create_page (GncPlugin *plugin,
|
||||
static void
|
||||
gnc_plugin_account_tree_cmd_new_account_tree (GtkAction *action,
|
||||
GncMainWindowActionData *data)
|
||||
{
|
||||
g_return_if_fail (data != NULL);
|
||||
gnc_new_account_tree (data->window);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Other Functions *
|
||||
************************************************************/
|
||||
|
||||
void
|
||||
gnc_new_account_tree (GncMainWindow *window)
|
||||
{
|
||||
GncPluginPage *page;
|
||||
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
page = gnc_plugin_page_account_tree_new ();
|
||||
gnc_main_window_open_page (window, page);
|
||||
gnc_main_window_open_page (data->window, page);
|
||||
}
|
||||
|
||||
@@ -55,8 +55,6 @@ GType gnc_plugin_account_tree_get_type (void);
|
||||
|
||||
GncPlugin *gnc_plugin_account_tree_new (void);
|
||||
|
||||
void gnc_new_account_tree (GncMainWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GNC_PLUGIN_ACCOUNT_TREE_H */
|
||||
|
||||
@@ -106,6 +106,11 @@ GncPlugin * gnc_plugin_budget_new (void)
|
||||
{
|
||||
GncPluginBudget *plugin;
|
||||
ENTER(" ");
|
||||
|
||||
/* Reference the budget page plugin to ensure it exists in the gtk
|
||||
* type system. */
|
||||
GNC_TYPE_PLUGIN_PAGE_BUDGET;
|
||||
|
||||
plugin = g_object_new (GNC_TYPE_PLUGIN_BUDGET, NULL);
|
||||
LEAVE(" ");
|
||||
return GNC_PLUGIN (plugin);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* gnc-plugin-page-account-tree.c --
|
||||
*
|
||||
* Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
* Copyright (C) 2003 David Hampton <hampton@employees.org>
|
||||
* 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
|
||||
@@ -22,10 +22,22 @@
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org
|
||||
*/
|
||||
|
||||
/** @addtogroup ContentPlugins
|
||||
@{ */
|
||||
/** @addtogroup GncPluginPageAccountTree An Account Tree Plugin
|
||||
@{ */
|
||||
/** @file gnc-plugin-page-account-tree.c
|
||||
@brief utility functions for the GnuCash UI
|
||||
@author Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
Copyright (C) 2003,2005 David Hampton <hampton@employees.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifndef HAVE_GLIB26
|
||||
#include "gkeyfile.h"
|
||||
#endif
|
||||
#include "gnc-plugin-page-account-tree.h"
|
||||
#include "gnc-plugin-page-register.h"
|
||||
|
||||
@@ -69,8 +81,6 @@ typedef struct GncPluginPageAccountTreePrivate
|
||||
GtkWidget *widget;
|
||||
GtkTreeView *tree_view;
|
||||
|
||||
SCM name_change_callback_id;
|
||||
|
||||
GNCOptionDB * odb;
|
||||
SCM options;
|
||||
int options_id;
|
||||
@@ -95,6 +105,8 @@ static void gnc_plugin_page_account_tree_finalize (GObject *object);
|
||||
|
||||
static GtkWidget *gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page);
|
||||
static void gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page);
|
||||
static void gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
|
||||
static GncPluginPage *gnc_plugin_page_account_tree_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
|
||||
|
||||
/* Callbacks */
|
||||
static gboolean gnc_plugin_page_account_tree_button_press_cb (GtkWidget *widget,
|
||||
@@ -232,7 +244,7 @@ gnc_plugin_page_account_tree_get_type (void)
|
||||
};
|
||||
|
||||
gnc_plugin_page_account_tree_type = g_type_register_static (GNC_TYPE_PLUGIN_PAGE,
|
||||
"GncPluginPageAccountTree",
|
||||
GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME,
|
||||
&our_info, 0);
|
||||
}
|
||||
|
||||
@@ -266,6 +278,8 @@ gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass)
|
||||
gnc_plugin_class->plugin_name = GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME;
|
||||
gnc_plugin_class->create_widget = gnc_plugin_page_account_tree_create_widget;
|
||||
gnc_plugin_class->destroy_widget = gnc_plugin_page_account_tree_destroy_widget;
|
||||
gnc_plugin_class->save_page = gnc_plugin_page_account_tree_save_page;
|
||||
gnc_plugin_class->recreate_page = gnc_plugin_page_account_tree_recreate_page;
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GncPluginPageAccountTreePrivate));
|
||||
|
||||
@@ -280,11 +294,6 @@ gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass)
|
||||
G_TYPE_POINTER);
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_plugin_page_acct_tree_view_refresh (gpointer data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_page)
|
||||
{
|
||||
@@ -362,14 +371,6 @@ gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_page)
|
||||
|
||||
priv->odb = gnc_option_db_new(priv->options);
|
||||
|
||||
priv->name_change_callback_id =
|
||||
gnc_option_db_register_change_callback(priv->odb,
|
||||
gnc_plugin_page_acct_tree_view_refresh,
|
||||
priv,
|
||||
N_("Account Tree"),
|
||||
N_("Name of account view"));
|
||||
scm_gc_protect_object(priv->name_change_callback_id);
|
||||
|
||||
LEAVE("page %p, priv %p, action group %p",
|
||||
plugin_page, priv, action_group);
|
||||
}
|
||||
@@ -539,6 +540,240 @@ gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page)
|
||||
LEAVE("widget destroyed");
|
||||
}
|
||||
|
||||
#define ACCT_COUNT "Number of Open Accounts"
|
||||
#define ACCT_OPEN "Open Account %d"
|
||||
#define ACCT_SELECTED "Selected Account"
|
||||
|
||||
typedef struct foo {
|
||||
GKeyFile *key_file;
|
||||
const gchar *group_name;
|
||||
int count;
|
||||
} bar_t;
|
||||
|
||||
|
||||
/** Save information about an expanded row. This function is called
|
||||
* via a gtk_tree_view_map_expanded_rows, which calls it once per
|
||||
* expanded row. Its job is to write the full account name of the
|
||||
* row out to the state file.
|
||||
*
|
||||
* @param tree_view A pointer to the GtkTreeView embedded in an
|
||||
* account tree page.
|
||||
*
|
||||
* @param path A pointer to a particular entry in the tree.
|
||||
*
|
||||
* @param data A pointer to a data structure holding the information
|
||||
* related to the state file. */
|
||||
static void
|
||||
tree_save_expanded_row (GtkTreeView *tree_view,
|
||||
GtkTreePath *path,
|
||||
gpointer user_data)
|
||||
{
|
||||
Account *account;
|
||||
bar_t *bar = user_data;
|
||||
gchar *key;
|
||||
gchar *account_name;
|
||||
|
||||
account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT(tree_view), path);
|
||||
if (account == NULL)
|
||||
return;
|
||||
|
||||
account_name = xaccAccountGetFullName (account, gnc_get_account_separator ());
|
||||
if (account_name == NULL)
|
||||
return;
|
||||
|
||||
key = g_strdup_printf(ACCT_OPEN, ++bar->count);
|
||||
g_key_file_set_string(bar->key_file, bar->group_name, key, account_name);
|
||||
g_free(key);
|
||||
g_free(account_name);
|
||||
}
|
||||
|
||||
|
||||
/** Save information about the selected row. Its job is to write the
|
||||
* full account name of the row out to the state file.
|
||||
*
|
||||
* @param tree_view A pointer to the GtkTreeView embedded in an
|
||||
* account tree page.
|
||||
*
|
||||
* @param path A pointer to a particular entry in the tree.
|
||||
*
|
||||
* @param data A pointer to a data structure holding the information
|
||||
* related to the state file. */
|
||||
static void
|
||||
tree_save_selected_row (GncTreeViewAccount *view,
|
||||
gpointer user_data)
|
||||
{
|
||||
Account *account;
|
||||
bar_t *bar = user_data;
|
||||
gchar *account_name;
|
||||
|
||||
account = gnc_tree_view_account_get_selected_account(view);
|
||||
if (account == NULL)
|
||||
return;
|
||||
|
||||
account_name = xaccAccountGetFullName (account, gnc_get_account_separator ());
|
||||
if (account_name == NULL)
|
||||
return;
|
||||
|
||||
g_key_file_set_string(bar->key_file, bar->group_name, ACCT_SELECTED, account_name);
|
||||
g_free(account_name);
|
||||
}
|
||||
|
||||
|
||||
/** Save enough information about this account tree page that it can
|
||||
* be recreated next time the user starts gnucash.
|
||||
*
|
||||
* @param page The page to save.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be written.
|
||||
*
|
||||
* @param group_name The group name to use when saving data. */
|
||||
static void
|
||||
gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name)
|
||||
{
|
||||
GncPluginPageAccountTree *account_page;
|
||||
GncPluginPageAccountTreePrivate *priv;
|
||||
bar_t bar;
|
||||
|
||||
g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page));
|
||||
g_return_if_fail (key_file != NULL);
|
||||
g_return_if_fail (group_name != NULL);
|
||||
|
||||
ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
|
||||
group_name);
|
||||
|
||||
account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page);
|
||||
priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
|
||||
|
||||
bar.key_file = key_file;
|
||||
bar.group_name = group_name;
|
||||
bar.count = 0;
|
||||
tree_save_selected_row(GNC_TREE_VIEW_ACCOUNT(priv->tree_view), &bar);
|
||||
gtk_tree_view_map_expanded_rows(priv->tree_view,
|
||||
tree_save_expanded_row, &bar);
|
||||
g_key_file_set_integer(key_file, group_name, ACCT_COUNT, bar.count);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
|
||||
/** Expand a row in the tree that was expanded when the user last quit
|
||||
* gnucash. Its job is to map from account name to tree row and
|
||||
* expand the row.
|
||||
*
|
||||
* @param tree_view A pointer to the GtkTreeView embedded in an
|
||||
* account tree page.
|
||||
*
|
||||
* @param account_name A pointer to the full account name. */
|
||||
static void
|
||||
tree_restore_expanded_row (GtkTreeView *tree_view,
|
||||
const gchar *account_name)
|
||||
{
|
||||
Account *account;
|
||||
QofBook *book;
|
||||
|
||||
book = qof_session_get_book(qof_session_get_current_session());
|
||||
account = xaccGetAccountFromFullName(xaccGetAccountGroup(book),
|
||||
account_name,
|
||||
gnc_get_account_separator());
|
||||
if (account)
|
||||
gnc_tree_view_account_expand_to_account(GNC_TREE_VIEW_ACCOUNT(tree_view),
|
||||
account);
|
||||
}
|
||||
|
||||
|
||||
/** Select the row in the tree that was selected when the user last
|
||||
* quit gnucash. Its job is to map from account name to tree row and
|
||||
* select the row.
|
||||
*
|
||||
* @param tree_view A pointer to the GtkTreeView embedded in an
|
||||
* account tree page.
|
||||
*
|
||||
* @param account_name A pointer to the full account name. */
|
||||
static void
|
||||
tree_restore_selected_row (GtkTreeView *tree_view,
|
||||
const gchar *account_name)
|
||||
{
|
||||
Account *account;
|
||||
QofBook *book;
|
||||
|
||||
book = qof_session_get_book(qof_session_get_current_session());
|
||||
account = xaccGetAccountFromFullName(xaccGetAccountGroup(book),
|
||||
account_name,
|
||||
gnc_get_account_separator());
|
||||
if (account)
|
||||
gnc_tree_view_account_set_selected_account(GNC_TREE_VIEW_ACCOUNT(tree_view),
|
||||
account);
|
||||
}
|
||||
|
||||
|
||||
/** Create a new account tree page based on the information saved
|
||||
* during a previous instantiation of gnucash.
|
||||
*
|
||||
* @param window The window where this page should be installed.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be read.
|
||||
*
|
||||
* @param group_name The group name to use when restoring data. */
|
||||
static GncPluginPage *
|
||||
gnc_plugin_page_account_tree_recreate_page (GtkWidget *window,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name)
|
||||
{
|
||||
GncPluginPageAccountTree *account_page;
|
||||
GncPluginPageAccountTreePrivate *priv;
|
||||
GncPluginPage *page;
|
||||
GError *error = NULL;
|
||||
gchar *key, *value;
|
||||
gint i, count;
|
||||
|
||||
g_return_val_if_fail(key_file, NULL);
|
||||
g_return_val_if_fail(group_name, NULL);
|
||||
ENTER("key_file %p, group_name %s", key_file, group_name);
|
||||
|
||||
/* Create the new page. */
|
||||
page = gnc_plugin_page_account_tree_new();
|
||||
account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(page);
|
||||
priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
|
||||
|
||||
/* Install it now so we can them manipulate the created widget */
|
||||
gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);
|
||||
|
||||
/* Expanded accounts */
|
||||
count = g_key_file_get_integer(key_file, group_name, ACCT_COUNT, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
group_name, ACCT_COUNT, error->message);
|
||||
g_error_free(error);
|
||||
LEAVE("bad value");
|
||||
return page;
|
||||
}
|
||||
for (i = 1; i <= count; i++) {
|
||||
key = g_strdup_printf(ACCT_OPEN, i);
|
||||
value = g_key_file_get_string(key_file, group_name, key, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
group_name, key, error->message);
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
} else {
|
||||
tree_restore_expanded_row(priv->tree_view, value);
|
||||
g_free(value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Selected account (if any) */
|
||||
value = g_key_file_get_string(key_file, group_name, ACCT_SELECTED, NULL);
|
||||
if (value) {
|
||||
tree_restore_selected_row(priv->tree_view, value);
|
||||
g_free(value);
|
||||
}
|
||||
LEAVE(" ");
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
@@ -959,3 +1194,6 @@ gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAcco
|
||||
xaccGroupScrubOrphans (group);
|
||||
xaccGroupScrubImbalance (group);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
@@ -50,7 +50,7 @@ G_BEGIN_DECLS
|
||||
#define GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE))
|
||||
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTreeClass))
|
||||
|
||||
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME "gnc-plugin-page-account-tree"
|
||||
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME "GncPluginPageAccountTree"
|
||||
|
||||
/* typedefs & structures */
|
||||
typedef struct {
|
||||
|
||||
@@ -45,7 +45,7 @@ G_BEGIN_DECLS
|
||||
#define GNC_IS_PLUGIN_PAGE_BUDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_BUDGET))
|
||||
#define GNC_PLUGIN_PAGE_BUDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_BUDGET, GncPluginPageBudgetClass))
|
||||
|
||||
#define GNC_PLUGIN_PAGE_BUDGET_NAME "gnc-plugin-page-budget"
|
||||
#define GNC_PLUGIN_PAGE_BUDGET_NAME "GncPluginPageBudget"
|
||||
|
||||
/* typedefs & structures */
|
||||
typedef struct {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* gnc-plugin-page-register.c --
|
||||
*
|
||||
* Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
* Copyright (C) 2003 David Hampton <hampton@employees.org>
|
||||
* 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
|
||||
@@ -22,9 +22,22 @@
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org
|
||||
*/
|
||||
|
||||
/** @addtogroup ContentPlugins
|
||||
@{ */
|
||||
/** @addtogroup RegisterPlugin Register Page
|
||||
@{ */
|
||||
/** @file gnc-plugin-page-register.c
|
||||
@brief Functions for creating a register page for the GnuCash UI
|
||||
@author Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
@author Copyright (C) 2003,2005 David Hampton <hampton@employees.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#ifndef HAVE_GLIB26
|
||||
#include "gkeyfile.h"
|
||||
#endif
|
||||
#include <g-wrap-wct.h>
|
||||
|
||||
#include "gnc-plugin-page-register.h"
|
||||
@@ -75,6 +88,8 @@ static void gnc_plugin_page_register_finalize (GObject *object);
|
||||
static GtkWidget *gnc_plugin_page_register_create_widget (GncPluginPage *plugin_page);
|
||||
static void gnc_plugin_page_register_destroy_widget (GncPluginPage *plugin_page);
|
||||
static void gnc_plugin_page_register_window_changed (GncPluginPage *plugin_page, GtkWidget *window);
|
||||
static void gnc_plugin_page_register_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
|
||||
static GncPluginPage *gnc_plugin_page_register_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
|
||||
|
||||
static gchar *gnc_plugin_page_register_get_tab_name (GncPluginPage *plugin_page);
|
||||
|
||||
@@ -276,10 +291,11 @@ static action_short_labels short_labels[] = {
|
||||
};
|
||||
|
||||
|
||||
struct {
|
||||
struct status_action {
|
||||
const char *action_name;
|
||||
int value;
|
||||
} status_actions[] = {
|
||||
};
|
||||
static struct status_action status_actions[] = {
|
||||
{ "filter_status_reconciled", CLEARED_RECONCILED },
|
||||
{ "filter_status_cleared", CLEARED_CLEARED },
|
||||
{ "filter_status_voided", CLEARED_VOIDED },
|
||||
@@ -445,6 +461,8 @@ gnc_plugin_page_register_class_init (GncPluginPageRegisterClass *klass)
|
||||
gnc_plugin_class->create_widget = gnc_plugin_page_register_create_widget;
|
||||
gnc_plugin_class->destroy_widget = gnc_plugin_page_register_destroy_widget;
|
||||
gnc_plugin_class->window_changed = gnc_plugin_page_register_window_changed;
|
||||
gnc_plugin_class->save_page = gnc_plugin_page_register_save_page;
|
||||
gnc_plugin_class->recreate_page = gnc_plugin_page_register_recreate_page;
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GncPluginPageRegisterPrivate));
|
||||
}
|
||||
@@ -533,9 +551,9 @@ gnc_plugin_page_register_update_menus (GncPluginPageRegister *page)
|
||||
{
|
||||
GncPluginPageRegisterPrivate *priv ;
|
||||
GtkActionGroup *action_group;
|
||||
GtkAction *action;
|
||||
Account *account;
|
||||
SplitRegister *sr;
|
||||
GtkAction *action;
|
||||
int i;
|
||||
|
||||
priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
|
||||
@@ -683,6 +701,214 @@ gnc_plugin_page_register_window_changed (GncPluginPage *plugin_page,
|
||||
priv->gsr->window =
|
||||
GTK_WIDGET(gnc_window_get_gtk_window(GNC_WINDOW(window)));
|
||||
}
|
||||
|
||||
static const gchar *style_names[] = {
|
||||
"Ledger",
|
||||
"Auto Ledger",
|
||||
"Journal",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define KEY_REGISTER_TYPE "Register Type"
|
||||
#define KEY_ACCOUNT_NAME "Account Name"
|
||||
#define KEY_REGISTER_STYLE "Register Style"
|
||||
#define KEY_DOUBLE_LINE "Double Line Mode"
|
||||
|
||||
#define LABEL_ACCOUNT "Account"
|
||||
#define LABEL_SUBACCOUNT "SubAccount"
|
||||
#define LABEL_GL "GL"
|
||||
#define LABEL_SEARCH "Search"
|
||||
|
||||
|
||||
/** Save enough information about this register page that it can be
|
||||
* recreated next time the user starts gnucash.
|
||||
*
|
||||
* @param page The page to save.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be written.
|
||||
*
|
||||
* @param group_name The group name to use when saving data. */
|
||||
static void
|
||||
gnc_plugin_page_register_save_page (GncPluginPage *plugin_page,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name)
|
||||
{
|
||||
GncPluginPageRegister *page;
|
||||
GncPluginPageRegisterPrivate *priv;
|
||||
GNCLedgerDisplayType ledger_type;
|
||||
SplitRegister *reg;
|
||||
Account *leader;
|
||||
|
||||
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page));
|
||||
g_return_if_fail (key_file != NULL);
|
||||
g_return_if_fail (group_name != NULL);
|
||||
|
||||
ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
|
||||
group_name);
|
||||
|
||||
page = GNC_PLUGIN_PAGE_REGISTER(plugin_page);
|
||||
priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
|
||||
|
||||
reg = gnc_ledger_display_get_split_register(priv->ledger);
|
||||
ledger_type = gnc_ledger_display_type(priv->ledger);
|
||||
if (ledger_type > LD_GL) {
|
||||
LEAVE("Unsupported ledger type");
|
||||
return;
|
||||
}
|
||||
if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT)) {
|
||||
const gchar *label;
|
||||
label = (ledger_type == LD_SINGLE) ? LABEL_ACCOUNT : LABEL_SUBACCOUNT;
|
||||
leader = gnc_ledger_display_leader(priv->ledger);
|
||||
g_key_file_set_string(key_file, group_name, KEY_REGISTER_TYPE, label);
|
||||
g_key_file_set_string(key_file, group_name, KEY_ACCOUNT_NAME,
|
||||
xaccAccountGetFullName(leader,
|
||||
gnc_get_account_separator()));
|
||||
} else if (reg->type == GENERAL_LEDGER) {
|
||||
g_key_file_set_string(key_file, group_name, KEY_REGISTER_TYPE,
|
||||
LABEL_GL);
|
||||
} else if (reg->type == SEARCH_LEDGER) {
|
||||
g_key_file_set_string(key_file, group_name, KEY_REGISTER_TYPE,
|
||||
LABEL_SEARCH);
|
||||
} else {
|
||||
LEAVE("Unsupported register type");
|
||||
return;
|
||||
}
|
||||
|
||||
g_key_file_set_string(key_file, group_name, KEY_REGISTER_STYLE,
|
||||
style_names[reg->style]);
|
||||
g_key_file_set_boolean(key_file, group_name, KEY_DOUBLE_LINE,
|
||||
reg->use_double_line);
|
||||
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
|
||||
/** Read and restore the edit menu settings on the specified register
|
||||
* page. This function will restore the register style (ledger, auto
|
||||
* ledger, journal) and whether or not the register is in double line
|
||||
* mode. It should eventually restore the "filter by" and "sort by
|
||||
* settings.
|
||||
*
|
||||
* @param page The register being restored.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be read.
|
||||
*
|
||||
* @param group_name The group name to use when restoring data. */
|
||||
static void
|
||||
gnc_plugin_page_register_restore_edit_menu (GncPluginPage *page,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name)
|
||||
{
|
||||
GncPluginPageRegisterPrivate *priv;
|
||||
GtkActionGroup *action_group;
|
||||
GtkAction *action;
|
||||
GError *error = NULL;
|
||||
gchar *style_name;
|
||||
gint i;
|
||||
gboolean use_double_line;
|
||||
|
||||
ENTER(" ");
|
||||
priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
|
||||
action_group = gnc_plugin_page_get_action_group(page);
|
||||
|
||||
/* Convert the style name to an index */
|
||||
style_name = g_key_file_get_string(key_file, group_name,
|
||||
KEY_REGISTER_STYLE, &error);
|
||||
for (i = 0 ; style_names[i]; i++) {
|
||||
if (g_ascii_strcasecmp(style_name, style_names[i]) == 0) {
|
||||
DEBUG("Found match for style name: %s", style_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free(style_name);
|
||||
|
||||
/* Update the style menu action for this page */
|
||||
if (i <= REG_STYLE_JOURNAL) {
|
||||
DEBUG("Setting style: %d", i);
|
||||
action_group =
|
||||
gnc_plugin_page_get_action_group(page);
|
||||
action= gtk_action_group_get_action(action_group, radio_entries_2[i].name);
|
||||
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
|
||||
}
|
||||
|
||||
/* Update the double line action on this page */
|
||||
use_double_line =
|
||||
g_key_file_get_boolean(key_file, group_name, KEY_DOUBLE_LINE, &error);
|
||||
DEBUG("Setting double_line_mode: %d", use_double_line);
|
||||
action = gtk_action_group_get_action(action_group,
|
||||
"ViewStyleDoubleLineAction");
|
||||
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), use_double_line);
|
||||
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
|
||||
/** Create a new register page based on the information saved during a
|
||||
* previous instantiation of gnucash.
|
||||
*
|
||||
* @param window The window where this page should be installed.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be read.
|
||||
*
|
||||
* @param group_name The group name to use when restoring data. */
|
||||
static GncPluginPage *
|
||||
gnc_plugin_page_register_recreate_page (GtkWidget *window,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name)
|
||||
{
|
||||
GncPluginPage *page;
|
||||
GError *error = NULL;
|
||||
gchar *reg_type, *acct_name;
|
||||
Account *account;
|
||||
QofBook *book;
|
||||
gboolean include_subs;
|
||||
|
||||
g_return_val_if_fail(key_file, NULL);
|
||||
g_return_val_if_fail(group_name, NULL);
|
||||
ENTER("key_file %p, group_name %s", key_file, group_name);
|
||||
|
||||
/* Create the new page. */
|
||||
reg_type = g_key_file_get_string(key_file, group_name,
|
||||
KEY_REGISTER_TYPE, &error);
|
||||
DEBUG("Page type: %s", reg_type);
|
||||
if ((g_ascii_strcasecmp(reg_type, LABEL_ACCOUNT) == 0) ||
|
||||
(g_ascii_strcasecmp(reg_type, LABEL_SUBACCOUNT) == 0)) {
|
||||
include_subs = (g_ascii_strcasecmp(reg_type, LABEL_SUBACCOUNT) == 0);
|
||||
DEBUG("Include subs: %d", include_subs);
|
||||
acct_name = g_key_file_get_string(key_file, group_name,
|
||||
KEY_ACCOUNT_NAME, &error);
|
||||
book = qof_session_get_book(qof_session_get_current_session());
|
||||
account = xaccGetAccountFromFullName(xaccGetAccountGroup(book),
|
||||
acct_name,
|
||||
gnc_get_account_separator());
|
||||
g_free(acct_name);
|
||||
if (account == NULL) {
|
||||
LEAVE("Bad account name");
|
||||
g_free(reg_type);
|
||||
return NULL;
|
||||
}
|
||||
page = gnc_plugin_page_register_new (account, include_subs);
|
||||
} else if (g_ascii_strcasecmp(reg_type, LABEL_GL) == 0) {
|
||||
page = gnc_plugin_page_register_new_gl();
|
||||
} else {
|
||||
LEAVE("Bad ledger type");
|
||||
g_free(reg_type);
|
||||
return NULL;
|
||||
}
|
||||
g_free(reg_type);
|
||||
|
||||
/* Install it now so we can them manipulate the created widget */
|
||||
gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);
|
||||
|
||||
/* Now update the page to the last state it was in */
|
||||
gnc_plugin_page_register_restore_edit_menu(page, key_file, group_name);
|
||||
LEAVE(" ");
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
static gchar *
|
||||
gnc_plugin_page_register_get_tab_name (GncPluginPage *plugin_page)
|
||||
@@ -2370,3 +2596,6 @@ gnc_plugin_page_register_refresh_cb (GHashTable *changes, gpointer user_data)
|
||||
gnucash_register_refresh_from_gconf(priv->gsr->reg);
|
||||
gtk_widget_queue_draw(priv->widget);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
@@ -128,6 +128,10 @@ gnc_plugin_register_new (void)
|
||||
{
|
||||
GncPluginRegister *plugin;
|
||||
|
||||
/* Reference the register page plugin to ensure it exists in
|
||||
* the gtk type system. */
|
||||
GNC_TYPE_PLUGIN_PAGE_REGISTER;
|
||||
|
||||
plugin = g_object_new (GNC_TYPE_PLUGIN_REGISTER,
|
||||
NULL);
|
||||
|
||||
|
||||
@@ -130,14 +130,6 @@
|
||||
'()
|
||||
"Destroy the UI.")
|
||||
|
||||
(gw:wrap-function
|
||||
ws
|
||||
'gnc:new-account-tree
|
||||
'<gw:void>
|
||||
"gnc_new_account_tree"
|
||||
'((<gnc:MainWindow*> window))
|
||||
"Create a new account tree window.")
|
||||
|
||||
(gw:wrap-as-wct ws
|
||||
'<gnc:ProgressDialog*>
|
||||
"GNCProgressDialog *" "const GNCProgressDialog *")
|
||||
|
||||
@@ -14,6 +14,7 @@ AM_CFLAGS = \
|
||||
-I${top_srcdir}/src/gnome-utils \
|
||||
-I${top_srcdir}/src/gnome \
|
||||
-I${top_srcdir}/src/report/report-system \
|
||||
-I${top_srcdir}/lib/glib26 \
|
||||
${GLADE_CFLAGS} \
|
||||
${GUILE_INCS} \
|
||||
${GTKHTML_CFLAGS} \
|
||||
@@ -42,6 +43,7 @@ libgncmod_report_gnome_la_LIBADD = \
|
||||
${top_builddir}/src/gnc-module/libgncmodule.la \
|
||||
${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
|
||||
${top_builddir}/src/report/report-system/libgncmod-report-system.la \
|
||||
${top_builddir}/lib/glib26/libgncglib.la \
|
||||
${GLADE_LIBS} \
|
||||
${GUILE_LIBS} \
|
||||
${GNOME_PRINT_LIBS} \
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* gnc-plugin-page-report.c
|
||||
* Copyright (C) 2004 Joshua Sled <jsled@asynchronous.org>
|
||||
* Copyright (C) 2005 David Hampton <hampton@employees.org>
|
||||
*
|
||||
* Originally from window-report.c:
|
||||
* Copyright (C) 1997 Robin D. Clark
|
||||
@@ -26,10 +27,23 @@
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org
|
||||
*/
|
||||
|
||||
/** @addtogroup GUI
|
||||
@{ */
|
||||
/** @addtogroup GuiReport Reports
|
||||
@{ */
|
||||
/** @file gnc-plugin-page-report.c
|
||||
@brief Report page.
|
||||
@author Copyright (C) 2004 Joshua Sled <jsled@asynchronous.org>
|
||||
@author Copyright (C) 2005 David Hampton <hampton@employees.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <gtk/gtk.h>
|
||||
#ifndef HAVE_GLIB26
|
||||
#include "gkeyfile.h"
|
||||
#endif
|
||||
#include <g-wrap-wct.h>
|
||||
#include <libguile.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -47,6 +61,7 @@
|
||||
#include "gnc-ui-util.h"
|
||||
#include "gnc-ui.h"
|
||||
#include "gnc-window.h"
|
||||
#include "guile-util.h"
|
||||
#include "messages.h"
|
||||
#include "option-util.h"
|
||||
|
||||
@@ -111,6 +126,9 @@ static void gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page,
|
||||
|
||||
static GtkWidget* gnc_plugin_page_report_create_widget( GncPluginPage *plugin_page );
|
||||
static void gnc_plugin_page_report_destroy_widget( GncPluginPage *plugin_page );
|
||||
static void gnc_plugin_page_report_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
|
||||
static GncPluginPage *gnc_plugin_page_report_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
|
||||
static void gnc_plugin_page_report_name_changed (GncPluginPage *page, const gchar *name);
|
||||
|
||||
static int gnc_plugin_page_report_check_urltype(URLType t);
|
||||
static void gnc_plugin_page_report_load_cb(gnc_html * html, URLType type,
|
||||
@@ -233,6 +251,9 @@ gnc_plugin_page_report_class_init (GncPluginPageReportClass *klass)
|
||||
|
||||
gnc_plugin_page_class->create_widget = gnc_plugin_page_report_create_widget;
|
||||
gnc_plugin_page_class->destroy_widget = gnc_plugin_page_report_destroy_widget;
|
||||
gnc_plugin_page_class->save_page = gnc_plugin_page_report_save_page;
|
||||
gnc_plugin_page_class->recreate_page = gnc_plugin_page_report_recreate_page;
|
||||
gnc_plugin_page_class->page_name_changed = gnc_plugin_page_report_name_changed;
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GncPluginPageReportPrivate));
|
||||
|
||||
@@ -474,7 +495,7 @@ gnc_plugin_page_report_load_cb(gnc_html * html, URLType type,
|
||||
priv->option_change_cb_id =
|
||||
gnc_option_db_register_change_callback(priv->cur_odb,
|
||||
gnc_plugin_page_report_option_change_cb,
|
||||
priv, NULL, NULL);
|
||||
report, NULL, NULL);
|
||||
|
||||
if (gnc_html_history_forward_p(gnc_html_get_history(priv->html))) {
|
||||
gnc_plugin_page_report_set_fwd_button(report, TRUE);
|
||||
@@ -491,17 +512,45 @@ gnc_plugin_page_report_load_cb(gnc_html * html, URLType type,
|
||||
LEAVE( "done" );
|
||||
}
|
||||
|
||||
|
||||
/** This function is called when one of the options for a register
|
||||
* page has changed. It is responsible for marking the report as
|
||||
* dirty, and causing the report to reload using the new options.
|
||||
*
|
||||
* @note This function currently also calls the main window code to
|
||||
* update it if the name of the report has changed. This code should
|
||||
* eventually go away, and the only way to change the name should be
|
||||
* via the main window. gnucash.
|
||||
*
|
||||
* @param data A pointer to the GncPluginPageReport data structure
|
||||
* that describes a report. */
|
||||
static void
|
||||
gnc_plugin_page_report_option_change_cb(gpointer data)
|
||||
{
|
||||
GncPluginPageReportPrivate *priv = data;
|
||||
GncPluginPageReport *report;
|
||||
GncPluginPageReportPrivate *priv;
|
||||
SCM dirty_report = scm_c_eval_string("gnc:report-set-dirty?!");
|
||||
const gchar *old_name;
|
||||
gchar *new_name;
|
||||
|
||||
g_return_if_fail(GNC_IS_PLUGIN_PAGE_REPORT(data));
|
||||
report = GNC_PLUGIN_PAGE_REPORT(data);
|
||||
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report);
|
||||
|
||||
DEBUG( "option_change" );
|
||||
if (priv->cur_report == SCM_BOOL_F)
|
||||
return;
|
||||
DEBUG( "set-dirty, queue-draw" );
|
||||
|
||||
/* Update the page (i.e. the notebook tab and window title) */
|
||||
old_name = gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(report));
|
||||
new_name = gnc_option_db_lookup_string_option(priv->cur_odb, "General",
|
||||
"Report name", NULL);
|
||||
if (strcmp(old_name, new_name) != 0) {
|
||||
gnc_plugin_page_set_page_name(GNC_PLUGIN_PAGE(report), new_name);
|
||||
}
|
||||
g_free(new_name);
|
||||
|
||||
/* it's probably already dirty, but make sure */
|
||||
scm_call_2(dirty_report, priv->cur_report, SCM_BOOL_T);
|
||||
|
||||
@@ -590,6 +639,144 @@ gnc_plugin_page_report_destroy_widget(GncPluginPage *plugin_page)
|
||||
scm_call_1(remover, scm_int2num(report_id));
|
||||
}
|
||||
|
||||
|
||||
/** The key name used it the state file for storing the report
|
||||
* options. */
|
||||
#define SCHEME_OPTIONS "Scheme Options"
|
||||
|
||||
|
||||
/** Save enough information about this report page that it can be
|
||||
* recreated next time the user starts gnucash.
|
||||
*
|
||||
* @param page The page to save.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be written.
|
||||
*
|
||||
* @param group_name The group name to use when saving data. */
|
||||
static void
|
||||
gnc_plugin_page_report_save_page (GncPluginPage *plugin_page,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name)
|
||||
{
|
||||
GncPluginPageReport *report;
|
||||
GncPluginPageReportPrivate *priv;
|
||||
SCM gen_save_text, scm_text;
|
||||
gchar *text;
|
||||
|
||||
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REPORT(plugin_page));
|
||||
g_return_if_fail (key_file != NULL);
|
||||
g_return_if_fail (group_name != NULL);
|
||||
|
||||
ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
|
||||
group_name);
|
||||
|
||||
report = GNC_PLUGIN_PAGE_REPORT(plugin_page);
|
||||
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report);
|
||||
|
||||
gen_save_text = scm_c_eval_string("gnc:report-generate-restore-forms");
|
||||
scm_text = scm_call_1(gen_save_text, priv->cur_report);
|
||||
|
||||
if (!SCM_STRINGP (scm_text)) {
|
||||
LEAVE("nothing to save");
|
||||
return;
|
||||
}
|
||||
|
||||
text = gnc_guile_strip_comments(SCM_STRING_CHARS(scm_text));
|
||||
g_key_file_set_string(key_file, group_name, SCHEME_OPTIONS, text);
|
||||
g_free(text);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
|
||||
/** Create a new report page based on the information saved during a
|
||||
* previous instantiation of gnucash.
|
||||
*
|
||||
* @param window The window where this page should be installed.
|
||||
*
|
||||
* @param key_file A pointer to the GKeyFile data structure where the
|
||||
* page information should be read.
|
||||
*
|
||||
* @param group_name The group name to use when restoring data. */
|
||||
static GncPluginPage *
|
||||
gnc_plugin_page_report_recreate_page (GtkWidget *window,
|
||||
GKeyFile *key_file,
|
||||
const gchar *group_name)
|
||||
{
|
||||
GncPluginPage *page;
|
||||
GError *error = NULL;
|
||||
gchar *option_string;
|
||||
gint report_id;
|
||||
SCM scm_id;
|
||||
|
||||
g_return_val_if_fail(key_file, NULL);
|
||||
g_return_val_if_fail(group_name, NULL);
|
||||
ENTER("key_file %p, group_name %s", key_file, group_name);
|
||||
|
||||
option_string = g_key_file_get_string(key_file, group_name,
|
||||
SCHEME_OPTIONS, &error);
|
||||
if (error) {
|
||||
g_warning("error reading group %s key %s: %s",
|
||||
group_name, SCHEME_OPTIONS, error->message);
|
||||
LEAVE("bad value");
|
||||
return NULL;
|
||||
}
|
||||
scm_id = scm_c_eval_string(option_string);
|
||||
if (!scm_integer_p(scm_id)) {
|
||||
g_free(option_string);
|
||||
LEAVE("report id not an integer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
report_id = scm_num2int(scm_id, SCM_ARG1, __FUNCTION__);
|
||||
page = gnc_plugin_page_report_new( report_id );
|
||||
|
||||
g_free(option_string);
|
||||
LEAVE(" ");
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
/** Update a report page to reflect a name change made by external
|
||||
* code. This is called from the main window code when a page's name
|
||||
* is changes. The report code will update its copy of the name and
|
||||
* regenerate the report.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param page The page whose name has changed.
|
||||
*
|
||||
* @param name The new name for the page. */
|
||||
static void
|
||||
gnc_plugin_page_report_name_changed (GncPluginPage *page, const gchar *name)
|
||||
{
|
||||
GncPluginPageReportPrivate *priv;
|
||||
static gint count = 1, max_count = 10;
|
||||
const gchar *old_name;
|
||||
|
||||
g_return_if_fail(GNC_IS_PLUGIN_PAGE_REPORT(page));
|
||||
g_return_if_fail(name != NULL);
|
||||
g_return_if_fail(count++ <= max_count);
|
||||
|
||||
ENTER("page %p, name %s", page, name);
|
||||
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(page);
|
||||
|
||||
/* Is this a redundant call? */
|
||||
old_name = gnc_option_db_lookup_string_option(priv->cur_odb, "General",
|
||||
"Report name", NULL);
|
||||
DEBUG("Comparing old name '%s' to new name '%s'", old_name, name);
|
||||
if (old_name && (strcmp(old_name, name) == 0)) {
|
||||
LEAVE("no change");
|
||||
return;
|
||||
}
|
||||
|
||||
gnc_option_db_set_string_option(priv->cur_odb, "General",
|
||||
"Report name", name);
|
||||
gnc_plugin_page_report_option_change_cb(page);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_report_window_destroy
|
||||
* free and destroy a window
|
||||
@@ -696,8 +883,8 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
|
||||
GncPluginPageReportPrivate *priv;
|
||||
GtkActionGroup *action_group;
|
||||
GncPluginPage *parent;
|
||||
GString *tmpStr;
|
||||
gboolean use_new;
|
||||
gchar *name;
|
||||
|
||||
DEBUG( "property reportId=%d", reportId );
|
||||
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(plugin_page);
|
||||
@@ -708,15 +895,14 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
|
||||
/* Init parent declared variables */
|
||||
parent = GNC_PLUGIN_PAGE(plugin_page);
|
||||
use_new = gnc_gconf_get_bool(GCONF_GENERAL_REPORT, KEY_USE_NEW, NULL);
|
||||
tmpStr = g_string_sized_new( 32 );
|
||||
g_string_sprintf( tmpStr, "%s: %s", _("Report"),
|
||||
gnc_report_name( priv->initial_report ) );
|
||||
name = gnc_report_name( priv->initial_report );
|
||||
g_object_set(G_OBJECT(plugin_page),
|
||||
"page-name", tmpStr->str,
|
||||
"page-name", name,
|
||||
"page-uri", "default:",
|
||||
"ui-description", "gnc-plugin-page-report-ui.xml",
|
||||
"use-new-window", use_new,
|
||||
NULL);
|
||||
g_free(name);
|
||||
|
||||
/* change me when the system supports multiple books */
|
||||
gnc_plugin_page_add_book(parent, gnc_get_current_book());
|
||||
@@ -1125,3 +1311,6 @@ gnc_main_window_open_report_url(const char * url, GncMainWindow *window)
|
||||
reportPage = gnc_plugin_page_report_new( 42 /* url? */ );
|
||||
gnc_main_window_open_page( window, reportPage );
|
||||
}
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
@@ -47,7 +47,7 @@ G_BEGIN_DECLS
|
||||
#define GNC_IS_PLUGIN_PAGE_REPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_REPORT))
|
||||
#define GNC_PLUGIN_PAGE_REPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_REPORT, GncPluginPageReportClass))
|
||||
|
||||
#define GNC_PLUGIN_PAGE_REPORT_NAME "gnc-plugin-page-report"
|
||||
#define GNC_PLUGIN_PAGE_REPORT_NAME "GncPluginPageReport"
|
||||
|
||||
/* typedefs & structures */
|
||||
typedef struct {
|
||||
|
||||
@@ -293,6 +293,10 @@ gnc_html_help_url_cb (const char *location, const char *label,
|
||||
void
|
||||
gnc_report_init (void)
|
||||
{
|
||||
/* Reference the report page plugin to ensure it exists in the gtk
|
||||
* type system. */
|
||||
GNC_TYPE_PLUGIN_PAGE_REPORT;
|
||||
|
||||
gnc_html_register_stream_handler (URL_TYPE_HELP, gnc_html_file_stream_cb);
|
||||
gnc_html_register_stream_handler (URL_TYPE_FILE, gnc_html_file_stream_cb);
|
||||
gnc_html_register_stream_handler (URL_TYPE_REPORT, gnc_html_report_stream_cb);
|
||||
|
||||
@@ -39,12 +39,6 @@
|
||||
(lambda (opt)
|
||||
(gnc:register-option options opt))))
|
||||
|
||||
(add-option
|
||||
(gnc:make-string-option
|
||||
(N_ "Account Tree") (N_ "Name of account view")
|
||||
"a" (N_ "If you keep multiple account views open, it may be helpful \
|
||||
to give each one a descriptive name") (_ "Accounts")))
|
||||
|
||||
(add-option
|
||||
(gnc:make-simple-boolean-option
|
||||
(N_ "Account Tree") (N_ "Double click expands parent accounts")
|
||||
@@ -138,8 +132,6 @@ the account instead of opening a register.") #f))
|
||||
))))
|
||||
|
||||
(define (gnc:main-window-book-close-handler session)
|
||||
(gnc:main-window-save-state session)
|
||||
|
||||
(let ((dead-reports '()))
|
||||
;; get a list of the reports we'll be needing to nuke
|
||||
(hash-fold
|
||||
@@ -169,7 +161,6 @@ the account instead of opening a register.") #f))
|
||||
(dead-reports '()))
|
||||
(if conf-file-name
|
||||
(try-load conf-file-name))
|
||||
(gnc:new-account-tree #f)
|
||||
|
||||
;; the reports have only been created at this point; create their ui component.
|
||||
(hash-fold (lambda (key val prior-result)
|
||||
@@ -190,11 +181,6 @@ the account instead of opening a register.") #f))
|
||||
slots (_ "Book Options")
|
||||
changed_cb)))
|
||||
|
||||
(gnc:hook-remove-dangler gnc:*book-opened-hook*
|
||||
gnc:main-window-book-open-handler)
|
||||
(gnc:hook-add-dangler gnc:*book-opened-hook*
|
||||
gnc:main-window-book-open-handler)
|
||||
|
||||
(gnc:hook-remove-dangler gnc:*book-closed-hook*
|
||||
gnc:main-window-book-close-handler)
|
||||
(gnc:hook-add-dangler gnc:*book-closed-hook*
|
||||
|
||||
Reference in New Issue
Block a user