diff --git a/projectbuilders/ninjabuilder/kdevninjabuilderplugin.cpp b/projectbuilders/ninjabuilder/kdevninjabuilderplugin.cpp index e504125bed..d903f7b8ff 100644 --- a/projectbuilders/ninjabuilder/kdevninjabuilderplugin.cpp +++ b/projectbuilders/ninjabuilder/kdevninjabuilderplugin.cpp @@ -1,207 +1,203 @@ /* This file is part of KDevelop Copyright 2012 Aleix Pol Gonzalez This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kdevninjabuilderplugin.h" #include "ninjajob.h" #include "ninjabuilderpreferences.h" #include #include #include #include #include #include #include #include #include #include Q_DECLARE_LOGGING_CATEGORY(NINJABUILDER) Q_LOGGING_CATEGORY(NINJABUILDER, "kdevelop.projectbuilders.ninjabuilder") K_PLUGIN_FACTORY_WITH_JSON(NinjaBuilderFactory, "kdevninja.json", registerPlugin(); ) KDevNinjaBuilderPlugin::KDevNinjaBuilderPlugin(QObject* parent, const QVariantList& ) : KDevelop::IPlugin("kdevninja", parent) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IProjectBuilder ) - if(hasError()) - qWarning() << "Ninja plugin installed but ninja is not installed."; -} - -bool KDevNinjaBuilderPlugin::hasError() const -{ - return NinjaJob::ninjaBinary().isEmpty(); + if(NinjaJob::ninjaBinary().isEmpty()) { + setErrorDescription(i18n("Unable to find ninja executable. Is it installed on the system?")); + } } static QStringList targetsInFolder(KDevelop::ProjectFolderItem* item) { QStringList ret; foreach(KDevelop::ProjectTargetItem* target, item->targetList()) { ret += target->text(); } return ret; } /** * Returns the first non-empty list of targets in folder @p item * or any of its ancestors if possible */ static QStringList closestTargetsForFolder(KDevelop::ProjectFolderItem* item) { KDevelop::ProjectFolderItem* current = item; while (current) { const QStringList targets = targetsInFolder(current); if (!targets.isEmpty()) { return targets; } current = (current->parent() ? current->parent()->folder() : 0); } return QStringList(); } static QStringList argumentsForItem(KDevelop::ProjectBaseItem* item) { if(!item->parent() && QFile::exists(item->project()->buildSystemManager()->buildDirectory(item->project()->projectItem()).toLocalFile())) return QStringList(); switch(item->type()) { case KDevelop::ProjectBaseItem::File: return QStringList(item->path().toLocalFile()+'^'); case KDevelop::ProjectBaseItem::Target: case KDevelop::ProjectBaseItem::ExecutableTarget: case KDevelop::ProjectBaseItem::LibraryTarget: return QStringList(item->target()->text()); case KDevelop::ProjectBaseItem::Folder: case KDevelop::ProjectBaseItem::BuildFolder: return closestTargetsForFolder(item->folder()); } return QStringList(); } NinjaJob* KDevNinjaBuilderPlugin::runNinja(KDevelop::ProjectBaseItem* item, const QStringList& args, const QByteArray& signal) { ///Running the same builder twice may result in serious problems, ///so kill jobs already running on the same project foreach (NinjaJob* ninjaJob, m_activeNinjaJobs.data()) { if(item && ninjaJob->item() && ninjaJob->item()->project() == item->project() ) { qCDebug(NINJABUILDER) << "killing running ninja job, due to new started build on same project:" << ninjaJob; ninjaJob->kill(KJob::EmitResult); } } // Build arguments using data from KCM QStringList jobArguments; KSharedConfigPtr config = item->project()->projectConfiguration(); KConfigGroup group = config->group( "NinjaBuilder" ); if( !group.readEntry( "Abort on First Error", true ) ) { jobArguments << "-k"; } if( group.readEntry( "Override Number Of Jobs", false ) ) { int jobCount = group.readEntry( "Number Of Jobs", 1 ); if( jobCount > 0 ) { jobArguments << QString( "-j%1" ).arg( jobCount ); } } int errorCount = group.readEntry( "Number Of Errors", 1 ); if( errorCount > 1 ) { jobArguments << QString( "-k%1" ).arg( errorCount ); } if( group.readEntry( "Display Only", false ) ) { jobArguments << "-n"; } QString extraOptions = group.readEntry( "Additional Options", QString() ); if( !extraOptions.isEmpty() ) { foreach(const QString& option, KShell::splitArgs( extraOptions ) ) { jobArguments << option; } } jobArguments << args; NinjaJob* job = new NinjaJob(item, jobArguments, signal, this); m_activeNinjaJobs.append(job); return job; } KJob* KDevNinjaBuilderPlugin::build(KDevelop::ProjectBaseItem* item) { return runNinja(item, argumentsForItem(item), "built"); } KJob* KDevNinjaBuilderPlugin::clean(KDevelop::ProjectBaseItem* item) { return runNinja(item, QStringList("-t") << "clean", "cleaned"); } KJob* KDevNinjaBuilderPlugin::install(KDevelop::ProjectBaseItem* item) { NinjaJob* installJob = runNinja( item, QStringList( "install" ), "installed" ); installJob->setIsInstalling( true ); KSharedConfigPtr configPtr = item->project()->projectConfiguration(); KConfigGroup builderGroup( configPtr, "NinjaBuilder" ); bool installAsRoot = builderGroup.readEntry("Install As Root", false); if(installAsRoot) { KDevelop::BuilderJob* job = new KDevelop::BuilderJob; job->addCustomJob( KDevelop::BuilderJob::Build, build( item ), item ); job->addCustomJob( KDevelop::BuilderJob::Install, installJob, item ); job->updateJobName(); return job; } else { return installJob; } } int KDevNinjaBuilderPlugin::perProjectConfigPages() const { return 1; } KDevelop::ConfigPage* KDevNinjaBuilderPlugin::perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent) { if (number == 0) { return new NinjaBuilderPreferences(this, options, parent); } return nullptr; } class ErrorJob : public KJob { public: ErrorJob(QObject* parent, const QString& error) : KJob(parent) , m_error(error) {} void start() override { setError(!m_error.isEmpty()); setErrorText(m_error); emitResult(); } private: QString m_error; }; KJob* KDevNinjaBuilderPlugin::install(KDevelop::ProjectBaseItem *dom, const QUrl &installPath) { return installPath.isEmpty() ? install(dom) : new ErrorJob(nullptr, i18n("Cannot specify prefix in %1, on ninja", installPath.toDisplayString())); } #include "kdevninjabuilderplugin.moc" diff --git a/projectbuilders/ninjabuilder/kdevninjabuilderplugin.h b/projectbuilders/ninjabuilder/kdevninjabuilderplugin.h index 6886be5920..9fe886d543 100644 --- a/projectbuilders/ninjabuilder/kdevninjabuilderplugin.h +++ b/projectbuilders/ninjabuilder/kdevninjabuilderplugin.h @@ -1,58 +1,57 @@ /* This file is part of KDevelop Copyright 2012 Aleix Pol Gonzalez This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVNINJABUILDERPLUGIN_H #define KDEVNINJABUILDERPLUGIN_H #include #include #include #include #include class NinjaJob; class KDevNinjaBuilderPlugin : public KDevelop::IPlugin, KDevelop::IProjectBuilder { Q_OBJECT Q_INTERFACES( KDevelop::IProjectBuilder ) public: KDevNinjaBuilderPlugin(QObject* parent = 0, const QVariantList& args = QVariantList()); - bool hasError() const override; KJob* build(KDevelop::ProjectBaseItem* item) override; KJob* clean(KDevelop::ProjectBaseItem* item) override; KJob* install(KDevelop::ProjectBaseItem *dom, const QUrl &installPath) override; KJob* install(KDevelop::ProjectBaseItem* item); NinjaJob* runNinja(KDevelop::ProjectBaseItem* item, const QStringList& args, const QByteArray& signal); int perProjectConfigPages() const override; KDevelop::ConfigPage* perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent) override; Q_SIGNALS: void built( KDevelop::ProjectBaseItem* item); void failed( KDevelop::ProjectBaseItem* item); void installed(KDevelop::ProjectBaseItem* item); void cleaned(KDevelop::ProjectBaseItem* item); private: KDevelop::ObjectList m_activeNinjaJobs; }; #endif // KDEVNINJABUILDERPLUGIN_H diff --git a/projectmanagers/cmake/cmakedocumentation.cpp b/projectmanagers/cmake/cmakedocumentation.cpp index f8efa55df9..a873a6d5b9 100644 --- a/projectmanagers/cmake/cmakedocumentation.cpp +++ b/projectmanagers/cmake/cmakedocumentation.cpp @@ -1,207 +1,198 @@ /* KDevelop CMake Support * * Copyright 2009 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "cmakedocumentation.h" #include "cmakeutils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cmakemanager.h" #include "cmakeparserutils.h" #include "cmakehelpdocumentation.h" #include "cmakedoc.h" #include "debug.h" K_PLUGIN_FACTORY_WITH_JSON(CMakeSupportDocFactory, "kdevcmakedocumentation.json", registerPlugin(); ) CMakeDocumentation* CMakeDoc::s_provider=0; KDevelop::IDocumentationProvider* CMakeDoc::provider() const { return s_provider; } CMakeDocumentation::CMakeDocumentation(QObject* parent, const QVariantList&) : KDevelop::IPlugin( "kdevcmakedocumentation", parent ) , mCMakeCmd(QStandardPaths::findExecutable("cmake")) , m_index(nullptr) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IDocumentationProvider ) KDEV_USE_EXTENSION_INTERFACE( ICMakeDocumentation ) if (mCMakeCmd.isEmpty()) { + setErrorDescription(i18n("Unable to find cmake executable. Is it installed on the system?") ); return; } CMakeDoc::s_provider=this; m_index= new QStringListModel(this); initializeModel(); } -bool CMakeDocumentation::hasError() const -{ - return mCMakeCmd.isEmpty(); -} - -QString CMakeDocumentation::errorDescription() const -{ - return mCMakeCmd.isEmpty() ? i18n("cmake is not installed") : QString(); -} - static const char* args[] = { "--help-command", "--help-variable", "--help-module", "--help-property", 0, 0 }; void CMakeDocumentation::delayedInitialization() { for(int i=0; i<=Property; i++) { collectIds(QString(args[i])+"-list", (Type) i); } m_index->setStringList(m_typeForName.keys()); } void CMakeDocumentation::collectIds(const QString& param, Type type) { QStringList ids=CMake::executeProcess(mCMakeCmd, QStringList(param)).split('\n'); ids.takeFirst(); foreach(const QString& name, ids) { m_typeForName[name]=type; } } QStringList CMakeDocumentation::names(CMakeDocumentation::Type t) const { return m_typeForName.keys(t); } QString CMakeDocumentation::descriptionForIdentifier(const QString& id, Type t) const { QString desc; if(args[t]) { desc = CMake::executeProcess(mCMakeCmd, QStringList(args[t]) << id.simplified()).toHtmlEscaped(); int firstLine = desc.indexOf('\n'); firstLine = desc.indexOf('\n', firstLine+1); if(firstLine>=0) desc = desc.mid(firstLine+1).trimmed(); //we remove the cmake version and the command name desc.replace(QLatin1String("\n "), QLatin1String("\n")); desc = QString("%1
%2
").arg(id).arg(desc); } return desc; } KDevelop::IDocumentation::Ptr CMakeDocumentation::description(const QString& identifier, const QUrl &file) const { initializeModel(); //make it not queued if (!file.isEmpty() && !QMimeDatabase().mimeTypeForUrl(file).inherits("text/x-cmake")) { return KDevelop::IDocumentation::Ptr(); } QString desc; if(m_typeForName.contains(identifier)) { desc=descriptionForIdentifier(identifier, m_typeForName[identifier]); } else if(m_typeForName.contains(identifier.toLower())) { desc=descriptionForIdentifier(identifier, m_typeForName[identifier.toLower()]); } else if(m_typeForName.contains(identifier.toUpper())) { desc=descriptionForIdentifier(identifier, m_typeForName[identifier.toUpper()]); } KDevelop::IProject* p=KDevelop::ICore::self()->projectController()->findProjectForUrl(file); ICMakeManager* m=0; if(p) m=p->managerPlugin()->extension(); if(m) { QPair entry = m->cacheValue(p, identifier); if(!entry.first.isEmpty()) desc += i18n("
Cache Value: %1\n", entry.first); if(!entry.second.isEmpty()) desc += i18n("
Cache Documentation: %1\n", entry.second); } if(desc.isEmpty()) return KDevelop::IDocumentation::Ptr(); else return KDevelop::IDocumentation::Ptr(new CMakeDoc(identifier, desc)); } KDevelop::IDocumentation::Ptr CMakeDocumentation::documentationForDeclaration(KDevelop::Declaration* decl) const { return description(decl->identifier().toString(), decl->url().toUrl()); } KDevelop::IDocumentation::Ptr CMakeDocumentation::documentationForIndex(const QModelIndex& idx) const { return description(idx.data().toString(), QUrl()); } QAbstractListModel* CMakeDocumentation::indexModel() const { initializeModel(); return m_index; } QIcon CMakeDocumentation::icon() const { return QIcon::fromTheme("cmake"); } QString CMakeDocumentation::name() const { return "CMake"; } KDevelop::IDocumentation::Ptr CMakeDocumentation::homePage() const { if(m_typeForName.isEmpty()) const_cast(this)->delayedInitialization(); // initializeModel(); return KDevelop::IDocumentation::Ptr(new CMakeHomeDocumentation); } void CMakeDocumentation::initializeModel() const { if(!m_typeForName.isEmpty()) return; QMetaObject::invokeMethod(const_cast(this), "delayedInitialization", Qt::QueuedConnection); } //////////CMakeDoc QWidget* CMakeDoc::documentationWidget(KDevelop::DocumentationFindWidget* findWidget, QWidget* parent) { KDevelop::StandardDocumentationView* view = new KDevelop::StandardDocumentationView(findWidget, parent); view->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); view->setHtml(""+description()+""); return view; } #include "cmakedocumentation.moc" diff --git a/projectmanagers/cmake/cmakedocumentation.h b/projectmanagers/cmake/cmakedocumentation.h index 5affbfc145..7aee1621cc 100644 --- a/projectmanagers/cmake/cmakedocumentation.h +++ b/projectmanagers/cmake/cmakedocumentation.h @@ -1,75 +1,72 @@ /* KDevelop CMake Support * * Copyright 2009 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef CMAKEDOCUMENTATION_H #define CMAKEDOCUMENTATION_H #include #include #include #include #include #include "icmakedocumentation.h" class QStringListModel; namespace KDevelop { class Declaration; } class CMakeManager; class QUrl; class CMakeDocumentation : public KDevelop::IPlugin, public ICMakeDocumentation { Q_OBJECT Q_INTERFACES( ICMakeDocumentation ) Q_INTERFACES( KDevelop::IDocumentationProvider ) public: explicit CMakeDocumentation( QObject* parent = 0, const QVariantList& args = QVariantList() ); - bool hasError() const override; - QString errorDescription() const override; - KDevelop::IDocumentation::Ptr description(const QString& identifier, const QUrl &file) const override; KDevelop::IDocumentation::Ptr documentationForDeclaration(KDevelop::Declaration* declaration) const override; QStringList names(Type t) const override; QAbstractListModel* indexModel() const override; KDevelop::IDocumentation::Ptr documentationForIndex(const QModelIndex& idx) const override; QIcon icon() const override; QString name() const override; KDevelop::IDocumentation::Ptr homePage() const override; QString descriptionForIdentifier(const QString& identifier, Type t) const; public slots: void delayedInitialization(); Q_SIGNALS: void addHistory(const KDevelop::IDocumentation::Ptr& doc) const override; private: void initializeModel() const; void collectIds(const QString& param, Type type); QMap m_typeForName; const QString mCMakeCmd; QStringListModel* m_index; }; #endif // CMAKEDOCUMENTATION_H diff --git a/projectmanagers/cmake/cmakemanager.cpp b/projectmanagers/cmake/cmakemanager.cpp index 717dabe93a..2e41e01752 100644 --- a/projectmanagers/cmake/cmakemanager.cpp +++ b/projectmanagers/cmake/cmakemanager.cpp @@ -1,896 +1,887 @@ /* KDevelop CMake Support * * Copyright 2006 Matt Rogers * Copyright 2007-2013 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "cmakemanager.h" #include "cmakeedit.h" #include "cmakeutils.h" #include "cmakeprojectdata.h" #include "duchain/cmakeparsejob.h" #include "cmakeimportjsonjob.h" #include "debug.h" #include "settings/cmakepreferences.h" #include #include "cmakecodecompletionmodel.h" #include "cmakenavigationwidget.h" #include "icmakedocumentation.h" #include "cmakemodelitems.h" #include "testing/ctestutils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(KDevelop::IProject*); using namespace KDevelop; K_PLUGIN_FACTORY_WITH_JSON(CMakeSupportFactory, "kdevcmakemanager.json", registerPlugin(); ) const QString DIALOG_CAPTION = i18n("KDevelop - CMake Support"); CMakeManager::CMakeManager( QObject* parent, const QVariantList& ) : KDevelop::AbstractFileManagerPlugin( "kdevcmakemanager", parent ) , m_filter( new ProjectFilterManager( this ) ) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IBuildSystemManager ) KDEV_USE_EXTENSION_INTERFACE( KDevelop::IProjectFileManager ) KDEV_USE_EXTENSION_INTERFACE( KDevelop::ILanguageSupport ) KDEV_USE_EXTENSION_INTERFACE( ICMakeManager) - if (hasError()) { + if (CMake::findExecutable().isEmpty()) { + setErrorDescription(i18n("Unable to find cmake executable. Is it installed on the system?")); m_highlight = nullptr; return; } m_highlight = new KDevelop::CodeHighlighting(this); new CodeCompletion(this, new CMakeCodeCompletionModel(this), name()); connect(ICore::self()->projectController(), &IProjectController::projectClosing, this, &CMakeManager::projectClosing); connect(this, &KDevelop::AbstractFileManagerPlugin::folderAdded, this, &CMakeManager::folderAdded); // m_fileSystemChangeTimer = new QTimer(this); // m_fileSystemChangeTimer->setSingleShot(true); // m_fileSystemChangeTimer->setInterval(100); // connect(m_fileSystemChangeTimer,SIGNAL(timeout()),SLOT(filesystemBuffererTimeout())); } -bool CMakeManager::hasError() const -{ - return CMake::findExecutable().isEmpty(); -} - -QString CMakeManager::errorDescription() const -{ - return hasError() ? i18n("cmake is not installed") : QString(); -} - CMakeManager::~CMakeManager() { parseLock()->lockForWrite(); // By locking the parse-mutexes, we make sure that parse jobs get a chance to finish in a good state parseLock()->unlock(); } bool CMakeManager::hasBuildInfo(ProjectBaseItem* item) const { return m_projects[item->project()].jsonData.files.contains(item->path()); } Path CMakeManager::buildDirectory(KDevelop::ProjectBaseItem *item) const { // CMakeFolderItem *fi=dynamic_cast(item); // Path ret; // ProjectBaseItem* parent = fi ? fi->formerParent() : item->parent(); // if (parent) // ret=buildDirectory(parent); // else // ret=Path(CMake::currentBuildDir(item->project())); // // if(fi) // ret.addPath(fi->buildDir()); // return ret; return Path(CMake::currentBuildDir(item->project())); } KDevelop::ProjectFolderItem* CMakeManager::import( KDevelop::IProject *project ) { CMake::checkForNeedingConfigure(project); return AbstractFileManagerPlugin::import(project); } KJob* CMakeManager::createImportJob(ProjectFolderItem* item) { auto project = item->project(); QList jobs; // create the JSON file if it doesn't exist auto commandsFile = CMake::commandsFile(project); if (!QFileInfo::exists(commandsFile.toLocalFile())) { qCDebug(CMAKE) << "couldn't find commands file:" << commandsFile << "- now trying to reconfigure"; jobs << builder()->configure(project); } // parse the JSON file CMakeImportJob* job = new CMakeImportJob(project, this); connect(job, &CMakeImportJob::result, this, &CMakeManager::importFinished); jobs << job; // generate the file system listing jobs << KDevelop::AbstractFileManagerPlugin::createImportJob(item); Q_ASSERT(!jobs.contains(nullptr)); ExecuteCompositeJob* composite = new ExecuteCompositeJob(this, jobs); // even if the cmake call failed, we want to load the project so that the project can be worked on composite->setAbortOnError(false); return composite; } // QList CMakeManager::parse(ProjectFolderItem*) // { return QList< ProjectFolderItem* >(); } // // QList CMakeManager::targets() const { QList ret; foreach(IProject* p, m_projects.keys()) { ret+=p->projectItem()->targetList(); } return ret; } CMakeFile CMakeManager::fileInformation(KDevelop::ProjectBaseItem* item) const { const CMakeJsonData & data = m_projects[item->project()].jsonData; QHash::const_iterator it = data.files.constFind(item->path()); if (it == data.files.constEnd()) { // if the item path contains a symlink, then we will not find it in the lookup table // as that only only stores canonicalized paths. Thus, we fallback to // to the canonicalized path and see if that brings up any matches const auto canonicalized = Path(QFileInfo(item->path().toLocalFile()).canonicalFilePath()); it = data.files.constFind(canonicalized); } if (it != data.files.constEnd()) { return *it; } else { // otherwise look for siblings and use the include paths of any we find const Path folder = item->folder() ? item->path() : item->path().parent(); for( it = data.files.constBegin(); it != data.files.constEnd(); ++it) { if (folder.isDirectParentOf(it.key())) { return *it; } } } // last-resort fallback: bubble up the parent chain, and keep looking for include paths if (auto parent = item->parent()) { return fileInformation(parent); } return {}; } Path::List CMakeManager::includeDirectories(KDevelop::ProjectBaseItem *item) const { return fileInformation(item).includes; } Path::List CMakeManager::frameworkDirectories(KDevelop::ProjectBaseItem *item) const { return fileInformation(item).frameworkDirectories; } QHash CMakeManager::defines(KDevelop::ProjectBaseItem *item ) const { return fileInformation(item).defines; } KDevelop::IProjectBuilder * CMakeManager::builder() const { IPlugin* i = core()->pluginController()->pluginForExtension( "org.kdevelop.IProjectBuilder", "KDevCMakeBuilder"); Q_ASSERT(i); KDevelop::IProjectBuilder* _builder = i->extension(); Q_ASSERT(_builder ); return _builder ; } bool CMakeManager::reload(KDevelop::ProjectFolderItem* folder) { qCDebug(CMAKE) << "reloading" << folder->path(); IProject* project = folder->project(); if (!project->isReady()) return false; KJob *job = createImportJob(folder); project->setReloadJob(job); ICore::self()->runController()->registerJob( job ); return true; } static void populateTargets(ProjectFolderItem* folder, const QHash& targets) { QStringList dirTargets = targets[folder->path()]; foreach (ProjectTargetItem* item, folder->targetList()) { if(!dirTargets.contains(item->text())) { delete item; } else { dirTargets.removeAll(item->text()); } } static QSet standardTargets = { QStringLiteral("edit_cache"), QStringLiteral("rebuild_cache"), QStringLiteral("list_install_components"), QStringLiteral("test"), //not really standard, but applicable for make and ninja QStringLiteral("install") }; foreach (const QString& name, dirTargets) { if (!name.endsWith(QLatin1String("_automoc")) && !standardTargets.contains(name) && !name.startsWith(QLatin1String("install/")) ) new CMakeTargetItem(folder, name); } foreach (ProjectFolderItem* children, folder->folderList()) { populateTargets(children, targets); } } void CMakeManager::importFinished(KJob* j) { CMakeImportJob* job = qobject_cast(j); Q_ASSERT(job); auto project = job->project(); if (job->error() != 0) { qCDebug(CMAKE) << "Import failed for project" << project->name() << job->errorText(); m_projects.remove(project); } qCDebug(CMAKE) << "Successfully imported project" << project->name(); CMakeProjectData data; data.watcher->addPath(CMake::commandsFile(project).toLocalFile()); data.watcher->addPath(CMake::targetDirectoriesFile(project).toLocalFile()); data.jsonData = job->jsonData(); data.targets = job->targets(); connect(data.watcher.data(), &QFileSystemWatcher::fileChanged, this, &CMakeManager::dirtyFile); connect(data.watcher.data(), &QFileSystemWatcher::directoryChanged, this, &CMakeManager::dirtyFile); m_projects[job->project()] = data; populateTargets(job->project()->projectItem(), job->targets()); CTestUtils::createTestSuites(job->testSuites(), project); } // void CMakeManager::deletedWatchedDirectory(IProject* p, const QUrl &dir) // { // if(p->folder().equals(dir, QUrl::CompareWithoutTrailingSlash)) { // ICore::self()->projectController()->closeProject(p); // } else { // if(dir.fileName()=="CMakeLists.txt") { // QList folders = p->foldersForUrl(dir.upUrl()); // foreach(ProjectFolderItem* folder, folders) // reload(folder); // } else { // qDeleteAll(p->itemsForUrl(dir)); // } // } // } // void CMakeManager::directoryChanged(const QString& dir) // { // m_fileSystemChangedBuffer << dir; // m_fileSystemChangeTimer->start(); // } // void CMakeManager::filesystemBuffererTimeout() // { // Q_FOREACH(const QString& file, m_fileSystemChangedBuffer) { // realDirectoryChanged(file); // } // m_fileSystemChangedBuffer.clear(); // } // void CMakeManager::realDirectoryChanged(const QString& dir) // { // QUrl path(dir); // IProject* p=ICore::self()->projectController()->findProjectForUrl(dir); // if(!p || !p->isReady()) { // if(p) { // m_fileSystemChangedBuffer << dir; // m_fileSystemChangeTimer->start(); // } // return; // } // // if(!QFile::exists(dir)) { // path.adjustPath(QUrl::AddTrailingSlash); // deletedWatchedDirectory(p, path); // } else // dirtyFile(dir); // } QList< KDevelop::ProjectTargetItem * > CMakeManager::targets(KDevelop::ProjectFolderItem * folder) const { return folder->targetList(); } QString CMakeManager::name() const { return languageName().str(); } IndexedString CMakeManager::languageName() { static IndexedString name("CMake"); return name; } KDevelop::ParseJob * CMakeManager::createParseJob(const IndexedString &url) { return new CMakeParseJob(url, this); } KDevelop::ICodeHighlighting* CMakeManager::codeHighlighting() const { return m_highlight; } // ContextMenuExtension CMakeManager::contextMenuExtension( KDevelop::Context* context ) // { // if( context->type() != KDevelop::Context::ProjectItemContext ) // return IPlugin::contextMenuExtension( context ); // // KDevelop::ProjectItemContext* ctx = dynamic_cast( context ); // QList items = ctx->items(); // // if( items.isEmpty() ) // return IPlugin::contextMenuExtension( context ); // // m_clickedItems = items; // ContextMenuExtension menuExt; // if(items.count()==1 && dynamic_cast(items.first())) // { // QAction * action = new QAction( i18n( "Jump to Target Definition" ), this ); // connect( action, SIGNAL(triggered()), this, SLOT(jumpToDeclaration()) ); // menuExt.addAction( ContextMenuExtension::ProjectGroup, action ); // } // // return menuExt; // } // // void CMakeManager::jumpToDeclaration() // { // DUChainAttatched* du=dynamic_cast(m_clickedItems.first()); // if(du) // { // KTextEditor::Cursor c; // QUrl url; // { // KDevelop::DUChainReadLocker lock; // Declaration* decl = du->declaration().data(); // if(!decl) // return; // c = decl->rangeInCurrentRevision().start(); // url = decl->url().toUrl(); // } // // ICore::self()->documentController()->openDocument(url, c); // } // } // // // TODO: Port to Path API // bool CMakeManager::moveFilesAndFolders(const QList< ProjectBaseItem* > &items, ProjectFolderItem* toFolder) // { // using namespace CMakeEdit; // // ApplyChangesWidget changesWidget; // changesWidget.setCaption(DIALOG_CAPTION); // changesWidget.setInformation(i18n("Move files and folders within CMakeLists as follows:")); // // bool cmakeSuccessful = true; // CMakeFolderItem *nearestCMakeFolderItem = nearestCMakeFolder(toFolder); // IProject* project=toFolder->project(); // // QList movedUrls; // QList oldUrls; // foreach(ProjectBaseItem *movedItem, items) // { // QList dirtyItems = cmakeListedItemsAffectedByUrlChange(project, movedItem->url()); // QUrl movedItemNewUrl = toFolder->url(); // movedItemNewUrl.addPath(movedItem->baseName()); // if (movedItem->folder()) // movedItemNewUrl.adjustPath(QUrl::AddTrailingSlash); // foreach(ProjectBaseItem* dirtyItem, dirtyItems) // { // QUrl dirtyItemNewUrl = afterMoveUrl(dirtyItem->url(), movedItem->url(), movedItemNewUrl); // if (CMakeFolderItem* folder = dynamic_cast(dirtyItem)) // { // cmakeSuccessful &= changesWidgetRemoveCMakeFolder(folder, &changesWidget); // cmakeSuccessful &= changesWidgetAddFolder(dirtyItemNewUrl, nearestCMakeFolderItem, &changesWidget); // } // else if (dirtyItem->parent()->target()) // { // cmakeSuccessful &= changesWidgetMoveTargetFile(dirtyItem, dirtyItemNewUrl, &changesWidget); // } // } // // oldUrls += movedItem->url(); // movedUrls += movedItemNewUrl; // } // // if (changesWidget.hasDocuments() && cmakeSuccessful) // cmakeSuccessful &= changesWidget.exec() && changesWidget.applyAllChanges(); // // if (!cmakeSuccessful) // { // if (KMessageBox::questionYesNo( QApplication::activeWindow(), // i18n("Changes to CMakeLists failed, abort move?"), // DIALOG_CAPTION ) == KMessageBox::Yes) // return false; // } // // QList::const_iterator it1=oldUrls.constBegin(), it1End=oldUrls.constEnd(); // QList::const_iterator it2=movedUrls.constBegin(); // Q_ASSERT(oldUrls.size()==movedUrls.size()); // for(; it1!=it1End; ++it1, ++it2) // { // if (!KDevelop::renameUrl(project, *it1, *it2)) // return false; // // QList renamedItems = project->itemsForUrl(*it2); // bool dir = QFileInfo(it2->toLocalFile()).isDir(); // foreach(ProjectBaseItem* item, renamedItems) { // if(dir) // emit folderRenamed(Path(*it1), item->folder()); // else // emit fileRenamed(Path(*it1), item->file()); // } // } // // return true; // } // // bool CMakeManager::copyFilesAndFolders(const KDevelop::Path::List &items, KDevelop::ProjectFolderItem* toFolder) // { // IProject* project = toFolder->project(); // foreach(const Path& path, items) { // if (!KDevelop::copyUrl(project, path.toUrl(), toFolder->url())) // return false; // } // // return true; // } // // bool CMakeManager::removeFilesAndFolders(const QList &items) // { // using namespace CMakeEdit; // // IProject* p = 0; // QList urls; // foreach(ProjectBaseItem* item, items) // { // Q_ASSERT(item->folder() || item->file()); // // urls += item->url(); // if(!p) // p = item->project(); // } // // //First do CMakeLists changes // ApplyChangesWidget changesWidget; // changesWidget.setCaption(DIALOG_CAPTION); // changesWidget.setInformation(i18n("Remove files and folders from CMakeLists as follows:")); // // bool cmakeSuccessful = changesWidgetRemoveItems(cmakeListedItemsAffectedByItemsChanged(items).toSet(), &changesWidget); // // if (changesWidget.hasDocuments() && cmakeSuccessful) // cmakeSuccessful &= changesWidget.exec() && changesWidget.applyAllChanges(); // // if (!cmakeSuccessful) // { // if (KMessageBox::questionYesNo( QApplication::activeWindow(), // i18n("Changes to CMakeLists failed, abort deletion?"), // DIALOG_CAPTION ) == KMessageBox::Yes) // return false; // } // // bool ret = true; // //Then delete the files/folders // foreach(const QUrl& file, urls) // { // ret &= KDevelop::removeUrl(p, file, QDir(file.toLocalFile()).exists()); // } // // return ret; // } bool CMakeManager::removeFilesFromTargets(const QList &/*files*/) { // using namespace CMakeEdit; // // ApplyChangesWidget changesWidget; // changesWidget.setCaption(DIALOG_CAPTION); // changesWidget.setInformation(i18n("Modify project targets as follows:")); // // if (!files.isEmpty() && // changesWidgetRemoveFilesFromTargets(files, &changesWidget) && // changesWidget.exec() && // changesWidget.applyAllChanges()) { // return true; // } return false; } // ProjectFolderItem* CMakeManager::addFolder(const Path& folder, ProjectFolderItem* parent) // { // using namespace CMakeEdit; // // CMakeFolderItem *cmakeParent = nearestCMakeFolder(parent); // if(!cmakeParent) // return 0; // // ApplyChangesWidget changesWidget; // changesWidget.setCaption(DIALOG_CAPTION); // changesWidget.setInformation(i18n("Create folder '%1':", folder.lastPathSegment())); // // ///FIXME: use path in changes widget // changesWidgetAddFolder(folder.toUrl(), cmakeParent, &changesWidget); // // if(changesWidget.exec() && changesWidget.applyAllChanges()) // { // if(KDevelop::createFolder(folder.toUrl())) { //If saved we create the folder then the CMakeLists.txt file // Path newCMakeLists(folder, "CMakeLists.txt"); // KDevelop::createFile( newCMakeLists.toUrl() ); // } else // KMessageBox::error(0, i18n("Could not save the change."), // DIALOG_CAPTION); // } // // return 0; // } // // KDevelop::ProjectFileItem* CMakeManager::addFile( const Path& file, KDevelop::ProjectFolderItem* parent) // { // KDevelop::ProjectFileItem* created = 0; // if ( KDevelop::createFile(file.toUrl()) ) { // QList< ProjectFileItem* > files = parent->project()->filesForPath(IndexedString(file.pathOrUrl())); // if(!files.isEmpty()) // created = files.first(); // else // created = new KDevelop::ProjectFileItem( parent->project(), file, parent ); // } // return created; // } bool CMakeManager::addFilesToTarget(const QList< ProjectFileItem* > &/*_files*/, ProjectTargetItem* /*target*/) { return false; // using namespace CMakeEdit; // // const QSet headerExt = QSet() << ".h" << ".hpp" << ".hxx"; // QList< ProjectFileItem* > files = _files; // for (int i = files.count() - 1; i >= 0; --i) // { // QString fileName = files[i]->fileName(); // QString fileExt = fileName.mid(fileName.lastIndexOf('.')); // QList sameUrlItems = files[i]->project()->itemsForUrl(files[i]->url()); // if (headerExt.contains(fileExt)) // files.removeAt(i); // else foreach(ProjectBaseItem* item, sameUrlItems) // { // if (item->parent() == target) // { // files.removeAt(i); // break; // } // } // } // // if(files.isEmpty()) // return true; // // ApplyChangesWidget changesWidget; // changesWidget.setCaption(DIALOG_CAPTION); // changesWidget.setInformation(i18n("Modify target '%1' as follows:", target->baseName())); // // bool success = changesWidgetAddFilesToTarget(files, target, &changesWidget) && // changesWidget.exec() && // changesWidget.applyAllChanges(); // // if(!success) // KMessageBox::error(0, i18n("CMakeLists changes failed."), DIALOG_CAPTION); // // return success; } // bool CMakeManager::renameFileOrFolder(ProjectBaseItem *item, const Path &newPath) // { // using namespace CMakeEdit; // // ApplyChangesWidget changesWidget; // changesWidget.setCaption(DIALOG_CAPTION); // changesWidget.setInformation(i18n("Rename '%1' to '%2':", item->text(), // newPath.lastPathSegment())); // // bool cmakeSuccessful = true, changedCMakeLists=false; // IProject* project=item->project(); // const Path oldPath=item->path(); // QUrl oldUrl=oldPath.toUrl(); // if (item->file()) // { // QList targetFiles = cmakeListedItemsAffectedByUrlChange(project, oldUrl); // foreach(ProjectBaseItem* targetFile, targetFiles) // ///FIXME: use path in changes widget // cmakeSuccessful &= changesWidgetMoveTargetFile(targetFile, newPath.toUrl(), &changesWidget); // } // else if (CMakeFolderItem *folder = dynamic_cast(item)) // ///FIXME: use path in changes widget // cmakeSuccessful &= changesWidgetRenameFolder(folder, newPath.toUrl(), &changesWidget); // // item->setPath(newPath); // if (changesWidget.hasDocuments() && cmakeSuccessful) { // changedCMakeLists = changesWidget.exec() && changesWidget.applyAllChanges(); // cmakeSuccessful &= changedCMakeLists; // } // // if (!cmakeSuccessful) // { // if (KMessageBox::questionYesNo( QApplication::activeWindow(), // i18n("Changes to CMakeLists failed, abort rename?"), // DIALOG_CAPTION ) == KMessageBox::Yes) // return false; // } // // bool ret = KDevelop::renameUrl(project, oldUrl, newPath.toUrl()); // if(!ret) { // item->setPath(oldPath); // } // return ret; // } // // bool CMakeManager::renameFile(ProjectFileItem *item, const Path &newPath) // { // return renameFileOrFolder(item, newPath); // } // // bool CMakeManager::renameFolder(ProjectFolderItem* item, const Path &newPath) // { // return renameFileOrFolder(item, newPath); // } QWidget* CMakeManager::specialLanguageObjectNavigationWidget(const QUrl &url, const KTextEditor::Cursor& position) { KDevelop::TopDUContextPointer top= TopDUContextPointer(KDevelop::DUChain::self()->chainForDocument(url)); Declaration *decl=0; if(top) { int useAt=top->findUseAt(top->transformToLocalRevision(position)); if(useAt>=0) { Use u=top->uses()[useAt]; decl=u.usedDeclaration(top->topContext()); } } CMakeNavigationWidget* doc=0; if(decl) { doc=new CMakeNavigationWidget(top, decl); } else { const IDocument* d=ICore::self()->documentController()->documentForUrl(url); const KTextEditor::Document* e=d->textDocument(); KTextEditor::Cursor start=position, end=position, step(0,1); for(QChar i=e->characterAt(start); i.isLetter() || i=='_'; i=e->characterAt(start-=step)) {} start+=step; for(QChar i=e->characterAt(end); i.isLetter() || i=='_'; i=e->characterAt(end+=step)) {} QString id=e->text(KTextEditor::Range(start, end)); ICMakeDocumentation* docu=CMake::cmakeDocumentation(); if( docu ) { IDocumentation::Ptr desc=docu->description(id, url); if(desc) { doc=new CMakeNavigationWidget(top, desc); } } } return doc; } QPair CMakeManager::cacheValue(KDevelop::IProject* /*project*/, const QString& /*id*/) const { return QPair(); } // { // QPair ret; // if(project==0 && !m_projectsData.isEmpty()) // { // project=m_projectsData.keys().first(); // } // // // qCDebug(CMAKE) << "cache value " << id << project << (m_projectsData.contains(project) && m_projectsData[project].cache.contains(id)); // CMakeProjectData* data = m_projectsData[project]; // if(data && data->cache.contains(id)) // { // const CacheEntry& e=data->cache.value(id); // ret.first=e.value; // ret.second=e.doc; // } // return ret; // }Add // void CMakeManager::projectClosing(IProject* p) { m_projects.remove(p); // delete m_projectsData.take(p); // delete m_watchers.take(p); // // m_filter->remove(p); // // qCDebug(CMAKE) << "Project closed" << p; } // // QStringList CMakeManager::processGeneratorExpression(const QStringList& expr, IProject* project, ProjectTargetItem* target) const // { // QStringList ret; // const CMakeProjectData* data = m_projectsData[project]; // GenerationExpressionSolver exec(data->properties, data->targetAlias); // if(target) // exec.setTargetName(target->text()); // // exec.defineVariable("INSTALL_PREFIX", data->vm.value("CMAKE_INSTALL_PREFIX").join(QString())); // for(QStringList::const_iterator it = expr.constBegin(), itEnd = expr.constEnd(); it!=itEnd; ++it) { // QStringList val = exec.run(*it).split(';'); // ret += val; // } // return ret; // } /* void CMakeManager::addPending(const Path& path, CMakeFolderItem* folder) { m_pending.insert(path, folder); } CMakeFolderItem* CMakeManager::takePending(const Path& path) { return m_pending.take(path); } void CMakeManager::addWatcher(IProject* p, const QString& path) { if (QFileSystemWatcher* watcher = m_watchers.value(p)) { watcher->addPath(path); } else { qWarning() << "Could not find a watcher for project" << p << p->name() << ", path " << path; Q_ASSERT(false); } }*/ // CMakeProjectData CMakeManager::projectData(IProject* project) // { // Q_ASSERT(QThread::currentThread() == project->thread()); // CMakeProjectData* data = m_projectsData[project]; // if(!data) { // data = new CMakeProjectData; // m_projectsData[project] = data; // } // return *data; // } ProjectFilterManager* CMakeManager::filterManager() const { return m_filter; } void CMakeManager::dirtyFile(const QString& path) { qCDebug(CMAKE) << "dirty!" << path; //we initialize again hte project that sent the signal for(QHash::const_iterator it = m_projects.constBegin(), itEnd = m_projects.constEnd(); it!=itEnd; ++it) { if(it->watcher == sender()) { reload(it.key()->projectItem()); break; } } } void CMakeManager::folderAdded(KDevelop::ProjectFolderItem* folder) { populateTargets(folder, m_projects[folder->project()].targets); } ProjectFolderItem* CMakeManager::createFolderItem(IProject* project, const Path& path, ProjectBaseItem* parent) { // TODO: when we have data about targets, use folders with targets or similar if (QFile::exists(path.toLocalFile()+"/CMakeLists.txt")) return new KDevelop::ProjectBuildFolderItem( project, path, parent ); else return KDevelop::AbstractFileManagerPlugin::createFolderItem(project, path, parent); } int CMakeManager::perProjectConfigPages() const { return 1; } ConfigPage* CMakeManager::perProjectConfigPage(int number, const ProjectConfigOptions& options, QWidget* parent) { if (number == 0) { return new CMakePreferences(this, options, parent); } return nullptr; } #include "cmakemanager.moc" diff --git a/projectmanagers/cmake/cmakemanager.h b/projectmanagers/cmake/cmakemanager.h index 0a6571e863..9a1b2be7fc 100644 --- a/projectmanagers/cmake/cmakemanager.h +++ b/projectmanagers/cmake/cmakemanager.h @@ -1,171 +1,168 @@ /* KDevelop CMake Support * * Copyright 2006 Matt Rogers * Copyright 2007-2009 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef CMAKEMANAGER_H #define CMAKEMANAGER_H #include #include #include #include #include #include #include #include #include #include #include "cmakeprojectdata.h" #include "icmakemanager.h" #include "cmakeprojectvisitor.h" class WaitAllJobs; class CMakeCommitChangesJob; struct CMakeProjectData; class QStandardItem; class QDir; class QObject; class CMakeHighlighting; class CMakeDocumentation; namespace KDevelop { class IProject; class IProjectBuilder; class ICodeHighlighting; class ProjectFolderItem; class ProjectBaseItem; class ProjectFileItem; class ProjectTargetItem; class ProjectFilterManager; class IProjectFilter; class ParseJob; class ContextMenuExtension; class Context; } class CMakeFolderItem; class CMakeManager : public KDevelop::AbstractFileManagerPlugin , public KDevelop::IBuildSystemManager , public KDevelop::ILanguageSupport , public ICMakeManager { Q_OBJECT Q_INTERFACES( KDevelop::IBuildSystemManager ) Q_INTERFACES( KDevelop::IProjectFileManager ) Q_INTERFACES( KDevelop::ILanguageSupport ) Q_INTERFACES( ICMakeManager ) public: explicit CMakeManager( QObject* parent = 0, const QVariantList& args = QVariantList() ); ~CMakeManager() override; - bool hasError() const override; - QString errorDescription() const override; - Features features() const override { return Features(Folders | Targets | Files ); } KDevelop::IProjectBuilder* builder() const override; bool hasBuildInfo(KDevelop::ProjectBaseItem*) const override; KDevelop::Path buildDirectory(KDevelop::ProjectBaseItem*) const override; KDevelop::Path::List includeDirectories(KDevelop::ProjectBaseItem *) const override; KDevelop::Path::List frameworkDirectories(KDevelop::ProjectBaseItem *item) const override; QHash defines(KDevelop::ProjectBaseItem *) const override; KDevelop::ProjectTargetItem* createTarget( const QString&, KDevelop::ProjectFolderItem* ) override { return 0; } virtual QList targets() const; QList targets(KDevelop::ProjectFolderItem* folder) const override; // virtual KDevelop::ProjectFolderItem* addFolder( const KDevelop::Path& folder, KDevelop::ProjectFolderItem* parent ); // virtual KDevelop::ProjectFileItem* addFile( const KDevelop::Path&, KDevelop::ProjectFolderItem* ); bool addFilesToTarget( const QList &files, KDevelop::ProjectTargetItem* target) override; bool removeTarget( KDevelop::ProjectTargetItem* ) override { return false; } bool removeFilesFromTargets( const QList &files ) override; // virtual bool removeFilesAndFolders( const QList &items); // // virtual bool renameFile(KDevelop::ProjectFileItem*, const KDevelop::Path&); // virtual bool renameFolder(KDevelop::ProjectFolderItem*, const KDevelop::Path&); // virtual bool moveFilesAndFolders(const QList< KDevelop::ProjectBaseItem* > &items, KDevelop::ProjectFolderItem *newParent); // virtual bool copyFilesAndFolders(const KDevelop::Path::List &items, KDevelop::ProjectFolderItem* newParent); // // virtual QList parse( KDevelop::ProjectFolderItem* dom ); KDevelop::ProjectFolderItem* import( KDevelop::IProject *project ) override; KJob* createImportJob(KDevelop::ProjectFolderItem* item) override; // bool reload(KDevelop::ProjectFolderItem*) override; // // virtual KDevelop::ContextMenuExtension contextMenuExtension( KDevelop::Context* context ); KDevelop::ProjectFolderItem* createFolderItem(KDevelop::IProject* project, const KDevelop::Path& path, KDevelop::ProjectBaseItem* parent = 0) override; QPair cacheValue(KDevelop::IProject* project, const QString& id) const override; //LanguageSupport QString name() const override; KDevelop::ParseJob *createParseJob(const KDevelop::IndexedString &url) override; KDevelop::ICodeHighlighting* codeHighlighting() const override; QWidget* specialLanguageObjectNavigationWidget(const QUrl &url, const KTextEditor::Cursor& position) override; // void addPending(const KDevelop::Path& path, CMakeFolderItem* folder); // CMakeFolderItem* takePending(const KDevelop::Path& path); // void addWatcher(KDevelop::IProject* p, const QString& path); // CMakeProjectData projectData(KDevelop::IProject* project); KDevelop::ProjectFilterManager* filterManager() const; static KDevelop::IndexedString languageName(); int perProjectConfigPages() const override; KDevelop::ConfigPage* perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent) override; signals: void folderRenamed(const KDevelop::Path& oldFolder, KDevelop::ProjectFolderItem* newFolder); void fileRenamed(const KDevelop::Path& oldFile, KDevelop::ProjectFileItem* newFile); private slots: // void dirtyFile(const QString& file); // // void jumpToDeclaration(); void projectClosing(KDevelop::IProject*); void dirtyFile(const QString& file); // // void directoryChanged(const QString& dir); // void filesystemBuffererTimeout(); void importFinished(KJob* job); private: CMakeFile fileInformation(KDevelop::ProjectBaseItem* item) const; void folderAdded(KDevelop::ProjectFolderItem* folder); QHash m_projects; KDevelop::ProjectFilterManager* m_filter; KDevelop::ICodeHighlighting* m_highlight; }; #endif