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 | |
24 | class KNotifyEventList::KNotifyEventListDelegate : public QStyledItemDelegate |
25 | { |
26 | public: |
27 | explicit KNotifyEventListDelegate(QObject *parent = nullptr); |
28 | |
29 | void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; |
30 | |
31 | private: |
32 | }; |
33 | |
34 | KNotifyEventList::KNotifyEventListDelegate::KNotifyEventListDelegate(QObject *parent) |
35 | : QStyledItemDelegate(parent) |
36 | { |
37 | } |
38 | |
39 | void 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 | |
71 | KNotifyEventList::KNotifyEventList(QWidget *parent) |
72 | : QTreeWidget(parent) |
73 | , config(nullptr) |
74 | { |
75 | QStringList ; |
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 | |
96 | KNotifyEventList::~KNotifyEventList() |
97 | { |
98 | delete config; |
99 | } |
100 | |
101 | void 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 | auto configSources = |
108 | QStandardPaths::locateAll(type: QStandardPaths::GenericDataLocation, QStringLiteral("knotifications6/" ) + appname + QStringLiteral(".notifyrc" )); |
109 | // `QStandardPaths` follows the order of precedence given by `$XDG_DATA_DIRS |
110 | // (more priority goest first), but for `addConfigSources() it is the opposite |
111 | std::reverse(first: configSources.begin(), last: configSources.end()); |
112 | config->addConfigSources(sources: configSources); |
113 | |
114 | QStringList conflist = config->groupList(); |
115 | QRegularExpression rx(QStringLiteral("^Event/([^/]*)$" )); |
116 | conflist = conflist.filter(re: rx); |
117 | |
118 | for (const QString &group : std::as_const(t&: conflist)) { |
119 | KConfigGroup cg(config, group); |
120 | QString id = rx.match(subject: group).captured(nth: 1); |
121 | QString name = cg.readEntry(key: "Name" ); |
122 | QString description = cg.readEntry(key: "Comment" ); |
123 | |
124 | if (loadDefaults) { |
125 | KConfigGroup g(config, QStringLiteral("Event/" ) + id); |
126 | const auto keyList = g.keyList(); |
127 | for (const QString &entry : keyList) { |
128 | g.revertToDefault(key: entry); |
129 | } |
130 | } |
131 | |
132 | m_elements << new KNotifyEventListItem(this, id, name, description, config); |
133 | } |
134 | |
135 | resizeColumnToContents(column: 2); |
136 | } |
137 | |
138 | void KNotifyEventList::save() |
139 | { |
140 | for (KNotifyEventListItem *it : std::as_const(t&: m_elements)) { |
141 | it->save(); |
142 | } |
143 | config->sync(); |
144 | } |
145 | |
146 | bool KNotifyEventList::disableAllSounds() |
147 | { |
148 | bool changed = false; |
149 | for (KNotifyEventListItem *it : std::as_const(t&: m_elements)) { |
150 | QStringList actions = it->configElement()->readEntry(QStringLiteral("Action" )).split(sep: QLatin1Char('|')); |
151 | if (actions.removeAll(QStringLiteral("Sound" ))) { |
152 | it->configElement()->writeEntry(QStringLiteral("Action" ), data: actions.join(sep: QLatin1Char('|'))); |
153 | changed = true; |
154 | } |
155 | } |
156 | return changed; |
157 | } |
158 | |
159 | void KNotifyEventList::slotSelectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) |
160 | { |
161 | Q_UNUSED(current); |
162 | |
163 | KNotifyEventListItem *it = dynamic_cast<KNotifyEventListItem *>(currentItem()); |
164 | if (it) { |
165 | Q_EMIT eventSelected(it->configElement()); |
166 | } else { |
167 | Q_EMIT eventSelected(nullptr); |
168 | } |
169 | |
170 | it = dynamic_cast<KNotifyEventListItem *>(previous); |
171 | if (it) { |
172 | it->update(); |
173 | } |
174 | } |
175 | |
176 | void KNotifyEventList::updateCurrentItem() |
177 | { |
178 | KNotifyEventListItem *it = dynamic_cast<KNotifyEventListItem *>(currentItem()); |
179 | if (it) { |
180 | it->update(); |
181 | } |
182 | } |
183 | |
184 | void KNotifyEventList::updateAllItems() |
185 | { |
186 | for (KNotifyEventListItem *it : std::as_const(t&: m_elements)) { |
187 | it->update(); |
188 | } |
189 | } |
190 | |
191 | void KNotifyEventList::selectEvent(const QString &eventId) |
192 | { |
193 | auto it = std::find_if(first: m_elements.constBegin(), last: m_elements.constEnd(), pred: [&eventId](KNotifyEventListItem *item) { |
194 | return item->configElement()->eventId() == eventId; |
195 | }); |
196 | |
197 | if (it != m_elements.constEnd()) { |
198 | setCurrentItem(*it); |
199 | } |
200 | } |
201 | |
202 | QSize KNotifyEventList::sizeHint() const |
203 | { |
204 | int fontSize = fontMetrics().height(); |
205 | return QSize(48 * fontSize, 12 * fontSize); |
206 | } |
207 | |
208 | KNotifyEventListItem::KNotifyEventListItem(QTreeWidget *parent, const QString &eventName, const QString &name, const QString &description, KConfig *config) |
209 | : QTreeWidgetItem(parent) |
210 | , m_config(eventName, config) |
211 | { |
212 | setText(column: 1, atext: name); |
213 | setToolTip(column: 1, atoolTip: description); |
214 | setText(column: 2, atext: description); |
215 | setToolTip(column: 2, atoolTip: description); |
216 | update(); |
217 | } |
218 | |
219 | KNotifyEventListItem::~KNotifyEventListItem() |
220 | { |
221 | } |
222 | |
223 | void KNotifyEventListItem::save() |
224 | { |
225 | m_config.save(); |
226 | } |
227 | |
228 | void KNotifyEventListItem::update() |
229 | { |
230 | setData(column: 0, role: Qt::UserRole, value: m_config.readEntry(QStringLiteral("Action" ))); |
231 | } |
232 | |
233 | #include "moc_knotifyeventlist.cpp" |
234 | |