Progress bar for windows taskbar button

This commit is contained in:
Jakub Melka 2019-11-09 17:27:17 +01:00
parent eab366b90d
commit 11bdba0580
8 changed files with 207 additions and 8 deletions

View File

@ -46,6 +46,7 @@ SOURCES += \
sources/pdfdocument.cpp \
sources/pdfdocumentreader.cpp \
sources/pdfpattern.cpp \
sources/pdfprogress.cpp \
sources/pdfsecurityhandler.cpp \
sources/pdfutils.cpp \
sources/pdfxreftable.cpp \
@ -80,6 +81,7 @@ HEADERS += \
sources/pdfdocument.h \
sources/pdfdocumentreader.h \
sources/pdfpattern.h \
sources/pdfprogress.h \
sources/pdfsecurityhandler.h \
sources/pdfxreftable.h \
sources/pdfflatmap.h \

View File

@ -33,9 +33,10 @@
namespace pdf
{
PDFDocumentReader::PDFDocumentReader(const std::function<QString(bool*)>& getPasswordCallback) :
PDFDocumentReader::PDFDocumentReader(PDFProgress* progress, const std::function<QString(bool*)>& getPasswordCallback) :
m_result(Result::OK),
m_getPasswordCallback(getPasswordCallback)
m_getPasswordCallback(getPasswordCallback),
m_progress(progress)
{
}
@ -253,6 +254,8 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer)
PDFParsingContext context(objectFetcher);
PDFObject object = getObject(&context, entry.offset, entry.reference);
progressStep();
QMutexLocker lock(&m_mutex);
objects[entry.reference.objectNumber] = PDFObjectStorage::Entry(entry.reference.generation, object);
}
@ -266,7 +269,9 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer)
};
// Now, we are ready to scan all objects
progressStart(occupiedEntries.size());
std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), processEntry);
progressFinish();
if (m_result != Result::OK)
{
@ -351,8 +356,10 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer)
// decipher object streams here. 4) must be handled in the security handler.
if (securityHandler->getMode() != EncryptionMode::None)
{
auto decryptEntry = [encryptObjectReference, &securityHandler, &objects](const PDFXRefTable::Entry& entry)
auto decryptEntry = [this, encryptObjectReference, &securityHandler, &objects](const PDFXRefTable::Entry& entry)
{
progressStep();
if (encryptObjectReference.objectNumber != 0 && encryptObjectReference == entry.reference)
{
// 2) - Encrypt dictionary
@ -362,7 +369,9 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer)
objects[entry.reference.objectNumber].object = securityHandler->decryptObject(objects[entry.reference.objectNumber].object, entry.reference);
};
progressStart(occupiedEntries.size());
std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), decryptEntry);
progressFinish();
}
// ------------------------------------------------------------------------------------------
@ -520,4 +529,28 @@ int PDFDocumentReader::findFromEnd(const char* what, const QByteArray& byteArray
return FIND_NOT_FOUND_RESULT;
}
void PDFDocumentReader::progressStart(size_t stepCount)
{
if (m_progress)
{
m_progress->start(stepCount);
}
}
void PDFDocumentReader::progressStep()
{
if (m_progress)
{
m_progress->step();
}
}
void PDFDocumentReader::progressFinish()
{
if (m_progress)
{
m_progress->finish();
}
}
} // namespace pdf

View File

@ -21,6 +21,7 @@
#include "pdfglobal.h"
#include "pdfdocument.h"
#include "pdfprogress.h"
#include <QtCore>
#include <QIODevice>
@ -36,7 +37,7 @@ class PDFFORQTLIBSHARED_EXPORT PDFDocumentReader
Q_DECLARE_TR_FUNCTIONS(pdf::PDFDocumentReader)
public:
explicit PDFDocumentReader(const std::function<QString(bool*)>& getPasswordCallback);
explicit PDFDocumentReader(PDFProgress* progress, const std::function<QString(bool*)>& getPasswordCallback);
constexpr inline PDFDocumentReader(const PDFDocumentReader&) = delete;
constexpr inline PDFDocumentReader(PDFDocumentReader&&) = delete;
@ -86,6 +87,10 @@ private:
/// \returns Position of string, or FIND_NOT_FOUND_RESULT
int findFromEnd(const char* what, const QByteArray& byteArray, int limit);
void progressStart(size_t stepCount);
void progressStep();
void progressFinish();
/// Mutex for access to variables of this reader from more threads
/// (providing thread safety)
QMutex m_mutex;
@ -101,6 +106,9 @@ private:
/// Callback to obtain password from the user
std::function<QString(bool*)> m_getPasswordCallback;
/// Progress indicator
PDFProgress* m_progress;
};
} // namespace pdf

View File

@ -0,0 +1,60 @@
// Copyright (C) 2019 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#include "pdfprogress.h"
namespace pdf
{
void PDFProgress::start(size_t stepCount)
{
Q_ASSERT(stepCount > 0);
m_currentStep = 0;
m_stepCount = stepCount;
m_percentage = 0;
emit progressStarted();
}
void PDFProgress::step()
{
// Atomically increment by one. We must add + 1 to the current step,
// because fetch_add will return old value. Then we must test, if percentage
// has been changed.
size_t currentStep = m_currentStep.fetch_add(1) + 1;
int newPercentage = int((size_t(100) * currentStep) / m_stepCount);
int oldPercentage = m_percentage.load(std::memory_order_acquire);
bool emitSignal = oldPercentage < newPercentage;
do
{
emitSignal = oldPercentage < newPercentage;
} while (oldPercentage < newPercentage && !m_percentage.compare_exchange_weak(oldPercentage, newPercentage, std::memory_order_release, std::memory_order_relaxed));
if (emitSignal)
{
progressStep(newPercentage);
}
}
void PDFProgress::finish()
{
emit progressFinished();
}
} // namespace pdf

View File

@ -0,0 +1,54 @@
// Copyright (C) 2019 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#ifndef PDFPROGRESS_H
#define PDFPROGRESS_H
#include "pdfglobal.h"
#include <QObject>
#include <atomic>
namespace pdf
{
class PDFFORQTLIBSHARED_EXPORT PDFProgress : public QObject
{
Q_OBJECT
public:
explicit PDFProgress(QObject* parent) : QObject(parent) { }
void start(size_t stepCount);
void step();
void finish();
signals:
void progressStarted();
void progressStep(int percentage);
void progressFinished();
private:
std::atomic<size_t> m_currentStep = 0;
std::atomic<size_t> m_stepCount = 0;
std::atomic<int> m_percentage = 0;
};
} // namespace pdf
#endif // PDFPROGRESS_H

View File

@ -4,7 +4,7 @@
#
#-------------------------------------------------
QT += core gui
QT += core gui winextras
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

View File

@ -61,10 +61,16 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
m_pageNumberSpinBox(nullptr),
m_pageNumberLabel(nullptr),
m_pageZoomSpinBox(nullptr),
m_isLoadingUI(false)
m_isLoadingUI(false),
m_progress(new pdf::PDFProgress(this)),
m_taskbarButton(new QWinTaskbarButton(this)),
m_progressTaskbarIndicator(nullptr)
{
ui->setupUi(this);
// Initialize task bar progress
m_progressTaskbarIndicator = m_taskbarButton->progress();
// Initialize shortcuts
ui->actionOpen->setShortcut(QKeySequence::Open);
ui->actionClose->setShortcut(QKeySequence::Close);
@ -164,6 +170,9 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::pageLayoutChanged, this, &PDFViewerMainWindow::onPageLayoutChanged);
connect(m_pdfWidget, &pdf::PDFWidget::pageRenderingErrorsChanged, this, &PDFViewerMainWindow::onPageRenderingErrorsChanged, Qt::QueuedConnection);
connect(m_settings, &PDFViewerSettings::settingsChanged, this, &PDFViewerMainWindow::onViewerSettingsChanged);
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);
updatePageLayoutActions();
updateUI(true);
@ -242,6 +251,23 @@ void PDFViewerMainWindow::onPageZoomSpinboxEditingFinished()
m_pdfWidget->getDrawWidgetProxy()->zoom(m_pageZoomSpinBox->value() / 100.0);
}
void PDFViewerMainWindow::onProgressStarted()
{
m_progressTaskbarIndicator->setRange(0, 100);
m_progressTaskbarIndicator->reset();
m_progressTaskbarIndicator->show();
}
void PDFViewerMainWindow::onProgressStep(int percentage)
{
m_progressTaskbarIndicator->setValue(percentage);
}
void PDFViewerMainWindow::onProgressFinished()
{
m_progressTaskbarIndicator->hide();
}
void PDFViewerMainWindow::readSettings()
{
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
@ -403,7 +429,7 @@ void PDFViewerMainWindow::openDocument(const QString& fileName)
// Try to open a new document
QApplication::setOverrideCursor(Qt::WaitCursor);
pdf::PDFDocumentReader reader(qMove(getPasswordCallback));
pdf::PDFDocumentReader reader(m_progress, qMove(getPasswordCallback));
pdf::PDFDocument document = reader.readFromFile(fileName);
QApplication::restoreOverrideCursor();
@ -497,6 +523,12 @@ void PDFViewerMainWindow::closeEvent(QCloseEvent* event)
event->accept();
}
void PDFViewerMainWindow::showEvent(QShowEvent* event)
{
Q_UNUSED(event);
m_taskbarButton->setWindow(windowHandle());
}
void PDFViewerMainWindow::on_actionPageLayoutSinglePage_triggered()
{
setPageLayout(pdf::PageLayout::SinglePage);

View File

@ -20,12 +20,14 @@
#include "pdfcatalog.h"
#include "pdfrenderer.h"
#include "pdfprogress.h"
#include "pdfviewersettings.h"
#include <QTreeView>
#include <QMainWindow>
#include <QSharedPointer>
#include <QWinTaskbarButton>
#include <QWinTaskbarProgress>
class QLabel;
class QSpinBox;
@ -56,6 +58,7 @@ public:
virtual ~PDFViewerMainWindow() override;
virtual void closeEvent(QCloseEvent* event) override;
virtual void showEvent(QShowEvent* event) override;
private slots:
void on_actionPageLayoutSinglePage_triggered();
@ -77,6 +80,10 @@ private:
void onPageNumberSpinboxEditingFinished();
void onPageZoomSpinboxEditingFinished();
void onProgressStarted();
void onProgressStep(int percentage);
void onProgressFinished();
void readSettings();
void writeSettings();
@ -111,6 +118,9 @@ private:
QLabel* m_pageNumberLabel;
QDoubleSpinBox* m_pageZoomSpinBox;
bool m_isLoadingUI;
pdf::PDFProgress* m_progress;
QWinTaskbarButton* m_taskbarButton;
QWinTaskbarProgress* m_progressTaskbarIndicator;
};
} // namespace pdfviewer