KWin
Loading...
Searching...
No Matches
layoutpreview.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2009, 2011 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9// own
10#include "layoutpreview.h"
11
12#include <KApplicationTrader>
13#include <KConfigGroup>
14#include <KDesktopFile>
15#include <KLocalizedString>
16#include <QApplication>
17#include <QDebug>
18#include <QQmlContext>
19#include <QQmlEngine>
20#include <QScreen>
21#include <QStandardPaths>
22
23namespace KWin
24{
25namespace TabBox
26{
27
28LayoutPreview::LayoutPreview(const QString &path, bool showDesktopThumbnail, QObject *parent)
29 : QObject(parent)
30 , m_item(nullptr)
31{
32 QQmlEngine *engine = new QQmlEngine(this);
33 QQmlComponent *component = new QQmlComponent(engine, this);
34 qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 3, 0, "WindowThumbnail");
35 qmlRegisterType<SwitcherItem>("org.kde.kwin", 3, 0, "TabBoxSwitcher");
36 qmlRegisterType<DesktopBackground>("org.kde.kwin", 3, 0, "DesktopBackground");
37 qmlRegisterAnonymousType<QAbstractItemModel>("org.kde.kwin", 3);
38 component->loadUrl(QUrl::fromLocalFile(path));
39 if (component->isError()) {
40 qDebug() << component->errorString();
41 }
42 QObject *item = component->create();
43 auto findSwitcher = [item]() -> SwitcherItem * {
44 if (!item) {
45 return nullptr;
46 }
47 if (SwitcherItem *i = qobject_cast<SwitcherItem *>(item)) {
48 return i;
49 } else if (QQuickWindow *w = qobject_cast<QQuickWindow *>(item)) {
50 return w->contentItem()->findChild<SwitcherItem *>();
51 }
52 return item->findChild<SwitcherItem *>();
53 };
54 if (SwitcherItem *switcher = findSwitcher()) {
55 m_item = switcher;
56 static_cast<ExampleClientModel *>(switcher->model())->showDesktopThumbnail(showDesktopThumbnail);
57 switcher->setVisible(true);
58 }
59 auto findWindow = [item]() -> QQuickWindow * {
60 if (!item) {
61 return nullptr;
62 }
63 if (QQuickWindow *w = qobject_cast<QQuickWindow *>(item)) {
64 return w;
65 }
66 return item->findChild<QQuickWindow *>();
67 };
68 if (QQuickWindow *w = findWindow()) {
69 w->setKeyboardGrabEnabled(true);
70 w->installEventFilter(this);
71 }
72}
73
77
78bool LayoutPreview::eventFilter(QObject *object, QEvent *event)
79{
80 if (event->type() == QEvent::KeyPress) {
81 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
82 if (keyEvent->key() == Qt::Key_Escape || keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Space) {
83 object->deleteLater();
84 deleteLater();
85 }
86 if (m_item && keyEvent->key() == Qt::Key_Tab) {
87 m_item->incrementIndex();
88 }
89 if (m_item && keyEvent->key() == Qt::Key_Backtab) {
90 m_item->decrementIndex();
91 }
92 } else if (event->type() == QEvent::FocusOut) {
93 object->deleteLater();
94 deleteLater();
95 }
96 return QObject::eventFilter(object, event);
97}
98
100 : QAbstractListModel(parent)
101{
102 init();
103}
104
108
109void ExampleClientModel::init()
110{
111 if (const auto s = KApplicationTrader::preferredService(QStringLiteral("inode/directory"))) {
112 m_thumbnails << ThumbnailInfo{WindowThumbnailItem::Dolphin, s->name(), s->icon()};
113 }
114 if (const auto s = KApplicationTrader::preferredService(QStringLiteral("text/html"))) {
115 m_thumbnails << ThumbnailInfo{WindowThumbnailItem::Konqueror, s->name(), s->icon()};
116 }
117 if (const auto s = KApplicationTrader::preferredService(QStringLiteral("message/rfc822"))) {
118 m_thumbnails << ThumbnailInfo{WindowThumbnailItem::KMail, s->name(), s->icon()};
119 }
120 if (const auto s = KService::serviceByDesktopName(QStringLiteral("kdesystemsettings"))) {
121 m_thumbnails << ThumbnailInfo{WindowThumbnailItem::Systemsettings, s->name(), s->icon()};
122 }
123}
124
126{
127 const ThumbnailInfo desktopThumbnail = ThumbnailInfo{WindowThumbnailItem::Desktop, i18n("Show Desktop"), QStringLiteral("desktop")};
128 const int desktopIndex = m_thumbnails.indexOf(desktopThumbnail);
129 if (showDesktop == (desktopIndex >= 0)) {
130 return;
131 }
132
133 Q_EMIT beginResetModel();
134 if (showDesktop) {
135 m_thumbnails << desktopThumbnail;
136 } else {
137 m_thumbnails.removeAt(desktopIndex);
138 }
139 Q_EMIT endResetModel();
140}
141
142QVariant ExampleClientModel::data(const QModelIndex &index, int role) const
143{
144 if (!index.isValid() || index.row() >= rowCount()) {
145 return QVariant();
146 }
147
148 const ThumbnailInfo &item = m_thumbnails.at(index.row());
149
150 switch (role) {
151 case Qt::DisplayRole:
152 case CaptionRole:
153 return item.caption;
154 case MinimizedRole:
155 return false;
156 case DesktopNameRole:
157 return i18nc("An example Desktop Name", "Desktop 1");
158 case IconRole:
159 return item.icon;
160 case WindowIdRole:
161 return item.wId;
162 case CloseableRole:
163 return item.wId != WindowThumbnailItem::Desktop;
164 }
165 return QVariant();
166}
167
169{
170 QString caption;
171 for (const auto &item : m_thumbnails) {
172 if (item.caption.size() > caption.size()) {
173 caption = item.caption;
174 }
175 }
176 return caption;
177}
178
179int ExampleClientModel::rowCount(const QModelIndex &parent) const
180{
181 return m_thumbnails.size();
182}
183
184QHash<int, QByteArray> ExampleClientModel::roleNames() const
185{
186 return {
187 {CaptionRole, QByteArrayLiteral("caption")},
188 {MinimizedRole, QByteArrayLiteral("minimized")},
189 {DesktopNameRole, QByteArrayLiteral("desktopName")},
190 {IconRole, QByteArrayLiteral("icon")},
191 {WindowIdRole, QByteArrayLiteral("windowId")},
192 {CloseableRole, QByteArrayLiteral("closeable")},
193 };
194}
195
197 : QObject(parent)
198 , m_model(new ExampleClientModel(this))
199 , m_item(nullptr)
200 , m_currentIndex(0)
201 , m_visible(false)
202{
203}
204
208
209void SwitcherItem::setVisible(bool visible)
210{
211 if (m_visible == visible) {
212 return;
213 }
214 m_visible = visible;
215 Q_EMIT visibleChanged();
216}
217
218void SwitcherItem::setItem(QObject *item)
219{
220 m_item = item;
221 Q_EMIT itemChanged();
222}
223
225{
226 if (m_currentIndex == index) {
227 return;
228 }
229 m_currentIndex = index;
230 Q_EMIT currentIndexChanged(m_currentIndex);
231}
232
234{
235 const QScreen *primaryScreen = qApp->primaryScreen();
236 return primaryScreen->geometry();
237}
238
240{
241 setCurrentIndex((m_currentIndex + 1) % m_model->rowCount());
242}
243
245{
246 int index = m_currentIndex - 1;
247 if (index < 0) {
248 index = m_model->rowCount() - 1;
249 }
250 setCurrentIndex(index);
251}
252
254 : WindowThumbnailItem(parent)
255{
257
258 connect(this, &QQuickItem::windowChanged, this, &DesktopBackground::stretchToScreen);
259 stretchToScreen();
260};
261
262void DesktopBackground::stretchToScreen()
263{
264 const QQuickWindow *w = window();
265 if (!w) {
266 return;
267 }
268 const QScreen *screen = w->screen();
269 if (!screen) {
270 return;
271 }
272 setImplicitSize(screen->size().width(), screen->size().height());
273};
274
275} // namespace KWin
276} // namespace TabBox
277
278#include "moc_layoutpreview.cpp"
DesktopBackground(QQuickItem *parent=nullptr)
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
ExampleClientModel(QObject *parent=nullptr)
void showDesktopThumbnail(bool showDesktop)
Q_INVOKABLE QString longestCaption() const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QHash< int, QByteArray > roleNames() const override
bool eventFilter(QObject *object, QEvent *event) override
LayoutPreview(const QString &path, bool showDesktopThumbnail=false, QObject *parent=nullptr)
void currentIndexChanged(int index)
void setVisible(bool visible)
void setItem(QObject *item)
SwitcherItem(QObject *parent=nullptr)
void setWId(qulonglong wId)