summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2019-11-09 02:55:48 +0100
committerMatthias Clasen <mclasen@redhat.com>2020-05-30 12:30:23 -0400
commit1df17f2feaf37bc4f0aa1f18d26f2deba91f7dd7 (patch)
tree53576ed061f9d8d3c4a8ec6a5ec6fda7f278a31a
parent682e97826c99e56c79aca8b5d54e171a18f63546 (diff)
downloadgtk+-1df17f2feaf37bc4f0aa1f18d26f2deba91f7dd7.tar.gz
Add GtkFilter
-rw-r--r--docs/reference/gtk/gtk4-docs.xml3
-rw-r--r--docs/reference/gtk/gtk4-sections.txt20
-rw-r--r--docs/reference/gtk/gtk4.types.in1
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkfilter.c181
-rw-r--r--gtk/gtkfilter.h121
-rw-r--r--gtk/meson.build2
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
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 3a6312d35d..6953d0d3e5 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -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',