Merge branch 'wip/otte/boolfilter' into 'master'

Add GtkBoolFilter

See merge request GNOME/gtk!2288
This commit is contained in:
Benjamin Otte 2020-07-26 19:24:25 +00:00
commit ea0fc7619d
7 changed files with 411 additions and 1 deletions

View File

@ -55,6 +55,7 @@
<xi:include href="xml/gtkfilter.xml" /> <xi:include href="xml/gtkfilter.xml" />
<xi:include href="xml/gtkcustomfilter.xml" /> <xi:include href="xml/gtkcustomfilter.xml" />
<xi:include href="xml/gtkmultifilter.xml" /> <xi:include href="xml/gtkmultifilter.xml" />
<xi:include href="xml/gtkboolfilter.xml" />
<xi:include href="xml/gtkstringfilter.xml" /> <xi:include href="xml/gtkstringfilter.xml" />
<xi:include href="xml/gtkfilefilter.xml" /> <xi:include href="xml/gtkfilefilter.xml" />
</section> </section>

View File

@ -7571,6 +7571,19 @@ GTK_TYPE_EXPRESSION
gtk_expression_get_type gtk_expression_get_type
</SECTION> </SECTION>
<SECTION>
<FILE>gtkboolfilter</FILE>
GtkBoolFilter
gtk_bool_filter_new
gtk_bool_filter_get_expression
gtk_bool_filter_set_expression
gtk_bool_filter_get_invert
gtk_bool_filter_set_invert
<SUBSECTION Private>
gtk_bool_filter_get_type
</SECTION>
<SECTION> <SECTION>
<FILE>gtkstringfilter</FILE> <FILE>gtkstringfilter</FILE>
GtkStringFilter GtkStringFilter

View File

@ -49,6 +49,7 @@
#include <gtk/gtkbinlayout.h> #include <gtk/gtkbinlayout.h>
#include <gtk/gtkbitset.h> #include <gtk/gtkbitset.h>
#include <gtk/gtkbookmarklist.h> #include <gtk/gtkbookmarklist.h>
#include <gtk/gtkboolfilter.h>
#include <gtk/gtkborder.h> #include <gtk/gtkborder.h>
#include <gtk/gtkboxlayout.h> #include <gtk/gtkboxlayout.h>
#include <gtk/gtkbox.h> #include <gtk/gtkbox.h>

295
gtk/gtkboolfilter.c Normal file
View File

@ -0,0 +1,295 @@
/*
* Copyright © 2020 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 "gtkboolfilter.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
/**
* SECTION:gtkboolfilter
* @Title: GtkBoolFilter
* @Short_description: Filtering by boolean expressions
*
* GtkBoolFilter is a simple filter that takes a boolean #GtkExpression
* to determine whether to include items.
*/
struct _GtkBoolFilter
{
GtkFilter parent_instance;
gboolean invert;
GtkExpression *expression;
};
enum {
PROP_0,
PROP_EXPRESSION,
PROP_INVERT,
NUM_PROPERTIES
};
G_DEFINE_TYPE (GtkBoolFilter, gtk_bool_filter, GTK_TYPE_FILTER)
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
static gboolean
gtk_bool_filter_match (GtkFilter *filter,
gpointer item)
{
GtkBoolFilter *self = GTK_BOOL_FILTER (filter);
GValue value = G_VALUE_INIT;
gboolean result;
if (self->expression == NULL ||
!gtk_expression_evaluate (self->expression, item, &value))
return FALSE;
result = g_value_get_boolean (&value);
g_value_unset (&value);
if (self->invert)
result = !result;
return result;
}
static GtkFilterMatch
gtk_bool_filter_get_strictness (GtkFilter *filter)
{
GtkBoolFilter *self = GTK_BOOL_FILTER (filter);
if (self->expression == NULL)
return GTK_FILTER_MATCH_NONE;
return GTK_FILTER_MATCH_SOME;
}
static void
gtk_bool_filter_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkBoolFilter *self = GTK_BOOL_FILTER (object);
switch (prop_id)
{
case PROP_EXPRESSION:
gtk_bool_filter_set_expression (self, gtk_value_get_expression (value));
break;
case PROP_INVERT:
gtk_bool_filter_set_invert (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_bool_filter_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkBoolFilter *self = GTK_BOOL_FILTER (object);
switch (prop_id)
{
case PROP_EXPRESSION:
gtk_value_set_expression (value, self->expression);
break;
case PROP_INVERT:
g_value_set_boolean (value, self->invert);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_bool_filter_dispose (GObject *object)
{
GtkBoolFilter *self = GTK_BOOL_FILTER (object);
g_clear_pointer (&self->expression, gtk_expression_unref);
G_OBJECT_CLASS (gtk_bool_filter_parent_class)->dispose (object);
}
static void
gtk_bool_filter_class_init (GtkBoolFilterClass *class)
{
GtkFilterClass *filter_class = GTK_FILTER_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
filter_class->match = gtk_bool_filter_match;
filter_class->get_strictness = gtk_bool_filter_get_strictness;
object_class->get_property = gtk_bool_filter_get_property;
object_class->set_property = gtk_bool_filter_set_property;
object_class->dispose = gtk_bool_filter_dispose;
/**
* GtkBoolFilter:expression: (type GtkExpression)
*
* The boolean expression to evalute on item
*/
properties[PROP_EXPRESSION] =
gtk_param_spec_expression ("expression",
P_("Expression"),
P_("Expression to evaluate"),
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkBoolFilter:invert:
*
* If the expression result should be inverted
*/
properties[PROP_INVERT] =
g_param_spec_boolean ("invert",
P_("Invert"),
P_("If the expression result should be inverted"),
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
}
static void
gtk_bool_filter_init (GtkBoolFilter *self)
{
}
/**
* gtk_bool_filter_new:
* @expression: (transfer full) (nullable): The expression to evaluate
* or %NULL for none
*
* Creates a new bool filter.
*
* Returns: a new #GtkBoolFilter
**/
GtkFilter *
gtk_bool_filter_new (GtkExpression *expression)
{
GtkFilter *result;
result = g_object_new (GTK_TYPE_BOOL_FILTER,
"expression", expression,
NULL);
g_clear_pointer (&expression, gtk_expression_unref);
return result;
}
/**
* gtk_bool_filter_get_expression:
* @self: a #GtkBoolFilter
*
* Gets the expression that the filter uses to evaluate if
* an item should be filtered.
*
* Returns: (transfer none): a #GtkExpression
*/
GtkExpression *
gtk_bool_filter_get_expression (GtkBoolFilter *self)
{
g_return_val_if_fail (GTK_IS_BOOL_FILTER (self), NULL);
return self->expression;
}
/**
* gtk_bool_filter_set_expression:
* @self: a #GtkBoolFilter
* @expression: a #GtkExpression
*
* Sets the expression that the filter uses to
* check if items should be filtered. The expression must have
* a value type of #G_TYPE_BOOLEAN.
*/
void
gtk_bool_filter_set_expression (GtkBoolFilter *self,
GtkExpression *expression)
{
g_return_if_fail (GTK_IS_BOOL_FILTER (self));
g_return_if_fail (expression == NULL || gtk_expression_get_value_type (expression) == G_TYPE_BOOLEAN);
if (self->expression == expression)
return;
g_clear_pointer (&self->expression, gtk_expression_unref);
if (expression)
self->expression = gtk_expression_ref (expression);
gtk_filter_changed (GTK_FILTER (self), GTK_FILTER_CHANGE_DIFFERENT);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EXPRESSION]);
}
/**
* gtk_bool_filter_get_invert:
* @self: a #GtkBoolFilter
*
* Returns whether the filter inverts the expression.
*
* Returns: %TRUE if the filter inverts
*/
gboolean
gtk_bool_filter_get_invert (GtkBoolFilter *self)
{
g_return_val_if_fail (GTK_IS_BOOL_FILTER (self), TRUE);
return self->invert;
}
/**
* gtk_bool_filter_set_invert:
* @self: a #GtkBoolFilter
* @invert: %TRUE to invert
*
* Sets whether the filter should invert the expression.
*/
void
gtk_bool_filter_set_invert (GtkBoolFilter *self,
gboolean invert)
{
g_return_if_fail (GTK_IS_BOOL_FILTER (self));
if (self->invert == invert)
return;
self->invert = invert;
gtk_filter_changed (GTK_FILTER (self), GTK_FILTER_CHANGE_DIFFERENT);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INVERT]);
}

53
gtk/gtkboolfilter.h Normal file
View File

@ -0,0 +1,53 @@
/*
* Copyright © 2020 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_BOOL_FILTER_H__
#define __GTK_BOOL_FILTER_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkexpression.h>
#include <gtk/gtkfilter.h>
G_BEGIN_DECLS
#define GTK_TYPE_BOOL_FILTER (gtk_bool_filter_get_type ())
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkBoolFilter, gtk_bool_filter, GTK, BOOL_FILTER, GtkFilter)
GDK_AVAILABLE_IN_ALL
GtkFilter * gtk_bool_filter_new (GtkExpression *expression);
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_bool_filter_get_expression (GtkBoolFilter *self);
GDK_AVAILABLE_IN_ALL
void gtk_bool_filter_set_expression (GtkBoolFilter *self,
GtkExpression *expression);
GDK_AVAILABLE_IN_ALL
gboolean gtk_bool_filter_get_invert (GtkBoolFilter *self);
GDK_AVAILABLE_IN_ALL
void gtk_bool_filter_set_invert (GtkBoolFilter *self,
gboolean invert);
G_END_DECLS
#endif /* __GTK_BOOL_FILTER_H__ */

View File

@ -27,6 +27,7 @@ gtk_private_sources = files([
'gtkbookmarksmanager.c', 'gtkbookmarksmanager.c',
'gtkbuilder-menus.c', 'gtkbuilder-menus.c',
'gtkbuilderprecompile.c', 'gtkbuilderprecompile.c',
'gtkbuiltinicon.c',
'gtkcellareaboxcontext.c', 'gtkcellareaboxcontext.c',
'gtkcoloreditor.c', 'gtkcoloreditor.c',
'gtkcolorplane.c', 'gtkcolorplane.c',
@ -108,7 +109,6 @@ gtk_private_sources = files([
'gtkgizmo.c', 'gtkgizmo.c',
'gtkgladecatalog.c', 'gtkgladecatalog.c',
'gtkhsla.c', 'gtkhsla.c',
'gtkbuiltinicon.c',
'gtkiconcache.c', 'gtkiconcache.c',
'tools/gtkiconcachevalidator.c', 'tools/gtkiconcachevalidator.c',
'gtkiconhelper.c', 'gtkiconhelper.c',
@ -164,6 +164,7 @@ gtk_public_sources = files([
'gtkassistant.c', 'gtkassistant.c',
'gtkbinlayout.c', 'gtkbinlayout.c',
'gtkbitset.c', 'gtkbitset.c',
'gtkboolfilter.c',
'gtkbookmarklist.c', 'gtkbookmarklist.c',
'gtkborder.c', 'gtkborder.c',
'gtkboxlayout.c', 'gtkboxlayout.c',
@ -452,6 +453,7 @@ gtk_public_headers = files([
'gtkbinlayout.h', 'gtkbinlayout.h',
'gtkbitset.h', 'gtkbitset.h',
'gtkbookmarklist.h', 'gtkbookmarklist.h',
'gtkboolfilter.h',
'gtkborder.h', 'gtkborder.h',
'gtkbox.h', 'gtkbox.h',
'gtkboxlayout.h', 'gtkboxlayout.h',

View File

@ -309,6 +309,50 @@ test_string_properties (void)
g_object_unref (filter); g_object_unref (filter);
} }
static void
test_bool_simple (void)
{
GtkFilterListModel *model;
GtkExpression *expr;
GtkFilter *filter;
filter = gtk_bool_filter_new (
gtk_cclosure_expression_new (G_TYPE_BOOLEAN,
NULL,
0, NULL,
G_CALLBACK (divisible_by),
GUINT_TO_POINTER (3), NULL));
model = new_model (20, filter);
assert_model (model, "3 6 9 12 15 18");
gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), TRUE);
assert_model (model, "1 2 4 5 7 8 10 11 13 14 16 17 19 20");
gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), FALSE);
assert_model (model, "3 6 9 12 15 18");
expr = gtk_cclosure_expression_new (G_TYPE_BOOLEAN,
NULL,
0, NULL,
G_CALLBACK (divisible_by),
GUINT_TO_POINTER (5), NULL);
gtk_bool_filter_set_expression (GTK_BOOL_FILTER (filter), expr);
gtk_expression_unref (expr);
assert_model (model, "5 10 15 20");
gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), TRUE);
assert_model (model, "1 2 3 4 6 7 8 9 11 12 13 14 16 17 18 19");
gtk_bool_filter_set_expression (GTK_BOOL_FILTER (filter), NULL);
assert_model (model, "");
gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), FALSE);
assert_model (model, "");
g_object_unref (filter);
g_object_unref (model);
}
static void static void
test_every_dispose (void) test_every_dispose (void)
{ {
@ -343,6 +387,7 @@ main (int argc, char *argv[])
g_test_add_func ("/filter/any/simple", test_any_simple); g_test_add_func ("/filter/any/simple", test_any_simple);
g_test_add_func ("/filter/string/simple", test_string_simple); g_test_add_func ("/filter/string/simple", test_string_simple);
g_test_add_func ("/filter/string/properties", test_string_properties); g_test_add_func ("/filter/string/properties", test_string_properties);
g_test_add_func ("/filter/bool/simple", test_bool_simple);
g_test_add_func ("/filter/every/dispose", test_every_dispose); g_test_add_func ("/filter/every/dispose", test_every_dispose);
return g_test_run (); return g_test_run ();