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 | |
21 | class QMouseEvent; |
22 | |
23 | class KFilePlacesModel; |
24 | class KUrlComboBox; |
25 | |
26 | class 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 | */ |
76 | class KIOFILEWIDGETS_EXPORT KUrlNavigator : public QWidget |
77 | { |
78 | Q_OBJECT |
79 | |
80 | public: |
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 | |
367 | public 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 | |
386 | Q_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 | |
479 | protected: |
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 | |
509 | private: |
510 | friend class KUrlNavigatorPrivate; |
511 | std::unique_ptr<KUrlNavigatorPrivate> const d; |
512 | |
513 | Q_DISABLE_COPY(KUrlNavigator) |
514 | }; |
515 | |
516 | #endif |
517 | |