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_signal_handlers_disconnect_by_func(G_OBJECT(page->notebook_page),
G_CALLBACK(gnc_main_window_button_press_cb), 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 */ /* Disconnect the page and summarybar from the window */
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
if (priv->current_page == page) if (priv->current_page == page)
@ -3780,7 +3783,7 @@ gnc_quartz_shutdown (GtkosxApplication *theApp, gpointer data)
/* Do Nothing. It's too late. */ /* Do Nothing. It's too late. */
} }
/* Should quit responds to NSApplicationBlockTermination; returning /* 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 static gboolean
gnc_quartz_should_quit (GtkosxApplication *theApp, GncMainWindow *window) 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); tab_widget = gtk_notebook_get_tab_label (notebook, page->notebook_page);
menu_widget = gtk_notebook_get_menu_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 */ /* Ref the page components, then remove it from its old window */
g_object_ref(page); g_object_ref(page);
g_object_ref(tab_widget); g_object_ref(tab_widget);

View File

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

View File

@ -156,6 +156,21 @@ typedef struct
* @param window The window where the page was added. */ * @param window The window where the page was added. */
void (* window_changed) (GncPluginPage *plugin_page, GtkWidget *window); 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 /** This function vector allows page specific actions to occur
* when the page name is changed. * 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. * @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. * should not be freed by the caller.
*/ */
void gnc_plugin_page_set_page_color (GncPluginPage *page, const char *color); 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. /** Retrieve the Uniform Resource Identifier for this page.
* *
* @param page The page whose URI should be retrieved. * @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; GncBudget *budget;
GncPluginPage *page; GncPluginPage *page;
gchar *description, *date;
g_return_if_fail (user_data != NULL); g_return_if_fail (user_data != NULL);
budget = gnc_budget_new (gnc_get_current_book()); budget = gnc_budget_new (gnc_get_current_book());
page = gnc_plugin_page_budget_new (budget); 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); 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_finalize (GObject *object);
static void gnc_plugin_page_account_tree_selected (GObject *object, gpointer user_data); 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 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_destroy_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group); 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->destroy_widget = gnc_plugin_page_account_tree_destroy_widget;
gnc_plugin_class->save_page = gnc_plugin_page_account_tree_save_page; 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->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] = plugin_page_signals[ACCOUNT_SELECTED] =
g_signal_new ("account_selected", g_signal_new ("account_selected",
@ -573,12 +575,16 @@ gnc_plugin_page_account_tree_get_current_account (GncPluginPageAccountTree *page
return account; 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); GtkTreeView *view = GTK_TREE_VIEW(priv->tree_view);
if (!gtk_widget_is_focus (GTK_WIDGET(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); 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 * static GtkWidget *
gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page) gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page)
{ {
GncPluginPageAccountTree *page; GncPluginPageAccountTree *page;
GncPluginPageAccountTreePrivate *priv; GncPluginPageAccountTreePrivate *priv;
GncMainWindow *window;
GtkTreeSelection *selection; GtkTreeSelection *selection;
GtkTreeView *tree_view; GtkTreeView *tree_view;
GtkWidget *scrolled_window; 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, gnc_plugin_page_account_tree_summarybar_position_changed,
page); page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window); g_signal_connect (G_OBJECT(plugin_page), "inserted",
g_signal_connect (window, "page_changed", G_CALLBACK(gnc_plugin_page_inserted_cb),
G_CALLBACK(gnc_plugin_account_tree_main_window_page_changed), NULL);
plugin_page);
// Read account filter state information from account section // Read account filter state information from account section
gnc_tree_view_account_restore_filter (GNC_TREE_VIEW_ACCOUNT(priv->tree_view), &priv->fd, 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 // Destroy the filter override hash table
g_hash_table_destroy(priv->fd.filter_override); 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 // 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) 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); 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 /** Given a pointer to an account, the account tree will open
* and the account will be selected (if any). * and the account will be selected (if any).
* *

View File

@ -59,6 +59,7 @@
#include "gnc-tree-view-account.h" #include "gnc-tree-view-account.h"
#include "gnc-ui.h" #include "gnc-ui.h"
#include "gnc-ui-util.h" #include "gnc-ui-util.h"
#include "gnc-window.h"
#include "option-util.h" #include "option-util.h"
#include "gnc-main-window.h" #include "gnc-main-window.h"
#include "gnc-component-manager.h" #include "gnc-component-manager.h"
@ -86,6 +87,7 @@ static void gnc_plugin_page_budget_finalize (GObject *object);
static GtkWidget * static GtkWidget *
gnc_plugin_page_budget_create_widget (GncPluginPage *plugin_page); 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_destroy_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_budget_save_page (GncPluginPage *plugin_page, static void gnc_plugin_page_budget_save_page (GncPluginPage *plugin_page,
GKeyFile *file, 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->destroy_widget = gnc_plugin_page_budget_destroy_widget;
gnc_plugin_class->save_page = gnc_plugin_page_budget_save_page; 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->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; GncBudgetView *budget_view = priv->budget_view;
GtkWidget *account_view = gnc_budget_view_get_account_tree_view (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 * * GncPluginPage Functions *
***************************/ ***************************/
@ -463,7 +449,6 @@ gnc_plugin_page_budget_create_widget (GncPluginPage *plugin_page)
{ {
GncPluginPageBudget *page; GncPluginPageBudget *page;
GncPluginPageBudgetPrivate *priv; GncPluginPageBudgetPrivate *priv;
GncMainWindow *window;
ENTER("page %p", plugin_page); ENTER("page %p", plugin_page);
page = GNC_PLUGIN_PAGE_BUDGET(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), gnc_budget_get_guid (priv->budget),
QOF_EVENT_DESTROY | QOF_EVENT_MODIFY); QOF_EVENT_DESTROY | QOF_EVENT_MODIFY);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window); g_signal_connect (G_OBJECT(plugin_page), "inserted",
g_signal_connect (window, "page_changed", G_CALLBACK(gnc_plugin_page_inserted_cb),
G_CALLBACK(gnc_plugin_budget_main_window_page_changed), NULL);
plugin_page);
LEAVE("widget = %p", priv->budget_view); LEAVE("widget = %p", priv->budget_view);
return GTK_WIDGET(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); ENTER("page %p", plugin_page);
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(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 // 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) 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); 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 G_END_DECLS
#endif /* __GNC_PLUGIN_PAGE_BUDGET_H */ #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 void gnc_plugin_page_invoice_finalize (GObject *object);
static GtkWidget *gnc_plugin_page_invoice_create_widget (GncPluginPage *plugin_page); 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_destroy_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_invoice_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group); 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); 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->save_page = gnc_plugin_page_invoice_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_invoice_recreate_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->window_changed = gnc_plugin_page_invoice_window_changed;
gnc_plugin_class->focus_page_function = gnc_plugin_page_invoice_focus_widget;
} }
static void 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 * Whenever the current page is changed, if an invoice page is
* the current page, set focus on the sheet or notes field. * the current page, set focus on the sheet or notes field.
*/ */
static void static gboolean
gnc_plugin_page_invoice_main_window_page_changed (GncMainWindow *window, gnc_plugin_page_invoice_focus_widget (GncPluginPage *invoice_plugin_page)
GncPluginPage *current_plugin_page,
GncPluginPage *invoice_plugin_page)
{ {
// We continue only if the plugin_page is a valid if (GNC_IS_PLUGIN_PAGE_INVOICE(invoice_plugin_page))
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)
{ {
GncPluginPageInvoicePrivate *priv = GNC_PLUGIN_PAGE_INVOICE_GET_PRIVATE(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 GtkWidget *regWidget = gnc_invoice_get_register(priv->iw);
// to use an idle_add to change the focus to the sheet GtkWidget *notes = gnc_invoice_get_notes(priv->iw);
g_idle_remove_by_data (priv->iw); GnucashSheet *sheet;
g_idle_add ((GSourceFunc)gnc_plugin_page_invoice_focus, priv->iw);
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; GncPluginPageInvoice *page;
GncPluginPageInvoicePrivate *priv; GncPluginPageInvoicePrivate *priv;
GtkWidget *regWidget, *widget; GtkWidget *regWidget, *widget;
GncMainWindow *window;
ENTER("page %p", plugin_page); ENTER("page %p", plugin_page);
page = GNC_PLUGIN_PAGE_INVOICE (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, gnc_plugin_page_invoice_refresh_cb,
NULL, page); NULL, page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window); g_signal_connect (G_OBJECT(plugin_page), "inserted",
g_signal_connect(window, "page_changed", G_CALLBACK(gnc_plugin_page_inserted_cb),
G_CALLBACK(gnc_plugin_page_invoice_main_window_page_changed), NULL);
plugin_page);
LEAVE(""); LEAVE("");
return priv->widget; return priv->widget;
@ -708,8 +691,11 @@ gnc_plugin_page_invoice_destroy_widget (GncPluginPage *plugin_page)
gnc_plugin_page_invoice_summarybar_position_changed, gnc_plugin_page_invoice_summarybar_position_changed,
page); 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 // 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) if (priv->widget == NULL)
{ {

View File

@ -58,6 +58,7 @@
#include "gnc-tree-view-owner.h" #include "gnc-tree-view-owner.h"
#include "gnc-ui.h" #include "gnc-ui.h"
#include "gnc-ui-util.h" #include "gnc-ui-util.h"
#include "gnc-window.h"
#include "guile-mappings.h" #include "guile-mappings.h"
#include "dialog-lot-viewer.h" #include "dialog-lot-viewer.h"
#include "dialog-object-references.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); 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 * 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 static gboolean
gnc_plugin_page_owner_main_window_page_changed (GncMainWindow *window, gnc_plugin_page_owner_focus_widget (GncPluginPage *owner_plugin_page)
GncPluginPage *current_plugin_page,
GncPluginPage *owner_plugin_page)
{ {
// We continue only if the plugin_page is a valid if (GNC_IS_PLUGIN_PAGE_OWNER_TREE(owner_plugin_page))
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)
{ {
GncPluginPageOwnerTreePrivate *priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(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 if (GTK_IS_TREE_VIEW(tree_view))
// to use an idle_add to change the focus to the tree view {
g_idle_remove_by_data (GTK_TREE_VIEW (priv->tree_view)); if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
g_idle_add ((GSourceFunc)gnc_plugin_page_owner_focus, gtk_widget_grab_focus (GTK_WIDGET(tree_view));
GTK_TREE_VIEW (priv->tree_view)); }
} }
return FALSE;
} }
G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageOwnerTree, gnc_plugin_page_owner_tree, GNC_TYPE_PLUGIN_PAGE) 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->destroy_widget = gnc_plugin_page_owner_tree_destroy_widget;
gnc_plugin_class->save_page = gnc_plugin_page_owner_tree_save_page; 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->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] = plugin_page_signals[OWNER_SELECTED] =
g_signal_new ("owner_selected", g_signal_new ("owner_selected",
@ -571,7 +555,6 @@ gnc_plugin_page_owner_tree_create_widget (GncPluginPage *plugin_page)
{ {
GncPluginPageOwnerTree *page; GncPluginPageOwnerTree *page;
GncPluginPageOwnerTreePrivate *priv; GncPluginPageOwnerTreePrivate *priv;
GncMainWindow *window;
GtkTreeSelection *selection; GtkTreeSelection *selection;
GtkTreeView *tree_view; GtkTreeView *tree_view;
GtkWidget *scrolled_window; 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_gui_component_set_session (priv->component_id,
gnc_get_current_session()); gnc_get_current_session());
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window); g_signal_connect (G_OBJECT(plugin_page), "inserted",
g_signal_connect(window, "page_changed", G_CALLBACK(gnc_plugin_page_inserted_cb),
G_CALLBACK(gnc_plugin_page_owner_main_window_page_changed), NULL);
plugin_page);
LEAVE("widget = %p", priv->widget); LEAVE("widget = %p", priv->widget);
return 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); page = GNC_PLUGIN_PAGE_OWNER_TREE (plugin_page);
priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(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 // 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) 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 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_destroy_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_register_window_changed (GncPluginPage *plugin_page, GtkWidget *window); 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 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 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); 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->create_widget = gnc_plugin_page_register_create_widget;
gnc_plugin_class->destroy_widget = gnc_plugin_page_register_destroy_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->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->save_page = gnc_plugin_page_register_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_register_recreate_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->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->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); 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); 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); gnc_split_reg_focus_on_sheet (gsr);
} }
return FALSE; return FALSE;
@ -1145,31 +1153,33 @@ get_filter_default_num_of_days (GNCLedgerDisplayType ledger_type)
return "0"; 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 static void
gnc_plugin_register_main_window_page_changed (GncMainWindow *window, gnc_plugin_page_register_focus (GncPluginPage *plugin_page,
GncPluginPage *current_plugin_page, gboolean on_current_page)
GncPluginPage *register_plugin_page)
{ {
GncPluginPageRegister *page;
GncPluginPageRegisterPrivate *priv; GncPluginPageRegisterPrivate *priv;
GNCSplitReg *gsr; GNCSplitReg *gsr;
// We continue only if the plugin_page is a valid g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
if (!current_plugin_page || !GNC_IS_PLUGIN_PAGE_REGISTER(current_plugin_page) ||
!register_plugin_page || !GNC_IS_PLUGIN_PAGE_REGISTER(register_plugin_page))
return;
priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(register_plugin_page); page = GNC_PLUGIN_PAGE_REGISTER(plugin_page);
gsr = gnc_plugin_page_register_get_gsr (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; priv->page_focus = TRUE;
// The page changed signal is emitted multiple times so we need // Chain up to use parent version of 'focus_page' which will
// to use an idle_add to change the focus to the register // use an idle_add as the page changed signal is emitted multiple times.
g_idle_remove_by_data (GNC_PLUGIN_PAGE_REGISTER (register_plugin_page)); GNC_PLUGIN_PAGE_CLASS(parent_class)->focus_page (plugin_page, TRUE);
g_idle_add ((GSourceFunc)gnc_plugin_page_register_focus,
GNC_PLUGIN_PAGE_REGISTER (register_plugin_page));
} }
else else
priv->page_focus = FALSE; priv->page_focus = FALSE;
@ -1183,7 +1193,6 @@ gnc_plugin_page_register_create_widget (GncPluginPage *plugin_page)
{ {
GncPluginPageRegister *page; GncPluginPageRegister *page;
GncPluginPageRegisterPrivate *priv; GncPluginPageRegisterPrivate *priv;
GncMainWindow *window;
GNCLedgerDisplayType ledger_type; GNCLedgerDisplayType ledger_type;
GncWindow *gnc_window; GncWindow *gnc_window;
guint numRows; guint numRows;
@ -1398,10 +1407,9 @@ gnc_plugin_page_register_create_widget (GncPluginPage *plugin_page)
gnc_split_reg_set_moved_cb gnc_split_reg_set_moved_cb
(priv->gsr, (GFunc)gnc_plugin_page_register_ui_update, page); (priv->gsr, (GFunc)gnc_plugin_page_register_ui_update, page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window); g_signal_connect (G_OBJECT(plugin_page), "inserted",
g_signal_connect (window, "page_changed", G_CALLBACK(gnc_plugin_page_inserted_cb),
G_CALLBACK(gnc_plugin_register_main_window_page_changed), NULL);
plugin_page);
/* DRH - Probably lots of other stuff from regWindowLedger should end up here. */ /* DRH - Probably lots of other stuff from regWindowLedger should end up here. */
LEAVE(" "); LEAVE(" ");
@ -1427,6 +1435,9 @@ gnc_plugin_page_register_destroy_widget (GncPluginPage *plugin_page)
gnc_plugin_page_register_summarybar_position_changed, gnc_plugin_page_register_summarybar_position_changed,
page); 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 // Remove the page focus idle function if present
g_idle_remove_by_data (GNC_PLUGIN_PAGE_REGISTER (plugin_page)); 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 static void
gnc_plugin_page_register_window_changed (GncPluginPage *plugin_page, gnc_plugin_page_register_window_changed (GncPluginPage *plugin_page,
GtkWidget *window) GtkWidget *window)
{ {
GncPluginPageRegister *page; GncPluginPageRegister *page;
GncPluginPageRegisterPrivate *priv; GncPluginPageRegisterPrivate *priv;

View File

@ -163,16 +163,6 @@ gnc_plugin_page_register_get_account (GncPluginPageRegister *page);
Transaction * Transaction *
gnc_plugin_page_register_get_current_txn (GncPluginPageRegister *page); 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 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 * Whenever the current page is changed, if a report page is
* the current page, set focus on the report. * the current page, set focus on the report.
*/ */
static void static gboolean
gnc_plugin_page_report_main_window_page_changed (GncMainWindow *window, gnc_plugin_page_report_focus_widget (GncPluginPage *report_plugin_page)
GncPluginPage *current_plugin_page,
GncPluginPage *report_plugin_page)
{ {
// We continue only if the plugin_page is a valid if (GNC_IS_PLUGIN_PAGE_REPORT(report_plugin_page))
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)
{ {
GncPluginPageReportPrivate *priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report_plugin_page); GncPluginPageReportPrivate *priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report_plugin_page);
GtkWidget *widget = gnc_html_get_widget (priv->html); GtkWidget *widget = gnc_html_get_widget (priv->html);
// The page changed signal is emitted multiple times so we need if (GTK_IS_WIDGET(widget))
// to use an idle_add to change the focus to the webkit widget {
g_idle_remove_by_data (widget); if (!gtk_widget_is_focus (GTK_WIDGET(widget)))
g_idle_add ((GSourceFunc)gnc_plugin_page_report_focus, widget); gtk_widget_grab_focus (GTK_WIDGET(widget));
}
} }
return FALSE;
} }
static void 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->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->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->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 // create the "reportId" property
g_object_class_install_property( object_class, g_object_class_install_property( object_class,
@ -412,7 +397,6 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
{ {
GncPluginPageReport *report; GncPluginPageReport *report;
GncPluginPageReportPrivate *priv; GncPluginPageReportPrivate *priv;
GncMainWindow *window;
GtkWindow *topLvl; GtkWindow *topLvl;
GtkAction *action; GtkAction *action;
URLType type; 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_signal_connect (G_OBJECT(GTK_WIDGET(priv->container)), "realize",
G_CALLBACK(gnc_plugin_page_report_realize_uri), page); G_CALLBACK(gnc_plugin_page_report_realize_uri), page);
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window); g_signal_connect (G_OBJECT(page), "inserted",
g_signal_connect(window, "page_changed", G_CALLBACK(gnc_plugin_page_inserted_cb),
G_CALLBACK(gnc_plugin_page_report_main_window_page_changed), NULL);
page);
gtk_widget_show_all( GTK_WIDGET(priv->container) ); gtk_widget_show_all( GTK_WIDGET(priv->container) );
LEAVE("container %p", 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); 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 // 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) if (priv->component_manager_id)
{ {

View File

@ -73,6 +73,7 @@
#include "gnc-tree-view-sx-list.h" #include "gnc-tree-view-sx-list.h"
#include "gnc-ui-util.h" #include "gnc-ui-util.h"
#include "gnc-ui.h" #include "gnc-ui.h"
#include "gnc-window.h"
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "gnc.gui.plugin-page.sx-list" #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 * Whenever the current page is changed, if a sx page is
* the current page, set focus on the treeview. * the current page, set focus on the tree view.
*/ */
static void static gboolean
gnc_plugin_page_sx_list_main_window_page_changed (GncMainWindow *window, gnc_plugin_page_sx_list_focus_widget (GncPluginPage *sx_plugin_page)
GncPluginPage *current_plugin_page,
GncPluginPage *sx_plugin_page)
{ {
// We continue only if the plugin_page is a valid if (GNC_IS_PLUGIN_PAGE_SX_LIST(sx_plugin_page))
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)
{ {
GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(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 if (GTK_IS_TREE_VIEW(tree_view))
// to use an idle_add to change the focus to the tree view {
g_idle_remove_by_data (GTK_TREE_VIEW (priv->tree_view)); if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
g_idle_add ((GSourceFunc)gnc_plugin_page_sx_list_focus, gtk_widget_grab_focus (GTK_WIDGET(tree_view));
GTK_TREE_VIEW (priv->tree_view)); }
} }
return FALSE;
} }
G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageSxList, gnc_plugin_page_sx_list, GNC_TYPE_PLUGIN_PAGE) 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->destroy_widget = gnc_plugin_page_sx_list_destroy_widget;
gnc_plugin_class->save_page = gnc_plugin_page_sx_list_save_page; 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->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; GncPluginPageSxList *page;
GncPluginPageSxListPrivate *priv; GncPluginPageSxListPrivate *priv;
GncMainWindow *window;
GtkWidget *widget; GtkWidget *widget;
GtkWidget *vbox; GtkWidget *vbox;
GtkWidget *label; 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_gui_component_set_session (priv->gnc_component_id,
gnc_get_current_session()); gnc_get_current_session());
window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window); g_signal_connect (G_OBJECT(plugin_page), "inserted",
g_signal_connect(window, "page_changed", G_CALLBACK(gnc_plugin_page_inserted_cb),
G_CALLBACK(gnc_plugin_page_sx_list_main_window_page_changed), NULL);
plugin_page);
return priv->widget; 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); page = GNC_PLUGIN_PAGE_SX_LIST (plugin_page);
priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(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 // 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) if (priv->widget)
{ {

View File

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

View File

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

View File

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

View File

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

View File

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