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 - + + +