[gnome-software] Add an upgrade banner widget



commit 86231447bf6539a83fe5ae37184394a1b542c81e
Author: Kalev Lember <klember redhat com>
Date:   Thu Jan 28 11:07:47 2016 +0100

    Add an upgrade banner widget

 po/POTFILES.in                          |    2 +
 src/Makefile.am                         |    3 +
 src/gnome-software.gresource.xml        |    1 +
 src/gs-upgrade-banner.c                 |  291 +++++++++++++++++++++++++++++++
 src/gs-upgrade-banner.h                 |   50 ++++++
 src/gs-upgrade-banner.ui                |  133 ++++++++++++++
 src/gtk-style.css                       |   17 ++
 src/plugins/gs-plugin-systemd-updates.c |    2 +-
 8 files changed, 498 insertions(+), 1 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 643e044..56ea9e7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -40,6 +40,8 @@ src/gs-sources-dialog.c
 [type: gettext/glade]src/gs-sources-dialog.ui
 src/gs-update-dialog.c
 [type: gettext/glade]src/gs-update-dialog.ui
+src/gs-upgrade-banner.c
+[type: gettext/glade]src/gs-upgrade-banner.ui
 src/gs-update-list.c
 src/gs-update-monitor.c
 [type: gettext/glade]src/gs-star-widget.ui
diff --git a/src/Makefile.am b/src/Makefile.am
index 5e8bd0d..0013150 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -48,6 +48,7 @@ UI_FILES =                                            \
        gs-sources-dialog-row.ui                        \
        gs-star-widget.ui                               \
        gs-update-dialog.ui                             \
+       gs-upgrade-banner.ui                            \
        screenshot-image.ui                             \
        popular-tile.ui
 
@@ -168,6 +169,8 @@ gnome_software_SOURCES =                            \
        gs-update-list.h                                \
        gs-update-monitor.c                             \
        gs-update-monitor.h                             \
+       gs-upgrade-banner.c                             \
+       gs-upgrade-banner.h                             \
        gs-vendor.c                                     \
        gs-vendor.h                                     \
        gs-plugin-loader.c                              \
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index dbeb2af..a53ef00 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -24,6 +24,7 @@
   <file preprocess="xml-stripblanks">gs-sources-dialog-row.ui</file>
   <file preprocess="xml-stripblanks">gs-star-widget.ui</file>
   <file preprocess="xml-stripblanks">gs-update-dialog.ui</file>
+  <file preprocess="xml-stripblanks">gs-upgrade-banner.ui</file>
   <file preprocess="xml-stripblanks">org.freedesktop.PackageKit.xml</file>
   <file>gtk-style.css</file>
   <file>gtk-style-hc.css</file>
diff --git a/src/gs-upgrade-banner.c b/src/gs-upgrade-banner.c
new file mode 100644
index 0000000..00353cc
--- /dev/null
+++ b/src/gs-upgrade-banner.c
@@ -0,0 +1,291 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Kalev Lember <klember redhat com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include "gs-upgrade-banner.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <stdlib.h>
+
+typedef struct
+{
+       GsApp           *app;
+
+       GtkWidget       *button_upgrades_download;
+       GtkWidget       *button_upgrades_install;
+       GtkWidget       *button_upgrades_learn_more;
+       GtkWidget       *label_upgrades_summary;
+       GtkWidget       *label_upgrades_title;
+       GtkWidget       *progressbar;
+} GsUpgradeBannerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsUpgradeBanner, gs_upgrade_banner, GTK_TYPE_BIN)
+
+enum {
+       SIGNAL_DOWNLOAD_BUTTON_CLICKED,
+       SIGNAL_INSTALL_BUTTON_CLICKED,
+       SIGNAL_LEARN_MORE_BUTTON_CLICKED,
+       SIGNAL_LAST
+};
+
+static guint signals [SIGNAL_LAST] = { 0 };
+
+static void
+gs_upgrade_banner_refresh (GsUpgradeBanner *self)
+{
+       GsUpgradeBannerPrivate *priv = gs_upgrade_banner_get_instance_private (self);
+
+       if (priv->app == NULL)
+               return;
+
+       /* Refresh the title. Normally a distro upgrade state goes from
+        *
+        * AVAILABLE (available to download) to
+        * INSTALLING (downloading packages for later installation) to
+        * UPDATABLE (packages are downloaded and upgrade is ready to go)
+        */
+       switch (gs_app_get_state (priv->app)) {
+       case AS_APP_STATE_AVAILABLE:
+       {
+               g_autofree gchar *str = NULL;
+
+               /* TRANSLATORS: This is the text displayed when a distro
+                * upgrade is available. First %s is the distro name and the
+                * 2nd %s is the version, e.g. "Fedora 23 Now Available" */
+               str = g_strdup_printf (_("%s %s Now Available"),
+                                      gs_app_get_name (priv->app),
+                                      gs_app_get_version (priv->app));
+               gtk_label_set_text (GTK_LABEL (priv->label_upgrades_title), str);
+               break;
+       }
+       case AS_APP_STATE_INSTALLING:
+       {
+               g_autofree gchar *str = NULL;
+
+               /* TRANSLATORS: This is the text displayed while downloading a
+                * distro upgrade. First %s is the distro name and the 2nd %s
+                * is the version, e.g. "Downloading Fedora 23" */
+               str = g_strdup_printf (_("Downloading %s %s"),
+                                      gs_app_get_name (priv->app),
+                                      gs_app_get_version (priv->app));
+               gtk_label_set_text (GTK_LABEL (priv->label_upgrades_title), str);
+               break;
+       }
+       case AS_APP_STATE_UPDATABLE:
+       {
+               g_autofree gchar *str = NULL;
+
+               /* TRANSLATORS: This is the text displayed when a distro
+                * upgrade has been downloaded and is ready to be installed.
+                * First %s is the distro name and the 2nd %s is the version,
+                * e.g. "Fedora 23 Ready to be Installed" */
+               str = g_strdup_printf (_("%s %s Ready to be Installed"),
+                                      gs_app_get_name (priv->app),
+                                      gs_app_get_version (priv->app));
+               gtk_label_set_text (GTK_LABEL (priv->label_upgrades_title), str);
+               break;
+       }
+       default:
+               g_critical ("Unexpected app state");
+               break;
+       }
+
+       /* Refresh the summary if we got anything better than the default blurb */
+       if (gs_app_get_summary (priv->app) != NULL)
+               gtk_label_set_text (GTK_LABEL (priv->label_upgrades_summary),
+                                   gs_app_get_summary (priv->app));
+
+       /* Show the right buttons for the current state */
+       switch (gs_app_get_state (priv->app)) {
+       case AS_APP_STATE_AVAILABLE:
+               gtk_widget_show (priv->button_upgrades_learn_more);
+               gtk_widget_show (priv->button_upgrades_download);
+               gtk_widget_hide (priv->button_upgrades_install);
+               break;
+       case AS_APP_STATE_INSTALLING:
+               gtk_widget_show (priv->button_upgrades_learn_more);
+               gtk_widget_hide (priv->button_upgrades_download);
+               gtk_widget_hide (priv->button_upgrades_install);
+               break;
+       case AS_APP_STATE_UPDATABLE:
+               gtk_widget_show (priv->button_upgrades_learn_more);
+               gtk_widget_hide (priv->button_upgrades_download);
+               gtk_widget_show (priv->button_upgrades_install);
+               break;
+       default:
+               g_critical ("Unexpected app state");
+               break;
+       }
+
+       /* do a fill bar for the current progress */
+       switch (gs_app_get_state (priv->app)) {
+       case AS_APP_STATE_INSTALLING:
+               gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progressbar),
+                                              gs_app_get_progress (priv->app));
+               gtk_widget_show (priv->progressbar);
+               break;
+       default:
+               gtk_widget_hide (priv->progressbar);
+               break;
+       }
+}
+
+static gboolean
+app_state_changed_idle (gpointer user_data)
+{
+       GsUpgradeBanner *self = GS_UPGRADE_BANNER (user_data);
+
+       gs_upgrade_banner_refresh (self);
+
+       g_object_unref (self);
+       return G_SOURCE_REMOVE;
+}
+
+static void
+app_state_changed (GsApp *app, GParamSpec *pspec, GsUpgradeBanner *self)
+{
+       g_idle_add (app_state_changed_idle, g_object_ref (self));
+}
+
+static void
+download_button_cb (GtkWidget *widget, GsUpgradeBanner *self)
+{
+       g_signal_emit (self, signals[SIGNAL_DOWNLOAD_BUTTON_CLICKED], 0);
+}
+
+static void
+install_button_cb (GtkWidget *widget, GsUpgradeBanner *self)
+{
+       g_signal_emit (self, signals[SIGNAL_INSTALL_BUTTON_CLICKED], 0);
+}
+
+static void
+learn_more_button_cb (GtkWidget *widget, GsUpgradeBanner *self)
+{
+       g_signal_emit (self, signals[SIGNAL_LEARN_MORE_BUTTON_CLICKED], 0);
+}
+
+static void
+gs_upgrade_banner_set_app (GsUpgradeBanner *self, GsApp *app)
+{
+       GsUpgradeBannerPrivate *priv = gs_upgrade_banner_get_instance_private (self);
+
+       g_return_if_fail (GS_IS_UPGRADE_BANNER (self));
+       g_return_if_fail (GS_IS_APP (app) || app == NULL);
+
+       if (priv->app)
+               g_signal_handlers_disconnect_by_func (priv->app, app_state_changed, self);
+
+       g_set_object (&priv->app, app);
+       if (!app)
+               return;
+
+       g_signal_connect (priv->app, "notify::state",
+                         G_CALLBACK (app_state_changed), self);
+
+       gs_upgrade_banner_refresh (self);
+}
+
+static void
+gs_upgrade_banner_destroy (GtkWidget *widget)
+{
+       GsUpgradeBanner *self = GS_UPGRADE_BANNER (widget);
+       GsUpgradeBannerPrivate *priv = gs_upgrade_banner_get_instance_private (self);
+
+       if (priv->app)
+               g_signal_handlers_disconnect_by_func (priv->app, app_state_changed, self);
+
+       g_clear_object (&priv->app);
+
+       GTK_WIDGET_CLASS (gs_upgrade_banner_parent_class)->destroy (widget);
+}
+
+static void
+gs_upgrade_banner_init (GsUpgradeBanner *self)
+{
+       GsUpgradeBannerPrivate *priv = gs_upgrade_banner_get_instance_private (self);
+
+       gtk_widget_init_template (GTK_WIDGET (self));
+
+       g_signal_connect (priv->button_upgrades_download, "clicked",
+                         G_CALLBACK (download_button_cb),
+                         self);
+       g_signal_connect (priv->button_upgrades_install, "clicked",
+                         G_CALLBACK (install_button_cb),
+                         self);
+       g_signal_connect (priv->button_upgrades_learn_more, "clicked",
+                         G_CALLBACK (learn_more_button_cb),
+                         self);
+}
+
+static void
+gs_upgrade_banner_class_init (GsUpgradeBannerClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       widget_class->destroy = gs_upgrade_banner_destroy;
+
+       signals [SIGNAL_DOWNLOAD_BUTTON_CLICKED] =
+               g_signal_new ("download-button-clicked",
+                             G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GsUpgradeBannerClass, download_button_clicked),
+                             NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+       signals [SIGNAL_INSTALL_BUTTON_CLICKED] =
+               g_signal_new ("install-button-clicked",
+                             G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GsUpgradeBannerClass, install_button_clicked),
+                             NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+       signals [SIGNAL_LEARN_MORE_BUTTON_CLICKED] =
+               g_signal_new ("learn-more-button-clicked",
+                             G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GsUpgradeBannerClass, learn_more_button_clicked),
+                             NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Software/gs-upgrade-banner.ui");
+
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, 
button_upgrades_download);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, button_upgrades_install);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, 
button_upgrades_learn_more);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, label_upgrades_summary);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, label_upgrades_title);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, progressbar);
+}
+
+GtkWidget *
+gs_upgrade_banner_new (GsApp *app)
+{
+       GsUpgradeBanner *self;
+
+       self = g_object_new (GS_TYPE_UPGRADE_BANNER, NULL);
+       gs_upgrade_banner_set_app (self, app);
+
+       return GTK_WIDGET (self);
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-upgrade-banner.h b/src/gs-upgrade-banner.h
new file mode 100644
index 0000000..4cc741e
--- /dev/null
+++ b/src/gs-upgrade-banner.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Kalev Lember <klember redhat com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GS_UPGRADE_BANNER_H
+#define GS_UPGRADE_BANNER_H
+
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_UPGRADE_BANNER (gs_upgrade_banner_get_type ())
+
+G_DECLARE_DERIVABLE_TYPE (GsUpgradeBanner, gs_upgrade_banner, GS, UPGRADE_BANNER, GtkBin)
+
+struct _GsUpgradeBannerClass
+{
+       GtkBinClass      parent_class;
+
+       void            (*download_button_clicked)      (GsUpgradeBanner        *self);
+       void            (*install_button_clicked)       (GsUpgradeBanner        *self);
+       void            (*learn_more_button_clicked)    (GsUpgradeBanner        *self);
+};
+
+GtkWidget      *gs_upgrade_banner_new                  (GsApp                  *app);
+
+G_END_DECLS
+
+#endif /* GS_UPGRADE_BANNER_H */
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-upgrade-banner.ui b/src/gs-upgrade-banner.ui
new file mode 100644
index 0000000..0ee10db
--- /dev/null
+++ b/src/gs-upgrade-banner.ui
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <template class="GsUpgradeBanner" parent="GtkBin">
+    <child>
+      <object class="GtkBox" id="box_upgrades">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <style>
+          <class name="upgrade-banner"/>
+        </style>
+        <child>
+          <object class="GtkLabel" id="label_upgrades_title">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_top">42</property>
+            <property name="margin_bottom">8</property>
+            <!-- Just a placeholder; actual label text is set in code -->
+            <property name="label">GNOME 3.20 Now Available</property>
+            <attributes>
+              <attribute name="scale" value="1.8"/>
+            </attributes>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_upgrades_summary">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">A major upgrade, with new features and added 
polish.</property>
+            <property name="margin_bottom">12</property>
+            <attributes>
+              <attribute name="scale" value="1.2"/>
+            </attributes>
+          </object>
+        </child>
+        <child>
+          <object class="GtkProgressBar" id="progressbar">
+            <property name="visible">True</property>
+            <property name="width_request">480</property>
+            <property name="halign">center</property>
+            <property name="fraction">0.3</property>
+            <property name="margin_top">8</property>
+            <style>
+              <class name="upgrade-progressbar"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box_upgrades_buttons">
+            <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
+            <property name="halign">center</property>
+            <property name="spacing">12</property>
+            <property name="margin_top">16</property>
+            <property name="margin_bottom">28</property>
+            <child>
+              <object class="GtkButton" id="button_upgrades_learn_more">
+                <property name="label" translatable="yes">_Learn More</property>
+                <property name="width_request">150</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="relief">none</property>
+                <style>
+                  <class name="upgrade-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_upgrades_download">
+                <property name="label" translatable="yes">_Download</property>
+                <property name="width_request">150</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="relief">none</property>
+                <style>
+                  <class name="upgrade-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_upgrades_install">
+                <property name="label" translatable="yes">_Install</property>
+                <property name="width_request">150</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="relief">none</property>
+                <style>
+                  <class name="upgrade-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_upgrades_warning">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">It is recommended that you back up your data and files 
before upgrading.</property>
+            <property name="margin_top">8</property>
+            <property name="margin_bottom">24</property>
+            <attributes>
+              <attribute name="scale" value="0.9"/>
+            </attributes>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/gtk-style.css b/src/gtk-style.css
index 898fb1b..100799d 100644
--- a/src/gtk-style.css
+++ b/src/gtk-style.css
@@ -214,3 +214,20 @@ button.star, .button.star {
        font-size: 90%;
        padding: 16px
 }
+
+.upgrade-banner {
+       background-color: #1c5288;
+       color: @theme_selected_fg_color;
+}
+
+.upgrade-button {
+       background-image: none;
+       background-color: #5899dc;
+       box-shadow: none;
+       color: @theme_selected_fg_color;
+       border-color: @theme_selected_bg_color;
+}
+
+.upgrade-progressbar {
+       box-shadow: none
+}
diff --git a/src/plugins/gs-plugin-systemd-updates.c b/src/plugins/gs-plugin-systemd-updates.c
index 4a36d39..4444963 100644
--- a/src/plugins/gs-plugin-systemd-updates.c
+++ b/src/plugins/gs-plugin-systemd-updates.c
@@ -142,7 +142,7 @@ gs_plugin_add_updates (GsPlugin *plugin,
                split = pk_package_id_split (package_ids[i]);
                gs_app_add_source (app, split[PK_PACKAGE_ID_NAME]);
                gs_app_set_update_version (app, split[PK_PACKAGE_ID_VERSION]);
-               gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
+               gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
                gs_app_set_kind (app, GS_APP_KIND_PACKAGE);
                gs_plugin_add_app (list, app);
        }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]