diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/gtk.h | 1 | ||||
-rw-r--r-- | gtk/gtk.symbols | 12 | ||||
-rw-r--r-- | gtk/gtkmountoperation.c | 795 | ||||
-rw-r--r-- | gtk/gtkmountoperation.h | 80 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/testmountoperation.c | 165 |
8 files changed, 1075 insertions, 0 deletions
@@ -1,3 +1,20 @@ +2008-03-17 Christian Kellner <gicmo@gnome.org> + + Implement GtkMountOperation, a subclass of GMountOperation + to be used with gio wherever there is the need to ask the + user for credentials or questions while mounting a volume. + This is bug #522245 + + * gtk/gtkmountoperation.c: + * gtk/gtkmountoperation.h: + Implement GtkMountOperation. + + * gtk/gtk.h: Add gtkmountoperation.h + * gtk/Makefile.am: Add gtkmountoperation.[hc] + * gtk/gtk.symbols: Add symbols of GtkMountOperation. + * tests/testmountoperation.c: Test program for it. + * tests/Makefile.am: Add testmountoperation. + 2008-03-17 Emmanuele Bassi <ebassi@gnome.org> * gtk/gtkcontainer.c: Properly document diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 35ddd2db9c..3d911ddebf 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -229,6 +229,7 @@ gtk_public_h_sources = \ gtkmessagedialog.h \ gtkmisc.h \ gtkmodules.h \ + gtkmountoperation.h \ gtknotebook.h \ gtkobject.h \ gtkpagesetup.h \ @@ -489,6 +490,7 @@ gtk_base_c_sources = \ gtkmisc.c \ gtkmnemonichash.c \ gtkmodules.c \ + gtkmountoperation.c \ gtknotebook.c \ gtkobject.c \ gtkpagesetup.c \ @@ -119,6 +119,7 @@ #include <gtk/gtkmessagedialog.h> #include <gtk/gtkmisc.h> #include <gtk/gtkmodules.h> +#include <gtk/gtkmountoperation.h> #include <gtk/gtknotebook.h> #include <gtk/gtkobject.h> #include <gtk/gtkpaned.h> diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 31dc0fbdde..55dabbcbdc 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -2404,6 +2404,18 @@ gtk_misc_set_padding #endif #endif +#if IN_HEADER(__GTK_MOUNT_OPERATION_H__) +#if IN_FILE(__GTK_MOUNT_OPERATION_C__) +gtk_mount_operation_get_type G_GNUC_CONST +gtk_mount_operation_new +gtk_mount_operation_is_showing +gtk_mount_operation_set_parent +gtk_mount_operation_get_parent +gtk_mount_operation_set_screen +gtk_mount_operation_get_screen +#endif +#endif + #if IN_HEADER(__GTK_NOTEBOOK_H__) #if IN_FILE(__GTK_NOTEBOOK_C__) gtk_notebook_append_page diff --git a/gtk/gtkmountoperation.c b/gtk/gtkmountoperation.c new file mode 100644 index 0000000000..5438230441 --- /dev/null +++ b/gtk/gtkmountoperation.c @@ -0,0 +1,795 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* GTK - The GIMP Toolkit + * Copyright (C) Christian Kellner <gicmo@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <config.h> + +#include <string.h> + +#include "gtkalignment.h" +#include "gtkbox.h" +#include "gtkentry.h" +#include "gtkhbox.h" +#include "gtkintl.h" +#include "gtklabel.h" +#include "gtkvbox.h" +#include "gtkmessagedialog.h" +#include "gtkmisc.h" +#include "gtkmountoperation.h" +#include "gtkprivate.h" +#include "gtkradiobutton.h" +#include "gtkstock.h" +#include "gtktable.h" +#include "gtkwindow.h" +#include "gtkalias.h" + +/* GObject, GtkObject methods + */ +static void gtk_mount_operation_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_mount_operation_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void gtk_mount_operation_finalize (GObject *object); + +/* GMountOperation methods + */ +static void gtk_mount_operation_ask_password (GMountOperation *op, + const char *message, + const char *default_user, + const char *default_domain, + GAskPasswordFlags flags); + +static void gtk_mount_operation_ask_question (GMountOperation *op, + const char *message, + const char *choices[]); + +G_DEFINE_TYPE (GtkMountOperation, gtk_mount_operation, G_TYPE_MOUNT_OPERATION); + +enum { + PROP_0, + PROP_PARENT, + PROP_IS_SHOWING, + PROP_SCREEN + +}; + +struct GtkMountOperationPrivate { + GtkWindow *parent_window; + GtkDialog *dialog; + GdkScreen *screen; + + /* for the ask-password dialog */ + GtkWidget *entry_container; + GtkWidget *username_entry; + GtkWidget *domain_entry; + GtkWidget *password_entry; + GtkWidget *anonymous_toggle; + + GAskPasswordFlags ask_flags; + GPasswordSave password_save; + gboolean anonymous; +}; + +static void +gtk_mount_operation_finalize (GObject *object) +{ + GtkMountOperation *operation; + GtkMountOperationPrivate *priv; + + operation = GTK_MOUNT_OPERATION (object); + + priv = operation->priv; + + if (priv->parent_window) + g_object_unref (priv->parent_window); + + if (priv->screen) + g_object_unref (priv->screen); + + G_OBJECT_CLASS (gtk_mount_operation_parent_class)->finalize (object); +} + +static void +gtk_mount_operation_class_init (GtkMountOperationClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GMountOperationClass *mount_op_class; + + g_type_class_add_private (klass, sizeof (GtkMountOperationPrivate)); + + object_class->finalize = gtk_mount_operation_finalize; + object_class->get_property = gtk_mount_operation_get_property; + object_class->set_property = gtk_mount_operation_set_property; + + mount_op_class = G_MOUNT_OPERATION_CLASS (klass); + mount_op_class->ask_password = gtk_mount_operation_ask_password; + mount_op_class->ask_question = gtk_mount_operation_ask_question; + + g_object_class_install_property (object_class, + PROP_PARENT, + g_param_spec_object ("parent", + P_("Parent"), + P_("The parent window"), + GTK_TYPE_WINDOW, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_IS_SHOWING, + g_param_spec_boolean ("is-showing", + P_("Is Showing"), + P_("Are we showing a dialog"), + FALSE, + GTK_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_SCREEN, + g_param_spec_object ("screen", + P_("Screen"), + P_("The screen where this window will be displayed."), + GTK_TYPE_WINDOW, + GTK_PARAM_READWRITE)); + +} + + +static void +gtk_mount_operation_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkMountOperation *operation; + gpointer tmp; + + operation = GTK_MOUNT_OPERATION (object); + + switch (prop_id) + { + case PROP_PARENT: + tmp = g_value_get_object (value); + gtk_mount_operation_set_parent (operation, tmp); + break; + + case PROP_SCREEN: + tmp = g_value_get_object (value); + gtk_mount_operation_set_screen (operation, tmp); + break; + + case PROP_IS_SHOWING: + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_mount_operation_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkMountOperationPrivate *priv; + GtkMountOperation *operation; + + operation = GTK_MOUNT_OPERATION (object); + priv = operation->priv; + + switch (prop_id) + { + case PROP_PARENT: + g_value_set_object (value, priv->parent_window); + break; + + case PROP_IS_SHOWING: + g_value_set_boolean (value, priv->dialog != NULL); + break; + + case PROP_SCREEN: + g_value_set_object (value, priv->screen); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_mount_operation_init (GtkMountOperation *operation) +{ + operation->priv = G_TYPE_INSTANCE_GET_PRIVATE (operation, + GTK_TYPE_MOUNT_OPERATION, + GtkMountOperationPrivate); +} + +static void +remember_button_toggled (GtkWidget *widget, + GtkMountOperation *operation) +{ + GtkMountOperationPrivate *priv = operation->priv; + gpointer data; + + data = g_object_get_data (G_OBJECT (widget), "password-save"); + priv->password_save = GPOINTER_TO_INT (data); +} + +static void +pw_dialog_got_response (GtkDialog *dialog, + gint response_id, + GtkMountOperation *mount_op) +{ + GtkMountOperationPrivate *priv; + GMountOperation *op; + + priv = mount_op->priv; + op = G_MOUNT_OPERATION (mount_op); + + if (response_id == GTK_RESPONSE_OK) + { + const char *text; + + if (priv->ask_flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED) + g_mount_operation_set_anonymous (op, priv->anonymous); + + if (priv->username_entry) + { + text = gtk_entry_get_text (GTK_ENTRY (priv->username_entry)); + g_mount_operation_set_username (op, text); + } + + if (priv->domain_entry) + { + text = gtk_entry_get_text (GTK_ENTRY (priv->domain_entry)); + g_mount_operation_set_domain (op, text); + } + + if (priv->password_entry) + { + text = gtk_entry_get_text (GTK_ENTRY (priv->password_entry)); + g_mount_operation_set_password (op, text); + } + + if (priv->ask_flags & G_ASK_PASSWORD_SAVING_SUPPORTED) + g_mount_operation_set_password_save (op, priv->password_save); + + g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED); + } + else + g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED); + + priv->dialog = NULL; + g_object_notify (G_OBJECT (op), "is-showing"); + gtk_widget_destroy (GTK_WIDGET (dialog)); + g_object_unref (op); +} + +static gboolean +entry_has_input (GtkWidget *entry_widget) +{ + const char *text; + + if (entry_widget == NULL) + return TRUE; + + text = gtk_entry_get_text (GTK_ENTRY (entry_widget)); + + return text != NULL && text[0] != '\0'; +} + +static gboolean +pw_dialog_input_is_valid (GtkMountOperation *operation) +{ + GtkMountOperationPrivate *priv = operation->priv; + gboolean is_valid = TRUE; + + is_valid = entry_has_input (priv->username_entry) && + entry_has_input (priv->domain_entry) && + entry_has_input (priv->password_entry); + + return is_valid; +} + +static void +pw_dialog_verify_input (GtkEditable *editable, + GtkMountOperation *operation) +{ + GtkMountOperationPrivate *priv = operation->priv; + gboolean is_valid; + + is_valid = pw_dialog_input_is_valid (operation); + gtk_dialog_set_response_sensitive (GTK_DIALOG (priv->dialog), + GTK_RESPONSE_OK, + is_valid); +} + +static void +pw_dialog_anonymous_toggled (GtkWidget *widget, + GtkMountOperation *operation) +{ + GtkMountOperationPrivate *priv = operation->priv; + gboolean is_valid; + + priv->anonymous = widget == priv->anonymous_toggle; + + if (priv->anonymous) + is_valid = TRUE; + else + is_valid = pw_dialog_input_is_valid (operation); + + gtk_widget_set_sensitive (priv->entry_container, priv->anonymous == FALSE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (priv->dialog), + GTK_RESPONSE_OK, + is_valid); +} + + +static void +pw_dialog_cycle_focus (GtkWidget *widget, + GtkMountOperation *operation) +{ + GtkMountOperationPrivate *priv; + GtkWidget *next_widget = NULL; + + priv = operation->priv; + + if (widget == priv->username_entry) + { + if (priv->domain_entry != NULL) + next_widget = priv->domain_entry; + else if (priv->password_entry != NULL) + next_widget = priv->password_entry; + } + else if (widget == priv->domain_entry && priv->password_entry) + next_widget = priv->password_entry; + + if (next_widget) + gtk_widget_grab_focus (next_widget); + else if (pw_dialog_input_is_valid (operation)) + gtk_window_activate_default (GTK_WINDOW (priv->dialog)); +} + +static GtkWidget * +table_add_entry (GtkWidget *table, + int row, + const char *label_text, + const char *value, + gpointer user_data) +{ + GtkWidget *entry; + GtkWidget *label; + + label = gtk_label_new_with_mnemonic (label_text); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + + entry = gtk_entry_new (); + + if (value) + gtk_entry_set_text (GTK_ENTRY (entry), value); + + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach_defaults (GTK_TABLE (table), entry, + 1, 2, row, row + 1); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); + + g_signal_connect (entry, "changed", + G_CALLBACK (pw_dialog_verify_input), user_data); + + g_signal_connect (entry, "activate", + G_CALLBACK (pw_dialog_cycle_focus), user_data); + + return entry; +} + +static void +gtk_mount_operation_ask_password (GMountOperation *mount_op, + const char *message, + const char *default_user, + const char *default_domain, + GAskPasswordFlags flags) +{ + GtkMountOperation *operation; + GtkMountOperationPrivate *priv; + GtkWidget *widget; + GtkDialog *dialog; + GtkWindow *window; + GtkWidget *entry_container; + GtkWidget *hbox, *main_vbox, *vbox, *icon; + GtkWidget *table; + GtkWidget *message_label; + gboolean can_anonymous; + guint rows; + + operation = GTK_MOUNT_OPERATION (mount_op); + priv = operation->priv; + + priv->ask_flags = flags; + + widget = gtk_dialog_new (); + dialog = GTK_DIALOG (widget); + window = GTK_WINDOW (widget); + + priv->dialog = dialog; + + /* Set the dialog up with HIG properties */ + gtk_dialog_set_has_separator (dialog, FALSE); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */ + gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5); + gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6); + + gtk_window_set_resizable (window, FALSE); + gtk_window_set_icon_name (window, GTK_STOCK_DIALOG_AUTHENTICATION); + + gtk_dialog_add_buttons (dialog, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("Co_nnect"), GTK_RESPONSE_OK, + NULL); + gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK); + + /* Build contents */ + hbox = gtk_hbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + gtk_box_pack_start (GTK_BOX (dialog->vbox), hbox, TRUE, TRUE, 0); + + icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, + GTK_ICON_SIZE_DIALOG); + + gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0); + gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0); + + main_vbox = gtk_vbox_new (FALSE, 18); + gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0); + + message_label = gtk_label_new (message); + gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (message_label), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (message_label), + FALSE, FALSE, 0); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); + + can_anonymous = flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED; + + if (can_anonymous) + { + GtkWidget *anon_box; + GtkWidget *choice; + GSList *group; + + anon_box = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), anon_box, + FALSE, FALSE, 0); + + choice = gtk_radio_button_new_with_mnemonic (NULL, _("Connect _anonymously")); + gtk_box_pack_start (GTK_BOX (anon_box), + choice, + FALSE, FALSE, 0); + g_signal_connect (choice, "toggled", + G_CALLBACK (pw_dialog_anonymous_toggled), operation); + priv->anonymous_toggle = choice; + + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice)); + choice = gtk_radio_button_new_with_mnemonic (group, _("Connect as u_ser:")); + gtk_box_pack_start (GTK_BOX (anon_box), + choice, + FALSE, FALSE, 0); + g_signal_connect (choice, "toggled", + G_CALLBACK (pw_dialog_anonymous_toggled), operation); + } + + rows = 0; + + if (flags & G_ASK_PASSWORD_NEED_PASSWORD) + rows++; + + if (flags & G_ASK_PASSWORD_NEED_USERNAME) + rows++; + + if (flags &G_ASK_PASSWORD_NEED_DOMAIN) + rows++; + + /* The table that holds the entries */ + entry_container = gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + + gtk_alignment_set_padding (GTK_ALIGNMENT (entry_container), + 0, 0, can_anonymous ? 12 : 0, 0); + + gtk_box_pack_start (GTK_BOX (vbox), entry_container, + FALSE, FALSE, 0); + priv->entry_container = entry_container; + + table = gtk_table_new (rows, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 12); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (entry_container), table); + + rows = 0; + + if (flags & G_ASK_PASSWORD_NEED_USERNAME) + priv->username_entry = table_add_entry (table, rows++, _("_Username:"), + default_user, operation); + + if (flags & G_ASK_PASSWORD_NEED_DOMAIN) + priv->domain_entry = table_add_entry (table, rows++, _("_Domain:"), + default_domain, operation); + + if (flags & G_ASK_PASSWORD_NEED_PASSWORD) + { + priv->password_entry = table_add_entry (table, rows++, _("_Password:"), + NULL, operation); + gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), FALSE); + } + + if (flags & G_ASK_PASSWORD_SAVING_SUPPORTED) + { + GtkWidget *choice; + GtkWidget *remember_box; + GSList *group; + + remember_box = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), remember_box, + FALSE, FALSE, 0); + + choice = gtk_radio_button_new_with_mnemonic (NULL, _("_Forget password immediately")); + g_object_set_data (G_OBJECT (choice), "password-save", + GINT_TO_POINTER (G_PASSWORD_SAVE_NEVER)); + g_signal_connect (choice, "toggled", + G_CALLBACK (remember_button_toggled), operation); + gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0); + + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice)); + choice = gtk_radio_button_new_with_mnemonic (group, _("_Remember password until you logout")); + g_object_set_data (G_OBJECT (choice), "password-save", + GINT_TO_POINTER (G_PASSWORD_SAVE_FOR_SESSION)); + g_signal_connect (choice, "toggled", + G_CALLBACK (remember_button_toggled), operation); + gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0); + + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice)); + choice = gtk_radio_button_new_with_mnemonic (group, _("_Remember forever")); + g_object_set_data (G_OBJECT (choice), "password-save", + GINT_TO_POINTER (G_PASSWORD_SAVE_PERMANENTLY)); + g_signal_connect (choice, "toggled", + G_CALLBACK (remember_button_toggled), operation); + gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0); + } + + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (pw_dialog_got_response), operation); + + if (can_anonymous) + gtk_widget_set_sensitive (priv->entry_container, FALSE); + else if (! pw_dialog_input_is_valid (operation)) + gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, FALSE); + + g_object_notify (G_OBJECT (operation), "is-showing"); + + if (priv->parent_window == NULL && priv->screen) + gtk_window_set_screen (GTK_WINDOW (dialog), priv->screen); + + gtk_widget_show_all (GTK_WIDGET (dialog)); + + g_object_ref (operation); +} + +static void +question_dialog_button_clicked (GtkDialog *dialog, + gint button_number, + GMountOperation *op) +{ + GtkMountOperationPrivate *priv; + GtkMountOperation *operation; + + operation = GTK_MOUNT_OPERATION (op); + priv = operation->priv; + + if (button_number >= 0) + { + g_mount_operation_set_choice (op, button_number); + g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED); + } + else + g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED); + + priv->dialog = NULL; + g_object_notify (G_OBJECT (operation), "is-showing"); + gtk_widget_destroy (GTK_WIDGET (dialog)); + g_object_unref (op); +} + +static void +gtk_mount_operation_ask_question (GMountOperation *op, + const char *message, + const char *choices[]) +{ + GtkMountOperationPrivate *priv; + GtkWidget *dialog; + const char *secondary = NULL; + char *primary; + int count, len = 0; + + g_return_if_fail (GTK_IS_MOUNT_OPERATION (op)); + g_return_if_fail (message != NULL); + g_return_if_fail (choices != NULL); + + priv = GTK_MOUNT_OPERATION (op)->priv; + + primary = strstr (message, "\n"); + if (primary) + { + secondary = primary + 1; + primary = g_strndup (message, primary - message); + } + + dialog = gtk_message_dialog_new (priv->parent_window, 0, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, "%s", + primary != NULL ? primary : message); + g_free (primary); + + if (secondary) + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + "%s", secondary); + + /* First count the items in the list then + * add the buttons in reverse order */ + + while (choices[len] != NULL) + len++; + + for (count = len - 1; count >= 0; count--) + gtk_dialog_add_button (GTK_DIALOG (dialog), choices[count], count); + + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (question_dialog_button_clicked), op); + + priv->dialog = GTK_DIALOG (dialog); + g_object_notify (G_OBJECT (op), "is-showing"); + + if (priv->parent_window == NULL && priv->screen) + gtk_window_set_screen (GTK_WINDOW (dialog), priv->screen); + + gtk_widget_show (dialog); + g_object_ref (op); +} + +GMountOperation * +gtk_mount_operation_new (GtkWindow *parent) +{ + GMountOperation *mount_operation; + + mount_operation = g_object_new (GTK_TYPE_MOUNT_OPERATION, + "parent", parent, NULL); + + return mount_operation; +} + +gboolean +gtk_mount_operation_is_showing (GtkMountOperation *op) +{ + g_return_val_if_fail (GTK_IS_MOUNT_OPERATION (op), FALSE); + + return op->priv->dialog != NULL; +} + +void +gtk_mount_operation_set_parent (GtkMountOperation *op, + GtkWindow *parent) +{ + GtkMountOperationPrivate *priv; + + g_return_if_fail (GTK_IS_MOUNT_OPERATION (op)); + g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent)); + + priv = op->priv; + + if (priv->parent_window == parent) + return; + + if (priv->parent_window) + { + g_signal_handlers_disconnect_by_func (priv->parent_window, + gtk_widget_destroyed, + &priv->parent_window); + priv->parent_window = NULL; + } + + if (parent) + { + priv->parent_window = g_object_ref (parent); + + g_signal_connect (parent, "destroy", + G_CALLBACK (gtk_widget_destroyed), + &priv->parent_window); + + if (priv->dialog) + gtk_window_set_transient_for (GTK_WINDOW (priv->dialog), parent); + } + + g_object_notify (G_OBJECT (op), "parent"); +} + +GtkWindow * +gtk_mount_operation_get_parent (GtkMountOperation *op) +{ + g_return_val_if_fail (GTK_IS_MOUNT_OPERATION (op), NULL); + + return op->priv->parent_window; +} + +void +gtk_mount_operation_set_screen (GtkMountOperation *op, + GdkScreen *screen) +{ + GtkMountOperationPrivate *priv; + + g_return_if_fail (GTK_IS_MOUNT_OPERATION (op)); + g_return_if_fail (GDK_IS_SCREEN (screen)); + + priv = op->priv; + + if (priv->screen == screen) + return; + + if (priv->screen) + g_object_unref (priv->screen); + + priv->screen = g_object_ref (screen); + + if (priv->dialog) + gtk_window_set_screen (GTK_WINDOW (priv->dialog), screen); + + g_object_notify (G_OBJECT (op), "screen"); +} + +GdkScreen * +gtk_mount_operation_get_screen (GtkMountOperation *op) +{ + GtkMountOperationPrivate *priv; + + g_return_val_if_fail (GTK_IS_MOUNT_OPERATION (op), NULL); + + priv = op->priv; + + if (priv->dialog) + return gtk_window_get_screen (GTK_WINDOW (priv->dialog)); + else if (priv->parent_window) + return gtk_window_get_screen (GTK_WINDOW (priv->parent_window)); + else if (priv->screen) + return priv->screen; + else + return gdk_screen_get_default (); +} + +#define __GTK_MOUNT_OPERATION_C__ +#include "gtkaliasdef.c" diff --git a/gtk/gtkmountoperation.h b/gtk/gtkmountoperation.h new file mode 100644 index 0000000000..3fe99c5ef0 --- /dev/null +++ b/gtk/gtkmountoperation.h @@ -0,0 +1,80 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) Christian Kellner <gicmo@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __GTK_MOUNT_OPERATION_H__ +#define __GTK_MOUNT_OPERATION_H__ + +#include <glib.h> +#include <gio/gio.h> +#include <gdk/gdkscreen.h> +#include <gtk/gtkwindow.h> + +G_BEGIN_DECLS + +#define GTK_TYPE_MOUNT_OPERATION (gtk_mount_operation_get_type ()) +#define GTK_MOUNT_OPERATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_MOUNT_OPERATION, GtkMountOperation)) +#define GTK_MOUNT_OPERATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_MOUNT_OPERATION, GtkMountOperationClass)) +#define GTK_IS_MOUNT_OPERATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_MOUNT_OPERATION)) +#define GTK_IS_MOUNT_OPERATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_MOUNT_OPERATION)) +#define GTK_MOUNT_OPERATION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_MOUNT_OPERATION, GtkMountOperationClass)) + +typedef struct GtkMountOperation GtkMountOperation; +typedef struct GtkMountOperationClass GtkMountOperationClass; +typedef struct GtkMountOperationPrivate GtkMountOperationPrivate; + +struct GtkMountOperation +{ + GMountOperation parent_instance; + + GtkMountOperationPrivate *priv; +}; + +struct GtkMountOperationClass +{ + GMountOperationClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +GType gtk_mount_operation_get_type (void); +GMountOperation *gtk_mount_operation_new (GtkWindow *parent); +gboolean gtk_mount_operation_is_showing (GtkMountOperation *op); +void gtk_mount_operation_set_parent (GtkMountOperation *op, + GtkWindow *parent); +GtkWindow * gtk_mount_operation_get_parent (GtkMountOperation *op); +void gtk_mount_operation_set_screen (GtkMountOperation *op, + GdkScreen *screen); +GdkScreen *gtk_mount_operation_get_screen (GtkMountOperation *op); + +G_END_DECLS + +#endif /* __GTK_MOUNT_OPERATION_H__ */ + diff --git a/tests/Makefile.am b/tests/Makefile.am index a985187b3c..f1d6c312b9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -77,6 +77,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \ testinput \ testmenus \ testmenubars \ + testmountoperation \ testmultidisplay \ testmultiscreen \ testnotebookdnd \ @@ -150,6 +151,7 @@ testinput_DEPENDENCIES = $(TEST_DEPS) testimage_DEPENDENCIES = $(TEST_DEPS) testmenus_DEPENDENCIES = $(TEST_DEPS) testmenubars_DEPENDENCIES = $(TEST_DEPS) +testmountoperation_DEPENDENCIES = $(TEST_DEPS) testmultidisplay_DEPENDENCIES = $(TEST_DEPS) testmultiscreen_DEPENDENCIES = $(TEST_DEPS) testnotebookdnd_DEPENDENCIES = $(TEST_DEPS) @@ -203,6 +205,7 @@ testinput_LDADD = $(LDADDS) testimage_LDADD = $(LDADDS) testmenus_LDADD = $(LDADDS) testmenubars_LDADD = $(LDADDS) +testmountoperation_LDADD = $(LDADDS) testmultidisplay_LDADD = $(LDADDS) testmultiscreen_LDADD = $(LDADDS) testnotebookdnd_LDADD = $(LDADDS) diff --git a/tests/testmountoperation.c b/tests/testmountoperation.c new file mode 100644 index 0000000000..92edf3324e --- /dev/null +++ b/tests/testmountoperation.c @@ -0,0 +1,165 @@ +/* testmultidisplay.c + * Copyright (C) 2008 Christian Kellner + * Author: Christian Kellner <gicmo@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include <gtk/gtk.h> +#include <gtk/gtkmountoperation.h> + +static gboolean ask_question = FALSE; +static gboolean anonymous = FALSE; +static gboolean dont_ask_username = FALSE; +static gboolean dont_ask_domain = FALSE; +static gboolean dont_ask_password = FALSE; +static gboolean dont_save_password = FALSE; + + +static void +got_reply (GMountOperation *op, + GMountOperationResult result, + gpointer user_data) +{ + if (result == G_MOUNT_OPERATION_HANDLED) + { + + if (ask_question) + { + gint choice = g_mount_operation_get_choice (op); + g_print ("User chose: %d\n", choice); + } + else + { + if (anonymous) + g_print ("Anymous: %s\n", + g_mount_operation_get_anonymous (op) ? "true" : "false"); + + if (!dont_ask_username) + g_print ("Username: %s\n", g_mount_operation_get_username (op)); + + if (!dont_ask_domain) + g_print ("Domain: %s\n", g_mount_operation_get_domain (op)); + + if (!dont_ask_password) + g_print ("Password: %s\n", g_mount_operation_get_password (op)); + + if (!dont_save_password) + { + GPasswordSave pw_save; + + pw_save = g_mount_operation_get_password_save (op); + g_print ("Save password: "); + switch (pw_save) + { + case G_PASSWORD_SAVE_NEVER: + g_print ("never"); + break; + + case G_PASSWORD_SAVE_FOR_SESSION: + g_print ("session"); + break; + + case G_PASSWORD_SAVE_PERMANENTLY: + g_print ("forever"); + break; + + default: + g_assert_not_reached (); + } + g_print ("\n"); + } + } + } + else if (result == G_MOUNT_OPERATION_ABORTED) + g_print ("Operation aborted.\n"); + else if (G_MOUNT_OPERATION_UNHANDLED) + g_assert_not_reached (); + + gtk_main_quit (); +} + +int +main (int argc, char *argv[]) +{ + GMountOperation *op; + gboolean force_rtl = FALSE; + GError *error = NULL; + GOptionEntry options[] = { + { "ask-question", 'q', 0, G_OPTION_ARG_NONE, &ask_question, "Ask a question not a password.", NULL }, + { "right-to-left", 'r', 0, G_OPTION_ARG_NONE, &force_rtl, "Force right-to-left layout.", NULL }, + { "anonymous", 'a', 0, G_OPTION_ARG_NONE, &anonymous, "Anonymous login allowed.", NULL }, + { "no-username", 'u', 0, G_OPTION_ARG_NONE, &dont_ask_username, "Don't ask for the username.", NULL }, + { "no-password", 'p', 0, G_OPTION_ARG_NONE, &dont_ask_password, "Don't ask for the password.", NULL }, + { "no-domain", 'd', 0, G_OPTION_ARG_NONE, &dont_ask_domain, "Don't ask for the domain.", NULL }, + { "no-pw-save", 's', 0, G_OPTION_ARG_NONE, &dont_save_password, "Don't show password save options.", NULL }, + { NULL } + }; + + if (!gtk_init_with_args (&argc, &argv, "", options, NULL, &error)) + { + g_print ("Failed to parse args: %s\n", error->message); + g_error_free (error); + return 1; + } + + if (force_rtl) + gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL); + + op = gtk_mount_operation_new (NULL); + + g_signal_connect (op, "reply", G_CALLBACK (got_reply), NULL); + + if (ask_question) + { + static const char *choices[] = { + "Yes", "No", "Sauerkraut", NULL + }; + + g_signal_emit_by_name (op, "ask_question", "Foo\nbar", choices); + } + else + { + GAskPasswordFlags flags; + + flags = 0; + + if (!dont_ask_password) + flags |= G_ASK_PASSWORD_NEED_PASSWORD; + + if (!dont_ask_username) + flags |= G_ASK_PASSWORD_NEED_USERNAME; + + if (!dont_ask_domain) + flags |= G_ASK_PASSWORD_NEED_DOMAIN; + + if (anonymous) + flags |= G_ASK_PASSWORD_ANONYMOUS_SUPPORTED; + + if (!dont_save_password) + flags |= G_ASK_PASSWORD_SAVING_SUPPORTED; + + g_signal_emit_by_name (op, "ask_password", + argc > 1 ? argv[1] : "Credentials needed", + argc > 2 ? argv[2] : "default user", + argc > 3 ? argv[3] : "default domain", + flags); + } + + gtk_main (); + return 0; +} |