From 490af0a0db32f7caf07d56c2444e84c8fc727a67 Mon Sep 17 00:00:00 2001 From: sergiotarxz Date: Mon, 15 Nov 2021 22:26:20 +0100 Subject: [PATCH] Adding support to look the first image of the manga... --- include/openmg/backend/readmng.h | 3 + include/openmg/chapter.h | 2 + include/openmg/view/chapter_view.h | 6 ++ include/openmg/view/detail_manga.h | 5 +- include/openmg/view/list_view_chapter.h | 6 +- meson.build | 1 + src/backend/readmng.c | 74 ++++++++++++++++++++++++- src/chapter.c | 8 +++ src/view/chapter_view.c | 64 +++++++++++++++++++++ src/view/detail_manga.c | 4 +- src/view/list_view_chapter.c | 18 +++++- src/view/list_view_manga.c | 2 +- 12 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 include/openmg/view/chapter_view.h create mode 100644 src/view/chapter_view.c diff --git a/include/openmg/backend/readmng.h b/include/openmg/backend/readmng.h index c175c82..ae44321 100644 --- a/include/openmg/backend/readmng.h +++ b/include/openmg/backend/readmng.h @@ -5,6 +5,7 @@ #include #include +#include G_BEGIN_DECLS; @@ -32,5 +33,7 @@ mg_backend_readmng_get_featured_manga (MgBackendReadmng *self); void mg_backend_readmng_retrieve_manga_details (MgBackendReadmng *self, MgManga *manga); +GListModel * +mg_backend_readmng_get_chapter_images (MgBackendReadmng *self, MgMangaChapter *chapter); G_END_DECLS diff --git a/include/openmg/chapter.h b/include/openmg/chapter.h index 791043d..ea2eb91 100644 --- a/include/openmg/chapter.h +++ b/include/openmg/chapter.h @@ -12,5 +12,7 @@ mg_manga_chapter_new (const char *const title, const char *const url); char * mg_manga_chapter_get_title (MgMangaChapter *self); +char * +mg_manga_chapter_get_url (MgMangaChapter *self); G_END_DECLS diff --git a/include/openmg/view/chapter_view.h b/include/openmg/view/chapter_view.h new file mode 100644 index 0000000..445774c --- /dev/null +++ b/include/openmg/view/chapter_view.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void +setup_chapter_view (MgMangaChapter *chapter, AdwLeaflet *views_leaflet); diff --git a/include/openmg/view/detail_manga.h b/include/openmg/view/detail_manga.h index 8ef7a97..2cd1334 100644 --- a/include/openmg/view/detail_manga.h +++ b/include/openmg/view/detail_manga.h @@ -1,4 +1,7 @@ +#include +#include + #include GtkBox * -create_detail_view (MgManga *manga); +create_detail_view (MgManga *manga, AdwLeaflet *views_leaflet); diff --git a/include/openmg/view/list_view_chapter.h b/include/openmg/view/list_view_chapter.h index 4047980..21ffaee 100644 --- a/include/openmg/view/list_view_chapter.h +++ b/include/openmg/view/list_view_chapter.h @@ -1,5 +1,9 @@ +#pragma once + #include +#include + #include GtkListView * -create_list_view_chapters (MgManga *manga); +create_list_view_chapters (MgManga *manga, AdwLeaflet *views_leaflet); diff --git a/meson.build b/meson.build index d3c0866..8998c98 100644 --- a/meson.build +++ b/meson.build @@ -12,6 +12,7 @@ openmgdeps = [ ] sources = [ + 'src/view/chapter_view.c', 'src/view/list_view_chapter.c', 'src/view/picture.c', 'src/util/gobject_utility_extensions.c', diff --git a/src/backend/readmng.c b/src/backend/readmng.c index 1c66981..faf10b6 100644 --- a/src/backend/readmng.c +++ b/src/backend/readmng.c @@ -1,3 +1,4 @@ +#include #include #include @@ -57,6 +58,12 @@ static MgMangaChapter * mg_backend_readmng_loop_li_chapter ( MgBackendReadmng *self, xmlNodePtr li); +static GListModel * +mg_backend_readmng_parse_page (MgBackendReadmng *self, + xmlDocPtr html_document); +static xmlDocPtr +mg_backend_readmng_fetch_page_url (MgBackendReadmng *self, + MgMangaChapter *chapter); static GListStore * mg_backend_readmng_recover_chapter_list (MgBackendReadmng *self, xmlDocPtr html_document_details); @@ -147,6 +154,67 @@ mg_backend_readmng_get_property (GObject *object, } } +GListModel * +mg_backend_readmng_get_chapter_images (MgBackendReadmng *self, MgMangaChapter *chapter) { + GListModel *images; + xmlDocPtr html_document; + html_document = mg_backend_readmng_fetch_page_url (self, chapter); + images = mg_backend_readmng_parse_page (self, html_document); + + xmlFreeDoc (html_document); + return images; +} + +static GListModel * +mg_backend_readmng_parse_page (MgBackendReadmng *self, + xmlDocPtr html_document) { + GListModel *images = G_LIST_MODEL + (gtk_string_list_new (NULL)); + + MgUtilXML *xml_utils = self->xml_utils; + xmlXPathObjectPtr xpath_result = NULL; + xmlNodeSetPtr node_set = NULL; + xpath_result = mg_util_xml_get_nodes_xpath_expression (xml_utils, + html_document, "//img[@class]"); + node_set = xpath_result->nodesetval; + if (!node_set) { + fprintf(stderr, "No match for images.\n"); + return images; + } + for (int i = 0; i < node_set->nodeNr; i++) { + xmlNodePtr node = node_set->nodeTab[i]; + const char *image_url = mg_util_xml_get_attr (xml_utils, node, "src"); + gtk_string_list_append (GTK_STRING_LIST (images), (void *)image_url); + } + + return images; +} + +static xmlDocPtr +mg_backend_readmng_fetch_page_url (MgBackendReadmng *self, + MgMangaChapter *chapter) { + size_t response_len = 0; + MgUtilSoup *util_soup = mg_util_soup_new (); + char *url = mg_manga_chapter_get_url (chapter); + size_t concat_all_pages_len; + char *concated_url; + + concat_all_pages_len = snprintf (NULL, 0, "%s/all-pages", url); + concated_url = g_malloc + (sizeof *concated_url * (concat_all_pages_len + 1)); + snprintf (concated_url, concat_all_pages_len + 1, + "%s/all-pages", url); + + const char *html_response = mg_util_soup_get_request (util_soup, concated_url, + &response_len); + return htmlReadMemory (html_response, response_len, + NULL, NULL, + HTML_PARSE_RECOVER | HTML_PARSE_NODEFDTD + | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING ); + +} + + GListStore * mg_backend_readmng_get_featured_manga (MgBackendReadmng *self) { GListStore *mangas; @@ -175,10 +243,10 @@ mg_backend_readmng_retrieve_manga_details (MgBackendReadmng *self, if (mg_manga_has_details (manga)) { goto cleanup_mg_backend_readmng_retrieve_manga_details; } - + xml_utils = self->xml_utils; html_document = mg_backend_readmng_fetch_xml_details (self, - manga); + manga); xpath_result = mg_util_xml_get_nodes_xpath_expression (xml_utils, html_document, "//li[@class]"); node_set = xpath_result->nodesetval; @@ -205,7 +273,7 @@ cleanup_mg_backend_readmng_retrieve_manga_details: static GListStore * mg_backend_readmng_recover_chapter_list (MgBackendReadmng *self, xmlDocPtr html_document_details) { - MgUtilXML *xml_utils = self->xml_utils; + MgUtilXML *xml_utils = self->xml_utils; xmlXPathObjectPtr xpath_result = NULL; xmlNodeSetPtr node_set = NULL; xmlNodePtr *uls = NULL; diff --git a/src/chapter.c b/src/chapter.c index 70c2c4f..1fedbec 100644 --- a/src/chapter.c +++ b/src/chapter.c @@ -160,3 +160,11 @@ mg_manga_chapter_get_title (MgMangaChapter *self) { g_object_get_property (G_OBJECT (self), "title", &value); return g_value_dup_string (&value); } + +char * +mg_manga_chapter_get_url (MgMangaChapter *self) { + GValue value = G_VALUE_INIT; + g_value_init (&value, G_TYPE_STRING); + g_object_get_property (G_OBJECT (self), "url", &value); + return g_value_dup_string (&value); +} diff --git a/src/view/chapter_view.c b/src/view/chapter_view.c new file mode 100644 index 0000000..8d21d19 --- /dev/null +++ b/src/view/chapter_view.c @@ -0,0 +1,64 @@ +#include + +#include +#include +#include +#include +#include +#include + +static void +fire_zoom (GtkGestureZoom *zoom, + gdouble scale, + gpointer user_data); + +typedef struct { + guint current_page; + GListModel *pages; + GtkPicture *current_picture; +} ChapterVisorData; +void +setup_chapter_view (MgMangaChapter *chapter, AdwLeaflet *views_leaflet) { + MgBackendReadmng *readmng = mg_backend_readmng_new (); + MgUtilString *string_util = mg_util_string_new (); + GtkBox *chapter_view_container = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0)); + GtkScrolledWindow *zoomable_picture_container = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new ()); + GtkGesture *zoom_controller = gtk_gesture_zoom_new (); + GListModel *pages = mg_backend_readmng_get_chapter_images (readmng, chapter); + ChapterVisorData *chapter_visor_data = g_malloc (sizeof *chapter_visor_data); + GtkPicture *current_picture; + chapter_visor_data->current_page = 0; + chapter_visor_data->pages = pages; + const char *url_image_not_owned = + gtk_string_list_get_string (GTK_STRING_LIST + (pages), 0); + char *url_image = mg_util_string_alloc_string (string_util, strlen (url_image_not_owned)); + mg_util_string_copy_substring (string_util, + url_image_not_owned, url_image, + strlen(url_image_not_owned) + 1, 0, + strlen (url_image_not_owned)); + + current_picture = create_picture_from_url + (url_image, 200); + g_object_set_property_int (G_OBJECT (current_picture), "vexpand", 1); + g_object_set_property_int (G_OBJECT (current_picture), "hexpand", 1); + chapter_visor_data->current_picture = + current_picture; + gtk_scrolled_window_set_child (zoomable_picture_container, GTK_WIDGET (current_picture)); + + + gtk_widget_add_controller (GTK_WIDGET (zoomable_picture_container), + GTK_EVENT_CONTROLLER (zoom_controller)); + g_signal_connect (G_OBJECT (zoom_controller), "scale-changed", G_CALLBACK (fire_zoom), NULL); + + gtk_box_append (chapter_view_container, GTK_WIDGET (zoomable_picture_container)); + adw_leaflet_append (views_leaflet, GTK_WIDGET (chapter_view_container)); + adw_leaflet_navigate (views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD); +} + +static void +fire_zoom (GtkGestureZoom *zoom, + gdouble scale, + gpointer user_data) { + // Do something. +} diff --git a/src/view/detail_manga.c b/src/view/detail_manga.c index fafff58..137e8fc 100644 --- a/src/view/detail_manga.c +++ b/src/view/detail_manga.c @@ -48,7 +48,7 @@ toggle_folded (GtkButton *toggle_folded_button, } GtkBox * -create_detail_view (MgManga *manga) { +create_detail_view (MgManga *manga, AdwLeaflet *views_leaflet) { MgBackendReadmng *readmng = mg_backend_readmng_new (); GtkWidget *scroll; GtkBox *detail_view = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0)); @@ -73,7 +73,7 @@ create_detail_view (MgManga *manga) { g_object_set_property_int (G_OBJECT (scroll), "vexpand", 1); mg_backend_readmng_retrieve_manga_details (readmng, manga); - chapter_list = create_list_view_chapters (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); diff --git a/src/view/list_view_chapter.c b/src/view/list_view_chapter.c index 2c7333c..346bdc4 100644 --- a/src/view/list_view_chapter.c +++ b/src/view/list_view_chapter.c @@ -4,14 +4,17 @@ #include #include #include +#include +static void +activate_chapter (GtkListView *list_view, guint position, gpointer user_data); static void setup_list_view_chapter_list (GtkSignalListItemFactory *factory, GtkListItem *list_item, gpointer user_data); GtkListView * -create_list_view_chapters (MgManga *manga) { +create_list_view_chapters (MgManga *manga, AdwLeaflet *views_leaflet) { GListStore *manga_chapter_list = NULL; GtkListView *list_view_chapters = NULL; GtkSingleSelection *selection = NULL; @@ -28,6 +31,9 @@ create_list_view_chapters (MgManga *manga) { list_view_chapters = GTK_LIST_VIEW (gtk_list_view_new (GTK_SELECTION_MODEL (selection), factory)); + gtk_list_view_set_single_click_activate (list_view_chapters, 1); + g_signal_connect (G_OBJECT (list_view_chapters), "activate", + G_CALLBACK (activate_chapter), views_leaflet); return list_view_chapters; } @@ -47,3 +53,13 @@ setup_list_view_chapter_list (GtkSignalListItemFactory *factory, gtk_box_append (box, GTK_WIDGET (title)); gtk_list_item_set_child (list_item, GTK_WIDGET (box)); } + +static void +activate_chapter (GtkListView *list_view, guint position, gpointer user_data) { + GtkSingleSelection *selection = GTK_SINGLE_SELECTION + (gtk_list_view_get_model (list_view)); + GListModel *chapters = gtk_single_selection_get_model (selection); + MgMangaChapter *chapter = MG_MANGA_CHAPTER (g_list_model_get_item (chapters, position)); + AdwLeaflet *views_leaflet = ADW_LEAFLET (user_data); + setup_chapter_view (chapter, views_leaflet); +} diff --git a/src/view/list_view_manga.c b/src/view/list_view_manga.c index 5efacd6..1ba754e 100644 --- a/src/view/list_view_manga.c +++ b/src/view/list_view_manga.c @@ -39,7 +39,7 @@ manga_selected (GtkListView *list_view, ADW_NAVIGATION_DIRECTION_FORWARD); } - GtkBox *detail_view = create_detail_view (manga); + GtkBox *detail_view = create_detail_view (manga, views_leaflet); adw_leaflet_append (views_leaflet, GTK_WIDGET (detail_view)); adw_leaflet_navigate (views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD); }