1/*
2 * Copyright © 2019 Benjamin Otte
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Benjamin Otte <otte@gnome.org>
18 */
19
20#include "config.h"
21
22#include "gtkfilter.h"
23
24#include "gtkintl.h"
25#include "gtktypebuiltins.h"
26
27/**
28 * GtkFilter:
29 *
30 * A `GtkFilter` object describes the filtering to be performed by a
31 * [class@Gtk.FilterListModel].
32 *
33 * The model will use the filter to determine if it should include items
34 * or not by calling [method@Gtk.Filter.match] for each item and only
35 * keeping the ones that the function returns %TRUE for.
36 *
37 * Filters may change what items they match through their lifetime. In that
38 * case, they will emit the [signal@Gtk.Filter::changed] signal to notify
39 * that previous filter results are no longer valid and that items should
40 * be checked again via [method@Gtk.Filter.match].
41 *
42 * GTK provides various pre-made filter implementations for common filtering
43 * operations. These filters often include properties that can be linked to
44 * various widgets to easily allow searches.
45 *
46 * However, in particular for large lists or complex search methods, it is
47 * also possible to subclass `GtkFilter` and provide one's own filter.
48 */
49
50enum {
51 CHANGED,
52 LAST_SIGNAL
53};
54
55G_DEFINE_TYPE (GtkFilter, gtk_filter, G_TYPE_OBJECT)
56
57static guint signals[LAST_SIGNAL] = { 0 };
58
59static gboolean
60gtk_filter_default_match (GtkFilter *self,
61 gpointer item)
62{
63 g_critical ("Filter of type '%s' does not implement GtkFilter::match", G_OBJECT_TYPE_NAME (self));
64
65 return FALSE;
66}
67
68static GtkFilterMatch
69gtk_filter_default_get_strictness (GtkFilter *self)
70{
71 return GTK_FILTER_MATCH_SOME;
72}
73
74static void
75gtk_filter_class_init (GtkFilterClass *class)
76{
77 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
78
79 class->match = gtk_filter_default_match;
80 class->get_strictness = gtk_filter_default_get_strictness;
81
82 /**
83 * GtkFilter::changed:
84 * @self: The `GtkFilter`
85 * @change: how the filter changed
86 *
87 * Emitted whenever the filter changed.
88 *
89 * Users of the filter should then check items again via
90 * [method@Gtk.Filter.match].
91 *
92 * `GtkFilterListModel` handles this signal automatically.
93 *
94 * Depending on the @change parameter, not all items need
95 * to be checked, but only some. Refer to the [enum@Gtk.FilterChange]
96 * documentation for details.
97 */
98 signals[CHANGED] =
99 g_signal_new (I_("changed"),
100 G_TYPE_FROM_CLASS (gobject_class),
101 signal_flags: G_SIGNAL_RUN_LAST,
102 class_offset: 0,
103 NULL, NULL,
104 c_marshaller: g_cclosure_marshal_VOID__ENUM,
105 G_TYPE_NONE, n_params: 1,
106 GTK_TYPE_FILTER_CHANGE);
107 g_signal_set_va_marshaller (signal_id: signals[CHANGED],
108 G_TYPE_FROM_CLASS (gobject_class),
109 va_marshaller: g_cclosure_marshal_VOID__ENUMv);
110}
111
112static void
113gtk_filter_init (GtkFilter *self)
114{
115}
116
117/**
118 * gtk_filter_match:
119 * @self: a `GtkFilter`
120 * @item: (type GObject) (transfer none): The item to check
121 *
122 * Checks if the given @item is matched by the filter or not.
123 *
124 * Returns: %TRUE if the filter matches the item and a filter model should
125 * keep it, %FALSE if not.
126 */
127gboolean
128gtk_filter_match (GtkFilter *self,
129 gpointer item)
130{
131 g_return_val_if_fail (GTK_IS_FILTER (self), FALSE);
132 g_return_val_if_fail (item != NULL, FALSE);
133
134 return GTK_FILTER_GET_CLASS (ptr: self)->match (self, item);
135}
136
137/**
138 * gtk_filter_get_strictness:
139 * @self: a `GtkFilter`
140 *
141 * Gets the known strictness of @filters.
142 *
143 * If the strictness is not known, %GTK_FILTER_MATCH_SOME is returned.
144 *
145 * This value may change after emission of the [signal@Gtk.Filter::changed]
146 * signal.
147 *
148 * This function is meant purely for optimization purposes, filters can
149 * choose to omit implementing it, but `GtkFilterListModel` uses it.
150 *
151 * Returns: the strictness of @self
152 */
153GtkFilterMatch
154gtk_filter_get_strictness (GtkFilter *self)
155{
156 g_return_val_if_fail (GTK_IS_FILTER (self), GTK_FILTER_MATCH_SOME);
157
158 return GTK_FILTER_GET_CLASS (ptr: self)->get_strictness (self);
159}
160
161/**
162 * gtk_filter_changed:
163 * @self: a `GtkFilter`
164 * @change: How the filter changed
165 *
166 * Notifies all users of the filter that it has changed.
167 *
168 * This emits the [signal@Gtk.Filter::changed] signal. Users
169 * of the filter should then check items again via
170 * [method@Gtk.Filter.match].
171 *
172 * Depending on the @change parameter, not all items need to
173 * be changed, but only some. Refer to the [enum@Gtk.FilterChange]
174 * documentation for details.
175 *
176 * This function is intended for implementors of `GtkFilter`
177 * subclasses and should not be called from other functions.
178 */
179void
180gtk_filter_changed (GtkFilter *self,
181 GtkFilterChange change)
182{
183 g_return_if_fail (GTK_IS_FILTER (self));
184
185 g_signal_emit (instance: self, signal_id: signals[CHANGED], detail: 0, change);
186}
187
188

source code of gtk/gtk/gtkfilter.c