Коммит 8b732849 создал по автору a.begichev's avatar a.begichev 🤡
Просмотр файлов

[Search] Search word in document and and highlighting of found words.

владелец ea5fe99b
......@@ -23,6 +23,7 @@ Rectangle {
property alias contentX: viewFlick.contentX
property alias contentY: viewFlick.contentY
property alias bookmarksModel: pdfView.bookmarksModel
property alias searchPhraseModel: pdfView.searchPhraseModel
property alias fileVersion: pdfView.fileVersion
property alias documentEdited: pdfView.documentEdited
property alias pagesWithNotesModel: pdfView.pagesWithNotesModel
......@@ -71,6 +72,10 @@ Rectangle {
function editNote(pageIndex, noteIndex, newColor, newContent) {
pdfView.editNote(pageIndex, noteIndex, newContent, newColor)
}
function findPhrase(str) {
pdfView.findPhrase(str);
}
color: "transparent"
data: [
......
......@@ -27,6 +27,7 @@ public:
QPointF pageCoordinate;
QColor color{Qt::white};
int annotationId;
bool isSearchResult;
};
#endif // BASEANNOTATION_H
......@@ -5,7 +5,9 @@
#define BASEDOCUMENT_H
#include <QObject>
#include <QMap>
#include <QSharedPointer>
#include <baseword.h>
class BasePage;
class BaseBookmark;
......@@ -47,6 +49,8 @@ public:
virtual QVector<BaseBookmark *> bookmarks() const = 0;
virtual int fileVersion() const = 0;
virtual bool saveDocumentAs(const QString &path) const = 0;
virtual void findPhrase(QString phrase) = 0;
virtual QVector<BaseWord *> foundPhrases() = 0;
public slots:
virtual void setPath(const QString &path) = 0;
......@@ -57,6 +61,7 @@ signals:
void pageLoaded(int pageNumber, PageLoadStatus loadStatus);
void bookmarksLoaded();
void fileVersionChanged(int version);
void phraseFound(QVector<BaseWord *> phrases, QString phraseToFind);
protected:
DocumentStatus m_status;
......
......@@ -29,7 +29,9 @@ public:
const QPointF &bias = QPointF()) const = 0;
virtual void addAnnotation(const QRectF &rect, const QColor &color,
const QString &author, const QString &content) = 0;
virtual void addSearchResultAnnotation(const QRectF &rect, const QString &content) = 0;
virtual void removeAnnotation(int annotationId) = 0;
virtual void removeSearchResultAnnotations() = 0;
virtual void editNote(int noteId, const QString &newContent, const QColor &newColor) = 0;
signals:
......
// SPDX-FileCopyrightText: 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef BASEWORD_H
#define BASEWORD_H
#include <QPointF>
#include <QRectF>
#include <QString>
struct BaseWord
{
QString value;
int pageIndex {-1};
QRectF rect;
BaseWord(QString value, int pageIndex, QRectF rect) {
this->value = value;
this->pageIndex = pageIndex;
this->rect = rect;
}
};
#endif // BASEWORD_H
......@@ -7,10 +7,16 @@
#include <QThreadPool>
#include <QVector>
#include <QPair>
#include <pdfannotation.h>
#include <amberpdf/pdfdocument.h>
#include <amberpdf/pdfbookmark.h>
#include <pdfpharsesearchworker.h>
#include <baseannotation.h>
#include <pdfpharsehighlighter.h>
#include <QMap>
#include "pagessizesloader.h"
#include "pagepreloader.h"
#include "basepage.h"
......@@ -166,6 +172,42 @@ int PdfDocumentItem::fileVersion() const
return (m_pdfiumDocument.isNull() ? -1 : m_pdfiumDocument->fileVersion());
}
QVector<BaseWord *> PdfDocumentItem::foundPhrases() {
return m_foundPhrases;
}
void PdfDocumentItem::findPhrase(QString phrase)
{
auto phraseSearchWorker = new PdfPhraseSearchWorker(m_pdfiumDocument, phrase);
connect(phraseSearchWorker, &PdfPhraseSearchWorker::done, this, &PdfDocumentItem::updateTextSearchResult);
QThreadPool::globalInstance()->start(phraseSearchWorker);
}
void PdfDocumentItem::updateTextSearchResult(QVector<BaseWord *> phrases, QString phraseToFind) {
QMap<int, QList<BaseWord*>> pagesWithContent;
foreach (BaseWord *previosFoundWord, m_foundPhrases) {
if (!pagesWithContent.contains(previosFoundWord->pageIndex)){
pagesWithContent[previosFoundWord->pageIndex] = QList<BaseWord*>();
}
}
foreach (BaseWord *foundWord, phrases) {
if (!pagesWithContent.contains(foundWord->pageIndex)) {
pagesWithContent[foundWord->pageIndex] = QList<BaseWord*>();
}
pagesWithContent[foundWord->pageIndex].append(foundWord);
}
m_foundPhrases.clear();
m_foundPhrases.append(phrases);
auto pdfPhraseHighlighter = new PdfPhraseHighlighter(m_pdfiumDocument, pagesWithContent);
connect(pdfPhraseHighlighter, &PdfPhraseHighlighter::done, this, [this, phraseToFind](){
emit BasePdfDocument::phraseFound(m_foundPhrases, phraseToFind);
});
QThreadPool::globalInstance()->start(pdfPhraseHighlighter);
}
bool PdfDocumentItem::saveDocumentAs(const QString &path) const
{
if (!m_pdfiumDocument)
......
......@@ -10,6 +10,8 @@
#include <QSet>
#include <QVector>
#include <QPointer>
#include <pdfword.h>
#include <baseword.h>
#include "basedocument.h"
#include "pdfpageitem.h"
......@@ -33,11 +35,15 @@ public:
void startLoadBookmarks() const override;
QVector<BaseBookmark *> bookmarks() const override;
int fileVersion() const override;
bool saveDocumentAs(const QString &path) const override;
bool saveDocumentAs(const QString &path) const override;
void findPhrase(QString phrase) override;
QVector<BaseWord *> foundPhrases() override;
public slots:
void setPath(const QString &path) override;
private slots:
void updateTextSearchResult(QVector<BaseWord *> phrases, QString phraseToFind);
private:
void onPagePreloaderDone(int loadedPageIndex, PageLoadStatus loadStatus);
......@@ -47,6 +53,7 @@ private:
QHash<int, QSharedPointer<BasePage>> m_loadedPages;
QSet<int> m_pagesInProcess;
QVector<BaseBookmark *> m_baseBookmarks;
QVector<BaseWord *> m_foundPhrases;
QPointer<PagePreloader> m_preloaderAllPage;
};
......
......@@ -48,7 +48,8 @@
PdfPageItem::PdfPageItem(QSharedPointer<PdfPage> amberPage, QObject *parent) : BasePage(parent),
m_amberPage(amberPage)
{ }
{
}
PdfPageItem::~PdfPageItem()
{
......@@ -94,6 +95,7 @@ void PdfPageItem::loadAnnotations()
baseAnnotation->linkToPage = pdfAnnotation->linkToPage();
baseAnnotation->pageCoordinate = pdfAnnotation->linkPosition();
baseAnnotation->content = pdfAnnotation->uri();
baseAnnotation->isSearchResult = false;
}
if (pdfAnnotation->type() == PdfAnnotation::Highlight || pdfAnnotation->type() == PdfAnnotation::Text) {
......@@ -101,6 +103,8 @@ void PdfPageItem::loadAnnotations()
baseAnnotation->type = BaseAnnotation::AnnotationType::HighLight;
baseAnnotation->author = pdfAnnotation->values().value(
pdfAnnotation->annotationKeyToQString(PdfAnnotation::T)).toString();
if (baseAnnotation->author != nullptr)
baseAnnotation->isSearchResult = baseAnnotation->author == PdfAnnotation::TEXT_SEARCH_AUTHOR_NAME;
baseAnnotation->content = pdfAnnotation->values().value(
pdfAnnotation->annotationKeyToQString(PdfAnnotation::Contents)).toString();
......@@ -145,9 +149,7 @@ void PdfPageItem::loadAnnotations()
m_annotations.append(baseAnnotation);
}
}
if (!m_annotations.isEmpty())
emit annotationsLoaded();
emit annotationsLoaded();
}
watcher->deleteLater();
......@@ -201,6 +203,27 @@ void PdfPageItem::addAnnotation(const QRectF &rect, const QColor &color, const Q
watcher->setFuture(future);
}
void PdfPageItem::addSearchResultAnnotation(const QRectF &rect, const QString &content) {
if (!m_amberPage)
return;
auto *watcher = new QFutureWatcher<bool>();
connect(watcher, &QFutureWatcher<bool>::finished, this, [this, watcher]() {
if (watcher == nullptr)
return;
if (watcher->isFinished() && !watcher->isCanceled())
emit annotationAdded(true);
else
emit annotationAdded(false);
watcher->deleteLater();
});
auto future = m_amberPage->addSearchResultAnnotation(rect, content);
watcher->setFuture(future);
}
void PdfPageItem::removeAnnotation(int annotationId)
{
if (!m_amberPage)
......@@ -220,6 +243,23 @@ void PdfPageItem::removeAnnotation(int annotationId)
watcher->setFuture(m_amberPage->removeAnnotation(annotationId));
}
void PdfPageItem::removeSearchResultAnnotations()
{
if (!m_amberPage)
return;
auto *watcher = new QFutureWatcher<bool>();
connect(watcher, &QFutureWatcher<bool>::finished, this, [this, watcher]() {
if (watcher == nullptr)
return;
if (watcher->isFinished() && !watcher->isCanceled())
emit annotationDelete(-1, watcher->result());
else
emit annotationDelete(-1, false);
});
watcher->setFuture(m_amberPage->removeTextSearchResult());
}
void PdfPageItem::editNote(int noteId, const QString &newContent, const QColor &newColor)
{
BaseAnnotation *annotationToEdit = nullptr;
......
......@@ -29,7 +29,10 @@ public:
const QPointF &bias = QPointF()) const override;
void addAnnotation(const QRectF &rect, const QColor &color,
const QString &author, const QString &content) override;
void addSearchResultAnnotation(const QRectF &rect, const QString &content) override;
void removeAnnotation(int annotationId) override;
void removeSearchResultAnnotations() override;
void editNote(int noteId, const QString &newContent, const QColor &newColor) override;
private:
......
......@@ -34,7 +34,6 @@ PdfPageContainer::PdfPageContainer(QQuickItem *parent)
, m_fitToPage(true)
{
setFlag(QQuickItem::ItemHasContents, true);
auto itemWindow = window();
if (itemWindow != nullptr)
connect(itemWindow, &QQuickWindow::beforeSynchronizing, this, &PdfPageContainer::_updateVisible, Qt::DirectConnection);
......@@ -114,6 +113,11 @@ bool PdfPageContainer::checked() const
return m_checked;
}
void PdfPageContainer::loadAnnotations()
{
m_pageSource->loadAnnotations();
}
void PdfPageContainer::setPageSource(QSharedPointer<BasePage> pageSource)
{
if (!pageSource)
......@@ -224,6 +228,14 @@ bool PdfPageContainer::annotationsPaint() const
return m_annotationsPaint;
}
void PdfPageContainer::setTextResultSearchVisible(bool isVisible)
{
for (auto &annotation : m_notesItems) {
annotation->setVisible(isVisible);
}
}
bool PdfPageContainer::notesPaint() const
{
return m_notesPaint;
......@@ -599,6 +611,7 @@ void PdfPageContainer::_loadAnnotations()
continue;
}
}
emit pageChanged();
}
void PdfPageContainer::_prepareBackgroundPage()
......
......@@ -39,6 +39,7 @@ public:
Qt::Orientation orientation() const;
qreal scale() const;
bool checked() const;
void loadAnnotations();
void setPageSource(QSharedPointer<BasePage> pageSource);
void setPageGeometry(const PageGeometry &pg);
int index() const;
......@@ -54,6 +55,7 @@ public:
void removeNote(int noteId);
void editNote(int noteId, const QString &newContent, const QColor &newColor);
void setTextResultSearchVisible(bool isVisible);
public slots:
void setRequestedSize(QSizeF requestedSize);
void setOrientation(Qt::Orientation orientation);
......
// SPDX-FileCopyrightText: 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#include "pdfpharsehighlighter.h"
PdfPhraseHighlighter::PdfPhraseHighlighter(QSharedPointer<PdfDocument> pdfiumDocument, QMap<int, QList<BaseWord*>> pagesToRehighlight)
{
this->m_pagesToRehighlight = pagesToRehighlight;
m_pdfiumDocument = pdfiumDocument;
}
void PdfPhraseHighlighter::run()
{
for (QMap<int, QList<BaseWord*>>::const_iterator it = m_pagesToRehighlight.cbegin(), end = m_pagesToRehighlight.cend(); it != end; ++it) {
auto page = m_pdfiumDocument->page(it.key()).result();
page->removeTextSearchResult().waitForFinished();
foreach (BaseWord * phrase, it.value()) {
page->addSearchResultAnnotation(phrase->rect, phrase->value);
}
}
emit done();
}
// SPDX-FileCopyrightText: 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef PDFPHARSEHIGHLIGHTER_H
#define PDFPHARSEHIGHLIGHTER_H
#include <QObject>
#include <QRunnable>
#include <baseword.h>
#include <pdfdocument.h>
#include <pdfdocumentitem.h>
class PdfPhraseHighlighter : public QObject, public QRunnable
{
Q_OBJECT
public:
PdfPhraseHighlighter(QSharedPointer<PdfDocument> pdfiumDocument, QMap<int, QList<BaseWord*>> pagesToRehighlight);
void run() override;
signals:
void done();
private:
QMap<int, QList<BaseWord*>> m_pagesToRehighlight;
QSharedPointer<PdfDocument> m_pdfiumDocument;
};
#endif // PDFPHARSEHIGHLIGHTER_H
// SPDX-FileCopyrightText: 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#include "pdfpharsesearchworker.h"
PdfPhraseSearchWorker::PdfPhraseSearchWorker(QSharedPointer<PdfDocument> document, QString phrase)
{
this->m_document = document;
this->m_phrase = phrase;
}
void PdfPhraseSearchWorker::run()
{
QVector<BaseWord*> phrasesForModel;
for (int i = 0; i < m_document->pageCount(); i++ ) {
auto page = m_document->page(i);
page.waitForFinished();
auto wordsF = page.result()->words();
wordsF.waitForFinished();
auto words = wordsF.result();
foreach (QObject *word, words) {
PdfWord* casted = (PdfWord*)word;
if ((casted)->value().toLower().trimmed() == m_phrase.toLower().trimmed()) {
(casted)->setIndex(i);
phrasesForModel.append(new BaseWord(casted->value(), casted->index(), casted->rect()));
}
}
}
emit done(phrasesForModel, m_phrase);
}
// SPDX-FileCopyrightText: 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef PDFPHARSESEARCHWORKER_H
#define PDFPHARSESEARCHWORKER_H
#include <QObject>
#include <QRunnable>
#include <baseword.h>
#include <pdfdocument.h>
#include <pdfdocumentitem.h>
class PdfPhraseSearchWorker : public QObject, public QRunnable
{
Q_OBJECT
public:
PdfPhraseSearchWorker(QSharedPointer<PdfDocument> pdfiumDocument, QString phrase);
void run() override;
signals:
void done(QVector<BaseWord *>, QString);
private:
QSharedPointer<PdfDocument> m_document;
QString m_phrase;
};
#endif // PDFPHARSESEARCHWORKER_H
// SPDX-FileCopyrightText: 2022-2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-FileCopyrightText: 2022-2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#include <QQuickWindow>
#include <QTimer>
#include <QFutureWatcher>
#include <pdfword.h>
#include <pdfpharsesearchworker.h>
#include <pdfdocumentitem.h>
#include <QtConcurrent/QtConcurrent>
#include "basedocument.h"
......@@ -15,6 +18,13 @@
#include "pdfview.h"
namespace
{
void deleteQuickItem(QQuickItem *item) {
item->deleteLater();
}
}
PdfView::PdfView(QQuickItem *parent)
: QQuickItem(parent)
, m_count(-1)
......@@ -41,6 +51,7 @@ PdfView::PdfView(QQuickItem *parent)
, m_specialPagesCount(-1)
, m_pageSpacing(SPACING_DEFAULT_VALUE)
, m_fitToPage(true)
, m_searchPhraseModel(nullptr)
{
setFlag(QQuickItem::ItemHasContents, true);
setFlag(QQuickItem::ItemAcceptsInputMethod, true);
......@@ -92,7 +103,7 @@ void PdfView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeomet
return;
for (auto paintItem : m_pages) {
auto *page = qobject_cast<PdfPageContainer *>(paintItem);
auto *page = qobject_cast<PdfPageContainer *>(paintItem.data());
if (page == nullptr)
continue;
......@@ -226,11 +237,20 @@ BookmarksModel *PdfView::bookmarksModel() const
return m_bookmarksModel;
}
PdfWordModel *PdfView::searchPhraseModel() const
{
return m_searchPhraseModel;
}
int PdfView::fileVersion() const
{
return m_documentProvider == nullptr ? -1 : m_documentProvider->fileVersion();
}
void PdfView::findPhrase(QString phrase)
{
m_documentProvider->findPhrase(phrase);
}
void PdfView::saveDocumentAs(const QString &path)
{
auto *watcher = new QFutureWatcher<bool>();
......@@ -261,22 +281,25 @@ void PdfView::addAnnotation(const QRectF &rect, const QColor &color, const QStri
auto pagePosition = m_mapper->actualPagePosition(page);
if (m_orientation == Qt::Vertical) {
if (rect.y() >= pagePosition.start && rect.y() <= pagePosition.end) {
if (!m_pages.contains(page))
if (!m_pages.contains(page)) {
return;
}
QRectF localRect(rect);
localRect.setY(rect.y() - pagePosition.start);
localRect.setHeight(rect.height());
localRect.setWidth(rect.width());
auto pageContainer = qobject_cast<PdfPageContainer *>(m_pages.value(page));
connect(pageContainer.data(), &PdfPageContainer::pageChanged, this, &PdfView::annotationAdded);
pageContainer->addAnnotation(localRect, color, author, content);
return;
}
} else {
if (rect.x() > pagePosition.start && rect.x() <= pagePosition.end) {
if (!m_pages.contains(page))
if (!m_pages.contains(page)) {
return;
}
QRectF localRect(rect);
localRect.setX(rect.x() - pagePosition.start);
......@@ -284,7 +307,9 @@ void PdfView::addAnnotation(const QRectF &rect, const QColor &color, const QStri
localRect.setWidth(rect.width());
auto pageContainer = qobject_cast<PdfPageContainer *>(m_pages.value(page));
connect(pageContainer.data(), &PdfPageContainer::pageChanged, this, &PdfView::annotationAdded);
pageContainer->addAnnotation(localRect, color, author, content);
return;
}
}
......@@ -588,6 +613,26 @@ void PdfView::setDocumentProvider(BasePdfDocument *documentProvider)
emit statusChanged(BasePdfDocument::DocumentStatus::Null);
if (m_searchPhraseModel != nullptr) {
m_searchPhraseModel->deleteLater();
m_searchPhraseModel = nullptr;
}
m_searchPhraseModel = new PdfWordModel(this);
connect(m_documentProvider,
&PdfDocumentItem::phraseFound,
this,
[&](QVector<BaseWord *> words, QString phrase) {
m_searchPhraseModel->setNewData(phrase, words);
emit searchPhraseModelChanged(m_searchPhraseModel);
for (QHash<int, QSharedPointer<QQuickItem>>::const_iterator it = m_pages.cbegin(), end = m_pages.cend(); it != end; ++it) {
auto pageContainer = qobject_cast<PdfPageContainer *>(it.value());
connect(pageContainer.data(), &PdfPageContainer::pageChanged, this, [pageContainer](){
pageContainer->setTextResultSearchVisible(true);
});
pageContainer->loadAnnotations();
}
});
if (m_pagesWithNotesModel != nullptr) {
m_pagesWithNotesModel->deleteLater();
m_pagesWithNotesModel = nullptr;
......@@ -851,7 +896,7 @@ void PdfView::_positionPages()
maxSize = qMax(maxSize, float(page->width()));
if (!qFuzzyCompare(float(m_contentTopMargin), paintStart)) {
if (!qFuzzyCompare(double(m_contentTopMargin), paintStart)) {
m_contentTopMargin = paintStart;
emit contentTopMarginChanged(m_contentTopMargin);
}
......@@ -1022,20 +1067,16 @@ void PdfView::_calculateVisible()
std::sort(m_paintedPages.begin(), m_paintedPages.end());
if (!m_pageCheckComponent) {
QMutableHashIterator<int, QQuickItem *> pagesCheckerIt(m_pageCheckerItems);
QMutableHashIterator<int, QSharedPointer<QQuickItem>> pagesCheckerIt(m_pageCheckerItems);
while (pagesCheckerIt.hasNext()) {
pagesCheckerIt.next();
if (!pagesCheckerIt.value()) {
pagesCheckerIt.remove();
continue;
}
pagesCheckerIt.value()->deleteLater();
pagesCheckerIt.remove();
}
}
QMutableHashIterator<int, QQuickItem *> pagesIt(m_pages);
auto copiesPages = m_pages;
auto copiesCheckerItems = m_pageCheckerItems;
QMutableHashIterator<int, QSharedPointer<QQuickItem>> pagesIt(copiesPages);
while (pagesIt.hasNext()) {
pagesIt.next();
......@@ -1045,17 +1086,18 @@ void PdfView::_calculateVisible()
}
if (!m_paintedPages.contains(pagesIt.key())) {
pagesIt.value()->deleteLater();
pagesIt.remove();
//pagesIt.remove();
// just erase because page is checker's parent
auto checkerIt = m_pageCheckerItems.find(pagesIt.key());
if (checkerIt != m_pageCheckerItems.end())
m_pageCheckerItems.erase(checkerIt);
auto checkerIt = copiesCheckerItems.find(pagesIt.key());
if (checkerIt != copiesCheckerItems.end())
copiesCheckerItems.erase(checkerIt);
}
}
m_pages = copiesPages;
m_pageCheckerItems = copiesCheckerItems;
QMutableHashIterator<int, QQuickItem *> pagesNumberIt(m_pageNumberItems);
QMutableHashIterator<int, QSharedPointer<QQuickItem>> pagesNumberIt(m_pageNumberItems);
while (pagesNumberIt.hasNext()) {
pagesNumberIt.next();
......@@ -1262,7 +1304,7 @@ void PdfView::_preparePages()
}
}
_preparePageChecker(pageContainer, pageIndex);
_preparePageChecker(pageContainer.data(), pageIndex);
continue;
}
......@@ -1302,7 +1344,7 @@ void PdfView::_preparePages()
if (pageSource)
page->setPageSource(pageSource);
m_pages.insert(pageIndex, page);
m_pages.insert(pageIndex, QSharedPointer<QQuickItem>(page, deleteQuickItem));
if (m_pageNumberComponent && !m_pageNumberItems.keys().contains(pageIndex)) {
QString pageNumber = QString::number(pageIndex + 1);
......@@ -1312,7 +1354,7 @@ void PdfView::_preparePages()
pageNumberItem->setScale(m_itemScale);
pageNumberItem->setVisible(true);
pageNumberItem->setParentItem(this);
m_pageNumberItems.insert(pageIndex, pageNumberItem);
m_pageNumberItems.insert(pageIndex, QSharedPointer<QQuickItem>(pageNumberItem, deleteQuickItem));
}
}
......@@ -1333,10 +1375,10 @@ void PdfView::_preparePageChecker(PdfPageContainer *page, int pageIndex)
auto isCheck = m_mapper->isIndexSpecal(pageIndex);
QQuickItem *pageCheckerItem = nullptr;
if (m_pageCheckerItems.keys().contains(pageIndex))
pageCheckerItem = m_pageCheckerItems.value(pageIndex);
pageCheckerItem = m_pageCheckerItems.value(pageIndex).data();
else {
pageCheckerItem = qobject_cast<QQuickItem *>(m_pageCheckComponent->create());
m_pageCheckerItems.insert(pageIndex, pageCheckerItem);
m_pageCheckerItems.insert(pageIndex, QSharedPointer<QQuickItem>(pageCheckerItem, deleteQuickItem));
}
if (pageCheckerItem) {
......
......@@ -5,6 +5,8 @@
#define PDFVIEW_H
#include <QQuickItem>
#include <QSharedPointer>
#include "pdfwordmodel.h"
#include "basedocument.h"
......@@ -38,6 +40,7 @@ class PdfView : public QQuickItem
Q_PROPERTY(BasePdfDocument::DocumentStatus status READ status NOTIFY statusChanged)
Q_PROPERTY(qreal contentTopMargin READ contentTopMargin NOTIFY contentTopMarginChanged)
Q_PROPERTY(BookmarksModel* bookmarksModel READ bookmarksModel NOTIFY bookmarksModelChanged)
Q_PROPERTY(PdfWordModel* searchPhraseModel READ searchPhraseModel NOTIFY searchPhraseModelChanged)
Q_PROPERTY(int fileVersion READ fileVersion NOTIFY fileVersionChanged)
Q_PROPERTY(bool documentEdited READ documentEdited NOTIFY documentEditedChanged)
Q_PROPERTY(PagesWithNotesModel* pagesWithNotesModel READ pagesWithNotesModel NOTIFY pagesWithNotesModelChanged)
......@@ -83,7 +86,9 @@ public:
BasePdfDocument::DocumentStatus status() const;
qreal contentTopMargin() const;
BookmarksModel *bookmarksModel() const;
PdfWordModel *searchPhraseModel() const;
int fileVersion() const;
Q_INVOKABLE void findPhrase(QString phrase);
Q_INVOKABLE void saveDocumentAs(const QString &path);
bool documentEdited() const;
......@@ -137,6 +142,7 @@ signals:
void contentYChanged(qreal contentY);
void contentXChanged(qreal contentX);
void loadPages();
void annotationAdded();
void currentIndexChanged(int currentIndex);
void catchBoundChanged(qreal catchBound);
void contentChanged();
......@@ -154,6 +160,7 @@ signals:
void statusChanged(BasePdfDocument::DocumentStatus status);
void contentTopMarginChanged(qreal contentTopMargin);
void bookmarksModelChanged(BookmarksModel *bookmarksModel);
void searchPhraseModelChanged(PdfWordModel *searchTextModel);
void fileVersionChanged(int fileVersion);
void documentSaved(bool saveStatus);
void documentEditedChanged(bool documentEdited);
......@@ -200,7 +207,7 @@ private:
qreal m_contentY;
qreal m_contentX;
qreal m_moveDirection;
QHash<int, QQuickItem *> m_pages;
QHash<int, QSharedPointer<QQuickItem>> m_pages;
QList<int> m_paintedPages;
QPointF m_absolutePosition;
qreal m_paintedItemsSize;
......@@ -219,18 +226,19 @@ private:
BookmarksModel *m_bookmarksModel;
bool m_documentEdited;
PagesWithNotesModel *m_pagesWithNotesModel;
QHash<int, QQuickItem *> m_pageNumberItems;
QHash<int, QSharedPointer<QQuickItem>> m_pageNumberItems;
QQmlComponent *m_pageNumberComponent;
bool m_grayScaleRendering;
qreal m_pageAspectRatio;
bool m_reverse;
QQmlComponent *m_pageCheckComponent;
QHash<int, QQuickItem *> m_pageCheckerItems;
QHash<int, QSharedPointer<QQuickItem>> m_pageCheckerItems;
qreal m_hiddenPagesOpacity;
int m_specialPagesCount;
qreal m_pageSpacing;
bool m_fitToPage;
bool m_centering;
PdfWordModel* m_searchPhraseModel;
};
#endif // PDFVIEW_H
// SPDX-FileCopyrightText: 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#include "pdfwordmodel.h"
#include <QSharedPointer>
#include <baseannotation.h>
#include <pdfpageitem.h>
PdfWordModel::PdfWordModel(QObject *parent) : QAbstractListModel(parent) { }
int PdfWordModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_data.size();
}
QString PdfWordModel::getPhrase() {
return m_phrase;
}
QVariant PdfWordModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() >= m_data.size())
return { };
const auto *word = m_data.at(index.row());
if (word == nullptr)
return { };
switch (role) {
case ValueRole : return QVariant::fromValue(word->value);
case PageIndexRole: return QVariant::fromValue(word->pageIndex);
case InRect: return QVariant::fromValue(word->rect);
}
return { };
}
QHash<int, QByteArray> PdfWordModel::roleNames() const
{
return {
{ ValueRole, "value" },
{ PageIndexRole, "phrasePageIndex" },
{ InRect, "rect" }
};
}
void PdfWordModel::setNewData(QString phrase, const QVector<BaseWord *> &newData)
{
beginResetModel();
qDeleteAll(m_data);
m_data.clear();
m_data = newData;
m_phrase = phrase;
endResetModel();
}
// SPDX-FileCopyrightText: 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef PDFWORDMODEL_H
#define PDFWORDMODEL_H
#include <QAbstractListModel>
#include <QVector>
#include <basedocument.h>
#include <baseword.h>
struct BaseWord;
class PdfWordModel : public QAbstractListModel
{
Q_OBJECT
public:
enum PagePropertyRoles
{
ValueRole = Qt::UserRole + 1,
PageIndexRole,
InRect
};
explicit PdfWordModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
void setNewData(QString phrase, const QVector<BaseWord *> &newData);
Q_INVOKABLE QString getPhrase();
private:
QVector<BaseWord *> m_data;
QString m_phrase;
};
#endif // PDFWORDMODEL_H
......@@ -33,6 +33,7 @@ public:
qmlRegisterType<PagesWithNotesModel>(uri, 1, 0, "PagesWithNotesModel");
qmlRegisterType<PageWithNotesSortModel>(uri, 1, 0, "PageWithNotesSortModel");
qmlRegisterInterface<BasePdfDocument>("BasePdfDocument");
qRegisterMetaType<QVector<BaseWord*> >("QVector<BaseWord*>");
}
};
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать