File indexing completed on 2024-04-28 05:34:20
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Giorgos Tsiapaliokas <terietor@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "view.h" 0008 0009 #include <QDBusInterface> 0010 #include <QDBusReply> 0011 #include <QDebug> 0012 #include <QFileDialog> 0013 #include <QQmlContext> 0014 #include <QQmlEngine> 0015 #include <QQuickItem> 0016 0017 #include <KDesktopFile> 0018 #include <KLocalizedString> 0019 0020 #include <KPackage/Package> 0021 #include <KPackage/PackageLoader> 0022 #include <Plasma/PluginLoader> 0023 #include <plasmaquick/appletquickitem.h> 0024 0025 class ViewerCorona : public Plasma::Corona 0026 { 0027 public: 0028 ViewerCorona() 0029 : Plasma::Corona() 0030 , m_view(nullptr) 0031 { 0032 } 0033 0034 void setView(View *view) 0035 { 0036 m_view = view; 0037 } 0038 0039 QRect screenGeometry(int id) const override 0040 { 0041 Q_UNUSED(id); 0042 if (m_view) { 0043 return m_view->geometry(); 0044 } else { 0045 return QRect(); 0046 } 0047 } 0048 0049 int screenForContainment(const Plasma::Containment *containment) const override 0050 { 0051 return 0; 0052 } 0053 0054 private: 0055 View *m_view; 0056 }; 0057 0058 View::View(ViewerCorona *cor, QWindow *parent) 0059 : PlasmaQuick::ContainmentView(cor, parent) 0060 { 0061 cor->setView(this); 0062 engine()->rootContext()->setContextProperty("desktop", this); 0063 setSource(QUrl::fromLocalFile(cor->kPackage().filePath("views", "Desktop.qml"))); 0064 } 0065 0066 View::~View() 0067 { 0068 } 0069 0070 void View::resizeEvent(QResizeEvent *event) 0071 { 0072 emit corona()->screenGeometryChanged(0); 0073 emit corona()->availableScreenRectChanged(0); 0074 emit corona()->availableScreenRegionChanged(0); 0075 PlasmaQuick::ContainmentView::resizeEvent(event); 0076 } 0077 0078 QString View::pluginFromPath(const QString &path) const 0079 { 0080 QDir dir(path); 0081 if (!dir.exists()) { 0082 return QString(); 0083 } 0084 0085 QString metadataPath = dir.absolutePath(); 0086 if (!QFile(metadataPath).exists()) { 0087 return QString(); 0088 } else { 0089 return metadataPath; 0090 } 0091 } 0092 0093 void View::addApplet(const QString &applet) 0094 { 0095 QString metadataPath = pluginFromPath(applet); 0096 0097 Plasma::Containment *c = containment(); 0098 0099 if (!c) { 0100 qCritical("Containment doesn't exist"); 0101 return; 0102 } 0103 0104 Plasma::Applet *a = nullptr; 0105 if (metadataPath.isEmpty()) { 0106 a = containment()->createApplet(applet); 0107 } else { 0108 a = Plasma::PluginLoader::self()->loadApplet(metadataPath); 0109 0110 // Load translations from KPackage files if bundled 0111 // TODO: what to do in KF6? 0112 /*const QString localePath = a->kPackage().filePath("translations"); 0113 if (!localePath.isEmpty()) { 0114 const QString localeDomain = QByteArray("plasma_applet_") + a->pluginMetaData().pluginId(); 0115 KLocalizedString::addDomainLocaleDir(localeDomain.toLatin1(), localePath); 0116 }*/ 0117 0118 containment()->addApplet(a); 0119 } 0120 0121 if (!a->pluginMetaData().isValid()) { 0122 // xgettext:no-c-format 0123 qCritical() << i18n("Applet %1 does not exist.", applet); 0124 return; 0125 } 0126 m_lastAppletName = applet; 0127 } 0128 0129 void View::addContainment(const QString &cont) 0130 { 0131 QString actualCont = pluginFromPath(cont); 0132 if (actualCont.isEmpty()) { 0133 actualCont = cont; 0134 } 0135 0136 Plasma::Containment *c = corona()->createContainment(actualCont); 0137 0138 if (!c->pluginMetaData().isValid()) { 0139 // xgettext:no-c-format 0140 qCritical() << i18n("Containment %1 does not exist.", actualCont); 0141 return; 0142 } 0143 0144 setContainment(c); 0145 0146 connect(containment(), &Plasma::Containment::appletRemoved, [=](Plasma::Applet *applet) { 0147 if (applet && applet->pluginMetaData().isValid()) { 0148 addApplet(applet->pluginMetaData().pluginId()); 0149 } 0150 }); 0151 } 0152 0153 void View::addFormFactor(const QString &formFactor) 0154 { 0155 Plasma::Types::FormFactor formFactorType = Plasma::Types::Planar; 0156 const QString ff = formFactor.toLower(); 0157 0158 if (ff.isEmpty() || ff == QStringLiteral("planar")) { 0159 formFactorType = Plasma::Types::Planar; 0160 } else if (ff == QStringLiteral("vertical")) { 0161 formFactorType = Plasma::Types::Vertical; 0162 } else if (ff == QStringLiteral("horizontal")) { 0163 formFactorType = Plasma::Types::Horizontal; 0164 } else if (ff == QStringLiteral("mediacenter")) { 0165 formFactorType = Plasma::Types::MediaCenter; 0166 } else if (ff == QStringLiteral("application")) { 0167 formFactorType = Plasma::Types::Application; 0168 } else { 0169 qWarning() << "FormFactor " << ff << "doesn't exist. Planar formFactor has been used!!"; 0170 } 0171 0172 Plasma::Containment *c = containment(); 0173 if (!c) { 0174 qCritical("Containment doesn't exist!"); 0175 return; 0176 } 0177 0178 c->setFormFactor(formFactorType); 0179 } 0180 0181 void View::changeFormFactor(int formFactor) 0182 { 0183 QString formFactorType = "planar"; 0184 switch (formFactor) { 0185 case Plasma::Types::Planar: 0186 formFactorType = "planar"; 0187 break; 0188 case Plasma::Types::Vertical: 0189 formFactorType = "vertical"; 0190 break; 0191 case Plasma::Types::Horizontal: 0192 formFactorType = "horizontal"; 0193 break; 0194 case Plasma::Types::MediaCenter: 0195 formFactorType = "mediacenter"; 0196 break; 0197 case Plasma::Types::Application: 0198 formFactorType = "application"; 0199 break; 0200 } 0201 0202 addFormFactor(formFactorType); 0203 } 0204 0205 void View::addLocation(const QString &location) 0206 { 0207 Plasma::Types::Location locationType = Plasma::Types::Floating; 0208 0209 const QString l = location.toLower(); 0210 0211 if (l.isEmpty() || l == QStringLiteral("floating")) { 0212 locationType = Plasma::Types::Floating; 0213 } else if (l == QStringLiteral("desktop")) { 0214 locationType = Plasma::Types::Desktop; 0215 } else if (l == QStringLiteral("fullscreen")) { 0216 locationType = Plasma::Types::FullScreen; 0217 } else if (l == QStringLiteral("topedge")) { 0218 locationType = Plasma::Types::TopEdge; 0219 } else if (l == QStringLiteral("bottomedge")) { 0220 locationType = Plasma::Types::BottomEdge; 0221 } else if (l == QStringLiteral("rightedge")) { 0222 locationType = Plasma::Types::RightEdge; 0223 } else if (l == QStringLiteral("leftedge")) { 0224 locationType = Plasma::Types::LeftEdge; 0225 } else { 0226 qWarning() << "Location " << l << "doesn't exist. Floating location has been used!!"; 0227 } 0228 0229 Plasma::Containment *c = containment(); 0230 if (!c) { 0231 qCritical("Containment doesn't exist!"); 0232 return; 0233 } 0234 0235 setLocation(locationType); 0236 } 0237 0238 void View::emitExternalData(const QString &data) 0239 { 0240 if (data.isEmpty()) { 0241 return; 0242 } 0243 0244 Plasma::Applet *applet = containment()->applets().constFirst(); 0245 0246 PlasmaQuick::AppletQuickItem *graphicsObject = PlasmaQuick::AppletQuickItem::itemForApplet(applet); 0247 0248 if (!graphicsObject) { 0249 return; 0250 } 0251 0252 QMetaObject::invokeMethod(graphicsObject, "externalData", Q_ARG(QString, QString()), Q_ARG(QVariant, data)); 0253 } 0254 0255 void View::changeLocation(int location) 0256 { 0257 QString locationType = "floating"; 0258 switch (location) { 0259 case Plasma::Types::Floating: 0260 locationType = "floating"; 0261 break; 0262 case Plasma::Types::Desktop: 0263 locationType = "desktop"; 0264 break; 0265 case Plasma::Types::FullScreen: 0266 locationType = "fullscreen"; 0267 break; 0268 case Plasma::Types::TopEdge: 0269 locationType = "topedge"; 0270 break; 0271 case Plasma::Types::BottomEdge: 0272 locationType = "bottomedge"; 0273 break; 0274 case Plasma::Types::RightEdge: 0275 locationType = "rightedge"; 0276 break; 0277 case Plasma::Types::LeftEdge: 0278 locationType = "leftedge"; 0279 break; 0280 } 0281 0282 addLocation(locationType); 0283 } 0284 0285 ViewerCorona *View::createCorona() 0286 { 0287 KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("Plasma/Shell"); 0288 package.setPath("org.kde.plasma.plasmoidviewershell"); 0289 0290 ViewerCorona *cor = new ViewerCorona(); 0291 cor->setKPackage(package); 0292 0293 return cor; 0294 } 0295 0296 void View::takeScreenShot() 0297 { 0298 QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); 0299 0300 QDBusPendingCall async = interface.asyncCall(QStringLiteral("screenshotArea"), x(), y(), width(), height()); 0301 0302 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); 0303 0304 connect(watcher, &QDBusPendingCallWatcher::finished, [](QDBusPendingCallWatcher *call) { 0305 QDBusPendingReply<QString> reply = *call; 0306 call->deleteLater(); 0307 0308 if (!reply.isValid()) { 0309 qDebug() << "The screenshot has failed, the reply is invalid with error" << reply.error().message(); 0310 return; 0311 } 0312 0313 QString dest = QFileDialog::getSaveFileName(nullptr, i18nc("@title:window", "Save Screenshot"), QDir::homePath(), QStringLiteral("Images (*.png)")); 0314 0315 if (dest.isEmpty()) { 0316 return; 0317 } 0318 0319 if (!dest.endsWith(QStringLiteral(".png"))) { 0320 dest.append(QStringLiteral(".png")); 0321 } 0322 0323 QFile f(reply.value()); 0324 f.rename(dest); 0325 }); 0326 } 0327 0328 #include "moc_view.cpp"