feat: Improve fingerprint comparison dialog, to show both remote and local prints (server is always on left of dialog)

fixes: #8866
This commit is contained in:
sithlord48 2025-08-24 00:33:06 -04:00 committed by Chris Rizzitello
parent 66366dd95b
commit d864361085
3 changed files with 100 additions and 44 deletions

View file

@ -525,8 +525,7 @@ void MainWindow::updateSize()
void MainWindow::showMyFingerprint() void MainWindow::showMyFingerprint()
{ {
Fingerprint sha256Print = localFingerprint(); FingerprintDialog fingerprintDialog(this, localFingerprint());
FingerprintDialog fingerprintDialog(this, sha256Print);
fingerprintDialog.exec(); fingerprintDialog.exec();
} }
@ -878,10 +877,8 @@ void MainWindow::checkFingerprint(const QString &line)
m_checkedClients.append(sha256Text); m_checkedClients.append(sha256Text);
} }
auto dialogMode = isClient ? FingerprintDialogMode::Client : FingerprintDialogMode::Server; auto mode = isClient ? FingerprintDialogMode::Client : FingerprintDialogMode::Server;
FingerprintDialog fingerprintDialog(this, localFingerprint(), mode, sha256);
FingerprintDialog fingerprintDialog(this, sha256, dialogMode);
connect(&fingerprintDialog, &FingerprintDialog::requestLocalPrintsDialog, this, &MainWindow::showMyFingerprint);
if (fingerprintDialog.exec() == QDialog::Accepted) { if (fingerprintDialog.exec() == QDialog::Accepted) {
db.addTrusted(sha256); db.addTrusted(sha256);

View file

@ -13,65 +13,120 @@
#include <QPushButton> #include <QPushButton>
#include <QVBoxLayout> #include <QVBoxLayout>
FingerprintDialog::FingerprintDialog(QWidget *parent, const Fingerprint &fingerprint, FingerprintDialogMode mode) FingerprintDialog::FingerprintDialog(
QWidget *parent, const Fingerprint &localFingerprint, FingerprintDialogMode mode,
const Fingerprint &remoteFingerprint
)
: QDialog(parent), : QDialog(parent),
m_lblHeader{new QLabel(this)}, m_lblHeader{new QLabel(this)},
m_lblFooter{new QLabel(this)}, m_lblFooter{new QLabel(this)},
m_fingerprintPreview{new FingerprintPreview(this, fingerprint)}, m_buttonBox{new QDialogButtonBox(QDialogButtonBox::Help, this)}
m_buttonBox{new QDialogButtonBox(this)}
{ {
setWindowIcon(QIcon::fromTheme("fingerprint"));
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
m_lblHeader->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
m_lblHeader->setWordWrap(true); const bool localMode = mode == FingerprintDialogMode::Local;
m_lblFooter->setWordWrap(true); const bool isServer = mode == FingerprintDialogMode::Server;
m_lblFooter->setAlignment(Qt::AlignHCenter);
auto layout = new QVBoxLayout(); auto layout = new QVBoxLayout();
layout->addWidget(m_lblHeader); layout->addWidget(m_lblHeader);
layout->addSpacerItem(new QSpacerItem(0, 10, QSizePolicy::Fixed, QSizePolicy::Fixed)); 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_lblFooter);
layout->addWidget(m_buttonBox); layout->addWidget(m_buttonBox);
setLayout(layout); setLayout(layout);
if (mode == FingerprintDialogMode::Local) { if (localMode) {
setWindowTitle(tr("Local Fingerprints")); setWindowTitle(tr("Local Fingerprints"));
m_lblHeader->setText(tr("Local computer's fingerprints")); setWindowIcon(QIcon::fromTheme("fingerprint"));
m_lblHeader->setWordWrap(false);
m_lblFooter->setVisible(false); m_lblHeader->setText(tr("Local computer's fingerprint"));
m_buttonBox->setStandardButtons(QDialogButtonBox::Ok);
m_buttonBox->addButton(QDialogButtonBox::Ok);
connect(m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &QDialog::accept); connect(m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &QDialog::accept);
} else { } else {
setWindowTitle(tr("Security Question")); setWindowIcon(QIcon::fromTheme("question"));
m_lblHeader->setAlignment(Qt::AlignHCenter);
m_lblFooter->setAlignment(Qt::AlignHCenter);
auto body = auto body =
tr("Compare the fingerprints in this dialog to those on the %1.\n" tr("Compare the fingerprints in this dialog to those on the %1.\n"
"Only connect if they match!"); "Only connect if they match!");
if (mode == FingerprintDialogMode::Server) { if (isServer) {
m_lblHeader->setText(tr("A new client is connecting.\n%1").arg(body.arg(tr("client")))); 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")); m_lblFooter->setText(tr("\nDo you want connect to and trust the client?\n"));
} else { } 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_lblFooter->setText(tr("\nDo you want connect to the server?\n"));
} }
m_buttonBox->setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::Yes | QDialogButtonBox::No); m_buttonBox->addButton(QDialogButtonBox::Yes);
m_buttonBox->addButton(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->button(QDialogButtonBox::No)->setFocus(); m_buttonBox->button(QDialogButtonBox::No)->setFocus();
connect(m_buttonBox->button(QDialogButtonBox::No), &QPushButton::clicked, this, &QDialog::reject); connect(m_buttonBox->button(QDialogButtonBox::No), &QPushButton::clicked, this, &QDialog::reject);
connect(m_buttonBox->button(QDialogButtonBox::Yes), &QPushButton::clicked, this, &QDialog::accept); 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(); adjustSize();
setFixedSize(size()); 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);
}

View file

@ -11,6 +11,9 @@
#include <QDialog> #include <QDialog>
#include <QDialogButtonBox> #include <QDialogButtonBox>
class QLabel;
class FingerprintPreview;
enum class FingerprintDialogMode enum class FingerprintDialogMode
{ {
Local, Local,
@ -18,26 +21,27 @@ enum class FingerprintDialogMode
Server Server
}; };
class QLabel;
class FingerprintPreview;
class FingerprintDialog : public QDialog class FingerprintDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit FingerprintDialog( explicit FingerprintDialog(
QWidget *parent = nullptr, const Fingerprint &fingerprint = {}, QWidget *parent = nullptr, const Fingerprint &localFingerprint = {},
FingerprintDialogMode mode = FingerprintDialogMode::Local FingerprintDialogMode mode = FingerprintDialogMode::Local, const Fingerprint &remoteFingerprint = {}
); );
~FingerprintDialog() override = default; ~FingerprintDialog() override = default;
Q_SIGNALS:
void requestLocalPrintsDialog();
private: 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_lblHeader = nullptr;
QLabel *m_lblFooter = nullptr; QLabel *m_lblFooter = nullptr;
FingerprintPreview *m_fingerprintPreview = nullptr; FingerprintPreview *m_localPreview = nullptr;
FingerprintPreview *m_remotePreview = nullptr;
QDialogButtonBox *m_buttonBox = nullptr; QDialogButtonBox *m_buttonBox = nullptr;
}; };