File indexing completed on 2024-04-28 16:49:26
0001 /* 0002 * Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com> 0003 * 0004 * This file is part of Latte-Dock 0005 * 0006 * Latte-Dock is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * Latte-Dock is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "indicator.h" 0021 0022 // local 0023 #include "indicatorinfo.h" 0024 #include "../view.h" 0025 #include "../../lattecorona.h" 0026 #include "../../indicator/factory.h" 0027 #include "../../../liblatte2/types.h" 0028 0029 // Qt 0030 #include <QFileDialog> 0031 0032 // KDE 0033 #include <KLocalizedString> 0034 #include <KPluginMetaData> 0035 #include <KDeclarative/ConfigPropertyMap> 0036 #include <KDeclarative/QmlObjectSharedEngine> 0037 0038 namespace Latte { 0039 namespace ViewPart { 0040 0041 Indicator::Indicator(Latte::View *parent) 0042 : QObject(parent), 0043 m_view(parent), 0044 m_info(new IndicatorPart::Info(this)), 0045 m_resources(new IndicatorPart::Resources(this)) 0046 { 0047 m_corona = qobject_cast<Latte::Corona *>(m_view->corona()); 0048 loadConfig(); 0049 0050 connect(this, &Indicator::enabledChanged, this, &Indicator::saveConfig); 0051 connect(this, &Indicator::enabledForAppletsChanged, this, &Indicator::saveConfig); 0052 connect(this, &Indicator::paddingChanged, this, &Indicator::saveConfig); 0053 connect(this, &Indicator::pluginChanged, this, &Indicator::saveConfig); 0054 0055 connect(m_view, &Latte::View::latteTasksArePresentChanged, this, &Indicator::latteTasksArePresentChanged); 0056 0057 connect(m_view, &Latte::View::customPluginsChanged, [this]() { 0058 if (m_corona && !m_corona->indicatorFactory()->pluginExists(m_type)) { 0059 setType("org.kde.latte.default"); 0060 } 0061 0062 emit customPluginsChanged(); 0063 }); 0064 0065 connect(this, &Indicator::pluginChanged, [this]() { 0066 if ((m_type != "org.kde.latte.default") && m_type != "org.kde.latte.plasma") { 0067 setCustomType(m_type); 0068 } 0069 }); 0070 0071 load(m_type); 0072 0073 loadPlasmaComponent(); 0074 } 0075 0076 Indicator::~Indicator() 0077 { 0078 if (m_component) { 0079 m_component->deleteLater(); 0080 } 0081 0082 if (m_configLoader) { 0083 m_configLoader->deleteLater(); 0084 } 0085 0086 if (m_configuration) { 0087 m_configuration->deleteLater(); 0088 } 0089 0090 if (m_info) { 0091 m_info->deleteLater(); 0092 } 0093 } 0094 0095 bool Indicator::enabled() const 0096 { 0097 return m_enabled; 0098 } 0099 0100 void Indicator::setEnabled(bool enabled) 0101 { 0102 if (m_enabled == enabled) { 0103 return; 0104 } 0105 0106 m_enabled = enabled; 0107 emit enabledChanged(); 0108 } 0109 0110 bool Indicator::enabledForApplets() const 0111 { 0112 return m_enabledForApplets; 0113 } 0114 0115 void Indicator::setEnabledForApplets(bool enabled) 0116 { 0117 if (m_enabledForApplets == enabled) { 0118 return; 0119 } 0120 0121 m_enabledForApplets = enabled; 0122 emit enabledForAppletsChanged(); 0123 } 0124 0125 bool Indicator::latteTasksArePresent() 0126 { 0127 return m_view->latteTasksArePresent(); 0128 } 0129 0130 bool Indicator::providesConfigUi() const 0131 { 0132 return m_providesConfigUi; 0133 } 0134 0135 void Indicator::setProvidesConfigUi(bool provides) 0136 { 0137 if (m_providesConfigUi == provides) { 0138 return; 0139 } 0140 0141 m_providesConfigUi = provides; 0142 emit providesConfigUiChanged(); 0143 } 0144 0145 float Indicator::padding() const 0146 { 0147 return m_padding; 0148 } 0149 0150 void Indicator::setPadding(float padding) 0151 { 0152 if (m_padding == padding) { 0153 return; 0154 } 0155 0156 m_padding = padding; 0157 emit paddingChanged(); 0158 } 0159 0160 bool Indicator::pluginIsReady() 0161 { 0162 return m_pluginIsReady; 0163 } 0164 0165 void Indicator::setPluginIsReady(bool ready) 0166 { 0167 if (m_pluginIsReady == ready) { 0168 return; 0169 } 0170 0171 m_pluginIsReady = ready; 0172 emit pluginIsReadyChanged(); 0173 } 0174 0175 QString Indicator::type() const 0176 { 0177 return m_type; 0178 } 0179 0180 void Indicator::setType(QString type) 0181 { 0182 if (m_type == type) { 0183 return; 0184 } 0185 0186 load(type); 0187 } 0188 0189 QString Indicator::customType() const 0190 { 0191 return m_customType; 0192 } 0193 0194 void Indicator::setCustomType(QString type) 0195 { 0196 if (m_customType == type) { 0197 return; 0198 } 0199 0200 m_customType = type; 0201 emit customPluginChanged(); 0202 } 0203 0204 int Indicator::customPluginsCount() const 0205 { 0206 return m_corona->indicatorFactory()->customPluginsCount(); 0207 } 0208 0209 QString Indicator::uiPath() const 0210 { 0211 return m_corona->indicatorFactory()->uiPath(m_type); 0212 } 0213 0214 QStringList Indicator::customPluginIds() const 0215 { 0216 return m_corona->indicatorFactory()->customPluginIds(); 0217 } 0218 0219 QStringList Indicator::customPluginNames() const 0220 { 0221 return m_corona->indicatorFactory()->customPluginNames(); 0222 } 0223 0224 QStringList Indicator::customLocalPluginIds() const 0225 { 0226 return m_corona->indicatorFactory()->customLocalPluginIds(); 0227 } 0228 0229 IndicatorPart::Info *Indicator::info() const 0230 { 0231 return m_info; 0232 } 0233 0234 IndicatorPart::Resources *Indicator::resources() const 0235 { 0236 return m_resources; 0237 } 0238 0239 QQmlComponent *Indicator::component() const 0240 { 0241 return m_component; 0242 } 0243 0244 QQmlComponent *Indicator::plasmaComponent() const 0245 { 0246 return m_plasmaComponent; 0247 } 0248 0249 QObject *Indicator::configuration() const 0250 { 0251 return m_configuration; 0252 } 0253 0254 void Indicator::load(QString type) 0255 { 0256 KPluginMetaData metadata = m_corona->indicatorFactory()->metadata(type); 0257 0258 if (metadata.isValid()) { 0259 bool state{m_enabled}; 0260 //! remove all previous indicators 0261 setPluginIsReady(false); 0262 0263 m_metadata = metadata; 0264 m_type = type; 0265 0266 QString path = m_metadata.fileName(); 0267 m_pluginPath = path.remove("metadata.desktop"); 0268 0269 updateScheme(); 0270 updateComponent(); 0271 0272 emit pluginChanged(); 0273 0274 //! create all indicators with the new type 0275 setPluginIsReady(true); 0276 } else if (type!="org.kde.latte.default") { 0277 qDebug() << " Indicator metadata are not valid : " << type; 0278 setType("org.kde.latte.default"); 0279 } 0280 } 0281 0282 void Indicator::updateComponent() 0283 { 0284 auto prevComponent = m_component; 0285 0286 QString uiPath = m_metadata.value("X-Latte-MainScript"); 0287 0288 if (!uiPath.isEmpty()) { 0289 uiPath = m_pluginPath + "package/" + uiPath; 0290 m_component = new QQmlComponent(m_view->engine(), uiPath); 0291 } 0292 0293 if (prevComponent) { 0294 prevComponent->deleteLater(); 0295 } 0296 } 0297 0298 void Indicator::loadPlasmaComponent() 0299 { 0300 auto prevComponent = m_plasmaComponent; 0301 0302 KPluginMetaData metadata = m_corona->indicatorFactory()->metadata("org.kde.latte.plasma"); 0303 QString uiPath = metadata.value("X-Latte-MainScript"); 0304 0305 if (!uiPath.isEmpty()) { 0306 QString path = metadata.fileName(); 0307 path = path.remove("metadata.desktop"); 0308 0309 uiPath = path + "package/" + uiPath; 0310 m_plasmaComponent = new QQmlComponent(m_view->engine(), uiPath); 0311 } 0312 0313 if (prevComponent) { 0314 prevComponent->deleteLater(); 0315 } 0316 0317 emit plasmaComponentChanged(); 0318 } 0319 0320 void Indicator::configUiFor(QString type, QQuickItem *parent) 0321 { 0322 if (m_lastCreatedConfigUi) { 0323 delete m_lastCreatedConfigUi; 0324 m_lastCreatedConfigUi = nullptr; 0325 } 0326 auto prevConfigUi = m_lastCreatedConfigUi; 0327 0328 KPluginMetaData metadata; 0329 0330 if (m_metadata.pluginId() == type) { 0331 metadata = m_metadata; 0332 } else { 0333 metadata = m_corona->indicatorFactory()->metadata(type); 0334 } 0335 0336 if (metadata.isValid()) { 0337 QString uiPath = metadata.value("X-Latte-ConfigUi"); 0338 0339 if (!uiPath.isEmpty()) { 0340 m_lastCreatedConfigUi = new KDeclarative::QmlObjectSharedEngine(parent); 0341 m_lastCreatedConfigUi->setTranslationDomain(QLatin1String("latte_indicator_") + m_metadata.pluginId()); 0342 m_lastCreatedConfigUi->setInitializationDelayed(true); 0343 uiPath = m_pluginPath + "package/" + uiPath; 0344 m_lastCreatedConfigUi->setSource(QUrl::fromLocalFile(uiPath)); 0345 m_lastCreatedConfigUi->rootContext()->setContextProperty(QStringLiteral("dialog"), parent); 0346 m_lastCreatedConfigUi->rootContext()->setContextProperty(QStringLiteral("indicator"), this); 0347 m_lastCreatedConfigUi->completeInitialization(); 0348 0349 QQuickItem *qmlItem = qobject_cast<QQuickItem*>(m_lastCreatedConfigUi->rootObject()); 0350 qmlItem->setParentItem(parent); 0351 0352 setProvidesConfigUi(true); 0353 } else { 0354 setProvidesConfigUi(false); 0355 } 0356 } 0357 } 0358 0359 void Indicator::unloadIndicators() 0360 { 0361 setPluginIsReady(false); 0362 } 0363 0364 void Indicator::updateScheme() 0365 { 0366 auto prevConfigLoader = m_configLoader; 0367 auto prevConfiguration = m_configuration; 0368 0369 QString xmlPath = m_metadata.value("X-Latte-ConfigXml"); 0370 0371 if (!xmlPath.isEmpty()) { 0372 QFile file(m_pluginPath + "package/" + xmlPath); 0373 m_configLoader = new KConfigLoader(m_view->containment()->config().group("Indicator").group(m_metadata.pluginId()), &file); 0374 m_configuration = new KDeclarative::ConfigPropertyMap(m_configLoader, this); 0375 } else { 0376 m_configLoader = nullptr; 0377 m_configuration = nullptr; 0378 } 0379 0380 if (prevConfigLoader) { 0381 prevConfigLoader->deleteLater(); 0382 } 0383 0384 if (prevConfiguration) { 0385 prevConfiguration->deleteLater(); 0386 } 0387 } 0388 0389 void Indicator::addIndicator() 0390 { 0391 QFileDialog *fileDialog = new QFileDialog(nullptr 0392 , i18nc("add indicator", "Add Indicator") 0393 , QDir::homePath() 0394 , QStringLiteral("indicator.latte")); 0395 0396 fileDialog->setFileMode(QFileDialog::AnyFile); 0397 fileDialog->setAcceptMode(QFileDialog::AcceptOpen); 0398 fileDialog->setDefaultSuffix("indicator.latte"); 0399 0400 QStringList filters; 0401 filters << QString(i18nc("add indicator file", "Latte Indicator") + "(*.indicator.latte)"); 0402 fileDialog->setNameFilters(filters); 0403 0404 connect(fileDialog, &QFileDialog::finished, fileDialog, &QFileDialog::deleteLater); 0405 0406 connect(fileDialog, &QFileDialog::fileSelected, this, [&](const QString & file) { 0407 qDebug() << "Trying to import indicator file ::: " << file; 0408 m_corona->indicatorFactory()->importIndicatorFile(file); 0409 }); 0410 0411 fileDialog->open(); 0412 } 0413 0414 void Indicator::downloadIndicator() 0415 { 0416 //! call asynchronously in order to not crash when view settings window 0417 //! loses focus and it closes 0418 QTimer::singleShot(0, [this]() { 0419 m_corona->indicatorFactory()->downloadIndicator(); 0420 }); 0421 } 0422 0423 void Indicator::removeIndicator(QString pluginId) 0424 { //! call asynchronously in order to not crash when view settings window 0425 //! loses focus and it closes 0426 QTimer::singleShot(0, [this, pluginId]() { 0427 m_corona->indicatorFactory()->removeIndicator(pluginId); 0428 }); 0429 } 0430 0431 void Indicator::loadConfig() 0432 { 0433 auto config = m_view->containment()->config().group("Indicator"); 0434 m_customType = config.readEntry("customType", QString()); 0435 m_enabled = config.readEntry("enabled", true); 0436 m_enabledForApplets = config.readEntry("enabledForApplets", true); 0437 m_padding = config.readEntry("padding", (float)0.08); 0438 m_type = config.readEntry("type", "org.kde.latte.default"); 0439 } 0440 0441 void Indicator::saveConfig() 0442 { 0443 auto config = m_view->containment()->config().group("Indicator"); 0444 config.writeEntry("customType", m_customType); 0445 config.writeEntry("enabled", m_enabled); 0446 config.writeEntry("enabledForApplets", m_enabledForApplets); 0447 config.writeEntry("padding", m_padding); 0448 config.writeEntry("type", m_type); 0449 0450 config.sync(); 0451 } 0452 0453 } 0454 }