gtksourceview r2276 - in branches/gtksourcecompletion: gtksourceview tests
- From: jessevdk svn gnome org
- To: svn-commits-list gnome org
- Subject: gtksourceview r2276 - in branches/gtksourcecompletion: gtksourceview tests
- Date: Mon, 13 Apr 2009 17:44:09 +0000 (UTC)
Author: jessevdk
Date: Mon Apr 13 17:44:09 2009
New Revision: 2276
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=2276&view=rev
Log:
Implemented custom tree model for storing the proposals, increases performance significantly.
Added:
branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.c
branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.h
Modified:
branches/gtksourcecompletion/gtksourceview/Makefile.am
branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c
branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h
branches/gtksourcecompletion/tests/completion-simple.c
branches/gtksourcecompletion/tests/gsc-provider-test.c
Modified: branches/gtksourcecompletion/gtksourceview/Makefile.am
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/Makefile.am (original)
+++ branches/gtksourcecompletion/gtksourceview/Makefile.am Mon Apr 13 17:44:09 2009
@@ -32,9 +32,11 @@
gtksourcecompletioninfo.h \
gtksourcecompletionitem.h \
gtksourcecompletionproposal.h \
- gtksourcecompletionprovider.h
+ gtksourcecompletionprovider.h \
+ gtksourcecompletionmodel.h
NOINST_H_FILES = \
+ gtksourcecompletionutils.h \
gtksourcecompletion-private.h
libgtksourceview_2_0_la_SOURCES = \
@@ -69,8 +71,8 @@
gtksourcecompletionitem.c \
gtksourcecompletionproposal.c \
gtksourcecompletionprovider.c \
+ gtksourcecompletionmodel.c \
gtksourcecompletionutils.c \
- gtksourcecompletionutils.h \
$(libgtksourceview_headers) \
$(NOINST_H_FILES)
Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c (original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c Mon Apr 13 17:44:09 2009
@@ -33,6 +33,7 @@
#include "gtksourceview-marshal.h"
#include <gtksourceview/gtksourcecompletion.h>
#include "gtksourceview-i18n.h"
+#include "gtksourcecompletionmodel.h"
#include <string.h>
#include <gtksourceview/gtksourceview.h>
#include "gtksourcecompletion-private.h"
@@ -45,15 +46,6 @@
GTK_TYPE_SOURCE_COMPLETION, \
GtkSourceCompletionPrivate))
-enum
-{
- COLUMN_PIXBUF,
- COLUMN_NAME,
- COLUMN_PROPOSAL,
- COLUMN_PROVIDER,
- N_COLUMNS
-};
-
/* Signals */
enum
{
@@ -93,8 +85,7 @@
GtkWidget *default_info;
GtkWidget *tree_view_proposals;
- GtkListStore *list_store_proposals;
- GtkTreeModelFilter *model_filter_proposals;
+ GtkSourceCompletionModel *model_proposals;
gboolean destroy_has_run;
gboolean manage_keys;
@@ -139,10 +130,10 @@
if (gtk_tree_selection_get_selected (selection, NULL, &piter))
{
- model = GTK_TREE_MODEL (completion->priv->model_filter_proposals);
+ model = GTK_TREE_MODEL (completion->priv->model_proposals);
gtk_tree_model_get (model, &piter,
- COLUMN_PROPOSAL,
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL,
proposal, -1);
if (iter != NULL)
@@ -198,7 +189,7 @@
return FALSE;
}
- model = GTK_TREE_MODEL (completion->priv->model_filter_proposals);
+ model = GTK_TREE_MODEL (completion->priv->model_proposals);
hasselection = gtk_tree_selection_get_selected (selection, NULL, &iter);
@@ -338,6 +329,20 @@
}
}
+static void
+do_refilter (GtkSourceCompletion *completion,
+ gboolean finish_if_empty)
+{
+ gtk_source_completion_model_refilter (completion->priv->model_proposals);
+
+ /* Check if there are any proposals left */
+ if (finish_if_empty &&
+ gtk_source_completion_model_is_empty (completion->priv->model_proposals))
+ {
+ gtk_source_completion_finish (completion);
+ }
+}
+
typedef GList * (*ListSelector)(GList *);
static gboolean
@@ -380,8 +385,8 @@
completion->priv->filter_provider = p1;
}
- update_selection_label (completion);
- gtk_tree_model_filter_refilter (completion->priv->model_filter_proposals);
+ update_selection_label (completion);
+ do_refilter (completion, FALSE);
return TRUE;
}
@@ -441,24 +446,13 @@
}
static gboolean
-proposals_filter_func (GtkTreeModel *model,
- GtkTreeIter *iter,
- GtkSourceCompletion *completion)
+proposals_filter_func (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ GtkSourceCompletion *completion)
{
- GtkSourceCompletionProvider *provider;
- GtkSourceCompletionProposal *proposal;
gboolean ret;
- gtk_tree_model_get (model, iter,
- COLUMN_PROVIDER, &provider,
- COLUMN_PROPOSAL, &proposal,
- -1);
-
- if (provider == NULL)
- {
- return TRUE;
- }
-
/* Filter on provider */
if (completion->priv->filter_provider != NULL &&
completion->priv->filter_provider != provider)
@@ -476,11 +470,7 @@
completion->priv->filter_criteria);
}
- g_object_unref (provider);
- g_object_unref (proposal);
-
return ret;
-
}
static void
@@ -535,8 +525,8 @@
if (get_selected_proposal (completion, &iter, &proposal))
{
- model = GTK_TREE_MODEL (completion->priv->model_filter_proposals);
- gtk_tree_model_get (model, &iter, COLUMN_PROVIDER, &provider, -1);
+ model = GTK_TREE_MODEL (completion->priv->model_proposals);
+ gtk_tree_model_get (model, &iter, GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER, &provider, -1);
update_proposal_info_real (completion, provider, proposal);
@@ -566,14 +556,10 @@
{
GtkTreeIter iter;
- gtk_list_store_append (completion->priv->list_store_proposals, &iter);
- gtk_list_store_set (completion->priv->list_store_proposals,
- &iter,
- COLUMN_PIXBUF, gtk_source_completion_proposal_get_icon (proposal),
- COLUMN_NAME, gtk_source_completion_proposal_get_label (proposal),
- COLUMN_PROPOSAL, proposal,
- COLUMN_PROVIDER, provider,
- -1);
+ gtk_source_completion_model_append (completion->priv->model_proposals,
+ provider,
+ proposal,
+ &iter);
}
static void
@@ -663,7 +649,7 @@
gtk_label_set_markup (GTK_LABEL (completion->priv->default_info), "");
- gtk_list_store_clear (completion->priv->list_store_proposals);
+ gtk_source_completion_model_clear (completion->priv->model_proposals);
g_list_free (completion->priv->active_providers);
completion->priv->active_providers = NULL;
@@ -814,6 +800,7 @@
!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (completion->priv->info_button)));
ret = TRUE;
}
+ break;
}
case GDK_Left:
{
@@ -845,8 +832,25 @@
completion->priv->filter_criteria =
gtk_source_completion_utils_get_word (GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (view)));
+
+ do_refilter (completion, TRUE);
+}
- gtk_tree_model_filter_refilter (completion->priv->model_filter_proposals);
+static void
+update_typing_offsets (GtkSourceCompletion *completion)
+{
+ GtkTextBuffer *buffer;
+ GtkTextMark *mark;
+ GtkTextIter iter;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (completion->priv->view));
+ mark = gtk_text_buffer_get_insert (buffer);
+
+ /* Check if the user has changed the cursor position.If yes, we don't complete */
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+
+ completion->priv->typing_line = gtk_text_iter_get_line (&iter);
+ completion->priv->typing_line_offset = gtk_text_iter_get_line_offset (&iter);
}
static gboolean
@@ -924,19 +928,21 @@
if (!GTK_WIDGET_VISIBLE (completion))
{
- completion->priv->typing_line = gtk_text_iter_get_line (location);
- completion->priv->typing_line_offset = gtk_text_iter_get_line_offset (location);
-
- if (completion->priv->show_timed_out_id != 0)
+ if (completion->priv->auto_providers != NULL)
{
- g_source_remove (completion->priv->show_timed_out_id);
- completion->priv->show_timed_out_id = 0;
- }
+ 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);
+ completion->priv->show_timed_out_id =
+ g_timeout_add (completion->priv->auto_complete_delay,
+ (GSourceFunc)show_auto_completion,
+ completion);
+ }
}
else
{
@@ -1265,26 +1271,15 @@
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
- GtkTreeModel *model;
GtkTreeSelection *selection;
GtkWidget *scrolled_window;
GtkWidget *tree_view;
- completion->priv->list_store_proposals = gtk_list_store_new (N_COLUMNS,
- GDK_TYPE_PIXBUF,
- G_TYPE_STRING,
- G_TYPE_OBJECT,
- G_TYPE_OBJECT);
-
- model = gtk_tree_model_filter_new (GTK_TREE_MODEL (completion->priv->list_store_proposals), NULL);
- completion->priv->model_filter_proposals = GTK_TREE_MODEL_FILTER (model);
-
- gtk_tree_model_filter_set_visible_func (completion->priv->model_filter_proposals,
- (GtkTreeModelFilterVisibleFunc)proposals_filter_func,
- completion,
- NULL);
+ completion->priv->model_proposals =
+ gtk_source_completion_model_new ((GtkSourceCompletionModelVisibleFunc)proposals_filter_func,
+ completion);
- tree_view = gtk_tree_view_new_with_model (model);
+ tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (completion->priv->model_proposals));
completion->priv->tree_view_proposals = tree_view;
gtk_widget_show (tree_view);
@@ -1297,12 +1292,12 @@
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", COLUMN_PIXBUF, NULL);
+ gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON, NULL);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, TRUE);
- gtk_tree_view_column_set_attributes (column, renderer, "text", COLUMN_NAME, NULL);
+ gtk_tree_view_column_set_attributes (column, renderer, "text", GTK_SOURCE_COMPLETION_MODEL_COLUMN_LABEL, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
g_signal_connect (tree_view,
@@ -1469,7 +1464,7 @@
g_list_free (proposals);
}
-void
+gboolean
gtk_source_completion_popup (GtkSourceCompletion *completion,
GList *providers,
const gchar *criteria)
@@ -1477,7 +1472,7 @@
GList *l;
gint x, y;
- g_return_if_fail (GTK_IS_SOURCE_COMPLETION (completion));
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), FALSE);
/* Make sure to clear any active completion */
gtk_source_completion_finish_real (completion);
@@ -1491,10 +1486,11 @@
if (providers == NULL)
{
gtk_source_completion_finish (completion);
- return;
+ return FALSE;
}
completion->priv->filter_criteria = g_strdup (criteria);
+ update_typing_offsets (completion);
/* Make sure all providers are ours */
for (l = providers; l; l = g_list_next (l))
@@ -1512,6 +1508,13 @@
completion->priv->active_providers =
g_list_reverse (completion->priv->active_providers);
+
+ /* Check if there are any completions */
+ if (gtk_source_completion_model_is_empty (completion->priv->model_proposals))
+ {
+ gtk_source_completion_finish (completion);
+ return FALSE;
+ }
update_selection_label (completion);
@@ -1529,6 +1532,8 @@
{
select_first_proposal (completion);
}
+
+ return TRUE;
}
/**
Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h (original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h Mon Apr 13 17:44:09 2009
@@ -69,7 +69,7 @@
gboolean gtk_source_completion_remove_provider (GtkSourceCompletion *completion,
GtkSourceCompletionProvider *provider);
-void gtk_source_completion_popup (GtkSourceCompletion *completion,
+gboolean gtk_source_completion_popup (GtkSourceCompletion *completion,
GList *providers,
const gchar *criteria);
Added: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.c
==============================================================================
--- (empty file)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.c Mon Apr 13 17:44:09 2009
@@ -0,0 +1,689 @@
+#include "gtksourcecompletionmodel.h"
+
+#define GTK_SOURCE_COMPLETION_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_COMPLETION_MODEL, GtkSourceCompletionModelPrivate))
+
+typedef struct
+{
+ GtkSourceCompletionProvider *provider;
+ GtkSourceCompletionProposal *proposal;
+
+ gboolean filtered;
+} ProposalNode;
+
+struct _GtkSourceCompletionModelPrivate
+{
+ GType column_types[GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS];
+ GList *store;
+ GList *last;
+
+ guint num;
+ GHashTable *num_per_provider;
+
+ GtkSourceCompletionModelVisibleFunc filter;
+ gpointer filter_data;
+};
+
+static void tree_model_iface_init (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionModel,
+ gtk_source_completion_model,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+ tree_model_iface_init))
+
+
+/* Interface implementation */
+static ProposalNode *
+node_from_iter (GtkTreeIter *iter)
+{
+ return (ProposalNode *)(((GList *)iter->user_data)->data);
+}
+
+static GtkTreePath *
+path_from_list (GtkSourceCompletionModel *model,
+ GList *item)
+{
+ gint index = 0;
+ GList *ptr = model->priv->store;
+ ProposalNode *node;
+
+ while (ptr && ptr != item)
+ {
+ node = (ProposalNode *)ptr->data;
+
+ if (!node->filtered)
+ {
+ ++index;
+ }
+
+ ptr = g_list_next (ptr);
+ }
+
+ if (ptr != item)
+ {
+ return NULL;
+ }
+ else
+ {
+ return gtk_tree_path_new_from_indices (index, -1);
+ }
+}
+
+static GtkTreeModelFlags
+tree_model_get_flags (GtkTreeModel *tree_model)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), 0);
+
+ return 0;
+}
+
+static gint
+tree_model_get_n_columns (GtkTreeModel *tree_model)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), 0);
+
+ return GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS;
+}
+
+static GType
+tree_model_get_column_type (GtkTreeModel *tree_model,
+ gint index)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), G_TYPE_INVALID);
+ g_return_val_if_fail (index >= 0 && index < GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS, G_TYPE_INVALID);
+
+ return GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->column_types[index];
+}
+
+static gboolean
+get_iter_from_index (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter,
+ gint index)
+{
+ GList *item;
+ ProposalNode *node;
+
+ if (index < 0 || index >= model->priv->num)
+ {
+ return FALSE;
+ }
+
+ item = model->priv->store;
+
+ while (item != NULL && index >= 0)
+ {
+ node = (ProposalNode *)item->data;
+
+ if (!node->filtered)
+ {
+ --index;
+ }
+
+ if (index != -1)
+ {
+ item = g_list_next (item);
+ }
+ }
+
+ if (item != NULL)
+ {
+ iter->user_data = item;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static gboolean
+tree_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ GtkSourceCompletionModel *model;
+ gint *indices;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ model = GTK_SOURCE_COMPLETION_MODEL (tree_model);
+ indices = gtk_tree_path_get_indices (path);
+
+ return get_iter_from_index (model, iter, indices[0]);
+}
+
+static GtkTreePath *
+tree_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ GtkSourceCompletionModel *model;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+ g_return_val_if_fail (iter->user_data != NULL, NULL);
+
+ model = GTK_SOURCE_COMPLETION_MODEL (tree_model);
+
+ return path_from_list (model, (GList *)iter->user_data);
+}
+
+static void
+tree_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gint column,
+ GValue *value)
+{
+ ProposalNode *node;
+
+ g_return_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (iter->user_data != NULL);
+ g_return_if_fail (column >= 0 && column < GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS);
+
+ node = node_from_iter (iter);
+
+ g_value_init (value, GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->column_types[column]);
+
+ switch (column)
+ {
+ case GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER:
+ g_value_set_object (value, node->provider);
+ break;
+ case GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL:
+ g_value_set_object (value, node->proposal);
+ break;
+ case GTK_SOURCE_COMPLETION_MODEL_COLUMN_LABEL:
+ g_value_set_string (value, gtk_source_completion_proposal_get_label (node->proposal));
+ break;
+ case GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON:
+ g_value_set_object (value, (gpointer)gtk_source_completion_proposal_get_icon (node->proposal));
+ break;
+ }
+}
+
+static gboolean
+find_first_not_filtered (GList *item,
+ GtkTreeIter *iter)
+{
+ ProposalNode *node;
+
+ while (item)
+ {
+ node = (ProposalNode *)item->data;
+
+ if (!node->filtered)
+ {
+ break;
+ }
+
+ item = g_list_next (item);
+ }
+
+ if (item != NULL)
+ {
+ iter->user_data = item;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+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);
+
+ item = g_list_next ((GList *)iter->user_data);
+
+ return find_first_not_filtered (item, iter);
+}
+
+static gboolean
+tree_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
+
+ if (parent != NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return find_first_not_filtered (GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->store, iter);
+ }
+}
+
+static gboolean
+tree_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ return FALSE;
+}
+
+static gint
+tree_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), 0);
+ g_return_val_if_fail (iter == NULL || iter->user_data != NULL, 0);
+
+ if (iter == NULL)
+ {
+ return GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->num;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static gboolean
+tree_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ gint n)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
+
+ if (parent != NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return get_iter_from_index (GTK_SOURCE_COMPLETION_MODEL (tree_model),
+ iter,
+ n);
+ }
+}
+
+static gboolean
+tree_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (child != NULL, FALSE);
+
+ iter->user_data = NULL;
+ return FALSE;
+}
+
+static void
+tree_model_row_inserted (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter)
+{
+}
+
+static void
+tree_model_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GtkTreeModelIface *iface = (GtkTreeModelIface *)g_iface;
+
+ iface->get_flags = tree_model_get_flags;
+ iface->get_n_columns = tree_model_get_n_columns;
+ iface->get_column_type = tree_model_get_column_type;
+ iface->get_iter = tree_model_get_iter;
+ iface->get_path = tree_model_get_path;
+ iface->get_value = tree_model_get_value;
+ iface->iter_next = tree_model_iter_next;
+ iface->iter_children = tree_model_iter_children;
+ iface->iter_has_child = tree_model_iter_has_child;
+ iface->iter_n_children = tree_model_iter_n_children;
+ iface->iter_nth_child = tree_model_iter_nth_child;
+ iface->iter_parent = tree_model_iter_parent;
+ iface->row_inserted = tree_model_row_inserted;
+}
+
+static void
+gtk_source_completion_model_finalize (GObject *object)
+{
+ GtkSourceCompletionModel *model = GTK_SOURCE_COMPLETION_MODEL (object);
+
+ g_hash_table_destroy (model->priv->num_per_provider);
+
+ G_OBJECT_CLASS (gtk_source_completion_model_parent_class)->finalize (object);
+}
+
+static void
+gtk_source_completion_model_class_init (GtkSourceCompletionModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_source_completion_model_finalize;
+
+ g_type_class_add_private (object_class, sizeof(GtkSourceCompletionModelPrivate));
+}
+
+static void
+free_num (gpointer data)
+{
+ g_slice_free (guint, data);
+}
+
+static void
+gtk_source_completion_model_init (GtkSourceCompletionModel *self)
+{
+ self->priv = GTK_SOURCE_COMPLETION_MODEL_GET_PRIVATE (self);
+
+ self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER] = G_TYPE_OBJECT;
+ self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL] = G_TYPE_OBJECT;
+ self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_LABEL] = G_TYPE_STRING;
+ self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON] = GDK_TYPE_PIXBUF;
+
+ self->priv->num_per_provider = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ free_num);
+}
+
+static void
+num_inc (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider)
+{
+ guint *num;
+ ++model->priv->num;
+
+ num = g_hash_table_lookup (model->priv->num_per_provider, provider);
+
+ if (num != NULL)
+ {
+ ++(*num);
+ }
+ else
+ {
+ num = g_slice_new (guint);
+ *num = 1;
+
+ g_hash_table_insert (model->priv->num_per_provider, provider, num);
+ }
+
+}
+
+static void
+num_dec (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider)
+{
+ guint *num;
+
+ --model->priv->num;
+
+ num = g_hash_table_lookup (model->priv->num_per_provider, provider);
+
+ if (num != NULL && *num > 0)
+ {
+ --(*num);
+ }
+}
+
+static gboolean
+node_update_filter_state (GtkSourceCompletionModel *model,
+ ProposalNode *node)
+{
+ gboolean ret;
+
+ ret = node->filtered;
+
+ node->filtered = !model->priv->filter (model,
+ node->provider,
+ node->proposal,
+ model->priv->filter_data);
+
+ return ret;
+}
+
+static void
+free_node (ProposalNode *node)
+{
+ g_object_unref (node->provider);
+ g_object_unref (node->proposal);
+
+ g_slice_free (ProposalNode, node);
+}
+
+static void
+remove_node (GtkSourceCompletionModel *model,
+ GList *item)
+{
+ ProposalNode *node;
+ GtkTreePath *path;
+ gboolean filtered;
+ GtkSourceCompletionProvider *provider;
+
+ path = path_from_list (model, item);
+
+ node = (ProposalNode *)item->data;
+ provider = g_object_ref (node->provider);
+
+ filtered = node->filtered;
+ free_node (node);
+
+ if (item == model->priv->last)
+ {
+ model->priv->last = item->prev;
+ }
+
+ model->priv->store = g_list_remove_link (model->priv->store, item);
+
+ if (!filtered)
+ {
+ num_dec (model, provider);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ }
+
+ gtk_tree_path_free (path);
+ g_object_unref (provider);
+}
+
+/* Public */
+GtkSourceCompletionModel*
+gtk_source_completion_model_new (GtkSourceCompletionModelVisibleFunc func,
+ gpointer userdata)
+{
+ GtkSourceCompletionModel *model = g_object_new (GTK_TYPE_SOURCE_COMPLETION_MODEL, NULL);
+
+ model->priv->filter = func;
+ model->priv->filter_data = userdata;
+
+ return model;
+}
+
+gboolean
+gtk_source_completion_model_append (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ GtkTreeIter *iter)
+{
+ ProposalNode *node;
+ GList *item;
+ GtkTreePath *path;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model), FALSE);
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), FALSE);
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROPOSAL (proposal), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ node = g_slice_new (ProposalNode);
+ node->provider = g_object_ref (provider);
+ node->proposal = g_object_ref (proposal);
+
+ node_update_filter_state (model, node);
+
+ item = model->priv->last;
+ item = g_list_append (item, node);
+
+ if (model->priv->store == NULL)
+ {
+ model->priv->store = item;
+ }
+ else
+ {
+ item = item->next;
+ }
+
+ model->priv->last = item;
+ iter->user_data = item;
+
+ if (!node->filtered)
+ {
+ path = path_from_list (model, item);
+
+ num_inc (model, node->provider);
+
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, iter);
+ gtk_tree_path_free (path);
+ }
+
+ return TRUE;
+}
+
+gboolean
+gtk_source_completion_model_remove (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter->user_data != NULL, FALSE);
+
+ remove_node (model, (GList *)iter->user_data);
+ return TRUE;
+}
+
+void
+gtk_source_completion_model_clear (GtkSourceCompletionModel *model)
+{
+ GtkTreePath *path;
+ ProposalNode *node;
+ GList *list;
+ gboolean filtered;
+
+ g_return_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model));
+
+ path = gtk_tree_path_new_first ();
+ list = model->priv->store;
+
+ while (model->priv->store)
+ {
+ node = (ProposalNode *)model->priv->store->data;
+ filtered = node->filtered;
+
+ free_node (node);
+
+ model->priv->store = model->priv->store->next;
+
+ if (model->priv->store == NULL)
+ {
+ model->priv->last = NULL;
+ }
+
+ if (!filtered)
+ {
+ num_dec (model, node->provider);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ }
+ }
+
+ g_list_free (list);
+ gtk_tree_path_free (path);
+
+ g_hash_table_remove_all (model->priv->num_per_provider);
+}
+
+void
+gtk_source_completion_model_refilter (GtkSourceCompletionModel *model)
+{
+ GList *item;
+ gboolean filtered;
+ ProposalNode *node;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ g_return_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model));
+
+ path = gtk_tree_path_new_first ();
+
+ for (item = model->priv->store; item != NULL; item = g_list_next (item))
+ {
+ iter.user_data = item;
+
+ node = (ProposalNode *)item->data;
+ filtered = node_update_filter_state (model, node);
+
+ if (filtered == node->filtered)
+ {
+ /* 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);
+ 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);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model),
+ path);
+ }
+ }
+
+ gtk_tree_path_free (path);
+}
+
+gboolean
+gtk_source_completion_model_is_empty (GtkSourceCompletionModel *model)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model), FALSE);
+
+ return model->priv->num == 0;
+}
+
+guint
+gtk_source_completion_model_n_proposals (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider)
+{
+ guint *num;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model), 0);
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), 0);
+
+ num = g_hash_table_lookup (model->priv->num_per_provider, provider);
+
+ if (num == NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ return *num;
+ }
+}
+
Added: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.h
==============================================================================
--- (empty file)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.h Mon Apr 13 17:44:09 2009
@@ -0,0 +1,93 @@
+/*
+ * gtksourcecompletionmodel.h
+ * This file is part of gtksourcecompletion
+ *
+ * Copyright (C) 2009 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_COMPLETION_MODEL_H__
+#define __GTK_SOURCE_COMPLETION_MODEL_H__
+
+#include <gtk/gtk.h>
+#include <gtksourceview/gtksourcecompletionprovider.h>
+#include <gtksourceview/gtksourcecompletionproposal.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_COMPLETION_MODEL (gtk_source_completion_model_get_type ())
+#define GTK_SOURCE_COMPLETION_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_COMPLETION_MODEL, GtkSourceCompletionModel))
+#define GTK_SOURCE_COMPLETION_MODEL_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_COMPLETION_MODEL, GtkSourceCompletionModel const))
+#define GTK_SOURCE_COMPLETION_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_COMPLETION_MODEL, GtkSourceCompletionModelClass))
+#define GTK_IS_SOURCE_COMPLETION_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_COMPLETION_MODEL))
+#define GTK_IS_SOURCE_COMPLETION_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_COMPLETION_MODEL))
+#define GTK_SOURCE_COMPLETION_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_COMPLETION_MODEL, GtkSourceCompletionModelClass))
+
+typedef struct _GtkSourceCompletionModel GtkSourceCompletionModel;
+typedef struct _GtkSourceCompletionModelClass GtkSourceCompletionModelClass;
+typedef struct _GtkSourceCompletionModelPrivate GtkSourceCompletionModelPrivate;
+
+struct _GtkSourceCompletionModel {
+ GObject parent;
+
+ GtkSourceCompletionModelPrivate *priv;
+};
+
+struct _GtkSourceCompletionModelClass {
+ GObjectClass parent_class;
+};
+
+enum
+{
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_LABEL,
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON,
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL,
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER,
+ GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS
+};
+
+typedef gboolean (* 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 (GtkSourceCompletionModelVisibleFunc func,
+ gpointer userdata);
+
+gboolean gtk_source_completion_model_append (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ GtkTreeIter *iter);
+
+gboolean gtk_source_completion_model_remove (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter);
+
+gboolean gtk_source_completion_model_is_empty (GtkSourceCompletionModel *model);
+guint gtk_source_completion_model_n_proposals (GtkSourceCompletionModel *model,
+ GtkSourceCompletionProvider *provider);
+
+void gtk_source_completion_model_clear (GtkSourceCompletionModel *model);
+
+void gtk_source_completion_model_refilter (GtkSourceCompletionModel *model);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_COMPLETION_MODEL_H__ */
+
Modified: branches/gtksourcecompletion/tests/completion-simple.c
==============================================================================
--- branches/gtksourcecompletion/tests/completion-simple.c (original)
+++ branches/gtksourcecompletion/tests/completion-simple.c Mon Apr 13 17:44:09 2009
@@ -160,18 +160,15 @@
create_completion(void)
{
GscProviderTest *prov_test1;
- GscProviderTest *prov_test2;
- //GscProviderDevhelp *prov_devhelp;
+ GscProviderDevhelp *prov_devhelp;
comp = gtk_source_view_get_completion (GTK_SOURCE_VIEW (view));
prov_test1 = gsc_provider_test_new ("Test 1");
- prov_test2 = gsc_provider_test_new ("Test 2");
- //prov_devhelp = gsc_provider_devhelp_new ();
+ prov_devhelp = gsc_provider_devhelp_new ();
gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_test1));
- gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_test2));
- //gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_devhelp));
+ gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_devhelp));
}
int
@@ -190,5 +187,3 @@
gtk_main ();
return 0;
}
-
-
Modified: branches/gtksourcecompletion/tests/gsc-provider-test.c
==============================================================================
--- branches/gtksourcecompletion/tests/gsc-provider-test.c (original)
+++ branches/gtksourcecompletion/tests/gsc-provider-test.c Mon Apr 13 17:44:09 2009
@@ -55,17 +55,31 @@
{
GList *list = NULL;
- list = append_item (list, "Proposal 1.1", NULL, "Info proposal 1.1");
- list = append_item (list, "Proposal 1.2", NULL, "Info proposal 1.2");
- list = append_item (list, "Proposal 1.3", NULL, "Info proposal 1.3");
-
- list = append_item (list, "Proposal 2.1", NULL, "Info proposal 2.1");
- list = append_item (list, "Proposal 2.2", NULL, "Info proposal 2.2");
- list = append_item (list, "Proposal 2.3", NULL, "Info proposal 2.3");
-
+ list = append_item (list, "aa", NULL, "Info proposal 1.1");
+ list = append_item (list, "ab", NULL, "Info proposal 1.2");
+ list = append_item (list, "bc", NULL, "Info proposal 1.3");
+ list = append_item (list, "bd", NULL, "Info proposal 1.3");
+
return list;
}
+static gboolean
+gsc_provider_test_filter_proposal (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ const gchar *criteria)
+{
+ const gchar *label;
+
+ label = gtk_source_completion_proposal_get_label (proposal);
+ return g_str_has_prefix (label, criteria);
+}
+
+static gboolean
+gsc_provider_test_can_auto_complete (GtkSourceCompletionProvider *provider)
+{
+ return TRUE;
+}
+
static void
gsc_provider_test_finalize (GObject *object)
{
@@ -92,6 +106,8 @@
{
iface->get_name = gsc_provider_test_get_name;
iface->get_proposals = gsc_provider_test_get_proposals;
+ iface->filter_proposal = gsc_provider_test_filter_proposal;
+ iface->can_auto_complete = gsc_provider_test_can_auto_complete;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]