[gnome-software] Add an initial loading panel when there is no metadata
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Add an initial loading panel when there is no metadata
- Date: Tue, 12 Apr 2016 13:29:31 +0000 (UTC)
commit 995f9967c1e943760bba40b89462b65ea2bea311
Author: Richard Hughes <richard hughsie com>
Date: Mon Apr 11 15:24:57 2016 +0100
Add an initial loading panel when there is no metadata
po/POTFILES.in | 2 +
src/Makefile.am | 3 +
src/gnome-software.gresource.xml | 1 +
src/gnome-software.ui | 8 ++
src/gs-application.c | 24 ++++-
src/gs-shell-loading.c | 225 ++++++++++++++++++++++++++++++++++++++
src/gs-shell-loading.h | 55 +++++++++
src/gs-shell-loading.ui | 64 +++++++++++
src/gs-shell.c | 17 +++-
src/gs-shell.h | 2 +
src/plugins/gs-plugin-steam.c | 5 +
11 files changed, 400 insertions(+), 6 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index dcb1383..0f37728 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -59,3 +59,5 @@ src/gs-utils.c
src/org.gnome.Software.desktop.in
src/plugins/menu-spec-common.c
[type: gettext/glade]src/gs-popular-tile.ui
+src/gs-shell-loading.c
+[type: gettext/glade]src/gs-shell-loading.ui
diff --git a/src/Makefile.am b/src/Makefile.am
index 82deb31..6d2a8d4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,7 @@ UI_FILES = \
gs-shell-extras.ui \
gs-shell-installed.ui \
gs-shell-moderate.ui \
+ gs-shell-loading.ui \
gs-shell-overview.ui \
gs-shell-search.ui \
gs-shell-updates.ui \
@@ -177,6 +178,8 @@ gnome_software_SOURCES = \
gs-shell-installed.h \
gs-shell-moderate.c \
gs-shell-moderate.h \
+ gs-shell-loading.c \
+ gs-shell-loading.h \
gs-shell-overview.c \
gs-shell-overview.h \
gs-shell-updates.c \
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index c73be6a..773ce8e 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -21,6 +21,7 @@
<file preprocess="xml-stripblanks">gs-shell-details.ui</file>
<file preprocess="xml-stripblanks">gs-shell-extras.ui</file>
<file preprocess="xml-stripblanks">gs-shell-installed.ui</file>
+ <file preprocess="xml-stripblanks">gs-shell-loading.ui</file>
<file preprocess="xml-stripblanks">gs-shell-moderate.ui</file>
<file preprocess="xml-stripblanks">gs-shell-overview.ui</file>
<file preprocess="xml-stripblanks">gs-shell-search.ui</file>
diff --git a/src/gnome-software.ui b/src/gnome-software.ui
index 1d9ddad..857ded6 100644
--- a/src/gnome-software.ui
+++ b/src/gnome-software.ui
@@ -354,6 +354,14 @@
</packing>
</child>
<child>
+ <object class="GsShellLoading" id="shell_loading">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">loading</property>
+ </packing>
+ </child>
+ <child>
<object class="GsShellSearch" id="shell_search">
<property name="visible">True</property>
</object>
diff --git a/src/gs-application.c b/src/gs-application.c
index 872b33c..463813c 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -314,9 +314,6 @@ gs_application_initialize_ui (GsApplication *app)
gs_shell_setup (app->shell, app->plugin_loader, app->cancellable);
gtk_application_add_window (GTK_APPLICATION (app), gs_shell_get_window (app->shell));
-
- g_signal_connect_swapped (app->shell, "loaded",
- G_CALLBACK (gtk_window_present), gs_shell_get_window (app->shell));
}
static void
@@ -747,11 +744,30 @@ gs_application_startup (GApplication *application)
}
static void
+gs_application_shell_loaded_cb (GsShell *shell, GsApplication *app)
+{
+ gs_shell_set_mode (app->shell, GS_SHELL_MODE_OVERVIEW);
+}
+
+static void
gs_application_activate (GApplication *application)
{
+ GsApplication *app = GS_APPLICATION (application);
+
gs_application_initialize_ui (GS_APPLICATION (application));
- gs_shell_set_mode (GS_APPLICATION (application)->shell, GS_SHELL_MODE_OVERVIEW);
+
+ /* start metadata loading screen */
+ if (gs_shell_get_mode (app->shell) == GS_SHELL_MODE_UNKNOWN) {
+ g_signal_connect (app->shell, "loaded",
+ G_CALLBACK (gs_application_shell_loaded_cb),
+ app);
+ gs_shell_set_mode (app->shell, GS_SHELL_MODE_LOADING);
+ } else {
+ gs_shell_set_mode (app->shell, GS_SHELL_MODE_OVERVIEW);
+ }
+
gs_shell_activate (GS_APPLICATION (application)->shell);
+
gs_application_show_first_run_dialog (GS_APPLICATION (application));
}
diff --git a/src/gs-shell-loading.c b/src/gs-shell-loading.c
new file mode 100644
index 0000000..2dc0b65
--- /dev/null
+++ b/src/gs-shell-loading.c
@@ -0,0 +1,225 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 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 "gs-app.h"
+#include "gs-shell.h"
+#include "gs-shell-loading.h"
+
+typedef struct {
+ GsPage parent_instance;
+
+ GsPluginLoader *plugin_loader;
+ GCancellable *cancellable;
+ GsShell *shell;
+
+ GtkWidget *progressbar;
+ GtkWidget *label;
+} GsShellLoadingPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsShellLoading, gs_shell_loading, GS_TYPE_PAGE)
+
+enum {
+ SIGNAL_REFRESHED,
+ SIGNAL_LAST
+};
+
+static guint signals [SIGNAL_LAST] = { 0 };
+
+/**
+ * gs_shell_loading_status_changed_cb:
+ **/
+static void
+gs_shell_loading_status_changed_cb (GsPluginLoader *plugin_loader,
+ GsApp *app,
+ GsPluginStatus status,
+ GsShellLoading *self)
+{
+ GsShellLoadingPrivate *priv = gs_shell_loading_get_instance_private (self);
+
+ /* update label */
+ switch (status) {
+ case GS_PLUGIN_STATUS_DOWNLOADING:
+ gtk_label_set_label (GTK_LABEL (priv->label),
+ /* TRANSLATORS: initial start */
+ _("Software catalog is being downloaded"));
+ break;
+ default:
+ gtk_label_set_label (GTK_LABEL (priv->label),
+ /* TRANSLATORS: initial start */
+ _("Software catalog is being loaded"));
+ break;
+ }
+
+ /* update progresbar */
+ if (app != NULL) {
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progressbar),
+ (gdouble) gs_app_get_progress (app) / 100.0f);
+ }
+}
+
+/**
+ * gs_shell_loading_refresh_cb:
+ **/
+static void
+gs_shell_loading_refresh_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
+ GsShellLoading *self = GS_SHELL_LOADING (user_data);
+ g_autoptr(GError) error = NULL;
+
+ /* no longer care */
+ g_signal_handlers_disconnect_by_data (plugin_loader, self);
+
+ /* not sure how to handle this */
+ if (!gs_plugin_loader_refresh_finish (plugin_loader, res, &error)) {
+ g_warning ("failed to load metadata: %s", error->message);
+ return;
+ }
+
+ /* UI is good to go */
+ g_signal_emit (self, signals[SIGNAL_REFRESHED], 0);
+}
+
+/**
+ * gs_shell_loading_load:
+ */
+static void
+gs_shell_loading_load (GsShellLoading *self)
+{
+ GsShellLoadingPrivate *priv = gs_shell_loading_get_instance_private (self);
+
+ /* ensure that at least some metadata of any age is present, and also
+ * spin up the plugins enough as to prime caches */
+ gs_plugin_loader_refresh_async (priv->plugin_loader, -1,
+ GS_PLUGIN_REFRESH_FLAGS_METADATA,
+ priv->cancellable,
+ gs_shell_loading_refresh_cb,
+ self);
+ g_signal_connect (priv->plugin_loader, "status-changed",
+ G_CALLBACK (gs_shell_loading_status_changed_cb),
+ self);
+}
+
+/**
+ * gs_shell_loading_switch_to:
+ **/
+static void
+gs_shell_loading_switch_to (GsPage *page, gboolean scroll_up)
+{
+ GsShellLoading *self = GS_SHELL_LOADING (page);
+ GsShellLoadingPrivate *priv = gs_shell_loading_get_instance_private (self);
+
+ if (gs_shell_get_mode (priv->shell) != GS_SHELL_MODE_LOADING) {
+ g_warning ("Called switch_to(loading) when in mode %s",
+ gs_shell_get_mode_string (priv->shell));
+ return;
+ }
+ gs_shell_loading_load (self);
+}
+
+/**
+ * gs_shell_loading_setup:
+ */
+void
+gs_shell_loading_setup (GsShellLoading *self,
+ GsShell *shell,
+ GsPluginLoader *plugin_loader,
+ GtkBuilder *builder,
+ GCancellable *cancellable)
+{
+ GsShellLoadingPrivate *priv = gs_shell_loading_get_instance_private (self);
+
+ g_return_if_fail (GS_IS_SHELL_LOADING (self));
+
+ priv->shell = shell;
+ priv->plugin_loader = g_object_ref (plugin_loader);
+ priv->cancellable = g_object_ref (cancellable);
+
+ /* chain up */
+ gs_page_setup (GS_PAGE (self), shell, plugin_loader, cancellable);
+}
+
+/**
+ * gs_shell_loading_dispose:
+ **/
+static void
+gs_shell_loading_dispose (GObject *object)
+{
+ GsShellLoading *self = GS_SHELL_LOADING (object);
+ GsShellLoadingPrivate *priv = gs_shell_loading_get_instance_private (self);
+
+ g_clear_object (&priv->plugin_loader);
+ g_clear_object (&priv->cancellable);
+
+ G_OBJECT_CLASS (gs_shell_loading_parent_class)->dispose (object);
+}
+
+/**
+ * gs_shell_loading_class_init:
+ **/
+static void
+gs_shell_loading_class_init (GsShellLoadingClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GsPageClass *page_class = GS_PAGE_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gs_shell_loading_dispose;
+ page_class->switch_to = gs_shell_loading_switch_to;
+
+ signals [SIGNAL_REFRESHED] =
+ g_signal_new ("refreshed",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsShellLoadingClass, refreshed),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-shell-loading.ui");
+
+ gtk_widget_class_bind_template_child_private (widget_class, GsShellLoading, progressbar);
+ gtk_widget_class_bind_template_child_private (widget_class, GsShellLoading, label);
+}
+
+/**
+ * gs_shell_loading_init:
+ **/
+static void
+gs_shell_loading_init (GsShellLoading *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+/**
+ * gs_shell_loading_new:
+ **/
+GsShellLoading *
+gs_shell_loading_new (void)
+{
+ GsShellLoading *self;
+ self = g_object_new (GS_TYPE_SHELL_LOADING, NULL);
+ return GS_SHELL_LOADING (self);
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-shell-loading.h b/src/gs-shell-loading.h
new file mode 100644
index 0000000..5808560
--- /dev/null
+++ b/src/gs-shell-loading.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 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_SHELL_LOADING_H
+#define __GS_SHELL_LOADING_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gs-page.h"
+#include "gs-plugin-loader.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_SHELL_LOADING (gs_shell_loading_get_type ())
+
+G_DECLARE_DERIVABLE_TYPE (GsShellLoading, gs_shell_loading, GS, SHELL_LOADING, GsPage)
+
+struct _GsShellLoadingClass
+{
+ GsPageClass parent_class;
+
+ void (*refreshed) (GsShellLoading *self);
+};
+
+GsShellLoading *gs_shell_loading_new (void);
+void gs_shell_loading_setup (GsShellLoading *self,
+ GsShell *shell,
+ GsPluginLoader *plugin_loader,
+ GtkBuilder *builder,
+ GCancellable *cancellable);
+
+G_END_DECLS
+
+#endif /* __GS_SHELL_LOADING_H */
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-shell-loading.ui b/src/gs-shell-loading.ui
new file mode 100644
index 0000000..d5245ee
--- /dev/null
+++ b/src/gs-shell-loading.ui
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <template class="GsShellLoading" parent="GsPage">
+ <child internal-child="accessible">
+ <object class="AtkObject" id="loading-accessible">
+ <property name="accessible-name" translatable="yes">Loading page</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">48</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <child type="center">
+ <object class="GtkBox" id="centerbox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixel_size">256</property>
+ <property name="icon_name">org.gnome.Software-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkProgressBar" id="progressbar">
+ <property name="visible">True</property>
+ <property name="width_request">480</property>
+ <property name="halign">center</property>
+ <property name="fraction">0.0</property>
+ <property name="margin_top">8</property>
+ <style>
+ <class name="upgrade-progressbar"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Starting up…</property>
+ <attributes>
+ <attribute name="scale" value="1.4"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/gs-shell.c b/src/gs-shell.c
index 5f7e95c..6839c7f 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
* Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
*
* Licensed under the GNU General Public License Version 2
@@ -30,6 +30,7 @@
#include "gs-shell-details.h"
#include "gs-shell-installed.h"
#include "gs-shell-moderate.h"
+#include "gs-shell-loading.h"
#include "gs-shell-search.h"
#include "gs-shell-overview.h"
#include "gs-shell-updates.h"
@@ -40,6 +41,7 @@
#include "gs-update-monitor.h"
static const gchar *page_name[] = {
+ "unknown",
"overview",
"installed",
"search",
@@ -48,6 +50,7 @@ static const gchar *page_name[] = {
"category",
"extras",
"moderate",
+ "loading",
};
typedef struct {
@@ -66,6 +69,7 @@ typedef struct
GsShellOverview *shell_overview;
GsShellInstalled *shell_installed;
GsShellModerate *shell_moderate;
+ GsShellLoading *shell_loading;
GsShellSearch *shell_search;
GsShellUpdates *shell_updates;
GsShellDetails *shell_details;
@@ -286,6 +290,9 @@ gs_shell_change_mode (GsShell *shell,
case GS_SHELL_MODE_MODERATE:
new_page = GS_PAGE (priv->shell_moderate);
break;
+ case GS_SHELL_MODE_LOADING:
+ new_page = GS_PAGE (priv->shell_loading);
+ break;
case GS_SHELL_MODE_SEARCH:
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "entry_search"));
text = gtk_entry_get_text (GTK_ENTRY (widget));
@@ -770,6 +777,12 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
priv->plugin_loader,
priv->builder,
priv->cancellable);
+ priv->shell_loading = GS_SHELL_LOADING (gtk_builder_get_object (priv->builder, "shell_loading"));
+ gs_shell_loading_setup (priv->shell_loading,
+ shell,
+ priv->plugin_loader,
+ priv->builder,
+ priv->cancellable);
priv->shell_search = GS_SHELL_SEARCH (gtk_builder_get_object (priv->builder, "shell_search"));
gs_shell_search_setup (priv->shell_search,
shell,
@@ -808,7 +821,7 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
G_CALLBACK (search_changed_handler), shell);
/* load content */
- g_signal_connect (priv->shell_overview, "refreshed",
+ g_signal_connect (priv->shell_loading, "refreshed",
G_CALLBACK (initial_overview_load_done), shell);
}
diff --git a/src/gs-shell.h b/src/gs-shell.h
index 4a68228..ae95209 100644
--- a/src/gs-shell.h
+++ b/src/gs-shell.h
@@ -43,6 +43,7 @@ struct _GsShellClass
};
typedef enum {
+ GS_SHELL_MODE_UNKNOWN,
GS_SHELL_MODE_OVERVIEW,
GS_SHELL_MODE_INSTALLED,
GS_SHELL_MODE_SEARCH,
@@ -51,6 +52,7 @@ typedef enum {
GS_SHELL_MODE_CATEGORY,
GS_SHELL_MODE_EXTRAS,
GS_SHELL_MODE_MODERATE,
+ GS_SHELL_MODE_LOADING,
GS_SHELL_MODE_LAST
} GsShellMode;
diff --git a/src/plugins/gs-plugin-steam.c b/src/plugins/gs-plugin-steam.c
index faedb03..b1dc8b1 100644
--- a/src/plugins/gs-plugin-steam.c
+++ b/src/plugins/gs-plugin-steam.c
@@ -698,11 +698,16 @@ gs_plugin_steam_update_store (GsPlugin *plugin, AsStore *store, GPtrArray *apps,
{
guint i;
GHashTable *app;
+ g_autoptr(GsApp) dummy = gs_app_new (NULL);
for (i = 0; i < apps->len; i++) {
app = g_ptr_array_index (apps, i);
if (!gs_plugin_steam_update_store_app (plugin, store, app, error))
return FALSE;
+
+ /* update progress */
+ gs_app_set_progress (dummy, (gdouble) i * 100.f / (gdouble) apps->len);
+ gs_plugin_status_update (plugin, dummy, GS_PLUGIN_STATUS_DOWNLOADING);
}
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]