From 26bae6e6d9a7968bbc2e189bf72c8d1588135dfa Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sun, 24 Jan 2021 13:59:17 -0500 Subject: [PATCH 4/4] info: Better support registered-but-no-subscriptions cases There are cases when the machine can be registered for updates, but not have any active subscriptions. For instance, if the admin runs "subscription-manager register" but fails to pass --auto-attach. As another case, the org may be configured to be in "Simple Content Access" mode where updates don't require specific production subscriptions. This commit tries to accomodate those cases better. If the user is registered, but needs a subscription, the dialog provides a way to attach one. If the user is registered and doesn't need a subscription, the dialog now shows an updated message to reflect that fact. --- panels/info/cc-info-overview-panel.c | 25 +- panels/info/cc-subscription-details-dialog.c | 180 ++++++++++++- panels/info/cc-subscription-details-dialog.ui | 249 +++++++++++++++--- panels/info/info-overview.ui | 35 ++- 4 files changed, 431 insertions(+), 58 deletions(-) diff --git a/panels/info/cc-info-overview-panel.c b/panels/info/cc-info-overview-panel.c index 65246758e..571654fa0 100644 --- a/panels/info/cc-info-overview-panel.c +++ b/panels/info/cc-info-overview-panel.c @@ -49,60 +49,61 @@ #include #endif #include "gsd-disk-space-helper.h" #include "cc-info-overview-panel.h" typedef struct { /* Will be one or 2 GPU name strings, or "Unknown" */ char *hardware_string; } GraphicsData; typedef struct { GtkWidget *system_image; GtkWidget *version_label; GtkWidget *name_entry; GtkWidget *memory_label; GtkWidget *processor_label; GtkWidget *os_name_label; GtkWidget *os_type_label; GtkWidget *disk_label; GtkWidget *graphics_label; GtkWidget *virt_type_label; GtkWidget *subscription_stack; GtkWidget *details_button; GtkWidget *register_button; GtkWidget *updates_separator; GtkWidget *updates_button; + GtkWidget *updates_stack; /* Virtualisation labels */ GtkWidget *label8; GtkWidget *grid1; GtkWidget *label18; char *gnome_version; char *gnome_distributor; char *gnome_date; GCancellable *cancellable; GCancellable *subscription_cancellable; /* Free space */ GList *primary_mounts; guint64 total_bytes; GraphicsData *graphics_data; GDBusProxy *subscription_proxy; } CcInfoOverviewPanelPrivate; struct _CcInfoOverviewPanel { CcPanel parent_instance; /*< private >*/ CcInfoOverviewPanelPrivate *priv; }; @@ -796,72 +797,85 @@ info_overview_panel_setup_overview (CcInfoOverviewPanel *self) os_name_text = get_os_name (); gtk_label_set_text (GTK_LABEL (priv->os_name_label), os_name_text ? os_name_text : ""); get_primary_disc_info (self); gtk_label_set_markup (GTK_LABEL (priv->graphics_label), priv->graphics_data->hardware_string); } static void reload_subscription_status (CcInfoOverviewPanel *self) { CcInfoOverviewPanelPrivate *priv = cc_info_overview_panel_get_instance_private (self); GsdSubmanSubscriptionStatus status; if (priv->subscription_proxy == NULL) { gtk_widget_hide (priv->subscription_stack); return; } if (!get_subscription_status (priv->subscription_proxy, &status)) { gtk_widget_hide (priv->subscription_stack); return; } switch (status) { case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: - case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: - case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: - case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: gtk_stack_set_visible_child_name (GTK_STACK (priv->subscription_stack), "not-registered"); + gtk_stack_set_visible_child_name (GTK_STACK (priv->updates_stack), "no-updates"); gtk_widget_set_sensitive (priv->updates_button, FALSE); break; - + case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: + gtk_stack_set_visible_child_name (GTK_STACK (priv->subscription_stack), "registered"); + gtk_stack_set_visible_child_name (GTK_STACK (priv->updates_stack), "updates"); + gtk_widget_set_sensitive (priv->updates_button, TRUE); + break; case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: + case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: gtk_stack_set_visible_child_name (GTK_STACK (priv->subscription_stack), "registered"); + gtk_stack_set_visible_child_name (GTK_STACK (priv->updates_stack), "updates"); gtk_widget_set_sensitive (priv->updates_button, TRUE); break; - + case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: + gtk_stack_set_visible_child_name (GTK_STACK (priv->subscription_stack), "registered"); + gtk_stack_set_visible_child_name (GTK_STACK (priv->updates_stack), "no-updates"); + gtk_widget_set_sensitive (priv->updates_button, FALSE); + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: + gtk_stack_set_visible_child_name (GTK_STACK (priv->subscription_stack), "not-registered"); + gtk_stack_set_visible_child_name (GTK_STACK (priv->updates_stack), "no-updates"); + gtk_widget_set_sensitive (priv->updates_button, FALSE); + break; default: g_assert_not_reached (); break; } } static void on_details_button_clicked (GtkWidget *widget, CcInfoOverviewPanel *self) { CcInfoOverviewPanelPrivate *priv = cc_info_overview_panel_get_instance_private (self); CcSubscriptionDetailsDialog *dialog; GtkWindow *toplevel; dialog = cc_subscription_details_dialog_new (priv->subscription_proxy, priv->subscription_cancellable); toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (GTK_WIDGET (dialog)); } static void on_register_button_clicked (GtkWidget *widget, CcInfoOverviewPanel *self) { CcInfoOverviewPanelPrivate *priv = cc_info_overview_panel_get_instance_private (self); CcSubscriptionRegisterDialog *dialog; GtkWindow *toplevel; @@ -994,60 +1008,61 @@ cc_info_overview_panel_finalize (GObject *object) G_OBJECT_CLASS (cc_info_overview_panel_parent_class)->finalize (object); } static void cc_info_overview_panel_class_init (CcInfoOverviewPanelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->finalize = cc_info_overview_panel_finalize; object_class->dispose = cc_info_overview_panel_dispose; gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/info/info-overview.ui"); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, system_image); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, version_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, name_entry); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, memory_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, processor_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, os_name_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, os_type_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, disk_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, graphics_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, virt_type_label); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, subscription_stack); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, details_button); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, register_button); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, updates_separator); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, updates_button); + gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, updates_stack); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, label8); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, grid1); gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, label18); g_type_ensure (CC_TYPE_HOSTNAME_ENTRY); } static void cc_info_overview_panel_init (CcInfoOverviewPanel *self) { CcInfoOverviewPanelPrivate *priv = cc_info_overview_panel_get_instance_private (self); gtk_widget_init_template (GTK_WIDGET (self)); g_resources_register (cc_info_get_resource ()); priv->cancellable = g_cancellable_new (); priv->subscription_cancellable = g_cancellable_new (); priv->graphics_data = get_graphics_data (); if (does_gnome_software_exist () || does_gpk_update_viewer_exist ()) g_signal_connect (priv->updates_button, "clicked", G_CALLBACK (on_updates_button_clicked), self); else gtk_widget_hide (priv->updates_button); info_overview_panel_setup_overview (self); info_overview_panel_setup_virt (self); info_overview_panel_setup_subscriptions (self); diff --git a/panels/info/cc-subscription-details-dialog.c b/panels/info/cc-subscription-details-dialog.c index 3d77e6c48..f8e70d751 100644 --- a/panels/info/cc-subscription-details-dialog.c +++ b/panels/info/cc-subscription-details-dialog.c @@ -1,420 +1,578 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright 2019 Red Hat, Inc, * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Written by: Kalev Lember */ #include "config.h" #include #include #include #include "cc-subscription-details-dialog.h" +#include "cc-subscription-common.h" #define DBUS_TIMEOUT 300000 /* 5 minutes */ typedef enum { DIALOG_STATE_SHOW_DETAILS, + DIALOG_STATE_SUBSCRIBE, + DIALOG_STATE_SUBSCRIBING, DIALOG_STATE_UNREGISTER, DIALOG_STATE_UNREGISTERING } DialogState; struct _CcSubscriptionDetailsDialog { GtkDialog parent_instance; DialogState state; GCancellable *cancellable; GDBusProxy *subscription_proxy; GPtrArray *products; /* template widgets */ GtkButton *back_button; GtkSpinner *spinner; + GtkStack *header_stack; + GtkButton *header_subscribe_button; GtkButton *header_unregister_button; GtkRevealer *notification_revealer; GtkLabel *error_label; GtkStack *stack; + GtkStack *status_stack; GtkBox *products_box1; GtkBox *products_box2; + GtkBox *products_box3; + GtkButton *subscribe_button; + GtkSeparator *separator; GtkButton *unregister_button; }; G_DEFINE_TYPE (CcSubscriptionDetailsDialog, cc_subscription_details_dialog, GTK_TYPE_DIALOG); +static void reload_installed_products (CcSubscriptionDetailsDialog *self); + typedef struct { gchar *product_name; gchar *product_id; gchar *version; gchar *arch; gchar *status; gchar *starts; gchar *ends; } ProductData; static void product_data_free (ProductData *product) { g_free (product->product_name); g_free (product->product_id); g_free (product->version); g_free (product->arch); g_free (product->status); g_free (product->starts); g_free (product->ends); g_free (product); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free); static void add_product_row (GtkGrid *product_grid, const gchar *name, const gchar *value, gint top_attach) { GtkWidget *w; w = gtk_label_new (name); gtk_style_context_add_class (gtk_widget_get_style_context (w), "dim-label"); gtk_grid_attach (product_grid, w, 0, top_attach, 1, 1); gtk_widget_set_halign (w, GTK_ALIGN_END); gtk_widget_show (w); if (value == NULL) value = _("Unknown"); w = gtk_label_new (value); gtk_grid_attach (product_grid, w, 1, top_attach, 1, 1); gtk_widget_set_halign (w, GTK_ALIGN_START); gtk_widget_set_hexpand (w, TRUE); gtk_widget_show (w); } static GtkWidget * -add_product (CcSubscriptionDetailsDialog *self, ProductData *product) +add_product (CcSubscriptionDetailsDialog *self, ProductData *product, GsdSubmanSubscriptionStatus status) { GtkGrid *product_grid; const gchar *status_text; if (g_strcmp0 (product->status, "subscribed") == 0) status_text = _("Subscribed"); + else if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED) + status_text = _("No Specific Subscription"); else - status_text = _("Not Subscribed (Not supported by a valid subscription.)"); + status_text = _("Not Subscribed"); product_grid = GTK_GRID (gtk_grid_new ()); gtk_grid_set_column_spacing (product_grid, 12); gtk_grid_set_row_spacing (product_grid, 6); gtk_widget_set_margin_top (GTK_WIDGET (product_grid), 18); gtk_widget_set_margin_bottom (GTK_WIDGET (product_grid), 12); gtk_widget_show (GTK_WIDGET (product_grid)); add_product_row (product_grid, _("Product Name"), product->product_name, 0); add_product_row (product_grid, _("Product ID"), product->product_id, 1); add_product_row (product_grid, _("Version"), product->version, 2); add_product_row (product_grid, _("Arch"), product->arch, 3); add_product_row (product_grid, _("Status"), status_text, 4); - add_product_row (product_grid, _("Starts"), product->starts, 5); - add_product_row (product_grid, _("Ends"), product->ends, 6); + + if (product->starts[0] != '\0' && product->ends[0] != '\0') + { + add_product_row (product_grid, _("Starts"), product->starts, 5); + add_product_row (product_grid, _("Ends"), product->ends, 6); + } return GTK_WIDGET (product_grid); } static void remove_all_children (GtkContainer *container) { g_autoptr(GList) list = gtk_container_get_children (container); for (GList *l = list; l != NULL; l = l->next) gtk_container_remove (container, (GtkWidget *) l->data); } static void dialog_reload (CcSubscriptionDetailsDialog *self) { GtkHeaderBar *header = GTK_HEADER_BAR (gtk_dialog_get_header_bar (GTK_DIALOG (self))); + GsdSubmanSubscriptionStatus status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; + + reload_installed_products (self); switch (self->state) { case DIALOG_STATE_SHOW_DETAILS: gtk_header_bar_set_show_close_button (header, TRUE); gtk_window_set_title (GTK_WINDOW (self), _("Registration Details")); gtk_widget_set_sensitive (GTK_WIDGET (self->header_unregister_button), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (self->header_subscribe_button), TRUE); gtk_widget_hide (GTK_WIDGET (self->back_button)); - gtk_widget_hide (GTK_WIDGET (self->header_unregister_button)); + gtk_widget_hide (GTK_WIDGET (self->header_stack)); gtk_stack_set_visible_child_name (self->stack, "show-details"); break; + case DIALOG_STATE_SUBSCRIBE: + gtk_header_bar_set_show_close_button (header, FALSE); + gtk_stack_set_visible_child_name (self->header_stack, "subscribe"); + gtk_window_set_title (GTK_WINDOW (self), _("Subscribe System")); + gtk_widget_set_sensitive (GTK_WIDGET (self->header_subscribe_button), TRUE); + + gtk_widget_show (GTK_WIDGET (self->back_button)); + + gtk_stack_set_visible_child_name (self->header_stack, "subscribe"); + gtk_widget_show (GTK_WIDGET (self->header_stack)); + + gtk_stack_set_visible_child_name (self->stack, "subscribe"); + break; + + case DIALOG_STATE_SUBSCRIBING: + gtk_header_bar_set_show_close_button (header, FALSE); + gtk_window_set_title (GTK_WINDOW (self), _("Looking For Available Subscriptions…")); + gtk_widget_set_sensitive (GTK_WIDGET (self->header_subscribe_button), FALSE); + + gtk_widget_show (GTK_WIDGET (self->back_button)); + + gtk_stack_set_visible_child_name (self->header_stack, "subscribe"); + gtk_widget_show (GTK_WIDGET (self->header_stack)); + + gtk_stack_set_visible_child_name (self->stack, "subscribe"); + break; + case DIALOG_STATE_UNREGISTER: gtk_header_bar_set_show_close_button (header, FALSE); gtk_window_set_title (GTK_WINDOW (self), _("Unregister System")); gtk_widget_set_sensitive (GTK_WIDGET (self->header_unregister_button), TRUE); gtk_widget_show (GTK_WIDGET (self->back_button)); - gtk_widget_show (GTK_WIDGET (self->header_unregister_button)); + + gtk_stack_set_visible_child_name (self->header_stack, "unregister"); + gtk_widget_show (GTK_WIDGET (self->header_stack)); gtk_stack_set_visible_child_name (self->stack, "unregister"); break; case DIALOG_STATE_UNREGISTERING: gtk_header_bar_set_show_close_button (header, FALSE); gtk_window_set_title (GTK_WINDOW (self), _("Unregistering System…")); gtk_widget_set_sensitive (GTK_WIDGET (self->header_unregister_button), FALSE); gtk_widget_show (GTK_WIDGET (self->back_button)); - gtk_widget_show (GTK_WIDGET (self->header_unregister_button)); + + gtk_stack_set_visible_child_name (self->header_stack, "unregister"); + gtk_widget_show (GTK_WIDGET (self->header_stack)); gtk_stack_set_visible_child_name (self->stack, "unregister"); break; default: g_assert_not_reached (); break; } remove_all_children (GTK_CONTAINER (self->products_box1)); remove_all_children (GTK_CONTAINER (self->products_box2)); + remove_all_children (GTK_CONTAINER (self->products_box3)); if (self->products == NULL || self->products->len == 0) { /* the widgets are duplicate to allow sliding between two stack pages */ GtkWidget *w1 = gtk_label_new (_("No installed products detected.")); GtkWidget *w2 = gtk_label_new (_("No installed products detected.")); + GtkWidget *w3 = gtk_label_new (_("No installed products detected.")); gtk_widget_show (w1); gtk_widget_show (w2); + gtk_widget_show (w3); gtk_container_add (GTK_CONTAINER (self->products_box1), w1); gtk_container_add (GTK_CONTAINER (self->products_box2), w2); + gtk_container_add (GTK_CONTAINER (self->products_box3), w3); + gtk_stack_set_visible_child_name (self->status_stack, "no-installed-products"); + + gtk_widget_hide (GTK_WIDGET (self->subscribe_button)); + gtk_widget_hide (GTK_WIDGET (self->separator)); return; } + get_subscription_status (self->subscription_proxy, &status); + for (guint i = 0; i < self->products->len; i++) { ProductData *product = g_ptr_array_index (self->products, i); /* the widgets are duplicate to allow sliding between two stack pages */ - GtkWidget *w1 = add_product (self, product); - GtkWidget *w2 = add_product (self, product); + GtkWidget *w1 = add_product (self, product, status); + GtkWidget *w2 = add_product (self, product, status); + GtkWidget *w3 = add_product (self, product, status); gtk_container_add (GTK_CONTAINER (self->products_box1), w1); gtk_container_add (GTK_CONTAINER (self->products_box2), w2); + gtk_container_add (GTK_CONTAINER (self->products_box3), w3); } + + switch (status) + { + case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: + gtk_stack_set_visible_child_name (self->status_stack, "fully-subscribed"); + gtk_widget_hide (GTK_WIDGET (self->subscribe_button)); + break; + + case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: + gtk_stack_set_visible_child_name (self->status_stack, "partly-subscribed"); + gtk_widget_show (GTK_WIDGET (self->subscribe_button)); + break; + + case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: + gtk_stack_set_visible_child_name (self->status_stack, "subscription-not-needed"); + gtk_widget_hide (GTK_WIDGET (self->subscribe_button)); + break; + + case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: + default: + gtk_stack_set_visible_child_name (self->status_stack, "not-subscribed"); + gtk_widget_show (GTK_WIDGET (self->subscribe_button)); + break; + } + + gtk_widget_set_visible (GTK_WIDGET (self->separator), + gtk_widget_get_visible (GTK_WIDGET (self->subscribe_button))); + } static ProductData * parse_product_variant (GVariant *product_variant) { g_autoptr(ProductData) product = g_new0 (ProductData, 1); g_auto(GVariantDict) dict; g_variant_dict_init (&dict, product_variant); g_variant_dict_lookup (&dict, "product-name", "s", &product->product_name); g_variant_dict_lookup (&dict, "product-id", "s", &product->product_id); g_variant_dict_lookup (&dict, "version", "s", &product->version); g_variant_dict_lookup (&dict, "arch", "s", &product->arch); g_variant_dict_lookup (&dict, "status", "s", &product->status); g_variant_dict_lookup (&dict, "starts", "s", &product->starts); g_variant_dict_lookup (&dict, "ends", "s", &product->ends); return g_steal_pointer (&product); } static void -load_installed_products (CcSubscriptionDetailsDialog *self) +reload_installed_products (CcSubscriptionDetailsDialog *self) { GVariantIter iter_array; GVariant *child; g_autoptr(GError) error = NULL; g_autoptr(GVariant) installed_products_variant = NULL; installed_products_variant = g_dbus_proxy_get_cached_property (self->subscription_proxy, "InstalledProducts"); if (installed_products_variant == NULL) { g_debug ("Unable to get InstalledProducts dbus property"); return; } g_ptr_array_set_size (self->products, 0); g_variant_iter_init (&iter_array, installed_products_variant); while ((child = g_variant_iter_next_value (&iter_array)) != NULL) { g_autoptr(GVariant) product_variant = g_steal_pointer (&child); g_ptr_array_add (self->products, parse_product_variant (product_variant)); } } +static void +subscription_done_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) user_data; + g_autoptr(GVariant) results = NULL; + g_autoptr(GError) error = NULL; + + results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), + res, + &error); + if (results == NULL) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_dbus_error_strip_remote_error (error); + gtk_label_set_text (self->error_label, error->message); + gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); + + gtk_spinner_stop (self->spinner); + + self->state = DIALOG_STATE_SUBSCRIBE; + dialog_reload (self); + return; + } + + gtk_spinner_stop (self->spinner); + + self->state = DIALOG_STATE_SHOW_DETAILS; + dialog_reload (self); +} + +static void +header_subscribe_button_clicked_cb (CcSubscriptionDetailsDialog *self) +{ + gtk_spinner_start (self->spinner); + + self->state = DIALOG_STATE_SUBSCRIBING; + dialog_reload (self); + + g_dbus_proxy_call (self->subscription_proxy, + "Attach", + NULL, + G_DBUS_CALL_FLAGS_NONE, + DBUS_TIMEOUT, + self->cancellable, + subscription_done_cb, + self); +} + static void unregistration_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) user_data; g_autoptr(GVariant) results = NULL; g_autoptr(GError) error = NULL; results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (results == NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; g_dbus_error_strip_remote_error (error); gtk_label_set_text (self->error_label, error->message); gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); gtk_spinner_stop (self->spinner); self->state = DIALOG_STATE_UNREGISTER; dialog_reload (self); return; } gtk_spinner_stop (self->spinner); gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT); } static void header_unregister_button_clicked_cb (CcSubscriptionDetailsDialog *self) { gtk_spinner_start (self->spinner); self->state = DIALOG_STATE_UNREGISTERING; dialog_reload (self); g_dbus_proxy_call (self->subscription_proxy, "Unregister", NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, self->cancellable, unregistration_done_cb, self); } static void back_button_clicked_cb (CcSubscriptionDetailsDialog *self) { gtk_spinner_stop (self->spinner); self->state = DIALOG_STATE_SHOW_DETAILS; dialog_reload (self); } +static void +subscribe_button_clicked_cb (CcSubscriptionDetailsDialog *self) +{ + self->state = DIALOG_STATE_SUBSCRIBE; + dialog_reload (self); +} + static void unregister_button_clicked_cb (CcSubscriptionDetailsDialog *self) { self->state = DIALOG_STATE_UNREGISTER; dialog_reload (self); } static void dismiss_notification (CcSubscriptionDetailsDialog *self) { gtk_revealer_set_reveal_child (self->notification_revealer, FALSE); } static void cc_subscription_details_dialog_init (CcSubscriptionDetailsDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); self->products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); self->state = DIALOG_STATE_SHOW_DETAILS; } static void cc_subscription_details_dialog_dispose (GObject *obj) { CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) obj; g_cancellable_cancel (self->cancellable); g_clear_object (&self->cancellable); g_clear_object (&self->subscription_proxy); G_OBJECT_CLASS (cc_subscription_details_dialog_parent_class)->dispose (obj); } static void cc_subscription_details_dialog_finalize (GObject *obj) { CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) obj; g_clear_pointer (&self->products, g_ptr_array_unref); G_OBJECT_CLASS (cc_subscription_details_dialog_parent_class)->finalize (obj); } static void cc_subscription_details_dialog_class_init (CcSubscriptionDetailsDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = cc_subscription_details_dialog_dispose; object_class->finalize = cc_subscription_details_dialog_finalize; gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/info/cc-subscription-details-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, back_button); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, spinner); + gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, header_stack); + gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, header_subscribe_button); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, header_unregister_button); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, notification_revealer); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, error_label); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, stack); + gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, status_stack); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, products_box1); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, products_box2); + gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, products_box3); + gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, subscribe_button); + gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, separator); gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, unregister_button); gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, header_subscribe_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, header_unregister_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, subscribe_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, unregister_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, dismiss_notification); } static void on_dialog_cancelled (CcSubscriptionDetailsDialog *self) { gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CLOSE); } CcSubscriptionDetailsDialog * cc_subscription_details_dialog_new (GDBusProxy *subscription_proxy, GCancellable *cancellable) { CcSubscriptionDetailsDialog *self; self = g_object_new (CC_TYPE_SUBSCRIPTION_DETAILS_DIALOG, "use-header-bar", TRUE, NULL); self->subscription_proxy = g_object_ref (subscription_proxy); self->cancellable = g_object_ref (cancellable); g_signal_connect_object (G_OBJECT (self->cancellable), "cancelled", G_CALLBACK (on_dialog_cancelled), self, G_CONNECT_SWAPPED); - load_installed_products (self); dialog_reload (self); return self; } diff --git a/panels/info/cc-subscription-details-dialog.ui b/panels/info/cc-subscription-details-dialog.ui index 6f0b16930..6cdfc1220 100644 --- a/panels/info/cc-subscription-details-dialog.ui +++ b/panels/info/cc-subscription-details-dialog.ui @@ -6,75 +6,106 @@ True True dialog Registration Details 1 True False False True True True center True False go-previous-symbolic - - _Unregister + True - True - True - True - True - False - True - center - - + False + slide-left-right + + + _Unregister + True + True + True + True + True + False + True + center + + + + + unregister + + + + + _Subscribe + True + True + True + True + True + False + True + center + + + + + subscribe + + end True False center 6 6 end True False vertical 0 True @@ -120,129 +151,275 @@ Unable to reach developers.redhat.com. Please try again later. True start True window-close-symbolic True False slide-left-right + + + True + vertical + 24 + 32 + 12 + 12 + + + True + False + + + True + False + This system is subscribed to receive software updates. + 45 + 45 + 0 + start + True + + + + fully-subscribed + + + + + True + False + This system lacks subscriptions to receive updates for some installed software. + 45 + 45 + 0 + start + True + + + + partly-subscribed + + + + + True + False + This system lacks subscriptions to receive software updates. + 45 + 45 + 0 + start + True + + + + not-subscribed + + + + + True + False + This system is registered to receive software updates. + 45 + 45 + 0 + start + True + + + + subscription-not-needed + + + + + True + False + This system has no supported software installed. + 45 + 45 + 0 + start + True + + + + no-installed-products + + + + + + + True + vertical + True + 6 + 6 + + + + + True + False + horizontal + 12 + end + + + _Unregister… + True + True + True + False + end + True + + + + + + + True + + + + + _Subscribe… + True + True + True + False + end + True + + + + + + + + + show-details + + True vertical 24 32 32 20 True False - Registration with Red Hat allows this system to receive software updates. + Subscribing with Red Hat will allow this system to receive software updates. 45 45 0 start True - - + True vertical 6 6 True - - - _Unregister… - True - True - True - False - end - True - - - - - show-details + subscribe True vertical 24 32 32 20 True False Warning: unregistering this system will result in it no longer receiving software updates. 45 45 0 start True - + True vertical 6 6 True unregister False True 0 diff --git a/panels/info/info-overview.ui b/panels/info/info-overview.ui index e33ba399a..3ed79712a 100644 --- a/panels/info/info-overview.ui +++ b/panels/info/info-overview.ui @@ -366,68 +366,91 @@ not-registered True False horizontal 12 True False vertical True False 0 Registered System - + True False - 0 - System is registered and able to receive software updates. - - - + + + True + False + 0 + System is registered and able to receive software updates. + + + + + + updates + + + + + True + False + 0 + System is registered but is unable to receive all software updates. + + + + + + no-updates + + _Details True True True False True end True registered True -- 2.28.0