1 | /* |
2 | SPDX-FileCopyrightText: 2015 Eike Hein <hein@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | #include "plasmawindowmodel.h" |
7 | #include "plasmawindowmanagement.h" |
8 | |
9 | #include <QMetaEnum> |
10 | |
11 | namespace KWayland |
12 | { |
13 | namespace Client |
14 | { |
15 | class Q_DECL_HIDDEN PlasmaWindowModel::Private |
16 | { |
17 | public: |
18 | Private(PlasmaWindowModel *q); |
19 | QList<PlasmaWindow *> windows; |
20 | PlasmaWindow *window = nullptr; |
21 | |
22 | void addWindow(PlasmaWindow *window); |
23 | void dataChanged(PlasmaWindow *window, int role); |
24 | |
25 | private: |
26 | PlasmaWindowModel *q; |
27 | }; |
28 | |
29 | PlasmaWindowModel::Private::Private(PlasmaWindowModel *q) |
30 | : q(q) |
31 | { |
32 | } |
33 | |
34 | void PlasmaWindowModel::Private::addWindow(PlasmaWindow *window) |
35 | { |
36 | if (windows.indexOf(t: window) != -1) { |
37 | return; |
38 | } |
39 | |
40 | const int count = windows.count(); |
41 | q->beginInsertRows(parent: QModelIndex(), first: count, last: count); |
42 | windows.append(t: window); |
43 | q->endInsertRows(); |
44 | |
45 | auto removeWindow = [window, this] { |
46 | const int row = windows.indexOf(t: window); |
47 | if (row != -1) { |
48 | q->beginRemoveRows(parent: QModelIndex(), first: row, last: row); |
49 | windows.removeAt(i: row); |
50 | q->endRemoveRows(); |
51 | } |
52 | }; |
53 | |
54 | QObject::connect(sender: window, signal: &PlasmaWindow::unmapped, context: q, slot&: removeWindow); |
55 | QObject::connect(sender: window, signal: &QObject::destroyed, context: q, slot&: removeWindow); |
56 | |
57 | QObject::connect(sender: window, signal: &PlasmaWindow::titleChanged, context: q, slot: [window, this] { |
58 | this->dataChanged(window, role: Qt::DisplayRole); |
59 | }); |
60 | |
61 | QObject::connect(sender: window, signal: &PlasmaWindow::iconChanged, context: q, slot: [window, this] { |
62 | this->dataChanged(window, role: Qt::DecorationRole); |
63 | }); |
64 | |
65 | QObject::connect(sender: window, signal: &PlasmaWindow::appIdChanged, context: q, slot: [window, this] { |
66 | this->dataChanged(window, role: PlasmaWindowModel::AppId); |
67 | }); |
68 | |
69 | QObject::connect(sender: window, signal: &PlasmaWindow::activeChanged, context: q, slot: [window, this] { |
70 | this->dataChanged(window, role: IsActive); |
71 | }); |
72 | |
73 | QObject::connect(sender: window, signal: &PlasmaWindow::fullscreenableChanged, context: q, slot: [window, this] { |
74 | this->dataChanged(window, role: IsFullscreenable); |
75 | }); |
76 | |
77 | QObject::connect(sender: window, signal: &PlasmaWindow::fullscreenChanged, context: q, slot: [window, this] { |
78 | this->dataChanged(window, role: IsFullscreen); |
79 | }); |
80 | |
81 | QObject::connect(sender: window, signal: &PlasmaWindow::maximizeableChanged, context: q, slot: [window, this] { |
82 | this->dataChanged(window, role: IsMaximizable); |
83 | }); |
84 | |
85 | QObject::connect(sender: window, signal: &PlasmaWindow::maximizedChanged, context: q, slot: [window, this] { |
86 | this->dataChanged(window, role: IsMaximized); |
87 | }); |
88 | |
89 | QObject::connect(sender: window, signal: &PlasmaWindow::minimizeableChanged, context: q, slot: [window, this] { |
90 | this->dataChanged(window, role: IsMinimizable); |
91 | }); |
92 | |
93 | QObject::connect(sender: window, signal: &PlasmaWindow::minimizedChanged, context: q, slot: [window, this] { |
94 | this->dataChanged(window, role: IsMinimized); |
95 | }); |
96 | |
97 | QObject::connect(sender: window, signal: &PlasmaWindow::keepAboveChanged, context: q, slot: [window, this] { |
98 | this->dataChanged(window, role: IsKeepAbove); |
99 | }); |
100 | |
101 | QObject::connect(sender: window, signal: &PlasmaWindow::keepBelowChanged, context: q, slot: [window, this] { |
102 | this->dataChanged(window, role: IsKeepBelow); |
103 | }); |
104 | |
105 | QObject::connect(sender: window, signal: &PlasmaWindow::onAllDesktopsChanged, context: q, slot: [window, this] { |
106 | this->dataChanged(window, role: IsOnAllDesktops); |
107 | }); |
108 | |
109 | QObject::connect(sender: window, signal: &PlasmaWindow::demandsAttentionChanged, context: q, slot: [window, this] { |
110 | this->dataChanged(window, role: IsDemandingAttention); |
111 | }); |
112 | |
113 | QObject::connect(sender: window, signal: &PlasmaWindow::skipTaskbarChanged, context: q, slot: [window, this] { |
114 | this->dataChanged(window, role: SkipTaskbar); |
115 | }); |
116 | |
117 | QObject::connect(sender: window, signal: &PlasmaWindow::skipSwitcherChanged, context: q, slot: [window, this] { |
118 | this->dataChanged(window, role: SkipSwitcher); |
119 | }); |
120 | |
121 | QObject::connect(sender: window, signal: &PlasmaWindow::shadeableChanged, context: q, slot: [window, this] { |
122 | this->dataChanged(window, role: IsShadeable); |
123 | }); |
124 | |
125 | QObject::connect(sender: window, signal: &PlasmaWindow::shadedChanged, context: q, slot: [window, this] { |
126 | this->dataChanged(window, role: IsShaded); |
127 | }); |
128 | |
129 | QObject::connect(sender: window, signal: &PlasmaWindow::movableChanged, context: q, slot: [window, this] { |
130 | this->dataChanged(window, role: IsMovable); |
131 | }); |
132 | |
133 | QObject::connect(sender: window, signal: &PlasmaWindow::resizableChanged, context: q, slot: [window, this] { |
134 | this->dataChanged(window, role: IsResizable); |
135 | }); |
136 | |
137 | QObject::connect(sender: window, signal: &PlasmaWindow::virtualDesktopChangeableChanged, context: q, slot: [window, this] { |
138 | this->dataChanged(window, role: IsVirtualDesktopChangeable); |
139 | }); |
140 | |
141 | QObject::connect(sender: window, signal: &PlasmaWindow::closeableChanged, context: q, slot: [window, this] { |
142 | this->dataChanged(window, role: IsCloseable); |
143 | }); |
144 | |
145 | QObject::connect(sender: window, signal: &PlasmaWindow::geometryChanged, context: q, slot: [window, this] { |
146 | this->dataChanged(window, role: Geometry); |
147 | }); |
148 | |
149 | QObject::connect(sender: window, signal: &PlasmaWindow::plasmaVirtualDesktopEntered, context: q, slot: [window, this] { |
150 | this->dataChanged(window, role: VirtualDesktops); |
151 | }); |
152 | |
153 | QObject::connect(sender: window, signal: &PlasmaWindow::plasmaVirtualDesktopLeft, context: q, slot: [window, this] { |
154 | this->dataChanged(window, role: VirtualDesktops); |
155 | }); |
156 | } |
157 | |
158 | void PlasmaWindowModel::Private::dataChanged(PlasmaWindow *window, int role) |
159 | { |
160 | QModelIndex idx = q->index(row: windows.indexOf(t: window)); |
161 | Q_EMIT q->dataChanged(topLeft: idx, bottomRight: idx, roles: QList<int>() << role); |
162 | } |
163 | |
164 | PlasmaWindowModel::PlasmaWindowModel(PlasmaWindowManagement *parent) |
165 | : QAbstractListModel(parent) |
166 | , d(new Private(this)) |
167 | { |
168 | connect(sender: parent, signal: &PlasmaWindowManagement::interfaceAboutToBeReleased, context: this, slot: [this] { |
169 | beginResetModel(); |
170 | d->windows.clear(); |
171 | endResetModel(); |
172 | }); |
173 | |
174 | connect(sender: parent, signal: &PlasmaWindowManagement::windowCreated, context: this, slot: [this](PlasmaWindow *window) { |
175 | d->addWindow(window); |
176 | }); |
177 | |
178 | for (auto it = parent->windows().constBegin(); it != parent->windows().constEnd(); ++it) { |
179 | d->addWindow(window: *it); |
180 | } |
181 | } |
182 | |
183 | PlasmaWindowModel::~PlasmaWindowModel() |
184 | { |
185 | } |
186 | |
187 | QHash<int, QByteArray> PlasmaWindowModel::roleNames() const |
188 | { |
189 | QHash<int, QByteArray> roles; |
190 | |
191 | roles.insert(key: Qt::DisplayRole, value: "display" ); |
192 | roles.insert(key: Qt::DecorationRole, value: "decoration" ); |
193 | |
194 | QMetaEnum e = metaObject()->enumerator(index: metaObject()->indexOfEnumerator(name: "AdditionalRoles" )); |
195 | |
196 | for (int i = 0; i < e.keyCount(); ++i) { |
197 | roles.insert(key: e.value(index: i), value: e.key(index: i)); |
198 | } |
199 | |
200 | return roles; |
201 | } |
202 | |
203 | QVariant PlasmaWindowModel::data(const QModelIndex &index, int role) const |
204 | { |
205 | if (!index.isValid() || index.row() >= d->windows.count()) { |
206 | return QVariant(); |
207 | } |
208 | |
209 | const PlasmaWindow *window = d->windows.at(i: index.row()); |
210 | |
211 | if (role == Qt::DisplayRole) { |
212 | return window->title(); |
213 | } else if (role == Qt::DecorationRole) { |
214 | return window->icon(); |
215 | } else if (role == AppId) { |
216 | return window->appId(); |
217 | } else if (role == Pid) { |
218 | return window->pid(); |
219 | } else if (role == IsActive) { |
220 | return window->isActive(); |
221 | } else if (role == IsFullscreenable) { |
222 | return window->isFullscreenable(); |
223 | } else if (role == IsFullscreen) { |
224 | return window->isFullscreen(); |
225 | } else if (role == IsMaximizable) { |
226 | return window->isMaximizeable(); |
227 | } else if (role == IsMaximized) { |
228 | return window->isMaximized(); |
229 | } else if (role == IsMinimizable) { |
230 | return window->isMinimizeable(); |
231 | } else if (role == IsMinimized) { |
232 | return window->isMinimized(); |
233 | } else if (role == IsKeepAbove) { |
234 | return window->isKeepAbove(); |
235 | } else if (role == IsKeepBelow) { |
236 | return window->isKeepBelow(); |
237 | } else if (role == IsOnAllDesktops) { |
238 | return window->isOnAllDesktops(); |
239 | } else if (role == IsDemandingAttention) { |
240 | return window->isDemandingAttention(); |
241 | } else if (role == SkipTaskbar) { |
242 | return window->skipTaskbar(); |
243 | } else if (role == SkipSwitcher) { |
244 | return window->skipSwitcher(); |
245 | } else if (role == IsShadeable) { |
246 | return window->isShadeable(); |
247 | } else if (role == IsShaded) { |
248 | return window->isShaded(); |
249 | } else if (role == IsMovable) { |
250 | return window->isMovable(); |
251 | } else if (role == IsResizable) { |
252 | return window->isResizable(); |
253 | } else if (role == IsVirtualDesktopChangeable) { |
254 | return window->isVirtualDesktopChangeable(); |
255 | } else if (role == IsCloseable) { |
256 | return window->isCloseable(); |
257 | } else if (role == Geometry) { |
258 | return window->geometry(); |
259 | } else if (role == VirtualDesktops) { |
260 | return window->plasmaVirtualDesktops(); |
261 | } else if (role == Uuid) { |
262 | return window->uuid(); |
263 | } |
264 | |
265 | return QVariant(); |
266 | } |
267 | QMap<int, QVariant> PlasmaWindowModel::itemData(const QModelIndex &index) const |
268 | { |
269 | QMap<int, QVariant> ret = QAbstractItemModel::itemData(index); |
270 | for (int role = AppId; role < LastRole; ++role) { |
271 | ret.insert(key: role, value: data(index, role)); |
272 | } |
273 | return ret; |
274 | } |
275 | |
276 | int PlasmaWindowModel::rowCount(const QModelIndex &parent) const |
277 | { |
278 | return parent.isValid() ? 0 : d->windows.count(); |
279 | } |
280 | |
281 | QModelIndex PlasmaWindowModel::index(int row, int column, const QModelIndex &parent) const |
282 | { |
283 | return hasIndex(row, column, parent) ? createIndex(arow: row, acolumn: column, adata: d->windows.at(i: row)) : QModelIndex(); |
284 | } |
285 | |
286 | Q_INVOKABLE void PlasmaWindowModel::requestActivate(int row) |
287 | { |
288 | if (row >= 0 && row < d->windows.count()) { |
289 | d->windows.at(i: row)->requestActivate(); |
290 | } |
291 | } |
292 | |
293 | Q_INVOKABLE void PlasmaWindowModel::requestClose(int row) |
294 | { |
295 | if (row >= 0 && row < d->windows.count()) { |
296 | d->windows.at(i: row)->requestClose(); |
297 | } |
298 | } |
299 | |
300 | Q_INVOKABLE void PlasmaWindowModel::requestMove(int row) |
301 | { |
302 | if (row >= 0 && row < d->windows.count()) { |
303 | d->windows.at(i: row)->requestMove(); |
304 | } |
305 | } |
306 | |
307 | Q_INVOKABLE void PlasmaWindowModel::requestResize(int row) |
308 | { |
309 | if (row >= 0 && row < d->windows.count()) { |
310 | d->windows.at(i: row)->requestResize(); |
311 | } |
312 | } |
313 | |
314 | Q_INVOKABLE void PlasmaWindowModel::requestEnterVirtualDesktop(int row, const QString &id) |
315 | { |
316 | if (row >= 0 && row < d->windows.count()) { |
317 | d->windows.at(i: row)->requestEnterVirtualDesktop(id); |
318 | } |
319 | } |
320 | |
321 | Q_INVOKABLE void PlasmaWindowModel::requestToggleKeepAbove(int row) |
322 | { |
323 | if (row >= 0 && row < d->windows.count()) { |
324 | d->windows.at(i: row)->requestToggleKeepAbove(); |
325 | } |
326 | } |
327 | |
328 | Q_INVOKABLE void PlasmaWindowModel::requestToggleKeepBelow(int row) |
329 | { |
330 | if (row >= 0 && row < d->windows.count()) { |
331 | d->windows.at(i: row)->requestToggleKeepBelow(); |
332 | } |
333 | } |
334 | |
335 | Q_INVOKABLE void PlasmaWindowModel::requestToggleMinimized(int row) |
336 | { |
337 | if (row >= 0 && row < d->windows.count()) { |
338 | d->windows.at(i: row)->requestToggleMinimized(); |
339 | } |
340 | } |
341 | |
342 | Q_INVOKABLE void PlasmaWindowModel::requestToggleMaximized(int row) |
343 | { |
344 | if (row >= 0 && row < d->windows.count()) { |
345 | d->windows.at(i: row)->requestToggleMaximized(); |
346 | } |
347 | } |
348 | |
349 | Q_INVOKABLE void PlasmaWindowModel::requestToggleFullscreen(int row) |
350 | { |
351 | if (row >= 0 && row < d->windows.count()) { |
352 | d->windows.at(i: row)->requestToggleFullscreen(); |
353 | } |
354 | } |
355 | |
356 | Q_INVOKABLE void PlasmaWindowModel::setMinimizedGeometry(int row, Surface *panel, const QRect &geom) |
357 | { |
358 | if (row >= 0 && row < d->windows.count()) { |
359 | d->windows.at(i: row)->setMinimizedGeometry(panel, geom); |
360 | } |
361 | } |
362 | |
363 | Q_INVOKABLE void PlasmaWindowModel::requestToggleShaded(int row) |
364 | { |
365 | if (row >= 0 && row < d->windows.count()) { |
366 | d->windows.at(i: row)->requestToggleShaded(); |
367 | } |
368 | } |
369 | |
370 | } |
371 | } |
372 | |
373 | #include "moc_plasmawindowmodel.cpp" |
374 | |