Add GtkFilter

This commit is contained in:
Benjamin Otte
2019-11-09 02:55:48 +01:00
parent 94cb76788d
commit 8bf8bdb8ef
6 changed files with 331 additions and 0 deletions

View File

@@ -44,6 +44,7 @@
<chapter id="Lists">
<title>GListModel support</title>
<xi:include href="xml/gtkfilter.xml" />
<xi:include href="xml/gtkfilterlistmodel.xml" />
<xi:include href="xml/gtkflattenlistmodel.xml" />
<xi:include href="xml/gtkmaplistmodel.xml" />

View File

@@ -1369,6 +1369,25 @@ GTK_DIRECTORY_LIST_GET_CLASS
gtk_directory_list_get_type
</SECTION>
<SECTION>
<FILE>gtkfilter</FILE>
<TITLE>GtkFilter</TITLE>
GtkFilter
gtk_filter_match
gtk_filter_get_strictness
<SUBSECTION>
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>

View File

@@ -115,6 +115,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>

179
gtk/gtkfilter.c Normal file
View File

@@ -0,0 +1,179 @@
/*
* 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
* @Short_description: Filtering items in GTK
* @Title: GtkFilter
* @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().
*
* Depending on the @change variable, not all items need to be changed, but
* only some. Refer to the #GtkFilterChange documentation for details on that.
*/
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 variable, not all items need to be changed, but
* only some. Refer to the #GtkFilterChange documentation for details on that.
*
* 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);
}

129
gtk/gtkfilter.h Normal file
View File

@@ -0,0 +1,129 @@
/*
* 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_MATCH_ALL: The filter now matches every
* item: gtk_filter_get_strictness() will now return
* %GTK_FILTER_MATCH_ALL
* @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.
* @GTK_FILTER_CHANGE_MATCH_NONE: The filter now matches no item:
* gtk_filter_get_strictness() will now return
* %GTK_FILTER_MATCH_NONE
*
* 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_MATCH_ALL,
GTK_FILTER_CHANGE_LESS_STRICT,
GTK_FILTER_CHANGE_MORE_STRICT,
GTK_FILTER_CHANGE_MATCH_NONE
} 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 *filter,
gpointer item);
GDK_AVAILABLE_IN_ALL
GtkFilterMatch gtk_filter_get_strictness (GtkFilter *filter);
/* for filter implementations */
GDK_AVAILABLE_IN_ALL
void gtk_filter_changed (GtkFilter *filter,
GtkFilterChange change);
G_END_DECLS
#endif /* __GTK_FILTER_H__ */

View File

@@ -237,6 +237,7 @@ gtk_public_sources = files([
'gtkfilechoosernative.c',
'gtkfilechooserwidget.c',
'gtkfilefilter.c',
'gtkfilter.c',
'gtkfilterlistmodel.c',
'gtkfixed.c',
'gtkfixedlayout.c',
@@ -504,6 +505,7 @@ gtk_public_headers = files([
'gtkfilechoosernative.h',
'gtkfilechooserwidget.h',
'gtkfilefilter.h',
'gtkfilter.h',
'gtkfilterlistmodel.h',
'gtkfixed.h',
'gtkfixedlayout.h',