Merge branch 'maint'

This commit is contained in:
Christopher Lam 2020-02-15 23:13:40 +08:00
commit efed709414
19 changed files with 412 additions and 381 deletions

View File

@ -2859,6 +2859,9 @@ gnc_main_window_disconnect (GncMainWindow *window,
g_signal_handlers_disconnect_by_func(G_OBJECT(page->notebook_page),
G_CALLBACK(gnc_main_window_button_press_cb), page);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(page));
/* Disconnect the page and summarybar from the window */
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
if (priv->current_page == page)
@ -3780,7 +3783,7 @@ gnc_quartz_shutdown (GtkosxApplication *theApp, gpointer data)
/* Do Nothing. It's too late. */
}
/* Should quit responds to NSApplicationBlockTermination; returning
* TRUE means "don't terminate", FALSE means "do terminate".
* TRUE means "don't terminate", FALSE means "do terminate".
*/
static gboolean
gnc_quartz_should_quit (GtkosxApplication *theApp, GncMainWindow *window)
@ -4431,6 +4434,9 @@ gnc_main_window_cmd_window_move_page (GtkAction *action, GncMainWindow *window)
tab_widget = gtk_notebook_get_tab_label (notebook, page->notebook_page);
menu_widget = gtk_notebook_get_menu_label (notebook, page->notebook_page);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(page));
/* Ref the page components, then remove it from its old window */
g_object_ref(page);
g_object_ref(tab_widget);

View File

@ -58,6 +58,9 @@ static void gnc_plugin_page_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
static void gnc_plugin_page_default_focus (GncPluginPage *plugin_page,
gboolean on_current_page);
enum
{
INSERTED,
@ -102,6 +105,9 @@ typedef struct _GncPluginPagePrivate
gchar *page_color;
gchar *uri;
gchar *statusbar_text;
gulong page_changed_id;
} GncPluginPagePrivate;
GNC_DEFINE_TYPE_WITH_CODE(GncPluginPage, gnc_plugin_page, G_TYPE_OBJECT,
@ -371,6 +377,7 @@ gnc_plugin_page_class_init (GncPluginPageClass *klass)
klass->tab_icon = NULL;
klass->plugin_name = NULL;
klass->focus_page = gnc_plugin_page_default_focus;
g_object_class_install_property
(gobject_class,
@ -506,18 +513,19 @@ 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->uri = NULL;
priv->page_changed_id = 0;
page->window = NULL;
page->summarybar = NULL;
gnc_gobject_tracking_remember(G_OBJECT(page),
gnc_gobject_tracking_remember(G_OBJECT(page),
G_OBJECT_CLASS(klass));
}
@ -848,6 +856,96 @@ gnc_plugin_page_set_page_color (GncPluginPage *page, const gchar *color)
}
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
g_idle_remove_by_data (GNC_PLUGIN_PAGE(plugin_page));
g_idle_add ((GSourceFunc)(GNC_PLUGIN_PAGE_GET_CLASS(plugin_page)->focus_page_function),
GNC_PLUGIN_PAGE(plugin_page));
}
}
/* 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 Uniform Resource Identifier for this page. */
const gchar *
gnc_plugin_page_get_uri (GncPluginPage *page)

View File

@ -156,6 +156,21 @@ typedef struct
* @param window The window where the page was added. */
void (* window_changed) (GncPluginPage *plugin_page, GtkWidget *window);
/** Perform plugin specific actions to set the focus.
*
* @param page The page that was added to a window.
*
* @param on_current_pgae Whether this page is the currentone. */
void (* focus_page) (GncPluginPage *plugin_page, gboolean on_current_page);
/** This function performs specific actions to set the focus on a specific
* widget.
*
* @param page The page that was added to a window.
*
* @param on_current_pgae Whether this page is the currentone. */
gboolean (* focus_page_function) (GncPluginPage *plugin_page);
/** This function vector allows page specific actions to occur
* when the page name is changed.
*
@ -393,12 +408,30 @@ const gchar *gnc_plugin_page_get_page_color (GncPluginPage *page);
*
* @param page The page whose name should be retrieved.
*
* @return The color for this page. This string is owned by the page and
* @param The color for this page. This string is owned by the page and
* should not be freed by the caller.
*/
void gnc_plugin_page_set_page_color (GncPluginPage *page, const char *color);
/** Set up the page_changed callback for when the current page is changed.
* This will store a pointer to the page focus funtion passed as a parameter
* so that it can be used in setting up the g_idle_add
*
* @param page The page the callback is setup for.
*
* @param user_data The page focus function
*/
void gnc_plugin_page_inserted_cb (GncPluginPage *page, gpointer user_data);
/** Disconnect the page_changed_id signal callback.
*
* @param page The page whose name should be retrieved.
*/
void gnc_plugin_page_disconnect_page_changed (GncPluginPage *page);
/** Retrieve the Uniform Resource Identifier for this page.
*
* @param page The page whose URI should be retrieved.

View File

@ -149,11 +149,19 @@ gnc_plugin_budget_cmd_new_budget (GtkAction *action,
{
GncBudget *budget;
GncPluginPage *page;
gchar *description, *date;
g_return_if_fail (user_data != NULL);
budget = gnc_budget_new (gnc_get_current_book());
page = gnc_plugin_page_budget_new (budget);
date = qof_print_date (gnc_time (NULL));
description = g_strdup_printf ("%s: %s", _("Created"), date);
gnc_budget_set_description (budget, description);
g_free (description);
g_free (date);
gnc_main_window_open_page (user_data->window, page);
}

View File

@ -114,6 +114,7 @@ static void gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_
static void gnc_plugin_page_account_tree_finalize (GObject *object);
static void gnc_plugin_page_account_tree_selected (GObject *object, gpointer user_data);
static gboolean gnc_plugin_page_account_tree_focus_widget (GncPluginPage *plugin_page);
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);
@ -405,6 +406,7 @@ gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass)
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;
gnc_plugin_class->focus_page_function = gnc_plugin_page_account_tree_focus_widget;
plugin_page_signals[ACCOUNT_SELECTED] =
g_signal_new ("account_selected",
@ -573,12 +575,16 @@ gnc_plugin_page_account_tree_get_current_account (GncPluginPageAccountTree *page
return account;
}
gboolean
gnc_plugin_page_account_tree_focus (GncPluginPageAccountTree *page)
/**
* Whenever the current page is changed, if an account page is
* the current page, set focus on the tree view.
*/
static gboolean
gnc_plugin_page_account_tree_focus_widget (GncPluginPage *account_plugin_page)
{
if (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page))
if (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(account_plugin_page))
{
GncPluginPageAccountTreePrivate *priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
GncPluginPageAccountTreePrivate *priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_plugin_page);
GtkTreeView *view = GTK_TREE_VIEW(priv->tree_view);
if (!gtk_widget_is_focus (GTK_WIDGET(view)))
@ -636,32 +642,11 @@ gnc_plugin_page_account_editing_finished_cb (gpointer various, GncPluginPageRegi
gtk_action_set_sensitive (action, TRUE);
}
static void
gnc_plugin_account_tree_main_window_page_changed (GncMainWindow *window,
GncPluginPage *current_plugin_page,
GncPluginPage *account_plugin_page)
{
// We continue only if the plugin_page is a valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(current_plugin_page)||
!account_plugin_page || !GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(account_plugin_page))
return;
if (current_plugin_page == account_plugin_page)
{
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus to the tree view
g_idle_remove_by_data (GNC_PLUGIN_PAGE_ACCOUNT_TREE (account_plugin_page));
g_idle_add ((GSourceFunc)gnc_plugin_page_account_tree_focus,
GNC_PLUGIN_PAGE_ACCOUNT_TREE (account_plugin_page));
}
}
static GtkWidget *
gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page)
{
GncPluginPageAccountTree *page;
GncPluginPageAccountTreePrivate *priv;
GncMainWindow *window;
GtkTreeSelection *selection;
GtkTreeView *tree_view;
GtkWidget *scrolled_window;
@ -759,10 +744,9 @@ gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page)
gnc_plugin_page_account_tree_summarybar_position_changed,
page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window);
g_signal_connect (window, "page_changed",
G_CALLBACK(gnc_plugin_account_tree_main_window_page_changed),
plugin_page);
g_signal_connect (G_OBJECT(plugin_page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
// Read account filter state information from account section
gnc_tree_view_account_restore_filter (GNC_TREE_VIEW_ACCOUNT(priv->tree_view), &priv->fd,
@ -798,8 +782,11 @@ gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page)
// Destroy the filter override hash table
g_hash_table_destroy(priv->fd.filter_override);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
// Remove the page focus idle function if present
g_idle_remove_by_data (GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page));
g_idle_remove_by_data (plugin_page);
if (priv->widget)
{

View File

@ -95,15 +95,6 @@ GncPluginPage *gnc_plugin_page_account_tree_new (void);
Account * gnc_plugin_page_account_tree_get_current_account (GncPluginPageAccountTree *page);
/** Given a pointer to an account tree plugin page, set the focus to
* the GtkTreeView. This is used in a g_idle_add so return FALSE.
*
* @param page The "account tree" page.
*
* @return FALSE;
*/
gboolean gnc_plugin_page_account_tree_focus (GncPluginPageAccountTree *page);
/** Given a pointer to an account, the account tree will open
* and the account will be selected (if any).
*

View File

@ -59,6 +59,7 @@
#include "gnc-tree-view-account.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "gnc-window.h"
#include "option-util.h"
#include "gnc-main-window.h"
#include "gnc-component-manager.h"
@ -86,6 +87,7 @@ static void gnc_plugin_page_budget_finalize (GObject *object);
static GtkWidget *
gnc_plugin_page_budget_create_widget (GncPluginPage *plugin_page);
static gboolean gnc_plugin_page_budget_focus_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_budget_destroy_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_budget_save_page (GncPluginPage *plugin_page,
GKeyFile *file,
@ -310,6 +312,7 @@ gnc_plugin_page_budget_class_init (GncPluginPageBudgetClass *klass)
gnc_plugin_class->destroy_widget = gnc_plugin_page_budget_destroy_widget;
gnc_plugin_class->save_page = gnc_plugin_page_budget_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_budget_recreate_page;
gnc_plugin_class->focus_page_function = gnc_plugin_page_budget_focus_widget;
}
@ -383,12 +386,16 @@ gnc_plugin_page_budget_close_cb (gpointer user_data)
}
gboolean
gnc_plugin_page_budget_focus (GncPluginPageBudget *page)
/**
* Whenever the current page is changed, if a budget page is
* the current page, set focus on the budget tree view.
*/
static gboolean
gnc_plugin_page_budget_focus_widget (GncPluginPage *budget_plugin_page)
{
if (GNC_IS_PLUGIN_PAGE_BUDGET(page))
if (GNC_IS_PLUGIN_PAGE_BUDGET(budget_plugin_page))
{
GncPluginPageBudgetPrivate *priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
GncPluginPageBudgetPrivate *priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(budget_plugin_page);
GncBudgetView *budget_view = priv->budget_view;
GtkWidget *account_view = gnc_budget_view_get_account_tree_view (budget_view);
@ -434,27 +441,6 @@ gnc_plugin_page_budget_refresh_cb (GHashTable *changes, gpointer user_data)
}
static void
gnc_plugin_budget_main_window_page_changed (GncMainWindow *window,
GncPluginPage *current_plugin_page,
GncPluginPage *budget_plugin_page)
{
// We continue only if the plugin_page is a valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_BUDGET(current_plugin_page) ||
!budget_plugin_page || !GNC_IS_PLUGIN_PAGE_BUDGET(budget_plugin_page))
return;
if (current_plugin_page == budget_plugin_page)
{
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus to the tree view
g_idle_remove_by_data (GNC_PLUGIN_PAGE_BUDGET(budget_plugin_page));
g_idle_add ((GSourceFunc)gnc_plugin_page_budget_focus,
GNC_PLUGIN_PAGE_BUDGET(budget_plugin_page));
}
}
/****************************
* GncPluginPage Functions *
***************************/
@ -463,7 +449,6 @@ gnc_plugin_page_budget_create_widget (GncPluginPage *plugin_page)
{
GncPluginPageBudget *page;
GncPluginPageBudgetPrivate *priv;
GncMainWindow *window;
ENTER("page %p", plugin_page);
page = GNC_PLUGIN_PAGE_BUDGET(plugin_page);
@ -498,10 +483,9 @@ gnc_plugin_page_budget_create_widget (GncPluginPage *plugin_page)
gnc_budget_get_guid (priv->budget),
QOF_EVENT_DESTROY | QOF_EVENT_MODIFY);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window);
g_signal_connect (window, "page_changed",
G_CALLBACK(gnc_plugin_budget_main_window_page_changed),
plugin_page);
g_signal_connect (G_OBJECT(plugin_page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
LEAVE("widget = %p", priv->budget_view);
return GTK_WIDGET(priv->budget_view);
@ -516,8 +500,11 @@ gnc_plugin_page_budget_destroy_widget (GncPluginPage *plugin_page)
ENTER("page %p", plugin_page);
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(plugin_page);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
// Remove the page focus idle function if present
g_idle_remove_by_data (GNC_PLUGIN_PAGE_BUDGET(plugin_page));
g_idle_remove_by_data (plugin_page);
if (priv->budget_view)
{

View File

@ -70,16 +70,6 @@ GncPluginPage *gnc_plugin_page_budget_new (GncBudget *budget);
void gnc_budget_gui_delete_budget (GncBudget *budget);
/** Given a pointer to a budget plugin page, set the focus to
* the Account GtkTreeView. This is used in a g_idle_add so
* return FALSE.
*
* @param page The "budget" page.
*
* @return FALSE
*/
gboolean gnc_plugin_page_budget_focus (GncPluginPageBudget *page);
G_END_DECLS
#endif /* __GNC_PLUGIN_PAGE_BUDGET_H */

View File

@ -52,6 +52,7 @@ static void gnc_plugin_page_invoice_init (GncPluginPageInvoice *plugin_page);
static void gnc_plugin_page_invoice_finalize (GObject *object);
static GtkWidget *gnc_plugin_page_invoice_create_widget (GncPluginPage *plugin_page);
static gboolean gnc_plugin_page_invoice_focus_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_invoice_destroy_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_invoice_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
static GncPluginPage *gnc_plugin_page_invoice_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
@ -448,6 +449,7 @@ gnc_plugin_page_invoice_class_init (GncPluginPageInvoiceClass *klass)
gnc_plugin_class->save_page = gnc_plugin_page_invoice_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_invoice_recreate_page;
gnc_plugin_class->window_changed = gnc_plugin_page_invoice_window_changed;
gnc_plugin_class->focus_page_function = gnc_plugin_page_invoice_focus_widget;
}
static void
@ -572,56 +574,39 @@ gnc_plugin_page_invoice_update_menus (GncPluginPage *page, gboolean is_posted, g
}
static gboolean
gnc_plugin_page_invoice_focus (InvoiceWindow *iw)
{
GtkWidget *regWidget = gnc_invoice_get_register(iw);
GtkWidget *notes = gnc_invoice_get_notes(iw);
GnucashSheet *sheet;
if (!GNUCASH_IS_REGISTER(regWidget))
return FALSE;
sheet = gnucash_register_get_sheet (GNUCASH_REGISTER(regWidget));
// Test for the sheet being read only
if (!gnucash_sheet_is_read_only (sheet))
{
if (!gtk_widget_is_focus (GTK_WIDGET(sheet)))
gtk_widget_grab_focus (GTK_WIDGET(sheet));
}
else // set focus to the notes field
{
if (!gtk_widget_is_focus (GTK_WIDGET(notes)))
gtk_widget_grab_focus (GTK_WIDGET(notes));
}
return FALSE;
}
/**
* Whenever the current page is changed, if an invoice page is
* the current page, set focus on the sheet or notes field.
*/
static void
gnc_plugin_page_invoice_main_window_page_changed (GncMainWindow *window,
GncPluginPage *current_plugin_page,
GncPluginPage *invoice_plugin_page)
static gboolean
gnc_plugin_page_invoice_focus_widget (GncPluginPage *invoice_plugin_page)
{
// We continue only if the plugin_page is a valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_INVOICE(current_plugin_page) ||
!invoice_plugin_page || !GNC_IS_PLUGIN_PAGE_INVOICE(invoice_plugin_page))
return;
if (current_plugin_page == invoice_plugin_page)
if (GNC_IS_PLUGIN_PAGE_INVOICE(invoice_plugin_page))
{
GncPluginPageInvoicePrivate *priv = GNC_PLUGIN_PAGE_INVOICE_GET_PRIVATE(invoice_plugin_page);
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus to the sheet
g_idle_remove_by_data (priv->iw);
g_idle_add ((GSourceFunc)gnc_plugin_page_invoice_focus, priv->iw);
GtkWidget *regWidget = gnc_invoice_get_register(priv->iw);
GtkWidget *notes = gnc_invoice_get_notes(priv->iw);
GnucashSheet *sheet;
if (!GNUCASH_IS_REGISTER(regWidget))
return FALSE;
sheet = gnucash_register_get_sheet (GNUCASH_REGISTER(regWidget));
// Test for the sheet being read only
if (!gnucash_sheet_is_read_only (sheet))
{
if (!gtk_widget_is_focus (GTK_WIDGET(sheet)))
gtk_widget_grab_focus (GTK_WIDGET(sheet));
}
else // set focus to the notes field
{
if (!gtk_widget_is_focus (GTK_WIDGET(notes)))
gtk_widget_grab_focus (GTK_WIDGET(notes));
}
}
return FALSE;
}
@ -633,7 +618,6 @@ gnc_plugin_page_invoice_create_widget (GncPluginPage *plugin_page)
GncPluginPageInvoice *page;
GncPluginPageInvoicePrivate *priv;
GtkWidget *regWidget, *widget;
GncMainWindow *window;
ENTER("page %p", plugin_page);
page = GNC_PLUGIN_PAGE_INVOICE (plugin_page);
@ -680,10 +664,9 @@ gnc_plugin_page_invoice_create_widget (GncPluginPage *plugin_page)
gnc_plugin_page_invoice_refresh_cb,
NULL, page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
g_signal_connect(window, "page_changed",
G_CALLBACK(gnc_plugin_page_invoice_main_window_page_changed),
plugin_page);
g_signal_connect (G_OBJECT(plugin_page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
LEAVE("");
return priv->widget;
@ -708,8 +691,11 @@ gnc_plugin_page_invoice_destroy_widget (GncPluginPage *plugin_page)
gnc_plugin_page_invoice_summarybar_position_changed,
page);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
// Remove the page focus idle function if present
g_idle_remove_by_data (priv->iw);
g_idle_remove_by_data (plugin_page);
if (priv->widget == NULL)
{

View File

@ -58,6 +58,7 @@
#include "gnc-tree-view-owner.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "gnc-window.h"
#include "guile-mappings.h"
#include "dialog-lot-viewer.h"
#include "dialog-object-references.h"
@ -365,43 +366,25 @@ gnc_plugin_page_owner_tree_new (GncOwnerType owner_type)
return GNC_PLUGIN_PAGE(plugin_page);
}
static gboolean
gnc_plugin_page_owner_focus (GtkTreeView *tree_view)
{
if (GTK_IS_TREE_VIEW(tree_view))
{
if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
gtk_widget_grab_focus (GTK_WIDGET(tree_view));
}
return FALSE;
}
/**
* Whenever the current page is changed, if an owner page is
* the current page, set focus on the treeview.
* the current page, set focus on the tree view.
*/
static void
gnc_plugin_page_owner_main_window_page_changed (GncMainWindow *window,
GncPluginPage *current_plugin_page,
GncPluginPage *owner_plugin_page)
static gboolean
gnc_plugin_page_owner_focus_widget (GncPluginPage *owner_plugin_page)
{
// We continue only if the plugin_page is a valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_OWNER_TREE(current_plugin_page) ||
!owner_plugin_page || !GNC_IS_PLUGIN_PAGE_OWNER_TREE(owner_plugin_page))
return;
if (current_plugin_page == owner_plugin_page)
if (GNC_IS_PLUGIN_PAGE_OWNER_TREE(owner_plugin_page))
{
GncPluginPageOwnerTreePrivate *priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(owner_plugin_page);
GtkTreeView *tree_view = priv->tree_view;
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus to the tree view
g_idle_remove_by_data (GTK_TREE_VIEW (priv->tree_view));
g_idle_add ((GSourceFunc)gnc_plugin_page_owner_focus,
GTK_TREE_VIEW (priv->tree_view));
if (GTK_IS_TREE_VIEW(tree_view))
{
if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
gtk_widget_grab_focus (GTK_WIDGET(tree_view));
}
}
return FALSE;
}
G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageOwnerTree, gnc_plugin_page_owner_tree, GNC_TYPE_PLUGIN_PAGE)
@ -422,6 +405,7 @@ gnc_plugin_page_owner_tree_class_init (GncPluginPageOwnerTreeClass *klass)
gnc_plugin_class->destroy_widget = gnc_plugin_page_owner_tree_destroy_widget;
gnc_plugin_class->save_page = gnc_plugin_page_owner_tree_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_owner_tree_recreate_page;
gnc_plugin_class->focus_page_function = gnc_plugin_page_owner_focus_widget;
plugin_page_signals[OWNER_SELECTED] =
g_signal_new ("owner_selected",
@ -571,7 +555,6 @@ gnc_plugin_page_owner_tree_create_widget (GncPluginPage *plugin_page)
{
GncPluginPageOwnerTree *page;
GncPluginPageOwnerTreePrivate *priv;
GncMainWindow *window;
GtkTreeSelection *selection;
GtkTreeView *tree_view;
GtkWidget *scrolled_window;
@ -686,10 +669,9 @@ gnc_plugin_page_owner_tree_create_widget (GncPluginPage *plugin_page)
gnc_gui_component_set_session (priv->component_id,
gnc_get_current_session());
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
g_signal_connect(window, "page_changed",
G_CALLBACK(gnc_plugin_page_owner_main_window_page_changed),
plugin_page);
g_signal_connect (G_OBJECT(plugin_page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
LEAVE("widget = %p", priv->widget);
return priv->widget;
@ -705,8 +687,11 @@ gnc_plugin_page_owner_tree_destroy_widget (GncPluginPage *plugin_page)
page = GNC_PLUGIN_PAGE_OWNER_TREE (plugin_page);
priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(page);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
// Remove the page focus idle function if present
g_idle_remove_by_data (GTK_TREE_VIEW (priv->tree_view));
g_idle_remove_by_data (plugin_page);
if (priv->widget)
{

View File

@ -102,6 +102,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 gboolean gnc_plugin_page_register_focus_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_register_focus (GncPluginPage *plugin_page, gboolean current_page);
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 void gnc_plugin_page_register_update_edit_menu (GncPluginPage *page, gboolean hide);
@ -750,10 +752,12 @@ 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->focus_page = gnc_plugin_page_register_focus;
gnc_plugin_class->save_page = gnc_plugin_page_register_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_register_recreate_page;
gnc_plugin_class->update_edit_menu_actions = gnc_plugin_page_register_update_edit_menu;
gnc_plugin_class->finish_pending = gnc_plugin_page_register_finish_pending;
gnc_plugin_class->focus_page_function = gnc_plugin_page_register_focus_widget;
gnc_ui_register_account_destroy_callback (gppr_account_destroy_cb);
}
@ -843,12 +847,16 @@ gnc_plugin_page_register_get_current_txn (GncPluginPageRegister *page)
return gnc_split_register_get_current_trans(reg);
}
gboolean
gnc_plugin_page_register_focus (GncPluginPageRegister *page)
/**
* Whenever the current page is changed, if a register page is
* the current page, set focus on the sheet.
*/
static gboolean
gnc_plugin_page_register_focus_widget (GncPluginPage *register_plugin_page)
{
if (GNC_IS_PLUGIN_PAGE_REGISTER(page))
if (GNC_IS_PLUGIN_PAGE_REGISTER(register_plugin_page))
{
GNCSplitReg *gsr = gnc_plugin_page_register_get_gsr(GNC_PLUGIN_PAGE(page));
GNCSplitReg *gsr = gnc_plugin_page_register_get_gsr(GNC_PLUGIN_PAGE(register_plugin_page));
gnc_split_reg_focus_on_sheet (gsr);
}
return FALSE;
@ -1145,31 +1153,33 @@ get_filter_default_num_of_days (GNCLedgerDisplayType ledger_type)
return "0";
}
/* For setting the focus on a register page, the default gnc_plugin
* function for 'focus_page' is overridden so that the page focus
* can be condionally set. This is to allow for enabling the setting
* of the sheet focus only when the page is the current one.
*/
static void
gnc_plugin_register_main_window_page_changed (GncMainWindow *window,
GncPluginPage *current_plugin_page,
GncPluginPage *register_plugin_page)
gnc_plugin_page_register_focus (GncPluginPage *plugin_page,
gboolean on_current_page)
{
GncPluginPageRegister *page;
GncPluginPageRegisterPrivate *priv;
GNCSplitReg *gsr;
// We continue only if the plugin_page is a valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_REGISTER(current_plugin_page) ||
!register_plugin_page || !GNC_IS_PLUGIN_PAGE_REGISTER(register_plugin_page))
return;
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(register_plugin_page);
gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE(register_plugin_page));
page = GNC_PLUGIN_PAGE_REGISTER(plugin_page);
priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
if (current_plugin_page == register_plugin_page)
gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE(plugin_page));
if (on_current_page)
{
priv->page_focus = TRUE;
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus to the register
g_idle_remove_by_data (GNC_PLUGIN_PAGE_REGISTER (register_plugin_page));
g_idle_add ((GSourceFunc)gnc_plugin_page_register_focus,
GNC_PLUGIN_PAGE_REGISTER (register_plugin_page));
// Chain up to use parent version of 'focus_page' which will
// use an idle_add as the page changed signal is emitted multiple times.
GNC_PLUGIN_PAGE_CLASS(parent_class)->focus_page (plugin_page, TRUE);
}
else
priv->page_focus = FALSE;
@ -1183,7 +1193,6 @@ gnc_plugin_page_register_create_widget (GncPluginPage *plugin_page)
{
GncPluginPageRegister *page;
GncPluginPageRegisterPrivate *priv;
GncMainWindow *window;
GNCLedgerDisplayType ledger_type;
GncWindow *gnc_window;
guint numRows;
@ -1398,10 +1407,9 @@ gnc_plugin_page_register_create_widget (GncPluginPage *plugin_page)
gnc_split_reg_set_moved_cb
(priv->gsr, (GFunc)gnc_plugin_page_register_ui_update, page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
g_signal_connect (window, "page_changed",
G_CALLBACK(gnc_plugin_register_main_window_page_changed),
plugin_page);
g_signal_connect (G_OBJECT(plugin_page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
/* DRH - Probably lots of other stuff from regWindowLedger should end up here. */
LEAVE(" ");
@ -1427,6 +1435,9 @@ gnc_plugin_page_register_destroy_widget (GncPluginPage *plugin_page)
gnc_plugin_page_register_summarybar_position_changed,
page);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
// Remove the page focus idle function if present
g_idle_remove_by_data (GNC_PLUGIN_PAGE_REGISTER (plugin_page));
@ -1468,7 +1479,7 @@ gnc_plugin_page_register_destroy_widget (GncPluginPage *plugin_page)
static void
gnc_plugin_page_register_window_changed (GncPluginPage *plugin_page,
GtkWidget *window)
GtkWidget *window)
{
GncPluginPageRegister *page;
GncPluginPageRegisterPrivate *priv;

View File

@ -163,16 +163,6 @@ gnc_plugin_page_register_get_account (GncPluginPageRegister *page);
Transaction *
gnc_plugin_page_register_get_current_txn (GncPluginPageRegister *page);
/** Given a pointer to a register plugin page, set the focus to
* the sheet. This is used in a g_idle_add so return FALSE.
*
* @param page The "register" page.
*
* @return FALSE
*/
gboolean
gnc_plugin_page_register_focus (GncPluginPageRegister *page);
G_END_DECLS
/** @} */
/** @} */

View File

@ -233,41 +233,25 @@ gnc_plugin_page_report_set_property( GObject *obj,
}
static gboolean
gnc_plugin_page_report_focus (GtkWidget *widget)
{
if (GTK_IS_WIDGET(widget))
{
if (!gtk_widget_is_focus (GTK_WIDGET(widget)))
gtk_widget_grab_focus (GTK_WIDGET(widget));
}
return FALSE;
}
/**
* Whenever the current page is changed, if a report page is
* the current page, set focus on the report.
*/
static void
gnc_plugin_page_report_main_window_page_changed (GncMainWindow *window,
GncPluginPage *current_plugin_page,
GncPluginPage *report_plugin_page)
static gboolean
gnc_plugin_page_report_focus_widget (GncPluginPage *report_plugin_page)
{
// We continue only if the plugin_page is a valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_REPORT(current_plugin_page) ||
!report_plugin_page || !GNC_IS_PLUGIN_PAGE_REPORT(report_plugin_page))
return;
if (current_plugin_page == report_plugin_page)
if (GNC_IS_PLUGIN_PAGE_REPORT(report_plugin_page))
{
GncPluginPageReportPrivate *priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report_plugin_page);
GtkWidget *widget = gnc_html_get_widget (priv->html);
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus to the webkit widget
g_idle_remove_by_data (widget);
g_idle_add ((GSourceFunc)gnc_plugin_page_report_focus, widget);
if (GTK_IS_WIDGET(widget))
{
if (!gtk_widget_is_focus (GTK_WIDGET(widget)))
gtk_widget_grab_focus (GTK_WIDGET(widget));
}
}
return FALSE;
}
static void
@ -294,6 +278,7 @@ gnc_plugin_page_report_class_init (GncPluginPageReportClass *klass)
gnc_plugin_page_class->page_name_changed = gnc_plugin_page_report_name_changed;
gnc_plugin_page_class->update_edit_menu_actions = gnc_plugin_page_report_update_edit_menu;
gnc_plugin_page_class->finish_pending = gnc_plugin_page_report_finish_pending;
gnc_plugin_page_class->focus_page_function = gnc_plugin_page_report_focus_widget;
// create the "reportId" property
g_object_class_install_property( object_class,
@ -412,7 +397,6 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
{
GncPluginPageReport *report;
GncPluginPageReportPrivate *priv;
GncMainWindow *window;
GtkWindow *topLvl;
GtkAction *action;
URLType type;
@ -477,10 +461,9 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
g_signal_connect (G_OBJECT(GTK_WIDGET(priv->container)), "realize",
G_CALLBACK(gnc_plugin_page_report_realize_uri), page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window);
g_signal_connect(window, "page_changed",
G_CALLBACK(gnc_plugin_page_report_main_window_page_changed),
page);
g_signal_connect (G_OBJECT(page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
gtk_widget_show_all( GTK_WIDGET(priv->container) );
LEAVE("container %p", priv->container);
@ -783,8 +766,11 @@ gnc_plugin_page_report_destroy_widget(GncPluginPage *plugin_page)
widget = gnc_html_get_widget(priv->html);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
// Remove the page focus idle function if present
g_idle_remove_by_data (widget);
g_idle_remove_by_data (plugin_page);
if (priv->component_manager_id)
{

View File

@ -73,6 +73,7 @@
#include "gnc-tree-view-sx-list.h"
#include "gnc-ui-util.h"
#include "gnc-ui.h"
#include "gnc-window.h"
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "gnc.gui.plugin-page.sx-list"
@ -187,42 +188,25 @@ gnc_plugin_page_sx_list_new (void)
}
static gboolean
gnc_plugin_page_sx_list_focus (GtkTreeView *tree_view)
{
if (GTK_IS_TREE_VIEW(tree_view))
{
if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
gtk_widget_grab_focus (GTK_WIDGET(tree_view));
}
return FALSE;
}
/**
* Whenever the current page is changed, if a schedule editor page is
* the current page, set focus on the treeview.
* Whenever the current page is changed, if a sx page is
* the current page, set focus on the tree view.
*/
static void
gnc_plugin_page_sx_list_main_window_page_changed (GncMainWindow *window,
GncPluginPage *current_plugin_page,
GncPluginPage *sx_plugin_page)
static gboolean
gnc_plugin_page_sx_list_focus_widget (GncPluginPage *sx_plugin_page)
{
// We continue only if the plugin_page is a valid
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_SX_LIST(current_plugin_page) ||
!sx_plugin_page || !GNC_IS_PLUGIN_PAGE_SX_LIST(sx_plugin_page))
return;
if (current_plugin_page == sx_plugin_page)
if (GNC_IS_PLUGIN_PAGE_SX_LIST(sx_plugin_page))
{
GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(sx_plugin_page);
GtkTreeView *tree_view = priv->tree_view;
// The page changed signal is emitted multiple times so we need
// to use an idle_add to change the focus to the tree view
g_idle_remove_by_data (GTK_TREE_VIEW (priv->tree_view));
g_idle_add ((GSourceFunc)gnc_plugin_page_sx_list_focus,
GTK_TREE_VIEW (priv->tree_view));
if (GTK_IS_TREE_VIEW(tree_view))
{
if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
gtk_widget_grab_focus (GTK_WIDGET(tree_view));
}
}
return FALSE;
}
G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageSxList, gnc_plugin_page_sx_list, GNC_TYPE_PLUGIN_PAGE)
@ -244,6 +228,7 @@ gnc_plugin_page_sx_list_class_init (GncPluginPageSxListClass *klass)
gnc_plugin_class->destroy_widget = gnc_plugin_page_sx_list_destroy_widget;
gnc_plugin_class->save_page = gnc_plugin_page_sx_list_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_sx_list_recreate_page;
gnc_plugin_class->focus_page_function = gnc_plugin_page_sx_list_focus_widget;
}
@ -371,7 +356,6 @@ gnc_plugin_page_sx_list_create_widget (GncPluginPage *plugin_page)
{
GncPluginPageSxList *page;
GncPluginPageSxListPrivate *priv;
GncMainWindow *window;
GtkWidget *widget;
GtkWidget *vbox;
GtkWidget *label;
@ -498,10 +482,9 @@ gnc_plugin_page_sx_list_create_widget (GncPluginPage *plugin_page)
gnc_gui_component_set_session (priv->gnc_component_id,
gnc_get_current_session());
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
g_signal_connect(window, "page_changed",
G_CALLBACK(gnc_plugin_page_sx_list_main_window_page_changed),
plugin_page);
g_signal_connect (G_OBJECT(plugin_page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
return priv->widget;
}
@ -516,8 +499,11 @@ gnc_plugin_page_sx_list_destroy_widget (GncPluginPage *plugin_page)
page = GNC_PLUGIN_PAGE_SX_LIST (plugin_page);
priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
// Remove the page_changed signal callback
gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
// Remove the page focus idle function if present
g_idle_remove_by_data (GTK_TREE_VIEW (priv->tree_view));
g_idle_remove_by_data (plugin_page);
if (priv->widget)
{

View File

@ -511,10 +511,17 @@ gsr_update_summary_label( GtkWidget *label,
{
gnc_numeric amount;
char string[256];
const gchar *label_str = NULL;
GtkWidget *text_label, *hbox;
gchar *tooltip;
if ( label == NULL )
return;
hbox = g_object_get_data (G_OBJECT(label), "text_box");
text_label = g_object_get_data (G_OBJECT(label), "text_label");
label_str = gtk_label_get_text (GTK_LABEL(text_label));
amount = (*getter)( leader );
if ( reverse )
@ -534,6 +541,13 @@ gsr_update_summary_label( GtkWidget *label,
gnc_set_label_color( label, amount );
gtk_label_set_text( GTK_LABEL(label), string );
if (label_str)
{
tooltip = g_strdup_printf ("%s %s", label_str, string);
gtk_widget_set_tooltip_text (GTK_WIDGET(hbox), tooltip);
g_free (tooltip);
}
}
static
@ -2418,7 +2432,7 @@ GtkWidget*
add_summary_label (GtkWidget *summarybar, gboolean pack_start, const char *label_str, GtkWidget *extra)
{
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *text_label, *secondary_label;
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
@ -2427,18 +2441,21 @@ add_summary_label (GtkWidget *summarybar, gboolean pack_start, const char *label
else
gtk_box_pack_end( GTK_BOX(summarybar), hbox, FALSE, FALSE, 5 );
label = gtk_label_new( label_str );
gnc_label_set_alignment(label, 1.0, 0.5 );
gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, FALSE, 0 );
text_label = gtk_label_new (label_str);
gnc_label_set_alignment (text_label, 1.0, 0.5 );
gtk_label_set_ellipsize (GTK_LABEL(text_label), PANGO_ELLIPSIZE_END);
gtk_box_pack_start (GTK_BOX(hbox), text_label, FALSE, FALSE, 0);
label = gtk_label_new( "" );
gnc_label_set_alignment(label, 1.0, 0.5 );
gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, FALSE, 0 );
secondary_label = gtk_label_new ( "" );
g_object_set_data (G_OBJECT(secondary_label), "text_label", text_label);
g_object_set_data (G_OBJECT(secondary_label), "text_box", hbox);
gnc_label_set_alignment (secondary_label, 1.0, 0.5 );
gtk_box_pack_start (GTK_BOX(hbox), secondary_label, FALSE, FALSE, 0);
if (extra != NULL)
gtk_box_pack_start( GTK_BOX(hbox), extra, FALSE, FALSE, 0 );
return label;
return secondary_label;
}
static void

View File

@ -22,6 +22,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-modules (gnucash html))
(use-modules (ice-9 match))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; <html-document> class
@ -221,69 +222,49 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (gnc:html-document-markup-start doc markup end-tag? . rest)
(let ((childinfo (gnc:html-document-fetch-markup-style doc markup))
(extra-attrib (and (pair? rest) rest)))
;; now generate the start tag
(let ((tag (gnc:html-markup-style-info-tag childinfo))
(attr (gnc:html-markup-style-info-attributes childinfo)))
(let* ((childinfo (gnc:html-document-fetch-markup-style doc markup))
(extra-attrib (and (pair? rest) rest))
(retval '())
(tag (or (gnc:html-markup-style-info-tag childinfo) markup))
(attr (gnc:html-markup-style-info-attributes childinfo)))
;; "" tags mean "show no tag"; #f tags means use default.
(cond ((not tag)
(set! tag markup))
((and (string? tag) (string=? tag ""))
(set! tag #f)))
(let* ((retval '())
(push (lambda (l) (set! retval (cons l retval))))
(add-internal-tag (lambda (tag) (push "<") (push tag) (push ">")))
(add-attribute
(lambda (key value prior)
(push " ") (push key)
(if value (begin (push "=\"")
(push value)
(push "\"")))
#t))
(addextraatt
(lambda (attr)
(cond ((string? attr) (push " ") (push attr))
(attr (gnc:warn "non-string attribute" attr)))))
(build-first-tag
(lambda (tag)
(push "<") (push tag)
(if attr (hash-fold add-attribute #f attr))
(if extra-attrib (for-each addextraatt extra-attrib))
(if (not end-tag?)
(push " /")) ;;add closing "/" for no-end elements...
(push ">"))))
(if tag
(if (list? tag)
(begin
(build-first-tag (car tag))
(for-each add-internal-tag (cdr tag)))
(build-first-tag tag)))
retval))))
(define (push l) (set! retval (cons l retval)))
(define (add-internal-tag tag) (push "<") (push tag) (push ">"))
(define (add-attribute key value)
(push " ") (push key)
(when value (push "=\"") (push value) (push "\"")))
(define (addextraatt attr)
(cond ((string? attr) (push " ") (push attr))
(attr (gnc:warn "non-string attribute" attr))))
(define (build-first-tag tag)
(push "<") (push tag)
(if attr (hash-for-each add-attribute attr))
(if extra-attrib (for-each addextraatt extra-attrib))
(unless end-tag? (push " /")) ;;add closing "/" for no-end elements...
(push ">"))
(match tag
("" #f)
((head . tail) (build-first-tag head) (for-each add-internal-tag tail))
(_ (build-first-tag tag)))
retval))
(define (gnc:html-document-markup-end doc markup)
(let ((childinfo (gnc:html-document-fetch-markup-style doc markup)))
(let* ((childinfo (gnc:html-document-fetch-markup-style doc markup))
(tag (or (gnc:html-markup-style-info-tag childinfo) markup))
(retval '()))
(define (push l) (set! retval (cons l retval)))
(define (addtag t)
(push "</")
(push t)
(push ">\n"))
;; now generate the end tag
(let ((tag (gnc:html-markup-style-info-tag childinfo)))
;; "" tags mean "show no tag"; #f tags means use default.
(cond ((not tag)
(set! tag markup))
((and (string? tag) (string=? tag ""))
(set! tag #f)))
(let* ((retval '())
(push (lambda (l) (set! retval (cons l retval)))))
(if tag
(let ((addtag (lambda (t)
(push "</")
(push tag)
(push ">\n"))))
(cond
((string? tag)
(addtag tag))
((list? tag)
(for-each addtag (reverse tag))))))
retval))))
;; "" tags mean "show no tag"; #f tags means use default.)
(match tag
("" #f)
((? string?) (addtag tag))
((? list?) (for-each addtag (reverse tag))))
retval))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; html-document-render-data

View File

@ -60,18 +60,22 @@
(define javascript "
<script>
function getID(cell) { return cell.getAttribute('link-id'); }
function mousedown(e) {
var id = getID(e.target);
var ishighlighted = e.target.classList.contains('highlight');
e.preventDefault ();
TDs.forEach(TD => TD.classList.remove('highlight'));
function clicky() {
var id = getID(this);
var ishighlighted = this.classList.contains('highlight');
TDs.forEach (function (item, idx) {
item.classList.remove('highlight')});
if (ishighlighted) return;
TDs
.filter (TD => getID(TD) == id)
.forEach (TD => TD.classList.add('highlight'));}
TDs.forEach (function (item, idx) {
if (getID(item) == id)
item.classList.add('highlight')})}
var TDs = document.getElementsByTagName('td');
TDs = [...TDs].filter(getID);
TDs.forEach(TD => TD.onmousedown = mousedown);
TDs = Array.prototype.slice.call (TDs);
TDs = TDs.filter (getID);
TDs.forEach(function (item, idx) {
item.addEventListener('click', clicky)});
</script>
")

View File

@ -28,6 +28,7 @@
(define-module (gnucash reports standard view-column))
(use-modules (gnucash engine))
(use-modules (ice-9 match))
(use-modules (gnucash utilities))
(use-modules (gnucash core-utils))
(use-modules (gnucash app-utils))
@ -81,20 +82,14 @@
;; make sure each subreport has an option change callback that
;; pings the parent
(let loop ((new-reports '())
(reports reports))
(if (null? reports)
(gnc:option-set-value report-opt (reverse new-reports))
(let* ((report-info (car reports))
(child (car report-info))
(rowspan (cadr report-info))
(colspan (caddr report-info))
(callback (or (cadddr report-info)
(make-child-options-callback
report (gnc-report-find child)))))
(loop (cons (list child rowspan colspan callback)
new-reports)
(cdr reports)))))
(let loop ((reports reports) (new-reports '()))
(match reports
(() (gnc:option-set-value report-opt (reverse new-reports)))
(((child rowspan colspan callback) . rest)
(let ((callback (or callback
(make-child-options-callback
report (gnc-report-find child)))))
(loop rest (cons (list child rowspan colspan callback) new-reports))))))
;; we really would rather do something smart here with the
;; report's cached text if possible. For the moment, we'll have
@ -212,17 +207,11 @@
(define (cleanup-options report)
(let* ((options (gnc:report-options report))
(report-opt (gnc:lookup-option options "__general" "report-list")))
(let loop ((new-reports '())
(reports (gnc:option-value report-opt)))
(if (null? reports)
(gnc:option-set-value report-opt (reverse new-reports))
(let* ((report-info (car reports))
(child (car report-info))
(rowspan (cadr report-info))
(colspan (caddr report-info)))
(loop (cons (list child rowspan colspan #f)
new-reports)
(cdr reports)))))))
(let loop ((reports (gnc:option-value report-opt)) (new-reports '()))
(match reports
(() (gnc:option-set-value report-opt (reverse new-reports)))
(((child rowspan colspan _) . rest)
(loop rest (cons (list child rowspan colspan #f) new-reports)))))))
;; define the view now.
(gnc:define-report

View File

@ -1939,18 +1939,14 @@ be excluded from periodic reporting.")
(define BOOK-SPLIT-ACTION
(qof-book-use-split-action-for-num-field (gnc-get-current-book)))
(define (is-filter-member split account-list)
(let* ((txn (xaccSplitGetParent split))
(splitcount (xaccTransCountSplits txn))
(is-in-account-list? (lambda (acc) (member acc account-list))))
(cond
((= splitcount 2)
(is-in-account-list?
(xaccSplitGetAccount (xaccSplitGetOtherSplit split))))
((> splitcount 2)
(or-map is-in-account-list?
(map xaccSplitGetAccount
(delete split (xaccTransGetSplitList txn)))))
(else #f))))
(define (same-split? s) (equal? s split))
(define (from-account? s) (member (xaccSplitGetAccount s) account-list))
(let lp ((splits (xaccTransGetSplitList (xaccSplitGetParent split))))
(match splits
(() #f)
(((? same-split?) . rest) (lp rest))
(((? from-account?) . _) #t)
((_ . rest) (lp rest)))))
(gnc:report-starting (opt-val gnc:pagename-general gnc:optname-reportname))