[gnome-software/1111-version-history-box: 71/71] Add version history to app details pages




commit 88ff93c936d65a4c0081351922e1aa234984963b
Author: Phaedrus Leeds <mwleeds endlessos org>
Date:   Wed Feb 3 12:45:34 2021 -0800

    Add version history to app details pages
    
    Instead of showing the Version and Release Date in the table of info on
    app details pages, show it as seen in the mock-ups (#1111).
    
    For now, leave the "Last Updated" information since the latest available
    version isn't necessarily the installed version, so this UI doesn't
    duplicate that information.
    
    Helps: #1111

 plugins/core/gs-appstream.c          |  10 ++-
 po/POTFILES.in                       |   3 +
 src/gnome-software.gresource.xml     |   2 +
 src/gs-app-version-history-dialog.c  | 109 ++++++++++++++++++++++++++++++
 src/gs-app-version-history-dialog.h  |  24 +++++++
 src/gs-app-version-history-dialog.ui |  51 ++++++++++++++
 src/gs-app-version-history-row.c     | 104 ++++++++++++++++++++++++++++
 src/gs-app-version-history-row.h     |  27 ++++++++
 src/gs-app-version-history-row.ui    |  63 +++++++++++++++++
 src/gs-common.c                      |   1 +
 src/gs-details-page.c                |  85 +++++++++++++----------
 src/gs-details-page.ui               | 127 +++++++++++++++--------------------
 src/meson.build                      |   2 +
 13 files changed, 498 insertions(+), 110 deletions(-)
---
diff --git a/plugins/core/gs-appstream.c b/plugins/core/gs-appstream.c
index a273abf7f..6fd38cc4c 100644
--- a/plugins/core/gs-appstream.c
+++ b/plugins/core/gs-appstream.c
@@ -608,16 +608,19 @@ gs_appstream_refine_add_version_history (GsApp *app, XbNode *component, GError *
        version_history = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
        for (guint i = 0; i < releases->len; i++) {
                XbNode *release_node = g_ptr_array_index (releases, i);
-               const gchar *version = xb_node_get_attr (release, "version");
+               const gchar *version = xb_node_get_attr (release_node, "version");
                g_autoptr(XbNode) description_node = NULL;
                g_autofree gchar *description = NULL;
                guint64 timestamp;
+               g_autoptr(AsRelease) release = NULL;
+               g_autofree char *timestamp_xpath = NULL;
 
                /* ignore releases with no version */
                if (version == NULL)
                        continue;
 
-               timestamp = xb_node_query_attr_as_uint (release_node, "timestamp", NULL);
+               timestamp_xpath = g_strdup_printf ("releases/release[%u]", i+1);
+               timestamp = xb_node_query_attr_as_uint (component, timestamp_xpath, "timestamp", NULL);
 
                /* include updates with or without a description */
                description_node = xb_node_query_first (release_node, "description", NULL);
@@ -626,7 +629,8 @@ gs_appstream_refine_add_version_history (GsApp *app, XbNode *component, GError *
 
                release = as_release_new ();
                as_release_set_version (release, version);
-               as_release_set_timestamp (release, timestamp);
+               if (timestamp != G_MAXUINT64)
+                       as_release_set_timestamp (release, timestamp);
                if (description != NULL)
                        as_release_set_description (release, description, NULL);
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c119b8628..9f92fa4f5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,6 +6,9 @@ src/gnome-software.ui
 lib/gs-app.c
 src/gs-app-addon-row.c
 src/gs-app-addon-row.ui
+src/gs-app-version-history-dialog.ui
+src/gs-app-version-history-row.c
+src/gs-app-version-history-row.ui
 src/gs-application.c
 src/gs-app-row.c
 src/gs-app-row.ui
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index 459ecf821..d0f7ea95c 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -3,6 +3,8 @@
  <gresource prefix="/org/gnome/Software">
   <file preprocess="xml-stripblanks">gnome-software.ui</file>
   <file preprocess="xml-stripblanks">gs-app-addon-row.ui</file>
+  <file preprocess="xml-stripblanks">gs-app-version-history-dialog.ui</file>
+  <file preprocess="xml-stripblanks">gs-app-version-history-row.ui</file>
   <file preprocess="xml-stripblanks">gs-app-row.ui</file>
   <file preprocess="xml-stripblanks">gs-basic-auth-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-category-page.ui</file>
diff --git a/src/gs-app-version-history-dialog.c b/src/gs-app-version-history-dialog.c
new file mode 100644
index 000000000..439ad2946
--- /dev/null
+++ b/src/gs-app-version-history-dialog.c
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Matthew Leeds <mwleeds endlessos org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include "gs-app-version-history-dialog.h"
+
+#include "gnome-software-private.h"
+#include "gs-common.h"
+#include "gs-app-version-history-row.h"
+#include <glib/gi18n.h>
+
+struct _GsAppVersionHistoryDialog
+{
+       GtkDialog        parent_instance;
+       GsApp           *app;
+       GtkWidget       *listbox;
+};
+
+G_DEFINE_TYPE (GsAppVersionHistoryDialog, gs_app_version_history_dialog, GTK_TYPE_DIALOG)
+
+static void
+populate_version_history (GsAppVersionHistoryDialog *dialog,
+                         GsApp                     *app)
+{
+       GPtrArray *version_history;
+
+       /* remove previous */
+       gs_container_remove_all (GTK_CONTAINER (dialog->listbox));
+
+       version_history = gs_app_get_version_history (app);
+       if (version_history == NULL) {
+               GtkWidget *row;
+               row = gs_app_version_history_row_new ();
+               gs_app_version_history_row_set_info (GS_APP_VERSION_HISTORY_ROW (row),
+                                                    gs_app_get_version (app),
+                                                    gs_app_get_release_date (app), NULL);
+               gtk_list_box_insert (GTK_LIST_BOX (dialog->listbox), row, -1);
+               gtk_widget_show (row);
+               return;
+       }
+
+       /* add each */
+       for (guint i = 0; i < version_history->len; i++) {
+               GtkWidget *row;
+               AsRelease *version = g_ptr_array_index (version_history, i);
+
+               row = gs_app_version_history_row_new ();
+               gs_app_version_history_row_set_info (GS_APP_VERSION_HISTORY_ROW (row),
+                                                    as_release_get_version (version),
+                                                    as_release_get_timestamp (version),
+                                                    as_release_get_description (version));
+
+               gtk_list_box_insert (GTK_LIST_BOX (dialog->listbox), row, -1);
+               gtk_widget_show (row);
+       }
+}
+
+static void
+list_header_func (GtkListBoxRow *row,
+                 GtkListBoxRow *before,
+                 gpointer user_data)
+{
+       GtkWidget *header = NULL;
+       if (before != NULL)
+               header = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+       gtk_list_box_row_set_header (row, header);
+}
+
+static void
+gs_app_version_history_dialog_init (GsAppVersionHistoryDialog *dialog)
+{
+       gtk_widget_init_template (GTK_WIDGET (dialog));
+
+       gtk_list_box_set_header_func (GTK_LIST_BOX (dialog->listbox),
+                                     list_header_func,
+                                     dialog,
+                                     NULL);
+}
+
+static void
+gs_app_version_history_dialog_class_init (GsAppVersionHistoryDialogClass *klass)
+{
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Software/gs-app-version-history-dialog.ui");
+
+       gtk_widget_class_bind_template_child (widget_class, GsAppVersionHistoryDialog, listbox);
+}
+
+GtkWidget *
+gs_app_version_history_dialog_new (GtkWindow *parent, GsApp *app)
+{
+       GsAppVersionHistoryDialog *dialog;
+
+       dialog = g_object_new (GS_TYPE_APP_VERSION_HISTORY_DIALOG,
+                              "use-header-bar", TRUE,
+                              "transient-for", parent,
+                              "modal", TRUE,
+                              NULL);
+       populate_version_history (dialog, app);
+
+       return GTK_WIDGET (dialog);
+}
diff --git a/src/gs-app-version-history-dialog.h b/src/gs-app-version-history-dialog.h
new file mode 100644
index 000000000..6abed18e2
--- /dev/null
+++ b/src/gs-app-version-history-dialog.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Matthew Leeds <mwleeds endlessos org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "gnome-software-private.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_APP_VERSION_HISTORY_DIALOG (gs_app_version_history_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsAppVersionHistoryDialog, gs_app_version_history_dialog, GS, 
APP_VERSION_HISTORY_DIALOG, GtkDialog)
+
+GtkWidget      *gs_app_version_history_dialog_new      (GtkWindow      *parent,
+                                                        GsApp          *app);
+
+G_END_DECLS
diff --git a/src/gs-app-version-history-dialog.ui b/src/gs-app-version-history-dialog.ui
new file mode 100644
index 000000000..b8527a041
--- /dev/null
+++ b/src/gs-app-version-history-dialog.ui
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.10"/>
+  <template class="GsAppVersionHistoryDialog" parent="GtkDialog">
+    <property name="title" translatable="yes">Version History</property>
+    <property name="default_width">550</property>
+    <property name="default_height">600</property>
+    <property name="width_request">360</property>
+    <property name="height_request">400</property>
+    <property name="use_header_bar">1</property>
+    <child internal-child="headerbar">
+      <object class="HdyHeaderBar"/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="border_width">0</property>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <child>
+              <object class="HdyClamp">
+                <property name="visible">True</property>
+                <property name="vexpand">True</property>
+                <property name="hexpand">False</property>
+                <child>
+                  <object class="GtkFrame">
+                    <property name="visible">True</property>
+                    <property name="shadow_type">in</property>
+                    <property name="margin-bottom">18</property>
+                    <property name="margin-top">18</property>
+                    <child>
+                      <object class="GtkListBox" id="listbox">
+                        <property name="visible">True</property>
+                        <property name="selection-mode">none</property>
+                        <style>
+                          <class name="content"/>
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/gs-app-version-history-row.c b/src/gs-app-version-history-row.c
new file mode 100644
index 000000000..e01e6987e
--- /dev/null
+++ b/src/gs-app-version-history-row.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Matthew Leeds <mwleeds endlessos org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "gs-app-version-history-row.h"
+
+#include "gs-common.h"
+
+struct _GsAppVersionHistoryRow
+{
+       GtkListBoxRow    parent_instance;
+
+       GtkWidget       *version_number_label;
+       GtkWidget       *version_date_label;
+       GtkWidget       *version_description_label;
+};
+
+G_DEFINE_TYPE (GsAppVersionHistoryRow, gs_app_version_history_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+gs_app_version_history_row_class_init (GsAppVersionHistoryRowClass *klass)
+{
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Software/gs-app-version-history-row.ui");
+
+       gtk_widget_class_bind_template_child (widget_class, GsAppVersionHistoryRow, version_number_label);
+       gtk_widget_class_bind_template_child (widget_class, GsAppVersionHistoryRow, version_date_label);
+       gtk_widget_class_bind_template_child (widget_class, GsAppVersionHistoryRow, 
version_description_label);
+}
+
+static void
+gs_app_version_history_row_init (GsAppVersionHistoryRow *row)
+{
+       gtk_widget_set_has_window (GTK_WIDGET (row), FALSE);
+       gtk_widget_init_template (GTK_WIDGET (row));
+}
+
+void
+gs_app_version_history_row_set_info (GsAppVersionHistoryRow *row,
+                                    const char *version_number,
+                                    guint64     version_date,
+                                    const char *version_description)
+{
+       g_autofree char *version_date_string = NULL;
+       g_autofree char *version_date_string_tooltip = NULL;
+
+       if (version_number == NULL || *version_number == '\0')
+               return;
+
+       if (version_description != NULL && *version_description != '\0') {
+               g_autofree char *version_tmp = NULL;
+               version_tmp = g_strdup_printf (_("New in Version %s"), version_number);
+               gtk_label_set_label (GTK_LABEL (row->version_number_label), version_tmp);
+               gtk_label_set_label (GTK_LABEL (row->version_description_label), version_description);
+       } else {
+               g_autofree char *version_tmp = NULL;
+               const gchar *version_description_fallback;
+               version_tmp = g_strdup_printf (_("Version %s"), version_number);
+               gtk_label_set_label (GTK_LABEL (row->version_number_label), version_tmp);
+               version_description_fallback = _("No details for this release");
+               gtk_label_set_label (GTK_LABEL (row->version_description_label), 
version_description_fallback);
+               gtk_style_context_add_class (gtk_widget_get_style_context (row->version_description_label), 
"dim-label");
+       }
+
+       if (version_date != 0) {
+               g_autoptr(GDateTime) date_time = NULL;
+               const gchar *format_string;
+
+               /* this is the date in the form of "x weeks ago" or "y months ago" */
+               version_date_string = gs_utils_time_to_string ((gint64) version_date);
+
+               /* TRANSLATORS: This is the date string with: day number, month name, year.
+                  i.e. "25 May 2012" */
+               format_string = _("%e %B %Y");
+               date_time = g_date_time_new_from_unix_local (version_date);
+               version_date_string_tooltip = g_date_time_format (date_time, format_string);
+       }
+
+       if (version_date_string == NULL)
+               gtk_widget_set_visible (row->version_date_label, FALSE);
+       else
+               gtk_label_set_label (GTK_LABEL (row->version_date_label), version_date_string);
+
+       if (version_date_string_tooltip != NULL)
+               gtk_widget_set_tooltip_text (row->version_date_label, version_date_string_tooltip);
+}
+
+GtkWidget *
+gs_app_version_history_row_new (void)
+{
+       GsAppVersionHistoryRow *row;
+
+       row = g_object_new (GS_TYPE_APP_VERSION_HISTORY_ROW, NULL);
+       return GTK_WIDGET (row);
+}
diff --git a/src/gs-app-version-history-row.h b/src/gs-app-version-history-row.h
new file mode 100644
index 000000000..0e91ac6e2
--- /dev/null
+++ b/src/gs-app-version-history-row.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Matthew Leeds <mwleeds endlessos org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "gnome-software-private.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_APP_VERSION_HISTORY_ROW (gs_app_version_history_row_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsAppVersionHistoryRow, gs_app_version_history_row, GS, APP_VERSION_HISTORY_ROW, 
GtkListBoxRow)
+
+GtkWidget      *gs_app_version_history_row_new         (void);
+void            gs_app_version_history_row_set_info    (GsAppVersionHistoryRow *row,
+                                                        const char             *version_number,
+                                                        guint64                 version_date,
+                                                        const char             *version_description);
+
+G_END_DECLS
diff --git a/src/gs-app-version-history-row.ui b/src/gs-app-version-history-row.ui
new file mode 100644
index 000000000..97b016dbb
--- /dev/null
+++ b/src/gs-app-version-history-row.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <template class="GsAppVersionHistoryRow" parent="GtkListBoxRow">
+    <property name="visible">True</property>
+    <property name="selectable">False</property>
+    <property name="activatable">False</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="margin_start">15</property>
+        <property name="margin_top">15</property>
+        <property name="margin_bottom">15</property>
+        <property name="margin_end">15</property>
+        <property name="orientation">vertical</property>
+        <property name="valign">start</property>
+        <property name="hexpand">True</property>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="margin_top">3</property>
+            <property name="margin_bottom">3</property>
+            <property name="orientation">horizontal</property>
+            <child>
+              <object class="GtkLabel" id="version_number_label">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0.5</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="version_date_label">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0.5</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="pack_type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="version_description_label">
+            <property name="visible">True</property>
+            <property name="margin_top">6</property>
+            <property name="wrap">True</property>
+            <property name="max_width_chars">20</property>
+            <property name="xalign">0</property>
+            <property name="yalign">0.5</property>
+            <property name="vexpand">True</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/gs-common.c b/src/gs-common.c
index 79ff95c4a..dd1ba3f51 100644
--- a/src/gs-common.c
+++ b/src/gs-common.c
@@ -681,6 +681,7 @@ gs_utils_time_to_string (gint64 unix_time_seconds)
 
        if (unix_time_seconds <= 0)
                return NULL;
+
        date_time = g_date_time_new_from_unix_local (unix_time_seconds);
        now = g_date_time_new_now_local ();
        timespan = g_date_time_difference (now, date_time);
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 0dd4fa297..099ff06d0 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -19,6 +19,8 @@
 
 #include "gs-details-page.h"
 #include "gs-app-addon-row.h"
+#include "gs-app-version-history-row.h"
+#include "gs-app-version-history-dialog.h"
 #include "gs-description-box.h"
 #include "gs-history-dialog.h"
 #include "gs-origin-popover-row.h"
@@ -111,16 +113,16 @@ struct _GsDetailsPage
        GtkWidget               *label_details_size_download_value;
        GtkWidget               *label_details_updated_title;
        GtkWidget               *label_details_updated_value;
-       GtkWidget               *label_details_version_title;
-       GtkWidget               *label_details_version_value;
-       GtkWidget               *label_details_released_title;
-       GtkWidget               *label_details_released_value;
        GtkWidget               *label_details_permissions_title;
        GtkWidget               *button_details_permissions_value;
        GtkWidget               *label_failed;
        GtkWidget               *label_license_nonfree_details;
        GtkWidget               *label_licenses_intro;
        GtkWidget               *list_box_addons;
+       GtkWidget               *list_box_version_history;
+       GtkWidget               *box_version_history_frame;
+       GtkWidget               *row_latest_version;
+       GtkWidget               *version_history_button;
        GtkWidget               *box_reviews;
        GtkWidget               *box_details_screenshot_fallback;
        GtkWidget               *histogram;
@@ -1109,6 +1111,7 @@ gs_details_page_refresh_all (GsDetailsPage *self)
        guint64 user_integration_bf;
        gboolean show_support_box = FALSE;
        g_autofree gchar *origin = NULL;
+       GPtrArray *version_history;
 
        /* change widgets */
        tmp = gs_app_get_name (self->app);
@@ -1200,34 +1203,26 @@ gs_details_page_refresh_all (GsDetailsPage *self)
                gtk_widget_set_visible (self->label_details_channel_value, FALSE);
        }
 
-       /* set version */
-       tmp = gs_app_get_version (self->app);
-       if (tmp != NULL){
-               gtk_label_set_label (GTK_LABEL (self->label_details_version_value), tmp);
+       /* set version history */
+       version_history = gs_app_get_version_history (self->app);
+       if (version_history == NULL) {
+               const char *version = gs_app_get_version (self->app);
+               if (version == NULL || *version == '\0')
+                       gtk_widget_set_visible (self->box_version_history_frame, FALSE);
+               else
+                       gs_app_version_history_row_set_info (GS_APP_VERSION_HISTORY_ROW 
(self->row_latest_version),
+                                                            version, gs_app_get_release_date (self->app), 
NULL);
        } else {
-               /* TRANSLATORS: this is where the version is not known */
-               gtk_label_set_label (GTK_LABEL (self->label_details_version_value), C_("version", "Unknown"));
+               AsRelease *latest_version = g_ptr_array_index (version_history, 0);
+               gs_app_version_history_row_set_info (GS_APP_VERSION_HISTORY_ROW (self->row_latest_version),
+                                                    as_release_get_version (latest_version),
+                                                    as_release_get_timestamp (latest_version),
+                                                    as_release_get_description (latest_version));
        }
 
        /* refresh size information */
        gs_details_page_refresh_size (self);
 
-       /* set the released date */
-       if (gs_app_get_release_date (self->app)) {
-               g_autoptr(GDateTime) dt = NULL;
-               g_autofree gchar *released_str = NULL;
-
-               dt = g_date_time_new_from_unix_utc ((gint64) gs_app_get_release_date (self->app));
-               released_str = g_date_time_format (dt, "%x");
-
-               gtk_label_set_label (GTK_LABEL (self->label_details_released_value), released_str);
-               gtk_widget_set_visible (self->label_details_released_title, TRUE);
-               gtk_widget_set_visible (self->label_details_released_value, TRUE);
-       } else {
-               gtk_widget_set_visible (self->label_details_released_title, FALSE);
-               gtk_widget_set_visible (self->label_details_released_value, FALSE);
-       }
-
        /* set the updated date */
        updated = gs_app_get_install_date (self->app);
        if (updated == GS_APP_INSTALL_DATE_UNSET) {
@@ -1421,14 +1416,10 @@ gs_details_page_refresh_all (GsDetailsPage *self)
        case AS_COMPONENT_KIND_REPOSITORY:
                gtk_widget_set_visible (self->label_details_license_title, FALSE);
                gtk_widget_set_visible (self->box_details_license_value, FALSE);
-               gtk_widget_set_visible (self->label_details_version_title, FALSE);
-               gtk_widget_set_visible (self->label_details_version_value, FALSE);
                break;
        default:
                gtk_widget_set_visible (self->label_details_license_title, TRUE);
                gtk_widget_set_visible (self->box_details_license_value, TRUE);
-               gtk_widget_set_visible (self->label_details_version_title, TRUE);
-               gtk_widget_set_visible (self->label_details_version_value, TRUE);
                break;
        }
 
@@ -1465,6 +1456,26 @@ list_sort_func (GtkListBoxRow *a,
                                     gs_app_get_name (a2));
 }
 
+static void
+version_history_list_row_activated_cb (GtkListBox *list_box,
+                                      GtkListBoxRow *row,
+                                      GsDetailsPage *self)
+{
+       GtkWidget *dialog;
+
+       /* Only the row with the arrow is clickable */
+       if (GS_IS_APP_VERSION_HISTORY_ROW (row))
+               return;
+
+       dialog = gs_app_version_history_dialog_new (gs_shell_get_window (self->shell),
+                                                   self->app);
+       gs_shell_modal_dialog_present (self->shell, GTK_DIALOG (dialog));
+
+       /* just destroy */
+       g_signal_connect_swapped (dialog, "response",
+                                 G_CALLBACK (gtk_widget_destroy), dialog);
+}
+
 static void gs_details_page_addon_selected_cb (GsAppAddonRow *row, GParamSpec *pspec, GsDetailsPage *self);
 static void gs_details_page_addon_remove_cb (GsAppAddonRow *row, gpointer user_data);
 
@@ -2882,14 +2893,14 @@ gs_details_page_class_init (GsDetailsPageClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, 
label_details_size_installed_value);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_details_updated_title);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_details_updated_value);
-       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_details_version_title);
-       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_details_version_value);
-       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_details_released_title);
-       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_details_released_value);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_details_permissions_title);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, button_details_permissions_value);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, label_failed);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, list_box_addons);
+       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, list_box_version_history);
+       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, box_version_history_frame);
+       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, row_latest_version);
+       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, version_history_button);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, box_reviews);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, box_details_screenshot_fallback);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, histogram);
@@ -2948,6 +2959,12 @@ gs_details_page_init (GsDetailsPage *self)
                                    list_sort_func,
                                    self, NULL);
 
+       gtk_list_box_set_header_func (GTK_LIST_BOX (self->list_box_version_history),
+                                     list_header_func,
+                                     self, NULL);
+       g_signal_connect (self->list_box_version_history, "row-activated",
+                         G_CALLBACK (version_history_list_row_activated_cb), self);
+
        gtk_style_context_add_class (gtk_widget_get_style_context (self->button_details_permissions_value), 
"content-rating-permissions");
 }
 
diff --git a/src/gs-details-page.ui b/src/gs-details-page.ui
index fce2ca3af..e4f65d527 100644
--- a/src/gs-details-page.ui
+++ b/src/gs-details-page.ui
@@ -444,6 +444,60 @@
                             </child>
                           </object>
                         </child>
+                        <child>
+                          <object class="GtkFrame" id="box_version_history_frame">
+                            <property name="visible">True</property>
+                            <property name="shadow_type">in</property>
+                            <property name="halign">fill</property>
+                            <property name="valign">start</property>
+                            <style>
+                              <class name="view"/>
+                            </style>
+                            <child>
+                              <object class="GtkListBox" id="list_box_version_history">
+                                <property name="visible">True</property>
+                                <property name="selection_mode">none</property>
+                                <style>
+                                  <class name="content"/>
+                                </style>
+                                <child>
+                                  <object class="GsAppVersionHistoryRow" id="row_latest_version">
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkListBoxRow" id="version_history_button">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <child>
+                                      <object class="GtkBox">
+                                        <property name="visible">True</property>
+                                        <property name="orientation">horizontal</property>
+                                        <property name="halign">center</property>
+                                        <property name="margin_top">12</property>
+                                        <property name="margin_bottom">12</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="xalign">0</property>
+                                            <property name="yalign">0.5</property>
+                                            <property name="label" translatable="yes">Version 
History</property>
+                                          </object>
+                                        </child>
+                                        <child>
+                                          <object class="GtkImage">
+                                            <property name="visible">True</property>
+                                            <property name="icon-name">go-next-symbolic</property>
+                                            <property name="margin_start">6</property>
+                                          </object>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
                         <child>
                           <object class="GtkLabel" id="label_webapp_warning">
                             <property name="visible">False</property>
@@ -713,77 +767,6 @@
                                   </packing>
                                 </child>
 
-                                <child>
-                                  <object class="GtkLabel" id="label_details_version_title">
-                                    <property name="visible">True</property>
-                                    <property name="label" translatable="yes">Version</property>
-                                    <property name="xalign">0</property>
-                                    <property name="yalign">0.5</property>
-                                    <property name="vexpand">True</property>
-                                    <style>
-                                      <class name="dim-label"/>
-                                    </style>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">0</property>
-                                    <property name="top_attach">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label_details_version_value">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="hexpand">True</property>
-                                    <property name="label">0.12.3</property>
-                                    <property name="selectable">True</property>
-                                    <property name="ellipsize">end</property>
-                                    <property name="xalign">0</property>
-                                    <property name="yalign">0.5</property>
-                                    <accessibility>
-                                      <relation type="labelled-by" target="label_details_version_title"/>
-                                    </accessibility>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="top_attach">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label_details_released_title">
-                                    <property name="visible">True</property>
-                                    <property name="label" translatable="yes">Released</property>
-                                    <property name="xalign">0</property>
-                                    <property name="yalign">0.5</property>
-                                    <property name="vexpand">True</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="GtkLabel" id="label_details_released_value">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="hexpand">True</property>
-                                    <property name="label">0.12.3</property>
-                                    <property name="selectable">True</property>
-                                    <property name="ellipsize">end</property>
-                                    <property name="xalign">0</property>
-                                    <property name="yalign">0.5</property>
-                                    <accessibility>
-                                      <relation type="labelled-by" target="label_details_released_title"/>
-                                    </accessibility>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="top_attach">2</property>
-                                  </packing>
-                                </child>
-
                                 <child>
                                   <object class="GtkLabel" id="label_details_rating_title">
                                     <property name="visible">True</property>
@@ -1262,7 +1245,6 @@
   <object class="GtkSizeGroup" id="sizegroup_details_title">
     <property name="ignore_hidden">True</property>
     <widgets>
-      <widget name="label_details_version_title"/>
       <widget name="label_details_updated_title"/>
       <widget name="label_details_category_title"/>
       <widget name="label_details_origin_title"/>
@@ -1275,7 +1257,6 @@
   <object class="GtkSizeGroup" id="sizegroup_details_value">
     <property name="ignore_hidden">True</property>
     <widgets>
-      <widget name="label_details_version_value"/>
       <widget name="label_details_updated_value"/>
       <widget name="label_details_category_value"/>
       <widget name="label_details_size_installed_value"/>
diff --git a/src/meson.build b/src/meson.build
index 7e4cf4f66..49d708c6e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -17,6 +17,8 @@ gdbus_src = gnome.gdbus_codegen(
 
 gnome_software_sources = [
   'gs-app-addon-row.c',
+  'gs-app-version-history-dialog.c',
+  'gs-app-version-history-row.c',
   'gs-application.c',
   'gs-app-row.c',
   'gs-app-tile.c',


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