File indexing completed on 2024-05-12 05:35:49

0001 /*
0002     SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "BlacklistedApplicationsModel.h"
0008 
0009 #include <QDebug>
0010 #include <QList>
0011 #include <QScopeGuard>
0012 #include <QSet>
0013 #include <QSqlDatabase>
0014 #include <QSqlError>
0015 #include <QSqlQuery>
0016 #include <QVariant>
0017 
0018 #include <KService>
0019 
0020 #include "kactivitymanagerd_plugins_settings.h"
0021 
0022 #include <utils/d_ptr_implementation.h>
0023 
0024 #include "definitions.h"
0025 
0026 class BlacklistedApplicationsModel::Private
0027 {
0028 public:
0029     struct ApplicationData {
0030         QString name;
0031         QString title;
0032         QString icon;
0033         bool blocked;
0034     };
0035 
0036     QList<ApplicationData> applications;
0037 
0038     KActivityManagerdPluginsSettings *pluginConfig;
0039     bool enabled;
0040 };
0041 
0042 BlacklistedApplicationsModel::BlacklistedApplicationsModel(QObject *parent)
0043     : QAbstractListModel(parent)
0044 {
0045     d->enabled = false;
0046     d->pluginConfig = new KActivityManagerdPluginsSettings;
0047 }
0048 
0049 BlacklistedApplicationsModel::~BlacklistedApplicationsModel()
0050 {
0051 }
0052 
0053 QHash<int, QByteArray> BlacklistedApplicationsModel::roleNames() const
0054 {
0055     return {{ApplicationIdRole, "name"}, {Qt::DecorationRole, "icon"}, {Qt::DisplayRole, "title"}, {BlockedApplicationRole, "blocked"}};
0056 }
0057 
0058 void BlacklistedApplicationsModel::load()
0059 {
0060     QSqlDatabase database;
0061 
0062     const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kactivitymanagerd/resources/database");
0063     database = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("plugins_sqlite_db_resources"));
0064     database.setDatabaseName(path);
0065     auto databaseRemove = qScopeGuard([&] {
0066         QSqlDatabase::removeDatabase(database.connectionName());
0067     });
0068 
0069     // Loading plugin configuration
0070     d->pluginConfig->load();
0071     const auto defaultBlockedValue = d->pluginConfig->defaultBlockedByDefaultValue();
0072     const auto &blockedAppList = d->pluginConfig->blockedApplications();
0073     auto blockedApplications = QSet<QString>(blockedAppList.cbegin(), blockedAppList.cend());
0074     const auto &allowedAppList = d->pluginConfig->allowedApplications();
0075     auto allowedApplications = QSet<QString>(allowedAppList.cbegin(), allowedAppList.cend());
0076 
0077     // Reading new applications from the database
0078 
0079     if (!database.open()) {
0080         // qDebug() << "Failed to open the database" << path << d->database.lastError();
0081         return;
0082     }
0083 
0084     auto query = database.exec(QStringLiteral("SELECT DISTINCT(initiatingAgent) FROM ResourceScoreCache ORDER BY initiatingAgent"));
0085 
0086     if (d->applications.length() > 0) {
0087         beginRemoveRows(QModelIndex(), 0, d->applications.length() - 1);
0088         d->applications.clear();
0089         endRemoveRows();
0090     }
0091 
0092     while (query.next()) {
0093         const auto name = query.value(0).toString();
0094 
0095         if (defaultBlockedValue) {
0096             if (!allowedApplications.contains(name)) {
0097                 blockedApplications << name;
0098             }
0099         } else {
0100             if (!blockedApplications.contains(name)) {
0101                 allowedApplications << name;
0102             }
0103         }
0104     }
0105 
0106     QStringList applications = (blockedApplications + allowedApplications).values();
0107 
0108     if (applications.length() > 0) {
0109         std::sort(applications.begin(), applications.end());
0110 
0111         beginInsertRows(QModelIndex(), 0, applications.length() - 1);
0112 
0113         for (const auto &name : std::as_const(applications)) {
0114             const auto service = KService::serviceByDesktopName(name);
0115             const auto blocked = blockedApplications.contains(name);
0116 
0117             if (service) {
0118                 d->applications << Private::ApplicationData{name, service->name(), service->icon(), blocked};
0119             } else {
0120                 d->applications << Private::ApplicationData{name, name, QString(), blocked};
0121             }
0122         }
0123 
0124         endInsertRows();
0125     }
0126 }
0127 
0128 void BlacklistedApplicationsModel::save()
0129 {
0130     d->pluginConfig->save();
0131     Q_EMIT changed(false);
0132 }
0133 
0134 void BlacklistedApplicationsModel::defaults()
0135 {
0136     for (int i = 0; i < rowCount(); i++) {
0137         d->applications[i].blocked = false;
0138     }
0139 
0140     Q_EMIT dataChanged(QAbstractListModel::index(0), QAbstractListModel::index(rowCount() - 1));
0141 
0142     Q_EMIT defaulted(true);
0143 }
0144 
0145 void BlacklistedApplicationsModel::toggleApplicationBlocked(int index)
0146 {
0147     if (index > rowCount()) {
0148         return;
0149     }
0150 
0151     d->applications[index].blocked = !d->applications[index].blocked;
0152     Q_EMIT dataChanged(QAbstractListModel::index(index), QAbstractListModel::index(index));
0153 
0154     QStringList blockedApplications;
0155     QStringList allowedApplications;
0156 
0157     for (int i = 0; i < rowCount(); i++) {
0158         const auto name = d->applications[i].name;
0159         if (d->applications[i].blocked) {
0160             blockedApplications << name;
0161         } else {
0162             allowedApplications << name;
0163         }
0164     }
0165 
0166     d->pluginConfig->setBlockedApplications(blockedApplications);
0167     d->pluginConfig->setAllowedApplications(allowedApplications);
0168 
0169     const auto allowedApplicationsItem = d->pluginConfig->findItem("allowedApplications");
0170     Q_ASSERT(allowedApplicationsItem);
0171     const auto blockedApplicationsItem = d->pluginConfig->findItem("allowedApplications");
0172     Q_ASSERT(blockedApplicationsItem);
0173 
0174     Q_EMIT changed(blockedApplicationsItem->isSaveNeeded() && allowedApplicationsItem->isSaveNeeded());
0175     Q_EMIT defaulted(blockedApplicationsItem->isDefault() && allowedApplicationsItem->isDefault());
0176 }
0177 
0178 QVariant BlacklistedApplicationsModel::headerData(int section, Qt::Orientation orientation, int role) const
0179 {
0180     Q_UNUSED(section)
0181     Q_UNUSED(orientation)
0182     Q_UNUSED(role)
0183     return QVariant();
0184 }
0185 
0186 QVariant BlacklistedApplicationsModel::data(const QModelIndex &modelIndex, int role) const
0187 {
0188     const auto index = modelIndex.row();
0189 
0190     if (index > rowCount()) {
0191         return QVariant();
0192     }
0193 
0194     const auto &application = d->applications[index];
0195 
0196     switch (role) {
0197     default:
0198         return QVariant();
0199 
0200     case ApplicationIdRole:
0201         return application.name;
0202 
0203     case Qt::DisplayRole:
0204         return application.title;
0205 
0206     case Qt::DecorationRole:
0207         return application.icon.isEmpty() ? QStringLiteral("application-x-executable") : application.icon;
0208 
0209     case BlockedApplicationRole:
0210         return application.blocked;
0211     }
0212 }
0213 
0214 int BlacklistedApplicationsModel::rowCount(const QModelIndex &parent) const
0215 {
0216     Q_UNUSED(parent)
0217     return d->applications.size();
0218 }
0219 
0220 bool BlacklistedApplicationsModel::enabled() const
0221 {
0222     return d->enabled;
0223 }
0224 
0225 void BlacklistedApplicationsModel::setEnabled(bool enabled)
0226 {
0227     d->enabled = enabled;
0228     Q_EMIT enabledChanged(enabled);
0229 }
0230 
0231 // #include <BlacklistedApplicationsModel.moc>