diff --git a/autotests/kfileplacesmodeltest.cpp b/autotests/kfileplacesmodeltest.cpp index b9224ed7..3191d144 100644 --- a/autotests/kfileplacesmodeltest.cpp +++ b/autotests/kfileplacesmodeltest.cpp @@ -1,759 +1,828 @@ /* This file is part of the KDE project Copyright (C) 2007 Kevin Ottens This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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 #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN //c:\ as root for windows #define KDE_ROOT_PATH "C:\\" #else #define KDE_ROOT_PATH "/" #endif // Avoid QHash randomization so that the order of the devices is stable static void seedInit() { qputenv("QT_HASH_SEED", "0"); // This env var has no effect because this comes too late. qCpuFeatures() was already called by // a Q_CONSTRUCTOR_FUNCTION inside QtGui (see image/qimage_conversions.cpp). Argh. QTBUG-47566. qputenv("QT_NO_CPU_FEATURE", "sse4.2"); } Q_CONSTRUCTOR_FUNCTION(seedInit) class KFilePlacesModelTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void testInitialState(); void testInitialList(); void testReparse(); void testInternalBookmarksHaveIds(); void testHiding(); void testMove(); void testPlacesLifecycle(); void testDevicePlugging(); void testDragAndDrop(); void testDeviceSetupTeardown(); void testEnableBaloo(); + void testRemoteUrls_data(); + void testRemoteUrls(); private: QStringList placesUrls() const; QDBusInterface *fakeManager(); QDBusInterface *fakeDevice(const QString &udi); KFilePlacesModel *m_places; KFilePlacesModel *m_places2; // To check that they always stay in sync // actually supposed to work across processes, // but much harder to test QMap m_interfacesMap; }; static QString bookmarksFile() { return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/user-places.xbel"; } void KFilePlacesModelTest::initTestCase() { qputenv("KDE_FORK_SLAVES", "yes"); // to avoid a runtime dependency on klauncher QStandardPaths::setTestModeEnabled(true); // Ensure we'll have a clean bookmark file to start QFile::remove(bookmarksFile()); // disable baloo by default KConfig config(QStringLiteral("baloofilerc")); KConfigGroup basicSettings = config.group("Basic Settings"); basicSettings.writeEntry("Indexing-Enabled", false); config.sync(); qRegisterMetaType(); const QString fakeHw = QFINDTESTDATA("fakecomputer.xml"); QVERIFY(!fakeHw.isEmpty()); qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw)); m_places = new KFilePlacesModel(); m_places2 = new KFilePlacesModel(); } void KFilePlacesModelTest::cleanupTestCase() { delete m_places; delete m_places2; qDeleteAll(m_interfacesMap); QFile::remove(bookmarksFile()); } QStringList KFilePlacesModelTest::placesUrls() const { QStringList urls; for (int row = 0; row < m_places->rowCount(); ++row) { QModelIndex index = m_places->index(row, 0); urls << m_places->url(index).toDisplayString(QUrl::PreferLocalFile); } return urls; } #define CHECK_PLACES_URLS(urls) \ if (placesUrls() != urls) { \ qDebug() << "Expected:" << urls; \ qDebug() << "Got:" << placesUrls(); \ QCOMPARE(placesUrls(), urls); \ } \ for (int row = 0; row < urls.size(); ++row) { \ QModelIndex index = m_places->index(row, 0); \ \ QCOMPARE(m_places->url(index).toString(), QUrl::fromUserInput(urls[row]).toString()); \ QCOMPARE(m_places->data(index, KFilePlacesModel::UrlRole).toUrl(), \ QUrl(m_places->url(index))); \ \ index = m_places2->index(row, 0); \ \ QCOMPARE(m_places2->url(index).toString(), QUrl::fromUserInput(urls[row]).toString()); \ QCOMPARE(m_places2->data(index, KFilePlacesModel::UrlRole).toUrl(), \ QUrl(m_places2->url(index))); \ } \ \ QCOMPARE(urls.size(), m_places->rowCount()); \ QCOMPARE(urls.size(), m_places2->rowCount()); QDBusInterface *KFilePlacesModelTest::fakeManager() { return fakeDevice(QStringLiteral("/org/kde/solid/fakehw")); } QDBusInterface *KFilePlacesModelTest::fakeDevice(const QString &udi) { if (m_interfacesMap.contains(udi)) { return m_interfacesMap[udi]; } QDBusInterface *iface = new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi); m_interfacesMap[udi] = iface; return iface; } void KFilePlacesModelTest::testInitialState() { QCOMPARE(m_places->rowCount(), 4); // when the xbel file is empty, KFilePlacesModel fills it with 4 default items QCoreApplication::processEvents(); // Devices have a delayed loading QCOMPARE(m_places->rowCount(), 9); } static const QStringList initialListOfUrls() { - return QStringList() << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + return QStringList() << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") // places + << QStringLiteral("remote:/") // shared << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); } void KFilePlacesModelTest::testInitialList() { const QStringList urls = initialListOfUrls(); CHECK_PLACES_URLS(urls); } void KFilePlacesModelTest::testReparse() { QStringList urls; // add item m_places->addPlace(QStringLiteral("foo"), QUrl::fromLocalFile(QStringLiteral("/foo")), QString(), QString()); urls = initialListOfUrls(); - urls.insert(4, QStringLiteral("/foo")); + + // it will be added at the end of places section + urls.insert(3, QStringLiteral("/foo")); CHECK_PLACES_URLS(urls); // reparse the bookmark file KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces")); bookmarkManager->notifyCompleteChange(QString()); // check if they are the same CHECK_PLACES_URLS(urls); // try to remove item - - m_places->removePlace(m_places->index(4, 0)); + m_places->removePlace(m_places->index(3, 0)); urls = initialListOfUrls(); CHECK_PLACES_URLS(urls); } void KFilePlacesModelTest::testInternalBookmarksHaveIds() { KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces")); KBookmarkGroup root = bookmarkManager->root(); // Verify every entry has an id or an udi KBookmark bookmark = root.first(); while (!bookmark.isNull()) { QVERIFY(!bookmark.metaDataItem(QStringLiteral("ID")).isEmpty() || !bookmark.metaDataItem(QStringLiteral("UDI")).isEmpty()); // It's mutualy exclusive though QVERIFY(bookmark.metaDataItem(QStringLiteral("ID")).isEmpty() || bookmark.metaDataItem(QStringLiteral("UDI")).isEmpty()); bookmark = root.next(bookmark); } // Verify that adding a bookmark behind its back the model gives it an id // (in real life it requires the user to modify the file by hand, // unlikely but better safe than sorry). // It induces a small race condition which means several ids will be // successively set on the same bookmark but no big deal since it won't // break the system KBookmark foo = root.addBookmark(QStringLiteral("Foo"), QUrl(QStringLiteral("file:/foo")), QStringLiteral("red-folder")); QCOMPARE(foo.text(), QStringLiteral("Foo")); QVERIFY(foo.metaDataItem(QStringLiteral("ID")).isEmpty()); bookmarkManager->emitChanged(root); QCOMPARE(foo.text(), QStringLiteral("Foo")); QVERIFY(!foo.metaDataItem(QStringLiteral("ID")).isEmpty()); // Verify that all the ids are different bookmark = root.first(); QSet ids; while (!bookmark.isNull()) { QString id; if (!bookmark.metaDataItem(QStringLiteral("UDI")).isEmpty()) { id = bookmark.metaDataItem(QStringLiteral("UDI")); } else { id = bookmark.metaDataItem(QStringLiteral("ID")); } QVERIFY2(!ids.contains(id), "Duplicated ID found!"); ids << id; bookmark = root.next(bookmark); } // Cleanup foo root.deleteBookmark(foo); bookmarkManager->emitChanged(root); } void KFilePlacesModelTest::testHiding() { // Verify that nothing is hidden for (int row = 0; row < m_places->rowCount(); ++row) { QModelIndex index = m_places->index(row, 0); QVERIFY(!m_places->isHidden(index)); } QModelIndex a = m_places->index(2, 0); QModelIndex b = m_places->index(6, 0); QList args; QSignalSpy spy(m_places, SIGNAL(dataChanged(QModelIndex,QModelIndex))); // Verify that hidden is taken into account and is not global m_places->setPlaceHidden(a, true); QVERIFY(m_places->isHidden(a)); QVERIFY(m_places->data(a, KFilePlacesModel::HiddenRole).toBool()); QVERIFY(!m_places->isHidden(b)); QVERIFY(!m_places->data(b, KFilePlacesModel::HiddenRole).toBool()); QCOMPARE(spy.count(), 1); args = spy.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), a); QCOMPARE(args.at(1).toModelIndex(), a); m_places->setPlaceHidden(b, true); QVERIFY(m_places->isHidden(a)); QVERIFY(m_places->data(a, KFilePlacesModel::HiddenRole).toBool()); QVERIFY(m_places->isHidden(b)); QVERIFY(m_places->data(b, KFilePlacesModel::HiddenRole).toBool()); QCOMPARE(spy.count(), 1); args = spy.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), b); QCOMPARE(args.at(1).toModelIndex(), b); m_places->setPlaceHidden(a, false); m_places->setPlaceHidden(b, false); QVERIFY(!m_places->isHidden(a)); QVERIFY(!m_places->data(a, KFilePlacesModel::HiddenRole).toBool()); QVERIFY(!m_places->isHidden(b)); QVERIFY(!m_places->data(b, KFilePlacesModel::HiddenRole).toBool()); QCOMPARE(spy.count(), 2); args = spy.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), a); QCOMPARE(args.at(1).toModelIndex(), a); args = spy.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), b); QCOMPARE(args.at(1).toModelIndex(), b); } void KFilePlacesModelTest::testMove() { QList args; QSignalSpy spy_inserted(m_places, SIGNAL(rowsInserted(QModelIndex,int,int))); QSignalSpy spy_removed(m_places, SIGNAL(rowsRemoved(QModelIndex,int,int))); KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces")); KBookmarkGroup root = bookmarkManager->root(); - KBookmark remote = m_places->bookmarkForIndex(m_places->index(1, 0)); - KBookmark before_remote = m_places->bookmarkForIndex(m_places->index(0, 0)); + KBookmark system_root = m_places->bookmarkForIndex(m_places->index(1, 0)); + KBookmark before_system_root = m_places->bookmarkForIndex(m_places->index(0, 0)); - // Trying move the remote at the end of the list, should move it to the end of places section instead + // Trying move the root at the end of the list, should move it to the end of places section instead // to keep it grouped KBookmark last = root.first(); while (!root.next(last).isNull()) { last = root.next(last); } - root.moveBookmark(remote, last); + root.moveBookmark(system_root, last); bookmarkManager->emitChanged(root); QStringList urls; - urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") << QStringLiteral("remote:/") + urls << QDir::homePath() << QStringLiteral("trash:/") << QStringLiteral(KDE_ROOT_PATH) + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 3); - QCOMPARE(args.at(2).toInt(), 3); + QCOMPARE(args.at(1).toInt(), 2); + QCOMPARE(args.at(2).toInt(), 2); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 1); QCOMPARE(args.at(2).toInt(), 1); - // Move the remote at the beginning of the list - root.moveBookmark(remote, KBookmark()); + // Move the root at the beginning of the list + root.moveBookmark(system_root, KBookmark()); bookmarkManager->emitChanged(root); urls.clear(); - urls << QStringLiteral("remote:/") << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QStringLiteral(KDE_ROOT_PATH) << QDir::homePath() << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 0); QCOMPARE(args.at(2).toInt(), 0); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 4); - QCOMPARE(args.at(2).toInt(), 4); + QCOMPARE(args.at(1).toInt(), 3); + QCOMPARE(args.at(2).toInt(), 3); - // Move the remote in the list (at its original place) - root.moveBookmark(remote, before_remote); + // Move the root in the list (at its original place) + root.moveBookmark(system_root, before_system_root); bookmarkManager->emitChanged(root); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 1); QCOMPARE(args.at(2).toInt(), 1); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 0); QCOMPARE(args.at(2).toInt(), 0); } void KFilePlacesModelTest::testDragAndDrop() { QList args; QSignalSpy spy_moved(m_places, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int))); // Monitor rowsInserted() and rowsRemoved() to ensure they are never emitted: // Moving with drag and drop is expected to emit rowsMoved() QSignalSpy spy_inserted(m_places, SIGNAL(rowsInserted(QModelIndex,int,int))); QSignalSpy spy_removed(m_places, SIGNAL(rowsRemoved(QModelIndex,int,int))); - // Move the remote at the end of the places list + // Move the KDE_ROOT_PATH at the end of the places list QModelIndexList indexes; indexes << m_places->index(1, 0); QMimeData *mimeData = m_places->mimeData(indexes); - QVERIFY(m_places->dropMimeData(mimeData, Qt::MoveAction, 4, 0, QModelIndex())); + QVERIFY(m_places->dropMimeData(mimeData, Qt::MoveAction, 3, 0, QModelIndex())); QStringList urls; - urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") << QStringLiteral("remote:/") + urls << QDir::homePath() << QStringLiteral("trash:/") << QStringLiteral(KDE_ROOT_PATH) + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 0); QCOMPARE(spy_moved.count(), 1); args = spy_moved.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 1); QCOMPARE(args.at(2).toInt(), 1); QCOMPARE(args.at(3).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(4).toInt(), 4); + QCOMPARE(args.at(4).toInt(), 3); - // Move the remote at the beginning of the list + // Move the KDE_ROOT_PATH at the beginning of the list indexes.clear(); - indexes << m_places->index(3, 0); + indexes << m_places->index(2, 0); mimeData = m_places->mimeData(indexes); QVERIFY(m_places->dropMimeData(mimeData, Qt::MoveAction, 0, 0, QModelIndex())); urls.clear(); - urls << QStringLiteral("remote:/") << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QStringLiteral(KDE_ROOT_PATH) << QDir::homePath() << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 0); QCOMPARE(spy_moved.count(), 1); args = spy_moved.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 3); - QCOMPARE(args.at(2).toInt(), 3); + QCOMPARE(args.at(1).toInt(), 2); + QCOMPARE(args.at(2).toInt(), 2); QCOMPARE(args.at(3).toModelIndex(), QModelIndex()); QCOMPARE(args.at(4).toInt(), 0); - // Move the remote in the list (at its original place) + // Move the KDE_ROOT_PATH in the list (at its original place) indexes.clear(); indexes << m_places->index(0, 0); mimeData = m_places->mimeData(indexes); QVERIFY(m_places->dropMimeData(mimeData, Qt::MoveAction, 2, 0, QModelIndex())); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 0); QCOMPARE(spy_moved.count(), 1); args = spy_moved.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 0); QCOMPARE(args.at(2).toInt(), 0); QCOMPARE(args.at(3).toModelIndex(), QModelIndex()); QCOMPARE(args.at(4).toInt(), 2); // Dropping on an item is not allowed indexes.clear(); indexes << m_places->index(4, 0); mimeData = m_places->mimeData(indexes); QVERIFY(!m_places->dropMimeData(mimeData, Qt::MoveAction, -1, 0, m_places->index(2, 0))); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 0); QCOMPARE(spy_moved.count(), 0); } void KFilePlacesModelTest::testPlacesLifecycle() { QList args; QSignalSpy spy_inserted(m_places, SIGNAL(rowsInserted(QModelIndex,int,int))); QSignalSpy spy_removed(m_places, SIGNAL(rowsRemoved(QModelIndex,int,int))); QSignalSpy spy_changed(m_places, SIGNAL(dataChanged(QModelIndex,QModelIndex))); m_places->addPlace(QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/home/foo"))); QStringList urls; - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") << QStringLiteral("/home/foo") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") << QStringLiteral("/home/foo") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 4); - QCOMPARE(args.at(2).toInt(), 4); + QCOMPARE(args.at(1).toInt(), 3); + QCOMPARE(args.at(2).toInt(), 3); QCOMPARE(spy_removed.count(), 0); KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces")); KBookmarkGroup root = bookmarkManager->root(); - KBookmark before_trash = m_places->bookmarkForIndex(m_places->index(2, 0)); - KBookmark foo = m_places->bookmarkForIndex(m_places->index(4, 0)); + KBookmark before_trash = m_places->bookmarkForIndex(m_places->index(1, 0)); + KBookmark foo = m_places->bookmarkForIndex(m_places->index(3, 0)); root.moveBookmark(foo, before_trash); bookmarkManager->emitChanged(root); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("/home/foo") << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("/home/foo") << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 4); - QCOMPARE(args.at(2).toInt(), 4); + QCOMPARE(args.at(1).toInt(), 3); + QCOMPARE(args.at(2).toInt(), 3); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 3); - QCOMPARE(args.at(2).toInt(), 3); + QCOMPARE(args.at(1).toInt(), 2); + QCOMPARE(args.at(2).toInt(), 2); - m_places->editPlace(m_places->index(3, 0), QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/mnt/foo"))); + m_places->editPlace(m_places->index(2, 0), QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/mnt/foo"))); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("/mnt/foo") << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("/mnt/foo") << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 0); QCOMPARE(spy_changed.count(), 1); args = spy_changed.takeFirst(); - QCOMPARE(args.at(0).toModelIndex(), m_places->index(3, 0)); - QCOMPARE(args.at(1).toModelIndex(), m_places->index(3, 0)); + QCOMPARE(args.at(0).toModelIndex(), m_places->index(2, 0)); + QCOMPARE(args.at(1).toModelIndex(), m_places->index(2, 0)); - foo = m_places->bookmarkForIndex(m_places->index(3, 0)); + foo = m_places->bookmarkForIndex(m_places->index(2, 0)); foo.setFullText(QStringLiteral("Bar")); bookmarkManager->notifyCompleteChange(QString()); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("/mnt/foo") << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("/mnt/foo") << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 0); QCOMPARE(spy_changed.count(), 10); - args = spy_changed[3]; - QCOMPARE(args.at(0).toModelIndex(), m_places->index(3, 0)); - QCOMPARE(args.at(1).toModelIndex(), m_places->index(3, 0)); + args = spy_changed[2]; + QCOMPARE(args.at(0).toModelIndex(), m_places->index(2, 0)); + QCOMPARE(args.at(1).toModelIndex(), m_places->index(2, 0)); spy_changed.clear(); - m_places->removePlace(m_places->index(3, 0)); + m_places->removePlace(m_places->index(2, 0)); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 3); - QCOMPARE(args.at(2).toInt(), 3); + QCOMPARE(args.at(1).toInt(), 2); + QCOMPARE(args.at(2).toInt(), 2); - m_places->addPlace(QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/home/foo")), QString(), QString(), m_places->index(1, 0)); + m_places->addPlace(QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/home/foo")), QString(), QString(), m_places->index(0, 0)); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral("/home/foo") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral("/home/foo") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); - QCOMPARE(args.at(1).toInt(), 2); - QCOMPARE(args.at(2).toInt(), 2); + QCOMPARE(args.at(1).toInt(), 1); + QCOMPARE(args.at(2).toInt(), 1); QCOMPARE(spy_removed.count(), 0); - m_places->removePlace(m_places->index(2, 0)); + m_places->removePlace(m_places->index(1, 0)); } void KFilePlacesModelTest::testDevicePlugging() { QList args; QSignalSpy spy_inserted(m_places, SIGNAL(rowsInserted(QModelIndex,int,int))); QSignalSpy spy_removed(m_places, SIGNAL(rowsRemoved(QModelIndex,int,int))); fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); QStringList urls; - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 7); QCOMPARE(args.at(2).toInt(), 7); fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 7); QCOMPARE(args.at(2).toInt(), 7); QCOMPARE(spy_removed.count(), 0); // Move the device in the list, and check that it memorizes the position across plug/unplug KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces")); KBookmarkGroup root = bookmarkManager->root(); KBookmark before_floppy; KBookmark device = root.first(); // The device we'll move is the 7th bookmark for (int i = 0; i < 6; i++) { if (i == 3) { // store item before to be able to move it back to original position device = before_floppy = root.next(device); } else { device = root.next(device); } } root.moveBookmark(device, before_floppy); bookmarkManager->emitChanged(root); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 7); QCOMPARE(args.at(2).toInt(), 7); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 6); QCOMPARE(args.at(2).toInt(), 6); fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 0); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 6); QCOMPARE(args.at(2).toInt(), 6); fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 6); QCOMPARE(args.at(2).toInt(), 6); QCOMPARE(spy_removed.count(), 0); KBookmark seventh = root.first(); for (int i = 0; i < 6; i++) { seventh = root.next(seventh); } root.moveBookmark(device, seventh); bookmarkManager->emitChanged(root); urls.clear(); - urls << QDir::homePath() << QStringLiteral("remote:/") << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); CHECK_PLACES_URLS(urls); QCOMPARE(spy_inserted.count(), 1); args = spy_inserted.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 7); QCOMPARE(args.at(2).toInt(), 7); QCOMPARE(spy_removed.count(), 1); args = spy_removed.takeFirst(); QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); QCOMPARE(args.at(1).toInt(), 6); QCOMPARE(args.at(2).toInt(), 6); } void KFilePlacesModelTest::testDeviceSetupTeardown() { QList args; QSignalSpy spy_changed(m_places, SIGNAL(dataChanged(QModelIndex,QModelIndex))); fakeDevice(QStringLiteral("/org/kde/solid/fakehw/volume_part1_size_993284096/StorageAccess"))->call(QStringLiteral("teardown")); QCOMPARE(spy_changed.count(), 1); args = spy_changed.takeFirst(); QCOMPARE(args.at(0).toModelIndex().row(), 7); QCOMPARE(args.at(1).toModelIndex().row(), 7); fakeDevice(QStringLiteral("/org/kde/solid/fakehw/volume_part1_size_993284096/StorageAccess"))->call(QStringLiteral("setup")); QCOMPARE(spy_changed.count(), 1); args = spy_changed.takeFirst(); QCOMPARE(args.at(0).toModelIndex().row(), 7); QCOMPARE(args.at(1).toModelIndex().row(), 7); } void KFilePlacesModelTest::testEnableBaloo() { KConfig config(QStringLiteral("baloofilerc")); KConfigGroup basicSettings = config.group("Basic Settings"); basicSettings.writeEntry("Indexing-Enabled", true); config.sync(); KFilePlacesModel places_with_baloo; QStringList urls; for (int row = 0; row < places_with_baloo.rowCount(); ++row) { QModelIndex index = places_with_baloo.index(row, 0); urls << places_with_baloo.url(index).toDisplayString(QUrl::PreferLocalFile); } QVERIFY(urls.contains("timeline:/today")); QVERIFY(urls.contains("timeline:/yesterday")); QVERIFY(urls.contains("timeline:/thismonth")); QVERIFY(urls.contains("timeline:/lastmonth")); QVERIFY(urls.contains("search:/documents")); QVERIFY(urls.contains("search:/images")); QVERIFY(urls.contains("search:/audio")); QVERIFY(urls.contains("search:/videos")); } +void KFilePlacesModelTest::testRemoteUrls_data() +{ + QTest::addColumn("url"); + QTest::addColumn("expectedRow"); + QTest::addColumn("expectedGroup"); + + QTest::newRow("Ftp") << QUrl(QStringLiteral("ftp://192.168.1.1/ftp")) << 4 << QStringLiteral("Remote"); + QTest::newRow("Samba") << QUrl(QStringLiteral("smb://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); + QTest::newRow("Sftp") << QUrl(QStringLiteral("sftp://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); + QTest::newRow("Fish") << QUrl(QStringLiteral("fish://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); + QTest::newRow("Webdav") << QUrl(QStringLiteral("webdav://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); +} + +void KFilePlacesModelTest::testRemoteUrls() +{ + QFETCH(QUrl, url); + QFETCH(int, expectedRow); + QFETCH(QString, expectedGroup); + + QList args; + QSignalSpy spy_inserted(m_places, SIGNAL(rowsInserted(QModelIndex,int,int))); + + // insert a new network url + m_places->addPlace(QStringLiteral("My Shared"), url, QString(), QString(), QModelIndex()); + + // check if url list is correct after insertion + QStringList urls; + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") // places + << QStringLiteral("remote:/") << url.toString() + << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") + << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); + CHECK_PLACES_URLS(urls); + + // check if the new url was inserted in the right position (end of "Remote" section) + QTRY_COMPARE(spy_inserted.count(), 1); + args = spy_inserted.takeFirst(); + QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); + QCOMPARE(args.at(1).toInt(), expectedRow); + QCOMPARE(args.at(2).toInt(), expectedRow); + + // check if the new url has the right group "Remote" + const QModelIndex index = m_places->index(expectedRow, 0); + QCOMPARE(index.data(KFilePlacesModel::GroupRole).toString(), expectedGroup); + + m_places->removePlace(index); +} + QTEST_MAIN(KFilePlacesModelTest) #include "kfileplacesmodeltest.moc" diff --git a/src/filewidgets/kfileplacesitem.cpp b/src/filewidgets/kfileplacesitem.cpp index a043b8f1..96e700c2 100644 --- a/src/filewidgets/kfileplacesitem.cpp +++ b/src/filewidgets/kfileplacesitem.cpp @@ -1,387 +1,396 @@ /* This file is part of the KDE project Copyright (C) 2007 Kevin Ottens This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kfileplacesitem_p.h" #include "kfileplacesmodel.h" #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include static bool isTrash(const KBookmark &bk) { return bk.url().toString() == QLatin1String("trash:/"); } KFilePlacesItem::KFilePlacesItem(KBookmarkManager *manager, const QString &address, const QString &udi) : m_manager(manager), m_folderIsEmpty(true), m_isCdrom(false), m_isAccessible(false) { updateDeviceInfo(udi); setBookmark(m_manager->findByAddress(address)); if (udi.isEmpty() && m_bookmark.metaDataItem(QStringLiteral("ID")).isEmpty()) { m_bookmark.setMetaDataItem(QStringLiteral("ID"), generateNewId()); } else if (udi.isEmpty()) { if (isTrash(m_bookmark)) { KConfig cfg(QStringLiteral("trashrc"), KConfig::SimpleConfig); const KConfigGroup group = cfg.group("Status"); m_folderIsEmpty = group.readEntry("Empty", true); } } } KFilePlacesItem::~KFilePlacesItem() { } QString KFilePlacesItem::id() const { if (isDevice()) { return bookmark().metaDataItem(QStringLiteral("UDI")); } else { return bookmark().metaDataItem(QStringLiteral("ID")); } } bool KFilePlacesItem::isDevice() const { return !bookmark().metaDataItem(QStringLiteral("UDI")).isEmpty(); } KBookmark KFilePlacesItem::bookmark() const { return m_bookmark; } void KFilePlacesItem::setBookmark(const KBookmark &bookmark) { m_bookmark = bookmark; updateDeviceInfo(m_bookmark.metaDataItem(QStringLiteral("UDI"))); if (bookmark.metaDataItem(QStringLiteral("isSystemItem")) == QLatin1String("true")) { // This context must stay as it is - the translated system bookmark names // are created with 'KFile System Bookmarks' as their context, so this // ensures the right string is picked from the catalog. // (coles, 13th May 2009) m_text = i18nc("KFile System Bookmarks", bookmark.text().toUtf8().data()); } else { m_text = bookmark.text(); } const GroupType type = groupType(); switch (type) { case PlacesType: m_groupName = i18nc("@item", "Places"); break; + case RemoteType: + m_groupName = i18nc("@item", "Remote"); + break; case RecentlySavedType: m_groupName = i18nc("@item", "Recently Saved"); break; case SearchForType: m_groupName = i18nc("@item", "Search For"); break; case DevicesType: m_groupName = i18nc("@item", "Devices"); break; case RemovableDevicesType: m_groupName = i18nc("@item", "Removable Devices"); break; default: Q_UNREACHABLE(); break; } } Solid::Device KFilePlacesItem::device() const { return m_device; } QVariant KFilePlacesItem::data(int role) const { if (role == KFilePlacesModel::GroupRole) { return QVariant(m_groupName); } else if (role != KFilePlacesModel::HiddenRole && role != Qt::BackgroundRole && isDevice()) { return deviceData(role); } else { return bookmarkData(role); } } KFilePlacesItem::GroupType KFilePlacesItem::groupType() const { if (!isDevice()) { const QString protocol = bookmark().url().scheme(); if (protocol == QLatin1String("timeline")) { return RecentlySavedType; } if (protocol.contains(QLatin1String("search"))) { return SearchForType; } if (protocol == QLatin1String("bluetooth") || protocol == QLatin1String("obexftp") || protocol == QLatin1String("kdeconnect")) { return DevicesType; } - return PlacesType; + if (protocol == QLatin1String("remote") || + KProtocolInfo::protocolClass(protocol) != QLatin1String(":local")) { + return RemoteType; + } else { + return PlacesType; + } } if (m_drive && (m_drive->isHotpluggable() || m_drive->isRemovable())) { return RemovableDevicesType; } else { return DevicesType; } } QVariant KFilePlacesItem::bookmarkData(int role) const { KBookmark b = bookmark(); if (b.isNull()) { return QVariant(); } switch (role) { case Qt::DisplayRole: return m_text; case Qt::DecorationRole: return QIcon::fromTheme(iconNameForBookmark(b)); case Qt::BackgroundRole: if (b.metaDataItem(QStringLiteral("IsHidden")) == QLatin1String("true")) { return QColor(Qt::lightGray); } else { return QVariant(); } case KFilePlacesModel::UrlRole: return b.url(); case KFilePlacesModel::SetupNeededRole: return false; case KFilePlacesModel::HiddenRole: return b.metaDataItem(QStringLiteral("IsHidden")) == QLatin1String("true"); default: return QVariant(); } } QVariant KFilePlacesItem::deviceData(int role) const { Solid::Device d = device(); if (d.isValid()) { switch (role) { case Qt::DisplayRole: return d.description(); case Qt::DecorationRole: return KDE::icon(m_iconPath, m_emblems); case KFilePlacesModel::UrlRole: if (m_access) { const QString path = m_access->filePath(); return path.isEmpty() ? QUrl() : QUrl::fromLocalFile(path); } else if (m_disc && (m_disc->availableContent() & Solid::OpticalDisc::Audio) != 0) { Solid::Block *block = d.as(); if (block) { QString device = block->device(); return QUrl(QStringLiteral("audiocd:/?device=%1").arg(device)); } // We failed to get the block device. Assume audiocd:/ can // figure it out, but cannot handle multiple disc drives. // See https://bugs.kde.org/show_bug.cgi?id=314544#c40 return QUrl(QStringLiteral("audiocd:/")); } else if (m_mtp) { return QUrl(QStringLiteral("mtp:udi=%1").arg(d.udi())); } else { return QVariant(); } case KFilePlacesModel::SetupNeededRole: if (m_access) { return !m_isAccessible; } else { return QVariant(); } case KFilePlacesModel::FixedDeviceRole: { if (m_drive != nullptr) { return !m_drive->isHotpluggable() && !m_drive->isRemovable(); } return true; } case KFilePlacesModel::CapacityBarRecommendedRole: return m_isAccessible && !m_isCdrom; default: return QVariant(); } } else { return QVariant(); } } KBookmark KFilePlacesItem::createBookmark(KBookmarkManager *manager, const QString &label, const QUrl &url, const QString &iconName, KFilePlacesItem *after) { KBookmarkGroup root = manager->root(); if (root.isNull()) { return KBookmark(); } QString empty_icon = iconName; if (url.toString() == QLatin1String("trash:/")) { if (empty_icon.endsWith(QLatin1String("-full"))) { empty_icon.chop(5); } else if (empty_icon.isEmpty()) { empty_icon = QStringLiteral("user-trash"); } } KBookmark bookmark = root.addBookmark(label, url, empty_icon); bookmark.setMetaDataItem(QStringLiteral("ID"), generateNewId()); if (after) { root.moveBookmark(bookmark, after->bookmark()); } return bookmark; } KBookmark KFilePlacesItem::createSystemBookmark(KBookmarkManager *manager, const QString &untranslatedLabel, const QString &translatedLabel, const QUrl &url, const QString &iconName) { Q_UNUSED(translatedLabel); // parameter is only necessary to force the caller // providing a translated string for the label KBookmark bookmark = createBookmark(manager, untranslatedLabel, url, iconName); if (!bookmark.isNull()) { bookmark.setMetaDataItem(QStringLiteral("isSystemItem"), QStringLiteral("true")); } return bookmark; } KBookmark KFilePlacesItem::createDeviceBookmark(KBookmarkManager *manager, const QString &udi) { KBookmarkGroup root = manager->root(); if (root.isNull()) { return KBookmark(); } KBookmark bookmark = root.createNewSeparator(); bookmark.setMetaDataItem(QStringLiteral("UDI"), udi); bookmark.setMetaDataItem(QStringLiteral("isSystemItem"), QStringLiteral("true")); return bookmark; } QString KFilePlacesItem::generateNewId() { static int count = 0; // return QString::number(count++); return QString::number(QDateTime::currentDateTimeUtc().toTime_t()) + '/' + QString::number(count++); // return QString::number(QDateTime::currentDateTime().toTime_t()) // + '/' + QString::number(qrand()); } bool KFilePlacesItem::updateDeviceInfo(const QString &udi) { if (m_device.udi() == udi) { return false; } if (m_access) { m_access->disconnect(this); } m_device = Solid::Device(udi); if (m_device.isValid()) { m_access = m_device.as(); m_volume = m_device.as(); m_disc = m_device.as(); m_mtp = m_device.as(); m_iconPath = m_device.icon(); m_emblems = m_device.emblems(); m_drive = nullptr; Solid::Device parentDevice = m_device; while (parentDevice.isValid() && !m_drive) { m_drive = parentDevice.as(); parentDevice = parentDevice.parent(); } if (m_access) { connect(m_access, &Solid::StorageAccess::accessibilityChanged, this, &KFilePlacesItem::onAccessibilityChanged); onAccessibilityChanged(m_access->isAccessible()); } } else { m_access = nullptr; m_volume = nullptr; m_disc = nullptr; m_mtp = nullptr; m_drive = nullptr; m_iconPath.clear(); m_emblems.clear(); } return true; } void KFilePlacesItem::onAccessibilityChanged(bool isAccessible) { m_isAccessible = isAccessible; m_isCdrom = m_device.is() || m_device.parent().is(); m_emblems = m_device.emblems(); emit itemChanged(id()); } QString KFilePlacesItem::iconNameForBookmark(const KBookmark &bookmark) const { if (!m_folderIsEmpty && isTrash(bookmark)) { return bookmark.icon() + "-full"; } else { return bookmark.icon(); } } #include "moc_kfileplacesitem_p.cpp" diff --git a/src/filewidgets/kfileplacesitem_p.h b/src/filewidgets/kfileplacesitem_p.h index 2b433e01..b0401c20 100644 --- a/src/filewidgets/kfileplacesitem_p.h +++ b/src/filewidgets/kfileplacesitem_p.h @@ -1,113 +1,114 @@ /* This file is part of the KDE project Copyright (C) 2007 Kevin Ottens This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KFILEPLACESITEM_P_H #define KFILEPLACESITEM_P_H #include #include #include #include #include #include #include class KDirLister; namespace Solid { class StorageAccess; class StorageVolume; class StorageDrive; class OpticalDisc; class PortableMediaPlayer; } class KFilePlacesItem : public QObject { Q_OBJECT public: enum GroupType { - PlacesType = 0, - RecentlySavedType = 1, - SearchForType = 2, - DevicesType = 3, - RemovableDevicesType = 4 + PlacesType, + RemoteType, + RecentlySavedType, + SearchForType, + DevicesType, + RemovableDevicesType }; KFilePlacesItem(KBookmarkManager *manager, const QString &address, const QString &udi = QString()); ~KFilePlacesItem(); QString id() const; bool isDevice() const; KBookmark bookmark() const; void setBookmark(const KBookmark &bookmark); Solid::Device device() const; QVariant data(int role) const; GroupType groupType() const; static KBookmark createBookmark(KBookmarkManager *manager, const QString &label, const QUrl &url, const QString &iconName, KFilePlacesItem *after = nullptr); static KBookmark createSystemBookmark(KBookmarkManager *manager, const QString &untranslatedLabel, const QString &translatedLabel, const QUrl &url, const QString &iconName); static KBookmark createDeviceBookmark(KBookmarkManager *manager, const QString &udi); Q_SIGNALS: void itemChanged(const QString &id); private Q_SLOTS: void onAccessibilityChanged(bool); private: QVariant bookmarkData(int role) const; QVariant deviceData(int role) const; QString iconNameForBookmark(const KBookmark &bookmark) const; static QString generateNewId(); bool updateDeviceInfo(const QString &udi); KBookmarkManager *m_manager; KBookmark m_bookmark; bool m_folderIsEmpty; bool m_isCdrom; bool m_isAccessible; QString m_text; Solid::Device m_device; QPointer m_access; QPointer m_volume; QPointer m_drive; QPointer m_disc; QPointer m_mtp; QString m_iconPath; QStringList m_emblems; QString m_groupName; }; #endif