File indexing completed on 2024-05-12 05:46:37
0001 /* 0002 * Copyright 2013 Marco Martin <mart@kde.org> 0003 * 0004 * This program is free software; you can redistribute it and/or modify 0005 * it under the terms of the GNU General Public License as published by 0006 * the Free Software Foundation; either version 2 of the License, or 0007 * (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0017 */ 0018 0019 #include "view.h" 0020 #include "configview.h" 0021 0022 #include <QDebug> 0023 #include <QQuickItem> 0024 #include <QQmlContext> 0025 #include <QTimer> 0026 #include <QScreen> 0027 #include <QQmlEngine> 0028 0029 #include "plasma/pluginloader.h" 0030 #include <packageurlinterceptor.h> 0031 #include <kdeclarative/kdeclarative.h> 0032 0033 namespace PlasmaQuick 0034 { 0035 0036 class ViewPrivate 0037 { 0038 public: 0039 0040 ViewPrivate(Plasma::Corona *corona, View *view); 0041 ~ViewPrivate(); 0042 0043 void setContainment(Plasma::Containment *cont); 0044 Plasma::Types::FormFactor formFactor() const; 0045 Plasma::Types::Location location() const; 0046 void showConfigurationInterface(Plasma::Applet *applet); 0047 void updateDestroyed(bool destroyed); 0048 0049 View *q; 0050 friend class View; 0051 Plasma::Corona *corona; 0052 QPointer<Plasma::Containment> containment; 0053 QPointer<ConfigView> configView; 0054 }; 0055 0056 ViewPrivate::ViewPrivate(Plasma::Corona *cor, View *view) 0057 : q(view), 0058 corona(cor) 0059 { 0060 } 0061 0062 ViewPrivate::~ViewPrivate() 0063 { 0064 } 0065 0066 void ViewPrivate::setContainment(Plasma::Containment *cont) 0067 { 0068 if (containment == cont) { 0069 return; 0070 } 0071 0072 Plasma::Types::Location oldLoc = location(); 0073 Plasma::Types::FormFactor oldForm = formFactor(); 0074 0075 if (containment) { 0076 QObject::disconnect(containment, nullptr, q, nullptr); 0077 QObject *oldGraphicObject = containment->property("_plasma_graphicObject").value<QObject *>(); 0078 if (oldGraphicObject) { 0079 // qDebug() << "Old graphics Object:" << oldGraphicObject << "Old containment" << containment.data(); 0080 //make sure the graphic object won't die with us 0081 //FIXME:we need a way to reparent to *NO* graphics item, but this makes Qt crash 0082 oldGraphicObject->setParent(containment); 0083 } 0084 containment->reactToScreenChange(); 0085 } 0086 0087 containment = cont; 0088 0089 if (oldLoc != location()) { 0090 emit q->locationChanged(location()); 0091 } 0092 if (oldForm != formFactor()) { 0093 emit q->formFactorChanged(formFactor()); 0094 } 0095 0096 emit q->containmentChanged(); 0097 0098 if (cont) { 0099 cont->reactToScreenChange(); 0100 QObject::connect(cont, &Plasma::Containment::locationChanged, 0101 q, &View::locationChanged); 0102 QObject::connect(cont, &Plasma::Containment::formFactorChanged, 0103 q, &View::formFactorChanged); 0104 QObject::connect(cont, &Plasma::Containment::configureRequested, 0105 q, &View::showConfigurationInterface); 0106 QObject::connect(cont, SIGNAL(destroyedChanged(bool)), 0107 q, SLOT(updateDestroyed(bool))); 0108 if (cont->containmentType() == Plasma::Types::PanelContainment || 0109 cont->containmentType() == Plasma::Types::CustomPanelContainment) { 0110 q->setVisible(!cont->destroyed() && cont->isUiReady()); 0111 } 0112 } else { 0113 return; 0114 } 0115 0116 QQuickItem *graphicObject = qobject_cast<QQuickItem *>(containment->property("_plasma_graphicObject").value<QObject *>()); 0117 0118 if (graphicObject) { 0119 // qDebug() << "using as graphic containment" << graphicObject << containment.data(); 0120 0121 //by resizing before adding, it will avoid some resizes in most cases 0122 graphicObject->setSize(q->size()); 0123 graphicObject->setParentItem(q->rootObject()); 0124 if (q->rootObject()) { 0125 q->rootObject()->setProperty("containment", QVariant::fromValue(graphicObject)); 0126 QObject *wpGraphicObject = containment->property("wallpaperGraphicsObject").value<QObject *>(); 0127 if (wpGraphicObject) { 0128 q->rootObject()->setProperty("wallpaper", QVariant::fromValue(wpGraphicObject)); 0129 } 0130 } else { 0131 qWarning() << "Could not set containment property on rootObject"; 0132 } 0133 } else { 0134 qWarning() << "Containment graphic object not valid"; 0135 } 0136 } 0137 0138 Plasma::Types::Location ViewPrivate::location() const 0139 { 0140 if (!containment) { 0141 return Plasma::Types::Desktop; 0142 } 0143 return containment->location(); 0144 } 0145 0146 Plasma::Types::FormFactor ViewPrivate::formFactor() const 0147 { 0148 if (!containment) { 0149 return Plasma::Types::Planar; 0150 } 0151 return containment->formFactor(); 0152 } 0153 0154 void ViewPrivate::showConfigurationInterface(Plasma::Applet *applet) 0155 { 0156 if (configView) { 0157 if (configView->applet() != applet) { 0158 configView->hide(); 0159 configView->deleteLater(); 0160 } else { 0161 configView->raise(); 0162 configView->requestActivate(); 0163 return; 0164 } 0165 } 0166 0167 if (!applet || !applet->containment()) { 0168 return; 0169 } 0170 0171 configView = new ConfigView(applet); 0172 0173 configView->init(); 0174 configView->show(); 0175 } 0176 0177 void ViewPrivate::updateDestroyed(bool destroyed) 0178 { 0179 q->setVisible(!destroyed); 0180 } 0181 0182 View::View(Plasma::Corona *corona, QWindow *parent) 0183 : QQuickView(parent), 0184 d(new ViewPrivate(corona, this)) 0185 { 0186 setColor(Qt::transparent); 0187 0188 QObject::connect(screen(), &QScreen::geometryChanged, 0189 this, &View::screenGeometryChanged); 0190 0191 const auto pkg = corona->kPackage(); 0192 if (pkg.isValid()) { 0193 PackageUrlInterceptor *interceptor = new PackageUrlInterceptor(engine(), pkg); 0194 interceptor->setForcePlasmaStyle(true); 0195 engine()->setUrlInterceptor(interceptor); 0196 0197 KDeclarative::KDeclarative kdeclarative; 0198 kdeclarative.setDeclarativeEngine(engine()); 0199 //binds things like kconfig and icons 0200 kdeclarative.setTranslationDomain(QStringLiteral("plasma_shell_") + pkg.metadata().pluginId()); 0201 kdeclarative.setupBindings(); 0202 } else { 0203 qWarning() << "Invalid home screen package"; 0204 } 0205 0206 //Force QtQuickControls to use the "Plasma" style for this engine. 0207 //this way is possible to mix QtQuickControls and plasma components in applets 0208 //while still having the desktop style in configuration dialogs 0209 QQmlComponent c(engine()); 0210 c.setData("import QtQuick 2.1\n\ 0211 import QtQuick.Controls 1.0\n\ 0212 import QtQuick.Controls.Private 1.0\n \ 0213 Item {\ 0214 Component.onCompleted: {\ 0215 Settings.styleName = \"Plasma\";\ 0216 }\ 0217 }", QUrl()); 0218 QObject *o = c.create(); 0219 o->deleteLater(); 0220 0221 setResizeMode(View::SizeRootObjectToView); 0222 } 0223 0224 View::~View() 0225 { 0226 delete d; 0227 } 0228 0229 Plasma::Corona *View::corona() const 0230 { 0231 return d->corona; 0232 } 0233 0234 KConfigGroup View::config() const 0235 { 0236 if (!containment()) { 0237 return KConfigGroup(); 0238 } 0239 KConfigGroup views(KSharedConfig::openConfig(), "PlasmaViews"); 0240 return KConfigGroup(&views, QString::number(containment()->screen())); 0241 } 0242 0243 void View::setContainment(Plasma::Containment *cont) 0244 { 0245 d->setContainment(cont); 0246 } 0247 0248 Plasma::Containment *View::containment() const 0249 { 0250 return d->containment; 0251 } 0252 0253 void View::setLocation(Plasma::Types::Location location) 0254 { 0255 d->containment->setLocation(location); 0256 } 0257 0258 Plasma::Types::Location View::location() const 0259 { 0260 return d->location(); 0261 } 0262 0263 Plasma::Types::FormFactor View::formFactor() const 0264 { 0265 return d->formFactor(); 0266 } 0267 0268 QRectF View::screenGeometry() 0269 { 0270 return screen()->geometry(); 0271 } 0272 0273 void View::showConfigurationInterface(Plasma::Applet *applet) 0274 { 0275 d->showConfigurationInterface(applet); 0276 } 0277 0278 } 0279 0280 #include "moc_view.cpp"