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 | |
50 | enum { |
51 | CHANGED, |
52 | LAST_SIGNAL |
53 | }; |
54 | |
55 | G_DEFINE_TYPE (GtkFilter, gtk_filter, G_TYPE_OBJECT) |
56 | |
57 | static guint signals[LAST_SIGNAL] = { 0 }; |
58 | |
59 | static gboolean |
60 | gtk_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 | |
68 | static GtkFilterMatch |
69 | gtk_filter_default_get_strictness (GtkFilter *self) |
70 | { |
71 | return GTK_FILTER_MATCH_SOME; |
72 | } |
73 | |
74 | static void |
75 | gtk_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 | |
112 | static void |
113 | gtk_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 | */ |
127 | gboolean |
128 | gtk_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 | */ |
153 | GtkFilterMatch |
154 | gtk_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 | */ |
179 | void |
180 | gtk_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 | |