Commit 46a7f880 authored by Cyril Rossi's avatar Cyril Rossi
Browse files

KCM Notifications use KCModuleData to highlight the module when settings has changed

The particularity is in the per application/service's settings, which are created and loaded dynamically from the model in the KCM, meaning they are not yet available when KCModuleData check for isDefault.

Simple solution introduced here is to allow the KCModuleData derived class to load them from the plasmanotifyrc file since the non default settings are saved here.

Also, show the default indicator in the Applications / Services list and hihglight the "Configure..." button
parent a57104e7
......@@ -5,6 +5,7 @@ set(kcm_notifications_SRCS
kcm.cpp
sourcesmodel.cpp
filterproxymodel.cpp
notificationsdata.cpp
)
add_library(kcm_notifications MODULE ${kcm_notifications_SRCS})
......
......@@ -43,6 +43,7 @@
#include "sourcesmodel.h"
#include "filterproxymodel.h"
#include "notificationsdata.h"
#include <notificationmanager/donotdisturbsettings.h>
#include <notificationmanager/notificationsettings.h>
......@@ -50,16 +51,13 @@
#include <notificationmanager/badgesettings.h>
#include <notificationmanager/behaviorsettings.h>
K_PLUGIN_FACTORY_WITH_JSON(KCMNotificationsFactory, "kcm_notifications.json", registerPlugin<KCMNotifications>();)
K_PLUGIN_FACTORY_WITH_JSON(KCMNotificationsFactory, "kcm_notifications.json", registerPlugin<KCMNotifications>(); registerPlugin<NotificationsData>();)
KCMNotifications::KCMNotifications(QObject *parent, const QVariantList &args)
: KQuickAddons::ManagedConfigModule(parent, args)
, m_sourcesModel(new SourcesModel(this))
, m_filteredModel(new FilterProxyModel(this))
, m_dndSettings(new NotificationManager::DoNotDisturbSettings(this))
, m_notificationSettings(new NotificationManager::NotificationSettings(this))
, m_jobSettings(new NotificationManager::JobSettings(this))
, m_badgeSettings(new NotificationManager::BadgeSettings(this))
, m_data(new NotificationsData(this))
, m_toggleDoNotDisturbAction(new QAction(this))
{
......@@ -114,6 +112,7 @@ KCMNotifications::KCMNotifications(QObject *parent, const QVariantList &args)
setInitialEventId(parser.value(eventIdOption));
connect(this, &KCMNotifications::toggleDoNotDisturbShortcutChanged, this, &KCMNotifications::settingsChanged);
connect(this, &KCMNotifications::defaultsIndicatorsVisibleChanged, this, &KCMNotifications::onDefaultsIndicatorsVisibleChanged);
}
KCMNotifications::~KCMNotifications()
......@@ -133,22 +132,22 @@ FilterProxyModel *KCMNotifications::filteredModel() const
NotificationManager::DoNotDisturbSettings *KCMNotifications::dndSettings() const
{
return m_dndSettings;
return m_data->dndSettings();
}
NotificationManager::NotificationSettings *KCMNotifications::notificationSettings() const
{
return m_notificationSettings;
return m_data->notificationSettings();
}
NotificationManager::JobSettings *KCMNotifications::jobSettings() const
{
return m_jobSettings;
return m_data->jobSettings();
}
NotificationManager::BadgeSettings *KCMNotifications::badgeSettings() const
{
return m_badgeSettings;
return m_data->badgeSettings();
}
QKeySequence KCMNotifications::toggleDoNotDisturbShortcut() const
......@@ -253,7 +252,12 @@ NotificationManager::BehaviorSettings *KCMNotifications::behaviorSettings(const
if (!index.isValid()) {
return nullptr;
}
return m_behaviorSettingsList.value(index.row());
return m_data->behaviorSettings(index.row());
}
bool KCMNotifications::isDefaultsBehaviorSettings() const
{
return m_data->isDefaultsBehaviorSettings();
}
void KCMNotifications::load()
......@@ -281,14 +285,12 @@ void KCMNotifications::load()
groupName = m_sourcesModel->data(index, SourcesModel::NotifyRcNameRole).toString();
}
auto *toAdd = new NotificationManager::BehaviorSettings(typeName, groupName, this);
m_behaviorSettingsList[index.row()] = toAdd;
createConnections(toAdd);
m_data->insertBehaviorSettings(index.row(), toAdd);
createConnections(toAdd, index);
}
}
for (auto *behaviorSettings : qAsConst(m_behaviorSettingsList)) {
behaviorSettings->load();
}
m_data->loadBehaviorSettings();
const QKeySequence toggleDoNotDisturbShortcut = KGlobalAccel::self()->globalShortcut(
m_toggleDoNotDisturbAction->property("componentName").toString(),
......@@ -308,9 +310,7 @@ void KCMNotifications::load()
void KCMNotifications::save()
{
ManagedConfigModule::save();
for (auto *behaviorSettings : qAsConst(m_behaviorSettingsList)) {
behaviorSettings->save();
}
m_data->saveBehaviorSettings();
if (m_toggleDoNotDisturbShortcutDirty) {
// KeySequenceItem will already have checked whether the shortcut is available
......@@ -323,40 +323,56 @@ void KCMNotifications::save()
void KCMNotifications::defaults()
{
ManagedConfigModule::defaults();
for (auto *behaviorSettings : qAsConst(m_behaviorSettingsList)) {
behaviorSettings->setDefaults();
}
m_data->defaultsBehaviorSettings();
setToggleDoNotDisturbShortcut(QKeySequence());
}
bool KCMNotifications::isSaveNeeded() const
void KCMNotifications::onDefaultsIndicatorsVisibleChanged()
{
for (int i = 0; i < m_sourcesModel->rowCount(); ++i) {
const QModelIndex index = m_sourcesModel->index(i, 0);
updateModelIsDefaultStatus(index);
}
}
void KCMNotifications::updateModelIsDefaultStatus(const QModelIndex &index)
{
bool needSave = std::any_of(m_behaviorSettingsList.cbegin(),
m_behaviorSettingsList.cend(),
[](const NotificationManager::BehaviorSettings *settings) {
return settings->isSaveNeeded();
});
if (index.isValid()) {
m_sourcesModel->setData(index, behaviorSettings(index)->isDefaults(), SourcesModel::IsDefaultRole);
emit isDefaultsBehaviorSettingsChanged();
}
}
return needSave || m_toggleDoNotDisturbShortcutDirty;
bool KCMNotifications::isSaveNeeded() const
{
return m_toggleDoNotDisturbShortcutDirty || m_data->isSaveNeededBehaviorSettings();
}
bool KCMNotifications::isDefaults() const
{
bool notDefault = std::any_of(m_behaviorSettingsList.cbegin(),
m_behaviorSettingsList.cend(),
[](const NotificationManager::BehaviorSettings *settings) {
return !settings->isDefaults();
});
return !notDefault;
return m_data->isDefaultsBehaviorSettings();
}
void KCMNotifications::createConnections(NotificationManager::BehaviorSettings *settings)
void KCMNotifications::createConnections(NotificationManager::BehaviorSettings *settings, const QModelIndex &index)
{
connect(settings, &NotificationManager::BehaviorSettings::ShowPopupsChanged, this, &KCMNotifications::settingsChanged);
connect(settings, &NotificationManager::BehaviorSettings::ShowPopupsInDndModeChanged, this, &KCMNotifications::settingsChanged);
connect(settings, &NotificationManager::BehaviorSettings::ShowInHistoryChanged, this, &KCMNotifications::settingsChanged);
connect(settings, &NotificationManager::BehaviorSettings::ShowBadgesChanged, this, &KCMNotifications::settingsChanged);
connect(settings, &NotificationManager::BehaviorSettings::ShowPopupsChanged, this, [this, index] {
updateModelIsDefaultStatus(index);
});
connect(settings, &NotificationManager::BehaviorSettings::ShowPopupsInDndModeChanged, this, [this, index] {
updateModelIsDefaultStatus(index);
});
connect(settings, &NotificationManager::BehaviorSettings::ShowInHistoryChanged, this, [this, index] {
updateModelIsDefaultStatus(index);
});
connect(settings, &NotificationManager::BehaviorSettings::ShowBadgesChanged, this, [this, index] {
updateModelIsDefaultStatus(index);
});
}
#include "kcm.moc"
......@@ -29,6 +29,7 @@ class QAction;
class SourcesModel;
class FilterProxyModel;
class NotificationsData;
namespace NotificationManager {
class DoNotDisturbSettings;
......@@ -49,6 +50,7 @@ class KCMNotifications : public KQuickAddons::ManagedConfigModule
Q_PROPERTY(NotificationManager::NotificationSettings *notificationSettings READ notificationSettings CONSTANT)
Q_PROPERTY(NotificationManager::JobSettings *jobSettings READ jobSettings CONSTANT)
Q_PROPERTY(NotificationManager::BadgeSettings *badgeSettings READ badgeSettings CONSTANT)
Q_PROPERTY(bool isDefaultsBehaviorSettings READ isDefaultsBehaviorSettings NOTIFY isDefaultsBehaviorSettingsChanged)
Q_PROPERTY(QKeySequence toggleDoNotDisturbShortcut
READ toggleDoNotDisturbShortcut
......@@ -89,6 +91,8 @@ public:
Q_INVOKABLE NotificationManager::BehaviorSettings *behaviorSettings(const QModelIndex &index);
bool isDefaultsBehaviorSettings() const;
public Q_SLOTS:
void load() override;
void save() override;
......@@ -99,20 +103,21 @@ signals:
void initialNotifyRcNameChanged();
void initialEventIdChanged();
void firstLoadDone();
void isDefaultsBehaviorSettingsChanged();
private Q_SLOTS:
void onDefaultsIndicatorsVisibleChanged();
void updateModelIsDefaultStatus(const QModelIndex &index);
private:
bool isSaveNeeded() const override;
bool isDefaults() const override;
void createConnections(NotificationManager::BehaviorSettings *settings);
void createConnections(NotificationManager::BehaviorSettings *settings, const QModelIndex &index);
SourcesModel *m_sourcesModel;
FilterProxyModel *m_filteredModel;
NotificationManager::DoNotDisturbSettings *m_dndSettings;
NotificationManager::NotificationSettings *m_notificationSettings;
NotificationManager::JobSettings *m_jobSettings;
NotificationManager::BadgeSettings *m_badgeSettings;
QHash<int, NotificationManager::BehaviorSettings *> m_behaviorSettingsList;
NotificationsData *m_data;
QAction *m_toggleDoNotDisturbAction;
QKeySequence m_toggleDoNotDisturbShortcut;
......
/*
* Copyright (c) 2020 Cyril Rossi <cyril.rossi@enioka.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "notificationsdata.h"
#include <notificationmanager/donotdisturbsettings.h>
#include <notificationmanager/notificationsettings.h>
#include <notificationmanager/jobsettings.h>
#include <notificationmanager/badgesettings.h>
#include <notificationmanager/behaviorsettings.h>
NotificationsData::NotificationsData(QObject *parent, const QVariantList &args)
: KCModuleData(parent, args)
, m_dndSettings(new NotificationManager::DoNotDisturbSettings(this))
, m_notificationSettings(new NotificationManager::NotificationSettings(this))
, m_jobSettings(new NotificationManager::JobSettings(this))
, m_badgeSettings(new NotificationManager::BadgeSettings(this))
{
autoRegisterSkeletons();
readBehaviorSettings();
}
NotificationManager::DoNotDisturbSettings *NotificationsData::dndSettings() const
{
return m_dndSettings;
}
NotificationManager::NotificationSettings *NotificationsData::notificationSettings() const
{
return m_notificationSettings;
}
NotificationManager::JobSettings *NotificationsData::jobSettings() const
{
return m_jobSettings;
}
NotificationManager::BadgeSettings *NotificationsData::badgeSettings() const
{
return m_badgeSettings;
}
NotificationManager::BehaviorSettings *NotificationsData::behaviorSettings(int index) const
{
return m_behaviorSettingsList.value(index);
}
void NotificationsData::insertBehaviorSettings(int index, NotificationManager::BehaviorSettings *settings)
{
m_behaviorSettingsList[index] = settings;
}
void NotificationsData::loadBehaviorSettings()
{
for (auto *behaviorSettings : qAsConst(m_behaviorSettingsList)) {
behaviorSettings->load();
}
}
void NotificationsData::saveBehaviorSettings()
{
for (auto *behaviorSettings : qAsConst(m_behaviorSettingsList)) {
behaviorSettings->save();
}
}
void NotificationsData::defaultsBehaviorSettings()
{
for (auto *behaviorSettings : qAsConst(m_behaviorSettingsList)) {
behaviorSettings->setDefaults();
}
}
bool NotificationsData::isSaveNeededBehaviorSettings() const
{
bool needSave = std::any_of(m_behaviorSettingsList.cbegin(),
m_behaviorSettingsList.cend(),
[](const NotificationManager::BehaviorSettings *settings) {
return settings->isSaveNeeded();
});
return needSave;
}
bool NotificationsData::isDefaultsBehaviorSettings() const
{
bool notDefault = std::any_of(m_behaviorSettingsList.cbegin(),
m_behaviorSettingsList.cend(),
[](const NotificationManager::BehaviorSettings *settings) {
return !settings->isDefaults();
});
return !notDefault;
}
void NotificationsData::readBehaviorSettings()
{
KConfig config("plasmanotifyrc", KConfig::SimpleConfig);
for (auto groupEntry : { QStringLiteral("Applications"), QStringLiteral("Services") }) {
KConfigGroup group(&config, groupEntry);
for (const QString &desktopEntry : group.groupList()) {
m_behaviorSettingsList.insert(m_behaviorSettingsList.count(), new NotificationManager::BehaviorSettings(groupEntry, desktopEntry, this));
}
}
}
bool NotificationsData::isDefaults() const
{
return KCModuleData::isDefaults() && isDefaultsBehaviorSettings();
}
/*
* Copyright (c) 2020 Cyril Rossi <cyril.rossi@enioka.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef NOTIFICATIONSDATA_H
#define NOTIFICATIONSDATA_H
#include <QObject>
#include <KCModuleData>
namespace NotificationManager {
class DoNotDisturbSettings;
class NotificationSettings;
class JobSettings;
class BadgeSettings;
class BehaviorSettings;
}
class NotificationsData : public KCModuleData
{
Q_OBJECT
public:
explicit NotificationsData(QObject *parent = nullptr, const QVariantList &args = QVariantList());
bool isDefaults() const override;
NotificationManager::DoNotDisturbSettings *dndSettings() const;
NotificationManager::NotificationSettings *notificationSettings() const;
NotificationManager::JobSettings *jobSettings() const;
NotificationManager::BadgeSettings *badgeSettings() const;
NotificationManager::BehaviorSettings *behaviorSettings(int index) const;
void insertBehaviorSettings(int index, NotificationManager::BehaviorSettings *settings);
void loadBehaviorSettings();
void saveBehaviorSettings();
void defaultsBehaviorSettings();
bool isSaveNeededBehaviorSettings() const;
bool isDefaultsBehaviorSettings() const;
private:
void readBehaviorSettings();
NotificationManager::DoNotDisturbSettings *m_dndSettings;
NotificationManager::NotificationSettings *m_notificationSettings;
NotificationManager::JobSettings *m_jobSettings;
NotificationManager::BadgeSettings *m_badgeSettings;
QHash<int, NotificationManager::BehaviorSettings *> m_behaviorSettingsList;
};
#endif // NOTIFICATIONSDATA_H
......@@ -122,6 +122,15 @@ Kirigami.Page {
sourcesList.forceActiveFocus();
sourcesList.currentIndex = index;
}
Rectangle {
id: defaultIndicator
radius: width * 0.5
implicitWidth: Kirigami.Units.largeSpacing
implicitHeight: Kirigami.Units.largeSpacing
visible: kcm.defaultsIndicatorsVisible
opacity: !model.isDefault
color: Kirigami.Theme.neutralTextColor
}
}
Kirigami.PlaceholderMessage {
......
......@@ -23,7 +23,7 @@ import QtQuick.Layouts 1.1
import QtQuick.Controls 2.3 as QtControls
import org.kde.kirigami 2.4 as Kirigami
import org.kde.kquickcontrols 2.0 as KQuickControls
import org.kde.kcm 1.3 as KCM
import org.kde.kcm 1.5 as KCM
import org.kde.notificationmanager 1.0 as NotificationManager
......@@ -322,6 +322,10 @@ KCM.SimpleKCM {
icon.name: "configure"
enabled: root.notificationsAvailable
onClicked: root.openSourcesSettings()
KCM.SettingHighlighter {
highlight: !kcm.isDefaultsBehaviorSettings
}
}
Connections {
......
......@@ -126,6 +126,7 @@ QVariant SourcesModel::data(const QModelIndex &index, int role) const
case SourceTypeRole: return source.desktopEntry.isEmpty() ? ServiceType : ApplicationType;
case NotifyRcNameRole: return source.notifyRcName;
case DesktopEntryRole: return source.desktopEntry;
case IsDefaultRole: return source.isDefault;
}
return QVariant();
......@@ -153,6 +154,18 @@ bool SourcesModel::setData(const QModelIndex &index, const QVariant &value, int
}
}
auto &source = m_data[index.row()];
switch (role) {
case IsDefaultRole: {
if (source.isDefault != value.toBool()) {
source.isDefault = value.toBool();
dirty = true;
}
break;
}
}
if (dirty) {
emit dataChanged(index, index, {role});
}
......@@ -199,6 +212,7 @@ QHash<int, QByteArray> SourcesModel::roleNames() const
{SourceTypeRole, QByteArrayLiteral("sourceType")},
{NotifyRcNameRole, QByteArrayLiteral("notifyRcName")},
{DesktopEntryRole, QByteArrayLiteral("desktopEntry")},
{IsDefaultRole, QByteArrayLiteral("isDefault")},
{EventIdRole, QByteArrayLiteral("eventId")},
{ActionsRole, QByteArrayLiteral("actions")}
};
......@@ -258,6 +272,7 @@ void SourcesModel::load()
globalGroup.readEntry(QStringLiteral("Name")),
globalGroup.readEntry(QStringLiteral("Comment")),
globalGroup.readEntry(QStringLiteral("IconName")),
true,
notifyRcName,
desktopEntry,
{} // events
......@@ -311,6 +326,7 @@ void SourcesModel::load()
service->name(),
service->comment(),
service->icon(),
true,
QString(), //notifyRcFile
service->desktopEntryName(),
{} // events
......@@ -336,6 +352,7 @@ void SourcesModel::load()
service->name(),
service->comment(),
service->icon(),
true,
QString(), //notifyRcFile
service->desktopEntryName(),
{}
......@@ -353,6 +370,7 @@ void SourcesModel::load()
i18n("Other Applications"),
{},
QStringLiteral("applications-other"),
true,
QString(),
QStringLiteral("@other"),
{}
......
......@@ -40,6 +40,7 @@ struct SourceData
QString name;
QString comment;
QString iconName;
bool isDefault;
QString notifyRcName;
QString desktopEntry;
......@@ -64,6 +65,7 @@ public:
SourceTypeRole = Qt::UserRole + 1,
NotifyRcNameRole,
DesktopEntryRole,
IsDefaultRole,
EventIdRole,
ActionsRole
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment