X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/f510339f033658eae27f8400bf042b78b36f82f2..91273c8b03dbf184d7a9043d4f5ffe5b45c87b71:/src/views/dolphinviewactionhandler.cpp diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp index 4408a9e47..c215f1bf7 100644 --- a/src/views/dolphinviewactionhandler.cpp +++ b/src/views/dolphinviewactionhandler.cpp @@ -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,8 +59,11 @@ 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()); connect(view, &DolphinView::selectionModeChangeRequested, this, [this](bool enabled) { Q_EMIT selectionModeChangeTriggered(enabled); }); @@ -89,7 +93,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac renameAction->setWhatsThis(xi18nc("@info:whatsthis", "This renames the " "items in your current selection.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(); @@ -101,8 +105,8 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac trashAction->setWhatsThis(xi18nc("@info:whatsthis", "This moves the " "items in your current selection to the Trash" - ".The trash is a temporary storage where " - "items can be deleted from if disk space is needed.")); + ".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(); @@ -113,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 @@ -198,7 +202,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac compactAction->setWhatsThis(xi18nc("@info:whatsthis Compact view mode", "This switches to a compact view mode that lists the folders " "and files in columns with the names beside the icons." - "This helps to keep the overview in folders with many items.")); + "This helps to give you an overview in folders with many items.")); detailsAction->setWhatsThis(xi18nc("@info:whatsthis Details view mode", "This switches to a list view mode that focuses on folder " "and file details.Click on a detail in the column " @@ -206,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.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.")); + "location by clicking the region to the left of it. This way you can " + "view the contents of multiple folders in the same list.")); KSelectAction *viewModeActions = m_actionCollection->add(QStringLiteral("view_mode")); viewModeActions->setText(i18nc("@action:intoolbar", "View Mode")); @@ -248,6 +252,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac "contents.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(QStringLiteral("folders_first")); @@ -273,27 +278,72 @@ 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(QStringLiteral("ascending")); - ascendingAction->setActionGroup(group); - connect(ascendingAction, &QAction::triggered, this, [this] { + KToggleAction *sortAscendingAction = m_actionCollection->add(QStringLiteral("sort_ascending")); + sortAscendingAction->setActionGroup(groupForSort); + connect(sortAscendingAction, &QAction::triggered, this, [this] { m_currentView->setSortOrder(Qt::AscendingOrder); }); - KToggleAction *descendingAction = m_actionCollection->add(QStringLiteral("descending")); - descendingAction->setActionGroup(group); - connect(descendingAction, &QAction::triggered, this, [this] { + KToggleAction *sortDescendingAction = m_actionCollection->add(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_")); + + KToggleAction *groupAsNone = m_actionCollection->add(QStringLiteral("group_none")); + groupAsNone->setData("none"); + groupAsNone->setActionGroup(groupByActionGroup); + groupAsNone->setText(i18nc("@label", "No grouping")); + m_groupByActions.insert("none", groupAsNone); + + KToggleAction *groupAsFollowSort = m_actionCollection->add(QStringLiteral("group_followSort")); + groupAsFollowSort->setData("followSort"); + groupAsFollowSort->setActionGroup(groupByActionGroup); + groupAsFollowSort->setText(i18nc("@label", "Follow sorting")); + m_groupByActions.insert("followSort", groupAsFollowSort); + + KActionMenu *groupByActionMenu = m_actionCollection->add(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(QStringLiteral("group_ascending")); + groupAscendingAction->setActionGroup(groupForGroup); + connect(groupAscendingAction, &QAction::triggered, this, [this] { + m_currentView->setGroupOrder(Qt::AscendingOrder); + }); + + KToggleAction *groupDescendingAction = m_actionCollection->add(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_")); @@ -318,11 +368,15 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac showHiddenFiles->setText(i18nc("@action:inmenu View", "Show Hidden Files")); showHiddenFiles->setWhatsThis(xi18nc("@info:whatsthis", "When " - "this is enabled hidden files and folders " + "this is enabled, hidden files and folders " "are visible. They will be displayed semi-transparent." - "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.")); + "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." + "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.")); m_actionCollection->setDefaultShortcuts(showHiddenFiles, KStandardShortcut::showHideHiddenFiles()); connect(showHiddenFiles, &KToggleAction::triggered, this, &DolphinViewActionHandler::toggleShowHiddenFiles); @@ -338,12 +392,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); } @@ -358,9 +415,10 @@ QActionGroup *DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt indexingEnabled = config.fileIndexingEnabled(); #endif - const QList rolesInfo = KFileItemModel::rolesInformation(); + QList rolesInfo = KFileItemModel::rolesInformation(); + 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; } @@ -378,9 +436,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); } @@ -398,6 +458,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); } @@ -502,6 +564,8 @@ void DolphinViewActionHandler::updateViewActions() slotVisibleRolesChanged(m_currentView->visibleRoles(), QList()); 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 @@ -542,13 +606,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); @@ -668,8 +741,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")); @@ -691,6 +764,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) @@ -714,7 +822,7 @@ void DolphinViewActionHandler::slotSortTriggered(QAction *action) // 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 : qAsConst(m_sortByActions)) { + for (QAction *groupAction : std::as_const(m_sortByActions)) { KActionMenu *actionMenu = qobject_cast(groupAction); if (actionMenu) { const auto actions = actionMenu->menu()->actions(); @@ -732,6 +840,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(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();