gtksourceview r2280 - in branches/gtksourcecompletion: gtksourceview tests
- From: jessevdk svn gnome org
- To: svn-commits-list gnome org
- Subject: gtksourceview r2280 - in branches/gtksourcecompletion: gtksourceview tests
- Date: Mon, 13 Apr 2009 23:12:13 +0000 (UTC)
Author: jessevdk
Date: Mon Apr 13 23:12:12 2009
New Revision: 2280
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=2280&view=rev
Log:
Implemented showing headers of providers in the completion model
Implemented provider icons
Modified:
branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c
branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.c
branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.h
branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c
branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h
branches/gtksourcecompletion/tests/completion-simple.c
branches/gtksourcecompletion/tests/gsc-provider-test.c
branches/gtksourcecompletion/tests/gsc-provider-test.h
Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c (original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c Mon Apr 13 23:12:12 2009
@@ -60,6 +60,7 @@
PROP_MANAGE_KEYS,
PROP_REMEMBER_INFO_VISIBILITY,
PROP_SELECT_ON_SHOW,
+ PROP_SHOW_HEADERS,
PROP_MINIMUM_AUTO_COMPLETE_LENGTH,
PROP_AUTO_COMPLETE_DELAY
@@ -83,6 +84,7 @@
GtkWidget *selection_label;
GtkWidget *bottom_bar;
GtkWidget *default_info;
+ GtkWidget *selection_image;
GtkWidget *tree_view_proposals;
GtkSourceCompletionModel *model_proposals;
@@ -92,6 +94,7 @@
gboolean remember_info_visibility;
gboolean info_visible;
gboolean select_on_show;
+ gboolean show_headers;
/* Completion management */
GtkSourceView *view;
@@ -164,7 +167,11 @@
return activated;
}
-typedef gboolean (*ProposalSelector)(GtkTreeModel *model, GtkTreeIter *iter, gboolean hasselection, gpointer userdata);
+typedef gboolean (*ProposalSelector)(GtkSourceCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean hasselection,
+ gpointer userdata);
static gboolean
select_proposal (GtkSourceCompletion *completion,
@@ -193,7 +200,7 @@
hasselection = gtk_tree_selection_get_selected (selection, NULL, &iter);
- if (selector (model, &iter, hasselection, userdata))
+ if (selector (completion, model, &iter, hasselection, userdata))
{
gtk_tree_selection_select_iter (selection, &iter);
@@ -212,77 +219,162 @@
return TRUE;
}
+static void
+scroll_to_iter (GtkSourceCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (model, iter);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (completion->priv->tree_view_proposals),
+ path,
+ NULL,
+ FALSE,
+ 0,
+ 0);
+ gtk_tree_path_free (path);
+}
+
static gboolean
-selector_first (GtkTreeModel *model,
- GtkTreeIter *iter,
- gboolean hasselection,
- gpointer userdata)
+selector_first (GtkSourceCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean hasselection,
+ gpointer userdata)
{
- return gtk_tree_model_get_iter_first (model, iter);
+ gboolean ret;
+ gboolean hasfirst;
+ GtkTreeIter first;
+
+ ret = gtk_tree_model_get_iter_first (model, iter);
+ hasfirst = ret;
+ first = *iter;
+
+ while (ret && gtk_source_completion_model_iter_is_header (
+ GTK_SOURCE_COMPLETION_MODEL (model), iter))
+ {
+ ret = gtk_tree_model_iter_next (model, iter);
+ }
+
+ if (hasfirst && !ret)
+ {
+ scroll_to_iter (completion, model, &first);
+ }
+
+ return ret;
}
static gboolean
-selector_last (GtkTreeModel *model,
- GtkTreeIter *iter,
- gboolean hasselection,
- gpointer userdata)
+selector_last (GtkSourceCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean hasselection,
+ gpointer userdata)
{
- gint num = gtk_tree_model_iter_n_children (model, NULL);
- return gtk_tree_model_iter_nth_child (model, iter, NULL, num - 1);
+ gboolean ret;
+ gboolean haslast;
+ GtkTreeIter last;
+
+ ret = gtk_source_completion_model_iter_last (GTK_SOURCE_COMPLETION_MODEL (model),
+ iter);
+
+ haslast = ret;
+ last = *iter;
+
+ while (ret && gtk_source_completion_model_iter_is_header (
+ GTK_SOURCE_COMPLETION_MODEL (model), iter))
+ {
+ ret = gtk_source_completion_model_iter_previous (GTK_SOURCE_COMPLETION_MODEL (model),
+ iter);
+ }
+
+ if (haslast && !ret)
+ {
+ scroll_to_iter (completion, model, &last);
+ }
+
+ return ret;
}
static gboolean
-selector_previous (GtkTreeModel *model,
- GtkTreeIter *iter,
- gboolean hasselection,
- gpointer userdata)
+selector_previous (GtkSourceCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean hasselection,
+ gpointer userdata)
{
gint num = GPOINTER_TO_INT (userdata);
- GtkTreePath *path;
gboolean ret = FALSE;
-
+ GtkTreeIter next;
+ GtkTreeIter last;
+
if (!hasselection)
{
- return selector_last (model, iter, hasselection, userdata);
+ return selector_last (completion, model, iter, hasselection, userdata);
}
- path = gtk_tree_model_get_path (model, iter);
-
- while (num > 0 && gtk_tree_path_prev (path))
+ next = *iter;
+ last = *iter;
+
+ while (num > 0 && gtk_source_completion_model_iter_previous (
+ GTK_SOURCE_COMPLETION_MODEL (model), &next))
{
- ret = TRUE;
- --num;
+ if (!gtk_source_completion_model_iter_is_header (GTK_SOURCE_COMPLETION_MODEL (model),
+ &next))
+ {
+ ret = TRUE;
+ *iter = next;
+ --num;
+ }
+
+ last = next;
}
- ret = ret && gtk_tree_model_get_iter (model, iter, path);
- gtk_tree_path_free (path);
+ if (!ret)
+ {
+ scroll_to_iter (completion, model, &last);
+ }
return ret;
}
static gboolean
-selector_next (GtkTreeModel *model,
- GtkTreeIter *iter,
- gboolean hasselection,
- gpointer userdata)
+selector_next (GtkSourceCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean hasselection,
+ gpointer userdata)
{
gint num = GPOINTER_TO_INT (userdata);
gboolean ret = FALSE;
GtkTreeIter next;
-
+ GtkTreeIter last;
+
if (!hasselection)
{
- return selector_first (model, iter, hasselection, userdata);
+ return selector_first (completion, model, iter, hasselection, userdata);
}
next = *iter;
+ last = *iter;
while (num > 0 && gtk_tree_model_iter_next (model, &next))
{
- ret = TRUE;
+ if (!gtk_source_completion_model_iter_is_header (GTK_SOURCE_COMPLETION_MODEL (model),
+ &next))
+ {
+ ret = TRUE;
+ *iter = next;
+ --num;
+ }
- *iter = next;
- --num;
+ last = next;
+ }
+
+ if (!ret)
+ {
+ scroll_to_iter (completion, model, &last);
}
return ret;
@@ -347,12 +439,17 @@
if (completion->priv->filter_provider == NULL)
{
name = g_strdup_printf("[<i>%s</i>]", _("All"));
+
+ gtk_image_clear (GTK_IMAGE (completion->priv->selection_image));
}
else
{
name = g_markup_escape_text (
gtk_source_completion_provider_get_name (completion->priv->filter_provider),
-1);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (completion->priv->selection_image),
+ (GdkPixbuf *)gtk_source_completion_provider_get_icon (completion->priv->filter_provider));
}
if (num > 1)
@@ -1176,6 +1273,9 @@
case PROP_SELECT_ON_SHOW:
g_value_set_boolean (value, completion->priv->select_on_show);
break;
+ case PROP_SHOW_HEADERS:
+ g_value_set_boolean (value, completion->priv->show_headers);
+ break;
case PROP_AUTO_COMPLETE_DELAY:
g_value_set_uint (value, completion->priv->auto_complete_delay);
break;
@@ -1216,6 +1316,15 @@
case PROP_SELECT_ON_SHOW:
completion->priv->select_on_show = g_value_get_boolean (value);
break;
+ case PROP_SHOW_HEADERS:
+ completion->priv->show_headers = g_value_get_boolean (value);
+
+ if (completion->priv->model_proposals != NULL)
+ {
+ gtk_source_completion_model_set_show_headers (completion->priv->model_proposals,
+ completion->priv->show_headers);
+ }
+ break;
case PROP_AUTO_COMPLETE_DELAY:
completion->priv->auto_complete_delay = g_value_get_uint (value);
break;
@@ -1305,6 +1414,20 @@
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
+ * GtkSourceCompletion:show-headers:
+ *
+ * %TRUE if providers should be shown as separator headers in the
+ * popup when there are proposals from multiple providers
+ */
+ g_object_class_install_property (object_class,
+ PROP_SHOW_HEADERS,
+ g_param_spec_boolean ("show-headers",
+ _("Show Headers"),
+ _("Show provider headers when proposals from multiple providers are available"),
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
* GtkSourceCompletion:auto-complete-delay:
*
* The auto completion delay when typing
@@ -1362,6 +1485,127 @@
}
+static void
+render_proposal_icon_func (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkSourceCompletion *completion)
+{
+ gboolean isheader;
+ GdkPixbuf *icon;
+ GtkStyle *style;
+
+ isheader = gtk_source_completion_model_iter_is_header (completion->priv->model_proposals,
+ iter);
+
+ style = gtk_widget_get_style (GTK_WIDGET (completion->priv->tree_view_proposals));
+
+ if (isheader)
+ {
+ g_object_set (cell,
+ "cell-background-gdk", &(style->bg[GTK_STATE_INSENSITIVE]),
+ NULL);
+ }
+ else
+ {
+ g_object_set (cell,
+ "cell-background-set", FALSE,
+ NULL);
+ }
+
+ gtk_tree_model_get (model,
+ iter,
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON,
+ &icon,
+ -1);
+
+ g_object_set (cell, "pixbuf", icon, NULL);
+
+ if (icon)
+ {
+ g_object_unref (icon);
+ }
+}
+
+static void
+render_proposal_text_func (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkSourceCompletion *completion)
+{
+ gchar *name;
+ GtkSourceCompletionProvider *provider;
+ gboolean isheader;
+ GtkStyle *style;
+
+ isheader = gtk_source_completion_model_iter_is_header (completion->priv->model_proposals,
+ iter);
+
+ if (isheader)
+ {
+ gtk_tree_model_get (model,
+ iter,
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER,
+ &provider,
+ -1);
+
+ name = g_strdup_printf ("<b>%s</b>",
+ g_markup_escape_text (gtk_source_completion_provider_get_name (provider),
+ -1));
+
+ style = gtk_widget_get_style (GTK_WIDGET (completion->priv->tree_view_proposals));
+
+ g_object_set (cell,
+ "markup", name,
+ "background-gdk", &(style->bg[GTK_STATE_INSENSITIVE]),
+ "foreground-gdk", &(style->fg[GTK_STATE_INSENSITIVE]),
+ NULL);
+ g_free (name);
+
+ g_object_unref (provider);
+ }
+ else
+ {
+ gtk_tree_model_get (model,
+ iter,
+ GTK_SOURCE_COMPLETION_MODEL_COLUMN_LABEL,
+ &name,
+ -1);
+
+ g_object_set (cell,
+ "text", name,
+ "background-set", FALSE,
+ "foreground-set", FALSE,
+ NULL);
+
+ g_free (name);
+ }
+}
+
+static gboolean
+selection_func (GtkTreeSelection *selection,
+ GtkTreeModel *model,
+ GtkTreePath *path,
+ gboolean path_currently_selected,
+ GtkSourceCompletion *completion)
+{
+ GtkTreeIter iter;
+
+ gtk_tree_model_get_iter (model, &iter, path);
+
+ if (gtk_source_completion_model_iter_is_header (completion->priv->model_proposals,
+ &iter))
+ {
+ return path_currently_selected;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
static GtkWidget *
initialize_proposals_ui (GtkSourceCompletion *completion)
{
@@ -1375,9 +1619,13 @@
gtk_source_completion_model_new ((GtkSourceCompletionModelVisibleFunc)proposals_filter_func,
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));
completion->priv->tree_view_proposals = tree_view;
+ gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (tree_view), FALSE);
+
gtk_widget_show (tree_view);
g_object_set (tree_view, "can-focus", FALSE, NULL);
@@ -1388,12 +1636,22 @@
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON, NULL);
+
+ gtk_tree_view_column_set_cell_data_func (column,
+ renderer,
+ (GtkTreeCellDataFunc)render_proposal_icon_func,
+ completion,
+ NULL);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, TRUE);
+
+ gtk_tree_view_column_set_cell_data_func (column,
+ renderer,
+ (GtkTreeCellDataFunc)render_proposal_text_func,
+ completion,
+ 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,
@@ -1402,6 +1660,10 @@
completion);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ gtk_tree_selection_set_select_function (selection,
+ (GtkTreeSelectionFunc)selection_func,
+ completion,
+ NULL);
g_signal_connect (selection,
"changed",
G_CALLBACK (selection_changed_cb),
@@ -1469,7 +1731,14 @@
FALSE,
TRUE,
10);
-
+
+ completion->priv->selection_image = gtk_image_new ();
+ gtk_widget_show (completion->priv->selection_image);
+ gtk_box_pack_end (GTK_BOX (completion->priv->bottom_bar),
+ completion->priv->selection_image,
+ FALSE,
+ TRUE,
+ 0);
container = initialize_proposals_ui (completion);
Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.c (original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.c Mon Apr 13 23:12:12 2009
@@ -10,6 +10,13 @@
GtkSourceCompletionModelFilterFlag filtered;
} ProposalNode;
+typedef struct
+{
+ GList *item;
+ guint num;
+ guint visible_items;
+} HeaderInfo;
+
struct _GtkSourceCompletionModelPrivate
{
GType column_types[GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS];
@@ -21,6 +28,8 @@
GtkSourceCompletionModelVisibleFunc filter;
gpointer filter_data;
+
+ gboolean show_headers;
};
static void tree_model_iface_init (gpointer g_iface, gpointer iface_data);
@@ -198,7 +207,18 @@
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));
+ if (node->proposal == NULL)
+ {
+ g_value_set_object (value,
+ (gpointer)gtk_source_completion_provider_get_icon (
+ node->provider));
+ }
+ else
+ {
+ g_value_set_object (value,
+ (gpointer)gtk_source_completion_proposal_get_icon (
+ node->proposal));
+ }
break;
}
}
@@ -386,7 +406,7 @@
static void
free_num (gpointer data)
{
- g_slice_free (guint, data);
+ g_slice_free (HeaderInfo, data);
}
static void
@@ -411,32 +431,24 @@
gboolean inc_local,
gboolean inc_global)
{
- guint *num;
+ HeaderInfo *info;
+
+ info = g_hash_table_lookup (model->priv->num_per_provider, provider);
if (inc_global)
{
++model->priv->num;
+
+ if (info != NULL)
+ {
+ ++info->visible_items;
+ }
}
- if (!inc_local)
- {
- return;
- }
-
- num = g_hash_table_lookup (model->priv->num_per_provider, provider);
-
- if (num != NULL)
+ if (inc_local && info != NULL)
{
- ++(*num);
+ ++(info->num);
}
- else
- {
- num = g_slice_new (guint);
- *num = 1;
-
- g_hash_table_insert (model->priv->num_per_provider, provider, num);
- }
-
}
static void
@@ -445,23 +457,23 @@
gboolean dec_local,
gboolean dec_global)
{
- guint *num;
+ HeaderInfo *info;
+
+ info = g_hash_table_lookup (model->priv->num_per_provider, provider);
if (dec_global)
{
--model->priv->num;
+
+ if (info != NULL)
+ {
+ --info->visible_items;
+ }
}
- if (!dec_local)
+ if (dec_local && info != NULL && info->num > 0)
{
- return;
- }
-
- num = g_hash_table_lookup (model->priv->num_per_provider, provider);
-
- if (num != NULL && *num > 0)
- {
- --(*num);
+ --(info->num);
}
}
@@ -471,6 +483,11 @@
{
GtkSourceCompletionModelFilterFlag ret;
+ if (node->proposal == NULL)
+ {
+ return node->filtered;
+ }
+
ret = node->filtered;
node->filtered = model->priv->filter (model,
@@ -485,47 +502,128 @@
free_node (ProposalNode *node)
{
g_object_unref (node->provider);
- g_object_unref (node->proposal);
+
+ if (node->proposal != NULL)
+ {
+ g_object_unref (node->proposal);
+ }
g_slice_free (ProposalNode, node);
}
static void
-remove_node (GtkSourceCompletionModel *model,
- GList *item)
+update_show_headers (GtkSourceCompletionModel *model,
+ gboolean show)
{
+ GtkSourceCompletionProvider *provider;
+ HeaderInfo *info;
+ guint num = 0;
+ GList *items = NULL;
+ GList *item;
+ GHashTableIter hiter;
+
ProposalNode *node;
GtkTreePath *path;
- GtkSourceCompletionModelFilterFlag filtered;
- GtkSourceCompletionProvider *provider;
+ GtkTreeIter iter;
- path = path_from_list (model, item);
-
- node = (ProposalNode *)item->data;
- provider = g_object_ref (node->provider);
+ if (!model->priv->show_headers)
+ {
+ return;
+ }
+
+ /* Check headers */
+ g_hash_table_iter_init (&hiter, model->priv->num_per_provider);
+
+ while (g_hash_table_iter_next (&hiter, (gpointer *)&provider, (gpointer *)&info))
+ {
+ if (info->visible_items > 0)
+ {
+ node = (ProposalNode *)info->item->data;
+ ++num;
+
+ if (show && node->filtered)
+ {
+ items = g_list_append (items, info);
+ }
+
+ if (!show && !node->filtered)
+ {
+ items = g_list_append (items, info);
+ }
+ }
+
+ if (show && num > 1)
+ break;
+ }
- filtered = node->filtered;
- free_node (node);
+ if (show && num > 1 && items != NULL)
+ {
+ for (item = items; item; item = g_list_next (item))
+ {
+ 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, FALSE, TRUE);
- if (item == model->priv->last)
+ path = path_from_list (model, info->item);
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model),
+ path,
+ &iter);
+ gtk_tree_path_free (path);
+ }
+ }
+
+ if (!show && num <= 1 && items)
{
- model->priv->last = item->prev;
+ info = (HeaderInfo *)items->data;
+ node = (ProposalNode *)info->item->data;
+
+ 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);
}
- model->priv->store = g_list_remove_link (model->priv->store, item);
-
- num_dec (model,
- provider,
- !filtered || (filtered & GTK_SOURCE_COMPLETION_MODEL_COUNT),
- !filtered);
+ 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);
- if (!filtered)
+ while (g_hash_table_iter_next (&hiter, (gpointer *)&provider, (gpointer *)&info))
{
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ 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);
+ }
}
- gtk_tree_path_free (path);
- g_object_unref (provider);
+ if (model->priv->show_headers)
+ {
+ update_show_headers (model, TRUE);
+ return;
+ }
}
/* Public */
@@ -541,6 +639,26 @@
return model;
}
+static void
+append_list (GtkSourceCompletionModel *model,
+ ProposalNode *node)
+{
+ GList *item;
+
+ item = g_list_append (model->priv->last, node);
+
+ if (model->priv->store == NULL)
+ {
+ model->priv->store = item;
+ }
+ else
+ {
+ item = item->next;
+ }
+
+ model->priv->last = item;
+}
+
gboolean
gtk_source_completion_model_append (GtkSourceCompletionModel *model,
GtkSourceCompletionProvider *provider,
@@ -550,31 +668,41 @@
ProposalNode *node;
GList *item;
GtkTreePath *path;
+ ProposalNode *header = NULL;
+ HeaderInfo *info;
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);
+
+ if (g_hash_table_lookup (model->priv->num_per_provider, provider) == NULL)
+ {
+ header = g_slice_new (ProposalNode);
+ header->provider = g_object_ref (provider);
+ header->proposal = NULL;
+ header->filtered = GTK_SOURCE_COMPLETION_MODEL_FILTERED;
+
+ append_list (model, header);
+
+ info = g_slice_new (HeaderInfo);
+ info->item = model->priv->last;
+ info->num = 0;
+ info->visible_items = 0;
+
+ g_hash_table_insert (model->priv->num_per_provider, provider, info);
+ }
+
node = g_slice_new (ProposalNode);
node->provider = g_object_ref (provider);
node->proposal = g_object_ref (proposal);
node_update_filter_state (model, node);
+ append_list (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;
num_inc (model,
@@ -585,26 +713,18 @@
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)
+ {
+ update_show_headers (model, TRUE);
+ }
}
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)
{
@@ -634,7 +754,7 @@
num_dec (model,
node->provider,
- !filtered || (filtered & GTK_SOURCE_COMPLETION_MODEL_COUNT),
+ (!filtered || (filtered & GTK_SOURCE_COMPLETION_MODEL_COUNT)) && node->proposal != NULL,
!filtered);
if (!filtered)
@@ -704,6 +824,7 @@
}
gtk_tree_path_free (path);
+ refilter_headers (model);
}
gboolean
@@ -744,3 +865,81 @@
}
}
+void
+gtk_source_completion_model_set_show_headers (GtkSourceCompletionModel *model,
+ gboolean show_headers)
+{
+ g_return_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model));
+
+ if (model->priv->show_headers != show_headers)
+ {
+ model->priv->show_headers = show_headers;
+ refilter_headers (model);
+ }
+}
+
+gboolean
+gtk_source_completion_model_iter_is_header (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);
+
+ return node_from_iter (iter)->proposal == NULL;
+}
+
+gboolean
+gtk_source_completion_model_iter_previous (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter)
+{
+ GList *item;
+
+ 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);
+
+ item = iter->user_data;
+
+ do
+ {
+ item = g_list_previous (item);
+ } while (item && ((ProposalNode *)item->data)->filtered);
+
+
+ if (item != NULL)
+ {
+ iter->user_data = item;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+gboolean
+gtk_source_completion_model_iter_last (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter)
+{
+ GList *item;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_MODEL (model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ item = model->priv->last;
+ iter->user_data = item;
+
+ if (!((ProposalNode *)item->data)->filtered)
+ {
+ return TRUE;
+ }
+ else if (item != NULL)
+ {
+ return gtk_source_completion_model_iter_previous (model, iter);
+ }
+ else
+ {
+ return FALSE;
+ }
+}
Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.h
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.h (original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionmodel.h Mon Apr 13 23:12:12 2009
@@ -83,9 +83,6 @@
GtkSourceCompletionProposal *proposal,
GtkTreeIter *iter);
-gboolean gtk_source_completion_model_remove (GtkSourceCompletionModel *model,
- GtkTreeIter *iter);
-
gboolean gtk_source_completion_model_is_empty (GtkSourceCompletionModel *model,
gboolean invisible);
@@ -96,6 +93,18 @@
void gtk_source_completion_model_refilter (GtkSourceCompletionModel *model);
+void gtk_source_completion_model_set_show_headers (GtkSourceCompletionModel *model,
+ gboolean show_headers);
+
+gboolean gtk_source_completion_model_iter_is_header (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter);
+
+gboolean gtk_source_completion_model_iter_previous (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter);
+
+gboolean gtk_source_completion_model_iter_last (GtkSourceCompletionModel *model,
+ GtkTreeIter *iter);
+
G_END_DECLS
#endif /* __GTK_SOURCE_COMPLETION_MODEL_H__ */
Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c (original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c Mon Apr 13 23:12:12 2009
@@ -40,6 +40,12 @@
g_return_val_if_reached (NULL);
}
+static const GdkPixbuf *
+gtk_source_completion_provider_get_icon_default (GtkSourceCompletionProvider *provider)
+{
+ return NULL;
+}
+
static GList *
gtk_source_completion_provider_get_proposals_default (GtkSourceCompletionProvider *provider)
{
@@ -80,6 +86,8 @@
static gboolean initialized = FALSE;
iface->get_name = gtk_source_completion_provider_get_name_default;
+ iface->get_icon = gtk_source_completion_provider_get_icon_default;
+
iface->get_proposals = gtk_source_completion_provider_get_proposals_default;
iface->filter_proposal = gtk_source_completion_provider_filter_proposal_default;
iface->can_auto_complete = gtk_source_completion_provider_can_auto_complete_default;
@@ -140,6 +148,13 @@
return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_name (provider);
}
+const GdkPixbuf *
+gtk_source_completion_provider_get_icon (GtkSourceCompletionProvider *provider)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), NULL);
+ return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_icon (provider);
+}
+
/**
* gtk_source_completion_provider_get_proposals:
* @provider: The #GtkSourceCompletionProvider
Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h (original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h Mon Apr 13 23:12:12 2009
@@ -45,6 +45,7 @@
GTypeInterface g_iface;
const gchar *(*get_name) (GtkSourceCompletionProvider *provider);
+ const GdkPixbuf *(*get_icon) (GtkSourceCompletionProvider *provider);
GList *(*get_proposals) (GtkSourceCompletionProvider *provider);
gboolean (*filter_proposal) (GtkSourceCompletionProvider *provider,
GtkSourceCompletionProposal *proposal,
@@ -63,6 +64,8 @@
const gchar *gtk_source_completion_provider_get_name (GtkSourceCompletionProvider *provider);
+const GdkPixbuf *gtk_source_completion_provider_get_icon (GtkSourceCompletionProvider *provider);
+
GList *gtk_source_completion_provider_get_proposals (GtkSourceCompletionProvider *provider);
gboolean gtk_source_completion_provider_filter_proposal (GtkSourceCompletionProvider *provider,
Modified: branches/gtksourcecompletion/tests/completion-simple.c
==============================================================================
--- branches/gtksourcecompletion/tests/completion-simple.c (original)
+++ branches/gtksourcecompletion/tests/completion-simple.c Mon Apr 13 23:12:12 2009
@@ -156,21 +156,53 @@
return window;
}
+static GdkPixbuf *
+get_icon_from_theme (const gchar *name)
+{
+ GtkIconTheme *theme;
+ gint width;
+
+ theme = gtk_icon_theme_get_default ();
+
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, NULL);
+ return gtk_icon_theme_load_icon (theme,
+ name,
+ width,
+ GTK_ICON_LOOKUP_USE_BUILTIN,
+ NULL);
+}
+
static void
create_completion(void)
{
GscProviderTest *prov_test1;
GscProviderDevhelp *prov_devhelp;
+ GdkPixbuf *icon;
comp = gtk_source_view_get_completion (GTK_SOURCE_VIEW (view));
- prov_test1 = gsc_provider_test_new ("Test 1");
+ icon = get_icon_from_theme (GTK_STOCK_NETWORK);
+
+ prov_test1 = gsc_provider_test_new ("Networking", icon);
+
+ if (icon != NULL)
+ {
+ g_object_unref (icon);
+ }
+
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_devhelp));
- prov_test1 = gsc_provider_test_new ("Test 2");
+ icon = get_icon_from_theme (GTK_STOCK_OPEN);
+ prov_test1 = gsc_provider_test_new ("Open Files", icon);
+
+ if (icon != NULL)
+ {
+ g_object_unref (icon);
+ }
+
gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_test1));
}
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 23:12:12 2009
@@ -27,6 +27,8 @@
struct _GscProviderTestPrivate
{
gchar *name;
+ GdkPixbuf *icon;
+ GdkPixbuf *proposal_icon;
};
G_DEFINE_TYPE_WITH_CODE (GscProviderTest,
@@ -41,6 +43,13 @@
return GSC_PROVIDER_TEST (self)->priv->name;
}
+static const GdkPixbuf *
+gsc_provider_test_get_icon (GtkSourceCompletionProvider *self)
+{
+ return GSC_PROVIDER_TEST (self)->priv->icon;
+}
+
+
static GList *
append_item (GList *list, const gchar *name, GdkPixbuf *icon, const gchar *info)
{
@@ -53,12 +62,13 @@
static GList *
gsc_provider_test_get_proposals (GtkSourceCompletionProvider *base)
{
+ GscProviderTest *provider = GSC_PROVIDER_TEST (base);
GList *list = NULL;
- 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");
+ list = append_item (list, "aa", provider->priv->proposal_icon, "Info proposal 1.1");
+ list = append_item (list, "ab", provider->priv->proposal_icon, "Info proposal 1.2");
+ list = append_item (list, "bc", provider->priv->proposal_icon, "Info proposal 1.3");
+ list = append_item (list, "bd", provider->priv->proposal_icon, "Info proposal 1.3");
return list;
}
@@ -86,6 +96,16 @@
GscProviderTest *provider = GSC_PROVIDER_TEST (object);
g_free (provider->priv->name);
+
+ if (provider->priv->icon != NULL)
+ {
+ g_object_unref (provider->priv->icon);
+ }
+
+ if (provider->priv->proposal_icon != NULL)
+ {
+ g_object_unref (provider->priv->proposal_icon);
+ }
G_OBJECT_CLASS (gsc_provider_test_parent_class)->finalize (object);
}
@@ -105,6 +125,8 @@
gsc_provider_test_iface_init (GtkSourceCompletionProviderIface *iface)
{
iface->get_name = gsc_provider_test_get_name;
+ iface->get_icon = gsc_provider_test_get_icon;
+
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;
@@ -113,14 +135,33 @@
static void
gsc_provider_test_init (GscProviderTest * self)
{
+ GtkIconTheme *theme;
+ gint width;
+
self->priv = GSC_PROVIDER_TEST_GET_PRIVATE (self);
+
+ theme = gtk_icon_theme_get_default ();
+
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, NULL);
+ self->priv->proposal_icon = gtk_icon_theme_load_icon (theme,
+ GTK_STOCK_YES,
+ width,
+ GTK_ICON_LOOKUP_USE_BUILTIN,
+ NULL);
}
GscProviderTest *
-gsc_provider_test_new (const gchar *name)
+gsc_provider_test_new (const gchar *name,
+ GdkPixbuf *icon)
{
GscProviderTest *ret = g_object_new (GSC_TYPE_PROVIDER_TEST, NULL);
ret->priv->name = g_strdup (name);
+
+ if (icon != NULL)
+ {
+ ret->priv->icon = g_object_ref (icon);
+ }
+
return ret;
}
Modified: branches/gtksourcecompletion/tests/gsc-provider-test.h
==============================================================================
--- branches/gtksourcecompletion/tests/gsc-provider-test.h (original)
+++ branches/gtksourcecompletion/tests/gsc-provider-test.h Mon Apr 13 23:12:12 2009
@@ -52,7 +52,8 @@
GType gsc_provider_test_get_type (void) G_GNUC_CONST;
-GscProviderTest *gsc_provider_test_new (const gchar *name);
+GscProviderTest *gsc_provider_test_new (const gchar *name,
+ GdkPixbuf *icon);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]