diff --git a/app/indicator/factory.cpp b/app/indicator/factory.cpp index f815a4d3f..54006ca7f 100644 --- a/app/indicator/factory.cpp +++ b/app/indicator/factory.cpp @@ -29,6 +29,7 @@ #include #include #include +#include // KDE #include @@ -49,23 +50,32 @@ Factory::Factory(QObject *parent) { m_parentWidget = new QWidget(); - m_watchedPaths = Latte::Layouts::Importer::standardPaths(); + m_mainPaths = Latte::Layouts::Importer::standardPaths(); - for(int i=0; iaddDir(dir); } connect(KDirWatch::self(), &KDirWatch::dirty, this, [ & ](const QString & path) { - if (m_watchedPaths.contains(path)) { - reload(); - emit pluginsUpdated(); + if (m_indicatorsPaths.contains(path)) { + //! indicator updated + reload(path); + } else if (m_mainPaths.contains(path)){ + //! consider indicator addition + discoverNewIndicators(path); + } + }); + + connect(KDirWatch::self(), &KDirWatch::deleted, this, [ & ](const QString & path) { + if (m_indicatorsPaths.contains(path)) { + //! indicator removed + removeIndicatorRecords(path); } }); @@ -111,62 +121,109 @@ KPluginMetaData Factory::metadata(QString pluginId) return KPluginMetaData(); } -void Factory::reload() +void Factory::reload(const QString &indicatorPath) { - m_plugins.clear(); - m_pluginUiPaths.clear(); - m_customPluginIds.clear(); - m_customPluginNames.clear(); - m_customLocalPluginIds.clear(); + QString pluginChangedId; - for(const auto &path : m_watchedPaths) { - QDir standard(path); + if (!indicatorPath.isEmpty() && indicatorPath != "." && indicatorPath != "..") { + QString metadataFile = indicatorPath + "/metadata.desktop"; - if (standard.exists()) { - QStringList pluginDirs = standard.entryList(QStringList(),QDir::AllDirs | QDir::NoSymLinks); + if(QFileInfo(metadataFile).exists()) { + KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(metadataFile); - for (const auto &pluginDir : pluginDirs) { - if (pluginDir != "." && pluginDir != "..") { - QString metadataFile = standard.absolutePath() + "/" + pluginDir + "/metadata.desktop"; + if (metadataAreValid(metadata)) { + pluginChangedId = metadata.pluginId(); + QString uiFile = indicatorPath + "/package/" + metadata.value("X-Latte-MainScript"); - if(QFileInfo(metadataFile).exists()) { - KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(metadataFile); + if (!m_plugins.contains(metadata.pluginId())) { + m_plugins[metadata.pluginId()] = metadata; + } - if (metadataAreValid(metadata)) { - QString uiFile = standard.absolutePath() + "/" + pluginDir + "/package/" + metadata.value("X-Latte-MainScript"); + if (QFileInfo(uiFile).exists()) { + m_pluginUiPaths[metadata.pluginId()] = QFileInfo(uiFile).absolutePath(); + } - if (QFileInfo(uiFile).exists() && !m_plugins.contains(metadata.pluginId())) { - m_plugins[metadata.pluginId()] = metadata; + if ((metadata.pluginId() != "org.kde.latte.default") + && (metadata.pluginId() != "org.kde.latte.plasma")) { - if ((metadata.pluginId() != "org.kde.latte.default") - && (metadata.pluginId() != "org.kde.latte.plasma")) { - m_customPluginIds << metadata.pluginId(); - m_customPluginNames << metadata.name(); - } + if (!m_customPluginIds.contains(metadata.pluginId())) { + m_customPluginIds << metadata.pluginId(); + } - if (standard.absolutePath().startsWith(QDir::homePath())) { - m_customLocalPluginIds << metadata.pluginId(); - } + if (!m_customPluginNames.contains(metadata.name())) { + m_customPluginNames << metadata.name(); + } + } - m_pluginUiPaths[metadata.pluginId()] = QFileInfo(uiFile).absolutePath(); + if (indicatorPath.startsWith(QDir::homePath())) { + m_customLocalPluginIds << metadata.pluginId(); + } + } - QString pluginPath = metadata.fileName().remove("metadata.desktop"); - qDebug() << " Indicator Package Loaded ::: " << metadata.name() << " [" << metadata.pluginId() << "]" << " - [" <addDir(iPath); + reload(iPath); + } + } +} + +void Factory::removeIndicatorRecords(const QString &path) +{ + if (m_indicatorsPaths.contains(path)) { + QString pluginId = path.section('/',-1); + m_plugins.remove(pluginId); + m_pluginUiPaths.remove(pluginId); + + int pos = m_customPluginIds.indexOf(pluginId); + + m_customPluginIds.removeAt(pos); + m_customPluginNames.removeAt(pos); + m_customLocalPluginIds.removeAll(pluginId); + + m_indicatorsPaths.removeAll(path); + + qDebug() << " indicator removed 1 :: " << pluginId; + + KDirWatch::self()->removeDir(path); + + //! delay informing the removal in case it is just an update + QTimer::singleShot(1000, [this, pluginId]() { + emit indicatorRemoved(pluginId); + }); + } +} + +bool Factory::isCustomType(const QString &id) const +{ + return ((id != "org.kde.latte.default") && (id != "org.kde.latte.plasma")); } bool Factory::metadataAreValid(KPluginMetaData &metadata) diff --git a/app/indicator/factory.h b/app/indicator/factory.h index 35ecc85d6..92fc25039 100644 --- a/app/indicator/factory.h +++ b/app/indicator/factory.h @@ -52,6 +52,7 @@ public: void removeIndicator(QString id); bool pluginExists(QString id) const; + bool isCustomType(const QString &id) const; QString uiPath(QString pluginName) const; @@ -63,11 +64,14 @@ public: //! imports an indicator compressed file static Latte::Types::ImportExportState importIndicatorFile(QString compressedFile); signals: - void customPluginsChanged(); - void pluginsUpdated(); + void indicatorChanged(const QString &indicatorId); + void indicatorRemoved(const QString &indicatorId); private: - void reload(); + void reload(const QString &indicatorPath); + + void removeIndicatorRecords(const QString &path); + void discoverNewIndicators(const QString &main); private: QHash m_plugins; @@ -77,7 +81,9 @@ private: QStringList m_customPluginNames; QStringList m_customLocalPluginIds; - QStringList m_watchedPaths; + //! plugins paths + QStringList m_mainPaths; + QStringList m_indicatorsPaths; QWidget *m_parentWidget; }; diff --git a/app/view/indicator/indicator.cpp b/app/view/indicator/indicator.cpp index 9d71284bd..defedde74 100644 --- a/app/view/indicator/indicator.cpp +++ b/app/view/indicator/indicator.cpp @@ -54,17 +54,19 @@ Indicator::Indicator(Latte::View *parent) connect(m_view, &Latte::View::latteTasksArePresentChanged, this, &Indicator::latteTasksArePresentChanged); - connect(m_view, &Latte::View::customPluginsChanged, [this]() { - if (m_corona && !m_corona->indicatorFactory()->pluginExists(m_type)) { - setType("org.kde.latte.default"); + connect(m_view, &Latte::View::indicatorPluginChanged, [this](const QString &indicatorId) { + if (m_corona && m_corona->indicatorFactory()->isCustomType(indicatorId)) { + emit customPluginsChanged(); } - - emit customPluginsChanged(); }); - connect(this, &Indicator::pluginChanged, [this]() { - if ((m_type != "org.kde.latte.default") && m_type != "org.kde.latte.plasma") { - setCustomType(m_type); + connect(m_view, &Latte::View::indicatorPluginRemoved, [this](const QString &indicatorId) { + if (m_corona && m_type == indicatorId && !m_corona->indicatorFactory()->pluginExists(indicatorId)) { + setType("org.kde.latte.default"); + } + + if (m_corona && m_corona->indicatorFactory()->isCustomType(indicatorId)) { + emit customPluginsChanged(); } }); @@ -266,6 +268,10 @@ void Indicator::load(QString type) QString path = m_metadata.fileName(); m_pluginPath = path.remove("metadata.desktop"); + if (m_corona && m_corona->indicatorFactory()->isCustomType(type)) { + setCustomType(type); + } + updateScheme(); updateComponent(); diff --git a/app/view/view.cpp b/app/view/view.cpp index b2bbadeae..acf3dfa90 100644 --- a/app/view/view.cpp +++ b/app/view/view.cpp @@ -253,9 +253,19 @@ void View::init() connect(m_contextMenu, &ViewPart::ContextMenu::menuChanged, this, &View::contextMenuIsShownChanged); - connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::pluginsUpdated, this, &View::reloadSource); //! View sends this signal in order to avoid crashes from ViewPart::Indicator when the view is recreated - connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::customPluginsChanged, this, &View::customPluginsChanged); + connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::indicatorChanged, this, [&](const QString &indicatorId) { + emit indicatorPluginChanged(indicatorId); + }); + + connect(this, &View::indicatorPluginChanged, this, [&](const QString &indicatorId) { + if (m_indicator && m_indicator->type() == indicatorId) { + reloadSource(); + } + }); + + connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::indicatorRemoved, this, &View::indicatorPluginRemoved); + connect(m_corona, &Latte::Corona::availableScreenRectChanged, this, &View::availableScreenRectChangedForViewParts); ///!!!!! diff --git a/app/view/view.h b/app/view/view.h index 30b257009..69a091f4d 100644 --- a/app/view/view.h +++ b/app/view/view.h @@ -298,7 +298,8 @@ signals: //! pass on signals to children in order to avoid crashes when View is recreated or destroyed void availableScreenRectChangedForViewParts(); - void customPluginsChanged(); + void indicatorPluginChanged(const QString &indicatorId); + void indicatorPluginRemoved(const QString &indicatorId); //! are used to trigger the Corona relevant signals and in that //! way we can disable any such signaling all together, e.g. through disconnectSensitiveSignals()