[gnumeric] ssconvert merge: inital patch from 581616.



commit e718a5d5dbd01faaf41f37699e296e238dfb9a66
Author: Morten Welinder <terra gnome org>
Date:   Mon May 11 19:43:54 2009 -0400

    ssconvert merge: inital patch from 581616.
---
 src/ssconvert.c |  192 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 187 insertions(+), 5 deletions(-)

diff --git a/src/ssconvert.c b/src/ssconvert.c
index 6205907..983ef8b 100644
--- a/src/ssconvert.c
+++ b/src/ssconvert.c
@@ -16,6 +16,11 @@
 #include "position.h"
 #include "parse-util.h"
 #include "workbook.h"
+#include "workbook-priv.h"
+#include "sheet.h"
+#include "dependent.h"
+#include "expr-name.h"
+#include "str.h"
 #include "libgnumeric.h"
 #include "gutils.h"
 #include "gnumeric-paths.h"
@@ -46,6 +51,7 @@ static char *ssconvert_import_encoding = NULL;
 static char *ssconvert_import_id = NULL;
 static char *ssconvert_export_id = NULL;
 static char *ssconvert_export_options = NULL;
+static char *ssconvert_merge_target = NULL;
 static char **ssconvert_goal_seek = NULL;
 
 static const GOptionEntry ssconvert_options [] = {
@@ -82,6 +88,13 @@ static const GOptionEntry ssconvert_options [] = {
 	/* ---------------------------------------- */
 
 	{
+		"merge-to", 'M',
+		0, G_OPTION_ARG_STRING, &ssconvert_merge_target,
+		N_("Merge listed files (all same format) to make this file"),
+		N_("file")
+	},
+
+	{
 		"export-type", 'T',
 		0, G_OPTION_ARG_STRING, &ssconvert_export_id,
 		N_("Optionally specify which exporter to use"),
@@ -225,8 +238,165 @@ list_them (get_them_f get_them,
 	}
 }
 
+/* Look at a set of workbooks, and pick a sheet size that would
+   be good for sheets in a workbook merging them all. */
+static int
+suggest_size (const char *inputs[], int *csuggest, int *rsuggest,
+	      GOFileOpener *fo, IOContext *io_context,
+	      GOCmdContext *cc)
+{
+	int rmax = 0;
+	int cmax = 0;
+	while (*inputs!=NULL) {
+		const char *fname = *inputs;
+		char *uri = go_shell_arg_to_uri (fname);
+		WorkbookView *wbv2 = 
+			wb_view_new_from_uri (uri, fo,
+					      io_context, 
+					      ssconvert_import_encoding);
+		inputs++;
+		if (wbv2!=NULL) {
+			Workbook *wb2 = wb_view_get_workbook (wbv2);
+			int i;
+			/* Looping through sheets should be redundant
+			   if all must be same size; let's do it anyway */
+			for (i=0; i<workbook_sheet_count (wb2); i++) {
+				Sheet *sheet = workbook_sheet_by_index (wb2,i);
+				int r = gnm_sheet_get_max_rows (sheet);
+				int c = gnm_sheet_get_max_cols (sheet);
+				if (r>rmax) rmax = r;
+				if (c>cmax) cmax = c;
+			}
+			g_object_unref (wb2);
+		}
+		g_free (uri);
+	}
+	gnm_sheet_suggest_size (&cmax, &rmax);
+	if (csuggest!=NULL) *csuggest = cmax;
+	if (rsuggest!=NULL) *rsuggest = rmax;
+	return 0;
+}
+
+
+/* Append the sheets of workbook wb2 to workbook wb.  Resize sheets
+   if necessary.  Fix workbook links in sheet if necessary.
+   Merge names in workbook scope (conflicts result in an error). */
+static int
+merge_single (Workbook *wb, Workbook *wb2, int cmax, int rmax, 
+	      GOCmdContext *cc) {
+
+	/* Move names with workbook scope in wb2 over to wb */
+	GSList *names = g_slist_sort (gnm_named_expr_collection_list (wb2->names),
+				      (GCompareFunc)expr_name_cmp_by_name);
+	GSList *p;
+	for (p = names; p; p = p->next) {
+		GnmNamedExpr *nexpr = p->data;
+		if (nexpr!=NULL) {
+			if (nexpr->pos.wb!=NULL) {
+				/* Check for clash with existing name */
+				GnmParsePos pp;
+				parse_pos_init (&pp,wb,NULL,0,0);
+				GnmNamedExpr *nexpr2;
+				nexpr2 = expr_name_lookup (&pp,
+							   nexpr->name->str);
+				if (nexpr2!=NULL) {
+					g_printerr (_("Name conflict during merge: '%s' appears twice at workbook scope.\n"),
+						    nexpr->name->str);
+					g_slist_free (names);
+					return -1;
+				}
+
+				/* Move name scope to workbook wb */
+				Sheet *sheet = workbook_sheet_by_index (wb2,0);
+				expr_name_set_scope(nexpr,sheet);
+				nexpr->pos.wb = wb;
+				expr_name_set_scope(nexpr,NULL);
+			}
+		}
+	}
+
+	while (workbook_sheet_count (wb2) > 0) {
+		/* Remove sheet from incoming workbook */
+		Sheet *sheet = workbook_sheet_by_index (wb2,0);
+		int loc = workbook_sheet_count (wb);
+		int r = gnm_sheet_get_max_rows (sheet);
+		int c = gnm_sheet_get_max_cols (sheet);
+		GOUndo *undo;
+		g_object_ref (sheet);
+		workbook_sheet_delete (sheet);
+		sheet->workbook = wb;
+		
+		/* Fix names that reference the old workbook */
+		GSList *names = g_slist_sort (gnm_named_expr_collection_list (sheet->names),
+					      (GCompareFunc)expr_name_cmp_by_name);
+		GSList *p;
+		for (p = names; p; p = p->next) {
+			GnmNamedExpr *nexpr = p->data;
+			if (nexpr!=NULL) {
+				if (nexpr->pos.wb!=NULL) {
+					nexpr->pos.wb = wb;
+				}
+			}
+		}
+		g_slist_free (names);
+
+		/* Resize if necessary (not sure if this is needed) */
+		if (r!=rmax || c!=cmax) {
+			undo = gnm_sheet_resize (sheet, 
+						 cmax, 
+						 rmax, 
+						 cc);
+			if (undo!=NULL) {
+				g_object_unref (undo);
+			}
+		}
+
+		/* Pick a free sheet name */
+		char *name = workbook_sheet_get_free_name(wb,
+							  sheet->name_unquoted,
+							  FALSE,
+							  TRUE);
+		g_object_set (sheet, "name", name, NULL);
+		g_free (name);
+
+		/* Insert and revive the sheet */
+		workbook_sheet_attach_at_pos (wb,sheet,loc);
+		dependents_revive_sheet (sheet);
+		g_object_unref (sheet);
+	}
+	return 0;
+}
+
+/* Merge a collection of workbooks into one. */
+merge (Workbook *wb, char const *inputs[], 
+       GOFileOpener *fo, IOContext *io_context,
+       GOCmdContext *cc)
+{
+	int result = 0;
+	int cmax, rmax;
+	suggest_size (inputs, &cmax, &rmax, fo, io_context, cc);
+
+	while (*inputs!=NULL && result==0) {
+		const char *fname = *inputs;
+		char *uri = go_shell_arg_to_uri (fname);
+		WorkbookView *wbv2 = 
+			wb_view_new_from_uri (uri, fo,
+					      io_context, 
+					      ssconvert_import_encoding);
+		inputs++;
+		if (wbv2!=NULL) {
+			g_print ("Adding %s\n", fname);
+			Workbook *wb2 = wb_view_get_workbook (wbv2);
+			result = merge_single (wb, wb2, cmax, rmax, cc);
+			g_object_unref (wb2);
+		}
+		g_free (uri);
+	}
+	return result;
+}
+
 static int
-convert (char const *inarg, char const *outarg,
+convert (char const *inarg, char const *outarg, char const *mergeargs[],
 	 GOCmdContext *cc)
 {
 	int res = 0;
@@ -288,8 +458,14 @@ convert (char const *inarg, char const *outarg,
 
 	if (fs != NULL) {
 		IOContext *io_context = gnumeric_io_context_new (cc);
-		WorkbookView *wbv = wb_view_new_from_uri (infile, fo,
-			io_context, ssconvert_import_encoding);
+		WorkbookView *wbv;
+		if (mergeargs==NULL) {
+			wbv = wb_view_new_from_uri (infile, fo,
+						    io_context, 
+						    ssconvert_import_encoding);
+		} else {
+			wbv = workbook_view_new (NULL);
+		}
 
 		if (wbv == NULL || gnumeric_io_error_occurred (io_context)) {
 			gnumeric_io_error_display (io_context);
@@ -304,6 +480,10 @@ convert (char const *inarg, char const *outarg,
 				goto out;
 			}
 
+			if (mergeargs!=NULL) {
+				merge (wb, mergeargs, fo, io_context, cc);
+			}
+
 			if (ssconvert_goal_seek) {
 				int i;
 
@@ -399,8 +579,10 @@ main (int argc, char const **argv)
 		list_them (&go_get_file_openers,
 			   (get_desc_f) &go_file_opener_get_id,
 			   (get_desc_f) &go_file_opener_get_description);
-	else if (argc == 2 || argc == 3) {
-		res = convert (argv[1], argv[2], cc);
+	else if (ssconvert_merge_target!=NULL && argc>=3) {
+		res = convert (argv[1], ssconvert_merge_target, argv+1, cc);
+	} else if (argc == 2 || argc == 3) {
+		res = convert (argv[1], argv[2], NULL, cc);
 	} else {
 		g_printerr (_("Usage: %s [OPTION...] %s\n"),
 			    g_get_prgname (),



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