[gnumeric] New-from-template: initial implementation.



commit c10bbf09385fe7f8c9840a646fe3230806f7cea0
Author: Morten Welinder <terra gnome org>
Date:   Sun Jun 14 10:01:14 2009 -0400

    New-from-template: initial implementation.

 ChangeLog                     |   12 ++++
 NEWS                          |    1 +
 src/GNOME_Gnumeric-gtk.xml.in |    2 +
 src/gui-file.c                |   30 +++++++++
 src/gui-file.h                |    1 +
 src/wbc-gtk-actions.c         |    8 ++-
 src/wbc-gtk-impl.h            |    4 +-
 src/wbc-gtk.c                 |  143 +++++++++++++++++++++++++++++++++++++++--
 8 files changed, 193 insertions(+), 8 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index be479d4..a43fbeb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2009-06-14  Morten Welinder  <terra gnome org>
 
+	Implement New-From-Template (#303657):
+
+	* src/wbc-gtk.c (wbc_gtk_reload_templates, wbc_gtk_load_templates,
+	cb_new_from_template): New functions.
+	(wbc_gtk_new): Arrange to load templates later.
+	(wbcg_update_title, regenerate_window_menu): Handle NULL uri.
+
+	* src/wbc-gtk-actions.c (cb_file_menu): New handler to ensure that
+	templates have been loaded.
+
+	* src/gui-file.c (gui_file_template): New function.
+
 	* src/workbook-view.c (wb_view_set_attribute): Handle problem with
 	old .gnumeric files.
 
diff --git a/NEWS b/NEWS
index 3e6bd04..3eb62cb 100644
--- a/NEWS
+++ b/NEWS
@@ -40,6 +40,7 @@ Morten:
 	* Parse x^y^z as (x^y)^z from ODF files.  [#585277]
 	* Fix text import problem.  [#135523]
 	* Fix problem loading very old .gnumeric files.
+	* Implement new-from-template.  [#303657]
 
 --------------------------------------------------------------------------
 Gnumeric 1.9.8
diff --git a/src/GNOME_Gnumeric-gtk.xml.in b/src/GNOME_Gnumeric-gtk.xml.in
index a736e6d..7c48e0a 100644
--- a/src/GNOME_Gnumeric-gtk.xml.in
+++ b/src/GNOME_Gnumeric-gtk.xml.in
@@ -3,6 +3,8 @@
   <menubar>
     <menu name="File" action="MenuFile">
       <menuitem action="FileNew"/>
+      <menu name="Templates" action="FileNewFromTemplate">
+      </menu>
       <menuitem action="FileOpen"/>
       <separator name="file-sep1"/>
       <menuitem action="FileSave"/>
diff --git a/src/gui-file.c b/src/gui-file.c
index 73d88d0..3ba0210 100644
--- a/src/gui-file.c
+++ b/src/gui-file.c
@@ -138,6 +138,36 @@ gui_file_read (WBCGtk *wbcg, char const *uri,
 	return FALSE;
 }
 
+gboolean
+gui_file_template (WBCGtk *wbcg, char const *uri)
+{
+	IOContext *io_context;
+	WorkbookView *wbv;
+	GOFileOpener const *optional_format = NULL;
+	gchar const *optional_encoding = NULL;
+
+	go_cmd_context_set_sensitive (GO_CMD_CONTEXT (wbcg), FALSE);
+	io_context = gnumeric_io_context_new (GO_CMD_CONTEXT (wbcg));
+	wbv = wb_view_new_from_uri (uri, optional_format, io_context,
+				    optional_encoding);
+
+	if (gnumeric_io_error_occurred (io_context) ||
+	    gnumeric_io_warning_occurred (io_context))
+		gnumeric_io_error_display (io_context);
+
+	g_object_unref (G_OBJECT (io_context));
+	go_cmd_context_set_sensitive (GO_CMD_CONTEXT (wbcg), TRUE);
+
+	if (wbv != NULL) {
+		Workbook *wb = wb_view_get_workbook (wbv);
+		go_doc_set_uri (GO_DOC (wb), NULL);
+		workbook_set_saveinfo (wb, FILE_FL_NEW, NULL);
+		gui_wb_view_show (wbcg, wbv);
+		return TRUE;
+	}
+	return FALSE;
+}
+
 static void
 file_format_changed_cb (GtkComboBox *format_combo,
 			file_format_changed_cb_data *data)
diff --git a/src/gui-file.h b/src/gui-file.h
index 9fddb24..4e3bf87 100644
--- a/src/gui-file.h
+++ b/src/gui-file.h
@@ -14,6 +14,7 @@ void     gui_wb_view_show   (WBCGtk *wbcg, WorkbookView *wbv);
 gboolean gui_file_read	    (WBCGtk *wbcg, char const *file_name,
 			     GOFileOpener const *optional_format,
 			     gchar const *optional_encoding);
+gboolean gui_file_template  (WBCGtk *wbcg, char const *uri);
 
 G_END_DECLS
 
diff --git a/src/wbc-gtk-actions.c b/src/wbc-gtk-actions.c
index 83fd95a..a110d9c 100644
--- a/src/wbc-gtk-actions.c
+++ b/src/wbc-gtk-actions.c
@@ -1672,9 +1672,15 @@ static GNM_ACTION_DEF (cb_format_row_unhide)
 	cmd_selection_colrow_hide (WORKBOOK_CONTROL (wbcg), FALSE, TRUE);
 }
 
+static GNM_ACTION_DEF (cb_file_menu)
+{
+	wbc_gtk_load_templates (wbcg);
+}
+
 /* Actions that are always sensitive */
 static GtkActionEntry const permanent_actions[] = {
-	{ "MenuFile",		NULL, N_("_File") },
+	{ "MenuFile",		NULL, N_("_File"), NULL, NULL, G_CALLBACK (cb_file_menu) },
+	{ "FileNewFromTemplate", GTK_STOCK_NEW, N_("New From Template"), "" },
 		{ "FilePrintArea",      NULL, N_("Print Area")},
 	{ "MenuEdit",		NULL, N_("_Edit") },
 		{ "MenuEditClear",	GTK_STOCK_CLEAR, N_("C_lear") },
diff --git a/src/wbc-gtk-impl.h b/src/wbc-gtk-impl.h
index baec8d9..321761a 100644
--- a/src/wbc-gtk-impl.h
+++ b/src/wbc-gtk-impl.h
@@ -110,7 +110,7 @@ struct _WBCGtk {
 	struct {
 		GtkActionGroup   *actions;
 		guint		  merge_id;
-	} file_history, toolbar, windows;
+	} file_history, toolbar, windows, templates;
 
 	GOActionComboStack	*undo_haction, *redo_haction;
 	GtkAction		*undo_vaction, *redo_vaction;
@@ -165,6 +165,8 @@ void	 wbc_gtk_init_editline	(WBCGtk *wbcg);
 void	 wbc_gtk_init_actions	(WBCGtk *wbcg);
 void	 wbc_gtk_markup_changer	(WBCGtk *wbcg);
 
+gboolean wbc_gtk_load_templates (WBCGtk *gtk);
+
 G_END_DECLS
 
 #endif /* _GNM_WBC_GTK_IMPL_H_ */
diff --git a/src/wbc-gtk.c b/src/wbc-gtk.c
index 3c5dc71..3353ea2 100644
--- a/src/wbc-gtk.c
+++ b/src/wbc-gtk.c
@@ -55,6 +55,7 @@
 #include "gnm-pane-impl.h"
 #include "graph.h"
 #include "selection.h"
+#include "file-autoft.h"
 
 #include <goffice/goffice.h>
 #include <gsf/gsf-impl-utils.h>
@@ -1341,7 +1342,7 @@ static void
 wbcg_update_title (WBCGtk *wbcg)
 {
 	GODoc *doc = wb_control_get_doc (WORKBOOK_CONTROL (wbcg));
-	char *basename = go_basename_from_uri (doc->uri);
+	char *basename = doc->uri ? go_basename_from_uri (doc->uri) : NULL;
 	char *title = g_strconcat
 		(go_doc_is_dirty (doc) ? "*" : "",
 		 basename ? basename : doc->uri,
@@ -3197,6 +3198,9 @@ static unsigned
 regenerate_window_menu (WBCGtk *gtk, Workbook *wb, unsigned i)
 {
 	int k, count;
+	char *basename = GO_DOC (wb)->uri
+		? go_basename_from_uri (GO_DOC (wb)->uri)
+		: NULL;
 
 	/* How many controls are there?  */
 	count = 0;
@@ -3207,11 +3211,9 @@ regenerate_window_menu (WBCGtk *gtk, Workbook *wb, unsigned i)
 
 	k = 1;
 	WORKBOOK_FOREACH_CONTROL (wb, wbv, wbc, {
-		char *basename;
 		if (i >= 20)
 			return i;
-		if (IS_WBC_GTK (wbc) &&
-			(basename = go_basename_from_uri (GO_DOC (wb)->uri)) != NULL) {
+		if (IS_WBC_GTK (wbc) && basename) {
 			GString *label = g_string_new (NULL);
 			char *name;
 			char const *s;
@@ -3241,9 +3243,9 @@ regenerate_window_menu (WBCGtk *gtk, Workbook *wb, unsigned i)
 
 			g_string_free (label, TRUE);
 			g_free (name);
-			g_free (basename);
 			i++;
 		}});
+	g_free (basename);
 	return i;
 }
 
@@ -4263,6 +4265,120 @@ wbc_gtk_reload_recent_file_menu (WBCGtk const *wbcg)
 }
 
 static void
+cb_new_from_template (GObject *action, WBCGtk *wbcg)
+{
+	const char *uri = g_object_get_data (action, "uri");
+	gui_file_template (wbcg, uri);
+}
+
+static void
+wbc_gtk_reload_templates (WBCGtk *gtk)
+{
+	unsigned i;
+	GDir *dir;
+	const char *name;
+	GSList *l, *names;
+	char *path;
+
+	if (gtk->templates.merge_id != 0)
+		gtk_ui_manager_remove_ui (gtk->ui, gtk->templates.merge_id);
+	gtk->templates.merge_id = gtk_ui_manager_new_merge_id (gtk->ui);
+
+	if (gtk->templates.actions != NULL) {
+		gtk_ui_manager_remove_action_group (gtk->ui,
+			gtk->templates.actions);
+		g_object_unref (gtk->templates.actions);
+	}
+	gtk->templates.actions = gtk_action_group_new ("TemplateList");
+
+	gtk_ui_manager_insert_action_group (gtk->ui, gtk->templates.actions, 0);
+
+	path = g_build_filename (gnm_sys_data_dir (), "templates", NULL);
+	dir = g_dir_open (path, 0, NULL);
+	if (!dir) {
+		g_free (path);
+		return;
+	}
+
+	names = NULL;
+	while ((name = g_dir_read_name (dir))) {
+		char *fullname = g_build_filename (path, name, NULL);
+		if (g_file_test (fullname, G_FILE_TEST_IS_REGULAR)) {
+			char *uri = go_filename_to_uri (fullname);
+			names = g_slist_prepend (names, uri);
+		}
+		g_free (fullname);
+	}
+	g_free (path);
+	g_dir_close (dir);
+
+	names = g_slist_sort (names, (GCompareFunc)g_utf8_collate);
+
+	for (i = 1, l = names; l; l = l->next) {
+		const char *uri = l->data;
+		GString *label = g_string_new (NULL);
+		GtkActionEntry entry;
+		char *gname;
+		const char *gpath;
+		char *basename = go_basename_from_uri (uri);
+		const char *s;
+		GtkAction *action;
+
+		if (i < 10) g_string_append_c (label, '_');
+		g_string_append_printf (label, "%d ", i);
+
+		for (s = basename; *s; s++) {
+			if (*s == '_') g_string_append_c (label, '_');
+			g_string_append_c (label, *s);
+		}
+
+		entry.name = gname = g_strdup_printf ("Template%d", i);
+		entry.stock_id = NULL;
+		entry.label = label->str;
+		entry.accelerator = NULL;
+		entry.tooltip = NULL;
+		entry.callback = G_CALLBACK (cb_new_from_template);
+
+		gtk_action_group_add_actions (gtk->templates.actions,
+					      &entry, 1, gtk);
+
+		action = gtk_action_group_get_action (gtk->templates.actions,
+						      entry.name);
+
+		g_object_set_data_full (G_OBJECT (action), "uri",
+			g_strdup (uri), (GDestroyNotify)g_free);
+
+
+		gpath =
+#ifdef GNM_USE_HILDON
+			"/popup/File/Templates"
+#else
+			"/menubar/File/Templates"
+#endif
+			;
+		gtk_ui_manager_add_ui (gtk->ui, gtk->templates.merge_id,
+				       gpath, gname, gname,
+				       GTK_UI_MANAGER_AUTO, FALSE);
+
+		g_string_free (label, TRUE);
+		g_free (gname);
+		g_free (basename);
+		i++;
+	}
+	go_slist_free_custom (names, (GFreeFunc)g_free);
+}
+
+gboolean
+wbc_gtk_load_templates (WBCGtk *wbcg)
+{
+	if (wbcg->templates.merge_id == 0) {
+		wbc_gtk_reload_templates (wbcg);
+	}
+
+	return FALSE;
+}
+
+static void
 wbcg_set_toplevel (WBCGtk *wbcg, GtkWidget *w)
 {
 	static GtkTargetEntry const drag_types[] = {
@@ -4370,6 +4486,10 @@ wbc_gtk_finalize (GObject *obj)
 		gtk_ui_manager_remove_ui (wbcg->ui, wbcg->windows.merge_id);
 	UNREF_OBJ (windows.actions);
 
+	if (wbcg->templates.merge_id != 0)
+		gtk_ui_manager_remove_ui (wbcg->ui, wbcg->templates.merge_id);
+	UNREF_OBJ (templates.actions);
+
 	g_hash_table_destroy (wbcg->custom_uis);
 
 	UNREF_OBJ (zoom);
@@ -4911,6 +5031,10 @@ wbc_gtk_init (GObject *obj)
 
 	wbcg->windows.actions = NULL;
 	wbcg->windows.merge_id = 0;
+
+	wbcg->templates.actions = NULL;
+	wbcg->templates.merge_id = 0;
+
 	gnm_app_foreach_extra_ui ((GFunc) cb_init_extra_ui, wbcg);
 	g_object_connect ((GObject *) gnm_app_get_app (),
 		"swapped-object-signal::window-list-changed",
@@ -5004,7 +5128,14 @@ wbc_gtk_new (WorkbookView *optional_view,
 		gtk_window_set_screen (wbcg_toplevel (wbcg), optional_screen);
 
 	/* Postpone showing the GUI, so that we may resize it freely. */
-	g_idle_add ((GSourceFunc) show_gui, wbcg);
+	g_idle_add ((GSourceFunc)show_gui, wbcg);
+
+	/* Load this later when thing have calmed down.  If this does not
+	   trigger by the time the file menu is activated, then the UI is
+	   updated right then -- and that looks sub-optimal because the
+	   "Templates" menu is empty (and thus not shown) until the
+	   update is done. */
+	g_timeout_add (1000, (GSourceFunc)wbc_gtk_load_templates, wbcg);
 
 	wb_control_init_state (wbc);
 	return wbcg;



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