[gnumeric] Check whether defined names are in use before deleting them.
- From: Andreas J. Guelzow <guelzow src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Check whether defined names are in use before deleting them.
- Date: Sun, 6 Jun 2010 21:03:51 +0000 (UTC)
commit a49b3b39590c9cb69013d3bf1b0c5a5dedbc168a
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date: Sun Jun 6 15:01:47 2010 -0600
Check whether defined names are in use before deleting them.
2010-06-06 Andreas J. Guelzow <aguelzow pyrshep ca>
* dialog-define-names.c (name_guru_warn): implement
2010-06-06 Andreas J. Guelzow <aguelzow pyrshep ca>
* src/expr-name.h (expr_name_in_use): new
* src/expr-name.c (expr_name_in_use): new
(do_expr_name_loop_check): add argument and change all callers
(cb_expr_name_check_for_name): new
(cb_expr_name_check_for_name_eq): new
(expr_name_check_for_name): new
ChangeLog | 9 +++
NEWS | 1 +
src/dialogs/ChangeLog | 4 +
src/dialogs/dialog-define-names.c | 12 +++-
src/expr-name.c | 116 ++++++++++++++++++++++++++++++++++---
src/expr-name.h | 1 +
6 files changed, 130 insertions(+), 13 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 258951a..2e96f15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-06-06 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * src/expr-name.h (expr_name_in_use): new
+ * src/expr-name.c (expr_name_in_use): new
+ (do_expr_name_loop_check): add argument and change all callers
+ (cb_expr_name_check_for_name): new
+ (cb_expr_name_check_for_name_eq): new
+ (expr_name_check_for_name): new
+
2010-06-04 Andreas J. Guelzow <aguelzow pyrshep ca>
* src/commands.c (cmd_define_name): be clearer with the error
diff --git a/NEWS b/NEWS
index bfa9414..4b39d19 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ Andreas:
* Add paste-names dialog. [#613325]
* Make changing the scope of a named expression undoable.
* Add search tool to paste- and define-names dialogs. [#465840]
+ * Check whether defined names are in use before deleting them.
Jean:
* Do not ungrab a not grabbed item. [#620369]
diff --git a/src/dialogs/ChangeLog b/src/dialogs/ChangeLog
index 3abd4b2..9f456fd 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,7 @@
+2010-06-06 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * dialog-define-names.c (name_guru_warn): implement
+
2010-06-04 Andreas J. Guelzow <aguelzow pyrshep ca>
* dialog-define-names.c (name_guru_parse_pos_init): new
diff --git a/src/dialogs/dialog-define-names.c b/src/dialogs/dialog-define-names.c
index 27ed6dd..d03a29e 100644
--- a/src/dialogs/dialog-define-names.c
+++ b/src/dialogs/dialog-define-names.c
@@ -176,11 +176,15 @@ name_guru_expand_at_iter (NameGuruState *state, GtkTreeIter *iter)
**/
static gboolean
-name_guru_warn (G_GNUC_UNUSED NameGuruState *state,
- G_GNUC_UNUSED GnmNamedExpr *nexpr)
+name_guru_warn (NameGuruState *state,
+ GnmNamedExpr *nexpr)
{
-#warning Implement warning on deletion of used names!
- return TRUE;
+ return (!expr_name_in_use (nexpr) ||
+ go_gtk_query_yes_no
+ (GTK_WINDOW (state->dialog), FALSE,
+ "The defined name '%s' is in use. "
+ "Do you really want to delete it?",
+ expr_name_name (nexpr)));
}
static gboolean
diff --git a/src/expr-name.c b/src/expr-name.c
index 4a2639f..fa98d3e 100644
--- a/src/expr-name.c
+++ b/src/expr-name.c
@@ -412,29 +412,33 @@ expr_name_new (char const *name, gboolean is_placeholder)
* NB. if we already have a circular reference in addition
* to this one we are checking we will come to serious grief.
*/
+
+/* Note: for a loopcheck stop_at_name must be FALSE. */
+/* stop_at_name = TRUE is used when we check all names anyways. */
static gboolean
-do_expr_name_loop_check (char const *name, GnmExpr const *expr)
+do_expr_name_loop_check (char const *name, GnmExpr const *expr,
+ gboolean stop_at_name)
{
switch (GNM_EXPR_GET_OPER (expr)) {
case GNM_EXPR_OP_RANGE_CTOR:
case GNM_EXPR_OP_INTERSECT:
case GNM_EXPR_OP_ANY_BINARY:
- return (do_expr_name_loop_check (name, expr->binary.value_a) ||
- do_expr_name_loop_check (name, expr->binary.value_b));
+ return (do_expr_name_loop_check (name, expr->binary.value_a, stop_at_name) ||
+ do_expr_name_loop_check (name, expr->binary.value_b, stop_at_name));
case GNM_EXPR_OP_ANY_UNARY:
- return do_expr_name_loop_check (name, expr->unary.value);
+ return do_expr_name_loop_check (name, expr->unary.value, stop_at_name);
case GNM_EXPR_OP_NAME: {
GnmNamedExpr const *nexpr = expr->name.name;
if (!strcmp (nexpr->name->str, name))
return TRUE;
- if (nexpr->texpr != NULL) /* look inside this name tree too */
+ if (!stop_at_name && nexpr->texpr != NULL) /* look inside this name tree too */
return expr_name_check_for_loop (name, nexpr->texpr);
return FALSE;
}
case GNM_EXPR_OP_FUNCALL: {
int i;
for (i = 0; i < expr->func.argc; i++)
- if (do_expr_name_loop_check (name, expr->func.argv[i]))
+ if (do_expr_name_loop_check (name, expr->func.argv[i], stop_at_name))
return TRUE;
break;
}
@@ -446,7 +450,7 @@ do_expr_name_loop_check (char const *name, GnmExpr const *expr)
case GNM_EXPR_OP_SET: {
int i;
for (i = 0; i < expr->set.argc; i++)
- if (do_expr_name_loop_check (name, expr->set.argv[i]))
+ if (do_expr_name_loop_check (name, expr->set.argv[i], stop_at_name))
return TRUE;
break;
}
@@ -459,7 +463,7 @@ expr_name_check_for_loop (char const *name, GnmExprTop const *texpr)
{
g_return_val_if_fail (texpr != NULL, TRUE);
- return do_expr_name_loop_check (name, texpr->expr);
+ return do_expr_name_loop_check (name, texpr->expr, FALSE);
}
static void
@@ -527,7 +531,8 @@ expr_name_add (GnmParsePos const *pp, char const *name,
nexpr->is_placeholder = FALSE;
} else {
nexpr = g_hash_table_lookup (scope->names, name);
- /* If this is a permanent name, we may be adding it on opening of a file, although */
+ /* If this is a permanent name, we may be adding it */
+ /* on opening of a file, although */
/* the name is already in place. */
if (nexpr != NULL) {
if (nexpr->is_permanent)
@@ -833,6 +838,99 @@ expr_name_is_placeholder (GnmNamedExpr const *nexpr)
gnm_expr_top_is_err (nexpr->texpr, GNM_ERROR_NAME));
}
+static gboolean
+cb_expr_name_check_for_name (gpointer key,
+ gpointer value,
+ gpointer name)
+{
+ GnmNamedExpr *nexpr = value;
+ char const *this_name = key;
+
+ if (strcmp (this_name, name) == 0)
+ return FALSE;
+
+ return do_expr_name_loop_check (name, nexpr->texpr->expr, TRUE);
+}
+
+static gboolean
+cb_expr_name_check_for_name_eq (gpointer key,
+ G_GNUC_UNUSED gpointer value,
+ gpointer name)
+{
+ char const *this_name = key;
+
+ return (strcmp (this_name, name) == 0);
+}
+
+static gboolean
+expr_name_check_for_name (gchar const *name, GnmNamedExprCollection *scope,
+ gboolean name_check)
+{
+ if (name_check) {
+ /* Since the name is used at workbook level we must */
+ /* first check whether a sheet-level name hides the */
+ /* workbook-level name. */
+ if (NULL != g_hash_table_find (scope->names,
+ cb_expr_name_check_for_name_eq,
+ (gpointer) name))
+ return FALSE;
+ }
+ return NULL != g_hash_table_find (scope->names,
+ cb_expr_name_check_for_name,
+ (gpointer) name);
+}
+
+gboolean
+expr_name_in_use (GnmNamedExpr *nexpr)
+{
+ gchar const *name;
+
+ if (nexpr->dependents != NULL &&
+ g_hash_table_size (nexpr->dependents) != 0)
+ return TRUE;
+
+ /* We must now check whether one of the other names */
+ /* uses this name. */
+ name = expr_name_name (nexpr);
+
+ if (nexpr->pos.sheet == NULL) {
+ /* The name is of global scope */
+ /* It could be used by any other name */
+ /* (unless hidden by a sheet-level name) */
+ gboolean res;
+ GSList *sheets, *sheets_orig;
+
+ res = expr_name_check_for_name
+ (name, nexpr->pos.wb->names, FALSE);
+ if (res)
+ return TRUE;
+
+ sheets_orig = workbook_sheets (nexpr->pos.wb);
+ for (sheets = sheets_orig;
+ sheets != NULL; sheets = sheets->next) {
+ Sheet *this = sheets->data;
+ res = expr_name_check_for_name
+ (name, this->names, TRUE);
+ if (res) {
+ g_slist_free (sheets_orig);
+ return TRUE;
+ }
+ }
+ g_slist_free (sheets_orig);
+ } else {
+ /* The name is of sheet level scope */
+ /* It can only be used by another sheet-level */
+ /* name of the same sheet. */
+
+ return expr_name_check_for_name
+ (name, nexpr->pos.sheet->names, FALSE);
+ }
+
+
+ return FALSE;
+}
+
+
int
expr_name_cmp_by_name (GnmNamedExpr const *a, GnmNamedExpr const *b)
{
diff --git a/src/expr-name.h b/src/expr-name.h
index 027ea4d..438ca60 100644
--- a/src/expr-name.h
+++ b/src/expr-name.h
@@ -50,6 +50,7 @@ void expr_name_add_dep (GnmNamedExpr *ne, GnmDependent *dep);
void expr_name_remove_dep (GnmNamedExpr *ne, GnmDependent *dep);
gboolean expr_name_is_placeholder (GnmNamedExpr const *ne);
void expr_name_downgrade_to_placeholder (GnmNamedExpr *nexpr);
+gboolean expr_name_in_use (GnmNamedExpr *nexpr);
int expr_name_cmp_by_name (GnmNamedExpr const *a, GnmNamedExpr const *b);
gboolean expr_name_check_for_loop (char const *name, GnmExprTop const *texpr);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]