diff options
Diffstat (limited to 'src/panels/places')
| -rw-r--r-- | src/panels/places/placesitem.cpp | 95 | ||||
| -rw-r--r-- | src/panels/places/placesitem.h | 32 | ||||
| -rw-r--r-- | src/panels/places/placesitemeditdialog.cpp | 8 | ||||
| -rw-r--r-- | src/panels/places/placesitemeditdialog.h | 6 | ||||
| -rw-r--r-- | src/panels/places/placesitemlistgroupheader.h | 8 | ||||
| -rw-r--r-- | src/panels/places/placesitemlistwidget.cpp | 3 | ||||
| -rw-r--r-- | src/panels/places/placesitemlistwidget.h | 6 | ||||
| -rw-r--r-- | src/panels/places/placesitemmodel.cpp | 989 | ||||
| -rw-r--r-- | src/panels/places/placesitemmodel.h | 205 | ||||
| -rw-r--r-- | src/panels/places/placesitemsignalhandler.h | 2 | ||||
| -rw-r--r-- | src/panels/places/placespanel.cpp | 62 | ||||
| -rw-r--r-- | src/panels/places/placespanel.h | 11 |
12 files changed, 454 insertions, 973 deletions
diff --git a/src/panels/places/placesitem.cpp b/src/panels/places/placesitem.cpp index 93cc4d5c3..3c6023ba8 100644 --- a/src/panels/places/placesitem.cpp +++ b/src/panels/places/placesitem.cpp @@ -66,7 +66,7 @@ void PlacesItem::setUrl(const QUrl &url) // watches for changes if the number of items has been changed. // The update of the icon is handled in onTrashDirListerCompleted(). m_trashDirLister = new KDirLister(); - m_trashDirLister->setAutoErrorHandlingEnabled(false, 0); + m_trashDirLister->setAutoErrorHandlingEnabled(false, nullptr); m_trashDirLister->setDelayedMimeTypes(true); QObject::connect(m_trashDirLister.data(), static_cast<void(KDirLister::*)()>(&KDirLister::completed), m_signalHandler.data(), &PlacesItemSignalHandler::onTrashDirListerCompleted); @@ -102,6 +102,16 @@ bool PlacesItem::isHidden() const return dataValue("isHidden").toBool(); } +bool PlacesItem::isGroupHidden() const +{ + return dataValue("isGroupHidden").toBool(); +} + +void PlacesItem::setGroupHidden(bool hidden) +{ + setDataValue("isGroupHidden", hidden); +} + void PlacesItem::setSystemItem(bool isSystemItem) { setDataValue("isSystemItem", isSystemItem); @@ -119,46 +129,30 @@ Solid::Device PlacesItem::device() const void PlacesItem::setBookmark(const KBookmark& bookmark) { - if (bookmark == m_bookmark) { - return; - } + const bool bookmarkDataChanged = !(bookmark == m_bookmark); + // bookmark object must be updated to keep in sync with source model m_bookmark = bookmark; + if (!bookmarkDataChanged) { + return; + } + delete m_access; delete m_volume; delete m_disc; delete m_mtp; - const QString udi = bookmark.metaDataItem(QStringLiteral("UDI")); if (udi.isEmpty()) { setIcon(bookmark.icon()); setText(i18nc("KFile System Bookmarks", bookmark.text().toUtf8().constData())); setUrl(bookmark.url()); + setSystemItem(bookmark.metaDataItem(QStringLiteral("isSystemItem")) == QLatin1String("true")); } else { initializeDevice(udi); } - const GroupType type = groupType(); - if (icon().isEmpty()) { - switch (type) { - case RecentlySavedType: setIcon(QStringLiteral("chronometer")); break; - case SearchForType: setIcon(QStringLiteral("system-search")); break; - case PlacesType: - default: setIcon(QStringLiteral("folder")); - } - - } - - switch (type) { - case PlacesType: setGroup(i18nc("@item", "Places")); break; - case RecentlySavedType: setGroup(i18nc("@item", "Recently Saved")); break; - case SearchForType: setGroup(i18nc("@item", "Search For")); break; - case DevicesType: setGroup(i18nc("@item", "Devices")); break; - default: Q_ASSERT(false); break; - } - setHidden(bookmark.metaDataItem(QStringLiteral("IsHidden")) == QLatin1String("true")); } @@ -167,62 +161,15 @@ KBookmark PlacesItem::bookmark() const return m_bookmark; } -PlacesItem::GroupType PlacesItem::groupType() const -{ - if (udi().isEmpty()) { - const QString protocol = 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; - } - - return DevicesType; -} - bool PlacesItem::storageSetupNeeded() const { return m_access ? !m_access->isAccessible() : false; } -KBookmark PlacesItem::createBookmark(KBookmarkManager* manager, - const QString& text, - const QUrl& url, - const QString& iconName) +bool PlacesItem::isSearchOrTimelineUrl() const { - KBookmarkGroup root = manager->root(); - if (root.isNull()) { - return KBookmark(); - } - - KBookmark bookmark = root.addBookmark(text, url, iconName); - bookmark.setFullText(text); - bookmark.setMetaDataItem(QStringLiteral("ID"), generateNewId()); - - return bookmark; -} - -KBookmark PlacesItem::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; + const QString urlScheme = url().scheme(); + return (urlScheme.contains("search") || urlScheme.contains("timeline")); } void PlacesItem::onDataValueChanged(const QByteArray& role, diff --git a/src/panels/places/placesitem.h b/src/panels/places/placesitem.h index d1b5b5d96..733265d46 100644 --- a/src/panels/places/placesitem.h +++ b/src/panels/places/placesitem.h @@ -40,16 +40,8 @@ class PlacesItem : public KStandardItem { public: - enum GroupType - { - PlacesType, - SearchForType, - RecentlySavedType, - DevicesType - }; - - explicit PlacesItem(const KBookmark& bookmark, PlacesItem* parent = 0); - virtual ~PlacesItem(); + explicit PlacesItem(const KBookmark& bookmark, PlacesItem* parent = nullptr); + ~PlacesItem() override; void setUrl(const QUrl& url); QUrl url() const; @@ -60,6 +52,9 @@ public: void setHidden(bool hidden); bool isHidden() const; + void setGroupHidden(bool hidden); + bool isGroupHidden() const; + void setSystemItem(bool isSystemItem); bool isSystemItem() const; @@ -68,26 +63,19 @@ public: void setBookmark(const KBookmark& bookmark); KBookmark bookmark() const; - GroupType groupType() const; - bool storageSetupNeeded() const; - static KBookmark createBookmark(KBookmarkManager* manager, - const QString& text, - const QUrl& url, - const QString& iconName); - static KBookmark createDeviceBookmark(KBookmarkManager* manager, - const QString& udi); + bool isSearchOrTimelineUrl() const; PlacesItemSignalHandler* signalHandler() const; protected: - virtual void onDataValueChanged(const QByteArray& role, + void onDataValueChanged(const QByteArray& role, const QVariant& current, - const QVariant& previous) Q_DECL_OVERRIDE; + const QVariant& previous) override; - virtual void onDataChanged(const QHash<QByteArray, QVariant>& current, - const QHash<QByteArray, QVariant>& previous) Q_DECL_OVERRIDE; + void onDataChanged(const QHash<QByteArray, QVariant>& current, + const QHash<QByteArray, QVariant>& previous) override; private: PlacesItem(const PlacesItem& item); diff --git a/src/panels/places/placesitemeditdialog.cpp b/src/panels/places/placesitemeditdialog.cpp index ffcac4c8f..4a56ce908 100644 --- a/src/panels/places/placesitemeditdialog.cpp +++ b/src/panels/places/placesitemeditdialog.cpp @@ -44,10 +44,10 @@ PlacesItemEditDialog::PlacesItemEditDialog(QWidget* parent) : m_text(), m_url(), m_allowGlobal(false), - m_urlEdit(0), - m_textEdit(0), - m_iconButton(0), - m_appLocal(0), + m_urlEdit(nullptr), + m_textEdit(nullptr), + m_iconButton(nullptr), + m_appLocal(nullptr), m_buttonBox(nullptr) { } diff --git a/src/panels/places/placesitemeditdialog.h b/src/panels/places/placesitemeditdialog.h index f2d69781a..73104a1b6 100644 --- a/src/panels/places/placesitemeditdialog.h +++ b/src/panels/places/placesitemeditdialog.h @@ -38,8 +38,8 @@ class PlacesItemEditDialog: public QDialog Q_OBJECT public: - explicit PlacesItemEditDialog(QWidget* parent = 0); - virtual ~PlacesItemEditDialog(); + explicit PlacesItemEditDialog(QWidget* parent = nullptr); + ~PlacesItemEditDialog() override; void setIcon(const QString& icon); QString icon() const; @@ -54,7 +54,7 @@ public: bool allowGlobal() const; protected: - virtual bool event(QEvent* event) Q_DECL_OVERRIDE; + bool event(QEvent* event) override; private slots: void slotUrlChanged(const QString& text); diff --git a/src/panels/places/placesitemlistgroupheader.h b/src/panels/places/placesitemlistgroupheader.h index ec845e0ae..4408aa9ef 100644 --- a/src/panels/places/placesitemlistgroupheader.h +++ b/src/panels/places/placesitemlistgroupheader.h @@ -27,13 +27,13 @@ class PlacesItemListGroupHeader : public KStandardItemListGroupHeader Q_OBJECT public: - PlacesItemListGroupHeader(QGraphicsWidget* parent = 0); - virtual ~PlacesItemListGroupHeader(); + PlacesItemListGroupHeader(QGraphicsWidget* parent = nullptr); + ~PlacesItemListGroupHeader() override; protected: - virtual void paintSeparator(QPainter* painter, const QColor& color) Q_DECL_OVERRIDE; + void paintSeparator(QPainter* painter, const QColor& color) override; - virtual QPalette::ColorRole normalTextColorRole() const Q_DECL_OVERRIDE; + QPalette::ColorRole normalTextColorRole() const override; }; #endif diff --git a/src/panels/places/placesitemlistwidget.cpp b/src/panels/places/placesitemlistwidget.cpp index 18e561864..b0b3fb2aa 100644 --- a/src/panels/places/placesitemlistwidget.cpp +++ b/src/panels/places/placesitemlistwidget.cpp @@ -30,7 +30,8 @@ PlacesItemListWidget::~PlacesItemListWidget() bool PlacesItemListWidget::isHidden() const { - return data().value("isHidden").toBool(); + return data().value("isHidden").toBool() || + data().value("isGroupHidden").toBool(); } QPalette::ColorRole PlacesItemListWidget::normalTextColorRole() const diff --git a/src/panels/places/placesitemlistwidget.h b/src/panels/places/placesitemlistwidget.h index e9e6a0767..3be5dde7c 100644 --- a/src/panels/places/placesitemlistwidget.h +++ b/src/panels/places/placesitemlistwidget.h @@ -32,11 +32,11 @@ class PlacesItemListWidget : public KStandardItemListWidget public: PlacesItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent); - virtual ~PlacesItemListWidget(); + ~PlacesItemListWidget() override; protected: - virtual bool isHidden() const Q_DECL_OVERRIDE; - virtual QPalette::ColorRole normalTextColorRole() const Q_DECL_OVERRIDE; + bool isHidden() const override; + QPalette::ColorRole normalTextColorRole() const override; }; #endif diff --git a/src/panels/places/placesitemmodel.cpp b/src/panels/places/placesitemmodel.cpp index abdd4c20b..077c9044c 100644 --- a/src/panels/places/placesitemmodel.cpp +++ b/src/panels/places/placesitemmodel.cpp @@ -40,6 +40,7 @@ #include <QMimeData> #include <QTimer> #include <KUrlMimeData> +#include <KFilePlacesModel> #include <Solid/Device> #include <Solid/DeviceNotifier> @@ -51,21 +52,10 @@ #include <views/dolphinview.h> #include <views/viewproperties.h> -#ifdef HAVE_BALOO - #include <Baloo/Query> - #include <Baloo/IndexerConfig> -#endif - namespace { - // As long as KFilePlacesView from kdelibs is available in parallel, the - // system-bookmarks for "Recently Saved" and "Search For" should be - // shown only inside the Places Panel. This is necessary as the stored - // URLs needs to get translated to a Baloo-search-URL on-the-fly to - // be independent from changes in the Baloo-search-URL-syntax. - // Hence a prefix to the application-name of the stored bookmarks is + // A suffix to the application-name of the stored bookmarks is // added, which is only read by PlacesItemModel. - const char AppNamePrefix[] = "-places-panel"; - + const QString AppNameSuffix = QStringLiteral("-places-panel"); static QList<QUrl> balooURLs = { QUrl(QStringLiteral("timeline:/today")), QUrl(QStringLiteral("timeline:/yesterday")), @@ -80,53 +70,33 @@ namespace { PlacesItemModel::PlacesItemModel(QObject* parent) : KStandardItemModel(parent), - m_fileIndexingEnabled(false), m_hiddenItemsShown(false), - m_availableDevices(), - m_predicate(), - m_bookmarkManager(0), - m_systemBookmarks(), - m_systemBookmarksIndexes(), - m_bookmarkedItems(), - m_hiddenItemToRemove(-1), - m_deviceToTearDown(0), - m_updateBookmarksTimer(0), - m_storageSetupInProgress() + m_deviceToTearDown(nullptr), + m_storageSetupInProgress(), + m_sourceModel(new KFilePlacesModel(KAboutData::applicationData().componentName() + AppNameSuffix, this)) { -#ifdef HAVE_BALOO - Baloo::IndexerConfig config; - m_fileIndexingEnabled = config.fileIndexingEnabled(); -#endif - const QString file = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/user-places.xbel"; - m_bookmarkManager = KBookmarkManager::managerForExternalFile(file); - - createSystemBookmarks(); - initializeAvailableDevices(); + cleanupBookmarks(); loadBookmarks(); + initializeDefaultViewProperties(); - const int syncBookmarksTimeout = 100; - - m_updateBookmarksTimer = new QTimer(this); - m_updateBookmarksTimer->setInterval(syncBookmarksTimeout); - m_updateBookmarksTimer->setSingleShot(true); - connect(m_updateBookmarksTimer, &QTimer::timeout, this, &PlacesItemModel::updateBookmarks); - - connect(m_bookmarkManager, &KBookmarkManager::changed, - m_updateBookmarksTimer, static_cast<void(QTimer::*)()>(&QTimer::start)); + connect(m_sourceModel.data(), &KFilePlacesModel::rowsInserted, this, &PlacesItemModel::onSourceModelRowsInserted); + connect(m_sourceModel.data(), &KFilePlacesModel::rowsAboutToBeRemoved, this, &PlacesItemModel::onSourceModelRowsAboutToBeRemoved); + connect(m_sourceModel.data(), &KFilePlacesModel::dataChanged, this, &PlacesItemModel::onSourceModelDataChanged); + connect(m_sourceModel.data(), &KFilePlacesModel::rowsAboutToBeMoved, this, &PlacesItemModel::onSourceModelRowsAboutToBeMoved); + connect(m_sourceModel.data(), &KFilePlacesModel::rowsMoved, this, &PlacesItemModel::onSourceModelRowsMoved); + connect(m_sourceModel.data(), &KFilePlacesModel::groupHiddenChanged, this, &PlacesItemModel::onSourceModelGroupHiddenChanged); } PlacesItemModel::~PlacesItemModel() { - qDeleteAll(m_bookmarkedItems); - m_bookmarkedItems.clear(); } -PlacesItem* PlacesItemModel::createPlacesItem(const QString& text, - const QUrl& url, - const QString& iconName) +void PlacesItemModel::createPlacesItem(const QString& text, + const QUrl& url, + const QString& iconName, + int after) { - const KBookmark bookmark = PlacesItem::createBookmark(m_bookmarkManager, text, url, iconName); - return new PlacesItem(bookmark); + m_sourceModel->addPlace(text, url, iconName, {}, mapToSource(after)); } PlacesItem* PlacesItemModel::placesItem(int index) const @@ -136,20 +106,7 @@ PlacesItem* PlacesItemModel::placesItem(int index) const int PlacesItemModel::hiddenCount() const { - int modelIndex = 0; - int hiddenItemCount = 0; - foreach (const PlacesItem* item, m_bookmarkedItems) { - if (item) { - ++hiddenItemCount; - } else { - if (placesItem(modelIndex)->isHidden()) { - ++hiddenItemCount; - } - ++modelIndex; - } - } - - return hiddenItemCount; + return m_sourceModel->hiddenCount(); } void PlacesItemModel::setHiddenItemsShown(bool show) @@ -161,38 +118,18 @@ void PlacesItemModel::setHiddenItemsShown(bool show) m_hiddenItemsShown = show; if (show) { - // Move all items that are part of m_bookmarkedItems to the model. - QList<PlacesItem*> itemsToInsert; - QList<int> insertPos; - int modelIndex = 0; - for (int i = 0; i < m_bookmarkedItems.count(); ++i) { - if (m_bookmarkedItems[i]) { - itemsToInsert.append(m_bookmarkedItems[i]); - m_bookmarkedItems[i] = 0; - insertPos.append(modelIndex); + for (int r = 0, rMax = m_sourceModel->rowCount(); r < rMax; r++) { + const QModelIndex index = m_sourceModel->index(r, 0); + if (!m_sourceModel->isHidden(index)) { + continue; } - ++modelIndex; - } - - // Inserting the items will automatically insert an item - // to m_bookmarkedItems in PlacesItemModel::onItemsInserted(). - // The items are temporary saved in itemsToInsert, so - // m_bookmarkedItems can be shrinked now. - m_bookmarkedItems.erase(m_bookmarkedItems.begin(), - m_bookmarkedItems.begin() + itemsToInsert.count()); - - for (int i = 0; i < itemsToInsert.count(); ++i) { - insertItem(insertPos[i], itemsToInsert[i]); + addItemFromSourceModel(index); } - - Q_ASSERT(m_bookmarkedItems.count() == count()); } else { - // Move all items of the model, where the "isHidden" property is true, to - // m_bookmarkedItems. - Q_ASSERT(m_bookmarkedItems.count() == count()); - for (int i = count() - 1; i >= 0; --i) { - if (placesItem(i)->isHidden()) { - hideItem(i); + for (int r = 0, rMax = m_sourceModel->rowCount(); r < rMax; r++) { + const QModelIndex index = m_sourceModel->index(r, 0); + if (m_sourceModel->isHidden(index)) { + removeItemByIndex(index); } } } @@ -210,75 +147,99 @@ bool PlacesItemModel::hiddenItemsShown() const int PlacesItemModel::closestItem(const QUrl& url) const { - int foundIndex = -1; - int maxLength = 0; - - for (int i = 0; i < count(); ++i) { - const QUrl itemUrl = placesItem(i)->url(); - if (url == itemUrl) { - // We can't find a closer one, so stop here. - foundIndex = i; - break; - } else if (itemUrl.isParentOf(url)) { - const int length = itemUrl.path().length(); - if (length > maxLength) { - foundIndex = i; - maxLength = length; - } - } - } - - return foundIndex; + return mapFromSource(m_sourceModel->closestItem(url)); } -void PlacesItemModel::appendItemToGroup(PlacesItem* item) +// look for the correct position for the item based on source model +void PlacesItemModel::insertSortedItem(PlacesItem* item) { if (!item) { return; } - int i = 0; - while (i < count() && placesItem(i)->group() != item->group()) { - ++i; - } + const KBookmark iBookmark = item->bookmark(); + const QString iBookmarkId = bookmarkId(iBookmark); + QModelIndex sourceIndex; + int pos = 0; - bool inserted = false; - while (!inserted && i < count()) { - if (placesItem(i)->group() != item->group()) { - insertItem(i, item); - inserted = true; + for(int r = 0, rMax = m_sourceModel->rowCount(); r < rMax; r++) { + sourceIndex = m_sourceModel->index(r, 0); + const KBookmark sourceBookmark = m_sourceModel->bookmarkForIndex(sourceIndex); + + if (bookmarkId(sourceBookmark) == iBookmarkId) { + break; } - ++i; - } - if (!inserted) { - appendItem(item); + if (m_hiddenItemsShown || !m_sourceModel->isHidden(sourceIndex)) { + pos++; + } } + + m_indexMap.insert(pos, sourceIndex); + insertItem(pos, item); +} + +void PlacesItemModel::onItemInserted(int index) +{ + KStandardItemModel::onItemInserted(index); +#ifdef PLACESITEMMODEL_DEBUG + qCDebug(DolphinDebug) << "Inserted item" << index; + showModelState(); +#endif } +void PlacesItemModel::onItemRemoved(int index, KStandardItem* removedItem) +{ + m_indexMap.removeAt(index); + + KStandardItemModel::onItemRemoved(index, removedItem); +#ifdef PLACESITEMMODEL_DEBUG + qCDebug(DolphinDebug) << "Removed item" << index; + showModelState(); +#endif +} + +void PlacesItemModel::onItemChanged(int index, const QSet<QByteArray>& changedRoles) +{ + const QModelIndex sourceIndex = mapToSource(index); + const PlacesItem *changedItem = placesItem(mapFromSource(sourceIndex)); + + if (!changedItem || !sourceIndex.isValid()) { + qWarning() << "invalid item changed signal"; + return; + } + if (changedRoles.contains("isHidden")) { + if (m_sourceModel->isHidden(sourceIndex) != changedItem->isHidden()) { + m_sourceModel->setPlaceHidden(sourceIndex, changedItem->isHidden()); + } else { + m_sourceModel->refresh(); + } + } + KStandardItemModel::onItemChanged(index, changedRoles); +} QAction* PlacesItemModel::ejectAction(int index) const { const PlacesItem* item = placesItem(index); if (item && item->device().is<Solid::OpticalDisc>()) { - return new QAction(QIcon::fromTheme(QStringLiteral("media-eject")), i18nc("@item", "Eject"), 0); + return new QAction(QIcon::fromTheme(QStringLiteral("media-eject")), i18nc("@item", "Eject"), nullptr); } - return 0; + return nullptr; } QAction* PlacesItemModel::teardownAction(int index) const { const PlacesItem* item = placesItem(index); if (!item) { - return 0; + return nullptr; } Solid::Device device = item->device(); const bool providesTearDown = device.is<Solid::StorageAccess>() && device.as<Solid::StorageAccess>()->isAccessible(); if (!providesTearDown) { - return 0; + return nullptr; } Solid::StorageDrive* drive = device.as<Solid::StorageDrive>(); @@ -306,10 +267,10 @@ QAction* PlacesItemModel::teardownAction(int index) const } if (iconName.isEmpty()) { - return new QAction(text, 0); + return new QAction(text, nullptr); } - return new QAction(QIcon::fromTheme(iconName), text, 0); + return new QAction(QIcon::fromTheme(iconName), text, nullptr); } void PlacesItemModel::requestEject(int index) @@ -415,25 +376,8 @@ void PlacesItemModel::dropMimeDataBefore(int index, const QMimeData* mimeData) QDataStream stream(&itemData, QIODevice::ReadOnly); int oldIndex; stream >> oldIndex; - if (oldIndex == index || oldIndex == index - 1) { - // No moving has been done - return; - } - PlacesItem* oldItem = placesItem(oldIndex); - if (!oldItem) { - return; - } - - PlacesItem* newItem = new PlacesItem(oldItem->bookmark()); - removeItem(oldIndex); - - if (oldIndex < index) { - --index; - } - - const int dropIndex = groupedDropIndex(index, newItem); - insertItem(dropIndex, newItem); + m_sourceModel->movePlace(oldIndex, index); } else if (mimeData->hasFormat(QStringLiteral("text/uri-list"))) { // One or more items must be added to the model const QList<QUrl> urls = KUrlMimeData::urlsFromMimeData(mimeData); @@ -451,152 +395,106 @@ void PlacesItemModel::dropMimeDataBefore(int index, const QMimeData* mimeData) continue; } - PlacesItem* newItem = createPlacesItem(text, url); - const int dropIndex = groupedDropIndex(index, newItem); - insertItem(dropIndex, newItem); + createPlacesItem(text, url, KIO::iconNameForUrl(url), qMax(0, index - 1)); } } + // will save bookmark alteration and fix sort if that is broken by the drag/drop operation + refresh(); } -QUrl PlacesItemModel::convertedUrl(const QUrl& url) -{ - QUrl newUrl = url; - if (url.scheme() == QLatin1String("timeline")) { - newUrl = createTimelineUrl(url); - } else if (url.scheme() == QLatin1String("search")) { - newUrl = createSearchUrl(url); - } - - return newUrl; -} - -void PlacesItemModel::onItemInserted(int index) +void PlacesItemModel::addItemFromSourceModel(const QModelIndex &index) { - const PlacesItem* insertedItem = placesItem(index); - if (insertedItem) { - // Take care to apply the PlacesItemModel-order of the inserted item - // also to the bookmark-manager. - const KBookmark insertedBookmark = insertedItem->bookmark(); - - const PlacesItem* previousItem = placesItem(index - 1); - KBookmark previousBookmark; - if (previousItem) { - previousBookmark = previousItem->bookmark(); - } - - m_bookmarkManager->root().moveBookmark(insertedBookmark, previousBookmark); + if (!m_hiddenItemsShown && m_sourceModel->isHidden(index)) { + return; } - if (index == count() - 1) { - // The item has been appended as last item to the list. In this - // case assure that it is also appended after the hidden items and - // not before (like done otherwise). - m_bookmarkedItems.append(0); - } else { - - int modelIndex = -1; - int bookmarkIndex = 0; - while (bookmarkIndex < m_bookmarkedItems.count()) { - if (!m_bookmarkedItems[bookmarkIndex]) { - ++modelIndex; - if (modelIndex + 1 == index) { - break; - } - } - ++bookmarkIndex; - } - m_bookmarkedItems.insert(bookmarkIndex, 0); + const KBookmark bookmark = m_sourceModel->bookmarkForIndex(index); + Q_ASSERT(!bookmark.isNull()); + PlacesItem *item = itemFromBookmark(bookmark); + if (!item) { + item = new PlacesItem(bookmark); } + updateItem(item, index); + insertSortedItem(item); -#ifdef PLACESITEMMODEL_DEBUG - qCDebug(DolphinDebug) << "Inserted item" << index; - showModelState(); -#endif -} - -void PlacesItemModel::onItemRemoved(int index, KStandardItem* removedItem) -{ - PlacesItem* placesItem = dynamic_cast<PlacesItem*>(removedItem); - if (placesItem) { - const KBookmark bookmark = placesItem->bookmark(); - m_bookmarkManager->root().deleteBookmark(bookmark); + if (m_sourceModel->isDevice(index)) { + connect(item->signalHandler(), &PlacesItemSignalHandler::tearDownExternallyRequested, + this, &PlacesItemModel::storageTearDownExternallyRequested); } - - const int boomarkIndex = bookmarkIndex(index); - Q_ASSERT(!m_bookmarkedItems[boomarkIndex]); - m_bookmarkedItems.removeAt(boomarkIndex); - -#ifdef PLACESITEMMODEL_DEBUG - qCDebug(DolphinDebug) << "Removed item" << index; - showModelState(); -#endif } -void PlacesItemModel::onItemChanged(int index, const QSet<QByteArray>& changedRoles) +void PlacesItemModel::removeItemByIndex(const QModelIndex &sourceIndex) { - const PlacesItem* changedItem = placesItem(index); - if (changedItem) { - // Take care to apply the PlacesItemModel-order of the changed item - // also to the bookmark-manager. - const KBookmark insertedBookmark = changedItem->bookmark(); - - const PlacesItem* previousItem = placesItem(index - 1); - KBookmark previousBookmark; - if (previousItem) { - previousBookmark = previousItem->bookmark(); - } - - m_bookmarkManager->root().moveBookmark(insertedBookmark, previousBookmark); - } + QString id = bookmarkId(m_sourceModel->bookmarkForIndex(sourceIndex)); - if (changedRoles.contains("isHidden")) { - if (!m_hiddenItemsShown && changedItem->isHidden()) { - m_hiddenItemToRemove = index; - QTimer::singleShot(0, this, static_cast<void (PlacesItemModel::*)()>(&PlacesItemModel::hideItem)); + for (int i = 0, iMax = count(); i < iMax; ++i) { + if (bookmarkId(placesItem(i)->bookmark()) == id) { + removeItem(i); + return; } } } -void PlacesItemModel::slotDeviceAdded(const QString& udi) +QString PlacesItemModel::bookmarkId(const KBookmark &bookmark) const { - const Solid::Device device(udi); - - if (!m_predicate.matches(device)) { - return; + QString id = bookmark.metaDataItem(QStringLiteral("UDI")); + if (id.isEmpty()) { + id = bookmark.metaDataItem(QStringLiteral("ID")); } - - m_availableDevices << udi; - const KBookmark bookmark = PlacesItem::createDeviceBookmark(m_bookmarkManager, udi); - - PlacesItem *item = new PlacesItem(bookmark); - appendItem(item); - connect(item->signalHandler(), &PlacesItemSignalHandler::tearDownExternallyRequested, - this, &PlacesItemModel::storageTearDownExternallyRequested); + return id; } -void PlacesItemModel::slotDeviceRemoved(const QString& udi) +void PlacesItemModel::initializeDefaultViewProperties() const { - if (!m_availableDevices.contains(udi)) { - return; - } - - for (int i = 0; i < m_bookmarkedItems.count(); ++i) { - PlacesItem* item = m_bookmarkedItems[i]; - if (item && item->udi() == udi) { - m_bookmarkedItems.removeAt(i); - delete item; - return; + for(int i = 0, iMax = m_sourceModel->rowCount(); i < iMax; i++) { + const QModelIndex index = m_sourceModel->index(i, 0); + const PlacesItem *item = placesItem(mapFromSource(index)); + if (!item) { + continue; } - } - for (int i = 0; i < count(); ++i) { - if (placesItem(i)->udi() == udi) { - removeItem(i); - return; + // Create default view-properties for all "Search For" and "Recently Saved" bookmarks + // in case the user has not already created custom view-properties for a corresponding + // query yet. + const bool createDefaultViewProperties = item->isSearchOrTimelineUrl() && !GeneralSettings::self()->globalViewProps(); + if (createDefaultViewProperties) { + const QUrl itemUrl = item->url(); + ViewProperties props(KFilePlacesModel::convertedUrl(itemUrl)); + if (!props.exist()) { + const QString path = itemUrl.path(); + if (path == QLatin1String("/documents")) { + props.setViewMode(DolphinView::DetailsView); + props.setPreviewsShown(false); + props.setVisibleRoles({"text", "path"}); + } else if (path == QLatin1String("/images")) { + props.setViewMode(DolphinView::IconsView); + props.setPreviewsShown(true); + props.setVisibleRoles({"text", "imageSize"}); + } else if (path == QLatin1String("/audio")) { + props.setViewMode(DolphinView::DetailsView); + props.setPreviewsShown(false); + props.setVisibleRoles({"text", "artist", "album"}); + } else if (path == QLatin1String("/videos")) { + props.setViewMode(DolphinView::IconsView); + props.setPreviewsShown(true); + props.setVisibleRoles({"text"}); + } else if (itemUrl.scheme() == QLatin1String("timeline")) { + props.setViewMode(DolphinView::DetailsView); + props.setVisibleRoles({"text", "modificationtime"}); + } + props.save(); + } } } } +void PlacesItemModel::updateItem(PlacesItem *item, const QModelIndex &index) +{ + item->setGroup(index.data(KFilePlacesModel::GroupRole).toString()); + item->setIcon(index.data(KFilePlacesModel::IconNameRole).toString()); + item->setGroupHidden(index.data(KFilePlacesModel::GroupHiddenRole).toBool()); +} + void PlacesItemModel::slotStorageTearDownDone(Solid::ErrorType error, const QVariant& errorData) { if (error && errorData.isValid()) { @@ -633,342 +531,133 @@ void PlacesItemModel::slotStorageSetupDone(Solid::ErrorType error, } } -void PlacesItemModel::hideItem() +void PlacesItemModel::onSourceModelRowsInserted(const QModelIndex &parent, int first, int last) { - hideItem(m_hiddenItemToRemove); - m_hiddenItemToRemove = -1; + for (int i = first; i <= last; i++) { + const QModelIndex index = m_sourceModel->index(i, 0, parent); + addItemFromSourceModel(index); + } } -void PlacesItemModel::updateBookmarks() +void PlacesItemModel::onSourceModelRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) { - // Verify whether new bookmarks have been added or existing - // bookmarks have been changed. - KBookmarkGroup root = m_bookmarkManager->root(); - KBookmark newBookmark = root.first(); - while (!newBookmark.isNull()) { - if (acceptBookmark(newBookmark, m_availableDevices)) { - bool found = false; - int modelIndex = 0; - for (int i = 0; i < m_bookmarkedItems.count(); ++i) { - PlacesItem* item = m_bookmarkedItems[i]; - if (!item) { - item = placesItem(modelIndex); - ++modelIndex; - } - - const KBookmark oldBookmark = item->bookmark(); - if (equalBookmarkIdentifiers(newBookmark, oldBookmark)) { - // The bookmark has been found in the model or as - // a hidden item. The content of the bookmark might - // have been changed, so an update is done. - found = true; - if (newBookmark.metaDataItem(QStringLiteral("UDI")).isEmpty()) { - item->setBookmark(newBookmark); - item->setText(i18nc("KFile System Bookmarks", newBookmark.text().toUtf8().constData())); - } - break; - } - } - - if (!found) { - const QString udi = newBookmark.metaDataItem(QStringLiteral("UDI")); - - /* - * See Bug 304878 - * Only add a new places item, if the item text is not empty - * and if the device is available. Fixes the strange behaviour - - * add a places item without text in the Places section - when you - * remove a device (e.g. a usb stick) without unmounting. - */ - if (udi.isEmpty() || Solid::Device(udi).isValid()) { - PlacesItem* item = new PlacesItem(newBookmark); - if (item->isHidden() && !m_hiddenItemsShown) { - m_bookmarkedItems.append(item); - } else { - appendItemToGroup(item); - } - } - } + for(int r = first; r <= last; r++) { + const QModelIndex index = m_sourceModel->index(r, 0, parent); + int oldIndex = mapFromSource(index); + if (oldIndex != -1) { + removeItem(oldIndex); } - - newBookmark = root.next(newBookmark); } +} - // Remove items that are not part of the bookmark-manager anymore - int modelIndex = 0; - for (int i = m_bookmarkedItems.count() - 1; i >= 0; --i) { - PlacesItem* item = m_bookmarkedItems[i]; - const bool itemIsPartOfModel = (item == 0); - if (itemIsPartOfModel) { - item = placesItem(modelIndex); - } - - bool hasBeenRemoved = true; - const KBookmark oldBookmark = item->bookmark(); - KBookmark newBookmark = root.first(); - while (!newBookmark.isNull()) { - if (equalBookmarkIdentifiers(newBookmark, oldBookmark)) { - hasBeenRemoved = false; - break; - } - newBookmark = root.next(newBookmark); - } - - if (hasBeenRemoved) { - if (m_bookmarkedItems[i]) { - delete m_bookmarkedItems[i]; - m_bookmarkedItems.removeAt(i); - } else { - removeItem(modelIndex); - --modelIndex; - } - } +void PlacesItemModel::onSourceModelRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) +{ + Q_UNUSED(destination); + Q_UNUSED(row); - if (itemIsPartOfModel) { - ++modelIndex; - } + for(int r = start; r <= end; r++) { + const QModelIndex sourceIndex = m_sourceModel->index(r, 0, parent); + // remove moved item + removeItem(mapFromSource(sourceIndex)); } } -void PlacesItemModel::saveBookmarks() +void PlacesItemModel::onSourceModelRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) { - m_bookmarkManager->emitChanged(m_bookmarkManager->root()); -} + Q_UNUSED(destination); + Q_UNUSED(parent); -void PlacesItemModel::loadBookmarks() -{ - KBookmarkGroup root = m_bookmarkManager->root(); - KBookmark bookmark = root.first(); - QSet<QString> devices = m_availableDevices; + const int blockSize = (end - start) + 1; - QSet<QUrl> missingSystemBookmarks; - foreach (const SystemBookmarkData& data, m_systemBookmarks) { - missingSystemBookmarks.insert(data.url); - } + for (int r = start; r <= end; r++) { + // insert the moved item in the new position + const int targetRow = row + (start - r) - (r < row ? blockSize : 0); + const QModelIndex targetIndex = m_sourceModel->index(targetRow, 0, destination); - // The bookmarks might have a mixed order of places, devices and search-groups due - // to the compatibility with the KFilePlacesPanel. In Dolphin's places panel the - // items should always be collected in one group so the items are collected first - // in separate lists before inserting them. - QList<PlacesItem*> placesItems; - QList<PlacesItem*> recentlySavedItems; - QList<PlacesItem*> searchForItems; - QList<PlacesItem*> devicesItems; + addItemFromSourceModel(targetIndex); + } +} - while (!bookmark.isNull()) { - if (acceptBookmark(bookmark, devices)) { - PlacesItem* item = new PlacesItem(bookmark); - if (item->groupType() == PlacesItem::DevicesType) { - devices.remove(item->udi()); - devicesItems.append(item); - } else { - const QUrl url = bookmark.url(); - if (missingSystemBookmarks.contains(url)) { - missingSystemBookmarks.remove(url); +void PlacesItemModel::onSourceModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) +{ + Q_UNUSED(roles); - // Try to retranslate the text of system bookmarks to have translated - // items when changing the language. In case if the user has applied a custom - // text, the retranslation will fail and the users custom text is still used. - // It is important to use "KFile System Bookmarks" as context (see - // createSystemBookmarks()). - item->setText(i18nc("KFile System Bookmarks", bookmark.text().toUtf8().constData())); - item->setSystemItem(true); - } + for (int r = topLeft.row(); r <= bottomRight.row(); r++) { + const QModelIndex sourceIndex = m_sourceModel->index(r, 0); + const KBookmark bookmark = m_sourceModel->bookmarkForIndex(sourceIndex); + PlacesItem *placeItem = itemFromBookmark(bookmark); - switch (item->groupType()) { - case PlacesItem::PlacesType: placesItems.append(item); break; - case PlacesItem::RecentlySavedType: recentlySavedItems.append(item); break; - case PlacesItem::SearchForType: searchForItems.append(item); break; - case PlacesItem::DevicesType: - default: Q_ASSERT(false); break; - } - } + if (placeItem && (!m_hiddenItemsShown && m_sourceModel->isHidden(sourceIndex))) { + //hide item if it became invisible + removeItem(index(placeItem)); + return; } - bookmark = root.next(bookmark); - } - - if (!missingSystemBookmarks.isEmpty()) { - // The current bookmarks don't contain all system-bookmarks. Add the missing - // bookmarks. - foreach (const SystemBookmarkData& data, m_systemBookmarks) { - if (missingSystemBookmarks.contains(data.url)) { - PlacesItem* item = createSystemPlacesItem(data); - switch (item->groupType()) { - case PlacesItem::PlacesType: placesItems.append(item); break; - case PlacesItem::RecentlySavedType: recentlySavedItems.append(item); break; - case PlacesItem::SearchForType: searchForItems.append(item); break; - case PlacesItem::DevicesType: - default: Q_ASSERT(false); break; - } - } + if (!placeItem && (m_hiddenItemsShown || !m_sourceModel->isHidden(sourceIndex))) { + //show item if it became visible + addItemFromSourceModel(sourceIndex); + return; } - } - // Create items for devices that have not been stored as bookmark yet - devicesItems.reserve(devicesItems.count() + devices.count()); - foreach (const QString& udi, devices) { - const KBookmark bookmark = PlacesItem::createDeviceBookmark(m_bookmarkManager, udi); - PlacesItem *item = new PlacesItem(bookmark); - devicesItems.append(item); - connect(item->signalHandler(), &PlacesItemSignalHandler::tearDownExternallyRequested, - this, &PlacesItemModel::storageTearDownExternallyRequested); - } - - QList<PlacesItem*> items; - items.append(placesItems); - items.append(recentlySavedItems); - items.append(searchForItems); - items.append(devicesItems); - - foreach (PlacesItem* item, items) { - if (!m_hiddenItemsShown && item->isHidden()) { - m_bookmarkedItems.append(item); - } else { - appendItem(item); + if (placeItem && !m_sourceModel->isDevice(sourceIndex)) { + placeItem->setText(bookmark.text()); + placeItem->setIcon(sourceIndex.data(KFilePlacesModel::IconNameRole).toString()); + placeItem->setUrl(m_sourceModel->url(sourceIndex)); + placeItem->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), + bookmark.metaDataItem(QStringLiteral("OnlyInApp"))); + // must update the bookmark object + placeItem->setBookmark(bookmark); } } - -#ifdef PLACESITEMMODEL_DEBUG - qCDebug(DolphinDebug) << "Loaded bookmarks"; - showModelState(); -#endif } -bool PlacesItemModel::acceptBookmark(const KBookmark& bookmark, - const QSet<QString>& availableDevices) const +void PlacesItemModel::onSourceModelGroupHiddenChanged(KFilePlacesModel::GroupType group, bool hidden) { - const QString udi = bookmark.metaDataItem(QStringLiteral("UDI")); - const QUrl url = bookmark.url(); - const QString appName = bookmark.metaDataItem(QStringLiteral("OnlyInApp")); - const bool deviceAvailable = availableDevices.contains(udi); - - if (balooURLs.contains(url) && appName.isEmpty()) { - // Does not accept baloo URLS with empty appName, this came from new KIO model and will cause duplications - qCWarning(DolphinDebug) << "Ignore KIO url:" << url; - return false; + for(const QModelIndex &sourceIndex : m_sourceModel->groupIndexes(group)) { + PlacesItem *item = placesItem(mapFromSource(sourceIndex)); + if (item) { + item->setGroupHidden(hidden); + } } - - const bool allowedHere = (appName.isEmpty() - || appName == KAboutData::applicationData().componentName() - || appName == KAboutData::applicationData().componentName() + AppNamePrefix) - && (m_fileIndexingEnabled || (url.scheme() != QLatin1String("timeline") && - url.scheme() != QLatin1String("search"))); - - return (udi.isEmpty() && allowedHere) || deviceAvailable; } -PlacesItem* PlacesItemModel::createSystemPlacesItem(const SystemBookmarkData& data) +void PlacesItemModel::cleanupBookmarks() { - KBookmark bookmark = PlacesItem::createBookmark(m_bookmarkManager, - data.text, - data.url, - data.icon); + // KIO model now provides support for baloo urls, and because of that we + // need to remove old URLs that were visible only in Dolphin to avoid duplication + int row = 0; + do { + const QModelIndex sourceIndex = m_sourceModel->index(row, 0); + const KBookmark bookmark = m_sourceModel->bookmarkForIndex(sourceIndex); + const QUrl url = bookmark.url(); + const QString appName = bookmark.metaDataItem(QStringLiteral("OnlyInApp")); - const QString protocol = data.url.scheme(); - if (protocol == QLatin1String("timeline") || protocol == QLatin1String("search")) { - // As long as the KFilePlacesView from kdelibs is available, the system-bookmarks - // for "Recently Saved" and "Search For" should be a setting available only - // in the Places Panel (see description of AppNamePrefix for more details). - const QString appName = KAboutData::applicationData().componentName() + AppNamePrefix; - bookmark.setMetaDataItem(QStringLiteral("OnlyInApp"), appName); - } - - PlacesItem* item = new PlacesItem(bookmark); - item->setSystemItem(true); - - // Create default view-properties for all "Search For" and "Recently Saved" bookmarks - // in case if the user has not already created custom view-properties for a corresponding - // query yet. - const bool createDefaultViewProperties = (item->groupType() == PlacesItem::SearchForType || - item->groupType() == PlacesItem::RecentlySavedType) && - !GeneralSettings::self()->globalViewProps(); - if (createDefaultViewProperties) { - ViewProperties props(convertedUrl(data.url)); - if (!props.exist()) { - const QString path = data.url.path(); - if (path == QLatin1String("/documents")) { - props.setViewMode(DolphinView::DetailsView); - props.setPreviewsShown(false); - props.setVisibleRoles({"text", "path"}); - } else if (path == QLatin1String("/images")) { - props.setViewMode(DolphinView::IconsView); - props.setPreviewsShown(true); - props.setVisibleRoles({"text", "imageSize"}); - } else if (path == QLatin1String("/audio")) { - props.setViewMode(DolphinView::DetailsView); - props.setPreviewsShown(false); - props.setVisibleRoles({"text", "artist", "album"}); - } else if (path == QLatin1String("/videos")) { - props.setViewMode(DolphinView::IconsView); - props.setPreviewsShown(true); - props.setVisibleRoles({"text"}); - } else if (data.url.scheme() == QLatin1String("timeline")) { - props.setViewMode(DolphinView::DetailsView); - props.setVisibleRoles({"text", "modificationtime"}); - } + if ((appName == KAboutData::applicationData().componentName() || + appName == KAboutData::applicationData().componentName() + AppNameSuffix) && balooURLs.contains(url)) { + qCDebug(DolphinDebug) << "Removing old baloo url:" << url; + m_sourceModel->removePlace(sourceIndex); + } else { + row++; } - } - - return item; + } while (row < m_sourceModel->rowCount()); } -void PlacesItemModel::createSystemBookmarks() +void PlacesItemModel::loadBookmarks() { - Q_ASSERT(m_systemBookmarks.isEmpty()); - Q_ASSERT(m_systemBookmarksIndexes.isEmpty()); - - // Note: The context of the I18N_NOOP2 must be "KFile System Bookmarks". The real - // i18nc call is done after reading the bookmark. The reason why the i18nc call is not - // done here is because otherwise switching the language would not result in retranslating the - // bookmarks. - m_systemBookmarks.append(SystemBookmarkData(QUrl::fromLocalFile(QDir::homePath()), - QStringLiteral("user-home"), - I18N_NOOP2("KFile System Bookmarks", "Home"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("remote:/")), - QStringLiteral("network-workgroup"), - I18N_NOOP2("KFile System Bookmarks", "Network"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl::fromLocalFile(QStringLiteral("/")), - QStringLiteral("folder-red"), - I18N_NOOP2("KFile System Bookmarks", "Root"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("trash:/")), - QStringLiteral("user-trash"), - I18N_NOOP2("KFile System Bookmarks", "Trash"))); - - if (m_fileIndexingEnabled) { - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("timeline:/today")), - QStringLiteral("go-jump-today"), - I18N_NOOP2("KFile System Bookmarks", "Today"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("timeline:/yesterday")), - QStringLiteral("view-calendar-day"), - I18N_NOOP2("KFile System Bookmarks", "Yesterday"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("timeline:/thismonth")), - QStringLiteral("view-calendar-month"), - I18N_NOOP2("KFile System Bookmarks", "This Month"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("timeline:/lastmonth")), - QStringLiteral("view-calendar-month"), - I18N_NOOP2("KFile System Bookmarks", "Last Month"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("search:/documents")), - QStringLiteral("folder-text"), - I18N_NOOP2("KFile System Bookmarks", "Documents"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("search:/images")), - QStringLiteral("folder-images"), - I18N_NOOP2("KFile System Bookmarks", "Images"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("search:/audio")), - QStringLiteral("folder-sound"), - I18N_NOOP2("KFile System Bookmarks", "Audio Files"))); - m_systemBookmarks.append(SystemBookmarkData(QUrl(QStringLiteral("search:/videos")), - QStringLiteral("folder-videos"), - I18N_NOOP2("KFile System Bookmarks", "Videos"))); + for(int r = 0, rMax = m_sourceModel->rowCount(); r < rMax; r++) { + const QModelIndex sourceIndex = m_sourceModel->index(r, 0); + if (m_hiddenItemsShown || !m_sourceModel->isHidden(sourceIndex)) { + addItemFromSourceModel(sourceIndex); + } } - for (int i = 0; i < m_systemBookmarks.count(); ++i) { - m_systemBookmarksIndexes.insert(m_systemBookmarks[i].url, i); - } +#ifdef PLACESITEMMODEL_DEBUG + qCDebug(DolphinDebug) << "Loaded bookmarks"; + showModelState(); +#endif } void PlacesItemModel::clear() { - m_bookmarkedItems.clear(); KStandardItemModel::clear(); } @@ -981,50 +670,16 @@ void PlacesItemModel::proceedWithTearDown() m_deviceToTearDown->teardown(); } -void PlacesItemModel::initializeAvailableDevices() +void PlacesItemModel::deleteItem(int index) { - QString predicate(QStringLiteral("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]" - " OR " - "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]" - " OR " - "OpticalDisc.availableContent & 'Audio' ]" - " OR " - "StorageAccess.ignored == false ]")); - - - if (KProtocolInfo::isKnownProtocol(QStringLiteral("mtp"))) { - predicate.prepend("["); - predicate.append(" OR PortableMediaPlayer.supportedProtocols == 'mtp']"); - } - - m_predicate = Solid::Predicate::fromString(predicate); - Q_ASSERT(m_predicate.isValid()); - - Solid::DeviceNotifier* notifier = Solid::DeviceNotifier::instance(); - connect(notifier, &Solid::DeviceNotifier::deviceAdded, this, &PlacesItemModel::slotDeviceAdded); - connect(notifier, &Solid::DeviceNotifier::deviceRemoved, this, &PlacesItemModel::slotDeviceRemoved); - - const QList<Solid::Device>& deviceList = Solid::Device::listFromQuery(m_predicate); - foreach (const Solid::Device& device, deviceList) { - m_availableDevices << device.udi(); - } + QModelIndex sourceIndex = mapToSource(index); + Q_ASSERT(sourceIndex.isValid()); + m_sourceModel->removePlace(sourceIndex); } -int PlacesItemModel::bookmarkIndex(int index) const +void PlacesItemModel::refresh() { - int bookmarkIndex = 0; - int modelIndex = 0; - while (bookmarkIndex < m_bookmarkedItems.count()) { - if (!m_bookmarkedItems[bookmarkIndex]) { - if (modelIndex == index) { - break; - } - ++modelIndex; - } - ++bookmarkIndex; - } - - return bookmarkIndex >= m_bookmarkedItems.count() ? -1 : bookmarkIndex; + m_sourceModel->refresh(); } void PlacesItemModel::hideItem(int index) @@ -1035,36 +690,6 @@ void PlacesItemModel::hideItem(int index) } shownItem->setHidden(true); - if (m_hiddenItemsShown) { - // Removing items from the model is not allowed if all hidden - // items should be shown. - return; - } - - const int newIndex = bookmarkIndex(index); - if (newIndex >= 0) { - const KBookmark hiddenBookmark = shownItem->bookmark(); - PlacesItem* hiddenItem = new PlacesItem(hiddenBookmark); - - const PlacesItem* previousItem = placesItem(index - 1); - KBookmark previousBookmark; - if (previousItem) { - previousBookmark = previousItem->bookmark(); - } - - const bool updateBookmark = (m_bookmarkManager->root().indexOf(hiddenBookmark) >= 0); - removeItem(index); - - if (updateBookmark) { - // removeItem() also removed the bookmark from m_bookmarkManager in - // PlacesItemModel::onItemRemoved(). However for hidden items the - // bookmark should still be remembered, so readd it again: - m_bookmarkManager->root().addBookmark(hiddenBookmark); - m_bookmarkManager->root().moveBookmark(hiddenBookmark, previousBookmark); - } - - m_bookmarkedItems.insert(newIndex, hiddenItem); - } } QString PlacesItemModel::internalMimeType() const @@ -1078,7 +703,7 @@ int PlacesItemModel::groupedDropIndex(int index, const PlacesItem* item) const Q_ASSERT(item); int dropIndex = index; - const PlacesItem::GroupType type = item->groupType(); + const QString group = item->group(); const int itemCount = count(); if (index < 0) { @@ -1088,7 +713,7 @@ int PlacesItemModel::groupedDropIndex(int index, const PlacesItem* item) const // Search nearest previous item with the same group int previousIndex = -1; for (int i = dropIndex - 1; i >= 0; --i) { - if (placesItem(i)->groupType() == type) { + if (placesItem(i)->group() == group) { previousIndex = i; break; } @@ -1097,7 +722,7 @@ int PlacesItemModel::groupedDropIndex(int index, const PlacesItem* item) const // Search nearest next item with the same group int nextIndex = -1; for (int i = dropIndex; i < count(); ++i) { - if (placesItem(i)->groupType() == type) { + if (placesItem(i)->group() == group) { nextIndex = i; break; } @@ -1128,52 +753,13 @@ bool PlacesItemModel::equalBookmarkIdentifiers(const KBookmark& b1, const KBookm } } -QUrl PlacesItemModel::createTimelineUrl(const QUrl& url) +int PlacesItemModel::mapFromSource(const QModelIndex &index) const { - // TODO: Clarify with the Baloo-team whether it makes sense - // provide default-timeline-URLs like 'yesterday', 'this month' - // and 'last month'. - QUrl timelineUrl; - - const QString path = url.toDisplayString(QUrl::PreferLocalFile); - if (path.endsWith(QLatin1String("yesterday"))) { - const QDate date = QDate::currentDate().addDays(-1); - const int year = date.year(); - const int month = date.month(); - const int day = date.day(); - timelineUrl = QUrl("timeline:/" + timelineDateString(year, month) + - '/' + timelineDateString(year, month, day)); - } else if (path.endsWith(QLatin1String("thismonth"))) { - const QDate date = QDate::currentDate(); - timelineUrl = QUrl("timeline:/" + timelineDateString(date.year(), date.month())); - } else if (path.endsWith(QLatin1String("lastmonth"))) { - const QDate date = QDate::currentDate().addMonths(-1); - timelineUrl = QUrl("timeline:/" + timelineDateString(date.year(), date.month())); - } else { - Q_ASSERT(path.endsWith(QLatin1String("today"))); - timelineUrl = url; + if (!index.isValid()) { + return -1; } - return timelineUrl; -} - -QString PlacesItemModel::timelineDateString(int year, int month, int day) -{ - QString date = QString::number(year) + '-'; - if (month < 10) { - date += '0'; - } - date += QString::number(month); - - if (day >= 1) { - date += '-'; - if (day < 10) { - date += '0'; - } - date += QString::number(day); - } - - return date; + return m_indexMap.indexOf(index); } bool PlacesItemModel::isDir(int index) const @@ -1182,39 +768,38 @@ bool PlacesItemModel::isDir(int index) const return true; } -QUrl PlacesItemModel::createSearchUrl(const QUrl& url) +KFilePlacesModel::GroupType PlacesItemModel::groupType(int row) const { - QUrl searchUrl; + return m_sourceModel->groupType(mapToSource(row)); +} -#ifdef HAVE_BALOO - const QString path = url.toDisplayString(QUrl::PreferLocalFile); - if (path.endsWith(QLatin1String("documents"))) { - searchUrl = searchUrlForType(QStringLiteral("Document")); - } else if (path.endsWith(QLatin1String("images"))) { - searchUrl = searchUrlForType(QStringLiteral("Image")); - } else if (path.endsWith(QLatin1String("audio"))) { - searchUrl = searchUrlForType(QStringLiteral("Audio")); - } else if (path.endsWith(QLatin1String("videos"))) { - searchUrl = searchUrlForType(QStringLiteral("Video")); - } else { - Q_ASSERT(false); - } -#else - Q_UNUSED(url); -#endif +bool PlacesItemModel::isGroupHidden(KFilePlacesModel::GroupType type) const +{ + return m_sourceModel->isGroupHidden(type); +} - return searchUrl; +void PlacesItemModel::setGroupHidden(KFilePlacesModel::GroupType type, bool hidden) +{ + return m_sourceModel->setGroupHidden(type, hidden); } -#ifdef HAVE_BALOO -QUrl PlacesItemModel::searchUrlForType(const QString& type) +QModelIndex PlacesItemModel::mapToSource(int row) const { - Baloo::Query query; - query.addType(type); + return m_indexMap.value(row); +} - return query.toSearchUrl(); +PlacesItem *PlacesItemModel::itemFromBookmark(const KBookmark &bookmark) const +{ + const QString id = bookmarkId(bookmark); + for (int i = 0, iMax = count(); i < iMax; i++) { + PlacesItem *item = placesItem(i); + const KBookmark itemBookmark = item->bookmark(); + if (bookmarkId(itemBookmark) == id) { + return item; + } + } + return nullptr; } -#endif #ifdef PLACESITEMMODEL_DEBUG void PlacesItemModel::showModelState() diff --git a/src/panels/places/placesitemmodel.h b/src/panels/places/placesitemmodel.h index 7dd49bf5a..a1b23b220 100644 --- a/src/panels/places/placesitemmodel.h +++ b/src/panels/places/placesitemmodel.h @@ -20,9 +20,8 @@ #ifndef PLACESITEMMODEL_H #define PLACESITEMMODEL_H -#include <config-baloo.h> - #include <kitemviews/kstandarditemmodel.h> +#include <KFilePlacesModel> #include <QUrl> #include <QHash> @@ -35,7 +34,6 @@ class KBookmark; class KBookmarkManager; class PlacesItem; class QAction; -class QTimer; // #define PLACESITEMMODEL_DEBUG @@ -50,20 +48,27 @@ class PlacesItemModel: public KStandardItemModel Q_OBJECT public: - explicit PlacesItemModel(QObject* parent = 0); - virtual ~PlacesItemModel(); + explicit PlacesItemModel(QObject* parent = nullptr); + ~PlacesItemModel() override; /** - * @return A new instance of a places item with the given - * attributes. + * @brief Create a new place entry in the bookmark file + * and add it to the model */ - PlacesItem* createPlacesItem(const QString& text, - const QUrl& url, - const QString& iconName = QString()); + void createPlacesItem(const QString& text, + const QUrl& url, + const QString& iconName = QString(), + int after = -1); PlacesItem* placesItem(int index) const; /** + * @brief Mark an item as hiden + * @param index of the item to be hidden + */ + void hideItem(int index); + + /** * If set to true, all items that are marked as hidden * will be shown in the view. The items will * stay marked as hidden, which is visually indicated @@ -89,15 +94,6 @@ public: */ int closestItem(const QUrl& url) const; - /** - * Appends the item \a item as last element of the group - * the item belongs to. If no item with the same group is - * present, the item gets appended as last element of the - * model. PlacesItemModel takes the ownership - * of the item. - */ - void appendItemToGroup(PlacesItem* item); - QAction* ejectAction(int index) const; QAction* teardownAction(int index) const; @@ -107,9 +103,9 @@ public: bool storageSetupNeeded(int index) const; void requestStorageSetup(int index); - virtual QMimeData* createMimeData(const KItemSet& indexes) const Q_DECL_OVERRIDE; + QMimeData* createMimeData(const KItemSet& indexes) const override; - virtual bool supportsDropping(int index) const Q_DECL_OVERRIDE; + bool supportsDropping(int index) const override; void dropMimeDataBefore(int index, const QMimeData* mimeData); @@ -121,18 +117,32 @@ public: */ static QUrl convertedUrl(const QUrl& url); - virtual void clear() Q_DECL_OVERRIDE; + void clear() override; void proceedWithTearDown(); /** - * Saves the bookmarks and indicates to other applications that the - * state of the bookmarks has been changed. Is only called by the - * timeout of m_saveBookmarksTimer to prevent unnecessary savings. + * @brief Remove item from bookmark + * + * This function remove the index from bookmark file permanently + * + * @param index - the item to be removed */ - void saveBookmarks(); + void deleteItem(int index); + + /** + * Force a sync on the bookmarks and indicates to other applications that the + * state of the bookmarks has been changed. + */ + void refresh(); + + bool isDir(int index) const override; + + + KFilePlacesModel::GroupType groupType(int row) const; + bool isGroupHidden(KFilePlacesModel::GroupType type) const; + void setGroupHidden(KFilePlacesModel::GroupType type, bool hidden); - bool isDir(int index) const Q_DECL_OVERRIDE; signals: void errorMessage(const QString& message); void storageSetupDone(int index, bool success); @@ -140,26 +150,28 @@ signals: void storageTearDownExternallyRequested(const QString& mountPath); protected: - virtual void onItemInserted(int index) Q_DECL_OVERRIDE; - virtual void onItemRemoved(int index, KStandardItem* removedItem) Q_DECL_OVERRIDE; - virtual void onItemChanged(int index, const QSet<QByteArray>& changedRoles) Q_DECL_OVERRIDE; + void onItemInserted(int index) override; + void onItemRemoved(int index, KStandardItem* removedItem) override; + void onItemChanged(int index, const QSet<QByteArray>& changedRoles) override; private slots: - void slotDeviceAdded(const QString& udi); - void slotDeviceRemoved(const QString& udi); void slotStorageTearDownDone(Solid::ErrorType error, const QVariant& errorData); void slotStorageSetupDone(Solid::ErrorType error, const QVariant& errorData, const QString& udi); - void hideItem(); - /** - * Updates the bookmarks from the model corresponding to the changed - * bookmarks stored by the bookmark-manager. Is called whenever the bookmarks - * have been changed by another application. - */ - void updateBookmarks(); + // source model control + void onSourceModelRowsInserted(const QModelIndex &parent, int first, int last); + void onSourceModelRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); + void onSourceModelRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row); + void onSourceModelRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row); + void onSourceModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles); + void onSourceModelGroupHiddenChanged(KFilePlacesModel::GroupType group, bool hidden); private: - struct SystemBookmarkData; + /** + * Remove bookmarks created by the previous version of dolphin that are + * not valid anymore + */ + void cleanupBookmarks(); /** * Loads the bookmarks from the bookmark-manager and creates items for @@ -167,43 +179,6 @@ private: */ void loadBookmarks(); - /** - * @return True, if the bookmark can be accepted in the context of the - * current application (e.g. bookmarks from other applications - * will be ignored). - */ - bool acceptBookmark(const KBookmark& bookmark, - const QSet<QString>& availableDevices) const; - - /** - * Creates a PlacesItem for a system-bookmark: - * - PlacesItem::isSystemItem() will return true - * - Default view-properties will be created for "Search For" items - * The item is not inserted to the model yet. - */ - PlacesItem* createSystemPlacesItem(const SystemBookmarkData& data); - - /** - * Creates system bookmarks that are shown per default and can - * only be hidden but not removed. The result will be stored - * in m_systemBookmarks. - */ - void createSystemBookmarks(); - - void initializeAvailableDevices(); - - /** - * @param index Item index related to the model. - * @return Corresponding index related to m_bookmarkedItems. - */ - int bookmarkIndex(int index) const; - - /** - * Marks the item with the index \a index as hidden and - * removes it from the model so that it gets invisible. - */ - void hideItem(int index); - QString internalMimeType() const; /** @@ -220,77 +195,41 @@ private: static bool equalBookmarkIdentifiers(const KBookmark& b1, const KBookmark& b2); /** - * @return URL using the timeline-protocol for searching (see convertedUrl()). - */ - static QUrl createTimelineUrl(const QUrl& url); - - /** - * Helper method for createTimelineUrl(). - * @return String that represents a date-path in the format that - * the timeline-protocol expects. - */ - static QString timelineDateString(int year, int month, int day = 0); - - /** - * @return URL that can be listed by KIO and results in searching - * for a given term. The URL \a url represents a places-internal - * URL like e.g. "search:/documents" (see convertedUrl()). - */ - static QUrl createSearchUrl(const QUrl& url); - -#ifdef HAVE_BALOO - /** - * Helper method for createSearchUrl() - * @return URL that can be listed by KIO and results in searching - * for the given type + * Appends the item \a item as last element of the group + * the item belongs to. If no item with the same group is + * present, the item gets appended as last element of the + * model. PlacesItemModel takes the ownership + * of the item. */ - static QUrl searchUrlForType(const QString& type); -#endif + void insertSortedItem(PlacesItem* item); #ifdef PLACESITEMMODEL_DEBUG void showModelState(); #endif -private: - bool m_fileIndexingEnabled; - bool m_hiddenItemsShown; + PlacesItem *itemFromBookmark(const KBookmark &bookmark) const; - QSet<QString> m_availableDevices; - Solid::Predicate m_predicate; - KBookmarkManager* m_bookmarkManager; + void addItemFromSourceModel(const QModelIndex &index); + void removeItemByIndex(const QModelIndex &mapToSource); - struct SystemBookmarkData - { - SystemBookmarkData(const QUrl& url, - const QString& icon, - const QString& text) : - url(url), icon(icon), text(text) {} - QUrl url; - QString icon; - QString text; - }; + QString bookmarkId(const KBookmark &bookmark) const; + void initializeDefaultViewProperties() const; - QList<SystemBookmarkData> m_systemBookmarks; - QHash<QUrl, int> m_systemBookmarksIndexes; + int mapFromSource(const QModelIndex &index) const; + QModelIndex mapToSource(int row) const; - // Contains hidden and unhidden items that are stored as - // bookmark (the model itself only contains items that - // are shown in the view). If an entry is 0, then the - // places-item is part of the model. If an entry is not - // 0, the item is hidden and not part of the model. - QList<PlacesItem*> m_bookmarkedItems; + static void updateItem(PlacesItem *item, const QModelIndex &index); - // Index of the hidden item that should be removed in - // removeHiddenItem(). The removing must be done - // asynchronously as in the scope of onItemChanged() - // removing an item is not allowed. - int m_hiddenItemToRemove; +private: + bool m_hiddenItemsShown; Solid::StorageAccess *m_deviceToTearDown; - QTimer* m_updateBookmarksTimer; - QHash<QObject*, int> m_storageSetupInProgress; + + QScopedPointer<KFilePlacesModel> m_sourceModel; + + QVector<QPersistentModelIndex> m_indexMap; }; #endif diff --git a/src/panels/places/placesitemsignalhandler.h b/src/panels/places/placesitemsignalhandler.h index 6110f717d..49c8e43c9 100644 --- a/src/panels/places/placesitemsignalhandler.h +++ b/src/panels/places/placesitemsignalhandler.h @@ -48,7 +48,7 @@ class PlacesItemSignalHandler: public QObject public: explicit PlacesItemSignalHandler(PlacesItem* item, QObject* parent = nullptr); - virtual ~PlacesItemSignalHandler(); + ~PlacesItemSignalHandler() override; public slots: /** diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index 0b76f18d3..f7ca7d010 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -34,6 +34,7 @@ #include <KIO/DropJob> #include <KIO/EmptyTrashJob> #include <KIO/JobUiDelegate> +#include <KFilePlacesModel> #include <KJobWidgets> #include <KLocalizedString> #include <KIconLoader> @@ -170,10 +171,10 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) QMenu menu(this); - QAction* emptyTrashAction = 0; - QAction* editAction = 0; - QAction* teardownAction = 0; - QAction* ejectAction = 0; + QAction* emptyTrashAction = nullptr; + QAction* editAction = nullptr; + QAction* teardownAction = nullptr; + QAction* ejectAction = nullptr; const QString label = item->text(); @@ -213,7 +214,7 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) editAction = menu.addAction(QIcon::fromTheme("document-properties"), i18nc("@item:inmenu", "Edit...")); } - QAction* removeAction = 0; + QAction* removeAction = nullptr; if (!isDevice && !item->isSystemItem()) { removeAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18nc("@item:inmenu", "Remove")); } @@ -222,6 +223,8 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) hideAction->setCheckable(true); hideAction->setChecked(item->isHidden()); + buildGroupContextMenu(&menu, index); + QAction* action = menu.exec(pos.toPoint()); if (action) { if (action == emptyTrashAction) { @@ -239,13 +242,11 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) if (action == editAction) { editEntry(index); } else if (action == removeAction) { - m_model->removeItem(index); - m_model->saveBookmarks(); + m_model->deleteItem(index); } else if (action == hideAction) { item->setHidden(hideAction->isChecked()); - m_model->saveBookmarks(); } else if (action == openInNewWindowAction) { - Dolphin::openNewWindow({PlacesItemModel::convertedUrl(m_model->data(index).value("url").toUrl())}, this); + Dolphin::openNewWindow({KFilePlacesModel::convertedUrl(m_model->data(index).value("url").toUrl())}, this); } else if (action == openInNewTabAction) { // TriggerItem does set up the storage first and then it will // emit the slotItemMiddleClicked signal, because of Qt::MiddleButton. @@ -267,13 +268,15 @@ void PlacesPanel::slotViewContextMenuRequested(const QPointF& pos) QAction* addAction = menu.addAction(QIcon::fromTheme(QStringLiteral("document-new")), i18nc("@item:inmenu", "Add Entry...")); - QAction* showAllAction = 0; + QAction* showAllAction = nullptr; if (m_model->hiddenCount() > 0) { showAllAction = menu.addAction(i18nc("@item:inmenu", "Show All Entries")); showAllAction->setCheckable(true); showAllAction->setChecked(m_model->hiddenItemsShown()); } + buildGroupContextMenu(&menu, m_controller->indexCloseToMousePressedPosition()); + QMenu* iconSizeSubMenu = new QMenu(i18nc("@item:inmenu", "Icon Size"), &menu); struct IconSizeInfo @@ -327,6 +330,24 @@ void PlacesPanel::slotViewContextMenuRequested(const QPointF& pos) selectClosestItem(); } +QAction *PlacesPanel::buildGroupContextMenu(QMenu *menu, int index) +{ + if (index == -1) { + return nullptr; + } + + KFilePlacesModel::GroupType groupType = m_model->groupType(index); + QAction *hideGroupAction = menu->addAction(i18nc("@item:inmenu", "Hide Section '%1'", m_model->item(index)->group())); + hideGroupAction->setCheckable(true); + hideGroupAction->setChecked(m_model->isGroupHidden(groupType)); + + connect(hideGroupAction, &QAction::triggered, this, [this, groupType, hideGroupAction]{ + m_model->setGroupHidden(groupType, hideGroupAction->isChecked()); + }); + + return hideGroupAction; +} + void PlacesPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event) { if (index < 0) { @@ -334,8 +355,8 @@ void PlacesPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even } const PlacesItem* destItem = m_model->placesItem(index); - const PlacesItem::GroupType group = destItem->groupType(); - if (group == PlacesItem::SearchForType || group == PlacesItem::RecentlySavedType) { + + if (destItem->isSearchOrTimelineUrl()) { return; } @@ -388,15 +409,14 @@ void PlacesPanel::slotItemDropEventStorageSetupDone(int index, bool success) delete m_itemDropEvent; m_itemDropEventIndex = -1; - m_itemDropEventMimeData = 0; - m_itemDropEvent = 0; + m_itemDropEventMimeData = nullptr; + m_itemDropEvent = nullptr; } } void PlacesPanel::slotAboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event) { m_model->dropMimeDataBefore(index, event->mimeData()); - m_model->saveBookmarks(); } void PlacesPanel::slotUrlsDropped(const QUrl& dest, QDropEvent* event, QWidget* parent) @@ -413,7 +433,7 @@ void PlacesPanel::slotTrashUpdated(KJob* job) emit errorMessage(job->errorString()); } // as long as KIO doesn't do this, do it ourselves - KNotification::event(QStringLiteral("Trash: emptied"), QString(), QPixmap(), 0, KNotification::DefaultEvent); + KNotification::event(QStringLiteral("Trash: emptied"), QString(), QPixmap(), nullptr, KNotification::DefaultEvent); } void PlacesPanel::slotStorageSetupDone(int index, bool success) @@ -456,9 +476,7 @@ void PlacesPanel::addEntry() dialog->setAllowGlobal(true); dialog->setUrl(url); if (dialog->exec() == QDialog::Accepted) { - PlacesItem* item = m_model->createPlacesItem(dialog->text(), dialog->url(), dialog->icon()); - m_model->appendItemToGroup(item); - m_model->saveBookmarks(); + m_model->createPlacesItem(dialog->text(), dialog->url(), dialog->icon()); } delete dialog; @@ -480,7 +498,7 @@ void PlacesPanel::editEntry(int index) oldItem->setText(dialog->text()); oldItem->setUrl(dialog->url()); oldItem->setIcon(dialog->icon()); - m_model->saveBookmarks(); + m_model->refresh(); } } @@ -517,9 +535,9 @@ void PlacesPanel::triggerItem(int index, Qt::MouseButton button) const QUrl url = m_model->data(index).value("url").toUrl(); if (!url.isEmpty()) { if (button == Qt::MiddleButton) { - emit placeMiddleClicked(PlacesItemModel::convertedUrl(url)); + emit placeMiddleClicked(KFilePlacesModel::convertedUrl(url)); } else { - emit placeActivated(PlacesItemModel::convertedUrl(url)); + emit placeActivated(KFilePlacesModel::convertedUrl(url)); } } } diff --git a/src/panels/places/placespanel.h b/src/panels/places/placespanel.h index 4e525a037..444785888 100644 --- a/src/panels/places/placespanel.h +++ b/src/panels/places/placespanel.h @@ -31,6 +31,7 @@ class PlacesItemModel; class PlacesView; class QGraphicsSceneDragDropEvent; class KJob; +class QMenu; /** * @brief Combines bookmarks and mounted devices as list. */ @@ -40,7 +41,7 @@ class PlacesPanel : public Panel public: explicit PlacesPanel(QWidget* parent); - virtual ~PlacesPanel(); + ~PlacesPanel() override; void proceedWithTearDown(); signals: @@ -51,11 +52,11 @@ signals: void storageTearDownExternallyRequested(const QString& mountPath); protected: - virtual bool urlChanged() Q_DECL_OVERRIDE; - virtual void showEvent(QShowEvent* event) Q_DECL_OVERRIDE; + bool urlChanged() override; + void showEvent(QShowEvent* event) override; public slots: - virtual void readSettings() Q_DECL_OVERRIDE; + void readSettings() override; private slots: void slotItemActivated(int index); @@ -82,6 +83,8 @@ private: void triggerItem(int index, Qt::MouseButton button); + QAction* buildGroupContextMenu(QMenu* menu, int index); + private: KItemListController* m_controller; PlacesItemModel* m_model; |
