[gcr] gcr: Show import errors in an info bar under the viewer



commit 62fbbdb564bfb28addeebf060a58dd20f026b398
Author: Stef Walter <stefw collabora co uk>
Date:   Wed Nov 30 11:20:07 2011 +0100

    gcr: Show import errors in an info bar under the viewer
    
     * Add importing signal to GcrImportButton
     * Add a GtkInfoBar to GcrViewerWindow

 docs/reference/gcr/gcr-sections.txt |    8 +---
 docs/reference/gcr/gcr.interfaces   |    7 +--
 gcr/gcr-import-button.c             |   16 +++++++
 gcr/gcr-import-button.h             |    6 +++
 gcr/gcr-viewer-widget.c             |   79 ++++++++++++++++++++++++++++++-----
 gcr/gcr-viewer-widget.h             |   11 +++--
 gcr/gcr-viewer-window.c             |   20 ++++++---
 7 files changed, 115 insertions(+), 32 deletions(-)
---
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index 2c32313..29432bc 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -601,21 +601,17 @@ GcrUnlockOptionsWidgetPrivate
 <SECTION>
 <FILE>gcr-viewer-widget</FILE>
 GcrViewerWidget
-GcrViewerWidgetClass
 gcr_viewer_widget_new
 gcr_viewer_widget_load_data
 gcr_viewer_widget_load_file
 gcr_viewer_widget_get_parser
+gcr_viewer_widget_show_error
+gcr_viewer_widget_clear_error
 <SUBSECTION Standard>
 gcr_viewer_widget_get_type
 GCR_TYPE_VIEWER_WIDGET
 GCR_IS_VIEWER_WIDGET
-GCR_IS_VIEWER_WIDGET_CLASS
 GCR_VIEWER_WIDGET
-GCR_VIEWER_WIDGET_CLASS
-GCR_VIEWER_WIDGET_GET_CLASS
-<SUBSECTION Private>
-GcrViewerWidgetPrivate
 </SECTION>
 
 <SECTION>
diff --git a/docs/reference/gcr/gcr.interfaces b/docs/reference/gcr/gcr.interfaces
index 1ef3691..c65f21a 100644
--- a/docs/reference/gcr/gcr.interfaces
+++ b/docs/reference/gcr/gcr.interfaces
@@ -10,14 +10,13 @@ GtkComboBox AtkImplementorIface GtkBuildable GtkCellLayout GtkCellEditable
 GcrComboSelector AtkImplementorIface GtkBuildable GtkCellLayout GtkCellEditable
 GtkButton AtkImplementorIface GtkBuildable GtkActivatable
 GcrImportButton AtkImplementorIface GtkBuildable GtkActivatable
-GtkScrolledWindow AtkImplementorIface GtkBuildable
-GcrDisplayScrolled AtkImplementorIface GtkBuildable GcrViewer
-GcrViewerWidget AtkImplementorIface GtkBuildable GcrViewer
 GtkWindow AtkImplementorIface GtkBuildable
 GcrViewerWindow AtkImplementorIface GtkBuildable
 GtkTreeView AtkImplementorIface GtkBuildable GtkScrollable
 GcrListSelector AtkImplementorIface GtkBuildable GtkScrollable
 GcrTreeSelector AtkImplementorIface GtkBuildable GtkScrollable
+GtkBox AtkImplementorIface GtkBuildable GtkOrientable
+GcrViewerWidget AtkImplementorIface GtkBuildable GtkOrientable
 GtkCellArea GtkCellLayout GtkBuildable
 GtkTreeViewColumn GtkCellLayout GtkBuildable
 GcrCollectionModel GtkTreeModel GtkTreeSortable
@@ -32,7 +31,7 @@ GtkContainerAccessible AtkComponent
 GtkComboBoxAccessible AtkComponent AtkAction AtkSelection
 GtkButtonAccessible AtkComponent AtkAction AtkImage
 GtkTreeViewAccessible AtkComponent AtkTable AtkSelection GtkCellAccessibleParent
-GtkScrolledWindowAccessible AtkComponent
+GtkBoxAccessible AtkComponent
 GtkWindowAccessible AtkComponent AtkWindow
 GtkAction GtkBuildable
 GckSession GInitable GAsyncInitable
diff --git a/gcr/gcr-import-button.c b/gcr/gcr-import-button.c
index 1e1c809..373eebb 100644
--- a/gcr/gcr-import-button.c
+++ b/gcr/gcr-import-button.c
@@ -56,6 +56,7 @@ enum {
 /**
  * GcrImportButtonClass:
  * @parent_class: The parent class
+ * @importing: Emitted when the import begins.
  * @imported: Emitted when the import completes, or fails.
  *
  * Class for #GcrImportButton.
@@ -76,6 +77,7 @@ struct _GcrImportButtonPrivate {
 };
 
 enum {
+	IMPORTING,
 	IMPORTED,
 	LAST_SIGNAL
 };
@@ -313,6 +315,8 @@ begin_import (GcrImportButton *self,
 
 	g_return_if_fail (self->pv->importing == FALSE);
 
+	g_signal_emit (self, signals[IMPORTING], 0, importer);
+
 	self->pv->importing = TRUE;
 	g_free (self->pv->imported);
 	self->pv->imported = NULL;
@@ -489,6 +493,18 @@ gcr_import_button_class_init (GcrImportButtonClass *klass)
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 
 	/**
+	 * GcrImportButton::importing:
+	 * @self: the import button
+	 * @importer: the importer that will be imported to
+	 *
+	 * Signal emitted when an import begins.
+	 */
+	signals[IMPORTING] = g_signal_new ("importing", GCR_TYPE_IMPORT_BUTTON, G_SIGNAL_RUN_LAST,
+	                                  G_STRUCT_OFFSET (GcrImportButtonClass, importing),
+	                                  NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
+	                                  G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+	/**
 	 * GcrImportButton::imported:
 	 * @self: the import button
 	 * @importer: the importer that was imported to
diff --git a/gcr/gcr-import-button.h b/gcr/gcr-import-button.h
index 41ed222..b30f3f3 100644
--- a/gcr/gcr-import-button.h
+++ b/gcr/gcr-import-button.h
@@ -51,9 +51,15 @@ struct _GcrImportButton {
 struct _GcrImportButtonClass {
 	GtkButtonClass parent_class;
 
+	void    (*importing)   (GcrImportButton *self,
+	                        GcrImporter *importer);
+
 	void    (*imported)    (GcrImportButton *self,
 	                        GcrImporter *importer,
 	                        GError *error);
+
+	/*< private >*/
+	gpointer padding[10];
 };
 
 GType               gcr_import_button_get_type               (void) G_GNUC_CONST;
diff --git a/gcr/gcr-viewer-widget.c b/gcr/gcr-viewer-widget.c
index 6e06599..df59a2c 100644
--- a/gcr/gcr-viewer-widget.c
+++ b/gcr/gcr-viewer-widget.c
@@ -70,14 +70,21 @@ enum {
  * implementation, the parent class we derive from.
  */
 
+#define GCR_VIEWER_WIDGET_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_VIEWER_WIDGET, GcrViewerWidgetClass))
+#define GCR_IS_VIEWER_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_VIEWER_WIDGET))
+#define GCR_VIEWER_WIDGET_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_VIEWER_WIDGET, GcrViewerWidgetClass))
+
+typedef struct _GcrViewerWidgetClass GcrViewerWidgetClass;
+typedef struct _GcrViewerWidgetPrivate GcrViewerWidgetPrivate;
+
 struct _GcrViewerWidget {
 	/*< private >*/
-	GcrDisplayScrolled parent;
+	GtkBox parent;
 	GcrViewerWidgetPrivate *pv;
 };
 
 struct _GcrViewerWidgetClass {
-	GcrDisplayScrolledClass parent_class;
+	GtkBoxClass parent_class;
 
 	void       (*added)        (GcrViewerWidget *widget,
 	                            GcrRenderer *renderer,
@@ -85,6 +92,9 @@ struct _GcrViewerWidgetClass {
 };
 
 struct _GcrViewerWidgetPrivate {
+	GcrViewer *viewer;
+	GtkInfoBar *message_bar;
+	GtkLabel *message_label;
 	GQueue *files_to_load;
 	GcrParser *parser;
 	GCancellable *cancellable;
@@ -103,7 +113,7 @@ static guint signals[LAST_SIGNAL] = { 0, };
 static void viewer_load_next_file (GcrViewerWidget *self);
 static void viewer_stop_loading_files (GcrViewerWidget *self);
 
-G_DEFINE_TYPE (GcrViewerWidget, gcr_viewer_widget, GCR_TYPE_DISPLAY_SCROLLED);
+G_DEFINE_TYPE (GcrViewerWidget, gcr_viewer_widget, GTK_TYPE_BOX);
 
 static const gchar *
 get_parsed_label_or_display_name (GcrViewerWidget *self,
@@ -139,7 +149,7 @@ on_parser_parsed (GcrParser *parser,
 	}
 
 	/* And show the data */
-	gcr_viewer_add_renderer (GCR_VIEWER (self), renderer);
+	gcr_viewer_add_renderer (self->pv->viewer, renderer);
 
 	/* Let callers know we're rendering data */
 	if (actual == TRUE)
@@ -183,7 +193,7 @@ on_unlock_renderer_clicked (GcrUnlockRenderer *unlock,
 	if (gcr_parser_parse_data (self->pv->parser, data, n_data, &error)) {
 
 		/* Done with this unlock renderer */
-		gcr_viewer_remove_renderer (GCR_VIEWER (self), GCR_RENDERER (unlock));
+		gcr_viewer_remove_renderer (self->pv->viewer, GCR_RENDERER (unlock));
 		self->pv->unlocks = g_list_remove (self->pv->unlocks, unlock);
 		g_object_unref (unlock);
 
@@ -210,7 +220,7 @@ on_parser_authenticate_for_data (GcrParser *parser,
 	unlock = _gcr_unlock_renderer_new_for_parsed (parser);
 	if (unlock != NULL) {
 		g_object_set (unlock, "label", get_parsed_label_or_display_name (self, parser), NULL);
-		gcr_viewer_add_renderer (GCR_VIEWER (self), GCR_RENDERER (unlock));
+		gcr_viewer_add_renderer (self->pv->viewer, GCR_RENDERER (unlock));
 		g_signal_connect (unlock, "unlock-clicked", G_CALLBACK (on_unlock_renderer_clicked), self);
 		self->pv->unlocks = g_list_prepend (self->pv->unlocks, unlock);
 	}
@@ -221,9 +231,28 @@ on_parser_authenticate_for_data (GcrParser *parser,
 static void
 gcr_viewer_widget_init (GcrViewerWidget *self)
 {
+	GtkWidget *area;
+
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_VIEWER_WIDGET,
 	                                        GcrViewerWidgetPrivate);
 
+	gtk_orientable_set_orientation (GTK_ORIENTABLE (self),
+	                                GTK_ORIENTATION_VERTICAL);
+
+	self->pv->viewer = gcr_viewer_new_scrolled ();
+	gtk_box_pack_start (GTK_BOX (self), GTK_WIDGET (self->pv->viewer), TRUE, TRUE, 0);
+	gtk_widget_show (GTK_WIDGET (self->pv->viewer));
+
+	self->pv->message_label = GTK_LABEL (gtk_label_new (""));
+	gtk_label_set_use_markup (self->pv->message_label, TRUE);
+	gtk_label_set_ellipsize (self->pv->message_label, PANGO_ELLIPSIZE_END);
+	gtk_widget_show (GTK_WIDGET (self->pv->message_label));
+
+	self->pv->message_bar = GTK_INFO_BAR (gtk_info_bar_new ());
+	gtk_box_pack_start (GTK_BOX (self), GTK_WIDGET (self->pv->message_bar), FALSE, TRUE, 0);
+	area = gtk_info_bar_get_content_area (self->pv->message_bar);
+	gtk_container_add (GTK_CONTAINER (area), GTK_WIDGET (self->pv->message_label));
+
 	self->pv->files_to_load = g_queue_new ();
 	self->pv->parser = gcr_parser_new ();
 	self->pv->cancellable = g_cancellable_new ();
@@ -298,6 +327,8 @@ gcr_viewer_widget_class_init (GcrViewerWidgetClass *klass)
 	gobject_class->finalize = gcr_viewer_widget_finalize;
 	gobject_class->get_property = gcr_viewer_widget_get_property;
 
+	g_type_class_add_private (klass, sizeof (GcrViewerWidgetPrivate));
+
 	/**
 	 * GcrViewerWidget:parser:
 	 *
@@ -307,8 +338,6 @@ gcr_viewer_widget_class_init (GcrViewerWidgetClass *klass)
 	           g_param_spec_object ("parser", "Parser", "Parser used to parse viewable items",
 	                                GCR_TYPE_PARSER, G_PARAM_READABLE));
 
-	g_type_class_add_private (klass, sizeof (GcrViewerWidget));
-
 	/**
 	 * GcrViewerWidget::added:
 	 * @self: the viewer widget
@@ -343,7 +372,7 @@ on_parser_parse_stream_returned (GObject *source,
 
 	} else if (error) {
 		renderer = gcr_failure_renderer_new (self->pv->display_name, error);
-		gcr_viewer_add_renderer (GCR_VIEWER (self), renderer);
+		gcr_viewer_add_renderer (self->pv->viewer, renderer);
 		g_object_unref (renderer);
 		g_error_free (error);
 	}
@@ -384,7 +413,7 @@ on_file_read_returned (GObject *source,
 
 	} else if (error) {
 		renderer = gcr_failure_renderer_new (self->pv->display_name, error);
-		gcr_viewer_add_renderer (GCR_VIEWER (self), renderer);
+		gcr_viewer_add_renderer (self->pv->viewer, renderer);
 		g_object_unref (renderer);
 		g_error_free (error);
 
@@ -482,7 +511,7 @@ gcr_viewer_widget_load_data (GcrViewerWidget *self,
 
 	if (!gcr_parser_parse_data (self->pv->parser, data, n_data, &error)) {
 		renderer = gcr_failure_renderer_new (display_name, error);
-		gcr_viewer_add_renderer (GCR_VIEWER (self), renderer);
+		gcr_viewer_add_renderer (self->pv->viewer, renderer);
 		g_object_unref (renderer);
 		g_error_free (error);
 	}
@@ -502,3 +531,31 @@ gcr_viewer_widget_get_parser (GcrViewerWidget *self)
 	g_return_val_if_fail (GCR_IS_VIEWER_WIDGET (self), NULL);
 	return self->pv->parser;
 }
+
+void
+gcr_viewer_widget_show_error (GcrViewerWidget *self,
+                              const gchar *message,
+                              GError *error)
+{
+	gchar *markup;
+
+	g_return_if_fail (GCR_IS_VIEWER_WIDGET (self));
+	g_return_if_fail (message != NULL);
+
+	if (error)
+		markup = g_markup_printf_escaped ("<b>%s</b>: %s", message, error->message);
+	else
+		markup = g_markup_printf_escaped ("%s", message);
+
+	gtk_info_bar_set_message_type (self->pv->message_bar, GTK_MESSAGE_ERROR);
+	gtk_label_set_markup (self->pv->message_label, markup);
+	gtk_widget_show (GTK_WIDGET (self->pv->message_bar));
+	g_free (markup);
+}
+
+void
+gcr_viewer_widget_clear_error (GcrViewerWidget *self)
+{
+	g_return_if_fail (GCR_IS_VIEWER_WIDGET (self));
+	gtk_widget_hide (GTK_WIDGET (self->pv->message_bar));
+}
diff --git a/gcr/gcr-viewer-widget.h b/gcr/gcr-viewer-widget.h
index 3e1e17e..e52afec 100644
--- a/gcr/gcr-viewer-widget.h
+++ b/gcr/gcr-viewer-widget.h
@@ -28,14 +28,9 @@
 
 #define GCR_TYPE_VIEWER_WIDGET               (gcr_viewer_widget_get_type ())
 #define GCR_VIEWER_WIDGET(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_VIEWER_WIDGET, GcrViewerWidget))
-#define GCR_VIEWER_WIDGET_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_VIEWER_WIDGET, GcrViewerWidgetClass))
 #define GCR_IS_VIEWER_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_VIEWER_WIDGET))
-#define GCR_IS_VIEWER_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_VIEWER_WIDGET))
-#define GCR_VIEWER_WIDGET_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_VIEWER_WIDGET, GcrViewerWidgetClass))
 
 typedef struct _GcrViewerWidget GcrViewerWidget;
-typedef struct _GcrViewerWidgetClass GcrViewerWidgetClass;
-typedef struct _GcrViewerWidgetPrivate GcrViewerWidgetPrivate;
 
 
 GType              gcr_viewer_widget_get_type         (void);
@@ -52,4 +47,10 @@ void               gcr_viewer_widget_load_data        (GcrViewerWidget *self,
 
 GcrParser *        gcr_viewer_widget_get_parser       (GcrViewerWidget *self);
 
+void               gcr_viewer_widget_show_error       (GcrViewerWidget *self,
+                                                       const gchar *message,
+                                                       GError *error);
+
+void               gcr_viewer_widget_clear_error      (GcrViewerWidget *self);
+
 #endif /* GCR_VIEWER_WIDGET_H */
diff --git a/gcr/gcr-viewer-window.c b/gcr/gcr-viewer-window.c
index c604d18..8bf816c 100644
--- a/gcr/gcr-viewer-window.c
+++ b/gcr/gcr-viewer-window.c
@@ -56,23 +56,28 @@ gcr_viewer_window_init (GcrViewerWindow *self)
 }
 
 static void
+on_import_button_importing (GcrImportButton *button,
+                            GcrImporter *importer,
+                            gpointer user_data)
+{
+	GcrViewerWindow *self = GCR_VIEWER_WINDOW (user_data);
+	gcr_viewer_widget_clear_error (self->pv->viewer);
+}
+
+static void
 on_import_button_imported (GcrImportButton *button,
                            GcrImporter *importer,
                            GError *error,
                            gpointer user_data)
 {
 	GcrViewerWindow *self = GCR_VIEWER_WINDOW (user_data);
-	GcrRenderer *renderer;
 
 	if (error == NULL) {
 		g_object_set (button, "label", _("Imported"), NULL);
 
 	} else {
-		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			renderer = gcr_failure_renderer_new (_("Import failed"), error);
-			gcr_viewer_add_renderer (GCR_VIEWER (self->pv->viewer), renderer);
-			g_object_unref (renderer);
-		}
+		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+			gcr_viewer_widget_show_error (self->pv->viewer, _("Import failed"), error);
 	}
 }
 
@@ -101,6 +106,9 @@ gcr_viewer_window_constructed (GObject *obj)
 	gtk_widget_show (bbox);
 
 	self->pv->import = gcr_import_button_new (_("Import"));
+	g_signal_connect_object (self->pv->import, "importing",
+	                         G_CALLBACK (on_import_button_importing),
+	                         self, 0);
 	g_signal_connect_object (self->pv->import, "imported",
 	                         G_CALLBACK (on_import_button_imported),
 	                         self, 0);



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