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 "plasmoid/containmentitem.h"
10
11#include <KPackage/Package>
12#include <QDebug>
13#include <QQmlContext>
14#include <QQmlEngine>
15#include <QQuickItem>
16#include <QScreen>
17#include <QTimer>
18
19namespace PlasmaQuick
20{
21class ContainmentViewPrivate
22{
23public:
24 ContainmentViewPrivate(Plasma::Corona *corona, ContainmentView *view);
25 ~ContainmentViewPrivate();
26
27 void setContainment(Plasma::Containment *cont);
28 Plasma::Types::FormFactor formFactor() const;
29 Plasma::Types::Location location() const;
30 void showConfigurationInterface(Plasma::Applet *applet);
31 void updateDestroyed(bool destroyed);
32 /**
33 * Reconnects the relevant signals after a screen change
34 **/
35 void reactToScreenChange();
36
37 ContainmentView *q;
38 friend class ContainmentView;
39 Plasma::Corona *corona;
40 QScreen *lastScreen;
42 QPointer<ConfigView> configContainmentView;
43};
44
45ContainmentViewPrivate::ContainmentViewPrivate(Plasma::Corona *cor, ContainmentView *view)
46 : q(view)
47 , corona(cor)
48{
49}
50
51ContainmentViewPrivate::~ContainmentViewPrivate()
52{
53}
54
55void ContainmentViewPrivate::setContainment(Plasma::Containment *cont)
56{
57 if (containment == cont) {
58 return;
59 }
60
62 Plasma::Types::FormFactor oldForm = formFactor();
63
64 if (containment) {
65 QObject::disconnect(containment, nullptr, q, nullptr);
66 QObject *oldGraphicObject = AppletQuickItem::itemForApplet(containment);
67 if (auto item = qobject_cast<QQuickItem *>(oldGraphicObject)) {
68 // TODO: delete the item when needed instead of just hiding, but there are quite a lot of cornercases to manage beforehand
69 item->setVisible(false);
70 }
71 containment->reactToScreenChange();
72 }
73
74 containment = cont;
75
76 if (oldLoc != location()) {
77 Q_EMIT q->locationChanged(location());
78 }
79 if (oldForm != formFactor()) {
80 Q_EMIT q->formFactorChanged(formFactor());
81 }
82
83 Q_EMIT q->containmentChanged();
84
85 // we are QuickViewSharedEngine::SizeRootObjectToView, but that's not enough, as
86 // the root object isn't immediately resized (done at the resizeEvent handler).
87 // by resizing it just before restoring the containment, it removes a chain of resizes at startup
88 if (q->rootObject()) {
89 q->rootObject()->setSize(q->size());
90 }
91 if (cont) {
92 cont->reactToScreenChange();
93 QObject::connect(cont, &Plasma::Containment::locationChanged, q, &ContainmentView::locationChanged);
94 QObject::connect(cont, &Plasma::Containment::formFactorChanged, q, &ContainmentView::formFactorChanged);
95 QObject::connect(cont, &Plasma::Containment::configureRequested, q, &ContainmentView::showConfigurationInterface);
96 QObject::connect(cont, SIGNAL(destroyedChanged(bool)), q, SLOT(updateDestroyed(bool)));
97
98 // Panels are created invisible and the code below ensures they are only
99 // shown once their contents have settled to avoid visual glitches on startup
100 if (cont->containmentType() == Plasma::Containment::Type::Panel || cont->containmentType() == Plasma::Containment::Type::CustomPanel) {
101 QObject::connect(cont, &Plasma::Containment::uiReadyChanged, q, [this, cont](bool ready) {
102 if (ready && !cont->destroyed()) {
103 q->setVisible(true);
104 }
105 });
106
107 q->setVisible(!cont->destroyed() && cont->isUiReady());
108 }
109 } else {
110 return;
111 }
112
113 QQuickItem *graphicObject = AppletQuickItem::itemForApplet(containment);
114
115 if (graphicObject) {
116 // qDebug() << "using as graphic containment" << graphicObject << containment.data();
117
118 graphicObject->setFocus(true);
119 // by resizing before adding, it will avoid some resizes in most cases
120 graphicObject->setSize(q->size());
121 graphicObject->setParentItem(q->rootObject());
122 if (q->rootObject()) {
123 q->rootObject()->setProperty("containment", QVariant::fromValue(graphicObject));
124 QObject *wpGraphicObject = containment->property("wallpaperGraphicsObject").value<QObject *>();
125 if (wpGraphicObject) {
126 q->rootObject()->setProperty("wallpaper", QVariant::fromValue(wpGraphicObject));
127 }
128 } else {
129 qWarning() << "Could not set containment property on rootObject";
130 }
131 } else {
132 qWarning() << "Containment graphic object not valid";
133 }
134}
135
136Plasma::Types::Location ContainmentViewPrivate::location() const
137{
138 if (!containment) {
140 }
141 return containment->location();
142}
143
144Plasma::Types::FormFactor ContainmentViewPrivate::formFactor() const
145{
146 if (!containment) {
148 }
149 return containment->formFactor();
150}
151
152void ContainmentViewPrivate::showConfigurationInterface(Plasma::Applet *applet)
153{
154 if (configContainmentView) {
155 if (configContainmentView->applet() != applet) {
156 configContainmentView->hide();
157 configContainmentView->deleteLater();
158 } else {
159 configContainmentView->raise();
160 configContainmentView->requestActivate();
161 return;
162 }
163 }
164
165 if (!applet || !applet->containment()) {
166 return;
167 }
168
169 configContainmentView = new ConfigView(applet);
170
171 configContainmentView->init();
172 configContainmentView->show();
173}
174
175void ContainmentViewPrivate::updateDestroyed(bool destroyed)
176{
177 q->setVisible(!destroyed);
178}
179
180void ContainmentViewPrivate::reactToScreenChange()
181{
182 QScreen *newScreen = q->screen();
183
184 if (newScreen == lastScreen) {
185 return;
186 }
187
188 QObject::disconnect(lastScreen, nullptr, q, nullptr);
189 lastScreen = newScreen;
191 &ContainmentView::screenGeometryChanged);
192 Q_EMIT q->screenGeometryChanged();
193}
194
195ContainmentView::ContainmentView(Plasma::Corona *corona, QWindow *parent)
196 : PlasmaQuick::QuickViewSharedEngine(parent)
197 , d(new ContainmentViewPrivate(corona, this))
198{
199 setColor(Qt::transparent);
200
201 d->lastScreen = screen();
202 QObject::connect(d->lastScreen, &QScreen::geometryChanged, this,
203 &ContainmentView::screenGeometryChanged);
204 QObject::connect(this, &ContainmentView::screenChanged, this,
205 [this]() {
206 d->reactToScreenChange();
207 });
208
209 if (corona->kPackage().isValid()) {
210 const auto info = corona->kPackage().metadata();
211 if (info.isValid()) {
212 setTranslationDomain(QStringLiteral("plasma_shell_") + info.pluginId());
213 } else {
214 qWarning() << "Invalid corona package metadata";
215 }
216 } else {
217 qWarning() << "Invalid home screen package";
218 }
219
220 setResizeMode(ContainmentView::SizeRootObjectToView);
221}
222
223ContainmentView::~ContainmentView()
224{
225 delete d;
226}
227
228void ContainmentView::destroy()
229{
230 // it will hide and deallocate the window so that no visibility or geometry
231 // changes will be emitted during the destructor, avoiding potential crash
232 // situations
234
235 // TODO: do we need a version which does not create?
236 QQuickItem *graphicObject = AppletQuickItem::itemForApplet(d->containment);
237 if (auto item = qobject_cast<QQuickItem *>(graphicObject)) {
238 item->setVisible(false);
239 item->setParentItem(nullptr); // First, remove the item from the view
240 }
241 deleteLater(); // delete the view
242}
243
244Plasma::Corona *ContainmentView::corona() const
245{
246 return d->corona;
247}
248
249KConfigGroup ContainmentView::config() const
250{
251 if (!containment()) {
252 return KConfigGroup();
253 }
254 KConfigGroup views(KSharedConfig::openConfig(), QStringLiteral("PlasmaContainmentViews"));
255 return KConfigGroup(&views, QString::number(containment()->lastScreen()));
256}
257
258void ContainmentView::setContainment(Plasma::Containment *cont)
259{
260 d->setContainment(cont);
261}
262
263Plasma::Containment *ContainmentView::containment() const
264{
265 return d->containment;
266}
267
268void ContainmentView::setLocation(Plasma::Types::Location location)
269{
270 d->containment->setLocation(location);
271}
272
273Plasma::Types::Location ContainmentView::location() const
274{
275 return d->location();
276}
277
278Plasma::Types::FormFactor ContainmentView::formFactor() const
279{
280 return d->formFactor();
281}
282
283QRectF ContainmentView::screenGeometry()
284{
285 return screen()->geometry();
286}
287
288void ContainmentView::showConfigurationInterface(Plasma::Applet *applet)
289{
290 d->showConfigurationInterface(applet);
291}
292
293}
294
295#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-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:34:35 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.