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 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 | */ |
69 | class KIOFILEWIDGETS_EXPORT KUrlNavigator : public QWidget |
70 | { |
71 | Q_OBJECT |
72 | |
73 | public: |
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 | |
335 | public 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 | |
356 | Q_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 | |
438 | protected: |
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 | |
471 | private: |
472 | friend class KUrlNavigatorPrivate; |
473 | std::unique_ptr<KUrlNavigatorPrivate> const d; |
474 | |
475 | Q_DISABLE_COPY(KUrlNavigator) |
476 | }; |
477 | |
478 | #endif |
479 | |