File indexing completed on 2024-04-28 04:39:08
0001 /* 0002 SPDX-FileCopyrightText: 2013 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "projectfilterprovider.h" 0008 0009 #include <KPluginFactory> 0010 #include <KMessageBox> 0011 #include <KParts/MainWindow> 0012 #include <KLocalizedString> 0013 0014 #include <QAction> 0015 #include <QIcon> 0016 0017 #include <interfaces/iproject.h> 0018 #include <interfaces/icore.h> 0019 #include <interfaces/iprojectcontroller.h> 0020 #include <interfaces/context.h> 0021 #include <interfaces/contextmenuextension.h> 0022 #include <interfaces/iuicontroller.h> 0023 0024 #include <debug.h> 0025 #include "projectfilterconfigpage.h" 0026 #include <project/projectmodel.h> 0027 0028 using namespace KDevelop; 0029 0030 K_PLUGIN_FACTORY_WITH_JSON(ProjectFilterProviderFactory, "kdevprojectfilter.json", registerPlugin<ProjectFilterProvider>();) 0031 0032 ProjectFilterProvider::ProjectFilterProvider( QObject* parent, const QVariantList& /*args*/ ) 0033 : IPlugin( QStringLiteral( "kdevprojectfilter" ), parent ) 0034 { 0035 connect(core()->projectController(), &IProjectController::projectClosing, 0036 this, &ProjectFilterProvider::projectClosing); 0037 connect(core()->projectController(), &IProjectController::projectAboutToBeOpened, 0038 this, &ProjectFilterProvider::projectAboutToBeOpened); 0039 0040 // initialize the filters for each project 0041 const auto projects = core()->projectController()->projects(); 0042 for (IProject* project : projects) { 0043 updateProjectFilters(project); 0044 } 0045 } 0046 0047 QSharedPointer<IProjectFilter> ProjectFilterProvider::createFilter(IProject* project) const 0048 { 0049 return QSharedPointer<IProjectFilter>(new ProjectFilter(project, m_filters[project])); 0050 } 0051 0052 ContextMenuExtension ProjectFilterProvider::contextMenuExtension(Context* context, QWidget* parent) 0053 { 0054 ContextMenuExtension ret; 0055 if (!context->hasType(Context::ProjectItemContext)) { 0056 return ret; 0057 } 0058 0059 auto* ctx = static_cast<ProjectItemContext*>( context ); 0060 0061 QList<ProjectBaseItem*> items = ctx->items(); 0062 // filter out project roots and items in targets 0063 QList< ProjectBaseItem* >::iterator it = items.begin(); 0064 while (it != items.end()) { 0065 if ((*it)->isProjectRoot() || !(*it)->parent()->folder()) { 0066 it = items.erase(it); 0067 } else { 0068 ++it; 0069 } 0070 } 0071 if (items.isEmpty()) { 0072 return ret; 0073 } 0074 0075 auto* action = new QAction(QIcon::fromTheme(QStringLiteral("view-filter")), 0076 i18ncp("@action:inmenu", "Exclude Item from Project", 0077 "Exclude Items from Project", 0078 items.size()), parent); 0079 action->setData(QVariant::fromValue(items)); 0080 connect(action, &QAction::triggered, this, &ProjectFilterProvider::addFilterFromContextMenu); 0081 ret.addAction(ContextMenuExtension::FileGroup, action); 0082 return ret; 0083 } 0084 0085 void ProjectFilterProvider::addFilterFromContextMenu() 0086 { 0087 auto* action = qobject_cast<QAction*>(sender()); 0088 Q_ASSERT(action); 0089 const QList<ProjectBaseItem*> items = action->data().value<QList<ProjectBaseItem*>>(); 0090 QHash<IProject*, SerializedFilters> changedProjectFilters; 0091 for (ProjectBaseItem* item : items) { 0092 auto filterIt = changedProjectFilters.find(item->project()); 0093 if (filterIt == changedProjectFilters.end()) { 0094 filterIt = changedProjectFilters.insert(item->project(), readFilters(item->project()->projectConfiguration())); 0095 } 0096 SerializedFilters& filters = *filterIt; 0097 Path path; 0098 if (item->target()) { 0099 path = Path(item->parent()->path(), item->text()); 0100 } else { 0101 path = item->path(); 0102 } 0103 filters << SerializedFilter(QLatin1Char('/') + item->project()->path().relativePath(path), 0104 item->folder() ? Filter::Folders : Filter::Files); 0105 } 0106 QHash< IProject*, SerializedFilters >::const_iterator it = changedProjectFilters.constBegin(); 0107 while (it != changedProjectFilters.constEnd()) { 0108 writeFilters(it.value(), it.key()->projectConfiguration()); 0109 m_filters[it.key()] = deserialize(it.value()); 0110 emit filterChanged(this, it.key()); 0111 ++it; 0112 } 0113 0114 KMessageBox::information(ICore::self()->uiController()->activeMainWindow(), 0115 i18np("A filter for the item was added. To undo, use the project filter settings.", 0116 "A filter for the items was added. To undo, use the project filter settings.", 0117 items.size()), i18nc("@title:window", "Project Filter Added"), QStringLiteral("projectfilter-addfromctxmenu")); 0118 } 0119 0120 void ProjectFilterProvider::updateProjectFilters(IProject* project) 0121 { 0122 Filters newFilters = deserialize(readFilters(project->projectConfiguration())); 0123 Filters& filters = m_filters[project]; 0124 if (filters != newFilters) { 0125 qCDebug(PLUGIN_PROJECTFILTER) << "project filter changed:" << project->name(); 0126 filters = newFilters; 0127 emit filterChanged(this, project); 0128 } 0129 } 0130 0131 void ProjectFilterProvider::projectAboutToBeOpened(IProject* project) 0132 { 0133 m_filters[project] = deserialize(readFilters(project->projectConfiguration())); 0134 } 0135 0136 void ProjectFilterProvider::projectClosing(IProject* project) 0137 { 0138 m_filters.remove(project); 0139 } 0140 0141 int ProjectFilterProvider::perProjectConfigPages() const 0142 { 0143 return 1; 0144 } 0145 0146 ConfigPage* ProjectFilterProvider::perProjectConfigPage(int i, const ProjectConfigOptions& options, QWidget* parent) 0147 { 0148 return i == 0 ? new ProjectFilterConfigPage(this, options, parent) : nullptr; 0149 } 0150 0151 #include "projectfilterprovider.moc" 0152 #include "moc_projectfilterprovider.cpp"