Index: src/widgets/checksumswidget.ui =================================================================== --- src/widgets/checksumswidget.ui +++ 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
kseparator.h
+ 1 + + + KCollapsibleGroupBox + QWidget +
kcollapsiblegroupbox.h
+ 1
Index: src/widgets/kpropertiesdialog.cpp =================================================================== --- src/widgets/kpropertiesdialog.cpp +++ src/widgets/kpropertiesdialog.cpp @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -2647,44 +2648,48 @@ Ui::ChecksumsWidget m_ui; QFileSystemWatcher fileWatcher; - QString m_md5; - QString m_sha1; - QString m_sha256; + QMap cache; }; 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,132 +2709,79 @@ 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::verifyChecksumRecursive(const QString input, QVector algorithms) { - auto label = new QLabel(i18nc("@action:button", "Calculating..."), &d->m_widget); - label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); - - d->m_ui.calculateWidget->layout()->replaceWidget(d->m_ui.md5Button, label); - d->m_ui.md5Button->hide(); - - showChecksum(QCryptographicHash::Md5, label, d->m_ui.md5CopyButton); -} - -void KChecksumsPlugin::slotShowSha1() -{ - auto label = new QLabel(i18nc("@action:button", "Calculating..."), &d->m_widget); - label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); - - d->m_ui.calculateWidget->layout()->replaceWidget(d->m_ui.sha1Button, label); - d->m_ui.sha1Button->hide(); - - showChecksum(QCryptographicHash::Sha1, label, d->m_ui.sha1CopyButton); -} - -void KChecksumsPlugin::slotShowSha256() -{ - auto label = new QLabel(i18nc("@action:button", "Calculating..."), &d->m_widget); - label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); - - d->m_ui.calculateWidget->layout()->replaceWidget(d->m_ui.sha256Button, label); - d->m_ui.sha256Button->hide(); - - showChecksum(QCryptographicHash::Sha256, label, d->m_ui.sha256CopyButton); -} - -void KChecksumsPlugin::slotVerifyChecksum(const QString &input) -{ - auto algorithm = detectAlgorithm(input); - - // Input is not a supported hash algorithm. - if (algorithm == QCryptographicHash::Md4) { - if (input.isEmpty()) { - setDefaultState(); - } else { - setInvalidChecksumState(); - } + if (algorithms.isEmpty()){ return; } - const QString checksum = cachedChecksum(algorithm); + auto algorithm = algorithms.back(); + algorithms.pop_back(); - // Checksum alread in cache. - if (!checksum.isEmpty()) { - const bool isMatch = (checksum == input); - if (isMatch) { + const QString cache = cachedChecksum(algorithm); + + // Checksum already in cache. + if (!cache.isEmpty()) { + if (cache == input) { 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); + auto buttons = getButtons(algorithm); + auto calculateButton = buttons.first; + auto copyButton = buttons.second; + showChecksum(algorithm, calculateButton, copyButton); - 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) { + if (checksum == input) { setMatchState(); - } else { + } else if (algorithms.isEmpty()) { setMismatchState(); + } else { + verifyChecksumRecursive(input, algorithms); } }); - // 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) +void KChecksumsPlugin::slotVerifyChecksum(const QString &input) { - QRegularExpression regex(QStringLiteral("^[a-f0-9]{32}$")); - return regex.match(input).hasMatch(); -} + auto algorithms = detectAlgorithm(input); -bool KChecksumsPlugin::isSha1(const QString &input) -{ - QRegularExpression regex(QStringLiteral("^[a-f0-9]{40}$")); - return regex.match(input).hasMatch(); -} + // Input is not a supported hash algorithm. + if (algorithms.isEmpty()) { + if (input.isEmpty()) { + setDefaultState(); + } else { + setInvalidChecksumState(); + } + return; + } -bool KChecksumsPlugin::isSha256(const QString &input) -{ - QRegularExpression regex(QStringLiteral("^[a-f0-9]{64}$")); - return regex.match(input).hasMatch(); + // Notify the user about the background computation. + setVerifyState(); + + verifyChecksumRecursive(input, algorithms); } QString KChecksumsPlugin::computeChecksum(QCryptographicHash::Algorithm algorithm, const QString &path) @@ -2845,22 +2797,31 @@ return QString::fromLatin1(hash.result().toHex()); } -QCryptographicHash::Algorithm KChecksumsPlugin::detectAlgorithm(const QString &input) +QVector KChecksumsPlugin::detectAlgorithm(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,10 +2889,25 @@ d->m_ui.feedbackLabel->show(); } -void KChecksumsPlugin::showChecksum(QCryptographicHash::Algorithm algorithm, QLabel *label, QPushButton *copyButton) +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); + const QString checksum = cachedChecksum(algorithm); + // If it is placed in the Advanced groupBox then expand it + auto groupBox = dynamic_cast(label->parentWidget()); + if (groupBox) + groupBox->expand(); + // Checksum in cache, nothing else to do. if (!checksum.isEmpty()) { label->setText(checksum); @@ -2954,37 +2930,24 @@ 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; - } + d->cache.insert(algorithm, checksum); } class KUrlPropsPlugin::KUrlPropsPluginPrivate Index: src/widgets/kpropertiesdialog_p.h =================================================================== --- src/widgets/kpropertiesdialog_p.h +++ src/widgets/kpropertiesdialog_p.h @@ -30,8 +30,10 @@ #include "kpropertiesdialog.h" +#include #include +class QPushButton; class QComboBox; class QLabel; @@ -173,27 +175,26 @@ 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 verifyChecksumRecursive(const QString input, QVector algorithms); + static QString computeChecksum(QCryptographicHash::Algorithm algorithm, const QString &path); - static QCryptographicHash::Algorithm detectAlgorithm(const QString &input); + static QVector detectAlgorithm(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); + + std::pair getButtons(QCryptographicHash::Algorithm algorithm); QString cachedChecksum(QCryptographicHash::Algorithm algorithm) const; void cacheChecksum(const QString &checksum, QCryptographicHash::Algorithm algorithm);