Compare commits

...

4 Commits

Author SHA1 Message Date
Matthias Clasen
0b8092a2ba entrycompletion: port to list models
Replace tree models and cell renderers with list models
and factories, in the entry completion api. The new apis
are

gtk_entry_completion_set_model
gtk_entry_completion_set_expression
gtk_entry_completion_set_factory

Port all internal uses of GtkEntryCompletion.

testentrycompletion has an example of using a custom model,
factory and expression.
2020-06-25 08:24:05 -04:00
Matthias Clasen
ab3b1d9d2a filechooserentry: remove entry completion
This may be a temporary measure. The entry completion
code in GtkFileChooserEntry is to entangles with
GtkFileSystemModel to make it work with a new entry
completion that is based on list models, so remove
the completion functionality for now. It may come
back when the file chooser as a whole is ported to
list models.
2020-06-25 08:24:05 -04:00
Matthias Clasen
24d871cf93 Drop unused includes
Don't include gtkfilechooserentry.h where it
isn't used.
2020-06-25 08:24:05 -04:00
Matthias Clasen
a193c7620e stringfilter: Fix a typo 2020-06-25 08:24:05 -04:00
19 changed files with 592 additions and 1367 deletions

View File

@@ -8,8 +8,8 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
/* Creates a tree model containing the completions */
static GtkTreeModel *
/* Creates a list model containing the completions */
static GListModel *
create_completion_model (void)
{
const char *strings[] = {
@@ -42,20 +42,8 @@ create_completion_model (void)
"aæz",
NULL
};
int i;
GtkListStore *store;
GtkTreeIter iter;
store = gtk_list_store_new (1, G_TYPE_STRING);
for (i = 0; strings[i]; i++)
{
/* Append one word */
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, strings[i], -1);
}
return GTK_TREE_MODEL (store);
return G_LIST_MODEL (gtk_string_list_new (strings));
}
@@ -67,7 +55,7 @@ do_entry_completion (GtkWidget *do_widget)
GtkWidget *label;
GtkWidget *entry;
GtkEntryCompletion *completion;
GtkTreeModel *completion_model;
GListModel *completion_model;
if (!window)
{
@@ -105,9 +93,6 @@ do_entry_completion (GtkWidget *do_widget)
gtk_entry_completion_set_model (completion, completion_model);
g_object_unref (completion_model);
/* Use model column 0 as the text column */
gtk_entry_completion_set_text_column (completion, 0);
gtk_entry_completion_set_inline_completion (completion, TRUE);
gtk_entry_completion_set_inline_selection (completion, TRUE);
}

View File

@@ -200,18 +200,18 @@
</row>
</data>
</object>
<object class="GtkStringList" id="name_list">
<items>
<item>Andrea</item>
<item>Otto</item>
<item>Orville</item>
<item>Benjamin</item>
</items>
</object>
<object class="GtkEntryCompletion" id="name_completion">
<property name="model">liststore1</property>
<property name="text-column">2</property>
<property name="model">name_list</property>
<property name="inline-completion">1</property>
<property name="popup-single-match">0</property>
<property name="inline-selection">1</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
<object class="GtkListStore" id="lrmodel">
<columns>

View File

@@ -1162,24 +1162,20 @@ gtk_entry_buffer_get_type
<FILE>gtkentrycompletion</FILE>
<TITLE>GtkEntryCompletion</TITLE>
GtkEntryCompletion
GtkEntryCompletionMatchFunc
gtk_entry_completion_new
gtk_entry_completion_new_with_area
gtk_entry_completion_get_entry
gtk_entry_completion_set_model
gtk_entry_completion_get_model
gtk_entry_completion_set_match_func
gtk_entry_completion_set_expression
gtk_entry_completion_get_expression
gtk_entry_completion_set_factory
gtk_entry_completion_get_factory
gtk_entry_completion_set_minimum_key_length
gtk_entry_completion_get_minimum_key_length
gtk_entry_completion_compute_prefix
gtk_entry_completion_complete
gtk_entry_completion_get_completion_prefix
gtk_entry_completion_insert_prefix
gtk_entry_completion_insert_action_text
gtk_entry_completion_insert_action_markup
gtk_entry_completion_delete_action
gtk_entry_completion_set_text_column
gtk_entry_completion_get_text_column
gtk_entry_completion_set_inline_completion
gtk_entry_completion_get_inline_completion
gtk_entry_completion_set_inline_selection

View File

@@ -1752,7 +1752,7 @@ gtk_entry_size_allocate (GtkWidget *widget,
completion = gtk_entry_get_completion (entry);
if (completion)
_gtk_entry_completion_resize_popup (completion);
gtk_entry_completion_resize_popup (completion);
}
if (priv->emoji_chooser)
@@ -3183,7 +3183,7 @@ gtk_entry_set_completion (GtkEntry *entry,
if (old)
{
_gtk_entry_completion_disconnect (old);
gtk_entry_completion_disconnect (old);
g_object_unref (old);
}
@@ -3196,7 +3196,7 @@ gtk_entry_set_completion (GtkEntry *entry,
/* hook into the entry */
g_object_ref (completion);
_gtk_entry_completion_connect (completion, entry);
gtk_entry_completion_connect (completion, entry);
g_object_set_qdata (G_OBJECT (entry), quark_entry_completion, completion);

File diff suppressed because it is too large Load Diff

View File

@@ -23,11 +23,8 @@
#endif
#include <gdk/gdk.h>
#include <gtk/gtktreemodel.h>
#include <gtk/gtkliststore.h>
#include <gtk/gtkcellarea.h>
#include <gtk/gtktreeviewcolumn.h>
#include <gtk/gtktreemodelfilter.h>
#include <gtk/gtklistitemfactory.h>
#include <gtk/gtkexpression.h>
G_BEGIN_DECLS
@@ -37,50 +34,31 @@ G_BEGIN_DECLS
typedef struct _GtkEntryCompletion GtkEntryCompletion;
/**
* GtkEntryCompletionMatchFunc:
* @completion: the #GtkEntryCompletion
* @key: the string to match, normalized and case-folded
* @iter: a #GtkTreeIter indicating the row to match
* @user_data: user data given to gtk_entry_completion_set_match_func()
*
* A function which decides whether the row indicated by @iter matches
* a given @key, and should be displayed as a possible completion for @key.
* Note that @key is normalized and case-folded (see g_utf8_normalize()
* and g_utf8_casefold()). If this is not appropriate, match functions
* have access to the unmodified key via
* `gtk_editable_get_text (GTK_EDITABLE (gtk_entry_completion_get_entry ()))`.
*
* Returns: %TRUE if @iter should be displayed as a possible completion
* for @key
*/
typedef gboolean (* GtkEntryCompletionMatchFunc) (GtkEntryCompletion *completion,
const gchar *key,
GtkTreeIter *iter,
gpointer user_data);
GDK_AVAILABLE_IN_ALL
GType gtk_entry_completion_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkEntryCompletion *gtk_entry_completion_new (void);
GDK_AVAILABLE_IN_ALL
GtkEntryCompletion *gtk_entry_completion_new_with_area (GtkCellArea *area);
GDK_AVAILABLE_IN_ALL
GtkWidget *gtk_entry_completion_get_entry (GtkEntryCompletion *completion);
GDK_AVAILABLE_IN_ALL
void gtk_entry_completion_set_model (GtkEntryCompletion *completion,
GtkTreeModel *model);
GListModel *model);
GDK_AVAILABLE_IN_ALL
GtkTreeModel *gtk_entry_completion_get_model (GtkEntryCompletion *completion);
GListModel * gtk_entry_completion_get_model (GtkEntryCompletion *completion);
GDK_AVAILABLE_IN_ALL
void gtk_entry_completion_set_match_func (GtkEntryCompletion *completion,
GtkEntryCompletionMatchFunc func,
gpointer func_data,
GDestroyNotify func_notify);
void gtk_entry_completion_set_expression (GtkEntryCompletion *completion,
GtkExpression *expression);
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_entry_completion_get_expression (GtkEntryCompletion *completion);
GDK_AVAILABLE_IN_ALL
void gtk_entry_completion_set_factory (GtkEntryCompletion *completion,
GtkListItemFactory *factory);
GDK_AVAILABLE_IN_ALL
GtkListItemFactory *gtk_entry_completion_get_factory (GtkEntryCompletion *completion);
GDK_AVAILABLE_IN_ALL
void gtk_entry_completion_set_minimum_key_length (GtkEntryCompletion *completion,
gint length);
@@ -122,12 +100,6 @@ gboolean gtk_entry_completion_get_popup_single_match (GtkEntryComplet
GDK_AVAILABLE_IN_ALL
const gchar *gtk_entry_completion_get_completion_prefix (GtkEntryCompletion *completion);
/* convenience */
GDK_AVAILABLE_IN_ALL
void gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
gint column);
GDK_AVAILABLE_IN_ALL
gint gtk_entry_completion_get_text_column (GtkEntryCompletion *completion);
G_END_DECLS

View File

@@ -38,43 +38,34 @@ struct _GtkEntryCompletion
GtkWidget *entry;
GtkWidget *tree_view;
GtkTreeViewColumn *column;
GtkTreeModelFilter *filter_model;
GtkCellArea *cell_area;
GtkEntryCompletionMatchFunc match_func;
gpointer match_data;
GDestroyNotify match_notify;
GListModel *filter_model;
GtkExpression *expression;
GtkListItemFactory *factory;
gint minimum_key_length;
gint text_column;
gchar *case_normalized_key;
char *case_normalized_key;
GtkEventController *entry_key_controller;
GtkEventController *entry_focus_controller;
/* only used by GtkEntry when attached: */
GtkWidget *popup_window;
GtkWidget *scrolled_window;
GtkWidget *list_view;
gulong completion_timeout;
gulong changed_id;
gulong insert_text_id;
gint current_selected;
int current_selected;
guint first_sel_changed : 1;
guint has_completion : 1;
guint inline_completion : 1;
guint popup_completion : 1;
guint popup_set_width : 1;
guint has_completion : 1;
guint inline_completion : 1;
guint popup_completion : 1;
guint popup_set_width : 1;
guint popup_single_match : 1;
guint inline_selection : 1;
guint has_grab : 1;
gchar *completion_prefix;
char *completion_prefix;
GSource *check_completion_idle;
};
@@ -84,23 +75,19 @@ struct _GtkEntryCompletionClass
GObjectClass parent_class;
gboolean (* match_selected) (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter);
void (* action_activated) (GtkEntryCompletion *completion,
gint index_);
guint position);
gboolean (* insert_prefix) (GtkEntryCompletion *completion,
const gchar *prefix);
const char *prefix);
gboolean (* cursor_on_match) (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter);
guint position);
void (* no_matches) (GtkEntryCompletion *completion);
};
void _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion);
void _gtk_entry_completion_popdown (GtkEntryCompletion *completion);
void _gtk_entry_completion_connect (GtkEntryCompletion *completion,
GtkEntry *entry);
void _gtk_entry_completion_disconnect (GtkEntryCompletion *completion);
void gtk_entry_completion_resize_popup (GtkEntryCompletion *completion);
void gtk_entry_completion_popdown (GtkEntryCompletion *completion);
void gtk_entry_completion_connect (GtkEntryCompletion *completion,
GtkEntry *entry);
void gtk_entry_completion_disconnect (GtkEntryCompletion *completion);
GtkIMContext * _gtk_entry_get_im_context (GtkEntry *entry);
GtkEventController * gtk_entry_get_key_controller (GtkEntry *entry);

View File

@@ -102,11 +102,6 @@ static void delete_text_callback (GtkFileChooserEntry *widget,
gpointer user_data);
#endif
static gboolean match_selected_callback (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter,
GtkFileChooserEntry *chooser_entry);
static void set_complete_on_load (GtkFileChooserEntry *chooser_entry,
gboolean complete_on_load);
static void refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry);
@@ -181,83 +176,6 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
G_TYPE_NONE, 0);
}
static gboolean
match_func (GtkEntryCompletion *compl,
const gchar *key,
GtkTreeIter *iter,
gpointer user_data)
{
GtkFileChooserEntry *chooser_entry = user_data;
/* If we arrive here, the GtkFileSystemModel's GtkFileFilter already filtered out all
* files that don't start with the current prefix, so we manually apply the GtkFileChooser's
* current file filter (e.g. just jpg files) here. */
if (chooser_entry->current_filter != NULL)
{
char *mime_type = NULL;
gboolean matches;
GFile *file;
GFileInfo *file_info;
GtkFileFilterInfo filter_info;
GtkFileFilterFlags needed_flags;
file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
iter);
file_info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
iter);
/* We always allow navigating into subfolders, so don't ever filter directories */
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR)
return TRUE;
needed_flags = gtk_file_filter_get_needed (chooser_entry->current_filter);
filter_info.display_name = g_file_info_get_display_name (file_info);
filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME;
if (needed_flags & GTK_FILE_FILTER_MIME_TYPE)
{
const char *s = g_file_info_get_content_type (file_info);
if (s != NULL)
{
mime_type = g_content_type_get_mime_type (s);
if (mime_type != NULL)
{
filter_info.mime_type = mime_type;
filter_info.contains |= GTK_FILE_FILTER_MIME_TYPE;
}
}
}
if (needed_flags & GTK_FILE_FILTER_FILENAME)
{
const char *path = g_file_get_path (file);
if (path != NULL)
{
filter_info.filename = path;
filter_info.contains |= GTK_FILE_FILTER_FILENAME;
}
}
if (needed_flags & GTK_FILE_FILTER_URI)
{
const char *uri = g_file_get_uri (file);
if (uri)
{
filter_info.uri = uri;
filter_info.contains |= GTK_FILE_FILTER_URI;
}
}
matches = gtk_file_filter_filter (chooser_entry->current_filter, &filter_info);
g_free (mime_type);
return matches;
}
return TRUE;
}
static void
chooser_entry_focus_out (GtkEventController *controller,
GtkFileChooserEntry *chooser_entry)
@@ -269,37 +187,9 @@ static void
_gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
{
GtkEventController *controller;
GtkEntryCompletion *comp;
GtkCellRenderer *cell;
g_object_set (chooser_entry, "truncate-multiline", TRUE, NULL);
comp = gtk_entry_completion_new ();
gtk_entry_completion_set_popup_single_match (comp, FALSE);
gtk_entry_completion_set_minimum_key_length (comp, 0);
/* see docs for gtk_entry_completion_set_text_column() */
g_object_set (comp, "text-column", FULL_PATH_COLUMN, NULL);
/* Need a match func here or entry completion uses a wrong one.
* We do our own filtering after all. */
gtk_entry_completion_set_match_func (comp,
match_func,
chooser_entry,
NULL);
cell = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comp),
cell, TRUE);
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (comp),
cell,
"text", DISPLAY_NAME_COLUMN);
g_signal_connect (comp, "match-selected",
G_CALLBACK (match_selected_callback), chooser_entry);
gtk_entry_set_completion (GTK_ENTRY (chooser_entry), comp);
g_object_unref (comp);
/* NB: This needs to happen after the completion is set, so this controller
* runs before the one installed by entrycompletion */
controller = gtk_event_controller_key_new ();
@@ -349,36 +239,6 @@ gtk_file_chooser_entry_dispose (GObject *object)
G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->dispose (object);
}
/* Match functions for the GtkEntryCompletion */
static gboolean
match_selected_callback (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter,
GtkFileChooserEntry *chooser_entry)
{
char *path;
gint pos;
gtk_tree_model_get (model, iter,
FULL_PATH_COLUMN, &path,
-1);
gtk_editable_delete_text (GTK_EDITABLE (chooser_entry),
0,
gtk_editable_get_position (GTK_EDITABLE (chooser_entry)));
pos = 0;
gtk_editable_insert_text (GTK_EDITABLE (chooser_entry),
path,
-1,
&pos);
gtk_editable_set_position (GTK_EDITABLE (chooser_entry), pos);
g_free (path);
return TRUE;
}
static void
set_complete_on_load (GtkFileChooserEntry *chooser_entry,
gboolean complete_on_load)
@@ -552,30 +412,6 @@ gtk_file_chooser_entry_tab_handler (GtkEventControllerKey *key,
return GDK_EVENT_STOP;
}
static void
update_inline_completion (GtkFileChooserEntry *chooser_entry)
{
GtkEntryCompletion *completion = gtk_entry_get_completion (GTK_ENTRY (chooser_entry));
if (!chooser_entry->current_folder_loaded)
{
gtk_entry_completion_set_inline_completion (completion, FALSE);
return;
}
switch (chooser_entry->action)
{
case GTK_FILE_CHOOSER_ACTION_OPEN:
case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
gtk_entry_completion_set_inline_completion (completion, TRUE);
break;
case GTK_FILE_CHOOSER_ACTION_SAVE:
default:
gtk_entry_completion_set_inline_completion (completion, FALSE);
break;
}
}
static void
discard_completion_store (GtkFileChooserEntry *chooser_entry)
{
@@ -583,7 +419,6 @@ discard_completion_store (GtkFileChooserEntry *chooser_entry)
return;
gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)), NULL);
update_inline_completion (chooser_entry);
g_object_unref (chooser_entry->completion_store);
chooser_entry->completion_store = NULL;
}
@@ -647,9 +482,6 @@ populate_completion_store (GtkFileChooserEntry *chooser_entry)
chooser_entry->action == GTK_FILE_CHOOSER_ACTION_SAVE);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser_entry->completion_store),
DISPLAY_NAME_COLUMN, GTK_SORT_ASCENDING);
gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)),
chooser_entry->completion_store);
}
/* Callback when the current folder finishes loading */
@@ -675,7 +507,6 @@ finished_loading_cb (GtkFileSystemModel *model,
gtk_widget_set_tooltip_text (GTK_WIDGET (chooser_entry), NULL);
completion = gtk_entry_get_completion (GTK_ENTRY (chooser_entry));
update_inline_completion (chooser_entry);
if (gtk_widget_has_focus (GTK_WIDGET (chooser_entry)))
{
@@ -960,32 +791,12 @@ _gtk_file_chooser_entry_set_action (GtkFileChooserEntry *chooser_entry,
if (chooser_entry->action != action)
{
GtkEntryCompletion *comp;
chooser_entry->action = action;
comp = gtk_entry_get_completion (GTK_ENTRY (chooser_entry));
/* FIXME: do we need to actually set the following? */
switch (action)
{
case GTK_FILE_CHOOSER_ACTION_OPEN:
case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
default:
gtk_entry_completion_set_popup_single_match (comp, FALSE);
break;
case GTK_FILE_CHOOSER_ACTION_SAVE:
gtk_entry_completion_set_popup_single_match (comp, TRUE);
break;
}
if (chooser_entry->completion_store)
_gtk_file_system_model_set_show_files (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
action == GTK_FILE_CHOOSER_ACTION_OPEN ||
action == GTK_FILE_CHOOSER_ACTION_SAVE);
update_inline_completion (chooser_entry);
}
}

View File

@@ -38,7 +38,6 @@
#include "gtkstylecontext.h"
#include "gtkheaderbar.h"
#include "gtklabel.h"
#include "gtkfilechooserentry.h"
#include "gtkfilefilterprivate.h"
/**

View File

@@ -39,7 +39,6 @@
#include "gtkheaderbar.h"
#include "gtklabel.h"
#include "gtkmain.h"
#include "gtkfilechooserentry.h"
#include "gtkfilefilterprivate.h"
#include "gtkwindowprivate.h"

View File

@@ -38,7 +38,6 @@
#include "gtkstylecontext.h"
#include "gtkheaderbar.h"
#include "gtklabel.h"
#include "gtkfilechooserentry.h"
#include "gtkfilefilterprivate.h"
#include "quartz/gdkquartz.h"

View File

@@ -44,7 +44,6 @@
#include "gtkstylecontext.h"
#include "gtkheaderbar.h"
#include "gtklabel.h"
#include "gtkfilechooserentry.h"
#include "gtkfilefilterprivate.h"
#include "gtknative.h"

View File

@@ -37,7 +37,6 @@
#include "gtkstylecontext.h"
#include "gtkheaderbar.h"
#include "gtklabel.h"
#include "gtkfilechooserentry.h"
/**
* SECTION:gtknativedialog

View File

@@ -30,6 +30,7 @@
#include "gtktypebuiltins.h"
#include "gtkeventcontrollerkey.h"
#include "gtkpopovermenu.h"
#include "gtkstringlist.h"
/*
* SECTION:gtkplacesview
@@ -98,7 +99,7 @@ struct _GtkPlacesView
GtkSizeGroup *space_size_group;
GtkEntryCompletion *address_entry_completion;
GtkListStore *completion_store;
GListModel *completion_store;
GCancellable *networks_fetching_cancellable;
@@ -551,12 +552,12 @@ populate_servers (GtkPlacesView *view)
while ((child = gtk_widget_get_first_child (GTK_WIDGET (view->recent_servers_listbox))))
gtk_list_box_remove (GTK_LIST_BOX (view->listbox), child);
gtk_list_store_clear (view->completion_store);
while (g_list_model_get_n_items (G_LIST_MODEL (view->completion_store)) > 0)
gtk_string_list_remove (GTK_STRING_LIST (view->completion_store), 0);
for (i = 0; i < num_uris; i++)
{
RemoveServerData *data;
GtkTreeIter iter;
GtkWidget *row;
GtkWidget *grid;
GtkWidget *button;
@@ -568,12 +569,7 @@ populate_servers (GtkPlacesView *view)
dup_uri = g_strdup (uris[i]);
/* add to the completion list */
gtk_list_store_append (view->completion_store, &iter);
gtk_list_store_set (view->completion_store,
&iter,
0, name,
1, uris[i],
-1);
gtk_string_list_append (GTK_STRING_LIST (view->completion_store), uris[i]);
/* add to the recent servers listbox */
row = gtk_list_box_row_new ();

View File

@@ -484,7 +484,7 @@ gtk_string_filter_get_match_mode (GtkStringFilter *self)
* @self: a #GtkStringFilter
* @mode: the new match mode
*
* Sets the match mode fot the filter.
* Sets the match mode for the filter.
*/
void
gtk_string_filter_set_match_mode (GtkStringFilter *self,

View File

@@ -1,15 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="gtk40">
<requires lib="gtk+" version="3.16"/>
<object class="GtkListStore" id="completion_store">
<columns>
<column type="gchararray"/>
<column type="gchararray"/>
</columns>
<object class="GtkStringList" id="completion_store">
</object>
<object class="GtkEntryCompletion" id="address_entry_completion">
<property name="model">completion_store</property>
<property name="text-column">1</property>
<property name="inline-completion">1</property>
<property name="popup-completion">0</property>
</object>

View File

@@ -21,272 +21,80 @@
#include <string.h>
#include <gtk/gtk.h>
/* Don't copy this bad example; inline RGB data is always a better
* idea than inline XPMs.
*/
static const char *book_closed_xpm[] = {
"16 16 6 1",
" c None s None",
". c black",
"X c red",
"o c yellow",
"O c #808080",
"# c white",
" ",
" .. ",
" ..XX. ",
" ..XXXXX. ",
" ..XXXXXXXX. ",
".ooXXXXXXXXX. ",
"..ooXXXXXXXXX. ",
".X.ooXXXXXXXXX. ",
".XX.ooXXXXXX.. ",
" .XX.ooXXX..#O ",
" .XX.oo..##OO. ",
" .XX..##OO.. ",
" .X.#OO.. ",
" ..O.. ",
" .. ",
" "
};
static GtkWidget *window = NULL;
/* Creates a tree model containing the completions */
static GtkTreeModel *
/* Creates a list model containing the completions */
static GListModel *
create_simple_completion_model (void)
{
GtkListStore *store;
GtkTreeIter iter;
store = gtk_list_store_new (1, G_TYPE_STRING);
const char *strings[] = {
"GNOME",
"gnominious",
"Gnomonic projection",
"total",
"totally",
"toto",
"tottery",
"totterer",
"Totten trust",
"totipotent",
"totipotency",
"totemism",
"totem pole",
"Totara",
"totalizer",
"totalizator",
"totalitarianism",
"total parenteral nutrition",
"total hysterectomy",
"total eclipse",
"Totipresence",
"Totipalmi",
"zombie",
"a\303\246x",
"a\303\246y",
"a\303\246z",
NULL
};
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "GNOME", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "gnominious", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "Gnomonic projection", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "total", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totally", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "toto", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "tottery", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totterer", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "Totten trust", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totipotent", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totipotency", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totemism", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totem pole", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "Totara", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totalizer", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totalizator", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totalitarianism", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "total parenteral nutrition", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "total hysterectomy", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "total eclipse", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "Totipresence", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "Totipalmi", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "zombie", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "a\303\246x", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "a\303\246y", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "a\303\246z", -1);
return GTK_TREE_MODEL (store);
return G_LIST_MODEL (gtk_string_list_new (strings));
}
/* Creates a tree model containing the completions */
static GtkTreeModel *
create_completion_model (void)
static char *
get_file_name (gpointer item)
{
GtkListStore *store;
GtkTreeIter iter;
GdkPixbuf *pixbuf;
pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambient", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambidextrously", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambidexter", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambiguity", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "American Party", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "American mountain ash", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "amelioration", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Amelia Earhart", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Totten trust", -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Laminated arch", -1);
return GTK_TREE_MODEL (store);
}
static gboolean
match_func (GtkEntryCompletion *completion,
const gchar *key,
GtkTreeIter *iter,
gpointer user_data)
{
gchar *item = NULL;
GtkTreeModel *model;
gboolean ret = FALSE;
model = gtk_entry_completion_get_model (completion);
gtk_tree_model_get (model, iter, 1, &item, -1);
if (item != NULL)
{
g_print ("compare %s %s\n", key, item);
if (strncmp (key, item, strlen (key)) == 0)
ret = TRUE;
g_free (item);
}
return ret;
}
static gint timer_count = 0;
static const char *dynamic_completions[] = {
"GNOME",
"gnominious",
"Gnomonic projection",
"total",
"totally",
"toto",
"tottery",
"totterer",
"Totten trust",
"totipotent",
"totipotency",
"totemism",
"totem pole",
"Totara",
"totalizer",
"totalizator",
"totalitarianism",
"total parenteral nutrition",
"total hysterectomy",
"total eclipse",
"Totipresence",
"Totipalmi",
"zombie"
};
static gint
animation_timer (GtkEntryCompletion *completion)
{
GtkTreeIter iter;
gint n_completions = G_N_ELEMENTS (dynamic_completions);
gint n;
static GtkListStore *old_store = NULL;
GtkListStore *store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion));
if (timer_count % 10 == 0)
{
if (!old_store)
{
g_print ("removing model!\n");
old_store = g_object_ref (store);
gtk_entry_completion_set_model (completion, NULL);
}
else
{
g_print ("readding model!\n");
gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (old_store));
g_object_unref (old_store);
old_store = NULL;
}
timer_count ++;
return TRUE;
}
if (!old_store)
{
if ((timer_count / n_completions) % 2 == 0)
{
n = timer_count % n_completions;
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, dynamic_completions[n], -1);
}
else
{
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
gtk_list_store_remove (store, &iter);
}
}
timer_count++;
return TRUE;
}
static gboolean
match_selected_cb (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter)
{
gchar *str;
GtkWidget *entry;
entry = gtk_entry_completion_get_entry (completion);
gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 1, &str, -1);
gtk_editable_set_text (GTK_EDITABLE (entry), str);
gtk_editable_set_position (GTK_EDITABLE (entry), -1);
g_free (str);
return TRUE;
return g_strdup (g_file_info_get_display_name (G_FILE_INFO (item)));
}
static void
quit_cb (GtkWidget *widget,
gpointer data)
setup_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
gboolean *done = data;
GtkWidget *box;
GtkWidget *icon;
GtkWidget *label;
*done = TRUE;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
icon = gtk_image_new ();
label = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_box_append (GTK_BOX (box), icon);
gtk_box_append (GTK_BOX (box), label);
gtk_list_item_set_child (item, box);
}
g_main_context_wakeup (NULL);
static void
bind_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GFileInfo *info = G_FILE_INFO (gtk_list_item_get_item (item));
GtkWidget *box = gtk_list_item_get_child (item);
GtkWidget *icon = gtk_widget_get_first_child (box);
GtkWidget *label = gtk_widget_get_last_child (box);
gtk_image_set_from_gicon (GTK_IMAGE (icon), g_file_info_get_icon (info));
gtk_label_set_label (GTK_LABEL (label), g_file_info_get_display_name (info));
}
int
@@ -296,124 +104,79 @@ main (int argc, char *argv[])
GtkWidget *label;
GtkWidget *entry;
GtkEntryCompletion *completion;
GtkTreeModel *completion_model;
GtkCellRenderer *cell;
gboolean done = FALSE;
GListModel *model;
char *cwd;
GFile *file;
GtkExpression *expression;
GtkListItemFactory *factory;
gtk_init ();
window = gtk_window_new ();
g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_widget_set_margin_start (vbox, 5);
gtk_widget_set_margin_end (vbox, 5);
gtk_widget_set_margin_top (vbox, 5);
gtk_widget_set_margin_bottom (vbox, 5);
gtk_window_set_child (GTK_WINDOW (window), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), "Completion demo, try writing <b>total</b> or <b>gnome</b> for example.");
gtk_box_append (GTK_BOX (vbox), label);
/* Create our first entry */
entry = gtk_entry_new ();
/* Create the completion object */
completion = gtk_entry_completion_new ();
gtk_entry_completion_set_inline_completion (completion, TRUE);
/* Assign the completion to the entry */
model = create_simple_completion_model ();
gtk_entry_completion_set_model (completion, model);
g_object_unref (model);
gtk_entry_set_completion (GTK_ENTRY (entry), completion);
g_object_unref (completion);
gtk_box_append (GTK_BOX (vbox), entry);
/* Create a tree model and use it as the completion model */
completion_model = create_simple_completion_model ();
gtk_entry_completion_set_model (completion, completion_model);
g_object_unref (completion_model);
/* Use model column 0 as the text column */
gtk_entry_completion_set_text_column (completion, 0);
/* Create our second entry */
entry = gtk_entry_new ();
/* Create the completion object */
completion = gtk_entry_completion_new ();
/* Assign the completion to the entry */
gtk_entry_set_completion (GTK_ENTRY (entry), completion);
g_object_unref (completion);
gtk_box_append (GTK_BOX (vbox), entry);
/* Create a tree model and use it as the completion model */
completion_model = create_completion_model ();
gtk_entry_completion_set_model (completion, completion_model);
gtk_entry_completion_set_minimum_key_length (completion, 2);
g_object_unref (completion_model);
/* Use model column 1 as the text column */
cell = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell,
"pixbuf", 0, NULL);
cell = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell,
"text", 1, NULL);
gtk_entry_completion_set_match_func (completion, match_func, NULL, NULL);
g_signal_connect (completion, "match-selected",
G_CALLBACK (match_selected_cb), NULL);
/* Create our third entry */
entry = gtk_entry_new ();
/* Create the completion object */
completion = gtk_entry_completion_new ();
/* Assign the completion to the entry */
gtk_entry_set_completion (GTK_ENTRY (entry), completion);
g_object_unref (completion);
gtk_box_append (GTK_BOX (vbox), entry);
/* Create a tree model and use it as the completion model */
completion_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
gtk_entry_completion_set_model (completion, completion_model);
g_object_unref (completion_model);
/* Use model column 0 as the text column */
gtk_entry_completion_set_text_column (completion, 0);
/* Fill the completion dynamically */
g_timeout_add (1000, (GSourceFunc) animation_timer, completion);
/* Fourth entry */
gtk_box_append (GTK_BOX (vbox), gtk_label_new ("Model-less entry completion"));
entry = gtk_entry_new ();
/* Create the completion object */
completion = gtk_entry_completion_new ();
/* Assign the completion to the entry */
gtk_entry_set_completion (GTK_ENTRY (entry), completion);
g_object_unref (completion);
gtk_box_append (GTK_BOX (vbox), entry);
gtk_widget_show (window);
cwd = g_get_current_dir ();
file = g_file_new_for_path (cwd);
model = G_LIST_MODEL (gtk_directory_list_new ("standard::display-name,standard::content-type,standard::icon,standard::size", file));
gtk_entry_completion_set_model (completion, model);
g_object_unref (model);
g_object_unref (file);
g_free (cwd);
while (!done)
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_file_name,
NULL, NULL);
gtk_entry_completion_set_expression (completion, expression);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
gtk_entry_completion_set_factory (completion, factory);
g_object_unref (factory);
gtk_expression_unref (expression);
g_object_unref (completion);
gtk_window_present (GTK_WINDOW (window));
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
g_main_context_iteration (NULL, TRUE);
gtk_window_destroy (GTK_WINDOW (window));
return 0;
}

View File

@@ -2850,17 +2850,10 @@ static const gchar *cursor_names[] = {
NULL
};
static GtkTreeModel *
static GListModel *
cursor_model (void)
{
GtkListStore *store;
gint i;
store = gtk_list_store_new (1, G_TYPE_STRING);
for (i = 0; i < G_N_ELEMENTS (cursor_names); i++)
gtk_list_store_insert_with_values (store, NULL, -1, 0, cursor_names[i], -1);
return (GtkTreeModel *)store;
return G_LIST_MODEL (gtk_string_list_new (cursor_names));
}
static void
@@ -2961,7 +2954,7 @@ create_cursors (GtkWidget *widget)
GtkWidget *entry;
GtkWidget *size;
GtkEntryCompletion *completion;
GtkTreeModel *model;
GListModel *model;
gboolean cursor_demo = FALSE;
GtkGesture *gesture;
@@ -3038,7 +3031,6 @@ create_cursors (GtkWidget *widget)
completion = gtk_entry_completion_new ();
model = cursor_model ();
gtk_entry_completion_set_model (completion, model);
gtk_entry_completion_set_text_column (completion, 0);
gtk_entry_set_completion (GTK_ENTRY (entry), completion);
g_object_unref (model);
gtk_widget_set_hexpand (entry, TRUE);

View File

@@ -255,53 +255,6 @@ test_column_object_new (void)
g_object_unref (col);
}
/* test that we have a cell area after new() */
static void
test_completion_new (void)
{
GtkEntryCompletion *c;
GtkCellArea *area;
c = gtk_entry_completion_new ();
area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c));
g_assert (GTK_IS_CELL_AREA_BOX (area));
g_object_ref_sink (c);
g_object_unref (c);
}
/* test that new_with_area() keeps the provided area */
static void
test_completion_new_with_area (void)
{
GtkEntryCompletion *c;
GtkCellArea *area;
area = gtk_cell_area_box_new ();
c = gtk_entry_completion_new_with_area (area);
g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c)) == area);
g_object_ref_sink (c);
g_object_unref (c);
}
/* test that g_object_new keeps the provided area */
static void
test_completion_object_new (void)
{
GtkEntryCompletion *c;
GtkCellArea *area;
area = gtk_cell_area_box_new ();
gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_HORIZONTAL);
c = g_object_new (GTK_TYPE_ENTRY_COMPLETION, "cell-area", area, NULL);
g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c)) == area);
g_object_ref_sink (c);
g_object_unref (c);
}
int
main (int argc, char *argv[])
{
@@ -324,9 +277,5 @@ main (int argc, char *argv[])
g_test_add_func ("/tests/column-new-with-area", test_column_new_with_area);
g_test_add_func ("/tests/column-object-new", test_column_object_new);
g_test_add_func ("/tests/completion-new", test_completion_new);
g_test_add_func ("/tests/completion-new-with-area", test_completion_new_with_area);
g_test_add_func ("/tests/completion-object-new", test_completion_object_new);
return g_test_run();
}