Display history items.

Refs #23
This commit is contained in:
Florian Geyer 2012-05-15 20:12:05 +02:00
parent d0557677c7
commit 810a6e4b39
10 changed files with 341 additions and 25 deletions

View File

@ -68,6 +68,7 @@ set(keepassx_SOURCES
gui/entry/EditEntryWidget.cpp
gui/entry/EntryAttachmentsModel.cpp
gui/entry/EntryAttributesModel.cpp
gui/entry/EntryHistoryModel.cpp
gui/entry/EntryModel.cpp
gui/entry/EntryView.cpp
gui/group/EditGroupWidget.cpp
@ -105,6 +106,7 @@ set(keepassx_MOC
gui/entry/EditEntryWidget.h
gui/entry/EntryAttachmentsModel.h
gui/entry/EntryAttributesModel.h
gui/entry/EntryHistoryModel.h
gui/entry/EntryModel.h
gui/entry/EntryView.h
gui/group/EditGroupWidget.h
@ -126,6 +128,7 @@ set(keepassx_FORMS
gui/EditWidgetIcons.ui
gui/MainWindow.ui
gui/entry/EditEntryWidgetAdvanced.ui
gui/entry/EditEntryWidgetHistory.ui
gui/entry/EditEntryWidgetMain.ui
gui/entry/EditEntryWidgetNotes.ui
gui/group/EditGroupWidgetMain.ui

View File

@ -111,7 +111,7 @@ bool EntryAttachments::operator!=(const EntryAttachments& other) const
return m_attachments != other.m_attachments;
}
EntryAttachments& EntryAttachments::operator=(EntryAttachments& other)
EntryAttachments& EntryAttachments::operator=(const EntryAttachments& other)
{
if (*this != other) {
Q_EMIT aboutToBeReset();

View File

@ -35,7 +35,7 @@ public:
int attachmentsSize(QList<QByteArray>* foundAttachements);
bool operator==(const EntryAttachments& other) const;
bool operator!=(const EntryAttachments& other) const;
EntryAttachments& operator=(EntryAttachments& other);
EntryAttachments& operator=(const EntryAttachments& other);
Q_SIGNALS:
void modified();

View File

@ -85,6 +85,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
m_editEntryWidget = new EditEntryWidget();
m_editEntryWidget->setObjectName("editEntryWidget");
m_historyEditEntryWidget = new EditEntryWidget();
m_editGroupWidget = new EditGroupWidget();
m_editGroupWidget->setObjectName("editGroupWidget");
m_changeMasterKeyWidget = new ChangeMasterKeyWidget();
@ -99,11 +100,14 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
addWidget(m_editGroupWidget);
addWidget(m_changeMasterKeyWidget);
addWidget(m_databaseSettingsWidget);
addWidget(m_historyEditEntryWidget);
connect(m_groupView, SIGNAL(groupChanged(Group*)), m_entryView, SLOT(setGroup(Group*)));
connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(clearLastGroup(Group*)));
connect(m_entryView, SIGNAL(entryActivated(Entry*)), SLOT(switchToEntryEdit(Entry*)));
connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool)));
connect(m_editEntryWidget, SIGNAL(historyEntryActivated(Entry*)), SLOT(switchToHistoryView(Entry*)));
connect(m_historyEditEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchBackToEntryEdit()));
connect(m_editGroupWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool)));
connect(m_changeMasterKeyWidget, SIGNAL(editFinished(bool)), SLOT(updateMasterKey(bool)));
connect(m_databaseSettingsWidget, SIGNAL(editFinished(bool)), SLOT(updateSettings(bool)));
@ -125,6 +129,7 @@ DatabaseWidget::Mode DatabaseWidget::currentMode()
case 2: // group edit
case 3: // change master key
case 4: // database settings
case 5: // entry history
return DatabaseWidget::EditMode;
default:
Q_ASSERT(false);
@ -270,6 +275,17 @@ void DatabaseWidget::switchToView(bool accepted)
setCurrentIndex(0);
}
void DatabaseWidget::switchToHistoryView(Entry* entry)
{
m_historyEditEntryWidget->loadEntry(entry, false, true, "", m_db);
setCurrentIndex(5);
}
void DatabaseWidget::switchBackToEntryEdit()
{
setCurrentIndex(1);
}
void DatabaseWidget::switchToEntryEdit(Entry* entry)
{
switchToEntryEdit(entry, false);
@ -284,7 +300,7 @@ void DatabaseWidget::switchToEntryEdit(Entry* entry, bool create)
}
Q_ASSERT(group);
m_editEntryWidget->loadEntry(entry, create, group->name(), m_db);
m_editEntryWidget->loadEntry(entry, create, false, group->name(), m_db);
setCurrentIndex(1);
}

View File

@ -58,7 +58,6 @@ public:
void setCurrentIndex(int index);
DatabaseWidget::Mode currentMode();
Q_SIGNALS:
void closeRequest();
void currentModeChanged(DatabaseWidget::Mode mode);
@ -73,7 +72,9 @@ public Q_SLOTS:
void search();
private Q_SLOTS:
void switchBackToEntryEdit();
void switchToView(bool accepted);
void switchToHistoryView(Entry *entry);
void switchToEntryEdit(Entry* entry);
void switchToEntryEdit(Entry* entry, bool create);
void switchToGroupEdit(Group* entry, bool create);
@ -89,6 +90,7 @@ private:
Database* const m_db;
QWidget* m_mainWidget;
EditEntryWidget* m_editEntryWidget;
EditEntryWidget* m_historyEditEntryWidget;
EditGroupWidget* m_editGroupWidget;
ChangeMasterKeyWidget* m_changeMasterKeyWidget;
DatabaseSettingsWidget* m_databaseSettingsWidget;

View File

@ -17,6 +17,7 @@
#include "EditEntryWidget.h"
#include "ui_EditEntryWidgetAdvanced.h"
#include "ui_EditEntryWidgetHistory.h"
#include "ui_EditEntryWidgetMain.h"
#include "ui_EditEntryWidgetNotes.h"
#include "ui_EditWidget.h"
@ -33,6 +34,7 @@
#include "gui/FileDialog.h"
#include "gui/entry/EntryAttachmentsModel.h"
#include "gui/entry/EntryAttributesModel.h"
#include "gui/entry/EntryHistoryModel.h"
EditEntryWidget::EditEntryWidget(QWidget* parent)
: EditWidget(parent)
@ -40,10 +42,12 @@ EditEntryWidget::EditEntryWidget(QWidget* parent)
, m_mainUi(new Ui::EditEntryWidgetMain())
, m_notesUi(new Ui::EditEntryWidgetNotes())
, m_advancedUi(new Ui::EditEntryWidgetAdvanced())
, m_historyUi(new Ui::EditEntryWidgetHistory())
, m_mainWidget(new QWidget())
, m_notesWidget(new QWidget())
, m_advancedWidget(new QWidget())
, m_iconsWidget(new EditWidgetIcons())
, m_historyWidget(new QWidget())
{
QFont headerLabelFont = headlineLabel()->font();
headerLabelFont.setBold(true);
@ -61,6 +65,9 @@ EditEntryWidget::EditEntryWidget(QWidget* parent)
add(tr("Icon"), m_iconsWidget);
m_historyUi->setupUi(m_historyWidget);
add(tr("History"), m_historyWidget);
m_entryAttachments = new EntryAttachments(this);
m_attachmentsModel = new EntryAttachmentsModel(m_advancedWidget);
m_attachmentsModel->setEntryAttachments(m_entryAttachments);
@ -85,6 +92,13 @@ EditEntryWidget::EditEntryWidget(QWidget* parent)
connect(m_mainUi->passwordEdit, SIGNAL(textEdited(QString)), SLOT(setPasswordCheckColors()));
connect(m_mainUi->passwordRepeatEdit, SIGNAL(textEdited(QString)), SLOT(setPasswordCheckColors()));
m_historyModel = new EntryHistoryModel(this);
m_historyUi->historyView->setModel(m_historyModel);
m_historyUi->historyView->setRootIsDecorated(false);
connect(m_historyUi->historyView, SIGNAL(activated(const QModelIndex&)),
SLOT(emitHistoryEntryActivated(const QModelIndex&)));
connect(this, SIGNAL(accepted()), SLOT(saveEntry()));
connect(this, SIGNAL(rejected()), SLOT(cancel()));
}
@ -96,20 +110,69 @@ EditEntryWidget::~EditEntryWidget()
const QColor EditEntryWidget::CorrectSoFarColor = QColor(255, 205, 15);
const QColor EditEntryWidget::ErrorColor = QColor(255, 125, 125);
void EditEntryWidget::loadEntry(Entry* entry, bool create, const QString& groupName,
void EditEntryWidget::emitHistoryEntryActivated(const QModelIndex& index)
{
Q_ASSERT(!m_history);
Entry* entry = m_historyModel->entryFromIndex(index);
Q_EMIT historyEntryActivated(entry);
}
void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const QString& groupName,
Database* database)
{
m_entry = entry;
m_database = database;
m_create = create;
m_history = history;
if (create) {
headlineLabel()->setText(groupName+" > "+tr("Add entry"));
if (history) {
headlineLabel()->setText("Entry history");
}
else {
headlineLabel()->setText(groupName+" > "+tr("Edit entry"));
if (create) {
headlineLabel()->setText(groupName+" > "+tr("Add entry"));
}
else {
headlineLabel()->setText(groupName+" > "+tr("Edit entry"));
}
}
m_mainUi->titleEdit->setReadOnly(history);
m_mainUi->usernameEdit->setReadOnly(history);
m_mainUi->urlEdit->setReadOnly(history);
m_mainUi->passwordEdit->setReadOnly(history);
m_mainUi->passwordRepeatEdit->setReadOnly(history);
m_mainUi->expireCheck->setEnabled(!history);
m_mainUi->expireDatePicker->setReadOnly(history);
m_notesUi->notesEdit->setReadOnly(history);
m_advancedUi->addAttachmentButton->setEnabled(!history);
m_advancedUi->removeAttachmentButton->setEnabled(!history);
m_advancedUi->addAttributeButton->setEnabled(!history);
m_advancedUi->editAttributeButton->setEnabled(false);
m_advancedUi->removeAttributeButton->setEnabled(false);
m_advancedUi->attributesEdit->setReadOnly(history);
QAbstractItemView::EditTriggers editTriggers;
if (history) {
editTriggers = QAbstractItemView::NoEditTriggers;
}
else {
editTriggers = QAbstractItemView::DoubleClicked;
}
m_advancedUi->attributesView->setEditTriggers(editTriggers);
m_iconsWidget->setEnabled(!history);
m_historyWidget->setEnabled(!history);
setForms(entry);
setCurrentRow(0);
m_mainUi->titleEdit->setFocus();
}
void EditEntryWidget::setForms(const Entry* entry)
{
m_mainUi->titleEdit->setText(entry->title());
m_mainUi->usernameEdit->setText(entry->username());
m_mainUi->urlEdit->setText(entry->url());
@ -122,10 +185,8 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, const QString& groupN
m_notesUi->notesEdit->setPlainText(entry->notes());
m_entryAttributes->copyCustomKeysFrom(entry->attributes());
*m_entryAttachments = *entry->attachments();
setCurrentRow(0);
m_entryAttributes->copyCustomKeysFrom(entry->attributes());
if (m_attributesModel->rowCount() != 0) {
m_advancedUi->attributesView->setCurrentIndex(m_attributesModel->index(0, 0));
@ -138,13 +199,22 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, const QString& groupN
IconStruct iconStruct;
iconStruct.uuid = entry->iconUuid();
iconStruct.number = entry->iconNumber();
m_iconsWidget->load(entry->uuid(), database, iconStruct);
m_mainUi->titleEdit->setFocus();
m_iconsWidget->load(entry->uuid(), m_database, iconStruct);
m_historyModel->setEntries(entry->historyItems());
}
void EditEntryWidget::saveEntry()
{
if (m_history) {
m_entry = 0;
m_database = 0;
m_entryAttributes->clear();
m_entryAttachments->clear();
m_historyModel->clear();
Q_EMIT editFinished(false);
return;
}
if (!passwordsEqual()) {
QMessageBox::warning(this, tr("Error"), tr("Different passwords supplied."));
return;
@ -194,12 +264,23 @@ void EditEntryWidget::saveEntry()
m_database = 0;
m_entryAttributes->clear();
m_entryAttachments->clear();
m_historyModel->clear();
Q_EMIT editFinished(true);
}
void EditEntryWidget::cancel()
{
if (m_history) {
m_entry = 0;
m_database = 0;
m_entryAttributes->clear();
m_entryAttachments->clear();
m_historyModel->clear();
Q_EMIT editFinished(false);
return;
}
if (!m_entry->iconUuid().isNull() &&
!m_database->metadata()->containsCustomIcon(m_entry->iconUuid())) {
m_entry->setIcon(Entry::DefaultIconNumber);
@ -209,6 +290,7 @@ void EditEntryWidget::cancel()
m_database = 0;
m_entryAttributes->clear();
m_entryAttachments->clear();
m_historyModel->clear();
Q_EMIT editFinished(false);
}
@ -245,6 +327,8 @@ void EditEntryWidget::setPasswordCheckColors()
void EditEntryWidget::insertAttribute()
{
Q_ASSERT(!m_history);
QString name = tr("New attribute");
int i = 1;
@ -262,6 +346,8 @@ void EditEntryWidget::insertAttribute()
void EditEntryWidget::editCurrentAttribute()
{
Q_ASSERT(!m_history);
QModelIndex index = m_advancedUi->attributesView->currentIndex();
if (index.isValid()) {
@ -271,6 +357,8 @@ void EditEntryWidget::editCurrentAttribute()
void EditEntryWidget::removeCurrentAttribute()
{
Q_ASSERT(!m_history);
QModelIndex index = m_advancedUi->attributesView->currentIndex();
if (index.isValid()) {
@ -282,13 +370,7 @@ void EditEntryWidget::updateCurrentAttribute()
{
QModelIndex newIndex = m_advancedUi->attributesView->currentIndex();
if (m_currentAttribute != newIndex) {
if (m_currentAttribute.isValid()) {
QString key = m_attributesModel->keyByIndex(m_currentAttribute);
m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(),
m_entryAttributes->isProtected(key));
}
if (m_history) {
if (newIndex.isValid()) {
QString key = m_attributesModel->keyByIndex(newIndex);
m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key));
@ -298,15 +380,36 @@ void EditEntryWidget::updateCurrentAttribute()
m_advancedUi->attributesEdit->setPlainText("");
m_advancedUi->attributesEdit->setEnabled(false);
}
}
else {
if (m_currentAttribute != newIndex) {
if (m_currentAttribute.isValid()) {
QString key = m_attributesModel->keyByIndex(m_currentAttribute);
m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(),
m_entryAttributes->isProtected(key));
}
m_advancedUi->editAttributeButton->setEnabled(newIndex.isValid());
m_advancedUi->removeAttributeButton->setEnabled(newIndex.isValid());
m_currentAttribute = newIndex;
if (newIndex.isValid()) {
QString key = m_attributesModel->keyByIndex(newIndex);
m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key));
m_advancedUi->attributesEdit->setEnabled(true);
}
else {
m_advancedUi->attributesEdit->setPlainText("");
m_advancedUi->attributesEdit->setEnabled(false);
}
m_advancedUi->editAttributeButton->setEnabled(newIndex.isValid());
m_advancedUi->removeAttributeButton->setEnabled(newIndex.isValid());
m_currentAttribute = newIndex;
}
}
}
void EditEntryWidget::insertAttachment()
{
Q_ASSERT(!m_history);
// TODO: save last used dir
QString filename = fileDialog()->getOpenFileName(this, tr("Select file"),
QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation));
@ -362,6 +465,8 @@ void EditEntryWidget::saveCurrentAttachment()
void EditEntryWidget::removeCurrentAttachment()
{
Q_ASSERT(!m_history);
QModelIndex index = m_advancedUi->attachmentsView->currentIndex();
if (!index.isValid()) {
return;

View File

@ -30,11 +30,13 @@ class EntryAttachments;
class EntryAttachmentsModel;
class EntryAttributes;
class EntryAttributesModel;
class EntryHistoryModel;
class QStackedLayout;
namespace Ui {
class EditEntryWidgetAdvanced;
class EditEntryWidgetMain;
class EditEntryWidgetHistory;
class EditEntryWidgetNotes;
class EditWidget;
}
@ -47,13 +49,15 @@ public:
explicit EditEntryWidget(QWidget* parent = 0);
~EditEntryWidget();
void loadEntry(Entry* entry, bool create, const QString& groupName, Database* database);
void loadEntry(Entry* entry, bool create, bool history, const QString& groupName,
Database *database);
static const QColor CorrectSoFarColor;
static const QColor ErrorColor;
Q_SIGNALS:
void editFinished(bool accepted);
void historyEntryActivated(Entry* entry);
private Q_SLOTS:
void saveEntry();
@ -67,23 +71,29 @@ private Q_SLOTS:
void insertAttachment();
void saveCurrentAttachment();
void removeCurrentAttachment();
void emitHistoryEntryActivated(const QModelIndex &index);
private:
bool passwordsEqual();
void setForms(const Entry* entry);
Entry* m_entry;
Database* m_database;
bool m_create;
bool m_history;
const QScopedPointer<Ui::EditEntryWidgetMain> m_mainUi;
const QScopedPointer<Ui::EditEntryWidgetNotes> m_notesUi;
const QScopedPointer<Ui::EditEntryWidgetAdvanced> m_advancedUi;
const QScopedPointer<Ui::EditEntryWidgetHistory> m_historyUi;
QWidget* const m_mainWidget;
QWidget* const m_notesWidget;
QWidget* const m_advancedWidget;
EditWidgetIcons* const m_iconsWidget;
QWidget* const m_historyWidget;
EntryAttachmentsModel* m_attachmentsModel;
EntryAttributesModel* m_attributesModel;
EntryHistoryModel* m_historyModel;
EntryAttachments* m_entryAttachments;
EntryAttributes* m_entryAttributes;
QPersistentModelIndex m_currentAttribute;

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditEntryWidgetHistory</class>
<widget class="QWidget" name="EditEntryWidgetHistory">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeView" name="historyView"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,111 @@
/*
* 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 "EntryHistoryModel.h"
#include "core/Entry.h"
EntryHistoryModel::EntryHistoryModel(QObject* parent)
: QAbstractTableModel(parent)
{
}
Entry* EntryHistoryModel::entryFromIndex(const QModelIndex& index) const
{
Q_ASSERT(index.isValid() && index.row() < m_historyEntries.size());
return m_historyEntries.at(index.row());
}
int EntryHistoryModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return 4;
}
int EntryHistoryModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid()) {
return m_historyEntries.count();
}
else {
return 0;
}
}
QVariant EntryHistoryModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
int row = index.row();
int column = index.column();
Entry* entry = m_historyEntries.at(row);
TimeInfo timeInfo = entry->timeInfo();
QDateTime lastModificationLocalTime = timeInfo.lastModificationTime().toLocalTime();
if (role == Qt::DisplayRole) {
switch (column) {
case 0:
return lastModificationLocalTime.toString(Qt::SystemLocaleShortDate);
case 1:
return entry->title();
case 2:
return entry->username();
case 3:
return entry->url();
}
}
return QVariant();
}
QVariant EntryHistoryModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case 0:
return tr("Last modified");
case 1:
return tr("Title");
case 2:
return tr("Username");
case 3:
return tr("URL");
}
}
return QVariant();
}
void EntryHistoryModel::setEntries(const QList<Entry*>& entries)
{
beginResetModel();
m_historyEntries = entries;
endResetModel();
}
void EntryHistoryModel::clear()
{
beginResetModel();
m_historyEntries.clear();
endResetModel();
}

View File

@ -0,0 +1,45 @@
/*
* 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_ENTRYHISTORYMODEL_H
#define KEEPASSX_ENTRYHISTORYMODEL_H
#include <QtCore/QAbstractTableModel>
class Entry;
class EntryHistoryModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit EntryHistoryModel(QObject* parent = 0);
Entry* entryFromIndex(const QModelIndex& index) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
int rowCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
void setEntries(const QList<Entry*>& entries);
void clear();
private:
QList<Entry*> m_historyEntries;
};
#endif // KEEPASSX_ENTRYHISTORYMODEL_H