+ if (iconName.isEmpty()) {
+ return new QAction(text, 0);
+ }
+
+ return new QAction(QIcon::fromTheme(iconName), text, 0);
+}
+
+void PlacesItemModel::requestEject(int index)
+{
+ const PlacesItem* item = placesItem(index);
+ if (item) {
+ Solid::OpticalDrive* drive = item->device().parent().as<Solid::OpticalDrive>();
+ if (drive) {
+ connect(drive, &Solid::OpticalDrive::ejectDone,
+ this, &PlacesItemModel::slotStorageTeardownDone);
+ drive->eject();
+ } else {
+ const QString label = item->text();
+ const QString message = i18nc("@info", "The device '%1' is not a disk and cannot be ejected.", label);
+ emit errorMessage(message);
+ }
+ }
+}
+
+void PlacesItemModel::requestTeardown(int index)
+{
+ const PlacesItem* item = placesItem(index);
+ if (item) {
+ Solid::StorageAccess* access = item->device().as<Solid::StorageAccess>();
+ if (access) {
+ connect(access, &Solid::StorageAccess::teardownDone,
+ this, &PlacesItemModel::slotStorageTeardownDone);
+ access->teardown();
+ }
+ }
+}
+
+bool PlacesItemModel::storageSetupNeeded(int index) const
+{
+ const PlacesItem* item = placesItem(index);
+ return item ? item->storageSetupNeeded() : false;
+}
+
+void PlacesItemModel::requestStorageSetup(int index)
+{
+ const PlacesItem* item = placesItem(index);
+ if (!item) {
+ return;
+ }
+
+ Solid::Device device = item->device();
+ const bool setup = device.is<Solid::StorageAccess>()
+ && !m_storageSetupInProgress.contains(device.as<Solid::StorageAccess>())
+ && !device.as<Solid::StorageAccess>()->isAccessible();
+ if (setup) {
+ Solid::StorageAccess* access = device.as<Solid::StorageAccess>();
+
+ m_storageSetupInProgress[access] = index;
+
+ connect(access, &Solid::StorageAccess::setupDone,
+ this, &PlacesItemModel::slotStorageSetupDone);
+
+ access->setup();
+ }
+}
+
+QMimeData* PlacesItemModel::createMimeData(const KItemSet& indexes) const
+{
+ QList<QUrl> urls;
+ QByteArray itemData;
+
+ QDataStream stream(&itemData, QIODevice::WriteOnly);
+
+ for (int index : indexes) {
+ const QUrl itemUrl = placesItem(index)->url();
+ if (itemUrl.isValid()) {
+ urls << itemUrl;
+ }
+ stream << index;
+ }
+
+ QMimeData* mimeData = new QMimeData();
+ if (!urls.isEmpty()) {
+ mimeData->setUrls(urls);
+ }
+ mimeData->setData(internalMimeType(), itemData);
+
+ return mimeData;
+}
+
+bool PlacesItemModel::supportsDropping(int index) const
+{
+ return index >= 0 && index < count();
+}
+
+void PlacesItemModel::dropMimeDataBefore(int index, const QMimeData* mimeData)
+{
+ if (mimeData->hasFormat(internalMimeType())) {
+ // The item has been moved inside the view
+ QByteArray itemData = mimeData->data(internalMimeType());
+ 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);
+ } 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);
+ for (int i = urls.count() - 1; i >= 0; --i) {
+ const QUrl& url = urls[i];
+
+ QString text = url.fileName();
+ if (text.isEmpty()) {
+ text = url.host();
+ }
+
+ if ((url.isLocalFile() && !QFileInfo(url.toLocalFile()).isDir())
+ || url.scheme() == QLatin1String("trash")) {
+ // Only directories outside the trash are allowed
+ continue;
+ }
+
+ PlacesItem* newItem = createPlacesItem(text, url);
+ const int dropIndex = groupedDropIndex(index, newItem);
+ insertItem(dropIndex, newItem);
+ }
+ }
+}
+
+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;