From 5ad584ca3b67236c563f5da25f935ee9f188592e Mon Sep 17 00:00:00 2001 From: Robert Fewell <14uBobIT@gmail.com> Date: Sun, 22 Jul 2018 12:36:35 +0100 Subject: [PATCH] Change the Options dialogue to use GtkWindow Change the report / book options dialogue from a GtkDialog to GtkWindow. This removes the need for setting the transient parent which allows the dialogue to be placed behind the main application when changing values making it easier to see the result. --- gnucash/gnome-utils/dialog-options.c | 184 ++++++++++++------ .../org.gnucash.dialogs.gschema.xml.in | 11 ++ gnucash/gtkbuilder/dialog-options.glade | 39 ++-- 3 files changed, 155 insertions(+), 79 deletions(-) diff --git a/gnucash/gnome-utils/dialog-options.c b/gnucash/gnome-utils/dialog-options.c index f981c5b087..6a78c4097e 100644 --- a/gnucash/gnome-utils/dialog-options.c +++ b/gnucash/gnome-utils/dialog-options.c @@ -70,6 +70,8 @@ static QofLogModule log_module = GNC_MOD_GUI; #define DIALOG_OPTIONS_CM_CLASS "dialog-options" #define DIALOG_BOOK_OPTIONS_CM_CLASS "dialog-book-options" +#define GNC_PREFS_GROUP "dialogs.options" + /* * Point where preferences switch control method from a set of * notebook tabs to a list. @@ -86,7 +88,7 @@ static int gain_loss_accounts_in_filter = 0; struct gnc_option_win { - GtkWidget * dialog; + GtkWidget * window; GtkWidget * notebook; GtkWidget * page_list_view; GtkWidget * page_list; @@ -107,6 +109,9 @@ struct gnc_option_win /* Hold on to this to unregister the right class */ const char *component_class; + + /* widget being destroyed */ + gboolean destroyed; }; typedef enum @@ -150,8 +155,6 @@ static currency_accounting_data *book_currency_data = NULL; static GNCOptionWinCallback global_help_cb = NULL; gpointer global_help_cb_data = NULL; -void gnc_options_dialog_response_cb(GtkDialog *dialog, gint response, - GNCOptionWin *window); static void gnc_options_dialog_reset_cb(GtkWidget * w, gpointer data); void gnc_options_dialog_list_select_cb (GtkTreeSelection *selection, gpointer data); @@ -172,16 +175,42 @@ gnc_option_get_gtk_widget (GNCOption *option) static void gnc_options_dialog_changed_internal (GtkWidget *widget, gboolean sensitive) { - GtkDialog *dialog; - - while (widget && !GTK_IS_DIALOG(widget)) + while (widget && !GTK_IS_WINDOW(widget)) widget = gtk_widget_get_parent(widget); if (widget == NULL) return; - dialog = GTK_DIALOG(widget); - gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, sensitive); - gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, sensitive); + /* find the ok and cancel buttons, we know where they will be so do it + this way as opposed to using gtk_container_foreach, much less iteration */ + if (GTK_IS_CONTAINER(widget)) + { + GList *children = gtk_container_get_children(GTK_CONTAINER(widget)); + for (GList *it = children; it; it = it->next) + { + if (GTK_IS_BOX (GTK_WIDGET(it->data))) + { + GList *children = gtk_container_get_children(GTK_CONTAINER(it->data)); + for (GList *it = children; it; it = it->next) + { + if (GTK_IS_BUTTON_BOX (GTK_WIDGET(it->data))) + { + GList *children = gtk_container_get_children(GTK_CONTAINER(it->data)); + for (GList *it = children; it; it = it->next) + { + if (g_strcmp0 (gtk_widget_get_name(GTK_WIDGET(it->data)), "ok_button") == 0) + gtk_widget_set_sensitive (GTK_WIDGET(it->data), sensitive); + + if (g_strcmp0 (gtk_widget_get_name(GTK_WIDGET(it->data)), "apply_button") == 0) + gtk_widget_set_sensitive (GTK_WIDGET(it->data), sensitive); + } + g_list_free (children); + } + } + g_list_free (children); + } + } + g_list_free (children); + } } void @@ -189,7 +218,7 @@ gnc_options_dialog_changed (GNCOptionWin *win) { if (!win) return; - gnc_options_dialog_changed_internal (win->dialog, TRUE); + gnc_options_dialog_changed_internal (win->window, TRUE); } void @@ -1968,15 +1997,15 @@ gnc_options_dialog_build_contents_full (GNCOptionWin *propertybox, gtk_tree_selection_select_iter (selection, &iter); gtk_notebook_set_current_page(GTK_NOTEBOOK(propertybox->notebook), default_page); } - gnc_options_dialog_changed_internal(propertybox->dialog, FALSE); + gnc_options_dialog_changed_internal(propertybox->window, FALSE); if (show_dialog) - gtk_widget_show(propertybox->dialog); + gtk_widget_show(propertybox->window); } GtkWidget * gnc_options_dialog_widget(GNCOptionWin * win) { - return win->dialog; + return win->window; } GtkWidget * @@ -1991,42 +2020,62 @@ gnc_options_dialog_notebook(GNCOptionWin * win) return win->notebook; } -void -gnc_options_dialog_response_cb(GtkDialog *dialog, gint response, GNCOptionWin *window) +static void +gnc_options_dialog_help_button_cb(GtkWidget * widget, GNCOptionWin *win) { - GNCOptionWinCallback close_cb; + if (win->help_cb) + (win->help_cb)(win, win->help_cb_data); +} - switch (response) +static void +gnc_options_dialog_cancel_button_cb(GtkWidget * widget, GNCOptionWin *win) +{ + if (win->close_cb) + (win->close_cb)(win, win->close_cb_data); + else + gtk_widget_hide(win->window); +} + +static void +gnc_options_dialog_apply_button_cb(GtkWidget * widget, GNCOptionWin *win) +{ + GNCOptionWinCallback close_cb = win->close_cb; + + win->close_cb = NULL; + if (win->apply_cb) + win->apply_cb (win, win->apply_cb_data); + win->close_cb = close_cb; + gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(win->window)); + gnc_options_dialog_changed_internal (win->window, FALSE); +} + +static void +gnc_options_dialog_ok_button_cb(GtkWidget * widget, GNCOptionWin *win) +{ + GNCOptionWinCallback close_cb = win->close_cb; + + win->close_cb = NULL; + if (win->apply_cb) + win->apply_cb (win, win->apply_cb_data); + win->close_cb = close_cb; + + gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(win->window)); + + if (win->close_cb) + (win->close_cb)(win, win->close_cb_data); + else + gtk_widget_hide(win->window); +} + +static void +gnc_options_dialog_destroy_cb (GtkWidget *object, GNCOptionWin *win) +{ + if (!win) return; + + if (win->destroyed == FALSE) { - case GTK_RESPONSE_HELP: - if (window->help_cb) - (window->help_cb)(window, window->help_cb_data); - break; - - case GTK_RESPONSE_OK: - case GTK_RESPONSE_APPLY: - close_cb = window->close_cb; - window->close_cb = NULL; - if (window->apply_cb) - window->apply_cb (window, window->apply_cb_data); - window->close_cb = close_cb; - if (response == GTK_RESPONSE_APPLY) - { - gnc_options_dialog_changed_internal (window->dialog, FALSE); - break; - } - /* fall through */ - - default: - if (window->close_cb) - { - (window->close_cb)(window, window->close_cb_data); - } - else - { - gtk_widget_hide(window->dialog); - } - break; + if (win->close_cb) + (win->close_cb)(win, win->close_cb_data); } } @@ -2043,7 +2092,7 @@ gnc_options_dialog_reset_cb(GtkWidget * w, gpointer data) section = (GNCOptionSection*)val; gnc_option_db_section_reset_widgets (section); - gnc_options_dialog_changed_internal (win->dialog, TRUE); + gnc_options_dialog_changed_internal (win->window, TRUE); } void @@ -2091,8 +2140,8 @@ gnc_options_register_stocks (void) static void component_close_handler (gpointer data) { - GNCOptionWin *window = data; - gtk_dialog_response(GTK_DIALOG(window->dialog), GTK_RESPONSE_CANCEL); + GNCOptionWin *win = data; + gnc_options_dialog_cancel_button_cb (NULL, win); } static void @@ -2152,16 +2201,17 @@ gnc_options_dialog_new_modal(gboolean modal, gchar *title, GtkBuilder *builder; GtkWidget *hbox; gint component_id; + GtkWidget *button; retval = g_new0(GNCOptionWin, 1); builder = gtk_builder_new(); - gnc_builder_add_from_file (builder, "dialog-options.glade", "gnucash_options_dialog"); - retval->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "gnucash_options_dialog")); + gnc_builder_add_from_file (builder, "dialog-options.glade", "gnucash_options_window"); + retval->window = GTK_WIDGET(gtk_builder_get_object (builder, "gnucash_options_window")); retval->page_list = GTK_WIDGET(gtk_builder_get_object (builder, "page_list_scroll")); // Set the style context for this dialog so it can be easily manipulated with css - gnc_widget_set_style_context (GTK_WIDGET(retval->dialog), "GncOptionsDialog"); - gtk_window_set_transient_for (GTK_WINDOW (retval->dialog), parent); + gnc_widget_set_style_context (GTK_WIDGET(retval->window), "GncOptionsDialog"); + /* Page List */ { GtkTreeView *view; @@ -2189,13 +2239,23 @@ gnc_options_dialog_new_modal(gboolean modal, gchar *title, gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); g_signal_connect (selection, "changed", G_CALLBACK (gnc_options_dialog_list_select_cb), retval); - } + button = GTK_WIDGET(gtk_builder_get_object (builder, "helpbutton")); + g_signal_connect(button, "clicked", G_CALLBACK(gnc_options_dialog_help_button_cb), retval); + button = GTK_WIDGET(gtk_builder_get_object (builder, "cancelbutton")); + g_signal_connect(button, "clicked", G_CALLBACK(gnc_options_dialog_cancel_button_cb), retval); + button = GTK_WIDGET(gtk_builder_get_object (builder, "applybutton")); + g_signal_connect(button, "clicked", G_CALLBACK(gnc_options_dialog_apply_button_cb), retval); + button = GTK_WIDGET(gtk_builder_get_object (builder, "okbutton")); + g_signal_connect(button, "clicked", G_CALLBACK(gnc_options_dialog_ok_button_cb), retval); + gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, retval); + gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(retval->window)); + if (title) - gtk_window_set_title(GTK_WINDOW(retval->dialog), title); + gtk_window_set_title(GTK_WINDOW(retval->window), title); /* modal */ if (modal == TRUE) @@ -2229,20 +2289,25 @@ gnc_options_dialog_new_modal(gboolean modal, gchar *title, GNC_ID_ACCOUNT, QOF_EVENT_MODIFY | QOF_EVENT_DESTROY); } + + g_signal_connect (retval->window, "destroy", + G_CALLBACK(gnc_options_dialog_destroy_cb), retval); + g_object_unref(G_OBJECT(builder)); + retval->destroyed = FALSE; return retval; } /* Creates a new GNCOptionWin structure, but assumes you have your own dialog widget you want to plugin */ GNCOptionWin * -gnc_options_dialog_new_w_dialog(gchar *title, GtkWidget *dialog) +gnc_options_dialog_new_w_dialog(gchar *title, GtkWidget *window) { GNCOptionWin * retval; retval = g_new0(GNCOptionWin, 1); - retval->dialog = dialog; + retval->window = window; return retval; } @@ -2286,9 +2351,10 @@ gnc_options_dialog_destroy(GNCOptionWin * win) gnc_unregister_gui_component_by_data(win->component_class, win); - gtk_widget_destroy(win->dialog); + win->destroyed = TRUE; + gtk_widget_destroy(win->window); - win->dialog = NULL; + win->window = NULL; win->notebook = NULL; win->apply_cb = NULL; win->help_cb = NULL; diff --git a/gnucash/gschemas/org.gnucash.dialogs.gschema.xml.in b/gnucash/gschemas/org.gnucash.dialogs.gschema.xml.in index 3d9670049f..7736671e2f 100644 --- a/gnucash/gschemas/org.gnucash.dialogs.gschema.xml.in +++ b/gnucash/gschemas/org.gnucash.dialogs.gschema.xml.in @@ -21,6 +21,7 @@ + @@ -245,4 +246,14 @@ followed by the width and height of the window. + + + + (-1,-1,-1,-1) + Last window position and size + This setting describes the size and position of the window when it was last closed. + The numbers are the X and Y coordinates of the top left corner of the window + followed by the width and height of the window. + + diff --git a/gnucash/gtkbuilder/dialog-options.glade b/gnucash/gtkbuilder/dialog-options.glade index ae7435e877..a30f3fccc8 100644 --- a/gnucash/gtkbuilder/dialog-options.glade +++ b/gnucash/gtkbuilder/dialog-options.glade @@ -1,27 +1,25 @@ - + - + False - GnuCash Options 640 480 - dialog - - - + + True False vertical - - + + True False end - + _Help + help_button True True True @@ -32,11 +30,13 @@ False False 0 + True - + _Cancel + cancel_button True True True @@ -53,6 +53,7 @@ _Apply + apply_button True True True @@ -67,8 +68,9 @@ - + _OK + ok_button True True True @@ -91,7 +93,7 @@ - + True False @@ -105,7 +107,7 @@ True True - + @@ -139,11 +141,8 @@ - - helpbutton1 - cancelbutton1 - applybutton - okbutton1 - + + +