summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKalev Lember <klember@redhat.com>2019-06-28 17:14:36 +0200
committerKalev Lember <klember@redhat.com>2019-06-28 19:53:26 +0200
commit0ce01af0e0e58d81f998093f5a8a068539f56c12 (patch)
treedf31b3dd97e45493366786f463a7540f431f3091
parent8b75602f6feef48e45d30bafd324814c01534ca7 (diff)
downloadgnome-control-center-wip/kalev/subscription-manager.tar.gz
info: Add subscription manager integrationwip/kalev/subscription-manager
-rw-r--r--panels/info/cc-info-overview-panel.c157
-rw-r--r--panels/info/cc-subscription-details-dialog.c407
-rw-r--r--panels/info/cc-subscription-details-dialog.h32
-rw-r--r--panels/info/cc-subscription-details-dialog.ui248
-rw-r--r--panels/info/cc-subscription-register-dialog.c403
-rw-r--r--panels/info/cc-subscription-register-dialog.h32
-rw-r--r--panels/info/cc-subscription-register-dialog.ui623
-rw-r--r--panels/info/info-overview.ui138
-rw-r--r--panels/info/info.gresource.xml2
-rw-r--r--panels/info/meson.build4
-rw-r--r--po/POTFILES.in4
11 files changed, 2038 insertions, 12 deletions
diff --git a/panels/info/cc-info-overview-panel.c b/panels/info/cc-info-overview-panel.c
index 2256b730c..1467060f9 100644
--- a/panels/info/cc-info-overview-panel.c
+++ b/panels/info/cc-info-overview-panel.c
@@ -24,6 +24,8 @@
#include "shell/cc-hostname-entry.h"
#include "cc-info-resources.h"
+#include "cc-subscription-details-dialog.h"
+#include "cc-subscription-register-dialog.h"
#include "info-cleanup.h"
#include <glib.h>
@@ -68,6 +70,10 @@ typedef struct
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;
/* Virtualisation labels */
@@ -86,6 +92,8 @@ typedef struct
guint64 total_bytes;
GraphicsData *graphics_data;
+
+ GDBusProxy *subscription_proxy;
} CcInfoOverviewPanelPrivate;
struct _CcInfoOverviewPanel
@@ -586,7 +594,6 @@ get_primary_disc_info (CcInfoOverviewPanel *self)
g_list_free (points);
g_hash_table_destroy (hash);
- priv->cancellable = g_cancellable_new ();
get_primary_disc_info_start (self);
}
@@ -793,6 +800,137 @@ info_overview_panel_setup_overview (CcInfoOverviewPanel *self)
gtk_label_set_markup (GTK_LABEL (priv->graphics_label), priv->graphics_data->hardware_string);
}
+typedef enum {
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN,
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID,
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID,
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED,
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID,
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST
+} GsdSubmanSubscriptionStatus;
+
+static gboolean
+get_subscription_status (CcInfoOverviewPanel *self, GsdSubmanSubscriptionStatus *status)
+{
+ CcInfoOverviewPanelPrivate *priv = cc_info_overview_panel_get_instance_private (self);
+ g_autoptr(GVariant) status_variant = NULL;
+ guint32 u;
+
+ status_variant = g_dbus_proxy_get_cached_property (priv->subscription_proxy, "SubscriptionStatus");
+ if (!status_variant)
+ {
+ g_debug ("Unable to get SubscriptionStatus property");
+ return FALSE;
+ }
+
+ g_variant_get (status_variant, "u", &u);
+ *status = u;
+
+ return TRUE;
+}
+
+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 (self, &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_widget_set_sensitive (priv->updates_button, FALSE);
+ break;
+
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID:
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->subscription_stack), "registered");
+ gtk_widget_set_sensitive (priv->updates_button, TRUE);
+ 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);
+ 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));
+
+ reload_subscription_status (self);
+}
+
+static void
+on_register_button_clicked (GtkWidget *widget,
+ CcInfoOverviewPanel *self)
+{
+ CcInfoOverviewPanelPrivate *priv = cc_info_overview_panel_get_instance_private (self);
+ CcSubscriptionRegisterDialog *dialog;
+ GtkWindow *toplevel;
+
+ dialog = cc_subscription_register_dialog_new (priv->subscription_proxy);
+ 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));
+
+ reload_subscription_status (self);
+}
+
+static void
+info_overview_panel_setup_subscriptions (CcInfoOverviewPanel *self)
+{
+ CcInfoOverviewPanelPrivate *priv = cc_info_overview_panel_get_instance_private (self);
+ g_autoptr(GError) error = NULL;
+
+ priv->subscription_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.SettingsDaemon.Subscription",
+ "/org/gnome/SettingsDaemon/Subscription",
+ "org.gnome.SettingsDaemon.Subscription",
+ NULL, &error);
+ if (error != NULL)
+ {
+ g_debug ("Unable to create a proxy for org.gnome.SettingsDaemon.Subscription: %s",
+ error->message);
+ reload_subscription_status (self);
+ return;
+ }
+
+ g_signal_connect (priv->details_button, "clicked", G_CALLBACK (on_details_button_clicked), self);
+ g_signal_connect (priv->register_button, "clicked", G_CALLBACK (on_register_button_clicked), self);
+
+ reload_subscription_status (self);
+}
+
static gboolean
does_gnome_software_exist (void)
{
@@ -856,6 +994,8 @@ cc_info_overview_panel_finalize (GObject *object)
g_free (priv->gnome_date);
g_free (priv->gnome_distributor);
+ g_clear_object (&priv->subscription_proxy);
+
G_OBJECT_CLASS (cc_info_overview_panel_parent_class)->finalize (object);
}
@@ -880,6 +1020,10 @@ cc_info_overview_panel_class_init (CcInfoOverviewPanelClass *klass)
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, label8);
gtk_widget_class_bind_template_child_private (widget_class, CcInfoOverviewPanel, grid1);
@@ -897,15 +1041,24 @@ cc_info_overview_panel_init (CcInfoOverviewPanel *self)
g_resources_register (cc_info_get_resource ());
+ priv->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_destroy (priv->updates_button);
+ gtk_widget_hide (priv->updates_button);
info_overview_panel_setup_overview (self);
info_overview_panel_setup_virt (self);
+ info_overview_panel_setup_subscriptions (self);
+
+ /* show separator when both items are visible */
+ if (gtk_widget_get_visible (priv->subscription_stack) && gtk_widget_get_visible (priv->updates_button))
+ gtk_widget_show (priv->updates_separator);
+ else
+ gtk_widget_hide (priv->updates_separator);
}
GtkWidget *
diff --git a/panels/info/cc-subscription-details-dialog.c b/panels/info/cc-subscription-details-dialog.c
new file mode 100644
index 000000000..1931ced81
--- /dev/null
+++ b/panels/info/cc-subscription-details-dialog.c
@@ -0,0 +1,407 @@
+/* -*- 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 <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Kalev Lember <klember@redhat.com>
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "cc-subscription-details-dialog.h"
+
+#define DBUS_TIMEOUT 300000 /* 5 minutes */
+
+typedef enum {
+ DIALOG_STATE_SHOW_DETAILS,
+ 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;
+ GtkButton *header_unregister_button;
+ GtkRevealer *notification_revealer;
+ GtkLabel *error_label;
+ GtkStack *stack;
+ GtkBox *products_box1;
+ GtkBox *products_box2;
+ GtkButton *unregister_button;
+};
+
+G_DEFINE_TYPE (CcSubscriptionDetailsDialog, cc_subscription_details_dialog, GTK_TYPE_DIALOG);
+
+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)
+{
+ GtkGrid *product_grid;
+ const gchar *status_text;
+
+ if (g_strcmp0 (product->status, "subscribed") == 0)
+ status_text = _("Subscribed");
+ else
+ status_text = _("Not Subscribed (Not supported by a valid subscription.)");
+
+ 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);
+
+ 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)));
+
+ 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_hide (GTK_WIDGET (self->back_button));
+ gtk_widget_hide (GTK_WIDGET (self->header_unregister_button));
+
+ gtk_stack_set_visible_child_name (self->stack, "show-details");
+ 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->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->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));
+
+ 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."));
+ gtk_widget_show (w1);
+ gtk_widget_show (w2);
+ gtk_container_add (GTK_CONTAINER (self->products_box1), w1);
+ gtk_container_add (GTK_CONTAINER (self->products_box2), w2);
+ return;
+ }
+
+ 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);
+ gtk_container_add (GTK_CONTAINER (self->products_box1), w1);
+ gtk_container_add (GTK_CONTAINER (self->products_box2), w2);
+ }
+}
+
+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)
+{
+ 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
+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
+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->cancellable = g_cancellable_new ();
+ 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_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, products_box1);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, products_box2);
+ 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_unregister_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);
+}
+
+CcSubscriptionDetailsDialog *
+cc_subscription_details_dialog_new (GDBusProxy *subscription_proxy)
+{
+ CcSubscriptionDetailsDialog *self;
+
+ self = g_object_new (CC_TYPE_SUBSCRIPTION_DETAILS_DIALOG, "use-header-bar", TRUE, NULL);
+ self->subscription_proxy = g_object_ref (subscription_proxy);
+
+ load_installed_products (self);
+ dialog_reload (self);
+
+ return self;
+}
diff --git a/panels/info/cc-subscription-details-dialog.h b/panels/info/cc-subscription-details-dialog.h
new file mode 100644
index 000000000..a61a22838
--- /dev/null
+++ b/panels/info/cc-subscription-details-dialog.h
@@ -0,0 +1,32 @@
+/* -*- 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 <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Kalev Lember <klember@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SUBSCRIPTION_DETAILS_DIALOG (cc_subscription_details_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcSubscriptionDetailsDialog, cc_subscription_details_dialog, CC, SUBSCRIPTION_DETAILS_DIALOG, GtkDialog)
+
+CcSubscriptionDetailsDialog *cc_subscription_details_dialog_new (GDBusProxy *subscription_proxy);
+
+G_END_DECLS
diff --git a/panels/info/cc-subscription-details-dialog.ui b/panels/info/cc-subscription-details-dialog.ui
new file mode 100644
index 000000000..6f0b16930
--- /dev/null
+++ b/panels/info/cc-subscription-details-dialog.ui
@@ -0,0 +1,248 @@
+<?xml version="1.0"?>
+<interface>
+ <template class="CcSubscriptionDetailsDialog" parent="GtkDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="title" translatable="yes">Registration Details</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_close_button">False</property>
+ <child>
+ <object class="GtkButton" id="back_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="back_button_clicked_cb" object="CcSubscriptionDetailsDialog" swapped="yes"/>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="header_unregister_button">
+ <property name="label" translatable="yes">_Unregister</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="header_unregister_button_clicked_cb" object="CcSubscriptionDetailsDialog" swapped="yes"/>
+ <style>
+ <class name="text-button"/>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="border_width">0</property>
+ <child>
+ <object class="GtkOverlay" id="overlay">
+ <property name="visible">True</property>
+ <child type="overlay">
+ <object class="GtkRevealer" id="notification_revealer">
+ <property name="visible">True</property>
+ <property name="halign">fill</property>
+ <property name="hexpand">True</property>
+ <property name="margin_start">20</property>
+ <property name="margin_end">20</property>
+ <property name="valign">start</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <style>
+ <class name="app-notification"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="hexpand">True</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Failed to Unregister System</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="error_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="label">Unable to reach developers.redhat.com. Please try again later.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="dismiss_button">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <signal name="clicked" handler="dismiss_notification" object="CcSubscriptionDetailsDialog" swapped="yes"/>
+ <style>
+ <class name="flat"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">window-close-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="transition-type">slide-left-right</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin_top">24</property>
+ <property name="margin_start">32</property>
+ <property name="margin_end">32</property>
+ <property name="margin_bottom">20</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Registration with Red Hat allows this system to receive software updates.</property>
+ <property name="width_chars">45</property>
+ <property name="max_width_chars">45</property>
+ <property name="xalign">0</property>
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="products_box1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="unregister_button">
+ <property name="label" translatable="yes">_Unregister…</property>
+ <property name="can_focus">True</property>
+ <property name="use_underline">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="halign">end</property>
+ <property name="visible">True</property>
+ <signal name="clicked" handler="unregister_button_clicked_cb" object="CcSubscriptionDetailsDialog" swapped="yes"/>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">show-details</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin_top">24</property>
+ <property name="margin_start">32</property>
+ <property name="margin_end">32</property>
+ <property name="margin_bottom">20</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Warning: unregistering this system will result in it no longer receiving software updates.</property>
+ <property name="width_chars">45</property>
+ <property name="max_width_chars">45</property>
+ <property name="xalign">0</property>
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="products_box2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">unregister</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/info/cc-subscription-register-dialog.c b/panels/info/cc-subscription-register-dialog.c
new file mode 100644
index 000000000..d7a17cc99
--- /dev/null
+++ b/panels/info/cc-subscription-register-dialog.c
@@ -0,0 +1,403 @@
+/* -*- 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 <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Kalev Lember <klember@redhat.com>
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "cc-subscription-register-dialog.h"
+
+#define DBUS_TIMEOUT 300000 /* 5 minutes */
+#define SERVER_URL "subscription.rhsm.redhat.com"
+
+typedef enum {
+ DIALOG_STATE_REGISTER,
+ DIALOG_STATE_REGISTERING
+} DialogState;
+
+static void dialog_validate (CcSubscriptionRegisterDialog *self);
+
+struct _CcSubscriptionRegisterDialog
+{
+ GtkDialog parent_instance;
+
+ DialogState state;
+ GCancellable *cancellable;
+ GDBusProxy *subscription_proxy;
+ gboolean valid;
+
+ /* template widgets */
+ GtkSpinner *spinner;
+ GtkButton *register_button;
+ GtkRevealer *notification_revealer;
+ GtkLabel *error_label;
+ GtkRadioButton *default_url_radio;
+ GtkRadioButton *custom_url_radio;
+ GtkRadioButton *register_radio;
+ GtkRadioButton *register_with_activation_keys_radio;
+ GtkStack *stack;
+ GtkGrid *register_grid;
+ GtkGrid *register_with_activation_keys_grid;
+ GtkEntry *url_label;
+ GtkEntry *url_entry;
+ GtkEntry *login_entry;
+ GtkEntry *password_entry;
+ GtkEntry *activation_keys_entry;
+ GtkLabel *organization_label;
+ GtkEntry *organization_entry;
+ GtkEntry *organization_entry_with_activation_keys;
+};
+
+G_DEFINE_TYPE (CcSubscriptionRegisterDialog, cc_subscription_register_dialog, GTK_TYPE_DIALOG);
+
+static void
+dialog_reload (CcSubscriptionRegisterDialog *self)
+{
+ gboolean sensitive;
+ gboolean url_entry_enabled;
+
+ switch (self->state)
+ {
+ case DIALOG_STATE_REGISTER:
+ gtk_window_set_title (GTK_WINDOW (self), _("Register System"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->register_button), self->valid);
+
+ sensitive = TRUE;
+ break;
+
+ case DIALOG_STATE_REGISTERING:
+ gtk_window_set_title (GTK_WINDOW (self), _("Registering System…"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->register_button), FALSE);
+
+ sensitive = FALSE;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ url_entry_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->custom_url_radio));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->url_entry), sensitive && url_entry_enabled);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->default_url_radio), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->custom_url_radio), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->register_radio), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->register_with_activation_keys_radio), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->login_entry), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->password_entry), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->activation_keys_entry), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->password_entry), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->organization_entry), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->organization_entry_with_activation_keys), sensitive);
+}
+
+static void
+custom_url_radio_toggled_cb (CcSubscriptionRegisterDialog *self)
+{
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->custom_url_radio));
+ if (active)
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->url_entry), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->url_label), TRUE);
+
+ gtk_entry_set_text (self->url_entry, "");
+ gtk_widget_grab_focus (GTK_WIDGET (self->url_entry));
+ }
+ else
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->url_entry), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->url_label), FALSE);
+
+ gtk_entry_set_text (self->url_entry, SERVER_URL);
+ }
+
+ dialog_validate (self);
+}
+
+static void
+register_with_activation_keys_radio_toggled_cb (CcSubscriptionRegisterDialog *self)
+{
+ gint active;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->register_with_activation_keys_radio));
+ if (active)
+ {
+ gtk_stack_set_visible_child_name (self->stack, "register-with-activation-keys");
+ gtk_widget_grab_focus (GTK_WIDGET (self->activation_keys_entry));
+ }
+ else
+ {
+ gtk_stack_set_visible_child_name (self->stack, "register");
+ gtk_widget_grab_focus (GTK_WIDGET (self->login_entry));
+ }
+
+ dialog_validate (self);
+}
+
+static void
+dialog_validate (CcSubscriptionRegisterDialog *self)
+{
+ gboolean valid_url = TRUE;
+ gboolean valid_login = TRUE;
+ gboolean valid_password = TRUE;
+ gboolean valid_activation_keys = TRUE;
+ gboolean valid_organization = TRUE;
+
+ /* require url when custom url radio is selected */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->custom_url_radio)))
+ {
+ const gchar *url;
+
+ url = gtk_entry_get_text (self->url_entry);
+ valid_url = url != NULL && strlen (url) != 0;
+ }
+
+ /* activation keys radio selected */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->register_with_activation_keys_radio)))
+ {
+ const gchar *activation_keys;
+ const gchar *organization;
+
+ /* require activation keys */
+ activation_keys = gtk_entry_get_text (self->activation_keys_entry);
+ valid_activation_keys = activation_keys != NULL && strlen (activation_keys) != 0;
+
+ /* organization is required when using activation keys */
+ organization = gtk_entry_get_text (self->organization_entry_with_activation_keys);
+ valid_organization = organization != NULL && strlen (organization) != 0;
+
+ /* username/password radio selected */
+ }
+ else
+ {
+ const gchar *login;
+ const gchar *password;
+
+ /* require login */
+ login = gtk_entry_get_text (self->login_entry);
+ valid_login = login != NULL && strlen (login) != 0;
+
+ /* require password */
+ password = gtk_entry_get_text (self->password_entry);
+ valid_password = password != NULL && strlen (password) != 0;
+ }
+
+ self->valid = valid_url && valid_login && valid_password && valid_activation_keys && valid_organization;
+ gtk_widget_set_sensitive (GTK_WIDGET (self->register_button), self->valid);
+}
+
+static void
+registration_done_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcSubscriptionRegisterDialog *self = (CcSubscriptionRegisterDialog *) 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_REGISTER;
+ dialog_reload (self);
+ return;
+ }
+
+ gtk_spinner_stop (self->spinner);
+ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT);
+ return;
+}
+
+static void
+subscription_register_with_activation_keys (CcSubscriptionRegisterDialog *self)
+{
+ g_autoptr(GVariantBuilder) options_builder = NULL;
+ const gchar *hostname;
+ const gchar *organization;
+ const gchar *activation_keys;
+
+ hostname = gtk_entry_get_text (self->url_entry);
+ organization = gtk_entry_get_text (self->organization_entry_with_activation_keys);
+ activation_keys = gtk_entry_get_text (self->activation_keys_entry);
+
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (options_builder, "{sv}", "kind", g_variant_new_string ("key"));
+ g_variant_builder_add (options_builder, "{sv}", "hostname", g_variant_new_string (hostname));
+ g_variant_builder_add (options_builder, "{sv}", "organisation", g_variant_new_string (organization));
+ g_variant_builder_add (options_builder, "{sv}", "activation-key", g_variant_new_string (activation_keys));
+
+ g_dbus_proxy_call (self->subscription_proxy,
+ "Register",
+ g_variant_new ("(a{sv})",
+ options_builder),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ self->cancellable,
+ registration_done_cb,
+ self);
+}
+
+static void
+subscription_register_with_username (CcSubscriptionRegisterDialog *self)
+{
+ g_autoptr(GVariantBuilder) options_builder = NULL;
+ const gchar *hostname;
+ const gchar *organization;
+ const gchar *username;
+ const gchar *password;
+
+ hostname = gtk_entry_get_text (self->url_entry);
+ organization = gtk_entry_get_text (self->organization_entry);
+ username = gtk_entry_get_text (self->login_entry);
+ password = gtk_entry_get_text (self->password_entry);
+
+ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (options_builder, "{sv}", "kind", g_variant_new_string ("username"));
+ g_variant_builder_add (options_builder, "{sv}", "hostname", g_variant_new_string (hostname));
+ g_variant_builder_add (options_builder, "{sv}", "organisation", g_variant_new_string (organization));
+ g_variant_builder_add (options_builder, "{sv}", "username", g_variant_new_string (username));
+ g_variant_builder_add (options_builder, "{sv}", "password", g_variant_new_string (password));
+
+ g_dbus_proxy_call (self->subscription_proxy,
+ "Register",
+ g_variant_new ("(a{sv})", options_builder),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ self->cancellable,
+ registration_done_cb,
+ self);
+}
+
+static void
+register_button_clicked_cb (CcSubscriptionRegisterDialog *self)
+{
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->register_with_activation_keys_radio)))
+ subscription_register_with_activation_keys (self);
+ else
+ subscription_register_with_username (self);
+
+ gtk_spinner_start (self->spinner);
+
+ self->state = DIALOG_STATE_REGISTERING;
+ dialog_reload (self);
+}
+
+static void
+dismiss_notification (CcSubscriptionRegisterDialog *self)
+{
+ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE);
+}
+
+static void
+cc_subscription_register_dialog_init (CcSubscriptionRegisterDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+ self->state = DIALOG_STATE_REGISTER;
+
+ gtk_entry_set_text (self->url_entry, SERVER_URL);
+ gtk_widget_grab_focus (GTK_WIDGET (self->login_entry));
+ dialog_validate (self);
+ dialog_reload (self);
+}
+
+static void
+cc_subscription_register_dialog_dispose (GObject *obj)
+{
+ CcSubscriptionRegisterDialog *self = (CcSubscriptionRegisterDialog *) obj;
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->subscription_proxy);
+
+ G_OBJECT_CLASS (cc_subscription_register_dialog_parent_class)->dispose (obj);
+}
+
+static void
+cc_subscription_register_dialog_finalize (GObject *obj)
+{
+ G_OBJECT_CLASS (cc_subscription_register_dialog_parent_class)->finalize (obj);
+}
+
+static void
+cc_subscription_register_dialog_class_init (CcSubscriptionRegisterDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_subscription_register_dialog_dispose;
+ object_class->finalize = cc_subscription_register_dialog_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/info/cc-subscription-register-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_button);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, notification_revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, error_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, default_url_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, custom_url_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_with_activation_keys_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_with_activation_keys_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, url_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, url_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, login_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, activation_keys_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, organization_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, organization_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, organization_entry_with_activation_keys);
+
+ gtk_widget_class_bind_template_callback (widget_class, dialog_validate);
+ gtk_widget_class_bind_template_callback (widget_class, register_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dismiss_notification);
+ gtk_widget_class_bind_template_callback (widget_class, custom_url_radio_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, register_with_activation_keys_radio_toggled_cb);
+}
+
+CcSubscriptionRegisterDialog *
+cc_subscription_register_dialog_new (GDBusProxy *subscription_proxy)
+{
+ CcSubscriptionRegisterDialog *self;
+
+ self = g_object_new (CC_TYPE_SUBSCRIPTION_REGISTER_DIALOG, "use-header-bar", TRUE, NULL);
+ self->subscription_proxy = g_object_ref (subscription_proxy);
+
+ return self;
+}
diff --git a/panels/info/cc-subscription-register-dialog.h b/panels/info/cc-subscription-register-dialog.h
new file mode 100644
index 000000000..c5918df9f
--- /dev/null
+++ b/panels/info/cc-subscription-register-dialog.h
@@ -0,0 +1,32 @@
+/* -*- 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 <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Kalev Lember <klember@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SUBSCRIPTION_REGISTER_DIALOG (cc_subscription_register_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcSubscriptionRegisterDialog, cc_subscription_register_dialog, CC, SUBSCRIPTION_REGISTER_DIALOG, GtkDialog)
+
+CcSubscriptionRegisterDialog *cc_subscription_register_dialog_new (GDBusProxy *subscription_proxy);
+
+G_END_DECLS
diff --git a/panels/info/cc-subscription-register-dialog.ui b/panels/info/cc-subscription-register-dialog.ui
new file mode 100644
index 000000000..21e317b41
--- /dev/null
+++ b/panels/info/cc-subscription-register-dialog.ui
@@ -0,0 +1,623 @@
+<?xml version="1.0"?>
+<interface>
+ <template class="CcSubscriptionRegisterDialog" parent="GtkDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="title" translatable="yes">Register System</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_close_button">False</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack_type">start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="register_button">
+ <property name="label" translatable="yes">_Register</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="register_button_clicked_cb" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <style>
+ <class name="text-button"/>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="border_width">0</property>
+ <child>
+ <object class="GtkOverlay" id="overlay">
+ <property name="visible">True</property>
+ <child type="overlay">
+ <object class="GtkRevealer" id="notification_revealer">
+ <property name="visible">True</property>
+ <property name="halign">fill</property>
+ <property name="hexpand">True</property>
+ <property name="margin_start">20</property>
+ <property name="margin_end">20</property>
+ <property name="valign">start</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <style>
+ <class name="app-notification"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="hexpand">True</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Failed to Register System</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="error_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="label">Unable to reach developers.redhat.com. Please try again later.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="dismiss_button">
+ <property name="visible">True</property>
+ <property name="valign">start</property>
+ <signal name="clicked" handler="dismiss_notification" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <style>
+ <class name="flat"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">window-close-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <property name="margin_top">24</property>
+ <property name="margin_start">32</property>
+ <property name="margin_end">32</property>
+ <property name="margin_bottom">20</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Register this system with Red Hat to receive software updates.</property>
+ <property name="width_chars">45</property>
+ <property name="max_width_chars">45</property>
+ <property name="xalign">0</property>
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Registration Server</property>
+ <property name="margin_top">12</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="margin_bottom">3</property>
+ <child>
+ <object class="GtkRadioButton" id="default_url_radio">
+ <property name="label" translatable="yes">Red Hat</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="custom_url_radio">
+ <property name="label" translatable="yes">Custom Address</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">default_url_radio</property>
+ <signal name="toggled" handler="custom_url_radio_toggled_cb" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="url_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_URL</property>
+ <property name="sensitive">False</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">url_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="url_entry">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="max-length">255</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="has_focus">True</property>
+ <signal name="changed" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Registration Type</property>
+ <property name="margin_top">12</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkRadioButton" id="register_radio">
+ <property name="label" translatable="yes">Red Hat Account</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="register_with_activation_keys_radio">
+ <property name="label" translatable="yes">Activation Keys</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">register_radio</property>
+ <signal name="toggled" handler="register_with_activation_keys_radio_toggled_cb" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="transition-type">none</property>
+ <child>
+ <object class="GtkGrid" id="register_grid">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Registration Details</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">6</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="login_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Login</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">login_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="login_entry">
+ <property name="visible">True</property>
+ <property name="max-length">255</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="has_focus">True</property>
+ <signal name="changed" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="input_purpose">password</property>
+ <signal name="notify::text" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="organization_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Organization</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">organization_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="organization_entry">
+ <property name="visible">True</property>
+ <property name="max-length">255</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="has_focus">True</property>
+ <signal name="changed" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">register</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="register_with_activation_keys_grid">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Registration Details</property>
+ <property name="margin_top">12</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Enter comma separated activation key(s). If the activation keys have conflicting settings, the rightmost key takes precedence.</property>
+ <property name="width_chars">45</property>
+ <property name="max_width_chars">45</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">6</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="activation_keys_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Activation Keys</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">activation_keys_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="activation_keys_entry">
+ <property name="visible">True</property>
+ <property name="max-length">255</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="has_focus">True</property>
+ <signal name="changed" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="organization_label_with_activation_keys">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Organization</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">organization_entry_with_activation_keys</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="organization_entry_with_activation_keys">
+ <property name="visible">True</property>
+ <property name="max-length">255</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="has_focus">True</property>
+ <signal name="changed" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcSubscriptionRegisterDialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">register-with-activation-keys</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancel_button</action-widget>
+ </action-widgets>
+ </template>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="url_label"/>
+ <widget name="login_label"/>
+ <widget name="password_label"/>
+ <widget name="activation_keys_label"/>
+ <widget name="organization_label"/>
+ <widget name="organization_label_with_activation_keys"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="url_entry"/>
+ <widget name="login_entry"/>
+ <widget name="password_entry"/>
+ <widget name="activation_keys_entry"/>
+ <widget name="password_entry"/>
+ <widget name="organization_entry"/>
+ <widget name="organization_entry_with_activation_keys"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="register_button"/>
+ <widget name="cancel_button"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/info/info-overview.ui b/panels/info/info-overview.ui
index aa87fbec2..e33ba399a 100644
--- a/panels/info/info-overview.ui
+++ b/panels/info/info-overview.ui
@@ -4,16 +4,17 @@
<template class="CcInfoOverviewPanel" parent="CcPanel">
<property name="visible">True</property>
<property name="can-focus">False</property>
- <property name="valign">center</property>
- <property name="halign">center</property>
<property name="expand">True</property>
- <property name="margin">24</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<property name="orientation">vertical</property>
+ <property name="margin_top">63</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="margin_bottom">12</property>
<child>
<object class="GtkImage" id="system_image">
<property name="visible">True</property>
@@ -303,26 +304,143 @@
</packing>
</child>
<child>
- <object class="GtkButtonBox" id="hbuttonbox1">
+ <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="layout_style">end</property>
<property name="orientation">horizontal</property>
+ <property name="margin_top">12</property>
+ <property name="spacing">12</property>
<child>
- <placeholder/>
+ <object class="GtkStack" id="subscription_stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">System Not Registered</property>
+ <attributes>
+ <attribute name="scale" value="0.95"/>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Register this system to receive software updates.</property>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="register_button">
+ <property name="label" translatable="yes">_Register…</property>
+ <property name="can_focus">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="hexpand">True</property>
+ <property name="halign">end</property>
+ <property name="visible">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">not-registered</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Registered System</property>
+ <attributes>
+ <attribute name="scale" value="0.95"/>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">System is registered and able to receive software updates.</property>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="details_button">
+ <property name="label" translatable="yes">_Details</property>
+ <property name="can_focus">True</property>
+ <property name="use_underline">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="hexpand">True</property>
+ <property name="halign">end</property>
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">registered</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="updates_separator">
+ <property name="visible">True</property>
+ </object>
</child>
<child>
<object class="GtkButton" id="updates_button">
- <property name="label" translatable="yes">Check for updates</property>
+ <property name="label" translatable="yes">_View Updates</property>
<property name="can_focus">True</property>
+ <property name="use_underline">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
+ <property name="halign">end</property>
<property name="visible">True</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="pack_type">end</property>
</packing>
</child>
</object>
diff --git a/panels/info/info.gresource.xml b/panels/info/info.gresource.xml
index c96722350..15d18daac 100644
--- a/panels/info/info.gresource.xml
+++ b/panels/info/info.gresource.xml
@@ -4,6 +4,8 @@
<file preprocess="xml-stripblanks">info-overview.ui</file>
<file preprocess="xml-stripblanks">info-default-apps.ui</file>
<file preprocess="xml-stripblanks">info-removable-media.ui</file>
+ <file preprocess="xml-stripblanks">cc-subscription-details-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-subscription-register-dialog.ui</file>
<file>GnomeLogoVerticalMedium.svg</file>
</gresource>
</gresources>
diff --git a/panels/info/meson.build b/panels/info/meson.build
index 13015b96c..a4ff83a42 100644
--- a/panels/info/meson.build
+++ b/panels/info/meson.build
@@ -41,11 +41,15 @@ sources = files(gsd_sources) + files(
'cc-info-default-apps-panel.c',
'cc-info-overview-panel.c',
'cc-info-removable-media-panel.c',
+ 'cc-subscription-details-dialog.c',
+ 'cc-subscription-register-dialog.c',
'info-cleanup.c'
)
resource_data = files(
'GnomeLogoVerticalMedium.svg',
+ 'cc-subscription-details-dialog.ui',
+ 'cc-subscription-register-dialog.ui',
'info-default-apps.ui',
'info-overview.ui',
'info-removable-media.ui'
diff --git a/po/POTFILES.in b/po/POTFILES.in
index dfd8ccff0..6cb8938e9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -34,6 +34,10 @@ panels/display/display.ui
panels/display/gnome-display-panel.desktop.in.in
panels/info/cc-info-overview-panel.c
panels/info/cc-info-removable-media-panel.c
+panels/info/cc-subscription-details-dialog.c
+panels/info/cc-subscription-details-dialog.ui
+panels/info/cc-subscription-register-dialog.c
+panels/info/cc-subscription-register-dialog.ui
panels/info/gnome-default-apps-panel.desktop.in.in
panels/info/gnome-info-overview-panel.desktop.in.in
panels/info/gnome-removable-media-panel.desktop.in.in