forked from sergiotarxz/mangareader
Adding support to look the first image of the
manga...
This commit is contained in:
parent
d91cd296a9
commit
490af0a0db
@ -5,6 +5,7 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
#include <openmg/manga.h>
|
#include <openmg/manga.h>
|
||||||
|
#include <openmg/chapter.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS;
|
G_BEGIN_DECLS;
|
||||||
|
|
||||||
@ -32,5 +33,7 @@ mg_backend_readmng_get_featured_manga (MgBackendReadmng *self);
|
|||||||
void
|
void
|
||||||
mg_backend_readmng_retrieve_manga_details (MgBackendReadmng *self,
|
mg_backend_readmng_retrieve_manga_details (MgBackendReadmng *self,
|
||||||
MgManga *manga);
|
MgManga *manga);
|
||||||
|
GListModel *
|
||||||
|
mg_backend_readmng_get_chapter_images (MgBackendReadmng *self, MgMangaChapter *chapter);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -12,5 +12,7 @@ mg_manga_chapter_new (const char *const title,
|
|||||||
const char *const url);
|
const char *const url);
|
||||||
char *
|
char *
|
||||||
mg_manga_chapter_get_title (MgMangaChapter *self);
|
mg_manga_chapter_get_title (MgMangaChapter *self);
|
||||||
|
char *
|
||||||
|
mg_manga_chapter_get_url (MgMangaChapter *self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
6
include/openmg/view/chapter_view.h
Normal file
6
include/openmg/view/chapter_view.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <adwaita.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
setup_chapter_view (MgMangaChapter *chapter, AdwLeaflet *views_leaflet);
|
@ -1,4 +1,7 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <adwaita.h>
|
||||||
|
|
||||||
#include <openmg/manga.h>
|
#include <openmg/manga.h>
|
||||||
|
|
||||||
GtkBox *
|
GtkBox *
|
||||||
create_detail_view (MgManga *manga);
|
create_detail_view (MgManga *manga, AdwLeaflet *views_leaflet);
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#include <adwaita.h>
|
||||||
|
|
||||||
#include <openmg/manga.h>
|
#include <openmg/manga.h>
|
||||||
|
|
||||||
GtkListView *
|
GtkListView *
|
||||||
create_list_view_chapters (MgManga *manga);
|
create_list_view_chapters (MgManga *manga, AdwLeaflet *views_leaflet);
|
||||||
|
@ -12,6 +12,7 @@ openmgdeps = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
|
'src/view/chapter_view.c',
|
||||||
'src/view/list_view_chapter.c',
|
'src/view/list_view_chapter.c',
|
||||||
'src/view/picture.c',
|
'src/view/picture.c',
|
||||||
'src/util/gobject_utility_extensions.c',
|
'src/util/gobject_utility_extensions.c',
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
#include <libxml/HTMLparser.h>
|
#include <libxml/HTMLparser.h>
|
||||||
|
|
||||||
#include <openmg/backend/readmng.h>
|
#include <openmg/backend/readmng.h>
|
||||||
@ -57,6 +58,12 @@ static MgMangaChapter *
|
|||||||
mg_backend_readmng_loop_li_chapter (
|
mg_backend_readmng_loop_li_chapter (
|
||||||
MgBackendReadmng *self,
|
MgBackendReadmng *self,
|
||||||
xmlNodePtr li);
|
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 *
|
static GListStore *
|
||||||
mg_backend_readmng_recover_chapter_list (MgBackendReadmng *self,
|
mg_backend_readmng_recover_chapter_list (MgBackendReadmng *self,
|
||||||
xmlDocPtr html_document_details);
|
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 *
|
GListStore *
|
||||||
mg_backend_readmng_get_featured_manga (MgBackendReadmng *self) {
|
mg_backend_readmng_get_featured_manga (MgBackendReadmng *self) {
|
||||||
GListStore *mangas;
|
GListStore *mangas;
|
||||||
@ -178,7 +246,7 @@ mg_backend_readmng_retrieve_manga_details (MgBackendReadmng *self,
|
|||||||
|
|
||||||
xml_utils = self->xml_utils;
|
xml_utils = self->xml_utils;
|
||||||
html_document = mg_backend_readmng_fetch_xml_details (self,
|
html_document = mg_backend_readmng_fetch_xml_details (self,
|
||||||
manga);
|
manga);
|
||||||
xpath_result = mg_util_xml_get_nodes_xpath_expression (xml_utils,
|
xpath_result = mg_util_xml_get_nodes_xpath_expression (xml_utils,
|
||||||
html_document, "//li[@class]");
|
html_document, "//li[@class]");
|
||||||
node_set = xpath_result->nodesetval;
|
node_set = xpath_result->nodesetval;
|
||||||
@ -205,7 +273,7 @@ cleanup_mg_backend_readmng_retrieve_manga_details:
|
|||||||
static GListStore *
|
static GListStore *
|
||||||
mg_backend_readmng_recover_chapter_list (MgBackendReadmng *self,
|
mg_backend_readmng_recover_chapter_list (MgBackendReadmng *self,
|
||||||
xmlDocPtr html_document_details) {
|
xmlDocPtr html_document_details) {
|
||||||
MgUtilXML *xml_utils = self->xml_utils;
|
MgUtilXML *xml_utils = self->xml_utils;
|
||||||
xmlXPathObjectPtr xpath_result = NULL;
|
xmlXPathObjectPtr xpath_result = NULL;
|
||||||
xmlNodeSetPtr node_set = NULL;
|
xmlNodeSetPtr node_set = NULL;
|
||||||
xmlNodePtr *uls = NULL;
|
xmlNodePtr *uls = NULL;
|
||||||
|
@ -160,3 +160,11 @@ mg_manga_chapter_get_title (MgMangaChapter *self) {
|
|||||||
g_object_get_property (G_OBJECT (self), "title", &value);
|
g_object_get_property (G_OBJECT (self), "title", &value);
|
||||||
return g_value_dup_string (&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);
|
||||||
|
}
|
||||||
|
64
src/view/chapter_view.c
Normal file
64
src/view/chapter_view.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <openmg/chapter.h>
|
||||||
|
#include <openmg/view/chapter_view.h>
|
||||||
|
#include <openmg/view/picture.h>
|
||||||
|
#include <openmg/util/gobject_utility_extensions.h>
|
||||||
|
#include <openmg/util/string.h>
|
||||||
|
#include <openmg/backend/readmng.h>
|
||||||
|
|
||||||
|
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.
|
||||||
|
}
|
@ -48,7 +48,7 @@ toggle_folded (GtkButton *toggle_folded_button,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GtkBox *
|
GtkBox *
|
||||||
create_detail_view (MgManga *manga) {
|
create_detail_view (MgManga *manga, AdwLeaflet *views_leaflet) {
|
||||||
MgBackendReadmng *readmng = mg_backend_readmng_new ();
|
MgBackendReadmng *readmng = mg_backend_readmng_new ();
|
||||||
GtkWidget *scroll;
|
GtkWidget *scroll;
|
||||||
GtkBox *detail_view = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
|
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);
|
g_object_set_property_int (G_OBJECT (scroll), "vexpand", 1);
|
||||||
|
|
||||||
mg_backend_readmng_retrieve_manga_details (readmng, manga);
|
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);
|
g_signal_connect (G_OBJECT (toggle_folded_button), "clicked", G_CALLBACK (toggle_folded), foldable_manga_data);
|
||||||
|
@ -4,14 +4,17 @@
|
|||||||
#include <openmg/chapter.h>
|
#include <openmg/chapter.h>
|
||||||
#include <openmg/backend/readmng.h>
|
#include <openmg/backend/readmng.h>
|
||||||
#include <openmg/view/list_view_chapter.h>
|
#include <openmg/view/list_view_chapter.h>
|
||||||
|
#include <openmg/view/chapter_view.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
activate_chapter (GtkListView *list_view, guint position, gpointer user_data);
|
||||||
static void
|
static void
|
||||||
setup_list_view_chapter_list (GtkSignalListItemFactory *factory,
|
setup_list_view_chapter_list (GtkSignalListItemFactory *factory,
|
||||||
GtkListItem *list_item,
|
GtkListItem *list_item,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
GtkListView *
|
GtkListView *
|
||||||
create_list_view_chapters (MgManga *manga) {
|
create_list_view_chapters (MgManga *manga, AdwLeaflet *views_leaflet) {
|
||||||
GListStore *manga_chapter_list = NULL;
|
GListStore *manga_chapter_list = NULL;
|
||||||
GtkListView *list_view_chapters = NULL;
|
GtkListView *list_view_chapters = NULL;
|
||||||
GtkSingleSelection *selection = 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),
|
list_view_chapters = GTK_LIST_VIEW (gtk_list_view_new (GTK_SELECTION_MODEL (selection),
|
||||||
factory));
|
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;
|
return list_view_chapters;
|
||||||
}
|
}
|
||||||
@ -47,3 +53,13 @@ setup_list_view_chapter_list (GtkSignalListItemFactory *factory,
|
|||||||
gtk_box_append (box, GTK_WIDGET (title));
|
gtk_box_append (box, GTK_WIDGET (title));
|
||||||
gtk_list_item_set_child (list_item, GTK_WIDGET (box));
|
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);
|
||||||
|
}
|
||||||
|
@ -39,7 +39,7 @@ manga_selected (GtkListView *list_view,
|
|||||||
ADW_NAVIGATION_DIRECTION_FORWARD);
|
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_append (views_leaflet, GTK_WIDGET (detail_view));
|
||||||
adw_leaflet_navigate (views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
|
adw_leaflet_navigate (views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user