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




commit b6535983955badcef3f98611b53d25724a65bb79
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          |  12 ++--
 po/POTFILES.in                       |   3 +
 src/gnome-software.gresource.xml     |   2 +
 src/gs-app-version-history-dialog.c  | 101 ++++++++++++++++++++++++++++
 src/gs-app-version-history-dialog.h  |  24 +++++++
 src/gs-app-version-history-dialog.ui |  59 +++++++++++++++++
 src/gs-app-version-history-row.c     | 102 ++++++++++++++++++++++++++++
 src/gs-app-version-history-row.h     |  27 ++++++++
 src/gs-app-version-history-row.ui    |  61 +++++++++++++++++
 src/gs-common.c                      |   1 +
 src/gs-details-page.c                |  86 ++++++++++++++----------
 src/gs-details-page.ui               | 124 ++++++++++++++---------------------
 src/meson.build                      |   2 +
 13 files changed, 493 insertions(+), 111 deletions(-)
---
diff --git a/plugins/core/gs-appstream.c b/plugins/core/gs-appstream.c
index 94b0666f8..aa8ba644f 100644
--- a/plugins/core/gs-appstream.c
+++ b/plugins/core/gs-appstream.c
@@ -574,16 +574,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);
@@ -592,9 +595,10 @@ 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);
+                       as_release_set_description (release, "C", description);
 
                g_ptr_array_add (version_history, g_steal_pointer (&release));
        }
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ecae3db32..83f714717 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..2d0af40b3
--- /dev/null
+++ b/src/gs-app-version-history-dialog.c
@@ -0,0 +1,101 @@
+/* -*- 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)
+               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, "C"));
+
+               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..e476ae904
--- /dev/null
+++ b/src/gs-app-version-history-dialog.ui
@@ -0,0 +1,59 @@
+<?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">400</property>
+    <property name="default_height">400</property>
+    <property name="modal">True</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="use_header_bar">1</property>
+    <child internal-child="headerbar">
+      <object class="GtkHeaderBar">
+        <child type="title">
+          <object class="GtkLabel" id="label_header">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">Version History</property>
+            <property name="selectable">False</property>
+            <style>
+              <class name="title"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow">
+            <property name="visible">True</property>
+            <property name="margin">6</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <object class="GtkFrame" id="frame">
+                <property name="visible">True</property>
+                <property name="shadow_type">in</property>
+                <property name="halign">fill</property>
+                <property name="valign">start</property>
+                <property name="vexpand">True</property>
+                <child>
+                  <object class="GtkListBox" id="listbox">
+                    <property name="visible">True</property>
+                    <property name="selection_mode">none</property>
+                  </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..8c2346718
--- /dev/null
+++ b/src/gs-app-version-history-row.c
@@ -0,0 +1,102 @@
+/* -*- 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);
+               gtk_widget_set_visible (row->version_description_label, TRUE);
+       } else {
+               g_autofree char *version_tmp = NULL;
+               version_tmp = g_strdup_printf (_("Version %s"), version_number);
+               gtk_label_set_label (GTK_LABEL (row->version_number_label), version_tmp);
+               gtk_widget_set_visible (row->version_description_label, FALSE);
+       }
+
+       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" */
+               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..85d019769
--- /dev/null
+++ b/src/gs-app-version-history-row.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <template class="GsAppVersionHistoryRow" parent="GtkListBoxRow">
+    <property name="visible">True</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 b8c39cb07..d389981e9 100644
--- a/src/gs-common.c
+++ b/src/gs-common.c
@@ -680,6 +680,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 379bb1bda..dccb8fab3 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -20,6 +20,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"
@@ -112,16 +114,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;
@@ -1110,6 +1112,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);
@@ -1201,34 +1204,27 @@ 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);
+               gtk_widget_set_visible (self->version_history_button, FALSE);
+               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, "C"));
        }
 
        /* 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) {
@@ -1422,14 +1418,10 @@ gs_details_page_refresh_all (GsDetailsPage *self)
        case AS_APP_KIND_SOURCE:
                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;
        }
 
@@ -1466,6 +1458,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);
 
@@ -2889,14 +2901,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);
@@ -2955,6 +2967,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 a26cc5b55..462f5e81f 100644
--- a/src/gs-details-page.ui
+++ b/src/gs-details-page.ui
@@ -444,6 +444,57 @@
                             </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>
+                                <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 +764,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 +1242,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 +1254,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 82d3fb391..2161a03f7 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]