diff options
Diffstat (limited to 'src/gs-repo-row.c')
-rw-r--r-- | src/gs-repo-row.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/src/gs-repo-row.c b/src/gs-repo-row.c new file mode 100644 index 0000000..72f0416 --- /dev/null +++ b/src/gs-repo-row.c @@ -0,0 +1,290 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2015-2018 Kalev Lember <klember@redhat.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "config.h" + +#include "gs-repo-row.h" + +#include <glib/gi18n.h> + +typedef struct +{ + GsApp *repo; + GtkWidget *button; + GtkWidget *name_label; + GtkWidget *comment_label; + GtkWidget *details_revealer; + GtkWidget *status_label; + GtkWidget *url_box; + GtkWidget *url_label; + guint refresh_idle_id; +} GsRepoRowPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (GsRepoRow, gs_repo_row, GTK_TYPE_LIST_BOX_ROW) + +enum { + SIGNAL_BUTTON_CLICKED, + SIGNAL_LAST +}; + +static guint signals [SIGNAL_LAST] = { 0 }; + +void +gs_repo_row_set_name (GsRepoRow *row, const gchar *name) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + gtk_label_set_text (GTK_LABEL (priv->name_label), name); + gtk_widget_set_visible (priv->name_label, name != NULL); +} + +void +gs_repo_row_set_comment (GsRepoRow *row, const gchar *comment) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + gtk_label_set_markup (GTK_LABEL (priv->comment_label), comment); + gtk_widget_set_visible (priv->comment_label, comment != NULL); +} + +void +gs_repo_row_set_url (GsRepoRow *row, const gchar *url) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + gtk_label_set_text (GTK_LABEL (priv->url_label), url); + gtk_widget_set_visible (priv->url_box, url != NULL); +} + +static gboolean +repo_supports_removal (GsApp *repo) +{ + const gchar *management_plugin = gs_app_get_management_plugin (repo); + + /* can't remove a repo, only enable/disable existing ones */ + if (g_strcmp0 (management_plugin, "fwupd") == 0 || + g_strcmp0 (management_plugin, "packagekit") == 0 || + g_strcmp0 (management_plugin, "rpm-ostree") == 0) + return FALSE; + + return TRUE; +} + +static void +refresh_ui (GsRepoRow *row) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + if (priv->repo == NULL) { + gtk_widget_set_visible (priv->button, FALSE); + return; + } + + gtk_widget_set_visible (priv->button, TRUE); + + /* set button text */ + switch (gs_app_get_state (priv->repo)) { + case AS_APP_STATE_AVAILABLE: + case AS_APP_STATE_AVAILABLE_LOCAL: + /* TRANSLATORS: this is a button in the software repositories + dialog for enabling a repo */ + gtk_button_set_label (GTK_BUTTON (priv->button), _("_Enable")); + /* enable button */ + gtk_widget_set_sensitive (priv->button, TRUE); + break; + case AS_APP_STATE_INSTALLED: + if (repo_supports_removal (priv->repo)) { + /* TRANSLATORS: this is a button in the software repositories dialog + for removing a repo. The ellipsis indicates that further + steps are required */ + gtk_button_set_label (GTK_BUTTON (priv->button), _("_Removeā¦")); + } else { + /* TRANSLATORS: this is a button in the software repositories dialog + for disabling a repo. The ellipsis indicates that further + steps are required */ + gtk_button_set_label (GTK_BUTTON (priv->button), _("_Disableā¦")); + } + /* enable button */ + gtk_widget_set_sensitive (priv->button, TRUE); + break; + case AS_APP_STATE_INSTALLING: + /* TRANSLATORS: this is a button in the software repositories dialog + that shows the status of a repo being enabled */ + gtk_button_set_label (GTK_BUTTON (priv->button), _("Enabling")); + /* disable button */ + gtk_widget_set_sensitive (priv->button, FALSE); + break; + case AS_APP_STATE_REMOVING: + if (repo_supports_removal (priv->repo)) { + /* TRANSLATORS: this is a button in the software repositories dialog + that shows the status of a repo being removed */ + gtk_button_set_label (GTK_BUTTON (priv->button), _("Removing")); + } else { + /* TRANSLATORS: this is a button in the software repositories dialog + that shows the status of a repo being disabled */ + gtk_button_set_label (GTK_BUTTON (priv->button), _("Disabling")); + } + /* disable button */ + gtk_widget_set_sensitive (priv->button, FALSE); + break; + default: + break; + } + + /* set enabled/disabled label */ + switch (gs_app_get_state (priv->repo)) { + case AS_APP_STATE_INSTALLED: + /* TRANSLATORS: this is a label in the software repositories + dialog that indicates that a repo is enabled. */ + gtk_label_set_text (GTK_LABEL (priv->status_label), _("Enabled")); + break; + case AS_APP_STATE_AVAILABLE: + case AS_APP_STATE_AVAILABLE_LOCAL: + /* TRANSLATORS: this is a label in the software repositories + dialog that indicates that a repo is disabled. */ + gtk_label_set_text (GTK_LABEL (priv->status_label), _("Disabled")); + break; + default: + break; + } +} + +static gboolean +refresh_idle (gpointer user_data) +{ + g_autoptr(GsRepoRow) row = (GsRepoRow *) user_data; + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + refresh_ui (row); + + priv->refresh_idle_id = 0; + return G_SOURCE_REMOVE; +} + +static void +repo_state_changed_cb (GsApp *repo, GParamSpec *pspec, GsRepoRow *row) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + if (priv->refresh_idle_id > 0) + return; + priv->refresh_idle_id = g_idle_add (refresh_idle, g_object_ref (row)); +} + +void +gs_repo_row_set_repo (GsRepoRow *row, GsApp *repo) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + g_assert (priv->repo == NULL); + + priv->repo = g_object_ref (repo); + g_signal_connect_object (priv->repo, "notify::state", + G_CALLBACK (repo_state_changed_cb), + row, 0); + refresh_ui (row); +} + +GsApp * +gs_repo_row_get_repo (GsRepoRow *row) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + return priv->repo; +} + +void +gs_repo_row_show_details (GsRepoRow *row) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); + gtk_revealer_set_reveal_child (GTK_REVEALER (priv->details_revealer), TRUE); +} + +void +gs_repo_row_hide_details (GsRepoRow *row) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE); + gtk_revealer_set_reveal_child (GTK_REVEALER (priv->details_revealer), FALSE); +} + +void +gs_repo_row_show_status (GsRepoRow *row) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + gtk_widget_set_visible (priv->status_label, TRUE); +} + +static void +button_clicked_cb (GtkWidget *widget, GsRepoRow *row) +{ + g_signal_emit (row, signals[SIGNAL_BUTTON_CLICKED], 0); +} + +static void +gs_repo_row_destroy (GtkWidget *object) +{ + GsRepoRow *row = GS_REPO_ROW (object); + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + if (priv->repo != NULL) { + g_signal_handlers_disconnect_by_func (priv->repo, repo_state_changed_cb, row); + g_clear_object (&priv->repo); + } + + if (priv->refresh_idle_id != 0) { + g_source_remove (priv->refresh_idle_id); + priv->refresh_idle_id = 0; + } + + GTK_WIDGET_CLASS (gs_repo_row_parent_class)->destroy (object); +} + +static void +gs_repo_row_init (GsRepoRow *row) +{ + GsRepoRowPrivate *priv = gs_repo_row_get_instance_private (row); + + gtk_widget_init_template (GTK_WIDGET (row)); + g_signal_connect (priv->button, "clicked", + G_CALLBACK (button_clicked_cb), row); +} + +static void +gs_repo_row_class_init (GsRepoRowClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + widget_class->destroy = gs_repo_row_destroy; + + signals [SIGNAL_BUTTON_CLICKED] = + g_signal_new ("button-clicked", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GsRepoRowClass, button_clicked), + NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-repo-row.ui"); + + gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, button); + gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, name_label); + gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, comment_label); + gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, details_revealer); + gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, status_label); + gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, url_box); + gtk_widget_class_bind_template_child_private (widget_class, GsRepoRow, url_label); +} + +GtkWidget * +gs_repo_row_new (void) +{ + return g_object_new (GS_TYPE_REPO_ROW, NULL); +} |