diff options
Diffstat (limited to 'src/gs-app-addon-row.c')
-rw-r--r-- | src/gs-app-addon-row.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/gs-app-addon-row.c b/src/gs-app-addon-row.c new file mode 100644 index 0000000..30fb4d6 --- /dev/null +++ b/src/gs-app-addon-row.c @@ -0,0 +1,273 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2012-2013 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2013 Matthias Clasen <mclasen@redhat.com> + * Copyright (C) 2014-2016 Kalev Lember <klember@redhat.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "config.h" + +#include <glib/gi18n.h> + +#include "gs-app-addon-row.h" + +struct _GsAppAddonRow +{ + GtkListBoxRow parent_instance; + + GsApp *app; + GtkWidget *name_label; + GtkWidget *description_label; + GtkWidget *label; + GtkWidget *checkbox; +}; + +G_DEFINE_TYPE (GsAppAddonRow, gs_app_addon_row, GTK_TYPE_LIST_BOX_ROW) + +enum { + PROP_ZERO, + PROP_SELECTED +}; + +static void +checkbox_toggled (GtkWidget *widget, GsAppAddonRow *row) +{ + g_object_notify (G_OBJECT (row), "selected"); +} + +/** + * gs_app_addon_row_get_summary: + * + * Return value: PangoMarkup + **/ +static GString * +gs_app_addon_row_get_summary (GsAppAddonRow *row) +{ + const gchar *tmp = NULL; + g_autofree gchar *escaped = NULL; + + /* try all these things in order */ + if (gs_app_get_state (row->app) == AS_APP_STATE_UNAVAILABLE) + tmp = gs_app_get_summary_missing (row->app); + if (tmp == NULL || (tmp != NULL && tmp[0] == '\0')) + tmp = gs_app_get_summary (row->app); + if (tmp == NULL || (tmp != NULL && tmp[0] == '\0')) + tmp = gs_app_get_description (row->app); + + escaped = g_markup_escape_text (tmp, -1); + return g_string_new (escaped); +} + +void +gs_app_addon_row_refresh (GsAppAddonRow *row) +{ + g_autoptr(GString) str = NULL; + + if (row->app == NULL) + return; + + /* join the lines */ + str = gs_app_addon_row_get_summary (row); + as_utils_string_replace (str, "\n", " "); + gtk_label_set_markup (GTK_LABEL (row->description_label), str->str); + gtk_label_set_label (GTK_LABEL (row->name_label), + gs_app_get_name (row->app)); + + /* update the state label */ + switch (gs_app_get_state (row->app)) { + case AS_APP_STATE_QUEUED_FOR_INSTALL: + gtk_widget_set_visible (row->label, TRUE); + gtk_label_set_label (GTK_LABEL (row->label), _("Pending")); + break; + case AS_APP_STATE_UPDATABLE: + case AS_APP_STATE_UPDATABLE_LIVE: + case AS_APP_STATE_INSTALLED: + gtk_widget_set_visible (row->label, TRUE); + gtk_label_set_label (GTK_LABEL (row->label), _("Installed")); + break; + case AS_APP_STATE_INSTALLING: + gtk_widget_set_visible (row->label, TRUE); + gtk_label_set_label (GTK_LABEL (row->label), _("Installing")); + break; + case AS_APP_STATE_REMOVING: + gtk_widget_set_visible (row->label, TRUE); + gtk_label_set_label (GTK_LABEL (row->label), _("Removing")); + break; + default: + gtk_widget_set_visible (row->label, FALSE); + break; + } + + /* update the checkbox */ + g_signal_handlers_block_by_func (row->checkbox, checkbox_toggled, row); + switch (gs_app_get_state (row->app)) { + case AS_APP_STATE_QUEUED_FOR_INSTALL: + gtk_widget_set_sensitive (row->checkbox, TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->checkbox), TRUE); + break; + case AS_APP_STATE_AVAILABLE: + case AS_APP_STATE_AVAILABLE_LOCAL: + gtk_widget_set_sensitive (row->checkbox, TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->checkbox), FALSE); + break; + case AS_APP_STATE_UPDATABLE: + case AS_APP_STATE_INSTALLED: + gtk_widget_set_sensitive (row->checkbox, TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->checkbox), TRUE); + break; + case AS_APP_STATE_INSTALLING: + gtk_widget_set_sensitive (row->checkbox, FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->checkbox), TRUE); + break; + case AS_APP_STATE_REMOVING: + gtk_widget_set_sensitive (row->checkbox, FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->checkbox), FALSE); + break; + default: + gtk_widget_set_sensitive (row->checkbox, FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->checkbox), FALSE); + break; + } + g_signal_handlers_unblock_by_func (row->checkbox, checkbox_toggled, row); +} + +GsApp * +gs_app_addon_row_get_addon (GsAppAddonRow *row) +{ + g_return_val_if_fail (GS_IS_APP_ADDON_ROW (row), NULL); + return row->app; +} + +static gboolean +gs_app_addon_row_refresh_idle (gpointer user_data) +{ + GsAppAddonRow *row = GS_APP_ADDON_ROW (user_data); + + gs_app_addon_row_refresh (row); + + g_object_unref (row); + return G_SOURCE_REMOVE; +} + +static void +gs_app_addon_row_notify_props_changed_cb (GsApp *app, + GParamSpec *pspec, + GsAppAddonRow *row) +{ + g_idle_add (gs_app_addon_row_refresh_idle, g_object_ref (row)); +} + +static void +gs_app_addon_row_set_addon (GsAppAddonRow *row, GsApp *app) +{ + row->app = g_object_ref (app); + + g_signal_connect_object (row->app, "notify::state", + G_CALLBACK (gs_app_addon_row_notify_props_changed_cb), + row, 0); + gs_app_addon_row_refresh (row); +} + +static void +gs_app_addon_row_destroy (GtkWidget *object) +{ + GsAppAddonRow *row = GS_APP_ADDON_ROW (object); + + if (row->app) + g_signal_handlers_disconnect_by_func (row->app, gs_app_addon_row_notify_props_changed_cb, row); + + g_clear_object (&row->app); + + GTK_WIDGET_CLASS (gs_app_addon_row_parent_class)->destroy (object); +} + +static void +gs_app_addon_row_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GsAppAddonRow *row = GS_APP_ADDON_ROW (object); + + switch (prop_id) { + case PROP_SELECTED: + gs_app_addon_row_set_selected (row, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gs_app_addon_row_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GsAppAddonRow *row = GS_APP_ADDON_ROW (object); + + switch (prop_id) { + case PROP_SELECTED: + g_value_set_boolean (value, gs_app_addon_row_get_selected (row)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gs_app_addon_row_class_init (GsAppAddonRowClass *klass) +{ + GParamSpec *pspec; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->set_property = gs_app_addon_row_set_property; + object_class->get_property = gs_app_addon_row_get_property; + + widget_class->destroy = gs_app_addon_row_destroy; + + pspec = g_param_spec_boolean ("selected", NULL, NULL, + FALSE, G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_SELECTED, pspec); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-app-addon-row.ui"); + + gtk_widget_class_bind_template_child (widget_class, GsAppAddonRow, name_label); + gtk_widget_class_bind_template_child (widget_class, GsAppAddonRow, description_label); + gtk_widget_class_bind_template_child (widget_class, GsAppAddonRow, label); + gtk_widget_class_bind_template_child (widget_class, GsAppAddonRow, checkbox); +} + +static void +gs_app_addon_row_init (GsAppAddonRow *row) +{ + gtk_widget_set_has_window (GTK_WIDGET (row), FALSE); + gtk_widget_init_template (GTK_WIDGET (row)); + + g_signal_connect (row->checkbox, "toggled", + G_CALLBACK (checkbox_toggled), row); +} + +void +gs_app_addon_row_set_selected (GsAppAddonRow *row, gboolean selected) +{ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->checkbox), selected); +} + +gboolean +gs_app_addon_row_get_selected (GsAppAddonRow *row) +{ + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (row->checkbox)); +} + +GtkWidget * +gs_app_addon_row_new (GsApp *app) +{ + GtkWidget *row; + + g_return_val_if_fail (GS_IS_APP (app), NULL); + + row = g_object_new (GS_TYPE_APP_ADDON_ROW, NULL); + gs_app_addon_row_set_addon (GS_APP_ADDON_ROW (row), app); + return row; +} |