]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/views/dolphinviewactionhandler.cpp
Reverted resortAllItems() in favor of a group comparator for lessThan. Minor bug...
[dolphin.git] / src / views / dolphinviewactionhandler.cpp
index 98cbbdf80092c2612638800a3b0c1eb6c52ea365..7454ed0b947f2979483d052da5a7a4a122c1ae08 100644 (file)
@@ -33,6 +33,7 @@ DolphinViewActionHandler::DolphinViewActionHandler(KActionCollection *collection
     , m_actionCollection(collection)
     , m_currentView(nullptr)
     , m_sortByActions()
+    , m_groupByActions()
     , m_visibleRoles()
 {
     Q_ASSERT(m_actionCollection);
@@ -58,6 +59,8 @@ void DolphinViewActionHandler::setCurrentView(DolphinView *view)
     connect(view, &DolphinView::groupedSortingChanged, this, &DolphinViewActionHandler::slotGroupedSortingChanged);
     connect(view, &DolphinView::hiddenFilesShownChanged, this, &DolphinViewActionHandler::slotHiddenFilesShownChanged);
     connect(view, &DolphinView::sortRoleChanged, this, &DolphinViewActionHandler::slotSortRoleChanged);
+    connect(view, &DolphinView::groupRoleChanged, this, &DolphinViewActionHandler::slotGroupRoleChanged);
+    connect(view, &DolphinView::groupOrderChanged, this, &DolphinViewActionHandler::slotGroupOrderChanged);
     connect(view, &DolphinView::zoomLevelChanged, this, &DolphinViewActionHandler::slotZoomLevelChanged);
     connect(view, &DolphinView::writeStateChanged, this, &DolphinViewActionHandler::slotWriteStateChanged);
     slotWriteStateChanged(view->isFolderWritable());
@@ -90,7 +93,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
     renameAction->setWhatsThis(xi18nc("@info:whatsthis",
                                       "This renames the "
                                       "items in your current selection.<nl/>Renaming multiple items "
-                                      "at once amounts to their new names differing only in a number."));
+                                      "at once results in their new names differing only in a number."));
 
     auto trashAction = KStandardAction::moveToTrash(this, &DolphinViewActionHandler::slotTrashActivated, m_actionCollection);
     auto trashShortcuts = trashAction->shortcuts();
@@ -102,8 +105,8 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
     trashAction->setWhatsThis(xi18nc("@info:whatsthis",
                                      "This moves the "
                                      "items in your current selection to the <filename>Trash"
-                                     "</filename>.<nl/>The trash is a temporary storage where "
-                                     "items can be deleted from if disk space is needed."));
+                                     "</filename>.<nl/>The trash is a temporary storage location where "
+                                     "items can be deleted later if disk space is needed."));
 
     auto deleteAction = KStandardAction::deleteFile(this, &DolphinViewActionHandler::slotDeleteItems, m_actionCollection);
     auto deleteShortcuts = deleteAction->shortcuts();
@@ -114,8 +117,8 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
     }
     deleteAction->setWhatsThis(xi18nc("@info:whatsthis",
                                       "This deletes "
-                                      "the items in your current selection completely. They can "
-                                      "not be recovered by normal means."));
+                                      "the items in your current selection permanently. They "
+                                      "cannot be recovered by normal means."));
 
     // This action is useful for being enabled when KStandardAction::MoveToTrash should be
     // disabled and KStandardAction::DeleteFile is enabled (e.g. non-local files), so that Key_Del
@@ -199,7 +202,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
     compactAction->setWhatsThis(xi18nc("@info:whatsthis Compact view mode",
                                        "<para>This switches to a compact view mode that lists the folders "
                                        "and files in columns with the names beside the icons.</para><para>"
-                                       "This helps to keep the overview in folders with many items.</para>"));
+                                       "This helps to give you an overview in folders with many items.</para>"));
     detailsAction->setWhatsThis(xi18nc("@info:whatsthis Details view mode",
                                        "<para>This switches to a list view mode that focuses on folder "
                                        "and file details.</para><para>Click on a detail in the column "
@@ -207,8 +210,8 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
                                        "way around. To select which details should be displayed click "
                                        "the header with the right mouse button.</para><para>You can "
                                        "view the contents of a folder without leaving the current "
-                                       "location by clicking to the left of it. This way you can view "
-                                       "the contents of multiple folders in the same list.</para>"));
+                                       "location by clicking the region to the left of it. This way you can "
+                                       "view the contents of multiple folders in the same list.</para>"));
 
     KSelectAction *viewModeActions = m_actionCollection->add<KSelectAction>(QStringLiteral("view_mode"));
     viewModeActions->setText(i18nc("@action:intoolbar", "View Mode"));
@@ -249,6 +252,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
                                      "contents.<nl/>For example the icons of images become scaled "
                                      "down versions of the images."));
     showPreview->setIcon(QIcon::fromTheme(QStringLiteral("view-preview")));
+    m_actionCollection->setDefaultShortcut(showPreview, QKeySequence(Qt::Key_F12));
     connect(showPreview, &KToggleAction::triggered, this, &DolphinViewActionHandler::togglePreview);
 
     KToggleAction *sortFoldersFirst = m_actionCollection->add<KToggleAction>(QStringLiteral("folders_first"));
@@ -274,27 +278,60 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
 
     sortByActionMenu->addSeparator();
 
-    QActionGroup *group = new QActionGroup(sortByActionMenu);
-    group->setExclusive(true);
+    QActionGroup *groupForSort = new QActionGroup(sortByActionMenu);
+    groupForSort->setExclusive(true);
 
-    KToggleAction *ascendingAction = m_actionCollection->add<KToggleAction>(QStringLiteral("ascending"));
-    ascendingAction->setActionGroup(group);
-    connect(ascendingAction, &QAction::triggered, this, [this] {
+    KToggleAction *sortAscendingAction = m_actionCollection->add<KToggleAction>(QStringLiteral("sort_ascending"));
+    sortAscendingAction->setActionGroup(groupForSort);
+    connect(sortAscendingAction, &QAction::triggered, this, [this] {
         m_currentView->setSortOrder(Qt::AscendingOrder);
     });
 
-    KToggleAction *descendingAction = m_actionCollection->add<KToggleAction>(QStringLiteral("descending"));
-    descendingAction->setActionGroup(group);
-    connect(descendingAction, &QAction::triggered, this, [this] {
+    KToggleAction *sortDescendingAction = m_actionCollection->add<KToggleAction>(QStringLiteral("sort_descending"));
+    sortDescendingAction->setActionGroup(groupForSort);
+    connect(sortDescendingAction, &QAction::triggered, this, [this] {
         m_currentView->setSortOrder(Qt::DescendingOrder);
     });
 
-    sortByActionMenu->addAction(ascendingAction);
-    sortByActionMenu->addAction(descendingAction);
+    sortByActionMenu->addAction(sortAscendingAction);
+    sortByActionMenu->addAction(sortDescendingAction);
     sortByActionMenu->addSeparator();
     sortByActionMenu->addAction(sortFoldersFirst);
     sortByActionMenu->addAction(sortHiddenLast);
 
+    // View -> Group By
+    QActionGroup *groupByActionGroup = createFileItemRolesActionGroup(QStringLiteral("group_by_"));
+
+    KActionMenu *groupByActionMenu = m_actionCollection->add<KActionMenu>(QStringLiteral("group"));
+    groupByActionMenu->setIcon(QIcon::fromTheme(QStringLiteral("view-group")));
+    groupByActionMenu->setText(i18nc("@action:inmenu View", "Group By"));
+    groupByActionMenu->setPopupMode(QToolButton::InstantPopup);
+
+    const auto groupByActionGroupActions = groupByActionGroup->actions();
+    for (QAction *action : groupByActionGroupActions) {
+        groupByActionMenu->addAction(action);
+    }
+
+    groupByActionMenu->addSeparator();
+
+    QActionGroup *groupForGroup = new QActionGroup(groupByActionMenu);
+    groupForGroup->setExclusive(true);
+
+    KToggleAction *groupAscendingAction = m_actionCollection->add<KToggleAction>(QStringLiteral("group_ascending"));
+    groupAscendingAction->setActionGroup(groupForGroup);
+    connect(groupAscendingAction, &QAction::triggered, this, [this] {
+        m_currentView->setGroupOrder(Qt::AscendingOrder);
+    });
+
+    KToggleAction *groupDescendingAction = m_actionCollection->add<KToggleAction>(QStringLiteral("group_descending"));
+    groupDescendingAction->setActionGroup(groupForGroup);
+    connect(groupDescendingAction, &QAction::triggered, this, [this] {
+        m_currentView->setGroupOrder(Qt::DescendingOrder);
+    });
+
+    groupByActionMenu->addAction(groupAscendingAction);
+    groupByActionMenu->addAction(groupDescendingAction);
+
     // View -> Additional Information
     QActionGroup *visibleRolesGroup = createFileItemRolesActionGroup(QStringLiteral("show_"));
 
@@ -319,11 +356,15 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
     showHiddenFiles->setText(i18nc("@action:inmenu View", "Show Hidden Files"));
     showHiddenFiles->setWhatsThis(xi18nc("@info:whatsthis",
                                          "<para>When "
-                                         "this is enabled <emphasis>hidden</emphasis> files and folders "
+                                         "this is enabled, <emphasis>hidden</emphasis> files and folders "
                                          "are visible. They will be displayed semi-transparent.</para>"
-                                         "<para>Hidden items only differ from other ones in that their "
-                                         "name starts with a \".\". In general there is no need for "
-                                         "users to access them which is why they are hidden.</para>"));
+                                         "<para>Hidden items only differ from normal ones in that their "
+                                         "name starts with a dot (\".\"). Typically, there is no need for "
+                                         "users to access them, which is why they are hidden.</para>"
+                                         "<para>Items can also be hidden if their names are listed in a text file "
+                                         "named \".hidden\". Files with the \"application/x-trash\" MIME type, "
+                                         "such as backup files, can also be hidden by enabling that setting in "
+                                         "Configure Dolphin > View > General.</para>"));
     m_actionCollection->setDefaultShortcuts(showHiddenFiles, KStandardShortcut::showHideHiddenFiles());
     connect(showHiddenFiles, &KToggleAction::triggered, this, &DolphinViewActionHandler::toggleShowHiddenFiles);
 
@@ -339,12 +380,15 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
 QActionGroup *DolphinViewActionHandler::createFileItemRolesActionGroup(const QString &groupPrefix)
 {
     const bool isSortGroup = (groupPrefix == QLatin1String("sort_by_"));
-    Q_ASSERT(isSortGroup || groupPrefix == QLatin1String("show_"));
+    const bool isGroupGroup = (groupPrefix == QLatin1String("group_by_"));
+    Q_ASSERT(isSortGroup || isGroupGroup || groupPrefix == QLatin1String("show_"));
 
     QActionGroup *rolesActionGroup = new QActionGroup(m_actionCollection);
-    rolesActionGroup->setExclusive(isSortGroup);
+    rolesActionGroup->setExclusive(isSortGroup || isGroupGroup);
     if (isSortGroup) {
         connect(rolesActionGroup, &QActionGroup::triggered, this, &DolphinViewActionHandler::slotSortTriggered);
+    } else if (isGroupGroup) {
+        connect(rolesActionGroup, &QActionGroup::triggered, this, &DolphinViewActionHandler::slotGroupTriggered);
     } else {
         connect(rolesActionGroup, &QActionGroup::triggered, this, &DolphinViewActionHandler::toggleVisibleRole);
     }
@@ -359,9 +403,13 @@ QActionGroup *DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt
     indexingEnabled = config.fileIndexingEnabled();
 #endif
 
-    const QList<KFileItemModel::RoleInfo> rolesInfo = KFileItemModel::rolesInformation();
+    QList<KFileItemModel::RoleInfo> rolesInfo = KFileItemModel::rolesInformation();
+    // Unlike sorting, grouping is optional. If creating for group_by_, include a None role.
+    if (isGroupGroup)
+        rolesInfo.append(KFileItemModel::roleInformation(nullptr));
+
     for (const KFileItemModel::RoleInfo &info : rolesInfo) {
-        if (!isSortGroup && info.role == "text") {
+        if (!isSortGroup && !isGroupGroup && info.role == "text") {
             // It should not be possible to hide the "text" role
             continue;
         }
@@ -379,9 +427,11 @@ QActionGroup *DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt
                 groupMenu->setActionGroup(rolesActionGroup);
 
                 groupMenuGroup = new QActionGroup(groupMenu);
-                groupMenuGroup->setExclusive(isSortGroup);
+                groupMenuGroup->setExclusive(isSortGroup || isGroupGroup);
                 if (isSortGroup) {
                     connect(groupMenuGroup, &QActionGroup::triggered, this, &DolphinViewActionHandler::slotSortTriggered);
+                } else if (isGroupGroup) {
+                    connect(groupMenuGroup, &QActionGroup::triggered, this, &DolphinViewActionHandler::slotGroupTriggered);
                 } else {
                     connect(groupMenuGroup, &QActionGroup::triggered, this, &DolphinViewActionHandler::toggleVisibleRole);
                 }
@@ -399,6 +449,8 @@ QActionGroup *DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt
 
         if (isSortGroup) {
             m_sortByActions.insert(info.role, action);
+        } else if (isGroupGroup) {
+            m_groupByActions.insert(info.role, action);
         } else {
             m_visibleRoles.insert(info.role, action);
         }
@@ -503,6 +555,8 @@ void DolphinViewActionHandler::updateViewActions()
     slotVisibleRolesChanged(m_currentView->visibleRoles(), QList<QByteArray>());
     slotGroupedSortingChanged(m_currentView->groupedSorting());
     slotSortRoleChanged(m_currentView->sortRole());
+    slotGroupRoleChanged(m_currentView->groupRole());
+    slotGroupOrderChanged(m_currentView->groupOrder());
     slotZoomLevelChanged(m_currentView->zoomLevel(), -1);
 
     // Updates the "show_hidden_files" action state and icon
@@ -543,13 +597,22 @@ void DolphinViewActionHandler::toggleSortHiddenLast()
 
 void DolphinViewActionHandler::slotSortOrderChanged(Qt::SortOrder order)
 {
-    QAction *descending = m_actionCollection->action(QStringLiteral("descending"));
-    QAction *ascending = m_actionCollection->action(QStringLiteral("ascending"));
+    QAction *descending = m_actionCollection->action(QStringLiteral("sort_descending"));
+    QAction *ascending = m_actionCollection->action(QStringLiteral("sort_ascending"));
     const bool sortDescending = (order == Qt::DescendingOrder);
     descending->setChecked(sortDescending);
     ascending->setChecked(!sortDescending);
 }
 
+void DolphinViewActionHandler::slotGroupOrderChanged(Qt::SortOrder order)
+{
+    QAction *descending = m_actionCollection->action(QStringLiteral("group_descending"));
+    QAction *ascending = m_actionCollection->action(QStringLiteral("group_ascending"));
+    const bool groupDescending = (order == Qt::DescendingOrder);
+    descending->setChecked(groupDescending);
+    ascending->setChecked(!groupDescending);
+}
+
 void DolphinViewActionHandler::slotSortFoldersFirstChanged(bool foldersFirst)
 {
     m_actionCollection->action(QStringLiteral("folders_first"))->setChecked(foldersFirst);
@@ -669,8 +732,8 @@ void DolphinViewActionHandler::slotSortRoleChanged(const QByteArray &role)
         }
     }
 
-    QAction *descending = m_actionCollection->action(QStringLiteral("descending"));
-    QAction *ascending = m_actionCollection->action(QStringLiteral("ascending"));
+    QAction *descending = m_actionCollection->action(QStringLiteral("sort_descending"));
+    QAction *ascending = m_actionCollection->action(QStringLiteral("sort_ascending"));
 
     if (role == "text" || role == "type" || role == "extension" || role == "tags" || role == "comment") {
         descending->setText(i18nc("Sort descending", "Z-A"));
@@ -692,6 +755,41 @@ void DolphinViewActionHandler::slotSortRoleChanged(const QByteArray &role)
     slotSortOrderChanged(m_currentView->sortOrder());
 }
 
+void DolphinViewActionHandler::slotGroupRoleChanged(const QByteArray &role)
+{
+    KToggleAction *action = m_groupByActions.value(role);
+    if (action) {
+        action->setChecked(true);
+
+        if (!action->icon().isNull()) {
+            QAction *groupByMenu = m_actionCollection->action(QStringLiteral("group"));
+            groupByMenu->setIcon(action->icon());
+        }
+    }
+
+    QAction *descending = m_actionCollection->action(QStringLiteral("group_descending"));
+    QAction *ascending = m_actionCollection->action(QStringLiteral("group_ascending"));
+
+    if (role == "text" || role == "type" || role == "extension" || role == "tags" || role == "comment") {
+        descending->setText(i18nc("Group descending", "Z-A"));
+        ascending->setText(i18nc("Group ascending", "A-Z"));
+    } else if (role == "size") {
+        descending->setText(i18nc("Group descending", "Largest First"));
+        ascending->setText(i18nc("Group ascending", "Smallest First"));
+    } else if (role == "modificationtime" || role == "creationtime" || role == "accesstime") {
+        descending->setText(i18nc("Group descending", "Newest First"));
+        ascending->setText(i18nc("Group ascending", "Oldest First"));
+    } else if (role == "rating") {
+        descending->setText(i18nc("Group descending", "Highest First"));
+        ascending->setText(i18nc("Group ascending", "Lowest First"));
+    } else {
+        descending->setText(i18nc("Group descending", "Descending"));
+        ascending->setText(i18nc("Group ascending", "Ascending"));
+    }
+
+    slotGroupOrderChanged(m_currentView->groupOrder());
+}
+
 void DolphinViewActionHandler::slotZoomLevelChanged(int current, int previous)
 {
     Q_UNUSED(previous)
@@ -733,6 +831,32 @@ void DolphinViewActionHandler::slotSortTriggered(QAction *action)
     m_currentView->setSortRole(role);
 }
 
+void DolphinViewActionHandler::slotGroupTriggered(QAction *action)
+{
+    // The radiobuttons of the "Group By"-menu are split between the main-menu
+    // and several sub-menus. Because of this they don't have a common
+    // action-group that assures an exclusive toggle-state between the main-menu
+    // actions and the sub-menu-actions. If an action gets checked, it must
+    // be assured that all other actions get unchecked, except the ascending/
+    // descending actions
+    for (QAction *groupAction : std::as_const(m_groupByActions)) {
+        KActionMenu *actionMenu = qobject_cast<KActionMenu *>(groupAction);
+        if (actionMenu) {
+            const auto actions = actionMenu->menu()->actions();
+            for (QAction *subAction : actions) {
+                subAction->setChecked(false);
+            }
+        } else if (groupAction->actionGroup()) {
+            groupAction->setChecked(false);
+        }
+    }
+    action->setChecked(true);
+
+    // Apply the activated sort-role to the view
+    const QByteArray role = action->data().toByteArray();
+    m_currentView->setGroupRole(role);
+}
+
 void DolphinViewActionHandler::slotAdjustViewProperties()
 {
     Q_EMIT actionBeingHandled();