diff --git a/include/openmg/view/picture.h b/include/openmg/view/picture.h index ff61283..6ab6451 100644 --- a/include/openmg/view/picture.h +++ b/include/openmg/view/picture.h @@ -1,4 +1,6 @@ #pragma once #include -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); diff --git a/src/database/.statement.c.swp b/src/database/.statement.c.swp index c82ae39..a2cbe57 100644 Binary files a/src/database/.statement.c.swp and b/src/database/.statement.c.swp differ diff --git a/src/view/chapter_view.c b/src/view/chapter_view.c index eb07d73..eed3269 100644 --- a/src/view/chapter_view.c +++ b/src/view/chapter_view.c @@ -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); } diff --git a/src/view/detail_manga.c b/src/view/detail_manga.c index 77ba530..37e7378 100644 --- a/src/view/detail_manga.c +++ b/src/view/detail_manga.c @@ -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); diff --git a/src/view/list_view_manga.c b/src/view/list_view_manga.c index ea8e5cc..1273cd5 100644 --- a/src/view/list_view_manga.c +++ b/src/view/list_view_manga.c @@ -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)); diff --git a/src/view/picture.c b/src/view/picture.c index 76fd986..9e2d3e1 100644 --- a/src/view/picture.c +++ b/src/view/picture.c @@ -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 *