[gtksourceview/gtksourcecompletion] Revert previous commits that I commited by mistake.
- From: Ignacio Casal Quinteiro <icq src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtksourceview/gtksourcecompletion] Revert previous commits that I commited by mistake.
- Date: Tue, 23 Jun 2009 05:49:12 -0400 (EDT)
commit b0e5df9e362a220c861ac39ff2dedf76b3a2f181
Author: Ignacio Casal Quinteiro <icq gnome org>
Date: Tue Jun 23 11:46:20 2009 +0200
Revert previous commits that I commited by mistake.
docs/reference/tmpl/view.sgml | 9 +
gtksourceview/gtksourcecompletion.c | 171 ++++++++--
gtksourceview/gtksourcecompletion.h | 1 +
gtksourceview/gtksourcecompletionmodel.c | 479 ++++++++++++++++++++-------
gtksourceview/gtksourcecompletionmodel.h | 15 +-
gtksourceview/gtksourcecompletionproposal.c | 72 ----
gtksourceview/gtksourcecompletionproposal.h | 8 -
gtksourceview/gtksourceview.c | 2 +-
8 files changed, 539 insertions(+), 218 deletions(-)
---
diff --git a/docs/reference/tmpl/view.sgml b/docs/reference/tmpl/view.sgml
index c172bc9..f599bb8 100644
--- a/docs/reference/tmpl/view.sgml
+++ b/docs/reference/tmpl/view.sgml
@@ -448,3 +448,12 @@ a text view which syntax highlighting, undo/redo and text marks. Use a
@Returns:
+<!-- ##### FUNCTION gtk_source_view_show_completion ##### -->
+<para>
+
+</para>
+
+ view:
+ proposals:
+
+
diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index b639c7e..f8cd7d2 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -107,11 +107,13 @@ struct _GtkSourceCompletionPrivate
guint show_timed_out_id;
guint auto_complete_delay;
+ guint minimum_auto_complete_length;
gint typing_line;
gint typing_line_offset;
GtkSourceCompletionProvider *filter_provider;
+ gchar *filter_criteria;
gboolean inserting_data;
gboolean is_interactive;
@@ -494,7 +496,7 @@ update_selection_label (GtkSourceCompletion *completion)
{
name = g_markup_escape_text (
gtk_source_completion_provider_get_name (completion->priv->filter_provider),
- -1);
+ -1);
gtk_image_set_from_pixbuf (GTK_IMAGE (completion->priv->selection_image),
(GdkPixbuf *)gtk_source_completion_provider_get_icon (completion->priv->filter_provider));
@@ -510,12 +512,28 @@ update_selection_label (GtkSourceCompletion *completion)
else
{
gtk_label_set_markup (GTK_LABEL (completion->priv->selection_label),
- name);
+ name);
}
g_free (name);
}
+static void
+do_refilter (GtkSourceCompletion *completion,
+ gboolean hide_if_empty)
+{
+ gtk_source_completion_model_refilter (completion->priv->model_proposals);
+
+ /* Check if there are any proposals left */
+ if (hide_if_empty && !completion->priv->inserting_data &&
+ gtk_source_completion_model_is_empty (completion->priv->model_proposals, FALSE))
+ {
+ gtk_source_completion_hide (completion);
+ }
+
+ update_selection_label (completion);
+}
+
typedef GList * (*ListSelector)(GList *);
static gboolean
@@ -547,7 +565,7 @@ select_provider (GtkSourceCompletion *completion,
completion->priv->filter_provider = NULL;
update_selection_label (completion);
- //do_refilter (completion, FALSE);
+ do_refilter (completion, FALSE);
return TRUE;
}
@@ -615,7 +633,7 @@ select_provider (GtkSourceCompletion *completion,
}
update_selection_label (completion);
- //do_refilter (completion, FALSE);
+ do_refilter (completion, FALSE);
return TRUE;
}
@@ -675,6 +693,51 @@ update_info_position (GtkSourceCompletion *completion)
gtk_window_move (GTK_WINDOW (completion->priv->info_window), x, y);
}
+static GtkSourceCompletionModelFilterFlag
+proposals_filter_func (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ GtkSourceCompletion *completion)
+{
+ GtkSourceCompletionModelFilterFlag ret = GTK_SOURCE_COMPLETION_MODEL_NONE;
+ gboolean visible;
+ gboolean count;
+ GtkTextIter iter;
+
+ /* Filter on provider */
+ if (completion->priv->filter_provider != NULL && completion->priv->filter_provider != provider)
+ {
+ visible = FALSE;
+ count = TRUE;
+ }
+ else if (completion->priv->filter_criteria == NULL)
+ {
+ visible = TRUE;
+ count = FALSE;
+ }
+ else
+ {
+ visible = gtk_source_completion_provider_filter_proposal (provider,
+ proposal,
+ &iter,
+ completion->priv->filter_criteria);
+
+ count = FALSE;
+ }
+
+ if (!visible)
+ {
+ ret |= GTK_SOURCE_COMPLETION_MODEL_FILTERED;
+
+ if (count)
+ {
+ ret |= GTK_SOURCE_COMPLETION_MODEL_COUNT;
+ }
+ }
+
+ return ret;
+}
+
static void
row_activated_cb (GtkTreeView *tree_view,
GtkTreePath *path,
@@ -975,6 +1038,20 @@ view_key_press_event_cb (GtkSourceView *view,
}
static void
+refilter_proposals_with_word (GtkSourceCompletion *completion)
+{
+ GtkTextView *view;
+
+ g_free (completion->priv->filter_criteria);
+ view = GTK_TEXT_VIEW (completion->priv->view);
+
+ completion->priv->filter_criteria =
+ gtk_source_completion_utils_get_word (GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (view)));
+
+ do_refilter (completion, TRUE);
+}
+
+static void
update_typing_offsets (GtkSourceCompletion *completion)
{
GtkTextBuffer *buffer;
@@ -1029,9 +1106,10 @@ show_auto_completion (GtkSourceCompletion *completion)
&end);
/* Check minimum amount of characters */
- if (g_utf8_strlen (word, -1) >= 1)
+ if (g_utf8_strlen (word, -1) >= completion->priv->minimum_auto_complete_length)
{
- gtk_source_completion_show (completion, providers, &start);
+ gtk_source_completion_show (completion, providers,
+ word, &start);
completion->priv->is_interactive = TRUE;
}
@@ -1071,14 +1149,14 @@ buffer_delete_range_cb (GtkTextBuffer *buffer,
{
if (gtk_text_iter_get_line (start) != completion->priv->typing_line ||
(completion->priv->is_interactive &&
- gtk_text_iter_get_line_offset (start) < completion->priv->typing_line_offset + 1))
+ gtk_text_iter_get_line_offset (start) < completion->priv->typing_line_offset +
+ completion->priv->minimum_auto_complete_length))
{
gtk_source_completion_hide (completion);
}
else
{
- //FIXME create the context, remove items, and add new ones
- //refilter_proposals_with_word (completion);
+ refilter_proposals_with_word (completion);
}
}
@@ -1105,16 +1183,15 @@ buffer_insert_text_cb (GtkTextBuffer *buffer,
}
else
{
- if ((completion->priv->is_interactive &&
- g_unichar_isspace (g_utf8_get_char (text))) ||
+ if ((completion->priv->is_interactive &&
+ gtk_source_completion_utils_is_separator (g_utf8_get_char (text))) ||
gtk_text_iter_get_line (location) != completion->priv->typing_line)
{
gtk_source_completion_hide (completion);
}
else
{
- //FIXME create the context, remove items, and add new ones
- //refilter_proposals_with_word (completion);
+ refilter_proposals_with_word (completion);
}
}
}
@@ -1211,6 +1288,8 @@ gtk_source_completion_finalize (GObject *object)
g_hash_table_destroy (completion->priv->capability_map);
g_list_free (completion->priv->providers);
+ g_free (completion->priv->filter_criteria);
+
G_OBJECT_CLASS (gtk_source_completion_parent_class)->finalize (object);
}
@@ -1246,6 +1325,9 @@ gtk_source_completion_get_property (GObject *object,
case PROP_AUTO_COMPLETE_DELAY:
g_value_set_uint (value, completion->priv->auto_complete_delay);
break;
+ case PROP_MINIMUM_AUTO_COMPLETE_LENGTH:
+ g_value_set_uint (value, completion->priv->minimum_auto_complete_length);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1292,6 +1374,9 @@ gtk_source_completion_set_property (GObject *object,
case PROP_AUTO_COMPLETE_DELAY:
completion->priv->auto_complete_delay = g_value_get_uint (value);
break;
+ case PROP_MINIMUM_AUTO_COMPLETE_LENGTH:
+ completion->priv->minimum_auto_complete_length = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1301,9 +1386,6 @@ gtk_source_completion_set_property (GObject *object,
static void
gtk_source_completion_hide_default (GtkSourceCompletion *completion)
{
- gtk_widget_hide (completion->priv->info_window);
- gtk_widget_hide (completion->priv->window);
-
completion->priv->filter_provider = NULL;
gtk_label_set_markup (GTK_LABEL (completion->priv->default_info), "");
@@ -1313,7 +1395,13 @@ gtk_source_completion_hide_default (GtkSourceCompletion *completion)
g_list_free (completion->priv->active_providers);
completion->priv->active_providers = NULL;
+ g_free (completion->priv->filter_criteria);
+ completion->priv->filter_criteria = NULL;
+
completion->priv->info_visible = GTK_WIDGET_VISIBLE (completion->priv->info_window);
+
+ gtk_widget_hide (completion->priv->info_window);
+ gtk_widget_hide (completion->priv->window);
}
static void
@@ -1432,6 +1520,21 @@ gtk_source_completion_class_init (GtkSourceCompletionClass *klass)
G_MAXUINT,
250,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ /**
+ * GtkSourceCompletion:min-len:
+ *
+ * The minimum word length to initiate interactive completion.
+ *
+ */
+ g_object_class_install_property (object_class,
+ PROP_MINIMUM_AUTO_COMPLETE_LENGTH,
+ g_param_spec_uint ("minimum-auto-complete-length",
+ _("Minimum Auto Complete Length"),
+ _("Minimum word length to initiate interactive completion"),
+ 0,
+ G_MAXUINT,
+ 3,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* GtkSourceCompletion::show:
@@ -1632,11 +1735,9 @@ on_row_inserted_cb (GtkTreeModel *tree_model,
g_signal_emit (completion, signals[SHOW], 0);
}
- /* FIXME this fixes the header visibility but produces the problem of
- * scrolling */
- /*gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (completion->priv->tree_view_proposals),
+ gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (completion->priv->tree_view_proposals),
0,
- 0);*/
+ 0);
}
static void
@@ -1652,6 +1753,17 @@ on_items_added_cb (GtkSourceCompletionModel *model,
}
}
+static void
+on_filter_done_cb (GtkSourceCompletionModel *model,
+ GtkSourceCompletion *completion)
+{
+ /* Check if there are any completions */
+ if (gtk_source_completion_model_is_empty (model, FALSE))
+ {
+ gtk_source_completion_hide (completion);
+ }
+}
+
static GtkWidget *
initialize_proposals_ui (GtkSourceCompletion *completion)
{
@@ -1661,13 +1773,20 @@ initialize_proposals_ui (GtkSourceCompletion *completion)
GtkWidget *scrolled_window;
GtkWidget *tree_view;
- completion->priv->model_proposals = gtk_source_completion_model_new ();
+ completion->priv->model_proposals =
+ gtk_source_completion_model_new ((GtkSourceCompletionModelVisibleFunc)proposals_filter_func,
+ completion);
g_signal_connect (completion->priv->model_proposals,
"items-added",
G_CALLBACK (on_items_added_cb),
completion);
+ g_signal_connect (completion->priv->model_proposals,
+ "filter-done",
+ G_CALLBACK (on_filter_done_cb),
+ completion);
+
gtk_source_completion_model_set_show_headers (completion->priv->model_proposals,
completion->priv->show_headers);
tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (completion->priv->model_proposals));
@@ -1883,6 +2002,7 @@ gtk_source_completion_init (GtkSourceCompletion *completion)
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)g_list_free);
+
initialize_ui (completion);
}
@@ -1915,7 +2035,7 @@ add_proposals (GtkSourceCompletion *completion,
}
gtk_source_completion_model_run_add_proposals (completion->priv->model_proposals);
-
+
g_list_free (proposals);
}
@@ -1991,6 +2111,7 @@ remove_capabilities (GtkSourceCompletion *completion,
* gtk_source_completion_show:
* @completion: A #GtkSourceCompletion
* @providers: A list of #GtkSourceCompletionProvider
+ * @criteria: The filter criteria
* @place: The place where you want to position the popup window, or %NULL
*
* Shows the show completion window. If @place if %NULL the popup window will
@@ -2001,6 +2122,7 @@ remove_capabilities (GtkSourceCompletion *completion,
gboolean
gtk_source_completion_show (GtkSourceCompletion *completion,
GList *providers,
+ const gchar *criteria,
GtkTextIter *place)
{
GList *l;
@@ -2016,6 +2138,7 @@ gtk_source_completion_show (GtkSourceCompletion *completion,
return FALSE;
}
+ completion->priv->filter_criteria = g_strdup (criteria);
update_typing_offsets (completion);
if (place == NULL)
@@ -2043,11 +2166,11 @@ 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;
+ completion->priv->is_interactive = FALSE;
update_selection_label (completion);
diff --git a/gtksourceview/gtksourcecompletion.h b/gtksourceview/gtksourcecompletion.h
index bd439c4..8c3b638 100644
--- a/gtksourceview/gtksourcecompletion.h
+++ b/gtksourceview/gtksourcecompletion.h
@@ -88,6 +88,7 @@ GList *gtk_source_completion_get_providers (GtkSourceCompletion *compl
const gchar *capabilities);
gboolean gtk_source_completion_show (GtkSourceCompletion *completion,
GList *providers,
+ const gchar *criteria,
GtkTextIter *place);
void gtk_source_completion_hide (GtkSourceCompletion *completion);
diff --git a/gtksourceview/gtksourcecompletionmodel.c b/gtksourceview/gtksourcecompletionmodel.c
index de4e9cd..4c90768 100644
--- a/gtksourceview/gtksourcecompletionmodel.c
+++ b/gtksourceview/gtksourcecompletionmodel.c
@@ -23,6 +23,7 @@
#include "gtksourcecompletionmodel.h"
#define ITEMS_PER_CALLBACK 500
+#define FILTER_PER_CALLBACK 1000
#define GTK_SOURCE_COMPLETION_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_COMPLETION_MODEL, GtkSourceCompletionModelPrivate))
@@ -33,14 +34,15 @@ typedef struct
GtkSourceCompletionProvider *provider;
GtkSourceCompletionProposal *proposal;
+ GtkSourceCompletionModelFilterFlag filtered;
gulong changed_id;
} ProposalNode;
typedef struct
{
GList *item;
- GHashTable *hash;
guint num;
+ guint visible_items;
} HeaderInfo;
struct _GtkSourceCompletionModelPrivate
@@ -52,16 +54,25 @@ struct _GtkSourceCompletionModelPrivate
guint num;
GHashTable *num_per_provider;
+ GtkSourceCompletionModelVisibleFunc filter;
+ gpointer filter_data;
+
gboolean show_headers;
guint idle_id;
GQueue *item_queue;
+
+ guint idle_filter_id;
+
+ GList *next_filter_item;
+ GtkTreeRowReference *next_filter_path;
};
/* Signals */
enum
{
ITEMS_ADDED,
+ FILTER_DONE,
LAST_SIGNAL
};
@@ -88,10 +99,22 @@ path_from_list (GtkSourceCompletionModel *model,
GList *item)
{
gint index = 0;
+ GList *ptr = model->priv->store;
+ ProposalNode *node;
- index = g_list_position (model->priv->store, item);
+ while (ptr && ptr != item)
+ {
+ node = (ProposalNode *)ptr->data;
+
+ if (!node->filtered)
+ {
+ ++index;
+ }
+
+ ptr = g_list_next (ptr);
+ }
- if (index == -1)
+ if (ptr != item)
{
return NULL;
}
@@ -133,6 +156,7 @@ get_iter_from_index (GtkSourceCompletionModel *model,
gint index)
{
GList *item;
+ ProposalNode *node;
if (index < 0 || index >= model->priv->num)
{
@@ -141,7 +165,20 @@ get_iter_from_index (GtkSourceCompletionModel *model,
item = model->priv->store;
- item = g_list_nth (item, index);
+ while (item != NULL && index >= 0)
+ {
+ node = (ProposalNode *)item->data;
+
+ if (!node->filtered)
+ {
+ --index;
+ }
+
+ if (index != -1)
+ {
+ item = g_list_next (item);
+ }
+ }
if (item != NULL)
{
@@ -236,16 +273,21 @@ tree_model_get_value (GtkTreeModel *tree_model,
}
static gboolean
-get_next_element (GList *item,
- GtkTreeIter *iter)
+find_first_not_filtered (GList *item,
+ GtkTreeIter *iter)
{
- while ((item = g_list_next (item)))
+ ProposalNode *node;
+
+ while (item)
{
- ProposalNode *node = (ProposalNode *)item->data;
+ node = (ProposalNode *)item->data;
- /* Skip headers */
- if (node->proposal != NULL)
+ if (!node->filtered)
+ {
break;
+ }
+
+ item = g_list_next (item);
}
if (item != NULL)
@@ -263,10 +305,14 @@ static gboolean
tree_model_iter_next (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
+ GList *item;
+
g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), FALSE);
g_return_val_if_fail (iter != NULL, FALSE);
- return get_next_element ((GList *)iter->user_data, iter);
+ item = g_list_next ((GList *)iter->user_data);
+
+ return find_first_not_filtered (item, iter);
}
static gboolean
@@ -278,9 +324,14 @@ tree_model_iter_children (GtkTreeModel *tree_model,
g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
- /* FIXME: not sure if this should be: (GList *)iter->user_data, iter */
- //return get_next_element (GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->store, iter);
- return get_next_element ((GList *)iter->user_data, iter);
+ if (parent != NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return find_first_not_filtered (GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->store, iter);
+ }
}
static gboolean
@@ -327,7 +378,7 @@ tree_model_iter_nth_child (GtkTreeModel *tree_model,
else
{
return get_iter_from_index (GTK_SOURCE_COMPLETION_MODEL (tree_model),
- iter,
+ iter,
n);
}
}
@@ -413,6 +464,24 @@ cancel_append (GtkSourceCompletionModel *model)
{
g_source_remove (model->priv->idle_id);
model->priv->idle_id = 0;
+ }
+}
+
+static void
+cancel_refilter (GtkSourceCompletionModel *model)
+{
+ if (model->priv->next_filter_path != NULL)
+ {
+ gtk_tree_row_reference_free (model->priv->next_filter_path);
+ model->priv->next_filter_path = NULL;
+ }
+
+ if (model->priv->idle_filter_id != 0)
+ {
+ g_source_remove (model->priv->idle_filter_id);
+ model->priv->idle_filter_id = 0;
+
+ g_signal_emit (model, signals[FILTER_DONE], 0);
}
}
@@ -422,6 +491,7 @@ gtk_source_completion_model_dispose (GObject *object)
GtkSourceCompletionModel *model = GTK_SOURCE_COMPLETION_MODEL (object);
cancel_append (model);
+ cancel_refilter (model);
if (model->priv->item_queue != NULL)
{
@@ -468,35 +538,26 @@ gtk_source_completion_model_class_init (GtkSourceCompletionModelClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
+
+ signals[FILTER_DONE] =
+ g_signal_new ("filter-done",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkSourceCompletionModelClass, filter_done),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
}
static void
free_num (gpointer data)
{
- HeaderInfo *info = (HeaderInfo *)data;
-
- g_hash_table_destroy (info->hash);
g_slice_free (HeaderInfo, data);
}
-static gboolean
-compare_nodes (gconstpointer a,
- gconstpointer b)
-{
- ProposalNode *p1 = (ProposalNode *)a;
- ProposalNode *p2 = (ProposalNode *)b;
-
- return gtk_source_completion_proposal_equals (p1->proposal, p2->proposal);
-}
-
-static guint
-hash_node (gconstpointer v)
-{
- ProposalNode *node = (ProposalNode *)v;
-
- return gtk_source_completion_proposal_get_hash (node->proposal);
-}
-
static void
gtk_source_completion_model_init (GtkSourceCompletionModel *self)
{
@@ -519,39 +580,78 @@ gtk_source_completion_model_init (GtkSourceCompletionModel *self)
}
static void
-num_inc (GtkSourceCompletionModel *model,
- GtkSourceCompletionProvider *provider,
- gboolean header)
+num_inc (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider,
+ gboolean inc_local,
+ gboolean inc_global)
{
HeaderInfo *info;
info = g_hash_table_lookup (model->priv->num_per_provider, provider);
- ++model->priv->num;
+ if (inc_global)
+ {
+ ++model->priv->num;
+
+ if (info != NULL)
+ {
+ ++info->visible_items;
+ }
+ }
- if (info != NULL && !header)
+ if (inc_local && info != NULL)
{
++(info->num);
}
}
static void
-num_dec (GtkSourceCompletionModel *model,
- GtkSourceCompletionProvider *provider,
- gboolean header)
+num_dec (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider,
+ gboolean dec_local,
+ gboolean dec_global)
{
HeaderInfo *info;
info = g_hash_table_lookup (model->priv->num_per_provider, provider);
- --model->priv->num;
+ if (dec_global)
+ {
+ --model->priv->num;
- if (info != NULL && !header)
+ if (info != NULL)
+ {
+ --info->visible_items;
+ }
+ }
+
+ if (dec_local && info != NULL && info->num > 0)
{
--(info->num);
}
}
+static GtkSourceCompletionModelFilterFlag
+node_update_filter_state (GtkSourceCompletionModel *model,
+ ProposalNode *node)
+{
+ GtkSourceCompletionModelFilterFlag ret;
+
+ if (node->proposal == NULL)
+ {
+ return node->filtered;
+ }
+
+ ret = node->filtered;
+
+ node->filtered = model->priv->filter (model,
+ node->provider,
+ node->proposal,
+ model->priv->filter_data);
+
+ return ret;
+}
+
static void
update_show_headers (GtkSourceCompletionModel *model,
gboolean show)
@@ -577,12 +677,20 @@ update_show_headers (GtkSourceCompletionModel *model,
while (g_hash_table_iter_next (&hiter, (gpointer *)&provider, (gpointer *)&info))
{
- if (info->num > 0)
+ if (info->visible_items > 0)
{
node = (ProposalNode *)info->item->data;
++num;
- items = g_list_append (items, info);
+ if (show && node->filtered)
+ {
+ items = g_list_append (items, info);
+ }
+
+ if (!show && !node->filtered)
+ {
+ items = g_list_append (items, info);
+ }
}
}
@@ -593,9 +701,10 @@ update_show_headers (GtkSourceCompletionModel *model,
info = (HeaderInfo *)item->data;
node = (ProposalNode *)info->item->data;
+ node->filtered = GTK_SOURCE_COMPLETION_MODEL_NONE;
iter.user_data = info->item;
- num_inc (model, node->provider, TRUE);
+ num_inc (model, node->provider, FALSE, TRUE);
path = path_from_list (model, info->item);
gtk_tree_model_row_inserted (GTK_TREE_MODEL (model),
@@ -610,8 +719,9 @@ update_show_headers (GtkSourceCompletionModel *model,
info = (HeaderInfo *)items->data;
node = (ProposalNode *)info->item->data;
- num_dec (model, node->provider, TRUE);
+ num_dec (model, node->provider, FALSE, TRUE);
+ node->filtered = GTK_SOURCE_COMPLETION_MODEL_FILTERED;
path = path_from_list (model, info->item);
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
gtk_tree_path_free (path);
@@ -620,52 +730,71 @@ update_show_headers (GtkSourceCompletionModel *model,
g_list_free (items);
}
+static void
+refilter_headers (GtkSourceCompletionModel *model)
+{
+ GtkSourceCompletionProvider *provider;
+ HeaderInfo *info;
+ GHashTableIter hiter;
+ ProposalNode *node;
+ GtkTreePath *path;
+
+ g_hash_table_iter_init (&hiter, model->priv->num_per_provider);
+
+ while (g_hash_table_iter_next (&hiter, (gpointer *)&provider, (gpointer *)&info))
+ {
+ node = (ProposalNode *)info->item->data;
+
+ if (!node->filtered)
+ {
+ node->filtered = GTK_SOURCE_COMPLETION_MODEL_FILTERED;
+ num_dec (model, provider, FALSE, TRUE);
+
+ path = path_from_list (model, info->item);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model),
+ path);
+ gtk_tree_path_free (path);
+ }
+ }
+
+ if (model->priv->show_headers)
+ {
+ update_show_headers (model, TRUE);
+ return;
+ }
+}
+
/* Public */
GtkSourceCompletionModel*
-gtk_source_completion_model_new (void)
+gtk_source_completion_model_new (GtkSourceCompletionModelVisibleFunc func,
+ gpointer userdata)
{
- return g_object_new (GTK_TYPE_SOURCE_COMPLETION_MODEL, NULL);
+ GtkSourceCompletionModel *model = g_object_new (GTK_TYPE_SOURCE_COMPLETION_MODEL, NULL);
+
+ model->priv->filter = func;
+ model->priv->filter_data = userdata;
+
+ return model;
}
-static GList *
+static void
append_list (GtkSourceCompletionModel *model,
- HeaderInfo *info,
- ProposalNode *node,
- gboolean *inserted)
+ ProposalNode *node)
{
- GList *item = NULL;
+ GList *item;
- if (info)
- item = g_hash_table_lookup (info->hash, node);
+ item = g_list_append (model->priv->last, node);
- if (item == NULL)
+ if (model->priv->store == NULL)
{
- item = g_list_append (model->priv->last, node);
-
- if (model->priv->store == NULL)
- {
- model->priv->store = item;
- }
- else
- {
- item = item->next;
- }
-
- if (info)
- g_hash_table_insert (info->hash, node, item);
- *inserted = TRUE;
+ model->priv->store = item;
}
else
{
- /*g_hash_table_replace (model->priv->hash_store, node, item);
- free_node (item->data);
- item->data = node;*/
- *inserted = FALSE;
+ item = item->next;
}
model->priv->last = item;
-
- return item;
}
static void
@@ -676,13 +805,16 @@ on_proposal_changed (GtkSourceCompletionProposal *proposal,
ProposalNode *node = (ProposalNode *)item->data;
GtkTreePath *path;
- iter.user_data = node;
- path = path_from_list (node->model, item);
+ if (!node->filtered)
+ {
+ iter.user_data = node;
+ path = path_from_list (node->model, item);
- gtk_tree_model_row_changed (GTK_TREE_MODEL (node->model),
- path,
- &iter);
- gtk_tree_path_free (path);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (node->model),
+ path,
+ &iter);
+ gtk_tree_path_free (path);
+ }
}
static gboolean
@@ -699,7 +831,6 @@ idle_append (gpointer data)
ProposalNode *node = (ProposalNode *)g_queue_pop_head (model->priv->item_queue);
ProposalNode *header = NULL;
GtkTreeIter iter;
- gboolean inserted;
if (node == NULL)
{
@@ -712,49 +843,52 @@ idle_append (gpointer data)
}
/* Check if it is a header */
- info = g_hash_table_lookup (model->priv->num_per_provider, node->provider);
-
- if (info == NULL)
+ if (g_hash_table_lookup (model->priv->num_per_provider, node->provider) == NULL)
{
- /*header = g_slice_new (ProposalNode);
+ header = g_slice_new (ProposalNode);
header->provider = g_object_ref (node->provider);
header->proposal = NULL;
+ header->filtered = GTK_SOURCE_COMPLETION_MODEL_FILTERED;
- append_list (model, NULL, header, &inserted);*/
+ append_list (model, header);
info = g_slice_new (HeaderInfo);
info->item = model->priv->last;
info->num = 0;
- info->hash = g_hash_table_new (hash_node,
- compare_nodes);
+ info->visible_items = 0;
g_hash_table_insert (model->priv->num_per_provider, node->provider, info);
}
- item = append_list (model, info, node, &inserted);
+ node_update_filter_state (model, node);
- if (inserted)
- {
- iter.user_data = item;
+ append_list (model, node);
+
+ item = model->priv->last;
+ iter.user_data = item;
- num_inc (model, node->provider, FALSE);
+ num_inc (model,
+ node->provider,
+ !node->filtered || (node->filtered & GTK_SOURCE_COMPLETION_MODEL_COUNT),
+ !node->filtered);
+ if (!node->filtered)
+ {
path = path_from_list (model, item);
gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
gtk_tree_path_free (path);
- }
-
- if (header != NULL)
- {
- g_warning ("header");
- update_show_headers (model, TRUE);
+
+ if (header != NULL)
+ {
+ update_show_headers (model, TRUE);
+ }
}
node->changed_id = g_signal_connect (node->proposal,
"changed",
G_CALLBACK (on_proposal_changed),
item);
-
+
i++;
}
@@ -798,11 +932,13 @@ gtk_source_completion_model_clear (GtkSourceCompletionModel *model)
GtkTreePath *path;
ProposalNode *node;
GList *list;
+ GtkSourceCompletionModelFilterFlag filtered;
g_return_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model));
/* Clear the queue of missing elements to append */
cancel_append (model);
+ cancel_refilter (model);
path = gtk_tree_path_new_first ();
list = model->priv->store;
@@ -810,8 +946,7 @@ gtk_source_completion_model_clear (GtkSourceCompletionModel *model)
while (model->priv->store)
{
node = (ProposalNode *)model->priv->store->data;
-
- num_dec (model, node->provider, node->proposal == NULL);
+ filtered = node->filtered;
free_node (node);
@@ -822,7 +957,15 @@ gtk_source_completion_model_clear (GtkSourceCompletionModel *model)
model->priv->last = NULL;
}
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ num_dec (model,
+ node->provider,
+ (!filtered || (filtered & GTK_SOURCE_COMPLETION_MODEL_COUNT)) && node->proposal != NULL,
+ !filtered);
+
+ if (!filtered)
+ {
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ }
}
g_list_free (list);
@@ -831,6 +974,110 @@ gtk_source_completion_model_clear (GtkSourceCompletionModel *model)
g_hash_table_remove_all (model->priv->num_per_provider);
}
+static gboolean
+idle_refilter (GtkSourceCompletionModel *model)
+{
+ guint i = 0;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ ProposalNode *node;
+ GtkSourceCompletionModelFilterFlag filtered;
+
+ if (model->priv->next_filter_path)
+ {
+ path = gtk_tree_row_reference_get_path (model->priv->next_filter_path);
+ gtk_tree_row_reference_free (model->priv->next_filter_path);
+ model->priv->next_filter_path = NULL;
+ }
+ else
+ {
+ path = gtk_tree_path_new_first ();
+ }
+
+ while (i < FILTER_PER_CALLBACK && model->priv->next_filter_item != NULL)
+ {
+ iter.user_data = model->priv->next_filter_item;
+
+ node = (ProposalNode *)model->priv->next_filter_item->data;
+ filtered = node_update_filter_state (model, node);
+
+ if ((filtered != 0) == (node->filtered != 0))
+ {
+ /* Keep the same, so increase path */
+ if (!filtered)
+ {
+ gtk_tree_path_next (path);
+ }
+ }
+ else if (filtered)
+ {
+ /* Was filtered, but not any more, so insert it */
+ num_inc (model,
+ node->provider,
+ !(filtered & GTK_SOURCE_COMPLETION_MODEL_COUNT),
+ TRUE);
+
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model),
+ path,
+ &iter);
+ gtk_tree_path_next (path);
+ }
+ else
+ {
+ /* Was not filtered, but is now, so remove it */
+ num_dec (model,
+ node->provider,
+ !(node->filtered & GTK_SOURCE_COMPLETION_MODEL_COUNT),
+ TRUE);
+
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model),
+ path);
+ }
+
+ model->priv->next_filter_item = g_list_next (model->priv->next_filter_item);
+ ++i;
+ }
+
+ refilter_headers (model);
+
+ if (model->priv->next_filter_item == NULL)
+ {
+ model->priv->idle_filter_id = 0;
+ gtk_tree_path_free (path);
+
+ g_signal_emit (model, signals[FILTER_DONE], 0);
+
+ return FALSE;
+ }
+
+ if (gtk_tree_path_prev (path))
+ {
+ model->priv->next_filter_path = gtk_tree_row_reference_new (GTK_TREE_MODEL (model),
+ path);
+ }
+
+ gtk_tree_path_free (path);
+
+ return TRUE;
+}
+
+void
+gtk_source_completion_model_refilter (GtkSourceCompletionModel *model)
+{
+ g_return_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model));
+
+ /* Cancel any running filter */
+ cancel_refilter (model);
+
+ model->priv->next_filter_item = model->priv->store;
+
+ if (idle_refilter (model))
+ {
+ model->priv->idle_filter_id = g_idle_add ((GSourceFunc)idle_refilter,
+ model);
+ }
+}
+
gboolean
gtk_source_completion_model_is_empty (GtkSourceCompletionModel *model,
gboolean invisible)
@@ -878,7 +1125,7 @@ gtk_source_completion_model_set_show_headers (GtkSourceCompletionModel *model,
if (model->priv->show_headers != show_headers)
{
model->priv->show_headers = show_headers;
- //update_show_headers (model, show_headers);
+ refilter_headers (model);
}
}
@@ -905,7 +1152,11 @@ gtk_source_completion_model_iter_previous (GtkSourceCompletionModel *model,
item = iter->user_data;
- item = g_list_previous (item);
+ do
+ {
+ item = g_list_previous (item);
+ } while (item && ((ProposalNode *)item->data)->filtered);
+
if (item != NULL)
{
@@ -930,7 +1181,11 @@ gtk_source_completion_model_iter_last (GtkSourceCompletionModel *model,
item = model->priv->last;
iter->user_data = item;
- if (item != NULL)
+ if (!((ProposalNode *)item->data)->filtered)
+ {
+ return TRUE;
+ }
+ else if (item != NULL)
{
return gtk_source_completion_model_iter_previous (model, iter);
}
diff --git a/gtksourceview/gtksourcecompletionmodel.h b/gtksourceview/gtksourcecompletionmodel.h
index 05c2039..bb112ae 100644
--- a/gtksourceview/gtksourcecompletionmodel.h
+++ b/gtksourceview/gtksourcecompletionmodel.h
@@ -54,6 +54,13 @@ struct _GtkSourceCompletionModelClass {
void (*filter_done) (GtkSourceCompletionModel *model);
};
+typedef enum
+{
+ GTK_SOURCE_COMPLETION_MODEL_NONE,
+ GTK_SOURCE_COMPLETION_MODEL_FILTERED = 1 << 0,
+ GTK_SOURCE_COMPLETION_MODEL_COUNT = 1 << 1
+} GtkSourceCompletionModelFilterFlag;
+
enum
{
GTK_SOURCE_COMPLETION_MODEL_COLUMN_LABEL,
@@ -64,10 +71,16 @@ enum
GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS
};
+typedef GtkSourceCompletionModelFilterFlag (* GtkSourceCompletionModelVisibleFunc) (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ gpointer userdata);
+
GType gtk_source_completion_model_get_type (void) G_GNUC_CONST;
GtkSourceCompletionModel *
- gtk_source_completion_model_new (void);
+ gtk_source_completion_model_new (GtkSourceCompletionModelVisibleFunc func,
+ gpointer userdata);
void gtk_source_completion_model_run_add_proposals (GtkSourceCompletionModel *model);
diff --git a/gtksourceview/gtksourcecompletionproposal.c b/gtksourceview/gtksourcecompletionproposal.c
index 2bfc8ee..fd1352e 100644
--- a/gtksourceview/gtksourcecompletionproposal.c
+++ b/gtksourceview/gtksourcecompletionproposal.c
@@ -74,59 +74,6 @@ gtk_source_completion_proposal_get_info_default (GtkSourceCompletionProposal *pr
return NULL;
}
-static guint
-gtk_source_completion_proposal_get_hash_default (GtkSourceCompletionProposal *proposal)
-{
- const gchar *label;
-
- label = gtk_source_completion_proposal_get_label (proposal);
-
- if (label == NULL)
- label = gtk_source_completion_proposal_get_markup (proposal);
-
- if (label != NULL)
- return g_str_hash (label);
- else
- g_return_val_if_reached (0);
-}
-
-static gboolean
-gtk_source_completion_proposal_equals_default (GtkSourceCompletionProposal *proposal1,
- GtkSourceCompletionProposal *proposal2)
-{
- const gchar *label1, *label2;
-
- label1 = gtk_source_completion_proposal_get_markup (proposal1);
- label2 = gtk_source_completion_proposal_get_markup (proposal2);
-
- if (label1 != NULL && label2 == NULL)
- {
- return FALSE;
- }
- else if (label2 != NULL && label1 == NULL)
- {
- return FALSE;
- }
- else if (label1 == NULL && label2 == NULL)
- {
- label1 = gtk_source_completion_proposal_get_label (proposal1);
- label2 = gtk_source_completion_proposal_get_label (proposal2);
- }
-
- if (label1 != NULL && label2 != NULL)
- {
- /* FIXME: g_utf8_collate ??? */
- if (g_strcmp0 (label1, label2) == 0)
- return TRUE;
- else
- return FALSE;
- }
- else
- {
- g_return_val_if_reached (FALSE);
- }
-}
-
static void
gtk_source_completion_proposal_init (GtkSourceCompletionProposalIface *iface)
{
@@ -139,9 +86,6 @@ gtk_source_completion_proposal_init (GtkSourceCompletionProposalIface *iface)
iface->get_icon = gtk_source_completion_proposal_get_icon_default;
iface->get_info = gtk_source_completion_proposal_get_info_default;
- iface->get_hash = gtk_source_completion_proposal_get_hash_default;
- iface->equals = gtk_source_completion_proposal_equals_default;
-
if (!initialized)
{
/**
@@ -282,22 +226,6 @@ gtk_source_completion_proposal_get_info (GtkSourceCompletionProposal *proposal)
return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_info (proposal);
}
-guint
-gtk_source_completion_proposal_get_hash (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROPOSAL (proposal), 0);
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_hash (proposal);
-}
-
-gboolean
-gtk_source_completion_proposal_equals (GtkSourceCompletionProposal *proposal1,
- GtkSourceCompletionProposal *proposal2)
-{
- g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROPOSAL (proposal1), FALSE);
- g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROPOSAL (proposal2), FALSE);
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal1)->equals (proposal1, proposal2);
-}
-
/**
* gtk_source_completion_proposal_changed:
* @proposal: A #GtkSourceCompletionProposal
diff --git a/gtksourceview/gtksourcecompletionproposal.h b/gtksourceview/gtksourcecompletionproposal.h
index 6ddcaa8..abb147a 100644
--- a/gtksourceview/gtksourcecompletionproposal.h
+++ b/gtksourceview/gtksourcecompletionproposal.h
@@ -49,10 +49,6 @@ struct _GtkSourceCompletionProposalIface
GdkPixbuf *(*get_icon) (GtkSourceCompletionProposal *proposal);
const gchar *(*get_info) (GtkSourceCompletionProposal *proposal);
- guint (*get_hash) (GtkSourceCompletionProposal *proposal);
- gboolean (*equals) (GtkSourceCompletionProposal *proposal1,
- GtkSourceCompletionProposal *proposal2);
-
/* Signals */
void (*changed) (GtkSourceCompletionProposal *proposal);
};
@@ -66,10 +62,6 @@ const gchar *gtk_source_completion_proposal_get_text (GtkSourceCompletionPropos
GdkPixbuf *gtk_source_completion_proposal_get_icon (GtkSourceCompletionProposal *proposal);
const gchar *gtk_source_completion_proposal_get_info (GtkSourceCompletionProposal *proposal);
-guint gtk_source_completion_proposal_get_hash (GtkSourceCompletionProposal *proposal);
-gboolean gtk_source_completion_proposal_equals (GtkSourceCompletionProposal *proposal1,
- GtkSourceCompletionProposal *proposal2);
-
void gtk_source_completion_proposal_changed (GtkSourceCompletionProposal *proposal);
G_END_DECLS
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index 41fbbde..4dbb012 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -1021,7 +1021,7 @@ gtk_source_view_show_completion_real (GtkSourceView *view)
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, NULL);
+ gtk_source_completion_show (completion, providers, word, NULL);
g_free (word);
g_list_foreach (providers, (GFunc)g_object_unref, NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]