forked from sergiotarxz/mangareader
Adding async picture load.
This commit is contained in:
parent
1ff3ba89dc
commit
329c679c2c
|
@ -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.
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
Loading…
Reference in New Issue