Add unlock dialog on Autotype and show default Autotype sequence (#89)

* Add unlockdialog on autotype. Fix #10
* Show default autotype sequence for existing entries
* NOTE: New entries/groups do not show the default autotype sequence
This commit is contained in:
TheZ3ro 2016-11-11 22:26:07 +01:00 committed by Jonathan White
parent 0657d343bf
commit 6927158daa
13 changed files with 202 additions and 11 deletions

View File

@ -105,6 +105,7 @@ set(keepassx_SOURCES
gui/SearchWidget.cpp
gui/SortFilterHideProxyModel.cpp
gui/UnlockDatabaseWidget.cpp
gui/UnlockDatabaseDialog.cpp
gui/WelcomeWidget.cpp
gui/entry/AutoTypeAssociationsModel.cpp
gui/entry/EditEntryWidget.cpp

View File

@ -192,9 +192,6 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
QList<Entry*> entryList;
QHash<Entry*, QString> sequenceHash;
// TODO: Check if there are any active databases here, if not do nothing
// TODO: Check if all databases are locked, if so ask to unlock them
for (Database* db : dbList) {
const QList<Entry*> dbEntries = db->rootGroup()->entriesRecursive();
for (Entry* entry : dbEntries) {
@ -316,7 +313,7 @@ bool AutoType::parseActions(const QString& sequence, const Entry* entry, QList<A
for (const QChar& ch : sequence) {
// TODO: implement support for {{}, {}} and {DELAY=X}
// TODO: implement support for {{}, {}}
if (inTmpl) {
if (ch == '{') {
@ -446,7 +443,7 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
else if (tmplName == "ptrsc") {
list.append(new AutoTypeKey(Qt::Key_Print));
}
else if (tmplName == "scolllock") {
else if (tmplName == "scrolllock") {
list.append(new AutoTypeKey(Qt::Key_ScrollLock));
}
// Qt doesn't know about keypad keys so use the normal ones instead

View File

@ -185,6 +185,35 @@ QString Entry::defaultAutoTypeSequence() const
return m_data.defaultAutoTypeSequence;
}
QString Entry::effectiveAutoTypeSequence() const
{
if (!m_data.defaultAutoTypeSequence.isEmpty()) {
return m_data.defaultAutoTypeSequence;
}
QString sequence;
const Group* grp = group();
if(grp) {
sequence = grp->effectiveAutoTypeSequence();
} else {
return QString();
}
if (sequence.isEmpty() && (!username().isEmpty() || !password().isEmpty())) {
if (username().isEmpty()) {
sequence = "{PASSWORD}{ENTER}";
}
else if (password().isEmpty()) {
sequence = "{USERNAME}{ENTER}";
}
else {
sequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}";
}
}
return sequence;
}
AutoTypeAssociations* Entry::autoTypeAssociations()
{
return m_autoTypeAssociations;

View File

@ -70,6 +70,7 @@ public:
bool autoTypeEnabled() const;
int autoTypeObfuscation() const;
QString defaultAutoTypeSequence() const;
QString effectiveAutoTypeSequence() const;
AutoTypeAssociations* autoTypeAssociations();
const AutoTypeAssociations* autoTypeAssociations() const;
QString title() const;

View File

@ -187,6 +187,23 @@ QString Group::defaultAutoTypeSequence() const
return m_data.defaultAutoTypeSequence;
}
QString Group::effectiveAutoTypeSequence() const
{
QString sequence;
const Group* group = this;
do {
if (group->autoTypeEnabled() == Group::Disable) {
return QString();
}
sequence = group->defaultAutoTypeSequence();
group = group->parentGroup();
} while (group && sequence.isEmpty());
return sequence;
}
Group::TriState Group::autoTypeEnabled() const
{
return m_data.autoTypeEnabled;

View File

@ -66,6 +66,7 @@ public:
TimeInfo timeInfo() const;
bool isExpanded() const;
QString defaultAutoTypeSequence() const;
QString effectiveAutoTypeSequence() const;
Group::TriState autoTypeEnabled() const;
Group::TriState searchingEnabled() const;
Group::MergeMode mergeMode() const;

View File

@ -37,6 +37,7 @@
#include "gui/MessageBox.h"
#include "gui/entry/EntryView.h"
#include "gui/group/GroupView.h"
#include "gui/UnlockDatabaseDialog.h"
DatabaseManagerStruct::DatabaseManagerStruct()
: dbWidget(nullptr)
@ -235,6 +236,7 @@ bool DatabaseTabWidget::closeDatabase(Database* db)
int index = databaseIndex(db);
Q_ASSERT(index != -1);
dbStruct.dbWidget->closeUnlockDialog();
QString dbName = tabText(index);
if (dbName.right(1) == "*") {
dbName.chop(1);
@ -813,5 +815,9 @@ void DatabaseTabWidget::performGlobalAutoType()
}
}
autoType()->performGlobalAutoType(unlockedDatabases);
if (unlockedDatabases.size() > 0) {
autoType()->performGlobalAutoType(unlockedDatabases);
} else if (m_dbList.size() > 0){
indexDatabaseManagerStruct(0).dbWidget->showUnlockDialog();
}
}

View File

@ -43,6 +43,7 @@
#include "gui/KeePass1OpenWidget.h"
#include "gui/MessageBox.h"
#include "gui/UnlockDatabaseWidget.h"
#include "gui/UnlockDatabaseDialog.h"
#include "gui/entry/EditEntryWidget.h"
#include "gui/entry/EntryView.h"
#include "gui/group/EditGroupWidget.h"
@ -124,6 +125,8 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
m_keepass1OpenWidget->setObjectName("keepass1OpenWidget");
m_unlockDatabaseWidget = new UnlockDatabaseWidget();
m_unlockDatabaseWidget->setObjectName("unlockDatabaseWidget");
m_unlockDatabaseDialog = new UnlockDatabaseDialog();
m_unlockDatabaseDialog->setObjectName("unlockDatabaseDialog");
addWidget(m_mainWidget);
addWidget(m_editEntryWidget);
addWidget(m_editGroupWidget);
@ -153,6 +156,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
connect(m_databaseOpenMergeWidget, SIGNAL(editFinished(bool)), SLOT(mergeDatabase(bool)));
connect(m_keepass1OpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool)));
connect(m_unlockDatabaseWidget, SIGNAL(editFinished(bool)), SLOT(unlockDatabase(bool)));
connect(m_unlockDatabaseDialog, SIGNAL(unlockDone(bool)), SLOT(unlockDatabase(bool)));
connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged()));
m_searchCaseSensitive = false;
@ -173,7 +177,8 @@ DatabaseWidget::Mode DatabaseWidget::currentMode() const
else if (currentWidget() == m_mainWidget) {
return DatabaseWidget::ViewMode;
}
else if (currentWidget() == m_unlockDatabaseWidget) {
else if (currentWidget() == m_unlockDatabaseWidget ||
currentWidget() == m_databaseOpenWidget) {
return DatabaseWidget::LockedMode;
}
else {
@ -696,7 +701,14 @@ void DatabaseWidget::unlockDatabase(bool accepted)
return;
}
replaceDatabase(static_cast<DatabaseOpenWidget*>(sender())->database());
Database *db = Q_NULLPTR;
if (sender() == m_unlockDatabaseDialog) {
db = m_unlockDatabaseDialog->database();
} else if (sender() == m_unlockDatabaseWidget) {
db = m_unlockDatabaseWidget->database();
}
replaceDatabase(db);
const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
for (Group* group : groups) {
@ -710,6 +722,12 @@ void DatabaseWidget::unlockDatabase(bool accepted)
setCurrentWidget(m_mainWidget);
m_unlockDatabaseWidget->clearForms();
Q_EMIT unlockedDatabase();
if (sender() == m_unlockDatabaseDialog) {
QList<Database*> dbList;
dbList.append(m_db);
autoType()->performGlobalAutoType(dbList);
}
}
void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::ModelColumn column)
@ -1009,3 +1027,16 @@ GroupView* DatabaseWidget::groupView() {
EntryView* DatabaseWidget::entryView() {
return m_entryView;
}
void DatabaseWidget::showUnlockDialog()
{
m_unlockDatabaseDialog->clearForms();
m_unlockDatabaseDialog->setDBFilename(m_filename);
m_unlockDatabaseDialog->show();
m_unlockDatabaseDialog->activateWindow();
}
void DatabaseWidget::closeUnlockDialog()
{
m_unlockDatabaseDialog->close();
}

View File

@ -41,6 +41,7 @@ class QMenu;
class QSplitter;
class QLabel;
class UnlockDatabaseWidget;
class UnlockDatabaseDialog;
class DatabaseWidget : public QStackedWidget
{
@ -86,6 +87,8 @@ public:
bool currentEntryHasNotes();
GroupView* groupView();
EntryView* entryView();
void showUnlockDialog();
void closeUnlockDialog();
Q_SIGNALS:
void closeRequest();
@ -168,6 +171,7 @@ private:
DatabaseOpenWidget* m_databaseOpenMergeWidget;
KeePass1OpenWidget* m_keepass1OpenWidget;
UnlockDatabaseWidget* m_unlockDatabaseWidget;
UnlockDatabaseDialog* m_unlockDatabaseDialog;
QSplitter* m_splitter;
GroupView* m_groupView;
EntryView* m_entryView;

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2016 KeePassXC Team
*
* 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 "UnlockDatabaseDialog.h"
#include "UnlockDatabaseWidget.h"
#include "autotype/AutoType.h"
#include "gui/DragTabBar.h"
#include "core/Database.h"
UnlockDatabaseDialog::UnlockDatabaseDialog(QWidget *parent)
: QDialog(parent)
, m_view(new UnlockDatabaseWidget(this))
{
connect(m_view, SIGNAL(editFinished(bool)), this, SLOT(complete(bool)));
}
void UnlockDatabaseDialog::setDBFilename(const QString &filename)
{
m_view->load(filename);
}
void UnlockDatabaseDialog::clearForms()
{
m_view->clearForms();
}
Database *UnlockDatabaseDialog::database()
{
return m_view->database();
}
void UnlockDatabaseDialog::complete(bool r)
{
if (r) {
accept();
Q_EMIT unlockDone(true);
} else {
reject();
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 KeePassXC Team
*
* 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/>.
*/
#ifndef KEEPASSX_AUTOTYPEUNLOCKDIALOG_H
#define KEEPASSX_AUTOTYPEUNLOCKDIALOG_H
#include <QDialog>
//#include <gui/DatabaseTabWidget.h>
#include "core/Global.h"
class UnlockDatabaseWidget;
class Database;
class UnlockDatabaseDialog : public QDialog
{
Q_OBJECT
public:
explicit UnlockDatabaseDialog(QWidget *parent = Q_NULLPTR);
void setDBFilename(const QString& filename);
void clearForms();
Database* database();
Q_SIGNALS:
void unlockDone(bool);
public Q_SLOTS:
void complete(bool r);
private:
UnlockDatabaseWidget* const m_view;
};
#endif // KEEPASSX_AUTOTYPEUNLOCKDIALOG_H

View File

@ -354,12 +354,11 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore)
m_autoTypeUi->enableButton->setChecked(entry->autoTypeEnabled());
if (entry->defaultAutoTypeSequence().isEmpty()) {
m_autoTypeUi->inheritSequenceButton->setChecked(true);
m_autoTypeUi->sequenceEdit->setText("");
}
else {
m_autoTypeUi->customSequenceButton->setChecked(true);
m_autoTypeUi->sequenceEdit->setText(entry->defaultAutoTypeSequence());
}
m_autoTypeUi->sequenceEdit->setText(entry->effectiveAutoTypeSequence());
m_autoTypeUi->windowTitleCombo->lineEdit()->clear();
m_autoTypeUi->defaultWindowSequenceButton->setChecked(true);
m_autoTypeUi->windowSequenceEdit->setText("");

View File

@ -82,7 +82,7 @@ void EditGroupWidget::loadGroup(Group* group, bool create, Database* database)
else {
m_mainUi->autoTypeSequenceCustomRadio->setChecked(true);
}
m_mainUi->autoTypeSequenceCustomEdit->setText(group->defaultAutoTypeSequence());
m_mainUi->autoTypeSequenceCustomEdit->setText(group->effectiveAutoTypeSequence());
IconStruct iconStruct;
iconStruct.uuid = group->iconUuid();