X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/4f4e3d392c9645e3d43c362af72e2066430890f6..4d81aabd1ee78c2fca61452ef3a866cfad0c88a5:/src/dolphinmainwindow.cpp diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 0ff7e77e5..305c7f282 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -9,7 +9,6 @@ #include "dolphinmainwindow.h" #include "dolphinmainwindowadaptor.h" -#include "config-terminal.h" #include "global.h" #include "dolphinbookmarkhandler.h" #include "dolphindockwidget.h" @@ -17,15 +16,15 @@ #include "dolphinnavigatorswidgetaction.h" #include "dolphinnewfilemenu.h" #include "dolphinrecenttabsmenu.h" +#include "dolphinplacesmodelsingleton.h" #include "dolphinurlnavigatorscontroller.h" #include "dolphinviewcontainer.h" #include "dolphintabpage.h" #include "middleclickactioneventfilter.h" #include "panels/folders/folderspanel.h" -#include "panels/places/placesitemmodel.h" #include "panels/places/placespanel.h" -#include "panels/information/informationpanel.h" #include "panels/terminal/terminalpanel.h" +#include "selectionmode/actiontexthelper.h" #include "settings/dolphinsettingsdialog.h" #include "statusbar/dolphinstatusbar.h" #include "views/dolphinviewactionhandler.h" @@ -42,34 +41,43 @@ #include #include #include -#include #include +#include +#if KIO_VERSION >= QT_VERSION_CHECK(5, 98, 0) +#include +#else #include +#endif #include #include #include #include #include -#include +#include #include #include #include +#include #include #include #include +#include #include #include #include -#include #include #include #include +#include + +#include #include #include #include #include #include +#include #include #include #include @@ -78,12 +86,13 @@ #include #include #include -#include namespace { // Used for GeneralSettings::version() to determine whether - // an updated version of Dolphin is running. - const int CurrentDolphinVersion = 200; + // an updated version of Dolphin is running, so as to migrate + // removed/renamed ...etc config entries; increment it in such + // cases + const int CurrentDolphinVersion = 202; // The maximum number of entries in the back/forward popup menu const int MaxNumberOfNavigationentries = 12; // The maximum number of "Activate Tab" shortcuts @@ -93,15 +102,12 @@ namespace { DolphinMainWindow::DolphinMainWindow() : KXmlGuiWindow(nullptr), m_newFileMenu(nullptr), - m_helpMenu(nullptr), m_tabWidget(nullptr), m_activeViewContainer(nullptr), m_actionHandler(nullptr), m_remoteEncoding(nullptr), m_settingsDialog(), m_bookmarkHandler(nullptr), - m_controlButton(nullptr), - m_updateToolBarTimer(nullptr), m_lastHandleUrlOpenJob(nullptr), m_terminalPanel(nullptr), m_placesPanel(nullptr), @@ -119,13 +125,15 @@ DolphinMainWindow::DolphinMainWindow() : setComponentName(QStringLiteral("dolphin"), QGuiApplication::applicationDisplayName()); setObjectName(QStringLiteral("Dolphin#")); + setStateConfigGroup("State"); + connect(&DolphinNewFileMenuObserver::instance(), &DolphinNewFileMenuObserver::errorMessage, this, &DolphinMainWindow::showErrorMessage); KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self(); undoManager->setUiInterface(new UndoUiInterface()); - connect(undoManager, QOverload::of(&KIO::FileUndoManager::undoAvailable), + connect(undoManager, &KIO::FileUndoManager::undoAvailable, this, &DolphinMainWindow::slotUndoAvailable); connect(undoManager, &KIO::FileUndoManager::undoTextChanged, this, &DolphinMainWindow::slotUndoTextChanged); @@ -153,11 +161,13 @@ DolphinMainWindow::DolphinMainWindow() : this, &DolphinMainWindow::updateWindowTitle); setCentralWidget(m_tabWidget); + m_actionTextHelper = new SelectionMode::ActionTextHelper(this); setupActions(); - m_actionHandler = new DolphinViewActionHandler(actionCollection(), this); + m_actionHandler = new DolphinViewActionHandler(actionCollection(), m_actionTextHelper, this); connect(m_actionHandler, &DolphinViewActionHandler::actionBeingHandled, this, &DolphinMainWindow::clearStatusBar); connect(m_actionHandler, &DolphinViewActionHandler::createDirectoryTriggered, this, &DolphinMainWindow::createDirectory); + connect(m_actionHandler, &DolphinViewActionHandler::selectionModeChangeTriggered, this, &DolphinMainWindow::slotSetSelectionMode); m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler); connect(this, &DolphinMainWindow::urlChanged, @@ -165,7 +175,7 @@ DolphinMainWindow::DolphinMainWindow() : setupDockWidgets(); - setupGUI(Keys | Save | Create | ToolBar); + setupGUI(Save | Create | ToolBar); stateChanged(QStringLiteral("new_file")); QClipboard* clipboard = QApplication::clipboard(); @@ -177,15 +187,21 @@ DolphinMainWindow::DolphinMainWindow() : if (firstRun) { menuBar()->setVisible(false); - // Assure a proper default size if Dolphin runs the first time - resize(750, 500); } const bool showMenu = !menuBar()->isHidden(); QAction* showMenuBarAction = actionCollection()->action(KStandardAction::name(KStandardAction::ShowMenubar)); showMenuBarAction->setChecked(showMenu); // workaround for bug #171080 - if (!showMenu) { - createControlButton(); + + auto hamburgerMenu = static_cast(actionCollection()->action( + KStandardAction::name(KStandardAction::HamburgerMenu))); + hamburgerMenu->setMenuBar(menuBar()); + hamburgerMenu->setShowMenuBarAction(showMenuBarAction); + connect(hamburgerMenu, &KHamburgerMenu::aboutToShowMenu, + this, &DolphinMainWindow::updateHamburgerMenu); + hamburgerMenu->hideActionsOf(toolBar()); + if (GeneralSettings::version() < 201 && !toolBar()->actions().contains(hamburgerMenu)) { + addHamburgerMenuToToolbar(); } updateAllowedToolbarAreas(); @@ -197,13 +213,23 @@ DolphinMainWindow::DolphinMainWindow() : setupWhatsThis(); - connect(KSycoca::self(), QOverload<>::of(&KSycoca::databaseChanged), this, &DolphinMainWindow::updateOpenPreferredSearchToolAction); + connect(KSycoca::self(), &KSycoca::databaseChanged, this, &DolphinMainWindow::updateOpenPreferredSearchToolAction); QTimer::singleShot(0, this, &DolphinMainWindow::updateOpenPreferredSearchToolAction); + + m_fileItemActions.setParentWidget(this); + connect(&m_fileItemActions, &KFileItemActions::error, this, [this](const QString &errorMessage) { + showErrorMessage(errorMessage); + }); + + connect(GeneralSettings::self(), &GeneralSettings::splitViewChanged, + this, &DolphinMainWindow::slotSplitViewChanged); } DolphinMainWindow::~DolphinMainWindow() { + // This fixes a crash on Wayland when closing the mainwindow while another dialog is open. + disconnect(QGuiApplication::clipboard(), &QClipboard::dataChanged, this, &DolphinMainWindow::updatePasteAction); } QVector DolphinMainWindow::viewContainers() const @@ -221,20 +247,6 @@ QVector DolphinMainWindow::viewContainers() const return viewContainers; } -void DolphinMainWindow::setViewsWithInvalidPathsToHome() -{ - const QVector theViewContainers = viewContainers(); - for (DolphinViewContainer *viewContainer : theViewContainers) { - - // Only consider local dirs, not remote locations and abstract protocols - if (viewContainer->url().isLocalFile()) { - if (!QFileInfo::exists(viewContainer->url().toLocalFile())) { - viewContainer->setUrl(QUrl::fromLocalFile(QDir::homePath())); - } - } - } -} - void DolphinMainWindow::openDirectories(const QList& dirs, bool splitView) { m_tabWidget->openDirectories(dirs, splitView); @@ -257,7 +269,7 @@ bool DolphinMainWindow::isFoldersPanelEnabled() const bool DolphinMainWindow::isInformationPanelEnabled() const { -#ifdef HAVE_BALOO +#if HAVE_BALOO return actionCollection()->action(QStringLiteral("show_information_panel"))->isChecked(); #else return false; @@ -276,6 +288,11 @@ void DolphinMainWindow::activateWindow() KWindowSystem::activateWindow(window()->effectiveWinId()); } +bool DolphinMainWindow::isActiveWindow() +{ + return window()->isActiveWindow(); +} + void DolphinMainWindow::showCommand(CommandType command) { DolphinStatusBar* statusBar = m_activeViewContainer->statusBar(); @@ -419,14 +436,13 @@ void DolphinMainWindow::addToPlaces() name = dirToAdd.name(); } if (url.isValid()) { - PlacesItemModel model; QString icon; if (m_activeViewContainer->isSearchModeEnabled()) { icon = QStringLiteral("folder-saved-search-symbolic"); } else { icon = KIO::iconNameForUrl(url); } - model.createPlacesItem(name, url, icon); + DolphinPlacesModelSingleton::instance().placesModel()->addPlace(name, url, icon); } } @@ -435,6 +451,22 @@ void DolphinMainWindow::openNewTab(const QUrl& url) m_tabWidget->openNewTab(url, QUrl()); } +void DolphinMainWindow::openNewTabAndActivate(const QUrl &url) +{ + m_tabWidget->openNewActivatedTab(url, QUrl()); +} + +void DolphinMainWindow::openNewWindow(const QUrl &url) +{ + Dolphin::openNewWindow({url}, this); +} + +void DolphinMainWindow::slotSplitViewChanged() +{ + m_tabWidget->currentTabPage()->setSplitViewEnabled(GeneralSettings::splitView(), WithAnimation); + updateSplitAction(); +} + void DolphinMainWindow::openInNewTab() { const KFileItemList& list = m_activeViewContainer->view()->selectedItems(); @@ -631,15 +663,21 @@ void DolphinMainWindow::readProperties(const KConfigGroup& group) void DolphinMainWindow::updateNewMenu() { - m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown()); m_newFileMenu->checkUpToDate(); +#if KIO_VERSION >= QT_VERSION_CHECK(5, 97, 0) + m_newFileMenu->setWorkingDirectory(activeViewContainer()->url()); +#else m_newFileMenu->setPopupFiles(QList() << activeViewContainer()->url()); +#endif } void DolphinMainWindow::createDirectory() { - m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown()); +#if KIO_VERSION >= QT_VERSION_CHECK(5, 97, 0) + m_newFileMenu->setWorkingDirectory(activeViewContainer()->url()); +#else m_newFileMenu->setPopupFiles(QList() << activeViewContainer()->url()); +#endif m_newFileMenu->createDirectory(); } @@ -678,12 +716,22 @@ void DolphinMainWindow::undo() void DolphinMainWindow::cut() { - m_activeViewContainer->view()->cutSelectedItemsToClipboard(); + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionMode::BottomBar::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(), SelectionMode::BottomBar::Contents::CopyContents); + } else { + m_activeViewContainer->view()->copySelectedItemsToClipboard(); + m_activeViewContainer->setSelectionModeEnabled(false); + } } void DolphinMainWindow::paste() @@ -728,14 +776,45 @@ void DolphinMainWindow::slotToolBarActionMiddleClicked(QAction *action) } } +QAction *DolphinMainWindow::urlNavigatorHistoryAction(const KUrlNavigator *urlNavigator, int historyIndex, QObject *parent) +{ + const QUrl url = urlNavigator->locationUrl(historyIndex); + + QString text = url.toDisplayString(QUrl::PreferLocalFile); + + if (!urlNavigator->showFullPath()) { + const KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel(); + + const QModelIndex closestIdx = placesModel->closestItem(url); + if (closestIdx.isValid()) { + const QUrl placeUrl = placesModel->url(closestIdx); + + text = placesModel->text(closestIdx); + + QString pathInsidePlace = url.path().mid(placeUrl.path().length()); + + if (!pathInsidePlace.isEmpty() && !pathInsidePlace.startsWith(QLatin1Char('/'))) { + pathInsidePlace.prepend(QLatin1Char('/')); + } + + if (pathInsidePlace != QLatin1Char('/')) { + text.append(pathInsidePlace); + } + } + } + + QAction *action = new QAction(QIcon::fromTheme(KIO::iconNameForUrl(url)), text, parent); + action->setData(historyIndex); + return action; +} + void DolphinMainWindow::slotAboutToShowBackPopupMenu() { const KUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory(); int entries = 0; m_backAction->menu()->clear(); for (int i = urlNavigator->historyIndex() + 1; i < urlNavigator->historySize() && entries < MaxNumberOfNavigationentries; ++i, ++entries) { - QAction* action = new QAction(urlNavigator->locationUrl(i).toString(QUrl::PreferLocalFile), m_backAction->menu()); - action->setData(i); + QAction *action = urlNavigatorHistoryAction(urlNavigator, i, m_backAction->menu()); m_backAction->menu()->addAction(action); } } @@ -763,8 +842,7 @@ void DolphinMainWindow::slotAboutToShowForwardPopupMenu() int entries = 0; m_forwardAction->menu()->clear(); for (int i = urlNavigator->historyIndex() - 1; i >= 0 && entries < MaxNumberOfNavigationentries; --i, ++entries) { - QAction* action = new QAction(urlNavigator->locationUrl(i).toString(QUrl::PreferLocalFile), m_forwardAction->menu()); - action->setData(i); + QAction *action = urlNavigatorHistoryAction(urlNavigator, i, m_forwardAction->menu()); m_forwardAction->menu()->addAction(action); } } @@ -778,6 +856,11 @@ void DolphinMainWindow::slotGoForward(QAction* action) } } +void DolphinMainWindow::slotSetSelectionMode(bool enabled, SelectionMode::BottomBar::Contents bottomBarContents) +{ + m_activeViewContainer->setSelectionModeEnabled(enabled, actionCollection(), bottomBarContents); +} + void DolphinMainWindow::selectAll() { clearStatusBar(); @@ -817,6 +900,26 @@ void DolphinMainWindow::toggleSplitStash() tabPage->setSplitViewEnabled(true, WithAnimation, QUrl("stash:/")); } +void DolphinMainWindow::copyToInactiveSplitView() +{ + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionMode::BottomBar::Contents::CopyToOtherViewContents); + } else { + m_tabWidget->copyToInactiveSplitView(); + m_activeViewContainer->setSelectionModeEnabled(false); + } +} + +void DolphinMainWindow::moveToInactiveSplitView() +{ + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionMode::BottomBar::Contents::MoveToOtherViewContents); + } else { + m_tabWidget->moveToInactiveSplitView(); + m_activeViewContainer->setSelectionModeEnabled(false); + } +} + void DolphinMainWindow::reloadView() { clearStatusBar(); @@ -839,6 +942,14 @@ void DolphinMainWindow::disableStopAction() actionCollection()->action(QStringLiteral("stop"))->setEnabled(false); } +void DolphinMainWindow::toggleSelectionMode() +{ + const bool checked = !m_activeViewContainer->isSelectionModeEnabled(); + + m_activeViewContainer->setSelectionModeEnabled(checked, actionCollection(), SelectionMode::BottomBar::Contents::GeneralContents); + actionCollection()->action(QStringLiteral("toggle_selection_mode"))->setChecked(checked); +} + void DolphinMainWindow::showFilterBar() { m_activeViewContainer->setFilterBarVisible(true); @@ -891,6 +1002,8 @@ void DolphinMainWindow::togglePanelLockState() } } + DolphinPlacesModelSingleton::instance().placesModel()->setPanelsLocked(newLockState); + GeneralSettings::setLockPanels(newLockState); } @@ -980,11 +1093,6 @@ void DolphinMainWindow::toggleShowMenuBar() { const bool visible = menuBar()->isVisible(); menuBar()->setVisible(!visible); - if (visible) { - createControlButton(); - } else { - deleteControlButton(); - } } QPointer DolphinMainWindow::preferredSearchTool() @@ -1014,7 +1122,11 @@ void DolphinMainWindow::updateOpenPreferredSearchToolAction() if (tool) { openPreferredSearchTool->setVisible(true); openPreferredSearchTool->setText(i18nc("@action:inmenu Tools", "Open %1", tool->text())); - openPreferredSearchTool->setIcon(tool->icon()); + // Only override with the app icon if it is the default, i.e. the user hasn't configured one manually + // https://bugs.kde.org/show_bug.cgi?id=442815 + if (openPreferredSearchTool->icon().name() == QLatin1String("search")) { + openPreferredSearchTool->setIcon(tool->icon()); + } } else { openPreferredSearchTool->setVisible(false); // still visible in Shortcuts configuration window @@ -1033,10 +1145,52 @@ void DolphinMainWindow::openPreferredSearchTool() void DolphinMainWindow::openTerminal() { - const QUrl url = m_activeViewContainer->url(); + openTerminalJob(m_activeViewContainer->url()); +} + +void DolphinMainWindow::openTerminalHere() +{ + QList urls = {}; + + for (const KFileItem& item : m_activeViewContainer->view()->selectedItems()) { + QUrl url = item.targetUrl(); + if (item.isFile()) { + url.setPath(QFileInfo(url.path()).absolutePath()); + } + if (!urls.contains(url)) { + urls << url; + } + } + + // No items are selected. Open a terminal window for the current location. + if (urls.count() == 0) { + openTerminal(); + return; + } + + if (urls.count() > 5) { + QString question = i18np("Are you sure you want to open 1 terminal window?", + "Are you sure you want to open %1 terminal windows?", urls.count()); + const int answer = KMessageBox::warningYesNo(this, question, {}, + KGuiItem(i18ncp("@action:button", "Open %1 Terminal", "Open %1 Terminals", urls.count()), + QStringLiteral("utilities-terminal")), + KStandardGuiItem::cancel()); + if (answer != KMessageBox::Yes) { + return; + } + } + for (const QUrl& url : urls) { + openTerminalJob(url); + } +} + +void DolphinMainWindow::openTerminalJob(const QUrl& url) +{ if (url.isLocalFile()) { - KToolInvocation::invokeTerminal(QString(), {}, url.toLocalFile()); + auto job = new KTerminalLauncherJob(QString()); + job->setWorkingDirectory(url.toLocalFile()); + job->start(); return; } @@ -1050,14 +1204,18 @@ void DolphinMainWindow::openTerminal() statUrl = job->mostLocalUrl(); } - KToolInvocation::invokeTerminal(QString(), {}, statUrl.isLocalFile() ? statUrl.toLocalFile() : QDir::homePath()); + auto job = new KTerminalLauncherJob(QString()); + job->setWorkingDirectory(statUrl.isLocalFile() ? statUrl.toLocalFile() : QDir::homePath()); + job->start(); }); return; } // Nothing worked, just use $HOME - KToolInvocation::invokeTerminal(QString(), {}, QDir::homePath()); + auto job = new KTerminalLauncherJob(QString()); + job->setWorkingDirectory(QDir::homePath()); + job->start(); } void DolphinMainWindow::editSettings() @@ -1088,7 +1246,11 @@ void DolphinMainWindow::handleUrl(const QUrl& url) activeViewContainer()->setUrl(url); } else { m_lastHandleUrlOpenJob = new KIO::OpenUrlJob(url); +#if KIO_VERSION >= QT_VERSION_CHECK(5, 98, 0) + m_lastHandleUrlOpenJob->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); +#else m_lastHandleUrlOpenJob->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); +#endif m_lastHandleUrlOpenJob->setShowOpenOrExecuteDialog(true); connect(m_lastHandleUrlOpenJob, &KIO::OpenUrlJob::mimeTypeFound, this, @@ -1118,32 +1280,11 @@ void DolphinMainWindow::slotWriteStateChanged(bool isFolderWritable) void DolphinMainWindow::openContextMenu(const QPoint& pos, const KFileItem& item, - const QUrl& url, - const QList& customActions) + const KFileItemList &selectedItems, + const QUrl& url) { - QPointer contextMenu = new DolphinContextMenu(this, pos, item, url); - contextMenu.data()->setCustomActions(customActions); - const DolphinContextMenu::Command command = contextMenu.data()->open(); - - switch (command) { - case DolphinContextMenu::OpenParentFolder: - changeUrl(KIO::upUrl(item.url())); - m_activeViewContainer->view()->markUrlsAsSelected({item.url()}); - m_activeViewContainer->view()->markUrlAsCurrent(item.url()); - break; - - case DolphinContextMenu::OpenParentFolderInNewWindow: - Dolphin::openNewWindow({item.url()}, this, Dolphin::OpenNewWindowFlag::Select); - break; - - case DolphinContextMenu::OpenParentFolderInNewTab: - openNewTab(KIO::upUrl(item.url())); - break; - - case DolphinContextMenu::None: - default: - break; - } + QPointer contextMenu = new DolphinContextMenu(this, item, selectedItems, url, &m_fileItemActions); + contextMenu.data()->exec(pos); // Delete the menu, unless it has been deleted in its own nested event loop already. if (contextMenu) { @@ -1151,87 +1292,106 @@ void DolphinMainWindow::openContextMenu(const QPoint& pos, } } -void DolphinMainWindow::updateControlMenu() +QMenu *DolphinMainWindow::createPopupMenu() { - QMenu* menu = qobject_cast(sender()); - Q_ASSERT(menu); - - // All actions get cleared by QMenu::clear(). This includes the sub-menus - // because 'menu' is their parent. - menu->clear(); - - KActionCollection* ac = actionCollection(); - - menu->addMenu(m_newFileMenu->menu()); - addActionToMenu(ac->action(QStringLiteral("file_new")), menu); - addActionToMenu(ac->action(QStringLiteral("new_tab")), menu); - addActionToMenu(ac->action(QStringLiteral("closed_tabs")), menu); + QMenu *menu = KXmlGuiWindow::createPopupMenu(); menu->addSeparator(); + menu->addAction(actionCollection()->action(QStringLiteral("lock_panels"))); - // Add "Edit" actions - bool added = addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Undo)), menu) | - addActionToMenu(ac->action(QString("copy_location")), menu) | - addActionToMenu(ac->action(QStringLiteral("copy_to_inactive_split_view")), menu) | - addActionToMenu(ac->action(QStringLiteral("move_to_inactive_split_view")), menu) | - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::SelectAll)), menu) | - addActionToMenu(ac->action(QStringLiteral("invert_selection")), menu); + return menu; +} - if (added) { - menu->addSeparator(); +void DolphinMainWindow::updateHamburgerMenu() +{ + KActionCollection* ac = actionCollection(); + auto hamburgerMenu = static_cast( + ac->action(KStandardAction::name(KStandardAction::HamburgerMenu))); + auto menu = hamburgerMenu->menu(); + if (!menu) { + menu = new QMenu(this); + hamburgerMenu->setMenu(menu); + hamburgerMenu->hideActionsOf(ac->action(QStringLiteral("basic_actions"))->menu()); + hamburgerMenu->hideActionsOf(ac->action(QStringLiteral("zoom"))->menu()); + } else { + menu->clear(); } + const QList toolbarActions = toolBar()->actions(); - // Add "View" actions - if (!GeneralSettings::showZoomSlider()) { - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomIn)), menu); - addActionToMenu(ac->action(QStringLiteral("view_zoom_reset")), menu); - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomOut)), menu); + if (!toolBar()->isVisible()) { + // If neither the menu bar nor the toolbar are visible, these actions should be available. + menu->addAction(ac->action(KStandardAction::name(KStandardAction::ShowMenubar))); + menu->addAction(toolBarMenuAction()); menu->addSeparator(); } - added = addActionToMenu(ac->action(QStringLiteral("show_preview")), menu) | - addActionToMenu(ac->action(QStringLiteral("show_in_groups")), menu) | - addActionToMenu(ac->action(QStringLiteral("show_hidden_files")), menu) | - addActionToMenu(ac->action(QStringLiteral("additional_info")), menu) | - addActionToMenu(ac->action(QStringLiteral("view_properties")), menu); + // This group of actions (until the next separator) contains all the most basic actions + // necessary to use Dolphin effectively. + menu->addAction(ac->action(QStringLiteral("go_back"))); + menu->addAction(ac->action(QStringLiteral("go_forward"))); - if (added) { - menu->addSeparator(); + menu->addMenu(m_newFileMenu->menu()); + if (!toolBar()->isVisible() + || !toolbarActions.contains(ac->action(QStringLiteral("toggle_selection_mode_tool_bar"))) + ) { + 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() + || (!toolbarActions.contains(ac->action(QStringLiteral("toggle_search"))) + && !toolbarActions.contains(ac->action(QStringLiteral("open_preferred_search_tool")))) + ) { + menu->addAction(ac->action(KStandardAction::name(KStandardAction::Find))); + // This way a search action will only be added if none of the three available + // search actions is present on the toolbar. + } + if (!toolBar()->isVisible() + || !toolbarActions.contains(ac->action(QStringLiteral("toggle_filter"))) + ) { + menu->addAction(ac->action(QStringLiteral("show_filter_bar"))); + // This way a filter action will only be added if none of the two available + // filter actions is present on the toolbar. } - - // Add a curated assortment of items from the "Tools" menu - addActionToMenu(ac->action(QStringLiteral("show_filter_bar")), menu); - addActionToMenu(ac->action(QStringLiteral("open_preferred_search_tool")), menu); - addActionToMenu(ac->action(QStringLiteral("open_terminal")), menu); - menu->addSeparator(); - // Add "Show Panels" menu - addActionToMenu(ac->action(QStringLiteral("panels")), menu); - - // Add "Settings" menu entries - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::KeyBindings)), menu); - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ConfigureToolbars)), menu); - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Preferences)), menu); - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ShowMenubar)), menu); - - // Add "Help" menu - auto helpMenu = m_helpMenu->menu(); - helpMenu->setIcon(QIcon::fromTheme(QStringLiteral("system-help"))); - menu->addMenu(helpMenu); -} - -void DolphinMainWindow::updateToolBar() -{ - if (!menuBar()->isVisible()) { - createControlButton(); + // The second group of actions (up until the next separator) contains actions for opening + // additional views to interact with the file system. + menu->addAction(ac->action(QStringLiteral("file_new"))); + menu->addAction(ac->action(QStringLiteral("new_tab"))); + if (ac->action(QStringLiteral("undo_close_tab"))->isEnabled()) { + menu->addAction(ac->action(QStringLiteral("closed_tabs"))); } -} + menu->addAction(ac->action(QStringLiteral("open_terminal"))); + menu->addSeparator(); -void DolphinMainWindow::slotControlButtonDeleted() -{ - m_controlButton = nullptr; - m_updateToolBarTimer->start(); + // The third group contains actions to change what one sees in the view + // and to change the more general UI. + if (!toolBar()->isVisible() + || (!toolbarActions.contains(ac->action(QStringLiteral("icons"))) + && !toolbarActions.contains(ac->action(QStringLiteral("compact"))) + && !toolbarActions.contains(ac->action(QStringLiteral("details"))) + && !toolbarActions.contains(ac->action(QStringLiteral("view_mode")))) + ) { + menu->addAction(ac->action(QStringLiteral("view_mode"))); + } + menu->addAction(ac->action(QStringLiteral("show_hidden_files"))); + menu->addAction(ac->action(QStringLiteral("sort"))); + menu->addAction(ac->action(QStringLiteral("additional_info"))); + if (!GeneralSettings::showStatusBar() || !GeneralSettings::showZoomSlider()) { + menu->addAction(ac->action(QStringLiteral("zoom"))); + } + menu->addAction(ac->action(QStringLiteral("panels"))); + + // The "Configure" menu is not added to the actionCollection() because there is hardly + // a good reason for users to put it on their toolbar. + auto configureMenu = menu->addMenu(QIcon::fromTheme(QStringLiteral("configure")), + i18nc("@action:inmenu menu for configure actions", "Configure")); + configureMenu->addAction(ac->action(KStandardAction::name(KStandardAction::SwitchApplicationLanguage))); + configureMenu->addAction(ac->action(KStandardAction::name(KStandardAction::KeyBindings))); + configureMenu->addAction(ac->action(KStandardAction::name(KStandardAction::ConfigureToolbars))); + configureMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Preferences))); + hamburgerMenu->hideActionsOf(configureMenu); } void DolphinMainWindow::slotPlaceActivated(const QUrl& url) @@ -1269,6 +1429,7 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer) // view and url navigator) and main window. oldViewContainer->disconnect(this); oldViewContainer->view()->disconnect(this); + oldViewContainer->urlNavigatorInternalWithHistory()->disconnect(this); auto navigators = static_cast (actionCollection()->action(QStringLiteral("url_navigators"))); navigators->primaryUrlNavigator()->disconnect(this); @@ -1279,6 +1440,10 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer) // except the requestItemInfo so that on hover the information panel can still be updated connect(oldViewContainer->view(), &DolphinView::requestItemInfo, this, &DolphinMainWindow::requestItemInfo); + + // Disconnect other slots. + disconnect(nullptr, &DolphinViewContainer::selectionModeChanged, + actionCollection()->action(QStringLiteral("toggle_selection_mode")), &QAction::setChecked); } connectViewSignals(viewContainer); @@ -1342,6 +1507,19 @@ void DolphinMainWindow::slotStorageTearDownExternallyRequested(const QString& mo } } +void DolphinMainWindow::slotKeyBindings() +{ + KShortcutsDialog dialog(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, this); + dialog.addCollection(actionCollection()); + if (m_terminalPanel) { + KActionCollection *konsolePartActionCollection = m_terminalPanel->actionCollection(); + if (konsolePartActionCollection) { + dialog.addCollection(konsolePartActionCollection, QStringLiteral("KonsolePart")); + } + } + dialog.configure(); +} + void DolphinMainWindow::setViewsToHomeIfMountPathOpen(const QString& mountPath) { const QVector theViewContainers = viewContainers(); @@ -1355,12 +1533,14 @@ void DolphinMainWindow::setViewsToHomeIfMountPathOpen(const QString& mountPath) void DolphinMainWindow::setupActions() { + auto hamburgerMenuAction = KStandardAction::hamburgerMenu(nullptr, nullptr, actionCollection()); + // setup 'File' menu m_newFileMenu = new DolphinNewFileMenu(actionCollection(), this); QMenu* menu = m_newFileMenu->menu(); menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New")); - menu->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); - m_newFileMenu->setDelayed(false); + menu->setIcon(QIcon::fromTheme(QStringLiteral("list-add"))); + m_newFileMenu->setPopupMode(QToolButton::InstantPopup); connect(menu, &QMenu::aboutToShow, this, &DolphinMainWindow::updateNewMenu); @@ -1412,12 +1592,14 @@ void DolphinMainWindow::setupActions() "next to each other on the keyboard: Ctrl+X, " "Ctrl+C and Ctrl+V."); QAction* cutAction = KStandardAction::cut(this, &DolphinMainWindow::cut, actionCollection()); + m_actionTextHelper->registerTextWhenNothingIsSelected(cutAction, i18nc("@action", "Cut…")); cutAction->setWhatsThis(xi18nc("@info:whatsthis cut", "This copies the items " "in your current selection to the clipboard." "Use the Paste action afterwards to copy them from " "the clipboard to a new location. The items will be removed from their " "initial location.") + cutCopyPastePara); QAction* copyAction = KStandardAction::copy(this, &DolphinMainWindow::copy, actionCollection()); + m_actionTextHelper->registerTextWhenNothingIsSelected(copyAction, i18nc("@action", "Copy…")); copyAction->setWhatsThis(xi18nc("@info:whatsthis copy", "This copies the " "items in your current selection to the clipboard." "Use the Paste action afterwards to copy them " @@ -1434,25 +1616,27 @@ void DolphinMainWindow::setupActions() QAction* copyToOtherViewAction = actionCollection()->addAction(QStringLiteral("copy_to_inactive_split_view")); copyToOtherViewAction->setText(i18nc("@action:inmenu", "Copy to Inactive Split View")); + m_actionTextHelper->registerTextWhenNothingIsSelected(copyToOtherViewAction, i18nc("@action:inmenu", "Copy to Inactive Split View…")); copyToOtherViewAction->setWhatsThis(xi18nc("@info:whatsthis Copy", "This copies the selected items from " "the active view to the inactive split view.")); 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")); + m_actionTextHelper->registerTextWhenNothingIsSelected(moveToOtherViewAction, i18nc("@action:inmenu", "Move to Inactive Split View…")); moveToOtherViewAction->setWhatsThis(xi18nc("@info:whatsthis Move", "This moves the selected items from " "the active view to the inactive split view.")); 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...")); - showFilterBar->setToolTip(i18nc("@info:tooltip", "Toggle Filter Bar")); + showFilterBar->setToolTip(i18nc("@info:tooltip", "Show Filter Bar")); showFilterBar->setWhatsThis(xi18nc("@info:whatsthis", "This opens the " "Filter Bar at the bottom of the window. " "There you can enter a text to filter the files and folders currently displayed. " @@ -1494,6 +1678,32 @@ 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. + // 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", "This application only knows which files or folders should be acted on if they are" + " selected first. Press this to toggle a Selection Mode which makes selecting and deselecting as easy as " + "pressing an item once.While in this mode, a quick access bar at the bottom shows available actions for the currently selected items." + "")); + 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_tool_bar"), 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.")); @@ -1506,6 +1716,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) @@ -1523,7 +1738,8 @@ void DolphinMainWindow::setupActions() stashSplit->setToolTip(i18nc("@info", "Opens the stash virtual directory in a split window")); stashSplit->setIcon(QIcon::fromTheme(QStringLiteral("folder-stash"))); stashSplit->setCheckable(false); - stashSplit->setVisible(QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kio.StashNotifier"))); + QDBusConnectionInterface *sessionInterface = QDBusConnection::sessionBus().interface(); + stashSplit->setVisible(sessionInterface && sessionInterface->isServiceRegistered(QStringLiteral("org.kde.kio.StashNotifier"))); connect(stashSplit, &QAction::triggered, this, &DolphinMainWindow::toggleSplitStash); KStandardAction::redisplay(this, &DolphinMainWindow::reloadView, actionCollection()); @@ -1563,8 +1779,7 @@ void DolphinMainWindow::setupActions() m_backAction->setObjectName(backAction->objectName()); m_backAction->setShortcuts(backAction->shortcuts()); } - m_backAction->setDelayed(true); - m_backAction->setStickyMenu(false); + m_backAction->setPopupMode(QToolButton::DelayedPopup); connect(m_backAction, &QAction::triggered, this, &DolphinMainWindow::goBack); connect(m_backAction->menu(), &QMenu::aboutToShow, this, &DolphinMainWindow::slotAboutToShowBackPopupMenu); connect(m_backAction->menu(), &QMenu::triggered, this, &DolphinMainWindow::slotGoBack); @@ -1607,8 +1822,7 @@ void DolphinMainWindow::setupActions() m_forwardAction->setObjectName(forwardAction->objectName()); m_forwardAction->setShortcuts(forwardAction->shortcuts()); } - m_forwardAction->setDelayed(true); - m_forwardAction->setStickyMenu(false); + m_forwardAction->setPopupMode(QToolButton::DelayedPopup); connect(m_forwardAction, &QAction::triggered, this, &DolphinMainWindow::goForward); connect(m_forwardAction->menu(), &QMenu::aboutToShow, this, &DolphinMainWindow::slotAboutToShowForwardPopupMenu); connect(m_forwardAction->menu(), &QMenu::triggered, this, &DolphinMainWindow::slotGoForward); @@ -1653,7 +1867,17 @@ void DolphinMainWindow::setupActions() actionCollection()->setDefaultShortcut(openTerminal, Qt::SHIFT | Qt::Key_F4); connect(openTerminal, &QAction::triggered, this, &DolphinMainWindow::openTerminal); -#ifdef HAVE_TERMINAL + QAction* openTerminalHere = actionCollection()->addAction(QStringLiteral("open_terminal_here")); + // i18n: "Here" refers to the location(s) of the currently selected item(s) or the currently viewed location if nothing is selected. + openTerminalHere->setText(i18nc("@action:inmenu Tools", "Open Terminal Here")); + openTerminalHere->setWhatsThis(xi18nc("@info:whatsthis", + "This opens terminal applications for the selected items' locations." + "To learn more about terminals use the help in the terminal application.")); + openTerminalHere->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal"))); + actionCollection()->setDefaultShortcut(openTerminalHere, Qt::SHIFT | Qt::ALT | Qt::Key_F4); + connect(openTerminalHere, &QAction::triggered, this, &DolphinMainWindow::openTerminalHere); + +#if HAVE_TERMINAL QAction* focusTerminalPanel = actionCollection()->addAction(QStringLiteral("focus_terminal_panel")); focusTerminalPanel->setText(i18nc("@action:inmenu Tools", "Focus Terminal Panel")); focusTerminalPanel->setIcon(QIcon::fromTheme(QStringLiteral("swap-panels"))); @@ -1666,26 +1890,32 @@ void DolphinMainWindow::setupActions() KActionMenu *bookmarkMenu = new KActionMenu(i18nc("@title:menu", "&Bookmarks"), this); bookmarkMenu->setIcon(QIcon::fromTheme(QStringLiteral("bookmarks"))); // Make the toolbar button version work properly on click - bookmarkMenu->setDelayed(false); + bookmarkMenu->setPopupMode(QToolButton::InstantPopup); m_bookmarkHandler = new DolphinBookmarkHandler(this, actionCollection(), bookmarkMenu->menu(), this); actionCollection()->addAction(QStringLiteral("bookmarks"), bookmarkMenu); // setup 'Settings' menu KToggleAction* showMenuBar = KStandardAction::showMenubar(nullptr, nullptr, actionCollection()); showMenuBar->setWhatsThis(xi18nc("@info:whatsthis", - "This switches between having a Menubar " - "and having a Control button. Both " - "contain mostly the same commands and configuration options.")); + "This switches between having a Menubar " + "and having a %1 button. Both " + "contain mostly the same actions and configuration options." + "The Menubar takes up more space but allows for fast and organised access to all " + "actions an application has to offer.The %1 button " + "is simpler and small which makes triggering advanced actions more time consuming.", hamburgerMenuAction->text().replace('&', ""))); connect(showMenuBar, &KToggleAction::triggered, // Fixes #286822 this, &DolphinMainWindow::toggleShowMenuBar, Qt::QueuedConnection); - KStandardAction::preferences(this, &DolphinMainWindow::editSettings, actionCollection()); - // setup 'Help' menu for the m_controlButton. The other one is set up in the base class. - m_helpMenu = new KHelpMenu(nullptr); - m_helpMenu->menu()->installEventFilter(this); - // remove duplicate shortcuts - m_helpMenu->action(KHelpMenu::menuHelpContents)->setShortcut(QKeySequence()); - m_helpMenu->action(KHelpMenu::menuWhatsThis)->setShortcut(QKeySequence()); + KToggleAction* showStatusBar = KStandardAction::showStatusbar(nullptr, nullptr, actionCollection()); + showStatusBar->setChecked(GeneralSettings::showStatusBar()); + connect(GeneralSettings::self(), &GeneralSettings::showStatusBarChanged, showStatusBar, &KToggleAction::setChecked); + connect(showStatusBar, &KToggleAction::triggered, this, [this](bool checked) { + GeneralSettings::setShowStatusBar(checked); + refreshViews(); + }); + + KStandardAction::keyBindings(this, &DolphinMainWindow::slotKeyBindings, actionCollection()); + KStandardAction::preferences(this, &DolphinMainWindow::editSettings, actionCollection()); // not in menu actions QList nextTabKeys = KStandardShortcut::tabNext(); @@ -1753,6 +1983,8 @@ void DolphinMainWindow::setupDockWidgets() { const bool lock = GeneralSettings::lockPanels(); + DolphinPlacesModelSingleton::instance().placesModel()->setPanelsLocked(lock); + KDualAction* lockLayoutAction = actionCollection()->add(QStringLiteral("lock_panels")); lockLayoutAction->setActiveText(i18nc("@action:inmenu Panels", "Unlock Panels")); lockLayoutAction->setActiveIcon(QIcon::fromTheme(QStringLiteral("object-unlocked"))); @@ -1772,7 +2004,7 @@ void DolphinMainWindow::setupDockWidgets() infoDock->setObjectName(QStringLiteral("infoDock")); infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); -#ifdef HAVE_BALOO +#if HAVE_BALOO InformationPanel* infoPanel = new InformationPanel(infoDock); infoPanel->setCustomContextMenuActions({lockLayoutAction}); connect(infoPanel, &InformationPanel::urlActivated, this, &DolphinMainWindow::handleUrl); @@ -1788,13 +2020,15 @@ void DolphinMainWindow::setupDockWidgets() infoPanel, &InformationPanel::setSelection); connect(this, &DolphinMainWindow::requestItemInfo, infoPanel, &InformationPanel::requestDelayedItemInfo); + connect(this, &DolphinMainWindow::fileItemsChanged, + infoPanel, &InformationPanel::slotFilesItemChanged); #endif // i18n: This is the last paragraph for the "What's This"-texts of all four panels. const QString panelWhatsThis = xi18nc("@info:whatsthis", "To show or " - "hide panels like this go to Control|Panels " + "hide panels like this go to Menu|Panels " "or View|Panels."); -#ifdef HAVE_BALOO +#if HAVE_BALOO actionCollection()->action(QStringLiteral("show_information_panel")) ->setWhatsThis(xi18nc("@info:whatsthis", " This toggles the " "information panel at the right side of the " @@ -1827,8 +2061,10 @@ void DolphinMainWindow::setupDockWidgets() foldersPanel, &FoldersPanel::setUrl); connect(foldersPanel, &FoldersPanel::folderActivated, this, &DolphinMainWindow::changeUrl); - connect(foldersPanel, &FoldersPanel::folderMiddleClicked, + connect(foldersPanel, &FoldersPanel::folderInNewTab, this, &DolphinMainWindow::openNewTab); + connect(foldersPanel, &FoldersPanel::folderInNewActiveTab, + this, &DolphinMainWindow::openNewTabAndActivate); connect(foldersPanel, &FoldersPanel::errorMessage, this, &DolphinMainWindow::showErrorMessage); @@ -1844,7 +2080,7 @@ void DolphinMainWindow::setupDockWidgets() "This allows quick switching between any folders.") + panelWhatsThis); // Setup "Terminal" -#ifdef HAVE_TERMINAL +#if HAVE_TERMINAL if (KAuthorized::authorize(QStringLiteral("shell_access"))) { DolphinDockWidget* terminalDock = new DolphinDockWidget(i18nc("@title:window Shell terminal", "Terminal")); terminalDock->setLocked(lock); @@ -1910,8 +2146,13 @@ void DolphinMainWindow::setupDockWidgets() addDockWidget(Qt::LeftDockWidgetArea, placesDock); connect(m_placesPanel, &PlacesPanel::placeActivated, this, &DolphinMainWindow::slotPlaceActivated); - connect(m_placesPanel, &PlacesPanel::placeMiddleClicked, + connect(m_placesPanel, &PlacesPanel::tabRequested, this, &DolphinMainWindow::openNewTab); + connect(m_placesPanel, &PlacesPanel::activeTabRequested, + this, &DolphinMainWindow::openNewTabAndActivate); + connect(m_placesPanel, &PlacesPanel::newWindowRequested, this, [this](const QUrl &url) { + Dolphin::openNewWindow({url}, this); + }); connect(m_placesPanel, &PlacesPanel::errorMessage, this, &DolphinMainWindow::showErrorMessage); connect(this, &DolphinMainWindow::urlChanged, @@ -1934,14 +2175,9 @@ void DolphinMainWindow::setupDockWidgets() "appear semi-transparent unless you uncheck their hide property.")); connect(actionShowAllPlaces, &QAction::triggered, this, [actionShowAllPlaces, this](bool checked){ - actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("view-visible") : QStringLiteral("view-hidden"))); - m_placesPanel->showHiddenEntries(checked); + m_placesPanel->setShowAll(checked); }); - - connect(m_placesPanel, &PlacesPanel::showHiddenEntriesChanged, this, [actionShowAllPlaces] (bool checked){ - actionShowAllPlaces->setChecked(checked); - actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("view-visible") : QStringLiteral("view-hidden"))); - }); + connect(m_placesPanel, &PlacesPanel::allPlacesShownChanged, actionShowAllPlaces, &QAction::setChecked); actionCollection()->action(QStringLiteral("show_places_panel")) ->setWhatsThis(xi18nc("@info:whatsthis", "This toggles the " @@ -1966,10 +2202,10 @@ void DolphinMainWindow::setupDockWidgets() KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Show Panels"), this); actionCollection()->addAction(QStringLiteral("panels"), panelsMenu); panelsMenu->setIcon(QIcon::fromTheme(QStringLiteral("view-sidetree"))); - panelsMenu->setDelayed(false); + panelsMenu->setPopupMode(QToolButton::InstantPopup); const KActionCollection* ac = actionCollection(); panelsMenu->addAction(ac->action(QStringLiteral("show_places_panel"))); -#ifdef HAVE_BALOO +#if HAVE_BALOO panelsMenu->addAction(ac->action(QStringLiteral("show_information_panel"))); #endif panelsMenu->addAction(ac->action(QStringLiteral("show_folders_panel"))); @@ -1979,7 +2215,7 @@ void DolphinMainWindow::setupDockWidgets() panelsMenu->addAction(lockLayoutAction); connect(panelsMenu->menu(), &QMenu::aboutToShow, this, [actionShowAllPlaces, this]{ - actionShowAllPlaces->setEnabled(m_placesPanel->hiddenListCount()); + actionShowAllPlaces->setEnabled(DolphinPlacesModelSingleton::instance().placesModel()->hiddenCount()); }); } @@ -1990,7 +2226,12 @@ void DolphinMainWindow::updateFileAndEditActions() const KActionCollection* col = actionCollection(); KFileItemListProperties capabilitiesSource(list); - QAction* addToPlacesAction = col->action(QStringLiteral("add_to_places")); + 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")); QAction* copyLocation = col->action(QString("copy_location")); @@ -1998,20 +2239,23 @@ 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); + // Them triggering selection mode and not directly acting on selected items is signified by adding "…" to their text. + m_actionTextHelper->textsWhenNothingIsSelectedEnabled(true); + } else { + m_actionTextHelper->textsWhenNothingIsSelectedEnabled(false); 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); @@ -2019,23 +2263,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()); @@ -2047,6 +2274,23 @@ 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() @@ -2076,75 +2320,11 @@ void DolphinMainWindow::updateGoActions() goUpAction->setEnabled(KIO::upUrl(currentUrl) != currentUrl); } -void DolphinMainWindow::createControlButton() -{ - if (m_controlButton) { - return; - } - Q_ASSERT(!m_controlButton); - - m_controlButton = new QToolButton(this); - m_controlButton->setAccessibleName(i18nc("@action:intoolbar", "Control")); - m_controlButton->setIcon(QIcon::fromTheme(QStringLiteral("application-menu"))); - m_controlButton->setToolTip(i18nc("@action", "Show menu")); - m_controlButton->setAttribute(Qt::WidgetAttribute::WA_CustomWhatsThis); - m_controlButton->setPopupMode(QToolButton::InstantPopup); - - QMenu* controlMenu = new QMenu(m_controlButton); - connect(controlMenu, &QMenu::aboutToShow, this, &DolphinMainWindow::updateControlMenu); - controlMenu->installEventFilter(this); - - m_controlButton->setMenu(controlMenu); - - toolBar()->addWidget(m_controlButton); - connect(toolBar(), &KToolBar::iconSizeChanged, - m_controlButton, &QToolButton::setIconSize); - - // The added widgets are owned by the toolbar and may get deleted when e.g. the toolbar - // gets edited. In this case we must add them again. The adding is done asynchronously by - // m_updateToolBarTimer. - connect(m_controlButton, &QToolButton::destroyed, this, &DolphinMainWindow::slotControlButtonDeleted); - m_updateToolBarTimer = new QTimer(this); - m_updateToolBarTimer->setInterval(500); - connect(m_updateToolBarTimer, &QTimer::timeout, this, &DolphinMainWindow::updateToolBar); -} - -void DolphinMainWindow::deleteControlButton() -{ - delete m_controlButton; - m_controlButton = nullptr; - - delete m_updateToolBarTimer; - m_updateToolBarTimer = nullptr; -} - -bool DolphinMainWindow::addActionToMenu(QAction* action, QMenu* menu) -{ - Q_ASSERT(action); - Q_ASSERT(menu); - - const KToolBar* toolBarWidget = toolBar(); - const auto associatedWidgets = action->associatedWidgets(); - for (const QWidget* widget : associatedWidgets) { - if (widget == toolBarWidget) { - return false; - } - } - - menu->addAction(action); - return true; -} - void DolphinMainWindow::refreshViews() { m_tabWidget->refreshViews(); if (GeneralSettings::modifiedStartupSettings()) { - // The startup settings have been changed by the user (see bug #254947). - // Synchronize the split-view setting with the active view: - const bool splitView = GeneralSettings::splitView(); - m_tabWidget->currentTabPage()->setSplitViewEnabled(splitView, WithAnimation); - updateSplitAction(); updateWindowTitle(); } @@ -2164,17 +2344,35 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container) this, &DolphinMainWindow::slotWriteStateChanged); connect(container, &DolphinViewContainer::searchModeEnabledChanged, this, &DolphinMainWindow::updateSearchAction); + connect(container, &DolphinViewContainer::captionChanged, + this, &DolphinMainWindow::updateWindowTitle); + connect(container, &DolphinViewContainer::tabRequested, + this, &DolphinMainWindow::openNewTab); + connect(container, &DolphinViewContainer::activeTabRequested, + this, &DolphinMainWindow::openNewTabAndActivate); const QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search")); connect(toggleSearchAction, &QAction::triggered, container, &DolphinViewContainer::setSearchModeEnabled); + // Make the toggled state of the selection mode actions visually follow the selection mode state of the view. + auto toggleSelectionModeAction = actionCollection()->action(QStringLiteral("toggle_selection_mode")); + toggleSelectionModeAction->setChecked(m_activeViewContainer->isSelectionModeEnabled()); + connect(m_activeViewContainer, &DolphinViewContainer::selectionModeChanged, + toggleSelectionModeAction, &QAction::setChecked); + const DolphinView* view = container->view(); connect(view, &DolphinView::selectionChanged, this, &DolphinMainWindow::slotSelectionChanged); connect(view, &DolphinView::requestItemInfo, this, &DolphinMainWindow::requestItemInfo); + connect(view, &DolphinView::fileItemsChanged, + this, &DolphinMainWindow::fileItemsChanged); connect(view, &DolphinView::tabRequested, this, &DolphinMainWindow::openNewTab); + connect(view, &DolphinView::activeTabRequested, + this, &DolphinMainWindow::openNewTabAndActivate); + connect(view, &DolphinView::windowRequested, + this, &DolphinMainWindow::openNewWindow); connect(view, &DolphinView::requestContextMenu, this, &DolphinMainWindow::openContextMenu); connect(view, &DolphinView::directoryLoadingStarted, @@ -2192,26 +2390,28 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container) connect(view, &DolphinView::goUpRequested, this, &DolphinMainWindow::goUp); + connect(container->urlNavigatorInternalWithHistory(), &KUrlNavigator::urlChanged, + this, &DolphinMainWindow::changeUrl); + connect(container->urlNavigatorInternalWithHistory(), &KUrlNavigator::historyChanged, + this, &DolphinMainWindow::updateHistory); + auto navigators = static_cast (actionCollection()->action(QStringLiteral("url_navigators"))); - const KUrlNavigator *navigator = m_tabWidget->currentTabPage()->primaryViewActive() ? navigators->primaryUrlNavigator() : navigators->secondaryUrlNavigator(); - connect(navigator, &KUrlNavigator::urlChanged, - this, &DolphinMainWindow::changeUrl); QAction *editableLocactionAction = actionCollection()->action(QStringLiteral("editable_location")); editableLocactionAction->setChecked(navigator->isUrlEditable()); connect(navigator, &KUrlNavigator::editableStateChanged, this, &DolphinMainWindow::slotEditableStateChanged); connect(navigator, &KUrlNavigator::tabRequested, this, &DolphinMainWindow::openNewTab); + connect(navigator, &KUrlNavigator::activeTabRequested, + this, &DolphinMainWindow::openNewTabAndActivate); + connect(navigator, &KUrlNavigator::newWindowRequested, + this, &DolphinMainWindow::openNewWindow); - disconnect(m_updateHistoryConnection); - m_updateHistoryConnection = connect( - container->urlNavigatorInternalWithHistory(), &KUrlNavigator::historyChanged, - this, &DolphinMainWindow::updateHistory); } void DolphinMainWindow::updateSplitAction() @@ -2273,6 +2473,7 @@ void DolphinMainWindow::createPanelAction(const QIcon& icon, panelAction->setChecked(dockAction->isChecked()); panelAction->setText(dockAction->text()); panelAction->setIcon(icon); + dockAction->setIcon(icon); actionCollection()->setDefaultShortcut(panelAction, shortcut); connect(panelAction, &QAction::triggered, dockAction, &QAction::trigger); @@ -2287,16 +2488,16 @@ void DolphinMainWindow::setupWhatsThis() "configuration options. Left-click on any of the menus on this " "bar to see its contents.The Menubar can be hidden " "by unchecking Settings|Show Menubar. Then " - "most of its contents become available through a Control" + "most of its contents become available through a Menu" " button on the Toolbar.")); toolBar()->setWhatsThis(xi18nc("@info:whatsthis", "This is the " "Toolbar. It allows quick access to " "frequently used actions.It is highly customizable. " - "All items you see in the Control menu or " + "All items you see in the Menu or " "in the Menubar can be placed on the " "Toolbar. Just right-click on it and select Configure " - "Toolbars… or find this action in the " - "Control or Settings menu." + "Toolbars… or find this action within the " + "menu." "The location of the bar and the style of its " "buttons can also be changed in the right-click menu. Right-click " "a button if you want to show or hide its text.")); @@ -2325,8 +2526,7 @@ void DolphinMainWindow::setupWhatsThis() actionCollection()->action(KStandardAction::name(KStandardAction::ConfigureToolbars)) ->setWhatsThis(xi18nc("@info:whatsthis","This opens a window in which " "you can change which buttons appear on the Toolbar." - "All items you see in the Control menu " - "or in the Menubar can also be placed on the Toolbar.")); + "All items you see in the Menu can also be placed on the Toolbar.")); actionCollection()->action(KStandardAction::name(KStandardAction::Preferences)) ->setWhatsThis(xi18nc("@info:whatsthis","This opens a window where you can " "change a multitude of settings for this application. For an explanation " @@ -2334,68 +2534,38 @@ void DolphinMainWindow::setupWhatsThis() " in Help|Dolphin Handbook.")); // Help menu - // The whatsthis has to be set for the m_helpMenu and for the - // StandardAction separately because both are used in different locations. - // m_helpMenu is only used for createControlButton() button. - // Links do not work within the Menubar so texts without links are provided there. - - // i18n: If the external link isn't available in your language you should - // probably state the external link language at least in brackets to not + // i18n: If the external link isn't available in your language it might make + // sense to state the external link's language in brackets to not // frustrate the user. If there are multiple languages that the user might // know with a reasonable chance you might want to have 2 external links. - // The same is in my opinion true for every external link you translate. - const QString whatsThisHelpContents = xi18nc("@info:whatsthis handbook", - "This opens the Handbook for this application. It provides " - "explanations for every part of Dolphin."); - actionCollection()->action(KStandardAction::name(KStandardAction::HelpContents)) - ->setWhatsThis(whatsThisHelpContents - + xi18nc("@info:whatsthis second half of handbook hb text without link", - "If you want more elaborate introductions to the " - "different features of Dolphin " - "go to the KDE UserBase Wiki.")); - m_helpMenu->action(KHelpMenu::menuHelpContents)->setWhatsThis(whatsThisHelpContents - + xi18nc("@info:whatsthis second half of handbook text with link", - "If you want more elaborate introductions to the " - "different features of Dolphin " - "click here. " - "It will open the dedicated page in the KDE UserBase Wiki.")); - - const QString whatsThisWhatsThis = xi18nc("@info:whatsthis whatsthis button", + // The same might be true for any external link you translate. + actionCollection()->action(KStandardAction::name(KStandardAction::HelpContents))->setWhatsThis(xi18nc("@info:whatsthis handbook", "This opens the Handbook for this application. It provides explanations for every part of Dolphin.If you want more elaborate introductions to the different features of Dolphin click here. It will open the dedicated page in the KDE UserBase Wiki.")); + // (The i18n call should be completely in the line following the i18n: comment without any line breaks within the i18n call or the comment might not be correctly extracted. See: https://commits.kde.org/kxmlgui/a31135046e1b3335b5d7bbbe6aa9a883ce3284c1 ) + + actionCollection()->action(KStandardAction::name(KStandardAction::WhatsThis))->setWhatsThis( + xi18nc("@info:whatsthis whatsthis button", "This is the button that invokes the help feature you are " "using right now! Click it, then click any component of this " "application to ask \"What's this?\" about it. The mouse cursor " - "will change appearance if no help is available for a spot."); - actionCollection()->action(KStandardAction::name(KStandardAction::WhatsThis)) - ->setWhatsThis(whatsThisWhatsThis - + xi18nc("@info:whatsthis second half of whatsthis button text without link", - "There are two other ways to get help for this application: The " - "Dolphin Handbook in the Help" - " menu and the KDE UserBase Wiki " - "article about File Management online." - "The \"What's this?\" help is " - "missing in most other windows so don't get too used to this.")); - m_helpMenu->action(KHelpMenu::menuWhatsThis)->setWhatsThis(whatsThisWhatsThis - + xi18nc("@info:whatsthis second half of whatsthis button text with link", + "will change appearance if no help is available for a spot." "There are two other ways to get help: " "The Dolphin Handbook and " "the KDE " "UserBase Wiki.The \"What's this?\" help is " "missing in most other windows so don't get too used to this.")); - const QString whatsThisReportBug = xi18nc("@info:whatsthis","This opens a " + actionCollection()->action(KStandardAction::name(KStandardAction::ReportBug))->setWhatsThis( + xi18nc("@info:whatsthis","This opens a " "window that will guide you through reporting errors or flaws " - "in this application or in other KDE software."); - actionCollection()->action(KStandardAction::name(KStandardAction::ReportBug)) - ->setWhatsThis(whatsThisReportBug); - m_helpMenu->action(KHelpMenu::menuReportBug)->setWhatsThis(whatsThisReportBug - + xi18nc("@info:whatsthis second half of reportbug text with link", + "in this application or in other KDE software." "High-quality bug reports are much appreciated. To learn " "how to make your bug report as effective as possible " "" "click here.")); - const QString whatsThisDonate = xi18nc("@info:whatsthis","This opens a " + actionCollection()->action(KStandardAction::name(KStandardAction::Donate))->setWhatsThis( + xi18nc("@info:whatsthis", "This opens a " "web page where you can donate to " "support the continued work on this application and many " "other projects by the KDE community." @@ -2404,57 +2574,54 @@ void DolphinMainWindow::setupWhatsThis() "free therefore your donation is needed to cover things that " "require money like servers, contributor meetings, etc." "KDE e.V. is the non-profit " - "organization behind the KDE community."); - actionCollection()->action(KStandardAction::name(KStandardAction::Donate)) - ->setWhatsThis(whatsThisDonate); - m_helpMenu->action(KHelpMenu::menuDonate)->setWhatsThis(whatsThisDonate); + "organization behind the KDE community.")); - const QString whatsThisSwitchLanguage = xi18nc("@info:whatsthis", + actionCollection()->action(KStandardAction::name(KStandardAction::SwitchApplicationLanguage))->setWhatsThis( + xi18nc("@info:whatsthis", "With this you can change the language this application uses." "You can even set secondary languages which will be used " - "if texts are not available in your preferred language."); - actionCollection()->action(KStandardAction::name(KStandardAction::SwitchApplicationLanguage)) - ->setWhatsThis(whatsThisSwitchLanguage); - m_helpMenu->action(KHelpMenu::menuSwitchLanguage)->setWhatsThis(whatsThisSwitchLanguage); + "if texts are not available in your preferred language.")); - const QString whatsThisAboutApp = xi18nc("@info:whatsthis","This opens a " + actionCollection()->action(KStandardAction::name(KStandardAction::AboutApp))->setWhatsThis( + xi18nc("@info:whatsthis","This opens a " "window that informs you about the version, license, " - "used libraries and maintainers of this application."); - actionCollection()->action(KStandardAction::name(KStandardAction::AboutApp)) - ->setWhatsThis(whatsThisAboutApp); - m_helpMenu->action(KHelpMenu::menuAboutApp)->setWhatsThis(whatsThisAboutApp); + "used libraries and maintainers of this application.")); - const QString whatsThisAboutKDE = xi18nc("@info:whatsthis","This opens a " + actionCollection()->action(KStandardAction::name(KStandardAction::AboutKDE))->setWhatsThis( + xi18nc("@info:whatsthis","This opens a " "window with information about KDE. " "The KDE community are the people behind this free software." "If you like using this application but don't know " - "about KDE or want to see a cute dragon have a look!"); - actionCollection()->action(KStandardAction::name(KStandardAction::AboutKDE)) - ->setWhatsThis(whatsThisAboutKDE); - m_helpMenu->action(KHelpMenu::menuAboutKDE)->setWhatsThis(whatsThisAboutKDE); + "about KDE or want to see a cute dragon have a look!")); } -bool DolphinMainWindow::event(QEvent *event) +bool DolphinMainWindow::addHamburgerMenuToToolbar() { - if (event->type() == QEvent::WhatsThisClicked) { - event->accept(); - QWhatsThisClickedEvent* whatsThisEvent = dynamic_cast(event); - QDesktopServices::openUrl(QUrl(whatsThisEvent->href())); - return true; + QDomDocument domDocument = KXMLGUIClient::domDocument(); + if (domDocument.isNull()) { + return false; + } + QDomNode toolbar = domDocument.elementsByTagName(QStringLiteral("ToolBar")).at(0); + if (toolbar.isNull()) { + return false; } - return KXmlGuiWindow::event(event); + + QDomElement hamburgerMenuElement = domDocument.createElement(QStringLiteral("Action")); + hamburgerMenuElement.setAttribute(QStringLiteral("name"), QStringLiteral("hamburger_menu")); + toolbar.appendChild(hamburgerMenuElement); + + KXMLGUIFactory::saveConfigFile(domDocument, xmlFile()); + reloadXML(); + createGUI(); + return true; + // Make sure to also remove the and include + // whenever this method is removed (maybe in the year ~2026). } -bool DolphinMainWindow::eventFilter(QObject* obj, QEvent* event) +// Set a sane initial window size +QSize DolphinMainWindow::sizeHint() const { - Q_UNUSED(obj) - if (event->type() == QEvent::WhatsThisClicked) { - event->accept(); - QWhatsThisClickedEvent* whatsThisEvent = dynamic_cast(event); - QDesktopServices::openUrl(QUrl(whatsThisEvent->href())); - return true; - } - return false; + return KXmlGuiWindow::sizeHint().expandedTo(QSize(760, 550)); } void DolphinMainWindow::saveNewToolbarConfig() @@ -2468,6 +2635,8 @@ void DolphinMainWindow::saveNewToolbarConfig() m_tabWidget->currentTabPage()->insertNavigatorsWidget(navigators); } updateAllowedToolbarAreas(); + (static_cast(actionCollection()->action(KStandardAction::name( + KStandardAction::HamburgerMenu))))->hideActionsOf(toolBar()); } void DolphinMainWindow::focusTerminalPanel() @@ -2506,8 +2675,12 @@ void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job) } } -bool DolphinMainWindow::isUrlOpen(const QString& url) +bool DolphinMainWindow::isUrlOpen(const QString &url) { - return m_tabWidget->isUrlOpen(QUrl::fromUserInput((url))); + return m_tabWidget->isUrlOpen(QUrl::fromUserInput(url)); } +bool DolphinMainWindow::isItemVisibleInAnyView(const QString &urlOfItem) +{ + return m_tabWidget->isItemVisibleInAnyView(QUrl::fromUserInput(urlOfItem)); +}