From 1ea4e2e69b405a15d6cf3f846ad58e5a85523131 Mon Sep 17 00:00:00 2001 From: Dmytro Maslenko Date: Tue, 31 Jan 2023 23:16:25 -0800 Subject: [PATCH] Scale and center QR code on window resizing * Also add GUI test for QR code resizing --- src/gui/SquareSvgWidget.cpp | 29 ++++++++++++++++++++++++++++ src/gui/SquareSvgWidget.h | 4 +++- src/gui/TotpExportSettingsDialog.cpp | 14 +++++++++----- src/gui/TotpExportSettingsDialog.h | 1 + tests/gui/TestGui.cpp | 15 ++++++++++++++ 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/gui/SquareSvgWidget.cpp b/src/gui/SquareSvgWidget.cpp index 5a907e95bf..b39cee9798 100644 --- a/src/gui/SquareSvgWidget.cpp +++ b/src/gui/SquareSvgWidget.cpp @@ -16,6 +16,14 @@ */ #include "SquareSvgWidget.h" +#include + +SquareSvgWidget::SquareSvgWidget(QWidget* parent) + : QSvgWidget(parent) +{ + Q_ASSERT(parent); + setObjectName("squareSvgWidget"); +} bool SquareSvgWidget::hasHeightForWidth() const { @@ -26,3 +34,24 @@ int SquareSvgWidget::heightForWidth(int width) const { return width; } + +// The overridden logic allows to keep the SVG image as square and centered by width and height. +void SquareSvgWidget::resizeEvent(QResizeEvent*) +{ + QWidget* pWidget = parentWidget(); + Q_ASSERT(pWidget); + if (pWidget) { + auto containerRect = pWidget->contentsRect(); + + auto containerWidth = containerRect.width(); + auto containerHeight = containerRect.height(); + + auto squareSize = qMin(containerWidth, containerHeight); + auto halfSquareSize = squareSize >> 1; + + auto startX = (containerWidth >> 1) - halfSquareSize; + auto startY = (containerHeight >> 1) - halfSquareSize; + + setGeometry(startX, startY, squareSize, squareSize); + } +} diff --git a/src/gui/SquareSvgWidget.h b/src/gui/SquareSvgWidget.h index c59548b749..479bd964df 100644 --- a/src/gui/SquareSvgWidget.h +++ b/src/gui/SquareSvgWidget.h @@ -23,11 +23,13 @@ class SquareSvgWidget : public QSvgWidget { public: - SquareSvgWidget() = default; + explicit SquareSvgWidget(QWidget* parent); ~SquareSvgWidget() override = default; bool hasHeightForWidth() const override; int heightForWidth(int width) const override; + + void resizeEvent(QResizeEvent* event) override; }; #endif // KEEPASSX_SquareSvgWidget_H diff --git a/src/gui/TotpExportSettingsDialog.cpp b/src/gui/TotpExportSettingsDialog.cpp index 93921e29c8..fa40aa62af 100644 --- a/src/gui/TotpExportSettingsDialog.cpp +++ b/src/gui/TotpExportSettingsDialog.cpp @@ -29,25 +29,29 @@ #include #include #include +#include TotpExportSettingsDialog::TotpExportSettingsDialog(DatabaseWidget* parent, Entry* entry) : QDialog(parent) , m_timer(new QTimer(this)) , m_verticalLayout(new QVBoxLayout()) - , m_totpSvgWidget(new SquareSvgWidget()) + , m_totpSvgContainerWidget(new QStackedWidget()) + , m_totpSvgWidget(new SquareSvgWidget(m_totpSvgContainerWidget)) , m_countDown(new QLabel()) , m_warningLabel(new QLabel()) , m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Close | QDialogButtonBox::Ok)) { + setObjectName("entryQrCodeWidget"); + m_totpSvgContainerWidget->addWidget(m_totpSvgWidget); + m_verticalLayout->addWidget(m_warningLabel); m_verticalLayout->addItem(new QSpacerItem(0, 0)); - - m_verticalLayout->addStretch(0); - m_verticalLayout->addWidget(m_totpSvgWidget); - m_verticalLayout->addStretch(0); + m_verticalLayout->addWidget(m_totpSvgContainerWidget); m_verticalLayout->addWidget(m_countDown); m_verticalLayout->addWidget(m_buttonBox); + m_verticalLayout->setAlignment(m_buttonBox, Qt::AlignBottom); + setLayout(m_verticalLayout); setAttribute(Qt::WA_DeleteOnClose); diff --git a/src/gui/TotpExportSettingsDialog.h b/src/gui/TotpExportSettingsDialog.h index 03bd98aad0..7a807cd0ce 100644 --- a/src/gui/TotpExportSettingsDialog.h +++ b/src/gui/TotpExportSettingsDialog.h @@ -44,6 +44,7 @@ private slots: QTimer* m_timer; QVBoxLayout* m_verticalLayout; + QStackedWidget* m_totpSvgContainerWidget; SquareSvgWidget* m_totpSvgWidget; QLabel* m_countDown; QLabel* m_warningLabel; diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index c1b339f33e..67d0b5507d 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -895,12 +895,27 @@ void TestGui::testTotp() auto* editEntryWidgetButtonBox = editEntryWidget->findChild("buttonBox"); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + // Test the TOTP value triggerAction("actionEntryTotp"); auto* totpDialog = m_dbWidget->findChild("TotpDialog"); auto* totpLabel = totpDialog->findChild("totpLabel"); QCOMPARE(totpLabel->text().replace(" ", ""), entry->totp()); + QTest::keyClick(totpDialog, Qt::Key_Escape); + + // Test the QR code + triggerAction("actionEntryTotpQRCode"); + auto* qrCodeDialog = m_mainWindow->findChild("entryQrCodeWidget"); + QVERIFY(qrCodeDialog); + QVERIFY(qrCodeDialog->isVisible()); + auto* qrCodeWidget = qrCodeDialog->findChild("squareSvgWidget"); + QVERIFY2(qrCodeWidget->geometry().width() == qrCodeWidget->geometry().height(), "Initial QR code is not square"); + + // Test the QR code window resizing, make the dialog bigger. + qrCodeDialog->setFixedSize(800, 600); + QVERIFY2(qrCodeWidget->geometry().width() == qrCodeWidget->geometry().height(), "Resized QR code is not square"); + QTest::keyClick(qrCodeDialog, Qt::Key_Escape); } void TestGui::testSearch()