1
0
Fork 0
gnome-software/lib/gs-app-query.c
Daniel Baumann 68ee05b3fd
Adding upstream version 48.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 21:00:23 +02:00

1452 lines
42 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
* vi:set noexpandtab tabstop=8 shiftwidth=8:
*
* Copyright (C) 2022 Endless OS Foundation LLC
*
* Author: Philip Withnall <pwithnall@endlessos.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/**
* SECTION:gs-app-query
* @short_description: Immutable representation of a query for apps
*
* #GsAppQuery is an object to represent a query for apps.
*
* It will typically be used with #GsPluginJobListApps, which searches for
* matching apps, but it may have multiple consumers. #GsAppQuery only
* represents the query and does not provide an implementation for executing
* that query.
*
* It is immutable after construction, and hence threadsafe. It may be extended
* in future by adding more query properties. The existing query properties are
* conjunctive: results should only be returned which match *all* properties
* which are set, not _any_ properties which are set.
*
* The set of apps returned for the query can be controlled with the
* #GsAppQuery:refine-flags,
* #GsAppQuery:max-results and
* #GsAppQuery:dedupe-flags properties. If `refine-flags` is
* set, all results must be refined using the given set of refine flags (see
* #GsPluginJobRefine). `max-results` and `dedupe-flags` are used to limit the
* set of results.
*
* Results must always be processed in this order:
* - Filtering using #GsAppQuery:filter-func (and any other custom filter
* functions the query executor provides).
* - Deduplication using #GsAppQuery:dedupe-flags.
* - Sorting using #GsAppQuery:sort-func.
* - Truncating result list length to #GsAppQuery:max-results.
*
* Since: 43
*/
#include "config.h"
#include <glib.h>
#include <glib-object.h>
#include "gs-app.h"
#include "gs-app-list.h"
#include "gs-app-query.h"
#include "gs-enums.h"
#include "gs-plugin-types.h"
#include "gs-utils.h"
struct _GsAppQuery
{
GObject parent;
GsPluginRefineFlags refine_flags;
guint max_results;
GsAppListFilterFlags dedupe_flags;
GsAppListSortFunc sort_func;
gpointer sort_user_data;
GDestroyNotify sort_user_data_notify;
GsAppListFilterFunc filter_func;
gpointer filter_user_data;
GDestroyNotify filter_user_data_notify;
/* This is guaranteed to either be %NULL, or a non-empty array */
gchar **provides_files; /* (owned) (nullable) (array zero-terminated=1) */
GDateTime *released_since; /* (owned) (nullable) */
GsAppQueryTristate is_curated;
GsAppQueryTristate is_featured;
GsCategory *category; /* (nullable) (owned) */
GsAppQueryTristate is_installed;
/* This is guaranteed to either be %NULL, or a non-empty array */
gchar **deployment_featured; /* (owned) (nullable) (array zero-terminated=1) */
/* This is guaranteed to either be %NULL, or a non-empty array */
gchar **developers; /* (owned) (nullable) (array zero-terminated=1) */
gchar **keywords; /* (owned) (nullable) (array zero-terminated=1) */
GsApp *alternate_of; /* (nullable) (owned) */
gchar *provides_tag; /* (owned) (nullable) */
GsAppQueryProvidesType provides_type;
GsAppQueryLicenseType license_type;
GsAppQueryDeveloperVerifiedType developer_verified_type;
GsAppQueryTristate is_for_update;
GsAppQueryTristate is_historical_update;
GsAppQueryTristate is_source;
};
G_DEFINE_TYPE (GsAppQuery, gs_app_query, G_TYPE_OBJECT)
typedef enum {
PROP_REFINE_FLAGS = 1,
PROP_MAX_RESULTS,
PROP_DEDUPE_FLAGS,
PROP_SORT_FUNC,
PROP_SORT_USER_DATA,
PROP_SORT_USER_DATA_NOTIFY,
PROP_FILTER_FUNC,
PROP_FILTER_USER_DATA,
PROP_FILTER_USER_DATA_NOTIFY,
PROP_DEPLOYMENT_FEATURED,
PROP_DEVELOPERS,
PROP_PROVIDES_FILES,
PROP_RELEASED_SINCE,
PROP_IS_CURATED,
PROP_IS_FEATURED,
PROP_CATEGORY,
PROP_IS_INSTALLED,
PROP_KEYWORDS,
PROP_ALTERNATE_OF,
PROP_PROVIDES_TAG,
PROP_PROVIDES_TYPE,
PROP_LICENSE_TYPE,
PROP_DEVELOPER_VERIFIED_TYPE,
PROP_IS_FOR_UPDATE,
PROP_IS_HISTORICAL_UPDATE,
PROP_IS_SOURCE,
} GsAppQueryProperty;
static GParamSpec *props[PROP_IS_SOURCE + 1] = { NULL, };
static gchar **
gs_app_query_sanitize_keywords (const gchar * const *terms)
{
g_autoptr(GStrvBuilder) keywords = NULL;
gboolean any_added = FALSE;
if (terms == NULL || terms[0] == NULL)
return NULL;
keywords = g_strv_builder_new ();
/* If the caller already split the terms, then use it as is */
if (terms[1] != NULL) {
g_strv_builder_addv (keywords, (const gchar **) terms);
any_added = TRUE;
} else {
g_autofree gchar *term = g_strdup (terms[0]);
g_strstrip (term);
if (strchr (term, ' ')) {
g_auto(GStrv) split = g_strsplit (term, " ", -1);
for (guint i = 0; split[i] != NULL; i++) {
gchar *word = g_strstrip (split[i]);
if (*word != '\0') {
g_strv_builder_add (keywords, word);
any_added = TRUE;
}
}
} else if (*term != '\0') {
g_strv_builder_add (keywords, term);
any_added = TRUE;
}
}
return any_added ? g_strv_builder_end (keywords) : NULL;
}
static void
gs_app_query_constructed (GObject *object)
{
GsAppQuery *self = GS_APP_QUERY (object);
G_OBJECT_CLASS (gs_app_query_parent_class)->constructed (object);
g_assert ((self->provides_tag != NULL) == (self->provides_type != GS_APP_QUERY_PROVIDES_UNKNOWN));
}
static void
gs_app_query_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GsAppQuery *self = GS_APP_QUERY (object);
switch ((GsAppQueryProperty) prop_id) {
case PROP_REFINE_FLAGS:
g_value_set_flags (value, self->refine_flags);
break;
case PROP_MAX_RESULTS:
g_value_set_uint (value, self->max_results);
break;
case PROP_DEDUPE_FLAGS:
g_value_set_flags (value, self->dedupe_flags);
break;
case PROP_SORT_FUNC:
g_value_set_pointer (value, self->sort_func);
break;
case PROP_SORT_USER_DATA:
g_value_set_pointer (value, self->sort_user_data);
break;
case PROP_SORT_USER_DATA_NOTIFY:
g_value_set_pointer (value, self->sort_user_data_notify);
break;
case PROP_FILTER_FUNC:
g_value_set_pointer (value, self->filter_func);
break;
case PROP_FILTER_USER_DATA:
g_value_set_pointer (value, self->filter_user_data);
break;
case PROP_FILTER_USER_DATA_NOTIFY:
g_value_set_pointer (value, self->filter_user_data_notify);
break;
case PROP_DEPLOYMENT_FEATURED:
g_value_set_boxed (value, self->deployment_featured);
break;
case PROP_DEVELOPERS:
g_value_set_boxed (value, self->developers);
break;
case PROP_PROVIDES_FILES:
g_value_set_boxed (value, self->provides_files);
break;
case PROP_RELEASED_SINCE:
g_value_set_boxed (value, self->released_since);
break;
case PROP_IS_CURATED:
g_value_set_enum (value, self->is_curated);
break;
case PROP_IS_FEATURED:
g_value_set_enum (value, self->is_featured);
break;
case PROP_CATEGORY:
g_value_set_object (value, self->category);
break;
case PROP_IS_INSTALLED:
g_value_set_enum (value, self->is_installed);
break;
case PROP_KEYWORDS:
g_value_set_boxed (value, self->keywords);
break;
case PROP_ALTERNATE_OF:
g_value_set_object (value, self->alternate_of);
break;
case PROP_PROVIDES_TAG:
g_value_set_string (value, self->provides_tag);
break;
case PROP_PROVIDES_TYPE:
g_value_set_enum (value, self->provides_type);
break;
case PROP_LICENSE_TYPE:
g_value_set_enum (value, self->license_type);
break;
case PROP_DEVELOPER_VERIFIED_TYPE:
g_value_set_enum (value, self->developer_verified_type);
break;
case PROP_IS_FOR_UPDATE:
g_value_set_enum (value, self->is_for_update);
break;
case PROP_IS_HISTORICAL_UPDATE:
g_value_set_enum (value, self->is_historical_update);
break;
case PROP_IS_SOURCE:
g_value_set_enum (value, self->is_source);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gs_app_query_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GsAppQuery *self = GS_APP_QUERY (object);
switch ((GsAppQueryProperty) prop_id) {
case PROP_REFINE_FLAGS:
/* Construct only. */
g_assert (self->refine_flags == 0);
self->refine_flags = g_value_get_flags (value);
break;
case PROP_MAX_RESULTS:
/* Construct only. */
g_assert (self->max_results == 0);
self->max_results = g_value_get_uint (value);
break;
case PROP_DEDUPE_FLAGS:
/* Construct only. */
g_assert (self->dedupe_flags == 0);
self->dedupe_flags = g_value_get_flags (value);
break;
case PROP_SORT_FUNC:
/* Construct only. */
g_assert (self->sort_func == NULL);
self->sort_func = g_value_get_pointer (value);
break;
case PROP_SORT_USER_DATA:
/* Construct only. */
g_assert (self->sort_user_data == NULL);
self->sort_user_data = g_value_get_pointer (value);
break;
case PROP_SORT_USER_DATA_NOTIFY:
/* Construct only. */
g_assert (self->sort_user_data_notify == NULL);
self->sort_user_data_notify = g_value_get_pointer (value);
break;
case PROP_FILTER_FUNC:
/* Construct only. */
g_assert (self->filter_func == NULL);
self->filter_func = g_value_get_pointer (value);
break;
case PROP_FILTER_USER_DATA:
/* Construct only. */
g_assert (self->filter_user_data == NULL);
self->filter_user_data = g_value_get_pointer (value);
break;
case PROP_FILTER_USER_DATA_NOTIFY:
/* Construct only. */
g_assert (self->filter_user_data_notify == NULL);
self->filter_user_data_notify = g_value_get_pointer (value);
break;
case PROP_DEPLOYMENT_FEATURED:
/* Construct only. */
g_assert (self->deployment_featured == NULL);
self->deployment_featured = g_value_dup_boxed (value);
/* Squash empty arrays to %NULL. */
if (self->deployment_featured != NULL && self->deployment_featured[0] == NULL)
g_clear_pointer (&self->deployment_featured, g_strfreev);
break;
case PROP_DEVELOPERS:
/* Construct only. */
g_assert (self->developers == NULL);
self->developers = g_value_dup_boxed (value);
/* Squash empty arrays to %NULL. */
if (self->developers != NULL && self->developers[0] == NULL)
g_clear_pointer (&self->developers, g_strfreev);
break;
case PROP_PROVIDES_FILES:
/* Construct only. */
g_assert (self->provides_files == NULL);
self->provides_files = g_value_dup_boxed (value);
/* Squash empty arrays to %NULL. */
if (self->provides_files != NULL && self->provides_files[0] == NULL)
g_clear_pointer (&self->provides_files, g_strfreev);
break;
case PROP_RELEASED_SINCE:
/* Construct only. */
g_assert (self->released_since == NULL);
self->released_since = g_value_dup_boxed (value);
break;
case PROP_IS_CURATED:
/* Construct only. */
g_assert (self->is_curated == GS_APP_QUERY_TRISTATE_UNSET);
self->is_curated = g_value_get_enum (value);
break;
case PROP_IS_FEATURED:
/* Construct only. */
g_assert (self->is_featured == GS_APP_QUERY_TRISTATE_UNSET);
self->is_featured = g_value_get_enum (value);
break;
case PROP_CATEGORY:
/* Construct only. */
g_assert (self->category == NULL);
self->category = g_value_dup_object (value);
break;
case PROP_IS_INSTALLED:
/* Construct only. */
g_assert (self->is_installed == GS_APP_QUERY_TRISTATE_UNSET);
self->is_installed = g_value_get_enum (value);
break;
case PROP_KEYWORDS:
/* Construct only. */
g_assert (self->keywords == NULL);
self->keywords = gs_app_query_sanitize_keywords (g_value_get_boxed (value));
break;
case PROP_ALTERNATE_OF:
/* Construct only. */
g_assert (self->alternate_of == NULL);
self->alternate_of = g_value_dup_object (value);
break;
case PROP_PROVIDES_TAG:
/* Construct only. */
g_assert (self->provides_tag == NULL);
self->provides_tag = g_value_dup_string (value);
break;
case PROP_PROVIDES_TYPE:
/* Construct only. */
g_assert (self->provides_type == GS_APP_QUERY_PROVIDES_UNKNOWN);
self->provides_type = g_value_get_enum (value);
break;
case PROP_LICENSE_TYPE:
/* Construct only. */
g_assert (self->license_type == GS_APP_QUERY_LICENSE_ANY);
self->license_type = g_value_get_enum (value);
break;
case PROP_DEVELOPER_VERIFIED_TYPE:
/* Construct only. */
g_assert (self->developer_verified_type == GS_APP_QUERY_DEVELOPER_VERIFIED_ANY);
self->developer_verified_type = g_value_get_enum (value);
break;
case PROP_IS_FOR_UPDATE:
/* Construct only. */
g_assert (self->is_for_update == GS_APP_QUERY_TRISTATE_UNSET);
self->is_for_update = g_value_get_enum (value);
break;
case PROP_IS_HISTORICAL_UPDATE:
/* Construct only. */
g_assert (self->is_historical_update == GS_APP_QUERY_TRISTATE_UNSET);
self->is_historical_update = g_value_get_enum (value);
break;
case PROP_IS_SOURCE:
/* Construct only. */
g_assert (self->is_source == GS_APP_QUERY_TRISTATE_UNSET);
self->is_source = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gs_app_query_dispose (GObject *object)
{
GsAppQuery *self = GS_APP_QUERY (object);
if (self->sort_user_data_notify != NULL && self->sort_user_data != NULL) {
self->sort_user_data_notify (g_steal_pointer (&self->sort_user_data));
self->sort_user_data_notify = NULL;
}
if (self->filter_user_data_notify != NULL && self->filter_user_data != NULL) {
self->filter_user_data_notify (g_steal_pointer (&self->filter_user_data));
self->filter_user_data_notify = NULL;
}
g_clear_object (&self->category);
g_clear_object (&self->alternate_of);
G_OBJECT_CLASS (gs_app_query_parent_class)->dispose (object);
}
static void
gs_app_query_finalize (GObject *object)
{
GsAppQuery *self = GS_APP_QUERY (object);
g_clear_pointer (&self->deployment_featured, g_strfreev);
g_clear_pointer (&self->developers, g_strfreev);
g_clear_pointer (&self->provides_files, g_strfreev);
g_clear_pointer (&self->released_since, g_date_time_unref);
g_clear_pointer (&self->keywords, g_strfreev);
g_clear_pointer (&self->provides_tag, g_free);
G_OBJECT_CLASS (gs_app_query_parent_class)->finalize (object);
}
static void
gs_app_query_class_init (GsAppQueryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = gs_app_query_constructed;
object_class->get_property = gs_app_query_get_property;
object_class->set_property = gs_app_query_set_property;
object_class->dispose = gs_app_query_dispose;
object_class->finalize = gs_app_query_finalize;
/**
* GsAppQuery:refine-flags:
*
* Flags to specify how the returned apps must be refined, if at all.
*
* Since: 43
*/
props[PROP_REFINE_FLAGS] =
g_param_spec_flags ("refine-flags", "Refine Flags",
"Flags to specify how the returned apps must be refined, if at all.",
GS_TYPE_PLUGIN_REFINE_FLAGS, GS_PLUGIN_REFINE_FLAGS_NONE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:max-results:
*
* Maximum number of results to return, or 0 for no limit.
*
* Since: 43
*/
props[PROP_MAX_RESULTS] =
g_param_spec_uint ("max-results", "Max Results",
"Maximum number of results to return, or 0 for no limit.",
0, G_MAXUINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:dedupe-flags:
*
* Flags to specify how to deduplicate the returned apps, if at all.
*
* Since: 43
*/
props[PROP_DEDUPE_FLAGS] =
g_param_spec_flags ("dedupe-flags", "Dedupe Flags",
"Flags to specify how to deduplicate the returned apps, if at all.",
GS_TYPE_APP_LIST_FILTER_FLAGS, GS_APP_LIST_FILTER_FLAG_NONE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:sort-func: (nullable)
*
* A sort function to sort the returned apps.
*
* This must be of type #GsAppListSortFunc.
*
* Since: 43
*/
props[PROP_SORT_FUNC] =
g_param_spec_pointer ("sort-func", "Sort Function",
"A sort function to sort the returned apps.",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:sort-user-data: (nullable)
*
* User data to pass to #GsAppQuery:sort-func.
*
* Since: 43
*/
props[PROP_SORT_USER_DATA] =
g_param_spec_pointer ("sort-user-data", "Sort User Data",
"User data to pass to #GsAppQuery:sort-func.",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:sort-user-data-notify: (nullable)
*
* A function to free #GsAppQuery:sort-user-data once it is no longer
* needed.
*
* This must be of type #GDestroyNotify.
*
* This will be called exactly once between being set and when the
* #GsAppQuery is finalized.
*
* Since: 43
*/
props[PROP_SORT_USER_DATA_NOTIFY] =
g_param_spec_pointer ("sort-user-data-notify", "Sort User Data Notify",
"A function to free #GsAppQuery:sort-user-data once it is no longer needed.",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:filter-func: (nullable)
*
* A filter function to filter the returned apps.
*
* This must be of type #GsAppListFilterFunc.
*
* Since: 43
*/
props[PROP_FILTER_FUNC] =
g_param_spec_pointer ("filter-func", "Filter Function",
"A filter function to filter the returned apps.",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:filter-user-data: (nullable)
*
* User data to pass to #GsAppQuery:filter-func.
*
* Since: 43
*/
props[PROP_FILTER_USER_DATA] =
g_param_spec_pointer ("filter-user-data", "Filter User Data",
"User data to pass to #GsAppQuery:filter-func.",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:filter-user-data-notify: (nullable)
*
* A function to free #GsAppQuery:filter-user-data once it is no longer
* needed.
*
* This must be of type #GDestroyNotify.
*
* This will be called exactly once between being set and when the
* #GsAppQuery is finalized.
*
* Since: 43
*/
props[PROP_FILTER_USER_DATA_NOTIFY] =
g_param_spec_pointer ("filter-user-data-notify", "Filter User Data Notify",
"A function to free #GsAppQuery:filter-user-data once it is no longer needed.",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:deployment-featured: (nullable)
*
* A list of `GnomeSoftware::DeploymentFeatured` app keys.
*
* Search for applications that should be featured in a deployment-specific
* section on the overview page.
* This is expected to be a curated list of applications that are high quality
* and feature-complete. Only apps matching at least one of the keys in this
* list are returned.
*
* This may be %NULL to not filter on it. An empty array is
* considered equivalent to %NULL.
*
* Since: 43
*/
props[PROP_DEPLOYMENT_FEATURED] =
g_param_spec_boxed ("deployment-featured", "Deployment Featured",
"A list of `GnomeSoftware::DeploymentFeatured` app keys.",
G_TYPE_STRV,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:developers: (nullable)
*
* A list of developers to search the apps for.
*
* Used to search for apps which are provided by given developer(s).
*
* This may be %NULL to not filter on by them. An empty array is
* considered equivalent to %NULL.
*
* Since: 43
*/
props[PROP_DEVELOPERS] =
g_param_spec_boxed ("developers", "Developers",
"A list of developers who provide the apps.",
G_TYPE_STRV,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:provides-files: (nullable)
*
* A list of file paths which the apps must provide.
*
* Used to search for apps which provide specific files on the local
* file system.
*
* This may be %NULL to not filter on file paths. An empty array is
* considered equivalent to %NULL.
*
* Since: 43
*/
props[PROP_PROVIDES_FILES] =
g_param_spec_boxed ("provides-files", "Provides Files",
"A list of file paths which the apps must provide.",
G_TYPE_STRV,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:released-since: (nullable)
*
* A date/time which apps must have been released since (exclusive).
*
* Used to search for apps which have been updated recently.
*
* This may be %NULL to not filter on release date.
*
* Since: 43
*/
props[PROP_RELEASED_SINCE] =
g_param_spec_boxed ("released-since", "Released Since",
"A date/time which apps must have been released since (exclusive).",
G_TYPE_DATE_TIME,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:is-curated:
*
* Whether apps must be curated (%GS_APP_QUERY_TRISTATE_TRUE), or not
* curated (%GS_APP_QUERY_TRISTATE_FALSE).
*
* If this is %GS_APP_QUERY_TRISTATE_UNSET, apps are not filtered by
* their curation state.
*
* Curated apps have been reviewed and picked by an editor to be
* promoted to users in some way. They should be high quality and
* feature complete.
*
* Since: 43
*/
props[PROP_IS_CURATED] =
g_param_spec_enum ("is-curated", "Is Curated",
"Whether apps must be curated, or not curated.",
GS_TYPE_APP_QUERY_TRISTATE,
GS_APP_QUERY_TRISTATE_UNSET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:is-featured:
*
* Whether apps must be featured (%GS_APP_QUERY_TRISTATE_TRUE), or not
* featured (%GS_APP_QUERY_TRISTATE_FALSE).
*
* If this is %GS_APP_QUERY_TRISTATE_UNSET, apps are not filtered by
* their featured state.
*
* Featured apps have been selected by the distribution or software
* source to be highlighted or promoted to users in some way. They
* should be high quality and feature complete.
*
* Since: 43
*/
props[PROP_IS_FEATURED] =
g_param_spec_enum ("is-featured", "Is Featured",
"Whether apps must be featured, or not featured.",
GS_TYPE_APP_QUERY_TRISTATE,
GS_APP_QUERY_TRISTATE_UNSET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:category: (nullable)
*
* A category which apps must be in.
*
* If this is %NULL, apps are not filtered by category.
*
* Since: 43
*/
props[PROP_CATEGORY] =
g_param_spec_object ("category", "Category",
"A category which apps must be in.",
GS_TYPE_CATEGORY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:is-installed:
*
* Whether apps must be installed (%GS_APP_QUERY_TRISTATE_TRUE), or not
* installed (%GS_APP_QUERY_TRISTATE_FALSE).
*
* If this is %GS_APP_QUERY_TRISTATE_UNSET, apps are not filtered by
* their installed state.
*
* Since: 43
*/
props[PROP_IS_INSTALLED] =
g_param_spec_enum ("is-installed", "Is Installed",
"Whether apps must be installed, or not installed.",
GS_TYPE_APP_QUERY_TRISTATE,
GS_APP_QUERY_TRISTATE_UNSET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:keywords:
*
* A set of search keywords which apps must match.
*
* Search matches may be done against multiple properties of the app,
* such as its name, description, supported content types, defined
* keywords, etc. The keywords in this property may be stemmed in an
* undefined way after being retrieved from #GsAppQuery.
*
* If this is %NULL, apps are not filtered by matches to this set of
* keywords. An empty array is considered equivalent to %NULL.
*
* Since: 43
*/
props[PROP_KEYWORDS] =
g_param_spec_boxed ("keywords", "Keywords",
"A set of search keywords which apps must match.",
G_TYPE_STRV,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:alternate-of: (nullable)
*
* An app which apps must be related to.
*
* The definition of related to depends on the code consuming
* #GsAppQuery, but it will typically be other applications which
* implement the same feature, or other applications which are packaged
* together with this one.
*
* If this is %NULL, apps are not filtered by alternatives.
*
* Since: 43
*/
props[PROP_ALTERNATE_OF] =
g_param_spec_object ("alternate-of", "Alternate Of",
"An app which apps must be related to.",
GS_TYPE_APP,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:provides-tag: (nullable)
*
* A tag which apps must provide.
*
* The interpretation of the tag depends on #GsAppQuery:provides-type,
* which must not be %GS_APP_QUERY_PROVIDES_UNKNOWN if this is
* non-%NULL. Typically a tag will be a content type which the app
* implements, or the name of a printer which the app provides the
* driver for, etc.
*
* If this is %NULL, apps are not filtered by what they provide.
*
* Since: 43
*/
props[PROP_PROVIDES_TAG] =
g_param_spec_string ("provides-tag", "Provides Tag",
"A tag which apps must provide.",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:provides-type:
*
* The type of #GsAppQuery:provides-tag.
*
* If this is %GS_APP_QUERY_PROVIDES_UNKNOWN, apps are not filtered by
* what they provide.
*
* Since: 43
*/
props[PROP_PROVIDES_TYPE] =
g_param_spec_enum ("provides-type", "Provides Type",
"The type of #GsAppQuery:provides-tag.",
GS_TYPE_APP_QUERY_PROVIDES_TYPE, GS_APP_QUERY_PROVIDES_UNKNOWN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:license-type:
*
* The type of license the app must be under.
*
* If this is %GS_APP_QUERY_LICENSE_ANY, apps are not filtered by
* their license type.
*
* Since: 44
*/
props[PROP_LICENSE_TYPE] =
g_param_spec_enum ("license-type", "License Type",
"The type of license the app must be under.",
GS_TYPE_APP_QUERY_LICENSE_TYPE, GS_APP_QUERY_LICENSE_ANY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:developer-verified-type:
*
* The type of developer verified state filter.
*
* If this is %GS_APP_QUERY_DEVELOPER_VERIFIED_ANY, apps are not filtered by
* the developer verified state.
*
* Since: 46
*/
props[PROP_DEVELOPER_VERIFIED_TYPE] =
g_param_spec_enum ("developer-verified-type", "Developer Verified Type",
"The type of developer verified state filter.",
GS_TYPE_APP_QUERY_DEVELOPER_VERIFIED_TYPE,
GS_APP_QUERY_DEVELOPER_VERIFIED_ANY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:is-for-update:
*
* Whether to include only apps which can be updated (%GS_APP_QUERY_TRISTATE_TRUE), or
* apps which cannot be updated (%GS_APP_QUERY_TRISTATE_FALSE).
*
* If this is %GS_APP_QUERY_TRISTATE_UNSET, then it doesn't matter.
*
* Since: 47
*/
props[PROP_IS_FOR_UPDATE] =
g_param_spec_enum ("is-for-update", "Is For Update",
"Whether to include only apps which can be updated.",
GS_TYPE_APP_QUERY_TRISTATE,
GS_APP_QUERY_TRISTATE_UNSET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:is-historical-update:
*
* Whether to include only apps which had been recently updated (%GS_APP_QUERY_TRISTATE_TRUE), or
* apps which had not been recently updated (%GS_APP_QUERY_TRISTATE_FALSE).
*
* If this is %GS_APP_QUERY_TRISTATE_UNSET, then it doesn't matter.
*
* Since: 47
*/
props[PROP_IS_HISTORICAL_UPDATE] =
g_param_spec_enum ("is-historical-update", "Is Historical Update",
"Whether to include only apps which had been recently updated.",
GS_TYPE_APP_QUERY_TRISTATE,
GS_APP_QUERY_TRISTATE_UNSET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GsAppQuery:is-source:
*
* Get the list of sources, for example the repos listed in `/etc/yum.repos.d`
* or the remotes configured in flatpak.
*
* Plugins are expected to add new apps using gs_app_list_add() of type
* %AS_COMPONENT_KIND_REPOSITORY.
*
* If this is %GS_APP_QUERY_TRISTATE_UNSET, then it doesn't matter.
*
* Since: 47
*/
props[PROP_IS_SOURCE] =
g_param_spec_enum ("is-source", "Is Source",
"Whether to include only repos.",
GS_TYPE_APP_QUERY_TRISTATE,
GS_APP_QUERY_TRISTATE_UNSET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, G_N_ELEMENTS (props), props);
}
static void
gs_app_query_init (GsAppQuery *self)
{
self->is_curated = GS_APP_QUERY_TRISTATE_UNSET;
self->is_featured = GS_APP_QUERY_TRISTATE_UNSET;
self->is_installed = GS_APP_QUERY_TRISTATE_UNSET;
self->is_for_update = GS_APP_QUERY_TRISTATE_UNSET;
self->is_historical_update = GS_APP_QUERY_TRISTATE_UNSET;
self->is_source = GS_APP_QUERY_TRISTATE_UNSET;
self->provides_type = GS_APP_QUERY_PROVIDES_UNKNOWN;
self->license_type = GS_APP_QUERY_LICENSE_ANY;
self->developer_verified_type = GS_APP_QUERY_DEVELOPER_VERIFIED_ANY;
}
/**
* gs_app_query_new:
* @first_property_name: name of the first #GObject property
* @...: value for the first property, followed by additional property/value
* pairs, then a terminating %NULL
*
* Create a new #GsAppQuery containing the given query properties.
*
* Returns: (transfer full): a new #GsAppQuery
* Since: 43
*/
GsAppQuery *
gs_app_query_new (const gchar *first_property_name,
...)
{
va_list args;
g_autoptr(GsAppQuery) query = NULL;
va_start (args, first_property_name);
query = GS_APP_QUERY (g_object_new_valist (GS_TYPE_APP_QUERY, first_property_name, args));
va_end (args);
return g_steal_pointer (&query);
}
/**
* gs_app_query_get_refine_flags:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:refine-flags.
*
* Returns: the refine flags for the query
* Since: 43
*/
GsPluginRefineFlags
gs_app_query_get_refine_flags (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_PLUGIN_REFINE_FLAGS_NONE);
return self->refine_flags;
}
/**
* gs_app_query_get_max_results:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:max-results.
*
* Returns: the maximum number of results to return for the query, or `0` to
* indicate no limit
* Since: 43
*/
guint
gs_app_query_get_max_results (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), 0);
return self->max_results;
}
/**
* gs_app_query_get_dedupe_flags:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:dedupe-flags.
*
* Returns: the dedupe flags for the query
* Since: 43
*/
GsAppListFilterFlags
gs_app_query_get_dedupe_flags (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_LIST_FILTER_FLAG_NONE);
return self->dedupe_flags;
}
/**
* gs_app_query_get_sort_func:
* @self: a #GsAppQuery
* @user_data_out: (out) (transfer none) (optional) (nullable): return location
* for the #GsAppQuery:sort-user-data, or %NULL to ignore
*
* Get the value of #GsAppQuery:sort-func.
*
* Returns: (nullable): the sort function for the query
* Since: 43
*/
GsAppListSortFunc
gs_app_query_get_sort_func (GsAppQuery *self,
gpointer *user_data_out)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
if (user_data_out != NULL)
*user_data_out = self->sort_user_data;
return self->sort_func;
}
/**
* gs_app_query_get_filter_func:
* @self: a #GsAppQuery
* @user_data_out: (out) (transfer none) (optional) (nullable): return location
* for the #GsAppQuery:filter-user-data, or %NULL to ignore
*
* Get the value of #GsAppQuery:filter-func.
*
* Returns: (nullable): the filter function for the query
* Since: 43
*/
GsAppListFilterFunc
gs_app_query_get_filter_func (GsAppQuery *self,
gpointer *user_data_out)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
if (user_data_out != NULL)
*user_data_out = self->filter_user_data;
return self->filter_func;
}
/**
* gs_app_query_get_n_properties_set:
* @self: a #GsAppQuery
*
* Get the number of query properties which have been set.
*
* These are the properties which determine the query results, rather than ones
* which control refining the results (#GsAppQuery:refine-flags,
* #GsAppQuery:max-results, #GsAppQuery:dedupe-flags, #GsAppQuery:sort-func and
* its user data, #GsAppQuery:filter-func and its user data,
* #GsAppQuery:license-type).
*
* Returns: number of properties set so they will affect query results
* Since: 43
*/
guint
gs_app_query_get_n_properties_set (GsAppQuery *self)
{
guint n = 0;
g_return_val_if_fail (GS_IS_APP_QUERY (self), 0);
if (self->provides_files != NULL)
n++;
if (self->released_since != NULL)
n++;
if (self->is_curated != GS_APP_QUERY_TRISTATE_UNSET)
n++;
if (self->is_featured != GS_APP_QUERY_TRISTATE_UNSET)
n++;
if (self->category != NULL)
n++;
if (self->is_installed != GS_APP_QUERY_TRISTATE_UNSET)
n++;
if (self->deployment_featured != NULL)
n++;
if (self->developers != NULL)
n++;
if (self->keywords != NULL)
n++;
if (self->alternate_of != NULL)
n++;
if (self->provides_tag != NULL)
n++;
if (self->is_for_update != GS_APP_QUERY_TRISTATE_UNSET)
n++;
if (self->is_historical_update != GS_APP_QUERY_TRISTATE_UNSET)
n++;
if (self->is_source != GS_APP_QUERY_TRISTATE_UNSET)
n++;
return n;
}
/**
* gs_app_query_get_provides_files:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:provides-files.
*
* Returns: (nullable): a list of file paths which the apps must provide,
* or %NULL to not filter on file paths
* Since: 43
*/
const gchar * const *
gs_app_query_get_provides_files (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
/* Always return %NULL or a non-empty array */
g_assert (self->provides_files == NULL || self->provides_files[0] != NULL);
return (const gchar * const *) self->provides_files;
}
/**
* gs_app_query_get_released_since:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:released-since.
*
* Returns: (nullable): a date/time which apps must have been released since,
* or %NULL to not filter on release date
* Since: 43
*/
GDateTime *
gs_app_query_get_released_since (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
return self->released_since;
}
/**
* gs_app_query_get_is_curated:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:is-curated.
*
* Returns: %GS_APP_QUERY_TRISTATE_TRUE if apps must be curated,
* %GS_APP_QUERY_TRISTATE_FALSE if they must be not curated, or
* %GS_APP_QUERY_TRISTATE_UNSET if it doesnt matter
* Since: 43
*/
GsAppQueryTristate
gs_app_query_get_is_curated (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_TRISTATE_UNSET);
return self->is_curated;
}
/**
* gs_app_query_get_is_featured:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:is-featured.
*
* Returns: %GS_APP_QUERY_TRISTATE_TRUE if apps must be featured,
* %GS_APP_QUERY_TRISTATE_FALSE if they must be not featured, or
* %GS_APP_QUERY_TRISTATE_UNSET if it doesnt matter
* Since: 43
*/
GsAppQueryTristate
gs_app_query_get_is_featured (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_TRISTATE_UNSET);
return self->is_featured;
}
/**
* gs_app_query_get_category:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:category.
*
* Returns: (nullable) (transfer none): a category which apps must be part of,
* or %NULL to not filter on category
* Since: 43
*/
GsCategory *
gs_app_query_get_category (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
return self->category;
}
/**
* gs_app_query_get_is_installed:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:is-installed.
*
* Returns: %GS_APP_QUERY_TRISTATE_TRUE if apps must be installed,
* %GS_APP_QUERY_TRISTATE_FALSE if they must be not installed, or
* %GS_APP_QUERY_TRISTATE_UNSET if it doesnt matter
* Since: 43
*/
GsAppQueryTristate
gs_app_query_get_is_installed (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_TRISTATE_UNSET);
return self->is_installed;
}
/**
* gs_app_query_get_deployment_featured:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:deployment-featured.
*
* Returns: (nullable): a list of `GnomeSoftware::DeploymentFeatured` app keys,
* which the apps have set in a custom key, or %NULL to not filter on this
* Since: 43
*/
const gchar * const *
gs_app_query_get_deployment_featured (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
/* Always return %NULL or a non-empty array */
g_assert (self->deployment_featured == NULL || self->deployment_featured[0] != NULL);
return (const gchar * const *) self->deployment_featured;
}
/**
* gs_app_query_get_developers:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:developers.
*
* Returns: (nullable): a list of developers who provide the apps,
* or %NULL to not filter by it
* Since: 43
*/
const gchar * const *
gs_app_query_get_developers (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
/* Always return %NULL or a non-empty array */
g_assert (self->developers == NULL || self->developers[0] != NULL);
return (const gchar * const *) self->developers;
}
/**
* gs_app_query_get_keywords:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:keywords.
*
* Returns: a set of search keywords which apps must match, or %NULL to not
* filter by it
* Since: 43
*/
const gchar * const *
gs_app_query_get_keywords (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
/* Always return %NULL or a non-empty array */
g_assert (self->keywords == NULL || self->keywords[0] != NULL);
return (const gchar * const *) self->keywords;
}
/**
* gs_app_query_get_alternate_of:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:alternate-of.
*
* Returns: (nullable) (transfer none): an app which apps must be related to,
* or %NULL to not filter on alternates
* Since: 43
*/
GsApp *
gs_app_query_get_alternate_of (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), NULL);
return self->alternate_of;
}
/**
* gs_app_query_get_provides:
* @self: a #GsAppQuery
* @out_provides_tag: (transfer none) (optional) (nullable) (out): return
* location for the value of #GsAppQuery:provides-tag, or %NULL to ignore
*
* Get the value of #GsAppQuery:provides-type and #GsAppQuery:provides-tag.
*
* Returns: the type of tag to filter on, or %GS_APP_QUERY_PROVIDES_UNKNOWN to
* not filter on provides
* Since: 43
*/
GsAppQueryProvidesType
gs_app_query_get_provides (GsAppQuery *self,
const gchar **out_provides_tag)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_PROVIDES_UNKNOWN);
if (out_provides_tag != NULL)
*out_provides_tag = self->provides_tag;
return self->provides_type;
}
/**
* gs_app_query_get_license_type:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:license-type.
*
* Returns: the type of license the app must be under, or
* %GS_APP_QUERY_LICENSE_ANY to not filter by license
* Since: 44
*/
GsAppQueryLicenseType
gs_app_query_get_license_type (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_LICENSE_ANY);
return self->license_type;
}
/**
* gs_app_query_get_developer_verified_type:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:developer-verified-type.
*
* Returns: the type of developer verified state filter, or
* %GS_APP_QUERY_DEVELOPER_VERIFIED_ANY to not filter by it
* Since: 46
*/
GsAppQueryDeveloperVerifiedType
gs_app_query_get_developer_verified_type (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_DEVELOPER_VERIFIED_ANY);
return self->developer_verified_type;
}
/**
* gs_app_query_get_is_for_update:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:is-for-update.
*
* Returns: %GS_APP_QUERY_TRISTATE_TRUE if query is only for apps which can be updated,
* %GS_APP_QUERY_TRISTATE_FALSE if query is only for apps which cannot be updated, or
* %GS_APP_QUERY_TRISTATE_UNSET if it doesnt matter
* Since: 47
*/
GsAppQueryTristate
gs_app_query_get_is_for_update (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_TRISTATE_UNSET);
return self->is_for_update;
}
/**
* gs_app_query_get_is_historical_update:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:is-historical-update.
*
* Returns: %GS_APP_QUERY_TRISTATE_TRUE if query is only for apps which had been recently updated,
* %GS_APP_QUERY_TRISTATE_FALSE if query is only for apps which had not been recently updated, or
* %GS_APP_QUERY_TRISTATE_UNSET if it doesnt matter
* Since: 47
*/
GsAppQueryTristate
gs_app_query_get_is_historical_update (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_TRISTATE_UNSET);
return self->is_historical_update;
}
/**
* gs_app_query_get_is_source:
* @self: a #GsAppQuery
*
* Get the value of #GsAppQuery:is-source.
*
* Returns: %GS_APP_QUERY_TRISTATE_TRUE if query is only for repos
* (aka #GsApps with type %AS_COMPONENT_KIND_REPOSITORY),
* %GS_APP_QUERY_TRISTATE_FALSE if query is only for non-repos apps, or
* %GS_APP_QUERY_TRISTATE_UNSET if it doesnt matter
* Since: 47
*/
GsAppQueryTristate
gs_app_query_get_is_source (GsAppQuery *self)
{
g_return_val_if_fail (GS_IS_APP_QUERY (self), GS_APP_QUERY_TRISTATE_UNSET);
return self->is_source;
}