Libplasma

containmentview.cpp
1/*
2 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "containmentview.h"
8#include "configview.h"
9#include "debug_p.h"
10#include "plasmoid/containmentitem.h"
11
12#include <KPackage/Package>
13#include <QDebug>
14#include <QLoggingCategory>
15#include <QQmlContext>
16#include <QQmlEngine>
17#include <QQuickItem>
18#include <QScreen>
19#include <QTimer>
20
21namespace PlasmaQuick
22{
23class ContainmentViewPrivate
24{
25public:
26 ContainmentViewPrivate(Plasma::Corona *corona, ContainmentView *view);
27 ~ContainmentViewPrivate();
28
29 void setContainment(Plasma::Containment *cont);
30 Plasma::Types::FormFactor formFactor() const;
31 Plasma::Types::Location location() const;
32 void showConfigurationInterface(Plasma::Applet *applet);
33 void updateDestroyed(bool destroyed);
34 /**
35 * Reconnects the relevant signals after a screen change
36 **/
37 void reactToScreenChange();
38
39 ContainmentView *q;
40 friend class ContainmentView;
41 Plasma::Corona *corona;
42 QScreen *lastScreen;
43 QPointer<Plasma::Containment> containment;
44 QPointer<ConfigView> configContainmentView;
45};
46
47ContainmentViewPrivate::ContainmentViewPrivate(Plasma::Corona *cor, ContainmentView *view)
48 : q(view)
49 , corona(cor)
50{
51}
52
53ContainmentViewPrivate::~ContainmentViewPrivate()
54{
55}
56
57void ContainmentViewPrivate::setContainment(Plasma::Containment *cont)
58{
59 if (containment == cont) {
60 return;
61 }
62
64 Plasma::Types::FormFactor oldForm = formFactor();
65
66 if (containment) {
67 QObject::disconnect(containment, nullptr, q, nullptr);
68 QObject *oldGraphicObject = AppletQuickItem::itemForApplet(containment);
69 if (auto item = qobject_cast<QQuickItem *>(oldGraphicObject)) {
70 // TODO: delete the item when needed instead of just hiding, but there are quite a lot of cornercases to manage beforehand
71 item->setVisible(false);
72 }
73 containment->reactToScreenChange();
74 }
75
76 containment = cont;
77
78 if (oldLoc != location()) {
79 Q_EMIT q->locationChanged(location());
80 }
81 if (oldForm != formFactor()) {
82 Q_EMIT q->formFactorChanged(formFactor());
83 }
84
85 Q_EMIT q->containmentChanged();
86
87 // we are QuickViewSharedEngine::SizeRootObjectToView, but that's not enough, as
88 // the root object isn't immediately resized (done at the resizeEvent handler).
89 // by resizing it just before restoring the containment, it removes a chain of resizes at startup
90 if (q->rootObject()) {
91 q->rootObject()->setSize(q->size());
92 }
93 if (cont) {
94 cont->reactToScreenChange();
95 QObject::connect(cont, &Plasma::Containment::locationChanged, q, &ContainmentView::locationChanged);
96 QObject::connect(cont, &Plasma::Containment::formFactorChanged, q, &ContainmentView::formFactorChanged);
97 QObject::connect(cont, &Plasma::Containment::configureRequested, q, &ContainmentView::showConfigurationInterface);
98 QObject::connect(cont, SIGNAL(destroyedChanged(bool)), q, SLOT(updateDestroyed(bool)));
99
100 // Panels are created invisible and the code below ensures they are only
101 // shown once their contents have settled to avoid visual glitches on startup
102 if (cont->containmentType() == Plasma::Containment::Type::Panel || cont->containmentType() == Plasma::Containment::Type::CustomPanel) {
103 QObject::connect(cont, &Plasma::Containment::uiReadyChanged, q, [this, cont](bool ready) {
104 if (ready && !cont->destroyed()) {
105 q->setVisible(true);
106 }
107 });
108
109 q->setVisible(!cont->destroyed() && cont->isUiReady());
110 }
111 } else {
112 return;
113 }
114
115 QQuickItem *graphicObject = AppletQuickItem::itemForApplet(containment);
116
117 if (graphicObject) {
118 // qDebug() << "using as graphic containment" << graphicObject << containment.data();
119
120 graphicObject->setFocus(true);
121 // by resizing before adding, it will avoid some resizes in most cases
122 graphicObject->setSize(q->size());
123 graphicObject->setParentItem(q->rootObject());
124 if (q->rootObject()) {
125 q->rootObject()->setProperty("containment", QVariant::fromValue(graphicObject));
126 QObject *wpGraphicObject = containment->property("wallpaperGraphicsObject").value<QObject *>();
127 if (wpGraphicObject) {
128 q->rootObject()->setProperty("wallpaper", QVariant::fromValue(wpGraphicObject));
129 }
130 } else {
131 qCWarning(LOG_PLASMAQUICK) << "Could not set containment property on rootObject";
132 }
133 } else {
134 qCWarning(LOG_PLASMAQUICK) << "Containment graphic object not valid";
135 }
136}
137
138Plasma::Types::Location ContainmentViewPrivate::location() const
139{
140 if (!containment) {
142 }
143 return containment->location();
144}
145
146Plasma::Types::FormFactor ContainmentViewPrivate::formFactor() const
147{
148 if (!containment) {
150 }
151 return containment->formFactor();
152}
153
154void ContainmentViewPrivate::showConfigurationInterface(Plasma::Applet *applet)
155{
156 if (configContainmentView) {
157 if (configContainmentView->applet() != applet) {
158 configContainmentView->hide();
159 configContainmentView->deleteLater();
160 } else {
161 configContainmentView->raise();
162 configContainmentView->requestActivate();
163 return;
164 }
165 }
166
167 if (!applet || !applet->containment()) {
168 return;
169 }
170
171 configContainmentView = new ConfigView(applet);
172
173 configContainmentView->init();
174 configContainmentView->show();
175}
176
177void ContainmentViewPrivate::updateDestroyed(bool destroyed)
178{
179 q->setVisible(!destroyed);
180}
181
182void ContainmentViewPrivate::reactToScreenChange()
183{
184 QScreen *newScreen = q->screen();
185
186 if (newScreen == lastScreen) {
187 return;
188 }
189
190 QObject::disconnect(lastScreen, nullptr, q, nullptr);
191 lastScreen = newScreen;
193 &ContainmentView::screenGeometryChanged);
194 Q_EMIT q->screenGeometryChanged();
195}
196
197ContainmentView::ContainmentView(Plasma::Corona *corona, QWindow *parent)
198 : PlasmaQuick::QuickViewSharedEngine(parent)
199 , d(new ContainmentViewPrivate(corona, this))
200{
201 setColor(Qt::transparent);
202
203 d->lastScreen = screen();
204 QObject::connect(d->lastScreen, &QScreen::geometryChanged, this,
205 &ContainmentView::screenGeometryChanged);
206 QObject::connect(this, &ContainmentView::screenChanged, this,
207 [this]() {
208 d->reactToScreenChange();
209 });
210
211 if (corona->kPackage().isValid()) {
212 const auto info = corona->kPackage().metadata();
213 if (info.isValid()) {
214 setTranslationDomain(QStringLiteral("plasma_shell_") + info.pluginId());
215 } else {
216 qCWarning(LOG_PLASMAQUICK) << "Invalid corona package metadata";
217 }
218 } else {
219 qCWarning(LOG_PLASMAQUICK) << "Invalid home screen package";
220 }
221
222 setResizeMode(ContainmentView::SizeRootObjectToView);
223}
224
225ContainmentView::~ContainmentView()
226{
227 delete d;
228}
229
230void ContainmentView::destroy()
231{
232 // it will hide and deallocate the window so that no visibility or geometry
233 // changes will be emitted during the destructor, avoiding potential crash
234 // situations
236
237 // TODO: do we need a version which does not create?
238 QQuickItem *graphicObject = AppletQuickItem::itemForApplet(d->containment);
239 if (auto item = qobject_cast<QQuickItem *>(graphicObject)) {
240 item->setVisible(false);
241 item->setParentItem(nullptr); // First, remove the item from the view
242 }
243 deleteLater(); // delete the view
244}
245
246Plasma::Corona *ContainmentView::corona() const
247{
248 return d->corona;
249}
250
251KConfigGroup ContainmentView::config() const
252{
253 if (!containment()) {
254 return KConfigGroup();
255 }
256 KConfigGroup views(KSharedConfig::openConfig(), QStringLiteral("PlasmaContainmentViews"));
257 return KConfigGroup(&views, QString::number(containment()->lastScreen()));
258}
259
260void ContainmentView::setContainment(Plasma::Containment *cont)
261{
262 d->setContainment(cont);
263}
264
265Plasma::Containment *ContainmentView::containment() const
266{
267 return d->containment;
268}
269
270void ContainmentView::setLocation(Plasma::Types::Location location)
271{
272 d->containment->setLocation(location);
273}
274
275Plasma::Types::Location ContainmentView::location() const
276{
277 return d->location();
278}
279
280Plasma::Types::FormFactor ContainmentView::formFactor() const
281{
282 return d->formFactor();
283}
284
285QRectF ContainmentView::screenGeometry()
286{
287 return screen()->geometry();
288}
289
290void ContainmentView::showConfigurationInterface(Plasma::Applet *applet)
291{
292 d->showConfigurationInterface(applet);
293}
294
295}
296
297#include "moc_containmentview.cpp"
bool isValid() const
KPluginMetaData metadata() const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
The base Applet class.
Definition applet.h:64
Plasma::Containment * containment
The Containment managing this applet.
Definition applet.h:189
The base class for plugins that provide backgrounds and applet grouping containers.
Definition containment.h:47
void uiReadyChanged(bool uiReady)
Emitted when the ui has been fully loaded and is fully working.
void configureRequested(Plasma::Applet *applet)
Emitted when the user wants to configure/change the containment, or an applet inside it.
void formFactorChanged(Plasma::Types::FormFactor formFactor)
Emitted when the formFactor has changed.
@ Panel
A desktop panel.
@ CustomPanel
A customized desktop panel.
void locationChanged(Plasma::Types::Location location)
Emitted when the location has changed.
void setLocation(Plasma::Types::Location location)
Informs the Corona as to what position it is in.
A bookkeeping Scene for Plasma::Applets.
Definition corona.h:28
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
Definition plasma.h:81
@ Desktop
On the planar desktop layer, extending across the full screen from edge to edge.
Definition plasma.h:84
FormFactor
The FormFactor enumeration describes how a Plasma::Applet should arrange itself.
Definition plasma.h:40
@ Planar
The applet lives in a plane and has two degrees of freedom to grow.
Definition plasma.h:41
QVariant location(const QVariant &res)
KGuiItem cont()
The EdgeEventForwarder class This class forwards edge events to be replayed within the given margin T...
Definition action.h:20
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QVariant property(const char *name) const const
void setFocus(bool focus, Qt::FocusReason reason)
void setParentItem(QQuickItem *parent)
void setSize(const QSizeF &size)
void geometryChanged(const QRect &geometry)
QString number(double n, char format, int precision)
transparent
QVariant fromValue(T &&value)
T value() const const
void destroy()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:56:56 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.