2010-08-24 16:26:52 -04:00
|
|
|
/*
|
|
|
|
* 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 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 "DatabaseWidget.h"
|
|
|
|
|
2013-10-03 09:18:16 -04:00
|
|
|
#include <QAction>
|
|
|
|
#include <QDesktopServices>
|
2017-01-28 08:18:43 -05:00
|
|
|
#include <QCheckBox>
|
2013-10-03 09:18:16 -04:00
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QLabel>
|
2014-05-03 10:59:41 -04:00
|
|
|
#include <QFile>
|
2013-10-03 09:18:16 -04:00
|
|
|
#include <QLineEdit>
|
2015-01-05 04:50:04 -05:00
|
|
|
#include <QKeyEvent>
|
2013-10-03 09:18:16 -04:00
|
|
|
#include <QSplitter>
|
2016-11-02 21:01:02 -04:00
|
|
|
#include <QLabel>
|
2015-05-12 12:25:43 -04:00
|
|
|
#include <QProcess>
|
2016-11-02 21:01:02 -04:00
|
|
|
#include <QHeaderView>
|
|
|
|
#include <QApplication>
|
2010-08-24 16:26:52 -04:00
|
|
|
|
2012-07-12 16:35:51 -04:00
|
|
|
#include "autotype/AutoType.h"
|
2013-10-29 15:54:56 -04:00
|
|
|
#include "core/Config.h"
|
2014-05-15 17:48:54 -04:00
|
|
|
#include "core/EntrySearcher.h"
|
2012-07-18 14:44:28 -04:00
|
|
|
#include "core/FilePath.h"
|
2013-10-29 22:00:02 -04:00
|
|
|
#include "core/Group.h"
|
2012-04-18 15:59:00 -04:00
|
|
|
#include "core/Metadata.h"
|
2012-04-18 18:46:37 -04:00
|
|
|
#include "core/Tools.h"
|
2014-05-03 10:59:41 -04:00
|
|
|
#include "format/KeePass2Reader.h"
|
2012-01-13 11:52:37 -05:00
|
|
|
#include "gui/ChangeMasterKeyWidget.h"
|
2012-05-26 10:20:32 -04:00
|
|
|
#include "gui/Clipboard.h"
|
2012-06-28 03:21:15 -04:00
|
|
|
#include "gui/DatabaseOpenWidget.h"
|
2012-04-19 10:20:20 -04:00
|
|
|
#include "gui/DatabaseSettingsWidget.h"
|
2012-06-28 03:21:15 -04:00
|
|
|
#include "gui/KeePass1OpenWidget.h"
|
2013-10-08 16:09:20 -04:00
|
|
|
#include "gui/MessageBox.h"
|
2012-10-12 06:12:00 -04:00
|
|
|
#include "gui/UnlockDatabaseWidget.h"
|
2016-11-11 16:26:07 -05:00
|
|
|
#include "gui/UnlockDatabaseDialog.h"
|
2012-05-16 04:16:32 -04:00
|
|
|
#include "gui/entry/EditEntryWidget.h"
|
|
|
|
#include "gui/entry/EntryView.h"
|
|
|
|
#include "gui/group/EditGroupWidget.h"
|
|
|
|
#include "gui/group/GroupView.h"
|
2010-08-24 16:26:52 -04:00
|
|
|
|
|
|
|
DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
|
2010-10-06 13:40:50 -04:00
|
|
|
: QStackedWidget(parent)
|
2012-01-13 11:52:37 -05:00
|
|
|
, m_db(db)
|
2015-07-24 12:28:12 -04:00
|
|
|
, m_newGroup(nullptr)
|
|
|
|
, m_newEntry(nullptr)
|
|
|
|
, m_newParent(nullptr)
|
2010-08-24 16:26:52 -04:00
|
|
|
{
|
2010-10-06 13:40:50 -04:00
|
|
|
m_mainWidget = new QWidget(this);
|
|
|
|
QLayout* layout = new QHBoxLayout(m_mainWidget);
|
2014-05-17 05:16:27 -04:00
|
|
|
m_splitter = new QSplitter(m_mainWidget);
|
2014-05-17 05:27:04 -04:00
|
|
|
m_splitter->setChildrenCollapsible(false);
|
2010-08-24 17:06:35 -04:00
|
|
|
|
2014-05-17 05:16:27 -04:00
|
|
|
QWidget* rightHandSideWidget = new QWidget(m_splitter);
|
2012-05-19 05:53:32 -04:00
|
|
|
|
2014-05-17 05:16:27 -04:00
|
|
|
m_groupView = new GroupView(db, m_splitter);
|
2012-04-14 14:31:35 -04:00
|
|
|
m_groupView->setObjectName("groupView");
|
2012-05-25 07:17:46 -04:00
|
|
|
m_groupView->setContextMenuPolicy(Qt::CustomContextMenu);
|
2012-08-01 04:35:37 -04:00
|
|
|
connect(m_groupView, SIGNAL(customContextMenuRequested(QPoint)),
|
|
|
|
SLOT(emitGroupContextMenuRequested(QPoint)));
|
2012-05-19 05:53:32 -04:00
|
|
|
|
|
|
|
m_entryView = new EntryView(rightHandSideWidget);
|
2012-04-14 14:31:35 -04:00
|
|
|
m_entryView->setObjectName("entryView");
|
2012-05-25 07:17:46 -04:00
|
|
|
m_entryView->setContextMenuPolicy(Qt::CustomContextMenu);
|
2012-06-28 03:21:15 -04:00
|
|
|
m_entryView->setGroup(db->rootGroup());
|
2012-08-01 04:35:37 -04:00
|
|
|
connect(m_entryView, SIGNAL(customContextMenuRequested(QPoint)),
|
|
|
|
SLOT(emitEntryContextMenuRequested(QPoint)));
|
2010-08-24 16:26:52 -04:00
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
// Add a notification for when we are searching
|
|
|
|
m_searchingLabel = new QLabel();
|
|
|
|
m_searchingLabel->setText(tr("Searching..."));
|
|
|
|
m_searchingLabel->setAlignment(Qt::AlignCenter);
|
|
|
|
m_searchingLabel->setStyleSheet("background-color: rgb(255, 253, 160);"
|
|
|
|
"border: 2px solid rgb(190, 190, 190);"
|
|
|
|
"border-radius: 5px;");
|
2012-05-16 03:56:18 -04:00
|
|
|
|
2012-05-19 05:53:32 -04:00
|
|
|
QVBoxLayout* vLayout = new QVBoxLayout(rightHandSideWidget);
|
2012-05-27 05:24:56 -04:00
|
|
|
vLayout->setMargin(0);
|
2016-11-02 21:01:02 -04:00
|
|
|
vLayout->addWidget(m_searchingLabel);
|
2012-05-12 07:22:41 -04:00
|
|
|
vLayout->addWidget(m_entryView);
|
2012-05-16 03:56:18 -04:00
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
m_searchingLabel->setVisible(false);
|
|
|
|
|
2012-05-16 03:56:18 -04:00
|
|
|
rightHandSideWidget->setLayout(vLayout);
|
|
|
|
|
2014-05-16 13:49:58 -04:00
|
|
|
setTabOrder(m_entryView, m_groupView);
|
|
|
|
|
2014-05-17 05:16:27 -04:00
|
|
|
m_splitter->addWidget(m_groupView);
|
|
|
|
m_splitter->addWidget(rightHandSideWidget);
|
2010-08-24 17:06:35 -04:00
|
|
|
|
2014-05-17 05:25:45 -04:00
|
|
|
m_splitter->setStretchFactor(0, 30);
|
|
|
|
m_splitter->setStretchFactor(1, 70);
|
|
|
|
|
2014-05-17 05:16:27 -04:00
|
|
|
layout->addWidget(m_splitter);
|
2010-10-06 13:40:50 -04:00
|
|
|
m_mainWidget->setLayout(layout);
|
|
|
|
|
2011-12-27 09:49:06 -05:00
|
|
|
m_editEntryWidget = new EditEntryWidget();
|
2012-04-14 14:31:35 -04:00
|
|
|
m_editEntryWidget->setObjectName("editEntryWidget");
|
2012-05-15 14:12:05 -04:00
|
|
|
m_historyEditEntryWidget = new EditEntryWidget();
|
2011-12-27 09:49:06 -05:00
|
|
|
m_editGroupWidget = new EditGroupWidget();
|
2012-04-14 14:31:35 -04:00
|
|
|
m_editGroupWidget->setObjectName("editGroupWidget");
|
2012-01-13 11:52:37 -05:00
|
|
|
m_changeMasterKeyWidget = new ChangeMasterKeyWidget();
|
|
|
|
m_changeMasterKeyWidget->headlineLabel()->setText(tr("Change master key"));
|
|
|
|
QFont headlineLabelFont = m_changeMasterKeyWidget->headlineLabel()->font();
|
|
|
|
headlineLabelFont.setBold(true);
|
|
|
|
headlineLabelFont.setPointSize(headlineLabelFont.pointSize() + 2);
|
|
|
|
m_changeMasterKeyWidget->headlineLabel()->setFont(headlineLabelFont);
|
2012-04-19 10:20:20 -04:00
|
|
|
m_databaseSettingsWidget = new DatabaseSettingsWidget();
|
2012-07-17 04:35:17 -04:00
|
|
|
m_databaseSettingsWidget->setObjectName("databaseSettingsWidget");
|
2012-06-28 03:21:15 -04:00
|
|
|
m_databaseOpenWidget = new DatabaseOpenWidget();
|
|
|
|
m_databaseOpenWidget->setObjectName("databaseOpenWidget");
|
2016-11-07 22:37:42 -05:00
|
|
|
m_databaseOpenMergeWidget = new DatabaseOpenWidget();
|
|
|
|
m_databaseOpenMergeWidget->setObjectName("databaseOpenMergeWidget");
|
2012-06-28 03:21:15 -04:00
|
|
|
m_keepass1OpenWidget = new KeePass1OpenWidget();
|
|
|
|
m_keepass1OpenWidget->setObjectName("keepass1OpenWidget");
|
2012-10-12 06:12:00 -04:00
|
|
|
m_unlockDatabaseWidget = new UnlockDatabaseWidget();
|
|
|
|
m_unlockDatabaseWidget->setObjectName("unlockDatabaseWidget");
|
2016-11-11 16:26:07 -05:00
|
|
|
m_unlockDatabaseDialog = new UnlockDatabaseDialog();
|
|
|
|
m_unlockDatabaseDialog->setObjectName("unlockDatabaseDialog");
|
2010-10-06 13:40:50 -04:00
|
|
|
addWidget(m_mainWidget);
|
2011-12-27 09:49:06 -05:00
|
|
|
addWidget(m_editEntryWidget);
|
|
|
|
addWidget(m_editGroupWidget);
|
2012-01-13 11:52:37 -05:00
|
|
|
addWidget(m_changeMasterKeyWidget);
|
2012-04-19 10:20:20 -04:00
|
|
|
addWidget(m_databaseSettingsWidget);
|
2012-05-15 14:12:05 -04:00
|
|
|
addWidget(m_historyEditEntryWidget);
|
2012-06-28 03:21:15 -04:00
|
|
|
addWidget(m_databaseOpenWidget);
|
2016-11-07 22:37:42 -05:00
|
|
|
addWidget(m_databaseOpenMergeWidget);
|
2012-06-28 03:21:15 -04:00
|
|
|
addWidget(m_keepass1OpenWidget);
|
2012-10-12 06:12:00 -04:00
|
|
|
addWidget(m_unlockDatabaseWidget);
|
2010-10-06 13:40:50 -04:00
|
|
|
|
2014-05-17 05:16:27 -04:00
|
|
|
connect(m_splitter, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterSizesChanged()));
|
2014-05-17 06:51:16 -04:00
|
|
|
connect(m_entryView->header(), SIGNAL(sectionResized(int,int,int)), SIGNAL(entryColumnSizesChanged()));
|
2016-11-28 19:02:21 -05:00
|
|
|
connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(onGroupChanged(Group*)));
|
2012-08-01 04:35:37 -04:00
|
|
|
connect(m_groupView, SIGNAL(groupChanged(Group*)), SIGNAL(groupChanged()));
|
2013-04-14 13:14:06 -04:00
|
|
|
connect(m_entryView, SIGNAL(entryActivated(Entry*, EntryModel::ModelColumn)),
|
|
|
|
SLOT(entryActivationSignalReceived(Entry*, EntryModel::ModelColumn)));
|
2012-08-01 04:35:37 -04:00
|
|
|
connect(m_entryView, SIGNAL(entrySelectionChanged()), SIGNAL(entrySelectionChanged()));
|
2011-12-27 09:49:06 -05:00
|
|
|
connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool)));
|
2012-05-15 14:12:05 -04:00
|
|
|
connect(m_editEntryWidget, SIGNAL(historyEntryActivated(Entry*)), SLOT(switchToHistoryView(Entry*)));
|
|
|
|
connect(m_historyEditEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchBackToEntryEdit()));
|
2011-12-27 09:49:06 -05:00
|
|
|
connect(m_editGroupWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool)));
|
2012-01-13 11:52:37 -05:00
|
|
|
connect(m_changeMasterKeyWidget, SIGNAL(editFinished(bool)), SLOT(updateMasterKey(bool)));
|
2012-05-19 08:52:00 -04:00
|
|
|
connect(m_databaseSettingsWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool)));
|
2012-06-28 03:21:15 -04:00
|
|
|
connect(m_databaseOpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool)));
|
2016-11-07 22:37:42 -05:00
|
|
|
connect(m_databaseOpenMergeWidget, SIGNAL(editFinished(bool)), SLOT(mergeDatabase(bool)));
|
2012-06-28 03:21:15 -04:00
|
|
|
connect(m_keepass1OpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool)));
|
2012-10-12 06:12:00 -04:00
|
|
|
connect(m_unlockDatabaseWidget, SIGNAL(editFinished(bool)), SLOT(unlockDatabase(bool)));
|
2016-11-11 16:47:01 -05:00
|
|
|
connect(m_unlockDatabaseDialog, SIGNAL(unlockDone(bool)), SLOT(unlockDatabase(bool)));
|
2016-11-09 07:38:14 -05:00
|
|
|
connect(&m_fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(onWatchedFileChanged()));
|
|
|
|
connect(&m_fileWatchTimer, SIGNAL(timeout()), this, SLOT(reloadDatabaseFile()));
|
2016-11-11 17:58:47 -05:00
|
|
|
connect(&m_ignoreWatchTimer, SIGNAL(timeout()), this, SLOT(onWatchedFileChanged()));
|
2012-04-24 19:32:05 -04:00
|
|
|
connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged()));
|
2016-11-02 21:01:02 -04:00
|
|
|
|
2016-11-11 17:58:47 -05:00
|
|
|
m_databaseModified = false;
|
|
|
|
|
2016-11-09 07:38:14 -05:00
|
|
|
m_fileWatchTimer.setSingleShot(true);
|
2016-11-11 17:58:47 -05:00
|
|
|
m_ignoreWatchTimer.setSingleShot(true);
|
|
|
|
m_ignoreNextAutoreload = false;
|
2016-11-09 07:38:14 -05:00
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
m_searchCaseSensitive = false;
|
2010-10-06 13:40:50 -04:00
|
|
|
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_mainWidget);
|
2010-10-06 13:40:50 -04:00
|
|
|
}
|
|
|
|
|
2012-05-19 05:53:32 -04:00
|
|
|
DatabaseWidget::~DatabaseWidget()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-05-15 16:51:13 -04:00
|
|
|
DatabaseWidget::Mode DatabaseWidget::currentMode() const
|
2012-04-24 19:32:05 -04:00
|
|
|
{
|
2015-07-24 12:28:12 -04:00
|
|
|
if (currentWidget() == nullptr) {
|
2012-04-25 14:22:55 -04:00
|
|
|
return DatabaseWidget::None;
|
2012-10-12 06:12:00 -04:00
|
|
|
}
|
|
|
|
else if (currentWidget() == m_mainWidget) {
|
2012-04-25 14:22:55 -04:00
|
|
|
return DatabaseWidget::ViewMode;
|
2012-10-12 06:12:00 -04:00
|
|
|
}
|
2016-11-11 16:26:07 -05:00
|
|
|
else if (currentWidget() == m_unlockDatabaseWidget ||
|
|
|
|
currentWidget() == m_databaseOpenWidget) {
|
2012-10-12 06:12:00 -04:00
|
|
|
return DatabaseWidget::LockedMode;
|
|
|
|
}
|
|
|
|
else {
|
2012-04-25 14:22:55 -04:00
|
|
|
return DatabaseWidget::EditMode;
|
2012-04-24 19:32:05 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-15 16:51:13 -04:00
|
|
|
bool DatabaseWidget::isInEditMode() const
|
|
|
|
{
|
2015-01-11 10:20:59 -05:00
|
|
|
return currentMode() == DatabaseWidget::EditMode;
|
2014-05-15 16:51:13 -04:00
|
|
|
}
|
|
|
|
|
2016-07-31 18:22:04 -04:00
|
|
|
bool DatabaseWidget::isEditWidgetModified() const
|
|
|
|
{
|
|
|
|
if (currentWidget() == m_editEntryWidget) {
|
|
|
|
return m_editEntryWidget->hasBeenModified();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// other edit widget don't have a hasBeenModified() method yet
|
|
|
|
// assume that they already have been modified
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-17 05:16:27 -04:00
|
|
|
QList<int> DatabaseWidget::splitterSizes() const
|
|
|
|
{
|
|
|
|
return m_splitter->sizes();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::setSplitterSizes(const QList<int>& sizes)
|
|
|
|
{
|
|
|
|
m_splitter->setSizes(sizes);
|
|
|
|
}
|
2014-05-15 16:51:13 -04:00
|
|
|
|
2014-05-17 06:51:16 -04:00
|
|
|
QList<int> DatabaseWidget::entryHeaderViewSizes() const
|
|
|
|
{
|
|
|
|
QList<int> sizes;
|
|
|
|
|
|
|
|
for (int i = 0; i < m_entryView->header()->count(); i++) {
|
|
|
|
sizes.append(m_entryView->header()->sectionSize(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
return sizes;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::setEntryViewHeaderSizes(const QList<int>& sizes)
|
|
|
|
{
|
|
|
|
if (sizes.size() != m_entryView->header()->count()) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < sizes.size(); i++) {
|
|
|
|
m_entryView->header()->resizeSection(i, sizes[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-11 10:20:59 -05:00
|
|
|
void DatabaseWidget::clearAllWidgets()
|
|
|
|
{
|
|
|
|
m_editEntryWidget->clear();
|
|
|
|
m_historyEditEntryWidget->clear();
|
|
|
|
m_editGroupWidget->clear();
|
|
|
|
}
|
|
|
|
|
2012-04-24 19:32:05 -04:00
|
|
|
void DatabaseWidget::emitCurrentModeChanged()
|
|
|
|
{
|
|
|
|
Q_EMIT currentModeChanged(currentMode());
|
|
|
|
}
|
|
|
|
|
2012-07-06 13:21:19 -04:00
|
|
|
Database* DatabaseWidget::database()
|
|
|
|
{
|
|
|
|
return m_db;
|
|
|
|
}
|
|
|
|
|
2011-12-27 10:04:59 -05:00
|
|
|
void DatabaseWidget::createEntry()
|
|
|
|
{
|
2012-05-25 07:40:17 -04:00
|
|
|
if (!m_groupView->currentGroup()) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-27 10:04:59 -05:00
|
|
|
m_newEntry = new Entry();
|
|
|
|
m_newEntry->setUuid(Uuid::random());
|
2012-04-23 14:10:07 -04:00
|
|
|
m_newEntry->setUsername(m_db->metadata()->defaultUserName());
|
2011-12-27 10:04:59 -05:00
|
|
|
m_newParent = m_groupView->currentGroup();
|
2014-04-14 17:20:24 -04:00
|
|
|
setIconFromParent();
|
|
|
|
switchToEntryEdit(m_newEntry, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::setIconFromParent()
|
|
|
|
{
|
2014-04-14 17:31:56 -04:00
|
|
|
if (!config()->get("UseGroupIconOnEntryCreation").toBool()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-14 17:20:24 -04:00
|
|
|
if (m_newParent->iconNumber() == Group::DefaultIconNumber && m_newParent->iconUuid().isNull()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_newParent->iconUuid().isNull()) {
|
2013-10-29 22:00:02 -04:00
|
|
|
m_newEntry->setIcon(m_newParent->iconNumber());
|
|
|
|
}
|
2014-04-14 17:20:24 -04:00
|
|
|
else {
|
|
|
|
m_newEntry->setIcon(m_newParent->iconUuid());
|
|
|
|
}
|
2011-12-27 10:04:59 -05:00
|
|
|
}
|
|
|
|
|
2015-01-11 10:20:59 -05:00
|
|
|
void DatabaseWidget::replaceDatabase(Database* db)
|
|
|
|
{
|
|
|
|
Database* oldDb = m_db;
|
|
|
|
m_db = db;
|
|
|
|
m_groupView->changeDatabase(m_db);
|
2016-11-11 17:58:47 -05:00
|
|
|
Q_EMIT databaseChanged(m_db, m_databaseModified);
|
2015-01-11 10:20:59 -05:00
|
|
|
delete oldDb;
|
|
|
|
}
|
|
|
|
|
2012-05-15 15:10:39 -04:00
|
|
|
void DatabaseWidget::cloneEntry()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
2012-05-25 07:40:17 -04:00
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-25 20:02:32 -05:00
|
|
|
Entry* entry = currentEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo | Entry::CloneRenameTitle);
|
2012-05-15 15:10:39 -04:00
|
|
|
entry->setGroup(currentEntry->group());
|
2017-01-25 20:02:32 -05:00
|
|
|
if (isInSearchMode())
|
|
|
|
search(m_lastSearchText);
|
2012-05-15 15:10:39 -04:00
|
|
|
m_entryView->setFocus();
|
|
|
|
m_entryView->setCurrentEntry(entry);
|
|
|
|
}
|
|
|
|
|
2013-10-08 15:36:01 -04:00
|
|
|
void DatabaseWidget::deleteEntries()
|
2012-04-18 14:08:54 -04:00
|
|
|
{
|
2013-10-08 15:36:01 -04:00
|
|
|
const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
|
|
|
|
|
|
|
|
if (selected.isEmpty()) {
|
2012-05-25 07:40:17 -04:00
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-08 15:36:01 -04:00
|
|
|
// get all entry pointers as the indexes change when removing multiple entries
|
|
|
|
QList<Entry*> selectedEntries;
|
2016-09-02 13:51:51 -04:00
|
|
|
for (const QModelIndex& index : selected) {
|
2013-10-08 15:36:01 -04:00
|
|
|
selectedEntries.append(m_entryView->entryFromIndex(index));
|
|
|
|
}
|
|
|
|
|
2016-12-01 23:04:42 -05:00
|
|
|
bool inRecycleBin = Tools::hasChild(m_db->metadata()->recycleBin(), selectedEntries.first());
|
|
|
|
if (inRecycleBin || !m_db->metadata()->recycleBinEnabled()) {
|
2013-10-08 15:36:01 -04:00
|
|
|
QMessageBox::StandardButton result;
|
|
|
|
|
|
|
|
if (selected.size() == 1) {
|
2013-10-08 16:09:20 -04:00
|
|
|
result = MessageBox::question(
|
2013-10-08 15:36:01 -04:00
|
|
|
this, tr("Delete entry?"),
|
|
|
|
tr("Do you really want to delete the entry \"%1\" for good?")
|
2017-02-06 14:23:51 -05:00
|
|
|
.arg(selectedEntries.first()->title().toHtmlEscaped()),
|
2013-10-08 15:36:01 -04:00
|
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
}
|
|
|
|
else {
|
2013-10-08 16:09:20 -04:00
|
|
|
result = MessageBox::question(
|
2013-10-08 15:36:01 -04:00
|
|
|
this, tr("Delete entries?"),
|
|
|
|
tr("Do you really want to delete %1 entries for good?")
|
|
|
|
.arg(selected.size()),
|
|
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
}
|
|
|
|
|
2012-04-18 15:59:00 -04:00
|
|
|
if (result == QMessageBox::Yes) {
|
2016-09-02 13:51:51 -04:00
|
|
|
for (Entry* entry : asConst(selectedEntries)) {
|
2013-10-08 15:36:01 -04:00
|
|
|
delete entry;
|
|
|
|
}
|
2012-04-18 15:59:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2016-09-02 06:00:12 -04:00
|
|
|
QMessageBox::StandardButton result;
|
|
|
|
|
|
|
|
if (selected.size() == 1) {
|
|
|
|
result = MessageBox::question(
|
|
|
|
this, tr("Move entry to recycle bin?"),
|
|
|
|
tr("Do you really want to move entry \"%1\" to the recycle bin?")
|
2017-02-06 14:23:51 -05:00
|
|
|
.arg(selectedEntries.first()->title().toHtmlEscaped()),
|
2016-09-02 06:00:12 -04:00
|
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result = MessageBox::question(
|
2013-10-08 15:36:01 -04:00
|
|
|
this, tr("Move entries to recycle bin?"),
|
2014-05-17 12:15:06 -04:00
|
|
|
tr("Do you really want to move %n entry(s) to the recycle bin?", 0, selected.size()),
|
2013-10-08 15:36:01 -04:00
|
|
|
QMessageBox::Yes | QMessageBox::No);
|
2016-09-02 06:00:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result == QMessageBox::No) {
|
|
|
|
return;
|
2013-10-08 15:36:01 -04:00
|
|
|
}
|
|
|
|
|
2016-09-02 13:51:51 -04:00
|
|
|
for (Entry* entry : asConst(selectedEntries)) {
|
2013-10-08 15:36:01 -04:00
|
|
|
m_db->recycleEntry(entry);
|
|
|
|
}
|
2012-04-18 15:59:00 -04:00
|
|
|
}
|
2012-04-18 14:08:54 -04:00
|
|
|
}
|
|
|
|
|
2016-12-22 02:21:52 -05:00
|
|
|
void DatabaseWidget::setFocus()
|
|
|
|
{
|
|
|
|
m_entryView->setFocus();
|
|
|
|
}
|
|
|
|
|
2013-12-01 03:43:41 -05:00
|
|
|
void DatabaseWidget::copyTitle()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-01 03:59:43 -05:00
|
|
|
setClipboardTextAndMinimize(currentEntry->title());
|
2013-12-01 03:43:41 -05:00
|
|
|
}
|
|
|
|
|
2012-05-26 10:20:32 -04:00
|
|
|
void DatabaseWidget::copyUsername()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-01 03:59:43 -05:00
|
|
|
setClipboardTextAndMinimize(currentEntry->username());
|
2012-05-26 10:20:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::copyPassword()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-01 03:59:43 -05:00
|
|
|
setClipboardTextAndMinimize(currentEntry->password());
|
2012-05-26 10:20:32 -04:00
|
|
|
}
|
|
|
|
|
2013-12-01 03:43:41 -05:00
|
|
|
void DatabaseWidget::copyURL()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-01 03:59:43 -05:00
|
|
|
setClipboardTextAndMinimize(currentEntry->url());
|
2013-12-01 03:43:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::copyNotes()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-01 03:59:43 -05:00
|
|
|
setClipboardTextAndMinimize(currentEntry->notes());
|
2013-12-01 03:43:41 -05:00
|
|
|
}
|
|
|
|
|
2012-10-23 18:15:23 -04:00
|
|
|
void DatabaseWidget::copyAttribute(QAction* action)
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-01 03:59:43 -05:00
|
|
|
setClipboardTextAndMinimize(currentEntry->attributes()->value(action->text()));
|
|
|
|
}
|
2013-10-29 15:54:56 -04:00
|
|
|
|
2013-12-01 03:59:43 -05:00
|
|
|
void DatabaseWidget::setClipboardTextAndMinimize(const QString& text)
|
|
|
|
{
|
|
|
|
clipboard()->setText(text);
|
2013-10-29 15:54:56 -04:00
|
|
|
if (config()->get("MinimizeOnCopy").toBool()) {
|
|
|
|
window()->showMinimized();
|
|
|
|
}
|
2012-10-23 18:15:23 -04:00
|
|
|
}
|
|
|
|
|
2012-07-12 16:35:51 -04:00
|
|
|
void DatabaseWidget::performAutoType()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
autoType()->performAutoType(currentEntry, window());
|
|
|
|
}
|
|
|
|
|
2012-07-27 12:38:52 -04:00
|
|
|
void DatabaseWidget::openUrl()
|
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-07 15:05:52 -04:00
|
|
|
openUrlForEntry(currentEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::openUrlForEntry(Entry* entry)
|
|
|
|
{
|
2016-11-25 12:26:59 -05:00
|
|
|
QString urlString = entry->resolveMultiplePlaceholders(entry->url());
|
2015-07-13 16:36:20 -04:00
|
|
|
if (urlString.isEmpty()) {
|
2015-05-12 12:25:43 -04:00
|
|
|
return;
|
2015-07-13 16:36:20 -04:00
|
|
|
}
|
2015-05-12 12:25:43 -04:00
|
|
|
|
2015-07-13 16:41:03 -04:00
|
|
|
if (urlString.startsWith("cmd://")) {
|
2017-01-28 08:18:43 -05:00
|
|
|
// check if decision to execute command was stored
|
|
|
|
if (entry->attributes()->hasKey(EntryAttributes::RememberCmdExecAttr)) {
|
|
|
|
if (entry->attributes()->value(EntryAttributes::RememberCmdExecAttr) == "1") {
|
|
|
|
QProcess::startDetached(urlString.mid(6));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise ask user
|
2015-07-13 16:41:03 -04:00
|
|
|
if (urlString.length() > 6) {
|
2017-01-28 08:24:33 -05:00
|
|
|
QString cmdTruncated = urlString.mid(6);
|
2017-01-28 08:18:43 -05:00
|
|
|
if (cmdTruncated.length() > 400)
|
|
|
|
cmdTruncated = cmdTruncated.left(400) + " […]";
|
|
|
|
QMessageBox msgbox(QMessageBox::Icon::Question,
|
|
|
|
tr("Execute command?"),
|
|
|
|
tr("Do you really want to execute the following command?<br><br>%1<br>")
|
|
|
|
.arg(cmdTruncated.toHtmlEscaped()),
|
|
|
|
QMessageBox::Yes | QMessageBox::No,
|
|
|
|
this
|
|
|
|
);
|
|
|
|
msgbox.setDefaultButton(QMessageBox::No);
|
|
|
|
|
|
|
|
QCheckBox* checkbox = new QCheckBox(tr("Remember my choice"), &msgbox);
|
|
|
|
msgbox.setCheckBox(checkbox);
|
|
|
|
bool remember = false;
|
|
|
|
QObject::connect(checkbox, &QCheckBox::stateChanged, [&](int state) {
|
|
|
|
if (static_cast<Qt::CheckState>(state) == Qt::CheckState::Checked) {
|
|
|
|
remember = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
int result = msgbox.exec();
|
2017-01-27 18:00:36 -05:00
|
|
|
if (result == QMessageBox::Yes) {
|
|
|
|
QProcess::startDetached(urlString.mid(6));
|
|
|
|
}
|
2017-01-28 08:18:43 -05:00
|
|
|
|
|
|
|
if (remember) {
|
|
|
|
entry->attributes()->set(EntryAttributes::RememberCmdExecAttr,
|
|
|
|
result == QMessageBox::Yes ? "1" : "0");
|
|
|
|
}
|
2015-07-13 16:41:03 -04:00
|
|
|
}
|
2012-07-27 12:38:52 -04:00
|
|
|
}
|
2015-07-13 16:36:20 -04:00
|
|
|
else {
|
2015-07-16 13:52:34 -04:00
|
|
|
QUrl url = QUrl::fromUserInput(urlString);
|
|
|
|
QDesktopServices::openUrl(url);
|
2012-07-27 12:38:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-27 09:49:06 -05:00
|
|
|
void DatabaseWidget::createGroup()
|
|
|
|
{
|
2012-05-25 07:40:17 -04:00
|
|
|
if (!m_groupView->currentGroup()) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-27 09:49:06 -05:00
|
|
|
m_newGroup = new Group();
|
|
|
|
m_newGroup->setUuid(Uuid::random());
|
2011-12-27 10:04:59 -05:00
|
|
|
m_newParent = m_groupView->currentGroup();
|
2011-12-27 09:49:06 -05:00
|
|
|
switchToGroupEdit(m_newGroup, true);
|
|
|
|
}
|
|
|
|
|
2012-04-21 13:06:28 -04:00
|
|
|
void DatabaseWidget::deleteGroup()
|
|
|
|
{
|
2012-05-25 07:40:17 -04:00
|
|
|
Group* currentGroup = m_groupView->currentGroup();
|
2014-05-15 16:56:36 -04:00
|
|
|
if (!currentGroup || !canDeleteCurrentGroup()) {
|
2012-05-25 07:40:17 -04:00
|
|
|
Q_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
2012-04-21 13:06:28 -04:00
|
|
|
|
2016-12-01 23:04:42 -05:00
|
|
|
bool inRecycleBin = Tools::hasChild(m_db->metadata()->recycleBin(), currentGroup);
|
2016-08-03 17:24:08 -04:00
|
|
|
bool isRecycleBin = (currentGroup == m_db->metadata()->recycleBin());
|
|
|
|
bool isRecycleBinSubgroup = Tools::hasChild(currentGroup, m_db->metadata()->recycleBin());
|
2016-12-01 23:04:42 -05:00
|
|
|
if (inRecycleBin || isRecycleBin || isRecycleBinSubgroup || !m_db->metadata()->recycleBinEnabled()) {
|
2013-10-08 16:09:20 -04:00
|
|
|
QMessageBox::StandardButton result = MessageBox::question(
|
2012-04-28 06:38:39 -04:00
|
|
|
this, tr("Delete group?"),
|
|
|
|
tr("Do you really want to delete the group \"%1\" for good?")
|
2017-02-06 14:23:51 -05:00
|
|
|
.arg(currentGroup->name().toHtmlEscaped()),
|
2012-04-21 13:06:28 -04:00
|
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
if (result == QMessageBox::Yes) {
|
2012-05-25 07:40:17 -04:00
|
|
|
delete currentGroup;
|
2012-04-21 13:06:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2012-05-25 07:40:17 -04:00
|
|
|
m_db->recycleGroup(currentGroup);
|
2012-04-21 13:06:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-24 04:51:22 -04:00
|
|
|
int DatabaseWidget::addWidget(QWidget* w)
|
|
|
|
{
|
|
|
|
w->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
|
|
|
|
|
|
|
int index = QStackedWidget::addWidget(w);
|
|
|
|
|
|
|
|
adjustSize();
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::setCurrentIndex(int index)
|
2012-10-12 06:12:00 -04:00
|
|
|
{
|
|
|
|
// use setCurrentWidget() instead
|
|
|
|
// index is not reliable
|
|
|
|
Q_UNUSED(index);
|
|
|
|
Q_ASSERT(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::setCurrentWidget(QWidget* widget)
|
2012-04-24 04:51:22 -04:00
|
|
|
{
|
|
|
|
if (currentWidget()) {
|
|
|
|
currentWidget()->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
|
|
|
}
|
|
|
|
|
2012-10-12 06:12:00 -04:00
|
|
|
QStackedWidget::setCurrentWidget(widget);
|
2012-04-24 04:51:22 -04:00
|
|
|
|
|
|
|
if (currentWidget()) {
|
|
|
|
currentWidget()->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
|
|
|
}
|
|
|
|
|
|
|
|
adjustSize();
|
|
|
|
}
|
|
|
|
|
2011-12-27 09:49:06 -05:00
|
|
|
void DatabaseWidget::switchToView(bool accepted)
|
|
|
|
{
|
|
|
|
if (m_newGroup) {
|
|
|
|
if (accepted) {
|
2011-12-27 10:04:59 -05:00
|
|
|
m_newGroup->setParent(m_newParent);
|
2012-04-27 12:45:26 -04:00
|
|
|
m_groupView->setCurrentGroup(m_newGroup);
|
|
|
|
m_groupView->expandGroup(m_newParent);
|
2011-12-27 09:49:06 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
delete m_newGroup;
|
|
|
|
}
|
|
|
|
|
2015-07-24 12:28:12 -04:00
|
|
|
m_newGroup = nullptr;
|
|
|
|
m_newParent = nullptr;
|
2011-12-27 10:04:59 -05:00
|
|
|
}
|
|
|
|
else if (m_newEntry) {
|
|
|
|
if (accepted) {
|
|
|
|
m_newEntry->setGroup(m_newParent);
|
2012-05-02 13:33:37 -04:00
|
|
|
m_entryView->setFocus();
|
|
|
|
m_entryView->setCurrentEntry(m_newEntry);
|
2011-12-27 10:04:59 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
delete m_newEntry;
|
|
|
|
}
|
|
|
|
|
2015-07-24 12:28:12 -04:00
|
|
|
m_newEntry = nullptr;
|
|
|
|
m_newParent = nullptr;
|
2011-12-27 09:49:06 -05:00
|
|
|
}
|
|
|
|
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_mainWidget);
|
2010-10-06 13:40:50 -04:00
|
|
|
}
|
|
|
|
|
2012-05-15 14:12:05 -04:00
|
|
|
void DatabaseWidget::switchToHistoryView(Entry* entry)
|
|
|
|
{
|
2012-10-21 15:45:54 -04:00
|
|
|
m_historyEditEntryWidget->loadEntry(entry, false, true, m_editEntryWidget->entryTitle(), m_db);
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_historyEditEntryWidget);
|
2012-05-15 14:12:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::switchBackToEntryEdit()
|
|
|
|
{
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_editEntryWidget);
|
2012-05-15 14:12:05 -04:00
|
|
|
}
|
|
|
|
|
2011-12-27 09:49:06 -05:00
|
|
|
void DatabaseWidget::switchToEntryEdit(Entry* entry)
|
2010-10-06 13:40:50 -04:00
|
|
|
{
|
2011-12-27 10:04:59 -05:00
|
|
|
switchToEntryEdit(entry, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::switchToEntryEdit(Entry* entry, bool create)
|
|
|
|
{
|
2016-11-28 19:02:21 -05:00
|
|
|
Group* group = currentGroup();
|
2013-03-10 15:03:22 -04:00
|
|
|
Q_ASSERT(group);
|
2012-05-15 19:26:30 -04:00
|
|
|
|
2013-03-10 15:03:22 -04:00
|
|
|
m_editEntryWidget->loadEntry(entry, create, false, group->name(), m_db);
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_editEntryWidget);
|
2010-08-24 16:26:52 -04:00
|
|
|
}
|
2011-12-27 09:49:06 -05:00
|
|
|
|
|
|
|
void DatabaseWidget::switchToGroupEdit(Group* group, bool create)
|
|
|
|
{
|
2012-05-15 07:31:56 -04:00
|
|
|
m_editGroupWidget->loadGroup(group, create, m_db);
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_editGroupWidget);
|
2011-12-27 09:49:06 -05:00
|
|
|
}
|
2012-01-13 11:52:37 -05:00
|
|
|
|
|
|
|
void DatabaseWidget::updateMasterKey(bool accepted)
|
|
|
|
{
|
|
|
|
if (accepted) {
|
2012-07-27 12:54:35 -04:00
|
|
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
2015-05-09 13:47:53 -04:00
|
|
|
bool result = m_db->setKey(m_changeMasterKeyWidget->newMasterKey());
|
2012-07-27 12:54:35 -04:00
|
|
|
QApplication::restoreOverrideCursor();
|
2015-05-09 13:47:53 -04:00
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
MessageBox::critical(this, tr("Error"), tr("Unable to calculate master key"));
|
|
|
|
return;
|
|
|
|
}
|
2012-04-11 14:35:52 -04:00
|
|
|
}
|
2012-04-16 18:22:44 -04:00
|
|
|
else if (!m_db->hasKey()) {
|
2012-04-11 14:35:52 -04:00
|
|
|
Q_EMIT closeRequest();
|
|
|
|
return;
|
2012-01-13 11:52:37 -05:00
|
|
|
}
|
|
|
|
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_mainWidget);
|
2012-01-13 11:52:37 -05:00
|
|
|
}
|
|
|
|
|
2012-06-28 03:21:15 -04:00
|
|
|
void DatabaseWidget::openDatabase(bool accepted)
|
|
|
|
{
|
|
|
|
if (accepted) {
|
2015-01-11 10:20:59 -05:00
|
|
|
replaceDatabase(static_cast<DatabaseOpenWidget*>(sender())->database());
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_mainWidget);
|
2016-10-08 12:55:05 -04:00
|
|
|
Q_EMIT unlockedDatabase();
|
2012-06-28 03:21:15 -04:00
|
|
|
|
|
|
|
// We won't need those anymore and KeePass1OpenWidget closes
|
|
|
|
// the file in its dtor.
|
|
|
|
delete m_databaseOpenWidget;
|
2015-07-24 12:28:12 -04:00
|
|
|
m_databaseOpenWidget = nullptr;
|
2012-06-28 03:21:15 -04:00
|
|
|
delete m_keepass1OpenWidget;
|
2015-07-24 12:28:12 -04:00
|
|
|
m_keepass1OpenWidget = nullptr;
|
2016-11-09 07:38:14 -05:00
|
|
|
m_fileWatcher.addPath(m_filename);
|
2012-06-28 03:21:15 -04:00
|
|
|
}
|
|
|
|
else {
|
2016-11-09 07:38:14 -05:00
|
|
|
m_fileWatcher.removePath(m_filename);
|
2012-06-28 03:21:15 -04:00
|
|
|
if (m_databaseOpenWidget->database()) {
|
|
|
|
delete m_databaseOpenWidget->database();
|
|
|
|
}
|
|
|
|
Q_EMIT closeRequest();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-07 22:37:42 -05:00
|
|
|
void DatabaseWidget::mergeDatabase(bool accepted)
|
|
|
|
{
|
|
|
|
if (accepted) {
|
|
|
|
if (!m_db) {
|
|
|
|
MessageBox::critical(this, tr("Error"), tr("No current database."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Database* srcDb = static_cast<DatabaseOpenWidget*>(sender())->database();
|
|
|
|
|
|
|
|
if (!srcDb) {
|
|
|
|
MessageBox::critical(this, tr("Error"), tr("No source database, nothing to do."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_db->merge(srcDb);
|
|
|
|
}
|
|
|
|
|
|
|
|
setCurrentWidget(m_mainWidget);
|
|
|
|
Q_EMIT databaseMerged(m_db);
|
|
|
|
}
|
|
|
|
|
2012-10-12 06:12:00 -04:00
|
|
|
void DatabaseWidget::unlockDatabase(bool accepted)
|
|
|
|
{
|
2015-01-11 10:20:59 -05:00
|
|
|
if (!accepted) {
|
|
|
|
Q_EMIT closeRequest();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-11 16:26:07 -05:00
|
|
|
Database *db = Q_NULLPTR;
|
|
|
|
if (sender() == m_unlockDatabaseDialog) {
|
|
|
|
db = m_unlockDatabaseDialog->database();
|
|
|
|
} else if (sender() == m_unlockDatabaseWidget) {
|
|
|
|
db = m_unlockDatabaseWidget->database();
|
|
|
|
}
|
|
|
|
|
|
|
|
replaceDatabase(db);
|
2012-10-12 06:12:00 -04:00
|
|
|
|
2017-01-24 22:17:16 -05:00
|
|
|
restoreGroupEntryFocus(m_groupBeforeLock, m_entryBeforeLock);
|
2015-01-11 10:20:59 -05:00
|
|
|
m_groupBeforeLock = Uuid();
|
2017-01-24 22:17:16 -05:00
|
|
|
m_entryBeforeLock = Uuid();
|
|
|
|
|
2015-01-11 10:20:59 -05:00
|
|
|
setCurrentWidget(m_mainWidget);
|
|
|
|
m_unlockDatabaseWidget->clearForms();
|
2012-10-12 06:12:00 -04:00
|
|
|
Q_EMIT unlockedDatabase();
|
2016-11-11 16:26:07 -05:00
|
|
|
|
|
|
|
if (sender() == m_unlockDatabaseDialog) {
|
|
|
|
QList<Database*> dbList;
|
|
|
|
dbList.append(m_db);
|
|
|
|
autoType()->performGlobalAutoType(dbList);
|
|
|
|
}
|
2012-10-12 06:12:00 -04:00
|
|
|
}
|
|
|
|
|
2013-04-14 13:14:06 -04:00
|
|
|
void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::ModelColumn column)
|
|
|
|
{
|
|
|
|
if (column == EntryModel::Url && !entry->url().isEmpty()) {
|
|
|
|
openUrlForEntry(entry);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switchToEntryEdit(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-27 09:49:06 -05:00
|
|
|
void DatabaseWidget::switchToEntryEdit()
|
|
|
|
{
|
2014-03-22 07:07:06 -04:00
|
|
|
Entry* entry = m_entryView->currentEntry();
|
2017-01-28 11:27:20 -05:00
|
|
|
|
2014-03-22 07:07:06 -04:00
|
|
|
if (!entry) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switchToEntryEdit(entry, false);
|
2011-12-27 09:49:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::switchToGroupEdit()
|
|
|
|
{
|
2014-03-22 07:07:06 -04:00
|
|
|
Group* group = m_groupView->currentGroup();
|
2017-01-28 11:27:20 -05:00
|
|
|
|
2014-03-22 07:07:06 -04:00
|
|
|
if (!group) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switchToGroupEdit(group, false);
|
2011-12-27 09:49:06 -05:00
|
|
|
}
|
2012-01-13 11:52:37 -05:00
|
|
|
|
|
|
|
void DatabaseWidget::switchToMasterKeyChange()
|
|
|
|
{
|
|
|
|
m_changeMasterKeyWidget->clearForms();
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_changeMasterKeyWidget);
|
2012-01-13 11:52:37 -05:00
|
|
|
}
|
2012-04-16 15:03:35 -04:00
|
|
|
|
2012-04-19 10:20:20 -04:00
|
|
|
void DatabaseWidget::switchToDatabaseSettings()
|
|
|
|
{
|
2012-05-19 08:52:00 -04:00
|
|
|
m_databaseSettingsWidget->load(m_db);
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_databaseSettingsWidget);
|
2012-04-19 10:20:20 -04:00
|
|
|
}
|
|
|
|
|
2012-07-06 12:50:52 -04:00
|
|
|
void DatabaseWidget::switchToOpenDatabase(const QString& fileName)
|
2012-06-28 03:21:15 -04:00
|
|
|
{
|
2012-10-12 06:12:00 -04:00
|
|
|
updateFilename(fileName);
|
2012-07-06 12:50:52 -04:00
|
|
|
m_databaseOpenWidget->load(fileName);
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_databaseOpenWidget);
|
2012-06-28 03:21:15 -04:00
|
|
|
}
|
|
|
|
|
2012-07-06 12:50:52 -04:00
|
|
|
void DatabaseWidget::switchToOpenDatabase(const QString& fileName, const QString& password,
|
|
|
|
const QString& keyFile)
|
2012-06-28 03:21:15 -04:00
|
|
|
{
|
2012-10-12 06:12:00 -04:00
|
|
|
updateFilename(fileName);
|
2012-07-06 12:50:52 -04:00
|
|
|
switchToOpenDatabase(fileName);
|
2012-06-28 03:21:15 -04:00
|
|
|
m_databaseOpenWidget->enterKey(password, keyFile);
|
|
|
|
}
|
|
|
|
|
2016-11-07 22:37:42 -05:00
|
|
|
void DatabaseWidget::switchToOpenMergeDatabase(const QString& fileName)
|
|
|
|
{
|
|
|
|
m_databaseOpenMergeWidget->load(fileName);
|
|
|
|
setCurrentWidget(m_databaseOpenMergeWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::switchToOpenMergeDatabase(const QString& fileName, const QString& password,
|
|
|
|
const QString& keyFile)
|
|
|
|
{
|
|
|
|
switchToOpenMergeDatabase(fileName);
|
|
|
|
m_databaseOpenMergeWidget->enterKey(password, keyFile);
|
|
|
|
}
|
|
|
|
|
2012-07-06 12:50:52 -04:00
|
|
|
void DatabaseWidget::switchToImportKeepass1(const QString& fileName)
|
2012-06-28 03:21:15 -04:00
|
|
|
{
|
2012-10-12 06:12:00 -04:00
|
|
|
updateFilename(fileName);
|
2012-07-06 12:50:52 -04:00
|
|
|
m_keepass1OpenWidget->load(fileName);
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_keepass1OpenWidget);
|
2012-06-28 03:21:15 -04:00
|
|
|
}
|
|
|
|
|
2016-11-11 17:58:47 -05:00
|
|
|
void DatabaseWidget::databaseModified()
|
|
|
|
{
|
|
|
|
m_databaseModified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::databaseSaved()
|
|
|
|
{
|
|
|
|
m_databaseModified = false;
|
|
|
|
}
|
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
void DatabaseWidget::search(const QString& searchtext)
|
2014-11-18 02:26:04 -05:00
|
|
|
{
|
2016-11-02 21:01:02 -04:00
|
|
|
if (searchtext.isEmpty())
|
|
|
|
{
|
|
|
|
endSearch();
|
|
|
|
return;
|
2014-11-18 02:26:04 -05:00
|
|
|
}
|
2014-05-17 12:05:02 -04:00
|
|
|
|
|
|
|
Q_EMIT searchModeAboutToActivate();
|
|
|
|
|
2016-11-28 19:02:21 -05:00
|
|
|
Qt::CaseSensitivity caseSensitive = m_searchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
2012-05-27 08:26:59 -04:00
|
|
|
|
2016-11-28 19:02:21 -05:00
|
|
|
QList<Entry*> searchResult = EntrySearcher().search(searchtext, currentGroup(), caseSensitive);
|
2012-05-27 08:47:15 -04:00
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
m_entryView->setEntryList(searchResult);
|
|
|
|
m_lastSearchText = searchtext;
|
2012-05-27 08:47:15 -04:00
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
// Display a label detailing our search results
|
|
|
|
if (searchResult.size() > 0) {
|
|
|
|
m_searchingLabel->setText(tr("Search Results (%1)").arg(searchResult.size()));
|
2012-05-27 08:26:59 -04:00
|
|
|
}
|
|
|
|
else {
|
2016-11-02 21:01:02 -04:00
|
|
|
m_searchingLabel->setText(tr("No Results"));
|
2012-05-27 08:26:59 -04:00
|
|
|
}
|
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
m_searchingLabel->setVisible(true);
|
2014-05-17 06:51:16 -04:00
|
|
|
|
|
|
|
Q_EMIT searchModeActivated();
|
2012-05-19 05:53:32 -04:00
|
|
|
}
|
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
void DatabaseWidget::setSearchCaseSensitive(bool state)
|
2012-05-12 07:22:41 -04:00
|
|
|
{
|
2016-11-02 21:01:02 -04:00
|
|
|
m_searchCaseSensitive = state;
|
2012-05-27 08:47:15 -04:00
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
if (isInSearchMode())
|
|
|
|
search(m_lastSearchText);
|
|
|
|
}
|
2012-05-12 07:22:41 -04:00
|
|
|
|
2016-11-28 19:02:21 -05:00
|
|
|
void DatabaseWidget::onGroupChanged(Group* group)
|
2016-11-02 21:01:02 -04:00
|
|
|
{
|
2016-11-28 19:02:21 -05:00
|
|
|
// Intercept group changes if in search mode
|
2016-11-02 21:01:02 -04:00
|
|
|
if (isInSearchMode())
|
|
|
|
search(m_lastSearchText);
|
2016-11-28 19:02:21 -05:00
|
|
|
else
|
|
|
|
m_entryView->setGroup(group);
|
2012-05-12 07:22:41 -04:00
|
|
|
}
|
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
QString DatabaseWidget::getCurrentSearch()
|
2012-05-19 05:53:32 -04:00
|
|
|
{
|
2016-11-02 21:01:02 -04:00
|
|
|
return m_lastSearchText;
|
2012-05-19 05:53:32 -04:00
|
|
|
}
|
|
|
|
|
2016-11-02 21:01:02 -04:00
|
|
|
void DatabaseWidget::endSearch()
|
2012-05-27 07:19:12 -04:00
|
|
|
{
|
2016-11-02 21:01:02 -04:00
|
|
|
if (isInSearchMode())
|
|
|
|
{
|
|
|
|
Q_EMIT listModeAboutToActivate();
|
|
|
|
|
2016-11-28 19:02:21 -05:00
|
|
|
// Show the normal entry view of the current group
|
|
|
|
m_entryView->setGroup(currentGroup());
|
2016-11-02 21:01:02 -04:00
|
|
|
|
|
|
|
Q_EMIT listModeActivated();
|
2012-05-27 07:19:12 -04:00
|
|
|
}
|
2016-11-02 21:01:02 -04:00
|
|
|
|
|
|
|
m_searchingLabel->setVisible(false);
|
|
|
|
m_searchingLabel->setText(tr("Searching..."));
|
|
|
|
|
|
|
|
m_lastSearchText.clear();
|
2012-05-27 07:19:12 -04:00
|
|
|
}
|
|
|
|
|
2012-08-01 04:35:37 -04:00
|
|
|
void DatabaseWidget::emitGroupContextMenuRequested(const QPoint& pos)
|
|
|
|
{
|
|
|
|
Q_EMIT groupContextMenuRequested(m_groupView->viewport()->mapToGlobal(pos));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::emitEntryContextMenuRequested(const QPoint& pos)
|
|
|
|
{
|
|
|
|
Q_EMIT entryContextMenuRequested(m_entryView->viewport()->mapToGlobal(pos));
|
|
|
|
}
|
|
|
|
|
2014-05-15 16:53:59 -04:00
|
|
|
bool DatabaseWidget::dbHasKey() const
|
2012-04-16 15:03:35 -04:00
|
|
|
{
|
|
|
|
return m_db->hasKey();
|
|
|
|
}
|
2012-04-21 13:06:28 -04:00
|
|
|
|
2014-05-15 16:56:36 -04:00
|
|
|
bool DatabaseWidget::canDeleteCurrentGroup() const
|
2012-04-21 13:06:28 -04:00
|
|
|
{
|
|
|
|
bool isRootGroup = m_db->rootGroup() == m_groupView->currentGroup();
|
2016-08-03 17:45:04 -04:00
|
|
|
return !isRootGroup;
|
2012-04-21 13:06:28 -04:00
|
|
|
}
|
2012-05-13 13:43:01 -04:00
|
|
|
|
2014-05-15 16:53:59 -04:00
|
|
|
bool DatabaseWidget::isInSearchMode() const
|
2012-08-01 04:35:37 -04:00
|
|
|
{
|
|
|
|
return m_entryView->inEntryListMode();
|
|
|
|
}
|
|
|
|
|
2016-11-07 22:37:42 -05:00
|
|
|
Group* DatabaseWidget::currentGroup() const
|
|
|
|
{
|
2016-11-28 19:02:21 -05:00
|
|
|
return m_groupView->currentGroup();
|
2012-05-15 19:26:30 -04:00
|
|
|
}
|
2012-10-12 06:12:00 -04:00
|
|
|
|
|
|
|
void DatabaseWidget::lock()
|
|
|
|
{
|
|
|
|
Q_ASSERT(currentMode() != DatabaseWidget::LockedMode);
|
2015-07-20 16:10:44 -04:00
|
|
|
|
|
|
|
if (m_groupView->currentGroup()) {
|
|
|
|
m_groupBeforeLock = m_groupView->currentGroup()->uuid();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_groupBeforeLock = m_db->rootGroup()->uuid();
|
|
|
|
}
|
2012-10-12 06:12:00 -04:00
|
|
|
|
2017-01-24 22:17:16 -05:00
|
|
|
if (m_entryView->currentEntry()) {
|
|
|
|
m_entryBeforeLock = m_entryView->currentEntry()->uuid();
|
|
|
|
}
|
|
|
|
|
2015-01-11 10:20:59 -05:00
|
|
|
clearAllWidgets();
|
|
|
|
m_unlockDatabaseWidget->load(m_filename);
|
2012-10-12 06:12:00 -04:00
|
|
|
setCurrentWidget(m_unlockDatabaseWidget);
|
2015-01-11 10:20:59 -05:00
|
|
|
Database* newDb = new Database();
|
|
|
|
newDb->metadata()->setName(m_db->metadata()->name());
|
|
|
|
replaceDatabase(newDb);
|
2012-10-12 06:12:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::updateFilename(const QString& fileName)
|
|
|
|
{
|
2016-11-11 17:58:47 -05:00
|
|
|
if (! m_filename.isEmpty()) {
|
|
|
|
m_fileWatcher.removePath(m_filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fileWatcher.addPath(fileName);
|
2012-10-12 06:12:00 -04:00
|
|
|
m_filename = fileName;
|
|
|
|
}
|
2014-05-15 12:05:58 -04:00
|
|
|
|
2016-11-11 17:58:47 -05:00
|
|
|
void DatabaseWidget::ignoreNextAutoreload()
|
|
|
|
{
|
|
|
|
m_ignoreNextAutoreload = true;
|
|
|
|
m_ignoreWatchTimer.start(100);
|
|
|
|
}
|
|
|
|
|
2016-11-09 07:38:14 -05:00
|
|
|
void DatabaseWidget::onWatchedFileChanged()
|
2014-05-03 10:59:41 -04:00
|
|
|
{
|
2016-11-11 17:58:47 -05:00
|
|
|
if (m_ignoreNextAutoreload) {
|
|
|
|
// Reset the watch
|
|
|
|
m_ignoreNextAutoreload = false;
|
|
|
|
m_ignoreWatchTimer.stop();
|
|
|
|
m_fileWatcher.addPath(m_filename);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (m_fileWatchTimer.isActive())
|
|
|
|
return;
|
2014-05-03 10:59:41 -04:00
|
|
|
|
2016-11-11 17:58:47 -05:00
|
|
|
m_fileWatchTimer.start(500);
|
|
|
|
}
|
2016-11-09 07:38:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::reloadDatabaseFile()
|
|
|
|
{
|
|
|
|
if (m_db == nullptr)
|
2014-06-09 04:51:24 -04:00
|
|
|
return;
|
|
|
|
|
2016-11-09 07:38:14 -05:00
|
|
|
if (! config()->get("AutoReloadOnChange").toBool()) {
|
|
|
|
// Ask if we want to reload the db
|
2016-11-11 17:58:47 -05:00
|
|
|
QMessageBox::StandardButton mb = MessageBox::question(this, tr("Autoreload Request"),
|
2016-11-09 07:38:14 -05:00
|
|
|
tr("The database file has changed. Do you want to load the changes?"),
|
|
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
|
|
|
|
if (mb == QMessageBox::No) {
|
2016-11-11 17:58:47 -05:00
|
|
|
// Notify everyone the database does not match the file
|
|
|
|
emit m_db->modified();
|
|
|
|
m_databaseModified = true;
|
2016-11-09 07:38:14 -05:00
|
|
|
// Rewatch the database file
|
|
|
|
m_fileWatcher.addPath(m_filename);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-03 10:59:41 -04:00
|
|
|
KeePass2Reader reader;
|
|
|
|
QFile file(m_filename);
|
2016-11-09 07:38:14 -05:00
|
|
|
if (file.open(QIODevice::ReadOnly)) {
|
|
|
|
Database* db = reader.readDatabase(&file, database()->key());
|
|
|
|
if (db != nullptr) {
|
2016-11-11 17:58:47 -05:00
|
|
|
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."
|
|
|
|
"Do you want to merge your changes?"),
|
|
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
|
|
|
|
if (mb == QMessageBox::Yes) {
|
|
|
|
// Merge the old database into the new one
|
|
|
|
m_db->setEmitModified(false);
|
|
|
|
db->merge(m_db);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Since we are accepting the new file as-is, internally mark as unmodified
|
|
|
|
// TODO: when saving is moved out of DatabaseTabWidget, this should be replaced
|
|
|
|
m_databaseModified = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-24 22:17:16 -05:00
|
|
|
Uuid groupBeforeReload;
|
|
|
|
if (m_groupView && m_groupView->currentGroup()) {
|
|
|
|
groupBeforeReload = m_groupView->currentGroup()->uuid();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
groupBeforeReload = m_db->rootGroup()->uuid();
|
|
|
|
}
|
|
|
|
|
|
|
|
Uuid entryBeforeReload;
|
|
|
|
if (m_entryView && m_entryView->currentEntry()) {
|
|
|
|
entryBeforeReload = m_entryView->currentEntry()->uuid();
|
|
|
|
}
|
|
|
|
|
2016-11-09 07:38:14 -05:00
|
|
|
replaceDatabase(db);
|
2017-01-24 22:17:16 -05:00
|
|
|
restoreGroupEntryFocus(groupBeforeReload, entryBeforeReload);
|
|
|
|
|
2016-11-09 07:38:14 -05:00
|
|
|
}
|
|
|
|
else {
|
2016-11-11 17:58:47 -05:00
|
|
|
MessageBox::critical(this, tr("Autoreload Failed"),
|
|
|
|
tr("Could not parse or unlock the new database file while attempting"
|
2017-01-11 21:12:43 -05:00
|
|
|
" to autoreload this database."));
|
2016-11-09 07:38:14 -05:00
|
|
|
}
|
2014-05-03 10:59:41 -04:00
|
|
|
}
|
2016-11-09 07:38:14 -05:00
|
|
|
else {
|
2016-11-11 17:58:47 -05:00
|
|
|
MessageBox::critical(this, tr("Autoreload Failed"),
|
|
|
|
tr("Could not open the new database file while attempting to autoreload"
|
2017-01-11 21:12:43 -05:00
|
|
|
" this database."));
|
2014-05-03 10:59:41 -04:00
|
|
|
}
|
2016-11-09 07:38:14 -05:00
|
|
|
|
|
|
|
// Rewatch the database file
|
|
|
|
m_fileWatcher.addPath(m_filename);
|
2014-05-03 10:59:41 -04:00
|
|
|
}
|
2014-06-09 03:54:29 -04:00
|
|
|
|
2014-05-15 16:53:59 -04:00
|
|
|
int DatabaseWidget::numberOfSelectedEntries() const
|
2014-05-15 12:05:58 -04:00
|
|
|
{
|
|
|
|
return m_entryView->numberOfSelectedEntries();
|
|
|
|
}
|
|
|
|
|
2014-05-15 16:53:59 -04:00
|
|
|
QStringList DatabaseWidget::customEntryAttributes() const
|
2014-05-15 12:05:58 -04:00
|
|
|
{
|
|
|
|
Entry* entry = m_entryView->currentEntry();
|
|
|
|
if (!entry) {
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
return entry->attributes()->customKeys();
|
|
|
|
}
|
|
|
|
|
2017-01-24 22:17:16 -05:00
|
|
|
/*
|
|
|
|
* Restores the focus on the group and entry that was focused
|
|
|
|
* before the database was locked or reloaded.
|
|
|
|
*/
|
|
|
|
void DatabaseWidget::restoreGroupEntryFocus(Uuid groupUuid, Uuid entryUuid)
|
|
|
|
{
|
|
|
|
Group* restoredGroup = nullptr;
|
|
|
|
const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
|
|
|
for (Group* group : groups) {
|
|
|
|
if (group->uuid() == groupUuid) {
|
|
|
|
restoredGroup = group;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (restoredGroup != nullptr) {
|
|
|
|
m_groupView->setCurrentGroup(restoredGroup);
|
|
|
|
|
|
|
|
const QList<Entry*> entries = restoredGroup->entries();
|
|
|
|
for (Entry* entry : entries) {
|
|
|
|
if (entry->uuid() == entryUuid) {
|
|
|
|
m_entryView->setCurrentEntry(entry);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-05-15 16:53:59 -04:00
|
|
|
bool DatabaseWidget::isGroupSelected() const
|
2014-05-15 12:05:58 -04:00
|
|
|
{
|
2015-07-24 12:28:12 -04:00
|
|
|
return m_groupView->currentGroup() != nullptr;
|
2014-05-15 12:05:58 -04:00
|
|
|
}
|
2015-05-12 15:50:10 -04:00
|
|
|
|
2015-05-12 15:54:39 -04:00
|
|
|
bool DatabaseWidget::currentEntryHasTitle()
|
2015-05-12 15:50:10 -04:00
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !currentEntry->title().isEmpty();
|
|
|
|
}
|
|
|
|
|
2015-05-12 15:54:39 -04:00
|
|
|
bool DatabaseWidget::currentEntryHasUsername()
|
2015-05-12 15:50:10 -04:00
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !currentEntry->username().isEmpty();
|
|
|
|
}
|
|
|
|
|
2015-05-12 15:54:39 -04:00
|
|
|
bool DatabaseWidget::currentEntryHasPassword()
|
2015-05-12 15:50:10 -04:00
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !currentEntry->password().isEmpty();
|
|
|
|
}
|
|
|
|
|
2015-05-12 15:54:39 -04:00
|
|
|
bool DatabaseWidget::currentEntryHasUrl()
|
2015-05-12 15:50:10 -04:00
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !currentEntry->url().isEmpty();
|
|
|
|
}
|
|
|
|
|
2015-05-12 15:54:39 -04:00
|
|
|
bool DatabaseWidget::currentEntryHasNotes()
|
2015-05-12 15:50:10 -04:00
|
|
|
{
|
|
|
|
Entry* currentEntry = m_entryView->currentEntry();
|
|
|
|
if (!currentEntry) {
|
|
|
|
Q_ASSERT(false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return !currentEntry->notes().isEmpty();
|
|
|
|
}
|
2016-11-07 22:37:42 -05:00
|
|
|
|
|
|
|
GroupView* DatabaseWidget::groupView() {
|
|
|
|
return m_groupView;
|
|
|
|
}
|
|
|
|
|
|
|
|
EntryView* DatabaseWidget::entryView() {
|
|
|
|
return m_entryView;
|
|
|
|
}
|
2016-11-11 16:26:07 -05:00
|
|
|
|
|
|
|
void DatabaseWidget::showUnlockDialog()
|
|
|
|
{
|
|
|
|
m_unlockDatabaseDialog->clearForms();
|
|
|
|
m_unlockDatabaseDialog->setDBFilename(m_filename);
|
|
|
|
m_unlockDatabaseDialog->show();
|
|
|
|
m_unlockDatabaseDialog->activateWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWidget::closeUnlockDialog()
|
|
|
|
{
|
|
|
|
m_unlockDatabaseDialog->close();
|
|
|
|
}
|