diff options
Diffstat (limited to 'src/gui/entry/EntryModel.cpp')
-rw-r--r-- | src/gui/entry/EntryModel.cpp | 215 |
1 files changed, 190 insertions, 25 deletions
diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index 2f79f02d9..6f7ebf6af 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -18,8 +18,11 @@ #include "EntryModel.h" #include <QFont> +#include <QFontMetrics> #include <QMimeData> #include <QPalette> +#include <QDateTime> +#include <QPainter> #include "core/DatabaseIcons.h" #include "core/Entry.h" @@ -27,9 +30,17 @@ #include "core/Group.h" #include "core/Metadata.h" +// String being displayed when hiding content +const QString EntryModel::HiddenContentDisplay(QString("\u25cf").repeated(6)); + +// Format used to display dates +const Qt::DateFormat EntryModel::DateFormat = Qt::DefaultLocaleShortDate; + EntryModel::EntryModel(QObject* parent) : QAbstractTableModel(parent) , m_group(nullptr) + , m_hideUsernames(false) + , m_hidePasswords(true) { } @@ -64,7 +75,7 @@ void EntryModel::setGroup(Group* group) makeConnections(group); endResetModel(); - emit switchedToGroupMode(); + emit switchedToListMode(); } void EntryModel::setEntryList(const QList<Entry*>& entries) @@ -101,24 +112,26 @@ void EntryModel::setEntryList(const QList<Entry*>& entries) } endResetModel(); - emit switchedToEntryListMode(); + emit switchedToSearchMode(); } int EntryModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) { return 0; - } - else { + } else { return m_entries.size(); } } int EntryModel::columnCount(const QModelIndex& parent) const { - Q_UNUSED(parent); + // Advised by Qt documentation + if (parent.isValid()) { + return 0; + } - return 4; + return 12; } QVariant EntryModel::data(const QModelIndex& index, int role) const @@ -141,25 +154,92 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const case Title: result = entry->resolveMultiplePlaceholders(entry->title()); if (attr->isReference(EntryAttributes::TitleKey)) { - result.prepend(tr("Ref: ","Reference abbreviation")); + result.prepend(tr("Ref: ", "Reference abbreviation")); } return result; case Username: - result = entry->resolveMultiplePlaceholders(entry->username()); + if (m_hideUsernames) { + result = EntryModel::HiddenContentDisplay; + } else { + result = entry->resolveMultiplePlaceholders(entry->username()); + } if (attr->isReference(EntryAttributes::UserNameKey)) { - result.prepend(tr("Ref: ","Reference abbreviation")); + result.prepend(tr("Ref: ", "Reference abbreviation")); + } + return result; + case Password: + if (m_hidePasswords) { + result = EntryModel::HiddenContentDisplay; + } else { + result = entry->resolveMultiplePlaceholders(entry->password()); + } + if (attr->isReference(EntryAttributes::PasswordKey)) { + result.prepend(tr("Ref: ", "Reference abbreviation")); } return result; case Url: - result = entry->maskPasswordPlaceholders(entry->url()); - result = entry->resolveMultiplePlaceholders(result); + result = entry->resolveMultiplePlaceholders(entry->displayUrl()); if (attr->isReference(EntryAttributes::URLKey)) { - result.prepend(tr("Ref: ","Reference abbreviation")); + result.prepend(tr("Ref: ", "Reference abbreviation")); + } + return result; + case Notes: + // Display only first line of notes in simplified format + result = entry->resolveMultiplePlaceholders(entry->notes().section("\n", 0, 0).simplified()); + if (attr->isReference(EntryAttributes::NotesKey)) { + result.prepend(tr("Ref: ", "Reference abbreviation")); + } + return result; + case Expires: + // Display either date of expiry or 'Never' + result = entry->timeInfo().expires() ? entry->timeInfo().expiryTime().toLocalTime().toString(EntryModel::DateFormat) : tr("Never"); + return result; + case Created: + result = entry->timeInfo().creationTime().toLocalTime().toString(EntryModel::DateFormat); + return result; + case Modified: + result = entry->timeInfo().lastModificationTime().toLocalTime().toString(EntryModel::DateFormat); + return result; + case Accessed: + result = entry->timeInfo().lastAccessTime().toLocalTime().toString(EntryModel::DateFormat); + return result; + case Attachments: + // Display comma-separated list of attachments + QList<QString> attachments = entry->attachments()->keys(); + for (int i = 0; i < attachments.size(); ++i) { + if (result.isEmpty()) { + result.append(attachments.at(i)); + continue; + } + result.append(QString(", ") + attachments.at(i)); } return result; } - } - else if (role == Qt::DecorationRole) { + } else if (role == Qt::UserRole) { // Qt::UserRole is used as sort role, see EntryView::EntryView() + switch (index.column()) { + case Username: + return entry->resolveMultiplePlaceholders(entry->username()); + case Password: + return entry->resolveMultiplePlaceholders(entry->password()); + case Expires: + // There seems to be no better way of expressing 'infinity' + return entry->timeInfo().expires() ? entry->timeInfo().expiryTime() : QDateTime(QDate(9999, 1, 1)); + case Created: + return entry->timeInfo().creationTime(); + case Modified: + return entry->timeInfo().lastModificationTime(); + case Accessed: + return entry->timeInfo().lastAccessTime(); + case Paperclip: + // Display entries with attachments above those without when + // sorting ascendingly (and vice versa when sorting descendingly) + return entry->attachments()->isEmpty() ? 1 : 0; + default: + // For all other columns, simply use data provided by Qt::Display- + // Role for sorting + return data(index, Qt::DisplayRole); + } + } else if (role == Qt::DecorationRole) { switch (index.column()) { case ParentGroup: if (entry->group()) { @@ -170,30 +250,44 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const if (entry->isExpired()) { return databaseIcons()->iconPixmap(DatabaseIcons::ExpiredIconIndex); } - else { - return entry->iconScaledPixmap(); + return entry->iconScaledPixmap(); + case Paperclip: + if (!entry->attachments()->isEmpty()) { + return m_paperClipPixmap; } + break; } - } - else if (role == Qt::FontRole) { + } else if (role == Qt::FontRole) { QFont font; if (entry->isExpired()) { font.setStrikeOut(true); } return font; - } - else if (role == Qt::TextColorRole) { + } else if (role == Qt::ForegroundRole) { if (entry->hasReferences()) { QPalette p; return QVariant(p.color(QPalette::Active, QPalette::Mid)); + } else if (entry->foregroundColor().isValid()) { + return QVariant(entry->foregroundColor()); + } + } else if (role == Qt::BackgroundRole) { + if (entry->backgroundColor().isValid()) { + return QVariant(entry->backgroundColor()); + } + } else if (role == Qt::TextAlignmentRole) { + if (index.column() == Paperclip) { + return Qt::AlignCenter; } } return QVariant(); } + QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + Q_UNUSED(orientation); + + if (role == Qt::DisplayRole) { switch (section) { case ParentGroup: return tr("Group"); @@ -201,8 +295,26 @@ QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int ro return tr("Title"); case Username: return tr("Username"); + case Password: + return tr("Password"); case Url: return tr("URL"); + case Notes: + return tr("Notes"); + case Expires: + return tr("Expires"); + case Created: + return tr("Created"); + case Modified: + return tr("Modified"); + case Accessed: + return tr("Accessed"); + case Attachments: + return tr("Attachments"); + } + } else if (role == Qt::DecorationRole) { + if (section == Paperclip) { + return m_paperClipPixmap; } } @@ -223,8 +335,7 @@ Qt::ItemFlags EntryModel::flags(const QModelIndex& modelIndex) const { if (!modelIndex.isValid()) { return Qt::NoItemFlags; - } - else { + } else { return QAbstractItemModel::flags(modelIndex) | Qt::ItemIsDragEnabled; } } @@ -265,8 +376,7 @@ QMimeData* EntryModel::mimeData(const QModelIndexList& indexes) const if (seenEntries.isEmpty()) { delete data; return nullptr; - } - else { + } else { data->setData(mimeTypes().at(0), encoded); return data; } @@ -338,3 +448,58 @@ void EntryModel::makeConnections(const Group* group) connect(group, SIGNAL(entryRemoved(Entry*)), SLOT(entryRemoved())); connect(group, SIGNAL(entryDataChanged(Entry*)), SLOT(entryDataChanged(Entry*))); } + +/** + * Get current state of 'Hide Usernames' setting + */ +bool EntryModel::isUsernamesHidden() const +{ + return m_hideUsernames; +} + +/** + * Set state of 'Hide Usernames' setting and signal change + */ +void EntryModel::setUsernamesHidden(const bool hide) +{ + m_hideUsernames = hide; + emit usernamesHiddenChanged(); +} + +/** + * Get current state of 'Hide Passwords' setting + */ +bool EntryModel::isPasswordsHidden() const +{ + return m_hidePasswords; +} + +/** + * Set state of 'Hide Passwords' setting and signal change + */ +void EntryModel::setPasswordsHidden(const bool hide) +{ + m_hidePasswords = hide; + emit passwordsHiddenChanged(); +} + +/** + * Toggle state of 'Hide Usernames' setting + */ +void EntryModel::toggleUsernamesHidden(const bool hide) +{ + setUsernamesHidden(hide); +} + +/** + * Toggle state of 'Hide Passwords' setting + */ +void EntryModel::togglePasswordsHidden(const bool hide) +{ + setPasswordsHidden(hide); +} + +void EntryModel::setPaperClipPixmap(const QPixmap& paperclip) +{ + m_paperClipPixmap = paperclip; +} |