From 1b18c5d51d8de2a278f950f575dff4bfab67f860 Mon Sep 17 00:00:00 2001 From: Ojas Anand Date: Fri, 17 Apr 2020 09:51:36 -0400 Subject: [PATCH] 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 --- src/core/Entry.cpp | 27 ++++++++++++++++++--------- src/core/Entry.h | 1 + src/gui/entry/EntryModel.cpp | 24 +++++++++++++++++++++++- src/gui/entry/EntryModel.h | 3 ++- src/gui/entry/EntryView.cpp | 3 ++- tests/TestEntryModel.cpp | 4 ++-- 6 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index c88e4a2fb..26371774b 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -336,6 +336,23 @@ QString Entry::attribute(const QString& key) const 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 { return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTimeUtc(); @@ -672,20 +689,12 @@ void Entry::truncateHistory() QMutableListIterator i(m_history); i.toBack(); - const QRegularExpression delimiter(",|:|;"); while (i.hasPrevious()) { Entry* historyItem = i.previous(); // don't calculate size if it's already above the maximum if (size <= histMaxSize) { - size += historyItem->attributes()->attributesSize(); - 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(); - } + size += historyItem->size(); foundAttachments += historyItem->attachments()->values(); } diff --git a/src/core/Entry.h b/src/core/Entry.h index 326728d11..591372cdc 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -107,6 +107,7 @@ public: QString attribute(const QString& key) const; QString totp() const; QSharedPointer totpSettings() const; + int size() const; bool hasTotp() const; bool isExpired() const; diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index ae520035e..4446cb7eb 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -129,7 +129,7 @@ int EntryModel::columnCount(const QModelIndex& parent) const return 0; } - return 13; + return 14; } QVariant EntryModel::data(const QModelIndex& index, int role) const @@ -222,6 +222,22 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const } 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() switch (index.column()) { @@ -244,6 +260,8 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const return !entry->attachments()->isEmpty(); case Totp: return entry->hasTotp(); + case Size: + return entry->size(); default: // For all other columns, simply use data provided by Qt::Display- // Role for sorting @@ -334,6 +352,8 @@ QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int ro return tr("Accessed"); case Attachments: return tr("Attachments"); + case Size: + return tr("Size"); } } else if (role == Qt::DecorationRole) { @@ -367,6 +387,8 @@ QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int ro return tr("Last access date"); case Attachments: return tr("Attached files"); + case Size: + return tr("Entry size"); case Paperclip: return tr("Has attachments"); case Totp: diff --git a/src/gui/entry/EntryModel.h b/src/gui/entry/EntryModel.h index ea2c96d5a..055455e57 100644 --- a/src/gui/entry/EntryModel.h +++ b/src/gui/entry/EntryModel.h @@ -43,7 +43,8 @@ public: Accessed = 9, Paperclip = 10, Attachments = 11, - Totp = 12 + Totp = 12, + Size = 13 }; explicit EntryModel(QObject* parent = nullptr); diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp index ea41b9b81..fd317cdd3 100644 --- a/src/gui/entry/EntryView.cpp +++ b/src/gui/entry/EntryView.cpp @@ -72,7 +72,7 @@ EntryView::EntryView(QWidget* parent) resetViewToDefaults(); // Actions to toggle column visibility, each carrying the corresponding - // colummn index as data + // column index as data m_columnActions = new QActionGroup(this); m_columnActions->setExclusive(false); for (int visualIndex = 1; visualIndex < header()->count(); ++visualIndex) { @@ -451,6 +451,7 @@ void EntryView::resetViewToDefaults() header()->hideSection(EntryModel::Created); header()->hideSection(EntryModel::Accessed); header()->hideSection(EntryModel::Attachments); + header()->hideSection(EntryModel::Size); // Reset column order to logical indices for (int i = 0; i < header()->count(); ++i) { diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index 670e43aab..6c4b97454 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -295,7 +295,7 @@ void TestEntryModel::testProxyModel() */ QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int))); modelProxy->hideColumn(0, true); - QCOMPARE(modelProxy->columnCount(), 12); + QCOMPARE(modelProxy->columnCount(), 13); QVERIFY(!spyColumnRemove.isEmpty()); int oldSpyColumnRemoveSize = spyColumnRemove.size(); @@ -317,7 +317,7 @@ void TestEntryModel::testProxyModel() */ QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int))); modelProxy->hideColumn(0, false); - QCOMPARE(modelProxy->columnCount(), 13); + QCOMPARE(modelProxy->columnCount(), 14); QVERIFY(!spyColumnInsert.isEmpty()); int oldSpyColumnInsertSize = spyColumnInsert.size();