[gnome-software/91-clicking-screenshots-doesn-t-switch-between-them: 42/42] gs-screenshot-image: Show spinner when load of image takes long time
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/91-clicking-screenshots-doesn-t-switch-between-them: 42/42] gs-screenshot-image: Show spinner when load of image takes long time
- Date: Tue, 24 Nov 2020 13:41:24 +0000 (UTC)
commit 2d63f5ced3d1465effca444c989aadacc6cfe199
Author: Milan Crha <mcrha redhat com>
Date: Tue Nov 24 14:40:39 2020 +0100
gs-screenshot-image: Show spinner when load of image takes long time
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/91
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/merge_requests/524
src/gs-screenshot-image.c | 57 +++++++++++++++++++++++++++-
src/gs-screenshot-image.ui | 92 +++++++++++++++++++++++++++-------------------
2 files changed, 111 insertions(+), 38 deletions(-)
---
diff --git a/src/gs-screenshot-image.c b/src/gs-screenshot-image.c
index 0ecba076..c816a84d 100644
--- a/src/gs-screenshot-image.c
+++ b/src/gs-screenshot-image.c
@@ -15,11 +15,14 @@
#include "gs-screenshot-image.h"
#include "gs-common.h"
+#define SPINNER_TIMEOUT_SECS 2
+
struct _GsScreenshotImage
{
GtkBin parent_instance;
AsScreenshot *screenshot;
+ GtkWidget *spinner;
GtkWidget *stack;
GtkWidget *box_error;
GtkWidget *image1;
@@ -33,6 +36,7 @@ struct _GsScreenshotImage
guint width;
guint height;
guint scale;
+ guint load_timeout_id;
gboolean showing_image;
};
@@ -45,6 +49,20 @@ gs_screenshot_image_get_screenshot (GsScreenshotImage *ssimg)
return ssimg->screenshot;
}
+static void
+gs_screenshot_image_start_spinner (GsScreenshotImage *ssimg)
+{
+ gtk_widget_show (ssimg->spinner);
+ gs_start_spinner (GTK_SPINNER (ssimg->spinner));
+}
+
+static void
+gs_screenshot_image_stop_spinner (GsScreenshotImage *ssimg)
+{
+ gs_stop_spinner (GTK_SPINNER (ssimg->spinner));
+ gtk_widget_hide (ssimg->spinner);
+}
+
static void
gs_screenshot_image_set_error (GsScreenshotImage *ssimg, const gchar *message)
{
@@ -58,6 +76,7 @@ gs_screenshot_image_set_error (GsScreenshotImage *ssimg, const gchar *message)
else
gtk_widget_show (ssimg->label_error);
ssimg->showing_image = FALSE;
+ gs_screenshot_image_stop_spinner (ssimg);
}
static void
@@ -95,6 +114,8 @@ as_screenshot_show_image (GsScreenshotImage *ssimg)
gtk_widget_show (GTK_WIDGET (ssimg));
ssimg->showing_image = TRUE;
+
+ gs_screenshot_image_stop_spinner (ssimg);
}
static void
@@ -214,6 +235,11 @@ gs_screenshot_image_complete_cb (SoupSession *session,
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autoptr(GInputStream) stream = NULL;
+ if (ssimg->load_timeout_id) {
+ g_source_remove (ssimg->load_timeout_id);
+ ssimg->load_timeout_id = 0;
+ }
+
/* return immediately if the message was cancelled or if we're in destruction */
if (msg->status_code == SOUP_STATUS_CANCELLED || ssimg->session == NULL)
return;
@@ -221,12 +247,14 @@ gs_screenshot_image_complete_cb (SoupSession *session,
if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
g_debug ("screenshot has not been modified");
as_screenshot_show_image (ssimg);
+ gs_screenshot_image_stop_spinner (ssimg);
return;
}
if (msg->status_code != SOUP_STATUS_OK) {
g_warning ("Result of screenshot downloading attempt with "
"status code '%u': %s", msg->status_code,
msg->reason_phrase);
+ gs_screenshot_image_stop_spinner (ssimg);
/* if we're already showing an image, then don't set the error
* as having an image (even if outdated) is better */
if (ssimg->showing_image)
@@ -241,8 +269,10 @@ gs_screenshot_image_complete_cb (SoupSession *session,
stream = g_memory_input_stream_new_from_data (msg->response_body->data,
msg->response_body->length,
NULL);
- if (stream == NULL)
+ if (stream == NULL) {
+ gs_screenshot_image_stop_spinner (ssimg);
return;
+ }
/* load the image */
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
@@ -345,6 +375,17 @@ gs_screenshot_soup_msg_set_modified_request (SoupMessage *msg, GFile *file)
mod_date);
}
+static gboolean
+gs_screenshot_show_spinner_cb (gpointer user_data)
+{
+ GsScreenshotImage *ssimg = user_data;
+
+ ssimg->load_timeout_id = 0;
+ gs_screenshot_image_start_spinner (ssimg);
+
+ return FALSE;
+}
+
void
gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
GCancellable *cancellable)
@@ -473,6 +514,11 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
return;
}
+ if (ssimg->load_timeout_id) {
+ g_source_remove (ssimg->load_timeout_id);
+ ssimg->load_timeout_id = 0;
+ }
+
/* cancel any previous messages */
if (ssimg->message != NULL) {
soup_session_cancel_message (ssimg->session,
@@ -495,6 +541,9 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
gs_screenshot_soup_msg_set_modified_request (ssimg->message, file);
}
+ ssimg->load_timeout_id = g_timeout_add_seconds (SPINNER_TIMEOUT_SECS,
+ gs_screenshot_show_spinner_cb, ssimg);
+
/* send async */
soup_session_queue_message (ssimg->session,
g_object_ref (ssimg->message) /* transfer full */,
@@ -513,6 +562,11 @@ gs_screenshot_image_destroy (GtkWidget *widget)
{
GsScreenshotImage *ssimg = GS_SCREENSHOT_IMAGE (widget);
+ if (ssimg->load_timeout_id) {
+ g_source_remove (ssimg->load_timeout_id);
+ ssimg->load_timeout_id = 0;
+ }
+
if (ssimg->message != NULL) {
soup_session_cancel_message (ssimg->session,
ssimg->message,
@@ -575,6 +629,7 @@ gs_screenshot_image_class_init (GsScreenshotImageClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Software/gs-screenshot-image.ui");
+ gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, spinner);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, stack);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, image1);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, image2);
diff --git a/src/gs-screenshot-image.ui b/src/gs-screenshot-image.ui
index 0dae6e86..4b58e5a2 100644
--- a/src/gs-screenshot-image.ui
+++ b/src/gs-screenshot-image.ui
@@ -7,62 +7,80 @@
<class name="screenshot-image"/>
</style>
<child>
- <object class="GtkStack" id="stack">
+ <object class="GtkOverlay" id="overlay">
<property name="visible">True</property>
- <property name="transition-type">crossfade</property>
- <child>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <style>
- <class name="image1"/>
- </style>
- </object>
- <packing>
- <property name="name">image1</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="image2">
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ <child type="overlay">
+ <object class="GtkSpinner" id="spinner">
<property name="visible">True</property>
+ <property name="width_request">32</property>
+ <property name="height_request">32</property>
<property name="halign">center</property>
<property name="valign">center</property>
- <style>
- <class name="image2"/>
- </style>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
</object>
- <packing>
- <property name="name">image2</property>
- </packing>
</child>
<child>
- <object class="GtkBox" id="box_error">
+ <object class="GtkStack" id="stack">
<property name="visible">True</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="orientation">vertical</property>
- <property name="spacing">4</property>
+ <property name="transition-type">crossfade</property>
<child>
- <object class="GtkImage" id="image_error">
+ <object class="GtkImage" id="image1">
<property name="visible">True</property>
- <property name="icon-name">dialog-error-symbolic</property>
- <property name="icon-size">6</property>
- <property name="pixel-size">48</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="image1"/>
+ </style>
</object>
+ <packing>
+ <property name="name">image1</property>
+ </packing>
</child>
<child>
- <object class="GtkLabel" id="label_error">
+ <object class="GtkImage" id="image2">
<property name="visible">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
<style>
- <class name="error-label"/>
+ <class name="image2"/>
</style>
</object>
+ <packing>
+ <property name="name">image2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_error">
+ <property name="visible">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkImage" id="image_error">
+ <property name="visible">True</property>
+ <property name="icon-name">dialog-error-symbolic</property>
+ <property name="icon-size">6</property>
+ <property name="pixel-size">48</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_error">
+ <property name="visible">True</property>
+ <style>
+ <class name="error-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">error</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="name">error</property>
- </packing>
</child>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]