[glade3] Added loading objects dialog with progress and cancel.



commit 0ce0e633795a5f5b0ff33987d936dfb4384f4dfa
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Tue Dec 21 13:30:37 2010 +0900

    	Added loading objects dialog with progress and cancel.
    
    	* src/main.c: Display window before loading command line specified projects.
    
    	* gladeui/glade-project.[ch]: Added dialog that pops up when about to load
    	  a large project with glade_project_push_project() to push the progress and
    	  glade_project_load_cancelled() to check and abort while loading the project.
    
    	* gladeui/glade-widget.c, gladeui/glade-widget-adaptor.c: Push progress and
    	  abort loading when project indicates the user cancelled the load.

 ChangeLog                      |   13 ++++
 gladeui/glade-project.c        |  144 +++++++++++++++++++++++++++++++++++++++-
 gladeui/glade-project.h        |    3 +
 gladeui/glade-widget-adaptor.c |    3 +
 gladeui/glade-widget.c         |   10 +++-
 src/main.c                     |    5 +-
 6 files changed, 171 insertions(+), 7 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 434cf67..2e173cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2010-12-21  Tristan Van Berkom <tristanvb openismus com>
+
+	Added loading objects dialog with progress and cancel.
+
+	* src/main.c: Display window before loading command line specified projects.
+
+	* gladeui/glade-project.[ch]: Added dialog that pops up when about to load
+	  a large project with glade_project_push_project() to push the progress and
+	  glade_project_load_cancelled() to check and abort while loading the project.
+
+	* gladeui/glade-widget.c, gladeui/glade-widget-adaptor.c: Push progress and
+	  abort loading when project indicates the user cancelled the load.
+
 2010-12-20  Tristan Van Berkom <tristanvb openismus com>
 
 	* plugins/gtk+/glade-gtk.c, plugins/gtk+/glade-column-types.[ch]: Added
diff --git a/gladeui/glade-project.c b/gladeui/glade-project.c
index 92593b1..1a2774d 100644
--- a/gladeui/glade-project.c
+++ b/gladeui/glade-project.c
@@ -157,6 +157,13 @@ struct _GladeProjectPrivate
 	GtkWidget *relative_path_entry;
 	GtkWidget *full_path_button;
 
+	/* For the loading progress dialog */
+	GtkWidget *progress_dialog;
+	GtkWidget *progress;
+	gint       progress_step;
+	gint       progress_full;
+	gboolean   load_cancel;
+
 	/* Store preview processes, so we can kill them on close */
 	GHashTable *preview_channels;
 };
@@ -229,6 +236,9 @@ static void         glade_project_model_get_iter_for_object (GladeProject* proje
                                                              GObject* object,
                                                              GtkTreeIter* iter);
 
+
+#define GLADE_PROJECT_LARGE_PROJECT 40
+
 G_DEFINE_TYPE_WITH_CODE (GladeProject, glade_project, G_TYPE_OBJECT,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
                                       gtk_tree_model_iface_init))
@@ -1412,6 +1422,119 @@ glade_project_introspect_gtk_version (GladeProject *project)
 }
 
 
+static gint 
+glade_project_count_xml_objects (GladeProject *project, GladeXmlNode *root, gint count)
+{
+	GladeXmlNode    *node;
+
+	for (node = glade_xml_node_get_children (root); 
+	     node; node = glade_xml_node_next (node))
+	{
+		if (glade_xml_node_verify_silent
+		    (node, GLADE_XML_TAG_WIDGET (project->priv->format)))
+			count = glade_project_count_xml_objects (project, node, ++count);
+		else if (glade_xml_node_verify_silent (node, GLADE_XML_TAG_CHILD))
+			count = glade_project_count_xml_objects (project, node, count);			
+	}
+	return count;
+}
+
+static gboolean
+glade_progress_dialog_show_on_delete (GtkWidget *widget,
+				      GdkEvent  *event,
+				      gpointer   nothing)
+{
+	gtk_widget_show (widget);
+	return TRUE;
+}
+
+static void
+project_load_cancelled (GtkWidget    *button,
+			GladeProject *project)
+{
+	project->priv->load_cancel = TRUE;
+}
+
+static void
+glade_project_loading_dialog (GladeProject *project, gint count)
+{	
+	GtkWidget *content, *cancel;
+	gchar     *str, *name;
+
+	project->priv->progress_dialog = gtk_dialog_new ();
+	content = gtk_dialog_get_content_area (GTK_DIALOG (project->priv->progress_dialog));
+
+	gtk_window_set_default_size (GTK_WINDOW (project->priv->progress_dialog), 400, -1);
+	gtk_window_set_deletable (GTK_WINDOW (project->priv->progress_dialog), FALSE);
+	g_signal_connect (project->priv->progress_dialog, "delete-event",
+			  G_CALLBACK (glade_progress_dialog_show_on_delete), NULL);
+
+	project->priv->progress = gtk_progress_bar_new ();
+	name     = glade_project_get_name (project);
+	str      = g_strdup_printf (_("Loading project %s"), name);
+	gtk_window_set_title (GTK_WINDOW (project->priv->progress_dialog), str);
+	g_free (str);
+	g_free (name);
+
+	gtk_box_pack_start (GTK_BOX (content), project->priv->progress, FALSE, FALSE, 2);
+	gtk_widget_show (project->priv->progress);
+
+	cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+	gtk_widget_show (cancel);
+	gtk_dialog_add_action_widget (GTK_DIALOG (project->priv->progress_dialog),
+				      cancel, GTK_RESPONSE_CANCEL);
+	g_signal_connect (cancel, "clicked", G_CALLBACK (project_load_cancelled), project);
+
+	project->priv->progress_full = count;
+	project->priv->progress_step = 0;
+
+	gtk_widget_show (project->priv->progress_dialog);
+}
+
+static void
+glade_project_destroy_loading_dialog (GladeProject *project)
+{
+	if (project->priv->progress_dialog)
+	{
+		gtk_widget_destroy (project->priv->progress_dialog);
+		project->priv->progress_dialog = NULL;
+		project->priv->progress = NULL;
+	}
+}
+
+gboolean
+glade_project_load_cancelled (GladeProject *project)
+{
+	g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
+
+	return project->priv->load_cancel;
+}
+
+void
+glade_project_push_progress (GladeProject *project)
+{
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+
+	if (project->priv->progress)
+	{
+		gchar  *text;
+		project->priv->progress_step++;
+
+		text = g_strdup_printf ("Loaded %d of %d objects", 
+					project->priv->progress_step,
+					project->priv->progress_full);
+		gtk_progress_bar_set_text (GTK_PROGRESS_BAR (project->priv->progress), text);
+		g_free (text);
+
+		gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (project->priv->progress),
+					       project->priv->progress_step * 1.0 / 
+					       project->priv->progress_full);
+
+		while (gtk_events_pending ())
+			gtk_main_iteration ();
+	}
+}
+
 static gboolean
 glade_project_load_from_file (GladeProject *project, const gchar *path)
 {
@@ -1421,6 +1544,7 @@ glade_project_load_from_file (GladeProject *project, const gchar *path)
 	GladeXmlNode    *node;
 	GladeWidget     *widget;
 	gboolean         has_gtk_dep = FALSE;
+	gint             count;
 
 	project->priv->selection = NULL;
 	project->priv->toplevels = NULL;
@@ -1466,6 +1590,12 @@ glade_project_load_from_file (GladeProject *project, const gchar *path)
 
 	glade_project_read_resource_path (project, root);
 
+	/* Launch a dialog if it's going to take enough time to be
+	 * worth showing at all */
+	count = glade_project_count_xml_objects (project, root, 0);
+	if (count > GLADE_PROJECT_LARGE_PROJECT)
+		glade_project_loading_dialog (project, count);
+
 	for (node = glade_xml_node_get_children (root); 
 	     node; node = glade_xml_node_next (node))
 	{
@@ -1476,17 +1606,25 @@ glade_project_load_from_file (GladeProject *project, const gchar *path)
 
 		if ((widget = glade_widget_read (project, NULL, node, NULL)) != NULL)
 			glade_project_add_object (project, NULL, widget->object);
+
+		if (project->priv->load_cancel)
+			break;
 	}
 
+	/* Finished with the xml context */
+	glade_xml_context_free (context);
+
+	glade_project_destroy_loading_dialog (project);
+
+	if (project->priv->load_cancel)
+		return FALSE;
+
 	if (!has_gtk_dep)
 		glade_project_introspect_gtk_version (project);
 
 	if (glade_util_file_is_writeable (project->priv->path) == FALSE)
 		glade_project_set_readonly (project, TRUE);
 
-	/* Finished with the xml context */
-	glade_xml_context_free (context);
-
 	project->priv->mtime = glade_util_get_file_mtime (project->priv->path, NULL);
 
 	/* Reset project status here too so that you get a clean
diff --git a/gladeui/glade-project.h b/gladeui/glade-project.h
index c73a798..cfc6447 100644
--- a/gladeui/glade-project.h
+++ b/gladeui/glade-project.h
@@ -217,6 +217,9 @@ void          glade_project_update_signal_support_warning (GladeWidget  *widget,
 
 gchar        *glade_project_display_dependencies (GladeProject *project);
 
+void          glade_project_push_progress (GladeProject *project);
+gboolean      glade_project_load_cancelled (GladeProject *project);
+
 G_END_DECLS
 
 #endif /* __GLADE_PROJECT_H__ */
diff --git a/gladeui/glade-widget-adaptor.c b/gladeui/glade-widget-adaptor.c
index 70308fc..f1c6529 100644
--- a/gladeui/glade-widget-adaptor.c
+++ b/gladeui/glade-widget-adaptor.c
@@ -930,6 +930,9 @@ glade_widget_adaptor_object_read_widget (GladeWidgetAdaptor *adaptor,
 	{
 		if (glade_xml_node_verify_silent (iter_node, GLADE_XML_TAG_CHILD))
 			glade_widget_read_child (widget, iter_node);
+
+		if (glade_project_load_cancelled (widget->project))
+			return;
 	}
 }
 
diff --git a/gladeui/glade-widget.c b/gladeui/glade-widget.c
index faa4bae..30e52ee 100644
--- a/gladeui/glade-widget.c
+++ b/gladeui/glade-widget.c
@@ -3748,6 +3748,9 @@ void
 glade_widget_read_child (GladeWidget  *widget,
 			 GladeXmlNode *node)
 {
+	if (glade_project_load_cancelled (widget->project))
+		return;
+
 	glade_widget_adaptor_read_child (widget->adaptor, widget, node);
 }
 
@@ -3769,6 +3772,9 @@ glade_widget_read (GladeProject *project,
 	GladeWidget  *widget = NULL;
 	gchar        *klass, *id;
 
+	if (glade_project_load_cancelled (project))
+		return NULL;
+
 	glade_widget_push_superuser ();
 	
 	if (!glade_xml_node_verify
@@ -3834,7 +3840,9 @@ glade_widget_read (GladeProject *project,
 	}
 
 	glade_widget_pop_superuser ();
-	
+
+	glade_project_push_progress (project);
+
 	return widget;
 }
 
diff --git a/src/main.c b/src/main.c
index e03de2a..4e440e3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -161,7 +161,8 @@ main (int argc, char *argv[])
 	
 	if (without_devhelp == FALSE)
 		glade_window_check_devhelp (window);
-	
+
+	gtk_widget_show (GTK_WIDGET (window));
 	
 	/* load files specified on commandline */
 	if (files != NULL)
@@ -181,8 +182,6 @@ main (int argc, char *argv[])
 	if (glade_app_get_project () == NULL)
 		glade_window_new_project (window);
 
-	gtk_widget_show (GTK_WIDGET (window));
-
 	gtk_main ();
 
 	return 0;



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