From 91b345e615e1f952238fa696ffaed7a315e27ba8 Mon Sep 17 00:00:00 2001 From: Michail Vourlakos Date: Tue, 31 Dec 2019 15:49:53 +0200 Subject: [PATCH] make indicators infrastructure smarter --indicators are now tracked only based on their installation path, that means that are updated more precise when changes are applied and at the same time views are recreated only when the show the specific indicator that was changed --- app/indicator/factory.cpp | 149 +++++++++++++++++++++---------- app/indicator/factory.h | 14 ++- app/view/indicator/indicator.cpp | 22 +++-- app/view/view.cpp | 14 ++- app/view/view.h | 3 +- 5 files changed, 141 insertions(+), 61 deletions(-) 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()