Compare commits
9 Commits
slice-list
...
builder-de
Author | SHA1 | Date | |
---|---|---|---|
|
78c0b1da9f | ||
|
e2dfd6296d | ||
|
0ee8c43f8f | ||
|
db55f2e16d | ||
|
2f3d2128ea | ||
|
0054bb6936 | ||
|
d10c862acd | ||
|
0640d95a11 | ||
|
542533a2a5 |
@@ -1,207 +0,0 @@
|
||||
<!-- ##### SECTION Title ##### -->
|
||||
GtkRecentFilter
|
||||
|
||||
<!-- ##### SECTION Short_Description ##### -->
|
||||
A filter for selecting a subset of recently used files
|
||||
|
||||
<!-- ##### SECTION Long_Description ##### -->
|
||||
<para>
|
||||
A #GtkRecentFilter can be used to restrict the files being shown
|
||||
in a #GtkRecentChooser. Files can be filtered based on their name
|
||||
(with gtk_recent_filter_add_pattern()), on their mime type (with
|
||||
gtk_file_filter_add_mime_type()), on the application that has
|
||||
registered them (with gtk_recent_filter_add_application()), or by
|
||||
a custom filter function (with gtk_recent_filter_add_custom()).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Filtering by mime type handles aliasing and subclassing of mime
|
||||
types; e.g. a filter for text/plain also matches a file with mime
|
||||
type application/rtf, since application/rtf is a subclass of text/plain.
|
||||
Note that #GtkRecentFilter allows wildcards for the subtype of a
|
||||
mime type, so you can e.g. filter for image/*.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Normally, filters are used by adding them to a #GtkRecentChooser,
|
||||
see gtk_recent_chooser_add_filter(), but it is also possible to
|
||||
manually use a filter on a file with gtk_recent_filter_filter().
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Recently used files are supported since GTK+ 2.10.
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION See_Also ##### -->
|
||||
<para>
|
||||
#GtkRecentChooser
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION Stability_Level ##### -->
|
||||
|
||||
|
||||
<!-- ##### SECTION Image ##### -->
|
||||
|
||||
|
||||
<!-- ##### STRUCT GtkRecentFilter ##### -->
|
||||
<para>
|
||||
The <structname>GtkRecentFilter</structname> struct contains
|
||||
only private fields and should not be directly accessed.
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### STRUCT GtkRecentFilterInfo ##### -->
|
||||
<para>
|
||||
A <structname>GtkRecentFilterInfo</structname> struct is used
|
||||
to pass information about the tested file to gtk_recent_filter_filter().
|
||||
</para>
|
||||
|
||||
@contains: Flags indicating which of the following fields need
|
||||
are filled
|
||||
@uri: the URI of the file being tested
|
||||
@display_name: the string that will be used to display the file
|
||||
in the recent chooser
|
||||
@mime_type: the mime type of the file
|
||||
@applications: the list of applications that have registered the file
|
||||
@groups: the groups to which the file belongs to
|
||||
@age: the number of days elapsed since the file has been registered
|
||||
|
||||
<!-- ##### ENUM GtkRecentFilterFlags ##### -->
|
||||
<para>
|
||||
These flags indicate what parts of a #GtkRecentFilterInfo struct
|
||||
are filled or need to be filled.
|
||||
</para>
|
||||
|
||||
@GTK_RECENT_FILTER_URI: the URI of the file being tested
|
||||
@GTK_RECENT_FILTER_DISPLAY_NAME: the string that will be used to
|
||||
display the file in the recent chooser
|
||||
@GTK_RECENT_FILTER_MIME_TYPE: the mime type of the file
|
||||
@GTK_RECENT_FILTER_APPLICATION: the list of applications that have
|
||||
registered the file
|
||||
@GTK_RECENT_FILTER_GROUP: the groups to which the file belongs to
|
||||
@GTK_RECENT_FILTER_AGE: the number of days elapsed since the file
|
||||
has been registered
|
||||
|
||||
<!-- ##### USER_FUNCTION GtkRecentFilterFunc ##### -->
|
||||
<para>
|
||||
The type of function that is used with custom filters,
|
||||
see gtk_recent_filter_add_custom().
|
||||
</para>
|
||||
|
||||
@filter_info: a #GtkRecentFilterInfo that is filled according
|
||||
to the @needed flags passed to gtk_recent_filter_add_custom()
|
||||
@user_data: user data passed to gtk_recent_filter_add_custom()
|
||||
@Returns: %TRUE if the file should be displayed
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@void:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_get_name ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_set_name ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@name:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_add_mime_type ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@mime_type:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_add_pattern ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@pattern:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_add_pixbuf_formats ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_add_application ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@application:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_add_group ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@group:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_add_age ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@days:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_add_custom ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@needed:
|
||||
@func:
|
||||
@data:
|
||||
@data_destroy:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_get_needed ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gtk_recent_filter_filter ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filter:
|
||||
@filter_info:
|
||||
@Returns:
|
||||
|
||||
|
@@ -232,7 +232,11 @@
|
||||
* <link linkend="GtkActionGroup-BUILDER-UI">GtkActionGroup</link>.
|
||||
* <link linkend="GtkMenuItem-BUILDER-UI">GtkMenuItem</link>,
|
||||
* <link linkend="GtkAssistant-BUILDER-UI">GtkAssistant</link>,
|
||||
* <link linkend="GtkScale-BUILDER-UI">GtkScale</link>.
|
||||
* <link linkend="GtkScale-BUILDER-UI">GtkScale</link>,
|
||||
* <link linkend="GtkComboBoxText-BUILDER-UI">GtkComboBoxText</link>,
|
||||
* <link linkend="GtkRecentFilter-BUILDER-UI">GtkRecentFilter</link>,
|
||||
* <link linkend="GtkFileFilter-BUILDER-UI">GtkFileFilter</link>,
|
||||
* <link linkend="GtkTextTagTable-BUILDER-UI">GtkTextTagTable</link>.
|
||||
* </para>
|
||||
* </refsect2>
|
||||
*/
|
||||
|
@@ -693,6 +693,7 @@ typedef struct {
|
||||
GtkBuilder *builder;
|
||||
GtkCellLayout *cell_layout;
|
||||
GtkCellRenderer *renderer;
|
||||
GString *string;
|
||||
gchar *cell_prop_name;
|
||||
gchar *context;
|
||||
gboolean translatable;
|
||||
@@ -743,53 +744,65 @@ cell_packing_text_element (GMarkupParseContext *context,
|
||||
GError **error)
|
||||
{
|
||||
CellPackingSubParserData *parser_data = (CellPackingSubParserData*)user_data;
|
||||
|
||||
if (parser_data->cell_prop_name)
|
||||
g_string_append_len (parser_data->string, text, text_len);
|
||||
}
|
||||
|
||||
static void
|
||||
cell_packing_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
CellPackingSubParserData *parser_data = (CellPackingSubParserData*)user_data;
|
||||
GtkCellArea *area;
|
||||
gchar* value;
|
||||
|
||||
if (!parser_data->cell_prop_name)
|
||||
return;
|
||||
|
||||
if (parser_data->translatable && text_len)
|
||||
/* Append the translated strings */
|
||||
if (parser_data->string->len)
|
||||
{
|
||||
const gchar* domain;
|
||||
domain = gtk_builder_get_translation_domain (parser_data->builder);
|
||||
area = gtk_cell_layout_get_area (parser_data->cell_layout);
|
||||
|
||||
value = _gtk_builder_parser_translate (domain,
|
||||
parser_data->context,
|
||||
text);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = g_strdup (text);
|
||||
if (area)
|
||||
{
|
||||
if (parser_data->translatable)
|
||||
{
|
||||
gchar *translated;
|
||||
const gchar* domain;
|
||||
|
||||
domain = gtk_builder_get_translation_domain (parser_data->builder);
|
||||
|
||||
translated = _gtk_builder_parser_translate (domain,
|
||||
parser_data->context,
|
||||
parser_data->string->str);
|
||||
g_string_set_size (parser_data->string, 0);
|
||||
g_string_append (parser_data->string, translated);
|
||||
}
|
||||
|
||||
gtk_cell_layout_buildable_set_cell_property (area,
|
||||
parser_data->builder,
|
||||
parser_data->renderer,
|
||||
parser_data->cell_prop_name,
|
||||
parser_data->string->str);
|
||||
}
|
||||
else
|
||||
g_warning ("%s does not have an internal GtkCellArea class and cannot apply child cell properties",
|
||||
g_type_name (G_OBJECT_TYPE (parser_data->cell_layout)));
|
||||
}
|
||||
|
||||
area = gtk_cell_layout_get_area (parser_data->cell_layout);
|
||||
|
||||
if (!area)
|
||||
{
|
||||
g_warning ("%s does not have an internal GtkCellArea class and cannot apply child cell properties",
|
||||
g_type_name (G_OBJECT_TYPE (parser_data->cell_layout)));
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_cell_layout_buildable_set_cell_property (area,
|
||||
parser_data->builder,
|
||||
parser_data->renderer,
|
||||
parser_data->cell_prop_name,
|
||||
value);
|
||||
|
||||
g_string_set_size (parser_data->string, 0);
|
||||
g_free (parser_data->cell_prop_name);
|
||||
g_free (parser_data->context);
|
||||
g_free (value);
|
||||
parser_data->cell_prop_name = NULL;
|
||||
parser_data->context = NULL;
|
||||
parser_data->translatable = FALSE;
|
||||
}
|
||||
|
||||
|
||||
static const GMarkupParser cell_packing_parser =
|
||||
{
|
||||
cell_packing_start_element,
|
||||
NULL,
|
||||
cell_packing_end_element,
|
||||
cell_packing_text_element,
|
||||
};
|
||||
|
||||
@@ -821,6 +834,7 @@ _gtk_cell_layout_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
else if (strcmp (tagname, "cell-packing") == 0)
|
||||
{
|
||||
packing_data = g_slice_new0 (CellPackingSubParserData);
|
||||
packing_data->string = g_string_new ("");
|
||||
packing_data->builder = builder;
|
||||
packing_data->cell_layout = GTK_CELL_LAYOUT (buildable);
|
||||
packing_data->renderer = GTK_CELL_RENDERER (child);
|
||||
@@ -841,6 +855,7 @@ _gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
gpointer *data)
|
||||
{
|
||||
AttributesSubParserData *attr_data;
|
||||
CellPackingSubParserData *packing_data;
|
||||
|
||||
if (strcmp (tagname, "attributes") == 0)
|
||||
{
|
||||
@@ -851,7 +866,9 @@ _gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
}
|
||||
else if (strcmp (tagname, "cell-packing") == 0)
|
||||
{
|
||||
g_slice_free (CellPackingSubParserData, (gpointer)data);
|
||||
packing_data = (CellPackingSubParserData *)data;
|
||||
g_string_free (packing_data->string, TRUE);
|
||||
g_slice_free (CellPackingSubParserData, packing_data);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
@@ -151,8 +151,9 @@ typedef struct {
|
||||
GObject *object;
|
||||
const gchar *domain;
|
||||
|
||||
GString *string;
|
||||
|
||||
gchar *context;
|
||||
gchar *string;
|
||||
guint translatable : 1;
|
||||
|
||||
guint is_text : 1;
|
||||
@@ -205,29 +206,9 @@ item_text (GMarkupParseContext *context,
|
||||
GError **error)
|
||||
{
|
||||
ItemParserData *data = (ItemParserData*)user_data;
|
||||
gchar *string;
|
||||
|
||||
if (!data->is_text)
|
||||
return;
|
||||
|
||||
string = g_strndup (text, text_len);
|
||||
|
||||
if (data->translatable && text_len)
|
||||
{
|
||||
gchar *translated;
|
||||
|
||||
/* FIXME: This will not use the domain set in the .ui file,
|
||||
* since the parser is not telling the builder about the domain.
|
||||
* However, it will work for gtk_builder_set_translation_domain() calls.
|
||||
*/
|
||||
translated = _gtk_builder_parser_translate (data->domain,
|
||||
data->context,
|
||||
string);
|
||||
g_free (string);
|
||||
string = translated;
|
||||
}
|
||||
|
||||
data->string = string;
|
||||
if (data->is_text)
|
||||
g_string_append_len (data->string, text, text_len);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -239,14 +220,30 @@ item_end_element (GMarkupParseContext *context,
|
||||
ItemParserData *data = (ItemParserData*)user_data;
|
||||
|
||||
/* Append the translated strings */
|
||||
if (data->string)
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (data->object), data->string);
|
||||
if (data->string->len)
|
||||
{
|
||||
if (data->translatable)
|
||||
{
|
||||
gchar *translated;
|
||||
|
||||
/* FIXME: This will not use the domain set in the .ui file,
|
||||
* since the parser is not telling the builder about the domain.
|
||||
* However, it will work for gtk_builder_set_translation_domain() calls.
|
||||
*/
|
||||
translated = _gtk_builder_parser_translate (data->domain,
|
||||
data->context,
|
||||
data->string->str);
|
||||
g_string_set_size (data->string, 0);
|
||||
g_string_append (data->string, translated);
|
||||
}
|
||||
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (data->object), data->string->str);
|
||||
}
|
||||
|
||||
data->translatable = FALSE;
|
||||
g_string_set_size (data->string, 0);
|
||||
g_free (data->context);
|
||||
g_free (data->string);
|
||||
data->context = NULL;
|
||||
data->string = NULL;
|
||||
data->is_text = FALSE;
|
||||
}
|
||||
|
||||
@@ -277,6 +274,7 @@ gtk_combo_box_text_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
parser_data->builder = g_object_ref (builder);
|
||||
parser_data->object = g_object_ref (buildable);
|
||||
parser_data->domain = gtk_builder_get_translation_domain (builder);
|
||||
parser_data->string = g_string_new ("");
|
||||
*parser = item_parser;
|
||||
*data = parser_data;
|
||||
return TRUE;
|
||||
@@ -302,6 +300,7 @@ gtk_combo_box_text_buildable_custom_finished (GtkBuildable *buildable,
|
||||
|
||||
g_object_unref (data->object);
|
||||
g_object_unref (data->builder);
|
||||
g_string_free (data->string, TRUE);
|
||||
g_slice_free (ItemParserData, data);
|
||||
}
|
||||
}
|
||||
|
@@ -579,9 +579,10 @@ typedef struct {
|
||||
GtkBuilder *builder;
|
||||
GtkContainer *container;
|
||||
GtkWidget *child;
|
||||
GString *string;
|
||||
gchar *child_prop_name;
|
||||
gchar *context;
|
||||
gboolean translatable;
|
||||
gboolean translatable;
|
||||
} PackingPropertiesData;
|
||||
|
||||
static void
|
||||
@@ -629,34 +630,46 @@ attributes_text_element (GMarkupParseContext *context,
|
||||
GError **error)
|
||||
{
|
||||
PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data;
|
||||
gchar* value;
|
||||
|
||||
if (!parser_data->child_prop_name)
|
||||
return;
|
||||
if (parser_data->child_prop_name)
|
||||
g_string_append_len (parser_data->string, text, text_len);
|
||||
}
|
||||
|
||||
if (parser_data->translatable && text_len)
|
||||
static void
|
||||
attributes_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data;
|
||||
|
||||
/* Append the translated strings */
|
||||
if (parser_data->string->len)
|
||||
{
|
||||
const gchar* domain;
|
||||
domain = gtk_builder_get_translation_domain (parser_data->builder);
|
||||
if (parser_data->translatable)
|
||||
{
|
||||
gchar *translated;
|
||||
const gchar* domain;
|
||||
|
||||
value = _gtk_builder_parser_translate (domain,
|
||||
parser_data->context,
|
||||
text);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = g_strdup (text);
|
||||
domain = gtk_builder_get_translation_domain (parser_data->builder);
|
||||
|
||||
translated = _gtk_builder_parser_translate (domain,
|
||||
parser_data->context,
|
||||
parser_data->string->str);
|
||||
g_string_set_size (parser_data->string, 0);
|
||||
g_string_append (parser_data->string, translated);
|
||||
}
|
||||
|
||||
gtk_container_buildable_set_child_property (parser_data->container,
|
||||
parser_data->builder,
|
||||
parser_data->child,
|
||||
parser_data->child_prop_name,
|
||||
parser_data->string->str);
|
||||
}
|
||||
|
||||
gtk_container_buildable_set_child_property (parser_data->container,
|
||||
parser_data->builder,
|
||||
parser_data->child,
|
||||
parser_data->child_prop_name,
|
||||
value);
|
||||
|
||||
g_string_set_size (parser_data->string, 0);
|
||||
g_free (parser_data->child_prop_name);
|
||||
g_free (parser_data->context);
|
||||
g_free (value);
|
||||
parser_data->child_prop_name = NULL;
|
||||
parser_data->context = NULL;
|
||||
parser_data->translatable = FALSE;
|
||||
@@ -665,7 +678,7 @@ attributes_text_element (GMarkupParseContext *context,
|
||||
static const GMarkupParser attributes_parser =
|
||||
{
|
||||
attributes_start_element,
|
||||
NULL,
|
||||
attributes_end_element,
|
||||
attributes_text_element,
|
||||
};
|
||||
|
||||
@@ -686,6 +699,7 @@ gtk_container_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
if (child && strcmp (tagname, "packing") == 0)
|
||||
{
|
||||
parser_data = g_slice_new0 (PackingPropertiesData);
|
||||
parser_data->string = g_string_new ("");
|
||||
parser_data->builder = builder;
|
||||
parser_data->container = GTK_CONTAINER (buildable);
|
||||
parser_data->child = GTK_WIDGET (child);
|
||||
@@ -708,15 +722,15 @@ gtk_container_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
{
|
||||
if (strcmp (tagname, "packing") == 0)
|
||||
{
|
||||
g_slice_free (PackingPropertiesData, (gpointer)data);
|
||||
PackingPropertiesData *parser_data = (PackingPropertiesData*)data;
|
||||
g_string_free (parser_data->string, TRUE);
|
||||
g_slice_free (PackingPropertiesData, parser_data);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (parent_buildable_iface->custom_tag_end)
|
||||
parent_buildable_iface->custom_tag_end (buildable, builder,
|
||||
child, tagname, data);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -39,6 +39,33 @@
|
||||
* see gtk_file_chooser_add_filter(), but it is also possible
|
||||
* to manually use a filter on a file with gtk_file_filter_filter().
|
||||
*
|
||||
* <refsect2 id="GtkFileFilter-BUILDER-UI">
|
||||
* <title>GtkFileFilter as GtkBuildable</title>
|
||||
* <para>
|
||||
* The GtkFileFilter implementation of the GtkBuildable interface
|
||||
* supports adding rules using the <mime-types>, <patterns> and
|
||||
* <applications> elements and listing the rules within. Specifying
|
||||
* a <mime-type> or <pattern> is the same
|
||||
* as calling gtk_recent_filter_add_mime_type() or gtk_recent_filter_add_pattern()
|
||||
*
|
||||
* <example>
|
||||
* <title>A UI definition fragment specifying GtkFileFilter rules</title>
|
||||
* <programlisting><![CDATA[
|
||||
* <object class="GtkFileFilter">
|
||||
* <mime-types>
|
||||
* <mime-type>text/plain</mime-type>
|
||||
* <mime-type>image/*</mime-type>
|
||||
* </mime-types>
|
||||
* <patterns>
|
||||
* <pattern>*.txt</pattern>
|
||||
* <pattern>*.png</pattern>
|
||||
* </patterns>
|
||||
* </object>
|
||||
* ]]></programlisting>
|
||||
* </example>
|
||||
* </para>
|
||||
* </refsect2>
|
||||
*
|
||||
* @see_also: #GtkFileChooser
|
||||
*/
|
||||
|
||||
@@ -48,6 +75,7 @@
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "gtkfilefilter.h"
|
||||
#include "gtkbuildable.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
@@ -100,7 +128,22 @@ struct _FilterRule
|
||||
static void gtk_file_filter_finalize (GObject *object);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GtkFileFilter, gtk_file_filter, G_TYPE_INITIALLY_UNOWNED)
|
||||
static void gtk_file_filter_buildable_init (GtkBuildableIface *iface);
|
||||
static gboolean gtk_file_filter_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
GMarkupParser *parser,
|
||||
gpointer *data);
|
||||
static void gtk_file_filter_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
gpointer *data);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkFileFilter, gtk_file_filter, G_TYPE_INITIALLY_UNOWNED,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
||||
gtk_file_filter_buildable_init))
|
||||
|
||||
static void
|
||||
gtk_file_filter_init (GtkFileFilter *object)
|
||||
@@ -153,6 +196,155 @@ gtk_file_filter_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gtk_file_filter_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/*
|
||||
* GtkBuildable implementation
|
||||
*/
|
||||
static void
|
||||
gtk_file_filter_buildable_init (GtkBuildableIface *iface)
|
||||
{
|
||||
iface->custom_tag_start = gtk_file_filter_buildable_custom_tag_start;
|
||||
iface->custom_tag_end = gtk_file_filter_buildable_custom_tag_end;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
PARSE_MIME_TYPES,
|
||||
PARSE_PATTERNS
|
||||
} ParserType;
|
||||
|
||||
typedef struct {
|
||||
GtkFileFilter *filter;
|
||||
ParserType type;
|
||||
GString *string;
|
||||
gboolean parsing;
|
||||
} SubParserData;
|
||||
|
||||
static void
|
||||
parser_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)user_data;
|
||||
|
||||
if (strcmp (element_name, "mime-types") == 0)
|
||||
return;
|
||||
else if (strcmp (element_name, "mime-type") == 0)
|
||||
{
|
||||
parser_data->parsing = TRUE;
|
||||
return;
|
||||
}
|
||||
else if (strcmp (element_name, "patterns") == 0)
|
||||
return;
|
||||
else if (strcmp (element_name, "pattern") == 0)
|
||||
{
|
||||
parser_data->parsing = TRUE;
|
||||
return;
|
||||
}
|
||||
else
|
||||
g_warning ("Unsupported tag for GtkFileFilter: %s\n", element_name);
|
||||
}
|
||||
|
||||
static void
|
||||
parser_text_element (GMarkupParseContext *context,
|
||||
const gchar *text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)user_data;
|
||||
|
||||
if (parser_data->parsing)
|
||||
g_string_append_len (parser_data->string, text, text_len);
|
||||
}
|
||||
|
||||
static void
|
||||
parser_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)user_data;
|
||||
|
||||
if (parser_data->string)
|
||||
{
|
||||
switch (parser_data->type)
|
||||
{
|
||||
case PARSE_MIME_TYPES:
|
||||
gtk_file_filter_add_mime_type (parser_data->filter, parser_data->string->str);
|
||||
break;
|
||||
case PARSE_PATTERNS:
|
||||
gtk_file_filter_add_pattern (parser_data->filter, parser_data->string->str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_string_set_size (parser_data->string, 0);
|
||||
parser_data->parsing = FALSE;
|
||||
}
|
||||
|
||||
static const GMarkupParser sub_parser =
|
||||
{
|
||||
parser_start_element,
|
||||
parser_end_element,
|
||||
parser_text_element,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gtk_file_filter_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
GMarkupParser *parser,
|
||||
gpointer *data)
|
||||
{
|
||||
SubParserData *parser_data = NULL;
|
||||
|
||||
if (strcmp (tagname, "mime-types") == 0)
|
||||
{
|
||||
parser_data = g_slice_new0 (SubParserData);
|
||||
parser_data->string = g_string_new ("");
|
||||
parser_data->type = PARSE_MIME_TYPES;
|
||||
parser_data->filter = GTK_FILE_FILTER (buildable);
|
||||
|
||||
*parser = sub_parser;
|
||||
*data = parser_data;
|
||||
}
|
||||
else if (strcmp (tagname, "patterns") == 0)
|
||||
{
|
||||
parser_data = g_slice_new0 (SubParserData);
|
||||
parser_data->string = g_string_new ("");
|
||||
parser_data->type = PARSE_PATTERNS;
|
||||
parser_data->filter = GTK_FILE_FILTER (buildable);
|
||||
|
||||
*parser = sub_parser;
|
||||
*data = parser_data;
|
||||
}
|
||||
|
||||
return parser_data != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_filter_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
gpointer *data)
|
||||
{
|
||||
if (strcmp (tagname, "mime-types") == 0 ||
|
||||
strcmp (tagname, "patterns") == 0)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)data;
|
||||
|
||||
g_string_free (parser_data->string, TRUE);
|
||||
g_slice_free (SubParserData, parser_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gtk_file_filter_new:
|
||||
*
|
||||
|
@@ -18,15 +18,87 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gtkrecentfilter
|
||||
* @Short_Description: A filter for selecting a subset of recently used files
|
||||
* @Title: GtkRecentFilter
|
||||
*
|
||||
* A #GtkRecentFilter can be used to restrict the files being shown
|
||||
* in a #GtkRecentChooser. Files can be filtered based on their name
|
||||
* (with gtk_recent_filter_add_pattern()), on their mime type (with
|
||||
* gtk_file_filter_add_mime_type()), on the application that has
|
||||
* registered them (with gtk_recent_filter_add_application()), or by
|
||||
* a custom filter function (with gtk_recent_filter_add_custom()).
|
||||
*
|
||||
* Filtering by mime type handles aliasing and subclassing of mime
|
||||
* types; e.g. a filter for text/plain also matches a file with mime
|
||||
* type application/rtf, since application/rtf is a subclass of text/plain.
|
||||
* Note that #GtkRecentFilter allows wildcards for the subtype of a
|
||||
* mime type, so you can e.g. filter for image/*.
|
||||
*
|
||||
* Normally, filters are used by adding them to a #GtkRecentChooser,
|
||||
* see gtk_recent_chooser_add_filter(), but it is also possible to
|
||||
* manually use a filter on a file with gtk_recent_filter_filter().
|
||||
*
|
||||
* Recently used files are supported since GTK+ 2.10.
|
||||
*
|
||||
* <refsect2 id="GtkRecentFilter-BUILDER-UI">
|
||||
* <title>GtkRecentFilter as GtkBuildable</title>
|
||||
* <para>
|
||||
* The GtkRecentFilter implementation of the GtkBuildable interface
|
||||
* supports adding rules using the <mime-types>, <patterns> and
|
||||
* <applications> elements and listing the rules within. Specifying
|
||||
* a <mime-type>, <pattern> or <application> is the same
|
||||
* as calling gtk_recent_filter_add_mime_type(), gtk_recent_filter_add_pattern()
|
||||
* or gtk_recent_filter_add_application().
|
||||
*
|
||||
* <example>
|
||||
* <title>A UI definition fragment specifying GtkRecentFilter rules</title>
|
||||
* <programlisting><![CDATA[
|
||||
* <object class="GtkRecentFilter">
|
||||
* <mime-types>
|
||||
* <mime-type>text/plain</mime-type>
|
||||
* <mime-type>image/*</mime-type>
|
||||
* </mime-types>
|
||||
* <patterns>
|
||||
* <pattern>*.txt</pattern>
|
||||
* <pattern>*.png</pattern>
|
||||
* </patterns>
|
||||
* <applications>
|
||||
* <application>gimp</application>
|
||||
* <application>gedit</application>
|
||||
* <application>glade</application>
|
||||
* </applications>
|
||||
* </object>
|
||||
* ]]></programlisting>
|
||||
* </example>
|
||||
* </para>
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "gtkrecentfilter.h"
|
||||
#include "gtkbuildable.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
static void gtk_recent_filter_buildable_init (GtkBuildableIface *iface);
|
||||
static gboolean gtk_recent_filter_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
GMarkupParser *parser,
|
||||
gpointer *data);
|
||||
static void gtk_recent_filter_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
gpointer *data);
|
||||
|
||||
typedef struct _GtkRecentFilterClass GtkRecentFilterClass;
|
||||
typedef struct _FilterRule FilterRule;
|
||||
|
||||
@@ -77,7 +149,9 @@ struct _FilterRule
|
||||
} u;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkRecentFilter, gtk_recent_filter, G_TYPE_INITIALLY_UNOWNED)
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkRecentFilter, gtk_recent_filter, G_TYPE_INITIALLY_UNOWNED,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
||||
gtk_recent_filter_buildable_init))
|
||||
|
||||
|
||||
static void
|
||||
@@ -149,6 +223,178 @@ gtk_recent_filter_init (GtkRecentFilter *filter)
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GtkBuildable implementation
|
||||
*/
|
||||
static void
|
||||
gtk_recent_filter_buildable_init (GtkBuildableIface *iface)
|
||||
{
|
||||
iface->custom_tag_start = gtk_recent_filter_buildable_custom_tag_start;
|
||||
iface->custom_tag_end = gtk_recent_filter_buildable_custom_tag_end;
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
PARSE_MIME_TYPES,
|
||||
PARSE_PATTERNS,
|
||||
PARSE_APPLICATIONS
|
||||
} ParserType;
|
||||
|
||||
typedef struct {
|
||||
GtkRecentFilter *filter;
|
||||
ParserType type;
|
||||
GString *string;
|
||||
gboolean parsing;
|
||||
} SubParserData;
|
||||
|
||||
static void
|
||||
parser_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)user_data;
|
||||
|
||||
if (strcmp (element_name, "mime-types") == 0)
|
||||
return;
|
||||
else if (strcmp (element_name, "mime-type") == 0)
|
||||
{
|
||||
parser_data->parsing = TRUE;
|
||||
return;
|
||||
}
|
||||
else if (strcmp (element_name, "patterns") == 0)
|
||||
return;
|
||||
else if (strcmp (element_name, "pattern") == 0)
|
||||
{
|
||||
parser_data->parsing = TRUE;
|
||||
return;
|
||||
}
|
||||
else if (strcmp (element_name, "applications") == 0)
|
||||
return;
|
||||
else if (strcmp (element_name, "application") == 0)
|
||||
{
|
||||
parser_data->parsing = TRUE;
|
||||
return;
|
||||
}
|
||||
else
|
||||
g_warning ("Unsupported tag for GtkRecentFilter: %s\n", element_name);
|
||||
}
|
||||
|
||||
static void
|
||||
parser_text_element (GMarkupParseContext *context,
|
||||
const gchar *text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)user_data;
|
||||
|
||||
if (parser_data->parsing)
|
||||
g_string_append_len (parser_data->string, text, text_len);
|
||||
}
|
||||
|
||||
static void
|
||||
parser_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)user_data;
|
||||
|
||||
if (parser_data->string)
|
||||
{
|
||||
switch (parser_data->type)
|
||||
{
|
||||
case PARSE_MIME_TYPES:
|
||||
gtk_recent_filter_add_mime_type (parser_data->filter, parser_data->string->str);
|
||||
break;
|
||||
case PARSE_PATTERNS:
|
||||
gtk_recent_filter_add_pattern (parser_data->filter, parser_data->string->str);
|
||||
break;
|
||||
case PARSE_APPLICATIONS:
|
||||
gtk_recent_filter_add_application (parser_data->filter, parser_data->string->str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_string_set_size (parser_data->string, 0);
|
||||
parser_data->parsing = FALSE;
|
||||
}
|
||||
|
||||
static const GMarkupParser sub_parser =
|
||||
{
|
||||
parser_start_element,
|
||||
parser_end_element,
|
||||
parser_text_element,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gtk_recent_filter_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
GMarkupParser *parser,
|
||||
gpointer *data)
|
||||
{
|
||||
SubParserData *parser_data = NULL;
|
||||
|
||||
if (strcmp (tagname, "mime-types") == 0)
|
||||
{
|
||||
parser_data = g_slice_new0 (SubParserData);
|
||||
parser_data->string = g_string_new ("");
|
||||
parser_data->type = PARSE_MIME_TYPES;
|
||||
parser_data->filter = GTK_RECENT_FILTER (buildable);
|
||||
|
||||
*parser = sub_parser;
|
||||
*data = parser_data;
|
||||
}
|
||||
else if (strcmp (tagname, "patterns") == 0)
|
||||
{
|
||||
parser_data = g_slice_new0 (SubParserData);
|
||||
parser_data->string = g_string_new ("");
|
||||
parser_data->type = PARSE_PATTERNS;
|
||||
parser_data->filter = GTK_RECENT_FILTER (buildable);
|
||||
|
||||
*parser = sub_parser;
|
||||
*data = parser_data;
|
||||
}
|
||||
else if (strcmp (tagname, "applications") == 0)
|
||||
{
|
||||
parser_data = g_slice_new0 (SubParserData);
|
||||
parser_data->string = g_string_new ("");
|
||||
parser_data->type = PARSE_APPLICATIONS;
|
||||
parser_data->filter = GTK_RECENT_FILTER (buildable);
|
||||
|
||||
*parser = sub_parser;
|
||||
*data = parser_data;
|
||||
}
|
||||
|
||||
return parser_data != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_recent_filter_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *tagname,
|
||||
gpointer *data)
|
||||
{
|
||||
if (strcmp (tagname, "mime-types") == 0 ||
|
||||
strcmp (tagname, "patterns") == 0 ||
|
||||
strcmp (tagname, "applications") == 0)
|
||||
{
|
||||
SubParserData *parser_data = (SubParserData*)data;
|
||||
|
||||
g_string_free (parser_data->string, TRUE);
|
||||
g_slice_free (SubParserData, parser_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Public API
|
||||
*/
|
||||
|
@@ -36,6 +36,21 @@ G_BEGIN_DECLS
|
||||
typedef struct _GtkRecentFilter GtkRecentFilter;
|
||||
typedef struct _GtkRecentFilterInfo GtkRecentFilterInfo;
|
||||
|
||||
/**
|
||||
* GtkRecentFilterFlags:
|
||||
* @GTK_RECENT_FILTER_URI: the URI of the file being tested
|
||||
* @GTK_RECENT_FILTER_DISPLAY_NAME: the string that will be used to
|
||||
* display the file in the recent chooser
|
||||
* @GTK_RECENT_FILTER_MIME_TYPE: the mime type of the file
|
||||
* @GTK_RECENT_FILTER_APPLICATION: the list of applications that have
|
||||
* registered the file
|
||||
* @GTK_RECENT_FILTER_GROUP: the groups to which the file belongs to
|
||||
* @GTK_RECENT_FILTER_AGE: the number of days elapsed since the file
|
||||
* has been registered
|
||||
*
|
||||
* These flags indicate what parts of a #GtkRecentFilterInfo struct
|
||||
* are filled or need to be filled.
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_RECENT_FILTER_URI = 1 << 0,
|
||||
GTK_RECENT_FILTER_DISPLAY_NAME = 1 << 1,
|
||||
@@ -45,9 +60,27 @@ typedef enum {
|
||||
GTK_RECENT_FILTER_AGE = 1 << 5
|
||||
} GtkRecentFilterFlags;
|
||||
|
||||
/**
|
||||
* GtkRecentFilterFunc:
|
||||
* @filter_info: a #GtkRecentFilterInfo that is filled according
|
||||
* to the @needed flags passed to gtk_recent_filter_add_custom()
|
||||
* @user_data: user data passed to gtk_recent_filter_add_custom()
|
||||
*
|
||||
* The type of function that is used with custom filters,
|
||||
* see gtk_recent_filter_add_custom().
|
||||
*
|
||||
* Return value: %TRUE if the file should be displayed
|
||||
*/
|
||||
typedef gboolean (*GtkRecentFilterFunc) (const GtkRecentFilterInfo *filter_info,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
/**
|
||||
* GtkRecentFilterInfo:
|
||||
*
|
||||
* A GtkRecentFilterInfo struct is used
|
||||
* to pass information about the tested file to gtk_recent_filter_filter().
|
||||
*/
|
||||
struct _GtkRecentFilterInfo
|
||||
{
|
||||
GtkRecentFilterFlags contains;
|
||||
|
Reference in New Issue
Block a user