Libplasma

wallpaperitem.cpp
1/*
2 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "wallpaperitem.h"
8#include "appletcontext_p.h"
9
10#include "containmentitem.h"
11#include "sharedqmlengine.h"
12
13#include <KConfigLoader>
14#include <KConfigPropertyMap>
15#include <KDesktopFile>
16
17#include <QDebug>
18#include <QFile>
19#include <QQmlContext>
20#include <QQmlExpression>
21#include <QQmlProperty>
22
23#include <Plasma/Corona>
24#include <Plasma/PluginLoader>
25#include <kpackage/packageloader.h>
26#include <qabstractitemmodel.h>
27#include <qtmetamacros.h>
28
29#include "debug_p.h"
30
31WallpaperItem::WallpaperItem(QQuickItem *parent)
32 : QQuickItem(parent)
33{
34 // resize at the beginning to avoid as much resize events as possible
35 if (parent) {
36 setSize(QSizeF(parent->width(), parent->height()));
37 }
38}
39
40WallpaperItem::~WallpaperItem()
41{
42}
43
44void WallpaperItem::classBegin()
45{
47 PlasmaQuick::AppletContext *ac = qobject_cast<PlasmaQuick::AppletContext *>(QQmlEngine::contextForObject(this)->parentContext());
48 Q_ASSERT(ac);
49 m_containment = ac->applet()->containment();
50 m_wallpaperPlugin = m_containment->wallpaperPlugin();
51 m_qmlObject = ac->sharedQmlEngine();
52 m_qmlObject->setParent(this);
53
54 m_pkg = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Wallpaper"));
55 m_pkg.setPath(m_wallpaperPlugin);
56
57 if (configScheme()) {
58 m_configuration = new KConfigPropertyMap(configScheme(), this);
59 }
60
61 connect(m_containment->corona(), &Plasma::Corona::startupCompleted, this, &WallpaperItem::accentColorChanged);
62}
63
64void WallpaperItem::componentComplete()
65{
67
68 m_loading = false;
69 Q_EMIT isLoadingChanged();
70}
71
73{
74 auto filter = [&mimetype, &formFactor](const KPluginMetaData &md) -> bool {
75 if (!formFactor.isEmpty() && !md.value(u"X-Plasma-FormFactors").contains(formFactor)) {
76 return false;
77 }
78 return md.value(u"X-Plasma-DropMimeTypes", QStringList()).contains(mimetype);
79 };
80 return KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Wallpaper"), QString(), filter);
81}
82
83KPackage::Package WallpaperItem::kPackage() const
84{
85 return m_pkg;
86}
87
88QString WallpaperItem::pluginName() const
89{
90 return m_wallpaperPlugin;
91}
92
93KConfigPropertyMap *WallpaperItem::configuration() const
94{
95 return m_configuration;
96}
97
98KConfigLoader *WallpaperItem::configScheme()
99{
100 if (!m_configLoader) {
101 // FIXME: do we need "mainconfigxml" in wallpaper packagestructures?
102 const QString xmlPath = m_pkg.filePath("config", QStringLiteral("main.xml"));
103
104 KConfigGroup cfg = m_containment->config();
105 cfg = KConfigGroup(&cfg, QStringLiteral("Wallpaper"));
106 cfg = KConfigGroup(&cfg, m_wallpaperPlugin);
107
108 if (xmlPath.isEmpty()) {
109 m_configLoader = new KConfigLoader(cfg, nullptr, this);
110 } else {
111 QFile file(xmlPath);
112 m_configLoader = new KConfigLoader(cfg, &file, this);
113 }
114 }
115
116 return m_configLoader;
117}
118
119void WallpaperItem::requestOpenUrl(const QUrl &url)
120{
121 Q_EMIT openUrlRequested(url);
122}
123
125{
126 if (containmentItem->containment()->wallpaperPlugin().isEmpty()) {
127 return nullptr;
128 }
129 KPackage::Package pkg = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Wallpaper"));
130 pkg.setPath(containmentItem->containment()->wallpaperPlugin());
131 if (!pkg.isValid()) {
132 qWarning() << "Error loading the wallpaper, no valid package loaded";
133 return nullptr;
134 }
135
136 PlasmaQuick::SharedQmlEngine *qmlObject = new PlasmaQuick::SharedQmlEngine(containmentItem->containment());
137 qmlObject->setInitializationDelayed(true);
138
139 const QString rootPath = pkg.metadata().value(u"X-Plasma-RootPath");
140 if (!rootPath.isEmpty()) {
141 qmlObject->setTranslationDomain(QLatin1String("plasma_wallpaper_") + rootPath);
142 } else {
143 qmlObject->setTranslationDomain(QLatin1String("plasma_wallpaper_") + pkg.metadata().pluginId());
144 }
145
146 /*
147 * The initialization is delayed, so it's fine to setSource first.
148 * This also prevents many undefined wallpaper warnings caused by "wallpaper" being set
149 * when the old wallpaper plugin still exists.
150 */
151 qmlObject->setSource(pkg.fileUrl("mainscript"));
152 WallpaperItem *wallpaper = qobject_cast<WallpaperItem *>(qmlObject->rootObject());
153 if (!wallpaper) {
154 if (qmlObject->mainComponent() && qmlObject->mainComponent()->isError()) {
155 qWarning() << "Error loading the wallpaper" << qmlObject->mainComponent()->errors();
156 } else if (qmlObject->rootObject()) {
157 qWarning() << "Root item of wallpaper" << containmentItem->containment()->wallpaperPlugin() << "not a WallpaperItem instance, instead is"
158 << qmlObject->rootObject();
159 }
160 qmlObject->completeInitialization();
161 delete qmlObject->rootObject();
162 return nullptr;
163 }
164
165 if (!qEnvironmentVariableIntValue("PLASMA_NO_CONTEXTPROPERTIES")) {
166 qmlObject->rootContext()->setContextProperty(QStringLiteral("wallpaper"), wallpaper);
167 }
168
169 // initialize with our size to avoid as much resize events as possible
170 QVariantHash props;
171 props[QStringLiteral("parent")] = QVariant::fromValue(containmentItem);
172 props[QStringLiteral("width")] = containmentItem->width();
173 props[QStringLiteral("height")] = containmentItem->height();
174 qmlObject->completeInitialization(props);
175 return wallpaper;
176}
177
179{
180 return m_contextualActions;
181}
182
183QQmlListProperty<QAction> WallpaperItem::qmlContextualActions()
184{
185 return QQmlListProperty<QAction>(this,
186 nullptr,
187 WallpaperItem::contextualActions_append,
188 WallpaperItem::contextualActions_count,
189 WallpaperItem::contextualActions_at,
190 WallpaperItem::contextualActions_clear,
191 WallpaperItem::contextualActions_replace,
192 WallpaperItem::contextualActions_removeLast);
193}
194
195bool WallpaperItem::supportsMimetype(const QString &mimetype) const
196{
197 return m_pkg.metadata().value(u"X-Plasma-DropMimeTypes", QStringList()).contains(mimetype);
198}
199
200bool WallpaperItem::isLoading() const
201{
202 return m_loading;
203}
204
205QColor WallpaperItem::accentColor() const
206{
207 return m_accentColor.value_or(QColor(Qt::transparent));
208}
209
210void WallpaperItem::setAccentColor(const QColor &newColor)
211{
212 if (m_accentColor.has_value() && m_accentColor == newColor) {
213 return;
214 }
215
216 m_accentColor = newColor;
217 Q_EMIT accentColorChanged();
218}
219
220void WallpaperItem::resetAccentColor()
221{
222 if (!m_accentColor.has_value()) {
223 return;
224 }
225
226 m_accentColor.reset();
227 Q_EMIT accentColorChanged();
228}
229
230void WallpaperItem::contextualActions_append(QQmlListProperty<QAction> *prop, QAction *action)
231{
232 WallpaperItem *w = static_cast<WallpaperItem *>(prop->object);
233 w->m_contextualActions.append(action);
234 QObject::connect(action, &QObject::destroyed, w, [w, action]() {
235 w->m_contextualActions.removeAll(action);
236 Q_EMIT w->contextualActionsChanged(w->m_contextualActions);
237 });
238 Q_EMIT w->contextualActionsChanged(w->m_contextualActions);
239};
240
241qsizetype WallpaperItem::contextualActions_count(QQmlListProperty<QAction> *prop)
242{
243 WallpaperItem *w = static_cast<WallpaperItem *>(prop->object);
244 return w->m_contextualActions.count();
245}
246
247QAction *WallpaperItem::contextualActions_at(QQmlListProperty<QAction> *prop, qsizetype idx)
248{
249 WallpaperItem *w = static_cast<WallpaperItem *>(prop->object);
250 return w->m_contextualActions.value(idx);
251}
252
253void WallpaperItem::contextualActions_clear(QQmlListProperty<QAction> *prop)
254{
255 WallpaperItem *w = static_cast<WallpaperItem *>(prop->object);
256 w->m_contextualActions.clear();
257 Q_EMIT w->contextualActionsChanged(w->m_contextualActions);
258}
259
260void WallpaperItem::contextualActions_replace(QQmlListProperty<QAction> *prop, qsizetype idx, QAction *action)
261{
262 WallpaperItem *w = static_cast<WallpaperItem *>(prop->object);
263 w->m_contextualActions.replace(idx, action);
264 Q_EMIT w->contextualActionsChanged(w->m_contextualActions);
265}
266
267void WallpaperItem::contextualActions_removeLast(QQmlListProperty<QAction> *prop)
268{
269 WallpaperItem *w = static_cast<WallpaperItem *>(prop->object);
270 w->m_contextualActions.pop_back();
271 Q_EMIT w->contextualActionsChanged(w->m_contextualActions);
272}
273
274#include "moc_wallpaperitem.cpp"
This class is exposed to containments QML as the attached property Plasmoid.
QList< KPluginMetaData > findPackages(const QString &packageFormat, const QString &packageRoot=QString(), std::function< bool(const KPluginMetaData &)> filter=std::function< bool(const KPluginMetaData &)>())
Package loadPackage(const QString &packageFormat, const QString &packagePath=QString())
static PackageLoader * self()
void setPath(const QString &path)
QUrl fileUrl(const QByteArray &key, const QString &filename=QString()) const
bool isValid() const
QString filePath(const QByteArray &key, const QString &filename=QString()) const
KPluginMetaData metadata() const
QString pluginId() const
bool value(QStringView key, bool defaultValue) const
An object that instantiates an entire QML context, with its own declarative engine.
QQmlContext * rootContext() const
The components's creation context.
void setInitializationDelayed(const bool delay)
Sets whether the execution of the QML file has to be delayed later in the event loop.
void setSource(const QUrl &source)
Sets the path of the QML file to parse and execute.
QQmlComponent * mainComponent() const
void setTranslationDomain(const QString &translationDomain)
Call this method before calling setupBindings to install a translation domain for all i18n global fun...
void completeInitialization(const QVariantHash &initialProperties=QVariantHash())
Finishes the process of initialization.
KConfigGroup config() const
Returns the KConfigGroup to access the applets configuration.
Definition applet.cpp:189
Plasma::Containment * containment
The Containment managing this applet.
Definition applet.h:189
Plasma::Corona * corona
The corona for this contaiment.
Definition containment.h:59
void startupCompleted()
Emitted when the startup phase has been completed.
This class is exposed to wallpapers as the WallpaperItem root qml item.
QQmlListProperty< QAction > contextualActions
Actions to be added in the desktop context menu.
static WallpaperItem * loadWallpaper(ContainmentItem *ContainmentItem)
Instantiate the WallpaperItem for a given containment, using the proper plugin.
static QList< KPluginMetaData > listWallpaperMetadataForMimetype(const QString &mimetype, const QString &formFactor=QString())
Returns a list of all known wallpapers that can accept the given mimetype.
void append(QList< T > &&value)
void clear()
qsizetype count() const const
void pop_back()
qsizetype removeAll(const AT &t)
void replace(qsizetype i, parameter_type value)
T value(qsizetype i) const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
T qobject_cast(QObject *object)
void setParent(QObject *parent)
QList< QQmlError > errors() const const
bool isError() const const
void setContextProperty(const QString &name, QObject *value)
QQmlContext * contextForObject(const QObject *object)
virtual void classBegin() override
virtual void componentComplete() override
bool isEmpty() const const
transparent
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:10:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.