Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/DatabaseWidget.cpp')
-rw-r--r--src/gui/DatabaseWidget.cpp435
1 files changed, 304 insertions, 131 deletions
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index 453b2009b..ff9d15fc0 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -1,19 +1,19 @@
/*
- * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
- * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
*
- * 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 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.
+ * 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/>.
+ * 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 "DatabaseWidget.h"
@@ -47,6 +47,7 @@
#include "gui/TotpDialog.h"
#include "gui/DatabaseOpenWidget.h"
#include "gui/DatabaseSettingsWidget.h"
+#include "gui/DetailsWidget.h"
#include "gui/KeePass1OpenWidget.h"
#include "gui/MessageBox.h"
#include "gui/UnlockDatabaseWidget.h"
@@ -56,28 +57,38 @@
#include "gui/group/EditGroupWidget.h"
#include "gui/group/GroupView.h"
+#include "config-keepassx.h"
+
+#ifdef WITH_XC_SSHAGENT
+#include "sshagent/SSHAgent.h"
+#endif
+
DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
: QStackedWidget(parent)
, m_db(db)
, m_newGroup(nullptr)
, m_newEntry(nullptr)
, m_newParent(nullptr)
+ , m_importingCsv(false)
{
m_mainWidget = new QWidget(this);
m_messageWidget = new MessageWidget(this);
m_messageWidget->setHidden(true);
- QVBoxLayout* mainLayout = new QVBoxLayout();
+ auto* mainLayout = new QVBoxLayout();
QLayout* layout = new QHBoxLayout();
mainLayout->addWidget(m_messageWidget);
mainLayout->addLayout(layout);
- m_splitter = new QSplitter(m_mainWidget);
- m_splitter->setChildrenCollapsible(false);
+ m_mainSplitter = new QSplitter(m_mainWidget);
+ m_mainSplitter->setChildrenCollapsible(false);
+ m_detailSplitter = new QSplitter(m_mainWidget);
+ m_detailSplitter->setOrientation(Qt::Vertical);
+ m_detailSplitter->setChildrenCollapsible(true);
- QWidget* rightHandSideWidget = new QWidget(m_splitter);
+ QWidget* rightHandSideWidget = new QWidget(m_mainSplitter);
- m_groupView = new GroupView(db, m_splitter);
+ m_groupView = new GroupView(db, m_mainSplitter);
m_groupView->setObjectName("groupView");
m_groupView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_groupView, SIGNAL(customContextMenuRequested(QPoint)),
@@ -99,10 +110,25 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
"border: 2px solid rgb(190, 190, 190);"
"border-radius: 5px;");
- QVBoxLayout* vLayout = new QVBoxLayout(rightHandSideWidget);
+ m_detailsView = new DetailsWidget(this);
+ m_detailsView->hide();
+ connect(this, SIGNAL(pressedEntry(Entry*)), m_detailsView, SLOT(setEntry(Entry*)));
+ connect(this, SIGNAL(pressedGroup(Group*)), m_detailsView, SLOT(setGroup(Group*)));
+ connect(this, SIGNAL(currentModeChanged(DatabaseWidget::Mode)),
+ m_detailsView, SLOT(setDatabaseMode(DatabaseWidget::Mode)));
+ connect(m_detailsView, SIGNAL(errorOccurred(QString)), this, SLOT(showErrorMessage(QString)));
+
+
+ auto* vLayout = new QVBoxLayout(rightHandSideWidget);
vLayout->setMargin(0);
vLayout->addWidget(m_searchingLabel);
- vLayout->addWidget(m_entryView);
+ vLayout->addWidget(m_detailSplitter);
+
+ m_detailSplitter->addWidget(m_entryView);
+ m_detailSplitter->addWidget(m_detailsView);
+
+ m_detailSplitter->setStretchFactor(0, 100);
+ m_detailSplitter->setStretchFactor(1, 0);
m_searchingLabel->setVisible(false);
@@ -110,13 +136,13 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
setTabOrder(m_entryView, m_groupView);
- m_splitter->addWidget(m_groupView);
- m_splitter->addWidget(rightHandSideWidget);
+ m_mainSplitter->addWidget(m_groupView);
+ m_mainSplitter->addWidget(rightHandSideWidget);
- m_splitter->setStretchFactor(0, 30);
- m_splitter->setStretchFactor(1, 70);
+ m_mainSplitter->setStretchFactor(0, 30);
+ m_mainSplitter->setStretchFactor(1, 70);
- layout->addWidget(m_splitter);
+ layout->addWidget(m_mainSplitter);
m_mainWidget->setLayout(mainLayout);
m_editEntryWidget = new EditEntryWidget();
@@ -125,13 +151,14 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
m_editGroupWidget = new EditGroupWidget();
m_editGroupWidget->setObjectName("editGroupWidget");
m_changeMasterKeyWidget = new ChangeMasterKeyWidget();
+ m_changeMasterKeyWidget->setObjectName("changeMasterKeyWidget");
m_changeMasterKeyWidget->headlineLabel()->setText(tr("Change master key"));
- m_csvImportWizard = new CsvImportWizard();
- m_csvImportWizard->setObjectName("csvImportWizard");
QFont headlineLabelFont = m_changeMasterKeyWidget->headlineLabel()->font();
headlineLabelFont.setBold(true);
headlineLabelFont.setPointSize(headlineLabelFont.pointSize() + 2);
m_changeMasterKeyWidget->headlineLabel()->setFont(headlineLabelFont);
+ m_csvImportWizard = new CsvImportWizard();
+ m_csvImportWizard->setObjectName("csvImportWizard");
m_databaseSettingsWidget = new DatabaseSettingsWidget();
m_databaseSettingsWidget->setObjectName("databaseSettingsWidget");
m_databaseOpenWidget = new DatabaseOpenWidget();
@@ -156,8 +183,9 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
addWidget(m_keepass1OpenWidget);
addWidget(m_unlockDatabaseWidget);
- connect(m_splitter, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterSizesChanged()));
- connect(m_entryView->header(), SIGNAL(sectionResized(int,int,int)), SIGNAL(entryColumnSizesChanged()));
+ connect(m_mainSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(mainSplitterSizesChanged()));
+ connect(m_detailSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(detailSplitterSizesChanged()));
+ connect(m_entryView, SIGNAL(viewStateChanged()), SIGNAL(entryViewStateChanged()));
connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(onGroupChanged(Group*)));
connect(m_groupView, SIGNAL(groupChanged(Group*)), SIGNAL(groupChanged()));
connect(m_entryView, SIGNAL(entryActivated(Entry*, EntryModel::ModelColumn)),
@@ -180,6 +208,12 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(unblockAutoReload()));
connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged()));
+ connect(m_groupView, SIGNAL(groupPressed(Group*)), SLOT(emitPressedGroup(Group*)));
+ connect(m_groupView, SIGNAL(groupChanged(Group*)), SLOT(emitPressedGroup(Group*)));
+ connect(m_entryView, SIGNAL(entryPressed(Entry*)), SLOT(emitPressedEntry(Entry*)));
+ connect(m_entryView, SIGNAL(entrySelectionChanged()), SLOT(emitPressedEntry()));
+ connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(emitPressedEntry()));
+
m_databaseModified = false;
m_fileWatchTimer.setSingleShot(true);
@@ -189,6 +223,13 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
m_searchCaseSensitive = false;
m_searchLimitGroup = config()->get("SearchLimitGroup", false).toBool();
+#ifdef WITH_XC_SSHAGENT
+ if (config()->get("SSHAgent", false).toBool()) {
+ connect(this, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), SSHAgent::instance(), SLOT(databaseModeChanged(DatabaseWidget::Mode)));
+ connect(this, SIGNAL(closeRequest()), SSHAgent::instance(), SLOT(databaseModeChanged()));
+ }
+#endif
+
setCurrentWidget(m_mainWidget);
}
@@ -233,37 +274,72 @@ bool DatabaseWidget::isEditWidgetModified() const
}
}
-QList<int> DatabaseWidget::splitterSizes() const
+QList<int> DatabaseWidget::mainSplitterSizes() const
{
- return m_splitter->sizes();
+ return m_mainSplitter->sizes();
}
-void DatabaseWidget::setSplitterSizes(const QList<int>& sizes)
+void DatabaseWidget::setMainSplitterSizes(const QList<int>& sizes)
{
- m_splitter->setSizes(sizes);
+ m_mainSplitter->setSizes(sizes);
}
-QList<int> DatabaseWidget::entryHeaderViewSizes() const
+QList<int> DatabaseWidget::detailSplitterSizes() const
{
- QList<int> sizes;
+ return m_detailSplitter->sizes();
+}
- for (int i = 0; i < m_entryView->header()->count(); i++) {
- sizes.append(m_entryView->header()->sectionSize(i));
- }
+void DatabaseWidget::setDetailSplitterSizes(const QList<int> &sizes)
+{
+ m_detailSplitter->setSizes(sizes);
+}
- return sizes;
+/**
+ * Get current state of entry view 'Hide Usernames' setting
+ */
+bool DatabaseWidget::isUsernamesHidden() const
+{
+ return m_entryView->isUsernamesHidden();
}
-void DatabaseWidget::setEntryViewHeaderSizes(const QList<int>& sizes)
+/**
+ * Set state of entry view 'Hide Usernames' setting
+ */
+void DatabaseWidget::setUsernamesHidden(const bool hide)
{
- if (sizes.size() != m_entryView->header()->count()) {
- Q_ASSERT(false);
- return;
- }
+ m_entryView->setUsernamesHidden(hide);
+}
- for (int i = 0; i < sizes.size(); i++) {
- m_entryView->header()->resizeSection(i, sizes[i]);
- }
+/**
+ * Get current state of entry view 'Hide Passwords' setting
+ */
+bool DatabaseWidget::isPasswordsHidden() const
+{
+ return m_entryView->isPasswordsHidden();
+}
+
+/**
+ * Set state of entry view 'Hide Passwords' setting
+ */
+void DatabaseWidget::setPasswordsHidden(const bool hide)
+{
+ m_entryView->setPasswordsHidden(hide);
+}
+
+/**
+ * Get current view state of entry view
+ */
+QByteArray DatabaseWidget::entryViewState() const
+{
+ return m_entryView->viewState();
+}
+
+/**
+ * Set view state of entry view
+ */
+bool DatabaseWidget::setEntryViewState(const QByteArray& state) const
+{
+ return m_entryView->setViewState(state);
}
void DatabaseWidget::clearAllWidgets()
@@ -285,12 +361,17 @@ Database* DatabaseWidget::database()
void DatabaseWidget::createEntry()
{
+ Q_ASSERT(m_groupView->currentGroup());
if (!m_groupView->currentGroup()) {
- Q_ASSERT(false);
return;
}
m_newEntry = new Entry();
+
+ if (isInSearchMode()) {
+ m_newEntry->setTitle(getCurrentSearch());
+ endSearch();
+ }
m_newEntry->setUuid(Uuid::random());
m_newEntry->setUsername(m_db->metadata()->defaultUserName());
m_newParent = m_groupView->currentGroup();
@@ -328,33 +409,32 @@ void DatabaseWidget::replaceDatabase(Database* db)
void DatabaseWidget::cloneEntry()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
- CloneDialog* cloneDialog = new CloneDialog(this, m_db, currentEntry);
+ auto cloneDialog = new CloneDialog(this, m_db, currentEntry);
cloneDialog->show();
- return;
}
void DatabaseWidget::showTotp()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
- TotpDialog* totpDialog = new TotpDialog(this, currentEntry);
+ auto totpDialog = new TotpDialog(this, currentEntry);
totpDialog->open();
}
void DatabaseWidget::copyTotp()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
setClipboardTextAndMinimize(currentEntry->totp());
@@ -363,20 +443,21 @@ void DatabaseWidget::copyTotp()
void DatabaseWidget::setupTotp()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
- SetupTotpDialog* setupTotpDialog = new SetupTotpDialog(this, currentEntry);
+ auto setupTotpDialog = new SetupTotpDialog(this, currentEntry);
if (currentEntry->hasTotp()) {
setupTotpDialog->setSeed(currentEntry->totpSeed());
setupTotpDialog->setStep(currentEntry->totpStep());
setupTotpDialog->setDigits(currentEntry->totpDigits());
+ // now that all settings are set, decide whether it's default, steam or custom
+ setupTotpDialog->setSettings(currentEntry->totpDigits());
}
setupTotpDialog->open();
-
}
@@ -384,8 +465,8 @@ void DatabaseWidget::deleteEntries()
{
const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
+ Q_ASSERT(!selected.isEmpty());
if (selected.isEmpty()) {
- Q_ASSERT(false);
return;
}
@@ -456,8 +537,8 @@ void DatabaseWidget::setFocus()
void DatabaseWidget::copyTitle()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -467,8 +548,8 @@ void DatabaseWidget::copyTitle()
void DatabaseWidget::copyUsername()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -478,8 +559,8 @@ void DatabaseWidget::copyUsername()
void DatabaseWidget::copyPassword()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -489,8 +570,8 @@ void DatabaseWidget::copyPassword()
void DatabaseWidget::copyURL()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -500,8 +581,8 @@ void DatabaseWidget::copyURL()
void DatabaseWidget::copyNotes()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -511,8 +592,8 @@ void DatabaseWidget::copyNotes()
void DatabaseWidget::copyAttribute(QAction* action)
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -530,8 +611,8 @@ void DatabaseWidget::setClipboardTextAndMinimize(const QString& text)
void DatabaseWidget::performAutoType()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -541,8 +622,8 @@ void DatabaseWidget::performAutoType()
void DatabaseWidget::openUrl()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return;
}
@@ -564,7 +645,7 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
}
return;
}
-
+
// otherwise ask user
if (urlString.length() > 6) {
QString cmdTruncated = urlString.mid(6);
@@ -578,7 +659,7 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
this
);
msgbox.setDefaultButton(QMessageBox::No);
-
+
QCheckBox* checkbox = new QCheckBox(tr("Remember my choice"), &msgbox);
msgbox.setCheckBox(checkbox);
bool remember = false;
@@ -587,12 +668,12 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
remember = true;
}
});
-
+
int result = msgbox.exec();
if (result == QMessageBox::Yes) {
QProcess::startDetached(urlString.mid(6));
}
-
+
if (remember) {
entry->attributes()->set(EntryAttributes::RememberCmdExecAttr,
result == QMessageBox::Yes ? "1" : "0");
@@ -607,8 +688,8 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
void DatabaseWidget::createGroup()
{
+ Q_ASSERT(m_groupView->currentGroup());
if (!m_groupView->currentGroup()) {
- Q_ASSERT(false);
return;
}
@@ -621,8 +702,8 @@ void DatabaseWidget::createGroup()
void DatabaseWidget::deleteGroup()
{
Group* currentGroup = m_groupView->currentGroup();
+ Q_ASSERT(currentGroup && canDeleteCurrentGroup());
if (!currentGroup || !canDeleteCurrentGroup()) {
- Q_ASSERT(false);
return;
}
@@ -695,21 +776,18 @@ void DatabaseWidget::switchToView(bool accepted)
m_newGroup->setParent(m_newParent);
m_groupView->setCurrentGroup(m_newGroup);
m_groupView->expandGroup(m_newParent);
- }
- else {
+ } else {
delete m_newGroup;
}
m_newGroup = nullptr;
m_newParent = nullptr;
- }
- else if (m_newEntry) {
+ } else if (m_newEntry) {
if (accepted) {
m_newEntry->setGroup(m_newParent);
m_entryView->setFocus();
m_entryView->setCurrentEntry(m_newEntry);
- }
- else {
+ } else {
delete m_newEntry;
}
@@ -738,7 +816,16 @@ void DatabaseWidget::switchToEntryEdit(Entry* entry)
void DatabaseWidget::switchToEntryEdit(Entry* entry, bool create)
{
- Group* group = currentGroup();
+ // If creating an entry, it will be in `currentGroup()` so it's
+ // okay to use but when editing, the entry may not be in
+ // `currentGroup()` so we get the entry's group.
+ Group* group;
+ if (create) {
+ group = currentGroup();
+ } else {
+ group = entry->group();
+ }
+
Q_ASSERT(group);
m_editEntryWidget->loadEntry(entry, create, false, group->name(), m_db);
@@ -753,9 +840,15 @@ void DatabaseWidget::switchToGroupEdit(Group* group, bool create)
void DatabaseWidget::updateMasterKey(bool accepted)
{
+ if (m_importingCsv) {
+ setCurrentWidget(m_csvImportWizard);
+ m_csvImportWizard->keyFinished(accepted, m_changeMasterKeyWidget->newMasterKey());
+ return;
+ }
+
if (accepted) {
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
- bool result = m_db->setKey(m_changeMasterKeyWidget->newMasterKey());
+ bool result = m_db->setKey(m_changeMasterKeyWidget->newMasterKey(), true, true);
QApplication::restoreOverrideCursor();
if (!result) {
@@ -784,10 +877,10 @@ void DatabaseWidget::openDatabase(bool accepted)
m_databaseOpenWidget = nullptr;
delete m_keepass1OpenWidget;
m_keepass1OpenWidget = nullptr;
- m_fileWatcher.addPath(m_filename);
+ m_fileWatcher.addPath(m_filePath);
}
else {
- m_fileWatcher.removePath(m_filename);
+ m_fileWatcher.removePath(m_filePath);
if (m_databaseOpenWidget->database()) {
delete m_databaseOpenWidget->database();
}
@@ -825,7 +918,7 @@ void DatabaseWidget::unlockDatabase(bool accepted)
return;
}
- Database *db = Q_NULLPTR;
+ Database* db = nullptr;
if (sender() == m_unlockDatabaseDialog) {
db = m_unlockDatabaseDialog->database();
} else if (sender() == m_unlockDatabaseWidget) {
@@ -851,10 +944,31 @@ void DatabaseWidget::unlockDatabase(bool accepted)
void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::ModelColumn column)
{
- if (column == EntryModel::Url && !entry->url().isEmpty()) {
- openUrlForEntry(entry);
+ Q_ASSERT(entry);
+ if (!entry) {
+ return;
}
- else {
+
+ // Implement 'copy-on-doubleclick' functionality for certain columns
+ switch (column) {
+ case EntryModel::Username:
+ setClipboardTextAndMinimize(entry->resolveMultiplePlaceholders(entry->username()));
+ break;
+ case EntryModel::Password:
+ setClipboardTextAndMinimize(entry->resolveMultiplePlaceholders(entry->password()));
+ break;
+ case EntryModel::Url:
+ if (!entry->url().isEmpty()) {
+ openUrlForEntry(entry);
+ }
+ break;
+ // TODO: switch to 'Notes' tab in details view/pane
+ //case EntryModel::Notes:
+ // break;
+ // TODO: switch to 'Attachments' tab in details view/pane
+ //case EntryModel::Attachments:
+ // break;
+ default:
switchToEntryEdit(entry);
}
}
@@ -862,7 +976,7 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod
void DatabaseWidget::switchToEntryEdit()
{
Entry* entry = m_entryView->currentEntry();
-
+
if (!entry) {
return;
}
@@ -873,7 +987,7 @@ void DatabaseWidget::switchToEntryEdit()
void DatabaseWidget::switchToGroupEdit()
{
Group* group = m_groupView->currentGroup();
-
+
if (!group) {
return;
}
@@ -886,6 +1000,7 @@ void DatabaseWidget::switchToMasterKeyChange(bool disableCancel)
m_changeMasterKeyWidget->clearForms();
m_changeMasterKeyWidget->setCancelEnabled(!disableCancel);
setCurrentWidget(m_changeMasterKeyWidget);
+ m_importingCsv = false;
}
void DatabaseWidget::switchToDatabaseSettings()
@@ -894,48 +1009,59 @@ void DatabaseWidget::switchToDatabaseSettings()
setCurrentWidget(m_databaseSettingsWidget);
}
-void DatabaseWidget::switchToOpenDatabase(const QString& fileName)
+void DatabaseWidget::switchToOpenDatabase(const QString& filePath)
{
- updateFilename(fileName);
- m_databaseOpenWidget->load(fileName);
- setCurrentWidget(m_databaseOpenWidget);
+ updateFilePath(filePath);
+ if (m_databaseOpenWidget) {
+ m_databaseOpenWidget->load(filePath);
+ setCurrentWidget(m_databaseOpenWidget);
+ } else if (m_unlockDatabaseWidget) {
+ m_unlockDatabaseWidget->load(filePath);
+ setCurrentWidget(m_unlockDatabaseWidget);
+ }
}
-void DatabaseWidget::switchToOpenDatabase(const QString& fileName, const QString& password,
+void DatabaseWidget::switchToOpenDatabase(const QString& filePath, const QString& password,
const QString& keyFile)
{
- updateFilename(fileName);
- switchToOpenDatabase(fileName);
- m_databaseOpenWidget->enterKey(password, keyFile);
+ updateFilePath(filePath);
+ switchToOpenDatabase(filePath);
+ if (m_databaseOpenWidget) {
+ m_databaseOpenWidget->enterKey(password, keyFile);
+ } else if (m_unlockDatabaseWidget) {
+ m_unlockDatabaseWidget->enterKey(password, keyFile);
+ }
}
-void DatabaseWidget::switchToImportCsv(const QString& fileName)
+void DatabaseWidget::switchToImportCsv(const QString& filePath)
{
- updateFilename(fileName);
- switchToMasterKeyChange();
- m_csvImportWizard->load(fileName, m_db);
- setCurrentWidget(m_csvImportWizard);
+ updateFilePath(filePath);
+ m_csvImportWizard->load(filePath, m_db);
+ m_changeMasterKeyWidget->clearForms();
+ m_changeMasterKeyWidget->setCancelEnabled(false);
+ setCurrentWidget(m_changeMasterKeyWidget);
+ m_importingCsv = true;
}
-void DatabaseWidget::switchToOpenMergeDatabase(const QString& fileName)
+void DatabaseWidget::switchToOpenMergeDatabase(const QString& filePath)
{
m_databaseOpenMergeWidget->clearForms();
- m_databaseOpenMergeWidget->load(fileName);
+ m_databaseOpenMergeWidget->load(filePath);
setCurrentWidget(m_databaseOpenMergeWidget);
}
-void DatabaseWidget::switchToOpenMergeDatabase(const QString& fileName, const QString& password,
+void DatabaseWidget::switchToOpenMergeDatabase(const QString& filePath, const QString& password,
const QString& keyFile)
{
- switchToOpenMergeDatabase(fileName);
+ switchToOpenMergeDatabase(filePath);
m_databaseOpenMergeWidget->enterKey(password, keyFile);
}
-void DatabaseWidget::switchToImportKeepass1(const QString& fileName)
+void DatabaseWidget::switchToImportKeepass1(const QString& filePath)
{
- updateFilename(fileName);
- m_keepass1OpenWidget->load(fileName);
+ updateFilePath(filePath);
+ m_keepass1OpenWidget->load(filePath);
setCurrentWidget(m_keepass1OpenWidget);
}
@@ -1041,6 +1167,32 @@ void DatabaseWidget::emitEntryContextMenuRequested(const QPoint& pos)
emit entryContextMenuRequested(m_entryView->viewport()->mapToGlobal(pos));
}
+void DatabaseWidget::emitPressedEntry()
+{
+ Entry* currentEntry = m_entryView->currentEntry();
+ emitPressedEntry(currentEntry);
+}
+
+void DatabaseWidget::emitPressedEntry(Entry* currentEntry)
+{
+ if (!currentEntry) {
+ // if no entry is pressed, leave in details the last entry
+ return;
+ }
+
+ emit pressedEntry(currentEntry);
+}
+
+void DatabaseWidget::emitPressedGroup(Group* currentGroup)
+{
+ if (!currentGroup) {
+ // if no group is pressed, leave in details the last group
+ return;
+ }
+
+ emit pressedGroup(currentGroup);
+}
+
bool DatabaseWidget::dbHasKey() const
{
return m_db->hasKey();
@@ -1054,7 +1206,7 @@ bool DatabaseWidget::canDeleteCurrentGroup() const
bool DatabaseWidget::isInSearchMode() const
{
- return m_entryView->inEntryListMode();
+ return m_entryView->inSearchMode();
}
Group* DatabaseWidget::currentGroup() const
@@ -1079,21 +1231,21 @@ void DatabaseWidget::lock()
endSearch();
clearAllWidgets();
- m_unlockDatabaseWidget->load(m_filename);
+ m_unlockDatabaseWidget->load(m_filePath);
setCurrentWidget(m_unlockDatabaseWidget);
Database* newDb = new Database();
newDb->metadata()->setName(m_db->metadata()->name());
replaceDatabase(newDb);
}
-void DatabaseWidget::updateFilename(const QString& fileName)
+void DatabaseWidget::updateFilePath(const QString &filePath)
{
- if (!m_filename.isEmpty()) {
- m_fileWatcher.removePath(m_filename);
+ if (!m_filePath.isEmpty()) {
+ m_fileWatcher.removePath(m_filePath);
}
- m_fileWatcher.addPath(fileName);
- m_filename = fileName;
+ m_fileWatcher.addPath(filePath);
+ m_filePath = filePath;
}
void DatabaseWidget::blockAutoReload(bool block)
@@ -1109,7 +1261,7 @@ void DatabaseWidget::blockAutoReload(bool block)
void DatabaseWidget::unblockAutoReload()
{
m_ignoreAutoReload = false;
- updateFilename(m_filename);
+ updateFilePath(m_filePath);
}
void DatabaseWidget::onWatchedFileChanged()
@@ -1125,12 +1277,17 @@ void DatabaseWidget::onWatchedFileChanged()
void DatabaseWidget::reloadDatabaseFile()
{
- if (m_db == nullptr || currentMode() == DatabaseWidget::LockedMode)
+ if (!m_db || currentMode() == DatabaseWidget::LockedMode) {
+ return;
+ }
+
+ if (currentMode() == DatabaseWidget::LockedMode) {
return;
+ }
if (! config()->get("AutoReloadOnChange").toBool()) {
// Ask if we want to reload the db
- QMessageBox::StandardButton mb = MessageBox::question(this, tr("Autoreload Request"),
+ QMessageBox::StandardButton mb = MessageBox::question(this, tr("File has changed"),
tr("The database file has changed. Do you want to load the changes?"),
QMessageBox::Yes | QMessageBox::No);
@@ -1139,20 +1296,20 @@ void DatabaseWidget::reloadDatabaseFile()
emit m_db->modified();
m_databaseModified = true;
// Rewatch the database file
- m_fileWatcher.addPath(m_filename);
+ m_fileWatcher.addPath(m_filePath);
return;
}
}
KeePass2Reader reader;
- QFile file(m_filename);
+ QFile file(m_filePath);
if (file.open(QIODevice::ReadOnly)) {
Database* db = reader.readDatabase(&file, database()->key());
if (db != nullptr) {
if (m_databaseModified) {
// Ask if we want to merge changes into new database
QMessageBox::StandardButton mb = MessageBox::question(this, tr("Merge Request"),
- tr("The database file has changed and you have unsaved changes."
+ tr("The database file has changed and you have unsaved changes.\n"
"Do you want to merge your changes?"),
QMessageBox::Yes | QMessageBox::No);
@@ -1186,12 +1343,16 @@ void DatabaseWidget::reloadDatabaseFile()
}
} else {
m_messageWidget->showMessage(
- tr("Could not open the new database file while attempting to autoreload this database."),
+ tr("Could not open the new database file while attempting to autoreload this database.")
+ .append("\n").append(file.errorString()),
MessageWidget::Error);
+ // HACK: Directly calling the database's signal
+ // Mark db as modified since existing data may differ from file or file was deleted
+ m_db->modified();
}
// Rewatch the database file
- m_fileWatcher.addPath(m_filename);
+ m_fileWatcher.addPath(m_filePath);
}
int DatabaseWidget::numberOfSelectedEntries() const
@@ -1246,8 +1407,8 @@ bool DatabaseWidget::isGroupSelected() const
bool DatabaseWidget::currentEntryHasTitle()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return false;
}
return !currentEntry->title().isEmpty();
@@ -1256,8 +1417,8 @@ bool DatabaseWidget::currentEntryHasTitle()
bool DatabaseWidget::currentEntryHasUsername()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return false;
}
return !currentEntry->resolveMultiplePlaceholders(currentEntry->username()).isEmpty();
@@ -1266,8 +1427,8 @@ bool DatabaseWidget::currentEntryHasUsername()
bool DatabaseWidget::currentEntryHasPassword()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return false;
}
return !currentEntry->resolveMultiplePlaceholders(currentEntry->password()).isEmpty();
@@ -1276,8 +1437,8 @@ bool DatabaseWidget::currentEntryHasPassword()
bool DatabaseWidget::currentEntryHasUrl()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return false;
}
return !currentEntry->resolveMultiplePlaceholders(currentEntry->url()).isEmpty();
@@ -1287,8 +1448,8 @@ bool DatabaseWidget::currentEntryHasUrl()
bool DatabaseWidget::currentEntryHasTotp()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return false;
}
return currentEntry->hasTotp();
@@ -1297,8 +1458,8 @@ bool DatabaseWidget::currentEntryHasTotp()
bool DatabaseWidget::currentEntryHasNotes()
{
Entry* currentEntry = m_entryView->currentEntry();
+ Q_ASSERT(currentEntry);
if (!currentEntry) {
- Q_ASSERT(false);
return false;
}
return !currentEntry->resolveMultiplePlaceholders(currentEntry->notes()).isEmpty();
@@ -1315,7 +1476,13 @@ EntryView* DatabaseWidget::entryView() {
void DatabaseWidget::showUnlockDialog()
{
m_unlockDatabaseDialog->clearForms();
- m_unlockDatabaseDialog->setDBFilename(m_filename);
+ m_unlockDatabaseDialog->setFilePath(m_filePath);
+
+#if defined(Q_OS_MAC)
+ autoType()->raiseWindow();
+ Tools::wait(500);
+#endif
+
m_unlockDatabaseDialog->show();
m_unlockDatabaseDialog->activateWindow();
}
@@ -1325,9 +1492,15 @@ void DatabaseWidget::closeUnlockDialog()
m_unlockDatabaseDialog->close();
}
-void DatabaseWidget::showMessage(const QString& text, MessageWidget::MessageType type)
+void DatabaseWidget::showMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton, int autoHideTimeout)
+{
+ m_messageWidget->setCloseButtonVisible(showClosebutton);
+ m_messageWidget->showMessage(text, type, autoHideTimeout);
+}
+
+void DatabaseWidget::showErrorMessage(const QString& errorMessage)
{
- m_messageWidget->showMessage(text, type);
+ showMessage(errorMessage, MessageWidget::MessageType::Error);
}
void DatabaseWidget::hideMessage()