diff --git a/CHANGELOG b/CHANGELOG
index 4a4c921a2..4a6c9d3f1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+2.5.0-Beta1 (2019-07-05)
+=========================
+- Group sorting feature [#3282]
+
2.4.3 (2019-06-12)
=========================
diff --git a/src/core/Group.cpp b/src/core/Group.cpp
index 814ac2f3b..a5d5087f0 100644
--- a/src/core/Group.cpp
+++ b/src/core/Group.cpp
@@ -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);
diff --git a/src/core/Group.h b/src/core/Group.h
index 59e455ac0..048c08854 100644
--- a/src/core/Group.h
+++ b/src/core/Group.h
@@ -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);
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index 59e6fcf39..824dab371 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -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();
diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h
index 73baae6b7..7da6b7a40 100644
--- a/src/gui/DatabaseWidget.h
+++ b/src/gui/DatabaseWidget.h
@@ -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();
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 5c9047608..e58070463 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -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);
diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui
index 0003c7015..ebfeba3f9 100644
--- a/src/gui/MainWindow.ui
+++ b/src/gui/MainWindow.ui
@@ -281,6 +281,9 @@
+
+
+