diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:57:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:57:27 +0000 |
commit | 6f0f7d1b40a8fa8d46a2d6f4317600001cdbbb18 (patch) | |
tree | d423850ae901365e582137bdf2b5cbdffd7ca266 /src/gs-app-translation-dialog.c | |
parent | Initial commit. (diff) | |
download | gnome-software-upstream.tar.xz gnome-software-upstream.zip |
Adding upstream version 43.5.upstream/43.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/gs-app-translation-dialog.c')
-rw-r--r-- | src/gs-app-translation-dialog.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/src/gs-app-translation-dialog.c b/src/gs-app-translation-dialog.c new file mode 100644 index 0000000..81a8a44 --- /dev/null +++ b/src/gs-app-translation-dialog.c @@ -0,0 +1,271 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2021 Endless OS Foundation LLC + * + * Author: Philip Withnall <pwithnall@endlessos.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/** + * SECTION:gs-app-translation-dialog + * @short_description: A dialog showing translation information about an app + * + * #GsAppTranslationDialog is a dialog which shows a message about the + * translation status of an app, and provides information and a link for how + * to contribute more translations to the app. + * + * It is intended to be shown if the app is not sufficiently translated to the + * current locale. + * + * The widget has no special appearance if the app is unset, so callers will + * typically want to hide the dialog in that case. + * + * Since: 41 + */ + +#include "config.h" + +#include <adwaita.h> +#include <glib.h> +#include <glib-object.h> +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <locale.h> + +#include "gs-app.h" +#include "gs-app-translation-dialog.h" +#include "gs-common.h" + +struct _GsAppTranslationDialog +{ + GsInfoWindow parent_instance; + + GsApp *app; /* (not nullable) (owned) */ + gulong app_notify_name_handler; + + GtkLabel *title; + GtkLabel *description; +}; + +G_DEFINE_TYPE (GsAppTranslationDialog, gs_app_translation_dialog, GS_TYPE_INFO_WINDOW) + +typedef enum { + PROP_APP = 1, +} GsAppTranslationDialogProperty; + +static GParamSpec *obj_props[PROP_APP + 1] = { NULL, }; + +static void +update_labels (GsAppTranslationDialog *self) +{ + g_autofree gchar *title = NULL; + g_autofree gchar *description = NULL; + + /* Translators: The placeholder is an application name */ + title = g_strdup_printf (_("Help Translate %s"), gs_app_get_name (self->app)); + + /* Translators: The placeholder is an application name */ + description = g_strdup_printf (_("%s is designed, developed, and translated by an " + "international community of volunteers." + "\n\n" + "This means that while it’s not yet available in " + "your language, you can get involved and help " + "translate it yourself."), gs_app_get_name (self->app)); + + gtk_label_set_text (self->title, title); + gtk_label_set_text (self->description, description); +} + +static void +app_notify_cb (GObject *obj, + GParamSpec *pspec, + gpointer user_data) +{ + GsAppTranslationDialog *self = GS_APP_TRANSLATION_DIALOG (user_data); + + update_labels (self); +} + +static const gchar * +get_url_for_app (GsApp *app) +{ + const gchar *url; + + /* Try the translate URL, or a fallback */ + url = gs_app_get_url (app, AS_URL_KIND_TRANSLATE); +#if AS_CHECK_VERSION(0, 15, 3) + if (url == NULL) + url = gs_app_get_url (app, AS_URL_KIND_CONTRIBUTE); +#endif + if (url == NULL) + url = gs_app_get_url (app, AS_URL_KIND_BUGTRACKER); + + return url; +} + +static void +button_clicked_cb (GtkButton *button, + gpointer user_data) +{ + GsAppTranslationDialog *self = GS_APP_TRANSLATION_DIALOG (user_data); + const gchar *url = get_url_for_app (self->app); + + gtk_show_uri (GTK_WINDOW (self), url, GDK_CURRENT_TIME); +} + +static void +gs_app_translation_dialog_init (GsAppTranslationDialog *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} + +static void +gs_app_translation_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GsAppTranslationDialog *self = GS_APP_TRANSLATION_DIALOG (object); + + switch ((GsAppTranslationDialogProperty) prop_id) { + case PROP_APP: + g_value_set_object (value, gs_app_translation_dialog_get_app (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gs_app_translation_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GsAppTranslationDialog *self = GS_APP_TRANSLATION_DIALOG (object); + + switch ((GsAppTranslationDialogProperty) prop_id) { + case PROP_APP: + /* Construct only */ + g_assert (self->app == NULL); + g_assert (self->app_notify_name_handler == 0); + + self->app = g_value_dup_object (value); + self->app_notify_name_handler = g_signal_connect (self->app, "notify::name", G_CALLBACK (app_notify_cb), self); + + /* Update the UI. */ + update_labels (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_APP]); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gs_app_translation_dialog_dispose (GObject *object) +{ + GsAppTranslationDialog *self = GS_APP_TRANSLATION_DIALOG (object); + + g_clear_signal_handler (&self->app_notify_name_handler, self->app); + g_clear_object (&self->app); + + G_OBJECT_CLASS (gs_app_translation_dialog_parent_class)->dispose (object); +} + +static void +gs_app_translation_dialog_class_init (GsAppTranslationDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->get_property = gs_app_translation_dialog_get_property; + object_class->set_property = gs_app_translation_dialog_set_property; + object_class->dispose = gs_app_translation_dialog_dispose; + + /** + * GsAppTranslationDialog:app: (not nullable) + * + * The app to display the translation details for. + * + * This must not be %NULL. + * + * Since: 41 + */ + obj_props[PROP_APP] = + g_param_spec_object ("app", NULL, NULL, + GS_TYPE_APP, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-app-translation-dialog.ui"); + + gtk_widget_class_bind_template_child (widget_class, GsAppTranslationDialog, title); + gtk_widget_class_bind_template_child (widget_class, GsAppTranslationDialog, description); + + gtk_widget_class_bind_template_callback (widget_class, button_clicked_cb); +} + +/** + * gs_app_translation_dialog_new: + * @app: (not nullable): the app to display translation information for + * + * Create a new #GsAppTranslationDialog and set its initial app to @app. + * + * Returns: (transfer full): a new #GsAppTranslationDialog + * Since: 41 + */ +GsAppTranslationDialog * +gs_app_translation_dialog_new (GsApp *app) +{ + g_return_val_if_fail (GS_IS_APP (app), NULL); + + return g_object_new (GS_TYPE_APP_TRANSLATION_DIALOG, + "app", app, + NULL); +} + +/** + * gs_app_translation_dialog_get_app: + * @self: a #GsAppTranslationDialog + * + * Gets the value of #GsAppTranslationDialog:app. + * + * Returns: (not nullable) (transfer none): app whose translation information is + * being displayed + * Since: 41 + */ +GsApp * +gs_app_translation_dialog_get_app (GsAppTranslationDialog *self) +{ + g_return_val_if_fail (GS_IS_APP_TRANSLATION_DIALOG (self), NULL); + + return self->app; +} + +/** + * gs_app_translation_dialog_app_has_url: + * @app: a #GsApp + * + * Check @app to see if it has appropriate URLs set on it to allow the user + * to be linked to a page relevant to translating the app. + * + * Generally this should be used to work out whether to show a + * #GsAppTranslationDialog dialog for a given @app. + * + * Returns: %TRUE if an URL exists, %FALSE otherwise + * Since: 41 + */ +gboolean +gs_app_translation_dialog_app_has_url (GsApp *app) +{ + g_return_val_if_fail (GS_IS_APP (app), FALSE); + + return (get_url_for_app (app) != NULL); +} |