File indexing completed on 2024-04-28 16:55:02
0001 /* 0002 SPDX-FileCopyrightText: 2014 Bhushan Shah <bhush94@gmail.com> 0003 SPDX-FileCopyrightText: 2014 Marco Martin <notmart@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #include "standaloneappcorona.h" 0009 #include "debug.h" 0010 #include "panelview.h" 0011 0012 #include <QAction> 0013 #include <QDebug> 0014 #include <QFile> 0015 #include <QQuickItem> 0016 0017 #include <KActionCollection> 0018 #include <Plasma/PluginLoader> 0019 #include <kactivities/consumer.h> 0020 0021 #include <KPackage/Package> 0022 #include <KPackage/PackageLoader> 0023 0024 #include "scripting/scriptengine.h" 0025 0026 StandaloneAppCorona::StandaloneAppCorona(const QString &coronaPlugin, QObject *parent) 0027 : Plasma::Corona(parent) 0028 , m_coronaPlugin(coronaPlugin) 0029 , m_activityConsumer(new KActivities::Consumer(this)) 0030 , m_view(nullptr) 0031 { 0032 qmlRegisterUncreatableType<DesktopView>("org.kde.plasma.shell", 2, 0, "Desktop", QStringLiteral("It is not possible to create objects of type Desktop")); 0033 qmlRegisterUncreatableType<PanelView>("org.kde.plasma.shell", 2, 0, "Panel", QStringLiteral("It is not possible to create objects of type Panel")); 0034 0035 KPackage::Package package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Shell")); 0036 package.setPath(m_coronaPlugin); 0037 package.setAllowExternalPaths(true); 0038 if (!package.isValid()) { 0039 qCritical() << "starting invalid corona" << m_coronaPlugin; 0040 } 0041 setKPackage(package); 0042 0043 Plasma::Theme theme; 0044 theme.setUseGlobalSettings(false); 0045 0046 KConfigGroup lnfCfg = KConfigGroup(KSharedConfig::openConfig(package.filePath("defaults")), "Theme"); 0047 theme.setThemeName(lnfCfg.readEntry("name", "default")); 0048 0049 m_desktopDefaultsConfig = KConfigGroup(KSharedConfig::openConfig(package.filePath("defaults")), "Desktop"); 0050 0051 m_view = new DesktopView(this); 0052 0053 connect(m_activityConsumer, &KActivities::Consumer::currentActivityChanged, this, &StandaloneAppCorona::currentActivityChanged); 0054 connect(m_activityConsumer, &KActivities::Consumer::activityAdded, this, &StandaloneAppCorona::activityAdded); 0055 connect(m_activityConsumer, &KActivities::Consumer::activityRemoved, this, &StandaloneAppCorona::activityRemoved); 0056 0057 connect(m_activityConsumer, &KActivities::Consumer::serviceStatusChanged, this, &StandaloneAppCorona::load); 0058 } 0059 0060 StandaloneAppCorona::~StandaloneAppCorona() 0061 { 0062 delete m_view; 0063 } 0064 0065 QRect StandaloneAppCorona::screenGeometry(int id) const 0066 { 0067 Q_UNUSED(id); 0068 if (m_view) { 0069 return m_view->geometry(); 0070 } else { 0071 return QRect(); 0072 } 0073 } 0074 0075 void StandaloneAppCorona::load() 0076 { 0077 loadLayout("plasma-" + m_coronaPlugin + "-appletsrc"); 0078 0079 bool found = false; 0080 for (auto c : containments()) { 0081 if (c->containmentType() == Plasma::Types::DesktopContainment || c->containmentType() == Plasma::Types::CustomContainment) { 0082 found = true; 0083 break; 0084 } 0085 } 0086 0087 if (!found) { 0088 qDebug() << "Loading default layout"; 0089 loadDefaultLayout(); 0090 saveLayout("plasma-" + m_coronaPlugin + "-appletsrc"); 0091 } 0092 0093 for (auto c : containments()) { 0094 qDebug() << "containment found"; 0095 if (c->containmentType() == Plasma::Types::DesktopContainment || c->containmentType() == Plasma::Types::CustomContainment) { 0096 QAction *removeAction = c->actions()->action(QStringLiteral("remove")); 0097 if (removeAction) { 0098 removeAction->deleteLater(); 0099 } 0100 m_view->setContainment(c); 0101 m_view->show(); 0102 connect(m_view, &QWindow::visibleChanged, [=](bool visible) { 0103 if (!visible) { 0104 deleteLater(); 0105 } 0106 }); 0107 break; 0108 } 0109 } 0110 } 0111 0112 void StandaloneAppCorona::loadDefaultLayout() 0113 { 0114 const QString script = kPackage().filePath("defaultlayout"); 0115 QFile file(script); 0116 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { 0117 QString code = file.readAll(); 0118 qDebug() << "evaluating startup script:" << script; 0119 0120 WorkspaceScripting::ScriptEngine scriptEngine(this); 0121 0122 connect(&scriptEngine, &WorkspaceScripting::ScriptEngine::printError, this, [](const QString &msg) { 0123 qCWarning(PLASMASHELL) << msg; 0124 }); 0125 connect(&scriptEngine, &WorkspaceScripting::ScriptEngine::print, this, [](const QString &msg) { 0126 qDebug() << msg; 0127 }); 0128 scriptEngine.evaluateScript(code); 0129 } 0130 } 0131 0132 Plasma::Containment *StandaloneAppCorona::createContainmentForActivity(const QString &activity, int screenNum) 0133 { 0134 for (Plasma::Containment *cont : containments()) { 0135 if (cont->activity() == activity 0136 && (cont->containmentType() == Plasma::Types::DesktopContainment || cont->containmentType() == Plasma::Types::CustomContainment)) { 0137 return cont; 0138 } 0139 } 0140 0141 Plasma::Containment *containment = 0142 containmentForScreen(screenNum, activity, m_desktopDefaultsConfig.readEntry("Containment", "org.kde.desktopcontainment"), QVariantList()); 0143 Q_ASSERT(containment); 0144 0145 if (containment) { 0146 containment->setActivity(activity); 0147 } 0148 0149 return containment; 0150 } 0151 0152 void StandaloneAppCorona::activityAdded(const QString &id) 0153 { 0154 // TODO more sanity checks 0155 if (m_activityContainmentPlugins.contains(id)) { 0156 qCWarning(PLASMASHELL) << "Activity added twice" << id; 0157 return; 0158 } 0159 0160 m_activityContainmentPlugins.insert(id, QString()); 0161 } 0162 0163 void StandaloneAppCorona::activityRemoved(const QString &id) 0164 { 0165 m_activityContainmentPlugins.remove(id); 0166 } 0167 0168 void StandaloneAppCorona::currentActivityChanged(const QString &newActivity) 0169 { 0170 // qDebug() << "Activity changed:" << newActivity; 0171 0172 if (containments().isEmpty()) { 0173 return; 0174 } 0175 0176 Plasma::Containment *c = createContainmentForActivity(newActivity, 0); 0177 0178 connect(c, &Plasma::Containment::showAddWidgetsInterface, this, &StandaloneAppCorona::toggleWidgetExplorer); 0179 0180 QAction *removeAction = c->actions()->action(QStringLiteral("remove")); 0181 if (removeAction) { 0182 removeAction->deleteLater(); 0183 } 0184 m_view->setContainment(c); 0185 } 0186 0187 void StandaloneAppCorona::toggleWidgetExplorer() 0188 { 0189 // The view QML has to provide something to display the widget explorer 0190 m_view->rootObject()->metaObject()->invokeMethod(m_view->rootObject(), "toggleWidgetExplorer", Q_ARG(QVariant, QVariant::fromValue(sender()))); 0191 return; 0192 } 0193 0194 QStringList StandaloneAppCorona::availableActivities() const 0195 { 0196 return m_activityContainmentPlugins.keys(); 0197 } 0198 0199 void StandaloneAppCorona::insertActivity(const QString &id, const QString &plugin) 0200 { 0201 m_activityContainmentPlugins.insert(id, plugin); 0202 Plasma::Containment *c = createContainmentForActivity(id, 0); 0203 if (c) { 0204 c->config().writeEntry("lastScreen", 0); 0205 } 0206 } 0207 0208 Plasma::Containment *StandaloneAppCorona::addPanel(const QString &plugin) 0209 { 0210 // this creates a panel that wwill be used for nothing 0211 // it's needed by the scriptengine to create 0212 // a corona useful also when launched in fullshell 0213 Plasma::Containment *panel = createContainment(plugin); 0214 if (!panel) { 0215 return nullptr; 0216 } 0217 0218 return panel; 0219 } 0220 0221 int StandaloneAppCorona::screenForContainment(const Plasma::Containment *containment) const 0222 { 0223 // this simple corona doesn't have multiscreen support 0224 if (containment->containmentType() != Plasma::Types::PanelContainment && containment->containmentType() != Plasma::Types::CustomPanelContainment) { 0225 if (containment->activity() != m_activityConsumer->currentActivity()) { 0226 return -1; 0227 } 0228 } 0229 return 0; 0230 }