Warning, file /plasma/plasma-mobile/containments/homescreens/folio/desktopmodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // SPDX-FileCopyrightText: 2014 Antonis Tsiapaliokas <antonis.tsiapaliokas@kde.org>
0002 // SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
0003 // SPDX-License-Identifier: GPL-2.0-or-later
0004 
0005 // Self
0006 #include "desktopmodel.h"
0007 
0008 // Qt
0009 #include <QByteArray>
0010 #include <QDebug>
0011 #include <QModelIndex>
0012 
0013 // KDE
0014 #include <KService>
0015 #include <KSharedConfig>
0016 
0017 #include <PlasmaQuick/AppletQuickItem>
0018 
0019 const int MAX_FAVORITES = 5;
0020 
0021 DesktopModel::DesktopModel(QObject *parent, Plasma::Applet *applet)
0022     : ApplicationListModel(parent)
0023     , m_applet{applet}
0024 {
0025 }
0026 
0027 DesktopModel::~DesktopModel() = default;
0028 
0029 QString DesktopModel::storageToUniqueId(const QString &storageId) const
0030 {
0031     if (storageId.isEmpty()) {
0032         return storageId;
0033     }
0034 
0035     int id = 0;
0036     QString uniqueId = storageId + QStringLiteral("-") + QString::number(id);
0037 
0038     while (m_appOrder.contains(uniqueId)) {
0039         uniqueId = storageId + QStringLiteral("-") + QString::number(++id);
0040     }
0041 
0042     return uniqueId;
0043 }
0044 
0045 QString DesktopModel::uniqueToStorageId(const QString &uniqueId) const
0046 {
0047     if (uniqueId.isEmpty()) {
0048         return uniqueId;
0049     }
0050 
0051     return uniqueId.split(QLatin1Char('-')).first();
0052 }
0053 
0054 void DesktopModel::loadSettings()
0055 {
0056     if (!m_applet) {
0057         return;
0058     }
0059     m_favorites = m_applet->config().readEntry("Favorites", QStringList());
0060     const auto di = m_applet->config().readEntry("DesktopItems", QStringList());
0061     m_desktopItems = QSet<QString>(di.begin(), di.end());
0062     m_appOrder = m_applet->config().readEntry("AppOrder", QStringList());
0063 
0064     int i = 0;
0065     for (const QString &app : qAsConst(m_appOrder)) {
0066         m_appPositions[app] = i;
0067         ++i;
0068     }
0069 }
0070 
0071 void DesktopModel::load()
0072 {
0073     loadSettings();
0074 
0075     // load applications
0076     beginResetModel();
0077 
0078     m_applicationList.clear();
0079 
0080     QSet<QString> appsToRemove;
0081 
0082     for (const auto &uniqueId : m_appOrder) {
0083         const QString storageId = uniqueToStorageId(uniqueId);
0084         if (KService::Ptr service = KService::serviceByStorageId(storageId)) {
0085             ApplicationData data;
0086             data.name = service->name();
0087             data.icon = service->icon();
0088             data.storageId = service->storageId();
0089             data.uniqueId = uniqueId;
0090             data.entryPath = service->exec();
0091             data.startupNotify = service->property(QStringLiteral("StartupNotify")).toBool();
0092 
0093             if (m_favorites.contains(uniqueId)) {
0094                 data.location = Favorites;
0095             } else if (m_desktopItems.contains(uniqueId)) {
0096                 data.location = Desktop;
0097             }
0098 
0099             m_applicationList << data;
0100         } else {
0101             appsToRemove.insert(uniqueId);
0102         }
0103     }
0104 
0105     bool favChanged = false;
0106 
0107     for (const auto &uniqueId : appsToRemove) {
0108         m_appOrder.removeAll(uniqueId);
0109         if (m_favorites.contains(uniqueId)) {
0110             favChanged = true;
0111             m_favorites.removeAll(uniqueId);
0112         }
0113         m_desktopItems.remove(uniqueId);
0114     }
0115 
0116     endResetModel();
0117 
0118     Q_EMIT countChanged();
0119 
0120     if (m_applet) {
0121         m_applet->config().writeEntry("Favorites", m_favorites);
0122         m_applet->config().writeEntry("AppOrder", m_appOrder);
0123         m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
0124         Q_EMIT m_applet->configNeedsSaving();
0125     }
0126 
0127     if (favChanged) {
0128         Q_EMIT favoriteCountChanged();
0129     }
0130 }
0131 
0132 int DesktopModel::count()
0133 {
0134     return m_applicationList.count();
0135 }
0136 
0137 int DesktopModel::favoriteCount()
0138 {
0139     return m_favorites.count();
0140 }
0141 
0142 int DesktopModel::maxFavoriteCount()
0143 {
0144     return MAX_FAVORITES;
0145 }
0146 
0147 void DesktopModel::setLocation(int row, LauncherLocation location)
0148 {
0149     if (row < 0 || row >= m_applicationList.length()) {
0150         return;
0151     }
0152 
0153     ApplicationData data = m_applicationList.at(row);
0154     if (data.location == location) {
0155         return;
0156     }
0157 
0158     if (location == Favorites) {
0159         qWarning() << "favoriting" << row << data.name;
0160         // Deny favorites when full
0161         if (row >= maxFavoriteCount() || m_favorites.count() >= maxFavoriteCount() || m_favorites.contains(data.uniqueId)) {
0162             return;
0163         }
0164 
0165         m_favorites.insert(row, data.uniqueId);
0166 
0167         if (m_applet) {
0168             m_applet->config().writeEntry("Favorites", m_favorites);
0169         }
0170         Q_EMIT favoriteCountChanged();
0171 
0172         // Out of favorites
0173     } else if (data.location == Favorites) {
0174         m_favorites.removeAll(data.uniqueId);
0175         if (m_applet) {
0176             m_applet->config().writeEntry("Favorites", m_favorites);
0177         }
0178         Q_EMIT favoriteCountChanged();
0179     }
0180 
0181     // In Desktop
0182     if (location == Desktop) {
0183         m_desktopItems.insert(data.uniqueId);
0184         if (m_applet) {
0185             m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
0186         }
0187 
0188         // Out of Desktop
0189     } else if (data.location == Desktop) {
0190         m_desktopItems.remove(data.uniqueId);
0191         if (m_applet) {
0192             m_applet->config().writeEntry(QStringLiteral("DesktopItems"), m_desktopItems.values());
0193         }
0194     }
0195 
0196     data.location = location;
0197     if (m_applet) {
0198         Q_EMIT m_applet->configNeedsSaving();
0199     }
0200     Q_EMIT dataChanged(index(row, 0), index(row, 0));
0201 }
0202 
0203 void DesktopModel::moveItem(int row, int destination)
0204 {
0205     if (row < 0 || destination < 0 || row >= m_applicationList.length() || destination >= m_applicationList.length() || row == destination) {
0206         return;
0207     }
0208     if (destination > row) {
0209         ++destination;
0210     }
0211 
0212     beginMoveRows(QModelIndex(), row, row, QModelIndex(), destination);
0213     if (destination > row) {
0214         ApplicationData data = m_applicationList.at(row);
0215         m_applicationList.insert(destination, data);
0216         m_applicationList.takeAt(row);
0217 
0218     } else {
0219         ApplicationData data = m_applicationList.takeAt(row);
0220         m_applicationList.insert(destination, data);
0221     }
0222 
0223     m_appOrder.clear();
0224     m_appPositions.clear();
0225     int i = 0;
0226     for (const ApplicationData &app : qAsConst(m_applicationList)) {
0227         m_appOrder << app.uniqueId;
0228         m_appPositions[app.uniqueId] = i;
0229         ++i;
0230     }
0231 
0232     if (m_applet) {
0233         m_applet->config().writeEntry("AppOrder", m_appOrder);
0234     }
0235 
0236     endMoveRows();
0237 }
0238 
0239 void DesktopModel::addFavorite(const QString &storageId, int row, LauncherLocation location)
0240 {
0241     if (row < 0 || row > m_applicationList.count()) {
0242         return;
0243     }
0244 
0245     if (KService::Ptr service = KService::serviceByStorageId(storageId)) {
0246         const QString uniqueId = storageToUniqueId(service->storageId());
0247         ApplicationData data;
0248         data.name = service->name();
0249         data.icon = service->icon();
0250         data.storageId = service->storageId();
0251         data.uniqueId = uniqueId;
0252         data.entryPath = service->exec();
0253         data.startupNotify = service->property(QStringLiteral("StartupNotify")).toBool();
0254 
0255         bool favChanged = false;
0256         if (location == Favorites) {
0257             data.location = Favorites;
0258             m_favorites.insert(qMin(row, m_favorites.count()), uniqueId);
0259             favChanged = true;
0260         } else {
0261             data.location = location;
0262             m_desktopItems.insert(data.uniqueId);
0263         }
0264 
0265         beginInsertRows(QModelIndex(), row, row);
0266         m_applicationList.insert(row, data);
0267         m_appOrder.insert(row, uniqueId);
0268         endInsertRows();
0269         if (favChanged) {
0270             Q_EMIT favoriteCountChanged();
0271         }
0272 
0273         if (m_applet) {
0274             m_applet->config().writeEntry("Favorites", m_favorites);
0275             m_applet->config().writeEntry("AppOrder", m_appOrder);
0276             m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
0277             Q_EMIT m_applet->configNeedsSaving();
0278         }
0279     }
0280 }
0281 
0282 void DesktopModel::removeFavorite(int row)
0283 {
0284     if (row < 0 || row >= m_applicationList.count()) {
0285         return;
0286     }
0287 
0288     beginRemoveRows(QModelIndex(), row, row);
0289     const QString uniqueId = m_applicationList[row].uniqueId;
0290     m_appOrder.removeAll(uniqueId);
0291 
0292     const bool favChanged = m_favorites.contains(uniqueId);
0293     m_favorites.removeAll(uniqueId);
0294     m_desktopItems.remove(uniqueId);
0295     m_appPositions.remove(uniqueId);
0296     m_applicationList.removeAt(row);
0297     endRemoveRows();
0298 
0299     if (favChanged) {
0300         Q_EMIT favoriteCountChanged();
0301     }
0302 
0303     if (m_applet) {
0304         m_applet->config().writeEntry("Favorites", m_favorites);
0305         m_applet->config().writeEntry("AppOrder", m_appOrder);
0306         m_applet->config().writeEntry("DesktopItems", m_desktopItems.values());
0307         Q_EMIT m_applet->configNeedsSaving();
0308     }
0309 }