]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/panels/places/placesitemmodel.cpp
Output of licensedigger + manual cleanup afterwards.
[dolphin.git] / src / panels / places / placesitemmodel.cpp
index 077c9044c24930e3c2b37224a2569dc089065175..de858389bee5393fe5cdd5ab0ef88935268fc464 100644 (file)
-/***************************************************************************
- *   Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   Based on KFilePlacesModel from kdelibs:                               *
- *   Copyright (C) 2007 Kevin Ottens <ervin@kde.org>                       *
- *   Copyright (C) 2007 David Faure <faure@kde.org>                        *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
+/*
+ * SPDX-FileCopyrightText: 2012 Peter Penz <peter.penz19@gmail.com>
+ *
+ * Based on KFilePlacesModel from kdelibs:
+ * SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
+ * SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
 
 #include "placesitemmodel.h"
-#include "placesitemsignalhandler.h"
 
 #include "dolphin_generalsettings.h"
-
-#include <KBookmark>
-#include <KBookmarkManager>
 #include "dolphindebug.h"
-#include <QIcon>
-#include <KProtocolInfo>
-#include <KLocalizedString>
-#include <QStandardPaths>
-#include <KAboutData>
+#include "dolphinplacesmodelsingleton.h"
 #include "placesitem.h"
-#include <QAction>
-#include <QDate>
-#include <QMimeData>
-#include <QTimer>
-#include <KUrlMimeData>
-#include <KFilePlacesModel>
+#include "placesitemsignalhandler.h"
+#include "views/dolphinview.h"
+#include "views/viewproperties.h"
 
-#include <Solid/Device>
+#include <KAboutData>
+#include <KLocalizedString>
+#include <KUrlMimeData>
 #include <Solid/DeviceNotifier>
-#include <Solid/OpticalDisc>
 #include <Solid/OpticalDrive>
-#include <Solid/StorageAccess>
-#include <Solid/StorageDrive>
-
-#include <views/dolphinview.h>
-#include <views/viewproperties.h>
+#include <KCoreAddons/KProcessList>
+#include <KCoreAddons/KListOpenFilesJob>
 
-namespace {
-    // A suffix to the application-name of the stored bookmarks is
-    // added, which is only read by PlacesItemModel.
-    const QString AppNameSuffix = QStringLiteral("-places-panel");
-    static QList<QUrl> balooURLs = {
-        QUrl(QStringLiteral("timeline:/today")),
-        QUrl(QStringLiteral("timeline:/yesterday")),
-        QUrl(QStringLiteral("timeline:/thismonth")),
-        QUrl(QStringLiteral("timeline:/lastmonth")),
-        QUrl(QStringLiteral("search:/documents")),
-        QUrl(QStringLiteral("search:/images")),
-        QUrl(QStringLiteral("search:/audio")),
-        QUrl(QStringLiteral("search:/videos"))
-    };
-}
+#include <QAction>
+#include <QIcon>
+#include <QMimeData>
+#include <QTimer>
 
 PlacesItemModel::PlacesItemModel(QObject* parent) :
     KStandardItemModel(parent),
     m_hiddenItemsShown(false),
     m_deviceToTearDown(nullptr),
     m_storageSetupInProgress(),
-    m_sourceModel(new KFilePlacesModel(KAboutData::applicationData().componentName() + AppNameSuffix, this))
+    m_sourceModel(DolphinPlacesModelSingleton::instance().placesModel())
 {
     cleanupBookmarks();
     loadBookmarks();
     initializeDefaultViewProperties();
 
-    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);
+    connect(m_sourceModel, &KFilePlacesModel::rowsInserted, this, &PlacesItemModel::onSourceModelRowsInserted);
+    connect(m_sourceModel, &KFilePlacesModel::rowsAboutToBeRemoved, this, &PlacesItemModel::onSourceModelRowsAboutToBeRemoved);
+    connect(m_sourceModel, &KFilePlacesModel::dataChanged, this, &PlacesItemModel::onSourceModelDataChanged);
+    connect(m_sourceModel, &KFilePlacesModel::rowsAboutToBeMoved, this, &PlacesItemModel::onSourceModelRowsAboutToBeMoved);
+    connect(m_sourceModel, &KFilePlacesModel::rowsMoved, this, &PlacesItemModel::onSourceModelRowsMoved);
+    connect(m_sourceModel, &KFilePlacesModel::groupHiddenChanged, this, &PlacesItemModel::onSourceModelGroupHiddenChanged);
 }
 
 PlacesItemModel::~PlacesItemModel()
 {
 }
 
-void PlacesItemModel::createPlacesItem(const QString& text,
-                                       const QUrl& url,
-                                       const QString& iconName,
-                                       int after)
+void PlacesItemModel::createPlacesItem(const QString &text, const QUrl &url, const QString &iconName, const QString &appName)
 {
-    m_sourceModel->addPlace(text, url, iconName, {}, mapToSource(after));
+    createPlacesItem(text, url, iconName, appName, -1);
+}
+
+void PlacesItemModel::createPlacesItem(const QString &text, const QUrl &url, const QString &iconName, const QString &appName, int after)
+{
+    m_sourceModel->addPlace(text, url, iconName, appName, mapToSource(after));
 }
 
 PlacesItem* PlacesItemModel::placesItem(int index) const
@@ -133,11 +98,6 @@ void PlacesItemModel::setHiddenItemsShown(bool show)
             }
         }
     }
-
-#ifdef PLACESITEMMODEL_DEBUG
-        qCDebug(DolphinDebug) << "Changed visibility of hidden items";
-        showModelState();
-#endif
 }
 
 bool PlacesItemModel::hiddenItemsShown() const
@@ -182,10 +142,6 @@ void PlacesItemModel::insertSortedItem(PlacesItem* 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)
@@ -193,10 +149,6 @@ 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)
@@ -377,7 +329,10 @@ void PlacesItemModel::dropMimeDataBefore(int index, const QMimeData* mimeData)
         int oldIndex;
         stream >> oldIndex;
 
-        m_sourceModel->movePlace(oldIndex, index);
+        QModelIndex sourceIndex = mapToSource(index);
+        QModelIndex oldSourceIndex = mapToSource(oldIndex);
+
+        m_sourceModel->movePlace(oldSourceIndex.row(), sourceIndex.row());
     } 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);
@@ -395,7 +350,7 @@ void PlacesItemModel::dropMimeDataBefore(int index, const QMimeData* mimeData)
                 continue;
             }
 
-            createPlacesItem(text, url, KIO::iconNameForUrl(url), qMax(0, index - 1));
+            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
@@ -410,10 +365,7 @@ void PlacesItemModel::addItemFromSourceModel(const QModelIndex &index)
 
     const KBookmark bookmark = m_sourceModel->bookmarkForIndex(index);
     Q_ASSERT(!bookmark.isNull());
-    PlacesItem *item = itemFromBookmark(bookmark);
-    if (!item) {
-        item = new PlacesItem(bookmark);
-    }
+    PlacesItem *item = new PlacesItem(bookmark);
     updateItem(item, index);
     insertSortedItem(item);
 
@@ -469,7 +421,7 @@ void PlacesItemModel::initializeDefaultViewProperties() const
                 } else if (path == QLatin1String("/images")) {
                     props.setViewMode(DolphinView::IconsView);
                     props.setPreviewsShown(true);
-                    props.setVisibleRoles({"text", "imageSize"});
+                    props.setVisibleRoles({"text", "height", "width"});
                 } else if (path == QLatin1String("/audio")) {
                     props.setViewMode(DolphinView::DetailsView);
                     props.setPreviewsShown(false);
@@ -498,9 +450,32 @@ void PlacesItemModel::updateItem(PlacesItem *item, const QModelIndex &index)
 void PlacesItemModel::slotStorageTearDownDone(Solid::ErrorType error, const QVariant& errorData)
 {
     if (error && errorData.isValid()) {
-        emit errorMessage(errorData.toString());
+        if (error == Solid::ErrorType::DeviceBusy) {
+            KListOpenFilesJob* listOpenFilesJob = new KListOpenFilesJob(m_deviceToTearDown->filePath());
+            connect(listOpenFilesJob, &KIO::Job::result, this, [this, listOpenFilesJob](KJob*) {
+                const KProcessList::KProcessInfoList blockingProcesses = listOpenFilesJob->processInfoList();
+                QString errorString;
+                if (blockingProcesses.isEmpty()) {
+                    errorString = i18n("One or more files on this device are open within an application.");
+                } else {
+                    QStringList blockingApps;
+                    for (const auto& process : blockingProcesses) {
+                        blockingApps << process.name();
+                    }
+                    blockingApps.removeDuplicates();
+                    errorString = xi18np("One or more files on this device are opened in application <application>\"%2\"</application>.",
+                            "One or more files on this device are opened in following applications: <application>%2</application>.",
+                            blockingApps.count(), blockingApps.join(i18nc("separator in list of apps blocking device unmount", ", ")));
+                }
+                emit errorMessage(errorString);
+            });
+            listOpenFilesJob->start();
+        } else {
+            emit errorMessage(errorData.toString());
+        }
     }
-    m_deviceToTearDown->disconnect();
+    disconnect(m_deviceToTearDown, &Solid::StorageAccess::teardownDone,
+               this, &PlacesItemModel::slotStorageTearDownDone);
     m_deviceToTearDown = nullptr;
 }
 
@@ -508,7 +483,7 @@ void PlacesItemModel::slotStorageSetupDone(Solid::ErrorType error,
                                            const QVariant& errorData,
                                            const QString& udi)
 {
-    Q_UNUSED(udi);
+    Q_UNUSED(udi)
 
     const int index = m_storageSetupInProgress.take(sender());
     const PlacesItem*  item = placesItem(index);
@@ -552,8 +527,8 @@ void PlacesItemModel::onSourceModelRowsAboutToBeRemoved(const QModelIndex &paren
 
 void PlacesItemModel::onSourceModelRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
 {
-    Q_UNUSED(destination);
-    Q_UNUSED(row);
+    Q_UNUSED(destination)
+    Q_UNUSED(row)
 
     for(int r = start; r <= end; r++) {
         const QModelIndex sourceIndex = m_sourceModel->index(r, 0, parent);
@@ -564,8 +539,8 @@ void PlacesItemModel::onSourceModelRowsAboutToBeMoved(const QModelIndex &parent,
 
 void PlacesItemModel::onSourceModelRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
 {
-    Q_UNUSED(destination);
-    Q_UNUSED(parent);
+    Q_UNUSED(destination)
+    Q_UNUSED(parent)
 
     const int blockSize = (end - start) + 1;
 
@@ -580,7 +555,7 @@ void PlacesItemModel::onSourceModelRowsMoved(const QModelIndex &parent, int star
 
 void PlacesItemModel::onSourceModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
 {
-    Q_UNUSED(roles);
+    Q_UNUSED(roles)
 
     for (int r = topLeft.row(); r <= bottomRight.row(); r++) {
         const QModelIndex sourceIndex = m_sourceModel->index(r, 0);
@@ -600,11 +575,6 @@ void PlacesItemModel::onSourceModelDataChanged(const QModelIndex &topLeft, const
         }
 
         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);
         }
@@ -613,7 +583,8 @@ void PlacesItemModel::onSourceModelDataChanged(const QModelIndex &topLeft, const
 
 void PlacesItemModel::onSourceModelGroupHiddenChanged(KFilePlacesModel::GroupType group, bool hidden)
 {
-    for(const QModelIndex &sourceIndex : m_sourceModel->groupIndexes(group)) {
+    const auto groupIndexes = m_sourceModel->groupIndexes(group);
+    for (const QModelIndex &sourceIndex : groupIndexes) {
         PlacesItem *item = placesItem(mapFromSource(sourceIndex));
         if (item) {
             item->setGroupHidden(hidden);
@@ -625,6 +596,18 @@ void PlacesItemModel::cleanupBookmarks()
 {
     // 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
+
+    static const QVector<QUrl> balooURLs = {
+        QUrl(QStringLiteral("timeline:/today")),
+        QUrl(QStringLiteral("timeline:/yesterday")),
+        QUrl(QStringLiteral("timeline:/thismonth")),
+        QUrl(QStringLiteral("timeline:/lastmonth")),
+        QUrl(QStringLiteral("search:/documents")),
+        QUrl(QStringLiteral("search:/images")),
+        QUrl(QStringLiteral("search:/audio")),
+        QUrl(QStringLiteral("search:/videos"))
+    };
+
     int row = 0;
     do {
         const QModelIndex sourceIndex = m_sourceModel->index(row, 0);
@@ -633,7 +616,7 @@ void PlacesItemModel::cleanupBookmarks()
         const QString appName = bookmark.metaDataItem(QStringLiteral("OnlyInApp"));
 
         if ((appName == KAboutData::applicationData().componentName() ||
-             appName == KAboutData::applicationData().componentName() + AppNameSuffix) && balooURLs.contains(url)) {
+             appName == KAboutData::applicationData().componentName() + DolphinPlacesModelSingleton::applicationNameSuffix()) && balooURLs.contains(url)) {
             qCDebug(DolphinDebug) << "Removing old baloo url:" << url;
             m_sourceModel->removePlace(sourceIndex);
         } else {
@@ -650,11 +633,6 @@ void PlacesItemModel::loadBookmarks()
             addItemFromSourceModel(sourceIndex);
         }
     }
-
-#ifdef PLACESITEMMODEL_DEBUG
-    qCDebug(DolphinDebug) << "Loaded bookmarks";
-    showModelState();
-#endif
 }
 
 void PlacesItemModel::clear() {
@@ -764,7 +742,7 @@ int PlacesItemModel::mapFromSource(const QModelIndex &index) const
 
 bool PlacesItemModel::isDir(int index) const
 {
-    Q_UNUSED(index);
+    Q_UNUSED(index)
     return true;
 }
 
@@ -801,44 +779,3 @@ PlacesItem *PlacesItemModel::itemFromBookmark(const KBookmark &bookmark) const
     return nullptr;
 }
 
-#ifdef PLACESITEMMODEL_DEBUG
-void PlacesItemModel::showModelState()
-{
-    qCDebug(DolphinDebug) << "=================================";
-    qCDebug(DolphinDebug) << "Model:";
-    qCDebug(DolphinDebug) << "hidden-index model-index   text";
-    int modelIndex = 0;
-    for (int i = 0; i < m_bookmarkedItems.count(); ++i) {
-        if (m_bookmarkedItems[i]) {
-            qCDebug(DolphinDebug) <<  i << "(Hidden)    " << "             " << m_bookmarkedItems[i]->dataValue("text").toString();
-        } else {
-            if (item(modelIndex)) {
-                qCDebug(DolphinDebug) <<  i << "          " << modelIndex << "           " << item(modelIndex)->dataValue("text").toString();
-            } else {
-                qCDebug(DolphinDebug) <<  i << "          " << modelIndex << "           " << "(not available yet)";
-            }
-            ++modelIndex;
-        }
-    }
-
-    qCDebug(DolphinDebug);
-    qCDebug(DolphinDebug) << "Bookmarks:";
-
-    int bookmarkIndex = 0;
-    KBookmarkGroup root = m_bookmarkManager->root();
-    KBookmark bookmark = root.first();
-    while (!bookmark.isNull()) {
-        const QString udi = bookmark.metaDataItem("UDI");
-        const QString text = udi.isEmpty() ? bookmark.text() : udi;
-        if (bookmark.metaDataItem("IsHidden") == QLatin1String("true")) {
-            qCDebug(DolphinDebug) << bookmarkIndex << "(Hidden)" << text;
-        } else {
-            qCDebug(DolphinDebug) << bookmarkIndex << "        " << text;
-        }
-
-        bookmark = root.next(bookmark);
-        ++bookmarkIndex;
-    }
-}
-#endif
-