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 * @since 4.5 113 */ 114 void saveLocationState(const QByteArray &state); 115 116 /** 117 * @return Location state given by \a historyIndex. If \a historyIndex 118 * is smaller than 0, the state of the current location is returned. 119 * @see KUrlNavigator::saveLocationState() 120 * @since 4.5 121 */ 122 QByteArray locationState(int historyIndex = -1) const; 123 124 /** 125 * Goes back one step in the URL history. The signals 126 * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and 127 * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned 128 * if the beginning of the history has already been reached and hence going back was 129 * not possible. The history index (see KUrlNavigator::historyIndex()) is 130 * increased by one if the operation was successful. 131 */ 132 bool goBack(); 133 134 /** 135 * Goes forward one step in the URL history. The signals 136 * KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() and 137 * KUrlNavigator::historyChanged() are emitted if true is returned. False is returned 138 * if the end of the history has already been reached and hence going forward 139 * was not possible. The history index (see KUrlNavigator::historyIndex()) is 140 * decreased by one if the operation was successful. 141 */ 142 bool goForward(); 143 144 /** 145 * Goes up one step of the URL path and remembers the old path 146 * in the history. The signals KUrlNavigator::urlAboutToBeChanged(), 147 * KUrlNavigator::urlChanged() and KUrlNavigator::historyChanged() are 148 * emitted if true is returned. False is returned if going up was not 149 * possible as the root has been reached. 150 */ 151 bool goUp(); 152 153 /** 154 * Goes to the home URL and remembers the old URL in the history. 155 * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() 156 * and KUrlNavigator::historyChanged() are emitted. 157 * 158 * @see KUrlNavigator::setHomeUrl() 159 */ 160 // KDE5: Remove the home-property. It is sufficient to invoke 161 // KUrlNavigator::setLocationUrl(homeUrl) on application-side. 162 void goHome(); 163 164 /** 165 * Sets the home URL used by KUrlNavigator::goHome(). If no 166 * home URL is set, the default home path of the user is used. 167 * @since 4.5 168 */ 169 // KDE5: Remove the home-property. It is sufficient to invoke 170 // KUrlNavigator::setLocationUrl(homeUrl) on application-side. 171 void setHomeUrl(const QUrl &url); 172 173 QUrl homeUrl() const; 174 175 /** 176 * Allows to edit the URL of the navigation bar if \a editable 177 * is true, and sets the focus accordingly. 178 * If \a editable is false, each part of 179 * the URL is presented by a button for a fast navigation ("breadcrumb view"). 180 */ 181 void setUrlEditable(bool editable); 182 183 /** 184 * @return True, if the URL is editable within a line editor. 185 * If false is returned, each part of the URL is presented by a button 186 * for fast navigation ("breadcrumb view"). 187 */ 188 bool isUrlEditable() const; 189 190 /** 191 * Shows the full path of the URL even if a place represents a part of the URL. 192 * Assuming that a place called "Pictures" uses the URL /home/user/Pictures. 193 * An URL like /home/user/Pictures/2008 is shown as [Pictures] > [2008] 194 * in the breadcrumb view, if showing the full path is turned off. If 195 * showing the full path is turned on, the URL is shown 196 * as [/] > [home] > [Pictures] > [2008]. 197 * @since 4.2 198 */ 199 void setShowFullPath(bool show); 200 201 /** 202 * @return True, if the full path of the URL should be shown in the breadcrumb view. 203 * @since 4.2 204 */ 205 bool showFullPath() const; 206 207 /** 208 * Set the URL navigator to the active mode, if \a active 209 * is true. The active mode is default. The inactive mode only differs 210 * visually from the active mode, no change of the behavior is given. 211 * 212 * Using the URL navigator in the inactive mode is useful when having split views, 213 * where the inactive view is indicated by an inactive URL 214 * navigator visually. 215 */ 216 void setActive(bool active); 217 218 /** 219 * @return True, if the URL navigator is in the active mode. 220 * @see KUrlNavigator::setActive() 221 */ 222 bool isActive() const; 223 224 /** 225 * Sets the places selector visible, if \a visible is true. 226 * The places selector allows to select the places provided 227 * by the places model passed in the constructor. Per default 228 * the places selector is visible. 229 */ 230 void setPlacesSelectorVisible(bool visible); 231 232 /** @return True, if the places selector is visible. */ 233 bool isPlacesSelectorVisible() const; 234 235 /** 236 * @return The currently entered, but not accepted URL. 237 * It is possible that the returned URL is not valid. 238 */ 239 QUrl uncommittedUrl() const; 240 241 /** 242 * @return The amount of locations in the history. The data for each 243 * location can be retrieved by KUrlNavigator::locationUrl() and 244 * KUrlNavigator::locationState(). 245 */ 246 int historySize() const; 247 248 /** 249 * @return The history index of the current location, where 250 * 0 <= history index < KUrlNavigator::historySize(). 0 is the most 251 * recent history entry. 252 */ 253 int historyIndex() const; 254 255 /** 256 * @return The used editor when the navigator is in the edit mode 257 * @see KUrlNavigator::setUrlEditable() 258 */ 259 KUrlComboBox *editor() const; 260 261 /** 262 * If an application supports only some special protocols, they can be set 263 * with \a protocols . 264 */ 265 // TODO KF6 rename to setSupportedSchemes to match KDirOperator and KFileWidget 266 void setCustomProtocols(const QStringList &protocols); 267 268 /** 269 * @return The custom protocols if they are set, QStringList() otherwise. 270 */ 271 QStringList customProtocols() const; 272 273 /** 274 * The child widget that received the QDropEvent when dropping on the URL 275 * navigator. You can pass this widget to KJobWidgets::setWindow() 276 * if you need to show a drop menu with KIO::drop(). 277 * @return Child widget that has received the last drop event, or nullptr if 278 * nothing has been dropped yet on the URL navigator. 279 * @since 5.37 280 * @see KIO::drop() 281 */ 282 QWidget *dropWidget() const; 283 284 /** 285 * Sets whether to show hidden folders in the subdirectories popup. 286 * @since 5.87 287 */ 288 void setShowHiddenFolders(bool showHiddenFolders); 289 290 /** 291 * Returns whether to show hidden folders in the subdirectories popup. 292 * @since 5.87 293 */ 294 bool showHiddenFolders() const; 295 296 /** 297 * Sets whether to sort hidden folders in the subdirectories popup last. 298 * @since 5.87 299 */ 300 void setSortHiddenFoldersLast(bool sortHiddenFoldersLast); 301 302 /** 303 * Returns whether to sort hidden folders in the subdirectories popup last. 304 * @since 5.87 305 */ 306 bool sortHiddenFoldersLast() const; 307 308 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 309 /** 310 * @return The current URL of the location. 311 * @deprecated Since 4.5, use KUrlNavigator::locationUrl() instead. 312 */ 313 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationUrl(int)") 314 const QUrl &url() const; 315 #endif 316 317 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 318 /** 319 * @return The portion of the current URL up to the path part given 320 * by \a index. Assuming that the current URL is /home/peter/Documents/Music, 321 * then the following URLs are returned for an index: 322 * - index <= 0: /home 323 * - index is 1: /home/peter 324 * - index is 2: /home/peter/Documents 325 * - index >= 3: /home/peter/Documents/Music 326 * @deprecated Since 4.5. It should not be necessary for a client of KUrlNavigator to query this information. 327 */ 328 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Do not use") 329 QUrl url(int index) const; 330 #endif 331 332 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 333 /** 334 * @return URL for the history element with the index \a historyIndex. 335 * The history index 0 represents the most recent URL. 336 * @since 4.3 337 * @deprecated Since 4.5, use KUrlNavigator::locationUrl(historyIndex) instead. 338 */ 339 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationUrl(int)") 340 QUrl historyUrl(int historyIndex) const; 341 #endif 342 343 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 344 /** 345 * @return The saved root URL for the current URL (see KUrlNavigator::saveRootUrl()). 346 * @deprecated Since 4.5, use KUrlNavigator::locationState() instead. 347 */ 348 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationState(int)") 349 const QUrl &savedRootUrl() const; 350 #endif 351 352 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 353 /** 354 * @return The saved contents position of the upper left corner 355 * for the current URL. 356 * @deprecated Since 4.5, use KUrlNavigator::locationState() instead. 357 */ 358 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::locationState(int)") 359 QPoint savedPosition() const; 360 #endif 361 362 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 363 /** @deprecated Since 4.5, use setHomeUrl(const QUrl& url) instead. */ 364 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::setHomeUrl(const QUrl&)") 365 void setHomeUrl(const QString &homeUrl); 366 #endif 367 368 public Q_SLOTS: 369 /** 370 * Sets the location to \a url. The old URL is added to the history. 371 * The signals KUrlNavigator::urlAboutToBeChanged(), KUrlNavigator::urlChanged() 372 * and KUrlNavigator::historyChanged() are emitted. Use 373 * KUrlNavigator::locationUrl() to read the location. 374 * @since 4.5 375 */ 376 void setLocationUrl(const QUrl &url); 377 378 /** 379 * Activates the URL navigator (KUrlNavigator::isActive() will return true) 380 * and emits the signal KUrlNavigator::activated(). 381 * @see KUrlNavigator::setActive() 382 */ 383 void requestActivation(); 384 385 #if !defined(K_DOXYGEN) 386 // KDE5: Remove and listen for focus-signal instead 387 void setFocus(); 388 #endif 389 390 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 391 /** 392 * Sets the location to \a url. 393 * @deprecated Since 4.5, use KUrlNavigator::setLocationUrl(url). 394 */ 395 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::setLocationUrl(const QUrl&))") 396 void setUrl(const QUrl &url); 397 #endif 398 399 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 400 /** 401 * Saves the used root URL of the content for the current history element. 402 * @deprecated Since 4.5, use KUrlNavigator::saveLocationState() instead. 403 */ 404 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::saveLocationState(const QByteArray &)") 405 void saveRootUrl(const QUrl &url); 406 #endif 407 408 #if KIOFILEWIDGETS_ENABLE_DEPRECATED_SINCE(4, 5) 409 /** 410 * Saves the coordinates of the contents for the current history element. 411 * @deprecated Since 4.5, use KUrlNavigator::saveLocationState() instead. 412 */ 413 KIOFILEWIDGETS_DEPRECATED_VERSION(4, 5, "Use KUrlNavigator::saveLocationState(const QByteArray &)") 414 void savePosition(int x, int y); 415 #endif 416 417 Q_SIGNALS: 418 /** 419 * Is emitted, if the URL navigator has been activated by 420 * an user interaction 421 * @see KUrlNavigator::setActive() 422 */ 423 void activated(); 424 425 /** 426 * Is emitted, if the location URL has been changed e. g. by 427 * the user. 428 * @see KUrlNavigator::setUrl() 429 */ 430 void urlChanged(const QUrl &url); 431 432 /** 433 * Is emitted, before the location URL is going to be changed to \a newUrl. 434 * The signal KUrlNavigator::urlChanged() will be emitted after the change 435 * has been done. Connecting to this signal is useful to save the state 436 * of a view with KUrlNavigator::saveLocationState(). 437 * @since 4.5 438 */ 439 void urlAboutToBeChanged(const QUrl &newUrl); 440 441 /** 442 * Is emitted, if the editable state for the URL has been changed 443 * (see KUrlNavigator::setUrlEditable()). 444 */ 445 void editableStateChanged(bool editable); 446 447 /** 448 * Is emitted, if the history has been changed. Usually 449 * the history is changed if a new URL has been selected. 450 */ 451 void historyChanged(); 452 453 /** 454 * Is emitted if a dropping has been done above the destination 455 * \a destination. The receiver must accept the drop event if 456 * the dropped data can be handled. 457 * @since 4.2 458 */ 459 void urlsDropped(const QUrl &destination, QDropEvent *event); 460 461 /** 462 * This signal is emitted when the Return or Enter key is pressed. 463 */ 464 void returnPressed(); 465 466 /** 467 * Is emitted if the URL \a url should be opened in a new inactive tab because 468 * the user clicked on a breadcrumb with the middle mouse button or 469 * left-clicked with the ctrl modifier pressed. 470 * @since 4.5 471 */ 472 void tabRequested(const QUrl &url); 473 474 /** 475 * Is emitted if the URL \a url should be opened in a new active tab because 476 * the user clicked on a breadcrumb with the middle mouse button with 477 * the shift modifier pressed or left-clicked with both the ctrl and shift 478 * modifiers pressed. 479 * @since 5.89 480 */ 481 void activeTabRequested(const QUrl &url); 482 483 /** 484 * Is emitted if the URL \a url should be opened in a new window because 485 * the user left-clicked on a breadcrumb with the shift modifier pressed. 486 * @since 5.89 487 */ 488 void newWindowRequested(const QUrl &url); 489 490 /** 491 * When the URL is changed and the new URL (e.g. /home/user1/) 492 * is a parent of the previous URL (e.g. /home/user1/data/stuff), 493 * then this signal is emitted and \a url is set to the child 494 * directory of the new URL which is an ancestor of the old URL 495 * (in the example paths this would be /home/user1/data/). 496 * This signal allows file managers to pre-select the directory 497 * that the user is navigating up from. 498 * @since 5.37.0 499 */ 500 void urlSelectionRequested(const QUrl &url); 501 502 protected: 503 #if !defined(K_DOXYGEN) 504 /** 505 * If the Escape key is pressed, the navigation bar should switch 506 * to the breadcrumb view. 507 * @see QWidget::keyPressEvent() 508 */ 509 void keyPressEvent(QKeyEvent *event) override; 510 511 /** 512 * Reimplemented for internal purposes. 513 */ 514 void keyReleaseEvent(QKeyEvent *event) override; 515 516 /** 517 * Paste the clipboard content as URL, if the middle mouse 518 * button has been clicked. 519 * @see QWidget::mouseReleaseEvent() 520 */ 521 void mouseReleaseEvent(QMouseEvent *event) override; 522 523 /** 524 * Reimplemented to activate on middle mousse button click 525 */ 526 void mousePressEvent(QMouseEvent *event) override; 527 528 void resizeEvent(QResizeEvent *event) override; 529 530 void wheelEvent(QWheelEvent *event) override; 531 532 bool eventFilter(QObject *watched, QEvent *event) override; 533 #endif 534 535 private: 536 friend class KUrlNavigatorPrivate; 537 std::unique_ptr<KUrlNavigatorPrivate> const d; 538 539 Q_DISABLE_COPY(KUrlNavigator) 540 }; 541 542 #endif 543