File indexing completed on 2024-04-28 09:40:55

0001 /*
0002  * SPDX-FileCopyrightText: 2006 Peter Penz <peter.penz19@gmail.com>
0003  * SPDX-FileCopyrightText: 2006 Stefan Monov <logixoul@gmail.com>
0004  * SPDX-FileCopyrightText: 2006 Cvetoslav Ludmiloff <ludmiloff@gmail.com>
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef DOLPHIN_MAINWINDOW_H
0010 #define DOLPHIN_MAINWINDOW_H
0011 
0012 #include "config-dolphin.h"
0013 #include "dolphintabwidget.h"
0014 #include "selectionmode/bottombar.h"
0015 #include <KFileItemActions>
0016 #include <kio/fileundomanager.h>
0017 #include <kxmlguiwindow.h>
0018 
0019 #if HAVE_BALOO
0020 #include "panels/information/informationpanel.h"
0021 #endif
0022 
0023 #include <QIcon>
0024 #include <QList>
0025 #include <QMenu>
0026 #include <QPointer>
0027 #include <QUrl>
0028 #include <QVector>
0029 
0030 typedef KIO::FileUndoManager::CommandType CommandType;
0031 
0032 class DolphinBookmarkHandler;
0033 class DolphinViewActionHandler;
0034 class DolphinSettingsDialog;
0035 class DolphinViewContainer;
0036 class DolphinRemoteEncoding;
0037 class DolphinTabWidget;
0038 class KFileItem;
0039 class KFileItemList;
0040 class KJob;
0041 class KNewFileMenu;
0042 class KToolBarPopupAction;
0043 class QToolButton;
0044 class PlacesPanel;
0045 class TerminalPanel;
0046 
0047 namespace KIO
0048 {
0049 class OpenUrlJob;
0050 }
0051 namespace SelectionMode
0052 {
0053 class ActionTextHelper;
0054 }
0055 
0056 /**
0057  * @short Main window for Dolphin.
0058  *
0059  * Handles the menus, toolbars and Dolphin views.
0060  */
0061 class DolphinMainWindow : public KXmlGuiWindow
0062 {
0063     Q_OBJECT
0064     Q_CLASSINFO("D-Bus Interface", "org.kde.dolphin.MainWindow")
0065 
0066 public:
0067     DolphinMainWindow();
0068     ~DolphinMainWindow() override;
0069 
0070     /**
0071      * Returns the currently active view.
0072      * All menu actions are applied to this view. When
0073      * having a split view setup, the nonactive view
0074      * is usually shown in darker colors.
0075      */
0076     DolphinViewContainer *activeViewContainer() const;
0077 
0078     /**
0079      * Returns view container for all tabs
0080      */
0081     QVector<DolphinViewContainer *> viewContainers() const;
0082 
0083     /**
0084      * Opens each directory in \p dirs in a separate tab. If \a splitView is set,
0085      * 2 directories are collected within one tab.
0086      * \pre \a dirs must contain at least one url.
0087      */
0088     void openDirectories(const QList<QUrl> &dirs, bool splitView);
0089 
0090     /**
0091      * Opens the directories which contain the files \p files and selects all files.
0092      * If \a splitView is set, 2 directories are collected within one tab.
0093      * \pre \a files must contain at least one url.
0094      */
0095     void openFiles(const QList<QUrl> &files, bool splitView);
0096 
0097     /**
0098      * Returns the 'Create New...' sub menu which also can be shared
0099      * with other menus (e. g. a context menu).
0100      */
0101     KNewFileMenu *newFileMenu() const;
0102 
0103     /**
0104      * Augments Qt's build-in QMainWindow context menu to add
0105      * Dolphin-specific actions, such as "unlock panels".
0106      */
0107     QMenu *createPopupMenu() override;
0108 
0109     /**
0110      * Switch the window's view containers' locations to display the home path
0111      * for any which are currently displaying a location corresponding to or
0112      * within mountPath.
0113      *
0114      * This typically done after unmounting a disk at mountPath to ensure that
0115      * the window is not displaying an invalid location.
0116      */
0117     void setViewsToHomeIfMountPathOpen(const QString &mountPath);
0118 
0119     bool isFoldersPanelEnabled() const;
0120     bool isInformationPanelEnabled() const;
0121     bool isSplitViewEnabledInCurrentTab() const;
0122 
0123 public Q_SLOTS:
0124     /**
0125      * Opens each directory in \p dirs in a separate tab. If \a splitView is set,
0126      * 2 directories are collected within one tab.
0127      * \pre \a dirs must contain at least one url.
0128      *
0129      * @note this function is overloaded so that it is callable via DBus.
0130      */
0131     void openDirectories(const QStringList &dirs, bool splitView);
0132 
0133     /**
0134      * Opens the directories which contain the files \p files and selects all files.
0135      * If \a splitView is set, 2 directories are collected within one tab.
0136      * \pre \a files must contain at least one url.
0137      *
0138      * @note this is overloaded so that this function is callable via DBus.
0139      */
0140     void openFiles(const QStringList &files, bool splitView);
0141 
0142     /**
0143      * Tries to raise/activate the Dolphin window.
0144      */
0145     void activateWindow(const QString &activationToken);
0146 
0147     bool isActiveWindow();
0148 
0149     /**
0150      * Determines if a URL is open in any tab.
0151      * @note Use of QString instead of QUrl is required to be callable via DBus.
0152      *
0153      * @param url URL to look for
0154      * @returns true if url is currently open in a tab, false otherwise.
0155      */
0156     bool isUrlOpen(const QString &url);
0157 
0158     /**
0159      * @return Whether the item with @p url can be found in any view only by switching
0160      * between already open tabs and scrolling in their primary or secondary view.
0161      * @note Use of QString instead of QUrl is required to be callable via DBus.
0162      */
0163     bool isItemVisibleInAnyView(const QString &urlOfItem);
0164 
0165     /**
0166      * Pastes the clipboard data into the currently selected folder
0167      * of the active view. If not exactly one folder is selected,
0168      * no pasting is done at all.
0169      */
0170     void pasteIntoFolder();
0171 
0172     /**
0173      * Implementation of the MainWindowAdaptor/QDBusAbstractAdaptor interface.
0174      * Inform all affected dolphin components (panels, views) of an URL
0175      * change.
0176      */
0177     void changeUrl(const QUrl &url);
0178 
0179     /**
0180      * The current directory of the Terminal Panel has changed, probably because
0181      * the user entered a 'cd' command. This slot calls changeUrl(url) and makes
0182      * sure that the panel keeps the keyboard focus.
0183      */
0184     void slotTerminalDirectoryChanged(const QUrl &url);
0185 
0186     /** Stores all settings and quits Dolphin. */
0187     void quit();
0188 
0189     /**
0190      * Opens a new tab in the background showing the URL \a url.
0191      */
0192     void openNewTab(const QUrl &url);
0193 
0194     /**
0195      * Opens a new tab  showing the URL \a url and activate it.
0196      */
0197     void openNewTabAndActivate(const QUrl &url);
0198 
0199     /**
0200      * Opens a new window showing the URL \a url.
0201      */
0202     void openNewWindow(const QUrl &url);
0203 
0204     /** @see GeneralSettings::splitViewChanged() */
0205     void slotSplitViewChanged();
0206 
0207 Q_SIGNALS:
0208     /**
0209      * Is sent if the selection of the currently active view has
0210      * been changed.
0211      */
0212     void selectionChanged(const KFileItemList &selection);
0213 
0214     /**
0215      * Is sent if the url of the currently active view has
0216      * been changed.
0217      */
0218     void urlChanged(const QUrl &url);
0219 
0220     /**
0221      * Is emitted if information of an item is requested to be shown e. g. in the panel.
0222      * If item is null, no item information request is pending.
0223      */
0224     void requestItemInfo(const KFileItem &item);
0225 
0226     /**
0227      * It is emitted when in the current view, files are changed,
0228      * or dirs have files/removed from them.
0229      */
0230     void fileItemsChanged(const KFileItemList &changedFileItems);
0231 
0232     /**
0233      * Is emitted if the settings have been changed.
0234      */
0235     void settingsChanged();
0236 
0237 protected:
0238     /** @see QObject::event() */
0239     bool event(QEvent *event) override;
0240 
0241     /** @see QWidget::showEvent() */
0242     void showEvent(QShowEvent *event) override;
0243 
0244     /** @see QMainWindow::closeEvent() */
0245     void closeEvent(QCloseEvent *event) override;
0246 
0247     /** @see KMainWindow::saveProperties() */
0248     void saveProperties(KConfigGroup &group) override;
0249 
0250     /** @see KMainWindow::readProperties() */
0251     void readProperties(const KConfigGroup &group) override;
0252 
0253     /** Sets a sane initial window size **/
0254     QSize sizeHint() const override;
0255 
0256 protected Q_SLOTS:
0257     /**
0258      * Calls the base method KXmlGuiWindow::saveNewToolbarConfig().
0259      * Is also used to set toolbar constraints and UrlNavigator position
0260      * based on the newly changed toolbar configuration.
0261      */
0262     void saveNewToolbarConfig() override;
0263 
0264 private Q_SLOTS:
0265     /**
0266      * Refreshes the views of the main window by recreating them according to
0267      * the given Dolphin settings.
0268      */
0269     void refreshViews();
0270 
0271     void clearStatusBar();
0272 
0273     /** Updates the 'Create New...' sub menu. */
0274     void updateNewMenu();
0275 
0276     void createDirectory();
0277 
0278     /** Shows the error message in the status bar of the active view. */
0279     void showErrorMessage(const QString &message);
0280 
0281     /**
0282      * Updates the state of the 'Undo' menu action dependent
0283      * on the parameter \a available.
0284      */
0285     void slotUndoAvailable(bool available);
0286 
0287     /** Sets the text of the 'Undo' menu action to \a text. */
0288     void slotUndoTextChanged(const QString &text);
0289 
0290     /** Performs the current undo operation. */
0291     void undo();
0292 
0293     /**
0294      * Copies all selected items to the clipboard and marks
0295      * the items as cut.
0296      */
0297     void cut();
0298 
0299     /** Copies all selected items to the clipboard. */
0300     void copy();
0301 
0302     /** Pastes the clipboard data to the active view. */
0303     void paste();
0304 
0305     /** Replaces the URL navigator by a search box to find files. */
0306     void find();
0307 
0308     /** Updates the state of the search action according to the view container. */
0309     void updateSearchAction();
0310 
0311     /**
0312      * Updates the text of the paste action dependent on
0313      * the number of items which are in the clipboard.
0314      */
0315     void updatePasteAction();
0316 
0317     /** Calls DolphinViewContainer::setSelectionMode() for m_activeViewContainer. */
0318     void slotSetSelectionMode(bool enabled, SelectionMode::BottomBar::Contents bottomBarContents);
0319 
0320     /** Selects all items from the active view. */
0321     void selectAll();
0322 
0323     /**
0324      * Inverts the selection of all items of the active view:
0325      * Selected items get nonselected and nonselected items get
0326      * selected.
0327      */
0328     void invertSelection();
0329 
0330     /**
0331      * Switches between one and two views:
0332      * If one view is visible, it will get split into two views.
0333      * If already two views are visible, the active view gets closed.
0334      */
0335     void toggleSplitView();
0336 
0337     /** Dedicated action to open the stash:/ ioslave in split view. */
0338     void toggleSplitStash();
0339 
0340     /** Copies all selected items to the inactive view. */
0341     void copyToInactiveSplitView();
0342 
0343     /** Moves all selected items to the inactive view. */
0344     void moveToInactiveSplitView();
0345 
0346     /** Reloads the currently active view. */
0347     void reloadView();
0348 
0349     /** Stops the loading process for the currently active view. */
0350     void stopLoading();
0351 
0352     void enableStopAction();
0353     void disableStopAction();
0354 
0355     void toggleSelectionMode();
0356 
0357     void showFilterBar();
0358     void toggleFilterBar();
0359 
0360     /**
0361      * Toggles between edit and browse mode of the navigation bar.
0362      */
0363     void toggleEditLocation();
0364 
0365     /**
0366      * Switches to the edit mode of the navigation bar and selects
0367      * the whole URL, so that it can be replaced by the user. If the edit mode is
0368      * already active, it is assured that the navigation bar get focused.
0369      */
0370     void replaceLocation();
0371 
0372     /**
0373      * Toggles the state of the panels between a locked and unlocked layout.
0374      */
0375     void togglePanelLockState();
0376 
0377     /**
0378      * Is invoked if the Terminal panel got visible/invisible and takes care
0379      * that the active view has the focus if the Terminal panel is invisible.
0380      */
0381     void slotTerminalPanelVisibilityChanged();
0382 
0383     /** Goes back one step of the URL history. */
0384     void goBack();
0385 
0386     /** Goes forward one step of the URL history. */
0387     void goForward();
0388 
0389     /** Goes up one hierarchy of the current URL. */
0390     void goUp();
0391 
0392     /** Changes the location to the home URL. */
0393     void goHome();
0394 
0395     /** Open the previous URL in the URL history in a new tab. */
0396     void goBackInNewTab();
0397 
0398     /** Open the next URL in the URL history in a new tab. */
0399     void goForwardInNewTab();
0400 
0401     /** Open the URL one hierarchy above the current URL in a new tab. */
0402     void goUpInNewTab();
0403 
0404     /** * Open the home URL in a new tab. */
0405     void goHomeInNewTab();
0406 
0407     /** Opens Kompare for 2 selected files. */
0408     void compareFiles();
0409 
0410     /**
0411      * Hides the menu bar if it is visible, makes the menu bar
0412      * visible if it is hidden.
0413      */
0414     void toggleShowMenuBar();
0415 
0416     /** Updates "Open Preferred Search Tool" action. */
0417     void updateOpenPreferredSearchToolAction();
0418 
0419     /** Opens preferred search tool for the current location. */
0420     void openPreferredSearchTool();
0421 
0422     /** Opens a terminal window for the current location. */
0423     void openTerminal();
0424 
0425     /** Opens terminal windows for the selected items' locations. */
0426     void openTerminalHere();
0427 
0428     /** Opens a terminal window for the URL. */
0429     void openTerminalJob(const QUrl &url);
0430 
0431     /** Focus a Terminal Panel. */
0432     void focusTerminalPanel();
0433 
0434     /** Opens the settings dialog for Dolphin. */
0435     void editSettings();
0436 
0437     /** Updates the state of the 'Show Full Location' action. */
0438     void slotEditableStateChanged(bool editable);
0439 
0440     /**
0441      * Updates the state of the 'Edit' menu actions and emits
0442      * the signal selectionChanged().
0443      */
0444     void slotSelectionChanged(const KFileItemList &selection);
0445 
0446     /**
0447      * Updates the state of the 'Back' and 'Forward' menu
0448      * actions corresponding to the current history.
0449      */
0450     void updateHistory();
0451 
0452     /** Updates the state of the 'Show filter bar' menu action. */
0453     void updateFilterBarAction(bool show);
0454 
0455     /** Open a new main window. */
0456     void openNewMainWindow();
0457 
0458     /**
0459      * Opens a new view with the current URL that is part of a tab and
0460      * activates it.
0461      */
0462     void openNewActivatedTab();
0463 
0464     /**
0465      * Adds the current URL as an entry to the Places panel
0466      */
0467     void addToPlaces();
0468 
0469     /**
0470      * Opens the selected folder in a new tab.
0471      */
0472     void openInNewTab();
0473 
0474     /**
0475      * Opens the selected folder in a new window.
0476      */
0477     void openInNewWindow();
0478 
0479     /**
0480      * Opens the selected folder in the other inactive split view, enables split view if necessary.
0481      */
0482     void openInSplitView(const QUrl &url);
0483 
0484     /**
0485      * Show the target of the selected symlink
0486      */
0487     void showTarget();
0488 
0489     /**
0490      * Indicates in the statusbar that the execution of the command \a command
0491      * has been finished.
0492      */
0493     void showCommand(CommandType command);
0494 
0495     /**
0496      * If the URL can be listed, open it in the current view, otherwise
0497      * run it through KRun.
0498      */
0499     void handleUrl(const QUrl &url);
0500 
0501     /**
0502      * Is invoked when the write state of a folder has been changed and
0503      * enables/disables the "Create New..." menu entry.
0504      */
0505     void slotWriteStateChanged(bool isFolderWritable);
0506 
0507     /**
0508      * Opens the context menu on the current mouse position.
0509      * @pos           Position in screen coordinates.
0510      * @item          File item context. If item is null, the context menu
0511      *                should be applied to \a url.
0512      * @selectedItems The selected items for which the context menu
0513      *                is opened. This list generally includes \a item.
0514      * @url           URL which contains \a item.
0515      */
0516     void openContextMenu(const QPoint &pos, const KFileItem &item, const KFileItemList &selectedItems, const QUrl &url);
0517 
0518     /**
0519      * Updates the menu that is by default at the right end of the toolbar.
0520      *
0521      * In true "simple by default" fashion, the menu only contains the most important
0522      * and necessary actions to be able to use Dolphin. This is supposed to hold true even
0523      * if the user does not know how to open a context menu. More advanced actions can be
0524      * discovered through a sub-menu (@see KConfigWidgets::KHamburgerMenu::setMenuBarAdvertised()).
0525      */
0526     void updateHamburgerMenu();
0527 
0528     /**
0529      * Is called if the user clicked an item in the Places Panel.
0530      * Reloads the view if \a url is the current URL already, and changes the
0531      * current URL otherwise.
0532      */
0533     void slotPlaceActivated(const QUrl &url);
0534 
0535     /**
0536      * Is called if the another view has been activated by changing the current
0537      * tab or activating another view in split-view mode.
0538      *
0539      * Activates the given view, which means that all menu actions are applied
0540      * to this view. When having a split view setup, the nonactive view is
0541      * usually shown in darker colors.
0542      */
0543     void activeViewChanged(DolphinViewContainer *viewContainer);
0544 
0545     void closedTabsCountChanged(unsigned int count);
0546 
0547     /**
0548      * Is called if a new tab has been opened or a tab has been closed to
0549      * enable/disable the tab actions.
0550      */
0551     void tabCountChanged(int count);
0552 
0553     /**
0554      * Updates the Window Title with the caption from the active view container
0555      */
0556     void updateWindowTitle();
0557 
0558     /**
0559      * This slot is called when the user requested to unmount a removable media
0560      * from the places menu
0561      */
0562     void slotStorageTearDownFromPlacesRequested(const QString &mountPath);
0563 
0564     /**
0565      * This slot is called when the user requested to unmount a removable media
0566      * _not_ from the dolphin's places menu (from the notification area for e.g.)
0567      * This slot is basically connected to each removable device's
0568      * Solid::StorageAccess::teardownRequested(const QString & udi)
0569      * signal through the places panel.
0570      */
0571     void slotStorageTearDownExternallyRequested(const QString &mountPath);
0572 
0573     /**
0574      * Is called when the view has finished loading the directory.
0575      */
0576     void slotDirectoryLoadingCompleted();
0577 
0578     /**
0579      * Is called when the user middle clicks a toolbar button.
0580      *
0581      * Here middle clicking Back/Forward/Up/Home will open the resulting
0582      * folder in a new tab.
0583      */
0584     void slotToolBarActionMiddleClicked(QAction *action);
0585 
0586     /**
0587      * Is called before the Back popup menu is shown. This slot will populate
0588      * the menu with history data
0589      */
0590     void slotAboutToShowBackPopupMenu();
0591 
0592     /**
0593       * This slot is used by the Back Popup Menu to go back to a specific
0594       * history index. The QAction::data will carry an int with the index
0595       * to go to.
0596       */
0597     void slotGoBack(QAction *action);
0598 
0599     /**
0600      * Middle clicking Back/Forward will open the resulting folder in a new tab.
0601      */
0602     void slotBackForwardActionMiddleClicked(QAction *action);
0603 
0604     /**
0605      * Is called before the Forward popup menu is shown. This slot will populate
0606      * the menu with history data
0607      */
0608     void slotAboutToShowForwardPopupMenu();
0609 
0610     /**
0611       * This slot is used by the Forward Popup Menu to go forward to a specific
0612       * history index. The QAction::data will carry an int with the index
0613       * to go to.
0614       */
0615     void slotGoForward(QAction *action);
0616 
0617     /**
0618      * Is called when configuring the keyboard shortcuts
0619      */
0620     void slotKeyBindings();
0621 
0622 private:
0623     /**
0624      * Sets up the various menus and actions and connects them.
0625      */
0626     void setupActions();
0627 
0628     /**
0629      * Sets up the dock widgets and their panels.
0630      */
0631     void setupDockWidgets();
0632 
0633     void updateFileAndEditActions();
0634     void updateViewActions();
0635     void updateGoActions();
0636 
0637     /**
0638      * Connects the signals from the created DolphinView with
0639      * the DolphinViewContainer \a container with the corresponding slots of
0640      * the DolphinMainWindow. This method must be invoked each
0641      * time a DolphinView has been created.
0642      */
0643     void connectViewSignals(DolphinViewContainer *container);
0644 
0645     /**
0646      * Updates the text of the split action:
0647      * If two views are shown, the text is set to "Split",
0648      * otherwise the text is set to "Join". The icon
0649      * is updated to match with the text and the currently active view.
0650      */
0651     void updateSplitAction();
0652 
0653     /**
0654      * Sets the window sides the toolbar may be moved to based on toolbar contents.
0655      */
0656     void updateAllowedToolbarAreas();
0657 
0658     bool isKompareInstalled() const;
0659 
0660     /**
0661      * Creates an action for showing/hiding a panel, that is accessible
0662      * in "Configure toolbars..." and "Configure shortcuts...".
0663      */
0664     void createPanelAction(const QIcon &icon, const QKeySequence &shortcut, QDockWidget *dockAction, const QString &actionName);
0665 
0666     /** Adds "What's This?" texts to many widgets and StandardActions. */
0667     void setupWhatsThis();
0668 
0669     /** Returns preferred search tool as configured in "More Search Tools" menu. */
0670     QPointer<QAction> preferredSearchTool();
0671 
0672     /**
0673      * Adds this action to the mainWindow's toolbar and saves the change
0674      * in the users ui configuration file.
0675      * This method is only needed for migration and should be removed once we can expect
0676      * that pretty much all users have been migrated. Remove in 2026 because that's when
0677      * even the most risk-averse distros will already have been forced to upgrade.
0678      * @return true if successful. Otherwise false.
0679      */
0680     bool addHamburgerMenuToToolbar();
0681 
0682     /** Creates an action representing an item in the URL navigator history */
0683     static QAction *urlNavigatorHistoryAction(const KUrlNavigator *urlNavigator, int historyIndex, QObject *parent = nullptr);
0684 
0685 private:
0686     /**
0687      * Implements a custom error handling for the undo manager. This
0688      * assures that all errors are shown in the status bar of Dolphin
0689      * instead as modal error dialog with an OK button.
0690      */
0691     class UndoUiInterface : public KIO::FileUndoManager::UiInterface
0692     {
0693     public:
0694         UndoUiInterface();
0695         ~UndoUiInterface() override;
0696         void jobError(KIO::Job *job) override;
0697     };
0698 
0699     KNewFileMenu *m_newFileMenu;
0700     DolphinTabWidget *m_tabWidget;
0701     DolphinViewContainer *m_activeViewContainer;
0702 
0703     DolphinViewActionHandler *m_actionHandler;
0704     DolphinRemoteEncoding *m_remoteEncoding;
0705     QPointer<DolphinSettingsDialog> m_settingsDialog;
0706     DolphinBookmarkHandler *m_bookmarkHandler;
0707     SelectionMode::ActionTextHelper *m_actionTextHelper;
0708 
0709     KIO::OpenUrlJob *m_lastHandleUrlOpenJob;
0710 
0711     TerminalPanel *m_terminalPanel;
0712     PlacesPanel *m_placesPanel;
0713     bool m_tearDownFromPlacesRequested;
0714 
0715     KToolBarPopupAction *m_backAction;
0716     KToolBarPopupAction *m_forwardAction;
0717 
0718     QMenu m_searchTools;
0719     KFileItemActions m_fileItemActions;
0720 
0721     friend class DolphinMainWindowTest;
0722 };
0723 
0724 inline DolphinViewContainer *DolphinMainWindow::activeViewContainer() const
0725 {
0726     return m_activeViewContainer;
0727 }
0728 
0729 inline KNewFileMenu *DolphinMainWindow::newFileMenu() const
0730 {
0731     return m_newFileMenu;
0732 }
0733 
0734 #endif // DOLPHIN_MAINWINDOW_H