mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Asynchronous calculation of document text layout
This commit is contained in:
@ -18,6 +18,7 @@
|
|||||||
#include "pdfcompiler.h"
|
#include "pdfcompiler.h"
|
||||||
#include "pdfcms.h"
|
#include "pdfcms.h"
|
||||||
#include "pdfdrawspacecontroller.h"
|
#include "pdfdrawspacecontroller.h"
|
||||||
|
#include "pdfprogress.h"
|
||||||
|
|
||||||
#include <QtConcurrent/QtConcurrent>
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
|
||||||
@ -74,7 +75,6 @@ void PDFAsynchronousPageCompiler::stop()
|
|||||||
}
|
}
|
||||||
m_tasks.clear();
|
m_tasks.clear();
|
||||||
m_cache.clear();
|
m_cache.clear();
|
||||||
m_textLayouts.dirty();
|
|
||||||
|
|
||||||
m_state = State::Inactive;
|
m_state = State::Inactive;
|
||||||
break;
|
break;
|
||||||
@ -121,7 +121,7 @@ const PDFPrecompiledPage* PDFAsynchronousPageCompiler::getCompiledPage(PDFIntege
|
|||||||
return compiledPage;
|
return compiledPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
m_proxy->getFontCache()->setCacheShrinkEnabled(false);
|
m_proxy->getFontCache()->setCacheShrinkEnabled(this, false);
|
||||||
CompileTask& task = m_tasks[pageIndex];
|
CompileTask& task = m_tasks[pageIndex];
|
||||||
task.taskFuture = QtConcurrent::run(compilePage);
|
task.taskFuture = QtConcurrent::run(compilePage);
|
||||||
task.taskWatcher = new QFutureWatcher<PDFPrecompiledPage>(this);
|
task.taskWatcher = new QFutureWatcher<PDFPrecompiledPage>(this);
|
||||||
@ -132,17 +132,6 @@ const PDFPrecompiledPage* PDFAsynchronousPageCompiler::getCompiledPage(PDFIntege
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFTextLayout PDFAsynchronousPageCompiler::getTextLayout(PDFInteger pageIndex)
|
|
||||||
{
|
|
||||||
if (m_state != State::Active || !m_proxy->getDocument())
|
|
||||||
{
|
|
||||||
// Engine is not active, always return empty layout
|
|
||||||
return PDFTextLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_textLayouts.get(this, &PDFAsynchronousPageCompiler::getTextLayoutsImpl).getTextLayout(pageIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PDFAsynchronousPageCompiler::onPageCompiled()
|
void PDFAsynchronousPageCompiler::onPageCompiled()
|
||||||
{
|
{
|
||||||
std::vector<PDFInteger> compiledPages;
|
std::vector<PDFInteger> compiledPages;
|
||||||
@ -182,7 +171,7 @@ void PDFAsynchronousPageCompiler::onPageCompiled()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We allow font cache shrinking, when we aren't doing something in parallel.
|
// We allow font cache shrinking, when we aren't doing something in parallel.
|
||||||
m_proxy->getFontCache()->setCacheShrinkEnabled(m_tasks.empty());
|
m_proxy->getFontCache()->setCacheShrinkEnabled(this, m_tasks.empty());
|
||||||
|
|
||||||
if (!compiledPages.empty())
|
if (!compiledPages.empty())
|
||||||
{
|
{
|
||||||
@ -268,15 +257,118 @@ void PDFTextLayoutGenerator::performOutputCharacter(const PDFTextCharacterInfo&
|
|||||||
m_textLayout.addCharacter(info);
|
m_textLayout.addCharacter(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFTextLayoutStorage PDFAsynchronousPageCompiler::getTextLayoutsImpl()
|
PDFAsynchronousTextLayoutCompiler::PDFAsynchronousTextLayoutCompiler(PDFDrawWidgetProxy* proxy) :
|
||||||
|
BaseClass(proxy),
|
||||||
|
m_proxy(proxy)
|
||||||
{
|
{
|
||||||
m_proxy->getFontCache()->setCacheShrinkEnabled(false);
|
connect(&m_textLayoutCompileFutureWatcher, &QFutureWatcher<PDFTextLayoutStorage>::finished, this, &PDFAsynchronousTextLayoutCompiler::onTextLayoutCreated);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFAsynchronousTextLayoutCompiler::start()
|
||||||
|
{
|
||||||
|
switch (m_state)
|
||||||
|
{
|
||||||
|
case State::Inactive:
|
||||||
|
{
|
||||||
|
m_state = State::Active;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::Active:
|
||||||
|
break; // We have nothing to do...
|
||||||
|
|
||||||
|
case State::Stopping:
|
||||||
|
{
|
||||||
|
// We shouldn't call this function while stopping!
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFAsynchronousTextLayoutCompiler::stop()
|
||||||
|
{
|
||||||
|
switch (m_state)
|
||||||
|
{
|
||||||
|
case State::Inactive:
|
||||||
|
break; // We have nothing to do...
|
||||||
|
|
||||||
|
case State::Active:
|
||||||
|
{
|
||||||
|
// Stop the engine
|
||||||
|
m_state = State::Stopping;
|
||||||
|
m_textLayoutCompileFutureWatcher.waitForFinished();
|
||||||
|
m_textLayouts = std::nullopt;
|
||||||
|
m_state = State::Inactive;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::Stopping:
|
||||||
|
{
|
||||||
|
// We shouldn't call this function while stopping!
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFAsynchronousTextLayoutCompiler::reset()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFTextLayout PDFAsynchronousTextLayoutCompiler::getTextLayout(PDFInteger pageIndex)
|
||||||
|
{
|
||||||
|
if (m_state != State::Active || !m_proxy->getDocument())
|
||||||
|
{
|
||||||
|
// Engine is not active, always return empty layout
|
||||||
|
return PDFTextLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_textLayouts)
|
||||||
|
{
|
||||||
|
return m_textLayouts->getTextLayout(pageIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PDFTextLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFAsynchronousTextLayoutCompiler::makeTextLayout()
|
||||||
|
{
|
||||||
|
if (m_state != State::Active || !m_proxy->getDocument())
|
||||||
|
{
|
||||||
|
// Engine is not active, do not calculate layout
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_textLayouts.has_value())
|
||||||
|
{
|
||||||
|
// Value is computed already
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_textLayoutCompileFuture.isRunning())
|
||||||
|
{
|
||||||
|
// Text layout is already being processed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressStartupInfo info;
|
||||||
|
info.showDialog = true;
|
||||||
|
info.text = tr("Generating text layouts for pages...");
|
||||||
|
|
||||||
|
m_proxy->getFontCache()->setCacheShrinkEnabled(this, false);
|
||||||
const PDFCatalog* catalog = m_proxy->getDocument()->getCatalog();
|
const PDFCatalog* catalog = m_proxy->getDocument()->getCatalog();
|
||||||
|
m_proxy->getProgress()->start(catalog->getPageCount(), qMove(info));
|
||||||
|
|
||||||
PDFCMSPointer cms = m_proxy->getCMSManager()->getCurrentCMS();
|
PDFCMSPointer cms = m_proxy->getCMSManager()->getCurrentCMS();
|
||||||
|
|
||||||
|
auto createTextLayout = [this, cms, catalog]() -> PDFTextLayoutStorage
|
||||||
|
{
|
||||||
PDFTextLayoutStorage result(catalog->getPageCount());
|
PDFTextLayoutStorage result(catalog->getPageCount());
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
auto generateTextLayout = [this, &result, &mutex, &cms, catalog](PDFInteger pageIndex)
|
auto generateTextLayout = [this, &result, &mutex, cms, catalog](PDFInteger pageIndex)
|
||||||
{
|
{
|
||||||
if (!catalog->getPage(pageIndex))
|
if (!catalog->getPage(pageIndex))
|
||||||
{
|
{
|
||||||
@ -291,15 +383,26 @@ PDFTextLayoutStorage PDFAsynchronousPageCompiler::getTextLayoutsImpl()
|
|||||||
PDFTextLayoutGenerator generator(m_proxy->getFeatures(), page, m_proxy->getDocument(), m_proxy->getFontCache(), cms.data(), m_proxy->getOptionalContentActivity(), QMatrix(), m_proxy->getMeshQualitySettings());
|
PDFTextLayoutGenerator generator(m_proxy->getFeatures(), page, m_proxy->getDocument(), m_proxy->getFontCache(), cms.data(), m_proxy->getOptionalContentActivity(), QMatrix(), m_proxy->getMeshQualitySettings());
|
||||||
generator.processContents();
|
generator.processContents();
|
||||||
result.setTextLayout(pageIndex, generator.createTextLayout(), &mutex);
|
result.setTextLayout(pageIndex, generator.createTextLayout(), &mutex);
|
||||||
|
m_proxy->getProgress()->step();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto pageRange = PDFIntegerRange<PDFInteger>(0, catalog->getPageCount());
|
auto pageRange = PDFIntegerRange<PDFInteger>(0, catalog->getPageCount());
|
||||||
std::for_each(std::execution::parallel_policy(), pageRange.begin(), pageRange.end(), generateTextLayout);
|
std::for_each(std::execution::parallel_policy(), pageRange.begin(), pageRange.end(), generateTextLayout);
|
||||||
|
|
||||||
// We allow font cache shrinking, when we aren't doing something in parallel.
|
|
||||||
m_proxy->getFontCache()->setCacheShrinkEnabled(m_tasks.empty());
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_ASSERT(!m_textLayoutCompileFuture.isRunning());
|
||||||
|
m_textLayoutCompileFuture = QtConcurrent::run(createTextLayout);
|
||||||
|
m_textLayoutCompileFutureWatcher.setFuture(m_textLayoutCompileFuture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFAsynchronousTextLayoutCompiler::onTextLayoutCreated()
|
||||||
|
{
|
||||||
|
m_proxy->getFontCache()->setCacheShrinkEnabled(this, true);
|
||||||
|
m_proxy->getProgress()->finish();
|
||||||
|
|
||||||
|
m_textLayouts = m_textLayoutCompileFuture.result();
|
||||||
|
emit textLayoutChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -73,11 +73,6 @@ public:
|
|||||||
/// \param compile Compile the page, if it is not found in the cache
|
/// \param compile Compile the page, if it is not found in the cache
|
||||||
const PDFPrecompiledPage* getCompiledPage(PDFInteger pageIndex, bool compile);
|
const PDFPrecompiledPage* getCompiledPage(PDFInteger pageIndex, bool compile);
|
||||||
|
|
||||||
/// Returns text layout of the page. If page index is invalid,
|
|
||||||
/// then empty text layout is returned.
|
|
||||||
/// \param pageIndex Page index
|
|
||||||
PDFTextLayout getTextLayout(PDFInteger pageIndex);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void pageImageChanged(bool all, const std::vector<PDFInteger>& pages);
|
void pageImageChanged(bool all, const std::vector<PDFInteger>& pages);
|
||||||
void renderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors);
|
void renderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors);
|
||||||
@ -85,9 +80,6 @@ signals:
|
|||||||
private:
|
private:
|
||||||
void onPageCompiled();
|
void onPageCompiled();
|
||||||
|
|
||||||
/// Returns text layouts for all pages
|
|
||||||
PDFTextLayoutStorage getTextLayoutsImpl();
|
|
||||||
|
|
||||||
struct CompileTask
|
struct CompileTask
|
||||||
{
|
{
|
||||||
QFuture<PDFPrecompiledPage> taskFuture;
|
QFuture<PDFPrecompiledPage> taskFuture;
|
||||||
@ -98,7 +90,57 @@ private:
|
|||||||
State m_state = State::Inactive;
|
State m_state = State::Inactive;
|
||||||
QCache<PDFInteger, PDFPrecompiledPage> m_cache;
|
QCache<PDFInteger, PDFPrecompiledPage> m_cache;
|
||||||
std::map<PDFInteger, CompileTask> m_tasks;
|
std::map<PDFInteger, CompileTask> m_tasks;
|
||||||
PDFCachedItem<PDFTextLayoutStorage> m_textLayouts;
|
};
|
||||||
|
|
||||||
|
class PDFAsynchronousTextLayoutCompiler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
using BaseClass = QObject;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PDFAsynchronousTextLayoutCompiler(PDFDrawWidgetProxy* proxy);
|
||||||
|
|
||||||
|
/// Starts the engine. Call this function only if the engine
|
||||||
|
/// is stopped.
|
||||||
|
void start();
|
||||||
|
|
||||||
|
/// Stops the engine and all underlying asynchronous tasks. Also
|
||||||
|
/// clears the cache. Call this function only if engine is active.
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
/// Resets the engine - calls stop and then calls start.
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
enum class State
|
||||||
|
{
|
||||||
|
Inactive,
|
||||||
|
Active,
|
||||||
|
Stopping
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Returns text layout of the page. If page index is invalid,
|
||||||
|
/// then empty text layout is returned.
|
||||||
|
/// \param pageIndex Page index
|
||||||
|
PDFTextLayout getTextLayout(PDFInteger pageIndex);
|
||||||
|
|
||||||
|
/// Create text layout for the document. Function is asynchronous,
|
||||||
|
/// it returns immediately. After text layout is created, signal
|
||||||
|
/// \p textLayoutChanged is emitted.
|
||||||
|
void makeTextLayout();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void textLayoutChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onTextLayoutCreated();
|
||||||
|
|
||||||
|
PDFDrawWidgetProxy* m_proxy;
|
||||||
|
State m_state = State::Inactive;
|
||||||
|
std::optional<PDFTextLayoutStorage> m_textLayouts;
|
||||||
|
QFuture<PDFTextLayoutStorage> m_textLayoutCompileFuture;
|
||||||
|
QFutureWatcher<PDFTextLayoutStorage> m_textLayoutCompileFutureWatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -269,7 +269,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Now, we are ready to scan all objects
|
// Now, we are ready to scan all objects
|
||||||
progressStart(occupiedEntries.size());
|
progressStart(occupiedEntries.size(), PDFTranslationContext::tr("Reading contents of document..."));
|
||||||
std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), processEntry);
|
std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), processEntry);
|
||||||
progressFinish();
|
progressFinish();
|
||||||
|
|
||||||
@ -369,7 +369,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer)
|
|||||||
objects[entry.reference.objectNumber].object = securityHandler->decryptObject(objects[entry.reference.objectNumber].object, entry.reference);
|
objects[entry.reference.objectNumber].object = securityHandler->decryptObject(objects[entry.reference.objectNumber].object, entry.reference);
|
||||||
};
|
};
|
||||||
|
|
||||||
progressStart(occupiedEntries.size());
|
progressStart(occupiedEntries.size(), PDFTranslationContext::tr("Decrypting encrypted contents of document..."));
|
||||||
std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), decryptEntry);
|
std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), decryptEntry);
|
||||||
progressFinish();
|
progressFinish();
|
||||||
}
|
}
|
||||||
@ -529,11 +529,15 @@ int PDFDocumentReader::findFromEnd(const char* what, const QByteArray& byteArray
|
|||||||
return FIND_NOT_FOUND_RESULT;
|
return FIND_NOT_FOUND_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFDocumentReader::progressStart(size_t stepCount)
|
void PDFDocumentReader::progressStart(size_t stepCount, QString text)
|
||||||
{
|
{
|
||||||
if (m_progress)
|
if (m_progress)
|
||||||
{
|
{
|
||||||
m_progress->start(stepCount);
|
ProgressStartupInfo info;
|
||||||
|
info.showDialog = !text.isEmpty();
|
||||||
|
info.text = qMove(text);
|
||||||
|
|
||||||
|
m_progress->start(stepCount, qMove(info));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ private:
|
|||||||
/// \returns Position of string, or FIND_NOT_FOUND_RESULT
|
/// \returns Position of string, or FIND_NOT_FOUND_RESULT
|
||||||
int findFromEnd(const char* what, const QByteArray& byteArray, int limit);
|
int findFromEnd(const char* what, const QByteArray& byteArray, int limit);
|
||||||
|
|
||||||
void progressStart(size_t stepCount);
|
void progressStart(size_t stepCount, QString text);
|
||||||
void progressStep();
|
void progressStep();
|
||||||
void progressFinish();
|
void progressFinish();
|
||||||
|
|
||||||
|
@ -59,6 +59,11 @@ void PDFDrawSpaceController::setDocument(const PDFDocument* document, const PDFO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFDrawSpaceController::onOptionalContentGroupStateChanged()
|
||||||
|
{
|
||||||
|
emit pageImageChanged(true, { });
|
||||||
|
}
|
||||||
|
|
||||||
void PDFDrawSpaceController::setPageLayout(PageLayout pageLayout)
|
void PDFDrawSpaceController::setPageLayout(PageLayout pageLayout)
|
||||||
{
|
{
|
||||||
if (m_pageLayoutMode != pageLayout)
|
if (m_pageLayoutMode != pageLayout)
|
||||||
@ -138,11 +143,6 @@ QSizeF PDFDrawSpaceController::getReferenceBoundingBox() const
|
|||||||
return rect.size();
|
return rect.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFDrawSpaceController::onOptionalContentGroupStateChanged()
|
|
||||||
{
|
|
||||||
emit pageImageChanged(true, { });
|
|
||||||
}
|
|
||||||
|
|
||||||
void PDFDrawSpaceController::recalculate()
|
void PDFDrawSpaceController::recalculate()
|
||||||
{
|
{
|
||||||
if (!m_document)
|
if (!m_document)
|
||||||
@ -400,7 +400,9 @@ PDFDrawWidgetProxy::PDFDrawWidgetProxy(QObject* parent) :
|
|||||||
m_verticalScrollbar(nullptr),
|
m_verticalScrollbar(nullptr),
|
||||||
m_features(PDFRenderer::getDefaultFeatures()),
|
m_features(PDFRenderer::getDefaultFeatures()),
|
||||||
m_compiler(new PDFAsynchronousPageCompiler(this)),
|
m_compiler(new PDFAsynchronousPageCompiler(this)),
|
||||||
m_rasterizer(new PDFRasterizer(this))
|
m_textLayoutCompiler(new PDFAsynchronousTextLayoutCompiler(this)),
|
||||||
|
m_rasterizer(new PDFRasterizer(this)),
|
||||||
|
m_progress(nullptr)
|
||||||
{
|
{
|
||||||
m_controller = new PDFDrawSpaceController(this);
|
m_controller = new PDFDrawSpaceController(this);
|
||||||
connect(m_controller, &PDFDrawSpaceController::drawSpaceChanged, this, &PDFDrawWidgetProxy::update);
|
connect(m_controller, &PDFDrawSpaceController::drawSpaceChanged, this, &PDFDrawWidgetProxy::update);
|
||||||
@ -408,6 +410,7 @@ PDFDrawWidgetProxy::PDFDrawWidgetProxy(QObject* parent) :
|
|||||||
connect(m_controller, &PDFDrawSpaceController::pageImageChanged, this, &PDFDrawWidgetProxy::pageImageChanged);
|
connect(m_controller, &PDFDrawSpaceController::pageImageChanged, this, &PDFDrawWidgetProxy::pageImageChanged);
|
||||||
connect(m_compiler, &PDFAsynchronousPageCompiler::renderingError, this, &PDFDrawWidgetProxy::renderingError);
|
connect(m_compiler, &PDFAsynchronousPageCompiler::renderingError, this, &PDFDrawWidgetProxy::renderingError);
|
||||||
connect(m_compiler, &PDFAsynchronousPageCompiler::pageImageChanged, this, &PDFDrawWidgetProxy::pageImageChanged);
|
connect(m_compiler, &PDFAsynchronousPageCompiler::pageImageChanged, this, &PDFDrawWidgetProxy::pageImageChanged);
|
||||||
|
connect(m_textLayoutCompiler, &PDFAsynchronousTextLayoutCompiler::textLayoutChanged, this, &PDFDrawWidgetProxy::onTextLayoutChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFDrawWidgetProxy::~PDFDrawWidgetProxy()
|
PDFDrawWidgetProxy::~PDFDrawWidgetProxy()
|
||||||
@ -418,8 +421,10 @@ PDFDrawWidgetProxy::~PDFDrawWidgetProxy()
|
|||||||
void PDFDrawWidgetProxy::setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity)
|
void PDFDrawWidgetProxy::setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity)
|
||||||
{
|
{
|
||||||
m_compiler->stop();
|
m_compiler->stop();
|
||||||
|
m_textLayoutCompiler->stop();
|
||||||
m_controller->setDocument(document, optionalContentActivity);
|
m_controller->setDocument(document, optionalContentActivity);
|
||||||
m_compiler->start();
|
m_compiler->start();
|
||||||
|
m_textLayoutCompiler->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFDrawWidgetProxy::init(PDFWidget* widget)
|
void PDFDrawWidgetProxy::init(PDFWidget* widget)
|
||||||
@ -626,7 +631,8 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect)
|
|||||||
// Draw text blocks/text lines, if it is enabled
|
// Draw text blocks/text lines, if it is enabled
|
||||||
if (m_features.testFlag(PDFRenderer::DebugTextBlocks))
|
if (m_features.testFlag(PDFRenderer::DebugTextBlocks))
|
||||||
{
|
{
|
||||||
PDFTextLayout layout = m_compiler->getTextLayout(item.pageIndex);
|
m_textLayoutCompiler->makeTextLayout();
|
||||||
|
PDFTextLayout layout = m_textLayoutCompiler->getTextLayout(item.pageIndex);
|
||||||
const PDFTextBlocks& textBlocks = layout.getTextBlocks();
|
const PDFTextBlocks& textBlocks = layout.getTextBlocks();
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
@ -648,7 +654,8 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect)
|
|||||||
}
|
}
|
||||||
if (m_features.testFlag(PDFRenderer::DebugTextLines))
|
if (m_features.testFlag(PDFRenderer::DebugTextLines))
|
||||||
{
|
{
|
||||||
PDFTextLayout layout = m_compiler->getTextLayout(item.pageIndex);
|
m_textLayoutCompiler->makeTextLayout();
|
||||||
|
PDFTextLayout layout = m_textLayoutCompiler->getTextLayout(item.pageIndex);
|
||||||
const PDFTextBlocks& textBlocks = layout.getTextBlocks();
|
const PDFTextBlocks& textBlocks = layout.getTextBlocks();
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
@ -989,6 +996,11 @@ QRectF PDFDrawWidgetProxy::fromDeviceSpace(const QRectF& rect) const
|
|||||||
rect.height() * m_deviceSpaceUnitToPixel);
|
rect.height() * m_deviceSpaceUnitToPixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFDrawWidgetProxy::onTextLayoutChanged()
|
||||||
|
{
|
||||||
|
emit repaintNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
bool PDFDrawWidgetProxy::isBlockMode() const
|
bool PDFDrawWidgetProxy::isBlockMode() const
|
||||||
{
|
{
|
||||||
switch (m_controller->getPageLayout())
|
switch (m_controller->getPageLayout())
|
||||||
@ -1137,8 +1149,10 @@ void PDFDrawWidgetProxy::setFeatures(PDFRenderer::Features features)
|
|||||||
if (m_features != features)
|
if (m_features != features)
|
||||||
{
|
{
|
||||||
m_compiler->stop();
|
m_compiler->stop();
|
||||||
|
m_textLayoutCompiler->stop();
|
||||||
m_features = features;
|
m_features = features;
|
||||||
m_compiler->start();
|
m_compiler->start();
|
||||||
|
m_textLayoutCompiler->start();
|
||||||
emit pageImageChanged(true, { });
|
emit pageImageChanged(true, { });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,12 @@ class QScrollBar;
|
|||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
class PDFProgress;
|
||||||
class PDFWidget;
|
class PDFWidget;
|
||||||
class IDrawWidget;
|
class IDrawWidget;
|
||||||
class PDFCMSManager;
|
class PDFCMSManager;
|
||||||
class PDFAsynchronousPageCompiler;
|
class PDFAsynchronousPageCompiler;
|
||||||
|
class PDFAsynchronousTextLayoutCompiler;
|
||||||
|
|
||||||
/// This class controls draw space - page layout. Pages are divided into blocks
|
/// This class controls draw space - page layout. Pages are divided into blocks
|
||||||
/// each block can contain one or multiple pages. Units are in milimeters.
|
/// each block can contain one or multiple pages. Units are in milimeters.
|
||||||
@ -274,6 +276,8 @@ public:
|
|||||||
const PDFMeshQualitySettings& getMeshQualitySettings() const { return m_meshQualitySettings; }
|
const PDFMeshQualitySettings& getMeshQualitySettings() const { return m_meshQualitySettings; }
|
||||||
PDFAsynchronousPageCompiler* getCompiler() const { return m_compiler; }
|
PDFAsynchronousPageCompiler* getCompiler() const { return m_compiler; }
|
||||||
const PDFCMSManager* getCMSManager() const;
|
const PDFCMSManager* getCMSManager() const;
|
||||||
|
PDFProgress* getProgress() const { return m_progress; }
|
||||||
|
void setProgress(PDFProgress* progress) { m_progress = progress; }
|
||||||
|
|
||||||
void setFeatures(PDFRenderer::Features features);
|
void setFeatures(PDFRenderer::Features features);
|
||||||
void setPreferredMeshResolutionRatio(PDFReal ratio);
|
void setPreferredMeshResolutionRatio(PDFReal ratio);
|
||||||
@ -326,6 +330,7 @@ private:
|
|||||||
/// Converts rectangle from device space to the pixel space
|
/// Converts rectangle from device space to the pixel space
|
||||||
QRectF fromDeviceSpace(const QRectF& rect) const;
|
QRectF fromDeviceSpace(const QRectF& rect) const;
|
||||||
|
|
||||||
|
void onTextLayoutChanged();
|
||||||
void onColorManagementSystemChanged();
|
void onColorManagementSystemChanged();
|
||||||
void onHorizontalScrollbarValueChanged(int value);
|
void onHorizontalScrollbarValueChanged(int value);
|
||||||
void onVerticalScrollbarValueChanged(int value);
|
void onVerticalScrollbarValueChanged(int value);
|
||||||
@ -408,8 +413,14 @@ private:
|
|||||||
/// Page compiler
|
/// Page compiler
|
||||||
PDFAsynchronousPageCompiler* m_compiler;
|
PDFAsynchronousPageCompiler* m_compiler;
|
||||||
|
|
||||||
|
/// Text layout compiler
|
||||||
|
PDFAsynchronousTextLayoutCompiler* m_textLayoutCompiler;
|
||||||
|
|
||||||
/// Page image rasterizer for thumbnails
|
/// Page image rasterizer for thumbnails
|
||||||
PDFRasterizer* m_rasterizer;
|
PDFRasterizer* m_rasterizer;
|
||||||
|
|
||||||
|
/// Progress
|
||||||
|
PDFProgress* m_progress;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -1610,7 +1610,7 @@ PDFFontPointer PDFFontCache::getFont(const PDFObject& fontObject) const
|
|||||||
// We must create the font
|
// We must create the font
|
||||||
PDFFontPointer font = PDFFont::createFont(fontObject, m_document);
|
PDFFontPointer font = PDFFont::createFont(fontObject, m_document);
|
||||||
|
|
||||||
if (m_fontCacheShrinkEnabled && m_fontCache.size() >= m_fontCacheLimit)
|
if (m_fontCacheShrinkDisabledObjects.empty() && m_fontCache.size() >= m_fontCacheLimit)
|
||||||
{
|
{
|
||||||
// We have exceeded the cache limit. Clear the cache.
|
// We have exceeded the cache limit. Clear the cache.
|
||||||
m_fontCache.clear();
|
m_fontCache.clear();
|
||||||
@ -1638,7 +1638,7 @@ PDFRealizedFontPointer PDFFontCache::getRealizedFont(const PDFFontPointer& font,
|
|||||||
// We must create the realized font
|
// We must create the realized font
|
||||||
PDFRealizedFontPointer realizedFont = PDFRealizedFont::createRealizedFont(font, size, reporter);
|
PDFRealizedFontPointer realizedFont = PDFRealizedFont::createRealizedFont(font, size, reporter);
|
||||||
|
|
||||||
if (m_fontCacheShrinkEnabled && m_realizedFontCache.size() >= m_realizedFontCacheLimit)
|
if (m_fontCacheShrinkDisabledObjects.empty() && m_realizedFontCache.size() >= m_realizedFontCacheLimit)
|
||||||
{
|
{
|
||||||
m_realizedFontCache.clear();
|
m_realizedFontCache.clear();
|
||||||
}
|
}
|
||||||
@ -1649,13 +1649,19 @@ PDFRealizedFontPointer PDFFontCache::getRealizedFont(const PDFFontPointer& font,
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFFontCache::setCacheShrinkEnabled(bool enabled)
|
void PDFFontCache::setCacheShrinkEnabled(void* source, bool enabled)
|
||||||
{
|
{
|
||||||
if (m_fontCacheShrinkEnabled != enabled)
|
QMutexLocker lock(&m_mutex);
|
||||||
|
if (enabled)
|
||||||
{
|
{
|
||||||
m_fontCacheShrinkEnabled = enabled;
|
m_fontCacheShrinkDisabledObjects.erase(source);
|
||||||
|
lock.unlock();
|
||||||
shrink();
|
shrink();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_fontCacheShrinkDisabledObjects.insert(source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFFontCache::setCacheLimits(int fontCacheLimit, int instancedFontCacheLimit)
|
void PDFFontCache::setCacheLimits(int fontCacheLimit, int instancedFontCacheLimit)
|
||||||
@ -1669,10 +1675,10 @@ void PDFFontCache::setCacheLimits(int fontCacheLimit, int instancedFontCacheLimi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PDFFontCache::shrink()
|
void PDFFontCache::shrink()
|
||||||
{
|
|
||||||
if (m_fontCacheShrinkEnabled)
|
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&m_mutex);
|
QMutexLocker lock(&m_mutex);
|
||||||
|
if (m_fontCacheShrinkDisabledObjects.empty())
|
||||||
|
{
|
||||||
if (m_fontCache.size() >= m_fontCacheLimit)
|
if (m_fontCache.size() >= m_fontCacheLimit)
|
||||||
{
|
{
|
||||||
m_fontCache.clear();
|
m_fontCache.clear();
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class QPainterPath;
|
class QPainterPath;
|
||||||
@ -388,7 +389,6 @@ class PDFFontCache
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline explicit PDFFontCache(size_t fontCacheLimit, size_t realizedFontCacheLimit) :
|
inline explicit PDFFontCache(size_t fontCacheLimit, size_t realizedFontCacheLimit) :
|
||||||
m_fontCacheShrinkEnabled(true),
|
|
||||||
m_fontCacheLimit(fontCacheLimit),
|
m_fontCacheLimit(fontCacheLimit),
|
||||||
m_realizedFontCacheLimit(realizedFontCacheLimit),
|
m_realizedFontCacheLimit(realizedFontCacheLimit),
|
||||||
m_document(nullptr)
|
m_document(nullptr)
|
||||||
@ -414,7 +414,12 @@ public:
|
|||||||
|
|
||||||
/// Sets or unsets font shrinking (i.e. font can be deleted from the cache). In multithreading environment,
|
/// Sets or unsets font shrinking (i.e. font can be deleted from the cache). In multithreading environment,
|
||||||
/// font deletion is not thread safe. For this reason, disable font deletion by calling this function.
|
/// font deletion is not thread safe. For this reason, disable font deletion by calling this function.
|
||||||
void setCacheShrinkEnabled(bool enabled);
|
/// First parameter, \p source determines which object enables cache shrinking (so some objects can
|
||||||
|
/// enable shrinking, while some objects will disable it). Only if all objects enables cache shrinking,
|
||||||
|
/// then cache can shrink.
|
||||||
|
/// \param source Source object
|
||||||
|
/// \param enabled Enable or disable cache shrinking
|
||||||
|
void setCacheShrinkEnabled(void* source, bool enabled);
|
||||||
|
|
||||||
/// Set font cache limits
|
/// Set font cache limits
|
||||||
void setCacheLimits(int fontCacheLimit, int instancedFontCacheLimit);
|
void setCacheLimits(int fontCacheLimit, int instancedFontCacheLimit);
|
||||||
@ -423,13 +428,13 @@ public:
|
|||||||
void shrink();
|
void shrink();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_fontCacheShrinkEnabled;
|
|
||||||
size_t m_fontCacheLimit;
|
size_t m_fontCacheLimit;
|
||||||
size_t m_realizedFontCacheLimit;
|
size_t m_realizedFontCacheLimit;
|
||||||
mutable QMutex m_mutex;
|
mutable QMutex m_mutex;
|
||||||
const PDFDocument* m_document;
|
const PDFDocument* m_document;
|
||||||
mutable std::map<PDFObjectReference, PDFFontPointer> m_fontCache;
|
mutable std::map<PDFObjectReference, PDFFontPointer> m_fontCache;
|
||||||
mutable std::map<std::pair<PDFFontPointer, PDFReal>, PDFRealizedFontPointer> m_realizedFontCache;
|
mutable std::map<std::pair<PDFFontPointer, PDFReal>, PDFRealizedFontPointer> m_realizedFontCache;
|
||||||
|
mutable std::set<void*> m_fontCacheShrinkDisabledObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Performs mapping from CID to GID (even identity mapping, if byte array is empty)
|
/// Performs mapping from CID to GID (even identity mapping, if byte array is empty)
|
||||||
|
@ -20,7 +20,13 @@
|
|||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
void PDFProgress::start(size_t stepCount)
|
PDFProgress::PDFProgress(QObject* parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
qRegisterMetaType<pdf::ProgressStartupInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFProgress::start(size_t stepCount, ProgressStartupInfo startupInfo)
|
||||||
{
|
{
|
||||||
Q_ASSERT(stepCount > 0);
|
Q_ASSERT(stepCount > 0);
|
||||||
|
|
||||||
@ -28,7 +34,7 @@ void PDFProgress::start(size_t stepCount)
|
|||||||
m_stepCount = stepCount;
|
m_stepCount = stepCount;
|
||||||
m_percentage = 0;
|
m_percentage = 0;
|
||||||
|
|
||||||
emit progressStarted();
|
emit progressStarted(qMove(startupInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFProgress::step()
|
void PDFProgress::step()
|
||||||
|
@ -27,19 +27,25 @@
|
|||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct ProgressStartupInfo
|
||||||
|
{
|
||||||
|
bool showDialog = false;
|
||||||
|
QString text;
|
||||||
|
};
|
||||||
|
|
||||||
class PDFFORQTLIBSHARED_EXPORT PDFProgress : public QObject
|
class PDFFORQTLIBSHARED_EXPORT PDFProgress : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PDFProgress(QObject* parent) : QObject(parent) { }
|
explicit PDFProgress(QObject* parent);
|
||||||
|
|
||||||
void start(size_t stepCount);
|
void start(size_t stepCount, ProgressStartupInfo startupInfo);
|
||||||
void step();
|
void step();
|
||||||
void finish();
|
void finish();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void progressStarted();
|
void progressStarted(ProgressStartupInfo info);
|
||||||
void progressStep(int percentage);
|
void progressStep(int percentage);
|
||||||
void progressFinished();
|
void progressFinished();
|
||||||
|
|
||||||
@ -49,6 +55,8 @@ private:
|
|||||||
std::atomic<int> m_percentage = 0;
|
std::atomic<int> m_percentage = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(ProgressStartupInfo)
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
|
||||||
#endif // PDFPROGRESS_H
|
#endif // PDFPROGRESS_H
|
||||||
|
@ -73,7 +73,9 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
|||||||
m_isLoadingUI(false),
|
m_isLoadingUI(false),
|
||||||
m_progress(new pdf::PDFProgress(this)),
|
m_progress(new pdf::PDFProgress(this)),
|
||||||
m_taskbarButton(new QWinTaskbarButton(this)),
|
m_taskbarButton(new QWinTaskbarButton(this)),
|
||||||
m_progressTaskbarIndicator(nullptr)
|
m_progressTaskbarIndicator(nullptr),
|
||||||
|
m_progressDialog(nullptr),
|
||||||
|
m_isBusy(false)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
@ -159,6 +161,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
|||||||
setCentralWidget(m_pdfWidget);
|
setCentralWidget(m_pdfWidget);
|
||||||
setFocusProxy(m_pdfWidget);
|
setFocusProxy(m_pdfWidget);
|
||||||
m_pdfWidget->updateCacheLimits(m_settings->getCompiledPageCacheLimit() * 1024, m_settings->getThumbnailsCacheLimit(), m_settings->getFontCacheLimit(), m_settings->getInstancedFontCacheLimit());
|
m_pdfWidget->updateCacheLimits(m_settings->getCompiledPageCacheLimit() * 1024, m_settings->getThumbnailsCacheLimit(), m_settings->getFontCacheLimit(), m_settings->getInstancedFontCacheLimit());
|
||||||
|
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
|
||||||
|
|
||||||
m_sidebarWidget = new PDFSidebarWidget(m_pdfWidget->getDrawWidgetProxy(), this);
|
m_sidebarWidget = new PDFSidebarWidget(m_pdfWidget->getDrawWidgetProxy(), this);
|
||||||
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
|
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
|
||||||
@ -507,21 +510,46 @@ void PDFViewerMainWindow::onActionTriggered(const pdf::PDFAction* action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFViewerMainWindow::onProgressStarted()
|
void PDFViewerMainWindow::onProgressStarted(pdf::ProgressStartupInfo info)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(!m_progressDialog);
|
||||||
|
if (info.showDialog)
|
||||||
|
{
|
||||||
|
m_progressDialog = new QProgressDialog(info.text, QString(), 0, 100, this);
|
||||||
|
m_progressDialog->setWindowModality(Qt::WindowModal);
|
||||||
|
m_progressDialog->setCancelButton(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
m_progressTaskbarIndicator->setRange(0, 100);
|
m_progressTaskbarIndicator->setRange(0, 100);
|
||||||
m_progressTaskbarIndicator->reset();
|
m_progressTaskbarIndicator->reset();
|
||||||
m_progressTaskbarIndicator->show();
|
m_progressTaskbarIndicator->show();
|
||||||
|
m_isBusy = true;
|
||||||
|
|
||||||
|
updateActionsAvailability();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFViewerMainWindow::onProgressStep(int percentage)
|
void PDFViewerMainWindow::onProgressStep(int percentage)
|
||||||
{
|
{
|
||||||
|
if (m_progressDialog)
|
||||||
|
{
|
||||||
|
m_progressDialog->setValue(percentage);
|
||||||
|
}
|
||||||
|
|
||||||
m_progressTaskbarIndicator->setValue(percentage);
|
m_progressTaskbarIndicator->setValue(percentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFViewerMainWindow::onProgressFinished()
|
void PDFViewerMainWindow::onProgressFinished()
|
||||||
{
|
{
|
||||||
|
if (m_progressDialog)
|
||||||
|
{
|
||||||
|
m_progressDialog->hide();
|
||||||
|
m_progressDialog->deleteLater();
|
||||||
|
m_progressDialog = nullptr;
|
||||||
|
}
|
||||||
m_progressTaskbarIndicator->hide();
|
m_progressTaskbarIndicator->hide();
|
||||||
|
m_isBusy = false;
|
||||||
|
|
||||||
|
updateActionsAvailability();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFViewerMainWindow::readSettings()
|
void PDFViewerMainWindow::readSettings()
|
||||||
@ -697,19 +725,20 @@ void PDFViewerMainWindow::updateUI(bool fullUpdate)
|
|||||||
|
|
||||||
void PDFViewerMainWindow::updateActionsAvailability()
|
void PDFViewerMainWindow::updateActionsAvailability()
|
||||||
{
|
{
|
||||||
const bool isReading = m_futureWatcher.isRunning();
|
const bool isBusy = m_futureWatcher.isRunning() || m_isBusy;
|
||||||
const bool hasDocument = m_pdfDocument;
|
const bool hasDocument = m_pdfDocument;
|
||||||
const bool hasValidDocument = !isReading && hasDocument;
|
const bool hasValidDocument = !isBusy && hasDocument;
|
||||||
|
|
||||||
ui->actionOpen->setEnabled(!isReading);
|
ui->actionOpen->setEnabled(!isBusy);
|
||||||
ui->actionClose->setEnabled(hasValidDocument);
|
ui->actionClose->setEnabled(hasValidDocument);
|
||||||
ui->actionQuit->setEnabled(!isReading);
|
ui->actionQuit->setEnabled(!isBusy);
|
||||||
ui->actionOptions->setEnabled(!isReading);
|
ui->actionOptions->setEnabled(!isBusy);
|
||||||
ui->actionAbout->setEnabled(!isReading);
|
ui->actionAbout->setEnabled(!isBusy);
|
||||||
ui->actionFitPage->setEnabled(hasValidDocument);
|
ui->actionFitPage->setEnabled(hasValidDocument);
|
||||||
ui->actionFitWidth->setEnabled(hasValidDocument);
|
ui->actionFitWidth->setEnabled(hasValidDocument);
|
||||||
ui->actionFitHeight->setEnabled(hasValidDocument);
|
ui->actionFitHeight->setEnabled(hasValidDocument);
|
||||||
ui->actionRendering_Errors->setEnabled(hasValidDocument);
|
ui->actionRendering_Errors->setEnabled(hasValidDocument);
|
||||||
|
setEnabled(!isBusy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFViewerMainWindow::onViewerSettingsChanged()
|
void PDFViewerMainWindow::onViewerSettingsChanged()
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <QWinTaskbarButton>
|
#include <QWinTaskbarButton>
|
||||||
#include <QWinTaskbarProgress>
|
#include <QWinTaskbarProgress>
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QSpinBox;
|
class QSpinBox;
|
||||||
@ -99,7 +100,7 @@ private:
|
|||||||
void onPageZoomSpinboxEditingFinished();
|
void onPageZoomSpinboxEditingFinished();
|
||||||
void onActionTriggered(const pdf::PDFAction* action);
|
void onActionTriggered(const pdf::PDFAction* action);
|
||||||
|
|
||||||
void onProgressStarted();
|
void onProgressStarted(pdf::ProgressStartupInfo info);
|
||||||
void onProgressStep(int percentage);
|
void onProgressStep(int percentage);
|
||||||
void onProgressFinished();
|
void onProgressFinished();
|
||||||
|
|
||||||
@ -156,6 +157,9 @@ private:
|
|||||||
|
|
||||||
QFuture<AsyncReadingResult> m_future;
|
QFuture<AsyncReadingResult> m_future;
|
||||||
QFutureWatcher<AsyncReadingResult> m_futureWatcher;
|
QFutureWatcher<AsyncReadingResult> m_futureWatcher;
|
||||||
|
|
||||||
|
QProgressDialog* m_progressDialog;
|
||||||
|
bool m_isBusy;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdfviewer
|
} // namespace pdfviewer
|
||||||
|
Reference in New Issue
Block a user