Merge pull request #378 from keepassxreboot/feature/view-references

Highlight reference field in Database view
This commit is contained in:
Janek Bevendorff 2017-03-07 22:33:06 +01:00 committed by GitHub
commit a1e1a33308
5 changed files with 68 additions and 12 deletions

View File

@ -254,6 +254,17 @@ bool Entry::isExpired() const
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc(); return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
} }
bool Entry::hasReferences() const
{
const QList<QString> keyList = EntryAttributes::DefaultAttributes;
for (const QString& key : keyList) {
if (m_attributes->isReference(key)) {
return true;
}
}
return false;
}
EntryAttributes* Entry::attributes() EntryAttributes* Entry::attributes()
{ {
return m_attributes; return m_attributes;
@ -679,20 +690,20 @@ QString Entry::resolvePlaceholder(const QString& str) const
// using format from http://keepass.info/help/base/fieldrefs.html at the time of writing, // using format from http://keepass.info/help/base/fieldrefs.html at the time of writing,
// but supporting lookups of standard fields and references by UUID only // but supporting lookups of standard fields and references by UUID only
QRegExp tmpRegExp("\\{REF:([TUPAN])@I:([^}]+)\\}", Qt::CaseInsensitive, QRegExp::RegExp2); QRegExp* tmpRegExp = m_attributes->referenceRegExp();
if (tmpRegExp.indexIn(result) != -1) { if (tmpRegExp->indexIn(result) != -1) {
// cap(0) contains the whole reference // cap(0) contains the whole reference
// cap(1) contains which field is wanted // cap(1) contains which field is wanted
// cap(2) contains the uuid of the referenced entry // cap(2) contains the uuid of the referenced entry
Entry* tmpRefEntry = m_group->database()->resolveEntry(Uuid(QByteArray::fromHex(tmpRegExp.cap(2).toLatin1()))); Entry* tmpRefEntry = m_group->database()->resolveEntry(Uuid(QByteArray::fromHex(tmpRegExp->cap(2).toLatin1())));
if (tmpRefEntry) { if (tmpRefEntry) {
// entry found, get the relevant field // entry found, get the relevant field
QString tmpRefField = tmpRegExp.cap(1).toLower(); QString tmpRefField = tmpRegExp->cap(1).toLower();
if (tmpRefField == "t") result.replace(tmpRegExp.cap(0), tmpRefEntry->title(), Qt::CaseInsensitive); if (tmpRefField == "t") result.replace(tmpRegExp->cap(0), tmpRefEntry->title(), Qt::CaseInsensitive);
else if (tmpRefField == "u") result.replace(tmpRegExp.cap(0), tmpRefEntry->username(), Qt::CaseInsensitive); else if (tmpRefField == "u") result.replace(tmpRegExp->cap(0), tmpRefEntry->username(), Qt::CaseInsensitive);
else if (tmpRefField == "p") result.replace(tmpRegExp.cap(0), tmpRefEntry->password(), Qt::CaseInsensitive); else if (tmpRefField == "p") result.replace(tmpRegExp->cap(0), tmpRefEntry->password(), Qt::CaseInsensitive);
else if (tmpRefField == "a") result.replace(tmpRegExp.cap(0), tmpRefEntry->url(), Qt::CaseInsensitive); else if (tmpRefField == "a") result.replace(tmpRegExp->cap(0), tmpRefEntry->url(), Qt::CaseInsensitive);
else if (tmpRefField == "n") result.replace(tmpRegExp.cap(0), tmpRefEntry->notes(), Qt::CaseInsensitive); else if (tmpRefField == "n") result.replace(tmpRegExp->cap(0), tmpRefEntry->notes(), Qt::CaseInsensitive);
} }
} }

View File

@ -79,6 +79,7 @@ public:
QString password() const; QString password() const;
QString notes() const; QString notes() const;
bool isExpired() const; bool isExpired() const;
bool hasReferences() const;
EntryAttributes* attributes(); EntryAttributes* attributes();
const EntryAttributes* attributes() const; const EntryAttributes* attributes() const;
EntryAttachments* attachments(); EntryAttachments* attachments();

View File

@ -28,6 +28,7 @@ const QString EntryAttributes::RememberCmdExecAttr = "_EXEC_CMD";
EntryAttributes::EntryAttributes(QObject* parent) EntryAttributes::EntryAttributes(QObject* parent)
: QObject(parent) : QObject(parent)
, m_referenceRegExp("\\{REF:([TUPAN])@I:([^}]+)\\}", Qt::CaseInsensitive, QRegExp::RegExp2)
{ {
clear(); clear();
} }
@ -69,6 +70,25 @@ bool EntryAttributes::isProtected(const QString& key) const
return m_protectedAttributes.contains(key); return m_protectedAttributes.contains(key);
} }
bool EntryAttributes::isReference(const QString& key) const
{
if (!m_attributes.contains(key)) {
Q_ASSERT(false);
return false;
}
QString data = value(key);
if (m_referenceRegExp.indexIn(data) != -1) {
return true;
}
return false;
}
QRegExp* EntryAttributes::referenceRegExp()
{
return &m_referenceRegExp;
}
void EntryAttributes::set(const QString& key, const QString& value, bool protect) void EntryAttributes::set(const QString& key, const QString& value, bool protect)
{ {
bool emitModified = false; bool emitModified = false;

View File

@ -35,6 +35,8 @@ public:
QString value(const QString& key) const; QString value(const QString& key) const;
bool contains(const QString& key) const; bool contains(const QString& key) const;
bool isProtected(const QString& key) const; bool isProtected(const QString& key) const;
bool isReference(const QString& key) const;
QRegExp* referenceRegExp();
void set(const QString& key, const QString& value, bool protect = false); void set(const QString& key, const QString& value, bool protect = false);
void remove(const QString& key); void remove(const QString& key);
void rename(const QString& oldKey, const QString& newKey); void rename(const QString& oldKey, const QString& newKey);
@ -71,6 +73,7 @@ Q_SIGNALS:
private: private:
QMap<QString, QString> m_attributes; QMap<QString, QString> m_attributes;
QSet<QString> m_protectedAttributes; QSet<QString> m_protectedAttributes;
QRegExp m_referenceRegExp;
}; };
#endif // KEEPASSX_ENTRYATTRIBUTES_H #endif // KEEPASSX_ENTRYATTRIBUTES_H

View File

@ -19,6 +19,7 @@
#include <QFont> #include <QFont>
#include <QMimeData> #include <QMimeData>
#include <QPalette>
#include "core/DatabaseIcons.h" #include "core/DatabaseIcons.h"
#include "core/Entry.h" #include "core/Entry.h"
@ -127,8 +128,10 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
} }
Entry* entry = entryFromIndex(index); Entry* entry = entryFromIndex(index);
EntryAttributes* attr = entry->attributes();
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
QString result;
switch (index.column()) { switch (index.column()) {
case ParentGroup: case ParentGroup:
if (entry->group()) { if (entry->group()) {
@ -136,11 +139,23 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
} }
break; break;
case Title: case Title:
return entry->title(); result = entry->resolvePlaceholder(entry->title());
if (attr->isReference(EntryAttributes::TitleKey)) {
result.prepend(tr("Ref: ","Reference abbreviation"));
}
return result;
case Username: case Username:
return entry->username(); result = entry->resolvePlaceholder(entry->username());
if (attr->isReference(EntryAttributes::UserNameKey)) {
result.prepend(tr("Ref: ","Reference abbreviation"));
}
return result;
case Url: case Url:
return entry->url(); result = entry->resolvePlaceholder(entry->url());
if (attr->isReference(EntryAttributes::URLKey)) {
result.prepend(tr("Ref: ","Reference abbreviation"));
}
return result;
} }
} }
else if (role == Qt::DecorationRole) { else if (role == Qt::DecorationRole) {
@ -166,6 +181,12 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
} }
return font; return font;
} }
else if (role == Qt::TextColorRole) {
if (entry->hasReferences()) {
QPalette p;
return QVariant(p.color(QPalette::Active, QPalette::Mid));
}
}
return QVariant(); return QVariant();
} }