[gnumeric] Functions: upgrade placeholders to proper functions when we load plugins.



commit 1b2d372cbf08391eba161f8e464becc5420226c1
Author: Morten Welinder <terra gnome org>
Date:   Thu Jan 10 19:24:57 2013 -0500

    Functions: upgrade placeholders to proper functions when we load plugins.

 ChangeLog        |    8 ++++++++
 NEWS             |    1 +
 src/func.c       |   54 ++++++++++++++++++++++++++++++++----------------------
 src/func.h       |   11 ++++++-----
 src/gnm-plugin.c |   52 ++++++++++++++++++++++++++++++++++++++++++++--------
 5 files changed, 91 insertions(+), 35 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c6319d3..68dab8a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2013-01-10  Morten Welinder  <terra gnome org>
 
+	* src/gnm-plugin.c (plugin_service_function_group_activate):
+	Upgrade existing placeholder functions as needed.
+
+	* src/func.c (gnm_func_upgrade_placeholder): Rename from
+	gnm_func_upgrade_placeholder.  Take GnmFunc argument, not name.
+
+2013-01-10  Morten Welinder  <terra gnome org>
+
 	* src/func.c (gnm_func_add_placeholder_localized): New function.
 	(gnm_func_add_placeholder_full): Extract from
 	gnm_func_add_placeholder.  Handle localization better.
diff --git a/NEWS b/NEWS
index bc833b4..8fdbf9b 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ Morten:
 	* Avoid using some deprecated symbols.
 	* Fix multihead issue with clipboard.
 	* Improve EIGEN.   [#687926]
+	* Improve handling of unknown functions.  [#109442]
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.0
diff --git a/src/func.c b/src/func.c
index 0c15695..b158a51 100644
--- a/src/func.c
+++ b/src/func.c
@@ -28,6 +28,7 @@
 #include "func-builtin.h"
 #include "command-context-stderr.h"
 #include "gnm-plugin.h"
+#include "gutils.h"
 
 #include <goffice/goffice.h>
 #include <glib.h>
@@ -1206,39 +1207,44 @@ unknownFunctionHandler (GnmFuncEvalInfo *ei,
 }
 
 /**
- * gnm_func_add_stub:
+ * gnm_func_upgrade_placeholder:
+ * @fd:
  * @fn_group:
- * @name:
  * @textdomain:
  * @load_desc: (scope async):
  * @opt_usage_notify: (scope async):
  **/
-GnmFunc *
-gnm_func_add_stub (GnmFuncGroup *fn_group,
-		   const char *name,
-		   const char *textdomain,
-		   GnmFuncLoadDesc   load_desc,
-		   GnmFuncUsageNotify opt_usage_notify)
+void
+gnm_func_upgrade_placeholder (GnmFunc *fd,
+			      GnmFuncGroup *fn_group,
+			      const char *textdomain,
+			      GnmFuncLoadDesc load_desc,
+			      GnmFuncUsageNotify opt_usage_notify)
 {
-	GnmFunc *func = g_new0 (GnmFunc, 1);
+	g_return_if_fail (fd != NULL);
+	g_return_if_fail (fd->flags & GNM_FUNC_IS_PLACEHOLDER);
+	g_return_if_fail (fn_group != NULL);
 
 	if (!textdomain)
 		textdomain = GETTEXT_PACKAGE;
 
-	func->name		= name;
-	func->usage_notify	= opt_usage_notify;
-	func->fn_type		= GNM_FUNC_TYPE_STUB;
-	func->fn.load_desc	= load_desc;
-	func->textdomain        = go_string_new (textdomain);
+	/* Remove from unknown_cat */
+	gnm_func_group_remove_func (fd->fn_group, fd);
 
-	func->fn_group = fn_group;
-	if (fn_group != NULL)
-		gnm_func_group_add_func (fn_group, func);
+	fd->fn_type = GNM_FUNC_TYPE_STUB;
+	fd->fn.load_desc = load_desc;
+	fd->usage_notify = opt_usage_notify;
 
-	g_hash_table_insert (functions_by_name,
-			     (gpointer)(func->name), func);
+	go_string_unref (fd->textdomain);
+	fd->textdomain = go_string_new (textdomain);
 
-	return func;
+	/* Clear localized_name so we can deduce the proper name.  */
+	gnm_func_set_localized_name (fd, NULL);
+
+	fd->flags &= ~GNM_FUNC_IS_PLACEHOLDER;
+
+	fd->fn_group = fn_group;
+	gnm_func_group_add_func (fn_group, fd);
 }
 
 static char *
@@ -1293,7 +1299,8 @@ gnm_func_add_placeholder_full (Workbook *scope,
 		copy_lname = FALSE;
 	}
 
-	g_printerr ("Adding placeholder for %s (aka %s)\n", gname, lname);
+	if (gnm_debug_flag ("func"))
+		g_printerr ("Adding placeholder for %s (aka %s)\n", gname, lname);
 
 	memset (&desc, 0, sizeof (GnmFuncDescriptor));
 	desc.name	  = copy_gname ? g_strdup (gname) : gname;
@@ -1309,9 +1316,12 @@ gnm_func_add_placeholder_full (Workbook *scope,
 
 	if (scope != NULL)
 		desc.flags |= GNM_FUNC_IS_WORKBOOK_LOCAL;
-	else
+	else {
+#if 0
 		/* WISHLIST : it would be nice to have a log if these. */
 		g_warning ("Unknown %s function : %s", type, gname);
+#endif
+	}
 
 	func = gnm_func_add (unknown_cat, &desc, NULL);
 
diff --git a/src/func.h b/src/func.h
index e2be56e..1d7a826 100644
--- a/src/func.h
+++ b/src/func.h
@@ -238,11 +238,6 @@ GSList	   *gnm_func_lookup_prefix   (char const *prefix, Workbook *scope,
 GnmFunc    *gnm_func_add	     (GnmFuncGroup *group,
 				      GnmFuncDescriptor const *descriptor,
 				      const char *textdomain);
-GnmFunc    *gnm_func_add_stub	     (GnmFuncGroup *group,
-				      const char *name,
-				      const char *textdomain,
-				      GnmFuncLoadDesc load_desc,
-				      GnmFuncUsageNotify opt_usage_notify);
 GnmFunc    *gnm_func_add_placeholder (Workbook *optional_scope,
 				      char const *name,
 				      char const *type,
@@ -251,6 +246,12 @@ GnmFunc    *gnm_func_add_placeholder_localized (char const *gname, char const *l
 GnmFunc	   *gnm_func_lookup_or_add_placeholder
                                       (char const *name, Workbook *scope,
 				       gboolean copy_name);
+void        gnm_func_upgrade_placeholder
+				      (GnmFunc *fd,
+				       GnmFuncGroup *fn_group,
+				       const char *textdomain,
+				       GnmFuncLoadDesc load_desc,
+				       GnmFuncUsageNotify opt_usage_notify);
 
 /* TODO */
 char const *gnm_func_get_description (GnmFunc const *fn_def);
diff --git a/src/gnm-plugin.c b/src/gnm-plugin.c
index 995310b..1e6a1bc 100644
--- a/src/gnm-plugin.c
+++ b/src/gnm-plugin.c
@@ -186,6 +186,17 @@ plugin_service_function_group_func_ref_notify (GnmFunc *fn_def, int refcount)
 }
 
 static void
+delayed_ref_notify (GOPlugin *plugin, GnmFunc *fd)
+{
+	g_signal_handlers_disconnect_by_func (plugin,
+					      G_CALLBACK (delayed_ref_notify),
+					      fd);
+
+	/* We cannot do this until after the plugin has been activated.  */
+	plugin_service_function_group_func_ref_notify (fd, 1);
+}
+
+static void
 plugin_service_function_group_activate (GOPluginService *service, GOErrorInfo **ret_error)
 {
 	PluginServiceFunctionGroup *sfg =
@@ -194,14 +205,36 @@ plugin_service_function_group_activate (GOPluginService *service, GOErrorInfo **
 	GO_INIT_RET_ERROR_INFO (ret_error);
 	sfg->func_group = gnm_func_group_fetch (sfg->category_name,
 						sfg->translated_category_name);
-	GO_SLIST_FOREACH (sfg->function_name_list, char, fname,
-		GnmFunc *fn_def;
-
-		fn_def = gnm_func_add_stub (
-			sfg->func_group, fname, sfg->textdomain,
-			plugin_service_function_group_func_desc_load,
-			plugin_service_function_group_func_ref_notify);
-		gnm_func_set_user_data (fn_def, service);
+	if (gnm_debug_flag ("plugin-func"))
+		g_printerr ("Activating group %s\n", sfg->category_name);
+	GO_SLIST_FOREACH
+		(sfg->function_name_list, char, fname,
+		 GnmFunc *fd;
+
+		 fd = gnm_func_lookup (fname, NULL);
+		 if (fd) {
+#if 0
+			 g_printerr ("Reusing placeholder for %s\n", fname);
+#endif
+		 } else {
+			 fd = gnm_func_add_placeholder
+				 (NULL, fname, "?", TRUE);
+		 }
+		 if (fd->flags & GNM_FUNC_IS_PLACEHOLDER) {
+			 gnm_func_set_user_data (fd, service);
+			 gnm_func_upgrade_placeholder
+				 (fd, sfg->func_group,
+				  sfg->textdomain,
+				  plugin_service_function_group_func_desc_load,
+				  plugin_service_function_group_func_ref_notify);
+			 if (fd->usage_count > 0)
+				 g_signal_connect (go_plugin_service_get_plugin (service),
+						   "state_changed",
+						   G_CALLBACK (delayed_ref_notify),
+						   fd);
+		 } else {
+			 g_warning ("Multiple definitions of function %s -- this cannot be good!", fname);
+		 }
 	);
 	service->is_active = TRUE;
 }
@@ -211,6 +244,9 @@ plugin_service_function_group_deactivate (GOPluginService *service, GOErrorInfo
 {
 	PluginServiceFunctionGroup *sfg = GNM_PLUGIN_SERVICE_FUNCTION_GROUP (service);
 
+	if (gnm_debug_flag ("plugin-func"))
+		g_printerr ("Deactivating group %s\n", sfg->category_name);
+
 	GO_INIT_RET_ERROR_INFO (ret_error);
 	GO_SLIST_FOREACH (sfg->function_name_list, char, fname,
 		gnm_func_free (gnm_func_lookup (fname, NULL));



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