diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -106,6 +106,8 @@ dolphinremoveaction.cpp middleclickactioneventfilter.cpp dolphinnewfilemenu.cpp + dolphindebug.cpp + utils/directoryfindchilditem.cpp ) ecm_qt_declare_logging_category(dolphinprivate_LIB_SRCS HEADER dolphindebug.h IDENTIFIER DolphinDebug CATEGORY_NAME org.kde.dolphin) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -61,6 +61,11 @@ TEST_NAME dolphinmainwindowtest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) +# CommonAncestorTest +ecm_add_test(directoryfindchilditemtest.cpp +TEST_NAME directoryfindchilditemtest +LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) + # DragAndDropHelperTest ecm_add_test(draganddrophelpertest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test) diff --git a/src/tests/directoryfindchilditemtest.cpp b/src/tests/directoryfindchilditemtest.cpp new file mode 100644 --- /dev/null +++ b/src/tests/directoryfindchilditemtest.cpp @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (C) 2018 by Emirald Mateli * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "utils/directoryfindchilditem.cpp" +#include + +class DirectoryFindChildItemTest : public QObject +{ + Q_OBJECT + +private slots: + void testDirectoryFindChildItem_data(); + void testDirectoryFindChildItem(); +}; + +void DirectoryFindChildItemTest::testDirectoryFindChildItem_data() +{ + QTest::addColumn("directory"); + QTest::addColumn("url"); + QTest::addColumn("expected"); + + QTest::newRow("Test directory with file located in one of its children") + << QUrl::fromLocalFile("dir") + << QUrl::fromLocalFile("dir/sub/x/y/z") + << QUrl::fromLocalFile("dir/sub"); + + QTest::newRow("Test directory with trailing path delimiter") + << QUrl::fromLocalFile("dir/sub/x/") + << QUrl::fromLocalFile("dir/sub/x/y/z") + << QUrl::fromLocalFile("dir/sub/x/y"); + + QTest::newRow("Test two unrelated directories") + << QUrl::fromLocalFile("unrelated") + << QUrl::fromLocalFile("dir/sub/x/y/z") + << QUrl(); +} + +void DirectoryFindChildItemTest::testDirectoryFindChildItem() +{ + QFETCH(QUrl, directory); + QFETCH(QUrl, url); + QFETCH(QUrl, expected); + + QCOMPARE(directoryFindChildItem(directory, url), expected); +} + +QTEST_MAIN(DirectoryFindChildItemTest) + +#include "directoryfindchilditemtest.moc" diff --git a/src/utils/directoryfindchilditem.h b/src/utils/directoryfindchilditem.h new file mode 100644 --- /dev/null +++ b/src/utils/directoryfindchilditem.h @@ -0,0 +1,6 @@ +#ifndef DIRECTORY_FIND_CHILD_ITEM +#define DIRECTORY_FIND_CHILD_ITEM + +QUrl directoryFindChildItem(const QUrl& directory, const QUrl& filename); + +#endif diff --git a/src/utils/directoryfindchilditem.cpp b/src/utils/directoryfindchilditem.cpp new file mode 100644 --- /dev/null +++ b/src/utils/directoryfindchilditem.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include "directoryfindchilditem.h" + +/** + * Returns the item which is located in "directory" argument + * when "filename" is an item located in it or one of its children. + * Returns an empty QUrl when that is not the case + * + *
directoryFindChildItem("~/dir", "~/dir/x/y/z") -> "~/dir/x"
+ * + * + * @param directory + * @param filename + * @return + */ +QUrl directoryFindChildItem(const QUrl& directory, const QUrl& filename) +{ + const QString dirStr = directory.adjusted(QUrl::StripTrailingSlash).toString(); + const QString urlStr = filename.toString(); + const int dirLen = dirStr.length() + 1; + + if (!urlStr.startsWith(dirStr)) { + return QUrl(); + } + + return QUrl(QStringLiteral("%1/%2").arg( + dirStr, urlStr.mid(dirLen, urlStr.indexOf(QDir::separator(), dirLen + 1) - dirLen))); +} diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -777,6 +777,7 @@ private: void updatePalette(); + QUrl m_observedCreatedItem; bool m_active; bool m_tabsForFiles; bool m_assureVisibleCurrentIndex; diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -68,6 +68,7 @@ #include #include #include +#include DolphinView::DolphinView(const QUrl& url, QWidget* parent) : QWidget(parent), @@ -1335,9 +1336,16 @@ void DolphinView::observeCreatedItem(const QUrl& url) { - if (m_active) { - forceUrlsSelection(url, {url}); + if (!m_active) { + return; } + + // In case url is located in a subdirectory, select its ancestor located in the current dir. + m_observedCreatedItem = directoryFindChildItem(m_model->directory(), url); + + forceUrlsSelection(m_observedCreatedItem, {m_observedCreatedItem}); + // updateViewState call is needed when the url is a directory and it already exists + updateViewState(); } void DolphinView::slotDirectoryRedirection(const QUrl& oldUrl, const QUrl& newUrl) @@ -1501,7 +1509,21 @@ { // Update the view-state. This has to be done asynchronously // because the view might not be in its final state yet. - QTimer::singleShot(0, this, &DolphinView::updateViewState); + QTimer::singleShot(0, [this]() { + // if a new item was created mark it as selected as soon as its found by the model + if (m_observedCreatedItem != QUrl()) { + const int index = m_model->index(m_observedCreatedItem); + + if (index) { + m_container->controller()->selectionManager()->setCurrentItem(index); + forceUrlsSelection(m_observedCreatedItem, {m_observedCreatedItem}); + + m_observedCreatedItem = QUrl(); + } + } + + updateViewState(); + }); emit directoryLoadingCompleted();