- related to trac#916
Signed-off-by: Jakub Filak jfilak@redhat.com --- po/POTFILES.in | 1 + src/gtk-helpers/Makefile.am | 3 +- src/gtk-helpers/ask_dialogs.c | 81 ++++++++++++++++++++++++++++++++ src/gtk-helpers/internal_libreport_gtk.h | 20 ++++++++ src/gui-wizard-gtk/wizard.c | 66 ++------------------------ 5 files changed, 107 insertions(+), 64 deletions(-) create mode 100644 src/gtk-helpers/ask_dialogs.c
diff --git a/po/POTFILES.in b/po/POTFILES.in index b310941..870856c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -5,6 +5,7 @@ src/cli/cli.c src/cli/cli-report.c src/client-python/debuginfo.py src/client-python/__init__.py +src/gtk-helpers/ask_dialogs.c src/gtk-helpers/config_dialog.c src/gtk-helpers/event_config_dialog.c src/gtk-helpers/secrets.c diff --git a/src/gtk-helpers/Makefile.am b/src/gtk-helpers/Makefile.am index 0d3f9d8..b67186f 100644 --- a/src/gtk-helpers/Makefile.am +++ b/src/gtk-helpers/Makefile.am @@ -14,7 +14,8 @@ libreport_gtk_la_SOURCES = \ hyperlinks.c \ autowrapped_label.c \ workflow_config_dialog.c \ - config_dialog.c + config_dialog.c \ + ask_dialogs.c
libreport_gtk_la_CPPFLAGS = \ -I$(srcdir)/../include \ diff --git a/src/gtk-helpers/ask_dialogs.c b/src/gtk-helpers/ask_dialogs.c new file mode 100644 index 0000000..7994e1b --- /dev/null +++ b/src/gtk-helpers/ask_dialogs.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 ABRT Team + * Copyright (C) 2012 RedHat inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <internal_libreport_gtk.h> + +static void save_dialog_response(GtkDialog *dialog, gint response_id, gpointer user_data) +{ + *(gint*)user_data = response_id; +} + +/* + * We don't allow users to remember 'No' answer therefore if 'Don't ask me again' box is + * checked we have to disable 'No' button + */ +static void on_toggle_ask_yes_no_yesforever_cb(GtkToggleButton *tb, gpointer user_data) +{ + gtk_widget_set_sensitive(GTK_WIDGET(user_data), !gtk_toggle_button_get_active(tb)); +} + +/* + * Function shows a dialog with 'Yes/No' buttons and a check box allowing to + * remember the answer. The "Don't ask me again" response is stored in + * configuration file under 'key'. + */ +int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent) +{ + const char *ask_result = get_user_setting(key); + + if (ask_result && string_to_bool(ask_result) == false) + /* Do you want to be asked? -> No, I don't. Do whatever you want */ + return true; + + GtkWidget *dialog = gtk_message_dialog_new(parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + "%s", message); + + gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_YES, GTK_RESPONSE_YES); + GtkWidget *no_button = gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_NO, GTK_RESPONSE_NO); + + gint response = GTK_RESPONSE_NO; + g_signal_connect(G_OBJECT(dialog), "response", + G_CALLBACK(save_dialog_response), &response); + + GtkWidget *ask_yes_no_cb = gtk_check_button_new_with_label(_("Don't ask me again")); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + ask_yes_no_cb, TRUE, TRUE, 0); + g_signal_connect(ask_yes_no_cb, "toggled", + G_CALLBACK(on_toggle_ask_yes_no_yesforever_cb), (gpointer)no_button); + + /* Don't check the box by default. If the box is checked the 'No' button is disabled and + * we don't want to force users to click on 'Yes' button. */ + + gtk_widget_show(ask_yes_no_cb); + gtk_dialog_run(GTK_DIALOG(dialog)); + + /* the box is checked -> Don't ask me again and my response is always 'Yes' */ + set_user_setting(key, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb)) ? "no" : "yes"); + + gtk_widget_destroy(dialog); + + return response == GTK_RESPONSE_YES; +} + diff --git a/src/gtk-helpers/internal_libreport_gtk.h b/src/gtk-helpers/internal_libreport_gtk.h index c59158e..cecad6f 100644 --- a/src/gtk-helpers/internal_libreport_gtk.h +++ b/src/gtk-helpers/internal_libreport_gtk.h @@ -95,6 +95,26 @@ struct url_token #define find_url_tokens libreport_find_url_tokens GList *find_url_tokens(const char *line);
+/* Ask dialogs */ + +/* + * Runs a dialog with 'Yes'/'No' buttons and 'Don't ask me again' check box and + * waits until the dialog is closed. This variant of dialog allows user to + * click only 'Yes' button if the check box is checked and stores "no" string + * in user settings if the check box is checked. + * + * Uses libreport's user settings. Don't forget to call load_user_settings() + * before the first call of this funcion and call save_user_settings() after + * the last call of this function. + * + * @param key Key under which the response is stored. Not NULL + * @param message Displayed message. Not NULL + * @param parent Transient parent or NULL + * @returns Non 0 if the answer is "Yes"; otherwise 0 + */ +#define run_ask_yes_no_yesforever_dialog libreport_run_ask_yes_no_yesforever_dialog +int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent); + #ifdef __cplusplus } #endif diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c index 8774653..781fd57 100644 --- a/src/gui-wizard-gtk/wizard.c +++ b/src/gui-wizard-gtk/wizard.c @@ -247,11 +247,6 @@ static void remove_child_widget(GtkWidget *widget, gpointer unused) gtk_widget_destroy(widget); }
-static void save_dialog_response(GtkDialog *dialog, gint response_id, gpointer user_data) -{ - *(gint*)user_data = response_id; -} - static void on_configure_event_cb(GtkWidget *button, gpointer user_data) { char *event_name = (char *)user_data; @@ -321,67 +316,12 @@ static void update_window_title(void) free(title); }
-/* - * We don't allow users to remember 'No' answer therefore if 'Don't ask me again' box is - * checked we have to disable 'No' button - */ -static void on_toggle_ask_yes_no_save_result_cb(GtkToggleButton *tb, gpointer user_data) -{ - gtk_widget_set_sensitive(GTK_WIDGET(user_data), !gtk_toggle_button_get_active(tb)); -} - -/* - * Function shows a dialog with 'Yes/No' buttons and a check box allowing to - * remember the answer. The answer is stored in configuration file under - * 'option_name' key. - */ -static bool ask_yes_no_save_result(const char *message, const char *option_name) -{ - const char *ask_result = get_user_setting(option_name); - - if (ask_result && string_to_bool(ask_result) == false) - /* Do you want to be asked? -> No, I don't. Do whatever you want */ - return true; - - GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_wnd_assistant), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - "%s", message); - - gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_YES, GTK_RESPONSE_YES); - GtkWidget *no_button = gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_NO, GTK_RESPONSE_NO); - - gint response = GTK_RESPONSE_NO; - g_signal_connect(G_OBJECT(dialog), "response", - G_CALLBACK(save_dialog_response), &response); - - GtkWidget *ask_yes_no_cb = gtk_check_button_new_with_label(_("Don't ask me again")); - gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), - ask_yes_no_cb, TRUE, TRUE, 0); - g_signal_connect(ask_yes_no_cb, "toggled", - G_CALLBACK(on_toggle_ask_yes_no_save_result_cb), (gpointer)no_button); - - /* Don't check the box by default. If the box is checked the 'No' button is disabled and - * we don't want to force users to click on 'Yes' button. */ - - gtk_widget_show(ask_yes_no_cb); - gtk_dialog_run(GTK_DIALOG(dialog)); - - /* the box is checked -> Don't ask me again and my response is always 'Yes' */ - set_user_setting(option_name, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb)) ? "no" : "yes"); - - gtk_widget_destroy(dialog); - - return response == GTK_RESPONSE_YES; -} - static bool ask_continue_before_steal(const char *base_dir, const char *dump_dir) { char *msg = xasprintf(_("Need writable directory, but '%s' is not writable." " Move it to '%s' and operate on the moved data?"), dump_dir, base_dir); - const bool response = ask_yes_no_save_result(msg, "ask_steal_dir"); + const bool response = run_ask_yes_no_yesforever_dialog("ask_steal_dir", msg, GTK_WINDOW(g_wnd_assistant)); free(msg); return response; } @@ -1674,7 +1614,7 @@ static int run_event_gtk_ask_yes_no(const char *msg, void *args)
static int run_event_gtk_ask_yes_no_yesforever(const char *key, const char *msg, void *args) { - const int ret = ask_yes_no_save_result(msg, key); + const int ret = run_ask_yes_no_yesforever_dialog(key, msg, GTK_WINDOW(g_wnd_assistant)); log_request_response_communication(msg, ret ? "YES" : "NO", (struct analyze_event_data *)args); return ret; } @@ -2518,7 +2458,7 @@ static bool get_sensitive_data_permission(const char *event_name) char *msg = xasprintf(_("Event '%s' requires permission to send possibly sensitive data." "\nDo you want to continue?"), ec_get_screen_name(event_cfg) ? ec_get_screen_name(event_cfg) : event_name); - const bool response = ask_yes_no_save_result(msg, "ask_send_sensitive_data"); + const bool response = run_ask_yes_no_yesforever_dialog("ask_send_sensitive_data", msg, GTK_WINDOW(g_wnd_assistant)); free(msg);
return response;
- related to trac#916
Signed-off-by: Jakub Filak jfilak@redhat.com --- src/gtk-helpers/ask_dialogs.c | 67 +++++++++++++++++++++++++------- src/gtk-helpers/internal_libreport_gtk.h | 18 +++++++++ 2 files changed, 70 insertions(+), 15 deletions(-)
diff --git a/src/gtk-helpers/ask_dialogs.c b/src/gtk-helpers/ask_dialogs.c index 7994e1b..43f8f6b 100644 --- a/src/gtk-helpers/ask_dialogs.c +++ b/src/gtk-helpers/ask_dialogs.c @@ -33,18 +33,28 @@ static void on_toggle_ask_yes_no_yesforever_cb(GtkToggleButton *tb, gpointer use gtk_widget_set_sensitive(GTK_WIDGET(user_data), !gtk_toggle_button_get_active(tb)); }
-/* - * Function shows a dialog with 'Yes/No' buttons and a check box allowing to - * remember the answer. The "Don't ask me again" response is stored in - * configuration file under 'key'. - */ -int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent) +/* Reserve 7 bits for configuration of dialog version */ +typedef enum { + ASK_YES_NO_SAVE_RESULT = 0x001, + ASK_YES_NO_YESFOREVER = 0x100, +} ask_yes_no_dialog_flags; + +static int run_ask_yes_no_save_generic_result_dialog(ask_yes_no_dialog_flags flags, + const char *key, + const char *message, + GtkWindow *parent) { const char *ask_result = get_user_setting(key);
- if (ask_result && string_to_bool(ask_result) == false) - /* Do you want to be asked? -> No, I don't. Do whatever you want */ - return true; + if (ask_result) + { + const bool ret = string_to_bool(ask_result); + if (flags & ASK_YES_NO_YESFOREVER && ret == false) + /* Do you want to be asked? -> No, I don't. Do whatever you want */ + return true; + + return ret; + }
GtkWidget *dialog = gtk_message_dialog_new(parent, GTK_DIALOG_DESTROY_WITH_PARENT, @@ -62,20 +72,47 @@ int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWi GtkWidget *ask_yes_no_cb = gtk_check_button_new_with_label(_("Don't ask me again")); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), ask_yes_no_cb, TRUE, TRUE, 0); - g_signal_connect(ask_yes_no_cb, "toggled", - G_CALLBACK(on_toggle_ask_yes_no_yesforever_cb), (gpointer)no_button);
- /* Don't check the box by default. If the box is checked the 'No' button is disabled and - * we don't want to force users to click on 'Yes' button. */ + if (flags & ASK_YES_NO_YESFOREVER) + { + /* Don't check the box by default. If the box is checked the 'No' + * button is disabled and we don't want to force users to click on + * 'Yes' button. */ + g_signal_connect(ask_yes_no_cb, "toggled", + G_CALLBACK(on_toggle_ask_yes_no_yesforever_cb), (gpointer)no_button); + }
gtk_widget_show(ask_yes_no_cb); gtk_dialog_run(GTK_DIALOG(dialog));
- /* the box is checked -> Don't ask me again and my response is always 'Yes' */ - set_user_setting(key, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb)) ? "no" : "yes"); + if (flags & ASK_YES_NO_YESFOREVER) + /* the box is checked -> Don't ask me again and my response is always 'Yes' */ + set_user_setting(key, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb)) ? "no" : "yes"); + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb))) + /* the box is checked -> remember my current answer */ + set_user_setting(key, response == GTK_RESPONSE_YES ? "yes" : "no");
gtk_widget_destroy(dialog);
return response == GTK_RESPONSE_YES; }
+/* + * Function shows a dialog with 'Yes/No' buttons and a check box allowing to + * remember the answer. The "Don't ask me again" response is stored in + * configuration file under 'key'. + */ +int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent) +{ + return run_ask_yes_no_save_generic_result_dialog(ASK_YES_NO_YESFOREVER, key, message, parent); +} + +/* + * Function runs a dialog with 'Yes/No' buttons and a check box allowing to + * remember the answer. The answer is stored in configuration file under + * 'key'. + */ +int run_ask_yes_no_save_result_dialog(const char *key, const char *message, GtkWindow *parent) +{ + return run_ask_yes_no_save_generic_result_dialog(ASK_YES_NO_SAVE_RESULT, key, message, parent); +} diff --git a/src/gtk-helpers/internal_libreport_gtk.h b/src/gtk-helpers/internal_libreport_gtk.h index cecad6f..ea94837 100644 --- a/src/gtk-helpers/internal_libreport_gtk.h +++ b/src/gtk-helpers/internal_libreport_gtk.h @@ -115,6 +115,24 @@ GList *find_url_tokens(const char *line); #define run_ask_yes_no_yesforever_dialog libreport_run_ask_yes_no_yesforever_dialog int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent);
+/* + * Runs a dialog with 'Yes'/'No' buttons and 'Don't ask me again' check box and + * waits until the dialog is closed. This variant of dialog allows user to + * click both of buttons if the check box is checked and stores a string which + * corresponds to an answer. + * + * Uses libreport's user settings. Don't forget to call load_user_settings() + * before the first call of this funcion and call save_user_settings() after + * the last call of this function. + * + * @param key Key under which the response is stored. Not NULL + * @param message Displayed message. Not NULL + * @param parent Transient parent or NULL + * @returns Non 0 if the answer is "Yes"; otherwise 0 + */ +#define run_ask_yes_no_save_result_dialog libreport_run_ask_yes_no_save_result_dialog +int run_ask_yes_no_save_result_dialog(const char *key, const char *message, GtkWindow *parent); + #ifdef __cplusplus } #endif
On 12/11/2012 01:45 PM, Jakub Filak wrote:
- related to trac#916
+/* Reserve 7 bits for configuration of dialog version */
I didn't understand the above comment...
+typedef enum {
- ASK_YES_NO_SAVE_RESULT = 0x001,
It looks like you don't check this bit anywhere, you only set it sometimes. Did I miss something?
- ASK_YES_NO_YESFOREVER = 0x100,
What ASK_YES_NO_YESFOREVER means?
+} ask_yes_no_dialog_flags;
+static int run_ask_yes_no_save_generic_result_dialog(ask_yes_no_dialog_flags flags,
const char *key,
const char *message,
GtkWindow *parent)
{ const char *ask_result = get_user_setting(key);
- if (ask_result && string_to_bool(ask_result) == false)
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
- if (ask_result)
- {
const bool ret = string_to_bool(ask_result);
if (flags & ASK_YES_NO_YESFOREVER && ret == false)
I would use ()s: ((flags & ASK_YES_NO_YESFOREVER) && ret == false) there is a subtlety in C's precedence rules in these operators somewhere... I only remember that < > <= >= == != are safe, but &, <<, ? : etc - can't memorize those :)
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
return ret;
- }
+/*
- Function shows a dialog with 'Yes/No' buttons and a check box allowing to
- remember the answer. The "Don't ask me again" response is stored in
- configuration file under 'key'.
- */
The comment needs to be in *.h file. I would imagine users read _that_ file. For one, they may _miss_ *.c file on their system.
Yes, like you did it here:
--- a/src/gtk-helpers/internal_libreport_gtk.h +++ b/src/gtk-helpers/internal_libreport_gtk.h @@ -115,6 +115,24 @@ GList *find_url_tokens(const char *line); #define run_ask_yes_no_yesforever_dialog libreport_run_ask_yes_no_yesforever_dialog int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent);
+/*
- Runs a dialog with 'Yes'/'No' buttons and 'Don't ask me again' check box and
- waits until the dialog is closed. This variant of dialog allows user to
- click both of buttons if the check box is checked and stores a string which
- corresponds to an answer.
Is the answer stored always, or only if checkbox is 'checked'?
- Uses libreport's user settings. Don't forget to call load_user_settings()
- before the first call of this funcion and call save_user_settings() after
- the last call of this function.
- @param key Key under which the response is stored. Not NULL
- @param message Displayed message. Not NULL
- @param parent Transient parent or NULL
- @returns Non 0 if the answer is "Yes"; otherwise 0
- */
+#define run_ask_yes_no_save_result_dialog libreport_run_ask_yes_no_save_result_dialog +int run_ask_yes_no_save_result_dialog(const char *key, const char *message, GtkWindow *parent);
#ifdef __cplusplus } #endif
On Tuesday 11 of December 2012 17:11:06 Denys Vlasenko wrote:
On 12/11/2012 01:45 PM, Jakub Filak wrote:
- related to trac#916
+/* Reserve 7 bits for configuration of dialog version */
I didn't understand the above comment..
I wanted to explain why I use 0x100 instead of 1 << 2 as we usually do. I'm trying to anticipate future needs :) bad idea, right?
.
+typedef enum {
- ASK_YES_NO_SAVE_RESULT = 0x001,
It looks like you don't check this bit anywhere, you only set it sometimes. Did I miss something?
No, you are right. I don't check this bit anywhere, I just pass it as an argument instead of '/* flags */ 0'. This construction looks more natural to me.
- ASK_YES_NO_YESFOREVER = 0x100,
What ASK_YES_NO_YESFOREVER means?
I'm sorry for that, I though that I comment it well with run_ask_yes_no_yesforever_dialog() function. I'll add a comment here.
ask_yes_no_yesforever means that you can reply with "Yes", "No" an "Yes && Don't ask me again".
How it works?
If you check the checkbox the "No" button will be disabled and you will be able to click only the "Yes" button.
Once you answer "Yes && Don't ask me again", the dialog won't appear next time you call the function and Non 0 value is returned immediately.
+} ask_yes_no_dialog_flags;
+static int run_ask_yes_no_save_generic_result_dialog(ask_yes_no_dialog_flags flags,
const char *key,
const char *message,
GtkWindow *parent)
{ const char *ask_result = get_user_setting(key);
- if (ask_result && string_to_bool(ask_result) == false)
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
- if (ask_result)
- {
const bool ret = string_to_bool(ask_result);
if (flags & ASK_YES_NO_YESFOREVER && ret == false)
I would use ()s: ((flags & ASK_YES_NO_YESFOREVER) && ret == false) there is a subtlety in C's precedence rules in these operators somewhere... I only remember that < > <= >= == != are safe, but &, <<, ? : etc
- can't memorize those :)
will do
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
return ret;
- }
+/*
- Function shows a dialog with 'Yes/No' buttons and a check box allowing to
- remember the answer. The "Don't ask me again" response is stored in
- configuration file under 'key'.
- */
The comment needs to be in *.h file. I would imagine users read _that_ file. For one, they may _miss_ *.c file on their system.
Yes, like you did it here:
--- a/src/gtk-helpers/internal_libreport_gtk.h +++ b/src/gtk-helpers/internal_libreport_gtk.h @@ -115,6 +115,24 @@ GList *find_url_tokens(const char *line); #define run_ask_yes_no_yesforever_dialog libreport_run_ask_yes_no_yesforever_dialog int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent);
+/*
- Runs a dialog with 'Yes'/'No' buttons and 'Don't ask me again' check box and
- waits until the dialog is closed. This variant of dialog allows user to
- click both of buttons if the check box is checked and stores a string which
- corresponds to an answer.
Is the answer stored always, or only if checkbox is 'checked'?
I'll write a clearer comment.
- Uses libreport's user settings. Don't forget to call load_user_settings()
- before the first call of this funcion and call save_user_settings() after
- the last call of this function.
- @param key Key under which the response is stored. Not NULL
- @param message Displayed message. Not NULL
- @param parent Transient parent or NULL
- @returns Non 0 if the answer is "Yes"; otherwise 0
- */
+#define run_ask_yes_no_save_result_dialog libreport_run_ask_yes_no_save_result_dialog +int run_ask_yes_no_save_result_dialog(const char *key, const char *message, GtkWindow *parent);
#ifdef __cplusplus } #endif
- related to trac#916
Signed-off-by: Jakub Filak jfilak@redhat.com --- src/gtk-helpers/ask_dialogs.c | 83 ++++++++++++++++++++++++++------ src/gtk-helpers/internal_libreport_gtk.h | 18 +++++++ 2 files changed, 86 insertions(+), 15 deletions(-)
diff --git a/src/gtk-helpers/ask_dialogs.c b/src/gtk-helpers/ask_dialogs.c index 7994e1b..254ba07 100644 --- a/src/gtk-helpers/ask_dialogs.c +++ b/src/gtk-helpers/ask_dialogs.c @@ -33,18 +33,38 @@ static void on_toggle_ask_yes_no_yesforever_cb(GtkToggleButton *tb, gpointer use gtk_widget_set_sensitive(GTK_WIDGET(user_data), !gtk_toggle_button_get_active(tb)); }
-/* - * Function shows a dialog with 'Yes/No' buttons and a check box allowing to - * remember the answer. The "Don't ask me again" response is stored in - * configuration file under 'key'. - */ -int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent) +typedef enum { + ASK_YES_NO_SAVE_RESULT = 1 << 0, + + /* + * ASK_YES_NO_YESFOREVER means that you can reply with "Yes", "No" an "Yes + * && Don't ask me again". + * + * If you check the checkbox the "No" button will be disabled and you will + * be able to click only the "Yes" button. + * + * Once you answer "Yes && Don't ask me again", the dialog won't appear + * next time you call the function and Non 0 value is returned immediately + */ + ASK_YES_NO_YESFOREVER = 1 << 1, +} ask_yes_no_dialog_flags; + +static int run_ask_yes_no_save_generic_result_dialog(ask_yes_no_dialog_flags flags, + const char *key, + const char *message, + GtkWindow *parent) { const char *ask_result = get_user_setting(key);
- if (ask_result && string_to_bool(ask_result) == false) - /* Do you want to be asked? -> No, I don't. Do whatever you want */ - return true; + if (ask_result) + { + const bool ret = string_to_bool(ask_result); + if ((flags & ASK_YES_NO_YESFOREVER) && ret == false) + /* Do you want to be asked? -> No, I don't. Do whatever you want */ + return true; + + return ret; + }
GtkWidget *dialog = gtk_message_dialog_new(parent, GTK_DIALOG_DESTROY_WITH_PARENT, @@ -62,20 +82,53 @@ int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWi GtkWidget *ask_yes_no_cb = gtk_check_button_new_with_label(_("Don't ask me again")); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), ask_yes_no_cb, TRUE, TRUE, 0); - g_signal_connect(ask_yes_no_cb, "toggled", - G_CALLBACK(on_toggle_ask_yes_no_yesforever_cb), (gpointer)no_button);
- /* Don't check the box by default. If the box is checked the 'No' button is disabled and - * we don't want to force users to click on 'Yes' button. */ + if (flags & ASK_YES_NO_YESFOREVER) + { + /* Don't check the box by default. If the box is checked the 'No' + * button is disabled and we don't want to force users to click on + * 'Yes' button. */ + g_signal_connect(ask_yes_no_cb, "toggled", + G_CALLBACK(on_toggle_ask_yes_no_yesforever_cb), (gpointer)no_button); + }
gtk_widget_show(ask_yes_no_cb); gtk_dialog_run(GTK_DIALOG(dialog));
- /* the box is checked -> Don't ask me again and my response is always 'Yes' */ - set_user_setting(key, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb)) ? "no" : "yes"); + if (flags & ASK_YES_NO_YESFOREVER) + /* the box is checked -> Don't ask me again and my response is always 'Yes' */ + set_user_setting(key, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb)) ? "no" : "yes"); + else if (flags & ASK_YES_NO_SAVE_RESULT) + { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ask_yes_no_cb))) + /* the box is checked -> remember my current answer */ + set_user_setting(key, response == GTK_RESPONSE_YES ? "yes" : "no"); + } + else /* should not happen */ + error_msg("BUG:%s:%d %s() unknown type (0x%x) of ask_yes_no dialog", + __FILE__, __LINE__, __func__, flags);
gtk_widget_destroy(dialog);
return response == GTK_RESPONSE_YES; }
+/* + * Function shows a dialog with 'Yes/No' buttons and a check box allowing to + * remember the answer. The "Don't ask me again" response is stored in + * configuration file under 'key'. + */ +int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent) +{ + return run_ask_yes_no_save_generic_result_dialog(ASK_YES_NO_YESFOREVER, key, message, parent); +} + +/* + * Function runs a dialog with 'Yes/No' buttons and a check box allowing to + * remember the answer. The answer is stored in configuration file under + * 'key'. + */ +int run_ask_yes_no_save_result_dialog(const char *key, const char *message, GtkWindow *parent) +{ + return run_ask_yes_no_save_generic_result_dialog(ASK_YES_NO_SAVE_RESULT, key, message, parent); +} diff --git a/src/gtk-helpers/internal_libreport_gtk.h b/src/gtk-helpers/internal_libreport_gtk.h index cecad6f..7b2093c 100644 --- a/src/gtk-helpers/internal_libreport_gtk.h +++ b/src/gtk-helpers/internal_libreport_gtk.h @@ -115,6 +115,24 @@ GList *find_url_tokens(const char *line); #define run_ask_yes_no_yesforever_dialog libreport_run_ask_yes_no_yesforever_dialog int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent);
+/* + * Runs a dialog with 'Yes'/'No' buttons and 'Don't ask me again' check box and + * waits until the dialog is closed. This variant of dialog allows user to + * click both of buttons if the check box is checked and stores the answer in + * user settings if the check box is checked. + * + * Uses libreport's user settings. Don't forget to call load_user_settings() + * before the first call of this funcion and call save_user_settings() after + * the last call of this function. + * + * @param key Key under which the response is stored. Not NULL + * @param message Displayed message. Not NULL + * @param parent Transient parent or NULL + * @returns Non 0 if the answer is "Yes"; otherwise 0 + */ +#define run_ask_yes_no_save_result_dialog libreport_run_ask_yes_no_save_result_dialog +int run_ask_yes_no_save_result_dialog(const char *key, const char *message, GtkWindow *parent); + #ifdef __cplusplus } #endif
On 12/12/2012 11:27 AM, Jakub Filak wrote:
- related to trac#916
Signed-off-by: Jakub Filak jfilak@redhat.com
Is it a patch against some branch? I don't see src/gtk-helpers/ask_dialogs.c in main branch...
diff --git a/src/gtk-helpers/ask_dialogs.c b/src/gtk-helpers/ask_dialogs.c index 7994e1b..254ba07 100644 --- a/src/gtk-helpers/ask_dialogs.c +++ b/src/gtk-helpers/ask_dialogs.c @@ -33,18 +33,38 @@ static void on_toggle_ask_yes_no_yesforever_cb(GtkToggleButton *tb, gpointer use gtk_widget_set_sensitive(GTK_WIDGET(user_data), !gtk_toggle_button_get_active(tb)); }
-/*
- Function shows a dialog with 'Yes/No' buttons and a check box allowing to
- remember the answer. The "Don't ask me again" response is stored in
- configuration file under 'key'.
- */
-int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent) +typedef enum {
- ASK_YES_NO_SAVE_RESULT = 1 << 0,
I'd separate prefix from the remainder. Maybe with two underscores? - "ASK_YES_NO__SAVE_RESULT"?
- /*
* ASK_YES_NO_YESFOREVER means that you can reply with "Yes", "No" an "Yes
* && Don't ask me again".
*
* If you check the checkbox the "No" button will be disabled and you will
* be able to click only the "Yes" button.
*
* Once you answer "Yes && Don't ask me again", the dialog won't appear
* next time you call the function and Non 0 value is returned immediately
*/
- ASK_YES_NO_YESFOREVER = 1 << 1,
I propose to call it ASK_YES_NO__DISALLOW_SAVING_NEGATIVE (naturally, it requires ASK_YES_NO__SAVE_RESULT bit to be meaningful).
+} ask_yes_no_dialog_flags;
+static int run_ask_yes_no_save_generic_result_dialog(ask_yes_no_dialog_flags flags,
const char *key,
const char *message,
GtkWindow *parent)
{ const char *ask_result = get_user_setting(key);
- if (ask_result && string_to_bool(ask_result) == false)
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
- if (ask_result)
- {
const bool ret = string_to_bool(ask_result);
if ((flags & ASK_YES_NO_YESFOREVER) && ret == false)
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
return ret;
- }
How about making the above part simpler, like this:
const char *ask_result = get_user_setting(key); if (ask_result) return string_to_bool(ask_result);
In other words, user setting does not remember "Do you want to be asked?" bit - it remembers the actual answer ("yes" or "no"). If user setting _does not exist_, then, naturally, it means "we want to be asked".
The rest of the code will become somewhat simpler as a result, since now the meaning of user setting does not depend on whether you DISALLOW_SAVING_NEGATIVE or not.
On Wednesday 12 of December 2012 17:07:33 Denys Vlasenko wrote:
On 12/12/2012 11:27 AM, Jakub Filak wrote:
- related to trac#916
Signed-off-by: Jakub Filak jfilak@redhat.com
Is it a patch against some branch? I don't see src/gtk-helpers/ask_dialogs.c in main branch...
The previous patch added the file ... not pushed yet
diff --git a/src/gtk-helpers/ask_dialogs.c b/src/gtk-helpers/ask_dialogs.c index 7994e1b..254ba07 100644 --- a/src/gtk-helpers/ask_dialogs.c +++ b/src/gtk-helpers/ask_dialogs.c @@ -33,18 +33,38 @@ static void on_toggle_ask_yes_no_yesforever_cb(GtkToggleButton *tb, gpointer use gtk_widget_set_sensitive(GTK_WIDGET(user_data), !gtk_toggle_button_get_active(tb)); }
-/*
- Function shows a dialog with 'Yes/No' buttons and a check box allowing to
- remember the answer. The "Don't ask me again" response is stored in
- configuration file under 'key'.
- */
-int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent) +typedef enum {
- ASK_YES_NO_SAVE_RESULT = 1 << 0,
I'd separate prefix from the remainder. Maybe with two underscores? - "ASK_YES_NO__SAVE_RESULT"?
will do
- /*
* ASK_YES_NO_YESFOREVER means that you can reply with "Yes", "No" an "Yes
* && Don't ask me again".
*
* If you check the checkbox the "No" button will be disabled and you will
* be able to click only the "Yes" button.
*
* Once you answer "Yes && Don't ask me again", the dialog won't appear
* next time you call the function and Non 0 value is returned immediately
*/
- ASK_YES_NO_YESFOREVER = 1 << 1,
I propose to call it ASK_YES_NO__DISALLOW_SAVING_NEGATIVE (naturally, it requires ASK_YES_NO__SAVE_RESULT bit to be meaningful).
+} ask_yes_no_dialog_flags;
+static int run_ask_yes_no_save_generic_result_dialog(ask_yes_no_dialog_flags flags,
const char *key,
const char *message,
GtkWindow *parent)
{ const char *ask_result = get_user_setting(key);
- if (ask_result && string_to_bool(ask_result) == false)
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
- if (ask_result)
- {
const bool ret = string_to_bool(ask_result);
if ((flags & ASK_YES_NO_YESFOREVER) && ret == false)
/* Do you want to be asked? -> No, I don't. Do whatever you want */
return true;
return ret;
- }
How about making the above part simpler, like this:
const char *ask_result = get_user_setting(key); if (ask_result) return string_to_bool(ask_result);
In other words, user setting does not remember "Do you want to be asked?" bit - it remembers the actual answer ("yes" or "no"). If user setting _does not exist_, then, naturally, it means "we want to be asked".
The rest of the code will become somewhat simpler as a result, since now the meaning of user setting does not depend on whether you DISALLOW_SAVING_NEGATIVE or not.
I'd really love to do it in that way but libreport has been using this version for some time and this change would break the current user configuration.
On 12/11/2012 01:45 PM, Jakub Filak wrote:
- related to trac#916
Looks good to me.
--- a/src/gtk-helpers/internal_libreport_gtk.h +++ b/src/gtk-helpers/internal_libreport_gtk.h @@ -95,6 +95,26 @@ struct url_token #define find_url_tokens libreport_find_url_tokens GList *find_url_tokens(const char *line);
+#define run_ask_yes_no_yesforever_dialog libreport_run_ask_yes_no_yesforever_dialog +int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent);
The function name needs to be more descriptive. I don't have a really good proposal, though...
"run_ask_yes_no_dialog_with_checkbox" maybe?
On Tuesday 11 of December 2012 17:00:24 Denys Vlasenko wrote:
On 12/11/2012 01:45 PM, Jakub Filak wrote:
- related to trac#916
Looks good to me.
--- a/src/gtk-helpers/internal_libreport_gtk.h +++ b/src/gtk-helpers/internal_libreport_gtk.h @@ -95,6 +95,26 @@ struct url_token #define find_url_tokens libreport_find_url_tokens GList *find_url_tokens(const char *line);
+#define run_ask_yes_no_yesforever_dialog libreport_run_ask_yes_no_yesforever_dialog +int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWindow *parent);
The function name needs to be more descriptive. I don't have a really good proposal, though...
"run_ask_yes_no_dialog_with_checkbox" maybe?
libreport uses ask_yes_no_yesforever at many places and abrt too Should I change the string everywhere?
crash-catcher@lists.fedorahosted.org