1/*
2 SPDX-FileCopyrightText: 2006-2010 Peter Penz <peter.penz@gmx.at>
3 SPDX-FileCopyrightText: 2006 Aaron J. Seigo <aseigo@kde.org>
4 SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
5 SPDX-FileCopyrightText: 2007 Urs Wolfer <uwolfer @ kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#ifndef KURLNAVIGATOR_H
11#define KURLNAVIGATOR_H
12
13#include "kiofilewidgets_export.h"
14
15#include <QByteArray>
16#include <QUrl>
17#include <QWidget>
18
19#include <memory>
20
21class QMouseEvent;
22
23class KFilePlacesModel;
24class KUrlComboBox;
25
26class KUrlNavigatorPrivate;
27
28/*!
29 * \class KUrlNavigator
30 * \inmodule KIOFileWidgets
31 *
32 * \brief Widget that allows to navigate through the paths of an URL.
33 *
34 * The URL navigator offers two modes:
35 * \list
36 * \li Editable: The URL of the location is editable inside an editor.
37 * By pressing RETURN the URL will get activated.
38 * \li Non editable ("breadcrumb view"): The URL of the location is represented by
39 * a number of buttons, where each button represents a path
40 * of the URL. By clicking on a button the path will get
41 * activated. This mode also supports drag and drop of items.
42 * \endlist
43 *
44 * The mode can be changed by clicking on the empty area of the URL navigator.
45 * It is recommended that the application remembers the setting
46 * or allows to configure the default mode (see KUrlNavigator::setUrlEditable()).
47 *
48 * The URL navigator remembers the URL history during navigation and allows to go
49 * back and forward within this history.
50 *
51 * In the non editable mode ("breadcrumb view") it can be configured whether
52 * the full path should be shown. It is recommended that the application
53 * remembers the setting or allows to configure the default mode (see
54 * KUrlNavigator::setShowFullPath()).
55 *
56 * The typical usage of the KUrlNavigator is:
57 * \list
58 * \li Create an instance providing a places model and an URL.
59 * \li Create an instance of QAbstractItemView which shows the content of the URL
60 * given by the URL navigator.
61 * \li Connect to the signal KUrlNavigator::urlChanged() and synchronize the content of
62 * QAbstractItemView with the URL given by the URL navigator.
63 * \endlist
64 *
65 * It is recommended, that the application remembers the state of the QAbstractItemView
66 * when the URL has been changed. This allows to restore the view state when going back in history.
67 * KUrlNavigator offers support for remembering the view state:
68 * \list
69 * \li The signal urlAboutToBeChanged() will be emitted before the URL change takes places.
70 * This allows the application to store the view state by KUrlNavigator::saveLocationState().
71 * \li The signal urlChanged() will be emitted after the URL change took place. This allows
72 * the application to restore the view state by getting the values from
73 * KUrlNavigator::locationState().
74 * \endlist
75 */
76class KIOFILEWIDGETS_EXPORT KUrlNavigator : public QWidget
77{
78 Q_OBJECT
79
80public:
81 /*! \since 4.5 */
82 KUrlNavigator(QWidget *parent = nullptr);
83
84 /*!
85 * \a placesModel Model for the places which are selectable inside a
86 * menu. A place can be a bookmark or a device. If it is 0,
87 * no places selector is displayed.
88 *
89 * \a url URL which is used for the navigation or editing.
90 *
91 * \a parent Parent widget.
92 */
93 KUrlNavigator(KFilePlacesModel *placesModel, const QUrl &url, QWidget *parent);
94 ~KUrlNavigator() override;
95
96 /*!
97 * Returns URL of the location given by the \a historyIndex. If \a historyIndex
98 * is smaller than 0, the URL of the current location is returned.
99 * \since 4.5
100 */
101 QUrl locationUrl(int historyIndex = -1) const;
102
103 /*!
104 * Saves the location state described by \a state for the current location. It is recommended
105 * that at least the scroll position of a view is remembered and restored when traversing
106 * through the history. Saving the location state should be done when the signal
107 * KUrlNavigator::urlAboutToBeChanged() has been emitted. Restoring the location state (see
108 * KUrlNavigator::locationState()) should be done when the signal KUrlNavigator::urlChanged()
109 * has been emitted.
110 *
111 * Example:
112 * \code
113 * QByteArray state;
114 * QDataStream data(&state, QIODevice::WriteOnly);
115 * data << QPoint(x, y);
116 * data << ...;
117 * ...
118 * urlNavigator->saveLocationState(state);
119 * \endcode
120 *
121 */
122 void saveLocationState(const QByteArray &state);
123
124 /*!
125 * Returns Location state given by \a historyIndex. If \a historyIndex
126 * is smaller than 0, the state of the current location is returned.
127 * \sa KUrlNavigator::saveLocationState()
128 * \since 4.5
129 */
130 QByteArray locationState(int historyIndex = -1) const;
131
132 /*!
133 * Goes back one step in the URL history. The signals
134 * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and
135 * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned
136 * if the beginning of the history has already been reached and hence going back was
137 * not possible. The history index (see KUrlNavigator::historyIndex()) is
138 * increased by one if the operation was successful.
139 */
140 bool goBack();
141
142 /*!
143 * Goes forward one step in the URL history. The signals
144 * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and
145 * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned
146 * if the end of the history has already been reached and hence going forward
147 * was not possible. The history index (see KUrlNavigator::historyIndex()) is
148 * decreased by one if the operation was successful.
149 */
150 bool goForward();
151
152 /*!
153 * Goes up one step of the URL path and remembers the old path
154 * in the history. The signals KUrlNavigator::urlAboutToBeChanged(),
155 * KUrlNavigator::urlChanged() and KUrlNavigator::historyChanged() are
156 * emitted if true is returned. False is returned if going up was not
157 * possible as the root has been reached.
158 */
159 bool goUp();
160
161 // KDE5: Remove the home-property. It is sufficient to invoke
162 // KUrlNavigator::setLocationUrl(homeUrl) on application-side.
163 /*!
164 * Goes to the home URL and remembers the old URL in the history.
165 * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged()
166 * and KUrlNavigator::historyChanged() are emitted.
167 *
168 * \sa setHomeUrl()
169 */
170 void goHome();
171
172 // KDE5: Remove the home-property. It is sufficient to invoke
173 // KUrlNavigator::setLocationUrl(homeUrl) on application-side.
174 /*!
175 * Sets the home URL used by KUrlNavigator::goHome(). If no
176 * home URL is set, the default home path of the user is used.
177 */
178 void setHomeUrl(const QUrl &url);
179
180 /*!
181 *
182 */
183 QUrl homeUrl() const;
184
185 /*!
186 * Allows to edit the URL of the navigation bar if \a editable
187 * is true, and sets the focus accordingly.
188 * If \a editable is false, each part of
189 * the URL is presented by a button for a fast navigation ("breadcrumb view").
190 */
191 void setUrlEditable(bool editable);
192
193 /*!
194 * Returns \c true, if the URL is editable within a line editor.
195 * If false is returned, each part of the URL is presented by a button
196 * for fast navigation ("breadcrumb view").
197 */
198 bool isUrlEditable() const;
199
200 /*!
201 * Shows the full path of the URL even if a place represents a part of the URL.
202 * Assuming that a place called "Pictures" uses the URL /home/user/Pictures.
203 * An URL like /home/user/Pictures/2008 is shown as [Pictures] > [2008]
204 * in the breadcrumb view, if showing the full path is turned off. If
205 * showing the full path is turned on, the URL is shown
206 * as [/] > [home] > [Pictures] > [2008].
207 */
208 void setShowFullPath(bool show);
209
210 /*!
211 * Returns \c true, if the full path of the URL should be shown in the breadcrumb view.
212 * \since 4.2
213 */
214 bool showFullPath() const;
215
216 /*!
217 * Set the URL navigator to the active mode, if \a active
218 * is true. The active mode is default. The inactive mode only differs
219 * visually from the active mode, no change of the behavior is given.
220 *
221 * Using the URL navigator in the inactive mode is useful when having split views,
222 * where the inactive view is indicated by an inactive URL
223 * navigator visually.
224 */
225 void setActive(bool active);
226
227 /*!
228 * Returns \c true, if the URL navigator is in the active mode.
229 * \sa setActive()
230 */
231 bool isActive() const;
232
233 /*!
234 * Sets the places selector visible, if \a visible is true.
235 * The places selector allows to select the places provided
236 * by the places model passed in the constructor. Per default
237 * the places selector is visible.
238 */
239 void setPlacesSelectorVisible(bool visible);
240
241 /*! Returns \c true, if the places selector is visible. */
242 bool isPlacesSelectorVisible() const;
243
244 /*!
245 * Returns the currently entered, but not accepted URL.
246 * It is possible that the returned URL is not valid.
247 */
248 QUrl uncommittedUrl() const;
249
250 /*!
251 * Returns the amount of locations in the history. The data for each
252 * location can be retrieved by KUrlNavigator::locationUrl() and
253 * KUrlNavigator::locationState().
254 */
255 int historySize() const;
256
257 /*!
258 * Returns the history index of the current location, where
259 * 0 <= history index < KUrlNavigator::historySize(). 0 is the most
260 * recent history entry.
261 */
262 int historyIndex() const;
263
264 /*!
265 * Returns the used editor when the navigator is in the edit mode
266 * \sa KUrlNavigator::setUrlEditable()
267 */
268 KUrlComboBox *editor() const;
269
270 /*!
271 * Set the URL schemes that the navigator should allow navigating to.
272 *
273 * If the passed list is empty, all schemes are supported. Examples for
274 * schemes are \c "file" or \c "ftp".
275 *
276 * \sa QFileDialog::setSupportedSchemes
277 * \since 5.103
278 */
279 void setSupportedSchemes(const QStringList &schemes);
280
281 /*!
282 * Returns the URL schemes that the navigator should allow navigating to.
283 *
284 * If the returned list is empty, all schemes are supported.
285 *
286 * \sa QFileDialog::supportedSchemes
287 * \since 5.103
288 */
289 QStringList supportedSchemes() const;
290
291 /*!
292 * The child widget that received the QDropEvent when dropping on the URL
293 * navigator. You can pass this widget to KJobWidgets::setWindow()
294 * if you need to show a drop menu with KIO::drop().
295 *
296 * Returns Child widget that has received the last drop event, or nullptr if
297 * nothing has been dropped yet on the URL navigator.
298 * \since 5.37
299 * \sa KIO::drop()
300 */
301 QWidget *dropWidget() const;
302
303 /*!
304 * Sets whether to show hidden folders in the subdirectories popup.
305 * \since 5.87
306 */
307 void setShowHiddenFolders(bool showHiddenFolders);
308
309 /*!
310 * Returns whether to show hidden folders in the subdirectories popup.
311 * \since 5.87
312 */
313 bool showHiddenFolders() const;
314
315 /*!
316 * Sets whether to sort hidden folders in the subdirectories popup last.
317 * \since 5.87
318 */
319 void setSortHiddenFoldersLast(bool sortHiddenFoldersLast);
320
321 /*!
322 * Returns whether to sort hidden folders in the subdirectories popup last.
323 * \since 5.87
324 */
325 bool sortHiddenFoldersLast() const;
326
327 /*!
328 * Puts \a widget to the right of the breadcrumb.
329 *
330 * KUrlNavigator takes ownership over \a widget. Any existing badge widget is deleted.
331 *
332 * \note There is no limit to the size of the badge widget. If your badge widget is taller than other
333 * controls in KUrlNavigator, then the whole KUrlNavigator will be resized to accommodate it. Also,
334 * KUrlNavigator has fixed minimumWidth of 100, so if your badge widget is too wide, it might be clipped
335 * when the space is tight. You might want to call KUrlNavigator::setMinimumWidth() with a larger value
336 * in that case.
337 * In general, it is recommended to keep the badge widget small and not expanding, to avoid layout issues.
338 * \since 6.2
339 */
340 void setBadgeWidget(QWidget *widget);
341
342 /*!
343 * Returns the badge widget set by setBadgeWidget(). If setBadgeWidget() hasn't been called, returns nullptr.
344 * \since 6.2
345 */
346 QWidget *badgeWidget() const;
347
348 /*!
349 * Sets the background painting enabled or disabled for the buttons layout.
350 *
351 * In frameless styles, its recommended to set the background to disabled.
352 *
353 * Does not affect the input mode.
354 * \since 6.14
355 */
356 void setBackgroundEnabled(bool enabled);
357
358 /*!
359 * Returns true if the background of the buttons layout is being painted.
360 *
361 * Does not represent the input mode background.
362 *
363 * \since 6.14
364 */
365 bool isBackgroundEnabled() const;
366
367public Q_SLOTS:
368 /*!
369 * Sets the location to \a url. The old URL is added to the history.
370 * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged()
371 * and KUrlNavigator::historyChanged() are emitted. Use
372 * KUrlNavigator::locationUrl() to read the location.
373 */
374 void setLocationUrl(const QUrl &url);
375
376 /*!
377 * Activates the URL navigator (KUrlNavigator::isActive() will return true)
378 * and emits the signal KUrlNavigator::activated().
379 * \sa setActive()
380 */
381 void requestActivation();
382
383 // KDE5: Remove and listen for focus-signal instead
384 void setFocus();
385
386Q_SIGNALS:
387 /*!
388 * Is emitted, if the URL navigator has been activated by
389 * an user interaction
390 * \sa setActive()
391 */
392 void activated();
393
394 /*!
395 * Is emitted, if the location URL has been changed e. g. by
396 * the user.
397 * \sa setUrl()
398 */
399 void urlChanged(const QUrl &url);
400
401 /*!
402 * Is emitted, before the location URL is going to be changed to \a newUrl.
403 * The signal KUrlNavigator::urlChanged() will be emitted after the change
404 * has been done. Connecting to this signal is useful to save the state
405 * of a view with KUrlNavigator::saveLocationState().
406 */
407 void urlAboutToBeChanged(const QUrl &newUrl);
408
409 /*!
410 * Is emitted, if the editable state for the URL has been changed
411 * (see KUrlNavigator::setUrlEditable()).
412 */
413 void editableStateChanged(bool editable);
414
415 /*!
416 * Is emitted, if the history has been changed. Usually
417 * the history is changed if a new URL has been selected.
418 */
419 void historyChanged();
420
421 /*!
422 * Is emitted if a dropping has been done above the destination
423 * \a destination. The receiver must accept the drop event if
424 * the dropped data can be handled.
425 */
426 void urlsDropped(const QUrl &destination, QDropEvent *event);
427
428 /*!
429 * This signal is emitted when the Return or Enter key is pressed.
430 */
431 void returnPressed();
432
433 /*!
434 * Is emitted if the URL \a url should be opened in a new inactive tab because
435 * the user clicked on a breadcrumb with the middle mouse button or
436 * left-clicked with the ctrl modifier pressed or pressed return with
437 * the alt modifier pressed.
438 */
439 void tabRequested(const QUrl &url);
440
441 /*!
442 * Is emitted if the URL \a url should be opened in a new active tab because
443 * the user clicked on a breadcrumb with the middle mouse button with
444 * the shift modifier pressed or left-clicked with both the ctrl and shift
445 * modifiers pressed or pressed return with both the alt and shift modifiers
446 * pressed.
447 * \since 5.89
448 */
449 void activeTabRequested(const QUrl &url);
450
451 /*!
452 * Is emitted if the URL \a url should be opened in a new window because
453 * the user left-clicked on a breadcrumb with the shift modifier pressed
454 * or pressed return with the shift modifier pressed.
455 * \since 5.89
456 */
457 void newWindowRequested(const QUrl &url);
458
459 /*!
460 * When the URL is changed and the new URL (e.g.\ /home/user1/)
461 * is a parent of the previous URL (e.g.\ /home/user1/data/stuff),
462 * then this signal is emitted and \a url is set to the child
463 * directory of the new URL which is an ancestor of the old URL
464 * (in the example paths this would be /home/user1/data/).
465 * This signal allows file managers to pre-select the directory
466 * that the user is navigating up from.
467 * \since 5.37.0
468 */
469 void urlSelectionRequested(const QUrl &url);
470
471 /*!
472 * The internal layout and graphical representation of components has changed,
473 * either after an url change or after a switch between editable mode and
474 * breadcrumb mode
475 * \since 6.11
476 */
477 void layoutChanged();
478
479protected:
480 /*
481 * If the Escape key is pressed, the navigation bar should switch
482 * to the breadcrumb view.
483 */
484 void keyPressEvent(QKeyEvent *event) override;
485
486 void keyReleaseEvent(QKeyEvent *event) override;
487
488 /*
489 * Paste the clipboard content as URL, if the middle mouse
490 * button has been clicked.
491 */
492 void mouseReleaseEvent(QMouseEvent *event) override;
493
494 /*
495 * Reimplemented to activate on middle mousse button click
496 */
497 void mousePressEvent(QMouseEvent *event) override;
498
499 void resizeEvent(QResizeEvent *event) override;
500
501 void wheelEvent(QWheelEvent *event) override;
502
503 void showEvent(QShowEvent *event) override;
504
505 bool eventFilter(QObject *watched, QEvent *event) override;
506
507 void paintEvent(QPaintEvent *event) override;
508
509private:
510 friend class KUrlNavigatorPrivate;
511 std::unique_ptr<KUrlNavigatorPrivate> const d;
512
513 Q_DISABLE_COPY(KUrlNavigator)
514};
515
516#endif
517

source code of kio/src/filewidgets/kurlnavigator.h