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

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