diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index e03ec7c0e9f2533a9d5e96a96fadbbb3955e9313..af8cfc13126e5c935d8039a8ae4f90e4577060ad 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -34,6 +34,7 @@ KFileItemModel::KFileItemModel(QObject* parent) :
KItemModelBase("text", parent),
m_dirLister(nullptr),
m_sortDirsFirst(true),
+ m_sortHiddenLast(false),
m_sortRole(NameRole),
m_sortingProgressPercent(-1),
m_roles(),
@@ -212,6 +213,19 @@ bool KFileItemModel::sortDirectoriesFirst() const
return m_sortDirsFirst;
}
+void KFileItemModel::setSortHiddenLast(bool hiddenLast)
+{
+ if (hiddenLast != m_sortHiddenLast) {
+ m_sortHiddenLast = hiddenLast;
+ resortAllItems();
+ }
+}
+
+bool KFileItemModel::sortHiddenLast() const
+{
+ return m_sortHiddenLast;
+}
+
void KFileItemModel::setShowHiddenFiles(bool show)
{
m_dirLister->setShowingDotFiles(show);
@@ -1734,12 +1748,14 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b, const QColla
}
// Show hidden files and folders last
- const bool isHiddenA = a->item.isHidden();
- const bool isHiddenB = b->item.isHidden();
- if (isHiddenA && !isHiddenB) {
- return false;
- } else if (!isHiddenA && isHiddenB) {
- return true;
+ if (m_sortHiddenLast) {
+ const bool isHiddenA = a->item.isHidden();
+ const bool isHiddenB = b->item.isHidden();
+ if (isHiddenA && !isHiddenB) {
+ return false;
+ } else if (!isHiddenA && isHiddenB) {
+ return true;
+ }
}
if (m_sortDirsFirst || (DetailsModeSettings::directorySizeCount() && m_sortRole == SizeRole)) {
diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h
index acf4b761cf51bde3b470c197ce5ad36e81721962..33838853df2cd5d920b2ab18c28ac5287a281fb9 100644
--- a/src/kitemviews/kfileitemmodel.h
+++ b/src/kitemviews/kfileitemmodel.h
@@ -80,6 +80,12 @@ public:
void setSortDirectoriesFirst(bool dirsFirst);
bool sortDirectoriesFirst() const;
+ /**
+ * Sets a separate sorting with hidden files and folders last (true) or not (false).
+ */
+ void setSortHiddenLast(bool hiddenLast);
+ bool sortHiddenLast() const;
+
void setShowHiddenFiles(bool show);
bool showHiddenFiles() const;
@@ -463,6 +469,7 @@ private:
QCollator m_collator;
bool m_naturalSorting;
bool m_sortDirsFirst;
+ bool m_sortHiddenLast;
RoleType m_sortRole;
int m_sortingProgressPercent; // Value of directorySortingProgress() signal
diff --git a/src/settings/dolphin_directoryviewpropertysettings.kcfg b/src/settings/dolphin_directoryviewpropertysettings.kcfg
index 6bcf3cd02bcdaec700c08f7d79b52a4a8fbe8681..f4d288369605528ab559a897119be875ab8f720c 100644
--- a/src/settings/dolphin_directoryviewpropertysettings.kcfg
+++ b/src/settings/dolphin_directoryviewpropertysettings.kcfg
@@ -57,6 +57,11 @@
true
+
+
+ false
+
+
diff --git a/src/settings/viewpropertiesdialog.cpp b/src/settings/viewpropertiesdialog.cpp
index 82d182d1d00c8a9e8cc736c9df3428596d7f65c5..6659d79b63f0b3c9f23cefd0cb4829ed7661e4df 100644
--- a/src/settings/viewpropertiesdialog.cpp
+++ b/src/settings/viewpropertiesdialog.cpp
@@ -44,6 +44,7 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
m_sortOrder(nullptr),
m_sorting(nullptr),
m_sortFoldersFirst(nullptr),
+ m_sortHiddenLast(nullptr),
m_previewsShown(nullptr),
m_showInGroups(nullptr),
m_showHiddenFiles(nullptr),
@@ -82,6 +83,7 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
}
m_sortFoldersFirst = new QCheckBox(i18nc("@option:check", "Show folders first"));
+ m_sortHiddenLast = new QCheckBox(i18nc("@option:check", "Show hidden files last"));
m_previewsShown = new QCheckBox(i18nc("@option:check", "Show preview"));
m_showInGroups = new QCheckBox(i18nc("@option:check", "Show in groups"));
m_showHiddenFiles = new QCheckBox(i18nc("@option:check", "Show hidden files"));
@@ -146,6 +148,7 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
layout->addRow(QString(), m_previewsShown);
layout->addRow(QString(), m_showInGroups);
layout->addRow(QString(), m_showHiddenFiles);
+ layout->addRow(QString(), m_sortHiddenLast);
connect(m_viewMode, QOverload::of(&QComboBox::currentIndexChanged),
this, &ViewPropertiesDialog::slotViewModeChanged);
@@ -155,6 +158,8 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
this, &ViewPropertiesDialog::slotSortOrderChanged);
connect(m_sortFoldersFirst, &QCheckBox::clicked,
this, &ViewPropertiesDialog::slotSortFoldersFirstChanged);
+ connect(m_sortHiddenLast, &QCheckBox::clicked,
+ this, &ViewPropertiesDialog::slotSortHiddenLastChanged);
connect(m_previewsShown, &QCheckBox::clicked,
this, &ViewPropertiesDialog::slotShowPreviewChanged);
connect(m_showInGroups, &QCheckBox::clicked,
@@ -282,6 +287,13 @@ void ViewPropertiesDialog::slotSortFoldersFirstChanged()
markAsDirty(true);
}
+void ViewPropertiesDialog::slotSortHiddenLastChanged()
+{
+ const bool hiddenLast = m_sortHiddenLast->isChecked();
+ m_viewProps->setSortHiddenLast(hiddenLast);
+ markAsDirty(true);
+}
+
void ViewPropertiesDialog::slotShowPreviewChanged()
{
const bool show = m_previewsShown->isChecked();
@@ -383,6 +395,7 @@ void ViewPropertiesDialog::applyViewProperties()
m_dolphinView->setSortRole(m_viewProps->sortRole());
m_dolphinView->setSortOrder(m_viewProps->sortOrder());
m_dolphinView->setSortFoldersFirst(m_viewProps->sortFoldersFirst());
+ m_dolphinView->setSortHiddenLast(m_viewProps->sortHiddenLast());
m_dolphinView->setGroupedSorting(m_viewProps->groupedSorting());
m_dolphinView->setVisibleRoles(m_viewProps->visibleRoles());
m_dolphinView->setPreviewsShown(m_viewProps->previewsShown());
@@ -418,6 +431,7 @@ void ViewPropertiesDialog::loadSettings()
m_sorting->setCurrentIndex(sortRoleIndex);
m_sortFoldersFirst->setChecked(m_viewProps->sortFoldersFirst());
+ m_sortHiddenLast->setChecked(m_viewProps->sortHiddenLast());
// Load show preview, show in groups and show hidden files settings
m_previewsShown->setChecked(m_viewProps->previewsShown());
diff --git a/src/settings/viewpropertiesdialog.h b/src/settings/viewpropertiesdialog.h
index f07bb8088f00df2abe7465865d27923bd94d6822..c58fda5c002fb2dc782540ee5d5a2eca3995d14e 100644
--- a/src/settings/viewpropertiesdialog.h
+++ b/src/settings/viewpropertiesdialog.h
@@ -46,6 +46,7 @@ private Q_SLOTS:
void slotSortOrderChanged(int index);
void slotGroupedSortingChanged();
void slotSortFoldersFirstChanged();
+ void slotSortHiddenLastChanged();
void slotShowPreviewChanged();
void slotShowHiddenFilesChanged();
void slotItemChanged(QListWidgetItem *item);
@@ -67,6 +68,7 @@ private:
QComboBox* m_sortOrder;
QComboBox* m_sorting;
QCheckBox* m_sortFoldersFirst;
+ QCheckBox* m_sortHiddenLast;
QCheckBox* m_previewsShown;
QCheckBox* m_showInGroups;
QCheckBox* m_showHiddenFiles;
diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp
index f527fbc61b2043bd7d45bed1e44bbe7add949652..4b84f157945d735bbc618f1bf9ed81a6fbc1fb5d 100644
--- a/src/tests/kfileitemmodeltest.cpp
+++ b/src/tests/kfileitemmodeltest.cpp
@@ -814,16 +814,16 @@ void KFileItemModelTest::testSorting()
{
// testDir structure is as follows
// ./
+ // ├─ .g/
// ├─ a
// ├─ b
// ├─ c/
// │ ├─ c-2/
// │ │ ├─ c-3
// │ ├─ c-1
+ // ├─ .f
// ├─ d
// ├─ e
- // ├─ .f
- // ├─ .g/
QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted);
QSignalSpy itemsMovedSpy(m_model, &KFileItemModel::itemsMoved);
@@ -968,10 +968,20 @@ void KFileItemModelTest::testSorting()
// 'Show Hidden Files' enabled
m_model->setShowHiddenFiles(true);
QVERIFY(m_model->showHiddenFiles());
- QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "d" << "e" << "b" << "a" << ".g" << ".f");
+ QVERIFY(!m_model->sortHiddenLast());
+ QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << ".g" << "d" << "e" << "b" << "a" << ".f");
QCOMPARE(itemsMovedSpy.count(), 0);
QCOMPARE(itemsInsertedSpy.count(), 1);
- QCOMPARE(itemsInsertedSpy.takeFirst().at(0).value(), KItemRangeList() << KItemRange(8, 2));
+ QCOMPARE(itemsInsertedSpy.takeFirst().at(0).value(), KItemRangeList() << KItemRange(4, 1) << KItemRange(8, 1));
+
+ // 'Sort Hidden Files Last' enabled
+ m_model->setSortHiddenLast(true);
+ QVERIFY(m_model->sortHiddenLast());
+ QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "d" << "e" << "b" << "a" << ".g" << ".f");
+ QCOMPARE(itemsMovedSpy.count(), 1);
+ QCOMPARE(itemsInsertedSpy.count(), 0);
+ QCOMPARE(itemsMovedSpy.first().at(0).value(), KItemRange(4, 5));
+ QCOMPARE(itemsMovedSpy.takeFirst().at(1).value >(), QList() << 8 << 4 << 5 << 6 << 7);
// Sort by Name
m_model->setSortRole("text");
@@ -1151,7 +1161,7 @@ void KFileItemModelTest::testRemoveHiddenItems()
m_model->setShowHiddenFiles(true);
m_model->loadDirectory(m_testDir->url());
QVERIFY(itemsInsertedSpy.wait());
- QCOMPARE(itemsInModel(), QStringList() << "c" << "d" << "h" << "i" << ".a" << ".b" <<".f" << ".g");
+ QCOMPARE(itemsInModel(), QStringList() << ".a" << ".b" << "c" << "d" <<".f" << ".g" << "h" << "i");
QCOMPARE(itemsInsertedSpy.count(), 1);
QCOMPARE(itemsRemovedSpy.count(), 0);
KItemRangeList itemRangeList = itemsInsertedSpy.takeFirst().at(0).value();
@@ -1162,14 +1172,14 @@ void KFileItemModelTest::testRemoveHiddenItems()
QCOMPARE(itemsInsertedSpy.count(), 0);
QCOMPARE(itemsRemovedSpy.count(), 1);
itemRangeList = itemsRemovedSpy.takeFirst().at(0).value();
- QCOMPARE(itemRangeList, KItemRangeList() << KItemRange(4, 4));
+ QCOMPARE(itemRangeList, KItemRangeList() << KItemRange(0, 2) << KItemRange(4, 2));
m_model->setShowHiddenFiles(true);
- QCOMPARE(itemsInModel(), QStringList() << "c" << "d" << "h" << "i" << ".a" << ".b" <<".f" << ".g");
+ QCOMPARE(itemsInModel(), QStringList() << ".a" << ".b" << "c" << "d" <<".f" << ".g" << "h" << "i");
QCOMPARE(itemsInsertedSpy.count(), 1);
QCOMPARE(itemsRemovedSpy.count(), 0);
itemRangeList = itemsInsertedSpy.takeFirst().at(0).value();
- QCOMPARE(itemRangeList, KItemRangeList() << KItemRange(4, 4));
+ QCOMPARE(itemRangeList, KItemRangeList() << KItemRange(0, 2) << KItemRange(2, 2));
m_model->clear();
QCOMPARE(itemsInModel(), QStringList());
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index f5c21a2c5561ecf16898f98b5aefeb5d61f9b3ed..57ed73a3a6488ab5032599722a1fc19ac76514e6 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -463,6 +463,18 @@ bool DolphinView::sortFoldersFirst() const
return m_model->sortDirectoriesFirst();
}
+void DolphinView::setSortHiddenLast(bool hiddenLast)
+{
+ if (sortHiddenLast() != hiddenLast) {
+ updateSortHiddenLast(hiddenLast);
+ }
+}
+
+bool DolphinView::sortHiddenLast() const
+{
+ return m_model->sortHiddenLast();
+}
+
void DolphinView::setVisibleRoles(const QList& roles)
{
const QList previousRoles = roles;
@@ -1373,6 +1385,17 @@ void DolphinView::updateSortFoldersFirst(bool foldersFirst)
Q_EMIT sortFoldersFirstChanged(foldersFirst);
}
+void DolphinView::updateSortHiddenLast(bool hiddenLast)
+{
+ ViewProperties props(viewPropertiesUrl());
+ props.setSortHiddenLast(hiddenLast);
+
+ m_model->setSortHiddenLast(hiddenLast);
+
+ Q_EMIT sortHiddenLastChanged(hiddenLast);
+}
+
+
QPair DolphinView::pasteInfo() const
{
const QMimeData *mimeData = QApplication::clipboard()->mimeData();
@@ -1903,6 +1926,12 @@ void DolphinView::applyViewProperties(const ViewProperties& props)
Q_EMIT sortFoldersFirstChanged(sortFoldersFirst);
}
+ const bool sortHiddenLast = props.sortHiddenLast();
+ if (sortHiddenLast != m_model->sortHiddenLast()) {
+ m_model->setSortHiddenLast(sortHiddenLast);
+ Q_EMIT sortHiddenLastChanged(sortHiddenLast);
+ }
+
const QList visibleRoles = props.visibleRoles();
if (visibleRoles != m_visibleRoles) {
const QList previousVisibleRoles = m_visibleRoles;
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index e4d7798300bee6f4cb0ccfbd392e9ddef5501fc8..75c9dd9856a382b9f9e2126b1ad2b66d4218424e 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -206,6 +206,10 @@ public:
void setSortFoldersFirst(bool foldersFirst);
bool sortFoldersFirst() const;
+ /** Sets a separate sorting with hidden files and folders last (true) or not (false). */
+ void setSortHiddenLast(bool hiddenLast);
+ bool sortHiddenLast() const;
+
/** Sets the additional information which should be shown for the items. */
void setVisibleRoles(const QList& roles);
@@ -470,6 +474,11 @@ Q_SIGNALS:
*/
void sortFoldersFirstChanged(bool foldersFirst);
+ /**
+ * Is emitted if the sorting of hidden files has been changed.
+ */
+ void sortHiddenLastChanged(bool hiddenLast);
+
/** Is emitted if the additional information shown for this view has been changed. */
void visibleRolesChanged(const QList& current,
const QList& previous);
@@ -679,6 +688,12 @@ private Q_SLOTS:
*/
void updateSortFoldersFirst(bool foldersFirst);
+ /**
+ * Updates the view properties of the current URL to the
+ * sorting of hidden files given by \a hiddenLast.
+ */
+ void updateSortHiddenLast(bool hiddenLast);
+
/**
* Indicates in the status bar that the delete operation
* of the job \a job has been finished.
diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp
index c9bab5f82f793e5a66f508a5c3781756fcdbc769..90109605b65a1ae4b9abfb5e358927d4b66b4987 100644
--- a/src/views/dolphinviewactionhandler.cpp
+++ b/src/views/dolphinviewactionhandler.cpp
@@ -57,6 +57,8 @@ void DolphinViewActionHandler::setCurrentView(DolphinView* view)
this, &DolphinViewActionHandler::slotSortOrderChanged);
connect(view, &DolphinView::sortFoldersFirstChanged,
this, &DolphinViewActionHandler::slotSortFoldersFirstChanged);
+ connect(view, &DolphinView::sortHiddenLastChanged,
+ this, &DolphinViewActionHandler::slotSortHiddenLastChanged);
connect(view, &DolphinView::visibleRolesChanged,
this, &DolphinViewActionHandler::slotVisibleRolesChanged);
connect(view, &DolphinView::groupedSortingChanged,
@@ -253,6 +255,10 @@ void DolphinViewActionHandler::createActions()
sortFoldersFirst->setText(i18nc("@action:inmenu Sort", "Folders First"));
connect(sortFoldersFirst, &KToggleAction::triggered, this, &DolphinViewActionHandler::toggleSortFoldersFirst);
+ KToggleAction* sortHiddenLast = m_actionCollection->add(QStringLiteral("hidden_last"));
+ sortHiddenLast->setText(i18nc("@action:inmenu Sort", "Hidden Files Last"));
+ connect(sortHiddenLast, &KToggleAction::triggered, this, &DolphinViewActionHandler::toggleSortHiddenLast);
+
// View -> Sort By
QActionGroup* sortByActionGroup = createFileItemRolesActionGroup(QStringLiteral("sort_by_"));
@@ -287,6 +293,7 @@ void DolphinViewActionHandler::createActions()
sortByActionMenu->addAction(descendingAction);
sortByActionMenu->addSeparator();
sortByActionMenu->addAction(sortFoldersFirst);
+ sortByActionMenu->addAction(sortHiddenLast);
// View -> Additional Information
QActionGroup* visibleRolesGroup = createFileItemRolesActionGroup(QStringLiteral("show_"));
@@ -481,6 +488,7 @@ void DolphinViewActionHandler::updateViewActions()
slotSortOrderChanged(m_currentView->sortOrder());
slotSortFoldersFirstChanged(m_currentView->sortFoldersFirst());
+ slotSortHiddenLastChanged(m_currentView->sortHiddenLast());
slotVisibleRolesChanged(m_currentView->visibleRoles(), QList());
slotGroupedSortingChanged(m_currentView->groupedSorting());
slotSortRoleChanged(m_currentView->sortRole());
@@ -516,6 +524,12 @@ void DolphinViewActionHandler::toggleSortFoldersFirst()
m_currentView->setSortFoldersFirst(!sortFirst);
}
+void DolphinViewActionHandler::toggleSortHiddenLast()
+{
+ const bool sortHiddenLast = m_currentView->sortHiddenLast();
+ m_currentView->setSortHiddenLast(!sortHiddenLast);
+}
+
void DolphinViewActionHandler::slotSortOrderChanged(Qt::SortOrder order)
{
QAction* descending = m_actionCollection->action(QStringLiteral("descending"));
@@ -530,6 +544,11 @@ void DolphinViewActionHandler::slotSortFoldersFirstChanged(bool foldersFirst)
m_actionCollection->action(QStringLiteral("folders_first"))->setChecked(foldersFirst);
}
+void DolphinViewActionHandler::slotSortHiddenLastChanged(bool hiddenLast)
+{
+ m_actionCollection->action(QStringLiteral("hidden_last"))->setChecked(hiddenLast);
+}
+
void DolphinViewActionHandler::toggleVisibleRole(QAction* action)
{
Q_EMIT actionBeingHandled();
diff --git a/src/views/dolphinviewactionhandler.h b/src/views/dolphinviewactionhandler.h
index 3f73153ea66f9d6b15c1c4efd5769358f1ab936e..6e9b4a432bbd4f3399b7e4a53b41b8ec4cccf01a 100644
--- a/src/views/dolphinviewactionhandler.h
+++ b/src/views/dolphinviewactionhandler.h
@@ -136,6 +136,16 @@ private Q_SLOTS:
*/
void slotSortFoldersFirstChanged(bool foldersFirst);
+ /**
+ * Switches between showing hidden files last or not.
+ */
+ void toggleSortHiddenLast();
+
+ /**
+ * Updates the state of the 'Sort Hidden Last' action.
+ */
+ void slotSortHiddenLastChanged(bool hiddenLast);
+
/**
* Updates the state of the 'Sort by' actions.
*/
diff --git a/src/views/viewproperties.cpp b/src/views/viewproperties.cpp
index 1f73f3b33ba01d6aac0be7c075b247cb5d59762d..4b8d017c72e8a2125b163f33d3946de59b4dfa33 100644
--- a/src/views/viewproperties.cpp
+++ b/src/views/viewproperties.cpp
@@ -245,6 +245,19 @@ bool ViewProperties::sortFoldersFirst() const
return m_node->sortFoldersFirst();
}
+void ViewProperties::setSortHiddenLast(bool hiddenLast)
+{
+ if (m_node->sortHiddenLast() != hiddenLast) {
+ m_node->setSortHiddenLast(hiddenLast);
+ update();
+ }
+}
+
+bool ViewProperties::sortHiddenLast() const
+{
+ return m_node->sortHiddenLast();
+}
+
void ViewProperties::setVisibleRoles(const QList& roles)
{
if (roles == visibleRoles()) {
@@ -353,6 +366,7 @@ void ViewProperties::setDirProperties(const ViewProperties& props)
setSortRole(props.sortRole());
setSortOrder(props.sortOrder());
setSortFoldersFirst(props.sortFoldersFirst());
+ setSortHiddenLast(props.sortHiddenLast());
setVisibleRoles(props.visibleRoles());
setHeaderColumnWidths(props.headerColumnWidths());
m_node->setVersion(props.m_node->version());
diff --git a/src/views/viewproperties.h b/src/views/viewproperties.h
index a9daafc87ad1fc3eceea9a5ea0eeec5bee6ada5c..def8aa7381f7c2c7657ca1904576705b1a7ebb0b 100644
--- a/src/views/viewproperties.h
+++ b/src/views/viewproperties.h
@@ -62,6 +62,9 @@ public:
void setSortFoldersFirst(bool foldersFirst);
bool sortFoldersFirst() const;
+ void setSortHiddenLast(bool hiddenLast);
+ bool sortHiddenLast() const;
+
/**
* Sets the additional information for the current set view-mode.
* Note that the additional-info property is the only property where