+void PlacesItemModel::onItemChanged(int index, const QSet<QByteArray>& changedRoles)
+{
+ 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);
+ }
+
+ if (changedRoles.contains("isHidden")) {
+ if (!m_hiddenItemsShown && changedItem->isHidden()) {
+ m_hiddenItemToRemove = index;
+ QTimer::singleShot(0, this, static_cast<void (PlacesItemModel::*)()>(&PlacesItemModel::hideItem));
+ }
+ }
+}
+
+void PlacesItemModel::slotDeviceAdded(const QString& udi)
+{
+ const Solid::Device device(udi);
+
+ if (!m_predicate.matches(device)) {
+ return;
+ }
+
+ 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);
+}
+
+void PlacesItemModel::slotDeviceRemoved(const QString& udi)
+{
+ 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; i < count(); ++i) {
+ if (placesItem(i)->udi() == udi) {
+ removeItem(i);
+ return;
+ }
+ }
+}
+
+void PlacesItemModel::slotStorageTearDownDone(Solid::ErrorType error, const QVariant& errorData)
+{
+ if (error && errorData.isValid()) {
+ emit errorMessage(errorData.toString());
+ }
+ m_deviceToTearDown->disconnect();
+ m_deviceToTearDown = nullptr;
+}
+
+void PlacesItemModel::slotStorageSetupDone(Solid::ErrorType error,
+ const QVariant& errorData,
+ const QString& udi)
+{
+ Q_UNUSED(udi);
+
+ const int index = m_storageSetupInProgress.take(sender());
+ const PlacesItem* item = placesItem(index);
+ if (!item) {
+ return;
+ }
+
+ if (error != Solid::NoError) {
+ if (errorData.isValid()) {
+ emit errorMessage(i18nc("@info", "An error occurred while accessing '%1', the system responded: %2",
+ item->text(),
+ errorData.toString()));
+ } else {
+ emit errorMessage(i18nc("@info", "An error occurred while accessing '%1'",
+ item->text()));
+ }
+ emit storageSetupDone(index, false);
+ } else {
+ emit storageSetupDone(index, true);
+ }
+}
+
+void PlacesItemModel::hideItem()
+{
+ hideItem(m_hiddenItemToRemove);
+ m_hiddenItemToRemove = -1;
+}
+
+void PlacesItemModel::updateBookmarks()
+{
+ // 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);
+ }
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+
+ if (itemIsPartOfModel) {
+ ++modelIndex;
+ }
+ }
+}
+
+void PlacesItemModel::saveBookmarks()
+{
+ m_bookmarkManager->emitChanged(m_bookmarkManager->root());
+}
+