File indexing completed on 2024-04-28 16:53:01
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 0024 class ViewerCorona : public Plasma::Corona 0025 { 0026 public: 0027 ViewerCorona() 0028 : Plasma::Corona() 0029 , m_view(nullptr) 0030 { 0031 } 0032 0033 void setView(View *view) 0034 { 0035 m_view = view; 0036 } 0037 0038 QRect screenGeometry(int id) const override 0039 { 0040 Q_UNUSED(id); 0041 if (m_view) { 0042 return m_view->geometry(); 0043 } else { 0044 return QRect(); 0045 } 0046 } 0047 0048 int screenForContainment(const Plasma::Containment *containment) const override 0049 { 0050 return 0; 0051 } 0052 0053 private: 0054 View *m_view; 0055 }; 0056 0057 View::View(ViewerCorona *cor, bool konsoleVisible, QWindow *parent) 0058 : PlasmaQuick::ContainmentView(cor, parent) 0059 { 0060 cor->setView(this); 0061 m_konsoleVisible = konsoleVisible; 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(); 0074 emit corona()->availableScreenRegionChanged(); 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 const QString localePath = a->kPackage().filePath("translations"); 0112 if (!localePath.isEmpty()) { 0113 const QString localeDomain = QByteArray("plasma_applet_") + a->pluginMetaData().pluginId(); 0114 KLocalizedString::addDomainLocaleDir(localeDomain.toLatin1(), localePath); 0115 } 0116 0117 containment()->addApplet(a); 0118 } 0119 0120 if (!a->pluginMetaData().isValid()) { 0121 // xgettext:no-c-format 0122 qCritical() << i18n("Applet %1 does not exist.", applet); 0123 return; 0124 } 0125 m_lastAppletName = applet; 0126 } 0127 0128 void View::addContainment(const QString &cont) 0129 { 0130 QString actualCont = pluginFromPath(cont); 0131 if (actualCont.isEmpty()) { 0132 actualCont = cont; 0133 } 0134 0135 Plasma::Containment *c = corona()->createContainment(actualCont); 0136 0137 if (!c->pluginMetaData().isValid()) { 0138 // xgettext:no-c-format 0139 qCritical() << i18n("Containment %1 does not exist.", actualCont); 0140 return; 0141 } 0142 0143 setContainment(c); 0144 0145 connect(containment(), &Plasma::Containment::appletRemoved, [=](Plasma::Applet *applet) { 0146 if (applet && applet->pluginMetaData().isValid()) { 0147 addApplet(applet->pluginMetaData().pluginId()); 0148 } 0149 }); 0150 } 0151 0152 void View::addFormFactor(const QString &formFactor) 0153 { 0154 Plasma::Types::FormFactor formFactorType = Plasma::Types::Planar; 0155 const QString ff = formFactor.toLower(); 0156 0157 if (ff.isEmpty() || ff == QStringLiteral("planar")) { 0158 formFactorType = Plasma::Types::Planar; 0159 } else if (ff == QStringLiteral("vertical")) { 0160 formFactorType = Plasma::Types::Vertical; 0161 } else if (ff == QStringLiteral("horizontal")) { 0162 formFactorType = Plasma::Types::Horizontal; 0163 } else if (ff == QStringLiteral("mediacenter")) { 0164 formFactorType = Plasma::Types::MediaCenter; 0165 } else if (ff == QStringLiteral("application")) { 0166 formFactorType = Plasma::Types::Application; 0167 } else { 0168 qWarning() << "FormFactor " << ff << "doesn't exist. Planar formFactor has been used!!"; 0169 } 0170 0171 Plasma::Containment *c = containment(); 0172 if (!c) { 0173 qCritical("Containment doesn't exist!"); 0174 return; 0175 } 0176 0177 c->setFormFactor(formFactorType); 0178 } 0179 0180 void View::changeFormFactor(int formFactor) 0181 { 0182 QString formFactorType = "planar"; 0183 switch (formFactor) { 0184 case Plasma::Types::Planar: 0185 formFactorType = "planar"; 0186 break; 0187 case Plasma::Types::Vertical: 0188 formFactorType = "vertical"; 0189 break; 0190 case Plasma::Types::Horizontal: 0191 formFactorType = "horizontal"; 0192 break; 0193 case Plasma::Types::MediaCenter: 0194 formFactorType = "mediacenter"; 0195 break; 0196 case Plasma::Types::Application: 0197 formFactorType = "application"; 0198 break; 0199 } 0200 0201 addFormFactor(formFactorType); 0202 } 0203 0204 void View::addLocation(const QString &location) 0205 { 0206 Plasma::Types::Location locationType = Plasma::Types::Floating; 0207 0208 const QString l = location.toLower(); 0209 0210 if (l.isEmpty() || l == QStringLiteral("floating")) { 0211 locationType = Plasma::Types::Floating; 0212 } else if (l == QStringLiteral("desktop")) { 0213 locationType = Plasma::Types::Desktop; 0214 } else if (l == QStringLiteral("fullscreen")) { 0215 locationType = Plasma::Types::FullScreen; 0216 } else if (l == QStringLiteral("topedge")) { 0217 locationType = Plasma::Types::TopEdge; 0218 } else if (l == QStringLiteral("bottomedge")) { 0219 locationType = Plasma::Types::BottomEdge; 0220 } else if (l == QStringLiteral("rightedge")) { 0221 locationType = Plasma::Types::RightEdge; 0222 } else if (l == QStringLiteral("leftedge")) { 0223 locationType = Plasma::Types::LeftEdge; 0224 } else { 0225 qWarning() << "Location " << l << "doesn't exist. Floating location has been used!!"; 0226 } 0227 0228 Plasma::Containment *c = containment(); 0229 if (!c) { 0230 qCritical("Containment doesn't exist!"); 0231 return; 0232 } 0233 0234 setLocation(locationType); 0235 } 0236 0237 void View::emitExternalData(const QString &data) 0238 { 0239 if (data.isEmpty()) { 0240 return; 0241 } 0242 0243 Plasma::Applet *applet = containment()->applets().constFirst(); 0244 0245 QObject *graphicsObject = qobject_cast<QQuickItem *>(applet->property("_plasma_graphicObject").value<QObject *>()); 0246 if (!graphicsObject) { 0247 return; 0248 } 0249 0250 QMetaObject::invokeMethod(graphicsObject, "externalData", Q_ARG(QString, QString()), Q_ARG(QVariant, data)); 0251 } 0252 0253 bool View::konsoleVisible() 0254 { 0255 return m_konsoleVisible; 0256 } 0257 0258 void View::changeLocation(int location) 0259 { 0260 QString locationType = "floating"; 0261 switch (location) { 0262 case Plasma::Types::Floating: 0263 locationType = "floating"; 0264 break; 0265 case Plasma::Types::Desktop: 0266 locationType = "desktop"; 0267 break; 0268 case Plasma::Types::FullScreen: 0269 locationType = "fullscreen"; 0270 break; 0271 case Plasma::Types::TopEdge: 0272 locationType = "topedge"; 0273 break; 0274 case Plasma::Types::BottomEdge: 0275 locationType = "bottomedge"; 0276 break; 0277 case Plasma::Types::RightEdge: 0278 locationType = "rightedge"; 0279 break; 0280 case Plasma::Types::LeftEdge: 0281 locationType = "leftedge"; 0282 break; 0283 } 0284 0285 addLocation(locationType); 0286 } 0287 0288 ViewerCorona *View::createCorona() 0289 { 0290 KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("Plasma/Shell"); 0291 package.setPath("org.kde.plasma.plasmoidviewershell"); 0292 0293 ViewerCorona *cor = new ViewerCorona(); 0294 cor->setKPackage(package); 0295 0296 return cor; 0297 } 0298 0299 void View::takeScreenShot() 0300 { 0301 QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); 0302 0303 QDBusPendingCall async = interface.asyncCall(QStringLiteral("screenshotArea"), x(), y(), width(), height()); 0304 0305 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); 0306 0307 connect(watcher, &QDBusPendingCallWatcher::finished, [](QDBusPendingCallWatcher *call) { 0308 QDBusPendingReply<QString> reply = *call; 0309 call->deleteLater(); 0310 0311 if (!reply.isValid()) { 0312 qDebug() << "The screenshot has failed, the reply is invalid with error" << reply.error().message(); 0313 return; 0314 } 0315 0316 QString dest = QFileDialog::getSaveFileName(nullptr, i18nc("@title:window", "Save Screenshot"), QDir::homePath(), QStringLiteral("Images (*.png)")); 0317 0318 if (dest.isEmpty()) { 0319 return; 0320 } 0321 0322 if (!dest.endsWith(QStringLiteral(".png"))) { 0323 dest.append(QStringLiteral(".png")); 0324 } 0325 0326 QFile f(reply.value()); 0327 f.rename(dest); 0328 }); 0329 } 0330 0331 #include "moc_view.cpp"