1/*****************************************************************************
2 * Copyright (C) 2006-2010 by Peter Penz <peter.penz@gmx.at> *
3 * Copyright (C) 2006 by Aaron J. Seigo <aseigo@kde.org> *
4 * Copyright (C) 2007 by Kevin Ottens <ervin@kde.org> *
5 * Copyright (C) 2007 by Urs Wolfer <uwolfer @ kde.org> *
6 * *
7 * This library is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU Library General Public *
9 * License as published by the Free Software Foundation; either *
10 * version 2 of the License, or (at your option) any later version. *
11 * *
12 * This library is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15 * Library General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Library General Public License *
18 * along with this library; see the file COPYING.LIB. If not, write to *
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 *****************************************************************************/
22
23#ifndef KURLNAVIGATOR_H
24#define KURLNAVIGATOR_H
25
26#include <kfile_export.h>
27
28#include <kurl.h>
29#include <QtGui/QWidget>
30#include <QtCore/QByteArray>
31
32class KFilePlacesModel;
33class KUrlComboBox;
34class QMouseEvent;
35
36/**
37 * @brief Widget that allows to navigate through the paths of an URL.
38 *
39 * The URL navigator offers two modes:
40 * - Editable: The URL of the location is editable inside an editor.
41 * By pressing RETURN the URL will get activated.
42 * - Non editable ("breadcrumb view"): The URL of the location is represented by
43 * a number of buttons, where each button represents a path
44 * of the URL. By clicking on a button the path will get
45 * activated. This mode also supports drag and drop of items.
46 *
47 * The mode can be changed by clicking on the empty area of the URL navigator.
48 * It is recommended that the application remembers the setting
49 * or allows to configure the default mode (see KUrlNavigator::setUrlEditable()).
50 *
51 * The URL navigator remembers the URL history during navigation and allows to go
52 * back and forward within this history.
53 *
54 * In the non editable mode ("breadcrumb view") it can be configured whether
55 * the full path should be shown. It is recommended that the application
56 * remembers the setting or allows to configure the default mode (see
57 * KUrlNavigator::setShowFullPath()).
58 *
59 * The typical usage of the KUrlNavigator is:
60 * - Create an instance providing a places model and an URL.
61 * - Create an instance of QAbstractItemView which shows the content of the URL
62 * given by the URL navigator.
63 * - Connect to the signal KUrlNavigator::urlChanged() and synchronize the content of
64 * QAbstractItemView with the URL given by the URL navigator.
65 *
66 * It is recommended, that the application remembers the state of the QAbstractItemView
67 * when the URL has been changed. This allows to restore the view state when going back in history.
68 * KUrlNavigator offers support for remembering the view state:
69 * - 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 * - 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 */
75class KFILE_EXPORT KUrlNavigator : public QWidget
76{
77 Q_OBJECT
78
79public:
80 /** @since 4.5 */
81 KUrlNavigator(QWidget* parent = 0);
82
83 /**
84 * @param placesModel Model for the places which are selectable inside a
85 * menu. A place can be a bookmark or a device. If it is 0,
86 * no places selector is displayed.
87 * @param url URL which is used for the navigation or editing.
88 * @param parent Parent widget.
89 */
90 KUrlNavigator(KFilePlacesModel* placesModel, const KUrl& url, QWidget* parent);
91 virtual ~KUrlNavigator();
92
93 /**
94 * @return URL of the location given by the \a historyIndex. If \a historyIndex
95 * is smaller than 0, the URL of the current location is returned.
96 * @since 4.5
97 */
98 KUrl locationUrl(int historyIndex = -1) const;
99
100 /**
101 * Saves the location state described by \a state for the current location. It is recommended
102 * that at least the scroll position of a view is remembered and restored when traversing
103 * through the history. Saving the location state should be done when the signal
104 * KUrlNavigator::urlAboutToBeChanged() has been emitted. Restoring the location state (see
105 * KUrlNavigator::locationState()) should be done when the signal KUrlNavigator::urlChanged()
106 * has been emitted.
107 *
108 * Example:
109 * \code
110 * QByteArray state;
111 * QDataStream data(&state, QIODevice::WriteOnly);
112 * data << QPoint(x, y);
113 * data << ...;
114 * ...
115 * urlNavigator->saveLocationState(state);
116 * \endcode
117 *
118 * @since 4.5
119 */
120 void saveLocationState(const QByteArray& state);
121
122 /**
123 * @return Location state given by \a historyIndex. If \a historyIndex
124 * is smaller than 0, the state of the current location is returned.
125 * @see KUrlNavigator::saveLocationState()
126 * @since 4.5
127 */
128 QByteArray locationState(int historyIndex = -1) const;
129
130 /**
131 * Goes back one step in the URL history. The signals
132 * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and
133 * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned
134 * if the beginning of the history has already been reached and hence going back was
135 * not possible. The history index (see KUrlNavigator::historyIndex()) is
136 * increased by one if the operation was successful.
137 */
138 bool goBack();
139
140 /**
141 * Goes forward one step in the URL history. The signals
142 * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and
143 * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned
144 * if the end of the history has already been reached and hence going forward
145 * was not possible. The history index (see KUrlNavigator::historyIndex()) is
146 * decreased by one if the operation was successful.
147 */
148 bool goForward();
149
150 /**
151 * Goes up one step of the URL path and remembers the old path
152 * in the history. The signals KUrlNavigator::urlAboutToBeChanged(),
153 * KUrlNavigator::urlChanged() and KUrlNavigator::historyChanged() are
154 * emitted if true is returned. False is returned if going up was not
155 * possible as the root has been reached.
156 */
157 bool goUp();
158
159 /**
160 * Goes to the home URL and remembers the old URL in the history.
161 * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged()
162 * and KUrlNavigator::historyChanged() are emitted.
163 *
164 * @see KUrlNavigator::setHomeUrl()
165 */
166 // KDE5: Remove the home-property. It is sufficient to invoke
167 // KUrlNavigator::setLocationUrl(homeUrl) on application-side.
168 void goHome();
169
170 /**
171 * Sets the home URL used by KUrlNavigator::goHome(). If no
172 * home URL is set, the default home path of the user is used.
173 * @since 4.5
174 */
175 // KDE5: Remove the home-property. It is sufficient to invoke
176 // KUrlNavigator::setLocationUrl(homeUrl) on application-side.
177 void setHomeUrl(const KUrl& url);
178
179 KUrl homeUrl() const;
180
181 /**
182 * Allows to edit the URL of the navigation bar if \a editable
183 * is true, and sets the focus accordingly.
184 * If \a editable is false, each part of
185 * the URL is presented by a button for a fast navigation ("breadcrumb view").
186 */
187 void setUrlEditable(bool editable);
188
189 /**
190 * @return True, if the URL is editable within a line editor.
191 * If false is returned, each part of the URL is presented by a button
192 * for fast navigation ("breadcrumb view").
193 */
194 bool isUrlEditable() const;
195
196 /**
197 * Shows the full path of the URL even if a place represents a part of the URL.
198 * Assuming that a place called "Pictures" uses the URL /home/user/Pictures.
199 * An URL like /home/user/Pictures/2008 is shown as [Pictures] > [2008]
200 * in the breadcrumb view, if showing the full path is turned off. If
201 * showing the full path is turned on, the URL is shown
202 * as [/] > [home] > [Pictures] > [2008].
203 * @since 4.2
204 */
205 void setShowFullPath(bool show);
206
207 /**
208 * @return True, if the full path of the URL should be shown in the breadcrumb view.
209 * @since 4.2
210 */
211 bool showFullPath() const;
212
213 /**
214 * Set the URL navigator to the active mode, if \a active
215 * is true. The active mode is default. The inactive mode only differs
216 * visually from the active mode, no change of the behavior is given.
217 *
218 * Using the URL navigator in the inactive mode is useful when having split views,
219 * where the inactive view is indicated by an inactive URL
220 * navigator visually.
221 */
222 void setActive(bool active);
223
224 /**
225 * @return True, if the URL navigator is in the active mode.
226 * @see KUrlNavigator::setActive()
227 */
228 bool isActive() const;
229
230 /**
231 * Sets the places selector visible, if \a visible is true.
232 * The places selector allows to select the places provided
233 * by the places model passed in the constructor. Per default
234 * the places selector is visible.
235 */
236 void setPlacesSelectorVisible(bool visible);
237
238 /** @return True, if the places selector is visible. */
239 bool isPlacesSelectorVisible() const;
240
241 /**
242 * @return The currently entered, but not accepted URL.
243 * It is possible that the returned URL is not valid.
244 */
245 KUrl uncommittedUrl() const;
246
247 /**
248 * @return The amount of locations in the history. The data for each
249 * location can be retrieved by KUrlNavigator::locationUrl() and
250 * KUrlNavigator::locationState().
251 */
252 int historySize() const;
253
254 /**
255 * @return The history index of the current location, where
256 * 0 <= history index < KUrlNavigator::historySize(). 0 is the most
257 * recent history entry.
258 */
259 int historyIndex() const;
260
261 /**
262 * @return The used editor when the navigator is in the edit mode
263 * @see KUrlNavigator::setUrlEditable()
264 */
265 KUrlComboBox* editor() const;
266
267 /**
268 * If an application supports only some special protocols, they can be set
269 * with \a protocols .
270 */
271 // KDE5: Think about removing the custom-protocols-property. It had been used
272 // only by one application currently which uses a different approach now.
273 void setCustomProtocols(const QStringList& protocols);
274
275 /**
276 * @return The custom protocols if they are set, QStringList() otherwise.
277 */
278 QStringList customProtocols() const;
279
280#if !defined(KDE_NO_DEPRECATED) && !defined(DOXYGEN_SHOULD_SKIP_THIS)
281 /**
282 * @return The current URL of the location.
283 * @deprecated Use KUrlNavigator::locationUrl() instead.
284 */
285 KDE_DEPRECATED const KUrl& url() const;
286
287 /**
288 * @return The portion of the current URL up to the path part given
289 * by \a index. Assuming that the current URL is /home/peter/Documents/Music,
290 * then the following URLs are returned for an index:
291 * - index <= 0: /home
292 * - index is 1: /home/peter
293 * - index is 2: /home/peter/Documents
294 * - index >= 3: /home/peter/Documents/Music
295 * @deprecated It should not be necessary for a client of KUrlNavigator to query this information.
296 */
297 KDE_DEPRECATED KUrl url(int index) const;
298
299 /**
300 * @return URL for the history element with the index \a historyIndex.
301 * The history index 0 represents the most recent URL.
302 * @since 4.3
303 * @deprecated Use KUrlNavigator::locationUrl(historyIndex) instead.
304 */
305 KDE_DEPRECATED KUrl historyUrl(int historyIndex) const;
306
307 /**
308 * @return The saved root URL for the current URL (see KUrlNavigator::saveRootUrl()).
309 * @deprecated Use KUrlNavigator::locationState() instead.
310 */
311 KDE_DEPRECATED const KUrl& savedRootUrl() const;
312
313 /**
314 * @return The saved contents position of the upper left corner
315 * for the current URL.
316 * @deprecated Use KUrlNavigator::locationState() instead.
317 */
318 KDE_DEPRECATED QPoint savedPosition() const;
319
320 /** @deprecated Use setHomeUrl(const KUrl& url) instead. */
321 KDE_DEPRECATED void setHomeUrl(const QString& homeUrl);
322#endif
323
324public Q_SLOTS:
325 /**
326 * Sets the location to \a url. The old URL is added to the history.
327 * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged()
328 * and KUrlNavigator::historyChanged() are emitted. Use
329 * KUrlNavigator::locationUrl() to read the location.
330 * @since 4.5
331 */
332 void setLocationUrl(const KUrl& url);
333
334 /**
335 * Activates the URL navigator (KUrlNavigator::isActive() will return true)
336 * and emits the signal KUrlNavigator::activated().
337 * @see KUrlNavigator::setActive()
338 */
339 void requestActivation();
340
341#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
342 // KDE5: Remove and listen for focus-signal instead
343 void setFocus();
344#endif
345
346#if !defined(KDE_NO_DEPRECATED) && !defined(DOXYGEN_SHOULD_SKIP_THIS)
347 /**
348 * Sets the location to \a url.
349 * @deprecated Use KUrlNavigator::setLocationUrl(url).
350 */
351 KDE_DEPRECATED void setUrl(const KUrl& url);
352
353 /**
354 * Saves the used root URL of the content for the current history element.
355 * @deprecated Use KUrlNavigator::saveLocationState() instead.
356 */
357 KDE_DEPRECATED void saveRootUrl(const KUrl& url);
358
359 /**
360 * Saves the coordinates of the contents for the current history element.
361 * @deprecated Use KUrlNavigator::saveLocationState() instead.
362 */
363 KDE_DEPRECATED void savePosition(int x, int y);
364#endif
365
366Q_SIGNALS:
367 /**
368 * Is emitted, if the URL navigator has been activated by
369 * an user interaction
370 * @see KUrlNavigator::setActive()
371 */
372 void activated();
373
374 /**
375 * Is emitted, if the location URL has been changed e. g. by
376 * the user.
377 * @see KUrlNavigator::setUrl()
378 */
379 void urlChanged(const KUrl& url);
380
381 /**
382 * Is emitted, before the location URL is going to be changed to \a newUrl.
383 * The signal KUrlNavigator::urlChanged() will be emitted after the change
384 * has been done. Connecting to this signal is useful to save the state
385 * of a view with KUrlNavigator::saveLocationState().
386 * @since 4.5
387 */
388 void urlAboutToBeChanged(const KUrl& newUrl);
389
390 /**
391 * Is emitted, if the editable state for the URL has been changed
392 * (see KUrlNavigator::setUrlEditable()).
393 */
394 void editableStateChanged(bool editable);
395
396 /**
397 * Is emitted, if the history has been changed. Usually
398 * the history is changed if a new URL has been selected.
399 */
400 void historyChanged();
401
402 /**
403 * Is emitted if a dropping has been done above the destination
404 * \a destination. The receiver must accept the drop event if
405 * the dropped data can be handled.
406 * @since 4.2
407 */
408 void urlsDropped(const KUrl& destination, QDropEvent* event);
409
410 /**
411 * This signal is emitted when the Return or Enter key is pressed.
412 */
413 void returnPressed();
414
415 /**
416 * Is emitted if the URL \a url should be opened in a new tab because
417 * the user clicked on a breadcrumb with the middle mouse button.
418 * @since 4.5
419 */
420 void tabRequested(const KUrl& url);
421
422#if !defined(KDE_NO_DEPRECATED) && !defined(DOXYGEN_SHOULD_SKIP_THIS)
423 /**
424 * Is emitted if the URLs \a urls have been dropped
425 * to the destination \a destination.
426 * @deprecated Use
427 * KUrlNavigator::urlsDropped(const KUrl& destination, QDropEvent* event)
428 * instead.
429 */
430 // KDE5: remove, as the signal has been replaced by
431 // urlsDropped(const KUrl& destination, QDropEvent* event)
432 KDE_DEPRECATED void urlsDropped(const KUrl::List& urls,
433 const KUrl& destination);
434#endif
435
436protected:
437#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
438 /**
439 * If the Escape key is pressed, the navigation bar should switch
440 * to the breadcrumb view.
441 * @see QWidget::keyPressEvent()
442 */
443 virtual void keyPressEvent(QKeyEvent* event);
444
445 /**
446 * Reimplemented for internal purposes.
447 */
448 virtual void keyReleaseEvent(QKeyEvent* event);
449
450 /**
451 * Paste the clipboard content as URL, if the middle mouse
452 * button has been clicked.
453 * @see QWidget::mouseReleaseEvent()
454 */
455 virtual void mouseReleaseEvent(QMouseEvent* event);
456
457 virtual void resizeEvent(QResizeEvent* event);
458
459 virtual void wheelEvent(QWheelEvent* event);
460
461 virtual bool eventFilter(QObject* watched, QEvent* event);
462#endif
463
464private:
465 Q_PRIVATE_SLOT(d, void slotReturnPressed())
466 Q_PRIVATE_SLOT(d, void slotProtocolChanged(const QString& protocol))
467 Q_PRIVATE_SLOT(d, void switchView())
468 Q_PRIVATE_SLOT(d, void dropUrls(const KUrl& destination, QDropEvent*))
469 Q_PRIVATE_SLOT(d, void slotNavigatorButtonClicked(const KUrl& url, Qt::MouseButton button))
470 Q_PRIVATE_SLOT(d, void openContextMenu())
471 Q_PRIVATE_SLOT(d, void openPathSelectorMenu())
472 Q_PRIVATE_SLOT(d, void updateButtonVisibility())
473 Q_PRIVATE_SLOT(d, void switchToBreadcrumbMode())
474 Q_PRIVATE_SLOT(d, void slotPathBoxChanged(const QString& text))
475 Q_PRIVATE_SLOT(d, void updateContent())
476
477private:
478 class Private;
479 Private* const d;
480
481 Q_DISABLE_COPY(KUrlNavigator)
482};
483
484#endif
485