Add EntryModel.

This commit is contained in:
Felix Geyer 2010-08-18 16:22:48 +02:00
parent 84bc5ef463
commit 8d623f37ca
11 changed files with 341 additions and 9 deletions

View File

@ -26,6 +26,7 @@ set(keepassx_SOURCES
core/Parser.cpp core/Parser.cpp
core/TimeInfo.cpp core/TimeInfo.cpp
core/Uuid.cpp core/Uuid.cpp
gui/EntryModel.cpp
gui/GroupModel.cpp gui/GroupModel.cpp
) )

View File

@ -26,6 +26,11 @@ Entry::Entry()
m_db = 0; m_db = 0;
} }
Entry::~Entry()
{
// TODO notify group
}
Uuid Entry::uuid() const Uuid Entry::uuid() const
{ {
return m_uuid; return m_uuid;
@ -182,6 +187,11 @@ void Entry::addAutoTypeAssociation(const AutoTypeAssociation& assoc)
void Entry::addAttribute(const QString& key, const QString& value) void Entry::addAttribute(const QString& key, const QString& value)
{ {
m_attributes.insert(key, value); m_attributes.insert(key, value);
// TODO add all visible oclumns
if (key == "Title") {
Q_EMIT dataChanged(this);
}
} }
void Entry::addAttachment(const QString& key, const QByteArray& value) void Entry::addAttachment(const QString& key, const QByteArray& value)
@ -191,27 +201,27 @@ void Entry::addAttachment(const QString& key, const QByteArray& value)
void Entry::setTitle(const QString& title) void Entry::setTitle(const QString& title)
{ {
m_attributes.insert("Title", title); addAttribute("Title", title);
} }
void Entry::setUrl(const QString& url) void Entry::setUrl(const QString& url)
{ {
m_attributes.insert("URL", url); addAttribute("URL", url);
} }
void Entry::setUsername(const QString& username) void Entry::setUsername(const QString& username)
{ {
m_attributes.insert("UserName", username); addAttribute("UserName", username);
} }
void Entry::setPassword(const QString& password) void Entry::setPassword(const QString& password)
{ {
m_attributes.insert("Password", password); addAttribute("Password", password);
} }
void Entry::setNotes(const QString& notes) void Entry::setNotes(const QString& notes)
{ {
m_attributes.insert("Notes", notes); addAttribute("Notes", notes);
} }
void Entry::setGroup(Group* group) void Entry::setGroup(Group* group)

View File

@ -41,6 +41,7 @@ class Entry : public QObject
public: public:
Entry(); Entry();
~Entry();
Uuid uuid() const; Uuid uuid() const;
QImage icon() const; QImage icon() const;
QColor foregroundColor() const; QColor foregroundColor() const;
@ -80,6 +81,9 @@ public:
void setGroup(Group* group); void setGroup(Group* group);
Q_SIGNALS:
void dataChanged(const Entry* entry);
private: private:
Uuid m_uuid; Uuid m_uuid;
int m_iconNumber; int m_iconNumber;

View File

@ -28,6 +28,11 @@ Group::Group()
m_db = 0; m_db = 0;
} }
Group::~Group()
{
// TODO notify parent
}
Uuid Group::uuid() const Uuid Group::uuid() const
{ {
return m_uuid; return m_uuid;
@ -229,14 +234,24 @@ QList<const Entry*> Group::entries() const
void Group::addEntry(Entry *entry) void Group::addEntry(Entry *entry)
{ {
Q_ASSERT(entry != 0); Q_ASSERT(entry);
Q_EMIT entryAboutToAdd(entry);
m_entries << entry; m_entries << entry;
connect(entry, SIGNAL(dataChanged(const Entry*)), SIGNAL(entryDataChanged(const Entry*)));
Q_EMIT entryAdded();
} }
void Group::removeEntry(Entry* entry) void Group::removeEntry(Entry* entry)
{ {
Q_EMIT entryAboutToRemove(entry);
entry->disconnect(this);
m_entries.removeAll(entry); m_entries.removeAll(entry);
Q_EMIT entryRemoved();
} }
void Group::recSetDatabase(Database* db) void Group::recSetDatabase(Database* db)

View File

@ -32,6 +32,7 @@ class Group : public QObject
public: public:
Group(); Group();
~Group();
Uuid uuid() const; Uuid uuid() const;
QString name() const; QString name() const;
QString notes() const; QString notes() const;
@ -65,10 +66,18 @@ public:
Q_SIGNALS: Q_SIGNALS:
void dataChanged(const Group* group); void dataChanged(const Group* group);
void aboutToRemove(const Group* group);
void removed();
void aboutToAdd(const Group* group, int index); void aboutToAdd(const Group* group, int index);
void added(); void added();
void aboutToRemove(const Group* group);
void removed();
void entryAboutToAdd(const Entry* entry);
void entryAdded();
void entryAboutToRemove(const Entry* entry);
void entryRemoved();
void entryDataChanged(const Entry* entry);
private: private:
void recSetDatabase(Database* db); void recSetDatabase(Database* db);

120
src/gui/EntryModel.cpp Normal file
View File

@ -0,0 +1,120 @@
/*
* 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 "EntryModel.h"
#include "core/Entry.h"
#include "core/Group.h"
EntryModel::EntryModel(QObject* parent)
: QAbstractTableModel(parent)
, m_group(0)
{
}
void EntryModel::setGroup(const Group* group)
{
beginResetModel();
if (m_group) {
disconnect(m_group, 0, this, 0);
}
m_group = group;
connect(group, SIGNAL(entryAboutToAdd(const Entry*)), SLOT(entryAboutToAdd(const Entry*)));
connect(group, SIGNAL(entryAdded()), SLOT(entryAdded()));
connect(group, SIGNAL(entryAboutToRemove(const Entry*)), SLOT(entryAboutToRemove(const Entry*)));
connect(group, SIGNAL(entryRemoved()), SLOT(entryRemoved()));
connect(group, SIGNAL(entryDataChanged(const Entry*)), SLOT(entryDataChanged(const Entry*)));
endResetModel();
}
int EntryModel::rowCount(const QModelIndex& parent) const
{
if (!m_group || parent.isValid()) {
return 0;
}
else {
return m_group->entries().size();
}
}
int EntryModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return 1;
}
QVariant EntryModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
const Entry* entry = m_group->entries().at(index.row());
// TODO implement other columns
if (role == Qt::DisplayRole) {
return entry->title();
}
else if (role == Qt::DecorationRole) {
return entry->icon();
}
else {
return QVariant();
}
}
QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int role) const
{
Q_UNUSED(section);
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
return tr("Title");
}
return QVariant();
}
void EntryModel::entryAboutToAdd(const Entry* entry)
{
Q_UNUSED(entry);
beginInsertRows(QModelIndex(), m_group->entries().size(), m_group->entries().size());
}
void EntryModel::entryAdded()
{
endInsertRows();
}
void EntryModel::entryAboutToRemove(const Entry* entry)
{
beginRemoveRows(QModelIndex(), m_group->entries().indexOf(entry), m_group->entries().indexOf(entry));
}
void EntryModel::entryRemoved()
{
endRemoveRows();
}
void EntryModel::entryDataChanged(const Entry* entry)
{
int row = m_group->entries().indexOf(entry);
qDebug("%d", index(row, 0).row());
Q_EMIT dataChanged(index(row, 0), index(row, columnCount()-1));
}

51
src/gui/EntryModel.h Normal file
View File

@ -0,0 +1,51 @@
/*
* 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/>.
*/
#ifndef KEEPASSX_ENTRYMODEL_H
#define KEEPASSX_ENTRYMODEL_H
#include <QtCore/QAbstractTableModel>
class Entry;
class Group;
class EntryModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit EntryModel(QObject* parent = 0);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
public Q_SLOTS:
void setGroup(const Group* group);
private Q_SLOTS:
void entryAboutToAdd(const Entry* entry);
void entryAdded();
void entryAboutToRemove(const Entry* entry);
void entryRemoved();
void entryDataChanged(const Entry* entry);
private:
const Group* m_group;
};
#endif // KEEPASSX_ENTRYMODEL_H

View File

@ -35,7 +35,7 @@ public:
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex& index) const; QModelIndex parent(const QModelIndex& index) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
private: private:
QModelIndex createIndex(int row, int column, const Group* group) const; QModelIndex createIndex(int row, int column, const Group* group) const;

View File

@ -71,3 +71,6 @@ target_link_libraries( testparser keepassx_core ${QT_QTCORE_LIBRARY} ${QT_QTGUI_
add_unit_test( testgroupmodel TestGroupModel.cpp modeltest.cpp ) add_unit_test( testgroupmodel TestGroupModel.cpp modeltest.cpp )
target_link_libraries( testgroupmodel keepassx_core ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTTEST_LIBRARY} ) target_link_libraries( testgroupmodel keepassx_core ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTTEST_LIBRARY} )
add_unit_test( testentrymodel TestEntryModel.cpp modeltest.cpp )
target_link_libraries( testentrymodel keepassx_core ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTTEST_LIBRARY} )

99
tests/TestEntryModel.cpp Normal file
View File

@ -0,0 +1,99 @@
/*
* 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 <QtTest/QSignalSpy>
#include <QtTest/QTest>
#include "modeltest.h"
#include "core/Entry.h"
#include "core/Group.h"
#include "gui/EntryModel.h"
class TestEntryModel : public QObject
{
Q_OBJECT
private Q_SLOTS:
void test();
};
void TestEntryModel::test()
{
qRegisterMetaType<QModelIndex>("QModelIndex");
Group* group1 = new Group();
Group* group2 = new Group();
Entry* entry1 = new Entry();
entry1->setGroup(group1);
entry1->setTitle("testTitle1");
Entry* entry2 = new Entry();
entry2->setGroup(group1);
entry2->setTitle("testTitle2");
EntryModel* model = new EntryModel(this);
new ModelTest(model, this);
model->setGroup(group1);
QCOMPARE(model->rowCount(), 2);
QSignalSpy spyDataChanged(model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)));
entry1->setTitle("changed");
QCOMPARE(spyDataChanged.count(), 1);
QModelIndex index1 = model->index(0, 0);
QModelIndex index2 = model->index(1, 0);
QCOMPARE(model->data(index1).toString(), entry1->title());
QCOMPARE(model->data(index2).toString(), entry2->title());
QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex&,int,int)));
QSignalSpy spyAdded(model, SIGNAL(rowsInserted(const QModelIndex&,int,int)));
QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&,int,int)));
QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(const QModelIndex&,int,int)));
Entry* entry3 = new Entry();
entry3->setGroup(group1);
QCOMPARE(spyAboutToAdd.count(), 1);
QCOMPARE(spyAdded.count(), 1);
QCOMPARE(spyAboutToRemove.count(), 0);
QCOMPARE(spyRemoved.count(), 0);
entry2->setGroup(group2);
QCOMPARE(spyAboutToAdd.count(), 1);
QCOMPARE(spyAdded.count(), 1);
QCOMPARE(spyAboutToRemove.count(), 1);
QCOMPARE(spyRemoved.count(), 1);
QSignalSpy spyReset(model, SIGNAL(modelReset()));
model->setGroup(group2);
QCOMPARE(spyReset.count(), 1);
delete group1;
delete group2;
}
QTEST_MAIN(TestEntryModel);
Q_DECLARE_METATYPE(QModelIndex);
#include "TestEntryModel.moc"

View File

@ -27,6 +27,7 @@ class TestGroup : public QObject
private Q_SLOTS: private Q_SLOTS:
void testParenting(); void testParenting();
void testSignals(); void testSignals();
void testEntries();
}; };
void TestGroup::testParenting() void TestGroup::testParenting()
@ -100,6 +101,25 @@ void TestGroup::testSignals()
QCOMPARE(spyAdded.count(), 1); QCOMPARE(spyAdded.count(), 1);
QCOMPARE(spyAboutToRemove.count(), 1); QCOMPARE(spyAboutToRemove.count(), 1);
QCOMPARE(spyRemoved.count(), 1); QCOMPARE(spyRemoved.count(), 1);
delete db;
}
void TestGroup::testEntries()
{
Group* group = new Group();
Entry* entry1 = new Entry();
entry1->setGroup(group);
Entry* entry2 = new Entry();
entry2->setGroup(group);
QCOMPARE(group->entries().size(), 2);
QVERIFY(group->entries().at(0) == entry1);
QVERIFY(group->entries().at(1) == entry2);
delete group;
} }
QTEST_MAIN(TestGroup); QTEST_MAIN(TestGroup);