File indexing completed on 2024-04-21 15:00:23

0001 /*
0002     SPDX-FileCopyrightText: 2006-2010 Peter Penz <peter.penz@gmx.at>
0003     SPDX-FileCopyrightText: 2006 Aaron J. Seigo <aseigo@kde.org>
0004     SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
0005     SPDX-FileCopyrightText: 2007 Urs Wolfer <uwolfer @ kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef KURLNAVIGATOR_H
0011 #define KURLNAVIGATOR_H
0012 
0013 #include "kiofilewidgets_export.h"
0014 
0015 #include <QByteArray>
0016 #include <QUrl>
0017 #include <QWidget>
0018 
0019 #include <memory>
0020 
0021 class QMouseEvent;
0022 
0023 class KFilePlacesModel;
0024 class KUrlComboBox;
0025 
0026 class KUrlNavigatorPrivate;
0027 
0028 /**
0029  * @class KUrlNavigator kurlnavigator.h <KUrlNavigator>
0030  *
0031  * @brief Widget that allows to navigate through the paths of an URL.
0032  *
0033  * The URL navigator offers two modes:
0034  * - Editable:     The URL of the location is editable inside an editor.
0035  *                 By pressing RETURN the URL will get activated.
0036  * - Non editable ("breadcrumb view"): The URL of the location is represented by
0037  *                 a number of buttons, where each button represents a path
0038  *                 of the URL. By clicking on a button the path will get
0039  *                 activated. This mode also supports drag and drop of items.
0040  *
0041  * The mode can be changed by clicking on the empty area of the URL navigator.
0042  * It is recommended that the application remembers the setting
0043  * or allows to configure the default mode (see KUrlNavigator::setUrlEditable()).
0044  *
0045  * The URL navigator remembers the URL history during navigation and allows to go
0046  * back and forward within this history.
0047  *
0048  * In the non editable mode ("breadcrumb view") it can be configured whether
0049  * the full path should be shown. It is recommended that the application
0050  * remembers the setting or allows to configure the default mode (see
0051  * KUrlNavigator::setShowFullPath()).
0052  *
0053  * The typical usage of the KUrlNavigator is:
0054  * - Create an instance providing a places model and an URL.
0055  * - Create an instance of QAbstractItemView which shows the content of the URL
0056  *   given by the URL navigator.
0057  * - Connect to the signal KUrlNavigator::urlChanged() and synchronize the content of
0058  *   QAbstractItemView with the URL given by the URL navigator.
0059  *
0060  * It is recommended, that the application remembers the state of the QAbstractItemView
0061  * when the URL has been changed. This allows to restore the view state when going back in history.
0062  * KUrlNavigator offers support for remembering the view state:
0063  * - The signal urlAboutToBeChanged() will be emitted before the URL change takes places.
0064  *   This allows the application to store the view state by KUrlNavigator::saveLocationState().
0065  * - The signal urlChanged() will be emitted after the URL change took place. This allows
0066  *   the application to restore the view state by getting the values from
0067  *   KUrlNavigator::locationState().
0068  */
0069 class KIOFILEWIDGETS_EXPORT KUrlNavigator : public QWidget
0070 {
0071     Q_OBJECT
0072 
0073 public:
0074     /** @since 4.5 */
0075     KUrlNavigator(QWidget *parent = nullptr);
0076 
0077     /**
0078      * @param placesModel    Model for the places which are selectable inside a
0079      *                       menu. A place can be a bookmark or a device. If it is 0,
0080      *                       no places selector is displayed.
0081      * @param url            URL which is used for the navigation or editing.
0082      * @param parent         Parent widget.
0083      */
0084     KUrlNavigator(KFilePlacesModel *placesModel, const QUrl &url, QWidget *parent);
0085     ~KUrlNavigator() override;
0086 
0087     /**
0088      * @return URL of the location given by the \a historyIndex. If \a historyIndex
0089      *         is smaller than 0, the URL of the current location is returned.
0090      * @since  4.5
0091      */
0092     QUrl locationUrl(int historyIndex = -1) const;
0093 
0094     /**
0095      * Saves the location state described by \a state for the current location. It is recommended
0096      * that at least the scroll position of a view is remembered and restored when traversing
0097      * through the history. Saving the location state should be done when the signal
0098      * KUrlNavigator::urlAboutToBeChanged() has been emitted. Restoring the location state (see
0099      * KUrlNavigator::locationState()) should be done when the signal KUrlNavigator::urlChanged()
0100      * has been emitted.
0101      *
0102      * Example:
0103      * \code
0104      * QByteArray state;
0105      * QDataStream data(&state, QIODevice::WriteOnly);
0106      * data << QPoint(x, y);
0107      * data << ...;
0108      * ...
0109      * urlNavigator->saveLocationState(state);
0110      * \endcode
0111      *
0112      * @since 4.5
0113      */
0114     void saveLocationState(const QByteArray &state);
0115 
0116     /**
0117      * @return Location state given by \a historyIndex. If \a historyIndex
0118      *         is smaller than 0, the state of the current location is returned.
0119      * @see    KUrlNavigator::saveLocationState()
0120      * @since  4.5
0121      */
0122     QByteArray locationState(int historyIndex = -1) const;
0123 
0124     /**
0125      * Goes back one step in the URL history. The signals
0126      * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and
0127      * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned
0128      * if the beginning of the history has already been reached and hence going back was
0129      * not possible. The history index (see KUrlNavigator::historyIndex()) is
0130      * increased by one if the operation was successful.
0131      */
0132     bool goBack();
0133 
0134     /**
0135      * Goes forward one step in the URL history. The signals
0136      * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and
0137      * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned
0138      * if the end of the history has already been reached and hence going forward
0139      * was not possible. The history index (see KUrlNavigator::historyIndex()) is
0140      * decreased by one if the operation was successful.
0141      */
0142     bool goForward();
0143 
0144     /**
0145      * Goes up one step of the URL path and remembers the old path
0146      * in the history. The signals KUrlNavigator::urlAboutToBeChanged(),
0147      * KUrlNavigator::urlChanged() and KUrlNavigator::historyChanged() are
0148      * emitted if true is returned. False is returned if going up was not
0149      * possible as the root has been reached.
0150      */
0151     bool goUp();
0152 
0153     /**
0154      * Goes to the home URL and remembers the old URL in the history.
0155      * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged()
0156      * and KUrlNavigator::historyChanged() are emitted.
0157      *
0158      * @see KUrlNavigator::setHomeUrl()
0159      */
0160     // KDE5: Remove the home-property. It is sufficient to invoke
0161     // KUrlNavigator::setLocationUrl(homeUrl) on application-side.
0162     void goHome();
0163 
0164     /**
0165      * Sets the home URL used by KUrlNavigator::goHome(). If no
0166      * home URL is set, the default home path of the user is used.
0167      * @since 4.5
0168      */
0169     // KDE5: Remove the home-property. It is sufficient to invoke
0170     // KUrlNavigator::setLocationUrl(homeUrl) on application-side.
0171     void setHomeUrl(const QUrl &url);
0172 
0173     QUrl homeUrl() const;
0174 
0175     /**
0176      * Allows to edit the URL of the navigation bar if \a editable
0177      * is true, and sets the focus accordingly.
0178      * If \a editable is false, each part of
0179      * the URL is presented by a button for a fast navigation ("breadcrumb view").
0180      */
0181     void setUrlEditable(bool editable);
0182 
0183     /**
0184      * @return True, if the URL is editable within a line editor.
0185      *         If false is returned, each part of the URL is presented by a button
0186      *         for fast navigation ("breadcrumb view").
0187      */
0188     bool isUrlEditable() const;
0189 
0190     /**
0191      * Shows the full path of the URL even if a place represents a part of the URL.
0192      * Assuming that a place called "Pictures" uses the URL /home/user/Pictures.
0193      * An URL like /home/user/Pictures/2008 is shown as [Pictures] > [2008]
0194      * in the breadcrumb view, if showing the full path is turned off. If
0195      * showing the full path is turned on, the URL is shown
0196      * as [/] > [home] > [Pictures] > [2008].
0197      * @since 4.2
0198      */
0199     void setShowFullPath(bool show);
0200 
0201     /**
0202      * @return True, if the full path of the URL should be shown in the breadcrumb view.
0203      * @since  4.2
0204      */
0205     bool showFullPath() const;
0206 
0207     /**
0208      * Set the URL navigator to the active mode, if \a active
0209      * is true. The active mode is default. The inactive mode only differs
0210      * visually from the active mode, no change of the behavior is given.
0211      *
0212      * Using the URL navigator in the inactive mode is useful when having split views,
0213      * where the inactive view is indicated by an inactive URL
0214      * navigator visually.
0215      */
0216     void setActive(bool active);
0217 
0218     /**
0219      * @return True, if the URL navigator is in the active mode.
0220      * @see    KUrlNavigator::setActive()
0221      */
0222     bool isActive() const;
0223 
0224     /**
0225      * Sets the places selector visible, if \a visible is true.
0226      * The places selector allows to select the places provided
0227      * by the places model passed in the constructor. Per default
0228      * the places selector is visible.
0229      */
0230     void setPlacesSelectorVisible(bool visible);
0231 
0232     /** @return True, if the places selector is visible. */
0233     bool isPlacesSelectorVisible() const;
0234 
0235     /**
0236      * @return The currently entered, but not accepted URL.
0237      *         It is possible that the returned URL is not valid.
0238      */
0239     QUrl uncommittedUrl() const;
0240 
0241     /**
0242      * @return The amount of locations in the history. The data for each
0243      *         location can be retrieved by KUrlNavigator::locationUrl() and
0244      *         KUrlNavigator::locationState().
0245      */
0246     int historySize() const;
0247 
0248     /**
0249      * @return  The history index of the current location, where
0250      *          0 <= history index < KUrlNavigator::historySize(). 0 is the most
0251      *          recent history entry.
0252      */
0253     int historyIndex() const;
0254 
0255     /**
0256      * @return The used editor when the navigator is in the edit mode
0257      * @see    KUrlNavigator::setUrlEditable()
0258      */
0259     KUrlComboBox *editor() const;
0260 
0261 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(5, 103)
0262     /**
0263      * If an application supports only some special protocols, they can be set
0264      * with \a protocols .
0265      * @deprecated Since 5.103, use setSupportedSchemes(const QStringList &) instead.
0266      */
0267     KIOFILEWIDGETS_DEPRECATED_VERSION(5, 103, "Use KUrlNavigator::setSupportedSchemes(const QStringList &)")
0268     void setCustomProtocols(const QStringList &protocols);
0269 #endif
0270 
0271 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(5, 103)
0272     /**
0273      * @return The custom protocols if they are set, QStringList() otherwise.
0274      * @deprecated Since 5.103, use supportedSchemes() const instead.
0275      */
0276     KIOFILEWIDGETS_DEPRECATED_VERSION(5, 103, "Use KUrlNavigator::supportedSchemes() const")
0277     QStringList customProtocols() const;
0278 #endif
0279 
0280     /**
0281      * Set the URL schemes that the navigator should allow navigating to.
0282      *
0283      * If the passed list is empty, all schemes are supported. Examples for
0284      * schemes are @c "file" or @c "ftp".
0285      *
0286      * @sa QFileDialog::setSupportedSchemes
0287      * @since 5.103
0288      */
0289     void setSupportedSchemes(const QStringList &schemes);
0290 
0291     /**
0292      * Returns the URL schemes that the navigator should allow navigating to.
0293      *
0294      * If the returned list is empty, all schemes are supported.
0295      *
0296      * @sa QFileDialog::supportedSchemes
0297      * @since 5.103
0298      */
0299     QStringList supportedSchemes() const;
0300 
0301     /**
0302      * The child widget that received the QDropEvent when dropping on the URL
0303      * navigator. You can pass this widget to KJobWidgets::setWindow()
0304      * if you need to show a drop menu with KIO::drop().
0305      * @return Child widget that has received the last drop event, or nullptr if
0306      *         nothing has been dropped yet on the URL navigator.
0307      * @since 5.37
0308      * @see KIO::drop()
0309      */
0310     QWidget *dropWidget() const;
0311 
0312     /**
0313      * Sets whether to show hidden folders in the subdirectories popup.
0314      * @since 5.87
0315      */
0316     void setShowHiddenFolders(bool showHiddenFolders);
0317 
0318     /**
0319      * Returns whether to show hidden folders in the subdirectories popup.
0320      * @since 5.87
0321      */
0322     bool showHiddenFolders() const;
0323 
0324     /**
0325      * Sets whether to sort hidden folders in the subdirectories popup last.
0326      * @since 5.87
0327      */
0328     void setSortHiddenFoldersLast(bool sortHiddenFoldersLast);
0329 
0330     /**
0331      * Returns whether to sort hidden folders in the subdirectories popup last.
0332      * @since 5.87
0333      */
0334     bool sortHiddenFoldersLast() const;
0335 
0336 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0337     /**
0338      * @return     The current URL of the location.
0339      * @deprecated Since 4.5, use KUrlNavigator::locationUrl() instead.
0340      */
0341     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationUrl(int)")
0342     const QUrl &url() const;
0343 #endif
0344 
0345 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0346     /**
0347      * @return The portion of the current URL up to the path part given
0348      * by \a index. Assuming that the current URL is /home/peter/Documents/Music,
0349      * then the following URLs are returned for an index:
0350      * - index <= 0: /home
0351      * - index is 1: /home/peter
0352      * - index is 2: /home/peter/Documents
0353      * - index >= 3: /home/peter/Documents/Music
0354      * @deprecated Since 4.5. It should not be necessary for a client of KUrlNavigator to query this information.
0355      */
0356     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Do not use")
0357     QUrl url(int index) const;
0358 #endif
0359 
0360 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0361     /**
0362      * @return URL for the history element with the index \a historyIndex.
0363      *         The history index 0 represents the most recent URL.
0364      * @since 4.3
0365      * @deprecated Since 4.5, use KUrlNavigator::locationUrl(historyIndex) instead.
0366      */
0367     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationUrl(int)")
0368     QUrl historyUrl(int historyIndex) const;
0369 #endif
0370 
0371 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0372     /**
0373      * @return The saved root URL for the current URL (see KUrlNavigator::saveRootUrl()).
0374      * @deprecated Since 4.5, use KUrlNavigator::locationState() instead.
0375      */
0376     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationState(int)")
0377     const QUrl &savedRootUrl() const;
0378 #endif
0379 
0380 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0381     /**
0382      * @return The saved contents position of the upper left corner
0383      *         for the current URL.
0384      * @deprecated Since 4.5, use KUrlNavigator::locationState() instead.
0385      */
0386     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationState(int)")
0387     QPoint savedPosition() const;
0388 #endif
0389 
0390 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0391     /** @deprecated Since 4.5, use setHomeUrl(const QUrl& url) instead. */
0392     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::setHomeUrl(const QUrl&)")
0393     void setHomeUrl(const QString &homeUrl);
0394 #endif
0395 
0396 public Q_SLOTS:
0397     /**
0398      * Sets the location to \a url. The old URL is added to the history.
0399      * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged()
0400      * and KUrlNavigator::historyChanged() are emitted. Use
0401      * KUrlNavigator::locationUrl() to read the location.
0402      * @since 4.5
0403      */
0404     void setLocationUrl(const QUrl &url);
0405 
0406     /**
0407      * Activates the URL navigator (KUrlNavigator::isActive() will return true)
0408      * and emits the signal KUrlNavigator::activated().
0409      * @see KUrlNavigator::setActive()
0410      */
0411     void requestActivation();
0412 
0413 #if !defined(K_DOXYGEN)
0414     // KDE5: Remove and listen for focus-signal instead
0415     void setFocus();
0416 #endif
0417 
0418 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0419     /**
0420      * Sets the location to \a url.
0421      * @deprecated Since 4.5, use KUrlNavigator::setLocationUrl(url).
0422      */
0423     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::setLocationUrl(const QUrl&))")
0424     void setUrl(const QUrl &url);
0425 #endif
0426 
0427 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0428     /**
0429      * Saves the used root URL of the content for the current history element.
0430      * @deprecated Since 4.5, use KUrlNavigator::saveLocationState() instead.
0431      */
0432     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::saveLocationState(const QByteArray &)")
0433     void saveRootUrl(const QUrl &url);
0434 #endif
0435 
0436 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5)
0437     /**
0438      * Saves the coordinates of the contents for the current history element.
0439      * @deprecated Since 4.5, use KUrlNavigator::saveLocationState() instead.
0440      */
0441     KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::saveLocationState(const QByteArray &)")
0442     void savePosition(int x, int y);
0443 #endif
0444 
0445 Q_SIGNALS:
0446     /**
0447      * Is emitted, if the URL navigator has been activated by
0448      * an user interaction
0449      * @see KUrlNavigator::setActive()
0450      */
0451     void activated();
0452 
0453     /**
0454      * Is emitted, if the location URL has been changed e. g. by
0455      * the user.
0456      * @see KUrlNavigator::setUrl()
0457      */
0458     void urlChanged(const QUrl &url);
0459 
0460     /**
0461      * Is emitted, before the location URL is going to be changed to \a newUrl.
0462      * The signal KUrlNavigator::urlChanged() will be emitted after the change
0463      * has been done. Connecting to this signal is useful to save the state
0464      * of a view with KUrlNavigator::saveLocationState().
0465      * @since 4.5
0466      */
0467     void urlAboutToBeChanged(const QUrl &newUrl);
0468 
0469     /**
0470      * Is emitted, if the editable state for the URL has been changed
0471      * (see KUrlNavigator::setUrlEditable()).
0472      */
0473     void editableStateChanged(bool editable);
0474 
0475     /**
0476      * Is emitted, if the history has been changed. Usually
0477      * the history is changed if a new URL has been selected.
0478      */
0479     void historyChanged();
0480 
0481     /**
0482      * Is emitted if a dropping has been done above the destination
0483      * \a destination. The receiver must accept the drop event if
0484      * the dropped data can be handled.
0485      * @since 4.2
0486      */
0487     void urlsDropped(const QUrl &destination, QDropEvent *event);
0488 
0489     /**
0490      * This signal is emitted when the Return or Enter key is pressed.
0491      */
0492     void returnPressed();
0493 
0494     /**
0495      * Is emitted if the URL \a url should be opened in a new inactive tab because
0496      * the user clicked on a breadcrumb with the middle mouse button or
0497      * left-clicked with the ctrl modifier pressed.
0498      * @since 4.5
0499      */
0500     void tabRequested(const QUrl &url);
0501 
0502     /**
0503      * Is emitted if the URL \a url should be opened in a new active tab because
0504      * the user clicked on a breadcrumb with the middle mouse button with
0505      * the shift modifier pressed or left-clicked with both the ctrl and shift
0506      * modifiers pressed.
0507      * @since 5.89
0508      */
0509     void activeTabRequested(const QUrl &url);
0510 
0511     /**
0512      * Is emitted if the URL \a url should be opened in a new window because
0513      * the user left-clicked on a breadcrumb with the shift modifier pressed.
0514      * @since 5.89
0515      */
0516     void newWindowRequested(const QUrl &url);
0517 
0518     /**
0519      * When the URL is changed and the new URL (e.g.\ /home/user1/)
0520      * is a parent of the previous URL (e.g.\ /home/user1/data/stuff),
0521      * then this signal is emitted and \p url is set to the child
0522      * directory of the new URL which is an ancestor of the old URL
0523      * (in the example paths this would be /home/user1/data/).
0524      * This signal allows file managers to pre-select the directory
0525      * that the user is navigating up from.
0526      * @since 5.37.0
0527      */
0528     void urlSelectionRequested(const QUrl &url);
0529 
0530 protected:
0531 #if !defined(K_DOXYGEN)
0532     /**
0533      * If the Escape key is pressed, the navigation bar should switch
0534      * to the breadcrumb view.
0535      * @see QWidget::keyPressEvent()
0536      */
0537     void keyPressEvent(QKeyEvent *event) override;
0538 
0539     /**
0540      * Reimplemented for internal purposes.
0541      */
0542     void keyReleaseEvent(QKeyEvent *event) override;
0543 
0544     /**
0545      * Paste the clipboard content as URL, if the middle mouse
0546      * button has been clicked.
0547      * @see QWidget::mouseReleaseEvent()
0548      */
0549     void mouseReleaseEvent(QMouseEvent *event) override;
0550 
0551     /**
0552      * Reimplemented to activate on middle mousse button click
0553      */
0554     void mousePressEvent(QMouseEvent *event) override;
0555 
0556     void resizeEvent(QResizeEvent *event) override;
0557 
0558     void wheelEvent(QWheelEvent *event) override;
0559 
0560     bool eventFilter(QObject *watched, QEvent *event) override;
0561 #endif
0562 
0563 private:
0564     friend class KUrlNavigatorPrivate;
0565     std::unique_ptr<KUrlNavigatorPrivate> const d;
0566 
0567     Q_DISABLE_COPY(KUrlNavigator)
0568 };
0569 
0570 #endif