mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-14 20:51:07 +00:00
dcd549aebe
C API users can keep dealing with the implicit equivalence of GdkFileList and GSList, but language bindings have no idea that one type is another, and none of them exposes GSList as a type anyway, so they will need a way to construct a GdkFileList. Instead of making GdkFileList mutable, and re-implement GSList, we only provide a constructors pair that lets you create a GdkFileList from a linked list or from an array.
912 lines
24 KiB
C
912 lines
24 KiB
C
/* GTK - The GIMP Toolkit
|
|
* Copyright (C) 2017 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 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/>.
|
|
*/
|
|
|
|
/**
|
|
* GdkContentFormats:
|
|
*
|
|
* The `GdkContentFormats` structure is used to advertise and negotiate the
|
|
* format of content.
|
|
*
|
|
* You will encounter `GdkContentFormats` when interacting with objects
|
|
* controlling operations that pass data between different widgets, window
|
|
* or application, like [class@Gdk.Drag], [class@Gdk.Drop],
|
|
* [class@Gdk.Clipboard] or [class@Gdk.ContentProvider].
|
|
*
|
|
* GDK supports content in 2 forms: `GType` and mime type.
|
|
* Using `GTypes` is meant only for in-process content transfers. Mime types
|
|
* are meant to be used for data passing both in-process and out-of-process.
|
|
* The details of how data is passed is described in the documentation of
|
|
* the actual implementations. To transform between the two forms,
|
|
* [class@Gdk.ContentSerializer] and [class@Gdk.ContentDeserializer] are used.
|
|
*
|
|
* A `GdkContentFormats` describes a set of possible formats content can be
|
|
* exchanged in. It is assumed that this set is ordered. `GTypes` are more
|
|
* important than mime types. Order between different `GTypes` or mime types
|
|
* is the order they were added in, most important first. Functions that
|
|
* care about order, such as [method@Gdk.ContentFormats.union], will describe
|
|
* in their documentation how they interpret that order, though in general the
|
|
* order of the first argument is considered the primary order of the result,
|
|
* followed by the order of further arguments.
|
|
*
|
|
* For debugging purposes, the function [method@Gdk.ContentFormats.to_string]
|
|
* exists. It will print a comma-separated list of formats from most important
|
|
* to least important.
|
|
*
|
|
* `GdkContentFormats` is an immutable struct. After creation, you cannot change
|
|
* the types it represents. Instead, new `GdkContentFormats` have to be created.
|
|
* The [struct@Gdk.ContentFormatsBuilder] structure is meant to help in this
|
|
* endeavor.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gdkcontentformats.h"
|
|
#include "gdkcontentformatsprivate.h"
|
|
|
|
#include <string.h>
|
|
|
|
struct _GdkContentFormats
|
|
{
|
|
/*< private >*/
|
|
guint ref_count;
|
|
|
|
const char **mime_types; /* interned */
|
|
gsize n_mime_types;
|
|
GType *gtypes;
|
|
gsize n_gtypes;
|
|
};
|
|
|
|
G_DEFINE_BOXED_TYPE (GdkContentFormats, gdk_content_formats,
|
|
gdk_content_formats_ref,
|
|
gdk_content_formats_unref)
|
|
|
|
|
|
/**
|
|
* gdk_intern_mime_type:
|
|
* @string: (transfer none): string of a potential mime type
|
|
*
|
|
* Canonicalizes the given mime type and interns the result.
|
|
*
|
|
* If @string is not a valid mime type, %NULL is returned instead.
|
|
* See RFC 2048 for the syntax if mime types.
|
|
*
|
|
* Returns: (nullable): An interned string for the canonicalized
|
|
* mime type or %NULL if the string wasn't a valid mime type
|
|
*/
|
|
const char *
|
|
gdk_intern_mime_type (const char *string)
|
|
{
|
|
char *tmp;
|
|
|
|
g_return_val_if_fail (string != NULL, NULL);
|
|
|
|
if (!strchr (string, '/'))
|
|
return NULL;
|
|
|
|
tmp = g_ascii_strdown (string, -1);
|
|
|
|
string = g_intern_string (tmp);
|
|
|
|
g_free (tmp);
|
|
|
|
return string;
|
|
}
|
|
|
|
static GdkContentFormats *
|
|
gdk_content_formats_new_take (GType * gtypes,
|
|
gsize n_gtypes,
|
|
const char **mime_types,
|
|
gsize n_mime_types)
|
|
{
|
|
GdkContentFormats *result = g_slice_new0 (GdkContentFormats);
|
|
result->ref_count = 1;
|
|
|
|
result->gtypes = gtypes;
|
|
result->n_gtypes = n_gtypes;
|
|
result->mime_types = mime_types;
|
|
result->n_mime_types = n_mime_types;
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_new:
|
|
* @mime_types: (array length=n_mime_types) (nullable): Pointer to an
|
|
* array of mime types
|
|
* @n_mime_types: number of entries in @mime_types.
|
|
*
|
|
* Creates a new `GdkContentFormats` from an array of mime types.
|
|
*
|
|
* The mime types must be valid and different from each other or the
|
|
* behavior of the return value is undefined. If you cannot guarantee
|
|
* this, use [struct@Gdk.ContentFormatsBuilder] instead.
|
|
*
|
|
* Returns: (transfer full): the new `GdkContentFormats`.
|
|
*/
|
|
GdkContentFormats *
|
|
gdk_content_formats_new (const char **mime_types,
|
|
guint n_mime_types)
|
|
{
|
|
guint i;
|
|
const char **mime_types_copy;
|
|
|
|
if (n_mime_types == 0)
|
|
return gdk_content_formats_new_take (NULL, 0, NULL, 0);
|
|
|
|
mime_types_copy = g_new (const char *, n_mime_types + 1);
|
|
|
|
for (i = 0; i < n_mime_types; i++)
|
|
mime_types_copy[i] = g_intern_string (mime_types[i]);
|
|
|
|
mime_types_copy[n_mime_types] = NULL;
|
|
|
|
return gdk_content_formats_new_take (NULL, 0, mime_types_copy, n_mime_types);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_new_for_gtype:
|
|
* @type: a `GType`
|
|
*
|
|
* Creates a new `GdkContentFormats` for a given `GType`.
|
|
*
|
|
* Returns: a new `GdkContentFormats`
|
|
*/
|
|
GdkContentFormats *
|
|
gdk_content_formats_new_for_gtype (GType type)
|
|
{
|
|
GType *data;
|
|
|
|
g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
|
|
|
|
data = g_new (GType, 2);
|
|
data[0] = type;
|
|
data[1] = G_TYPE_INVALID;
|
|
|
|
return gdk_content_formats_new_take (data, 1, NULL, 0);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_parse:
|
|
* @string: the string to parse
|
|
*
|
|
* Parses the given @string into `GdkContentFormats` and
|
|
* returns the formats.
|
|
*
|
|
* Strings printed via [method@Gdk.ContentFormats.to_string]
|
|
* can be read in again successfully using this function.
|
|
*
|
|
* If @string does not describe valid content formats, %NULL
|
|
* is returned.
|
|
*
|
|
* Returns: (nullable): the content formats if @string is valid
|
|
*
|
|
* Since: 4.4
|
|
*/
|
|
GdkContentFormats *
|
|
gdk_content_formats_parse (const char *string)
|
|
{
|
|
GdkContentFormatsBuilder *builder;
|
|
char **split;
|
|
gsize i;
|
|
|
|
g_return_val_if_fail (string != NULL, NULL);
|
|
|
|
split = g_strsplit_set (string, "\t\n\f\r ", -1); /* same as g_ascii_isspace() */
|
|
builder = gdk_content_formats_builder_new ();
|
|
|
|
/* first the GTypes */
|
|
for (i = 0; split[i] != NULL; i++)
|
|
{
|
|
GType type;
|
|
|
|
if (split[i][0] == 0)
|
|
continue;
|
|
|
|
type = g_type_from_name (split[i]);
|
|
if (type != 0)
|
|
gdk_content_formats_builder_add_gtype (builder, type);
|
|
else
|
|
break;
|
|
}
|
|
|
|
/* then the mime types */
|
|
for (; split[i] != NULL; i++)
|
|
{
|
|
const char *mime_type;
|
|
|
|
if (split[i][0] == 0)
|
|
continue;
|
|
|
|
mime_type = gdk_intern_mime_type (split[i]);
|
|
if (mime_type)
|
|
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (split[i] != NULL)
|
|
{
|
|
g_strfreev (split);
|
|
gdk_content_formats_builder_unref (builder);
|
|
return NULL;
|
|
}
|
|
|
|
g_strfreev (split);
|
|
return gdk_content_formats_builder_free_to_formats (builder);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_ref:
|
|
* @formats: a `GdkContentFormats`
|
|
*
|
|
* Increases the reference count of a `GdkContentFormats` by one.
|
|
*
|
|
* Returns: the passed in `GdkContentFormats`.
|
|
*/
|
|
GdkContentFormats *
|
|
gdk_content_formats_ref (GdkContentFormats *formats)
|
|
{
|
|
g_return_val_if_fail (formats != NULL, NULL);
|
|
|
|
formats->ref_count++;
|
|
|
|
return formats;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_unref:
|
|
* @formats: a `GdkContentFormats`
|
|
*
|
|
* Decreases the reference count of a `GdkContentFormats` by one.
|
|
*
|
|
* If the resulting reference count is zero, frees the formats.
|
|
*/
|
|
void
|
|
gdk_content_formats_unref (GdkContentFormats *formats)
|
|
{
|
|
g_return_if_fail (formats != NULL);
|
|
g_return_if_fail (formats->ref_count > 0);
|
|
|
|
formats->ref_count--;
|
|
if (formats->ref_count > 0)
|
|
return;
|
|
|
|
g_free (formats->gtypes);
|
|
g_free (formats->mime_types);
|
|
g_slice_free (GdkContentFormats, formats);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_print:
|
|
* @formats: a `GdkContentFormats`
|
|
* @string: a `GString` to print into
|
|
*
|
|
* Prints the given @formats into a string for human consumption.
|
|
*
|
|
* The result of this function can later be parsed with
|
|
* [func@Gdk.ContentFormats.parse].
|
|
*/
|
|
void
|
|
gdk_content_formats_print (GdkContentFormats *formats,
|
|
GString *string)
|
|
{
|
|
gsize i;
|
|
|
|
g_return_if_fail (formats != NULL);
|
|
g_return_if_fail (string != NULL);
|
|
|
|
for (i = 0; i < formats->n_gtypes; i++)
|
|
{
|
|
if (i > 0)
|
|
g_string_append (string, " ");
|
|
g_string_append (string, g_type_name (formats->gtypes[i]));
|
|
}
|
|
for (i = 0; i < formats->n_mime_types; i++)
|
|
{
|
|
if (i > 0 || formats->n_gtypes > 0)
|
|
g_string_append (string, " ");
|
|
g_string_append (string, formats->mime_types[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_to_string:
|
|
* @formats: a `GdkContentFormats`
|
|
*
|
|
* Prints the given @formats into a human-readable string.
|
|
*
|
|
* The resulting string can be parsed with [func@Gdk.ContentFormats.parse].
|
|
*
|
|
* This is a small wrapper around [method@Gdk.ContentFormats.print]
|
|
* to help when debugging.
|
|
*
|
|
* Returns: (transfer full): a new string
|
|
*/
|
|
char *
|
|
gdk_content_formats_to_string (GdkContentFormats *formats)
|
|
{
|
|
GString *string;
|
|
|
|
g_return_val_if_fail (formats != NULL, NULL);
|
|
|
|
string = g_string_new (NULL);
|
|
gdk_content_formats_print (formats, string);
|
|
|
|
return g_string_free (string, FALSE);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_union:
|
|
* @first: (transfer full): the `GdkContentFormats` to merge into
|
|
* @second: (transfer none): the `GdkContentFormats` to merge from
|
|
*
|
|
* Append all missing types from @second to @first, in the order
|
|
* they had in @second.
|
|
*
|
|
* Returns: a new `GdkContentFormats`
|
|
*/
|
|
GdkContentFormats *
|
|
gdk_content_formats_union (GdkContentFormats *first,
|
|
const GdkContentFormats *second)
|
|
{
|
|
GdkContentFormatsBuilder *builder;
|
|
|
|
g_return_val_if_fail (first != NULL, NULL);
|
|
g_return_val_if_fail (second != NULL, NULL);
|
|
|
|
builder = gdk_content_formats_builder_new ();
|
|
|
|
gdk_content_formats_builder_add_formats (builder, first);
|
|
gdk_content_formats_unref (first);
|
|
gdk_content_formats_builder_add_formats (builder, second);
|
|
|
|
return gdk_content_formats_builder_free_to_formats (builder);
|
|
}
|
|
|
|
static gboolean
|
|
gdk_content_formats_contain_interned_mime_type (const GdkContentFormats *formats,
|
|
const char *mime_type)
|
|
{
|
|
gsize i;
|
|
|
|
for (i = 0; i < formats->n_mime_types; i++)
|
|
{
|
|
if (mime_type == formats->mime_types[i])
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_match:
|
|
* @first: the primary `GdkContentFormats` to intersect
|
|
* @second: the `GdkContentFormats` to intersect with
|
|
*
|
|
* Checks if @first and @second have any matching formats.
|
|
*
|
|
* Returns: %TRUE if a matching format was found.
|
|
*/
|
|
gboolean
|
|
gdk_content_formats_match (const GdkContentFormats *first,
|
|
const GdkContentFormats *second)
|
|
{
|
|
g_return_val_if_fail (first != NULL, FALSE);
|
|
g_return_val_if_fail (second != NULL, FALSE);
|
|
|
|
return gdk_content_formats_match_gtype (first, second) != G_TYPE_INVALID
|
|
|| gdk_content_formats_match_mime_type (first, second) != NULL;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_match_gtype:
|
|
* @first: the primary `GdkContentFormats` to intersect
|
|
* @second: the `GdkContentFormats` to intersect with
|
|
*
|
|
* Finds the first `GType` from @first that is also contained
|
|
* in @second.
|
|
*
|
|
* If no matching `GType` is found, %G_TYPE_INVALID is returned.
|
|
*
|
|
* Returns: The first common `GType` or %G_TYPE_INVALID if none.
|
|
*/
|
|
GType
|
|
gdk_content_formats_match_gtype (const GdkContentFormats *first,
|
|
const GdkContentFormats *second)
|
|
{
|
|
gsize i;
|
|
|
|
g_return_val_if_fail (first != NULL, FALSE);
|
|
g_return_val_if_fail (second != NULL, FALSE);
|
|
|
|
for (i = 0; i < first->n_gtypes; i++)
|
|
{
|
|
if (gdk_content_formats_contain_gtype (second, first->gtypes[i]))
|
|
return first->gtypes[i];
|
|
}
|
|
|
|
return G_TYPE_INVALID;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_match_mime_type:
|
|
* @first: the primary `GdkContentFormats` to intersect
|
|
* @second: the `GdkContentFormats` to intersect with
|
|
*
|
|
* Finds the first mime type from @first that is also contained
|
|
* in @second.
|
|
*
|
|
* If no matching mime type is found, %NULL is returned.
|
|
*
|
|
* Returns: (nullable): The first common mime type or %NULL if none
|
|
*/
|
|
const char *
|
|
gdk_content_formats_match_mime_type (const GdkContentFormats *first,
|
|
const GdkContentFormats *second)
|
|
{
|
|
gsize i;
|
|
|
|
g_return_val_if_fail (first != NULL, FALSE);
|
|
g_return_val_if_fail (second != NULL, FALSE);
|
|
|
|
for (i = 0; i < first->n_mime_types; i++)
|
|
{
|
|
if (gdk_content_formats_contain_interned_mime_type (second, first->mime_types[i]))
|
|
return first->mime_types[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_contain_gtype:
|
|
* @formats: a `GdkContentFormats`
|
|
* @type: the `GType` to search for
|
|
*
|
|
* Checks if a given `GType` is part of the given @formats.
|
|
*
|
|
* Returns: %TRUE if the `GType` was found
|
|
*/
|
|
gboolean
|
|
gdk_content_formats_contain_gtype (const GdkContentFormats *formats,
|
|
GType type)
|
|
{
|
|
g_return_val_if_fail (formats != NULL, FALSE);
|
|
|
|
gsize i;
|
|
|
|
for (i = 0; i < formats->n_gtypes; i++)
|
|
{
|
|
if (type == formats->gtypes[i])
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_contain_mime_type:
|
|
* @formats: a `GdkContentFormats`
|
|
* @mime_type: the mime type to search for
|
|
*
|
|
* Checks if a given mime type is part of the given @formats.
|
|
*
|
|
* Returns: %TRUE if the mime_type was found
|
|
*/
|
|
gboolean
|
|
gdk_content_formats_contain_mime_type (const GdkContentFormats *formats,
|
|
const char *mime_type)
|
|
{
|
|
g_return_val_if_fail (formats != NULL, FALSE);
|
|
g_return_val_if_fail (mime_type != NULL, FALSE);
|
|
|
|
return gdk_content_formats_contain_interned_mime_type (formats,
|
|
g_intern_string (mime_type));
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_get_gtypes:
|
|
* @formats: a `GdkContentFormats`
|
|
* @n_gtypes: (out) (optional): optional pointer to take the
|
|
* number of `GType`s contained in the return value
|
|
*
|
|
* Gets the `GType`s included in @formats.
|
|
*
|
|
* Note that @formats may not contain any `GType`s, in particular when
|
|
* they are empty. In that case %NULL will be returned.
|
|
*
|
|
* Returns: (transfer none) (nullable) (array length=n_gtypes zero-terminated=1):
|
|
* %G_TYPE_INVALID-terminated array of types included in @formats
|
|
*/
|
|
const GType *
|
|
gdk_content_formats_get_gtypes (const GdkContentFormats *formats,
|
|
gsize *n_gtypes)
|
|
{
|
|
g_return_val_if_fail (formats != NULL, NULL);
|
|
|
|
if (n_gtypes)
|
|
*n_gtypes = formats->n_gtypes;
|
|
|
|
return formats->gtypes;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_get_mime_types:
|
|
* @formats: a `GdkContentFormats`
|
|
* @n_mime_types: (out) (optional): optional pointer to take the
|
|
* number of mime types contained in the return value
|
|
*
|
|
* Gets the mime types included in @formats.
|
|
*
|
|
* Note that @formats may not contain any mime types, in particular
|
|
* when they are empty. In that case %NULL will be returned.
|
|
*
|
|
* Returns: (transfer none) (nullable) (array length=n_mime_types zero-terminated=1):
|
|
* %NULL-terminated array of interned strings of mime types included
|
|
* in @formats
|
|
*/
|
|
const char * const *
|
|
gdk_content_formats_get_mime_types (const GdkContentFormats *formats,
|
|
gsize *n_mime_types)
|
|
{
|
|
g_return_val_if_fail (formats != NULL, NULL);
|
|
|
|
if (n_mime_types)
|
|
*n_mime_types = formats->n_mime_types;
|
|
|
|
return formats->mime_types;
|
|
}
|
|
|
|
/**
|
|
* GdkContentFormatsBuilder:
|
|
*
|
|
* A `GdkContentFormatsBuilder` is an auxiliary struct used to create
|
|
* new `GdkContentFormats`, and should not be kept around.
|
|
*/
|
|
|
|
struct _GdkContentFormatsBuilder
|
|
{
|
|
int ref_count;
|
|
|
|
/* (element-type GType) */
|
|
GSList *gtypes;
|
|
gsize n_gtypes;
|
|
|
|
/* (element-type utf8) (interned) */
|
|
GSList *mime_types;
|
|
gsize n_mime_types;
|
|
};
|
|
|
|
G_DEFINE_BOXED_TYPE (GdkContentFormatsBuilder,
|
|
gdk_content_formats_builder,
|
|
gdk_content_formats_builder_ref,
|
|
gdk_content_formats_builder_unref)
|
|
|
|
/**
|
|
* gdk_content_formats_builder_new:
|
|
*
|
|
* Create a new `GdkContentFormatsBuilder` object.
|
|
*
|
|
* The resulting builder would create an empty `GdkContentFormats`.
|
|
* Use addition functions to add types to it.
|
|
*
|
|
* Returns: a new `GdkContentFormatsBuilder`
|
|
*/
|
|
GdkContentFormatsBuilder *
|
|
gdk_content_formats_builder_new (void)
|
|
{
|
|
GdkContentFormatsBuilder *builder;
|
|
|
|
builder = g_slice_new0 (GdkContentFormatsBuilder);
|
|
builder->ref_count = 1;
|
|
|
|
return builder;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_builder_ref:
|
|
* @builder: a `GdkContentFormatsBuilder`
|
|
*
|
|
* Acquires a reference on the given @builder.
|
|
*
|
|
* This function is intended primarily for bindings.
|
|
* `GdkContentFormatsBuilder` objects should not be kept around.
|
|
*
|
|
* Returns: (transfer none): the given `GdkContentFormatsBuilder`
|
|
* with its reference count increased
|
|
*/
|
|
GdkContentFormatsBuilder *
|
|
gdk_content_formats_builder_ref (GdkContentFormatsBuilder *builder)
|
|
{
|
|
g_return_val_if_fail (builder != NULL, NULL);
|
|
g_return_val_if_fail (builder->ref_count > 0, NULL);
|
|
|
|
builder->ref_count += 1;
|
|
|
|
return builder;
|
|
}
|
|
|
|
static void
|
|
gdk_content_formats_builder_clear (GdkContentFormatsBuilder *builder)
|
|
{
|
|
g_clear_pointer (&builder->gtypes, g_slist_free);
|
|
g_clear_pointer (&builder->mime_types, g_slist_free);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_builder_unref:
|
|
* @builder: a `GdkContentFormatsBuilder`
|
|
*
|
|
* Releases a reference on the given @builder.
|
|
*/
|
|
void
|
|
gdk_content_formats_builder_unref (GdkContentFormatsBuilder *builder)
|
|
{
|
|
g_return_if_fail (builder != NULL);
|
|
g_return_if_fail (builder->ref_count > 0);
|
|
|
|
builder->ref_count -= 1;
|
|
|
|
if (builder->ref_count > 0)
|
|
return;
|
|
|
|
gdk_content_formats_builder_clear (builder);
|
|
g_slice_free (GdkContentFormatsBuilder, builder);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_builder_free_to_formats: (skip)
|
|
* @builder: a `GdkContentFormatsBuilder`
|
|
*
|
|
* Creates a new `GdkContentFormats` from the current state of the
|
|
* given @builder, and frees the @builder instance.
|
|
*
|
|
* Returns: (transfer full): the newly created `GdkContentFormats`
|
|
* with all the formats added to @builder
|
|
*/
|
|
GdkContentFormats *
|
|
gdk_content_formats_builder_free_to_formats (GdkContentFormatsBuilder *builder)
|
|
{
|
|
GdkContentFormats *res;
|
|
|
|
g_return_val_if_fail (builder != NULL, NULL);
|
|
|
|
res = gdk_content_formats_builder_to_formats (builder);
|
|
|
|
gdk_content_formats_builder_unref (builder);
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_builder_to_formats:
|
|
* @builder: a `GdkContentFormats`Builder
|
|
*
|
|
* Creates a new `GdkContentFormats` from the given @builder.
|
|
*
|
|
* The given `GdkContentFormatsBuilder` is reset once this function returns;
|
|
* you cannot call this function multiple times on the same @builder instance.
|
|
*
|
|
* This function is intended primarily for bindings. C code should use
|
|
* [method@Gdk.ContentFormatsBuilder.free_to_formats].
|
|
*
|
|
* Returns: (transfer full): the newly created `GdkContentFormats`
|
|
* with all the formats added to @builder
|
|
*/
|
|
GdkContentFormats *
|
|
gdk_content_formats_builder_to_formats (GdkContentFormatsBuilder *builder)
|
|
{
|
|
GdkContentFormats *result;
|
|
GType *gtypes;
|
|
const char **mime_types;
|
|
GSList *l;
|
|
gsize i;
|
|
|
|
g_return_val_if_fail (builder != NULL, NULL);
|
|
|
|
if (builder->n_gtypes > 0)
|
|
{
|
|
gtypes = g_new (GType, builder->n_gtypes + 1);
|
|
i = builder->n_gtypes;
|
|
gtypes[i--] = G_TYPE_INVALID;
|
|
/* add backwards because most important type is last in the list */
|
|
for (l = builder->gtypes; l; l = l->next)
|
|
gtypes[i--] = GPOINTER_TO_SIZE (l->data);
|
|
}
|
|
else
|
|
{
|
|
gtypes = NULL;
|
|
}
|
|
|
|
if (builder->n_mime_types > 0)
|
|
{
|
|
mime_types = g_new (const char *, builder->n_mime_types + 1);
|
|
i = builder->n_mime_types;
|
|
mime_types[i--] = NULL;
|
|
/* add backwards because most important type is last in the list */
|
|
for (l = builder->mime_types; l; l = l->next)
|
|
mime_types[i--] = l->data;
|
|
}
|
|
else
|
|
{
|
|
mime_types = NULL;
|
|
}
|
|
|
|
result = gdk_content_formats_new_take (gtypes, builder->n_gtypes,
|
|
mime_types, builder->n_mime_types);
|
|
|
|
gdk_content_formats_builder_clear (builder);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_builder_add_formats:
|
|
* @builder: a `GdkContentFormatsBuilder`
|
|
* @formats: the formats to add
|
|
*
|
|
* Appends all formats from @formats to @builder, skipping those that
|
|
* already exist.
|
|
*/
|
|
void
|
|
gdk_content_formats_builder_add_formats (GdkContentFormatsBuilder *builder,
|
|
const GdkContentFormats *formats)
|
|
{
|
|
gsize i;
|
|
|
|
g_return_if_fail (builder != NULL);
|
|
g_return_if_fail (formats != NULL);
|
|
|
|
for (i = 0; i < formats->n_gtypes; i++)
|
|
gdk_content_formats_builder_add_gtype (builder, formats->gtypes[i]);
|
|
|
|
for (i = 0; i < formats->n_mime_types; i++)
|
|
gdk_content_formats_builder_add_mime_type (builder, formats->mime_types[i]);
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_builder_add_gtype:
|
|
* @builder: a `GdkContentFormats`Builder
|
|
* @type: a `GType`
|
|
*
|
|
* Appends @type to @builder if it has not already been added.
|
|
**/
|
|
void
|
|
gdk_content_formats_builder_add_gtype (GdkContentFormatsBuilder *builder,
|
|
GType type)
|
|
{
|
|
g_return_if_fail (builder != NULL);
|
|
g_return_if_fail (type != G_TYPE_INVALID);
|
|
|
|
if (g_slist_find (builder->gtypes, GSIZE_TO_POINTER (type)))
|
|
return;
|
|
|
|
builder->gtypes = g_slist_prepend (builder->gtypes, GSIZE_TO_POINTER (type));
|
|
builder->n_gtypes++;
|
|
}
|
|
|
|
/**
|
|
* gdk_content_formats_builder_add_mime_type:
|
|
* @builder: a `GdkContentFormatsBuilder`
|
|
* @mime_type: a mime type
|
|
*
|
|
* Appends @mime_type to @builder if it has not already been added.
|
|
*/
|
|
void
|
|
gdk_content_formats_builder_add_mime_type (GdkContentFormatsBuilder *builder,
|
|
const char *mime_type)
|
|
{
|
|
g_return_if_fail (builder != NULL);
|
|
g_return_if_fail (mime_type != NULL);
|
|
|
|
mime_type = g_intern_string (mime_type);
|
|
|
|
if (g_slist_find (builder->mime_types, mime_type))
|
|
return;
|
|
|
|
builder->mime_types = g_slist_prepend (builder->mime_types, (gpointer) mime_type);
|
|
builder->n_mime_types++;
|
|
}
|
|
|
|
/* {{{ GdkFileList */
|
|
|
|
/* We're using GdkFileList* and GSList* interchangeably, counting on the
|
|
* fact that we're just passing around gpointers; the only reason why we
|
|
* have a GdkFileList opaque type is for language bindings, because they
|
|
* can have no idea what a GSList of GFiles is.
|
|
*/
|
|
|
|
static gpointer
|
|
gdk_file_list_copy (gpointer list)
|
|
{
|
|
return g_slist_copy_deep (list, (GCopyFunc) g_object_ref, NULL);
|
|
}
|
|
|
|
static void
|
|
gdk_file_list_free (gpointer list)
|
|
{
|
|
g_slist_free_full (list, g_object_unref);
|
|
}
|
|
|
|
G_DEFINE_BOXED_TYPE (GdkFileList, gdk_file_list, gdk_file_list_copy, gdk_file_list_free)
|
|
|
|
/**
|
|
* gdk_file_list_get_files:
|
|
* @file_list: the file list
|
|
*
|
|
* Retrieves the list of files inside a `GdkFileList`.
|
|
*
|
|
* This function is meant for language bindings.
|
|
*
|
|
* Returns: (transfer container) (element-type GFile): the files inside the list
|
|
*
|
|
* Since: 4.6
|
|
*/
|
|
GSList *
|
|
gdk_file_list_get_files (GdkFileList *file_list)
|
|
{
|
|
return g_slist_copy ((GSList *) file_list);
|
|
}
|
|
|
|
/**
|
|
* gdk_file_list_new_from_list:
|
|
* @files: (element-type GFile): a list of files
|
|
*
|
|
* Creates a new files list container from a singly linked list of
|
|
* `GFile` instances.
|
|
*
|
|
* This function is meant to be used by language bindings
|
|
*
|
|
* Returns: (transfer full): the newly created files list
|
|
*
|
|
* Since: 4.8
|
|
*/
|
|
GdkFileList *
|
|
gdk_file_list_new_from_list (GSList *files)
|
|
{
|
|
return gdk_file_list_copy (files);
|
|
}
|
|
|
|
/**
|
|
* gdk_file_list_new_from_array:
|
|
* @files: (array length=n_files): the files to add to the list
|
|
* @n_files: the number of files in the array
|
|
*
|
|
* Creates a new `GdkFileList` for the given array of files.
|
|
*
|
|
* This function is meant to be used by language bindings.
|
|
*
|
|
* Returns: (transfer full): the newly create files list
|
|
*
|
|
* Since: 4.8
|
|
*/
|
|
GdkFileList *
|
|
gdk_file_list_new_from_array (GFile **files,
|
|
gsize n_files)
|
|
{
|
|
if (files == NULL || n_files == 0)
|
|
return NULL;
|
|
|
|
GSList *res = NULL;
|
|
for (gssize i = n_files - 1; i >= 0; i--)
|
|
res = g_slist_prepend (res, g_object_ref (files[i]));
|
|
|
|
return (GdkFileList *) res;
|
|
}
|
|
|
|
/* }}} */
|