[gthumb] do not allow the user to create catalogs with a / in the name



commit f8b1898a99de9bbceab59efafa255ac97f801c31
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Jul 14 20:17:41 2011 +0200

    do not allow the user to create catalogs with a / in the name
    
    [bug #652482]

 extensions/catalogs/actions.c            |  178 +++++++++++++++----
 extensions/catalogs/dlg-add-to-catalog.c |  197 ++++++++++++++-------
 gthumb/Makefile.am                       |    2 +
 gthumb/gth-request-dialog.c              |  287 ++++++++++++++++++++++++++++++
 gthumb/gth-request-dialog.h              |   70 +++++++
 gthumb/gtk-utils.c                       |   49 ++---
 gthumb/gtk-utils.h                       |    2 +
 7 files changed, 653 insertions(+), 132 deletions(-)
---
diff --git a/extensions/catalogs/actions.c b/extensions/catalogs/actions.c
index daa720c..012060e 100644
--- a/extensions/catalogs/actions.c
+++ b/extensions/catalogs/actions.c
@@ -66,27 +66,44 @@ gth_browser_activate_action_edit_remove_from_catalog (GtkAction  *action,
 }
 
 
-void
-gth_browser_activate_action_catalog_new (GtkAction  *action,
-					 GthBrowser *browser)
+static void
+catalog_new_dialog_response_cb (GtkWidget *dialog,
+				int        response_id,
+				gpointer   user_data)
 {
+	GthBrowser    *browser = user_data;
 	char          *name;
 	GthFileData   *selected_parent;
 	GFile         *parent;
 	GthFileSource *file_source;
 	GFile         *gio_parent;
+	char          *display_name;
 	GError        *error = NULL;
 	GFile         *gio_file;
 
-	name = _gtk_request_dialog_run (GTK_WINDOW (browser),
-				        GTK_DIALOG_MODAL,
-				        _("Enter the catalog name: "),
-				        "",
-				        1024,
-				        GTK_STOCK_CANCEL,
-				        _("C_reate"));
-	if (name == NULL)
+	if (response_id != GTK_RESPONSE_OK) {
+		gtk_widget_destroy (dialog);
 		return;
+	}
+
+	name = gth_request_dialog_get_normalized_text (GTH_REQUEST_DIALOG (dialog));
+	if (_g_utf8_all_spaces (name)) {
+		g_free (name);
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("No name specified"));
+		return;
+	}
+
+	if (g_regex_match_simple ("/", name, 0, 0)) {
+		char *message;
+
+		message = g_strdup_printf (_("Invalid name. The following characters are not allowed: %s"), "/");
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, message);
+
+		g_free (message);
+		g_free (name);
+
+		return;
+	}
 
 	selected_parent = gth_browser_get_folder_popup_file_data (browser);
 	if (selected_parent != NULL) {
@@ -108,34 +125,75 @@ gth_browser_activate_action_catalog_new (GtkAction  *action,
 
 	file_source = gth_main_get_file_source (parent);
 	gio_parent = gth_file_source_to_gio_file (file_source, parent);
-	gio_file = _g_file_create_unique (gio_parent, name, ".catalog", &error);
+	display_name = g_strconcat (name, ".catalog", NULL);
+	gio_file = g_file_get_child_for_display_name (gio_parent, display_name, &error);
 	if (gio_file != NULL) {
-		GFile *file;
-		GList *list;
-
-		file = gth_catalog_file_from_gio_file (gio_file, NULL);
-		list = g_list_prepend (NULL, file);
-		gth_monitor_folder_changed (gth_main_get_default_monitor (),
-					    parent,
-					    list,
-					    GTH_MONITOR_EVENT_CREATED);
+		GFileOutputStream *stream;
+
+		stream = g_file_create (gio_file, G_FILE_CREATE_NONE, NULL, &error);
+		if (stream != NULL) {
+			GFile *file;
+			GList *list;
+
+			file = gth_catalog_file_from_gio_file (gio_file, NULL);
+			list = g_list_prepend (NULL, file);
+			gth_monitor_folder_changed (gth_main_get_default_monitor (),
+						    parent,
+						    list,
+						    GTH_MONITOR_EVENT_CREATED);
+
+			g_list_free (list);
+			g_object_unref (file);
+			g_object_unref (stream);
+		}
+
+		g_object_unref (gio_file);
+	}
 
-		g_list_free (list);
-		g_object_unref (file);
+	if (error != NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("Name already used"));
+		else
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, error->message);
+		g_clear_error (&error);
 	}
 	else
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (browser), _("Could not create the catalog"), &error);
+		gtk_widget_destroy (dialog);
 
-	g_object_unref (gio_file);
+	g_free (display_name);
 	g_object_unref (gio_parent);
 	g_object_unref (file_source);
+	g_free (name);
 }
 
 
 void
-gth_browser_activate_action_catalog_new_library (GtkAction  *action,
-						 GthBrowser *browser)
+gth_browser_activate_action_catalog_new (GtkAction  *action,
+					 GthBrowser *browser)
+{
+	GtkWidget *dialog;
+
+	dialog = gth_request_dialog_new (GTK_WINDOW (browser),
+					 GTK_DIALOG_MODAL,
+					 _("New catalog"),
+					 _("Enter the catalog name:"),
+					 GTK_STOCK_CANCEL,
+					 _("C_reate"));
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (catalog_new_dialog_response_cb),
+			  browser);
+
+	gtk_widget_show (dialog);
+}
+
+
+static void
+new_library_dialog_response_cb (GtkWidget *dialog,
+				int        response_id,
+				gpointer   user_data)
 {
+	GthBrowser    *browser = user_data;
 	char          *name;
 	GthFileData   *selected_parent;
 	GFile         *parent;
@@ -144,15 +202,29 @@ gth_browser_activate_action_catalog_new_library (GtkAction  *action,
 	GError        *error = NULL;
 	GFile         *gio_file;
 
-	name = _gtk_request_dialog_run (GTK_WINDOW (browser),
-				        GTK_DIALOG_MODAL,
-				        _("Enter the library name: "),
-				        "",
-				        1024,
-				        GTK_STOCK_CANCEL,
-				        _("C_reate"));
-	if (name == NULL)
+	if (response_id != GTK_RESPONSE_OK) {
+		gtk_widget_destroy (dialog);
 		return;
+	}
+
+	name = gth_request_dialog_get_normalized_text (GTH_REQUEST_DIALOG (dialog));
+	if (_g_utf8_all_spaces (name)) {
+		g_free (name);
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("No name specified"));
+		return;
+	}
+
+	if (g_regex_match_simple ("/", name, 0, 0)) {
+		char *message;
+
+		message = g_strdup_printf (_("Invalid name. The following characters are not allowed: %s"), "/");
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, message);
+
+		g_free (message);
+		g_free (name);
+
+		return;
+	}
 
 	selected_parent = gth_browser_get_folder_popup_file_data (browser);
 	if (selected_parent != NULL) {
@@ -174,8 +246,8 @@ gth_browser_activate_action_catalog_new_library (GtkAction  *action,
 
 	file_source = gth_main_get_file_source (parent);
 	gio_parent = gth_file_source_to_gio_file (file_source, parent);
-	gio_file = _g_directory_create_unique (gio_parent, name, "", &error);
-	if (gio_file != NULL) {
+	gio_file = g_file_get_child_for_display_name (gio_parent, name, &error);
+	if (g_file_make_directory (gio_file, NULL, &error)) {
 		GFile *file;
 		GList *list;
 
@@ -189,12 +261,42 @@ gth_browser_activate_action_catalog_new_library (GtkAction  *action,
 		g_list_free (list);
 		g_object_unref (file);
 	}
+
+	if (error != NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("Name already used"));
+		else
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, error->message);
+		g_clear_error (&error);
+	}
 	else
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (browser), _("Could not create the library"), &error);
+		gtk_widget_destroy (dialog);
 
 	g_object_unref (gio_file);
 	g_object_unref (gio_parent);
 	g_object_unref (file_source);
+	g_free (name);
+}
+
+
+void
+gth_browser_activate_action_catalog_new_library (GtkAction  *action,
+						 GthBrowser *browser)
+{
+	GtkWidget *dialog;
+
+	dialog = gth_request_dialog_new (GTK_WINDOW (browser),
+					 GTK_DIALOG_MODAL,
+					 _("New library"),
+					 _("Enter the library name:"),
+					 GTK_STOCK_CANCEL,
+					 _("C_reate"));
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (new_library_dialog_response_cb),
+			  browser);
+
+	gtk_widget_show (dialog);
 }
 
 
diff --git a/extensions/catalogs/dlg-add-to-catalog.c b/extensions/catalogs/dlg-add-to-catalog.c
index f622421..3063afc 100644
--- a/extensions/catalogs/dlg-add-to-catalog.c
+++ b/extensions/catalogs/dlg-add-to-catalog.c
@@ -250,25 +250,42 @@ new_catalog_metadata_ready_cb (GObject  *object,
 
 
 static void
-new_catalog_button_clicked_cb (GtkWidget  *widget,
-		       	       DialogData *data)
+new_catalog_dialog_response_cb (GtkWidget *dialog,
+				int        response_id,
+				gpointer   user_data)
 {
+	DialogData  *data = user_data;
 	char        *name;
 	GthFileData *selected_parent;
 	GFile       *parent;
 	GFile       *gio_parent;
+	char        *display_name;
 	GError      *error = NULL;
 	GFile       *gio_file;
 
-	name = _gtk_request_dialog_run (GTK_WINDOW (data->dialog),
-				        GTK_DIALOG_MODAL,
-				        _("Enter the catalog name: "),
-				        "",
-				        1024,
-				        GTK_STOCK_CANCEL,
-				        _("C_reate"));
-	if (name == NULL)
+	if (response_id != GTK_RESPONSE_OK) {
+		gtk_widget_destroy (dialog);
 		return;
+	}
+
+	name = gth_request_dialog_get_normalized_text (GTH_REQUEST_DIALOG (dialog));
+	if (_g_utf8_all_spaces (name)) {
+		g_free (name);
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("No name specified"));
+		return;
+	}
+
+	if (g_regex_match_simple ("/", name, 0, 0)) {
+		char *message;
+
+		message = g_strdup_printf (_("Invalid name. The following characters are not allowed: %s"), "/");
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, message);
+
+		g_free (message);
+		g_free (name);
+
+		return;
+	}
 
 	selected_parent = gth_folder_tree_get_selected_or_parent (GTH_FOLDER_TREE (data->source_tree));
 	if (selected_parent != NULL) {
@@ -291,33 +308,73 @@ new_catalog_button_clicked_cb (GtkWidget  *widget,
 	_g_object_unref (data->catalog_source);
 	data->catalog_source = gth_main_get_file_source (parent);
 	gio_parent = gth_file_source_to_gio_file (data->catalog_source, parent);
-	gio_file = _g_file_create_unique (gio_parent, name, ".catalog", &error);
+	display_name = g_strconcat (name, ".catalog", NULL);
+	gio_file = g_file_get_child_for_display_name (gio_parent, display_name, &error);
 	if (gio_file != NULL) {
-		GFile *file;
+		GFileOutputStream *stream;
 
-		_g_object_unref (data->new_catalog);
-		file = gth_catalog_file_from_gio_file (gio_file, NULL);
-		data->new_catalog = gth_file_data_new (file, NULL);
-		gth_file_source_read_metadata (data->catalog_source,
-					       data->new_catalog,
-					       "*",
-					       new_catalog_metadata_ready_cb,
-					       data);
+		stream = g_file_create (gio_file, G_FILE_CREATE_NONE, NULL, &error);
+		if (stream != NULL) {
+			GFile *file;
 
-		g_object_unref (file);
+			_g_object_unref (data->new_catalog);
+			file = gth_catalog_file_from_gio_file (gio_file, NULL);
+			data->new_catalog = gth_file_data_new (file, NULL);
+			gth_file_source_read_metadata (data->catalog_source,
+						       data->new_catalog,
+						       "*",
+						       new_catalog_metadata_ready_cb,
+						       data);
+
+			g_object_unref (file);
+			g_object_unref (stream);
+		}
+
+		g_object_unref (gio_file);
+	}
+
+	if (error != NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("Name already used"));
+		else
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, error->message);
+		g_clear_error (&error);
 	}
 	else
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not create the catalog"), &error);
+		gtk_widget_destroy (dialog);
 
-	g_object_unref (gio_file);
+	g_free (display_name);
 	g_object_unref (gio_parent);
 }
 
 
 static void
-new_library_button_clicked_cb (GtkWidget  *widget,
+new_catalog_button_clicked_cb (GtkWidget  *widget,
 		       	       DialogData *data)
 {
+	GtkWidget *dialog;
+
+	dialog = gth_request_dialog_new (GTK_WINDOW (data->dialog),
+					 GTK_DIALOG_MODAL,
+					 _("New catalog"),
+					 _("Enter the catalog name:"),
+					 GTK_STOCK_CANCEL,
+					 _("C_reate"));
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (new_catalog_dialog_response_cb),
+			  data);
+
+	gtk_widget_show (dialog);
+}
+
+
+static void
+new_library_dialog_response_cb (GtkWidget *dialog,
+				int        response_id,
+				gpointer   user_data)
+{
+	DialogData    *data = user_data;
 	char          *name;
 	GthFileData   *selected_parent;
 	GFile         *parent;
@@ -326,15 +383,29 @@ new_library_button_clicked_cb (GtkWidget  *widget,
 	GError        *error = NULL;
 	GFile         *gio_file;
 
-	name = _gtk_request_dialog_run (GTK_WINDOW (data->dialog),
-					GTK_DIALOG_MODAL,
-					_("Enter the library name: "),
-					"",
-					1024,
-					GTK_STOCK_CANCEL,
-					_("C_reate"));
-	if (name == NULL)
+	if (response_id != GTK_RESPONSE_OK) {
+		gtk_widget_destroy (dialog);
 		return;
+	}
+
+	name = gth_request_dialog_get_normalized_text (GTH_REQUEST_DIALOG (dialog));
+	if (_g_utf8_all_spaces (name)) {
+		g_free (name);
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("No name specified"));
+		return;
+	}
+
+	if (g_regex_match_simple ("/", name, 0, 0)) {
+		char *message;
+
+		message = g_strdup_printf (_("Invalid name. The following characters are not allowed: %s"), "/");
+		gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, message);
+
+		g_free (message);
+		g_free (name);
+
+		return;
+	}
 
 	selected_parent = gth_folder_tree_get_selected_or_parent (GTH_FOLDER_TREE (data->source_tree));
 	if (selected_parent != NULL) {
@@ -357,7 +428,7 @@ new_library_button_clicked_cb (GtkWidget  *widget,
 	file_source = gth_main_get_file_source (parent);
 	gio_parent = gth_file_source_to_gio_file (file_source, parent);
 	gio_file = _g_directory_create_unique (gio_parent, name, "", &error);
-	if (gio_file != NULL) {
+	if (g_file_make_directory (gio_file, NULL, &error)) {
 		GFile *file;
 		GList *list;
 
@@ -371,44 +442,42 @@ new_library_button_clicked_cb (GtkWidget  *widget,
 		g_list_free (list);
 		g_object_unref (file);
 	}
+
+	if (error != NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, _("Name already used"));
+		else
+			gth_request_dialog_set_info_text (GTH_REQUEST_DIALOG (dialog), GTK_MESSAGE_ERROR, error->message);
+		g_clear_error (&error);
+	}
 	else
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not create the library"), &error);
+		gtk_widget_destroy (dialog);
 
 	g_object_unref (gio_file);
 	g_object_unref (gio_parent);
 	g_object_unref (file_source);
+	g_free (name);
+}
 
-	/*
-
-	selected_catalog = gth_folder_tree_get_selected (GTH_FOLDER_TREE (data->source_tree));
-	parent = get_catalog_parent (selected_catalog->file);
-	new_library = g_file_get_child_for_display_name (parent, name, &error);
-
-	if ((new_library != NULL) && (strchr (display_name, '/') != NULL)) {
-		error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, _("The name \"%s\" is not valid because it contains the character \"/\". " "Please use a different name."), display_name);
-		g_object_unref (new_library);
-		new_library = NULL;
-	}
-
-	if (error == NULL) {
-		GFile *gio_file;
-
-		gio_file = gth_file_source_to_gio_file (data->file_source, new_library);
-		g_file_make_directory (new_library, NULL, &error);
-
-		g_object_unref (gio_file);
-	}
-
-	if (error != NULL)
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not create a new library"), &error);
 
-	if (new_library != NULL)
-		g_object_unref (new_library);
-	g_object_unref (parent);
-	g_object_unref (selected_catalog);
-	g_free (name);
+static void
+new_library_button_clicked_cb (GtkWidget  *widget,
+		       	       DialogData *data)
+{
+	GtkWidget *dialog;
+
+	dialog = gth_request_dialog_new (GTK_WINDOW (data->dialog),
+					 GTK_DIALOG_MODAL,
+					 _("New library"),
+					 _("Enter the library name:"),
+					 GTK_STOCK_CANCEL,
+					 _("C_reate"));
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (new_library_dialog_response_cb),
+			  data);
 
-	*/
+	gtk_widget_show (dialog);
 }
 
 
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index ff9b278..90569f2 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -90,6 +90,7 @@ PUBLIC_HEADER_FILES = 					\
 	gth-pixbuf-saver.h				\
 	gth-preferences.h				\
 	gth-progress-dialog.h				\
+	gth-request-dialog.h				\
 	gth-screensaver.h				\
 	gth-sidebar.h					\
 	gth-statusbar.h					\
@@ -216,6 +217,7 @@ gthumb_SOURCES = 					\
 	gth-pixbuf-saver.c				\
 	gth-preferences.c				\
 	gth-progress-dialog.c				\
+	gth-request-dialog.c				\
 	gth-screensaver.c				\
 	gth-sidebar.c					\
 	gth-source-tree.c				\
diff --git a/gthumb/gth-request-dialog.c b/gthumb/gth-request-dialog.c
new file mode 100644
index 0000000..d04a8df
--- /dev/null
+++ b/gthumb/gth-request-dialog.c
@@ -0,0 +1,287 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 Free Software Foundation, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include "gth-request-dialog.h"
+#include "gtk-utils.h"
+
+
+#define REQUEST_ENTRY_WIDTH_IN_CHARS 40
+
+
+static gpointer gth_request_dialog_parent_class = NULL;
+
+
+struct _GthRequestDialogPrivate {
+	GtkWidget *entry;
+	GtkWidget *infobar;
+	GtkWidget *info_label;
+};
+
+
+static void
+gth_request_dialog_finalize (GObject *base)
+{
+	/* GthRequestDialog *self = (GthRequestDialog *) base; */
+
+	G_OBJECT_CLASS (gth_request_dialog_parent_class)->finalize (base);
+}
+
+
+static void
+gth_request_dialog_class_init (GthRequestDialogClass *klass)
+{
+	gth_request_dialog_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GthRequestDialogPrivate));
+
+	G_OBJECT_CLASS (klass)->finalize = gth_request_dialog_finalize;
+}
+
+
+static void
+gth_request_dialog_init (GthRequestDialog *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_REQUEST_DIALOG, GthRequestDialogPrivate);
+
+	gtk_window_set_title (GTK_WINDOW (self), "");
+	gtk_window_set_resizable (GTK_WINDOW (self), TRUE);
+}
+
+
+GType
+gth_request_dialog_get_type (void)
+{
+	static GType type = 0;
+
+	if (type == 0) {
+		static const GTypeInfo g_define_type_info = {
+			sizeof (GthRequestDialogClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gth_request_dialog_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			sizeof (GthRequestDialog),
+			0,
+			(GInstanceInitFunc) gth_request_dialog_init,
+			NULL
+		};
+		type = g_type_register_static (GTK_TYPE_DIALOG,
+					       "GthRequestDialog",
+					       &g_define_type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+static void
+_gth_request_dialog_construct (GthRequestDialog *self,
+			       GtkWindow        *parent,
+			       GtkDialogFlags    flags,
+			       const char       *title,
+			       const char       *prompt,
+			       const char       *cancel_button_text,
+			       const char       *ok_button_text)
+{
+	GtkWidget     *title_label;
+	PangoAttrList *attributes;
+	GtkWidget     *title_container;
+	GtkWidget     *prompt_label;
+	GtkWidget     *image;
+	GtkWidget     *hbox;
+	GtkWidget     *vbox;
+	GtkWidget     *button;
+
+	if (parent)
+		gtk_window_set_transient_for (GTK_WINDOW (self), parent);
+
+	if (flags & GTK_DIALOG_MODAL)
+		gtk_window_set_modal (GTK_WINDOW (self), TRUE);
+
+	if (flags & GTK_DIALOG_DESTROY_WITH_PARENT)
+		gtk_window_set_destroy_with_parent (GTK_WINDOW (self), TRUE);
+
+	gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
+
+	/* Add label and image */
+
+	image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
+	gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+
+	title_label = gtk_label_new (title);
+
+	attributes = pango_attr_list_new ();
+	pango_attr_list_insert (attributes, pango_attr_size_new (15000));
+	gtk_label_set_attributes (GTK_LABEL (title_label), attributes);
+	pango_attr_list_unref (attributes);
+
+	gtk_label_set_line_wrap (GTK_LABEL (title_label), TRUE);
+	gtk_label_set_selectable (GTK_LABEL (title_label), FALSE);
+	gtk_misc_set_alignment (GTK_MISC (title_label), 0.0, 0.5);
+
+	prompt_label = gtk_label_new (prompt);
+	gtk_label_set_line_wrap (GTK_LABEL (prompt_label), TRUE);
+	gtk_label_set_selectable (GTK_LABEL (prompt_label), FALSE);
+	gtk_misc_set_alignment (GTK_MISC (prompt_label), 0.0, 0.5);
+
+	self->priv->entry = gtk_entry_new ();
+	gtk_entry_set_width_chars (GTK_ENTRY (self->priv->entry), REQUEST_ENTRY_WIDTH_IN_CHARS);
+	gtk_entry_set_activates_default (GTK_ENTRY (self->priv->entry), TRUE);
+
+	self->priv->infobar = gtk_info_bar_new ();
+
+	self->priv->info_label = gtk_label_new ("");
+	gtk_label_set_line_wrap (GTK_LABEL (self->priv->info_label), TRUE);
+	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (self->priv->infobar))), self->priv->info_label);
+
+	hbox = gtk_hbox_new (FALSE, 6);
+	vbox = gtk_vbox_new (FALSE, 6);
+
+	gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
+	gtk_box_set_spacing (GTK_BOX (hbox), 12);
+	gtk_box_set_spacing (GTK_BOX (vbox), 6);
+
+	title_container = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+	gtk_alignment_set_padding (GTK_ALIGNMENT (title_container), 0, 12, 0, 0);
+	gtk_container_add (GTK_CONTAINER (title_container), title_label);
+
+	gtk_box_pack_start (GTK_BOX (vbox), title_container,
+			    TRUE, TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), prompt_label,
+			    TRUE, TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), self->priv->entry,
+			    FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), self->priv->infobar,
+			    FALSE, FALSE, 0);
+
+	gtk_box_pack_start (GTK_BOX (hbox), image,
+			    FALSE, FALSE, 0);
+
+	gtk_box_pack_start (GTK_BOX (hbox), vbox,
+			    TRUE, TRUE, 0);
+
+	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))),
+			    hbox,
+			    FALSE, FALSE, 0);
+
+	gtk_widget_show_all (hbox);
+	gtk_widget_hide (self->priv->infobar);
+
+	/* Add buttons */
+
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_CANCEL, cancel_button_text);
+	gtk_dialog_add_action_widget (GTK_DIALOG (self),
+				      button,
+				      GTK_RESPONSE_CANCEL);
+
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_OK, ok_button_text);
+	gtk_dialog_add_action_widget (GTK_DIALOG (self),
+				      button,
+				      GTK_RESPONSE_OK);
+
+	gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+}
+
+
+GtkWidget *
+gth_request_dialog_new (GtkWindow      *parent,
+		    	GtkDialogFlags  flags,
+		    	const char     *message,
+		    	const char     *secondary_message,
+		    	const char     *cancel_button_text,
+		    	const char     *ok_button_text)
+{
+	GtkWidget *self;
+
+	self = g_object_new (GTH_TYPE_REQUEST_DIALOG, NULL);
+	_gth_request_dialog_construct (GTH_REQUEST_DIALOG (self),
+				       parent,
+				       flags,
+				       message,
+				       secondary_message,
+				       cancel_button_text,
+				       ok_button_text);
+
+	return self;
+}
+
+
+GtkWidget *
+gth_request_dialog_get_entry (GthRequestDialog *self)
+{
+	return self->priv->entry;
+}
+
+
+char *
+gth_request_dialog_get_normalized_text (GthRequestDialog *self)
+{
+	char       *result = NULL;
+	const char *text;
+
+	text = gtk_entry_get_text (GTK_ENTRY (self->priv->entry));
+	if ((text != NULL) && (strlen (text) > 0))
+		/* Normalize unicode text to "NFC" form for consistency. */
+		result = g_utf8_normalize (text, -1, G_NORMALIZE_NFC);
+	else
+		result = NULL;
+
+	return result;
+}
+
+
+GtkWidget *
+gth_request_dialog_get_info_bar (GthRequestDialog *self)
+{
+	return self->priv->infobar;
+}
+
+
+GtkWidget *
+gth_request_dialog_get_info_label (GthRequestDialog *self)
+{
+	return self->priv->info_label;
+}
+
+
+void
+gth_request_dialog_set_info_text (GthRequestDialog *self,
+				  GtkMessageType    message_type,
+				  const char       *text)
+{
+	gtk_info_bar_set_message_type (GTK_INFO_BAR (self->priv->infobar), message_type);
+	gtk_label_set_text (GTK_LABEL (self->priv->info_label), text);
+	gtk_widget_show (self->priv->infobar);
+}
+
+
+void
+gth_request_dialog_set_info_markup (GthRequestDialog *self,
+				    GtkMessageType    message_type,
+				    const char       *markup)
+{
+	gtk_info_bar_set_message_type (GTK_INFO_BAR (self->priv->infobar), message_type);
+	gtk_label_set_markup (GTK_LABEL (self->priv->info_label), markup);
+	gtk_widget_show (self->priv->infobar);
+}
diff --git a/gthumb/gth-request-dialog.h b/gthumb/gth-request-dialog.h
new file mode 100644
index 0000000..3e674a1
--- /dev/null
+++ b/gthumb/gth-request-dialog.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 The Free Software Foundation, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_REQUEST_DIALOG_H
+#define GTH_REQUEST_DIALOG_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_REQUEST_DIALOG            (gth_request_dialog_get_type ())
+#define GTH_REQUEST_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_REQUEST_DIALOG, GthRequestDialog))
+#define GTH_REQUEST_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_REQUEST_DIALOG, GthRequestDialogClass))
+#define GTH_IS_REQUEST_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_REQUEST_DIALOG))
+#define GTH_IS_REQUEST_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_REQUEST_DIALOG))
+#define GTH_REQUEST_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTH_TYPE_REQUEST_DIALOG, GthRequestDialogClass))
+
+typedef struct _GthRequestDialog        GthRequestDialog;
+typedef struct _GthRequestDialogClass   GthRequestDialogClass;
+typedef struct _GthRequestDialogPrivate GthRequestDialogPrivate;
+
+struct _GthRequestDialog {
+	GtkDialog parent_instance;
+	GthRequestDialogPrivate *priv;
+};
+
+struct _GthRequestDialogClass {
+	GtkDialogClass parent_class;
+};
+
+GType       gth_request_dialog_get_type              (void);
+GtkWidget * gth_request_dialog_new                   (GtkWindow        *parent,
+		    	    	    	              GtkDialogFlags    flags,
+		    	    	    	              const char       *message,
+		    	    	    	              const char       *secondary_message,
+		    	    	    	              const char       *cancel_button_text,
+		    	    	    	              const char       *ok_button_text);
+GtkWidget * gth_request_dialog_get_entry             (GthRequestDialog *dialog);
+char *      gth_request_dialog_get_normalized_text   (GthRequestDialog *dialog);
+GtkWidget * gth_request_dialog_get_info_bar          (GthRequestDialog *dialog);
+GtkWidget * gth_request_dialog_get_info_label        (GthRequestDialog *dialog);
+void        gth_request_dialog_set_info_text         (GthRequestDialog *dialog,
+					              GtkMessageType    message_type,
+					              const char       *text);
+void        gth_request_dialog_set_info_markup       (GthRequestDialog *dialog,
+					              GtkMessageType    message_type,
+					              const char       *markup);
+
+G_END_DECLS
+
+#endif /* GTH_REQUEST_DIALOG_H */
+
diff --git a/gthumb/gtk-utils.c b/gthumb/gtk-utils.c
index fa9fb9a..e31195c 100644
--- a/gthumb/gtk-utils.c
+++ b/gthumb/gtk-utils.c
@@ -25,18 +25,15 @@
 #include "gtk-utils.h"
 #include "pixbuf-utils.h"
 
-#define REQUEST_ENTRY_WIDTH 220
+#define REQUEST_ENTRY_WIDTH_IN_CHARS 40
 
 
-static GtkWidget *
-create_button (const char *stock_id,
-	       const char *text)
+GtkWidget *
+_gtk_button_new_from_stock_with_text (const char *stock_id,
+				      const char *text)
 {
 	GtkWidget    *button;
-	GtkWidget    *hbox;
 	GtkWidget    *image;
-	GtkWidget    *label;
-	GtkWidget    *align;
 	const char   *label_text;
 	gboolean      text_is_stock;
 	GtkStockItem  stock_item;
@@ -46,28 +43,20 @@ create_button (const char *stock_id,
 	if (gtk_stock_lookup (text, &stock_item)) {
 		label_text = stock_item.label;
 		text_is_stock = TRUE;
-	} else {
+	}
+	else {
 		label_text = text;
 		text_is_stock = FALSE;
 	}
 
-	if (text_is_stock)
-		image = gtk_image_new_from_stock (text, GTK_ICON_SIZE_BUTTON);
-	else
-		image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
-	label = gtk_label_new_with_mnemonic (label_text);
-	hbox = gtk_hbox_new (FALSE, 2);
-	align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
-
-	gtk_widget_set_can_default (button, TRUE);
-	gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
+	image = gtk_image_new_from_stock (text_is_stock ? text : stock_id, GTK_ICON_SIZE_BUTTON);
+	gtk_button_set_image (GTK_BUTTON (button), image);
 
-	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
-	gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-	gtk_container_add (GTK_CONTAINER (button), align);
-	gtk_container_add (GTK_CONTAINER (align), hbox);
+	gtk_button_set_use_underline (GTK_BUTTON (button), TRUE);
+	gtk_button_set_label (GTK_BUTTON (button), label_text);
 
-	gtk_widget_show_all (button);
+	gtk_widget_set_can_default (button, TRUE);
+	gtk_widget_show (button);
 
 	return button;
 }
@@ -206,7 +195,7 @@ _gtk_request_dialog_run (GtkWindow        *parent,
 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 
 	entry = gtk_entry_new ();
-	gtk_widget_set_size_request (entry, REQUEST_ENTRY_WIDTH, -1);
+	gtk_entry_set_width_chars (GTK_ENTRY (entry), REQUEST_ENTRY_WIDTH_IN_CHARS);
 	gtk_entry_set_max_length (GTK_ENTRY (entry), max_length);
 	gtk_entry_set_text (GTK_ENTRY (entry), default_value);
 	gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
@@ -238,14 +227,14 @@ _gtk_request_dialog_run (GtkWindow        *parent,
 
 	/* Add buttons */
 
-	button = create_button (GTK_STOCK_CANCEL, no_button_text);
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_CANCEL, no_button_text);
 	gtk_dialog_add_action_widget (GTK_DIALOG (d),
 				      button,
 				      GTK_RESPONSE_CANCEL);
 
 	/**/
 
-	button = create_button (GTK_STOCK_OK, yes_button_text);
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_OK, yes_button_text);
 	gtk_dialog_add_action_widget (GTK_DIALOG (d),
 				      button,
 				      GTK_RESPONSE_YES);
@@ -320,14 +309,14 @@ _gtk_yesno_dialog_new (GtkWindow        *parent,
 
 	/* Add buttons */
 
-	button = create_button (GTK_STOCK_CANCEL, no_button_text);
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_CANCEL, no_button_text);
 	gtk_dialog_add_action_widget (GTK_DIALOG (d),
 				      button,
 				      GTK_RESPONSE_CANCEL);
 
 	/**/
 
-	button = create_button (GTK_STOCK_OK, yes_button_text);
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_OK, yes_button_text);
 	gtk_dialog_add_action_widget (GTK_DIALOG (d),
 				      button,
 				      GTK_RESPONSE_YES);
@@ -407,14 +396,14 @@ _gtk_yesno_dialog_with_checkbutton_new (GtkWindow        *parent,
 
 	/* Add buttons */
 
-	button = create_button (GTK_STOCK_CANCEL, no_button_text);
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_CANCEL, no_button_text);
 	gtk_dialog_add_action_widget (GTK_DIALOG (d),
 				      button,
 				      GTK_RESPONSE_CANCEL);
 
 	/**/
 
-	button = create_button (GTK_STOCK_OK, yes_button_text);
+	button = _gtk_button_new_from_stock_with_text (GTK_STOCK_OK, yes_button_text);
 	gtk_dialog_add_action_widget (GTK_DIALOG (d),
 				      button,
 				      GTK_RESPONSE_YES);
diff --git a/gthumb/gtk-utils.h b/gthumb/gtk-utils.h
index 2482b1b..9eccb62 100644
--- a/gthumb/gtk-utils.h
+++ b/gthumb/gtk-utils.h
@@ -28,6 +28,8 @@
 
 G_BEGIN_DECLS
 
+GtkWidget * _gtk_button_new_from_stock_with_text (const char *stock_id,
+				      	      	  const char *text);
 GtkWidget*  _gtk_message_dialog_new        (GtkWindow        *parent,
 					    GtkDialogFlags    flags,
 					    const char       *stock_id,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]