summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Heinecke <aheinecke@intevation.de>2016-08-12 16:02:23 (GMT)
committerAndre Heinecke <aheinecke@intevation.de>2016-08-12 16:05:40 (GMT)
commitfab9fd5f804bdb54db16a1e51b3528b6036d0364 (patch)
tree2ba88149c7a8fe18b294f2601f904cadf3739622
parent98fe7602a1e9c5ea570eaa44dd808bf252193aa6 (diff)
Fix progress handling (for gnupg >= 2.1.15)
We finally have a solution for progress that works with Qt data types and how kleopatra passes data to GnuPG. This requires GpgME 1.7.0 and GnuPG 2.1.15 to work. This also simplifies progress handling for that case as we can finally use current and total values and GnuPG no longer overflows in progress messages since 2.1.14. BUG: 365931
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/crypto/gui/newresultpage.cpp21
-rw-r--r--src/crypto/task.cpp25
-rw-r--r--src/crypto/task.h4
-rw-r--r--src/crypto/taskcollection.cpp72
5 files changed, 67 insertions, 57 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b85c97f..38c327e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ option(DISABLE_KWATCHGNUPG "Don't build the kwatchgnupg tool [default=OFF]" OFF)
# Standalone build. Find / include everything neccessary.
set(KF5_VERSION "5.17.0")
-set(GPGMEPP_VERSION "5.3.42")
+set(GPGMEPP_VERSION "5.3.43")
set(KMIME_VERSION "5.1.40")
set(LIBKLEO_VERSION "5.3.44")
set(QT_REQUIRED_VERSION "5.4.0")
diff --git a/src/crypto/gui/newresultpage.cpp b/src/crypto/gui/newresultpage.cpp
index 11eae82..a34942f 100644
--- a/src/crypto/gui/newresultpage.cpp
+++ b/src/crypto/gui/newresultpage.cpp
@@ -110,23 +110,10 @@ NewResultPage::Private::Private(NewResultPage *qq) : q(qq), m_lastErrorItemIndex
void NewResultPage::Private::progress(const QString &msg, int progress, int total)
{
Q_UNUSED(msg);
- // FIXME as of 07 2016 GpgME / GnuPG's progress is broken.
- // Older versions overflow for files larger 2^31 bytes
- // GnuPG 2.1.14 does not overflow but scales down the progress
- // after more then 1024*1024 bytes are processed. Which is nearly
- // unhandable. Total is always zero unless the job is completed
- // for QGpgME as it internally uses memory based dataproviders
- // and without the patch in https://bugs.gnupg.org/gnupg/issue2368
- // has no way to handle this.
- //
- // See BKO #365931
- if (progress && progress == total) {
- m_progressBar->setRange(0, 1);
- m_progressBar->setValue(1);
- } else {
- m_progressBar->setRange(0, 0);
- m_progressBar->setValue(0);
- }
+ Q_ASSERT(progress >= 0);
+ Q_ASSERT(total >= 0);
+ m_progressBar->setRange(0, total);
+ m_progressBar->setValue(progress);
}
void NewResultPage::Private::keepOpenWhenDone(bool)
diff --git a/src/crypto/task.cpp b/src/crypto/task.cpp
index 82daafb..2822b84 100644
--- a/src/crypto/task.cpp
+++ b/src/crypto/task.cpp
@@ -32,6 +32,8 @@
#include <config-kleopatra.h>
+#include "kleopatra_debug.h"
+
#include "task.h"
#include "task_p.h"
@@ -104,7 +106,8 @@ public:
private:
QString m_progressLabel;
- double m_processedPercent;
+ int m_progress;
+ int m_totalProgress;
bool m_asciiArmor;
int m_id;
};
@@ -115,7 +118,7 @@ static int nextTaskId = 0;
}
Task::Private::Private(Task *qq)
- : q(qq), m_progressLabel(), m_processedPercent(0.0), m_asciiArmor(false), m_id(nextTaskId++)
+ : q(qq), m_progressLabel(), m_progress(0), m_totalProgress(0), m_asciiArmor(false), m_id(nextTaskId++)
{
}
@@ -150,14 +153,14 @@ int Task::id() const
return d->m_id;
}
-unsigned long long Task::processedSize() const
+int Task::currentProgress() const
{
- return qRound(d->m_processedPercent * totalSize());
+ return d->m_progress;
}
-unsigned long long Task::totalSize() const
+int Task::totalProgress() const
{
- return inputSize();
+ return d->m_totalProgress;
}
QString Task::tag() const
@@ -172,10 +175,10 @@ QString Task::progressLabel() const
void Task::setProgress(const QString &label, int processed, int total)
{
- const double percent = total > 0 ? static_cast<double>(processed) / total : 0.0;
- d->m_processedPercent = percent;
+ d->m_progress = processed;
+ d->m_totalProgress = total;
d->m_progressLabel = label;
- Q_EMIT progress(label, processedSize(), totalSize());
+ Q_EMIT progress(label, processed, total);
}
void Task::start()
@@ -201,8 +204,8 @@ void Task::emitError(int errCode, const QString &details)
void Task::emitResult(const shared_ptr<const Task::Result> &r)
{
- d->m_processedPercent = 1.0;
- Q_EMIT progress(progressLabel(), processedSize(), totalSize());
+ d->m_progress = d->m_totalProgress;
+ Q_EMIT progress(progressLabel(), currentProgress(), totalProgress());
Q_EMIT result(r);
}
diff --git a/src/crypto/task.h b/src/crypto/task.h
index 37c9851..8b0289a 100644
--- a/src/crypto/task.h
+++ b/src/crypto/task.h
@@ -73,8 +73,8 @@ public:
virtual QString tag() const;
QString progressLabel() const;
- unsigned long long processedSize() const;
- unsigned long long totalSize() const;
+ int currentProgress() const;
+ int totalProgress() const;
int id() const;
diff --git a/src/crypto/taskcollection.cpp b/src/crypto/taskcollection.cpp
index 07bc1d2..8cb6e5a 100644
--- a/src/crypto/taskcollection.cpp
+++ b/src/crypto/taskcollection.cpp
@@ -32,9 +32,12 @@
#include <config-kleopatra.h>
+#include "kleopatra_debug.h"
+
#include "taskcollection.h"
-#include <crypto/task.h>
+#include "crypto/task.h"
+#include "utils/gnupg-helper.h"
#include <boost/bind.hpp>
@@ -60,15 +63,15 @@ public:
void calculateAndEmitProgress();
std::map<int, shared_ptr<Task> > m_tasks;
- mutable int m_totalSize;
- mutable int m_processedSize;
+ mutable quint64 m_totalProgress;
+ mutable quint64 m_progress;
unsigned int m_nCompleted;
QString m_lastProgressMessage;
bool m_errorOccurred;
bool m_doneEmitted;
};
-TaskCollection::Private::Private(TaskCollection *qq) : q(qq), m_totalSize(0), m_processedSize(0), m_nCompleted(0), m_errorOccurred(false), m_doneEmitted(false)
+TaskCollection::Private::Private(TaskCollection *qq) : q(qq), m_totalProgress(0), m_progress(0), m_nCompleted(0), m_errorOccurred(false), m_doneEmitted(false)
{
}
@@ -121,34 +124,51 @@ void TaskCollection::Private::calculateAndEmitProgress()
{
typedef std::map<int, shared_ptr<Task> >::const_iterator ConstIterator;
- int total = 0;
- int processed = 0;
- uint knownSize = m_tasks.size();
+ quint64 total = 0;
+ quint64 processed = 0;
+
+ static bool haveWorkingProgress = hasFeature(0, GpgME::ProgressForCallbacks) && engineIsVersion(2, 1, 15);
+ if (!haveWorkingProgress) {
+ // GnuPG before 2.1.15 would overflow on progress values > max int.
+ // and did not emit a total for our Qt data types.
+ // As we can't know if it overflowed or what the total is we just knight
+ // rider in that case
+ if (m_doneEmitted) {
+ Q_EMIT q->progress(m_lastProgressMessage, 1, 1);
+ } else {
+ Q_EMIT q->progress(m_lastProgressMessage, 0, 0);
+ }
+ return;
+ }
+ bool unknowable = false;
for (ConstIterator it = m_tasks.begin(), end = m_tasks.end(); it != end; ++it) {
+ // Sum up progress and totals
const shared_ptr<Task> &i = it->second;
assert(i);
- if (i->totalSize() == 0) {
- --knownSize;
+ if (!i->totalProgress()) {
+ // There still might be jobs for which we don't know the progress.
+ qCDebug(KLEOPATRA_LOG) << "Task: " << i->label() << " has no total progress set. ";
+ unknowable = true;
+ break;
}
- processed += i->processedSize();
- total += i->totalSize();
- }
- // use the average of the known sizes to estimate the unknown ones:
- if (knownSize > 0) {
- total += static_cast<int>(std::ceil((m_tasks.size() - knownSize) * (static_cast<double>(total) / knownSize)));
+ processed += i->currentProgress();
+ total += i->totalProgress();
}
- if (m_totalSize == total && m_processedSize == processed) {
- return;
- }
- m_totalSize = total;
- m_processedSize = processed;
- if (processed) {
- Q_EMIT q->progress(m_lastProgressMessage, processed, total);
- } else
- // use knight-rider mode until we have some progress
- {
- Q_EMIT q->progress(m_lastProgressMessage, processed, 0);
+
+ m_totalProgress = total;
+ m_progress = processed;
+ if (!unknowable && processed && total >= processed) {
+ // Scale down to a promille value to avoid range issues.
+ int scaled = 1000 * (m_progress / static_cast<double>(m_totalProgress));
+ qCDebug(KLEOPATRA_LOG) << "Collection Progress: " << scaled << " total: " << 1000;
+ Q_EMIT q->progress(m_lastProgressMessage, scaled, 1000);
+ } else {
+ if (total < processed) {
+ qCDebug(KLEOPATRA_LOG) << "Total progress is smaller then current progress.";
+ }
+ // Knight rider.
+ Q_EMIT q->progress(m_lastProgressMessage, 0, 0);
}
}