2018-11-24 00:57:41 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 or (at your option)
|
|
|
|
* version 3 of the License.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "DatabaseOpenDialog.h"
|
2021-07-11 22:10:29 -04:00
|
|
|
|
2018-11-24 00:57:41 +01:00
|
|
|
#include "DatabaseOpenWidget.h"
|
2020-09-22 19:48:20 -04:00
|
|
|
#include "DatabaseTabWidget.h"
|
2018-11-24 00:57:41 +01:00
|
|
|
#include "DatabaseWidget.h"
|
2021-07-11 22:10:29 -04:00
|
|
|
|
2020-09-22 19:48:20 -04:00
|
|
|
#include <QFileInfo>
|
2021-07-11 22:10:29 -04:00
|
|
|
#include <QLayout>
|
2020-09-22 19:48:20 -04:00
|
|
|
#include <QShortcut>
|
2018-11-24 00:57:41 +01:00
|
|
|
|
2020-12-30 15:22:54 +01:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
#include <QtPlatformHeaders/QWindowsWindowFunctions>
|
|
|
|
#endif
|
|
|
|
|
2018-11-24 00:57:41 +01:00
|
|
|
DatabaseOpenDialog::DatabaseOpenDialog(QWidget* parent)
|
|
|
|
: QDialog(parent)
|
|
|
|
, m_view(new DatabaseOpenWidget(this))
|
2020-09-22 19:48:20 -04:00
|
|
|
, m_tabBar(new QTabBar(this))
|
2018-11-24 00:57:41 +01:00
|
|
|
{
|
|
|
|
setWindowTitle(tr("Unlock Database - KeePassXC"));
|
2020-08-29 20:47:26 +08:00
|
|
|
setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
|
2020-09-22 19:48:20 -04:00
|
|
|
// block input to the main window/application while the dialog is open
|
|
|
|
setWindowModality(Qt::ApplicationModal);
|
2020-12-30 15:22:54 +01:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
QWindowsWindowFunctions::setWindowActivationBehavior(QWindowsWindowFunctions::AlwaysActivateWindow);
|
|
|
|
#endif
|
2020-09-22 19:48:20 -04:00
|
|
|
connect(m_view, &DatabaseOpenWidget::dialogFinished, this, &DatabaseOpenDialog::complete);
|
|
|
|
|
|
|
|
m_tabBar->setAutoHide(true);
|
|
|
|
m_tabBar->setExpanding(false);
|
|
|
|
connect(m_tabBar, &QTabBar::currentChanged, this, &DatabaseOpenDialog::tabChanged);
|
|
|
|
|
2020-04-11 19:02:57 +02:00
|
|
|
auto* layout = new QVBoxLayout();
|
2020-09-22 19:48:20 -04:00
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
layout->setSpacing(0);
|
|
|
|
layout->addWidget(m_tabBar);
|
2020-04-11 19:02:57 +02:00
|
|
|
layout->addWidget(m_view);
|
2020-09-22 19:48:20 -04:00
|
|
|
setLayout(layout);
|
2019-11-09 13:52:10 +01:00
|
|
|
setMinimumWidth(700);
|
2020-09-22 19:48:20 -04:00
|
|
|
|
|
|
|
// set up Ctrl+PageUp and Ctrl+PageDown shortcuts to cycle tabs
|
|
|
|
auto* shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageUp, this);
|
|
|
|
shortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
|
|
|
connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(-1); });
|
|
|
|
shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageDown, this);
|
|
|
|
shortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
|
|
|
connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(1); });
|
2018-11-24 00:57:41 +01:00
|
|
|
}
|
|
|
|
|
2020-09-22 19:48:20 -04:00
|
|
|
void DatabaseOpenDialog::selectTabOffset(int offset)
|
2018-11-24 00:57:41 +01:00
|
|
|
{
|
2020-09-22 19:48:20 -04:00
|
|
|
if (offset == 0 || m_tabBar->count() <= 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int tab = m_tabBar->currentIndex() + offset;
|
|
|
|
int last = m_tabBar->count() - 1;
|
|
|
|
if (tab < 0) {
|
|
|
|
tab = last;
|
|
|
|
} else if (tab > last) {
|
|
|
|
tab = 0;
|
|
|
|
}
|
|
|
|
m_tabBar->setCurrentIndex(tab);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseOpenDialog::addDatabaseTab(DatabaseWidget* dbWidget)
|
|
|
|
{
|
|
|
|
Q_ASSERT(dbWidget);
|
|
|
|
if (!dbWidget) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// important - we must add the DB widget first, because addTab will fire
|
|
|
|
// tabChanged immediately which will look for a dbWidget in the list
|
|
|
|
m_tabDbWidgets.append(dbWidget);
|
|
|
|
QFileInfo fileInfo(dbWidget->database()->filePath());
|
|
|
|
m_tabBar->addTab(fileInfo.fileName());
|
|
|
|
Q_ASSERT(m_tabDbWidgets.count() == m_tabBar->count());
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseOpenDialog::setActiveDatabaseTab(DatabaseWidget* dbWidget)
|
|
|
|
{
|
|
|
|
if (!dbWidget) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int index = m_tabDbWidgets.indexOf(dbWidget);
|
|
|
|
if (index != -1) {
|
|
|
|
m_tabBar->setCurrentIndex(index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseOpenDialog::tabChanged(int index)
|
|
|
|
{
|
|
|
|
if (index < 0 || index >= m_tabDbWidgets.count()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_tabDbWidgets.count() == m_tabBar->count()) {
|
|
|
|
DatabaseWidget* dbWidget = m_tabDbWidgets[index];
|
|
|
|
setTarget(dbWidget, dbWidget->database()->filePath());
|
|
|
|
} else {
|
|
|
|
// if these list sizes don't match, there's a bug somewhere nearby
|
|
|
|
qWarning("DatabaseOpenDialog: mismatch between tab count %d and DB count %d",
|
|
|
|
m_tabBar->count(),
|
|
|
|
m_tabDbWidgets.count());
|
|
|
|
}
|
2018-11-24 00:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-09-22 19:48:20 -04:00
|
|
|
* Sets the target DB and reloads the UI.
|
2018-11-24 00:57:41 +01:00
|
|
|
*/
|
2020-09-22 19:48:20 -04:00
|
|
|
void DatabaseOpenDialog::setTarget(DatabaseWidget* dbWidget, const QString& filePath)
|
2018-11-24 00:57:41 +01:00
|
|
|
{
|
2020-09-22 19:48:20 -04:00
|
|
|
// reconnect finished signal to new dbWidget, then reload the UI
|
|
|
|
if (m_currentDbWidget) {
|
|
|
|
disconnect(this, &DatabaseOpenDialog::dialogFinished, m_currentDbWidget, nullptr);
|
2018-11-24 00:57:41 +01:00
|
|
|
}
|
2019-12-13 15:28:45 -05:00
|
|
|
connect(this, &DatabaseOpenDialog::dialogFinished, dbWidget, &DatabaseWidget::unlockDatabase);
|
2020-09-22 19:48:20 -04:00
|
|
|
|
|
|
|
m_currentDbWidget = dbWidget;
|
|
|
|
m_view->load(filePath);
|
2018-11-24 00:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseOpenDialog::setIntent(DatabaseOpenDialog::Intent intent)
|
|
|
|
{
|
|
|
|
m_intent = intent;
|
|
|
|
}
|
|
|
|
|
|
|
|
DatabaseOpenDialog::Intent DatabaseOpenDialog::intent() const
|
|
|
|
{
|
|
|
|
return m_intent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseOpenDialog::clearForms()
|
|
|
|
{
|
|
|
|
m_view->clearForms();
|
|
|
|
m_db.reset();
|
|
|
|
m_intent = Intent::None;
|
2020-09-22 19:48:20 -04:00
|
|
|
if (m_currentDbWidget) {
|
|
|
|
disconnect(this, &DatabaseOpenDialog::dialogFinished, m_currentDbWidget, nullptr);
|
2018-11-24 00:57:41 +01:00
|
|
|
}
|
2020-09-22 19:48:20 -04:00
|
|
|
m_currentDbWidget.clear();
|
|
|
|
m_tabDbWidgets.clear();
|
|
|
|
|
|
|
|
// block signals while removing tabs so that tabChanged doesn't get called
|
|
|
|
m_tabBar->blockSignals(true);
|
|
|
|
while (m_tabBar->count() > 0) {
|
|
|
|
m_tabBar->removeTab(0);
|
|
|
|
}
|
|
|
|
m_tabBar->blockSignals(false);
|
2018-11-24 00:57:41 +01:00
|
|
|
}
|
|
|
|
|
2020-09-22 19:48:20 -04:00
|
|
|
QSharedPointer<Database> DatabaseOpenDialog::database() const
|
2018-11-24 00:57:41 +01:00
|
|
|
{
|
|
|
|
return m_db;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseOpenDialog::complete(bool accepted)
|
|
|
|
{
|
|
|
|
// save DB, since DatabaseOpenWidget will reset its data after accept() is called
|
|
|
|
m_db = m_view->database();
|
|
|
|
|
|
|
|
if (accepted) {
|
|
|
|
accept();
|
|
|
|
} else {
|
|
|
|
reject();
|
|
|
|
}
|
2020-09-22 19:48:20 -04:00
|
|
|
|
|
|
|
emit dialogFinished(accepted, m_currentDbWidget);
|
2018-11-24 00:57:41 +01:00
|
|
|
clearForms();
|
|
|
|
}
|