Changeset View
Changeset View
Standalone View
Standalone View
src/filewidgets/kfileplacesmodel.cpp
Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | |||||
45 | #include <QDebug> | 45 | #include <QDebug> | ||
46 | #include <kurlmimedata.h> | 46 | #include <kurlmimedata.h> | ||
47 | 47 | | |||
48 | #include <kbookmarkmanager.h> | 48 | #include <kbookmarkmanager.h> | ||
49 | #include <kbookmark.h> | 49 | #include <kbookmark.h> | ||
50 | 50 | | |||
51 | #include <kio/job.h> | 51 | #include <kio/job.h> | ||
52 | #include <kprotocolinfo.h> | 52 | #include <kprotocolinfo.h> | ||
53 | #include <KCoreDirLister> | ||||
53 | 54 | | |||
54 | #include <kconfig.h> | 55 | #include <kconfig.h> | ||
55 | #include <kconfiggroup.h> | 56 | #include <kconfiggroup.h> | ||
56 | 57 | | |||
57 | #include <solid/devicenotifier.h> | 58 | #include <solid/devicenotifier.h> | ||
58 | #include <solid/storageaccess.h> | 59 | #include <solid/storageaccess.h> | ||
59 | #include <solid/storagedrive.h> | 60 | #include <solid/storagedrive.h> | ||
60 | #include <solid/storagevolume.h> | 61 | #include <solid/storagevolume.h> | ||
Show All 14 Lines | 70 | { | |||
75 | case KFilePlacesModel::RecentlySavedType: | 76 | case KFilePlacesModel::RecentlySavedType: | ||
76 | return QStringLiteral("GroupState-RecentlySaved-IsHidden"); | 77 | return QStringLiteral("GroupState-RecentlySaved-IsHidden"); | ||
77 | case KFilePlacesModel::SearchForType: | 78 | case KFilePlacesModel::SearchForType: | ||
78 | return QStringLiteral("GroupState-SearchFor-IsHidden"); | 79 | return QStringLiteral("GroupState-SearchFor-IsHidden"); | ||
79 | case KFilePlacesModel::DevicesType: | 80 | case KFilePlacesModel::DevicesType: | ||
80 | return QStringLiteral("GroupState-Devices-IsHidden"); | 81 | return QStringLiteral("GroupState-Devices-IsHidden"); | ||
81 | case KFilePlacesModel::RemovableDevicesType: | 82 | case KFilePlacesModel::RemovableDevicesType: | ||
82 | return QStringLiteral("GroupState-RemovableDevices-IsHidden"); | 83 | return QStringLiteral("GroupState-RemovableDevices-IsHidden"); | ||
84 | case KFilePlacesModel::TagsType: | ||||
85 | return QStringLiteral("GroupState-Tags-IsHidden"); | ||||
83 | default: | 86 | default: | ||
84 | Q_UNREACHABLE(); | 87 | Q_UNREACHABLE(); | ||
85 | } | 88 | } | ||
86 | } | 89 | } | ||
87 | 90 | | |||
88 | static bool isFileIndexingEnabled() | 91 | static bool isFileIndexingEnabled() | ||
89 | { | 92 | { | ||
90 | KConfig config(QStringLiteral("baloofilerc")); | 93 | KConfig config(QStringLiteral("baloofilerc")); | ||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Line(s) | |||||
159 | } | 162 | } | ||
160 | 163 | | |||
161 | class Q_DECL_HIDDEN KFilePlacesModel::Private | 164 | class Q_DECL_HIDDEN KFilePlacesModel::Private | ||
162 | { | 165 | { | ||
163 | public: | 166 | public: | ||
164 | explicit Private(KFilePlacesModel *self) | 167 | explicit Private(KFilePlacesModel *self) | ||
165 | : q(self), | 168 | : q(self), | ||
166 | bookmarkManager(nullptr), | 169 | bookmarkManager(nullptr), | ||
167 | fileIndexingEnabled(isFileIndexingEnabled()) | 170 | fileIndexingEnabled(isFileIndexingEnabled()), | ||
171 | tags(), | ||||
172 | tagsLister(new KCoreDirLister()) | ||||
chehrlic: While I way playing around with asan, I got a report that tagsLister is leaking. I can't see a… | |||||
168 | { | 173 | { | ||
174 | if (KProtocolInfo::isKnownProtocol(QStringLiteral("tags"))) { | ||||
175 | connect(tagsLister, &KCoreDirLister::itemsAdded, q, [this](const QUrl&, const KFileItemList& items) { | ||||
176 | | ||||
177 | if(tags.isEmpty()) { | ||||
178 | QList<QUrl> existingBookmarks; | ||||
179 | | ||||
180 | KBookmarkGroup root = bookmarkManager->root(); | ||||
181 | KBookmark bookmark = root.first(); | ||||
182 | | ||||
183 | while (!bookmark.isNull()) { | ||||
184 | existingBookmarks.append(bookmark.url()); | ||||
185 | bookmark = root.next(bookmark); | ||||
186 | } | ||||
187 | | ||||
const. But in fact, does this even need to be a variable? It's only used once. ngraham: const. But in fact, does this even need to be a variable? It's only used once. | |||||
nicolasfella: Will fix on push | |||||
188 | if (!existingBookmarks.contains(QUrl(tagsUrlBase))) { | ||||
189 | KBookmark alltags = KFilePlacesItem::createSystemBookmark(bookmarkManager, QStringLiteral("All tags"), i18n("All tags"), QUrl(tagsUrlBase), QStringLiteral("tag")); | ||||
190 | } | ||||
191 | } | ||||
192 | | ||||
193 | for (const KFileItem &item: items) { | ||||
194 | const QString name = item.name(); | ||||
195 | | ||||
196 | if (!tags.contains(name)) { | ||||
197 | tags.append(name); | ||||
198 | } | ||||
199 | } | ||||
200 | _k_reloadBookmarks(); | ||||
201 | }); | ||||
202 | | ||||
203 | connect(tagsLister, &KCoreDirLister::itemsDeleted, q, [this](const KFileItemList& items) { | ||||
204 | for (const KFileItem &item: items) { | ||||
205 | tags.removeAll(item.name()); | ||||
206 | } | ||||
207 | _k_reloadBookmarks(); | ||||
208 | }); | ||||
209 | | ||||
210 | tagsLister->openUrl(QUrl(tagsUrlBase), KCoreDirLister::OpenUrlFlag::Reload); | ||||
211 | } | ||||
169 | } | 212 | } | ||
170 | 213 | | |||
171 | ~Private() | 214 | ~Private() | ||
172 | { | 215 | { | ||
173 | qDeleteAll(items); | 216 | qDeleteAll(items); | ||
174 | } | 217 | } | ||
175 | 218 | | |||
176 | KFilePlacesModel * const q; | 219 | KFilePlacesModel * const q; | ||
Show All 9 Lines | |||||
186 | const bool fileIndexingEnabled; | 229 | const bool fileIndexingEnabled; | ||
187 | 230 | | |||
188 | QString alternativeApplicationName; | 231 | QString alternativeApplicationName; | ||
189 | 232 | | |||
190 | void reloadAndSignal(); | 233 | void reloadAndSignal(); | ||
191 | QList<KFilePlacesItem *> loadBookmarkList(); | 234 | QList<KFilePlacesItem *> loadBookmarkList(); | ||
192 | int findNearestPosition(int source, int target); | 235 | int findNearestPosition(int source, int target); | ||
193 | 236 | | |||
237 | QVector<QString> tags; | ||||
238 | const QString tagsUrlBase = QStringLiteral("tags:/"); | ||||
239 | KCoreDirLister* tagsLister; | ||||
240 | | ||||
194 | void _k_initDeviceList(); | 241 | void _k_initDeviceList(); | ||
195 | void _k_deviceAdded(const QString &udi); | 242 | void _k_deviceAdded(const QString &udi); | ||
196 | void _k_deviceRemoved(const QString &udi); | 243 | void _k_deviceRemoved(const QString &udi); | ||
197 | void _k_itemChanged(const QString &udi); | 244 | void _k_itemChanged(const QString &udi); | ||
198 | void _k_reloadBookmarks(); | 245 | void _k_reloadBookmarks(); | ||
199 | void _k_storageSetupDone(Solid::ErrorType error, const QVariant &errorData); | 246 | void _k_storageSetupDone(Solid::ErrorType error, const QVariant &errorData); | ||
200 | void _k_storageTeardownDone(Solid::ErrorType error, const QVariant &errorData); | 247 | void _k_storageTeardownDone(Solid::ErrorType error, const QVariant &errorData); | ||
201 | 248 | | |||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Line(s) | 311 | #endif | |||
265 | KFilePlacesItem::createSystemBookmark(d->bookmarkManager, | 312 | KFilePlacesItem::createSystemBookmark(d->bookmarkManager, | ||
266 | QStringLiteral("Trash"), I18N_NOOP2("KFile System Bookmarks", "Trash"), | 313 | QStringLiteral("Trash"), I18N_NOOP2("KFile System Bookmarks", "Trash"), | ||
267 | QUrl(QStringLiteral("trash:/")), QStringLiteral("user-trash")); | 314 | QUrl(QStringLiteral("trash:/")), QStringLiteral("user-trash")); | ||
268 | 315 | | |||
269 | setDefaultMetadataItemForGroup(PlacesType); | 316 | setDefaultMetadataItemForGroup(PlacesType); | ||
270 | setDefaultMetadataItemForGroup(RemoteType); | 317 | setDefaultMetadataItemForGroup(RemoteType); | ||
271 | setDefaultMetadataItemForGroup(DevicesType); | 318 | setDefaultMetadataItemForGroup(DevicesType); | ||
272 | setDefaultMetadataItemForGroup(RemovableDevicesType); | 319 | setDefaultMetadataItemForGroup(RemovableDevicesType); | ||
320 | setDefaultMetadataItemForGroup(TagsType); | ||||
273 | 321 | | |||
274 | // Force bookmarks to be saved. If on open/save dialog and the bookmarks are not saved, QFile::exists | 322 | // Force bookmarks to be saved. If on open/save dialog and the bookmarks are not saved, QFile::exists | ||
275 | // will always return false, which opening/closing all the time the open/save dialog would case the | 323 | // will always return false, which opening/closing all the time the open/save dialog would case the | ||
276 | // bookmarks to be added once each time, having lots of times each bookmark. (ereslibre) | 324 | // bookmarks to be added once each time, having lots of times each bookmark. (ereslibre) | ||
277 | d->bookmarkManager->saveAs(file); | 325 | d->bookmarkManager->saveAs(file); | ||
278 | } | 326 | } | ||
279 | 327 | | |||
280 | // if baloo is enabled, add new urls even if the bookmark file is not empty | 328 | // if baloo is enabled, add new urls even if the bookmark file is not empty | ||
▲ Show 20 Lines • Show All 373 Lines • ▼ Show 20 Line(s) | |||||
654 | 702 | | |||
655 | QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList() | 703 | QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList() | ||
656 | { | 704 | { | ||
657 | QList<KFilePlacesItem *> items; | 705 | QList<KFilePlacesItem *> items; | ||
658 | 706 | | |||
659 | KBookmarkGroup root = bookmarkManager->root(); | 707 | KBookmarkGroup root = bookmarkManager->root(); | ||
660 | KBookmark bookmark = root.first(); | 708 | KBookmark bookmark = root.first(); | ||
661 | QVector<QString> devices = availableDevices; | 709 | QVector<QString> devices = availableDevices; | ||
710 | QVector<QString> tagsList = tags; | ||||
662 | 711 | | |||
663 | while (!bookmark.isNull()) { | 712 | while (!bookmark.isNull()) { | ||
664 | const QString udi = bookmark.metaDataItem(QStringLiteral("UDI")); | 713 | const QString udi = bookmark.metaDataItem(QStringLiteral("UDI")); | ||
665 | const QUrl url = bookmark.url(); | 714 | const QUrl url = bookmark.url(); | ||
715 | const QString tag = bookmark.metaDataItem(QStringLiteral("tag")); | ||||
666 | if (!udi.isEmpty() || url.isValid()) { | 716 | if (!udi.isEmpty() || url.isValid()) { | ||
667 | QString appName = bookmark.metaDataItem(QStringLiteral("OnlyInApp")); | 717 | QString appName = bookmark.metaDataItem(QStringLiteral("OnlyInApp")); | ||
718 | | ||||
719 | // If it's not a tag it's a device | ||||
720 | if (tag.isEmpty()) { | ||||
668 | auto it = std::find(devices.begin(), devices.end(), udi); | 721 | auto it = std::find(devices.begin(), devices.end(), udi); | ||
669 | bool deviceAvailable = (it != devices.end()); | 722 | bool deviceAvailable = (it != devices.end()); | ||
670 | if (deviceAvailable) { | 723 | if (deviceAvailable) { | ||
671 | devices.erase(it); | 724 | devices.erase(it); | ||
672 | } | 725 | } | ||
673 | 726 | | |||
674 | bool allowedHere = appName.isEmpty() || | 727 | bool allowedHere = appName.isEmpty() || | ||
675 | ((appName == QCoreApplication::instance()->applicationName()) || | 728 | ((appName == QCoreApplication::instance()->applicationName()) || | ||
676 | (appName == alternativeApplicationName)); | 729 | (appName == alternativeApplicationName)); | ||
677 | bool isSupportedUrl = isBalooUrl(url) ? fileIndexingEnabled : true; | 730 | bool isSupportedUrl = isBalooUrl(url) ? fileIndexingEnabled : true; | ||
678 | bool isSupportedScheme = supportedSchemes.isEmpty() || supportedSchemes.contains(url.scheme()); | 731 | bool isSupportedScheme = supportedSchemes.isEmpty() || supportedSchemes.contains(url.scheme()); | ||
679 | 732 | | |||
680 | if (isSupportedScheme && ((isSupportedUrl && udi.isEmpty() && allowedHere) || deviceAvailable)) { | 733 | if (isSupportedScheme && ((isSupportedUrl && udi.isEmpty() && allowedHere) || deviceAvailable)) { | ||
681 | 734 | | |||
682 | KFilePlacesItem *item; | 735 | KFilePlacesItem *item; | ||
683 | if (deviceAvailable) { | 736 | if (deviceAvailable) { | ||
684 | item = new KFilePlacesItem(bookmarkManager, bookmark.address(), udi); | 737 | item = new KFilePlacesItem(bookmarkManager, bookmark.address(), udi); | ||
685 | // TODO: Update bookmark internal element | 738 | // TODO: Update bookmark internal element | ||
686 | } else { | 739 | } else { | ||
687 | item = new KFilePlacesItem(bookmarkManager, bookmark.address()); | 740 | item = new KFilePlacesItem(bookmarkManager, bookmark.address()); | ||
688 | } | 741 | } | ||
689 | connect(item, SIGNAL(itemChanged(QString)), | 742 | connect(item, SIGNAL(itemChanged(QString)), | ||
690 | q, SLOT(_k_itemChanged(QString))); | 743 | q, SLOT(_k_itemChanged(QString))); | ||
744 | | ||||
691 | items << item; | 745 | items << item; | ||
692 | } | 746 | } | ||
747 | } else { | ||||
748 | auto it = std::find(tagsList.begin(), tagsList.end(), tag); | ||||
749 | if (it != tagsList.end()) { | ||||
750 | tagsList.removeAll(tag); | ||||
751 | KFilePlacesItem *item = new KFilePlacesItem(bookmarkManager, bookmark.address()); | ||||
752 | items << item; | ||||
753 | connect(item, SIGNAL(itemChanged(QString)), | ||||
754 | q, SLOT(_k_itemChanged(QString))); | ||||
755 | } | ||||
693 | } | 756 | } | ||
757 | } | ||||
758 | | ||||
694 | bookmark = root.next(bookmark); | 759 | bookmark = root.next(bookmark); | ||
695 | } | 760 | } | ||
696 | 761 | | |||
697 | // Add bookmarks for the remaining devices, they were previously unknown | 762 | // Add bookmarks for the remaining devices, they were previously unknown | ||
698 | foreach (const QString &udi, devices) { | 763 | foreach (const QString &udi, devices) { | ||
699 | bookmark = KFilePlacesItem::createDeviceBookmark(bookmarkManager, udi); | 764 | bookmark = KFilePlacesItem::createDeviceBookmark(bookmarkManager, udi); | ||
700 | if (!bookmark.isNull()) { | 765 | if (!bookmark.isNull()) { | ||
701 | KFilePlacesItem *item = new KFilePlacesItem(bookmarkManager, | 766 | KFilePlacesItem *item = new KFilePlacesItem(bookmarkManager, | ||
702 | bookmark.address(), udi); | 767 | bookmark.address(), udi); | ||
703 | connect(item, SIGNAL(itemChanged(QString)), | 768 | connect(item, SIGNAL(itemChanged(QString)), | ||
704 | q, SLOT(_k_itemChanged(QString))); | 769 | q, SLOT(_k_itemChanged(QString))); | ||
705 | // TODO: Update bookmark internal element | 770 | // TODO: Update bookmark internal element | ||
706 | items << item; | 771 | items << item; | ||
707 | } | 772 | } | ||
708 | } | 773 | } | ||
709 | 774 | | |||
775 | for (const QString& tag: tagsList) { | ||||
776 | bookmark = KFilePlacesItem::createTagBookmark(bookmarkManager, tag); | ||||
777 | if (!bookmark.isNull()) { | ||||
778 | KFilePlacesItem *item = new KFilePlacesItem(bookmarkManager, | ||||
779 | bookmark.address(), tag); | ||||
780 | connect(item, SIGNAL(itemChanged(QString)), | ||||
781 | q, SLOT(_k_itemChanged(QString))); | ||||
782 | items << item; | ||||
783 | } | ||||
784 | } | ||||
785 | | ||||
710 | // return a sorted list based on groups | 786 | // return a sorted list based on groups | ||
711 | std::stable_sort(items.begin(), items.end(), | 787 | std::stable_sort(items.begin(), items.end(), | ||
712 | [](KFilePlacesItem *itemA, KFilePlacesItem *itemB) { | 788 | [](KFilePlacesItem *itemA, KFilePlacesItem *itemB) { | ||
713 | return (itemA->groupType() < itemB->groupType()); | 789 | return (itemA->groupType() < itemB->groupType()); | ||
714 | }); | 790 | }); | ||
715 | 791 | | |||
716 | return items; | 792 | return items; | ||
717 | } | 793 | } | ||
▲ Show 20 Lines • Show All 565 Lines • Show Last 20 Lines |
While I way playing around with asan, I got a report that tagsLister is leaking. I can't see a deletion of this object anywhere, even in current code.