From d86436108537845ccb93123af8ef430e7bdc9439 Mon Sep 17 00:00:00 2001 From: sithlord48 Date: Sun, 24 Aug 2025 00:33:06 -0400 Subject: [PATCH] feat: Improve fingerprint comparison dialog, to show both remote and local prints (server is always on left of dialog) fixes: #8866 --- src/lib/gui/MainWindow.cpp | 9 +- src/lib/gui/dialogs/FingerprintDialog.cpp | 113 ++++++++++++++++------ src/lib/gui/dialogs/FingerprintDialog.h | 22 +++-- 3 files changed, 100 insertions(+), 44 deletions(-) diff --git a/src/lib/gui/MainWindow.cpp b/src/lib/gui/MainWindow.cpp index 1560f14c0..d7ec9dcb1 100644 --- a/src/lib/gui/MainWindow.cpp +++ b/src/lib/gui/MainWindow.cpp @@ -525,8 +525,7 @@ void MainWindow::updateSize() void MainWindow::showMyFingerprint() { - Fingerprint sha256Print = localFingerprint(); - FingerprintDialog fingerprintDialog(this, sha256Print); + FingerprintDialog fingerprintDialog(this, localFingerprint()); fingerprintDialog.exec(); } @@ -878,10 +877,8 @@ void MainWindow::checkFingerprint(const QString &line) m_checkedClients.append(sha256Text); } - auto dialogMode = isClient ? FingerprintDialogMode::Client : FingerprintDialogMode::Server; - - FingerprintDialog fingerprintDialog(this, sha256, dialogMode); - connect(&fingerprintDialog, &FingerprintDialog::requestLocalPrintsDialog, this, &MainWindow::showMyFingerprint); + auto mode = isClient ? FingerprintDialogMode::Client : FingerprintDialogMode::Server; + FingerprintDialog fingerprintDialog(this, localFingerprint(), mode, sha256); if (fingerprintDialog.exec() == QDialog::Accepted) { db.addTrusted(sha256); diff --git a/src/lib/gui/dialogs/FingerprintDialog.cpp b/src/lib/gui/dialogs/FingerprintDialog.cpp index e81938eeb..fd61f3cf3 100644 --- a/src/lib/gui/dialogs/FingerprintDialog.cpp +++ b/src/lib/gui/dialogs/FingerprintDialog.cpp @@ -13,65 +13,120 @@ #include #include -FingerprintDialog::FingerprintDialog(QWidget *parent, const Fingerprint &fingerprint, FingerprintDialogMode mode) +FingerprintDialog::FingerprintDialog( + QWidget *parent, const Fingerprint &localFingerprint, FingerprintDialogMode mode, + const Fingerprint &remoteFingerprint +) : QDialog(parent), m_lblHeader{new QLabel(this)}, m_lblFooter{new QLabel(this)}, - m_fingerprintPreview{new FingerprintPreview(this, fingerprint)}, - m_buttonBox{new QDialogButtonBox(this)} + m_buttonBox{new QDialogButtonBox(QDialogButtonBox::Help, this)} { - setWindowIcon(QIcon::fromTheme("fingerprint")); setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_lblHeader->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - m_lblHeader->setWordWrap(true); - m_lblFooter->setWordWrap(true); - m_lblFooter->setAlignment(Qt::AlignHCenter); + const bool localMode = mode == FingerprintDialogMode::Local; + const bool isServer = mode == FingerprintDialogMode::Server; auto layout = new QVBoxLayout(); layout->addWidget(m_lblHeader); layout->addSpacerItem(new QSpacerItem(0, 10, QSizePolicy::Fixed, QSizePolicy::Fixed)); - layout->addWidget(m_fingerprintPreview, 0, Qt::AlignTop | Qt::AlignHCenter); + layout->addLayout( + localMode ? makeLocalLayout(localFingerprint) : makeCompareLayout(localFingerprint, isServer, remoteFingerprint) + ); layout->addWidget(m_lblFooter); layout->addWidget(m_buttonBox); setLayout(layout); - if (mode == FingerprintDialogMode::Local) { + if (localMode) { setWindowTitle(tr("Local Fingerprints")); - m_lblHeader->setText(tr("Local computer's fingerprints")); - m_lblHeader->setWordWrap(false); - m_lblFooter->setVisible(false); - m_buttonBox->setStandardButtons(QDialogButtonBox::Ok); + setWindowIcon(QIcon::fromTheme("fingerprint")); + + m_lblHeader->setText(tr("Local computer's fingerprint")); + + m_buttonBox->addButton(QDialogButtonBox::Ok); connect(m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &QDialog::accept); + } else { - setWindowTitle(tr("Security Question")); + setWindowIcon(QIcon::fromTheme("question")); + m_lblHeader->setAlignment(Qt::AlignHCenter); + m_lblFooter->setAlignment(Qt::AlignHCenter); + auto body = tr("Compare the fingerprints in this dialog to those on the %1.\n" "Only connect if they match!"); - if (mode == FingerprintDialogMode::Server) { - m_lblHeader->setText(tr("A new client is connecting.\n%1").arg(body.arg(tr("client")))); + if (isServer) { + setWindowTitle(tr("New client connecting")); + m_lblHeader->setText(body.arg(tr("client"))); m_lblFooter->setText(tr("\nDo you want connect to and trust the client?\n")); } else { - m_lblHeader->setText(tr("You are connecting to a new server.\n%1").arg(body.arg(tr("server")))); + setWindowTitle(tr("Connecting to a new server")); + m_lblHeader->setText(body.arg(tr("server"))); m_lblFooter->setText(tr("\nDo you want connect to the server?\n")); } - m_buttonBox->setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::Yes | QDialogButtonBox::No); - - // Use help to request a dialog with the host prints - // Help is used because its always to the furthest from the other buttons. - m_buttonBox->button(QDialogButtonBox::Help)->setText(tr("View local fingerprints")); - m_buttonBox->button(QDialogButtonBox::Help)->setIcon(QIcon::fromTheme("fingerprint")); - m_buttonBox->button(QDialogButtonBox::Help)->setToolTip(tr("Show the local machines fingerprints")); - connect( - m_buttonBox->button(QDialogButtonBox::Help), &QPushButton::clicked, this, - &FingerprintDialog::requestLocalPrintsDialog - ); - + m_buttonBox->addButton(QDialogButtonBox::Yes); + m_buttonBox->addButton(QDialogButtonBox::No); m_buttonBox->button(QDialogButtonBox::No)->setFocus(); connect(m_buttonBox->button(QDialogButtonBox::No), &QPushButton::clicked, this, &QDialog::reject); connect(m_buttonBox->button(QDialogButtonBox::Yes), &QPushButton::clicked, this, &QDialog::accept); } + + updateModeButton(false); + m_buttonBox->button(QDialogButtonBox::Help)->setCheckable(true); + m_buttonBox->button(QDialogButtonBox::Help)->setIcon(QIcon()); + connect( + m_buttonBox->button(QDialogButtonBox::Help), &QPushButton::toggled, this, &FingerprintDialog::togglePreviewMode + ); + adjustSize(); setFixedSize(size()); } + +QLayout *FingerprintDialog::makeLocalLayout(const Fingerprint &localFingerprint) +{ + m_localPreview = new FingerprintPreview(this, localFingerprint); + + auto layout = new QVBoxLayout(); + layout->addWidget(m_localPreview, 0, Qt::AlignTop | Qt::AlignHCenter); + return layout; +} + +QLayout *FingerprintDialog::makeCompareLayout( + const Fingerprint &localFingerprint, bool isServer, const Fingerprint &remoteFingerprint +) +{ + const auto serverText = tr("Server Fingerprint"); + const auto clientText = tr("Client Fingerprint"); + + m_localPreview = new FingerprintPreview(this, localFingerprint, isServer ? serverText : clientText, false); + m_remotePreview = new FingerprintPreview(this, remoteFingerprint, isServer ? clientText : serverText, false); + + auto fpLayout = new QHBoxLayout(); + fpLayout->setAlignment(Qt::AlignTop); + if (isServer) { + fpLayout->addWidget(m_localPreview, 0, Qt::AlignHCenter); + fpLayout->addWidget(m_remotePreview, 0, Qt::AlignHCenter); + } else { + fpLayout->addWidget(m_remotePreview, 0, Qt::AlignHCenter); + fpLayout->addWidget(m_localPreview, 0, Qt::AlignHCenter); + } + return fpLayout; +} + +void FingerprintDialog::togglePreviewMode(bool hashMode) +{ + m_localPreview->toggleMode(hashMode); + if (m_remotePreview) + m_remotePreview->toggleMode(hashMode); + updateModeButton(hashMode); +} + +void FingerprintDialog::updateModeButton(bool hashMode) const +{ + const auto text = tr("Show %1").arg(hashMode ? "Image" : "Hash"); + const auto toolTip = tr("Display the fingerprint as %1").arg(hashMode ? "an image" : "a hash"); + m_buttonBox->button(QDialogButtonBox::Help)->setText(text); + m_buttonBox->button(QDialogButtonBox::Help)->setToolTip(toolTip); +} diff --git a/src/lib/gui/dialogs/FingerprintDialog.h b/src/lib/gui/dialogs/FingerprintDialog.h index d7e0b3af5..aba2dce60 100644 --- a/src/lib/gui/dialogs/FingerprintDialog.h +++ b/src/lib/gui/dialogs/FingerprintDialog.h @@ -11,6 +11,9 @@ #include #include +class QLabel; +class FingerprintPreview; + enum class FingerprintDialogMode { Local, @@ -18,26 +21,27 @@ enum class FingerprintDialogMode Server }; -class QLabel; -class FingerprintPreview; - class FingerprintDialog : public QDialog { Q_OBJECT public: explicit FingerprintDialog( - QWidget *parent = nullptr, const Fingerprint &fingerprint = {}, - FingerprintDialogMode mode = FingerprintDialogMode::Local + QWidget *parent = nullptr, const Fingerprint &localFingerprint = {}, + FingerprintDialogMode mode = FingerprintDialogMode::Local, const Fingerprint &remoteFingerprint = {} ); ~FingerprintDialog() override = default; -Q_SIGNALS: - void requestLocalPrintsDialog(); - private: + QLayout *makeLocalLayout(const Fingerprint &localFingerprint = {}); + QLayout *makeCompareLayout( + const Fingerprint &localFingerprint = {}, bool isServer = true, const Fingerprint &remoteFingerprint = {} + ); + void togglePreviewMode(bool hashMode); + void updateModeButton(bool hashMode) const; QLabel *m_lblHeader = nullptr; QLabel *m_lblFooter = nullptr; - FingerprintPreview *m_fingerprintPreview = nullptr; + FingerprintPreview *m_localPreview = nullptr; + FingerprintPreview *m_remotePreview = nullptr; QDialogButtonBox *m_buttonBox = nullptr; };