Коммит 01a9d2c1 создал по автору OMP Education's avatar OMP Education
Просмотр файлов

[Source] Implement document text caching to speed up searching.

владелец 78a995d2
Конвейер #33667 пройдено с этапами
in 4 минуты и 52 секунды
......@@ -21,7 +21,7 @@ message( STATUS "Target CPU Name: ${CPU_NAME}" )
cmake_policy(VERSION 3.14...3.25)
set(PDFIUM_RELEASE chromium%2F7269)
set(PDFIUM_RELEASE chromium%2F7415)
set(PDFIUM_DIR ${CMAKE_BINARY_DIR}/pdfium)
set(PDFIUM_RELEASE_DIR ${PDFIUM_DIR}/${PDFIUM_RELEASE})
......
......@@ -95,3 +95,8 @@ Features and fixes.
Features.
1. Add sort PDF files by name, size, date in FilesPage.
2. Usage external pdfium, libjpeg.
## 1.3.11
Features.
1. Implement document text caching to speed up searching. Updating the pdfium library to 7269 version.
......@@ -30,6 +30,7 @@ set(INCLUDE_HEADERS
src/pdfword.h
src/pdfbookmark.h
src/userpdfbookmark.h
src/pdfpagetexts.h
)
add_definitions(-DTASK_PRIORITY_RATIO=10)
......
......@@ -40,7 +40,6 @@
#include <QFileInfo>
#include <QFutureWatcher>
#include <pdfpagewordstask.h>
#include "pdftaskqueue.h"
#include "tasks/pdfdocumentloadtask.h"
#include "tasks/pdfdocumentloadfrommemtask.h"
......@@ -311,7 +310,6 @@ void PdfDocument::loadDocument(const QString &fileName, const QString &password)
auto watcher = dynamic_cast<QFutureWatcher<QPair<int, QSharedPointer<fpdf_document_t__>>>*>(sender());
if (watcher == nullptr)
return;
if (watcher->isCanceled())
d->m_status = DocumentStatus::InternalError;
else
......@@ -472,6 +470,7 @@ QFuture<QString> PdfDocument::getFileId() const
return interface.future();
}
/*!
* Initialize a PdfDocumentExtractNewFileIdTask and returns its result in future.
*/
......@@ -565,12 +564,12 @@ bool PdfDocument::exportDocument(QIODevice *output) const
/*!
* Initialize a PdfDocumentPhraseSearchTask and returns its result in future.
*/
QFuture<QVector<QSharedPointer<PdfWord>>> PdfDocument::searchPhrase(const QString &phrase) const
QFuture<PdfPageTexts*> PdfDocument::searchPhrase(const QString &phrase, PdfPageTexts* pageTextsModel) const
{
Q_D(const PdfDocument);
QFutureInterface<QVector<QSharedPointer<PdfWord>>> interface;
auto task = QSharedPointer<PdfTask>(new PdfDocumentPhraseSearchTask(phrase, interface, d->m_documentHolder));
QFutureInterface<PdfPageTexts*> interface;
auto task = QSharedPointer<PdfTask>(new PdfDocumentPhraseSearchTask(phrase, pageTextsModel, interface, d->m_documentHolder));
auto addResult = PdfTaskQueue::instance().addTask(task, PdfTaskQueue::TaskPriority::Immediately);
if (!addResult) {
......@@ -582,7 +581,6 @@ QFuture<QVector<QSharedPointer<PdfWord>>> PdfDocument::searchPhrase(const QStrin
return interface.future();
}
/*!
* Initialize a PdfDocumentLoadTask and returns its result in future.
*/
......
......@@ -47,7 +47,9 @@
#include "pdfbookmark.h"
#include "userpdfbookmark.h"
#include "pdfpage.h"
#include "pdfpagetexts.h"
class PdfPageTexts;
class PdfPage;
class PdfWord;
class PdfDocumentPrivate;
......@@ -96,8 +98,7 @@ public:
QFuture<QString> getFileId() const;
QFuture<bool> renameBookmarksFile(const QString &prevFileName, const QString &newFileName) const;
QFuture<QString> getNewFileId(const QString &filePath) const;
QFuture<QVector<QSharedPointer<PdfWord>>> searchPhrase(const QString &phrase) const;
QFuture<PdfPageTexts*> searchPhrase(const QString &phrase, PdfPageTexts* pageTextsModel) const;
signals:
void statusChanged(PdfDocument::DocumentStatus status);
void pageCountChanged(int pageCount);
......
......@@ -397,7 +397,7 @@ QFuture<bool> PdfPage::drawInkAnnotation(const QRectF &rect, const QColor &color
pointfs.append(QPointF(points.first().at(i).x(), points.first().at(i).y()));
}
pointflist.append(pointfs);
PdfPageDrawSolidPaths::Strokes strokes{ rect, color, points, penSize };
PdfPageDrawSolidPaths::Strokes strokes{ rect, color, points, static_cast<int>(penSize) };
auto task = QSharedPointer<PdfTask>(new PdfPageDrawSolidPaths(d->m_page, strokes, interface, d->m_documentHolder));
auto addingResult = PdfTaskQueue::instance().addTask(task, PdfTaskQueue::TaskPriority::High,
......@@ -562,3 +562,8 @@ QList<QRectF> PdfPage::findTextRects(QPoint startPoint, QPoint endPoint)
}
return attachedPoints;
}
const QString PdfPage::text() const
{
return d->text;
}
......@@ -108,6 +108,7 @@ public:
QFuture<bool> addImage(const QPointF &topLeft, const qreal &pageRate, const QString &imagePath);
QFuture<bool> highlightText(QPoint startPoint, QPoint endPoint, QColor color);
QList<QRectF> findTextRects(QPoint startPoint, QPoint endPoint);
const QString text() const;
private:
QSharedDataPointer<PdfPageData> d;
......
......@@ -60,6 +60,7 @@ public:
PdfPageData &operator=(PdfPageData &&other);
int m_pageNumber;
QString text;
QSharedPointer<fpdf_page_t__> m_page;
mutable QSharedPointer<PdfDocumentHolder> m_documentHolder;
QSharedPointer<fpdf_textpage_t__> m_textPage;
......
#include "pdfpagetexts.h"
PdfPageTexts::PdfPageTexts(QObject *parent) : QObject(parent) { }
bool PdfPageTexts::isEmpty() const
{
return m_pageTexts.isEmpty();
}
bool PdfPageTexts::hasPage(int pageIndex) const
{
return m_pageTexts.contains(pageIndex);
}
int PdfPageTexts::size() const
{
return m_pageTexts.size();
}
void PdfPageTexts::addPage(int index, QString pageText)
{
m_pageTexts.insert(index, pageText);
}
void PdfPageTexts::addResult(QSharedPointer<PdfWord> result)
{
m_phrasesForModel.append(result);
}
const QHash<int, QString> &PdfPageTexts::pageTexts() const
{
return m_pageTexts;
}
void PdfPageTexts::addLastSearchResult(QVector<QSharedPointer<PdfWord>> res)
{
m_phrasesForModel.clear();
m_phrasesForModel.append(res);
}
QRegularExpressionMatchIterator PdfPageTexts::findTextOnPage(int pageIntex, QString text)
{
QRegularExpression regex(text, QRegularExpression::CaseInsensitiveOption);
return regex.globalMatch(m_pageTexts.value(pageIntex));
}
const QVector<QSharedPointer<PdfWord> > &PdfPageTexts::phrasesForModel() const
{
return m_phrasesForModel;
}
#ifndef PDFPAGETEXTS_H
#define PDFPAGETEXTS_H
#include <QObject>
#include <QRegularExpressionMatchIterator>
#include <QSharedPointer>
#include <QVector>
#include "pdfword.h"
class PdfPageTexts : public QObject
{
Q_OBJECT
public:
explicit PdfPageTexts(QObject *parent = nullptr);
bool isEmpty() const;
bool hasPage(int pageIndex) const;
int size() const;
void addPage(int index, QString pageText);
void addResult(QSharedPointer<PdfWord> result);
const QHash<int, QString> &pageTexts() const;
void addLastSearchResult(QVector<QSharedPointer<PdfWord>> res);
QRegularExpressionMatchIterator findTextOnPage(int pageIntex, QString text);
const QVector<QSharedPointer<PdfWord> > &phrasesForModel() const;
private:
QString m_phrase;
QVector<QSharedPointer<PdfWord>> m_phrasesForModel;
QHash<int, QString> m_pageTexts;
};
#endif // PDFPAGETEXTS_H
......@@ -2,6 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "pdfdocumentphrasesearchtask.h"
#include <QRegularExpression>
/*!
* \class PdfDocumentPhraseSearchTask
......@@ -16,8 +17,19 @@
* \a interface is QFutureInterface for future tasks.
* \a documentHolder is QSharedPointer to PdfDocumentHolder object with document.
*/
PdfDocumentPhraseSearchTask::PdfDocumentPhraseSearchTask(const QString phrase, PdfPageTexts *pageTextsModel,
const QFutureInterface<PdfPageTexts*> &interface,
const QSharedPointer<PdfDocumentHolder> &documentHolder)
: m_interface(interface),
m_documentHolder(documentHolder),
m_phrase(phrase),
m_pageTextsModel(pageTextsModel)
{
}
PdfDocumentPhraseSearchTask::PdfDocumentPhraseSearchTask(const QString phrase,
const QFutureInterface<QVector<QSharedPointer<PdfWord>>> &interface,
const QFutureInterface<PdfPageTexts*> &interface,
const QSharedPointer<PdfDocumentHolder> &documentHolder)
: m_interface(interface),
m_documentHolder(documentHolder),
......@@ -48,22 +60,30 @@ void PdfDocumentPhraseSearchTask::run()
m_interface.cancel();
return;
}
m_phrasesForModel.clear();
FPDF_WIDESTRING phraseWideString = m_phrase.utf16();
const int pageCount = FPDF_GetPageCount(m_documentHolder->document().data());
m_interface.setProgressRange(0, pageCount - 1);
for (int i = 0; i < m_pageTextsModel->phrasesForModel().size(); i++) {
m_oldResultByPage.insert(m_pageTextsModel->phrasesForModel().at(i)->index());
}
for (int i = 0; i < pageCount; ++i)
{
if (m_interface.isCanceled() || PdfTaskQueue::instance().blockedId().contains(m_documentHolder->id())) {
m_interface.reportResult(&m_phrasesForModel);
m_interface.reportResult(m_pageTextsModel);
return;
}
parsePage(i, phraseWideString);
if (m_pageTextsModel->hasPage(i)) {
findOnCachedPage(i, phraseWideString);
} else {
cacheAndFind(i, phraseWideString);
}
m_interface.setProgressValue(i);
}
m_interface.reportFinished(&m_phrasesForModel);
m_pageTextsModel->addLastSearchResult(m_phrasesForModel);
m_interface.reportFinished(&m_pageTextsModel);
}
/*!
......@@ -82,16 +102,22 @@ int PdfDocumentPhraseSearchTask::id() const
return m_documentHolder->id();
}
/*!
* Searches matching \a phrase for the given page by \a pageIndex.
*/
void PdfDocumentPhraseSearchTask::parsePage(const int& pageIndex, const FPDF_WIDESTRING& phrase)
{
void PdfDocumentPhraseSearchTask::findOnPage(const int& pageIndex, const FPDF_WIDESTRING& phrase) {
auto loadedPage = QSharedPointer<fpdf_page_t__>(FPDF_LoadPage(m_documentHolder->document().data(), pageIndex), [](fpdf_page_t__ *){ });
auto pageCharactersInfo = QSharedPointer<fpdf_textpage_t__>(FPDFText_LoadPage(loadedPage.data()), [](fpdf_textpage_t__ *){ });
auto searchContext = QSharedPointer<fpdf_schhandle_t__>(FPDFText_FindStart(pageCharactersInfo.data(), phrase, 0x00000000, 0), [](fpdf_schhandle_t__*){ });
int amountOfCharacters = FPDFText_CountChars(pageCharactersInfo.data());
QVector<QSharedPointer<PdfWord>> pageMatchingPhrases;
QVector<ushort> phraseBuffer(static_cast<qint32>(amountOfCharacters + 1));
FPDFText_GetText(pageCharactersInfo.data(), 0, amountOfCharacters, phraseBuffer.data());
if (!m_pageTextsModel->hasPage(pageIndex)) {
QString pageText = "";
for (int i = 0; i < amountOfCharacters; i++)
pageText.append(phraseBuffer.at(i));
m_pageTextsModel->addPage(pageIndex, pageText);
}
while (FPDFText_FindNext(searchContext.data())) {
int numberOfMatchedCharacters = FPDFText_GetSchCount(searchContext.data());
......@@ -153,23 +179,17 @@ void PdfDocumentPhraseSearchTask::parsePage(const int& pageIndex, const FPDF_WID
// Refreshing the character box borders for each character of the word or phrase.
FPDFText_GetCharBox(pageCharactersInfo.data(), startingCharacterIndex + i, &charLeft, &charRight, &charBottom, &charTop);
globalLeft = std::min(globalLeft, charLeft);
globalBottom = std::min(globalBottom, charBottom);
globalRight = std::max(globalRight, charRight);
globalTop = std::max(globalTop, charTop);
}
for (int i = 0; i < numberOfMatchedCharacters; ++i) {
double charLeft, charTop, charRight, charBottom;
// Refreshing the character box borders for each character of the word or phrase.
FPDFText_GetCharBox(pageCharactersInfo.data(), startingCharacterIndex + i, &charLeft, &charRight, &charBottom, &charTop);
if (charTop <= attachedRectBottom && i != 0) {
if (charTop <= attachedRectBottom && i != beforeCharacterIndex) {
attachedRects.append(QRectF(attachedRectLeft, attachedRectBottom, attachedRectRight - attachedRectLeft, attachedRectTop - attachedRectBottom));
attachedRectLeft = charLeft;
attachedRectTop = charTop;
attachedRectRight = charRight;
attachedRectBottom = charBottom;
}
globalLeft = std::min(globalLeft, charLeft);
globalBottom = std::min(globalBottom, charBottom);
globalRight = std::max(globalRight, charRight);
globalTop = std::max(globalTop, charTop);
attachedRectLeft = std::min(attachedRectLeft, charLeft);
attachedRectBottom = std::min(attachedRectBottom, charBottom);
attachedRectRight = std::max(attachedRectRight, charRight);
......@@ -192,13 +212,11 @@ void PdfDocumentPhraseSearchTask::parsePage(const int& pageIndex, const FPDF_WID
PdfWord* word = new PdfWord(text, pageIndex, rect, nullptr, context);
word->setAttachedRects(attachedRects);
pageMatchingPhrases.append(QSharedPointer<PdfWord>(word));
} else {
QList<QRectF> newAttachedRects = pageMatchingPhrases.last()->attachedRects();
newAttachedRects.append(attachedRects);
pageMatchingPhrases.last()->setAttachedRects(newAttachedRects);
}
}
// Clearing data.
m_oldResultByPage.remove(pageIndex);
FPDFText_FindClose(searchContext.data());
FPDFText_ClosePage(pageCharactersInfo.data());
FPDF_ClosePage(loadedPage.data());
......@@ -206,6 +224,21 @@ void PdfDocumentPhraseSearchTask::parsePage(const int& pageIndex, const FPDF_WID
m_phrasesForModel.append(pageMatchingPhrases);
}
/*!
* Searches matching \a phrase for the given page by \a pageIndex.
*/
void PdfDocumentPhraseSearchTask::cacheAndFind(const int& pageIndex, const FPDF_WIDESTRING& phrase)
{
findOnPage(pageIndex, phrase);
}
void PdfDocumentPhraseSearchTask::findOnCachedPage(const int& pageIndex, const FPDF_WIDESTRING& phrase) {
QRegularExpressionMatchIterator i = m_pageTextsModel->findTextOnPage(pageIndex, m_phrase);
if (i.hasNext())
findOnPage(pageIndex, phrase);
}
/*!
* Gets the context (current line, previous line, next line) for the given phrase.
* \a amountOfCharacters is amount of characters on the page.
......
......@@ -12,6 +12,7 @@
#include <QFuture>
#include <QColor>
#include <pdfpagetexts.h>
#include <pdfium/fpdf_text.h>
#include <pdfium/fpdf_annot.h>
......@@ -19,9 +20,14 @@
class PdfDocumentPhraseSearchTask : public PdfTask
{
public:
explicit PdfDocumentPhraseSearchTask(const QString phrase,
const QFutureInterface<QVector<QSharedPointer<PdfWord>>> &interface,
explicit PdfDocumentPhraseSearchTask(const QString phrase, PdfPageTexts *pageTextsModel,
const QFutureInterface<PdfPageTexts*> &interface,
const QSharedPointer<PdfDocumentHolder> &documentHolder);
PdfDocumentPhraseSearchTask(const QString phrase,
const QFutureInterface<PdfPageTexts*> &interface,
const QSharedPointer<PdfDocumentHolder> &documentHolder);
~PdfDocumentPhraseSearchTask();
void run() override;
......@@ -29,18 +35,20 @@ public:
int id() const override;
private:
void parsePage(const int& pageIndex, const FPDF_WIDESTRING& phrase);
QString getPhraseContext(const int& amountOfCharacters, const FPDF_TEXTPAGE page, const int& startIndex, const QString textWithColloredPhrase, const int wordLength);
void removePageOldSearchAnnotations(const QSharedPointer<fpdf_page_t__>& page);
void cacheAndFind(const int& pageIndex, const FPDF_WIDESTRING& phrase);
QVariant getAnnotationValue(FPDF_ANNOTATION currentAnnot, QString key);
void addPageResultAnnotations(const QVector<QSharedPointer<PdfWord> > &pagePhrases, const QSharedPointer<fpdf_page_t__>& page);
void findOnCachedPage(const int &pageIndex, const FPDF_WIDESTRING &phrase);
void findOnPage(const int& pageIndex, const FPDF_WIDESTRING& phrase);
private:
QFutureInterface<QVector<QSharedPointer<PdfWord>>> m_interface;
QFutureInterface<PdfPageTexts*> m_interface;
QSharedPointer<PdfDocumentHolder> m_documentHolder;
QString m_phrase;
QVector<QSharedPointer<PdfWord>> m_phrasesForModel;
QColor m_searchAnnotColor = QColor(Qt::GlobalColor::green);
QSet<int> m_oldResultByPage;
PdfPageTexts *m_pageTextsModel;
};
#endif // PDFDOCUMENTPHRASESEARCHTASK_H
......@@ -9,6 +9,7 @@
#include <QSharedPointer>
#include <baseword.h>
class PdfPageTexts;
class BasePage;
class BaseBookmark;
class UserBookmark;
......
......@@ -22,6 +22,7 @@ public:
virtual void loadAnnotations() = 0;
virtual bool isAnnotationsSupport() const = 0;
virtual int pageNumber() const = 0;
virtual QString text() = 0;
virtual QFuture<QSizeF> originalSize() = 0;
virtual QFuture<QImage> bitmapFull(qreal pageScale, int renderFlags = 0) const = 0;
virtual QFuture<QSharedPointer<QImage>> bitmapPart(qreal pageScaleX, qreal pageScaleY,
......
......@@ -28,9 +28,6 @@ QVariant PagesWithNotesModel::data(const QModelIndex &index, int role) const
if (m_notesModels.contains(index.row()) && m_notesModels.value(index.row()) != nullptr)
notesModel = m_notesModels.value(index.row());
if (notesModel == nullptr)
m_documentProvider->loadPage(index.row());
auto modelLoading = notesModel == nullptr || notesModel->isLoading();
switch (role) {
......@@ -89,7 +86,6 @@ void PagesWithNotesModel::_addPage(int pageIndex)
{
if (m_documentProvider == nullptr)
return;
auto page = m_documentProvider->loadPage(pageIndex);
if (!page)
return;
......@@ -110,6 +106,5 @@ void PagesWithNotesModel::_addPage(int pageIndex)
notesModel->setPageSource(page);
m_notesModels.insert(pageIndex, notesModel);
}
emit dataChanged(index(pageIndex), index(pageIndex), { LoadingRole });
}
......@@ -32,6 +32,7 @@ PdfDocumentItem::PdfDocumentItem(QObject *parent)
qRegisterMetaType<QHash<int, QSizeF>>();
m_status = DocumentStatus::Null;
m_pageTextsModel = new PdfPageTexts(this);
}
PdfDocumentItem::~PdfDocumentItem()
......@@ -129,14 +130,14 @@ QSharedPointer<BasePage> PdfDocumentItem::loadPage(int pageIndex)
m_pagesInProcess.insert(pageIndex);
auto *pageLoadingWatcher = new QFutureWatcher<QSharedPointer<PdfPage>>();
connect(pageLoadingWatcher, &QFutureWatcher<QSharedPointer<PdfPage>>::finished,
this, [pageLoadingWatcher, pageIndex, this] () {
m_loadedPages.insert(pageIndex, QSharedPointer<BasePage>(
new PdfPageItem(m_pdfiumDocument->page(pageIndex))));
emit pageLoaded(pageIndex, PageLoadStatus::Success);
pageLoadingWatcher->deleteLater();
});
connect(pageLoadingWatcher, &QFutureWatcher<QSharedPointer<PdfPage>>::finished,
this, [pageLoadingWatcher, pageIndex, this] () {
m_loadedPages.insert(pageIndex, QSharedPointer<BasePage>(
new PdfPageItem(m_pdfiumDocument->page(pageIndex))));
pageTextsModel()->addPage(pageIndex, m_loadedPages.value(pageIndex)->text());
emit pageLoaded(pageIndex, PageLoadStatus::Success);
pageLoadingWatcher->deleteLater();
});
pageLoadingWatcher->setFuture(m_pdfiumDocument->page(pageIndex));
return { };
......@@ -147,29 +148,29 @@ void PdfDocumentItem::startLoadBookmarks() const
auto *bookmarksWatcher = new QFutureWatcher<QVector<PdfBookmark>>();
connect(bookmarksWatcher, &QFutureWatcher<QVector<PdfBookmark>>::finished,
this, [bookmarksWatcher, ctx = const_cast<PdfDocumentItem *>(this)]() {
if (bookmarksWatcher == nullptr)
return;
if (bookmarksWatcher == nullptr)
return;
if (bookmarksWatcher->isFinished() && !bookmarksWatcher->isCanceled()) {
auto bookmarks = bookmarksWatcher->result();
if (bookmarks.isEmpty()) {
bookmarksWatcher->deleteLater();
return;
}
if (bookmarksWatcher->isFinished() && !bookmarksWatcher->isCanceled()) {
auto bookmarks = bookmarksWatcher->result();
if (bookmarks.isEmpty()) {
bookmarksWatcher->deleteLater();
return;
}
qDeleteAll(ctx->m_baseBookmarks);
ctx->m_baseBookmarks.clear();
qDeleteAll(ctx->m_baseBookmarks);
ctx->m_baseBookmarks.clear();
for (const auto &bookmark : bookmarks) {
ctx->m_baseBookmarks.push_back(new BaseBookmark{ bookmark.title, bookmark.page,
bookmark.level, bookmark.locationInPage
});
}
for (const auto &bookmark : bookmarks) {
ctx->m_baseBookmarks.push_back(new BaseBookmark{ bookmark.title, bookmark.page,
bookmark.level, bookmark.locationInPage
});
}
emit ctx->bookmarksLoaded();
}
emit ctx->bookmarksLoaded();
}
bookmarksWatcher->deleteLater();
bookmarksWatcher->deleteLater();
});
bookmarksWatcher->setFuture(m_pdfiumDocument->bookmarks());
}
......@@ -190,7 +191,7 @@ QVector<BaseWord *> PdfDocumentItem::foundPhrases() {
void PdfDocumentItem::findPhrase(QString phrase)
{
auto *searchWatcher = new QFutureWatcher<QVector<QSharedPointer<PdfWord>>>();
auto *searchWatcher = new QFutureWatcher<PdfPageTexts*>();
connect(this, &PdfDocumentItem::searchCanceled, searchWatcher, &QFutureWatcher<QVector<QSharedPointer<PdfWord>>>::cancel);
connect(searchWatcher, &QFutureWatcher<QVector<QSharedPointer<PdfWord>>>::finished,
this, [searchWatcher, phrase, ctx = const_cast<PdfDocumentItem *>(this)]() {
......@@ -199,7 +200,7 @@ void PdfDocumentItem::findPhrase(QString phrase)
QVector<BaseWord*> phrases;
if (searchWatcher->isFinished() && !searchWatcher->isCanceled()) {
auto foundPhrases = searchWatcher->result();
auto foundPhrases = searchWatcher->result()->phrasesForModel();
if (foundPhrases.isEmpty()) {
ctx->updateTextSearchResult(phrases, phrase);
......@@ -220,14 +221,13 @@ void PdfDocumentItem::findPhrase(QString phrase)
ctx->removeCanceledSearchResult(phrase);
searchWatcher->deleteLater();
});
searchWatcher->setFuture(m_pdfiumDocument->searchPhrase(phrase));
searchWatcher->setFuture(m_pdfiumDocument->searchPhrase(phrase, m_pageTextsModel));
}
void PdfDocumentItem::updateTextSearchResult(const QVector<BaseWord *>& phrases, const QString phraseToFind)
{
m_foundPhrases.clear();
m_foundPhrases.append(phrases);
emit BasePdfDocument::phraseFound(m_foundPhrases, phraseToFind);
}
......@@ -274,22 +274,22 @@ void PdfDocumentItem::startLoadUserBookmarks() const
auto *bookmarksWatcher = new QFutureWatcher<QVector<UserPdfBookmark>>();
connect(bookmarksWatcher, &QFutureWatcher<QVector<UserPdfBookmark>>::finished,
this, [bookmarksWatcher, ctx = const_cast<PdfDocumentItem *>(this)]() {
if (bookmarksWatcher == nullptr)
return;
if (bookmarksWatcher == nullptr)
return;
if (bookmarksWatcher->isFinished() && !bookmarksWatcher->isCanceled()) {
auto bookmarks = bookmarksWatcher->result();
if (bookmarksWatcher->isFinished() && !bookmarksWatcher->isCanceled()) {
auto bookmarks = bookmarksWatcher->result();
qDeleteAll(ctx->m_userBookmarks);
ctx->m_userBookmarks.clear();
qDeleteAll(ctx->m_userBookmarks);
ctx->m_userBookmarks.clear();
for (const auto &bookmark : bookmarks) {
ctx->m_userBookmarks.push_back(new UserBookmark{bookmark.page, bookmark.text});
}
for (const auto &bookmark : bookmarks) {
ctx->m_userBookmarks.push_back(new UserBookmark{bookmark.page, bookmark.text});
}
emit ctx->userBookmarksLoaded();
}
bookmarksWatcher->deleteLater();
emit ctx->userBookmarksLoaded();
}
bookmarksWatcher->deleteLater();
});
bookmarksWatcher->setFuture(m_pdfiumDocument->userBookmarks(m_fileName));
}
......@@ -480,6 +480,11 @@ QSharedPointer<PdfDocument> PdfDocumentItem::document()
return m_pdfiumDocument;
}
PdfPageTexts *PdfDocumentItem::pageTextsModel()
{
return m_pageTextsModel;
}
bool PdfDocumentItem::saveDocumentAs(const QString &path) const
{
if (!m_pdfiumDocument)
......
......@@ -10,6 +10,7 @@
#include <QSet>
#include <QVector>
#include <QPointer>
#include <amberpdf/pdfpagetexts.h>
#include <amberpdf/pdfword.h>
#include <baseword.h>
......@@ -17,6 +18,7 @@
#include "pdfpageitem.h"
#include "pagepreloader.h"
class PdfPageTexts;
class PdfPage;
class PdfDocument;
class PdfDocumentItem : public BasePdfDocument
......@@ -46,6 +48,7 @@ public:
void generateFileName() override;
void refreshBookmarksFile(const QString &filePath) override;
QSharedPointer<PdfDocument> document() override;
PdfPageTexts* pageTextsModel();
public slots:
void setPath(const QString &path) override;
......@@ -74,6 +77,7 @@ private:
bool m_refreshingBookmarksFile = false;
QVector<BaseWord *> m_foundPhrases;
QPointer<PagePreloader> m_preloaderAllPage;
PdfPageTexts* m_pageTextsModel;
};
#endif // PDFDOCUMENTITEM_H
......@@ -245,6 +245,11 @@ int PdfPageItem::pageNumber() const
return m_amberPage ? m_amberPage->pageNumber() : -1;
}
QString PdfPageItem::text()
{
return m_amberPage->text();
}
QFuture<QSizeF> PdfPageItem::originalSize()
{
return m_amberPage ? m_amberPage->originalSize() : QFuture<QSizeF>();
......
......@@ -22,6 +22,7 @@ public:
void loadAnnotations() override;
bool isAnnotationsSupport() const override;
int pageNumber() const override;
QString text() override;
QFuture<QSizeF> originalSize() override;
QFuture<QImage> bitmapFull(qreal pageScale, int renderFlags = 0) const override;
QFuture<QSharedPointer<QImage>> bitmapPart(qreal pageScaleX, qreal pageScaleY,
......
......@@ -9,6 +9,8 @@
#include "pdfsimplenote.h"
#define TEXT_SEARCH_AUTHOR "TEXT_SEARCH"
PdfSimpleNote::PdfSimpleNote(QQuickItem *parent, QSharedPointer<BaseAnnotation> source) : QQuickItem(parent),
m_highlighted(false),
m_needUpdateImage(false),
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать