mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-08-04 20:44:14 -04:00
Add group sorting feature
* Enabling sorting of groups and their children in ascending and descending direction
This commit is contained in:
parent
0c2d1bcc50
commit
09181fab13
15 changed files with 373 additions and 0 deletions
|
@ -521,6 +521,11 @@ QStringList Group::hierarchy() const
|
|||
return hierarchy;
|
||||
}
|
||||
|
||||
bool Group::hasChildren() const
|
||||
{
|
||||
return !children().isEmpty();
|
||||
}
|
||||
|
||||
Database* Group::database()
|
||||
{
|
||||
return m_db;
|
||||
|
@ -1074,6 +1079,23 @@ void Group::applyGroupIconTo(Entry* entry)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -144,6 +144,7 @@ public:
|
|||
const Group* parentGroup() const;
|
||||
void setParent(Group* parent, int index = -1);
|
||||
QStringList hierarchy() const;
|
||||
bool hasChildren() const;
|
||||
|
||||
Database* database();
|
||||
const Database* database() const;
|
||||
|
@ -169,6 +170,8 @@ public:
|
|||
|
||||
void applyGroupIconTo(Entry* entry);
|
||||
|
||||
void sortChildrenRecursively(bool reverse = false);
|
||||
|
||||
signals:
|
||||
void groupDataChanged(Group* group);
|
||||
void groupAboutToAdd(Group* group, int index);
|
||||
|
|
|
@ -1073,6 +1073,16 @@ void DatabaseWidget::switchToGroupEdit()
|
|||
switchToGroupEdit(group, false);
|
||||
}
|
||||
|
||||
void DatabaseWidget::sortGroupsAsc()
|
||||
{
|
||||
m_groupView->sortGroups();
|
||||
}
|
||||
|
||||
void DatabaseWidget::sortGroupsDesc()
|
||||
{
|
||||
m_groupView->sortGroups(true);
|
||||
}
|
||||
|
||||
void DatabaseWidget::switchToMasterKeyChange()
|
||||
{
|
||||
switchToDatabaseSettings();
|
||||
|
|
|
@ -175,6 +175,8 @@ public slots:
|
|||
void switchToMainView(bool previousDialogAccepted = false);
|
||||
void switchToEntryEdit();
|
||||
void switchToGroupEdit();
|
||||
void sortGroupsAsc();
|
||||
void sortGroupsDesc();
|
||||
void switchToMasterKeyChange();
|
||||
void switchToDatabaseSettings();
|
||||
void switchToOpenDatabase();
|
||||
|
|
|
@ -380,6 +380,8 @@ MainWindow::MainWindow()
|
|||
m_actionMultiplexer.connect(m_ui->actionGroupEdit, SIGNAL(triggered()), SLOT(switchToGroupEdit()));
|
||||
m_actionMultiplexer.connect(m_ui->actionGroupDelete, SIGNAL(triggered()), SLOT(deleteGroup()));
|
||||
m_actionMultiplexer.connect(m_ui->actionGroupEmptyRecycleBin, SIGNAL(triggered()), SLOT(emptyRecycleBin()));
|
||||
m_actionMultiplexer.connect(m_ui->actionGroupSortAsc, SIGNAL(triggered()), SLOT(sortGroupsAsc()));
|
||||
m_actionMultiplexer.connect(m_ui->actionGroupSortDesc, SIGNAL(triggered()), SLOT(sortGroupsDesc()));
|
||||
|
||||
connect(m_ui->actionSettings, SIGNAL(toggled(bool)), SLOT(switchToSettings(bool)));
|
||||
connect(m_ui->actionPasswordGenerator, SIGNAL(toggled(bool)), SLOT(switchToPasswordGen(bool)));
|
||||
|
@ -570,6 +572,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
|
|||
bool singleEntrySelected = dbWidget->numberOfSelectedEntries() == 1 && hasFocus;
|
||||
bool entriesSelected = dbWidget->numberOfSelectedEntries() > 0 && hasFocus;
|
||||
bool groupSelected = dbWidget->isGroupSelected();
|
||||
bool currentGroupHasChildren = dbWidget->currentGroup()->hasChildren();
|
||||
bool recycleBinSelected = dbWidget->isRecycleBinSelected();
|
||||
|
||||
m_ui->actionEntryNew->setEnabled(true);
|
||||
|
@ -592,6 +595,8 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
|
|||
m_ui->actionGroupNew->setEnabled(groupSelected);
|
||||
m_ui->actionGroupEdit->setEnabled(groupSelected);
|
||||
m_ui->actionGroupDelete->setEnabled(groupSelected && dbWidget->canDeleteCurrentGroup());
|
||||
m_ui->actionGroupSortAsc->setEnabled(groupSelected && currentGroupHasChildren);
|
||||
m_ui->actionGroupSortDesc->setEnabled(groupSelected && currentGroupHasChildren);
|
||||
m_ui->actionGroupEmptyRecycleBin->setVisible(recycleBinSelected);
|
||||
m_ui->actionGroupEmptyRecycleBin->setEnabled(recycleBinSelected);
|
||||
m_ui->actionChangeMasterKey->setEnabled(true);
|
||||
|
|
|
@ -281,6 +281,9 @@
|
|||
<addaction name="actionGroupEdit"/>
|
||||
<addaction name="actionGroupDelete"/>
|
||||
<addaction name="actionGroupEmptyRecycleBin"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionGroupSortAsc"/>
|
||||
<addaction name="actionGroupSortDesc"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
|
@ -452,6 +455,22 @@
|
|||
<string>&Delete group</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupSortAsc">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort &A-Z</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupSortDesc">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort &Z-A</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDatabaseSaveAs">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
|
|
|
@ -410,3 +410,30 @@ void GroupModel::groupMoved()
|
|||
{
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
void GroupModel::sortChildren(Group* rootGroup, bool reverse)
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
|
||||
QList<QModelIndex> oldIndexes;
|
||||
collectIndexesRecursively(oldIndexes, rootGroup->children());
|
||||
|
||||
rootGroup->sortChildrenRecursively(reverse);
|
||||
|
||||
QList<QModelIndex> newIndexes;
|
||||
collectIndexesRecursively(newIndexes, rootGroup->children());
|
||||
|
||||
for (int i = 0; i < oldIndexes.count(); i++) {
|
||||
changePersistentIndex(oldIndexes[i], newIndexes[i]);
|
||||
}
|
||||
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
void GroupModel::collectIndexesRecursively(QList<QModelIndex>& indexes, QList<Group*> groups)
|
||||
{
|
||||
for (auto group : groups) {
|
||||
indexes.append(index(group));
|
||||
collectIndexesRecursively(indexes, group->children());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,9 +45,11 @@ public:
|
|||
dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override;
|
||||
QStringList mimeTypes() const override;
|
||||
QMimeData* mimeData(const QModelIndexList& indexes) const override;
|
||||
void sortChildren(Group* rootGroup, bool reverse = false);
|
||||
|
||||
private:
|
||||
QModelIndex parent(Group* group) const;
|
||||
void collectIndexesRecursively(QList<QModelIndex>& indexes, QList<Group*> groups);
|
||||
|
||||
private slots:
|
||||
void groupDataChanged(Group* group);
|
||||
|
|
|
@ -115,6 +115,14 @@ void GroupView::expandGroup(Group* group, bool expand)
|
|||
setExpanded(index, expand);
|
||||
}
|
||||
|
||||
void GroupView::sortGroups(bool reverse)
|
||||
{
|
||||
Group* group = currentGroup();
|
||||
if (group) {
|
||||
m_model->sortChildren(group, reverse);
|
||||
}
|
||||
}
|
||||
|
||||
void GroupView::setModel(QAbstractItemModel* model)
|
||||
{
|
||||
Q_UNUSED(model);
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
Group* currentGroup();
|
||||
void setCurrentGroup(Group* group);
|
||||
void expandGroup(Group* group, bool expand = true);
|
||||
void sortGroups(bool reverse = false);
|
||||
|
||||
signals:
|
||||
void groupSelectionChanged(Group* group);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue