[gnumeric] Calculation: improve inter-workbook calculations.



commit 82d8f0699aac95c4ddad25752f04648d0fd46a04
Author: Morten Welinder <terra gnome org>
Date:   Mon Jul 30 14:49:11 2012 -0400

    Calculation: improve inter-workbook calculations.
    
    This introduces gnm_app_recalc -- about time, eh? -- that updates all
    workbooks which are set for automatic recalculation by recalculating
    dirty dependents and triggering the necessary redraw.
    
    Since we already dirty across workbooks, this cause inter-workbook
    calculations to start behaving sanely.  I hope.

 ChangeLog                                     |    6 ++++++
 NEWS                                          |    1 +
 plugins/glpk/glpk-write.c                     |    4 +++-
 plugins/lpsolve/lpsolve-write.c               |    4 +++-
 plugins/mps/mps.c                             |    4 +---
 plugins/nlsolve/gnm-nlsolve.c                 |    3 ++-
 plugins/sample_datasource/sample_datasource.c |    4 ++--
 src/application.c                             |   25 +++++++++++++++++++++++++
 src/application.h                             |    1 +
 src/commands.c                                |   16 +++-------------
 src/dependent.c                               |    8 +++++++-
 src/dialogs/dialog-goal-seek.c                |   10 +++++++---
 src/dialogs/dialog-solver.c                   |    3 ++-
 src/ssconvert.c                               |    4 ++--
 src/ssgrep.c                                  |    4 ++--
 src/sstest.c                                  |    4 ++++
 src/tools/tabulate.c                          |    3 ++-
 17 files changed, 73 insertions(+), 31 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f94392b..bbc3f11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-07-30  Morten Welinder  <terra gnome org>
+
+	* src/application.c (gnm_app_recalc): New function.  (After almost
+	15 years we get this?)  Most calls to workbook_recalc redirected
+	to this.
+
 2012-07-28  Morten Welinder  <terra gnome org>
 
 	* src/dependent.h (GnmDependentClass): Add new "changed" method
diff --git a/NEWS b/NEWS
index cd9f800..7eb164d 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,7 @@ Morten:
 	* Dependents code cleanups.
 	* Make cells regular dependents.
 	* Fix non-linear solver crash.  [#680719]
+	* Improve inter-workbook recalculations.
 
 --------------------------------------------------------------------------
 Gnumeric 1.11.5
diff --git a/plugins/glpk/glpk-write.c b/plugins/glpk/glpk-write.c
index 4582373..aabf46d 100644
--- a/plugins/glpk/glpk-write.c
+++ b/plugins/glpk/glpk-write.c
@@ -22,6 +22,7 @@
 #include <workbook-view.h>
 #include <sheet.h>
 #include <workbook.h>
+#include <application.h>
 #include <value.h>
 #include <cell.h>
 #include <expr.h>
@@ -42,6 +43,7 @@ gnm_solver_get_lp_coeff (GnmCell *target, GnmCell *cell,
         gnm_float x0, x1;
 	gboolean res = FALSE;
 
+	gnm_cell_eval (target);
 	if (!VALUE_IS_NUMBER (target->value))
 		goto fail;
 	x0 = value_get_as_float (target->value);
@@ -355,7 +357,7 @@ glpk_file_save (GOFileSaver const *fs, GOIOContext *io_context,
 	prg = glpk_create_program (sheet, io_context, ssol, &err);
 	gnm_pop_C_locale (locale);
 
-	workbook_recalc (sheet->workbook);
+	gnm_app_recalc ();
 
 	if (!prg) {
 		go_cmd_context_error_import (GO_CMD_CONTEXT (io_context),
diff --git a/plugins/lpsolve/lpsolve-write.c b/plugins/lpsolve/lpsolve-write.c
index ef1c5b5..94c81db 100644
--- a/plugins/lpsolve/lpsolve-write.c
+++ b/plugins/lpsolve/lpsolve-write.c
@@ -20,6 +20,7 @@
 #include <boot.h>
 #include <numbers.h>
 #include <workbook-view.h>
+#include <application.h>
 #include <sheet.h>
 #include <workbook.h>
 #include <value.h>
@@ -42,6 +43,7 @@ gnm_solver_get_lp_coeff (GnmCell *target, GnmCell *cell,
         gnm_float x0, x1;
 	gboolean res = FALSE;
 
+	gnm_cell_eval (target);
 	if (!VALUE_IS_NUMBER (target->value))
 		goto fail;
 	x0 = value_get_as_float (target->value);
@@ -338,7 +340,7 @@ lpsolve_file_save (GOFileSaver const *fs, GOIOContext *io_context,
 	prg = lpsolve_create_program (sheet, io_context, ssol, &err);
 	gnm_pop_C_locale (locale);
 
-	workbook_recalc (sheet->workbook);
+	gnm_app_recalc ();
 
 	if (!prg) {
 		go_cmd_context_error_import (GO_CMD_CONTEXT (io_context),
diff --git a/plugins/mps/mps.c b/plugins/mps/mps.c
index 55d5ede..9a9d499 100644
--- a/plugins/mps/mps.c
+++ b/plugins/mps/mps.c
@@ -724,9 +724,7 @@ mps_file_open (GOFileOpener const *fo, GOIOContext *io_context,
 				  (_("Error while reading MPS file.")));
 	} else {
 		mps_fill_sheet (&state);
-
-		workbook_queue_all_recalc (state.wb);
-		workbook_recalc (state.wb);
+		workbook_recalc_all (state.wb);
 	}
 
 	g_hash_table_destroy (state.row_hash);
diff --git a/plugins/nlsolve/gnm-nlsolve.c b/plugins/nlsolve/gnm-nlsolve.c
index ac061ed..6d9d5fe 100644
--- a/plugins/nlsolve/gnm-nlsolve.c
+++ b/plugins/nlsolve/gnm-nlsolve.c
@@ -7,6 +7,7 @@
 #include "regression.h"
 #include "rangefunc.h"
 #include "workbook.h"
+#include "application.h"
 #include <gsf/gsf-impl-utils.h>
 #include <glib/gi18n-lib.h>
 #include <string.h>
@@ -696,7 +697,7 @@ gnm_nlsolve_idle (gpointer data)
 
 	if (!call_again) {
 		set_vector (nl, nl->x0);
-		workbook_recalc (sol->params->sheet->workbook);
+		gnm_app_recalc ();
 
 		rosenbrock_shutdown (nl);
 	}
diff --git a/plugins/sample_datasource/sample_datasource.c b/plugins/sample_datasource/sample_datasource.c
index 70927cc..32a20d3 100644
--- a/plugins/sample_datasource/sample_datasource.c
+++ b/plugins/sample_datasource/sample_datasource.c
@@ -25,6 +25,7 @@
 #include "func.h"
 #include "value.h"
 #include "workbook.h"
+#include "application.h"
 #include "sheet.h"
 #include "gutils.h"
 #include "gnm-i18n.h"
@@ -103,8 +104,7 @@ cb_watcher_queue_recalc (gpointer key, gpointer value, gpointer closure)
 	Sheet *sheet = w->dep->sheet;
 	dependent_queue_recalc (w->dep);
 
-	if (sheet && workbook_get_recalcmode (sheet->workbook))
-		workbook_recalc (sheet->workbook);
+	gnm_app_recalc ();
 }
 
 static gboolean
diff --git a/src/application.c b/src/application.c
index fab6875..b2ff9a2 100644
--- a/src/application.c
+++ b/src/application.c
@@ -946,6 +946,31 @@ _gnm_app_flag_windows_changed (void)
 
 /**********************************************************************/
 
+/**
+ * gnm_app_recalc:
+ *
+ * Recalculate everything dirty in all workbooks that have automatic
+ * recalc turned on.
+ **/
+void
+gnm_app_recalc (void)
+{
+	GList *l;
+
+	g_return_if_fail (app != NULL);
+
+	gnm_app_recalc_start ();
+
+	for (l = app->workbook_list; l; l = l->next) {
+		Workbook *wb = l->data;
+
+		if (workbook_get_recalcmode (wb))
+			workbook_recalc (wb);
+	}
+
+	gnm_app_recalc_finish ();
+}
+
 void
 gnm_app_recalc_start (void)
 {
diff --git a/src/application.h b/src/application.h
index e59b725..2b1abfe 100644
--- a/src/application.h
+++ b/src/application.h
@@ -24,6 +24,7 @@ Workbook    *gnm_app_workbook_get_by_index (int i);
 GSList      *gnm_app_history_get_list	   (int max_elements);
 void	     gnm_app_history_add	   (char const *filename, const char *mimetype);
 
+void         gnm_app_recalc                (void);
 void         gnm_app_recalc_start          (void);
 void         gnm_app_recalc_finish         (void);
 void         gnm_app_recalc_clear_caches   (void);
diff --git a/src/commands.c b/src/commands.c
index 9e8a6d6..60f7625 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -109,7 +109,7 @@
  *    events.  None of the internal utility routines should do so.  Those are
  *    expensive events and should only be done once per command to avoid
  *    duplicating work.  The lower levels can queue redraws if they must, and
- *    flag state changes but the call to workbook_recalc and sheet_update is
+ *    flag state changes but the call to gnm_app_recalc and sheet_update is
  *    by GnmCommand.
  *
  * FIXME: Filter the list of commands when a sheet is deleted.
@@ -339,12 +339,12 @@ undo_redo_menu_labels (Workbook *wb)
 static void
 update_after_action (Sheet *sheet, WorkbookControl *wbc)
 {
+	gnm_app_recalc ();
+
 	if (sheet != NULL) {
 		g_return_if_fail (IS_SHEET (sheet));
 
 		sheet_mark_dirty (sheet);
-		if (workbook_get_recalcmode (sheet->workbook))
-			workbook_recalc (sheet->workbook);
 		sheet_update (sheet);
 
 		if (sheet->workbook == wb_control_get_workbook (wbc))
@@ -2620,16 +2620,10 @@ cmd_paste_cut_update (GnmExprRelocateInfo const *info,
 
 	/* Dirty and update both sheets */
 	sheet_mark_dirty (t);
-	if (workbook_get_recalcmode (t->workbook))
-		workbook_recalc (t->workbook);
 	sheet_update (t);
 
 	if (IS_SHEET (o) && o != t) {
 		sheet_mark_dirty (o);
-		if (o->workbook != t->workbook) {
-			if (workbook_get_recalcmode (o->workbook))
-				workbook_recalc (o->workbook);
-		}
 		sheet_update (o);
 	}
 }
@@ -5255,7 +5249,6 @@ cmd_analysis_tool_undo (GnmCommand *cmd, WorkbookControl *wbc)
 		if (me->newSheetObjects == NULL)
 			me->newSheetObjects = dao_surrender_so (me->dao);
 		g_slist_foreach (me->newSheetObjects, (GFunc)sheet_object_clear_sheet, NULL);
-		workbook_recalc (me->dao->sheet->workbook);
 		sheet_update (me->dao->sheet);
 	}
 
@@ -5343,7 +5336,6 @@ cmd_analysis_tool_redo (GnmCommand *cmd, WorkbookControl *wbc)
 
 	dao_autofit_columns (me->dao);
 	sheet_mark_dirty (me->dao->sheet);
-	workbook_recalc (me->dao->sheet->workbook);
 	sheet_update (me->dao->sheet);
 
 	/* The concept of an undo if we create a new worksheet is extremely strange,
@@ -6639,7 +6631,6 @@ static gboolean
 cmd_goal_seek_impl (GnmCell *cell, GnmValue *value)
 {
 	sheet_cell_set_value (cell, value_dup(value));
-	workbook_recalc (cell->base.sheet->workbook);
 	return FALSE;
 }
 
@@ -7069,7 +7060,6 @@ cmd_so_set_value_redo (GnmCommand *cmd, G_GNUC_UNUSED WorkbookControl *wbc)
 	GnmCell *cell = sheet_cell_fetch (sheet, me->ref.col, me->ref.row);
 
 	sheet_cell_set_value (cell, value_dup (me->val));
-	workbook_recalc (sheet->workbook);
 	sheet_update (sheet);
 
 	return FALSE;
diff --git a/src/dependent.c b/src/dependent.c
index 1155790..f23dd28 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -2713,13 +2713,19 @@ workbook_recalc (Workbook *wb)
  * workbook_recalc_all :
  * @wb :
  *
- * Queues all dependents for recalc and marks them all as dirty.
+ * Queues all dependents for recalc and recalculates.
  */
 void
 workbook_recalc_all (Workbook *wb)
 {
 	workbook_queue_all_recalc (wb);
+
+	/* Recalculate this workbook unconditionally.  */
 	workbook_recalc (wb);
+
+	/* Recalculate other workbooks when needed.  */
+	gnm_app_recalc ();
+
 	WORKBOOK_FOREACH_VIEW (wb, view,
 		sheet_update (wb_view_cur_sheet (view)););
 }
diff --git a/src/dialogs/dialog-goal-seek.c b/src/dialogs/dialog-goal-seek.c
index 6306895..4670211 100644
--- a/src/dialogs/dialog-goal-seek.c
+++ b/src/dialogs/dialog-goal-seek.c
@@ -47,6 +47,7 @@
 #include <mathfunc.h>
 #include <widgets/gnumeric-expr-entry.h>
 #include <selection.h>
+#include <application.h>
 #include <gtk/gtk.h>
 
 #include <math.h>
@@ -107,7 +108,7 @@ goal_seek_eval (gnm_float x, gnm_float *y, void *vevaldata)
 		gnm_cell_set_value (evaldata->xcell, v);
 		cell_queue_recalc (evaldata->xcell);
 	}
-	workbook_recalc (evaldata->state->wb);
+	gnm_cell_eval (evaldata->ycell);
 
 	if (evaldata->ycell->value) {
 		*y = value_get_as_float (evaldata->ycell->value) - evaldata->ytarget;
@@ -286,9 +287,10 @@ cb_dialog_cancel_clicked (G_GNUC_UNUSED GtkWidget *button,
 
 	if ((state->old_cell != NULL) && (state->old_value != NULL)) {
 		sheet_cell_set_value (state->old_cell, state->old_value);
-		workbook_recalc (state->wb);
 		state->old_value = NULL;
 	}
+
+	gnm_app_recalc ();
 	gtk_widget_destroy (state->dialog);
 }
 
@@ -398,14 +400,16 @@ cb_dialog_apply_clicked (G_GNUC_UNUSED GtkWidget *button,
 
 	if ((state->old_cell != NULL) && (state->old_value != NULL)) {
 		sheet_cell_set_value (state->old_cell, state->old_value);
-		workbook_recalc (state->wb);
 		state->old_value = NULL;
 	}
+	gnm_app_recalc ();
 	state->old_cell = state->change_cell;
 	state->old_value = value_dup (state->change_cell->value);
 
 	status = gnumeric_goal_seek (state);
 
+	gnm_app_recalc ();
+
 	switch (status) {
 	case GOAL_SEEK_OK: {
 		const char *actual_str;
diff --git a/src/dialogs/dialog-solver.c b/src/dialogs/dialog-solver.c
index a4e4ddf..f742808 100644
--- a/src/dialogs/dialog-solver.c
+++ b/src/dialogs/dialog-solver.c
@@ -44,6 +44,7 @@
 #include <commands.h>
 #include <clipboard.h>
 #include <selection.h>
+#include <application.h>
 #include <tools/gnm-solver.h>
 #include <widgets/gnumeric-expr-entry.h>
 
@@ -924,7 +925,7 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 
 	res = run_solver (state, param);
 
-	workbook_recalc (state->sheet->workbook);
+	gnm_app_recalc ();
 
 	if (res != NULL) {
 		if ((res->quality == GNM_SOLVER_RESULT_OPTIMAL ||
diff --git a/src/ssconvert.c b/src/ssconvert.c
index c026777..251a6f4 100644
--- a/src/ssconvert.c
+++ b/src/ssconvert.c
@@ -15,6 +15,7 @@
 #include "gnumeric.h"
 #include "position.h"
 #include "parse-util.h"
+#include "application.h"
 #include "workbook.h"
 #include "workbook-priv.h"
 #include "workbook-control.h"
@@ -637,8 +638,7 @@ convert (char const *inarg, char const *outarg, char const *mergeargs[],
 
 	if (ssconvert_recalc)
 		workbook_recalc_all (wb);
-	else
-		workbook_recalc (wb);
+	gnm_app_recalc ();
 
 	if (ssconvert_range)
 		setup_range (G_OBJECT (wb),
diff --git a/src/ssgrep.c b/src/ssgrep.c
index 6bd8af6..a0a468a 100644
--- a/src/ssgrep.c
+++ b/src/ssgrep.c
@@ -12,6 +12,7 @@
 #include "command-context-stderr.h"
 #include "workbook-view.h"
 #include "workbook.h"
+#include "application.h"
 #include "gutils.h"
 #include "gnm-plugin.h"
 #include "search.h"
@@ -289,8 +290,7 @@ ssgrep (const char *arg, char const *uri, GOIOContext *ioc, GHashTable *targets,
 	if (ssgrep_locus_results) {
 		if (ssgrep_recalc)
 			workbook_recalc_all (wb);
-		else
-			workbook_recalc (wb);
+		gnm_app_recalc ();
 	}
 
 	if (ssgrep_string_table) {
diff --git a/src/sstest.c b/src/sstest.c
index c9b4158..766cfd0 100644
--- a/src/sstest.c
+++ b/src/sstest.c
@@ -452,7 +452,9 @@ test_random_1 (int N, const char *expr,
 	define_cell (sheet, 1, 3, s);
 	g_free (s);
 
+	/* Force recalc of all dirty cells even in manual mode.  */
 	workbook_recalc (sheet->workbook);
+
 	for (i = 0; i < N; i++)
 		res[i] = value_get_as_float (sheet_cell_get (sheet, 0, i)->value);
 	*mean = value_get_as_float (sheet_cell_get (sheet, 1, 0)->value);
@@ -513,7 +515,9 @@ test_random_normality (int N, const char *expr,
 	define_cell (sheet, 1, 5, s);
 	g_free (s);
 
+	/* Force recalc of all dirty cells even in manual mode.  */
 	workbook_recalc (sheet->workbook);
+
 	for (i = 0; i < N; i++)
 		res[i] = value_get_as_float (sheet_cell_get (sheet, 0, i)->value);
 	*mean = value_get_as_float (sheet_cell_get (sheet, 1, 0)->value);
diff --git a/src/tools/tabulate.c b/src/tools/tabulate.c
index 244288c..15f03a3 100644
--- a/src/tools/tabulate.c
+++ b/src/tools/tabulate.c
@@ -264,7 +264,8 @@ do_tabulation (WorkbookControl *wbc,
 			gnm_cell_set_value (data->cells[i], old_values[i]);
 			cell_queue_recalc (data->cells[i]);
 		}
-		workbook_recalc (wb);
+		gnm_cell_eval (data->target);
+		gnm_app_recalc (wb);
 	}
 
 	g_free (values);



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