diff options
author | Benjamin Otte <otte@redhat.com> | 2019-11-09 02:55:48 +0100 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-05-30 12:30:23 -0400 |
commit | 1df17f2feaf37bc4f0aa1f18d26f2deba91f7dd7 (patch) | |
tree | 53576ed061f9d8d3c4a8ec6a5ec6fda7f278a31a | |
parent | 682e97826c99e56c79aca8b5d54e171a18f63546 (diff) | |
download | gtk+-1df17f2feaf37bc4f0aa1f18d26f2deba91f7dd7.tar.gz |
Add GtkFilter
-rw-r--r-- | docs/reference/gtk/gtk4-docs.xml | 3 | ||||
-rw-r--r-- | docs/reference/gtk/gtk4-sections.txt | 20 | ||||
-rw-r--r-- | docs/reference/gtk/gtk4.types.in | 1 | ||||
-rw-r--r-- | gtk/gtk.h | 1 | ||||
-rw-r--r-- | gtk/gtkfilter.c | 181 | ||||
-rw-r--r-- | gtk/gtkfilter.h | 121 | ||||
-rw-r--r-- | gtk/meson.build | 2 |
7 files changed, 329 insertions, 0 deletions
diff --git a/docs/reference/gtk/gtk4-docs.xml b/docs/reference/gtk/gtk4-docs.xml index 22e5fa0c82..48d28d412c 100644 --- a/docs/reference/gtk/gtk4-docs.xml +++ b/docs/reference/gtk/gtk4-docs.xml @@ -49,6 +49,9 @@ <chapter id="Lists"> <title>GListModel support</title> <xi:include href="xml/gtkfilterlistmodel.xml" /> + <section> + <xi:include href="xml/gtkfilter.xml" /> + </section> <xi:include href="xml/gtkflattenlistmodel.xml" /> <xi:include href="xml/gtkmaplistmodel.xml" /> <xi:include href="xml/gtkslicelistmodel.xml" /> diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index d519009a94..eda7e15c96 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -1185,6 +1185,26 @@ gtk_directory_list_get_type </SECTION> <SECTION> +<FILE>gtkfilter</FILE> +<TITLE>GtkFilter</TITLE> +GtkFilter +gtk_filter_match +gtk_filter_get_strictness +<SUBSECTION> +GtkFilterChange +gtk_filter_changed +<SUBSECTION Standard> +GTK_FILTER +GTK_IS_FILTER +GTK_TYPE_FILTER +GTK_FILTER_CLASS +GTK_IS_FILTER_CLASS +GTK_FILTER_GET_CLASS +<SUBSECTION Private> +gtk_filter_get_type +</SECTION> + +<SECTION> <FILE>gtkfilterlistmodel</FILE> <TITLE>GtkFilterListModel</TITLE> GtkFilterListModel diff --git a/docs/reference/gtk/gtk4.types.in b/docs/reference/gtk/gtk4.types.in index d93f495c80..df153a01e4 100644 --- a/docs/reference/gtk/gtk4.types.in +++ b/docs/reference/gtk/gtk4.types.in @@ -77,6 +77,7 @@ gtk_file_chooser_dialog_get_type gtk_file_chooser_get_type gtk_file_chooser_widget_get_type gtk_file_filter_get_type +gtk_filter_get_type gtk_filter_list_model_get_type gtk_fixed_get_type gtk_fixed_layout_get_type @@ -114,6 +114,7 @@ #include <gtk/gtkfilechoosernative.h> #include <gtk/gtkfilechooserwidget.h> #include <gtk/gtkfilefilter.h> +#include <gtk/gtkfilter.h> #include <gtk/gtkfilterlistmodel.h> #include <gtk/gtkflattenlistmodel.h> #include <gtk/gtkflowbox.h> diff --git a/gtk/gtkfilter.c b/gtk/gtkfilter.c new file mode 100644 index 0000000000..697359d74b --- /dev/null +++ b/gtk/gtkfilter.c @@ -0,0 +1,181 @@ +/* + * Copyright © 2019 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: Benjamin Otte <otte@gnome.org> + */ + +#include "config.h" + +#include "gtkfilter.h" + +#include "gtkintl.h" +#include "gtktypebuiltins.h" + +/** + * SECTION:gtkfilter + * @Title: GtkFilter + * @Short_description: Filtering items + * @See_also: #GtkFilerListModel + * + * #GtkFilter is the way to describe filters to be used in #GtkFilterListModel. + * + * The model will use a filter to determine if it should filter items or not + * by calling gtk_filter_match() for each item and only keeping the ones + * visible that the function returns %TRUE for. + * + * Filters may change what items they match through their lifetime. In that + * case, they can call gtk_filter_changed() which will emit the #GtkFilter:changed + * signal to notify that previous filter results are no longer valid and that + * items should be checked via gtk_filter_match() again. + * + * GTK provides various premade filter implementations for common filtering + * operations. These filters often include properties that can be linked to + * various widgets to easily allow searches. + * + * However, in particular for large lists or complex search methods, it is + * also possible to subclass #GtkFilter and provide one's own filter. + */ + +enum { + CHANGED, + LAST_SIGNAL +}; + +G_DEFINE_TYPE (GtkFilter, gtk_filter, G_TYPE_OBJECT) + +static guint signals[LAST_SIGNAL] = { 0 }; + +static gboolean +gtk_filter_default_match (GtkFilter *self, + gpointer item) +{ + g_critical ("Filter of type '%s' does not implement GtkFilter::match", G_OBJECT_TYPE_NAME (self)); + + return FALSE; +} + +static GtkFilterMatch +gtk_filter_default_get_strictness (GtkFilter *self) +{ + return GTK_FILTER_MATCH_SOME; +} + +static void +gtk_filter_class_init (GtkFilterClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + + class->match = gtk_filter_default_match; + class->get_strictness = gtk_filter_default_get_strictness; + + /** + * GtkFilter:changed: + * @self: The #GtkFilter + * @change: how the filter changed + * + * This signal is emitted whenever the filter changed. Users of the filter + * should then check items again via gtk_filter_match(). + * + * #GtkFilterListModel handles this signal automatically. + * + * Depending on the @change parameter, not all items need to be changed, but + * only some. Refer to the #GtkFilterChange documentation for details. + */ + signals[CHANGED] = + g_signal_new (I_("changed"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_FILTER_CHANGE); + g_signal_set_va_marshaller (signals[CHANGED], + G_TYPE_FROM_CLASS (gobject_class), + g_cclosure_marshal_VOID__ENUMv); +} + +static void +gtk_filter_init (GtkFilter *self) +{ +} + +/** + * gtk_filter_match: + * @self: a #GtkFilter + * @item: (type GObject) (transfer none): The item to check + * + * Checks if the given @item is matched by the filter or not. + * + * Returns: %TRUE if the filter matches the item and a filter model should + * keep it, %FALSE if not. + */ +gboolean +gtk_filter_match (GtkFilter *self, + gpointer item) +{ + g_return_val_if_fail (GTK_IS_FILTER (self), FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + return GTK_FILTER_GET_CLASS (self)->match (self, item); +} + +/** + * gtk_filter_get_strictness: + * @self: a #GtkFilter + * + * Gets the known strictness of @filters. If the strictness is not known, + * %GTK_FILTER_MATCH_SOME is returned. + * + * This value may change after emission of the GtkFilter:changed signal. + * + * This function is meant purely for optimization purposes, filters can + * choose to omit implementing it, but #GtkFilterListModel uses it. + * + * Returns: the strictness of @self + **/ +GtkFilterMatch +gtk_filter_get_strictness (GtkFilter *self) +{ + g_return_val_if_fail (GTK_IS_FILTER (self), GTK_FILTER_MATCH_SOME); + + return GTK_FILTER_GET_CLASS (self)->get_strictness (self); +} + +/** + * gtk_filter_changed: + * @self: a #GtkFilter + * @change: How the filter changed + * + * Emits the #GtkFilter:changed signal to notify all users of the filter that + * the filter changed. Users of the filter should then check items again via + * gtk_filter_match(). + * + * Depending on the @change parameter, not all items need to be changed, but + * only some. Refer to the #GtkFilterChange documentation for details. + * + * This function is intended for implementors of #GtkFilter subclasses and + * should not be called from other functions. + */ +void +gtk_filter_changed (GtkFilter *self, + GtkFilterChange change) +{ + g_return_if_fail (GTK_IS_FILTER (self)); + + g_signal_emit (self, signals[CHANGED], 0, change); +} + diff --git a/gtk/gtkfilter.h b/gtk/gtkfilter.h new file mode 100644 index 0000000000..fcd1c7b02c --- /dev/null +++ b/gtk/gtkfilter.h @@ -0,0 +1,121 @@ +/* + * Copyright © 2019 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: Benjamin Otte <otte@gnome.org> + */ + +#ifndef __GTK_FILTER_H__ +#define __GTK_FILTER_H__ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only <gtk/gtk.h> can be included directly." +#endif + +#include <gdk/gdk.h> + +G_BEGIN_DECLS + +/** + * GtkFilterMatch: + * @GTK_FILTER_MATCH_SOME: The filter matches some items, + * gtk_filter_match() may return %TRUE or %FALSE + * @GTK_FILTER_MATCH_NONE: The filter does not match any item, + * gtk_filter_match() will always return %FALSE. + * @GTK_FILTER_MATCH_ALL: The filter matches all items, + * gtk_filter_match() will alays return %TRUE. + * + * Describes the known strictness of a filter. + * + * Note that for filters where the strictness is not known, + * %@GTK_FILTER_MATCH_SOME is always an acceptable value, + * even if a filter does match all or no items. + */ +typedef enum { + GTK_FILTER_MATCH_SOME = 0, + GTK_FILTER_MATCH_NONE, + GTK_FILTER_MATCH_ALL +} GtkFilterMatch; + +/** + * GtkFilterChange: + * @GTK_FILTER_CHANGE_DIFFERENT: The filter change cannot be + * described with any of the other enumeration values. + * @GTK_FILTER_CHANGE_LESS_STRICT: The filter is less strict than + * it was before: All items that it used to return %TRUE for + * still return %TRUE, others now may, too. + * @GTK_FILTER_CHANGE_MORE_STRICT: The filter is more strict than + * it was before: All items that it used to return %FALSE for + * still return %FALSE, others now may, too. + * + * Describes changes in a filter in more detail and allows objects + * using the filter to optimize refiltering items. + * + * If you are writing an implementation and are not sure which + * value to pass, @GTK_FILTER_CHANGE_DIFFERENT is always a correct + * choice. + */ +typedef enum { + GTK_FILTER_CHANGE_DIFFERENT = 0, + GTK_FILTER_CHANGE_LESS_STRICT, + GTK_FILTER_CHANGE_MORE_STRICT, +} GtkFilterChange; + +#define GTK_TYPE_FILTER (gtk_filter_get_type ()) + +/** + * GtkFilter: + * + * The object describing a filter. + */ +GDK_AVAILABLE_IN_ALL +G_DECLARE_DERIVABLE_TYPE (GtkFilter, gtk_filter, GTK, FILTER, GObject) + +struct _GtkFilterClass +{ + GObjectClass parent_class; + + gboolean (* match) (GtkFilter *self, + gpointer item); + + /* optional */ + GtkFilterMatch (* get_strictness) (GtkFilter *self); + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); + void (*_gtk_reserved5) (void); + void (*_gtk_reserved6) (void); + void (*_gtk_reserved7) (void); + void (*_gtk_reserved8) (void); +}; + +GDK_AVAILABLE_IN_ALL +gboolean gtk_filter_match (GtkFilter *self, + gpointer item); +GDK_AVAILABLE_IN_ALL +GtkFilterMatch gtk_filter_get_strictness (GtkFilter *self); + +/* for filter implementations */ +GDK_AVAILABLE_IN_ALL +void gtk_filter_changed (GtkFilter *self, + GtkFilterChange change); + + +G_END_DECLS + +#endif /* __GTK_FILTER_H__ */ diff --git a/gtk/meson.build b/gtk/meson.build index 260e3ebd1b..91fb469abc 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -227,6 +227,7 @@ gtk_public_sources = files([ 'gtkfilechoosernative.c', 'gtkfilechooserwidget.c', 'gtkfilefilter.c', + 'gtkfilter.c', 'gtkfilterlistmodel.c', 'gtkfixed.c', 'gtkfixedlayout.c', @@ -482,6 +483,7 @@ gtk_public_headers = files([ 'gtkfilechoosernative.h', 'gtkfilechooserwidget.h', 'gtkfilefilter.h', + 'gtkfilter.h', 'gtkfilterlistmodel.h', 'gtkfixed.h', 'gtkfixedlayout.h', |