diff --git a/include/openmg/backend/readmng.h b/include/openmg/backend/readmng.h index 7ebe557..c175c82 100644 --- a/include/openmg/backend/readmng.h +++ b/include/openmg/backend/readmng.h @@ -29,4 +29,8 @@ mg_backend_readmng_new (void); GListStore * mg_backend_readmng_get_featured_manga (MgBackendReadmng *self); +void +mg_backend_readmng_retrieve_manga_details (MgBackendReadmng *self, + MgManga *manga); + G_END_DECLS diff --git a/include/openmg/manga.h b/include/openmg/manga.h index 5942bb8..60d9cb1 100644 --- a/include/openmg/manga.h +++ b/include/openmg/manga.h @@ -6,9 +6,22 @@ G_BEGIN_DECLS; #define MG_TYPE_MANGA mg_manga_get_type() G_DECLARE_FINAL_TYPE (MgManga, mg_manga, MG, MANGA, GObject) -char *mg_manga_get_image_url(MgManga *mg_manga); -char *mg_manga_get_title(MgManga *mg_manga); -char *mg_manga_get_id(MgManga *mg_manga); +char * +mg_manga_get_image_url (MgManga *mg_manga); +char * +mg_manga_get_title (MgManga *mg_manga); +char * +mg_manga_get_id (MgManga *mg_manga); +char * +mg_manga_get_id (MgManga *mg_manga); +char * +mg_manga_get_description (MgManga *mg_manga); +void +mg_manga_set_description (MgManga *mg_manga, const char *description); +int +mg_manga_has_details (MgManga *self); +void +mg_manga_details_recovered (MgManga *self); MgManga *mg_manga_new (const char *const image_url, const char *const title, const char *const id); diff --git a/src/backend/readmng.c b/src/backend/readmng.c index 99a9f4d..ba66d52 100644 --- a/src/backend/readmng.c +++ b/src/backend/readmng.c @@ -1,9 +1,12 @@ #include #include + #include #include #include +#include + #include typedef enum { @@ -41,10 +44,13 @@ mg_backend_readmng_class_init (MgBackendReadmngClass *class) { mg_backend_readmng_properties); } +static xmlDocPtr +mg_backend_readmng_fetch_xml_details (MgBackendReadmng *self, + MgManga *manga); static xmlNodePtr mg_backend_readmng_retrieve_img_from_thumbnail (MgBackendReadmng *self, xmlNodePtr thumbnail); static xmlNodePtr -mg_backend_readmng_retrieve_ul_slides(MgBackendReadmng *self, xmlNodePtr slides) ; +mg_backend_readmng_retrieve_ul_slides (MgBackendReadmng *self, xmlNodePtr slides) ; static void mg_backend_readmng_extract_manga_info_from_current_li (MgBackendReadmng *self, GListStore *mangas, xmlNodePtr current_li); @@ -125,16 +131,80 @@ mg_backend_readmng_get_featured_manga (MgBackendReadmng *self) { } +void +mg_backend_readmng_retrieve_manga_details (MgBackendReadmng *self, + MgManga *manga) { + MgUtilXML *xml_utils; + + xmlDocPtr html_document; + xmlNodePtr *movie_detail = NULL; + xmlXPathObjectPtr xpath_result = NULL; + xmlNodeSetPtr node_set = NULL; + + size_t movie_detail_len = 0; + + if (mg_manga_has_details (manga)) { + return; + } + xml_utils = mg_util_xml_new (); + html_document = mg_backend_readmng_fetch_xml_details (self, + manga); + xpath_result = mg_util_xml_get_nodes_xpath_expression (xml_utils, + html_document, "//li[@class]"); + node_set = xpath_result->nodesetval; + if (!node_set) { + fprintf(stderr, "No match\n"); + return; + } + for (int i = 0; i < node_set->nodeNr; i++) { + xmlNodePtr node = node_set->nodeTab[i]; + movie_detail = mg_util_xml_loop_search_class (xml_utils, + node, movie_detail, "movie-detail", &movie_detail_len); + } + if (movie_detail) { + mg_manga_set_description (manga, + (char *) xmlNodeGetContent (movie_detail[0])); + } + mg_manga_details_recovered (manga); +} + +static xmlDocPtr +mg_backend_readmng_fetch_xml_details (MgBackendReadmng *self, + MgManga *manga) { + MgUtilSoup *util_soup; + MgUtilString *string_util; + + char *request_url; + char *manga_id; + + size_t request_url_len; + size_t response_len = 0; + + + util_soup = mg_util_soup_new (); + string_util = mg_util_string_new (); + manga_id = mg_manga_get_id (manga); + request_url_len = snprintf ( NULL, 0, "%s/%s/", self->base_url, manga_id); + request_url = mg_util_string_alloc_string (string_util, request_url_len); + snprintf ( request_url, request_url_len+1, "%s/%s/", self->base_url, manga_id); + + char *html_response = mg_util_soup_get_request (util_soup, + request_url, &response_len); + return htmlReadMemory (html_response, response_len, NULL, NULL, + HTML_PARSE_RECOVER | HTML_PARSE_NODEFDTD + | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING ); +} + static xmlDocPtr mg_backend_readmng_fetch_xml_main_page (MgBackendReadmng *self) { size_t size_response_text = 0; return htmlReadMemory (mg_backend_readmng_get_main_page (self, &size_response_text), - size_response_text, - NULL, - NULL, - HTML_PARSE_RECOVER | HTML_PARSE_NODEFDTD - | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING - ); + size_response_text, + NULL, + NULL, + HTML_PARSE_RECOVER | HTML_PARSE_NODEFDTD + | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING + ); } static const char * @@ -163,7 +233,7 @@ mg_backend_readmng_parse_main_page (MgBackendReadmng *self, const xmlDocPtr html xmlNodePtr current_li = li[i]; mg_backend_readmng_extract_manga_info_from_current_li (self, mangas, current_li); - + } return mangas; } diff --git a/src/manga.c b/src/manga.c index 5a52f22..01d56d0 100644 --- a/src/manga.c +++ b/src/manga.c @@ -8,6 +8,8 @@ struct _MgManga { char *image_url; char *title; char *id; + char *description; + int has_details; }; G_DEFINE_TYPE (MgManga, mg_manga, G_TYPE_OBJECT) @@ -16,6 +18,7 @@ typedef enum { MG_MANGA_IMAGE_URL = 1, MG_MANGA_TITLE, MG_MANGA_ID, + MG_MANGA_DESCRIPTION, MG_MANGA_N_PROPERTIES } MgMangaProperties; @@ -50,9 +53,15 @@ mg_manga_class_init (MgMangaClass *class) { G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); manga_properties[MG_MANGA_ID] = g_param_spec_string ("id", "Id", - "Id of the manga", + "Id of the manga.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + manga_properties[MG_MANGA_DESCRIPTION] = g_param_spec_string ( + "description", + "Description", + "Description of the manga.", + NULL, + G_PARAM_READWRITE); g_object_class_install_properties (object_class, MG_MANGA_N_PROPERTIES, @@ -61,11 +70,22 @@ mg_manga_class_init (MgMangaClass *class) { static void mg_manga_init (MgManga *self) { + self->has_details = 0; +} + +int +mg_manga_has_details (MgManga *self) { + return self->has_details; +} + +void +mg_manga_details_recovered (MgManga *self) { + self->has_details = 1; } char * mg_manga_get_id (MgManga *self) { - GValue value = G_VALUE_INIT; + GValue value = G_VALUE_INIT; g_value_init (&value, G_TYPE_STRING); g_object_get_property (G_OBJECT (self), "id", @@ -93,6 +113,24 @@ mg_manga_get_title (MgManga *self) { return g_value_dup_string (&value); } +char * +mg_manga_get_description (MgManga *self) { + GValue value = G_VALUE_INIT; + g_value_init (&value, G_TYPE_STRING); + g_object_get_property (G_OBJECT (self), + "description", + &value); + return g_value_dup_string (&value); +} + +void +mg_manga_set_description (MgManga *self, const char *description) { + GValue value = G_VALUE_INIT; + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, description); + g_object_set_property (G_OBJECT (self), "description", &value); +} + static void mg_manga_set_property (GObject *object, guint property_id, @@ -112,6 +150,10 @@ mg_manga_set_property (GObject *object, g_free (self->id); self->id = g_value_dup_string (value); break; + case MG_MANGA_DESCRIPTION: + g_free (self->description); + self->description = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -134,6 +176,9 @@ mg_manga_get_property (GObject *object, case MG_MANGA_ID: g_value_set_string (value, self->id); break; + case MG_MANGA_DESCRIPTION: + g_value_set_string (value, self->description); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; diff --git a/src/view/detail_manga.c b/src/view/detail_manga.c index d5b46fa..3039e3e 100644 --- a/src/view/detail_manga.c +++ b/src/view/detail_manga.c @@ -3,6 +3,8 @@ #include +#include + #include #include @@ -10,19 +12,33 @@ GtkBox * create_detail_view (MgManga *manga) { + MgBackendReadmng *readmng = mg_backend_readmng_new (); GtkBox *detail_view = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0)); - GtkBox *descriptive_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0)); + GtkBox *avatar_title_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0)); MgUtilXML *xml_util = mg_util_xml_new (); GtkLabel *manga_title = NULL; + GtkLabel *manga_description = NULL; GtkPicture *manga_image = create_picture_from_url ( mg_manga_get_image_url(manga), 200); char *title_text = mg_util_xml_get_title_text ( xml_util, mg_manga_get_title (manga)); + char *description_text; + + mg_backend_readmng_retrieve_manga_details (readmng, manga); + + description_text = mg_manga_get_description (manga); + manga_title = GTK_LABEL (gtk_label_new (title_text)); + manga_description = GTK_LABEL (gtk_label_new (description_text)); + gtk_label_set_wrap (manga_title, 1); + gtk_label_set_wrap (manga_description, 1); + gtk_label_set_use_markup (GTK_LABEL (manga_title), 1); - gtk_box_append (descriptive_box, GTK_WIDGET (manga_image)); - gtk_box_append (descriptive_box, GTK_WIDGET (manga_title)); - gtk_box_append (detail_view, GTK_WIDGET (descriptive_box)); + gtk_box_append (avatar_title_box, GTK_WIDGET (manga_image)); + gtk_box_append (avatar_title_box, GTK_WIDGET (manga_title)); + gtk_box_append (detail_view, GTK_WIDGET (avatar_title_box)); + gtk_box_append (detail_view, GTK_WIDGET (manga_description)); + return detail_view; }