diff --git a/src/widgets/checksumswidget.ui b/src/widgets/checksumswidget.ui
--- a/src/widgets/checksumswidget.ui
+++ b/src/widgets/checksumswidget.ui
@@ -23,7 +23,7 @@
-
- Expected checksum (MD5, SHA1 or SHA256)...
+ Expected checksum (MD5, SHA1-SHA512, etc.)
@@ -57,30 +57,23 @@
-
-
+
MD5:
- -
-
-
- SHA1:
-
-
-
- -
-
+
-
+
-
-
+
Calculate
-
-
+
Qt::Horizontal
@@ -93,7 +86,7 @@
-
-
+
Click to copy the checksum to the clipboard.
@@ -108,24 +101,24 @@
- -
-
+
-
+
- SHA256:
+ SHA1:
- -
-
+
-
+
-
-
+
Calculate
-
-
+
Qt::Horizontal
@@ -138,7 +131,7 @@
-
-
+
Click to copy the checksum to the clipboard.
@@ -153,17 +146,24 @@
- -
-
+
-
+
+
+ SHA256:
+
+
+
+ -
+
-
-
+
Calculate
-
-
+
Qt::Horizontal
@@ -176,7 +176,7 @@
-
-
+
Click to copy the checksum to the clipboard.
@@ -191,6 +191,384 @@
+ -
+
+
+
+ 0
+ 22
+
+
+
+ Advanced
+
+
+ false
+
+
+
-
+
+
+ MD4:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+ -
+
+
+ SHA224:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+ -
+
+
+ SHA384:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+ -
+
+
+ SHA512:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+ -
+
+
+ SHA3-224:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+ -
+
+
+ SHA3-256:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+ -
+
+
+ SHA3-384:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+ -
+
+
+ SHA3-512:
+
+
+
+ -
+
+
-
+
+
+ Calculate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Click to copy the checksum to the clipboard.
+
+
+ Copy
+
+
+
+ ..
+
+
+
+
+
+
+
+
@@ -214,6 +592,13 @@
KSeparator
QFrame
+ 1
+
+
+ KCollapsibleGroupBox
+ QWidget
+
+ 1
diff --git a/src/widgets/kpropertiesdialog.cpp b/src/widgets/kpropertiesdialog.cpp
--- a/src/widgets/kpropertiesdialog.cpp
+++ b/src/widgets/kpropertiesdialog.cpp
@@ -53,6 +53,7 @@
#include
#include
+#include
#include
#include
#include
@@ -67,6 +68,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -2647,44 +2649,49 @@
Ui::ChecksumsWidget m_ui;
QFileSystemWatcher fileWatcher;
- QString m_md5;
- QString m_sha1;
- QString m_sha256;
+ QMap cache;
+ mutable QMutex mutex;
};
KChecksumsPlugin::KChecksumsPlugin(KPropertiesDialog *dialog)
: KPropertiesDialogPlugin(dialog), d(new KChecksumsPluginPrivate)
{
d->m_ui.setupUi(&d->m_widget);
- properties->addPage(&d->m_widget, i18nc("@title:tab", "C&hecksums"));
-
- d->m_ui.md5CopyButton->hide();
- d->m_ui.sha1CopyButton->hide();
- d->m_ui.sha256CopyButton->hide();
+ properties->addPage(&d->m_widget, i18nc("@title:tab", "Checksums"));
connect(d->m_ui.lineEdit, &QLineEdit::textChanged, this, [=](const QString &text) {
slotVerifyChecksum(text.toLower());
});
- connect(d->m_ui.md5Button, &QPushButton::clicked, this, &KChecksumsPlugin::slotShowMd5);
- connect(d->m_ui.sha1Button, &QPushButton::clicked, this, &KChecksumsPlugin::slotShowSha1);
- connect(d->m_ui.sha256Button, &QPushButton::clicked, this, &KChecksumsPlugin::slotShowSha256);
-
d->fileWatcher.addPath(properties->item().localPath());
connect(&d->fileWatcher, &QFileSystemWatcher::fileChanged, this, &KChecksumsPlugin::slotInvalidateCache);
auto clipboard = QApplication::clipboard();
- connect(d->m_ui.md5CopyButton, &QPushButton::clicked, this, [=]() {
- clipboard->setText(d->m_md5);
- });
- connect(d->m_ui.sha1CopyButton, &QPushButton::clicked, this, [=]() {
- clipboard->setText(d->m_sha1);
- });
-
- connect(d->m_ui.sha256CopyButton, &QPushButton::clicked, this, [=]() {
- clipboard->setText(d->m_sha256);
- });
+ for(const auto alg : {
+ QCryptographicHash::Md4,
+ QCryptographicHash::Md5,
+ QCryptographicHash::Sha1,
+ QCryptographicHash::Sha224,
+ QCryptographicHash::Sha256,
+ QCryptographicHash::Sha384,
+ QCryptographicHash::Sha512,
+ QCryptographicHash::Sha3_224,
+ QCryptographicHash::Sha3_256,
+ QCryptographicHash::Sha3_384,
+ QCryptographicHash::Sha3_512
+ }) {
+ auto buttons = getButtons(alg);
+ auto calculateButton = buttons.first;
+ auto copyButton = buttons.second;
+ connect(calculateButton, &QPushButton::clicked, this, [=]() {
+ showChecksum(alg, calculateButton, copyButton);
+ });
+ copyButton->hide();
+ connect(copyButton, &QPushButton::clicked, this, [=]() {
+ clipboard->setText(d->cache.value(alg, ""));
+ });
+ }
connect(d->m_ui.pasteButton, &QPushButton::clicked, this, [=]() {
d->m_ui.lineEdit->setText(clipboard->text());
@@ -2704,56 +2711,63 @@
return false;
}
- const KFileItem item = items.first();
+ const auto& item = items.first();
return item.isFile() && item.isLocalFile() && item.isReadable() && !item.isDesktopFile() && !item.isLink();
}
void KChecksumsPlugin::slotInvalidateCache()
{
- d->m_md5 = QString();
- d->m_sha1 = QString();
- d->m_sha256 = QString();
+ d->cache.clear();
}
-void KChecksumsPlugin::slotShowMd5()
+void KChecksumsPlugin::verifyChecksums(const QString input, QVector algorithms)
{
- auto label = new QLabel(i18nc("@action:button", "Calculating..."), &d->m_widget);
- label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
+ if (algorithms.isEmpty()) {
+ return;
+ }
- d->m_ui.calculateWidget->layout()->replaceWidget(d->m_ui.md5Button, label);
- d->m_ui.md5Button->hide();
+ auto futureWatcher = new QFutureWatcher(this);
- showChecksum(QCryptographicHash::Md5, label, d->m_ui.md5CopyButton);
-}
+ connect(futureWatcher, &QFutureWatcher::finished, this, [=]() {
+ const bool match = futureWatcher->result();
+ futureWatcher->deleteLater();
-void KChecksumsPlugin::slotShowSha1()
-{
- auto label = new QLabel(i18nc("@action:button", "Calculating..."), &d->m_widget);
- label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
+ showChecksums();
- d->m_ui.calculateWidget->layout()->replaceWidget(d->m_ui.sha1Button, label);
- d->m_ui.sha1Button->hide();
+ if (match) {
+ setMatchState();
+ } else {
+ setMismatchState();
+ }
+ });
- showChecksum(QCryptographicHash::Sha1, label, d->m_ui.sha1CopyButton);
-}
+ std::function mapper = [this](QCryptographicHash::Algorithm alg) {
+ const QString cache = cachedChecksum(alg);
+ if (!cache.isEmpty()) {
+ return cache;
+ }
-void KChecksumsPlugin::slotShowSha256()
-{
- auto label = new QLabel(i18nc("@action:button", "Calculating..."), &d->m_widget);
- label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
+ const QString checksum = computeChecksum(alg, properties->item().localPath());
+ cacheChecksum(checksum, alg);
+
+ return checksum;
+ };
- d->m_ui.calculateWidget->layout()->replaceWidget(d->m_ui.sha256Button, label);
- d->m_ui.sha256Button->hide();
+ std::function reducer = [input](bool& match, const QString& checksum) {
+ match |= checksum == input;
+ };
- showChecksum(QCryptographicHash::Sha256, label, d->m_ui.sha256CopyButton);
+ QFuture future = QtConcurrent::mappedReduced(algorithms, mapper, reducer);
+
+ futureWatcher->setFuture(future);
}
void KChecksumsPlugin::slotVerifyChecksum(const QString &input)
{
- auto algorithm = detectAlgorithm(input);
+ auto algorithms = detectAlgorithms(input);
// Input is not a supported hash algorithm.
- if (algorithm == QCryptographicHash::Md4) {
+ if (algorithms.isEmpty()) {
if (input.isEmpty()) {
setDefaultState();
} else {
@@ -2762,81 +2776,17 @@
return;
}
- const QString checksum = cachedChecksum(algorithm);
-
- // Checksum alread in cache.
- if (!checksum.isEmpty()) {
- const bool isMatch = (checksum == input);
- if (isMatch) {
- setMatchState();
- } else {
- setMismatchState();
- }
-
- return;
- }
-
- // Calculate checksum in another thread.
- auto futureWatcher = new QFutureWatcher(this);
- connect(futureWatcher, &QFutureWatcher::finished, this, [=]() {
-
- const QString checksum = futureWatcher->result();
- futureWatcher->deleteLater();
-
- cacheChecksum(checksum, algorithm);
-
- switch (algorithm) {
- case QCryptographicHash::Md5:
- slotShowMd5();
- break;
- case QCryptographicHash::Sha1:
- slotShowSha1();
- break;
- case QCryptographicHash::Sha256:
- slotShowSha256();
- break;
- default:
- break;
- }
-
- const bool isMatch = (checksum == input);
- if (isMatch) {
- setMatchState();
- } else {
- setMismatchState();
- }
- });
-
// Notify the user about the background computation.
setVerifyState();
- auto future = QtConcurrent::run(&KChecksumsPlugin::computeChecksum, algorithm, properties->item().localPath());
- futureWatcher->setFuture(future);
-}
-
-bool KChecksumsPlugin::isMd5(const QString &input)
-{
- QRegularExpression regex(QStringLiteral("^[a-f0-9]{32}$"));
- return regex.match(input).hasMatch();
-}
-
-bool KChecksumsPlugin::isSha1(const QString &input)
-{
- QRegularExpression regex(QStringLiteral("^[a-f0-9]{40}$"));
- return regex.match(input).hasMatch();
-}
-
-bool KChecksumsPlugin::isSha256(const QString &input)
-{
- QRegularExpression regex(QStringLiteral("^[a-f0-9]{64}$"));
- return regex.match(input).hasMatch();
+ verifyChecksums(input, algorithms);
}
QString KChecksumsPlugin::computeChecksum(QCryptographicHash::Algorithm algorithm, const QString &path)
{
QFile file(path);
if (!file.open(QIODevice::ReadOnly)) {
- return QString();
+ return {};
}
QCryptographicHash hash(algorithm);
@@ -2845,22 +2795,31 @@
return QString::fromLatin1(hash.result().toHex());
}
-QCryptographicHash::Algorithm KChecksumsPlugin::detectAlgorithm(const QString &input)
+QVector KChecksumsPlugin::detectAlgorithms(const QString &input)
{
- if (isMd5(input)) {
- return QCryptographicHash::Md5;
- }
+ static const QVector> regexes{
+ {QCryptographicHash::Md4, QRegularExpression("^[a-f0-9]{32}$")},
+ {QCryptographicHash::Md5, QRegularExpression("^[a-f0-9]{32}$")},
+ {QCryptographicHash::Sha1, QRegularExpression("^[a-f0-9]{40}$")},
+ {QCryptographicHash::Sha224, QRegularExpression("^[a-f0-9]{56}$")},
+ {QCryptographicHash::Sha256, QRegularExpression("^[a-f0-9]{64}$")},
+ {QCryptographicHash::Sha384, QRegularExpression("^[a-f0-9]{96}$")},
+ {QCryptographicHash::Sha512, QRegularExpression("^[a-f0-9]{128}$")},
+ {QCryptographicHash::Sha3_224, QRegularExpression("^[a-f0-9]{56}$")},
+ {QCryptographicHash::Sha3_256, QRegularExpression("^[a-f0-9]{64}$")},
+ {QCryptographicHash::Sha3_384, QRegularExpression("^[a-f0-9]{96}$")},
+ {QCryptographicHash::Sha3_512, QRegularExpression("^[a-f0-9]{128}$")}
+ };
- if (isSha1(input)) {
- return QCryptographicHash::Sha1;
- }
+ QVector algorithms;
- if (isSha256(input)) {
- return QCryptographicHash::Sha256;
+ for (const auto &p : regexes) {
+ if (p.second.match(input).hasMatch()) {
+ algorithms.push_back(p.first);
+ }
}
- // Md4 used as negative error code.
- return QCryptographicHash::Md4;
+ return algorithms;
}
void KChecksumsPlugin::setDefaultState()
@@ -2928,8 +2887,32 @@
d->m_ui.feedbackLabel->show();
}
-void KChecksumsPlugin::showChecksum(QCryptographicHash::Algorithm algorithm, QLabel *label, QPushButton *copyButton)
+void KChecksumsPlugin::showChecksums()
{
+ for (const auto alg : d->cache.keys()) {
+ auto buttons = getButtons(alg);
+ showChecksum(alg, buttons.first, buttons.second);
+ }
+}
+
+void KChecksumsPlugin::showChecksum(QCryptographicHash::Algorithm algorithm, QPushButton *calculateButton, QPushButton *copyButton)
+{
+ if (calculateButton == nullptr || copyButton == nullptr) {
+ return;
+ }
+
+ auto label = new QLabel(i18nc("@action:button", "Calculating..."), &d->m_widget);
+ label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
+
+ calculateButton->hide();
+ calculateButton->parentWidget()->layout()->replaceWidget(calculateButton, label);
+
+ // If it is placed in the "Advanced" KCollapsibleGroupBox then expand it
+ auto groupBox = dynamic_cast(label->parentWidget());
+ if (groupBox) {
+ groupBox->expand();
+ }
+
const QString checksum = cachedChecksum(algorithm);
// Checksum in cache, nothing else to do.
@@ -2954,37 +2937,25 @@
futureWatcher->setFuture(future);
}
-QString KChecksumsPlugin::cachedChecksum(QCryptographicHash::Algorithm algorithm) const
+std::pair KChecksumsPlugin::getButtons(QCryptographicHash::Algorithm algorithm)
{
- switch (algorithm) {
- case QCryptographicHash::Md5:
- return d->m_md5;
- case QCryptographicHash::Sha1:
- return d->m_sha1;
- case QCryptographicHash::Sha256:
- return d->m_sha256;
- default:
- break;
- }
+ QString name{QMetaEnum::fromType().valueToKey(algorithm)};
+ // TODO: Remove after QCryptographicHash::Algorithm is renamed from RealSha3 to Sha3
+ name.replace("Real", "");
+ auto calculateBtn = d->m_widget.findChild("calculate" + name);
+ auto copyBtn = d->m_widget.findChild("copy" + name);
+ return std::make_pair(calculateBtn, copyBtn);
+}
- return QString();
+QString KChecksumsPlugin::cachedChecksum(QCryptographicHash::Algorithm algorithm) const
+{
+ return d->cache.value(algorithm, QString{});
}
void KChecksumsPlugin::cacheChecksum(const QString &checksum, QCryptographicHash::Algorithm algorithm)
{
- switch (algorithm) {
- case QCryptographicHash::Md5:
- d->m_md5 = checksum;
- break;
- case QCryptographicHash::Sha1:
- d->m_sha1 = checksum;
- break;
- case QCryptographicHash::Sha256:
- d->m_sha256 = checksum;
- break;
- default:
- return;
- }
+ QMutexLocker locker(&d->mutex);
+ d->cache.insert(algorithm, checksum);
}
class KUrlPropsPlugin::KUrlPropsPluginPrivate
diff --git a/src/widgets/kpropertiesdialog_p.h b/src/widgets/kpropertiesdialog_p.h
--- a/src/widgets/kpropertiesdialog_p.h
+++ b/src/widgets/kpropertiesdialog_p.h
@@ -30,8 +30,10 @@
#include "kpropertiesdialog.h"
+#include
#include
+class QPushButton;
class QComboBox;
class QLabel;
@@ -173,27 +175,27 @@
private Q_SLOTS:
void slotInvalidateCache();
- void slotShowMd5();
- void slotShowSha1();
- void slotShowSha256();
+
/**
* Compare @p input (required to be lowercase) with the checksum in cache.
*/
void slotVerifyChecksum(const QString &input);
private:
- static bool isMd5(const QString &input);
- static bool isSha1(const QString &input);
- static bool isSha256(const QString &input);
+ void verifyChecksums(const QString input, QVector algorithms);
+
static QString computeChecksum(QCryptographicHash::Algorithm algorithm, const QString &path);
- static QCryptographicHash::Algorithm detectAlgorithm(const QString &input);
+ static QVector detectAlgorithms(const QString &input);
void setDefaultState();
void setInvalidChecksumState();
void setMatchState();
void setMismatchState();
void setVerifyState();
- void showChecksum(QCryptographicHash::Algorithm algorithm, QLabel *label, QPushButton *copyButton);
+ void showChecksum(QCryptographicHash::Algorithm algorithm, QPushButton *calculateButton, QPushButton *copyButton);
+ void showChecksums();
+
+ std::pair getButtons(QCryptographicHash::Algorithm algorithm);
QString cachedChecksum(QCryptographicHash::Algorithm algorithm) const;
void cacheChecksum(const QString &checksum, QCryptographicHash::Algorithm algorithm);