diff --git a/gnucash/gnome-utils/gnc-main-window.c b/gnucash/gnome-utils/gnc-main-window.c index 2989a7222f..b07381b298 100644 --- a/gnucash/gnome-utils/gnc-main-window.c +++ b/gnucash/gnome-utils/gnc-main-window.c @@ -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); diff --git a/gnucash/gnome-utils/gnc-plugin-page.c b/gnucash/gnome-utils/gnc-plugin-page.c index d757f3a530..0298d59a03 100644 --- a/gnucash/gnome-utils/gnc-plugin-page.c +++ b/gnucash/gnome-utils/gnc-plugin-page.c @@ -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) diff --git a/gnucash/gnome-utils/gnc-plugin-page.h b/gnucash/gnome-utils/gnc-plugin-page.h index fa09f9b240..82416acfe8 100644 --- a/gnucash/gnome-utils/gnc-plugin-page.h +++ b/gnucash/gnome-utils/gnc-plugin-page.h @@ -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. diff --git a/gnucash/gnome/gnc-plugin-budget.c b/gnucash/gnome/gnc-plugin-budget.c index 2056afe2aa..ff50121e2d 100644 --- a/gnucash/gnome/gnc-plugin-budget.c +++ b/gnucash/gnome/gnc-plugin-budget.c @@ -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); } diff --git a/gnucash/gnome/gnc-plugin-page-account-tree.c b/gnucash/gnome/gnc-plugin-page-account-tree.c index b627268fda..745efc8aab 100644 --- a/gnucash/gnome/gnc-plugin-page-account-tree.c +++ b/gnucash/gnome/gnc-plugin-page-account-tree.c @@ -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) { diff --git a/gnucash/gnome/gnc-plugin-page-account-tree.h b/gnucash/gnome/gnc-plugin-page-account-tree.h index 2dad1e7e42..57b8629878 100644 --- a/gnucash/gnome/gnc-plugin-page-account-tree.h +++ b/gnucash/gnome/gnc-plugin-page-account-tree.h @@ -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). * diff --git a/gnucash/gnome/gnc-plugin-page-budget.c b/gnucash/gnome/gnc-plugin-page-budget.c index a05e2ba2f3..76af4ed07e 100644 --- a/gnucash/gnome/gnc-plugin-page-budget.c +++ b/gnucash/gnome/gnc-plugin-page-budget.c @@ -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) { diff --git a/gnucash/gnome/gnc-plugin-page-budget.h b/gnucash/gnome/gnc-plugin-page-budget.h index 9efe5203b9..ffec5883f0 100644 --- a/gnucash/gnome/gnc-plugin-page-budget.h +++ b/gnucash/gnome/gnc-plugin-page-budget.h @@ -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 */ diff --git a/gnucash/gnome/gnc-plugin-page-invoice.c b/gnucash/gnome/gnc-plugin-page-invoice.c index f4fa4c4a71..c0143f3705 100644 --- a/gnucash/gnome/gnc-plugin-page-invoice.c +++ b/gnucash/gnome/gnc-plugin-page-invoice.c @@ -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) { diff --git a/gnucash/gnome/gnc-plugin-page-owner-tree.c b/gnucash/gnome/gnc-plugin-page-owner-tree.c index 1b54a06f69..83c87186b9 100644 --- a/gnucash/gnome/gnc-plugin-page-owner-tree.c +++ b/gnucash/gnome/gnc-plugin-page-owner-tree.c @@ -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) { diff --git a/gnucash/gnome/gnc-plugin-page-register.c b/gnucash/gnome/gnc-plugin-page-register.c index 1d19586983..0c311aea47 100644 --- a/gnucash/gnome/gnc-plugin-page-register.c +++ b/gnucash/gnome/gnc-plugin-page-register.c @@ -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; diff --git a/gnucash/gnome/gnc-plugin-page-register.h b/gnucash/gnome/gnc-plugin-page-register.h index 604836f407..43b2b2e2f5 100644 --- a/gnucash/gnome/gnc-plugin-page-register.h +++ b/gnucash/gnome/gnc-plugin-page-register.h @@ -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 /** @} */ /** @} */ diff --git a/gnucash/gnome/gnc-plugin-page-report.c b/gnucash/gnome/gnc-plugin-page-report.c index 19272f77e7..a46d968d48 100644 --- a/gnucash/gnome/gnc-plugin-page-report.c +++ b/gnucash/gnome/gnc-plugin-page-report.c @@ -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) { diff --git a/gnucash/gnome/gnc-plugin-page-sx-list.c b/gnucash/gnome/gnc-plugin-page-sx-list.c index 2f6ab431ff..7fa88a38f2 100644 --- a/gnucash/gnome/gnc-plugin-page-sx-list.c +++ b/gnucash/gnome/gnc-plugin-page-sx-list.c @@ -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) { diff --git a/gnucash/gnome/gnc-split-reg.c b/gnucash/gnome/gnc-split-reg.c index 599a167057..12dcfe5e53 100644 --- a/gnucash/gnome/gnc-split-reg.c +++ b/gnucash/gnome/gnc-split-reg.c @@ -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 diff --git a/gnucash/report/html-document.scm b/gnucash/report/html-document.scm index b1322387ea..a5a4c994be 100644 --- a/gnucash/report/html-document.scm +++ b/gnucash/report/html-document.scm @@ -22,6 +22,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (use-modules (gnucash html)) +(use-modules (ice-9 match)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 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 "\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 "\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 diff --git a/gnucash/report/reports/standard/new-owner-report.scm b/gnucash/report/reports/standard/new-owner-report.scm index afc8eea982..93a6ed2854 100644 --- a/gnucash/report/reports/standard/new-owner-report.scm +++ b/gnucash/report/reports/standard/new-owner-report.scm @@ -60,18 +60,22 @@ (define javascript " ") diff --git a/gnucash/report/reports/standard/view-column.scm b/gnucash/report/reports/standard/view-column.scm index d73e131786..516e6cba58 100644 --- a/gnucash/report/reports/standard/view-column.scm +++ b/gnucash/report/reports/standard/view-column.scm @@ -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 diff --git a/gnucash/report/trep-engine.scm b/gnucash/report/trep-engine.scm index 098d7dc524..1708de8449 100644 --- a/gnucash/report/trep-engine.scm +++ b/gnucash/report/trep-engine.scm @@ -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))