1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2005 Olivier Goffart <ogoffart at kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#include "knotifyeventlist.h"
9
10#include <knotifyconfig_debug.h>
11
12#include <KConfig>
13#include <KConfigGroup>
14#include <KLocalizedString>
15
16#include <QHeaderView>
17#include <QPainter>
18#include <QRegularExpression>
19#include <QStandardPaths>
20#include <QStyledItemDelegate>
21
22// BEGIN KNotifyEventListDelegate
23
24class KNotifyEventList::KNotifyEventListDelegate : public QStyledItemDelegate
25{
26public:
27 explicit KNotifyEventListDelegate(QObject *parent = nullptr);
28
29 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
30
31private:
32};
33
34KNotifyEventList::KNotifyEventListDelegate::KNotifyEventListDelegate(QObject *parent)
35 : QStyledItemDelegate(parent)
36{
37}
38
39void KNotifyEventList::KNotifyEventListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
40{
41 if (index.column() != 0) {
42 return QStyledItemDelegate::paint(painter, option, index);
43 }
44
45 QVariant displayData = index.data(arole: Qt::UserRole);
46 QString prstring = displayData.toString();
47
48 QStyledItemDelegate::paint(painter, option, index);
49
50 // qDebug() << prstring;
51
52 QRect rect = option.rect;
53
54 QStringList optionsList = prstring.split(sep: QLatin1Char('|'));
55 QList<QIcon> iconList;
56 iconList << (optionsList.contains(QStringLiteral("Sound")) ? QIcon::fromTheme(QStringLiteral("media-playback-start")) : QIcon());
57 iconList << (optionsList.contains(QStringLiteral("Popup")) ? QIcon::fromTheme(QStringLiteral("dialog-information")) : QIcon());
58
59 int mc_x = 0;
60
61 int iconWidth = option.decorationSize.width();
62 int iconHeight = option.decorationSize.height();
63 for (const QIcon &icon : std::as_const(t&: iconList)) {
64 icon.paint(painter, x: rect.left() + mc_x + 4, y: rect.top() + (rect.height() - iconHeight) / 2, w: iconWidth, h: iconHeight);
65 mc_x += iconWidth + 4;
66 }
67}
68
69// END KNotifyEventListDelegate
70
71KNotifyEventList::KNotifyEventList(QWidget *parent)
72 : QTreeWidget(parent)
73 , config(nullptr)
74{
75 QStringList headerLabels;
76 headerLabels << i18nc("State of the notified event", "State") << i18nc("Title of the notified event", "Title")
77 << i18nc("Description of the notified event", "Description");
78 setHeaderLabels(headerLabels);
79
80 setItemDelegate(new KNotifyEventListDelegate(this));
81 setRootIsDecorated(false);
82 setAlternatingRowColors(true);
83
84 // Extract icon size as the font height (as h=w on icons)
85 QStyleOptionViewItem iconOption;
86 iconOption.initFrom(w: this);
87 int iconWidth = iconOption.fontMetrics.height() - 2; // 1px margin top & bottom
88 setIconSize(QSize(iconWidth, iconWidth));
89
90 header()->setSectionResizeMode(logicalIndex: 0, mode: QHeaderView::Fixed);
91 header()->setSectionResizeMode(logicalIndex: 1, mode: QHeaderView::ResizeToContents);
92
93 connect(sender: this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), receiver: this, SLOT(slotSelectionChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
94}
95
96KNotifyEventList::~KNotifyEventList()
97{
98 delete config;
99}
100
101void KNotifyEventList::fill(const QString &appname, bool loadDefaults)
102{
103 m_elements.clear();
104 clear();
105 delete config;
106 config = new KConfig(appname + QStringLiteral(".notifyrc"), KConfig::NoGlobals);
107 config->addConfigSources(
108 sources: QStandardPaths::locateAll(type: QStandardPaths::GenericDataLocation, QStringLiteral("knotifications6/") + appname + QStringLiteral(".notifyrc")));
109
110 QStringList conflist = config->groupList();
111 QRegularExpression rx(QStringLiteral("^Event/([^/]*)$"));
112 conflist = conflist.filter(re: rx);
113
114 for (const QString &group : std::as_const(t&: conflist)) {
115 KConfigGroup cg(config, group);
116 QString id = rx.match(subject: group).captured(nth: 1);
117 QString name = cg.readEntry(key: "Name");
118 QString description = cg.readEntry(key: "Comment");
119
120 if (loadDefaults) {
121 KConfigGroup g(config, QStringLiteral("Event/") + id);
122 const auto keyList = g.keyList();
123 for (const QString &entry : keyList) {
124 g.revertToDefault(key: entry);
125 }
126 }
127
128 m_elements << new KNotifyEventListItem(this, id, name, description, config);
129 }
130
131 resizeColumnToContents(column: 2);
132}
133
134void KNotifyEventList::save()
135{
136 for (KNotifyEventListItem *it : std::as_const(t&: m_elements)) {
137 it->save();
138 }
139 config->sync();
140}
141
142bool KNotifyEventList::disableAllSounds()
143{
144 bool changed = false;
145 for (KNotifyEventListItem *it : std::as_const(t&: m_elements)) {
146 QStringList actions = it->configElement()->readEntry(QStringLiteral("Action")).split(sep: QLatin1Char('|'));
147 if (actions.removeAll(QStringLiteral("Sound"))) {
148 it->configElement()->writeEntry(QStringLiteral("Action"), data: actions.join(sep: QLatin1Char('|')));
149 changed = true;
150 }
151 }
152 return changed;
153}
154
155void KNotifyEventList::slotSelectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
156{
157 Q_UNUSED(current);
158
159 KNotifyEventListItem *it = dynamic_cast<KNotifyEventListItem *>(currentItem());
160 if (it) {
161 Q_EMIT eventSelected(it->configElement());
162 } else {
163 Q_EMIT eventSelected(nullptr);
164 }
165
166 it = dynamic_cast<KNotifyEventListItem *>(previous);
167 if (it) {
168 it->update();
169 }
170}
171
172void KNotifyEventList::updateCurrentItem()
173{
174 KNotifyEventListItem *it = dynamic_cast<KNotifyEventListItem *>(currentItem());
175 if (it) {
176 it->update();
177 }
178}
179
180void KNotifyEventList::updateAllItems()
181{
182 for (KNotifyEventListItem *it : std::as_const(t&: m_elements)) {
183 it->update();
184 }
185}
186
187void KNotifyEventList::selectEvent(const QString &eventId)
188{
189 auto it = std::find_if(first: m_elements.constBegin(), last: m_elements.constEnd(), pred: [&eventId](KNotifyEventListItem *item) {
190 return item->configElement()->eventId() == eventId;
191 });
192
193 if (it != m_elements.constEnd()) {
194 setCurrentItem(*it);
195 }
196}
197
198QSize KNotifyEventList::sizeHint() const
199{
200 int fontSize = fontMetrics().height();
201 return QSize(48 * fontSize, 12 * fontSize);
202}
203
204KNotifyEventListItem::KNotifyEventListItem(QTreeWidget *parent, const QString &eventName, const QString &name, const QString &description, KConfig *config)
205 : QTreeWidgetItem(parent)
206 , m_config(eventName, config)
207{
208 setText(column: 1, atext: name);
209 setToolTip(column: 1, atoolTip: description);
210 setText(column: 2, atext: description);
211 setToolTip(column: 2, atoolTip: description);
212 update();
213}
214
215KNotifyEventListItem::~KNotifyEventListItem()
216{
217}
218
219void KNotifyEventListItem::save()
220{
221 m_config.save();
222}
223
224void KNotifyEventListItem::update()
225{
226 setData(column: 0, role: Qt::UserRole, value: m_config.readEntry(QStringLiteral("Action")));
227}
228
229#include "moc_knotifyeventlist.cpp"
230

source code of knotifyconfig/src/knotifyeventlist.cpp