File indexing completed on 2024-05-05 05:50:42

0001 /*
0002     SPDX-FileCopyrightText: 2016 Ragnar Thomsen <rthomsen6@gmail.com>
0003 
0004     SPDX-License-Identifier: BSD-2-Clause
0005 */
0006 
0007 #include "propertiesdialog.h"
0008 #include "archive_kerfuffle.h"
0009 #include "ark_debug.h"
0010 #include "ui_propertiesdialog.h"
0011 
0012 #include <QDateTime>
0013 #include <QFileInfo>
0014 #include <QFontDatabase>
0015 #include <QFutureWatcher>
0016 #include <QIcon>
0017 #include <QtConcurrentRun>
0018 
0019 #include <KIO/Global>
0020 
0021 namespace Kerfuffle
0022 {
0023 class PropertiesDialogUI : public QWidget, public Ui::PropertiesDialog
0024 {
0025     Q_OBJECT
0026 
0027 public:
0028     PropertiesDialogUI(QWidget *parent = nullptr)
0029         : QWidget(parent)
0030     {
0031         setupUi(this);
0032     }
0033 };
0034 
0035 PropertiesDialog::PropertiesDialog(QWidget *parent, Archive *archive, qulonglong numberOfFiles, qulonglong numberOfFolders, qulonglong size)
0036     : QDialog(parent, Qt::Dialog)
0037 {
0038     setAttribute(Qt::WA_DeleteOnClose, true);
0039     QFileInfo fi(archive->fileName());
0040 
0041     setWindowTitle(i18nc("@title:window", "Properties for %1", fi.fileName()));
0042     setModal(true);
0043 
0044     m_ui = new PropertiesDialogUI(this);
0045     m_ui->lblArchiveName->setText(archive->fileName());
0046     m_ui->lblArchiveType->setText(archive->mimeType().comment());
0047     m_ui->lblMimetype->setText(archive->mimeType().name());
0048     m_ui->lblCompressionMethods->setText(archive->property("compressionMethods").toStringList().join(QLatin1String(", ")));
0049     m_ui->lblReadOnly->setText(archive->isReadOnly() ? i18n("yes") : i18n("no"));
0050     m_ui->lblMultiVolume->setText(archive->isMultiVolume() ? i18n("yes (%1 volumes)", archive->numberOfVolumes()) : i18n("no"));
0051     m_ui->lblHasComment->setText(archive->hasComment() ? i18n("yes") : i18n("no"));
0052     m_ui->lblNumberOfEntries->setText(i18np("%1 file", "%1 files", numberOfFiles) + i18np(", %1 folder", ", %1 folders", numberOfFolders));
0053     m_ui->lblUnpackedSize->setText(KIO::convertSize(size));
0054     m_ui->lblPackedSize->setText(KIO::convertSize(archive->packedSize()));
0055     m_ui->lblCompressionRatio->setText(QString::number(float(archive->unpackedSize()) / float(archive->packedSize()), 'f', 1));
0056     m_ui->lblLastModified->setText(fi.lastModified().toString(QStringLiteral("yyyy-MM-dd HH:mm")));
0057     m_ui->lblMD5->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
0058     m_ui->lblSHA1->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
0059     m_ui->lblSHA256->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
0060 
0061     switch (archive->encryptionType()) {
0062     case Archive::Unencrypted:
0063         m_ui->lblPasswordProtected->setText(i18n("no"));
0064         break;
0065     case Archive::Encrypted:
0066         m_ui->lblPasswordProtected->setText(i18n("only file contents (%1)", archive->property("encryptionMethods").toStringList().join(QLatin1String(", "))));
0067         break;
0068     case Archive::HeaderEncrypted:
0069         m_ui->lblPasswordProtected->setText(i18n("yes (%1)", archive->property("encryptionMethods").toStringList().join(QLatin1String(", "))));
0070         break;
0071     }
0072 
0073     // The Sha256 label is populated with 64 chars in the ui file. We fix the
0074     // size of the label so the dialog won't resize when the hashes are
0075     // calculated. This is an ugly hack and requires e.g. that we use monospace
0076     // font for the hashes.
0077     m_ui->lblSHA256->setMinimumSize(m_ui->lblSHA256->sizeHint());
0078 
0079     m_ui->adjustSize();
0080     setFixedSize(m_ui->size());
0081 
0082     // Show an icon representing the mimetype of the archive.
0083     QIcon icon = QIcon::fromTheme(archive->mimeType().iconName());
0084     m_ui->lblIcon->setPixmap(icon.pixmap(48));
0085 
0086     m_ui->lblMD5->setText(i18n("Calculating..."));
0087     m_ui->lblSHA1->setText(i18n("Calculating..."));
0088     m_ui->lblSHA256->setText(i18n("Calculating..."));
0089 
0090     showChecksum(QCryptographicHash::Md5, archive->fileName(), m_ui->lblMD5);
0091     showChecksum(QCryptographicHash::Sha1, archive->fileName(), m_ui->lblSHA1);
0092     showChecksum(QCryptographicHash::Sha256, archive->fileName(), m_ui->lblSHA256);
0093 
0094     connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
0095 }
0096 
0097 QString PropertiesDialog::calcHash(QCryptographicHash::Algorithm algorithm, const QString &path)
0098 {
0099     QFile file(path);
0100     if (!file.open(QIODevice::ReadOnly)) {
0101         return QString();
0102     }
0103 
0104     QCryptographicHash hash(algorithm);
0105     hash.addData(&file);
0106 
0107     return QString::fromLatin1(hash.result().toHex());
0108 }
0109 
0110 void PropertiesDialog::showChecksum(QCryptographicHash::Algorithm algorithm, const QString &fileName, QLabel *label)
0111 {
0112     // Calculate checksum in another thread.
0113     auto futureWatcher = new QFutureWatcher<QString>(this);
0114     connect(futureWatcher, &QFutureWatcher<QString>::finished, this, [=]() {
0115         label->setText(futureWatcher->result());
0116         futureWatcher->deleteLater();
0117     });
0118     auto future = QtConcurrent::run(&PropertiesDialog::calcHash, this, algorithm, fileName);
0119     futureWatcher->setFuture(future);
0120 }
0121 }
0122 
0123 #include "moc_propertiesdialog.cpp"
0124 #include "propertiesdialog.moc"