┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/dolphinmainwindow.cpp
diff options
context:
space:
mode:
authorFelix Ernst <[email protected]>2021-09-12 15:33:39 +0200
committerFelix Ernst <[email protected]>2022-08-14 14:42:40 +0000
commit3b7c05b385dc56fbc0b9ffdd332f8d30e7624d0c (patch)
treea54c8338e3dc7d420fd2223bbcfb5af0a186348e /src/dolphinmainwindow.cpp
parent9dbe48137748c6197363236b67f6302e20b72167 (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.cpp155
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());