keepassxc

Форк
0
/
ImportWizardPageSelect.cpp 
247 строк · 9.1 Кб
1
/*
2
 *  Copyright (C) 2023 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 "ImportWizardPageSelect.h"
19
#include "ui_ImportWizardPageSelect.h"
20

21
#include "ImportWizard.h"
22

23
#include "gui/DatabaseWidget.h"
24
#include "gui/FileDialog.h"
25
#include "gui/Icons.h"
26
#include "gui/MainWindow.h"
27

28
ImportWizardPageSelect::ImportWizardPageSelect(QWidget* parent)
29
    : QWizardPage(parent)
30
    , m_ui(new Ui::ImportWizardPageSelect())
31
{
32
    m_ui->setupUi(this);
33

34
    new QListWidgetItem(icons()->icon("csv"), tr("Comma Separated Values (.csv)"), m_ui->importTypeList);
35
    new QListWidgetItem(icons()->icon("onepassword"), tr("1Password Export (.1pux)"), m_ui->importTypeList);
36
    new QListWidgetItem(icons()->icon("onepassword"), tr("1Password Vault (.opvault)"), m_ui->importTypeList);
37
    new QListWidgetItem(icons()->icon("bitwarden"), tr("Bitwarden (.json)"), m_ui->importTypeList);
38
    new QListWidgetItem(icons()->icon("object-locked"), tr("KeePass 1 Database (.kdb)"), m_ui->importTypeList);
39

40
    m_ui->importTypeList->item(0)->setData(Qt::UserRole, ImportWizard::IMPORT_CSV);
41
    m_ui->importTypeList->item(1)->setData(Qt::UserRole, ImportWizard::IMPORT_OPUX);
42
    m_ui->importTypeList->item(2)->setData(Qt::UserRole, ImportWizard::IMPORT_OPVAULT);
43
    m_ui->importTypeList->item(3)->setData(Qt::UserRole, ImportWizard::IMPORT_BITWARDEN);
44
    m_ui->importTypeList->item(4)->setData(Qt::UserRole, ImportWizard::IMPORT_KEEPASS1);
45

46
    connect(m_ui->importTypeList, &QListWidget::currentItemChanged, this, &ImportWizardPageSelect::itemSelected);
47
    m_ui->importTypeList->setCurrentRow(0);
48

49
    connect(m_ui->importFileButton, &QAbstractButton::clicked, this, &ImportWizardPageSelect::chooseImportFile);
50
    connect(m_ui->keyFileButton, &QAbstractButton::clicked, this, &ImportWizardPageSelect::chooseKeyFile);
51
    connect(m_ui->existingDatabaseRadio, &QRadioButton::toggled, this, [this](bool state) {
52
        m_ui->existingDatabaseChoice->setEnabled(state);
53
    });
54

55
    updateDatabaseChoices();
56

57
    registerField("ImportType", this);
58
    registerField("ImportFile*", m_ui->importFileEdit);
59
    registerField("ImportInto", m_ui->importIntoLabel);
60
    registerField("ImportPassword", m_ui->passwordEdit, "text", "textChanged");
61
    registerField("ImportKeyFile", m_ui->keyFileEdit);
62
}
63

64
ImportWizardPageSelect::~ImportWizardPageSelect()
65
{
66
}
67

68
void ImportWizardPageSelect::initializePage()
69
{
70
    setField("ImportType", m_ui->importTypeList->currentItem()->data(Qt::UserRole).toInt());
71
    adjustSize();
72
}
73

74
bool ImportWizardPageSelect::validatePage()
75
{
76
    if (m_ui->existingDatabaseRadio->isChecked()) {
77
        if (m_ui->existingDatabaseChoice->currentIndex() == -1) {
78
            return false;
79
        }
80
        setField("ImportInto", m_ui->existingDatabaseChoice->currentData());
81
    } else {
82
        setField("ImportInto", {});
83
    }
84

85
    return true;
86
}
87

88
void ImportWizardPageSelect::itemSelected(QListWidgetItem* current, QListWidgetItem* previous)
89
{
90
    Q_UNUSED(previous)
91

92
    if (!current) {
93
        setCredentialState(false);
94
        return;
95
    }
96

97
    m_ui->importFileEdit->clear();
98
    m_ui->passwordEdit->clear();
99
    m_ui->keyFileEdit->clear();
100

101
    auto type = current->data(Qt::UserRole).toInt();
102
    setField("ImportType", type);
103
    switch (type) {
104
    // Unencrypted types
105
    case ImportWizard::IMPORT_CSV:
106
    case ImportWizard::IMPORT_OPUX:
107
        setCredentialState(false);
108
        break;
109
    // Password may be required
110
    case ImportWizard::IMPORT_BITWARDEN:
111
    case ImportWizard::IMPORT_OPVAULT:
112
        setCredentialState(true);
113
        break;
114
    // Password and/or Key File may be required
115
    case ImportWizard::IMPORT_KEEPASS1:
116
        setCredentialState(true, true);
117
        break;
118
    default:
119
        Q_ASSERT(false);
120
    }
121
}
122

123
void ImportWizardPageSelect::updateDatabaseChoices() const
124
{
125
    m_ui->existingDatabaseChoice->clear();
126
    auto mainWindow = getMainWindow();
127
    if (mainWindow) {
128
        for (auto dbWidget : mainWindow->getOpenDatabases()) {
129
            // Remove all connections
130
            disconnect(dbWidget, nullptr, nullptr, nullptr);
131

132
            // Skip over locked databases
133
            if (dbWidget->isLocked()) {
134
                continue;
135
            }
136

137
            connect(dbWidget, &DatabaseWidget::databaseLocked, this, &ImportWizardPageSelect::updateDatabaseChoices);
138
            connect(dbWidget, &DatabaseWidget::databaseModified, this, &ImportWizardPageSelect::updateDatabaseChoices);
139

140
            // Enable the selection of an existing database
141
            m_ui->existingDatabaseRadio->setEnabled(true);
142
            m_ui->existingDatabaseRadio->setToolTip("");
143

144
            // Add a separator between databases
145
            if (m_ui->existingDatabaseChoice->count() > 0) {
146
                m_ui->existingDatabaseChoice->insertSeparator(m_ui->existingDatabaseChoice->count());
147
            }
148

149
            // Add the root group as a special line item
150
            auto db = dbWidget->database();
151
            m_ui->existingDatabaseChoice->addItem(
152
                QString("%1 (%2)").arg(dbWidget->displayName(), db->rootGroup()->name()),
153
                QList<QVariant>() << db->uuid() << db->rootGroup()->uuid());
154

155
            if (dbWidget->isVisible()) {
156
                m_ui->existingDatabaseChoice->setCurrentIndex(m_ui->existingDatabaseChoice->count() - 1);
157
            }
158

159
            // Add remaining groups
160
            for (const auto& group : db->rootGroup()->groupsRecursive(false)) {
161
                if (!group->isRecycled()) {
162
                    auto path = group->hierarchy();
163
                    path.removeFirst();
164
                    m_ui->existingDatabaseChoice->addItem(QString("  / %1").arg(path.join(" / ")),
165
                                                          QList<QVariant>() << db->uuid() << group->uuid());
166
                }
167
            }
168
        }
169
    }
170

171
    if (m_ui->existingDatabaseChoice->count() == 0) {
172
        m_ui->existingDatabaseRadio->setEnabled(false);
173
        m_ui->newDatabaseRadio->setChecked(true);
174
    }
175
}
176

177
void ImportWizardPageSelect::chooseImportFile()
178
{
179
    QString file;
180
#ifndef Q_OS_MACOS
181
    // OPVault is a folder except on macOS
182
    if (field("ImportType").toInt() == ImportWizard::IMPORT_OPVAULT) {
183
        file = fileDialog()->getExistingDirectory(this, tr("Open OPVault"), QDir::homePath());
184
    } else {
185
#endif
186
        file = fileDialog()->getOpenFileName(this, tr("Select import file"), QDir::homePath(), importFileFilter());
187
#ifndef Q_OS_MACOS
188
    }
189
#endif
190

191
    if (!file.isEmpty()) {
192
        m_ui->importFileEdit->setText(file);
193
    }
194
}
195

196
void ImportWizardPageSelect::chooseKeyFile()
197
{
198
    auto filter = QString("%1 (*);;%2 (*.keyx; *.key)").arg(tr("All files"), tr("Key files"));
199
    auto file = fileDialog()->getOpenFileName(this, tr("Select key file"), QDir::homePath(), filter);
200
    if (!file.isEmpty()) {
201
        m_ui->keyFileEdit->setText(file);
202
    }
203
}
204

205
void ImportWizardPageSelect::setCredentialState(bool passwordEnabled, bool keyFileEnable)
206
{
207
    bool passwordStateChanged = m_ui->passwordLabel->isVisible() != passwordEnabled;
208
    m_ui->passwordLabel->setVisible(passwordEnabled);
209
    m_ui->passwordEdit->setVisible(passwordEnabled);
210

211
    bool keyFileStateChanged = m_ui->keyFileLabel->isVisible() != keyFileEnable;
212
    m_ui->keyFileLabel->setVisible(keyFileEnable);
213
    m_ui->keyFileEdit->setVisible(keyFileEnable);
214
    m_ui->keyFileButton->setVisible(keyFileEnable);
215

216
    // Workaround Qt bug where the wizard window is not updated when the internal layout changes
217
    if (window()) {
218
        int height = window()->height();
219
        if (passwordStateChanged) {
220
            auto diff = m_ui->passwordEdit->height() + m_ui->inputFields->layout()->spacing();
221
            height += passwordEnabled ? diff : -diff;
222
        }
223
        if (keyFileStateChanged) {
224
            auto diff = m_ui->keyFileEdit->height() + m_ui->inputFields->layout()->spacing();
225
            height += keyFileEnable ? diff : -diff;
226
        }
227
        window()->resize(window()->width(), height);
228
    }
229
}
230

231
QString ImportWizardPageSelect::importFileFilter()
232
{
233
    switch (field("ImportType").toInt()) {
234
    case ImportWizard::IMPORT_CSV:
235
        return QString("%1 (*.csv);;%2 (*)").arg(tr("Comma Separated Values"), tr("All files"));
236
    case ImportWizard::IMPORT_OPUX:
237
        return QString("%1 (*.1pux)").arg(tr("1Password Export"));
238
    case ImportWizard::IMPORT_BITWARDEN:
239
        return QString("%1 (*.json)").arg(tr("Bitwarden JSON Export"));
240
    case ImportWizard::IMPORT_OPVAULT:
241
        return QString("%1 (*.opvault)").arg(tr("1Password Vault"));
242
    case ImportWizard::IMPORT_KEEPASS1:
243
        return QString("%1 (*.kdb)").arg(tr("KeePass1 Database"));
244
    default:
245
        return {};
246
    }
247
}
248

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

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

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

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