diff --git a/kcms/notifications/sourcesmodel.cpp b/kcms/notifications/sourcesmodel.cpp index 3293a9540..a4ff2d6b4 100644 --- a/kcms/notifications/sourcesmodel.cpp +++ b/kcms/notifications/sourcesmodel.cpp @@ -1,348 +1,348 @@ /* * Copyright (C) 2007 Matthew Woehlke * Copyright (C) 2007 Jeremy Whiting * Copyright (C) 2016 Olivier Churlaud * Copyright (C) 2019 Kai Uwe Broulik * * 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) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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, see . */ #include "sourcesmodel.h" #include #include #include #include #include #include #include #include #include #include #include SourcesModel::SourcesModel(QObject *parent) : QAbstractItemModel(parent) { } SourcesModel::~SourcesModel() = default; QPersistentModelIndex SourcesModel::makePersistentModelIndex(const QModelIndex &idx) const { return QPersistentModelIndex(idx); } QPersistentModelIndex SourcesModel::persistentIndexForDesktopEntry(const QString &desktopEntry) const { const auto matches = match(index(0, 0), SourcesModel::DesktopEntryRole, desktopEntry, 1, Qt::MatchFixedString); if (matches.isEmpty()) { return QPersistentModelIndex(); } return QPersistentModelIndex(matches.first()); } QPersistentModelIndex SourcesModel::persistentIndexForNotifyRcName(const QString ¬ifyRcName) const { const auto matches = match(index(0, 0), SourcesModel::NotifyRcNameRole, notifyRcName, 1, Qt::MatchFixedString); if (matches.isEmpty()) { return QPersistentModelIndex(); } return QPersistentModelIndex(matches.first()); } int SourcesModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 1; } int SourcesModel::rowCount(const QModelIndex &parent) const { if (parent.column() > 0) { return 0; } if (!parent.isValid()) { return m_data.count(); } if (parent.internalId()) { return 0; } return m_data.at(parent.row()).events.count(); } QVariant SourcesModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.internalId()) { // event const auto &event = m_data.at(index.internalId() - 1).events.at(index.row()); switch (role) { case Qt::DisplayRole: return event.name; case Qt::DecorationRole: return event.iconName; case EventIdRole: return event.eventId; case ActionsRole: return event.actions; } return QVariant(); } const auto &source = m_data.at(index.row()); switch (role) { case Qt::DisplayRole: return source.display(); case Qt::DecorationRole: return source.iconName; case SourceTypeRole: return source.desktopEntry.isEmpty() ? ServiceType : ApplicationType; case NotifyRcNameRole: return source.notifyRcName; case DesktopEntryRole: return source.desktopEntry; } return QVariant(); } bool SourcesModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid()) { return false; } bool dirty = false; if (index.internalId()) { // event auto &event = m_data[index.internalId() - 1].events[index.row()]; switch (role) { case ActionsRole: { const QStringList newActions = value.toStringList(); if (event.actions != newActions) { event.actions = newActions; dirty = true; } break; } } } if (dirty) { emit dataChanged(index, index, {role}); } return dirty; } QModelIndex SourcesModel::index(int row, int column, const QModelIndex &parent) const { if (row < 0 || column != 0) { return QModelIndex(); } if (parent.isValid()) { const auto events = m_data.at(parent.row()).events; if (row < events.count()) { return createIndex(row, column, parent.row() + 1); } return QModelIndex(); } if (row < m_data.count()) { return createIndex(row, column, nullptr); } return QModelIndex(); } QModelIndex SourcesModel::parent(const QModelIndex &child) const { if (child.internalId()) { return createIndex(child.internalId() - 1, 0, nullptr); } return QModelIndex(); } QHash SourcesModel::roleNames() const { return { {Qt::DisplayRole, QByteArrayLiteral("display")}, {Qt::DecorationRole, QByteArrayLiteral("decoration")}, {SourceTypeRole, QByteArrayLiteral("sourceType")}, {NotifyRcNameRole, QByteArrayLiteral("notifyRcName")}, {DesktopEntryRole, QByteArrayLiteral("desktopEntry")}, {EventIdRole, QByteArrayLiteral("eventId")}, {ActionsRole, QByteArrayLiteral("actions")} }; } void SourcesModel::load() { beginResetModel(); m_data.clear(); QCollator collator; QVector appsData; QVector servicesData; QStringList notifyRcFiles; QStringList desktopEntries; // old code did KGlobal::dirs()->findAllResources("data", QStringLiteral("*/*.notifyrc")) but in KF5 // only notifyrc files in knotifications5/ folder are supported const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("knotifications5"), QStandardPaths::LocateDirectory); for (const QString &dir : dirs) { const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.notifyrc")); for (const QString &file : fileNames) { if (notifyRcFiles.contains(file)) { continue; } notifyRcFiles.append(file); - KConfig *config = new KConfig(file, KConfig::NoGlobals); - config->addConfigSources(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, + KConfig config(file, KConfig::NoGlobals); + config.addConfigSources(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("knotifications5/") + file)); - KConfigGroup globalGroup(config, QLatin1String("Global")); + KConfigGroup globalGroup(&config, QLatin1String("Global")); const QRegularExpression regExp(QStringLiteral("^Event/([^/]*)$")); - const QStringList groups = config->groupList().filter(regExp); + const QStringList groups = config.groupList().filter(regExp); const QString notifyRcName = file.section(QLatin1Char('.'), 0, -2); const QString desktopEntry = globalGroup.readEntry(QStringLiteral("DesktopEntry")); if (!desktopEntry.isEmpty()) { if (desktopEntries.contains(desktopEntry)) { continue; } desktopEntries.append(desktopEntry); } SourceData source{ // The old KCM read the Name and Comment from global settings disregarding // any user settings and just used user-specific files for actions config // I'm pretty sure there's a readEntry equivalent that does that without // reading the config stuff twice, assuming we care about this to begin with globalGroup.readEntry(QStringLiteral("Name")), globalGroup.readEntry(QStringLiteral("Comment")), globalGroup.readEntry(QStringLiteral("IconName")), notifyRcName, desktopEntry, {} // events }; QVector events; for (const QString &group : groups) { - KConfigGroup cg(config, group); + KConfigGroup cg(&config, group); const QString eventId = regExp.match(group).captured(1); // TODO context stuff // TODO load defaults thing EventData event{ cg.readEntry("Name"), cg.readEntry("Comment"), cg.readEntry("IconName"), eventId, // TODO Flags? cg.readEntry("Action").split(QLatin1Char('|')) }; events.append(event); } std::sort(events.begin(), events.end(), [&collator](const EventData &a, const EventData &b) { return collator.compare(a.name, b.name) < 0; }); source.events = events; if (!source.desktopEntry.isEmpty()) { appsData.append(source); } else { servicesData.append(source); } } } const auto services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and TRUE == [X-GNOME-UsesNotifications]")); for (const auto &service : services) { if (service->noDisplay()) { continue; } if (desktopEntries.contains(service->desktopEntryName())) { continue; } SourceData source{ service->name(), service->comment(), service->icon(), QString(), //notifyRcFile service->desktopEntryName(), {} // events }; appsData.append(source); desktopEntries.append(service->desktopEntryName()); } KSharedConfig::Ptr plasmanotifyrc = KSharedConfig::openConfig(QStringLiteral("plasmanotifyrc")); KConfigGroup applicationsGroup = plasmanotifyrc->group("Applications"); const QStringList seenApps = applicationsGroup.groupList(); for (const QString &app : seenApps) { if (desktopEntries.contains(app)) { continue; } KService::Ptr service = KService::serviceByDesktopName(app); if (!service || service->noDisplay()) { continue; } SourceData source{ service->name(), service->comment(), service->icon(), QString(), //notifyRcFile service->desktopEntryName(), {} }; appsData.append(source); desktopEntries.append(service->desktopEntryName()); } auto sortData = [&collator](const SourceData &a, const SourceData &b) { return collator.compare(a.display(), b.display()) < 0; }; std::sort(appsData.begin(), appsData.end(), sortData); std::sort(servicesData.begin(), servicesData.end(), sortData); m_data << appsData << servicesData; endResetModel(); }