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