diff --git a/src/control/xojfile/LoadHandler.cpp b/src/control/xojfile/LoadHandler.cpp index 19e24522..3d558c4d 100644 --- a/src/control/xojfile/LoadHandler.cpp +++ b/src/control/xojfile/LoadHandler.cpp @@ -225,6 +225,9 @@ auto LoadHandler::parseXml() -> bool { g_markup_parse_context_free(context); + // Add all parsed pages to the document + this->doc.addPages(pages.begin(), pages.end()); + if (this->pos != PASER_POS_FINISHED && this->lastError.empty()) { lastError = _("Document is not complete (maybe the end is cut off?)"); return false; @@ -288,7 +291,7 @@ void LoadHandler::parseContents() { this->page = std::make_unique(width, height); - this->doc.addPage(this->page); + pages.push_back(this->page); } else if (strcmp(elementName, "audio") == 0) { this->parseAudio(); } else if (strcmp(elementName, "title") == 0) { diff --git a/src/control/xojfile/LoadHandler.h b/src/control/xojfile/LoadHandler.h index 0899bc1c..c93b9477 100644 --- a/src/control/xojfile/LoadHandler.h +++ b/src/control/xojfile/LoadHandler.h @@ -125,6 +125,7 @@ private: vector pressureBuffer; + std::vector pages; PageRef page; Layer* layer; Stroke* stroke; diff --git a/src/model/Document.cpp b/src/model/Document.cpp index 06f5d9ba..162d825f 100644 --- a/src/model/Document.cpp +++ b/src/model/Document.cpp @@ -1,5 +1,6 @@ #include "Document.h" +#include #include #include @@ -85,6 +86,7 @@ void Document::clearDocument(bool destroy) { } this->pages.clear(); + this->pageIndex.reset(); freeTreeContentModel(); this->filename = ""; @@ -169,15 +171,15 @@ auto Document::isPdfDocumentLoaded() -> bool { return pdfDocument.isLoaded(); } auto Document::isAttachPdf() const -> bool { return this->attachPdf; } auto Document::findPdfPage(size_t pdfPage) -> size_t { - for (size_t i = 0; i < getPageCount(); i++) { - PageRef p = this->pages[i]; - if (p->getBackgroundType().isPdfPage()) { - if (p->getPdfPageNr() == pdfPage) { - return i; - } - } + // Create a page index if not already indexed. + if (!this->pageIndex) + indexPdfPages(); + auto pos = this->pageIndex->find(pdfPage); + if (pos == this->pageIndex->end()) { + return -1; + } else { + return pos->second; } - return -1; } void Document::buildTreeContentsModel(GtkTreeIter* parent, XojPdfBookmarkIterator* iter) { @@ -215,6 +217,18 @@ void Document::buildTreeContentsModel(GtkTreeIter* parent, XojPdfBookmarkIterato } while (iter->next()); } +void Document::indexPdfPages() { + auto index = std::make_unique(); + for (size_t i = 0; i < this->pages.size(); ++i) { + const auto& p = this->pages[i]; + if (p->getBackgroundType().isPdfPage()) { + index->emplace(p->getPdfPageNr(), i); + } + } + this->pageIndex.swap(index); +} + + void Document::buildContentsModel() { freeTreeContentModel(); @@ -298,10 +312,11 @@ auto Document::readPdf(const Path& filename, bool initPages, bool attachToDocume XojPdfPageSPtr page = pdfDocument.getPage(i); auto p = std::make_shared(page->getWidth(), page->getHeight()); p->setBackgroundPdfPageNr(i); - addPage(std::move(p)); + this->pages.emplace_back(std::move(p)); } } + indexPdfPages(); buildContentsModel(); updateIndexPageNumbers(); @@ -327,18 +342,24 @@ void Document::deletePage(size_t pNr) { auto it = this->pages.begin() + pNr; this->pages.erase(it); + // Reset the page index + this->pageIndex.reset(); updateIndexPageNumbers(); } void Document::insertPage(const PageRef& p, size_t position) { this->pages.insert(this->pages.begin() + position, p); + // Reset the page index + this->pageIndex.reset(); updateIndexPageNumbers(); } void Document::addPage(const PageRef& p) { this->pages.push_back(p); + // Reset the page index + this->pageIndex.reset(); updateIndexPageNumbers(); } @@ -378,11 +399,9 @@ auto Document::operator=(const Document& doc) -> Document& { this->createBackupOnSave = doc.createBackupOnSave; this->pdfFilename = doc.pdfFilename; this->filename = doc.filename; + this->pages = doc.pages; - for (const PageRef& p: doc.pages) { - addPage(p); - } - + indexPdfPages(); buildContentsModel(); updateIndexPageNumbers(); diff --git a/src/model/Document.h b/src/model/Document.h index 299a5cfc..e2a19dac 100644 --- a/src/model/Document.h +++ b/src/model/Document.h @@ -13,7 +13,9 @@ #pragma once +#include #include +#include #include #include "pdf/base/XojPdfBookmarkIterator.h" @@ -44,6 +46,8 @@ public: void insertPage(const PageRef& p, size_t position); void addPage(const PageRef& p); + template + void addPages(InputIter first, InputIter last); PageRef getPage(size_t page); void deletePage(size_t pNr); @@ -117,6 +121,23 @@ private: */ vector pages; + /** + * Index from pdf page number to document page number + */ + using PageIndex = std::unordered_map; + + /** + * The cached page index + */ + std::unique_ptr pageIndex; + + /** + * Creates an index from pdf page number to document page number + * + * Clears the index first in case it is already exists. + */ + void indexPdfPages(); + /** * The bookmark contents model */ @@ -137,3 +158,10 @@ private: */ GMutex documentLock{}; }; + +template +void Document::addPages(InputIter first, InputIter last) { + this->pages.insert(this->pages.end(), first, last); + this->pageIndex.reset(); + updateIndexPageNumbers(); +}