mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-03-01 09:57:45 +01:00
Asynchronous document loading
This commit is contained in:
parent
38748340fa
commit
fb47d22225
@ -50,6 +50,7 @@
|
||||
#include <QLabel>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "Windows.h"
|
||||
@ -188,11 +189,14 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
|
||||
connect(m_progress, &pdf::PDFProgress::progressStarted, this, &PDFViewerMainWindow::onProgressStarted);
|
||||
connect(m_progress, &pdf::PDFProgress::progressStep, this, &PDFViewerMainWindow::onProgressStep);
|
||||
connect(m_progress, &pdf::PDFProgress::progressFinished, this, &PDFViewerMainWindow::onProgressFinished);
|
||||
connect(&m_futureWatcher, &QFutureWatcher<AsyncReadingResult>::finished, this, &PDFViewerMainWindow::onDocumentReadingFinished);
|
||||
connect(this, &PDFViewerMainWindow::queryPasswordRequest, this, &PDFViewerMainWindow::onQueryPasswordRequest, Qt::BlockingQueuedConnection);
|
||||
|
||||
readActionSettings();
|
||||
updatePageLayoutActions();
|
||||
updateUI(true);
|
||||
onViewerSettingsChanged();
|
||||
updateActionsAvailability();
|
||||
}
|
||||
|
||||
PDFViewerMainWindow::~PDFViewerMainWindow()
|
||||
@ -688,6 +692,23 @@ void PDFViewerMainWindow::updateUI(bool fullUpdate)
|
||||
m_pageZoomSpinBox->setValue(m_pdfWidget->getDrawWidgetProxy()->getZoom() * 100);
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::updateActionsAvailability()
|
||||
{
|
||||
const bool isReading = m_futureWatcher.isRunning();
|
||||
const bool hasDocument = m_pdfDocument;
|
||||
const bool hasValidDocument = !isReading && hasDocument;
|
||||
|
||||
ui->actionOpen->setEnabled(!isReading);
|
||||
ui->actionClose->setEnabled(hasValidDocument);
|
||||
ui->actionQuit->setEnabled(!isReading);
|
||||
ui->actionOptions->setEnabled(!isReading);
|
||||
ui->actionAbout->setEnabled(!isReading);
|
||||
ui->actionFitPage->setEnabled(hasValidDocument);
|
||||
ui->actionFitWidth->setEnabled(hasValidDocument);
|
||||
ui->actionFitHeight->setEnabled(hasValidDocument);
|
||||
ui->actionRendering_Errors->setEnabled(hasValidDocument);
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::onViewerSettingsChanged()
|
||||
{
|
||||
m_pdfWidget->updateRenderer(m_settings->getRendererEngine(), m_settings->isMultisampleAntialiasingEnabled() ? m_settings->getRendererSamples() : -1);
|
||||
@ -725,37 +746,61 @@ void PDFViewerMainWindow::openDocument(const QString& fileName)
|
||||
m_fileInfo.lastModifiedTime = fileInfo.lastModified();
|
||||
m_fileInfo.lastReadTime = fileInfo.lastRead();
|
||||
|
||||
// Password callback
|
||||
auto getPasswordCallback = [this](bool* ok) -> QString
|
||||
{
|
||||
return QInputDialog::getText(this, tr("Encrypted document"), tr("Enter password to acces document content"), QLineEdit::Password, QString(), ok);
|
||||
};
|
||||
|
||||
// Try to open a new document
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
pdf::PDFDocumentReader reader(m_progress, qMove(getPasswordCallback));
|
||||
pdf::PDFDocument document = reader.readFromFile(fileName);
|
||||
auto readDocument = [this, fileName]() -> AsyncReadingResult
|
||||
{
|
||||
AsyncReadingResult result;
|
||||
|
||||
auto queryPassword = [this](bool* ok)
|
||||
{
|
||||
QString result;
|
||||
*ok = false;
|
||||
emit queryPasswordRequest(&result, ok);
|
||||
return result;
|
||||
};
|
||||
|
||||
// Try to open a new document
|
||||
pdf::PDFDocumentReader reader(m_progress, qMove(queryPassword));
|
||||
pdf::PDFDocument document = reader.readFromFile(fileName);
|
||||
|
||||
result.errorMessage = reader.getErrorMessage();
|
||||
result.result = reader.getReadingResult();
|
||||
if (result.result == pdf::PDFDocumentReader::Result::OK)
|
||||
{
|
||||
result.document.reset(new pdf::PDFDocument(qMove(document)));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
m_future = QtConcurrent::run(readDocument);
|
||||
m_futureWatcher.setFuture(m_future);
|
||||
updateActionsAvailability();
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::onDocumentReadingFinished()
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
switch (reader.getReadingResult())
|
||||
AsyncReadingResult result = m_future.result();
|
||||
switch (result.result)
|
||||
{
|
||||
case pdf::PDFDocumentReader::Result::OK:
|
||||
{
|
||||
// Mark current directory as this
|
||||
QFileInfo fileInfo(fileName);
|
||||
QFileInfo fileInfo(m_fileInfo.originalFileName);
|
||||
m_settings->setDirectory(fileInfo.dir().absolutePath());
|
||||
m_currentFile = fileInfo.fileName();
|
||||
|
||||
m_pdfDocument.reset(new pdf::PDFDocument(std::move(document)));
|
||||
m_pdfDocument = result.document;
|
||||
setDocument(m_pdfDocument.data());
|
||||
|
||||
statusBar()->showMessage(tr("Document '%1' was successfully loaded!").arg(fileName), 4000);
|
||||
statusBar()->showMessage(tr("Document '%1' was successfully loaded!").arg(m_fileInfo.fileName), 4000);
|
||||
break;
|
||||
}
|
||||
|
||||
case pdf::PDFDocumentReader::Result::Failed:
|
||||
{
|
||||
QMessageBox::critical(this, tr("PDF Viewer"), tr("Document read error: %1").arg(reader.getErrorMessage()));
|
||||
QMessageBox::critical(this, tr("PDF Viewer"), tr("Document read error: %1").arg(result.errorMessage));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -805,6 +850,8 @@ void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
|
||||
onActionTriggered(action);
|
||||
}
|
||||
}
|
||||
|
||||
updateActionsAvailability();
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::closeDocument()
|
||||
@ -837,9 +884,18 @@ int PDFViewerMainWindow::adjustDpiX(int value)
|
||||
|
||||
void PDFViewerMainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
writeSettings();
|
||||
closeDocument();
|
||||
event->accept();
|
||||
if (m_futureWatcher.isRunning())
|
||||
{
|
||||
// Jakub Melka: Do not allow to close the application, if document
|
||||
// reading is running.
|
||||
event->ignore();
|
||||
}
|
||||
else
|
||||
{
|
||||
writeSettings();
|
||||
closeDocument();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::showEvent(QShowEvent* event)
|
||||
@ -848,6 +904,11 @@ void PDFViewerMainWindow::showEvent(QShowEvent* event)
|
||||
m_taskbarButton->setWindow(windowHandle());
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::onQueryPasswordRequest(QString* password, bool* ok)
|
||||
{
|
||||
*password = QInputDialog::getText(this, tr("Encrypted document"), tr("Enter password to access document content"), QLineEdit::Password, QString(), ok);
|
||||
}
|
||||
|
||||
void PDFViewerMainWindow::on_actionPageLayoutSinglePage_triggered()
|
||||
{
|
||||
setPageLayout(pdf::PageLayout::SinglePage);
|
||||
|
@ -21,14 +21,18 @@
|
||||
#include "pdfcatalog.h"
|
||||
#include "pdfrenderer.h"
|
||||
#include "pdfprogress.h"
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfviewersettings.h"
|
||||
#include "pdfdocumentreader.h"
|
||||
#include "pdfdocumentpropertiesdialog.h"
|
||||
|
||||
#include <QFuture>
|
||||
#include <QTreeView>
|
||||
#include <QMainWindow>
|
||||
#include <QSharedPointer>
|
||||
#include <QWinTaskbarButton>
|
||||
#include <QWinTaskbarProgress>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
class QLabel;
|
||||
class QSpinBox;
|
||||
@ -63,7 +67,12 @@ public:
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
virtual void showEvent(QShowEvent* event) override;
|
||||
|
||||
signals:
|
||||
void queryPasswordRequest(QString* password, bool* ok);
|
||||
|
||||
private slots:
|
||||
void onQueryPasswordRequest(QString* password, bool* ok);
|
||||
|
||||
void on_actionPageLayoutSinglePage_triggered();
|
||||
void on_actionPageLayoutContinuous_triggered();
|
||||
void on_actionPageLayoutTwoPages_triggered();
|
||||
@ -96,6 +105,8 @@ private:
|
||||
void onProgressStep(int percentage);
|
||||
void onProgressFinished();
|
||||
|
||||
void onDocumentReadingFinished();
|
||||
|
||||
void readSettings();
|
||||
void readActionSettings();
|
||||
void writeSettings();
|
||||
@ -104,6 +115,7 @@ private:
|
||||
void updatePageLayoutActions();
|
||||
void updateRenderingOptionActions();
|
||||
void updateUI(bool fullUpdate);
|
||||
void updateActionsAvailability();
|
||||
|
||||
void onViewerSettingsChanged();
|
||||
void onRenderingOptionTriggered(bool checked);
|
||||
@ -119,6 +131,13 @@ private:
|
||||
|
||||
int adjustDpiX(int value);
|
||||
|
||||
struct AsyncReadingResult
|
||||
{
|
||||
QSharedPointer<pdf::PDFDocument> document;
|
||||
QString errorMessage;
|
||||
pdf::PDFDocumentReader::Result result = pdf::PDFDocumentReader::Result::Cancelled;
|
||||
};
|
||||
|
||||
Ui::PDFViewerMainWindow* ui;
|
||||
PDFViewerSettings* m_settings;
|
||||
pdf::PDFWidget* m_pdfWidget;
|
||||
@ -135,6 +154,9 @@ private:
|
||||
QWinTaskbarButton* m_taskbarButton;
|
||||
QWinTaskbarProgress* m_progressTaskbarIndicator;
|
||||
PDFFileInfo m_fileInfo;
|
||||
|
||||
QFuture<AsyncReadingResult> m_future;
|
||||
QFutureWatcher<AsyncReadingResult> m_futureWatcher;
|
||||
};
|
||||
|
||||
} // namespace pdfviewer
|
||||
|
Loading…
x
Reference in New Issue
Block a user