keepassxc

Форк
0
/
DatabaseOpenDialog.cpp 
213 строк · 6.7 Кб
1
/*
2
 *  Copyright (C) 2018 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 "DatabaseOpenDialog.h"
19

20
#include "DatabaseOpenWidget.h"
21
#include "DatabaseTabWidget.h"
22
#include "DatabaseWidget.h"
23

24
#include <QFileInfo>
25
#include <QLayout>
26
#include <QShortcut>
27

28
#ifdef Q_OS_WIN
29
#include <QtPlatformHeaders/QWindowsWindowFunctions>
30
#endif
31

32
DatabaseOpenDialog::DatabaseOpenDialog(QWidget* parent)
33
    : QDialog(parent)
34
    , m_view(new DatabaseOpenWidget(this))
35
    , m_tabBar(new QTabBar(this))
36
{
37
    setWindowTitle(tr("Unlock Database - KeePassXC"));
38
    setWindowFlags(Qt::Dialog);
39
    setWindowFlag(Qt::WindowContextHelpButtonHint, false);
40
#ifdef Q_OS_LINUX
41
    // Linux requires this to overcome some Desktop Environments (also no Quick Unlock)
42
    setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
43
#endif
44
    // block input to the main window/application while the dialog is open
45
    setWindowModality(Qt::ApplicationModal);
46
#ifdef Q_OS_WIN
47
    QWindowsWindowFunctions::setWindowActivationBehavior(QWindowsWindowFunctions::AlwaysActivateWindow);
48
#endif
49
    connect(m_view, &DatabaseOpenWidget::dialogFinished, this, &DatabaseOpenDialog::complete);
50

51
    m_tabBar->setAutoHide(true);
52
    m_tabBar->setExpanding(false);
53
    connect(m_tabBar, &QTabBar::currentChanged, this, &DatabaseOpenDialog::tabChanged);
54

55
    auto* layout = new QVBoxLayout();
56
    layout->setContentsMargins(0, 0, 0, 0);
57
    layout->setSpacing(0);
58
    layout->addWidget(m_tabBar);
59
    layout->addWidget(m_view);
60
    setLayout(layout);
61
    setMinimumWidth(700);
62

63
    // set up Ctrl+PageUp / Ctrl+PageDown and Ctrl+Tab / Ctrl+Shift+Tab shortcuts to cycle tabs
64
    // Ctrl+Tab is broken on Mac, so use Alt (i.e. the Option key) - https://bugreports.qt.io/browse/QTBUG-8596
65
    auto dbTabModifier = Qt::CTRL;
66
#ifdef Q_OS_MACOS
67
    dbTabModifier = Qt::ALT;
68
#endif
69
    auto* shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageUp, this);
70
    shortcut->setContext(Qt::WidgetWithChildrenShortcut);
71
    connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(-1); });
72
    shortcut = new QShortcut(dbTabModifier + Qt::SHIFT + Qt::Key_Tab, this);
73
    shortcut->setContext(Qt::WidgetWithChildrenShortcut);
74
    connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(-1); });
75
    shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageDown, this);
76
    shortcut->setContext(Qt::WidgetWithChildrenShortcut);
77
    connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(1); });
78
    shortcut = new QShortcut(dbTabModifier + Qt::Key_Tab, this);
79
    shortcut->setContext(Qt::WidgetWithChildrenShortcut);
80
    connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(1); });
81
}
82

83
void DatabaseOpenDialog::showEvent(QShowEvent* event)
84
{
85
    QDialog::showEvent(event);
86
    QTimer::singleShot(100, this, [=] {
87
        if (m_view->isOnQuickUnlockScreen() && !m_view->unlockingDatabase()) {
88
            m_view->triggerQuickUnlock();
89
        }
90
    });
91
}
92

93
void DatabaseOpenDialog::selectTabOffset(int offset)
94
{
95
    if (offset == 0 || m_tabBar->count() <= 1) {
96
        return;
97
    }
98
    int tab = m_tabBar->currentIndex() + offset;
99
    int last = m_tabBar->count() - 1;
100
    if (tab < 0) {
101
        tab = last;
102
    } else if (tab > last) {
103
        tab = 0;
104
    }
105
    m_tabBar->setCurrentIndex(tab);
106
}
107

108
void DatabaseOpenDialog::addDatabaseTab(DatabaseWidget* dbWidget)
109
{
110
    Q_ASSERT(dbWidget);
111
    if (!dbWidget) {
112
        return;
113
    }
114

115
    // important - we must add the DB widget first, because addTab will fire
116
    // tabChanged immediately which will look for a dbWidget in the list
117
    m_tabDbWidgets.append(dbWidget);
118
    QFileInfo fileInfo(dbWidget->database()->filePath());
119
    m_tabBar->addTab(fileInfo.fileName());
120
    Q_ASSERT(m_tabDbWidgets.count() == m_tabBar->count());
121
}
122

123
void DatabaseOpenDialog::setActiveDatabaseTab(DatabaseWidget* dbWidget)
124
{
125
    if (!dbWidget) {
126
        return;
127
    }
128
    int index = m_tabDbWidgets.indexOf(dbWidget);
129
    if (index != -1) {
130
        m_tabBar->setCurrentIndex(index);
131
    }
132
}
133

134
void DatabaseOpenDialog::tabChanged(int index)
135
{
136
    if (index < 0 || index >= m_tabDbWidgets.count()) {
137
        return;
138
    }
139

140
    if (m_tabDbWidgets.count() == m_tabBar->count()) {
141
        DatabaseWidget* dbWidget = m_tabDbWidgets[index];
142
        setTarget(dbWidget, dbWidget->database()->filePath());
143
    } else {
144
        // if these list sizes don't match, there's a bug somewhere nearby
145
        qWarning("DatabaseOpenDialog: mismatch between tab count %d and DB count %d",
146
                 m_tabBar->count(),
147
                 m_tabDbWidgets.count());
148
    }
149
}
150

151
/**
152
 * Sets the target DB and reloads the UI.
153
 */
154
void DatabaseOpenDialog::setTarget(DatabaseWidget* dbWidget, const QString& filePath)
155
{
156
    // reconnect finished signal to new dbWidget, then reload the UI
157
    if (m_currentDbWidget) {
158
        disconnect(this, &DatabaseOpenDialog::dialogFinished, m_currentDbWidget, nullptr);
159
    }
160
    connect(this, &DatabaseOpenDialog::dialogFinished, dbWidget, &DatabaseWidget::unlockDatabase);
161

162
    m_currentDbWidget = dbWidget;
163
    m_view->load(filePath);
164
}
165

166
void DatabaseOpenDialog::setIntent(DatabaseOpenDialog::Intent intent)
167
{
168
    m_intent = intent;
169
}
170

171
DatabaseOpenDialog::Intent DatabaseOpenDialog::intent() const
172
{
173
    return m_intent;
174
}
175

176
void DatabaseOpenDialog::clearForms()
177
{
178
    m_view->clearForms();
179
    m_db.reset();
180
    m_intent = Intent::None;
181
    if (m_currentDbWidget) {
182
        disconnect(this, &DatabaseOpenDialog::dialogFinished, m_currentDbWidget, nullptr);
183
    }
184
    m_currentDbWidget.clear();
185
    m_tabDbWidgets.clear();
186

187
    // block signals while removing tabs so that tabChanged doesn't get called
188
    m_tabBar->blockSignals(true);
189
    while (m_tabBar->count() > 0) {
190
        m_tabBar->removeTab(0);
191
    }
192
    m_tabBar->blockSignals(false);
193
}
194

195
QSharedPointer<Database> DatabaseOpenDialog::database() const
196
{
197
    return m_db;
198
}
199

200
void DatabaseOpenDialog::complete(bool accepted)
201
{
202
    // save DB, since DatabaseOpenWidget will reset its data after accept() is called
203
    m_db = m_view->database();
204

205
    if (accepted) {
206
        accept();
207
    } else {
208
        reject();
209
    }
210

211
    emit dialogFinished(accepted, m_currentDbWidget);
212
    clearForms();
213
}
214

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.