Refactoring - prepare for undo/redo and document modification

This commit is contained in:
Jakub Melka 2020-04-25 14:21:06 +02:00
parent 76af397b07
commit 57b3711210
28 changed files with 318 additions and 114 deletions

View File

@ -1185,13 +1185,17 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
}
}
void PDFAnnotationManager::setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity)
void PDFAnnotationManager::setDocument(const PDFModifiedDocument& document)
{
if (m_document != document)
{
m_document = document;
m_optionalActivity = optionalContentActivity;
m_pageAnnotations.clear();
m_optionalActivity = document.getOptionalContentActivity();
if (document.hasReset() || document.hasFlag(PDFModifiedDocument::Annotation))
{
m_pageAnnotations.clear();
}
}
}

View File

@ -44,6 +44,7 @@ class PDFObjectStorage;
class PDFDrawWidgetProxy;
class PDFFontCache;
class PDFFormManager;
class PDFModifiedDocument;
class PDFOptionalContentActivity;
using TextAlignment = Qt::Alignment;
@ -1287,7 +1288,9 @@ public:
const QMatrix& pagePointToDevicePointMatrix,
QList<PDFRenderError>& errors) const override;
void setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity);
/// Set document
/// \param document New document
void setDocument(const PDFModifiedDocument& document);
Target getTarget() const;
void setTarget(Target target);

View File

@ -57,7 +57,7 @@ void PDFAsynchronousPageCompiler::start()
}
}
void PDFAsynchronousPageCompiler::stop()
void PDFAsynchronousPageCompiler::stop(bool clearCache)
{
switch (m_state)
{
@ -75,7 +75,11 @@ void PDFAsynchronousPageCompiler::stop()
taskItem.second.taskWatcher->waitForFinished();
}
m_tasks.clear();
m_cache.clear();
if (clearCache)
{
m_cache.clear();
}
m_state = State::Inactive;
break;
@ -92,7 +96,7 @@ void PDFAsynchronousPageCompiler::stop()
void PDFAsynchronousPageCompiler::reset()
{
stop();
stop(true);
start();
}
@ -291,7 +295,7 @@ void PDFAsynchronousTextLayoutCompiler::start()
}
}
void PDFAsynchronousTextLayoutCompiler::stop()
void PDFAsynchronousTextLayoutCompiler::stop(bool clearCache)
{
switch (m_state)
{
@ -303,7 +307,12 @@ void PDFAsynchronousTextLayoutCompiler::stop()
// Stop the engine
m_state = State::Stopping;
m_textLayoutCompileFutureWatcher.waitForFinished();
m_textLayouts = std::nullopt;
if (clearCache)
{
m_textLayouts = std::nullopt;
}
m_state = State::Inactive;
break;
}
@ -319,7 +328,7 @@ void PDFAsynchronousTextLayoutCompiler::stop()
void PDFAsynchronousTextLayoutCompiler::reset()
{
stop();
stop(true);
start();
}

View File

@ -48,8 +48,13 @@ public:
void start();
/// Stops the engine and all underlying asynchronous tasks. Also
/// clears the cache. Call this function only if engine is active.
void stop();
/// clears the cache if needed. Call this function only if engine is active.
/// Cache is cleared only, if \p clearCache parameter is being set to true.
/// Set it to false, if "soft" document update occurs (this means change
/// to the document, which doesn't modify page content in precompiled
/// pages (graphic content / number of pages change).
/// \param clearCache Clear cache
void stop(bool clearCache);
/// Resets the engine - calls stop and then calls start.
void reset();
@ -107,8 +112,12 @@ public:
void start();
/// Stops the engine and all underlying asynchronous tasks. Also
/// clears the cache. Call this function only if engine is active.
void stop();
/// clears the cache if parameter \p clearCache. Call this function
/// only if engine is active. Clear cache should be set to false,
/// only if "soft" document update appears (no text on page is being
/// changed).
/// \param clearCache Clear cache
void stop(bool clearCache);
/// Resets the engine - calls stop and then calls start.
void reset();

View File

@ -479,6 +479,59 @@ private:
PDFCatalog m_catalog;
};
/// Helper class for document updates (for example, add/delete annotations,
/// fill form fields, do some other minor operations) and also for major
/// updates (document reset). It also contains modification flags, which are
/// hints for update operations (for example, if only annotations are changed,
/// then rebuilding outline tree is not needed). At least one of the flags
/// must be set. Reset flag is conservative, so it should be set, when document
/// changes are not known.
class PDFModifiedDocument
{
public:
enum ModificationFlag
{
None = 0x0000, ///< No flag
Reset = 0x0001, ///< Whole document content is changed (for example, new document is being set)
Annotation = 0x0002, ///< Annotations changed
FormField = 0x0004, ///< Form field content changed
};
Q_DECLARE_FLAGS(ModificationFlags, ModificationFlag)
explicit inline PDFModifiedDocument() = default;
explicit inline PDFModifiedDocument(PDFDocument* document, PDFOptionalContentActivity* optionalContentActivity) :
m_document(document),
m_optionalContentActivity(optionalContentActivity),
m_flags(Reset)
{
Q_ASSERT(document);
}
explicit inline PDFModifiedDocument(PDFDocument* document, PDFOptionalContentActivity* optionalContentActivity, ModificationFlags flags) :
m_document(document),
m_optionalContentActivity(optionalContentActivity),
m_flags(flags)
{
Q_ASSERT(document);
}
PDFDocument* getDocument() const { return m_document; }
PDFOptionalContentActivity* getOptionalContentActivity() const { return m_optionalContentActivity; }
void setOptionalContentActivity(PDFOptionalContentActivity* optionalContentActivity) { m_optionalContentActivity = optionalContentActivity; }
bool hasReset() const { return m_flags.testFlag(Reset); }
bool hasFlag(ModificationFlag flag) const { return m_flags.testFlag(flag); }
operator PDFDocument*() const { return m_document; }
private:
PDFDocument* m_document = nullptr;
PDFOptionalContentActivity* m_optionalContentActivity = nullptr;
ModificationFlags m_flags = Reset;
};
// Implementation
inline

View File

@ -49,14 +49,20 @@ PDFDrawSpaceController::~PDFDrawSpaceController()
}
void PDFDrawSpaceController::setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity)
void PDFDrawSpaceController::setDocument(const PDFModifiedDocument& document)
{
if (document != m_document)
{
m_document = document;
m_fontCache.setDocument(document);
m_optionalContentActivity = optionalContentActivity;
recalculate();
m_optionalContentActivity = document.getOptionalContentActivity();
// If document is not being reset, then recalculation is not needed,
// pages should remain the same.
if (document.hasReset())
{
recalculate();
}
}
}
@ -411,14 +417,22 @@ PDFDrawWidgetProxy::~PDFDrawWidgetProxy()
}
void PDFDrawWidgetProxy::setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity)
void PDFDrawWidgetProxy::setDocument(const PDFModifiedDocument& document)
{
m_compiler->stop();
m_textLayoutCompiler->stop();
m_controller->setDocument(document, optionalContentActivity);
connect(optionalContentActivity, &PDFOptionalContentActivity::optionalContentGroupStateChanged, this, &PDFDrawWidgetProxy::onOptionalContentGroupStateChanged);
m_compiler->start();
m_textLayoutCompiler->start();
if (getDocument() != document)
{
m_compiler->stop(document.hasReset());
m_textLayoutCompiler->stop(document.hasReset());
m_controller->setDocument(document);
if (PDFOptionalContentActivity* optionalContentActivity = document.getOptionalContentActivity())
{
connect(optionalContentActivity, &PDFOptionalContentActivity::optionalContentGroupStateChanged, this, &PDFDrawWidgetProxy::onOptionalContentGroupStateChanged, Qt::UniqueConnection);
}
m_compiler->start();
m_textLayoutCompiler->start();
}
}
void PDFDrawWidgetProxy::init(PDFWidget* widget)
@ -1312,8 +1326,8 @@ void PDFDrawWidgetProxy::setFeatures(PDFRenderer::Features features)
{
if (m_features != features)
{
m_compiler->stop();
m_textLayoutCompiler->stop();
m_compiler->stop(true);
m_textLayoutCompiler->stop(true);
m_features = features;
m_compiler->start();
m_textLayoutCompiler->start();
@ -1325,7 +1339,7 @@ void PDFDrawWidgetProxy::setPreferredMeshResolutionRatio(PDFReal ratio)
{
if (m_meshQualitySettings.preferredMeshResolutionRatio != ratio)
{
m_compiler->stop();
m_compiler->stop(true);
m_meshQualitySettings.preferredMeshResolutionRatio = ratio;
m_compiler->start();
emit pageImageChanged(true, { });
@ -1336,7 +1350,7 @@ void PDFDrawWidgetProxy::setMinimalMeshResolutionRatio(PDFReal ratio)
{
if (m_meshQualitySettings.minimalMeshResolutionRatio != ratio)
{
m_compiler->stop();
m_compiler->stop(true);
m_meshQualitySettings.minimalMeshResolutionRatio = ratio;
m_compiler->start();
emit pageImageChanged(true, { });
@ -1347,7 +1361,7 @@ void PDFDrawWidgetProxy::setColorTolerance(PDFReal colorTolerance)
{
if (m_meshQualitySettings.tolerance != colorTolerance)
{
m_compiler->stop();
m_compiler->stop(true);
m_meshQualitySettings.tolerance = colorTolerance;
m_compiler->start();
emit pageImageChanged(true, { });

View File

@ -56,8 +56,7 @@ public:
/// in that case, draw space is cleared. Optional content activity can be nullptr,
/// in that case, no content is suppressed.
/// \param document Document
/// \param optionalContentActivity Optional content activity
void setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity);
void setDocument(const PDFModifiedDocument& document);
/// Sets the page layout. Page layout can be one of the PDF's page layouts.
/// \param pageLayout Page layout
@ -193,8 +192,7 @@ public:
/// in that case, draw space is cleared. Optional content activity can be nullptr,
/// in that case, no content is suppressed.
/// \param document Document
/// \param optionalContentActivity Optional content activity
void setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity);
void setDocument(const PDFModifiedDocument& document);
void init(PDFWidget* widget);

View File

@ -66,9 +66,9 @@ PDFWidget::~PDFWidget()
}
void PDFWidget::setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity)
void PDFWidget::setDocument(const PDFModifiedDocument& document)
{
m_proxy->setDocument(document, optionalContentActivity);
m_proxy->setDocument(document);
m_pageRenderingErrors.clear();
}

View File

@ -32,6 +32,7 @@ class PDFCMSManager;
class PDFToolManager;
class PDFDrawWidget;
class PDFDrawWidgetProxy;
class PDFModifiedDocument;
class PDFWidgetAnnotationManager;
class IDrawWidgetInputInterface;
@ -64,8 +65,7 @@ public:
/// in that case, widget contents are cleared. Optional content activity can be nullptr,
/// if this occurs, no content is suppressed.
/// \param document Document
/// \param optionalContentActivity Optional content activity
void setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity);
void setDocument(const PDFModifiedDocument& document);
/// Update rendering engine according the settings
/// \param engine Engine type

View File

@ -1591,14 +1591,20 @@ FontType PDFTrueTypeFont::getFontType() const
return FontType::TrueType;
}
void PDFFontCache::setDocument(const PDFDocument* document)
void PDFFontCache::setDocument(const PDFModifiedDocument& document)
{
QMutexLocker lock(&m_mutex);
if (m_document != document)
{
m_document = document;
m_fontCache.clear();
m_realizedFontCache.clear();
// Jakub Melka: If document has not reset flag, then fonts of the
// document remains the same. So it is not needed to clear font cache.
if (document.hasReset())
{
m_fontCache.clear();
m_realizedFontCache.clear();
}
}
}

View File

@ -35,6 +35,7 @@ class QPainterPath;
namespace pdf
{
class PDFDocument;
class PDFModifiedDocument;
class PDFRenderErrorReporter;
using CID = unsigned int;
@ -396,9 +397,10 @@ public:
}
/// Sets the document to the cache. Whole cache is cleared.
/// Sets the document to the cache. Whole cache is cleared,
/// if it is needed.
/// \param document Document to be setted
void setDocument(const PDFDocument* document);
void setDocument(const PDFModifiedDocument& document);
/// Retrieves font from the cache. If font can't be accessed or created,
/// then exception is thrown.

View File

@ -69,6 +69,21 @@ void PDFFormField::fillWidgetToFormFieldMapping(PDFWidgetToFormFieldMapping& map
}
}
void PDFFormField::reloadValue(const PDFObjectStorage* storage, PDFObject parentValue)
{
Q_ASSERT(storage);
if (const PDFDictionary* fieldDictionary = storage->getDictionaryFromObject(storage->getObjectByReference(getSelfReference())))
{
m_value = fieldDictionary->hasKey("V") ? fieldDictionary->get("V") : parentValue;
}
for (const PDFFormFieldPointer& childField : m_childFields)
{
childField->reloadValue(storage, m_value);
}
}
PDFFormFieldPointer PDFFormField::parse(const PDFObjectStorage* storage, PDFObjectReference reference, PDFFormField* parentField)
{
PDFFormFieldPointer result;
@ -308,23 +323,31 @@ const PDFDocument* PDFFormManager::getDocument() const
return m_document;
}
void PDFFormManager::setDocument(const PDFDocument* document)
void PDFFormManager::setDocument(const PDFModifiedDocument& document)
{
if (m_document != document)
{
m_document = document;
if (m_document)
if (document.hasReset())
{
m_form = PDFForm::parse(&m_document->getStorage(), m_document->getCatalog()->getFormObject());
}
else
{
// Clean the form
m_form = PDFForm();
}
if (m_document)
{
m_form = PDFForm::parse(&m_document->getStorage(), m_document->getCatalog()->getFormObject());
}
else
{
// Clean the form
m_form = PDFForm();
}
updateWidgetToFormFieldMapping();
updateWidgetToFormFieldMapping();
}
else if (document.hasFlag(PDFModifiedDocument::FormField))
{
// Just update field values
updateFieldValues();
}
}
}
@ -338,6 +361,17 @@ void PDFFormManager::setAppearanceFlags(FormAppearanceFlags flags)
m_flags = flags;
}
void PDFFormManager::updateFieldValues()
{
if (m_document)
{
for (const PDFFormFieldPointer& childField : m_form.getFormFields())
{
childField->reloadValue(&m_document->getStorage(), PDFObject());
}
}
}
void PDFFormManager::updateWidgetToFormFieldMapping()
{
m_widgetToFormField.clear();

View File

@ -25,9 +25,9 @@
namespace pdf
{
class PDFObjectStorage;
class PDFFormField;
class PDFObjectStorage;
class PDFModifiedDocument;
using PDFFormFieldPointer = QSharedPointer<PDFFormField>;
using PDFFormFields = std::vector<PDFFormFieldPointer>;
@ -187,6 +187,9 @@ public:
/// \param mapping Form field mapping
void fillWidgetToFormFieldMapping(PDFWidgetToFormFieldMapping& mapping);
/// Reloads value from object storage. Actually stored value is lost.
void reloadValue(const PDFObjectStorage* storage, PDFObject parentValue);
/// Parses form field from the object reference. If some error occurs
/// then null pointer is returned, no exception is thrown.
/// \param storage Storage
@ -378,7 +381,7 @@ public:
void setAnnotationManager(PDFAnnotationManager* annotationManager);
const PDFDocument* getDocument() const;
void setDocument(const PDFDocument* document);
void setDocument(const PDFModifiedDocument& document);
/// Returns default form apperance flags
static constexpr FormAppearanceFlags getDefaultApperanceFlags() { return HighlightFields | HighlightRequiredFields; }
@ -387,6 +390,7 @@ public:
void setAppearanceFlags(FormAppearanceFlags flags);
private:
void updateFieldValues();
void updateWidgetToFormFieldMapping();
PDFDrawWidgetProxy* m_proxy;

View File

@ -40,12 +40,18 @@ PDFTreeItemModel::PDFTreeItemModel(QObject* parent) :
}
void PDFTreeItemModel::setDocument(const PDFDocument* document)
void PDFTreeItemModel::setDocument(const PDFModifiedDocument& document)
{
if (m_document != document)
{
m_document = document;
update();
// We must only update only, when document has been reset, i.e.
// all document content has been changed.
if (document.hasReset())
{
update();
}
}
}
@ -727,20 +733,29 @@ void PDFThumbnailsItemModel::setThumbnailsSize(int size)
}
}
void PDFThumbnailsItemModel::setDocument(const PDFDocument* document)
void PDFThumbnailsItemModel::setDocument(const PDFModifiedDocument& document)
{
if (m_document != document)
{
beginResetModel();
m_thumbnailCache.clear();
m_document = document;
m_pageCount = 0;
if (m_document)
if (document.hasReset() || document.hasFlag(PDFModifiedDocument::Annotation))
{
m_pageCount = static_cast<int>(m_document->getCatalog()->getPageCount());
beginResetModel();
m_thumbnailCache.clear();
m_document = document;
m_pageCount = 0;
if (m_document)
{
m_pageCount = static_cast<int>(m_document->getCatalog()->getPageCount());
}
endResetModel();
}
else
{
// Soft reset
m_document = document;
Q_ASSERT(!m_document || m_pageCount == static_cast<int>(m_document->getCatalog()->getPageCount()));
}
endResetModel();
}
}
@ -778,4 +793,19 @@ QString PDFThumbnailsItemModel::getKey(int pageIndex) const
return QString("PDF_THUMBNAIL_%1").arg(pageIndex);
}
PDFAttachmentsTreeItem::PDFAttachmentsTreeItem(PDFAttachmentsTreeItem* parent, QIcon icon, QString title, QString description, const PDFFileSpecification* fileSpecification) :
PDFTreeItem(parent),
m_icon(qMove(icon)),
m_title(qMove(title)),
m_description(qMove(description)),
m_fileSpecification(std::make_unique<PDFFileSpecification>(*fileSpecification))
{
}
PDFAttachmentsTreeItem::~PDFAttachmentsTreeItem()
{
}
} // namespace pdf

View File

@ -30,6 +30,7 @@ namespace pdf
class PDFAction;
class PDFDocument;
class PDFOutlineItem;
class PDFModifiedDocument;
class PDFFileSpecification;
class PDFOptionalContentActivity;
class PDFDrawWidgetProxy;
@ -66,13 +67,15 @@ private:
QList<PDFTreeItem*> m_children;
};
/// Root of all tree item models
/// Root of all tree item models. Reimplementations of this model
/// must handle "soft" document updates, such as only annotations changed etc.
/// Model should be rebuilded only, if it is neccessary.
class PDFFORQTLIBSHARED_EXPORT PDFTreeItemModel : public QAbstractItemModel
{
public:
explicit PDFTreeItemModel(QObject* parent);
void setDocument(const pdf::PDFDocument* document);
void setDocument(const PDFModifiedDocument& document);
bool isEmpty() const;
@ -172,26 +175,19 @@ private:
class PDFAttachmentsTreeItem : public PDFTreeItem
{
public:
explicit PDFAttachmentsTreeItem(PDFAttachmentsTreeItem* parent, QIcon icon, QString title, QString description, const PDFFileSpecification* fileSpecification) :
PDFTreeItem(parent),
m_icon(qMove(icon)),
m_title(qMove(title)),
m_description(qMove(description)),
m_fileSpecification(fileSpecification)
{
}
explicit PDFAttachmentsTreeItem(PDFAttachmentsTreeItem* parent, QIcon icon, QString title, QString description, const PDFFileSpecification* fileSpecification);
virtual ~PDFAttachmentsTreeItem() override;
const QIcon& getIcon() const { return m_icon; }
const QString& getTitle() const { return m_title; }
const QString& getDescription() const { return m_description; }
const PDFFileSpecification* getFileSpecification() const { return m_fileSpecification; }
const PDFFileSpecification* getFileSpecification() const { return m_fileSpecification.get(); }
private:
QIcon m_icon;
QString m_title;
QString m_description;
const PDFFileSpecification* m_fileSpecification;
std::unique_ptr<PDFFileSpecification> m_fileSpecification;
};
class PDFFORQTLIBSHARED_EXPORT PDFAttachmentsTreeItemModel : public PDFTreeItemModel
@ -235,7 +231,7 @@ public:
virtual QVariant data(const QModelIndex& index, int role) const override;
void setThumbnailsSize(int size);
void setDocument(const PDFDocument* document);
void setDocument(const PDFModifiedDocument& document);
/// Sets the extra item width/height for size hint. This space will be added to the size hint (pixmap size)
void setExtraItemSizeHint(int width, int height) { m_extraItemWidthHint = width; m_extraItemHeighHint = height; }

View File

@ -343,6 +343,16 @@ OCState PDFOptionalContentActivity::getState(PDFObjectReference ocg) const
return OCState::Unknown;
}
void PDFOptionalContentActivity::setDocument(const PDFDocument* document)
{
if (m_document != document)
{
Q_ASSERT(document);
m_document = document;
m_properties = document->getCatalog()->getOptionalContentProperties();
}
}
void PDFOptionalContentActivity::setState(PDFObjectReference ocg, OCState state, bool preserveRadioButtons)
{
auto it = m_states.find(ocg);

View File

@ -167,6 +167,11 @@ public:
/// \param ocg Optional content group
OCState getState(PDFObjectReference ocg) const;
/// Sets document to this object. Optional content settings
/// must be compatible and applicable to new document.
/// \param document Document
void setDocument(const PDFDocument* document);
/// Sets the state of optional content group. If optional content group doesn't exist,
/// then nothing happens. If optional content group is contained in radio button group, then
/// all other optional content groups in the group are switched off, if we are

View File

@ -434,9 +434,13 @@ void PDFRasterizerPool::render(const std::vector<PDFInteger>& pageIndices,
emit renderError(PDFRenderError(error.type, PDFTranslationContext::tr("Page %1: %2").arg(pageIndex + 1).arg(error.message)));
}
// We can const-cast here, because we do not modify the document in annotation manager.
// Annotations are just rendered to the target picture.
PDFModifiedDocument modifiedDocument(const_cast<PDFDocument*>(m_document), const_cast<PDFOptionalContentActivity*>(m_optionalContentActivity));
// Annotation manager
PDFAnnotationManager annotationManager(m_fontCache, m_cmsManager, m_optionalContentActivity, m_meshQualitySettings, m_features, PDFAnnotationManager::Target::Print, nullptr);
annotationManager.setDocument(m_document, m_optionalContentActivity);
annotationManager.setDocument(modifiedDocument);
// Render page to image
PDFRasterizer* rasterizer = acquire();

View File

@ -60,12 +60,17 @@ PDFWidgetTool::~PDFWidgetTool()
}
void PDFWidgetTool::setDocument(const PDFDocument* document)
void PDFWidgetTool::setDocument(const PDFModifiedDocument& document)
{
if (m_document != document)
{
// We must turn off the tool, if we are changing the document
setActive(false);
// We must turn off the tool, if we are changing the document. We turn off tool,
// only if whole document is being reset.
if (document.hasReset())
{
setActive(false);
}
m_document = document;
for (PDFWidgetTool* tool : m_toolStack)
@ -728,7 +733,7 @@ PDFToolManager::PDFToolManager(PDFDrawWidgetProxy* proxy, Actions actions, QObje
}
}
void PDFToolManager::setDocument(const PDFDocument* document)
void PDFToolManager::setDocument(const PDFModifiedDocument& document)
{
for (PDFWidgetTool* tool : m_tools)
{

View File

@ -48,7 +48,7 @@ public:
/// Sets document, shuts down the tool, if it is active, and document
/// is changing.
/// \param document Document
void setDocument(const PDFDocument* document);
void setDocument(const PDFModifiedDocument& document);
/// Sets tool as active or inactive. If tool is active, then it is processed
/// in draw widget proxy events (such as drawing etc.).
@ -416,7 +416,7 @@ public:
/// Sets document
/// \param document Document
void setDocument(const PDFDocument* document);
void setDocument(const PDFModifiedDocument& document);
enum PredefinedTools
{

View File

@ -49,14 +49,20 @@ PDFAdvancedFindWidget::~PDFAdvancedFindWidget()
delete ui;
}
void PDFAdvancedFindWidget::setDocument(const pdf::PDFDocument* document)
void PDFAdvancedFindWidget::setDocument(const pdf::PDFModifiedDocument& document)
{
if (m_document != document)
{
m_document = document;
m_findResults.clear();
updateUI();
updateResultsUI();
// If document is not being reset, then page text should remain the same,
// so, there is no need to clear the results.
if (document.hasReset())
{
m_findResults.clear();
updateUI();
updateResultsUI();
}
}
}

View File

@ -56,7 +56,7 @@ public:
const QMatrix& pagePointToDevicePointMatrix,
QList<pdf::PDFRenderError>& errors) const override;
void setDocument(const pdf::PDFDocument* document);
void setDocument(const pdf::PDFModifiedDocument& document);
protected:
virtual void showEvent(QShowEvent* event) override;

View File

@ -121,10 +121,10 @@ PDFSidebarWidget::~PDFSidebarWidget()
delete ui;
}
void PDFSidebarWidget::setDocument(const pdf::PDFDocument* document, pdf::PDFOptionalContentActivity* optionalContentActivity)
void PDFSidebarWidget::setDocument(const pdf::PDFModifiedDocument& document)
{
m_document = document;
m_optionalContentActivity = optionalContentActivity;
m_optionalContentActivity = document.getOptionalContentActivity();
// Update outline
m_outlineTreeModel->setDocument(document);

View File

@ -36,6 +36,7 @@ namespace pdf
class PDFAction;
class PDFDocument;
class PDFDrawWidgetProxy;
class PDFModifiedDocument;
class PDFOutlineTreeItemModel;
class PDFThumbnailsItemModel;
class PDFAttachmentsTreeItemModel;
@ -69,7 +70,7 @@ public:
_END
};
void setDocument(const pdf::PDFDocument* document, pdf::PDFOptionalContentActivity* optionalContentActivity);
void setDocument(const pdf::PDFModifiedDocument& document);
/// Returns true, if all items in sidebar are empty
bool isEmpty() const;

View File

@ -61,7 +61,7 @@ bool PDFTextToSpeech::isValid() const
return m_document != nullptr;
}
void PDFTextToSpeech::setDocument(const pdf::PDFDocument* document)
void PDFTextToSpeech::setDocument(const pdf::PDFModifiedDocument& document)
{
if (m_document != document)
{

View File

@ -34,6 +34,7 @@ namespace pdf
{
class PDFDocument;
class PDFDrawWidgetProxy;
class PDFModifiedDocument;
}
namespace pdfviewer
@ -66,7 +67,7 @@ public:
bool isValid() const;
/// Sets active document to text to speech engine
void setDocument(const pdf::PDFDocument* document);
void setDocument(const pdf::PDFModifiedDocument& document);
/// Apply settings to the reader
void setSettings(const PDFViewerSettings* viewerSettings);

View File

@ -959,7 +959,8 @@ void PDFViewerMainWindow::onDocumentReadingFinished()
m_recentFileManager->addRecentFile(m_fileInfo.originalFileName);
m_pdfDocument = result.document;
setDocument(m_pdfDocument.data());
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
setDocument(document);
statusBar()->showMessage(tr("Document '%1' was successfully loaded!").arg(m_fileInfo.fileName), 4000);
break;
@ -977,27 +978,36 @@ void PDFViewerMainWindow::onDocumentReadingFinished()
updateActionsAvailability();
}
void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
void PDFViewerMainWindow::setDocument(pdf::PDFModifiedDocument document)
{
if (m_optionalContentActivity)
if (document.hasReset())
{
// We use deleteLater, because we want to avoid consistency problem with model
// (we set document to the model before activity).
m_optionalContentActivity->deleteLater();
m_optionalContentActivity = nullptr;
if (m_optionalContentActivity)
{
// We use deleteLater, because we want to avoid consistency problem with model
// (we set document to the model before activity).
m_optionalContentActivity->deleteLater();
m_optionalContentActivity = nullptr;
}
if (document)
{
m_optionalContentActivity = new pdf::PDFOptionalContentActivity(document, pdf::OCUsage::View, this);
}
}
else if (m_optionalContentActivity)
{
Q_ASSERT(document);
m_optionalContentActivity->setDocument(document);
}
if (document)
{
m_optionalContentActivity = new pdf::PDFOptionalContentActivity(document, pdf::OCUsage::View, this);
}
m_annotationManager->setDocument(document, m_optionalContentActivity);
document.setOptionalContentActivity(m_optionalContentActivity);
m_annotationManager->setDocument(document);
m_formManager->setDocument(document);
m_toolManager->setDocument(document);
m_textToSpeech->setDocument(document);
m_pdfWidget->setDocument(document, m_optionalContentActivity);
m_sidebarWidget->setDocument(document, m_optionalContentActivity);
m_pdfWidget->setDocument(document);
m_sidebarWidget->setDocument(document);
m_advancedFindWidget->setDocument(document);
if (m_sidebarWidget->isEmpty())
@ -1034,7 +1044,7 @@ void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
void PDFViewerMainWindow::closeDocument()
{
setDocument(nullptr);
setDocument(pdf::PDFModifiedDocument());
m_pdfDocument.reset();
updateActionsAvailability();
}

View File

@ -135,7 +135,7 @@ private:
void onRenderingOptionTriggered(bool checked);
void openDocument(const QString& fileName);
void setDocument(const pdf::PDFDocument* document);
void setDocument(pdf::PDFModifiedDocument document);
void closeDocument();
void setPageLayout(pdf::PageLayout pageLayout);