diff options
| author | Felix Ernst <[email protected]> | 2021-09-12 15:33:39 +0200 |
|---|---|---|
| committer | Felix Ernst <[email protected]> | 2022-08-14 14:42:40 +0000 |
| commit | 3b7c05b385dc56fbc0b9ffdd332f8d30e7624d0c (patch) | |
| tree | a54c8338e3dc7d420fd2223bbcfb5af0a186348e /src/dolphinmainwindow.cpp | |
| parent | 9dbe48137748c6197363236b67f6302e20b72167 (diff) | |
Add Selection Mode
The selection mode action is a checkable toggle action named
"Select Files and Folders" which has "Space" as the default
shortcut.
In selection mode a bottom bar with contextual actions is shown.
These should mostly mirror the actions which are available through
the right-click context menu aka DolphinContextMenu.
Resizing of the window might make a overflow button appear in the
bottom selection mode bar.
This commit makes press and hold in the view activate selection
mode. This behaviour is not triggered if the press and hold is
used to either start a rubberband selection or a drag operation
within a short time. The length of the short timeframe is defined
by a QStyleHint. This is currently not implemented in touch
because I can't test it.
Mix the selection mode bars' background colors using a nice
combination of colors from the current color scheme
BUG: 427202
Diffstat (limited to 'src/dolphinmainwindow.cpp')
| -rw-r--r-- | src/dolphinmainwindow.cpp | 155 |
1 files changed, 125 insertions, 30 deletions
diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 39b820387..aea0d31ad 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -83,6 +83,8 @@ #include <QToolButton> #include <QWhatsThisClickedEvent> +#include <iostream> + namespace { // Used for GeneralSettings::version() to determine whether // an updated version of Dolphin is running, so as to migrate @@ -124,7 +126,7 @@ DolphinMainWindow::DolphinMainWindow() : setComponentName(QStringLiteral("dolphin"), QGuiApplication::applicationDisplayName()); setObjectName(QStringLiteral("Dolphin#")); - setStateConfigGroup("State"); + //setStateConfigGroup("State"); // TODO: Don't leave this as a comment. connect(&DolphinNewFileMenuObserver::instance(), &DolphinNewFileMenuObserver::errorMessage, this, &DolphinMainWindow::showErrorMessage); @@ -165,6 +167,7 @@ DolphinMainWindow::DolphinMainWindow() : m_actionHandler = new DolphinViewActionHandler(actionCollection(), this); connect(m_actionHandler, &DolphinViewActionHandler::actionBeingHandled, this, &DolphinMainWindow::clearStatusBar); connect(m_actionHandler, &DolphinViewActionHandler::createDirectoryTriggered, this, &DolphinMainWindow::createDirectory); + connect(m_actionHandler, &DolphinViewActionHandler::setSelectionMode, this, &DolphinMainWindow::slotSetSelectionMode); m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler); connect(this, &DolphinMainWindow::urlChanged, @@ -192,6 +195,7 @@ DolphinMainWindow::DolphinMainWindow() : auto hamburgerMenu = static_cast<KHamburgerMenu *>(actionCollection()->action( KStandardAction::name(KStandardAction::HamburgerMenu))); + hamburgerMenu->icon(); hamburgerMenu->setMenuBar(menuBar()); hamburgerMenu->setShowMenuBarAction(showMenuBarAction); connect(hamburgerMenu, &KHamburgerMenu::aboutToShowMenu, @@ -713,12 +717,22 @@ void DolphinMainWindow::undo() void DolphinMainWindow::cut() { - m_activeViewContainer->view()->cutSelectedItemsToClipboard(); + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::CutContents); + } else { + m_activeViewContainer->view()->cutSelectedItemsToClipboard(); + m_activeViewContainer->setSelectionModeEnabled(false); + } } void DolphinMainWindow::copy() { - m_activeViewContainer->view()->copySelectedItemsToClipboard(); + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::CopyContents); + } else { + m_activeViewContainer->view()->copySelectedItemsToClipboard(); + m_activeViewContainer->setSelectionModeEnabled(false); + } } void DolphinMainWindow::paste() @@ -845,6 +859,11 @@ void DolphinMainWindow::slotGoForward(QAction* action) } } +void DolphinMainWindow::slotSetSelectionMode(bool enabled, SelectionModeBottomBar::Contents bottomBarContents) +{ + m_activeViewContainer->setSelectionModeEnabled(enabled, actionCollection(), bottomBarContents); +} + void DolphinMainWindow::selectAll() { clearStatusBar(); @@ -884,6 +903,26 @@ void DolphinMainWindow::toggleSplitStash() tabPage->setSplitViewEnabled(true, WithAnimation, QUrl("stash:/")); } +void DolphinMainWindow::copyToInactiveSplitView() +{ + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::CopyToOtherViewContents); + } else { + m_tabWidget->copyToInactiveSplitView(); + m_activeViewContainer->setSelectionModeEnabled(false); + } +} + +void DolphinMainWindow::moveToInactiveSplitView() +{ + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::MoveToOtherViewContents); + } else { + m_tabWidget->moveToInactiveSplitView(); + m_activeViewContainer->setSelectionModeEnabled(false); + } +} + void DolphinMainWindow::reloadView() { clearStatusBar(); @@ -906,6 +945,14 @@ void DolphinMainWindow::disableStopAction() actionCollection()->action(QStringLiteral("stop"))->setEnabled(false); } +void DolphinMainWindow::toggleSelectionMode() +{ + const bool checked = !m_activeViewContainer->isSelectionModeEnabled(); + + m_activeViewContainer->setSelectionModeEnabled(checked, actionCollection(), SelectionModeBottomBar::Contents::GeneralContents); + actionCollection()->action(QStringLiteral("toggle_selection_mode"))->setChecked(checked); +} + void DolphinMainWindow::showFilterBar() { m_activeViewContainer->setFilterBarVisible(true); @@ -1283,6 +1330,11 @@ void DolphinMainWindow::updateHamburgerMenu() menu->addAction(ac->action(QStringLiteral("go_forward"))); menu->addMenu(m_newFileMenu->menu()); + if (!toolBar()->isVisible() + || !toolbarActions.contains(ac->action(QStringLiteral("toggle_selection_mode_with_popup"))) + ) { + menu->addAction(ac->action(QStringLiteral("toggle_selection_mode"))); + } menu->addAction(ac->action(QStringLiteral("basic_actions"))); menu->addAction(ac->action(KStandardAction::name(KStandardAction::Undo))); if (!toolBar()->isVisible() @@ -1562,7 +1614,7 @@ void DolphinMainWindow::setupActions() copyToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); copyToOtherViewAction->setIconText(i18nc("@action:inmenu Edit", "Copy to Inactive Split View")); actionCollection()->setDefaultShortcut(copyToOtherViewAction, Qt::SHIFT | Qt::Key_F5 ); - connect(copyToOtherViewAction, &QAction::triggered, m_tabWidget, &DolphinTabWidget::copyToInactiveSplitView); + connect(copyToOtherViewAction, &QAction::triggered, this, &DolphinMainWindow::copyToInactiveSplitView); QAction* moveToOtherViewAction = actionCollection()->addAction(QStringLiteral("move_to_inactive_split_view")); moveToOtherViewAction->setText(i18nc("@action:inmenu", "Move to Inactive Split View")); @@ -1571,7 +1623,7 @@ void DolphinMainWindow::setupActions() moveToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-cut"))); moveToOtherViewAction->setIconText(i18nc("@action:inmenu Edit", "Move to Inactive Split View")); actionCollection()->setDefaultShortcut(moveToOtherViewAction, Qt::SHIFT | Qt::Key_F6 ); - connect(moveToOtherViewAction, &QAction::triggered, m_tabWidget, &DolphinTabWidget::moveToInactiveSplitView); + connect(moveToOtherViewAction, &QAction::triggered, this, &DolphinMainWindow::moveToInactiveSplitView); QAction* showFilterBar = actionCollection()->addAction(QStringLiteral("show_filter_bar")); showFilterBar->setText(i18nc("@action:inmenu Tools", "Filter...")); @@ -1617,6 +1669,33 @@ void DolphinMainWindow::setupActions() toggleSearchAction->setWhatsThis(searchAction->whatsThis()); toggleSearchAction->setCheckable(true); + QAction *toggleSelectionModeAction = actionCollection()->addAction(QStringLiteral("toggle_selection_mode")); + // i18n: This action toggles a selection mode. + toggleSelectionModeAction->setText(i18nc("@action:inmenu", "Select Files and Folders")); + // i18n: Opens a selection mode for selecting files/folders and later selecting an action that acts on them. + // So in a way "Select" here is used to mean both "Select files" and also "Select what to do" but mostly the first. + // The text is kept so unspecific because it will be shown on the toolbar where space is at a premium. + toggleSelectionModeAction->setIconText(i18nc("@action:intoolbar", "Select")); + toggleSelectionModeAction->setWhatsThis(xi18nc("@info:whatsthis", "<para>This application doesn't know which files or folders should be acted on, " + "unless they are <emphasis>selected</emphasis> first. Press this to toggle the <emphasis>Selection Mode</emphasis> which makes selecting and deselecting as " + "easy as pressing an item once.</para><para>While in this mode, a quick access bar at the bottom shows all the available actions for the current " + "selection of items.</para>")); + toggleSelectionModeAction->setIcon(QIcon::fromTheme(QStringLiteral("quickwizard"))); + toggleSelectionModeAction->setCheckable(true); + actionCollection()->setDefaultShortcut(toggleSelectionModeAction, Qt::Key_Space ); + connect(toggleSelectionModeAction, &QAction::triggered, this, &DolphinMainWindow::toggleSelectionMode); + + // A special version of the toggleSelectionModeAction for the toolbar that also contains a menu + // with the selectAllAction and invertSelectionAction. + auto *toggleSelectionModeToolBarAction = new KToolBarPopupAction(toggleSelectionModeAction->icon(), toggleSelectionModeAction->iconText(), actionCollection()); + toggleSelectionModeToolBarAction->setToolTip(toggleSelectionModeAction->text()); + toggleSelectionModeToolBarAction->setWhatsThis(toggleSelectionModeAction->whatsThis()); + actionCollection()->addAction(QStringLiteral("toggle_selection_mode_with_popup"), toggleSelectionModeToolBarAction); + toggleSelectionModeToolBarAction->setCheckable(true); + toggleSelectionModeToolBarAction->setPopupMode(QToolButton::DelayedPopup); + connect(toggleSelectionModeToolBarAction, &QAction::triggered, toggleSelectionModeAction, &QAction::trigger); + connect(toggleSelectionModeAction, &QAction::toggled, toggleSelectionModeToolBarAction, &QAction::setChecked); + QAction* selectAllAction = KStandardAction::selectAll(this, &DolphinMainWindow::selectAll, actionCollection()); selectAllAction->setWhatsThis(xi18nc("@info:whatsthis", "This selects all " "files and folders in the current location.")); @@ -1629,6 +1708,11 @@ void DolphinMainWindow::setupActions() actionCollection()->setDefaultShortcut(invertSelection, Qt::CTRL | Qt::SHIFT | Qt::Key_A); connect(invertSelection, &QAction::triggered, this, &DolphinMainWindow::invertSelection); + QMenu *toggleSelectionModeActionMenu = new QMenu(this); + toggleSelectionModeActionMenu->addAction(selectAllAction); + toggleSelectionModeActionMenu->addAction(invertSelection); + toggleSelectionModeToolBarAction->setMenu(toggleSelectionModeActionMenu); + // setup 'View' menu // (note that most of it is set up in DolphinViewActionHandler) @@ -2143,6 +2227,11 @@ void DolphinMainWindow::updateFileAndEditActions() const KActionCollection* col = actionCollection(); KFileItemListProperties capabilitiesSource(list); + QAction* renameAction = col->action(KStandardAction::name(KStandardAction::RenameFile)); + QAction* moveToTrashAction = col->action(KStandardAction::name(KStandardAction::MoveToTrash)); + QAction* deleteAction = col->action(KStandardAction::name(KStandardAction::DeleteFile)); + QAction* cutAction = col->action(KStandardAction::name(KStandardAction::Cut)); + QAction* duplicateAction = col->action(QStringLiteral("duplicate")); // see DolphinViewActionHandler QAction* addToPlacesAction = col->action(QStringLiteral("add_to_places")); QAction* copyToOtherViewAction = col->action(QStringLiteral("copy_to_inactive_split_view")); QAction* moveToOtherViewAction = col->action(QStringLiteral("move_to_inactive_split_view")); @@ -2151,20 +2240,19 @@ void DolphinMainWindow::updateFileAndEditActions() if (list.isEmpty()) { stateChanged(QStringLiteral("has_no_selection")); + // All actions that need a selection to function can be enabled because they should trigger selection mode. + renameAction->setEnabled(true); + moveToTrashAction->setEnabled(true); + deleteAction->setEnabled(true); + cutAction->setEnabled(true); + duplicateAction->setEnabled(true); addToPlacesAction->setEnabled(true); - copyToOtherViewAction->setEnabled(false); - moveToOtherViewAction->setEnabled(false); - copyLocation->setEnabled(false); + copyLocation->setEnabled(true); } else { stateChanged(QStringLiteral("has_selection")); - QAction* renameAction = col->action(KStandardAction::name(KStandardAction::RenameFile)); - QAction* moveToTrashAction = col->action(KStandardAction::name(KStandardAction::MoveToTrash)); - QAction* deleteAction = col->action(KStandardAction::name(KStandardAction::DeleteFile)); - QAction* cutAction = col->action(KStandardAction::name(KStandardAction::Cut)); QAction* deleteWithTrashShortcut = col->action(QStringLiteral("delete_shortcut")); // see DolphinViewActionHandler QAction* showTarget = col->action(QStringLiteral("show_target")); - QAction* duplicateAction = col->action(QStringLiteral("duplicate")); // see DolphinViewActionHandler if (list.length() == 1 && list.first().isDir()) { addToPlacesAction->setEnabled(true); @@ -2172,23 +2260,6 @@ void DolphinMainWindow::updateFileAndEditActions() addToPlacesAction->setEnabled(false); } - if (m_tabWidget->currentTabPage()->splitViewEnabled()) { - DolphinTabPage* tabPage = m_tabWidget->currentTabPage(); - KFileItem capabilitiesDestination; - - if (tabPage->primaryViewActive()) { - capabilitiesDestination = tabPage->secondaryViewContainer()->url(); - } else { - capabilitiesDestination = tabPage->primaryViewContainer()->url(); - } - - copyToOtherViewAction->setEnabled(capabilitiesDestination.isWritable()); - moveToOtherViewAction->setEnabled(capabilitiesSource.supportsMoving() && capabilitiesDestination.isWritable()); - } else { - copyToOtherViewAction->setEnabled(false); - moveToOtherViewAction->setEnabled(false); - } - const bool enableMoveToTrash = capabilitiesSource.isLocal() && capabilitiesSource.supportsMoving(); renameAction->setEnabled(capabilitiesSource.supportsMoving()); @@ -2200,12 +2271,36 @@ void DolphinMainWindow::updateFileAndEditActions() showTarget->setEnabled(list.length() == 1 && list.at(0).isLink()); duplicateAction->setEnabled(capabilitiesSource.supportsWriting()); } + + if (m_tabWidget->currentTabPage()->splitViewEnabled()) { + DolphinTabPage* tabPage = m_tabWidget->currentTabPage(); + KFileItem capabilitiesDestination; + + if (tabPage->primaryViewActive()) { + capabilitiesDestination = tabPage->secondaryViewContainer()->url(); + } else { + capabilitiesDestination = tabPage->primaryViewContainer()->url(); + } + + copyToOtherViewAction->setEnabled(capabilitiesDestination.isWritable()); + moveToOtherViewAction->setEnabled((list.isEmpty() || capabilitiesSource.supportsMoving()) && capabilitiesDestination.isWritable()); + } else { + copyToOtherViewAction->setEnabled(false); + moveToOtherViewAction->setEnabled(false); + } } void DolphinMainWindow::updateViewActions() { m_actionHandler->updateViewActions(); + QAction *toggleSelectionModeAction = actionCollection()->action(QStringLiteral("toggle_selection_mode")); + disconnect(nullptr, &DolphinViewContainer::selectionModeChanged, + toggleSelectionModeAction, &QAction::setChecked); + toggleSelectionModeAction->setChecked(m_activeViewContainer->isSelectionModeEnabled()); + connect(m_activeViewContainer, &DolphinViewContainer::selectionModeChanged, + toggleSelectionModeAction, &QAction::setChecked); + QAction* toggleFilterBarAction = actionCollection()->action(QStringLiteral("toggle_filter")); toggleFilterBarAction->setChecked(m_activeViewContainer->isFilterBarVisible()); |
