Add "Size" column

- Sizes are displayed in B, KiB, MiB, and GiB with 2 significant
  digits after the decimal
- Column is hidden by default
- TestEntryModel updated for testing proxy model
This commit is contained in:
Ojas Anand 2020-04-17 09:51:36 -04:00 committed by Janek Bevendorff
parent d9214db404
commit 1b18c5d51d
6 changed files with 48 additions and 14 deletions

View File

@ -336,6 +336,23 @@ QString Entry::attribute(const QString& key) const
return m_attributes->value(key); return m_attributes->value(key);
} }
int Entry::size() const
{
int size = 0;
const QRegularExpression delimiter(",|:|;");
size += this->attributes()->attributesSize();
size += this->autoTypeAssociations()->associationsSize();
size += this->attachments()->attachmentsSize();
size += this->customData()->dataSize();
const QStringList tags = this->tags().split(delimiter, QString::SkipEmptyParts);
for (const QString& tag : tags) {
size += tag.toUtf8().size();
}
return size;
}
bool Entry::isExpired() const bool Entry::isExpired() const
{ {
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTimeUtc(); return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTimeUtc();
@ -672,20 +689,12 @@ void Entry::truncateHistory()
QMutableListIterator<Entry*> i(m_history); QMutableListIterator<Entry*> i(m_history);
i.toBack(); i.toBack();
const QRegularExpression delimiter(",|:|;");
while (i.hasPrevious()) { while (i.hasPrevious()) {
Entry* historyItem = i.previous(); Entry* historyItem = i.previous();
// don't calculate size if it's already above the maximum // don't calculate size if it's already above the maximum
if (size <= histMaxSize) { if (size <= histMaxSize) {
size += historyItem->attributes()->attributesSize(); size += historyItem->size();
size += historyItem->autoTypeAssociations()->associationsSize();
size += historyItem->attachments()->attachmentsSize();
size += historyItem->customData()->dataSize();
const QStringList tags = historyItem->tags().split(delimiter, QString::SkipEmptyParts);
for (const QString& tag : tags) {
size += tag.toUtf8().size();
}
foundAttachments += historyItem->attachments()->values(); foundAttachments += historyItem->attachments()->values();
} }

View File

@ -107,6 +107,7 @@ public:
QString attribute(const QString& key) const; QString attribute(const QString& key) const;
QString totp() const; QString totp() const;
QSharedPointer<Totp::Settings> totpSettings() const; QSharedPointer<Totp::Settings> totpSettings() const;
int size() const;
bool hasTotp() const; bool hasTotp() const;
bool isExpired() const; bool isExpired() const;

View File

@ -129,7 +129,7 @@ int EntryModel::columnCount(const QModelIndex& parent) const
return 0; return 0;
} }
return 13; return 14;
} }
QVariant EntryModel::data(const QModelIndex& index, int role) const QVariant EntryModel::data(const QModelIndex& index, int role) const
@ -222,6 +222,22 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
} }
return result; return result;
} }
case Size: {
const int unitsSize = 4;
QString units[unitsSize] = {"B", "KiB", "MiB", "GiB"};
float resultInt = entry->size();
for (int i = 0; i < unitsSize; i++) {
if (resultInt < 1024 || i == unitsSize - 1) {
resultInt = qRound(resultInt * 100) / 100.0;
result = QString::number(resultInt) + " " + units[i];
break;
}
resultInt /= 1024.0;
}
return result;
}
} }
} else if (role == Qt::UserRole) { // Qt::UserRole is used as sort role, see EntryView::EntryView() } else if (role == Qt::UserRole) { // Qt::UserRole is used as sort role, see EntryView::EntryView()
switch (index.column()) { switch (index.column()) {
@ -244,6 +260,8 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
return !entry->attachments()->isEmpty(); return !entry->attachments()->isEmpty();
case Totp: case Totp:
return entry->hasTotp(); return entry->hasTotp();
case Size:
return entry->size();
default: default:
// For all other columns, simply use data provided by Qt::Display- // For all other columns, simply use data provided by Qt::Display-
// Role for sorting // Role for sorting
@ -334,6 +352,8 @@ QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int ro
return tr("Accessed"); return tr("Accessed");
case Attachments: case Attachments:
return tr("Attachments"); return tr("Attachments");
case Size:
return tr("Size");
} }
} else if (role == Qt::DecorationRole) { } else if (role == Qt::DecorationRole) {
@ -367,6 +387,8 @@ QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int ro
return tr("Last access date"); return tr("Last access date");
case Attachments: case Attachments:
return tr("Attached files"); return tr("Attached files");
case Size:
return tr("Entry size");
case Paperclip: case Paperclip:
return tr("Has attachments"); return tr("Has attachments");
case Totp: case Totp:

View File

@ -43,7 +43,8 @@ public:
Accessed = 9, Accessed = 9,
Paperclip = 10, Paperclip = 10,
Attachments = 11, Attachments = 11,
Totp = 12 Totp = 12,
Size = 13
}; };
explicit EntryModel(QObject* parent = nullptr); explicit EntryModel(QObject* parent = nullptr);

View File

@ -72,7 +72,7 @@ EntryView::EntryView(QWidget* parent)
resetViewToDefaults(); resetViewToDefaults();
// Actions to toggle column visibility, each carrying the corresponding // Actions to toggle column visibility, each carrying the corresponding
// colummn index as data // column index as data
m_columnActions = new QActionGroup(this); m_columnActions = new QActionGroup(this);
m_columnActions->setExclusive(false); m_columnActions->setExclusive(false);
for (int visualIndex = 1; visualIndex < header()->count(); ++visualIndex) { for (int visualIndex = 1; visualIndex < header()->count(); ++visualIndex) {
@ -451,6 +451,7 @@ void EntryView::resetViewToDefaults()
header()->hideSection(EntryModel::Created); header()->hideSection(EntryModel::Created);
header()->hideSection(EntryModel::Accessed); header()->hideSection(EntryModel::Accessed);
header()->hideSection(EntryModel::Attachments); header()->hideSection(EntryModel::Attachments);
header()->hideSection(EntryModel::Size);
// Reset column order to logical indices // Reset column order to logical indices
for (int i = 0; i < header()->count(); ++i) { for (int i = 0; i < header()->count(); ++i) {

View File

@ -295,7 +295,7 @@ void TestEntryModel::testProxyModel()
*/ */
QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int))); QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)));
modelProxy->hideColumn(0, true); modelProxy->hideColumn(0, true);
QCOMPARE(modelProxy->columnCount(), 12); QCOMPARE(modelProxy->columnCount(), 13);
QVERIFY(!spyColumnRemove.isEmpty()); QVERIFY(!spyColumnRemove.isEmpty());
int oldSpyColumnRemoveSize = spyColumnRemove.size(); int oldSpyColumnRemoveSize = spyColumnRemove.size();
@ -317,7 +317,7 @@ void TestEntryModel::testProxyModel()
*/ */
QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int))); QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)));
modelProxy->hideColumn(0, false); modelProxy->hideColumn(0, false);
QCOMPARE(modelProxy->columnCount(), 13); QCOMPARE(modelProxy->columnCount(), 14);
QVERIFY(!spyColumnInsert.isEmpty()); QVERIFY(!spyColumnInsert.isEmpty());
int oldSpyColumnInsertSize = spyColumnInsert.size(); int oldSpyColumnInsertSize = spyColumnInsert.size();