diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f2ab34624..ed3ba87d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/core/EntryAttachments.cpp b/src/core/EntryAttachments.cpp index 0ce2d138c..ba0a6a1ae 100644 --- a/src/core/EntryAttachments.cpp +++ b/src/core/EntryAttachments.cpp @@ -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(); diff --git a/src/core/EntryAttachments.h b/src/core/EntryAttachments.h index 67e6a4231..19482e0ab 100644 --- a/src/core/EntryAttachments.h +++ b/src/core/EntryAttachments.h @@ -35,7 +35,7 @@ public: int attachmentsSize(QList* 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(); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 460034b44..2d457c63a 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -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); } diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 22d74e89f..bba4ff006 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -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; diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 5c31487c3..7b0f0e8e4 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -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; diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h index 84367b9de..5d88cdd0e 100644 --- a/src/gui/entry/EditEntryWidget.h +++ b/src/gui/entry/EditEntryWidget.h @@ -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 m_mainUi; const QScopedPointer m_notesUi; const QScopedPointer m_advancedUi; + const QScopedPointer 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; diff --git a/src/gui/entry/EditEntryWidgetHistory.ui b/src/gui/entry/EditEntryWidgetHistory.ui new file mode 100644 index 000000000..e92485b67 --- /dev/null +++ b/src/gui/entry/EditEntryWidgetHistory.ui @@ -0,0 +1,24 @@ + + + EditEntryWidgetHistory + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + + diff --git a/src/gui/entry/EntryHistoryModel.cpp b/src/gui/entry/EntryHistoryModel.cpp new file mode 100644 index 000000000..3e6cbba72 --- /dev/null +++ b/src/gui/entry/EntryHistoryModel.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 Felix Geyer + * + * 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 . + */ + +#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& entries) +{ + beginResetModel(); + + m_historyEntries = entries; + + endResetModel(); +} + +void EntryHistoryModel::clear() +{ + beginResetModel(); + + m_historyEntries.clear(); + + endResetModel(); +} diff --git a/src/gui/entry/EntryHistoryModel.h b/src/gui/entry/EntryHistoryModel.h new file mode 100644 index 000000000..bb836f2ec --- /dev/null +++ b/src/gui/entry/EntryHistoryModel.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012 Felix Geyer + * + * 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 . + */ + +#ifndef KEEPASSX_ENTRYHISTORYMODEL_H +#define KEEPASSX_ENTRYHISTORYMODEL_H + +#include + +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& entries); + void clear(); + +private: + QList m_historyEntries; +}; + +#endif // KEEPASSX_ENTRYHISTORYMODEL_H