diff options
Diffstat (limited to 'src/core/Group.cpp')
-rw-r--r-- | src/core/Group.cpp | 174 |
1 files changed, 150 insertions, 24 deletions
diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 87741ee0c..2c0d67091 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -75,17 +75,6 @@ Group::~Group() cleanupParent(); } -Group* Group::createRecycleBin() -{ - Group* recycleBin = new Group(); - recycleBin->setUuid(QUuid::createUuid()); - recycleBin->setName(tr("Recycle Bin")); - recycleBin->setIcon(RecycleBinIconNumber); - recycleBin->setSearchingEnabled(Group::Disable); - recycleBin->setAutoTypeEnabled(Group::Disable); - return recycleBin; -} - template <class P, class V> inline bool Group::set(P& property, const V& value) { if (property != value) { @@ -257,9 +246,9 @@ Entry* Group::lastTopVisibleEntry() const return m_lastTopVisibleEntry; } -bool Group::isRecycled() +bool Group::isRecycled() const { - Group* group = this; + auto group = this; if (!group->database()) { return false; } @@ -281,6 +270,11 @@ bool Group::isExpired() const return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTimeUtc(); } +bool Group::isEmpty() const +{ + return !hasChildren() && m_entries.isEmpty(); +} + CustomData* Group::customData() { return m_customData; @@ -504,16 +498,25 @@ void Group::setParent(Database* db) QObject::setParent(db); } -QStringList Group::hierarchy() const +QStringList Group::hierarchy(int height) const { QStringList hierarchy; const Group* group = this; const Group* parent = m_parent; + + if (height == 0) { + return hierarchy; + } + hierarchy.prepend(group->name()); - while (parent) { + int level = 1; + bool heightReached = level == height; + + while (parent && !heightReached) { group = group->parentGroup(); parent = group->parentGroup(); + heightReached = ++level == height; hierarchy.prepend(group->name()); } @@ -521,6 +524,11 @@ QStringList Group::hierarchy() const return hierarchy; } +bool Group::hasChildren() const +{ + return !children().isEmpty(); +} + Database* Group::database() { return m_db; @@ -577,13 +585,18 @@ QList<Entry*> Group::referencesRecursive(const Entry* entry) const [entry](const Entry* e) { return e->hasReferencesTo(entry->uuid()); }); } -Entry* Group::findEntryByUuid(const QUuid& uuid) const +Entry* Group::findEntryByUuid(const QUuid& uuid, bool recursive) const { if (uuid.isNull()) { return nullptr; } - for (Entry* entry : entriesRecursive(false)) { + auto entries = m_entries; + if (recursive) { + entries = entriesRecursive(false); + } + + for (auto entry : entries) { if (entry->uuid() == uuid) { return entry; } @@ -715,25 +728,34 @@ Group* Group::findGroupByPathRecursive(const QString& groupPath, const QString& return nullptr; } -QString Group::print(bool recursive, int depth) +QString Group::print(bool recursive, bool flatten, int depth) { - QString response; - QString indentation = QString(" ").repeated(depth); + QString prefix; + + if (flatten) { + const QString separator("/"); + prefix = hierarchy(depth).join(separator); + if (!prefix.isEmpty()) { + prefix += separator; + } + } else { + prefix = QString(" ").repeated(depth); + } if (entries().isEmpty() && children().isEmpty()) { - response += indentation + tr("[empty]", "group has no children") + "\n"; + response += prefix + tr("[empty]", "group has no children") + "\n"; return response; } for (Entry* entry : entries()) { - response += indentation + entry->title() + "\n"; + response += prefix + entry->title() + "\n"; } for (Group* innerGroup : children()) { - response += indentation + innerGroup->name() + "/\n"; + response += prefix + innerGroup->name() + "/\n"; if (recursive) { - response += innerGroup->print(recursive, depth + 1); + response += innerGroup->print(recursive, flatten, depth + 1); } } @@ -790,6 +812,42 @@ QSet<QUuid> Group::customIconsRecursive() const return result; } +QList<QString> Group::usernamesRecursive(int topN) const +{ + // Collect all usernames and sort for easy counting + QHash<QString, int> countedUsernames; + for (const auto* entry : entriesRecursive()) { + const auto username = entry->username(); + if (!username.isEmpty() && !entry->isAttributeReference(EntryAttributes::UserNameKey)) { + countedUsernames.insert(username, ++countedUsernames[username]); + } + } + + // Sort username/frequency pairs by frequency and name + QList<QPair<QString, int>> sortedUsernames; + for (const auto& key : countedUsernames.keys()) { + sortedUsernames.append({key, countedUsernames[key]}); + } + + auto comparator = [](const QPair<QString, int>& arg1, const QPair<QString, int>& arg2) { + if (arg1.second == arg2.second) { + return arg1.first < arg2.first; + } + return arg1.second > arg2.second; + }; + + std::sort(sortedUsernames.begin(), sortedUsernames.end(), comparator); + + // Take first topN usernames if set + QList<QString> usernames; + int actualUsernames = topN < 0 ? sortedUsernames.size() : std::min(topN, sortedUsernames.size()); + for (int i = 0; i < actualUsernames; i++) { + usernames.append(sortedUsernames[i].first); + } + + return usernames; +} + Group* Group::findGroupByUuid(const QUuid& uuid) { if (uuid.isNull()) { @@ -1057,6 +1115,74 @@ Entry* Group::addEntryWithPath(const QString& entryPath) return entry; } +void Group::applyGroupIconOnCreateTo(Entry* entry) +{ + Q_ASSERT(entry); + + if (!config()->get("UseGroupIconOnEntryCreation").toBool()) { + return; + } + + if (iconNumber() == Group::DefaultIconNumber && iconUuid().isNull()) { + return; + } + + applyGroupIconTo(entry); +} + +void Group::applyGroupIconTo(Entry* entry) +{ + Q_ASSERT(entry); + + if (iconUuid().isNull()) { + entry->setIcon(iconNumber()); + } else { + entry->setIcon(iconUuid()); + } +} + +void Group::applyGroupIconTo(Group* other) +{ + Q_ASSERT(other); + + if (iconUuid().isNull()) { + other->setIcon(iconNumber()); + } else { + other->setIcon(iconUuid()); + } +} + +void Group::applyGroupIconToChildGroups() +{ + for (Group* recursiveChild : groupsRecursive(false)) { + applyGroupIconTo(recursiveChild); + } +} + +void Group::applyGroupIconToChildEntries() +{ + for (Entry* recursiveEntry : entriesRecursive(false)) { + applyGroupIconTo(recursiveEntry); + } +} + +void Group::sortChildrenRecursively(bool reverse) +{ + std::sort( + m_children.begin(), m_children.end(), [reverse](const Group* childGroup1, const Group* childGroup2) -> bool { + QString name1 = childGroup1->name(); + QString name2 = childGroup2->name(); + return reverse ? name1.compare(name2, Qt::CaseInsensitive) > 0 + : name1.compare(name2, Qt::CaseInsensitive) < 0; + }); + + for (auto child : m_children) { + child->sortChildrenRecursively(reverse); + } + + emit groupModified(); +} + bool Group::GroupData::operator==(const Group::GroupData& other) const { return equals(other, CompareItemDefault); |