diff --git a/src/panels/places/placesitem.h b/src/panels/places/placesitem.h --- a/src/panels/places/placesitem.h +++ b/src/panels/places/placesitem.h @@ -45,7 +45,8 @@ PlacesType, SearchForType, RecentlySavedType, - DevicesType + DevicesType, + TagsType }; explicit PlacesItem(const KBookmark& bookmark, PlacesItem* parent = 0); diff --git a/src/panels/places/placesitem.cpp b/src/panels/places/placesitem.cpp --- a/src/panels/places/placesitem.cpp +++ b/src/panels/places/placesitem.cpp @@ -145,6 +145,7 @@ switch (type) { case RecentlySavedType: setIcon(QStringLiteral("chronometer")); break; case SearchForType: setIcon(QStringLiteral("system-search")); break; + case TagsType: setIcon(QStringLiteral("tag")); break; case PlacesType: default: setIcon(QStringLiteral("folder")); } @@ -156,6 +157,7 @@ case RecentlySavedType: setGroup(i18nc("@item", "Recently Saved")); break; case SearchForType: setGroup(i18nc("@item", "Search For")); break; case DevicesType: setGroup(i18nc("@item", "Devices")); break; + case TagsType: setGroup(i18nc("@item", "Tags")); break; default: Q_ASSERT(false); break; } @@ -171,6 +173,7 @@ { if (udi().isEmpty()) { const QString protocol = url().scheme(); + if (protocol == QLatin1String("timeline")) { return RecentlySavedType; } @@ -183,6 +186,10 @@ return DevicesType; } + if (protocol == QLatin1String("tags")) { + return TagsType; + } + return PlacesType; } diff --git a/src/panels/places/placesitemmodel.h b/src/panels/places/placesitemmodel.h --- a/src/panels/places/placesitemmodel.h +++ b/src/panels/places/placesitemmodel.h @@ -30,6 +30,7 @@ #include #include #include +#include class KBookmark; class KBookmarkManager; @@ -145,6 +146,8 @@ void slotStorageTeardownDone(Solid::ErrorType error, const QVariant& errorData); void slotStorageSetupDone(Solid::ErrorType error, const QVariant& errorData, const QString& udi); void hideItem(); + void addTag(KIO::Job* job, const KIO::UDSEntryList& list); + void applyTags(); /** * Updates the bookmarks from the model corresponding to the changed @@ -284,6 +287,11 @@ QTimer* m_updateBookmarksTimer; QHash m_storageSetupInProgress; + + QList m_tags; + QString tagsUrlBase = QStringLiteral("tags:/"); + + void createTagBookmarks(); }; #endif diff --git a/src/panels/places/placesitemmodel.cpp b/src/panels/places/placesitemmodel.cpp --- a/src/panels/places/placesitemmodel.cpp +++ b/src/panels/places/placesitemmodel.cpp @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -78,7 +80,8 @@ m_bookmarkedItems(), m_hiddenItemToRemove(-1), m_updateBookmarksTimer(0), - m_storageSetupInProgress() + m_storageSetupInProgress(), + m_tags() { #ifdef HAVE_BALOO Baloo::IndexerConfig config; @@ -89,7 +92,13 @@ createSystemBookmarks(); initializeAvailableDevices(); - loadBookmarks(); + + // if tags are supported load them before loading the bookmarks + if (KProtocolInfo::isKnownProtocol(QStringLiteral("tags"))) { + createTagBookmarks(); + } else { + loadBookmarks(); + } const int syncBookmarksTimeout = 100; @@ -731,6 +740,7 @@ QList recentlySavedItems; QList searchForItems; QList devicesItems; + QList tagsItems; while (!bookmark.isNull()) { if (acceptBookmark(bookmark, devices)) { @@ -756,6 +766,7 @@ case PlacesItem::PlacesType: placesItems.append(item); break; case PlacesItem::RecentlySavedType: recentlySavedItems.append(item); break; case PlacesItem::SearchForType: searchForItems.append(item); break; + case PlacesItem::TagsType: tagsItems.append(item); break; case PlacesItem::DevicesType: default: Q_ASSERT(false); break; } @@ -775,6 +786,7 @@ case PlacesItem::PlacesType: placesItems.append(item); break; case PlacesItem::RecentlySavedType: recentlySavedItems.append(item); break; case PlacesItem::SearchForType: searchForItems.append(item); break; + case PlacesItem::TagsType: tagsItems.append(item); break; case PlacesItem::DevicesType: default: Q_ASSERT(false); break; } @@ -794,6 +806,7 @@ items.append(recentlySavedItems); items.append(searchForItems); items.append(devicesItems); + items.append(tagsItems); foreach (PlacesItem* item, items) { if (!m_hiddenItemsShown && item->isHidden()) { @@ -1167,6 +1180,49 @@ return query.toSearchUrl(); } + +void PlacesItemModel::createTagBookmarks() +{ + KIO::ListJob* job = KIO::listDir(QUrl(tagsUrlBase), KIO::HideProgressInfo, false); + connect(job, &KIO::ListJob::entries, this, &PlacesItemModel::addTag); + connect(job, &KJob::result, this, &PlacesItemModel::applyTags); + job->start(); +} + +void PlacesItemModel::applyTags() +{ + m_systemBookmarks.append(SystemBookmarkData(QUrl(tagsUrlBase), + QStringLiteral("tag"), + I18N_NOOP2("KFile System Bookmarks", "All tags"))); + + for (QString tag: m_tags) { + m_systemBookmarks.append(SystemBookmarkData(QUrl(tagsUrlBase+tag), + QStringLiteral("tag"), + tag)); + } + loadBookmarks(); +} + +void PlacesItemModel::addTag(KIO::Job* job, const KIO::UDSEntryList& entries) +{ + Q_UNUSED(job); + KIO::UDSEntryList::ConstIterator it = entries.begin(); + const KIO::UDSEntryList::ConstIterator end = entries.end(); + + int maxTags = 8; + int numTags = 0; + + for (; it != end; ++it) { + const KIO::UDSEntry& entry = *it; + QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME); + + if (!m_tags.contains(name) && numTags < maxTags) { + m_tags.append(name); + numTags++; + } + } +} + #endif #ifdef PLACESITEMMODEL_DEBUG diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -321,7 +321,7 @@ const PlacesItem* destItem = m_model->placesItem(index); const PlacesItem::GroupType group = destItem->groupType(); - if (group == PlacesItem::SearchForType || group == PlacesItem::RecentlySavedType) { + if (group == PlacesItem::SearchForType || group == PlacesItem::RecentlySavedType || group == PlacesItem::TagsType) { return; }