Move Auto-Type associations handling from Entry into an own class.

This commit is contained in:
Felix Geyer 2012-07-16 09:54:04 +02:00
parent f4a4930f42
commit f98d834edb
9 changed files with 197 additions and 38 deletions

View File

@ -21,6 +21,7 @@ set(keepassx_SOURCES
autotype/AutoType.cpp autotype/AutoType.cpp
autotype/AutoTypeAction.cpp autotype/AutoTypeAction.cpp
autotype/ShortcutWidget.cpp autotype/ShortcutWidget.cpp
core/AutoTypeAssociations.cpp
core/Config.cpp core/Config.cpp
core/Database.cpp core/Database.cpp
core/DatabaseIcons.cpp core/DatabaseIcons.cpp
@ -97,6 +98,7 @@ set(keepassx_SOURCES
set(keepassx_MOC set(keepassx_MOC
autotype/AutoType.h autotype/AutoType.h
autotype/ShortcutWidget.h autotype/ShortcutWidget.h
core/AutoTypeAssociations.h
core/Config.h core/Config.h
core/Database.h core/Database.h
core/Entry.h core/Entry.h

View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 2012 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 "AutoTypeAssociations.h"
bool AutoTypeAssociations::Association::operator==(const AutoTypeAssociations::Association& other) const
{
return window == other.window && sequence == other.sequence;
}
bool AutoTypeAssociations::Association::operator!=(const AutoTypeAssociations::Association& other) const
{
return window != other.window || sequence != other.sequence;
}
AutoTypeAssociations::AutoTypeAssociations(QObject* parent)
: QObject(parent)
{
}
void AutoTypeAssociations::copyDataFrom(const AutoTypeAssociations* other)
{
if (m_associations == other->m_associations) {
return;
}
Q_EMIT aboutToReset();
m_associations = other->m_associations;
Q_EMIT reset();
Q_EMIT modified();
}
void AutoTypeAssociations::add(const AutoTypeAssociations::Association& association)
{
int index = m_associations.size();
Q_EMIT aboutToAdd(index);
m_associations.append(association);
Q_EMIT added(index);
Q_EMIT modified();
}
void AutoTypeAssociations::remove(int index)
{
Q_ASSERT(index >= 0 && index < m_associations.size());
Q_EMIT aboutToRemove(index);
m_associations.removeAt(index);
Q_EMIT removed(index);
Q_EMIT modified();
}
void AutoTypeAssociations::update(int index, const AutoTypeAssociations::Association& association)
{
Q_ASSERT(index >= 0 && index < m_associations.size());
if (m_associations.at(index) != association) {
m_associations[index] = association;
Q_EMIT dataChanged(index);
Q_EMIT modified();
}
}
AutoTypeAssociations::Association AutoTypeAssociations::get(int index) const
{
Q_ASSERT(index >= 0 && index < m_associations.size());
return m_associations.at(index);
}
QList<AutoTypeAssociations::Association> AutoTypeAssociations::getAll() const
{
return m_associations;
}
int AutoTypeAssociations::size() const
{
return m_associations.size();
}
void AutoTypeAssociations::clear()
{
m_associations.clear();
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2012 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/>.
*/
#ifndef KEEPASSX_AUTOTYPEASSOCIATIONS_H
#define KEEPASSX_AUTOTYPEASSOCIATIONS_H
#include <QtCore/QObject>
#include "core/Global.h"
class AutoTypeAssociations : public QObject
{
Q_OBJECT
public:
struct Association
{
QString window;
QString sequence;
bool operator==(const AutoTypeAssociations::Association& other) const;
bool operator!=(const AutoTypeAssociations::Association& other) const;
};
explicit AutoTypeAssociations(QObject* parent = Q_NULLPTR);
void copyDataFrom(const AutoTypeAssociations* other);
void add(const AutoTypeAssociations::Association& association);
void remove(int index);
void update(int index, const AutoTypeAssociations::Association& association);
AutoTypeAssociations::Association get(int index) const;
QList<AutoTypeAssociations::Association> getAll() const;
int size() const;
void clear();
private:
QList<AutoTypeAssociations::Association> m_associations;
Q_SIGNALS:
void modified();
void dataChanged(int index);
void aboutToAdd(int index);
void added(int index);
void aboutToRemove(int index);
void removed(int index);
void aboutToReset();
void reset();
};
Q_DECLARE_TYPEINFO(AutoTypeAssociations::Association, Q_MOVABLE_TYPE);
#endif // KEEPASSX_AUTOTYPEASSOCIATIONS_H

View File

@ -26,6 +26,9 @@
const int Entry::DefaultIconNumber = 0; const int Entry::DefaultIconNumber = 0;
Entry::Entry() Entry::Entry()
: m_attributes(new EntryAttributes(this))
, m_attachments(new EntryAttachments(this))
, m_autoTypeAssociations(new AutoTypeAssociations(this))
{ {
m_updateTimeinfo = true; m_updateTimeinfo = true;
m_tmpHistoryItem = Q_NULLPTR; m_tmpHistoryItem = Q_NULLPTR;
@ -34,14 +37,12 @@ Entry::Entry()
m_data.autoTypeEnabled = true; m_data.autoTypeEnabled = true;
m_data.autoTypeObfuscation = 0; m_data.autoTypeObfuscation = 0;
m_attributes = new EntryAttributes(this);
connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified())); connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified()));
connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged())); connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged()));
m_attachments = new EntryAttachments(this);
connect(m_attachments, SIGNAL(modified()), this, SIGNAL(modified())); connect(m_attachments, SIGNAL(modified()), this, SIGNAL(modified()));
connect(this, SIGNAL(modified()), this, SLOT(updateTimeinfo())); connect(m_autoTypeAssociations, SIGNAL(modified()), SIGNAL(modified()));
connect(this, SIGNAL(modified()), SLOT(updateTimeinfo()));
connect(this, SIGNAL(modified()), SLOT(updateModifiedSinceBegin())); connect(this, SIGNAL(modified()), SLOT(updateModifiedSinceBegin()));
} }
@ -166,9 +167,14 @@ QString Entry::defaultAutoTypeSequence() const
return m_data.defaultAutoTypeSequence; return m_data.defaultAutoTypeSequence;
} }
const QList<AutoTypeAssociation>& Entry::autoTypeAssociations() const AutoTypeAssociations* Entry::autoTypeAssociations()
{ {
return m_data.autoTypeAssociations; return m_autoTypeAssociations;
}
const AutoTypeAssociations* Entry::autoTypeAssociations() const
{
return m_autoTypeAssociations;
} }
QString Entry::autoTypeSequence(const QString& windowTitle) const QString Entry::autoTypeSequence(const QString& windowTitle) const
@ -180,9 +186,9 @@ QString Entry::autoTypeSequence(const QString& windowTitle) const
bool enableSet = false; bool enableSet = false;
QString sequence; QString sequence;
if (!windowTitle.isEmpty()) { if (!windowTitle.isEmpty()) {
Q_FOREACH (const AutoTypeAssociation& autoTypeAssoc, m_data.autoTypeAssociations) { Q_FOREACH (const AutoTypeAssociations::Association& assoc, m_autoTypeAssociations->getAll()) {
if (windowMatches(windowTitle, autoTypeAssoc.window)) { if (windowMatches(windowTitle, assoc.window)) {
sequence = autoTypeAssoc.sequence; sequence = assoc.sequence;
break; break;
} }
} }
@ -354,12 +360,6 @@ void Entry::setDefaultAutoTypeSequence(const QString& sequence)
set(m_data.defaultAutoTypeSequence, sequence); set(m_data.defaultAutoTypeSequence, sequence);
} }
void Entry::addAutoTypeAssociation(const AutoTypeAssociation& assoc)
{
m_data.autoTypeAssociations << assoc;
Q_EMIT modified();
}
void Entry::setTitle(const QString& title) void Entry::setTitle(const QString& title)
{ {
m_attributes->set("Title", title, m_attributes->isProtected("Title")); m_attributes->set("Title", title, m_attributes->isProtected("Title"));
@ -495,6 +495,7 @@ Entry* Entry::clone() const
entry->m_data = m_data; entry->m_data = m_data;
*entry->m_attributes = *m_attributes; *entry->m_attributes = *m_attributes;
*entry->m_attachments = *m_attachments; *entry->m_attachments = *m_attachments;
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
entry->setUpdateTimeinfo(true); entry->setUpdateTimeinfo(true);
return entry; return entry;

View File

@ -27,6 +27,7 @@
#include <QtGui/QPixmap> #include <QtGui/QPixmap>
#include <QtGui/QPixmapCache> #include <QtGui/QPixmapCache>
#include "core/AutoTypeAssociations.h"
#include "core/EntryAttachments.h" #include "core/EntryAttachments.h"
#include "core/EntryAttributes.h" #include "core/EntryAttributes.h"
#include "core/Global.h" #include "core/Global.h"
@ -36,14 +37,6 @@
class Database; class Database;
class Group; class Group;
struct AutoTypeAssociation
{
QString window;
QString sequence;
};
Q_DECLARE_TYPEINFO(AutoTypeAssociation, Q_MOVABLE_TYPE);
struct EntryData struct EntryData
{ {
int iconNumber; int iconNumber;
@ -55,7 +48,6 @@ struct EntryData
bool autoTypeEnabled; bool autoTypeEnabled;
int autoTypeObfuscation; int autoTypeObfuscation;
QString defaultAutoTypeSequence; QString defaultAutoTypeSequence;
QList<AutoTypeAssociation> autoTypeAssociations;
TimeInfo timeInfo; TimeInfo timeInfo;
}; };
@ -79,7 +71,8 @@ public:
bool autoTypeEnabled() const; bool autoTypeEnabled() const;
int autoTypeObfuscation() const; int autoTypeObfuscation() const;
QString defaultAutoTypeSequence() const; QString defaultAutoTypeSequence() const;
const QList<AutoTypeAssociation>& autoTypeAssociations() const; AutoTypeAssociations* autoTypeAssociations();
const AutoTypeAssociations* autoTypeAssociations() const;
QString autoTypeSequence(const QString& windowTitle = QString()) const; QString autoTypeSequence(const QString& windowTitle = QString()) const;
QString title() const; QString title() const;
QString url() const; QString url() const;
@ -105,7 +98,6 @@ public:
void setAutoTypeEnabled(bool enable); void setAutoTypeEnabled(bool enable);
void setAutoTypeObfuscation(int obfuscation); void setAutoTypeObfuscation(int obfuscation);
void setDefaultAutoTypeSequence(const QString& sequence); void setDefaultAutoTypeSequence(const QString& sequence);
void addAutoTypeAssociation(const AutoTypeAssociation& assoc);
void setTitle(const QString& title); void setTitle(const QString& title);
void setUrl(const QString& url); void setUrl(const QString& url);
void setUsername(const QString& username); void setUsername(const QString& username);
@ -156,8 +148,9 @@ private:
Uuid m_uuid; Uuid m_uuid;
EntryData m_data; EntryData m_data;
EntryAttributes* m_attributes; EntryAttributes* const m_attributes;
EntryAttachments* m_attachments; EntryAttachments* const m_attachments;
AutoTypeAssociations* const m_autoTypeAssociations;
QList<Entry*> m_history; QList<Entry*> m_history;
Entry* m_tmpHistoryItem; Entry* m_tmpHistoryItem;

View File

@ -712,14 +712,14 @@ void KeePass2XmlReader::parseAutoTypeAssoc(Entry* entry)
{ {
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Association"); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Association");
AutoTypeAssociation assoc; AutoTypeAssociations::Association assoc;
while (!m_xml.error() && m_xml.readNextStartElement()) { while (!m_xml.error() && m_xml.readNextStartElement()) {
if (m_xml.name() == "Window") { if (m_xml.name() == "Window") {
assoc.window = readString(); assoc.window = readString();
} }
else if (m_xml.name() == "KeystrokeSequence") { else if (m_xml.name() == "KeystrokeSequence") {
assoc.sequence = readString(); assoc.sequence = readString();
entry->addAutoTypeAssociation(assoc); entry->autoTypeAssociations()->add(assoc);
} }
else { else {
skipCurrentElement(); skipCurrentElement();

View File

@ -384,14 +384,14 @@ void KeePass2XmlWriter::writeAutoType(const Entry* entry)
writeNumber("DataTransferObfuscation", entry->autoTypeObfuscation()); writeNumber("DataTransferObfuscation", entry->autoTypeObfuscation());
writeString("DefaultSequence", entry->defaultAutoTypeSequence()); writeString("DefaultSequence", entry->defaultAutoTypeSequence());
Q_FOREACH (const AutoTypeAssociation& assoc, entry->autoTypeAssociations()) { Q_FOREACH (const AutoTypeAssociations::Association& assoc, entry->autoTypeAssociations()->getAll()) {
writeAutoTypeAssoc(assoc); writeAutoTypeAssoc(assoc);
} }
m_xml.writeEndElement(); m_xml.writeEndElement();
} }
void KeePass2XmlWriter::writeAutoTypeAssoc(const AutoTypeAssociation& assoc) void KeePass2XmlWriter::writeAutoTypeAssoc(const AutoTypeAssociations::Association& assoc)
{ {
m_xml.writeStartElement("Association"); m_xml.writeStartElement("Association");

View File

@ -58,7 +58,7 @@ private:
void writeDeletedObject(const DeletedObject& delObj); void writeDeletedObject(const DeletedObject& delObj);
void writeEntry(const Entry* entry); void writeEntry(const Entry* entry);
void writeAutoType(const Entry* entry); void writeAutoType(const Entry* entry);
void writeAutoTypeAssoc(const AutoTypeAssociation& assoc); void writeAutoTypeAssoc(const AutoTypeAssociations::Association& assoc);
void writeEntryHistory(const Entry* entry); void writeEntryHistory(const Entry* entry);
void writeString(const QString& qualifiedName, const QString& string); void writeString(const QString& qualifiedName, const QString& string);

View File

@ -255,8 +255,8 @@ void TestKeePass2XmlReader::testEntry1()
QCOMPARE(entry->autoTypeEnabled(), false); QCOMPARE(entry->autoTypeEnabled(), false);
QCOMPARE(entry->autoTypeObfuscation(), 0); QCOMPARE(entry->autoTypeObfuscation(), 0);
QCOMPARE(entry->defaultAutoTypeSequence(), QString("")); QCOMPARE(entry->defaultAutoTypeSequence(), QString(""));
QCOMPARE(entry->autoTypeAssociations().size(), 1); QCOMPARE(entry->autoTypeAssociations()->size(), 1);
const AutoTypeAssociation assoc1 = entry->autoTypeAssociations().at(0); const AutoTypeAssociations::Association assoc1 = entry->autoTypeAssociations()->get(0);
QCOMPARE(assoc1.window, QString("Target Window")); QCOMPARE(assoc1.window, QString("Target Window"));
QCOMPARE(assoc1.sequence, QString("")); QCOMPARE(assoc1.sequence, QString(""));
} }
@ -300,11 +300,11 @@ void TestKeePass2XmlReader::testEntry2()
QCOMPARE(entry->autoTypeEnabled(), true); QCOMPARE(entry->autoTypeEnabled(), true);
QCOMPARE(entry->autoTypeObfuscation(), 1); QCOMPARE(entry->autoTypeObfuscation(), 1);
QCOMPARE(entry->defaultAutoTypeSequence(), QString("{USERNAME}{TAB}{PASSWORD}{ENTER}")); QCOMPARE(entry->defaultAutoTypeSequence(), QString("{USERNAME}{TAB}{PASSWORD}{ENTER}"));
QCOMPARE(entry->autoTypeAssociations().size(), 2); QCOMPARE(entry->autoTypeAssociations()->size(), 2);
const AutoTypeAssociation assoc1 = entry->autoTypeAssociations().at(0); const AutoTypeAssociations::Association assoc1 = entry->autoTypeAssociations()->get(0);
QCOMPARE(assoc1.window, QString("Target Window")); QCOMPARE(assoc1.window, QString("Target Window"));
QCOMPARE(assoc1.sequence, QString("{Title}{UserName}")); QCOMPARE(assoc1.sequence, QString("{Title}{UserName}"));
const AutoTypeAssociation assoc2 = entry->autoTypeAssociations().at(1); const AutoTypeAssociations::Association assoc2 = entry->autoTypeAssociations()->get(1);
QCOMPARE(assoc2.window, QString("Target Window 2")); QCOMPARE(assoc2.window, QString("Target Window 2"));
QCOMPARE(assoc2.sequence, QString("{Title}{UserName} test")); QCOMPARE(assoc2.sequence, QString("{Title}{UserName} test"));
} }