[gnome-software] Break out the update dialog as a separate object
- From: Kalev Lember <klember src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Break out the update dialog as a separate object
- Date: Thu, 6 Mar 2014 22:36:41 +0000 (UTC)
commit 99fb74b1c04a467865a98ca75c546f9039b3af55
Author: Kalev Lember <kalevlember gmail com>
Date: Sat Mar 1 22:29:22 2014 +0100
Break out the update dialog as a separate object
At the same time, move to a separate GtkBuilder template.
https://bugzilla.gnome.org/show_bug.cgi?id=725579
po/POTFILES.in | 2 +
src/Makefile.am | 3 +
src/gnome-software.gresource.xml | 1 +
src/gnome-software.ui | 209 ---------------------------
src/gs-shell-updates.c | 244 ++------------------------------
src/gs-update-dialog.c | 288 ++++++++++++++++++++++++++++++++++++++
src/gs-update-dialog.h | 59 ++++++++
src/gs-update-dialog.ui | 212 ++++++++++++++++++++++++++++
8 files changed, 576 insertions(+), 442 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3b67194..9c5e3d8 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -24,6 +24,8 @@ src/gs-shell-installed.c
src/gs-shell-overview.c
src/gs-shell-search.c
src/gs-shell-updates.c
+src/gs-update-dialog.c
+[type: gettext/glade]src/gs-update-dialog.ui
src/gs-update-monitor.c
[type: gettext/glade]src/gs-star-widget.ui
src/gs-utils.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 4dda90c..258d59d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,7 @@ UI_FILES = \
gnome-software.ui \
gs-history-dialog.ui \
gs-star-widget.ui \
+ gs-update-dialog.ui \
screenshot-image.ui \
popular-tile.ui
@@ -130,6 +131,8 @@ gnome_software_SOURCES = \
gs-shell-updates.h \
gs-shell-search.c \
gs-shell-search.h \
+ gs-update-dialog.c \
+ gs-update-dialog.h \
gs-update-monitor.c \
gs-update-monitor.h \
gs-proxy-settings.c \
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index 23dd7a2..06f8f97 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -12,6 +12,7 @@
<file preprocess="xml-stripblanks">screenshot-image.ui</file>
<file preprocess="xml-stripblanks">gs-history-dialog.ui</file>
<file preprocess="xml-stripblanks">gs-star-widget.ui</file>
+ <file preprocess="xml-stripblanks">gs-update-dialog.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/gnome-software.ui b/src/gnome-software.ui
index 419bb01..1d58367 100644
--- a/src/gnome-software.ui
+++ b/src/gnome-software.ui
@@ -2037,215 +2037,6 @@
</object>
</child>
</object>
- <object class="GtkDialog" id="dialog_update">
- <property name="can_focus">False</property>
- <property name="modal">True</property>
- <property name="use-header-bar">1</property>
- <property name="default_width">600</property>
- <property name="default_height">600</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <property name="transient_for">window_software</property>
- <child internal-child="headerbar">
- <object class="GtkHeaderBar">
- <child>
- <object class="GtkButton" id="button_update_back">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="button_update_back_accessible">
- <property name="accessible-name" translatable="yes">Go back</property>
- </object>
- </child>
- <style>
- <class name="image-button"/>
- </style>
- <child>
- <object class="GtkImage" id="image_update_back">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">go-previous-symbolic</property>
- <property name="icon_size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="pack-type">start</property>
- </packing>
- </child>
- </object>
- </child>
- <child internal-child="vbox">
- <object class="GtkBox" id="dialog-vbox1">
- <property name="can_focus">False</property>
- <property name="margin_start">6</property>
- <property name="margin_end">6</property>
- <property name="margin_top">6</property>
- <property name="margin_bottom">6</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkBox" id="box7">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_bottom">3</property>
- <property name="border_width">3</property>
- <property name="orientation">vertical</property>
- <property name="spacing">9</property>
- <child>
- <object class="GtkBox" id="box_update_header">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">9</property>
- <child>
- <object class="GtkImage" id="image_update_icon">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">96</property>
- <property name="icon_name">accessories-calculator</property>
- <property name="icon_size">0</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="box9">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">3</property>
- <child>
- <object class="GtkLabel" id="label_update_name">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="label">Inkscape</property>
- <property name="angle">0.41999998688697815</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- <attribute name="scale" value="1.3999999999999999"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label_update_summary">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="label">Vector based drawing program</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow_update_details">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="vexpand">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">none</property>
- <property name="kinetic_scrolling">False</property>
- <child>
- <object class="GtkLabel" id="label_update_details">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="margin">6</property>
- <property name="label">New in kmod 14-1
-* Moo
-* bar</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow_update">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="vexpand">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">none</property>
- <property name="kinetic_scrolling">False</property>
- <child>
- <object class="GtkFrame" id="box_update_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_update">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="selection_mode">none</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <object class="GtkSizeGroup" id="sizegroup_update_details">
- <property name="ignore-hidden">False</property>
- <property name="mode">horizontal</property>
- <widgets>
- <widget name="scrolledwindow_update"/>
- <widget name="scrolledwindow_update_details"/>
- </widgets>
- </object>
<object class="GtkSizeGroup" id="sizegroup_details_buttons">
<widgets>
<widget name="button_details_website"/>
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index a10447d..2c596ae 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -30,6 +30,7 @@
#include "gs-app.h"
#include "gs-app-widget.h"
#include "gs-markdown.h"
+#include "gs-update-dialog.h"
/* this isn't ideal, as PK should be abstracted away in a plugin, but
* GNetworkMonitor doesn't provide us with a connection type */
@@ -59,7 +60,7 @@ struct GsShellUpdatesPrivate
GtkListBox *list_box_updates;
gboolean cache_valid;
GsShell *shell;
- GsApp *app;
+ GtkWidget *update_dialog;
PkControl *control;
GsShellUpdatesState state;
gboolean has_agreed_to_mobile_data;
@@ -428,150 +429,18 @@ gs_shell_updates_refresh (GsShellUpdates *shell_updates,
shell_updates);
}
-/**
- * gs_shell_updates_set_updates_description_ui:
- **/
-static void
-gs_shell_updates_set_updates_description_ui (GsShellUpdates *shell_updates, GsApp *app)
-{
- GsShellUpdatesPrivate *priv = shell_updates->priv;
- GsAppKind kind;
- GsMarkdown *markdown;
- GtkWidget *widget;
- gchar *tmp;
- gchar *update_desc;
-
- /* set window title */
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_update"));
- kind = gs_app_get_kind (app);
- if (kind == GS_APP_KIND_OS_UPDATE) {
- gtk_window_set_title (GTK_WINDOW (widget), gs_app_get_name (app));
- } else {
- tmp = g_strdup_printf ("%s %s",
- gs_app_get_source_default (app),
- gs_app_get_update_version_ui (app));
- gtk_window_set_title (GTK_WINDOW (widget), tmp);
- g_free (tmp);
- }
-
- /* get the update description */
- if (gs_app_get_update_details (app) == NULL) {
- /* TRANSLATORS: this is where the packager did not write a
- * description for the update */
- update_desc = g_strdup ("No update description");
- } else {
- markdown = gs_markdown_new (GS_MARKDOWN_OUTPUT_PANGO);
- gs_markdown_set_smart_quoting (markdown, FALSE);
- gs_markdown_set_autocode (markdown, TRUE);
- update_desc = gs_markdown_parse (markdown, gs_app_get_update_details (app));
- g_object_unref (markdown);
- }
-
- /* set update header */
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "box_update_header"));
- gtk_widget_set_visible (widget, kind == GS_APP_KIND_NORMAL || kind == GS_APP_KIND_SYSTEM);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "scrolledwindow_update_details"));
- gtk_widget_set_visible (widget, kind != GS_APP_KIND_OS_UPDATE);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "scrolledwindow_update"));
- gtk_widget_set_visible (widget, kind == GS_APP_KIND_OS_UPDATE);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_update_details"));
- gtk_label_set_markup (GTK_LABEL (widget), update_desc);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "image_update_icon"));
- gtk_image_set_from_pixbuf (GTK_IMAGE (widget), gs_app_get_pixbuf (app));
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_update_name"));
- gtk_label_set_label (GTK_LABEL (widget), gs_app_get_name (app));
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_update_summary"));
- gtk_label_set_label (GTK_LABEL (widget), gs_app_get_summary (app));
- g_free (update_desc);
-}
-
static void
-gs_shell_updates_row_activated_cb (GtkListBox *list_box,
- GtkListBoxRow *row,
- GsShellUpdates *shell_updates)
+show_update_details (GsApp *app, GsShellUpdates *shell_updates)
{
GsShellUpdatesPrivate *priv = shell_updates->priv;
- GsApp *app = NULL;
- GtkWidget *widget;
+ GtkWidget *toplevel;
- app = GS_APP (g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (row))), "app"));
- /* setup package view */
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "scrolledwindow_update"));
- gtk_widget_hide (widget);
- gs_shell_updates_set_updates_description_ui (shell_updates, app);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_update_back"));
- gtk_widget_show (widget);
-}
+ gs_update_dialog_set_app (GS_UPDATE_DIALOG (priv->update_dialog), app);
-static void
-show_update_details (GsApp *app, GsShellUpdates *shell_updates)
-{
- GsShellUpdatesPrivate *priv = shell_updates->priv;
- GsApp *app_related;
- GsAppKind kind;
- GtkWidget *widget;
- const gchar *sort;
-
- kind = gs_app_get_kind (app);
-
- /* set update header */
- gs_shell_updates_set_updates_description_ui (shell_updates, app);
-
- /* only OS updates can go back, and only on selection */
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_update_back"));
- gtk_widget_hide (widget);
-
- /* set update description */
- if (kind == GS_APP_KIND_OS_UPDATE) {
- GPtrArray *related;
- GtkListBox *list_box;
- guint i;
- GtkWidget *row, *label;
-
- list_box = GTK_LIST_BOX (gtk_builder_get_object (priv->builder, "list_box_update"));
- gs_container_remove_all (GTK_CONTAINER (list_box));
- related = gs_app_get_related (app);
- for (i = 0; i < related->len; i++) {
- app_related = g_ptr_array_index (related, i);
- row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
- g_object_set_data_full (G_OBJECT (row),
- "app",
- g_object_ref (app_related),
- g_object_unref);
- sort = gs_app_get_source_default (app_related);
- g_object_set_data_full (G_OBJECT (row),
- "sort",
- g_strdup (sort),
- g_free);
- label = gtk_label_new (gs_app_get_source_default (app_related));
- g_object_set (label,
- "margin-left", 20,
- "margin-right", 20,
- "margin-top", 6,
- "margin-bottom", 6,
- "xalign", 0.0,
- NULL);
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
- gtk_box_pack_start (GTK_BOX (row), label, TRUE, TRUE, 0);
- label = gtk_label_new (gs_app_get_update_version_ui (app_related));
- g_object_set (label,
- "margin-left", 20,
- "margin-right", 20,
- "margin-top", 6,
- "margin-bottom", 6,
- "xalign", 1.0,
- NULL);
- gtk_widget_set_halign (label, GTK_ALIGN_END);
- gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
- gtk_box_pack_start (GTK_BOX (row), label, FALSE, FALSE, 0);
- gtk_widget_show_all (row);
- gtk_list_box_insert (list_box,row, -1);
- }
- }
+ toplevel = GTK_WIDGET (gtk_builder_get_object (priv->builder, "window_software"));
+ gtk_window_set_transient_for (GTK_WINDOW (priv->update_dialog), GTK_WINDOW (toplevel));
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_update"));
- gtk_window_present (GTK_WINDOW (widget));
+ gtk_window_present (GTK_WINDOW (priv->update_dialog));
}
/**
@@ -582,17 +451,13 @@ gs_shell_updates_activated_cb (GtkListBox *list_box,
GtkListBoxRow *row,
GsShellUpdates *shell_updates)
{
- GsShellUpdatesPrivate *priv = shell_updates->priv;
GsAppWidget *app_widget;
GsApp *app;
app_widget = GS_APP_WIDGET (gtk_bin_get_child (GTK_BIN (row)));
app = gs_app_widget_get_app (app_widget);
- g_clear_object (&priv->app);
- priv->app = g_object_ref (app);
-
- show_update_details (priv->app, shell_updates);
+ show_update_details (app, shell_updates);
}
/**
@@ -869,28 +734,6 @@ gs_shell_updates_button_refresh_cb (GtkWidget *widget,
}
/**
- * gs_shell_updates_button_back_cb:
- **/
-static void
-gs_shell_updates_button_back_cb (GtkWidget *widget, GsShellUpdates *shell_updates)
-{
- GsShellUpdatesPrivate *priv = shell_updates->priv;
-
- /* return to the list view */
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_update_back"));
- gtk_widget_hide (widget);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "box_update_header"));
- gtk_widget_hide (widget);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "scrolledwindow_update_details"));
- gtk_widget_hide (widget);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "scrolledwindow_update"));
- gtk_widget_show (widget);
-
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_update"));
- gtk_window_set_title (GTK_WINDOW (widget), gs_app_get_name (priv->app));
-}
-
-/**
* gs_shell_updates_changed_cb:
*/
static void
@@ -919,31 +762,6 @@ gs_shell_updates_button_update_all_cb (GtkButton *button,
gs_reboot (gs_offline_updates_cancel);
}
-static void
-scrollbar_mapped_cb (GtkWidget *sb, GtkScrolledWindow *swin)
-{
- GtkWidget *frame;
-
- frame = gtk_bin_get_child (GTK_BIN (gtk_bin_get_child (GTK_BIN (swin))));
-
- if (gtk_widget_get_mapped (GTK_WIDGET (sb))) {
- gtk_scrolled_window_set_shadow_type (swin, GTK_SHADOW_IN);
- if (GTK_IS_FRAME (frame))
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
- } else {
- if (GTK_IS_FRAME (frame))
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
- gtk_scrolled_window_set_shadow_type (swin, GTK_SHADOW_NONE);
- }
-}
-
-static void
-dialog_update_hide_cb (GtkWidget *dialog, GsShellUpdates *shell_updates)
-{
- g_clear_object (&shell_updates->priv->app);
-}
-
-
/**
* gs_shell_installed_sort_func:
**/
@@ -1009,21 +827,6 @@ gs_shell_updates_sort_func (GtkListBoxRow *a,
}
/**
- * gs_shell_updates_os_updates_sort_func:
- **/
-static gint
-gs_shell_updates_os_updates_sort_func (GtkListBoxRow *a,
- GtkListBoxRow *b,
- gpointer user_data)
-{
- GObject *o1 = G_OBJECT (gtk_bin_get_child (GTK_BIN (a)));
- GObject *o2 = G_OBJECT (gtk_bin_get_child (GTK_BIN (b)));
- const gchar *key1 = g_object_get_data (o1, "sort");
- const gchar *key2 = g_object_get_data (o2, "sort");
- return g_strcmp0 (key1, key2);
-}
-
-/**
* gs_shell_updates_get_properties_cb:
**/
static void
@@ -1054,7 +857,6 @@ gs_shell_updates_setup (GsShellUpdates *shell_updates,
{
GsShellUpdatesPrivate *priv = shell_updates->priv;
GtkWidget *widget;
- GtkWidget *sw;
g_return_if_fail (GS_IS_SHELL_UPDATES (shell_updates));
@@ -1082,13 +884,6 @@ gs_shell_updates_setup (GsShellUpdates *shell_updates,
gs_shell_updates_sort_func,
shell_updates, NULL);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "list_box_update"));
- g_signal_connect (GTK_LIST_BOX (widget), "row-activated",
- G_CALLBACK (gs_shell_updates_row_activated_cb), shell_updates);
- gtk_list_box_set_sort_func (GTK_LIST_BOX (widget),
- gs_shell_updates_os_updates_sort_func,
- shell_updates, NULL);
-
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_update_all"));
g_signal_connect (widget, "clicked", G_CALLBACK (gs_shell_updates_button_update_all_cb),
shell_updates);
@@ -1105,25 +900,9 @@ gs_shell_updates_setup (GsShellUpdates *shell_updates,
g_signal_connect (widget, "clicked",
G_CALLBACK (gs_shell_updates_button_network_settings_cb),
shell_updates);
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_update"));
- g_signal_connect (widget, "delete-event",
+ priv->update_dialog = gs_update_dialog_new ();
+ g_signal_connect (priv->update_dialog, "delete-event",
G_CALLBACK (gtk_widget_hide_on_delete), shell_updates);
- g_signal_connect (widget, "hide",
- G_CALLBACK (dialog_update_hide_cb), shell_updates);
-
- widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_update_back"));
- g_signal_connect (widget, "clicked",
- G_CALLBACK (gs_shell_updates_button_back_cb),
- shell_updates);
- sw = GTK_WIDGET (gtk_builder_get_object (priv->builder, "scrolledwindow_update_details"));
- widget = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (sw));
- g_signal_connect (widget, "map", G_CALLBACK (scrollbar_mapped_cb), sw);
- g_signal_connect (widget, "unmap", G_CALLBACK (scrollbar_mapped_cb), sw);
-
- sw = GTK_WIDGET (gtk_builder_get_object (priv->builder, "scrolledwindow_update"));
- widget = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (sw));
- g_signal_connect (widget, "map", G_CALLBACK (scrollbar_mapped_cb), sw);
- g_signal_connect (widget, "unmap", G_CALLBACK (scrollbar_mapped_cb), sw);
g_signal_connect (priv->control, "notify::network-state",
G_CALLBACK (gs_shell_updates_notify_network_state_cb),
@@ -1175,7 +954,6 @@ gs_shell_updates_finalize (GObject *object)
g_object_unref (priv->plugin_loader);
g_object_unref (priv->cancellable);
g_object_unref (priv->control);
- g_clear_object (&priv->app);
G_OBJECT_CLASS (gs_shell_updates_parent_class)->finalize (object);
}
diff --git a/src/gs-update-dialog.c b/src/gs-update-dialog.c
new file mode 100644
index 0000000..9d9bee2
--- /dev/null
+++ b/src/gs-update-dialog.c
@@ -0,0 +1,288 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013-2014 Richard Hughes <richard hughsie 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 <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gs-update-dialog.h"
+#include "gs-markdown.h"
+#include "gs-utils.h"
+
+struct _GsUpdateDialogPrivate
+{
+ GsApp *app;
+ GtkWidget *box_header;
+ GtkWidget *button_back;
+ GtkWidget *image_icon;
+ GtkWidget *label_details;
+ GtkWidget *label_name;
+ GtkWidget *label_summary;
+ GtkWidget *list_box;
+ GtkWidget *scrolledwindow;
+ GtkWidget *scrolledwindow_details;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsUpdateDialog, gs_update_dialog, GTK_TYPE_DIALOG)
+
+static void
+set_updates_description_ui (GsUpdateDialog *dialog, GsApp *app)
+{
+ GsUpdateDialogPrivate *priv = gs_update_dialog_get_instance_private (dialog);
+ GsAppKind kind;
+ GsMarkdown *markdown;
+ gchar *tmp;
+ gchar *update_desc;
+
+ /* set window title */
+ kind = gs_app_get_kind (app);
+ if (kind == GS_APP_KIND_OS_UPDATE) {
+ gtk_window_set_title (GTK_WINDOW (dialog), gs_app_get_name (app));
+ } else {
+ tmp = g_strdup_printf ("%s %s",
+ gs_app_get_source_default (app),
+ gs_app_get_update_version_ui (app));
+ gtk_window_set_title (GTK_WINDOW (dialog), tmp);
+ g_free (tmp);
+ }
+
+ /* get the update description */
+ if (gs_app_get_update_details (app) == NULL) {
+ /* TRANSLATORS: this is where the packager did not write a
+ * description for the update */
+ update_desc = g_strdup ("No update description");
+ } else {
+ markdown = gs_markdown_new (GS_MARKDOWN_OUTPUT_PANGO);
+ gs_markdown_set_smart_quoting (markdown, FALSE);
+ gs_markdown_set_autocode (markdown, TRUE);
+ update_desc = gs_markdown_parse (markdown, gs_app_get_update_details (app));
+ g_object_unref (markdown);
+ }
+
+ /* set update header */
+ gtk_widget_set_visible (priv->box_header, kind == GS_APP_KIND_NORMAL || kind == GS_APP_KIND_SYSTEM);
+ gtk_widget_set_visible (priv->scrolledwindow_details, kind != GS_APP_KIND_OS_UPDATE);
+ gtk_widget_set_visible (priv->scrolledwindow, kind == GS_APP_KIND_OS_UPDATE);
+ gtk_label_set_markup (GTK_LABEL (priv->label_details), update_desc);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image_icon), gs_app_get_pixbuf (app));
+ gtk_label_set_label (GTK_LABEL (priv->label_name), gs_app_get_name (app));
+ gtk_label_set_label (GTK_LABEL (priv->label_summary), gs_app_get_summary (app));
+ g_free (update_desc);
+}
+
+static void
+row_activated_cb (GtkListBox *list_box,
+ GtkListBoxRow *row,
+ GsUpdateDialog *dialog)
+{
+ GsUpdateDialogPrivate *priv = gs_update_dialog_get_instance_private (dialog);
+ GsApp *app = NULL;
+
+ app = GS_APP (g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (row))), "app"));
+ /* setup package view */
+ gtk_widget_hide (priv->scrolledwindow);
+ set_updates_description_ui (dialog, app);
+ gtk_widget_show (priv->button_back);
+}
+
+void
+gs_update_dialog_set_app (GsUpdateDialog *dialog, GsApp *app)
+{
+ GsUpdateDialogPrivate *priv = gs_update_dialog_get_instance_private (dialog);
+ GsApp *app_related;
+ GsAppKind kind;
+ const gchar *sort;
+
+ g_clear_object (&priv->app);
+ priv->app = g_object_ref (app);
+
+ kind = gs_app_get_kind (app);
+
+ /* set update header */
+ set_updates_description_ui (dialog, app);
+
+ /* only OS updates can go back, and only on selection */
+ gtk_widget_hide (priv->button_back);
+
+ /* set update description */
+ if (kind == GS_APP_KIND_OS_UPDATE) {
+ GPtrArray *related;
+ GtkListBox *list_box;
+ guint i;
+ GtkWidget *row, *label;
+
+ list_box = GTK_LIST_BOX (priv->list_box);
+ gs_container_remove_all (GTK_CONTAINER (list_box));
+ related = gs_app_get_related (app);
+ for (i = 0; i < related->len; i++) {
+ app_related = g_ptr_array_index (related, i);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ g_object_set_data_full (G_OBJECT (row),
+ "app",
+ g_object_ref (app_related),
+ g_object_unref);
+ sort = gs_app_get_source_default (app_related);
+ g_object_set_data_full (G_OBJECT (row),
+ "sort",
+ g_strdup (sort),
+ g_free);
+ label = gtk_label_new (gs_app_get_source_default (app_related));
+ g_object_set (label,
+ "margin-left", 20,
+ "margin-right", 20,
+ "margin-top", 6,
+ "margin-bottom", 6,
+ "xalign", 0.0,
+ NULL);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), label, TRUE, TRUE, 0);
+ label = gtk_label_new (gs_app_get_update_version_ui (app_related));
+ g_object_set (label,
+ "margin-left", 20,
+ "margin-right", 20,
+ "margin-top", 6,
+ "margin-bottom", 6,
+ "xalign", 1.0,
+ NULL);
+ gtk_widget_set_halign (label, GTK_ALIGN_END);
+ gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), label, FALSE, FALSE, 0);
+ gtk_widget_show_all (row);
+ gtk_list_box_insert (list_box,row, -1);
+ }
+ }
+}
+
+static gint
+os_updates_sort_func (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ GObject *o1 = G_OBJECT (gtk_bin_get_child (GTK_BIN (a)));
+ GObject *o2 = G_OBJECT (gtk_bin_get_child (GTK_BIN (b)));
+ const gchar *key1 = g_object_get_data (o1, "sort");
+ const gchar *key2 = g_object_get_data (o2, "sort");
+ return g_strcmp0 (key1, key2);
+}
+
+
+static void
+button_back_cb (GtkWidget *widget, GsUpdateDialog *dialog)
+{
+ GsUpdateDialogPrivate *priv = gs_update_dialog_get_instance_private (dialog);
+
+ /* return to the list view */
+ gtk_widget_hide (priv->button_back);
+ gtk_widget_hide (priv->box_header);
+ gtk_widget_hide (priv->scrolledwindow_details);
+ gtk_widget_show (priv->scrolledwindow);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), gs_app_get_name (priv->app));
+}
+
+static void
+scrollbar_mapped_cb (GtkWidget *sb, GtkScrolledWindow *swin)
+{
+ GtkWidget *frame;
+
+ frame = gtk_bin_get_child (GTK_BIN (gtk_bin_get_child (GTK_BIN (swin))));
+
+ if (gtk_widget_get_mapped (GTK_WIDGET (sb))) {
+ gtk_scrolled_window_set_shadow_type (swin, GTK_SHADOW_IN);
+ if (GTK_IS_FRAME (frame))
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+ } else {
+ if (GTK_IS_FRAME (frame))
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_shadow_type (swin, GTK_SHADOW_NONE);
+ }
+}
+
+static void
+gs_update_dialog_finalize (GObject *object)
+{
+ GsUpdateDialog *dialog = GS_UPDATE_DIALOG (object);
+ GsUpdateDialogPrivate *priv = gs_update_dialog_get_instance_private (dialog);
+
+ g_clear_object (&priv->app);
+
+ G_OBJECT_CLASS (gs_update_dialog_parent_class)->finalize (object);
+}
+
+static void
+gs_update_dialog_init (GsUpdateDialog *dialog)
+{
+ GsUpdateDialogPrivate *priv = gs_update_dialog_get_instance_private (dialog);
+ GtkWidget *scrollbar;
+
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+
+ g_signal_connect (GTK_LIST_BOX (priv->list_box), "row-activated",
+ G_CALLBACK (row_activated_cb), dialog);
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->list_box),
+ os_updates_sort_func,
+ dialog, NULL);
+
+ g_signal_connect (priv->button_back, "clicked",
+ G_CALLBACK (button_back_cb),
+ dialog);
+
+ scrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (priv->scrolledwindow_details));
+ g_signal_connect (scrollbar, "map", G_CALLBACK (scrollbar_mapped_cb), priv->scrolledwindow_details);
+ g_signal_connect (scrollbar, "unmap", G_CALLBACK (scrollbar_mapped_cb), priv->scrolledwindow_details);
+
+ scrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
+ g_signal_connect (scrollbar, "map", G_CALLBACK (scrollbar_mapped_cb), priv->scrolledwindow);
+ g_signal_connect (scrollbar, "unmap", G_CALLBACK (scrollbar_mapped_cb), priv->scrolledwindow);
+}
+
+static void
+gs_update_dialog_class_init (GsUpdateDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = gs_update_dialog_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/software/gs-update-dialog.ui");
+
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, box_header);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, button_back);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, image_icon);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, label_details);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, label_name);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, label_summary);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, list_box);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, scrolledwindow);
+ gtk_widget_class_bind_template_child_private (widget_class, GsUpdateDialog, scrolledwindow_details);
+}
+
+GtkWidget *
+gs_update_dialog_new (void)
+{
+ return GTK_WIDGET (g_object_new (GS_TYPE_UPDATE_DIALOG,
+ "use-header-bar", TRUE,
+ NULL));
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-update-dialog.h b/src/gs-update-dialog.h
new file mode 100644
index 0000000..0a64c80
--- /dev/null
+++ b/src/gs-update-dialog.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie 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_UPDATE_DIALOG_H
+#define GS_UPDATE_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+
+#define GS_TYPE_UPDATE_DIALOG (gs_update_dialog_get_type())
+#define GS_UPDATE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GS_TYPE_UPDATE_DIALOG,
GsUpdateDialog))
+#define GS_UPDATE_DIALOG_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls), GS_TYPE_UPDATE_DIALOG,
GsUpdateDialogClass))
+#define GS_IS_UPDATE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GS_TYPE_UPDATE_DIALOG))
+#define GS_IS_UPDATE_DIALOG_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE((cls), GS_TYPE_UPDATE_DIALOG))
+#define GS_UPDATE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GS_TYPE_UPDATE_DIALOG,
GsUpdateDialogClass))
+
+G_BEGIN_DECLS
+
+typedef struct _GsUpdateDialog GsUpdateDialog;
+typedef struct _GsUpdateDialogClass GsUpdateDialogClass;
+typedef struct _GsUpdateDialogPrivate GsUpdateDialogPrivate;
+
+struct _GsUpdateDialog
+{
+ GtkDialog parent;
+};
+
+struct _GsUpdateDialogClass
+{
+ GtkDialogClass parent_class;
+};
+
+GType gs_update_dialog_get_type (void);
+GtkWidget *gs_update_dialog_new (void);
+void gs_update_dialog_set_app (GsUpdateDialog *dialog,
+ GsApp *app);
+
+#endif /* GS_UPDATE_DIALOG_H */
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-update-dialog.ui b/src/gs-update-dialog.ui
new file mode 100644
index 0000000..8628ec3
--- /dev/null
+++ b/src/gs-update-dialog.ui
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <template class="GsUpdateDialog" parent="GtkDialog">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">600</property>
+ <property name="default_height">600</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <child>
+ <object class="GtkButton" id="button_back">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="button_back_accessible">
+ <property name="accessible-name" translatable="yes">Go back</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="image_update_back">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkBox" id="box7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">3</property>
+ <property name="border_width">3</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkBox" id="box_header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkImage" id="image_icon">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixel_size">96</property>
+ <property name="icon_name">accessories-calculator</property>
+ <property name="icon_size">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkLabel" id="label_name">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label">Inkscape</property>
+ <property name="angle">0.41999998688697815</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.3999999999999999"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_summary">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label">Vector based drawing program</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_details">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">none</property>
+ <property name="kinetic_scrolling">False</property>
+ <child>
+ <object class="GtkLabel" id="label_details">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="margin">6</property>
+ <property name="label">New in kmod 14-1
+* Moo
+* bar</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">none</property>
+ <property name="kinetic_scrolling">False</property>
+ <child>
+ <object class="GtkFrame" id="box_update_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">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="selection_mode">none</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup" id="sizegroup_update_details">
+ <property name="ignore-hidden">False</property>
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="scrolledwindow"/>
+ <widget name="scrolledwindow_details"/>
+ </widgets>
+ </object>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]