/* * Copyright (C) 2000 Marco Pesenti Gritti * * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ephy-glade.h" #include "PromptService.h" #include "nsCOMPtr.h" #include "nsIFactory.h" #include "nsString.h" #include "nsReadableUtils.h" #include "nsIServiceManager.h" #include "nsXPComFactory.h" #include "MozillaPrivate.h" #include "nsIPromptService.h" #include "nsIUnicodeEncoder.h" #include #include #include #include #include #include /* local function prototypes */ static void set_title (GtkWidget *dialog, const PRUnichar *title); static void set_label_text (GtkWidget *label, const PRUnichar *text); static void set_check_button_text (GtkWidget *check_button, const PRUnichar *text); static void set_check_button (GtkWidget *button, PRBool *value); static void set_check_button_size_to_label (GtkWidget *check_button, GtkWidget *label); static void set_editable (GtkWidget *entry, PRUnichar **text); static void get_check_button (GtkWidget *button, PRBool *value); static void get_editable (GtkWidget *editable, PRUnichar **text); /** * class CPromptService: an GNOME implementation of prompt dialogs for * Mozilla */ class CPromptService: public nsIPromptService { public: CPromptService(); virtual ~CPromptService(); NS_DECL_ISUPPORTS NS_DECL_NSIPROMPTSERVICE private: nsresult AddButton (GtkWidget *dialog, char type, const PRUnichar *title, int id); }; NS_IMPL_ISUPPORTS1 (CPromptService, nsIPromptService) /** * CPromptService::CPromptService: constructor */ CPromptService::CPromptService () { NS_INIT_ISUPPORTS(); } /** * CPromptService::~CPromptService: destructor */ CPromptService::~CPromptService () { } /** * CPromptService::Alert: show an alert box */ NS_IMETHODIMP CPromptService::Alert (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text) { GtkWidget *dialog; GtkWidget *gparent; gparent = MozillaFindGtkParent (parent); const nsACString &msg = NS_ConvertUCS2toUTF8 (text); dialog = gtk_message_dialog_new (GTK_WINDOW(gparent), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", PromiseFlatCString(msg).get ()); set_title (dialog, dialogTitle); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); return NS_OK; } /** * CPromptService::AlertCheck: show an alert box with a checkbutton, * (typically for things like "dont show this warning again") */ NS_IMETHODIMP CPromptService::AlertCheck (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, const PRUnichar *checkMsg, PRBool *checkValue) { GtkWidget *dialog; GtkWidget *gparent; GtkWidget *check_button; gparent = MozillaFindGtkParent (parent); const nsACString &msg = NS_ConvertUCS2toUTF8 (text); dialog = gtk_message_dialog_new (GTK_WINDOW(gparent), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", PromiseFlatCString(msg).get ()); check_button = gtk_check_button_new_with_label (""); gtk_widget_show (check_button); gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), check_button, FALSE, FALSE, 5); set_check_button_text (check_button, checkMsg); set_check_button (check_button, checkValue); set_title (dialog, dialogTitle); gtk_dialog_run (GTK_DIALOG (dialog)); get_check_button (check_button, checkValue); gtk_widget_destroy (dialog); return NS_OK; } /** * CPromptService::Confirm: for simple yes/no dialogs */ NS_IMETHODIMP CPromptService::Confirm (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, PRBool *_retval) { GtkWidget *dialog; GtkWidget *gparent; int res; gparent = MozillaFindGtkParent (parent); const nsACString &msg = NS_ConvertUCS2toUTF8 (text); dialog = gtk_message_dialog_new (GTK_WINDOW(gparent), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", PromiseFlatCString(msg).get ()); set_title (dialog, dialogTitle); res = gtk_dialog_run (GTK_DIALOG (dialog)); *_retval = (res == GTK_RESPONSE_YES); gtk_widget_destroy (dialog); return NS_OK; } /** * CPromptService::Confirm: for simple yes/no dialogs, with an additional * check button */ NS_IMETHODIMP CPromptService::ConfirmCheck (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, const PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval) { GtkWidget *dialog; GtkWidget *gparent; GtkWidget *check_button; int res; gparent = MozillaFindGtkParent (parent); const nsACString &msg = NS_ConvertUCS2toUTF8 (text); dialog = gtk_message_dialog_new (GTK_WINDOW(gparent), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", PromiseFlatCString(msg).get ()); check_button = gtk_check_button_new_with_label (""); gtk_widget_show (check_button); gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), check_button, FALSE, FALSE, 5); set_check_button_text (check_button, checkMsg); set_check_button (check_button, checkValue); set_title (dialog, dialogTitle); res = gtk_dialog_run (GTK_DIALOG (dialog)); *_retval = (res == GTK_RESPONSE_YES); get_check_button (check_button, checkValue); gtk_widget_destroy (dialog); return NS_OK; } NS_IMETHODIMP CPromptService::AddButton (GtkWidget *dialog, char type, const PRUnichar *title, int id) { const char *btitle; const nsACString &utf8string = NS_ConvertUCS2toUTF8 (title); switch (type) { case BUTTON_TITLE_OK: btitle = GTK_STOCK_OK; break; case BUTTON_TITLE_CANCEL: btitle = GTK_STOCK_CANCEL; break; case BUTTON_TITLE_YES: btitle = GTK_STOCK_YES; break; case BUTTON_TITLE_NO: btitle = GTK_STOCK_NO; break; case BUTTON_TITLE_SAVE: btitle = _("Save"); break; case BUTTON_TITLE_REVERT: btitle = _("Revert"); break; case BUTTON_TITLE_DONT_SAVE: btitle = _("Don't save"); break; case BUTTON_TITLE_IS_STRING: btitle = NULL; break; default: return NS_ERROR_FAILURE; } gtk_dialog_add_button (GTK_DIALOG(dialog), btitle ? btitle : PromiseFlatCString(utf8string).get(), id); return NS_OK; } /** * CPromptService::ConfirmEx: For fancy confirmation dialogs */ NS_IMETHODIMP CPromptService::ConfirmEx (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, PRUint32 buttonFlags, const PRUnichar *button0Title, const PRUnichar *button1Title, const PRUnichar *button2Title, const PRUnichar *checkMsg, PRBool *checkValue, PRInt32 *buttonPressed) { GtkWidget *dialog; GtkWidget *gparent; GtkWidget *check_button = NULL; int ret; gparent = MozillaFindGtkParent (parent); const nsACString &msg = NS_ConvertUCS2toUTF8 (text); dialog = gtk_message_dialog_new (GTK_WINDOW(gparent), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", PromiseFlatCString(msg).get ()); set_title (dialog, dialogTitle); if (checkMsg) { check_button = gtk_check_button_new_with_label (""); gtk_widget_show (check_button); gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), check_button, FALSE, FALSE, 5); set_check_button_text (check_button, checkMsg); set_check_button (check_button, checkValue); } AddButton (dialog, (buttonFlags >> 16) & 0xFF, button2Title, 2); AddButton (dialog, (buttonFlags >> 8) & 0xFF, button1Title, 1); AddButton (dialog, buttonFlags & 0xFF, button0Title, 0); gtk_dialog_set_default_response (GTK_DIALOG(dialog), 0); /* make a suitable sound */ gnome_triggers_vdo ("", "generic", NULL); /* run dialog and capture return values */ ret = gtk_dialog_run (GTK_DIALOG (dialog)); /* handle return values */ if (checkMsg) { get_check_button (check_button, checkValue); } *buttonPressed = ret; /* done */ gtk_widget_destroy (dialog); return NS_OK; } /** * CPromptService::Prompt: show a prompt for text, with a checkbutton */ NS_IMETHODIMP CPromptService::Prompt (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, PRUnichar **value, const PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval) { GtkWidget *dialog; GtkWidget *entry; GtkWidget *label; GtkWidget *check_button; GtkWidget *gparent; GladeXML *gxml; gint ret; /* build and show the dialog */ gxml = ephy_glade_widget_new ("prompts.glade", "prompt_dialog", &dialog, NULL); entry = glade_xml_get_widget (gxml, "entry"); label = glade_xml_get_widget (gxml, "label"); check_button = glade_xml_get_widget (gxml, "check_button"); g_object_unref (G_OBJECT (gxml)); /* parent the dialog */ gparent = MozillaFindGtkParent (parent); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gparent)); /* set dynamic attributes */ set_title (dialog, dialogTitle); set_label_text (label, text); set_check_button_text (check_button, checkMsg); set_editable (entry, value); set_check_button (check_button, checkValue); set_check_button_size_to_label (check_button, label); /* make a suitable sound */ /* NB: should be question, but this is missing in many * of the current gnome sound packages that I've tried... */ gnome_triggers_vdo ("", "generic", NULL); /* run dialog and capture return values */ ret = gtk_dialog_run (GTK_DIALOG (dialog)); /* handle return values */ get_check_button (check_button, checkValue); get_editable (entry, value); *_retval = (ret == GTK_RESPONSE_OK); /* done */ gtk_widget_destroy (dialog); return NS_OK; } /** * CPromptService::PromptUsernameAndPassword: show a prompt for username * and password with an additional check button. */ NS_IMETHODIMP CPromptService::PromptUsernameAndPassword (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, PRUnichar **username, PRUnichar **password, const PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval) { GtkWidget *dialog; GtkWidget *check_button; GtkWidget *label; GtkWidget *username_entry; GtkWidget *password_entry; GtkWidget *gparent; GladeXML *gxml; gint ret; /* build and show the dialog */ gxml = ephy_glade_widget_new ("prompts.glade", "prompt_user_pass_dialog", &dialog, NULL); check_button = glade_xml_get_widget (gxml, "check_button"); label = glade_xml_get_widget (gxml, "label"); username_entry = glade_xml_get_widget (gxml, "username_entry"); password_entry = glade_xml_get_widget (gxml, "password_entry"); g_object_unref (G_OBJECT (gxml)); /* parent the dialog */ gparent = MozillaFindGtkParent (parent); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gparent)); /* set dynamic attributes */ set_title (dialog, dialogTitle); set_check_button_text (check_button, checkMsg); set_editable (username_entry, username); set_editable (password_entry, password); set_check_button (check_button, checkValue); set_label_text (label, text); set_check_button_size_to_label (check_button, label); /* make a suitable sound */ gnome_triggers_vdo ("", "question", NULL); /* run dialog and capture return values */ ret = gtk_dialog_run (GTK_DIALOG (dialog)); /* handle return values */ get_check_button (check_button, checkValue); get_editable (username_entry, username); get_editable (password_entry, password); *_retval = (ret == GTK_RESPONSE_OK); /* done */ gtk_widget_destroy (dialog); return NS_OK; } /** * CPromptService::PromptPassword: show a prompt for just * a password with an additional check button. */ NS_IMETHODIMP CPromptService::PromptPassword (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, PRUnichar **password, const PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval) { GtkWidget *dialog; GtkWidget *label; GtkWidget *check_button; GtkWidget *password_entry; GtkWidget *gparent; GladeXML *gxml; gint ret; /* build and show the dialog */ gxml = ephy_glade_widget_new ("prompts.glade", "prompt_pass_dialog", &dialog, NULL); check_button = glade_xml_get_widget (gxml, "check_button"); label = glade_xml_get_widget (gxml, "label"); password_entry = glade_xml_get_widget (gxml, "password_entry"); g_object_unref (G_OBJECT (gxml)); /* parent the dialog */ gparent = MozillaFindGtkParent (parent); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gparent)); /* set dynamic attributes */ set_title (dialog, dialogTitle); set_check_button_text (check_button, checkMsg); set_editable (password_entry, password); set_check_button (check_button, checkValue); set_label_text (label, text); set_check_button_size_to_label (check_button, label); /* make a suitable sound */ gnome_triggers_vdo ("", "question", NULL); /* run dialog and capture return values */ ret = gtk_dialog_run (GTK_DIALOG (dialog)); /* handle return values */ get_check_button (check_button, checkValue); get_editable (password_entry, password); *_retval = (ret == GTK_RESPONSE_OK); /* done */ gtk_widget_destroy (dialog); return NS_OK; } /** * CPromptService::Select: */ NS_IMETHODIMP CPromptService::Select (nsIDOMWindow *parent, const PRUnichar *dialogTitle, const PRUnichar *text, PRUint32 count, const PRUnichar **selectList, PRInt32 *outSelection, PRBool *_retval) { GtkWidget *dialog; GtkWidget *gparent; GtkWidget *label; GladeXML *gxml; GtkWidget *treeview; gint ret; /* build and show the dialog */ gxml = ephy_glade_widget_new ("prompts.glade", "select_dialog", &dialog, NULL); treeview = glade_xml_get_widget (gxml, "treeview"); label = glade_xml_get_widget (gxml, "label"); g_object_unref (G_OBJECT (gxml)); /* parent the dialog */ gparent = MozillaFindGtkParent (parent); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gparent)); /* set dynamic attributes */ set_title (dialog, dialogTitle); set_label_text (label, text); /* setup treeview */ GtkCellRenderer *renderer; GtkListStore *liststore; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; gtk_tree_view_set_reorderable (GTK_TREE_VIEW(treeview), TRUE); liststore = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); model = GTK_TREE_MODEL (liststore); gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), model); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), FALSE); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview), 0, "Items", renderer, "text", 0, NULL); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview)); for (PRUint32 i = 0 ; i < count ; i++) { char *itemText = ToNewCString(NS_ConvertUCS2toUTF8 (selectList[i])); gtk_list_store_append (GTK_LIST_STORE (model), &iter); gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, itemText, 1, i, -1); nsMemory::Free(itemText); } gtk_tree_model_get_iter_first (model, &iter); gtk_tree_selection_select_iter (selection, &iter); /* make a suitable sound */ gnome_triggers_vdo ("", "question", NULL); /* run dialog and capture return values */ ret = gtk_dialog_run (GTK_DIALOG (dialog)); /* handle return values */ if (gtk_tree_selection_get_selected (selection, &model, &iter)) { GValue val = {0, }; gtk_tree_model_get_value (model, &iter, 1, &val); *outSelection = g_value_get_int (&val); *_retval = (ret == GTK_RESPONSE_OK) ? PR_TRUE : PR_FALSE; } else { *_retval = PR_FALSE; } gtk_widget_destroy (dialog); return NS_OK; } NS_DEF_FACTORY (CPromptService, CPromptService); /** * NS_NewPromptServiceFactory: */ nsresult NS_NewPromptServiceFactory(nsIFactory** aFactory) { NS_ENSURE_ARG_POINTER(aFactory); *aFactory = nsnull; nsCPromptServiceFactory *result = new nsCPromptServiceFactory; if (result == NULL) { return NS_ERROR_OUT_OF_MEMORY; } NS_ADDREF(result); *aFactory = result; return NS_OK; } /** * set_title: set a dialog title to a unicode string */ static void set_title (GtkWidget *dialog, const PRUnichar *title) { const nsACString &utf8string = NS_ConvertUCS2toUTF8 (title); /* set it */ gtk_window_set_title (GTK_WINDOW (dialog), (title == NULL ? N_("Epiphany") : PromiseFlatCString(utf8string).get())); } /** * set_label_text: set a labels text to a unicode string */ static void set_label_text (GtkWidget *label, const PRUnichar *text) { const nsACString &utf8string = NS_ConvertUCS2toUTF8 (text); /* set it */ gtk_label_set_text (GTK_LABEL (label), PromiseFlatCString(utf8string).get()); } /** * set_check_button_text: set a check buttons text to a unicode string */ static void set_check_button_text (GtkWidget *check_button, const PRUnichar *text) { const nsACString &utf8string = NS_ConvertUCS2toUTF8 (text); /* set it */ gtk_label_set_text (GTK_LABEL (GTK_BIN (check_button)->child), PromiseFlatCString(utf8string).get()); } /** * set_check_button: set a togglebutton to an initial state */ static void set_check_button (GtkWidget *button, PRBool *value) { /* check pointer is valid */ if (value == NULL) { gtk_widget_hide (GTK_WIDGET (button)); return; } /* set the value of the check button */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), *value); } /** * se_check_button_size_to_label: sync text widgets sizes */ static void set_check_button_size_to_label (GtkWidget *check_button, GtkWidget *label) { GtkRequisition r, label_r; gtk_widget_size_request (check_button, &r); gtk_widget_size_request (label, &label_r); if (r.width <= label_r.width) return; gtk_widget_set_size_request (label, r.width, -1); } /** * set_editable: set an editable to a unicode string */ static void set_editable (GtkWidget *entry, PRUnichar **text) { const nsACString &utf8string = NS_ConvertUCS2toUTF8 (*text); /* set this string value in the widget */ gtk_entry_set_text (GTK_ENTRY (entry), PromiseFlatCString(utf8string).get()); } /** * get_check_button: get value of a toggle button and store it in a PRBool */ static void get_check_button (GtkWidget *button, PRBool *value) { /* check we can write */ if (value == NULL) { return; } /* set the value from the check button */ *value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); } /** * get_editable: get a string from an editable and store it as unicode */ static void get_editable (GtkWidget *editable, PRUnichar **text) { char *edited; /* check we can write */ if (text == NULL) { return; } /* get the text */ edited = gtk_editable_get_chars (GTK_EDITABLE (editable), 0, -1); /* decode and set it as the return value */ *text = ToNewUnicode(NS_ConvertUTF8toUCS2(edited)); }