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"