Adding async picture load.
This commit is contained in:
parent
1ff3ba89dc
commit
329c679c2c
@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include <gtk/gtk.h>
|
||||
GtkPicture *
|
||||
create_picture_from_url (char *url, gint picture_height);
|
||||
void
|
||||
create_picture_from_url (const char *const url, gint picture_size,
|
||||
GAsyncReadyCallback ready, gpointer source_object,
|
||||
gpointer callback_data);
|
||||
|
Binary file not shown.
@ -49,12 +49,15 @@ static void
|
||||
zoom_end (GtkGesture *zoom,
|
||||
GdkEventSequence *sequence,
|
||||
gpointer user_data);
|
||||
static void
|
||||
picture_ready_manga_page (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data);
|
||||
|
||||
static void
|
||||
image_page_show (GtkWidget *picture, gpointer user_data) {
|
||||
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
|
||||
|
||||
chapter_visor_data->zoom = 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->pages = pages;
|
||||
chapter_visor_data->views_leaflet = views_leaflet;
|
||||
chapter_visor_data->zoom = 1;
|
||||
chapter_visor_data->zoomable_picture_container = zoomable_picture_container;
|
||||
set_zoomable_picture_container_properties (zoomable_picture_container,
|
||||
chapter_visor_data);
|
||||
@ -148,12 +152,10 @@ go_prev (GtkButton *prev,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_image_zoomable_picture_container (ChapterVisorData *chapter_visor_data) {
|
||||
GtkScrolledWindow *zoomable_picture_container = chapter_visor_data->zoomable_picture_container;
|
||||
MgUtilString *string_util = mg_util_string_new ();
|
||||
GtkPicture *current_picture;
|
||||
GListModel *pages = chapter_visor_data->pages;
|
||||
guint current_page = chapter_visor_data->current_page;
|
||||
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));
|
||||
|
||||
current_picture = create_picture_from_url
|
||||
(url_image, 0);
|
||||
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));
|
||||
|
||||
create_picture_from_url (url_image, 0, picture_ready_manga_page,
|
||||
zoomable_picture_container, chapter_visor_data);
|
||||
g_free (url_image);
|
||||
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
|
||||
set_zoomable_picture_container_properties (
|
||||
GtkScrolledWindow *zoomable_picture_container,
|
||||
@ -219,7 +232,7 @@ zoom_end (GtkGesture *zoom,
|
||||
gpointer user_data) {
|
||||
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
|
||||
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);
|
||||
chapter_visor_data->zoom = pow (M_E, scale_factor);
|
||||
}
|
||||
|
@ -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 *
|
||||
create_detail_view (MgManga *manga, ControlsAdwaita *controls) {
|
||||
AdwLeaflet *views_leaflet = controls->views_leaflet;
|
||||
@ -77,7 +89,8 @@ create_detail_view (MgManga *manga, ControlsAdwaita *controls) {
|
||||
("network-transmit-receive-symbolic"));
|
||||
GtkListView *chapter_list = NULL;
|
||||
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 *title_text = mg_util_xml_get_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);
|
||||
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 (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_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 (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_signal_connect (detail_view, "map", G_CALLBACK (show_controls),
|
||||
buttons);
|
||||
buttons);
|
||||
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 (manga_title_text);
|
||||
g_free (title_text);
|
||||
|
@ -46,6 +46,19 @@ manga_selected (GtkListView *list_view,
|
||||
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
|
||||
setup_list_view_mangas (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *list_item,
|
||||
@ -56,13 +69,10 @@ setup_list_view_mangas (GtkSignalListItemFactory *factory,
|
||||
char *image_url = mg_manga_get_image_url (manga);
|
||||
|
||||
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 (picture), "margin-end", 5);
|
||||
gtk_box_append (box, picture);
|
||||
}
|
||||
g_object_set_property_int (G_OBJECT(box), "height-request", 100);
|
||||
gtk_box_append (box, label);
|
||||
|
||||
gtk_list_item_set_child (list_item, GTK_WIDGET (box));
|
||||
|
@ -13,24 +13,36 @@
|
||||
const char *const IMAGE_CACHE_FORMAT_STRING =
|
||||
"%s/.cache/openmg/%s";
|
||||
|
||||
typedef struct {
|
||||
char *url;
|
||||
gint picture_size;
|
||||
} PictureThreadAttributes;
|
||||
|
||||
static char *
|
||||
generate_cache_file_name (void);
|
||||
GFile *
|
||||
get_image_for_url (const char *url);
|
||||
|
||||
GtkPicture *
|
||||
create_picture_from_url (const char *const url, gint picture_size) {
|
||||
GtkPicture *picture = NULL;
|
||||
static void
|
||||
threaded_picture_recover (GTask *task, gpointer source_object,
|
||||
gpointer task_data, GCancellable *cancellable) {
|
||||
PictureThreadAttributes *attrs = (PictureThreadAttributes *) task_data;
|
||||
const char *url = attrs->url;
|
||||
gint picture_size = attrs->picture_size;
|
||||
GFileIOStream *iostream = NULL;
|
||||
GFile *image = NULL;
|
||||
GError *error = NULL;
|
||||
GdkTexture *texture = NULL;
|
||||
GtkPicture *picture = NULL;
|
||||
|
||||
size_t size_downloaded_image = 0;
|
||||
char *downloaded_image = NULL;
|
||||
|
||||
MgUtilSoup *util_soup = mg_util_soup_new ();
|
||||
static GMutex mutex;
|
||||
g_mutex_lock (&mutex);
|
||||
image = get_image_for_url (url);
|
||||
g_mutex_unlock (&mutex);
|
||||
if (!g_file_query_exists (image, NULL)) {
|
||||
downloaded_image =
|
||||
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;
|
||||
}
|
||||
picture = GTK_PICTURE (gtk_picture_new_for_paintable (GDK_PAINTABLE (texture)));
|
||||
g_object_set_property_int (G_OBJECT(picture), "height-request", picture_size);
|
||||
g_object_set_property_int (G_OBJECT(picture), "width-request", picture_size);
|
||||
if (GTK_IS_WIDGET (picture)) {
|
||||
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:
|
||||
if (downloaded_image) {
|
||||
@ -69,7 +83,31 @@ cleanup_create_picture_from_url:
|
||||
g_clear_object (&iostream);
|
||||
}
|
||||
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 *
|
||||
|
Loading…
Reference in New Issue
Block a user