From 5028995e3725c264b2487a1101c22e941b04c8fd Mon Sep 17 00:00:00 2001 From: rootavish Date: Mon, 23 Jun 2014 23:42:11 +0530 Subject: Functions for document info and EvPage,other changes Summary: I added functions in the backend to get document info. Added a member to evdocument to deal with web documents(ePub) on the frontend. Added a webview to the window, that shall replace the Atril view. Due to removing the view from the main Atril window, I have given rise to various GTK-critical errors in response to signals, will be sure to suppress these in the next commit. Worked towards overall blending in of ePub documents. --- backend/epub/epub-document.c | 148 +++++++++++++++++++++++------ backend/epub/epubdocument.atril-backend.in | 2 +- libdocument/ev-document.c | 28 +++++- libdocument/ev-document.h | 5 + shell/ev-window.c | 67 ++++++++----- 5 files changed, 196 insertions(+), 54 deletions(-) diff --git a/backend/epub/epub-document.c b/backend/epub/epub-document.c index 39c114e3..b61d2eac 100644 --- a/backend/epub/epub-document.c +++ b/backend/epub/epub-document.c @@ -23,6 +23,7 @@ typedef enum _xmlParseReturnType typedef struct _contentListNode { gchar* key ; gchar* value ; + gint index ; }contentListNode; typedef struct _EpubDocumentClass EpubDocumentClass; @@ -64,14 +65,6 @@ epub_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document, return thumbnail; } -static void -epub_document_get_page_size (EvDocument *document, - EvPage *page, - double *width, - double *height) -{ -} - static void epub_document_thumbnails_get_dimensions (EvDocumentThumbnails *document, EvRenderContext *rc, @@ -80,9 +73,10 @@ epub_document_thumbnails_get_dimensions (EvDocumentThumbnails *document, { gdouble page_width, page_height; - epub_document_get_page_size (EV_DOCUMENT (document), rc->page, - &page_width, &page_height); - + /*epub_document_get_page_size (EV_DOCUMENT (document), rc->page, + &page_width, &page_height);*/ + page_width = 800 ; + page_width = 600 ; if (rc->rotation == 90 || rc->rotation == 270) { *width = (gint) (page_height * rc->scale); *height = (gint) (page_width * rc->scale); @@ -486,7 +480,7 @@ extract_one_file(EpubDocument* epub_document,GError ** error) g_string_free(gfilepath,TRUE); g_free(currentfilename); g_free(buffer); - + return TRUE; } static gboolean @@ -585,7 +579,7 @@ get_uri_to_content(const gchar* uri,GError ** error,gchar* tmp_archive_dir) { GError * err = NULL ; gchar* containerpath = g_filename_from_uri(uri,NULL,&err); - GString* absolutepath = g_string_new(NULL); + GString* absolutepath ; gchar* content_uri ; xmlNodePtr rootfileNode ; xmlChar* relativepath; @@ -613,7 +607,7 @@ get_uri_to_content(const gchar* uri,GError ** error,gchar* tmp_archive_dir) return NULL ; } - if ( set_xml_root_node("container") == FALSE) { + if ( set_xml_root_node((xmlChar*)"container") == FALSE) { g_set_error_literal(error, EV_DOCUMENT_ERROR, @@ -622,7 +616,7 @@ get_uri_to_content(const gchar* uri,GError ** error,gchar* tmp_archive_dir) return NULL ; } - if ( (rootfileNode = xml_get_pointer_to_node("rootfile","media-type","application/oebps-package+xml")) == NULL) + if ( (rootfileNode = xml_get_pointer_to_node((xmlChar*)"rootfile",(xmlChar*)"media-type",(xmlChar*)"application/oebps-package+xml")) == NULL) { g_set_error_literal(error, EV_DOCUMENT_ERROR, @@ -640,8 +634,8 @@ get_uri_to_content(const gchar* uri,GError ** error,gchar* tmp_archive_dir) _("epub file is corrupt,no container")); return NULL ; } - g_string_printf(absolutepath,"%s/%s",tmp_archive_dir,relativepath); - + absolutepath = g_string_new(tmp_archive_dir); + g_string_append_printf(absolutepath,"/%s",relativepath); content_uri = g_filename_to_uri(absolutepath->str,NULL,&err); if ( !content_uri ) { if (err) { @@ -655,7 +649,7 @@ get_uri_to_content(const gchar* uri,GError ** error,gchar* tmp_archive_dir) } return NULL ; } - free(absolutepath); + g_string_free(absolutepath,TRUE); return content_uri ; } @@ -665,7 +659,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ { GList* newlist = NULL ; GError * err = NULL ; - + gint indexcounter= 1; xmlNodePtr manifest,spine,itemrefptr,itemptr ; gboolean errorflag = FALSE; @@ -681,7 +675,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ return FALSE ; } - if ( set_xml_root_node("package") == FALSE) { + if ( set_xml_root_node((xmlChar*)"package") == FALSE) { g_set_error_literal(error, EV_DOCUMENT_ERROR, @@ -690,7 +684,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ return FALSE ; } - if ( ( spine = xml_get_pointer_to_node("spine",NULL,NULL) )== NULL ) + if ( ( spine = xml_get_pointer_to_node((xmlChar*)"spine",NULL,NULL) )== NULL ) { g_set_error_literal(error, EV_DOCUMENT_ERROR, @@ -699,7 +693,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ return FALSE ; } - if ( ( manifest = xml_get_pointer_to_node("manifest",NULL,NULL) )== NULL ) + if ( ( manifest = xml_get_pointer_to_node((xmlChar*)"manifest",NULL,NULL) )== NULL ) { g_set_error_literal(error, EV_DOCUMENT_ERROR, @@ -711,7 +705,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ xmlretval = NULL ; /*Get first instance of itemref from the spine*/ - xml_parse_children_of_node(spine,"itemref",NULL,NULL); + xml_parse_children_of_node(spine,(xmlChar*)"itemref",NULL,NULL); if ( xmlretval != NULL ) itemrefptr = xmlretval ; @@ -730,7 +724,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ if ( xmlStrcmp(itemrefptr->name,(xmlChar*)"itemref") == 0) { contentListNode* newnode = g_malloc0(sizeof(newnode)); - newnode->key = xml_get_data_from_node(itemrefptr,XML_ATTRIBUTE,(xmlChar*)"idref"); + newnode->key = (gchar*)xml_get_data_from_node(itemrefptr,XML_ATTRIBUTE,(xmlChar*)"idref"); if ( newnode->key == NULL ) { errorflag =TRUE; @@ -748,7 +742,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ errorflag=TRUE; break; } - relativepath = xml_get_data_from_node(itemptr,XML_ATTRIBUTE,(xmlChar*)"href"); + relativepath = (gchar*)xml_get_data_from_node(itemptr,XML_ATTRIBUTE,(xmlChar*)"href"); g_string_assign(absolutepath,tmp_archive_dir); g_string_append_printf(absolutepath,"/%s",relativepath); newnode->value = g_filename_to_uri(absolutepath->str,NULL,&err); @@ -757,6 +751,8 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ errorflag =TRUE; break; } + + newnode->index = indexcounter++ ; newlist = g_list_prepend(newlist,newnode); } itemrefptr = itemrefptr->next ; @@ -781,7 +777,7 @@ setup_document_content_list(const gchar* content_uri, GError** error,gchar *tmp_ g_list_free_full(newlist,(GDestroyNotify)free_tree_nodes); return NULL ; } - + newlist = g_list_reverse(newlist); g_string_free(absolutepath,TRUE); return newlist ; @@ -823,6 +819,13 @@ epub_document_load (EvDocument* document, return FALSE; } + extract_epub_from_container (uri,epub_document,&err); + + if ( err ) + { + g_propagate_error( error,err ); + return FALSE; + } /*FIXME : can this be different, ever?*/ containerpath = g_string_new(epub_document->tmp_archive_dir); g_string_append_printf(containerpath,"/META-INF/container.xml"); @@ -841,8 +844,13 @@ epub_document_load (EvDocument* document, return FALSE; } + xml_free_doc() ; + epub_document->contentList = setup_document_content_list (contentOpfUri,&err,epub_document->tmp_archive_dir); + if ( xmldocument != NULL ) + xml_free_doc (); + if ( epub_document->contentList == NULL ) { g_propagate_error(error,err); @@ -875,6 +883,91 @@ epub_document_finalize (GObject *object) G_OBJECT_CLASS (epub_document_parent_class)->finalize (object); } +static EvDocumentInfo* +epub_document_get_info(EvDocument *document) +{ + EpubDocument *epub_document = EPUB_DOCUMENT(document); + GError *error = NULL ; + gchar* infofile ; + xmlNodePtr metanode ; + GString* buffer ; + gchar* archive_dir = epub_document->tmp_archive_dir; + GString* containerpath = g_string_new(epub_document->tmp_archive_dir); + g_string_append_printf(containerpath,"/META-INF/container.xml"); + gchar* containeruri = g_filename_to_uri(containerpath->str,NULL,&error); + if ( error ) + { + return NULL ; + } + gchar* uri = get_uri_to_content (containeruri,&error,archive_dir); + if ( error ) + { + return NULL ; + } + EvDocumentInfo* epubinfo = g_new0 (EvDocumentInfo, 1); + + if ( xmldocument != NULL ) + xml_free_doc(); + + infofile = g_filename_from_uri(uri,NULL,&error); + if ( error ) + return epubinfo; + + open_xml_document(infofile); + + set_xml_root_node((xmlChar*)"package"); + + metanode = xml_get_pointer_to_node((xmlChar*)"title",NULL,NULL); + if ( metanode == NULL ) + epubinfo->title = NULL ; + else + epubinfo->title = (char*)xml_get_data_from_node(metanode,XML_KEYWORD,NULL); + + metanode = xml_get_pointer_to_node((xmlChar*)"creator",NULL,NULL); + if ( metanode == NULL ) + epubinfo->author = g_strdup("unknown"); + else + epubinfo->author = xml_get_data_from_node(metanode,XML_KEYWORD,NULL); + + metanode = xml_get_pointer_to_node((xmlChar*)"subject",NULL,NULL); + if ( metanode == NULL ) + epubinfo->subject = g_strdup("unknown"); + else + epubinfo->subject = xml_get_data_from_node(metanode,XML_KEYWORD,NULL); + + buffer = g_string_new(xml_get_data_from_node (xmlroot,XML_ATTRIBUTE,(xmlChar*)"version")); + g_string_prepend(buffer,"epub "); + epubinfo->format = g_strdup(buffer->str); + + /*FIXME: Add more of these as you write the corresponding modules*/ + epubinfo->permissions = EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES; + + epubinfo->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE; + + metanode = xml_get_pointer_to_node((xmlChar*)"publisher",NULL,NULL); + if ( metanode == NULL ) + epubinfo->creator = g_strdup("unknown"); + else + epubinfo->creator = xml_get_data_from_node(metanode,XML_KEYWORD,NULL); + + /*TODO : Add a function to get date*/ + g_free(uri); + g_string_free(containerpath,TRUE); + g_string_free(buffer,TRUE); + return epubinfo ; +} + +static EvPage* +epub_document_get_page(EvDocument *document, + gint index) +{ + EpubDocument *epub_document = EPUB_DOCUMENT(document); + EvPage* page = ev_page_new(index); + contentListNode *listptr = g_list_nth_data (epub_document->contentList,--index); + page->backend_page = g_strdup(listptr->value); + return page ; +} + static void epub_document_class_init (EpubDocumentClass *klass) { @@ -886,6 +979,7 @@ epub_document_class_init (EpubDocumentClass *klass) ev_document_class->load = epub_document_load; ev_document_class->save = epub_document_save; ev_document_class->get_n_pages = epub_document_get_n_pages; - ev_document_class->get_page_size = epub_document_get_page_size; ev_document_class->render = epub_document_render; + ev_document_class->get_info = epub_document_get_info; + ev_document_class->get_page = epub_document_get_page; } diff --git a/backend/epub/epubdocument.atril-backend.in b/backend/epub/epubdocument.atril-backend.in index fe97354b..ef7767eb 100644 --- a/backend/epub/epubdocument.atril-backend.in +++ b/backend/epub/epubdocument.atril-backend.in @@ -1,4 +1,4 @@ [Atril Backend] Module=epubdocument -_TypeDescription=ePub Documents +_TypeDescription=epub Documents MimeType=application/epub+zip; diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c index 19d51d9b..588d0d89 100644 --- a/libdocument/ev-document.c +++ b/libdocument/ev-document.c @@ -26,6 +26,7 @@ #include "ev-document.h" #include "synctex_parser.h" +#include "ev-file-helpers.h" #define EV_DOCUMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EV_TYPE_DOCUMENT, EvDocumentPrivate)) @@ -141,6 +142,8 @@ ev_document_init (EvDocument *document) /* Assume all pages are the same size until proven otherwise */ document->priv->uniform = TRUE; + /* Assume that the document is not a web document*/ + document->iswebdocument = FALSE ; } static void @@ -237,6 +240,14 @@ ev_document_load (EvDocument *document, gboolean retval; GError *err = NULL; + /* + * Hardcoding a check for ePub documents, cause it needs a web document DOM + * and webkit, support for any other web document types can be added similarly. + */ + + if ( !g_strcmp0 (ev_file_get_mime_type(uri,TRUE,&err),"application/epub+zip") ) + document->iswebdocument=TRUE ; + retval = klass->load (document, uri, &err); if (!retval) { if (err) { @@ -258,16 +269,28 @@ ev_document_load (EvDocument *document, /* Cache some info about the document to avoid * going to the backends since it requires locks */ + priv->uri = g_strdup (uri); - priv->n_pages = _ev_document_get_n_pages (document); + priv->n_pages = _ev_document_get_n_pages (document); + for (i = 0; i < priv->n_pages; i++) { + + /* + * Since there is no sense of paging in an ePub,it makes no sense to have pages sizes. + * We are however geeneralising the scenario by considering epub as a type of web document. + * FIXME: Labels, or bookmarks though, can be done. + */ + if ( document->iswebdocument == TRUE ) + break; + EvPage *page = ev_document_get_page (document, i); gdouble page_width = 0; gdouble page_height = 0; EvPageSize *page_size; gchar *page_label; - + + _ev_document_get_page_size (document, page, &page_width, &page_height); if (i == 0) { @@ -277,6 +300,7 @@ ev_document_load (EvDocument *document, priv->max_height = priv->uniform_height; priv->min_width = priv->uniform_width; priv->min_height = priv->uniform_height; + } else if (priv->uniform && (priv->uniform_width != page_width || priv->uniform_height != page_height)) { diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h index d10d261a..940c7c80 100644 --- a/libdocument/ev-document.h +++ b/libdocument/ev-document.h @@ -85,6 +85,11 @@ struct _EvDocument GObject base; EvDocumentPrivate *priv; + /* + * Since we can only access the members of this structure from the window frontend, + * we need a flag to detemine whether to replace the atril-view with a web-view. + */ + gboolean iswebdocument; }; struct _EvDocumentClass diff --git a/shell/ev-window.c b/shell/ev-window.c index 9219a7cb..a423da98 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -1369,8 +1369,8 @@ ev_window_setup_document (EvWindow *ev_window) ev_window->priv->setup_document_idle = 0; ev_window_refresh_window_thumbnail (ev_window); - - ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT); + if ( document->iswebdocument == FALSE ) + ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT); ev_window_title_set_document (ev_window->priv->title, document); ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri); @@ -1405,12 +1405,15 @@ ev_window_setup_document (EvWindow *ev_window) info = ev_document_get_info (document); update_document_mode (ev_window, info->mode); - - if (EV_WINDOW_IS_PRESENTATION (ev_window)) + /*FIXME*/ + if (EV_WINDOW_IS_PRESENTATION (ev_window) && document->iswebdocument == FALSE) gtk_widget_grab_focus (ev_window->priv->presentation_view); - else - gtk_widget_grab_focus (ev_window->priv->view); - + else { + if ( gtk_widget_get_parent(ev_window->priv->view) != NULL ) + gtk_widget_grab_focus (ev_window->priv->view); + else + gtk_widget_grab_focus (ev_window->priv->web_view); + } return FALSE; } @@ -1431,15 +1434,28 @@ ev_window_set_document (EvWindow *ev_window, EvDocument *document) if (ev_document_get_n_pages (document) <= 0) { ev_window_warning_message (ev_window, "%s", _("The document contains no pages")); - } else if (!ev_document_check_dimensions (document)) { + } else if (!ev_document_check_dimensions (document) && document->iswebdocument == FALSE) { ev_window_warning_message (ev_window, "%s", _("The document contains only empty pages")); } +#ifdef ENABLE_EPUB + else if (document->iswebdocument == TRUE){ - if (EV_WINDOW_IS_PRESENTATION (ev_window)) { + /*We have encountered a web document, replace the atril view with a web view.*/ + gtk_container_remove (GTK_CONTAINER(ev_window->priv->scrolled_window),ev_window->priv->view); + gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window), + ev_window->priv->web_view); + gtk_widget_show(ev_window->priv->web_view); + } +#endif + if (EV_WINDOW_IS_PRESENTATION (ev_window) && document->iswebdocument == FALSE) { gtk_widget_destroy (ev_window->priv->presentation_view); ev_window->priv->presentation_view = NULL; ev_window_run_presentation (ev_window); + } else if ( EV_WINDOW_IS_PRESENTATION (ev_window) && document->iswebdocument == TRUE ) + { + ev_window_warning_message (ev_window, "%s", + _("Presentation mode is currently not supported for Web documents.")); } if (ev_window->priv->setup_document_idle > 0) @@ -1539,7 +1555,7 @@ ev_window_load_job_cb (EvJob *job, ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE); /* Success! */ - if (!ev_job_is_failed (job)) { + if (!ev_job_is_failed (job)) { ev_document_model_set_document (ev_window->priv->model, document); #ifdef ENABLE_DBUS @@ -5295,13 +5311,24 @@ ev_window_dispose (GObject *object) } if (priv->view) { - g_object_unref (priv->view); + if ( gtk_widget_get_parent (priv->view) == NULL ) + { + g_object_ref_sink (priv->view); + } + else + { + g_object_unref (priv->view); + } priv->view = NULL; } #ifdef ENABLE_EPUB if ( priv->web_view ) { - g_object_unref (priv->web_view); + if (gtk_widget_get_parent(priv->web_view) == NULL ) { + g_object_ref_sink (priv->web_view); + }else { + g_object_unref (priv->web_view); + } priv->web_view = NULL ; } #endif @@ -7079,18 +7106,10 @@ ev_window_init (EvWindow *ev_window) /* We own a ref on these widgets, as we can swap them in and out */ g_object_ref (ev_window->priv->view); g_object_ref (ev_window->priv->password_view); -#ifdef ENABLE_EPUB - if (0) - { - gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window), - ev_window->priv->web_view); - } - else -#endif - { - gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window), - ev_window->priv->view); - } + + gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window), + ev_window->priv->view); + /* Connect to model signals */ g_signal_connect_swapped (ev_window->priv->model, "page-changed", -- cgit v1.2.1