[gtksourceview/gtksourcecompletion] Remove provider automatic/interactive in favor of capabilities



commit ad8e79850199a5b662a9bfe83d2ff8eb27514340
Author: Jesse van den Kieboom <jesse icecrew nl>
Date:   Sat May 23 23:29:40 2009 +0200

    Remove provider automatic/interactive in favor of capabilities
    
    The capabilities of a provider are now handled in a similar manner as gio query attributes.
    Two predefined capabilities are standard::automatic and standard::interactive. Consumers
    of the API can define their own capabilities (e.g. language::c or provider names). Using
    gtk_source_completion_get_providers, providers supporting a set of capabilities can be
    requested and shown.
---
 gtksourceview/gtksourcecompletion.c         |  222 ++++++++++++++++++---------
 gtksourceview/gtksourcecompletion.h         |    2 +
 gtksourceview/gtksourcecompletionprovider.c |   48 ++-----
 gtksourceview/gtksourcecompletionprovider.h |   12 +-
 gtksourceview/gtksourceview.c               |   33 +++--
 gtksourceview/gtksourceview.h               |    3 -
 6 files changed, 191 insertions(+), 129 deletions(-)

diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index 9fc0ace..f8cd7d2 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -102,8 +102,7 @@ struct _GtkSourceCompletionPrivate
 	GtkSourceView *view;
 
 	GList *providers;
-	GList *automatic_providers;
-	GList *interactive_providers;
+	GHashTable *capability_map;
 	GList *active_providers;
 	
 	guint show_timed_out_id;
@@ -1079,8 +1078,17 @@ show_auto_completion (GtkSourceCompletion *completion)
 	GtkTextIter start;
 	GtkTextIter end;
 	gchar *word;
+	GList *providers;
 	
 	completion->priv->show_timed_out_id = 0;
+	
+	providers = g_hash_table_lookup (completion->priv->capability_map, 
+	                                 GTK_SOURCE_COMPLETION_CAPABILITY_INTERACTIVE);
+	
+	if (!providers)
+	{
+		return FALSE;
+	}
 
 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (completion->priv->view));
 
@@ -1100,7 +1108,7 @@ show_auto_completion (GtkSourceCompletion *completion)
 	/* Check minimum amount of characters */
 	if (g_utf8_strlen (word, -1) >= completion->priv->minimum_auto_complete_length)
 	{
-		gtk_source_completion_show (completion, completion->priv->interactive_providers,
+		gtk_source_completion_show (completion, providers,
 					    word, &start);
 		completion->priv->is_interactive = TRUE;
 	}
@@ -1110,6 +1118,23 @@ show_auto_completion (GtkSourceCompletion *completion)
 	return FALSE;
 }
 
+static void
+interactive_do_show (GtkSourceCompletion *completion)
+{
+	update_typing_offsets (completion);
+
+	if (completion->priv->show_timed_out_id != 0)
+	{
+		g_source_remove (completion->priv->show_timed_out_id);
+		completion->priv->show_timed_out_id = 0;
+	}
+
+	completion->priv->show_timed_out_id = 
+		g_timeout_add (completion->priv->auto_complete_delay,
+			       (GSourceFunc)show_auto_completion,
+			       completion);
+}
+
 static gboolean
 buffer_delete_range_cb (GtkTextBuffer       *buffer,
                         GtkTextIter         *start,
@@ -1118,21 +1143,7 @@ buffer_delete_range_cb (GtkTextBuffer       *buffer,
 {
 	if (!GTK_WIDGET_VISIBLE (completion->priv->window))
 	{
-		if (completion->priv->interactive_providers != NULL)
-		{
-			update_typing_offsets (completion);
-	
-			if (completion->priv->show_timed_out_id != 0)
-			{
-				g_source_remove (completion->priv->show_timed_out_id);
-				completion->priv->show_timed_out_id = 0;
-			}
-
-			completion->priv->show_timed_out_id = 
-				g_timeout_add (completion->priv->auto_complete_delay,
-					       (GSourceFunc)show_auto_completion,
-					       completion);
-		}
+		interactive_do_show (completion);
 	}
 	else
 	{
@@ -1168,21 +1179,7 @@ buffer_insert_text_cb (GtkTextBuffer       *buffer,
 	
 	if (!GTK_WIDGET_VISIBLE (completion->priv->window))
 	{
-		if (completion->priv->interactive_providers != NULL)
-		{
-			update_typing_offsets (completion);
-		
-			if (completion->priv->show_timed_out_id != 0)
-			{
-				g_source_remove (completion->priv->show_timed_out_id);
-				completion->priv->show_timed_out_id = 0;
-			}
-
-			completion->priv->show_timed_out_id = 
-				g_timeout_add (completion->priv->auto_complete_delay,
-					       (GSourceFunc)show_auto_completion,
-					       completion);
-		}
+		interactive_do_show (completion);
 	}
 	else
 	{
@@ -1288,8 +1285,7 @@ gtk_source_completion_finalize (GObject *object)
 		g_source_remove (completion->priv->show_timed_out_id);
 	}
 	
-	g_list_free (completion->priv->automatic_providers);
-	g_list_free (completion->priv->interactive_providers);
+	g_hash_table_destroy (completion->priv->capability_map);
 	g_list_free (completion->priv->providers);
 	
 	g_free (completion->priv->filter_criteria);
@@ -2002,6 +1998,12 @@ gtk_source_completion_init (GtkSourceCompletion *completion)
 {
 	completion->priv = GTK_SOURCE_COMPLETION_GET_PRIVATE (completion);
 
+	completion->priv->capability_map = g_hash_table_new_full (g_str_hash, 
+	                                                          g_str_equal,
+	                                                          (GDestroyNotify)g_free,
+	                                                          (GDestroyNotify)g_list_free);
+	                                                     
+
 	initialize_ui (completion);
 }
 
@@ -2031,12 +2033,80 @@ add_proposals (GtkSourceCompletion         *completion,
 			g_object_unref (proposal);
 		}
 	}
-	
+
 	gtk_source_completion_model_run_add_proposals (completion->priv->model_proposals);
 	
 	g_list_free (proposals);
 }
 
+static gchar **
+get_separate_capabilities (GtkSourceCompletionProvider *provider)
+{
+	const gchar *capabilities;
+	capabilities = gtk_source_completion_provider_get_capabilities (provider);
+	
+	return g_strsplit_set (capabilities, " ,", -1);
+}
+
+static void
+add_capabilities (GtkSourceCompletion          *completion,
+                  GtkSourceCompletionProvider  *provider)
+{
+	gchar **caps = get_separate_capabilities (provider);
+	gchar **orig = caps;
+	
+	while (caps && *caps)
+	{
+		GList *ptr = g_hash_table_lookup (completion->priv->capability_map,
+		                                  *caps);
+
+		ptr = g_list_copy (ptr);
+		ptr = g_list_append (ptr, provider);
+		
+		g_hash_table_insert (completion->priv->capability_map,
+		                     g_strdup (*caps),
+		                     ptr);
+		
+		++caps;
+	}
+	
+	if (orig)
+	{
+		g_strfreev (orig);
+	}
+}
+
+static void
+remove_capabilities (GtkSourceCompletion          *completion,
+                     GtkSourceCompletionProvider  *provider)
+{
+	gchar **caps = get_separate_capabilities (provider);
+	gchar **orig = caps;
+	
+	while (caps && *caps)
+	{
+		GList *ptr = g_hash_table_lookup (completion->priv->capability_map,
+		                                  *caps);
+
+		ptr = g_list_copy (ptr);
+		
+		if (ptr)
+		{
+			ptr = g_list_remove (ptr, provider);
+			g_hash_table_insert (completion->priv->capability_map,
+			                     g_strdup (*caps),
+			                     ptr);
+		}
+		
+		++caps;
+	}
+	
+	if (orig)
+	{
+		g_strfreev (orig);
+	}
+}
+
 /**
  * gtk_source_completion_show:
  * @completion: A #GtkSourceCompletion
@@ -2062,12 +2132,6 @@ gtk_source_completion_show (GtkSourceCompletion *completion,
 	/* Make sure to clear any active completion */
 	gtk_source_completion_hide_default (completion);
 	
-	/* Use all registered providers if no providers were specified */
-	if (providers == NULL)
-	{
-		providers = completion->priv->automatic_providers;
-	}
-	
 	if (providers == NULL)
 	{
 		gtk_source_completion_hide (completion);
@@ -2102,17 +2166,59 @@ gtk_source_completion_show (GtkSourceCompletion *completion,
 			add_proposals (completion, GTK_SOURCE_COMPLETION_PROVIDER (l->data));
 		}
 	}
-	
+		
 	completion->priv->active_providers = 
 		g_list_reverse (completion->priv->active_providers);
 
 	completion->priv->is_interactive = FALSE;		
 
 	update_selection_label (completion);
-
+	
 	return TRUE;
 }
 
+GList *
+gtk_source_completion_get_providers (GtkSourceCompletion  *completion,
+                                     const gchar          *capabilities)
+{
+	gchar **caps = NULL;
+	gchar **orig;
+	GList *ret = NULL;
+	
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), NULL);
+
+	if (capabilities)
+	{
+		caps = g_strsplit_set (capabilities, " ,", -1);
+	}
+	
+	if (caps)
+	{
+		orig = caps;
+		
+		while (*caps)
+		{
+			GList *ptr = g_hash_table_lookup (completion->priv->capability_map,
+			                                  *caps);
+
+			ret = g_list_concat (ret, g_list_copy (ptr));
+			
+			++caps;
+		}
+		
+		g_strfreev (orig);
+	}
+	else
+	{
+		ret = g_list_copy (completion->priv->providers);
+	}
+		
+	g_list_foreach (ret, (GFunc)g_object_ref, NULL);
+
+	
+	return ret;
+}
+
 GQuark
 gtk_source_completion_error_quark (void)
 {
@@ -2181,19 +2287,7 @@ gtk_source_completion_add_provider (GtkSourceCompletion          *completion,
 	completion->priv->providers = g_list_append (completion->priv->providers, 
 	                                             g_object_ref (provider));
 
-	if (gtk_source_completion_provider_get_interactive (provider))
-	{
-		completion->priv->interactive_providers = 
-			g_list_append (completion->priv->interactive_providers,
-			               provider);
-	}
-	
-	if (gtk_source_completion_provider_get_automatic (provider))
-	{
-		completion->priv->automatic_providers = 
-			g_list_append (completion->priv->automatic_providers,
-			               provider);
-	}
+	add_capabilities (completion, provider);
 
 	if (error)
 	{
@@ -2228,19 +2322,7 @@ gtk_source_completion_remove_provider (GtkSourceCompletion          *completion,
 
 	if (item != NULL)
 	{
-		if (gtk_source_completion_provider_get_interactive (provider))
-		{
-			completion->priv->interactive_providers = 
-				g_list_remove (completion->priv->interactive_providers,
-				               provider);
-		}
-		
-		if (gtk_source_completion_provider_get_automatic (provider))
-		{
-			completion->priv->automatic_providers = 
-				g_list_remove (completion->priv->automatic_providers,
-				               provider);
-		}
+		remove_capabilities (completion, provider);
 
 		completion->priv->providers = g_list_remove_link (completion->priv->providers, item);
 		g_object_unref (provider);
diff --git a/gtksourceview/gtksourcecompletion.h b/gtksourceview/gtksourcecompletion.h
index 684fe83..8c3b638 100644
--- a/gtksourceview/gtksourcecompletion.h
+++ b/gtksourceview/gtksourcecompletion.h
@@ -84,6 +84,8 @@ gboolean	 gtk_source_completion_remove_provider		(GtkSourceCompletion          *
 								 GtkSourceCompletionProvider  *provider,
 								 GError                      **error);
 
+GList		*gtk_source_completion_get_providers		(GtkSourceCompletion         *completion,
+                                                                 const gchar                 *capabilities);
 gboolean	 gtk_source_completion_show			(GtkSourceCompletion         *completion,
 								 GList                       *providers,
 								 const gchar                 *criteria,
diff --git a/gtksourceview/gtksourcecompletionprovider.c b/gtksourceview/gtksourcecompletionprovider.c
index 59f6e30..6b5c0c2 100644
--- a/gtksourceview/gtksourcecompletionprovider.c
+++ b/gtksourceview/gtksourcecompletionprovider.c
@@ -67,16 +67,10 @@ gtk_source_completion_provider_filter_proposal_default (GtkSourceCompletionProvi
 	return TRUE;
 }
 
-static gboolean
-gtk_source_completion_provider_get_automatic_default (GtkSourceCompletionProvider *provider)
-{
-	return TRUE;
-}
-
-static gboolean
-gtk_source_completion_provider_get_interactive_default (GtkSourceCompletionProvider *provider)
+static const gchar *
+gtk_source_completion_provider_get_capabilities_default (GtkSourceCompletionProvider *provider)
 {
-	return FALSE;
+	return GTK_SOURCE_COMPLETION_CAPABILITY_AUTOMATIC;
 }
 
 static GtkWidget *
@@ -112,8 +106,7 @@ gtk_source_completion_provider_base_init (GtkSourceCompletionProviderIface *ifac
 	iface->get_proposals = gtk_source_completion_provider_get_proposals_default;
 	iface->filter_proposal = gtk_source_completion_provider_filter_proposal_default;
 	
-	iface->get_automatic = gtk_source_completion_provider_get_automatic_default;
-	iface->get_interactive = gtk_source_completion_provider_get_interactive_default;
+	iface->get_capabilities = gtk_source_completion_provider_get_capabilities_default;
 	
 	iface->get_info_widget = gtk_source_completion_provider_get_info_widget_default;
 	iface->update_info = gtk_source_completion_provider_update_info_default;
@@ -239,37 +232,18 @@ gtk_source_completion_provider_filter_proposal (GtkSourceCompletionProvider *pro
 }
 
 /**
- * gtk_source_completion_provider_get_interactive:
- * @provider: The #GtkSourceCompletionProvider
- *
- * Get whether @provider responds to interactive completion (e.g. completion
- * when typing).
- *
- * Returns: %TRUE if @provider can be used interactively, or %FALSE otherwise.
- */
-gboolean
-gtk_source_completion_provider_get_interactive (GtkSourceCompletionProvider *provider)
-{
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), FALSE);
-	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_interactive (provider);
-}
-
-/**
- * gtk_source_completion_provider_get_automatic:
+ * gtk_source_completion_provider_get_capabilities:
  * @provider: The #GtkSourceCompletionProvider
  *
- * Get whether @provider is automatically included in the list of completions.
- * This means that it will be shown in the default list of completions as 
- * activated by the "show-completion" keybinding (&lt;Ctrl&gt;space by default) on
- * the #GtkSourceView.
+ * A list of capabilities this provider supports
  *
- * Returns: %TRUE if @provider is automatically included, or %FALSE otherwise.
+ * Returns: list of capabilities.
  */
-gboolean
-gtk_source_completion_provider_get_automatic (GtkSourceCompletionProvider *provider)
+const gchar *
+gtk_source_completion_provider_get_capabilities (GtkSourceCompletionProvider *provider)
 {
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), FALSE);
-	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_automatic (provider);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), NULL);
+	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_capabilities (provider);
 }
 
 /**
diff --git a/gtksourceview/gtksourcecompletionprovider.h b/gtksourceview/gtksourcecompletionprovider.h
index 8b840e6..719a6e5 100644
--- a/gtksourceview/gtksourcecompletionprovider.h
+++ b/gtksourceview/gtksourcecompletionprovider.h
@@ -31,12 +31,14 @@
 
 G_BEGIN_DECLS
 
-
 #define GTK_TYPE_SOURCE_COMPLETION_PROVIDER 			(gtk_source_completion_provider_get_type ())
 #define GTK_SOURCE_COMPLETION_PROVIDER(obj) 			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER, GtkSourceCompletionProvider))
 #define GTK_IS_SOURCE_COMPLETION_PROVIDER(obj) 			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER))
 #define GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE(obj) 	(G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER, GtkSourceCompletionProviderIface))
 
+#define GTK_SOURCE_COMPLETION_CAPABILITY_INTERACTIVE "standard::interactive"
+#define GTK_SOURCE_COMPLETION_CAPABILITY_AUTOMATIC "standard::automatic"
+
 typedef struct _GtkSourceCompletionProvider GtkSourceCompletionProvider;
 typedef struct _GtkSourceCompletionProviderIface GtkSourceCompletionProviderIface;
 
@@ -53,9 +55,8 @@ struct _GtkSourceCompletionProviderIface
 						 GtkTextIter                 *iter,
 						 const gchar                 *criteria);
 
-	gboolean         (*get_automatic)	(GtkSourceCompletionProvider *provider);
-	gboolean         (*get_interactive)	(GtkSourceCompletionProvider *provider);
-						 
+	const gchar     *(*get_capabilities)	(GtkSourceCompletionProvider *provider);
+
 	GtkWidget 	*(*get_info_widget)	(GtkSourceCompletionProvider *provider,
 						 GtkSourceCompletionProposal *proposal);
 	void		 (*update_info)		(GtkSourceCompletionProvider *provider,
@@ -82,8 +83,7 @@ gboolean	 gtk_source_completion_provider_filter_proposal	(GtkSourceCompletionPro
 								 GtkTextIter                 *iter,
 								 const gchar                 *criteria);
 
-gboolean 	 gtk_source_completion_provider_get_automatic	(GtkSourceCompletionProvider *provider);
-gboolean 	 gtk_source_completion_provider_get_interactive	(GtkSourceCompletionProvider *provider);
+const gchar 	*gtk_source_completion_provider_get_capabilities (GtkSourceCompletionProvider *provider);
 
 GtkWidget	*gtk_source_completion_provider_get_info_widget	(GtkSourceCompletionProvider *provider,
 								 GtkSourceCompletionProposal *proposal);
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index 7fd2074..4dbb012 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -40,6 +40,7 @@
 #include "gtksourcemark.h"
 #include "gtksourceview.h"
 #include "gtksourcecompletion-private.h"
+#include "gtksourcecompletionutils.h"
 
 /*
 #define ENABLE_DEBUG
@@ -1006,7 +1007,25 @@ gtk_source_view_redo (GtkSourceView *view)
 static void
 gtk_source_view_show_completion_real (GtkSourceView *view)
 {
-	gtk_source_view_show_completion (view, NULL);
+	GtkSourceCompletion *completion;
+	GList *providers;
+	gchar *word;
+
+	completion = gtk_source_view_get_completion (view);
+	
+	providers = gtk_source_completion_get_providers (completion, 
+	                                                 GTK_SOURCE_COMPLETION_CAPABILITY_AUTOMATIC);
+
+	/* Show automatic providers at the cursor with the current word as the
+	   criteria */
+	word = gtk_source_completion_utils_get_word (
+			GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))));
+
+	gtk_source_completion_show (completion, providers, word, NULL);
+
+	g_free (word);
+	g_list_foreach (providers, (GFunc)g_object_unref, NULL);
+	g_list_free (providers);
 }
 
 static void
@@ -4051,18 +4070,6 @@ gtk_source_view_update_style_scheme (GtkSourceView *view)
 			view->priv->style_scheme_applied = FALSE;
 	}
 }
-
-void
-gtk_source_view_show_completion	(GtkSourceView *view,
-                                 GList         *proposals)
-{
-	GtkSourceCompletion *completion;
-	
-	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
-
-	completion = gtk_source_view_get_completion (view);
-	gtk_source_completion_show (completion, proposals, NULL, NULL);
-}
 							 
 /**
  * gtk_source_view_get_completion:
diff --git a/gtksourceview/gtksourceview.h b/gtksourceview/gtksourceview.h
index b055c93..06b21e5 100644
--- a/gtksourceview/gtksourceview.h
+++ b/gtksourceview/gtksourceview.h
@@ -199,9 +199,6 @@ void		 gtk_source_view_set_draw_spaces	(GtkSourceView   *view,
 GtkSourceDrawSpacesFlags
 		gtk_source_view_get_draw_spaces		(GtkSourceView   *view);
 
-void		 gtk_source_view_show_completion	(GtkSourceView   *view,
-							 GList           *proposals);
-
 GtkSourceCompletion *
 		gtk_source_view_get_completion		(GtkSourceView   *view);
 



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