1 /*
2 * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 or (at your option)
7 * version 3 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "TotpExportSettingsDialog.h"
19
20 #include "core/Config.h"
21 #include "core/Entry.h"
22 #include "gui/Clipboard.h"
23 #include "gui/DatabaseWidget.h"
24 #include "gui/MainWindow.h"
25 #include "gui/SquareSvgWidget.h"
26 #include "qrcode/QrCode.h"
27 #include "totp/totp.h"
28
29 #include <QBuffer>
30 #include <QDialogButtonBox>
31 #include <QLabel>
32 #include <QMessageBox>
33 #include <QPushButton>
34 #include <QShortcut>
35 #include <QSizePolicy>
36 #include <QVBoxLayout>
37
TotpExportSettingsDialog(DatabaseWidget * parent,Entry * entry)38 TotpExportSettingsDialog::TotpExportSettingsDialog(DatabaseWidget* parent, Entry* entry)
39 : QDialog(parent)
40 , m_timer(new QTimer(this))
41 , m_verticalLayout(new QVBoxLayout())
42 , m_totpSvgWidget(new SquareSvgWidget())
43 , m_countDown(new QLabel())
44 , m_warningLabel(new QLabel())
45 , m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Close | QDialogButtonBox::Ok))
46 {
47 m_verticalLayout->addWidget(m_warningLabel);
48 m_verticalLayout->addItem(new QSpacerItem(0, 0));
49
50 m_verticalLayout->addStretch(0);
51 m_verticalLayout->addWidget(m_totpSvgWidget);
52 m_verticalLayout->addStretch(0);
53 m_verticalLayout->addWidget(m_countDown);
54 m_verticalLayout->addWidget(m_buttonBox);
55
56 setLayout(m_verticalLayout);
57 setAttribute(Qt::WA_DeleteOnClose);
58
59 connect(m_buttonBox, SIGNAL(rejected()), SLOT(close()));
60 connect(m_buttonBox, SIGNAL(accepted()), SLOT(copyToClipboard()));
61 connect(m_timer, SIGNAL(timeout()), SLOT(autoClose()));
62
63 new QShortcut(QKeySequence(QKeySequence::Copy), this, SLOT(copyToClipboard()));
64
65 m_buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Copy"));
66 m_buttonBox->setFocus();
67 m_countDown->setAlignment(Qt::AlignCenter);
68
69 m_secTillClose = 45;
70 autoClose();
71 m_timer->start(1000);
72
73 const auto totpSettings = entry->totpSettings();
74 if (totpSettings->custom || !totpSettings->encoder.shortName.isEmpty()) {
75 m_warningLabel->setWordWrap(true);
76 m_warningLabel->setMargin(5);
77 m_warningLabel->setText(tr("NOTE: These TOTP settings are custom and may not work with other authenticators.",
78 "TOTP QR code dialog warning"));
79 } else {
80 m_warningLabel->hide();
81 }
82
83 m_totpUri = Totp::writeSettings(entry->totpSettings(), entry->title(), entry->username(), true);
84 const QrCode qrc(m_totpUri);
85
86 if (qrc.isValid()) {
87 QBuffer buffer;
88 qrc.writeSvg(&buffer, logicalDpiX());
89 m_totpSvgWidget->load(buffer.data());
90 const int minsize = static_cast<int>(logicalDpiX() * 2.5);
91 m_totpSvgWidget->setMinimumSize(minsize, minsize);
92 } else {
93 auto errorBox = new QMessageBox(parent);
94 errorBox->setAttribute(Qt::WA_DeleteOnClose);
95 errorBox->setIcon(QMessageBox::Warning);
96 errorBox->setText(tr("There was an error creating the QR code."));
97 errorBox->exec();
98 close();
99 }
100 }
101
copyToClipboard()102 void TotpExportSettingsDialog::copyToClipboard()
103 {
104 clipboard()->setText(m_totpUri);
105 if (config()->get(Config::HideWindowOnCopy).toBool()) {
106 if (config()->get(Config::MinimizeOnCopy).toBool()) {
107 getMainWindow()->minimizeOrHide();
108 } else if (config()->get(Config::DropToBackgroundOnCopy).toBool()) {
109 getMainWindow()->lower();
110 window()->lower();
111 }
112 }
113 }
114
autoClose()115 void TotpExportSettingsDialog::autoClose()
116 {
117 if (--m_secTillClose > 0) {
118 m_countDown->setText(tr("Closing in %1 seconds.").arg(m_secTillClose));
119 } else {
120 m_timer->stop();
121 close();
122 }
123 }
124
125 TotpExportSettingsDialog::~TotpExportSettingsDialog() = default;
126