File indexing completed on 2024-04-28 04:37:04

0001 /*
0002     SPDX-FileCopyrightText: 2013 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "projectfiltermanager.h"
0008 
0009 #include <QVector>
0010 
0011 #include <interfaces/iproject.h>
0012 #include <interfaces/iplugin.h>
0013 #include <interfaces/icore.h>
0014 #include <interfaces/iplugincontroller.h>
0015 
0016 #include "interfaces/iprojectfilterprovider.h"
0017 #include "interfaces/iprojectfilter.h"
0018 #include "interfaces/iprojectfilemanager.h"
0019 #include "debug.h"
0020 
0021 using namespace KDevelop;
0022 
0023 //BEGIN helper
0024 namespace {
0025 
0026 struct Filter
0027 {
0028     QSharedPointer<IProjectFilter> filter;
0029     // required for bookkeeping
0030     IProjectFilterProvider* provider;
0031 };
0032 
0033 }
0034 
0035 Q_DECLARE_TYPEINFO(Filter, Q_MOVABLE_TYPE);
0036 
0037 //END helper
0038 
0039 //BEGIN private
0040 class KDevelop::ProjectFilterManagerPrivate
0041 {
0042 public:
0043     void pluginLoaded(IPlugin* plugin);
0044     void unloadingPlugin(IPlugin* plugin);
0045     void filterChanged(IProjectFilterProvider* provider, IProject* project);
0046 
0047     QVector<IProjectFilterProvider*> m_filterProvider;
0048     QHash<IProject*, QVector<Filter> > m_filters;
0049 
0050     ProjectFilterManager* q;
0051 };
0052 
0053 void ProjectFilterManagerPrivate::pluginLoaded(IPlugin* plugin)
0054 {
0055     auto* filterProvider = plugin->extension<IProjectFilterProvider>();
0056     if (filterProvider) {
0057         m_filterProvider << filterProvider;
0058         // can't use qt5 signal slot syntax here, IProjectFilterProvider is not a QObject
0059         QObject::connect(plugin, SIGNAL(filterChanged(KDevelop::IProjectFilterProvider*,KDevelop::IProject*)),
0060                          q, SLOT(filterChanged(KDevelop::IProjectFilterProvider*,KDevelop::IProject*)));
0061         QHash< IProject*, QVector< Filter > >::iterator it = m_filters.begin();
0062         while(it != m_filters.end()) {
0063             Filter filter;
0064             filter.provider = filterProvider;
0065             filter.filter = filterProvider->createFilter(it.key());
0066             it.value().append(filter);
0067             ++it;
0068         }
0069     }
0070 }
0071 
0072 void ProjectFilterManagerPrivate::unloadingPlugin(IPlugin* plugin)
0073 {
0074     auto* filterProvider = plugin->extension<IProjectFilterProvider>();
0075     if (filterProvider) {
0076         int idx = m_filterProvider.indexOf(qobject_cast<IProjectFilterProvider*>(plugin));
0077         Q_ASSERT(idx != -1);
0078         m_filterProvider.remove(idx);
0079         QHash< IProject*, QVector<Filter> >::iterator filtersIt = m_filters.begin();
0080         while(filtersIt != m_filters.end()) {
0081             QVector<Filter>& filters = filtersIt.value();
0082             QVector<Filter>::iterator filter = filters.begin();
0083             while(filter != filters.end()) {
0084                 if ((*filter).provider == filterProvider) {
0085                     filter = filters.erase(filter);
0086                     continue;
0087                 }
0088                 ++filter;
0089             }
0090             ++filtersIt;
0091         }
0092     }
0093 }
0094 
0095 void ProjectFilterManagerPrivate::filterChanged(IProjectFilterProvider* provider, IProject* project)
0096 {
0097     if (!m_filters.contains(project)) {
0098         return;
0099     }
0100 
0101     QVector< Filter >& filters = m_filters[project];
0102     for (auto& filter : filters) {
0103         if (filter.provider == provider) {
0104             filter.filter = provider->createFilter(project);
0105             qCDebug(PROJECT) << "project filter changed, reloading" << project->name();
0106             project->projectFileManager()->reload(project->projectItem());
0107             return;
0108         }
0109     }
0110     Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown provider changed its filter");
0111 }
0112 //END private
0113 
0114 //BEGIN
0115 ProjectFilterManager::ProjectFilterManager(QObject* parent)
0116     : QObject(parent)
0117     , d_ptr(new ProjectFilterManagerPrivate)
0118 {
0119     Q_D(ProjectFilterManager);
0120 
0121     d->q = this;
0122 
0123     connect(ICore::self()->pluginController(), &IPluginController::pluginLoaded,
0124             this, [this] (IPlugin* plugin) {  Q_D(ProjectFilterManager);d->pluginLoaded(plugin); });
0125     connect(ICore::self()->pluginController(), &IPluginController::unloadingPlugin,
0126             this, [this] (IPlugin* plugin) {  Q_D(ProjectFilterManager);d->unloadingPlugin(plugin); });
0127 
0128     const auto plugins = ICore::self()->pluginController()->loadedPlugins();
0129     for (IPlugin* plugin : plugins) {
0130         d->pluginLoaded(plugin);
0131     }
0132 }
0133 
0134 ProjectFilterManager::~ProjectFilterManager()
0135 {
0136 
0137 }
0138 
0139 void ProjectFilterManager::add(IProject* project)
0140 {
0141     Q_D(ProjectFilterManager);
0142 
0143     QVector<Filter> filters;
0144     filters.reserve(d->m_filterProvider.size());
0145     for (IProjectFilterProvider* provider : qAsConst(d->m_filterProvider)) {
0146         Filter filter;
0147         filter.provider = provider;
0148         filter.filter = provider->createFilter(project);
0149         filters << filter;
0150     }
0151     d->m_filters[project] = filters;
0152 }
0153 
0154 void ProjectFilterManager::remove(IProject* project)
0155 {
0156     Q_D(ProjectFilterManager);
0157 
0158     d->m_filters.remove(project);
0159 }
0160 
0161 bool ProjectFilterManager::isManaged(IProject* project) const
0162 {
0163     Q_D(const ProjectFilterManager);
0164 
0165     return d->m_filters.contains(project);
0166 }
0167 
0168 bool ProjectFilterManager::isValid(const Path& path, bool isFolder, IProject* project) const
0169 {
0170     Q_D(const ProjectFilterManager);
0171 
0172     const auto filters = d->m_filters[project];
0173     return std::all_of(filters.begin(), filters.end(), [&](const Filter& filter) {
0174         return (filter.filter->isValid(path, isFolder));
0175     });
0176 }
0177 
0178 QVector< QSharedPointer< IProjectFilter > > ProjectFilterManager::filtersForProject(IProject* project) const
0179 {
0180     Q_D(const ProjectFilterManager);
0181 
0182     QVector< QSharedPointer< IProjectFilter > > ret;
0183     const QVector<Filter>& filters = d->m_filters[project];
0184     ret.reserve(filters.size());
0185     for (const Filter& filter : filters) {
0186         ret << filter.filter;
0187     }
0188     return ret;
0189 }
0190 //END
0191 
0192 #include "moc_projectfiltermanager.cpp"