Index: src/CMakeLists.txt =================================================================== --- src/CMakeLists.txt +++ src/CMakeLists.txt @@ -25,6 +25,7 @@ set(NON_KIOCORE_LINK_QCHS Qt5Widgets_QCH Qt5Network_QCH + Qt5Core_QCH KF5Completion_QCH KF5WidgetsAddons_QCH KF5JobWidgets_QCH Index: src/filewidgets/CMakeLists.txt =================================================================== --- src/filewidgets/CMakeLists.txt +++ src/filewidgets/CMakeLists.txt @@ -40,8 +40,8 @@ kurlnavigator.cpp kurlnavigatormenu.cpp kurlnavigatorpathselectoreventfilter.cpp - - + + ) qt5_add_resources(kiofilewidgets_SRCS ../new_file_templates/templates.qrc) Index: src/filewidgets/kurlnavigator.h =================================================================== --- src/filewidgets/kurlnavigator.h +++ src/filewidgets/kurlnavigator.h @@ -466,6 +466,9 @@ */ void urlSelectionRequested(const QUrl &url); + void keyUpPressed(); + void keyDownPressed(); + protected: #if !defined(K_DOXYGEN) /** @@ -506,16 +509,18 @@ Q_PRIVATE_SLOT(d, void dropUrls(const QUrl &destination, QDropEvent *)) Q_PRIVATE_SLOT(d, void slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)) Q_PRIVATE_SLOT(d, void openContextMenu(QPoint)) + Q_PRIVATE_SLOT(d, void openHierarchyMenu()) Q_PRIVATE_SLOT(d, void openPathSelectorMenu()) Q_PRIVATE_SLOT(d, void updateButtonVisibility()) Q_PRIVATE_SLOT(d, void switchToBreadcrumbMode()) Q_PRIVATE_SLOT(d, void slotPathBoxChanged(const QString &text)) Q_PRIVATE_SLOT(d, void updateContent()) + Q_PRIVATE_SLOT(d, void slotKeyUpPressed()) private: class Private; Private *const d; - + Q_DISABLE_COPY(KUrlNavigator) }; Index: src/filewidgets/kurlnavigator.cpp =================================================================== --- src/filewidgets/kurlnavigator.cpp +++ src/filewidgets/kurlnavigator.cpp @@ -38,6 +38,7 @@ #include #include + #include #include #include @@ -48,6 +49,9 @@ #include #include #include +#include + +#include using namespace KDEPrivate; @@ -71,7 +75,9 @@ void slotReturnPressed(); void slotProtocolChanged(const QString &); void openPathSelectorMenu(); - + void openHierarchyMenu(); + QString parentDirectory(const QString ¤tPath) const; + bool hasParent(const QUrl directory) const; /** * Appends the widget at the end of the URL navigator. It is assured * that the filler widget remains as last widget to fill the remaining @@ -101,12 +107,16 @@ */ void slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers); + void slotKeyUpPressed(); + void keyUpPressed(); + void keyDownPressed(); + void openContextMenu(const QPoint &p); void slotPathBoxChanged(const QString &text); void updateContent(); - + /** * Updates all buttons to have one button for each part of the * current URL. Existing buttons, which are available by m_navButtons, @@ -158,7 +168,7 @@ bool isCompressedPath(const QUrl &path) const; void removeTrailingSlash(QString &url) const; - + /** * Returns the current history index, if \a historyIndex is * smaller than 0. If \a historyIndex is greater or equal than @@ -239,7 +249,7 @@ m_dropDownButton->installEventFilter(q); connect(m_dropDownButton, SIGNAL(clicked()), q, SLOT(openPathSelectorMenu())); - + // initialize the path box of the traditional view m_pathBox = new KUrlComboBox(KUrlComboBox::Directories, true, q); m_pathBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); @@ -271,10 +281,14 @@ m_layout->addWidget(m_dropDownButton); m_layout->addWidget(m_pathBox, 1); m_layout->addWidget(m_toggleEditableMode); + m_pathBox->installEventFilter(q); q->setContextMenuPolicy(Qt::CustomContextMenu); connect(q, SIGNAL(customContextMenuRequested(QPoint)), q, SLOT(openContextMenu(QPoint))); + connect(q, SIGNAL(keyUpPressed()), q, SLOT(slotKeyUpPressed())); + connect(q, SIGNAL(keyDownPressed()), + q, SLOT(openHierarchyMenu())); } void KUrlNavigator::Private::initialize(const QUrl &url) @@ -321,6 +335,11 @@ m_pathBox->setUrl(currentUrl); } +void KUrlNavigator::Private::slotKeyUpPressed() +{ + emit q->goUp(); +} + void KUrlNavigator::Private::slotReturnPressed() { applyUncommittedUrl(); @@ -352,6 +371,38 @@ m_pathBox->setEditUrl(url); } + QString KUrlNavigator::Private::parentDirectory(const QString ¤tPath) const + { + const int slash = currentPath.lastIndexOf(QLatin1Char('/')); + if (slash == -1) { + return QString(); + } + else if (slash == 0) { + return QString(QLatin1Char('/')); + } + else if (slash == currentPath.length()-1) { + return parentDirectory(currentPath.left(slash)); + } + return currentPath.left(slash); + } + +bool KUrlNavigator::Private::hasParent(const QUrl directory) const +{ + return (directory != QUrl(parentDirectory(directory.path()))); +} + +void KUrlNavigator::Private::openHierarchyMenu() { + QUrl currentDirectory = q->locationUrl(); + QStringList urlList = QStringList(); + urlList.append(currentDirectory.path()); + while (hasParent(currentDirectory)) { + currentDirectory = QUrl(parentDirectory(currentDirectory.path())); + urlList.append(currentDirectory.path()); + } + m_pathBox->setUrls(urlList, KUrlComboBox::KeepOld); + m_pathBox->showPopup(); +} + void KUrlNavigator::Private::openPathSelectorMenu() { if (m_navButtons.count() <= 0) { @@ -415,8 +466,8 @@ { if (m_editable) { applyUncommittedUrl(); - } - + } + switchView(); } @@ -526,7 +577,7 @@ } void KUrlNavigator::Private::slotPathBoxChanged(const QString &text) -{ +{ if (text.isEmpty()) { const QString protocol = q->locationUrl().scheme(); m_protocols->setProtocol(protocol); @@ -548,11 +599,11 @@ if (m_editable) { m_protocols->hide(); m_dropDownButton->hide(); - + deleteButtons(); m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); - + m_pathBox->show(); m_pathBox->setUrl(currentUrl); } else { @@ -1232,7 +1283,20 @@ button->setShowMnemonic(false); } break; - + case QEvent::KeyRelease: + { + QKeyEvent *actualEvent = static_cast(event); + if (actualEvent->key() == Qt::Key_Up) { + if (!d->m_pathBox->completionBox()->isVisible()) { + emit keyUpPressed(); + } + } else if (actualEvent->key() == Qt::Key_Down) { + if (!d->m_pathBox->completionBox()->isVisible()) { + emit keyDownPressed(); + } + } + break; + } default: break; } Index: src/widgets/kurlcombobox.h =================================================================== --- src/widgets/kurlcombobox.h +++ src/widgets/kurlcombobox.h @@ -66,7 +66,14 @@ * @li RemoveBottom means, that items will be removed from the bottom */ enum OverLoadResolving { RemoveTop, RemoveBottom }; - + + /** + * This Enumeration is used in setUrls() to determine if during adding + * new URLs old ones would be removed from a list. + * @li RemoveOld means that URL list would be cleared before adding new ones + * @li KeepOld means that URL list would be appended to + */ + enum OldUrlPolicy { RemoveOld, KeepOld }; /** * Constructs a KUrlComboBox. * @param mode is either Files, Directories or Both and controls the @@ -110,6 +117,7 @@ * will be stripped. */ void setUrls(const QStringList &urls); + void setUrls(const QStringList &urls, OldUrlPolicy removeOld); /** * Inserts @p urls into the combobox below the "default urls" (see @@ -119,6 +127,7 @@ * parameter determines whether the first or last items will be stripped. */ void setUrls(const QStringList &urls, OverLoadResolving remove); + void setUrls(const QStringList &urls, OverLoadResolving remove, OldUrlPolicy removeOld); /** * @returns a list of all urls currently handled. The list contains at most @@ -184,6 +193,7 @@ */ void setCompletionObject(KCompletion *compObj, bool hsig = true) override; + Q_SIGNALS: /** * Emitted when an item was clicked at. Index: src/widgets/kurlcombobox.cpp =================================================================== --- src/widgets/kurlcombobox.cpp +++ src/widgets/kurlcombobox.cpp @@ -70,6 +70,7 @@ QMap itemMapper; QIcon opendirIcon; + }; @@ -173,23 +174,34 @@ setUrls(urls, RemoveBottom); } -void KUrlComboBox::setUrls(const QStringList &_urls, OverLoadResolving remove) +void KUrlComboBox::setUrls(const QStringList &urls, OldUrlPolicy removeOld) +{ + setUrls(urls, RemoveBottom, removeOld); +} + +void KUrlComboBox::setUrls(const QStringList &_urls, OverLoadResolving remove) { + setUrls(_urls, remove, OldUrlPolicy::RemoveOld); +} + +void KUrlComboBox::setUrls(const QStringList& urls, OverLoadResolving remove, OldUrlPolicy removeOld) { setDefaults(); - d->itemList.clear(); + if (removeOld == OldUrlPolicy::RemoveOld) { + d->itemList.clear(); + } d->urlAdded = false; - if (_urls.isEmpty()) { + if (urls.isEmpty()) { return; } - QStringList urls; - QStringList::ConstIterator it = _urls.constBegin(); + QStringList _urls; + QStringList::ConstIterator it = urls.constBegin(); // kill duplicates - while (it != _urls.constEnd()) { + while (it != urls.constEnd()) { if (!urls.contains(*it)) { - urls += *it; + _urls += *it; } ++it; } @@ -201,11 +213,11 @@ while (Overload > 0) { if (remove == RemoveBottom) { if (!urls.isEmpty()) { - urls.removeLast(); + _urls.removeLast(); } } else { if (!urls.isEmpty()) { - urls.removeFirst(); + _urls.removeFirst(); } } Overload--;