Adding async picture load.

This commit is contained in:
sergiotarxz 2022-01-16 22:39:01 +01:00
parent 1ff3ba89dc
commit 329c679c2c
6 changed files with 106 additions and 31 deletions

View File

@ -1,4 +1,6 @@
#pragma once #pragma once
#include <gtk/gtk.h> #include <gtk/gtk.h>
GtkPicture * void
create_picture_from_url (char *url, gint picture_height); create_picture_from_url (const char *const url, gint picture_size,
GAsyncReadyCallback ready, gpointer source_object,
gpointer callback_data);

Binary file not shown.

View File

@ -49,12 +49,15 @@ static void
zoom_end (GtkGesture *zoom, zoom_end (GtkGesture *zoom,
GdkEventSequence *sequence, GdkEventSequence *sequence,
gpointer user_data); gpointer user_data);
static void
picture_ready_manga_page (GObject *source_object,
GAsyncResult *res,
gpointer user_data);
static void static void
image_page_show (GtkWidget *picture, gpointer user_data) { image_page_show (GtkWidget *picture, gpointer user_data) {
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data; ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
chapter_visor_data->zoom = 1;
set_image_dimensions (picture, chapter_visor_data, 1); set_image_dimensions (picture, chapter_visor_data, 1);
} }
@ -100,6 +103,7 @@ setup_chapter_view (MgMangaChapter *chapter, AdwLeaflet *views_leaflet) {
chapter_visor_data->current_page = 0; chapter_visor_data->current_page = 0;
chapter_visor_data->pages = pages; chapter_visor_data->pages = pages;
chapter_visor_data->views_leaflet = views_leaflet; chapter_visor_data->views_leaflet = views_leaflet;
chapter_visor_data->zoom = 1;
chapter_visor_data->zoomable_picture_container = zoomable_picture_container; chapter_visor_data->zoomable_picture_container = zoomable_picture_container;
set_zoomable_picture_container_properties (zoomable_picture_container, set_zoomable_picture_container_properties (zoomable_picture_container,
chapter_visor_data); chapter_visor_data);
@ -148,12 +152,10 @@ go_prev (GtkButton *prev,
} }
} }
static void static void
set_image_zoomable_picture_container (ChapterVisorData *chapter_visor_data) { set_image_zoomable_picture_container (ChapterVisorData *chapter_visor_data) {
GtkScrolledWindow *zoomable_picture_container = chapter_visor_data->zoomable_picture_container; GtkScrolledWindow *zoomable_picture_container = chapter_visor_data->zoomable_picture_container;
MgUtilString *string_util = mg_util_string_new (); MgUtilString *string_util = mg_util_string_new ();
GtkPicture *current_picture;
GListModel *pages = chapter_visor_data->pages; GListModel *pages = chapter_visor_data->pages;
guint current_page = chapter_visor_data->current_page; guint current_page = chapter_visor_data->current_page;
const char *url_image_not_owned = const char *url_image_not_owned =
@ -165,17 +167,28 @@ set_image_zoomable_picture_container (ChapterVisorData *chapter_visor_data) {
strlen(url_image_not_owned) + 1, 0, strlen(url_image_not_owned) + 1, 0,
strlen (url_image_not_owned)); strlen (url_image_not_owned));
current_picture = create_picture_from_url create_picture_from_url (url_image, 0, picture_ready_manga_page,
(url_image, 0); zoomable_picture_container, chapter_visor_data);
chapter_visor_data->current_picture = current_picture;
g_signal_connect (G_OBJECT (current_picture), "map",
G_CALLBACK (image_page_show), chapter_visor_data);
gtk_scrolled_window_set_child (zoomable_picture_container, GTK_WIDGET (current_picture));
g_free (url_image); g_free (url_image);
g_clear_object (&string_util); g_clear_object (&string_util);
} }
static void
picture_ready_manga_page (GObject *source_object,
GAsyncResult *res,
gpointer user_data) {
GTask *task = G_TASK (res);
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
GtkWidget *picture = g_task_propagate_pointer (task, NULL);
GtkScrolledWindow *zoomable_picture_container = GTK_SCROLLED_WINDOW (source_object);
if (GTK_IS_WIDGET (picture)) {
chapter_visor_data->current_picture = GTK_PICTURE (picture);
g_signal_connect (G_OBJECT (picture), "map",
G_CALLBACK (image_page_show), chapter_visor_data);
gtk_scrolled_window_set_child (zoomable_picture_container, GTK_WIDGET (picture));
}
}
static void static void
set_zoomable_picture_container_properties ( set_zoomable_picture_container_properties (
GtkScrolledWindow *zoomable_picture_container, GtkScrolledWindow *zoomable_picture_container,
@ -219,7 +232,7 @@ zoom_end (GtkGesture *zoom,
gpointer user_data) { gpointer user_data) {
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data; ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
gdouble scale = gtk_gesture_zoom_get_scale_delta gdouble scale = gtk_gesture_zoom_get_scale_delta
(GTK_GESTURE_ZOOM (zoom)); (GTK_GESTURE_ZOOM (zoom));
gdouble scale_factor = log (scale) / 20 + log (chapter_visor_data->zoom); gdouble scale_factor = log (scale) / 20 + log (chapter_visor_data->zoom);
chapter_visor_data->zoom = pow (M_E, scale_factor); chapter_visor_data->zoom = pow (M_E, scale_factor);
} }

View File

@ -59,6 +59,18 @@ toggle_folded (GtkButton *toggle_folded_button,
} }
} }
static void
picture_ready_manga_detail (GObject *source_object,
GAsyncResult *res,
gpointer user_data) {
GTask *task = G_TASK (res);
GtkWidget *picture = g_task_propagate_pointer (task, NULL);
GtkBox *box = GTK_BOX (source_object);
if (GTK_IS_WIDGET (picture)) {
gtk_box_prepend (box, GTK_WIDGET (picture));
}
}
GtkBox * GtkBox *
create_detail_view (MgManga *manga, ControlsAdwaita *controls) { create_detail_view (MgManga *manga, ControlsAdwaita *controls) {
AdwLeaflet *views_leaflet = controls->views_leaflet; AdwLeaflet *views_leaflet = controls->views_leaflet;
@ -77,7 +89,8 @@ create_detail_view (MgManga *manga, ControlsAdwaita *controls) {
("network-transmit-receive-symbolic")); ("network-transmit-receive-symbolic"));
GtkListView *chapter_list = NULL; GtkListView *chapter_list = NULL;
char *url_image = mg_manga_get_image_url(manga); char *url_image = mg_manga_get_image_url(manga);
GtkPicture *manga_image = create_picture_from_url (url_image, 200); create_picture_from_url (url_image, 200,
picture_ready_manga_detail, avatar_title_box, NULL);
char *manga_title_text = mg_manga_get_title (manga); char *manga_title_text = mg_manga_get_title (manga);
char *title_text = mg_util_xml_get_title_text ( char *title_text = mg_util_xml_get_title_text (
xml_util, manga_title_text); xml_util, manga_title_text);
@ -90,7 +103,7 @@ create_detail_view (MgManga *manga, ControlsAdwaita *controls) {
mg_backend_readmng_retrieve_manga_details (readmng, manga); mg_backend_readmng_retrieve_manga_details (readmng, manga);
chapter_list = create_list_view_chapters (manga, views_leaflet); chapter_list = create_list_view_chapters (manga, views_leaflet);
g_signal_connect (G_OBJECT (toggle_folded_button), "clicked", G_CALLBACK (toggle_folded), foldable_manga_data); g_signal_connect (G_OBJECT (toggle_folded_button), "clicked", G_CALLBACK (toggle_folded), foldable_manga_data);
g_signal_connect (G_OBJECT (reverse_list_button), "clicked", G_CALLBACK (reverse_list), chapter_list); g_signal_connect (G_OBJECT (reverse_list_button), "clicked", G_CALLBACK (reverse_list), chapter_list);
@ -103,7 +116,6 @@ create_detail_view (MgManga *manga, ControlsAdwaita *controls) {
gtk_widget_set_size_request (GTK_WIDGET (manga_description), 200, -1); gtk_widget_set_size_request (GTK_WIDGET (manga_description), 200, -1);
gtk_label_set_use_markup (GTK_LABEL (manga_title), 1); gtk_label_set_use_markup (GTK_LABEL (manga_title), 1);
gtk_box_append (avatar_title_box, GTK_WIDGET (manga_image));
gtk_box_append (avatar_title_box, GTK_WIDGET (manga_title)); gtk_box_append (avatar_title_box, GTK_WIDGET (manga_title));
gtk_box_append (foldable_manga_data, GTK_WIDGET (avatar_title_box)); gtk_box_append (foldable_manga_data, GTK_WIDGET (avatar_title_box));
@ -125,11 +137,11 @@ create_detail_view (MgManga *manga, ControlsAdwaita *controls) {
g_object_ref (G_OBJECT (toggle_folded_button)); g_object_ref (G_OBJECT (toggle_folded_button));
g_signal_connect (detail_view, "map", G_CALLBACK (show_controls), g_signal_connect (detail_view, "map", G_CALLBACK (show_controls),
buttons); buttons);
g_signal_connect (detail_view, "unmap", G_CALLBACK (hide_controls), g_signal_connect (detail_view, "unmap", G_CALLBACK (hide_controls),
buttons); buttons);
g_clear_object (&readmng); g_clear_object (&readmng);
g_free (url_image); g_free (url_image);
g_free (manga_title_text); g_free (manga_title_text);
g_free (title_text); g_free (title_text);

View File

@ -46,6 +46,19 @@ manga_selected (GtkListView *list_view,
adw_leaflet_navigate (views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD); adw_leaflet_navigate (views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
} }
static void
picture_ready_manga_preview (GObject *source_object,
GAsyncResult *res,
gpointer user_data) {
GTask *task = G_TASK (res);
GtkWidget *picture = g_task_propagate_pointer (task, NULL);
GtkBox *box = GTK_BOX (source_object);
if (GTK_IS_WIDGET (picture)) {
g_object_set_property_int (G_OBJECT (picture), "margin-end", 5);
gtk_box_prepend (box, picture);
}
}
static void static void
setup_list_view_mangas (GtkSignalListItemFactory *factory, setup_list_view_mangas (GtkSignalListItemFactory *factory,
GtkListItem *list_item, GtkListItem *list_item,
@ -56,13 +69,10 @@ setup_list_view_mangas (GtkSignalListItemFactory *factory,
char *image_url = mg_manga_get_image_url (manga); char *image_url = mg_manga_get_image_url (manga);
GtkWidget *label = gtk_label_new (manga_title); GtkWidget *label = gtk_label_new (manga_title);
GtkWidget *picture = GTK_WIDGET ( create_picture_from_url (image_url, 100,
create_picture_from_url (image_url, 100)); picture_ready_manga_preview, box, NULL);
if (GTK_IS_WIDGET (picture)) { g_object_set_property_int (G_OBJECT(box), "height-request", 100);
g_object_set_property_int (G_OBJECT (picture), "margin-end", 5);
gtk_box_append (box, picture);
}
gtk_box_append (box, label); gtk_box_append (box, label);
gtk_list_item_set_child (list_item, GTK_WIDGET (box)); gtk_list_item_set_child (list_item, GTK_WIDGET (box));

View File

@ -13,24 +13,36 @@
const char *const IMAGE_CACHE_FORMAT_STRING = const char *const IMAGE_CACHE_FORMAT_STRING =
"%s/.cache/openmg/%s"; "%s/.cache/openmg/%s";
typedef struct {
char *url;
gint picture_size;
} PictureThreadAttributes;
static char * static char *
generate_cache_file_name (void); generate_cache_file_name (void);
GFile * GFile *
get_image_for_url (const char *url); get_image_for_url (const char *url);
GtkPicture * static void
create_picture_from_url (const char *const url, gint picture_size) { threaded_picture_recover (GTask *task, gpointer source_object,
GtkPicture *picture = NULL; gpointer task_data, GCancellable *cancellable) {
PictureThreadAttributes *attrs = (PictureThreadAttributes *) task_data;
const char *url = attrs->url;
gint picture_size = attrs->picture_size;
GFileIOStream *iostream = NULL; GFileIOStream *iostream = NULL;
GFile *image = NULL; GFile *image = NULL;
GError *error = NULL; GError *error = NULL;
GdkTexture *texture = NULL; GdkTexture *texture = NULL;
GtkPicture *picture = NULL;
size_t size_downloaded_image = 0; size_t size_downloaded_image = 0;
char *downloaded_image = NULL; char *downloaded_image = NULL;
MgUtilSoup *util_soup = mg_util_soup_new (); MgUtilSoup *util_soup = mg_util_soup_new ();
static GMutex mutex;
g_mutex_lock (&mutex);
image = get_image_for_url (url); image = get_image_for_url (url);
g_mutex_unlock (&mutex);
if (!g_file_query_exists (image, NULL)) { if (!g_file_query_exists (image, NULL)) {
downloaded_image = downloaded_image =
mg_util_soup_get_request mg_util_soup_get_request
@ -57,8 +69,10 @@ create_picture_from_url (const char *const url, gint picture_size) {
goto cleanup_create_picture_from_url; goto cleanup_create_picture_from_url;
} }
picture = GTK_PICTURE (gtk_picture_new_for_paintable (GDK_PAINTABLE (texture))); picture = GTK_PICTURE (gtk_picture_new_for_paintable (GDK_PAINTABLE (texture)));
g_object_set_property_int (G_OBJECT(picture), "height-request", picture_size); if (GTK_IS_WIDGET (picture)) {
g_object_set_property_int (G_OBJECT(picture), "width-request", picture_size); g_object_set_property_int (G_OBJECT(picture), "height-request", picture_size);
g_object_set_property_int (G_OBJECT(picture), "width-request", picture_size);
}
cleanup_create_picture_from_url: cleanup_create_picture_from_url:
if (downloaded_image) { if (downloaded_image) {
@ -69,7 +83,31 @@ cleanup_create_picture_from_url:
g_clear_object (&iostream); g_clear_object (&iostream);
} }
g_clear_object (&image); g_clear_object (&image);
return picture; g_task_return_pointer (task, picture, NULL);
}
static void
free_picture_thread_attributes (gpointer user_data) {
PictureThreadAttributes *attrs = (PictureThreadAttributes *) user_data;
g_free (attrs->url);
g_free (attrs);
}
void
create_picture_from_url (const char *const url, gint picture_size,
GAsyncReadyCallback ready, gpointer source_object,
gpointer callback_data) {
GTask *task = g_task_new (source_object, NULL, ready, callback_data);
size_t url_len = strlen (url) + 1;
PictureThreadAttributes *attrs = g_malloc (sizeof *attrs);
attrs->url = g_malloc (url_len * sizeof *url);
snprintf (attrs->url, url_len, "%s", url);
attrs->picture_size = picture_size;
g_task_set_task_data (task, attrs, free_picture_thread_attributes);
g_task_run_in_thread (task, threaded_picture_recover);
} }
GFile * GFile *