diff options
Diffstat (limited to 'src/plugins/cmakeprojectmanager')
54 files changed, 1353 insertions, 1613 deletions
diff --git a/src/plugins/cmakeprojectmanager/CMakeLists.txt b/src/plugins/cmakeprojectmanager/CMakeLists.txt new file mode 100644 index 0000000000..6062e40d53 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/CMakeLists.txt @@ -0,0 +1,42 @@ +add_qtc_plugin(CMakeProjectManager + DEPENDS qmljs + PLUGIN_DEPENDS Core CppTools ProjectExplorer TextEditor QtSupport + PLUGIN_RECOMMENDS Designer + SOURCES + builddirmanager.cpp builddirmanager.h + builddirparameters.cpp builddirparameters.h + builddirreader.cpp builddirreader.h + cmake_global.h + cmakeautocompleter.cpp cmakeautocompleter.h + cmakebuildconfiguration.cpp cmakebuildconfiguration.h + cmakebuildsettingswidget.cpp cmakebuildsettingswidget.h + cmakebuildstep.cpp cmakebuildstep.h + cmakebuildtarget.h + cmakecbpparser.cpp cmakecbpparser.h + cmakeconfigitem.cpp cmakeconfigitem.h + cmakeeditor.cpp cmakeeditor.h + cmakefilecompletionassist.cpp cmakefilecompletionassist.h + cmakeindenter.cpp cmakeindenter.h + cmakekitinformation.cpp cmakekitinformation.h + cmakelocatorfilter.cpp cmakelocatorfilter.h + cmakeparser.cpp cmakeparser.h + cmakeproject.cpp cmakeproject.h + cmakeproject.qrc + cmakeprojectconstants.h + cmakeprojectimporter.cpp cmakeprojectimporter.h + cmakeprojectmanager.cpp cmakeprojectmanager.h + cmakeprojectnodes.cpp cmakeprojectnodes.h + cmakeprojectplugin.cpp cmakeprojectplugin.h + cmakerunconfiguration.cpp cmakerunconfiguration.h + cmakesettingspage.cpp cmakesettingspage.h + cmakespecificsettings.cpp cmakespecificsettings.h + cmakespecificsettingspage.cpp cmakespecificsettingspage.h cmakespecificsettingspage.ui + cmaketool.cpp cmaketool.h + cmaketoolmanager.cpp cmaketoolmanager.h + cmaketoolsettingsaccessor.cpp cmaketoolsettingsaccessor.h + configmodel.cpp configmodel.h + configmodelitemdelegate.cpp configmodelitemdelegate.h + servermode.cpp servermode.h + servermodereader.cpp servermodereader.h + tealeafreader.cpp tealeafreader.h +) diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index f17e356509..490082d517 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -50,6 +50,7 @@ #include <QSet> using namespace ProjectExplorer; +using namespace Utils; namespace CMakeProjectManager { namespace Internal { @@ -61,9 +62,9 @@ namespace Internal { BuildDirManager::BuildDirManager() = default; BuildDirManager::~BuildDirManager() = default; -Utils::FileName BuildDirManager::workDirectory(const BuildDirParameters ¶meters) const +Utils::FilePath BuildDirManager::workDirectory(const BuildDirParameters ¶meters) const { - const Utils::FileName bdir = parameters.buildDirectory; + const Utils::FilePath bdir = parameters.buildDirectory; const CMakeTool *cmake = parameters.cmakeTool(); if (bdir.exists()) { m_buildDirToTempDir.erase(bdir); @@ -87,7 +88,7 @@ Utils::FileName BuildDirManager::workDirectory(const BuildDirParameters ¶met return bdir; } } - return Utils::FileName::fromString(tmpDirIt->second->path()); + return Utils::FilePath::fromString(tmpDirIt->second->path()); } void BuildDirManager::emitDataAvailable() @@ -260,7 +261,7 @@ bool BuildDirManager::persistCMakeState() if (m_parameters.workDirectory == m_parameters.buildDirectory) return false; - const Utils::FileName buildDir = m_parameters.buildDirectory; + const Utils::FilePath buildDir = m_parameters.buildDirectory; QDir dir(buildDir.toString()); dir.mkpath(buildDir.toString()); @@ -310,8 +311,8 @@ void BuildDirManager::clearCache() QTC_ASSERT(m_parameters.isValid(), return); QTC_ASSERT(!m_isHandlingError, return); - auto cmakeCache = m_parameters.workDirectory.appendPath("CMakeCache.txt"); - auto cmakeFiles = m_parameters.workDirectory.appendPath("CMakeFiles"); + const FilePath cmakeCache = m_parameters.workDirectory.pathAppended("CMakeCache.txt"); + const FilePath cmakeFiles = m_parameters.workDirectory.pathAppended("CMakeFiles"); const bool mustCleanUp = cmakeCache.exists() || cmakeFiles.exists(); if (!mustCleanUp) @@ -366,7 +367,7 @@ CMakeConfig BuildDirManager::takeCMakeConfiguration() const return result; } -CMakeConfig BuildDirManager::parseCMakeConfiguration(const Utils::FileName &cacheFile, +CMakeConfig BuildDirManager::parseCMakeConfiguration(const Utils::FilePath &cacheFile, QString *errorMessage) { if (!cacheFile.exists()) { @@ -413,7 +414,7 @@ bool BuildDirManager::checkConfiguration() QStringList keyList = changedKeys.keys(); Utils::sort(keyList); QString table = QString::fromLatin1("<table><tr><th>%1</th><th>%2</th><th>%3</th></tr>") - .arg(tr("Key")).arg(tr("CMake")).arg(tr("Project")); + .arg(tr("Key")).arg(tr("CMakeCache.txt")).arg(tr("Project")); foreach (const QString &k, keyList) { const QPair<QString, QString> data = changedKeys.value(k); table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td><td>%3</td></tr>") @@ -426,7 +427,7 @@ bool BuildDirManager::checkConfiguration() QPointer<QMessageBox> box = new QMessageBox(Core::ICore::mainWindow()); box->setText(tr("CMake configuration has changed on disk.")); box->setInformativeText(table); - auto *defaultButton = box->addButton(tr("Overwrite Changes in CMake"), QMessageBox::RejectRole); + auto *defaultButton = box->addButton(tr("Overwrite Changes in CMakeCache.txt"), QMessageBox::RejectRole); auto *applyButton = box->addButton(tr("Apply Changes to Project"), QMessageBox::ApplyRole); box->setDefaultButton(defaultButton); diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h index d55e05aed2..e2f9b8ff05 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.h +++ b/src/plugins/cmakeprojectmanager/builddirmanager.h @@ -81,7 +81,7 @@ public: QList<CMakeBuildTarget> takeBuildTargets() const; CMakeConfig takeCMakeConfiguration() const; - static CMakeConfig parseCMakeConfiguration(const Utils::FileName &cacheFile, + static CMakeConfig parseCMakeConfiguration(const Utils::FilePath &cacheFile, QString *errorMessage); enum ReparseParameters { REPARSE_DEFAULT = 0, // use defaults @@ -104,7 +104,7 @@ private: void emitErrorOccured(const QString &message) const; bool checkConfiguration(); - Utils::FileName workDirectory(const BuildDirParameters ¶meters) const; + Utils::FilePath workDirectory(const BuildDirParameters ¶meters) const; void updateReaderType(const BuildDirParameters &p, std::function<void()> todo); @@ -114,7 +114,7 @@ private: void becameDirty(); BuildDirParameters m_parameters; - mutable std::unordered_map<Utils::FileName, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir; + mutable std::unordered_map<Utils::FilePath, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir; mutable std::unique_ptr<BuildDirReader> m_reader; mutable bool m_isHandlingError = false; }; diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.cpp b/src/plugins/cmakeprojectmanager/builddirparameters.cpp index f4377d42ae..160b50bef1 100644 --- a/src/plugins/cmakeprojectmanager/builddirparameters.cpp +++ b/src/plugins/cmakeprojectmanager/builddirparameters.cpp @@ -61,25 +61,25 @@ BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc) if (Utils::HostOsInfo::isAnyUnixHost()) environment.set("ICECC", "no"); - cmakeToolId = CMakeKitInformation::cmakeToolId(k); + cmakeToolId = CMakeKitAspect::cmakeToolId(k); - auto tc = ToolChainKitInformation::toolChain(k, Constants::CXX_LANGUAGE_ID); + auto tc = ToolChainKitAspect::toolChain(k, Constants::CXX_LANGUAGE_ID); if (tc) cxxToolChainId = tc->id(); - tc = ToolChainKitInformation::toolChain(k, Constants::C_LANGUAGE_ID); + tc = ToolChainKitAspect::toolChain(k, Constants::C_LANGUAGE_ID); if (tc) cToolChainId = tc->id(); - sysRoot = SysRootKitInformation::sysRoot(k); + sysRoot = SysRootKitAspect::sysRoot(k); expander = k->macroExpander(); configuration = bc->configurationForCMake(); - generator = CMakeGeneratorKitInformation::generator(k); - extraGenerator = CMakeGeneratorKitInformation::extraGenerator(k); - platform = CMakeGeneratorKitInformation::platform(k); - toolset = CMakeGeneratorKitInformation::toolset(k); - generatorArguments = CMakeGeneratorKitInformation::generatorArguments(k); + generator = CMakeGeneratorKitAspect::generator(k); + extraGenerator = CMakeGeneratorKitAspect::extraGenerator(k); + platform = CMakeGeneratorKitAspect::platform(k); + toolset = CMakeGeneratorKitAspect::toolset(k); + generatorArguments = CMakeGeneratorKitAspect::generatorArguments(k); } bool BuildDirParameters::isValid() const { return buildConfiguration && cmakeTool(); } @@ -90,6 +90,7 @@ CMakeTool *BuildDirParameters::cmakeTool() const } BuildDirParameters::BuildDirParameters(const BuildDirParameters &) = default; +BuildDirParameters &BuildDirParameters::operator=(const BuildDirParameters &) = default; } // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.h b/src/plugins/cmakeprojectmanager/builddirparameters.h index 92f5f16eee..d0bd9dd783 100644 --- a/src/plugins/cmakeprojectmanager/builddirparameters.h +++ b/src/plugins/cmakeprojectmanager/builddirparameters.h @@ -44,6 +44,7 @@ public: BuildDirParameters(); BuildDirParameters(CMakeBuildConfiguration *bc); BuildDirParameters(const BuildDirParameters &other); + BuildDirParameters &operator=(const BuildDirParameters &other); bool isValid() const; CMakeTool *cmakeTool() const; @@ -51,16 +52,16 @@ public: CMakeBuildConfiguration *buildConfiguration = nullptr; QString projectName; - Utils::FileName sourceDirectory; - Utils::FileName buildDirectory; - Utils::FileName workDirectory; // either buildDirectory or a QTemporaryDirectory! + Utils::FilePath sourceDirectory; + Utils::FilePath buildDirectory; + Utils::FilePath workDirectory; // either buildDirectory or a QTemporaryDirectory! Utils::Environment environment; Core::Id cmakeToolId; QByteArray cxxToolChainId; QByteArray cToolChainId; - Utils::FileName sysRoot; + Utils::FilePath sysRoot; Utils::MacroExpander *expander = nullptr; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 1deb85b1d1..f7cfa7f33f 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -34,6 +34,8 @@ #include "cmakeprojectmanager.h" #include "cmakeprojectnodes.h" +#include <android/androidconstants.h> + #include <coreplugin/icore.h> #include <projectexplorer/buildinfo.h> @@ -91,6 +93,37 @@ void CMakeBuildConfiguration::initialize(const BuildInfo &info) BuildStepList *buildSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD); buildSteps->appendStep(new CMakeBuildStep(buildSteps)); + if (DeviceTypeKitAspect::deviceTypeId(target()->kit()) + == Android::Constants::ANDROID_DEVICE_TYPE) { + buildSteps->appendStep(Android::Constants::ANDROID_BUILD_APK_ID); + const auto &bs = buildSteps->steps().constLast(); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_NATIVE_API_LEVEL", + CMakeProjectManager::CMakeConfigItem::Type::STRING, + "Android native API level", + bs->data(Android::Constants::AndroidNdkPlatform).toString().toUtf8()}); + auto ndkLocation = bs->data(Android::Constants::NdkLocation).value<FilePath>(); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_NDK", + CMakeProjectManager::CMakeConfigItem::Type::PATH, + "Android NDK PATH", + ndkLocation.toUserOutput().toUtf8()}); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_TOOLCHAIN_FILE", + CMakeProjectManager::CMakeConfigItem::Type::PATH, + "Android CMake toolchain file", + ndkLocation.pathAppended("build/cmake/android.toolchain.cmake").toUserOutput().toUtf8()}); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_ABI", + CMakeProjectManager::CMakeConfigItem::Type::STRING, + "Android ABI", + bs->data(Android::Constants::AndroidABI).toString().toUtf8()}); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_STL", + CMakeProjectManager::CMakeConfigItem::Type::STRING, + "Android STL", + "c++_shared"}); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_PROGRAM", "BOTH"}); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY", "BOTH"}); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_INCLUDE", "BOTH"}); + m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_PACKAGE", "BOTH"}); + } + BuildStepList *cleanSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN); cleanSteps->appendStep(new CMakeBuildStep(cleanSteps)); @@ -159,23 +192,22 @@ bool CMakeBuildConfiguration::isParsing() const return project()->isParsing() && isActive(); } -BuildTargetInfoList CMakeBuildConfiguration::appTargets() const +const QList<BuildTargetInfo> CMakeBuildConfiguration::appTargets() const { - BuildTargetInfoList appTargetList; - + QList<BuildTargetInfo> appTargetList; + bool forAndroid = DeviceTypeKitAspect::deviceTypeId(target()->kit()) == Android::Constants::ANDROID_DEVICE_TYPE; for (const CMakeBuildTarget &ct : m_buildTargets) { if (ct.targetType == UtilityType) continue; - if (ct.targetType == ExecutableType) { + if (ct.targetType == ExecutableType || (forAndroid && ct.targetType == DynamicLibraryType)) { BuildTargetInfo bti; bti.displayName = ct.title; bti.targetFilePath = ct.executable; - bti.projectFilePath = ct.sourceDirectory; - bti.projectFilePath.appendString('/'); + bti.projectFilePath = ct.sourceDirectory.stringAppended("/"); bti.workingDirectory = ct.workingDirectory; - bti.buildKey = ct.title + QChar('\n') + bti.projectFilePath.toString(); - appTargetList.list.append(bti); + bti.buildKey = CMakeTargetNode::generateId(ct.sourceDirectory, ct.title); + appTargetList.append(bti); } } @@ -197,11 +229,11 @@ DeploymentData CMakeBuildConfiguration::deploymentData() const deploymentFilePath = buildDir.filePath("QtCreatorDeployment.txt"); hasDeploymentFile = QFileInfo::exists(deploymentFilePath); } - if (hasDeploymentFile) { - deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath, - sourceDir.absolutePath()); - } + if (!hasDeploymentFile) + return result; + deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath, + sourceDir.absolutePath()); for (const CMakeBuildTarget &ct : m_buildTargets) { if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) { if (!ct.executable.isEmpty() @@ -221,20 +253,25 @@ QStringList CMakeBuildConfiguration::buildTargetTitles() const return transform(m_buildTargets, &CMakeBuildTarget::title); } -FileName CMakeBuildConfiguration::shadowBuildDirectory(const FileName &projectFilePath, +const QList<CMakeBuildTarget> &CMakeBuildConfiguration::buildTargets() const +{ + return m_buildTargets; +} + +FilePath CMakeBuildConfiguration::shadowBuildDirectory(const FilePath &projectFilePath, const Kit *k, const QString &bcName, BuildConfiguration::BuildType buildType) { if (projectFilePath.isEmpty()) - return FileName(); + return FilePath(); const QString projectName = projectFilePath.parentDir().fileName(); ProjectMacroExpander expander(projectFilePath.toString(), projectName, k, bcName, buildType); QDir projectDir = QDir(Project::projectDirectory(projectFilePath).toString()); QString buildPath = expander.expand(ProjectExplorerPlugin::buildDirectoryTemplate()); buildPath.replace(" ", "-"); - return FileName::fromUserInput(projectDir.absoluteFilePath(buildPath)); + return FilePath::fromUserInput(projectDir.absoluteFilePath(buildPath)); } void CMakeBuildConfiguration::buildTarget(const QString &buildTarget) @@ -342,10 +379,14 @@ static CMakeConfig removeDuplicates(const CMakeConfig &config) void CMakeBuildConfiguration::setConfigurationForCMake(const CMakeConfig &config) { - m_configurationForCMake = removeDuplicates(config); + auto configs = removeDuplicates(config); + if (m_configurationForCMake.isEmpty()) + m_configurationForCMake = removeDuplicates(configs + m_initialConfiguration); + else + m_configurationForCMake = configs; const Kit *k = target()->kit(); - CMakeConfig kitConfig = CMakeConfigurationKitInformation::configuration(k); + CMakeConfig kitConfig = CMakeConfigurationKitAspect::configuration(k); bool hasKitOverride = false; foreach (const CMakeConfigItem &i, m_configurationForCMake) { const QString b = CMakeConfigItem::expandedValueOf(k, i.key, kitConfig); @@ -365,7 +406,7 @@ void CMakeBuildConfiguration::setConfigurationForCMake(const CMakeConfig &config CMakeConfig CMakeBuildConfiguration::configurationForCMake() const { - return removeDuplicates(CMakeConfigurationKitInformation::configuration(target()->kit()) + m_configurationForCMake); + return removeDuplicates(CMakeConfigurationKitAspect::configuration(target()->kit()) + m_configurationForCMake); } void CMakeBuildConfiguration::setError(const QString &message) @@ -455,17 +496,12 @@ QList<BuildInfo> CMakeBuildConfigurationFactory::availableBuilds(const Target *p QList<BuildInfo> CMakeBuildConfigurationFactory::availableSetups(const Kit *k, const QString &projectPath) const { QList<BuildInfo> result; - const FileName projectPathName = FileName::fromString(projectPath); - for (int type = BuildTypeNone; type != BuildTypeLast; ++type) { + const FilePath projectPathName = FilePath::fromString(projectPath); + for (int type = BuildTypeDebug; type != BuildTypeLast; ++type) { BuildInfo info = createBuildInfo(k, ProjectExplorer::Project::projectDirectory(projectPathName).toString(), BuildType(type)); - if (type == BuildTypeNone) { - //: The name of the build configuration created by default for a cmake project. - info.displayName = tr("Default"); - } else { - info.displayName = info.typeName; - } + info.displayName = info.typeName; info.buildDirectory = CMakeBuildConfiguration::shadowBuildDirectory(projectPathName, k, info.displayName, info.buildType); @@ -517,10 +553,10 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(const Kit *k, if (!buildTypeItem.isNull()) extra.configuration.append(buildTypeItem); - const QString sysRoot = SysRootKitInformation::sysRoot(k).toString(); + const QString sysRoot = SysRootKitAspect::sysRoot(k).toString(); if (!sysRoot.isEmpty()) { extra.configuration.append(CMakeConfigItem("CMAKE_SYSROOT", sysRoot.toUtf8())); - ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain( + ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitAspect::toolChain( k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); if (tc) { const QByteArray targetTriple = tc->originalTargetTriple().toUtf8(); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index 587666b0bf..050dd6f084 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -63,16 +63,16 @@ public: QString warning() const; QStringList buildTargetTitles() const; - ProjectExplorer::BuildTargetInfoList appTargets() const; + const QList<CMakeBuildTarget> &buildTargets() const; + const QList<ProjectExplorer::BuildTargetInfo> appTargets() const; ProjectExplorer::DeploymentData deploymentData() const; - static Utils::FileName - shadowBuildDirectory(const Utils::FileName &projectFilePath, const ProjectExplorer::Kit *k, + static Utils::FilePath + shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k, const QString &bcName, BuildConfiguration::BuildType buildType); // Context menu action: void buildTarget(const QString &buildTarget); - signals: void errorOccured(const QString &message); void warningOccured(const QString &message); @@ -104,6 +104,7 @@ private: void setWarning(const QString &message); CMakeConfig m_configurationForCMake; + CMakeConfig m_initialConfiguration; QString m_error; QString m_warning; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp index 192d3b0af5..cf94cbf23d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp @@ -111,7 +111,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) connect(buildDirChooser, &Utils::PathChooser::rawPathChanged, this, [this](const QString &path) { m_configModel->flush(); // clear out config cache... - m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(path)); + m_buildConfiguration->setBuildDirectory(Utils::FilePath::fromString(path)); }); int row = 0; @@ -385,7 +385,7 @@ void CMakeBuildSettingsWidget::updateAdvancedCheckBox() void CMakeBuildSettingsWidget::updateFromKit() { const ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit(); - const CMakeConfig config = CMakeConfigurationKitInformation::configuration(k); + const CMakeConfig config = CMakeConfigurationKitAspect::configuration(k); QHash<QString, QString> configHash; for (const CMakeConfigItem &i : config) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index 40a809f581..364337308b 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -160,16 +160,16 @@ bool CMakeBuildStep::init() emit addTask(Task(Task::Error, QCoreApplication::translate("CMakeProjectManager::CMakeBuildStep", "The build configuration is currently disabled."), - Utils::FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); canInit = false; } - CMakeTool *tool = CMakeKitInformation::cmakeTool(target()->kit()); + CMakeTool *tool = CMakeKitAspect::cmakeTool(target()->kit()); if (!tool || !tool->isValid()) { emit addTask(Task(Task::Error, tr("A CMake tool must be set up for building. " "Configure a CMake tool in the kit options."), - Utils::FileName(), -1, + Utils::FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); canInit = false; } @@ -181,7 +181,7 @@ bool CMakeBuildStep::init() "You asked to build the current Run Configuration's build target only, " "but it is not associated with a build target. " "Update the Make Step in your build settings."), - Utils::FileName(), -1, + Utils::FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); canInit = false; } @@ -192,23 +192,19 @@ bool CMakeBuildStep::init() } // Warn if doing out-of-source builds with a CMakeCache.txt is the source directory - const Utils::FileName projectDirectory = bc->target()->project()->projectDirectory(); + const Utils::FilePath projectDirectory = bc->target()->project()->projectDirectory(); if (bc->buildDirectory() != projectDirectory) { - Utils::FileName cmc = projectDirectory; - cmc.appendPath("CMakeCache.txt"); - if (cmc.exists()) { + if (projectDirectory.pathAppended("CMakeCache.txt").exists()) { emit addTask(Task(Task::Warning, tr("There is a CMakeCache.txt file in \"%1\", which suggest an " "in-source build was done before. You are now building in \"%2\", " "and the CMakeCache.txt file might confuse CMake.") .arg(projectDirectory.toUserOutput(), bc->buildDirectory().toUserOutput()), - Utils::FileName(), -1, + Utils::FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } - QString arguments = allArguments(rc); - setIgnoreReturnValue(m_buildTarget == CMakeBuildStep::cleanTarget()); ProcessParameters *pp = processParameters(); @@ -218,9 +214,8 @@ bool CMakeBuildStep::init() if (!env.value("NINJA_STATUS").startsWith(m_ninjaProgressString)) env.set("NINJA_STATUS", m_ninjaProgressString + "%o/sec] "); pp->setEnvironment(env); - pp->setWorkingDirectory(bc->buildDirectory().toString()); - pp->setCommand(cmakeCommand()); - pp->setArguments(arguments); + pp->setWorkingDirectory(bc->buildDirectory()); + pp->setCommandLine(cmakeCommand(rc)); pp->resolveAll(); setOutputParser(new CMakeParser); @@ -344,12 +339,12 @@ void CMakeBuildStep::setToolArguments(const QString &list) m_toolArguments = list; } -QString CMakeBuildStep::allArguments(const CMakeRunConfiguration *rc) const +Utils::CommandLine CMakeBuildStep::cmakeCommand(CMakeRunConfiguration *rc) const { - QString arguments; + CMakeTool *tool = CMakeKitAspect::cmakeTool(target()->kit()); - Utils::QtcProcess::addArg(&arguments, "--build"); - Utils::QtcProcess::addArg(&arguments, "."); + Utils::CommandLine cmd(tool ? tool->cmakeExecutable() : Utils::FilePath(), {}); + cmd.addArgs({"--build", "."}); QString target; @@ -362,21 +357,14 @@ QString CMakeBuildStep::allArguments(const CMakeRunConfiguration *rc) const target = m_buildTarget; } - Utils::QtcProcess::addArg(&arguments, "--target"); - Utils::QtcProcess::addArg(&arguments, target); + cmd.addArgs({"--target", target}); if (!m_toolArguments.isEmpty()) { - Utils::QtcProcess::addArg(&arguments, "--"); - arguments += ' ' + m_toolArguments; + cmd.addArg("--"); + cmd.addArgs(m_toolArguments); } - return arguments; -} - -QString CMakeBuildStep::cmakeCommand() const -{ - CMakeTool *tool = CMakeKitInformation::cmakeTool(target()->kit()); - return tool ? tool->cmakeExecutable().toString() : QString(); + return cmd; } QString CMakeBuildStep::cleanTarget() @@ -531,9 +519,8 @@ void CMakeBuildStepConfigWidget::updateDetails() ProcessParameters param; param.setMacroExpander(bc->macroExpander()); param.setEnvironment(bc->environment()); - param.setWorkingDirectory(bc->buildDirectory().toString()); - param.setCommand(m_buildStep->cmakeCommand()); - param.setArguments(m_buildStep->allArguments(nullptr)); + param.setWorkingDirectory(bc->buildDirectory()); + param.setCommandLine(m_buildStep->cmakeCommand(nullptr)); setSummaryText(param.summary(displayName())); } diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h index 9e76889d28..9b906f883f 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h @@ -35,7 +35,10 @@ class QListWidget; class QListWidgetItem; QT_END_NAMESPACE -namespace Utils { class PathChooser; } +namespace Utils { +class CommandLine; +class PathChooser; +} // Utils namespace ProjectExplorer { class ToolChain; } @@ -64,9 +67,7 @@ public: QString toolArguments() const; void setToolArguments(const QString &list); - QString allArguments(const CMakeRunConfiguration *rc) const; - - QString cmakeCommand() const; + Utils::CommandLine cmakeCommand(CMakeRunConfiguration *rc) const; QVariantMap toMap() const override; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp deleted file mode 100644 index 357f66f6a5..0000000000 --- a/src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "cmakebuildtarget.h" - -using namespace Utils; - -namespace CMakeProjectManager { - -void CMakeBuildTarget::clear() -{ - executable.clear(); - makeCommand.clear(); - workingDirectory.clear(); - sourceDirectory.clear(); - title.clear(); - targetType = UtilityType; - includeFiles.clear(); - compilerOptions.clear(); - macros.clear(); - files.clear(); -} - -} // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakebuildtarget.h b/src/plugins/cmakeprojectmanager/cmakebuildtarget.h index 1b3f5fb700..e46394bef5 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildtarget.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildtarget.h @@ -46,19 +46,17 @@ class CMAKE_EXPORT CMakeBuildTarget { public: QString title; - Utils::FileName executable; // TODO: rename to output? + Utils::FilePath executable; // TODO: rename to output? TargetType targetType = UtilityType; - Utils::FileName workingDirectory; - Utils::FileName sourceDirectory; - Utils::FileName makeCommand; + Utils::FilePath workingDirectory; + Utils::FilePath sourceDirectory; + Utils::FilePath makeCommand; // code model - QList<Utils::FileName> includeFiles; + QList<Utils::FilePath> includeFiles; QStringList compilerOptions; ProjectExplorer::Macros macros; - QList<Utils::FileName> files; - - void clear(); + QList<Utils::FilePath> files; }; } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp index e5344df26f..b257d78619 100644 --- a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp +++ b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp @@ -46,7 +46,7 @@ namespace Internal { //// namespace { -int distance(const FileName &targetDirectory, const FileName &fileName) +int distance(const FilePath &targetDirectory, const FilePath &fileName) { const QString commonParent = commonPath(QStringList({targetDirectory.toString(), fileName.toString()})); return targetDirectory.toString().midRef(commonParent.size()).count('/') @@ -61,12 +61,12 @@ int distance(const FileName &targetDirectory, const FileName &fileName) void CMakeCbpParser::sortFiles() { QLoggingCategory log("qtc.cmakeprojectmanager.filetargetmapping", QtWarningMsg); - FileNameList fileNames = transform<QList>(m_fileList, &FileNode::filePath); + FilePathList fileNames = transform<QList>(m_fileList, &FileNode::filePath); sort(fileNames); CMakeBuildTarget *last = nullptr; - FileName parentDirectory; + FilePath parentDirectory; qCDebug(log) << "###############"; qCDebug(log) << "# Pre Dump #"; @@ -96,7 +96,7 @@ void CMakeCbpParser::sortFiles() qCDebug(log) << "# Sorting #"; qCDebug(log) << "###############"; - foreach (const FileName &fileName, fileNames) { + foreach (const FilePath &fileName, fileNames) { qCDebug(log) << fileName; const QStringList unitTargets = m_unitTargetMap[fileName]; if (!unitTargets.isEmpty()) { @@ -160,12 +160,12 @@ void CMakeCbpParser::sortFiles() << target.files << "\n"; } -bool CMakeCbpParser::parseCbpFile(CMakeTool::PathMapper mapper, const FileName &fileName, - const FileName &sourceDirectory) +bool CMakeCbpParser::parseCbpFile(CMakeTool::PathMapper mapper, const FilePath &fileName, + const FilePath &sourceDirectory) { m_pathMapper = mapper; - m_buildDirectory = FileName::fromString(fileName.toFileInfo().absolutePath()); + m_buildDirectory = FilePath::fromString(fileName.toFileInfo().absolutePath()); m_sourceDirectory = sourceDirectory; QFile fi(fileName.toString()); @@ -234,7 +234,7 @@ void CMakeCbpParser::parseBuild() void CMakeCbpParser::parseBuildTarget() { - m_buildTarget.clear(); + m_buildTarget = CMakeBuildTarget(); if (attributes().hasAttribute("title")) m_buildTarget.title = attributes().value("title").toString(); @@ -263,7 +263,7 @@ void CMakeCbpParser::parseBuildTarget() void CMakeCbpParser::parseBuildTargetOption() { if (attributes().hasAttribute("output")) { - m_buildTarget.executable = m_pathMapper(FileName::fromString(attributes().value("output").toString())); + m_buildTarget.executable = m_pathMapper(FilePath::fromString(attributes().value("output").toString())); } else if (attributes().hasAttribute("type")) { const QStringRef value = attributes().value("type"); if (value == "0" || value == "1") @@ -275,7 +275,7 @@ void CMakeCbpParser::parseBuildTargetOption() else m_buildTarget.targetType = UtilityType; } else if (attributes().hasAttribute("working_dir")) { - m_buildTarget.workingDirectory = FileName::fromUserInput(attributes().value("working_dir").toString()); + m_buildTarget.workingDirectory = FilePath::fromUserInput(attributes().value("working_dir").toString()); QFile cmakeSourceInfoFile(m_buildTarget.workingDirectory.toString() + QStringLiteral("/CMakeFiles/CMakeDirectoryInformation.cmake")); @@ -287,7 +287,7 @@ void CMakeCbpParser::parseBuildTargetOption() if (lineTopSource.startsWith(searchSource, Qt::CaseInsensitive)) { QString src = lineTopSource.mid(searchSource.size()); src.chop(2); - m_buildTarget.sourceDirectory = FileName::fromString(src); + m_buildTarget.sourceDirectory = FilePath::fromString(src); break; } } @@ -296,8 +296,7 @@ void CMakeCbpParser::parseBuildTargetOption() if (m_buildTarget.sourceDirectory.isEmpty()) { QDir dir(m_buildDirectory.toString()); const QString relative = dir.relativeFilePath(m_buildTarget.workingDirectory.toString()); - m_buildTarget.sourceDirectory = m_sourceDirectory; - m_buildTarget.sourceDirectory.appendPath(relative).toString(); + m_buildTarget.sourceDirectory = m_sourceDirectory.pathAppended(relative); } } while (!atEnd()) { @@ -349,7 +348,7 @@ void CMakeCbpParser::parseMakeCommands() void CMakeCbpParser::parseBuildTargetBuild() { if (attributes().hasAttribute("command")) - m_buildTarget.makeCommand = m_pathMapper(FileName::fromUserInput(attributes().value("command").toString())); + m_buildTarget.makeCommand = m_pathMapper(FilePath::fromUserInput(attributes().value("command").toString())); while (!atEnd()) { readNext(); if (isEndElement()) @@ -388,8 +387,8 @@ void CMakeCbpParser::parseAdd() // CMake only supports <Add option=\> and <Add directory=\> const QXmlStreamAttributes addAttributes = attributes(); - FileName includeDirectory - = m_pathMapper(FileName::fromString(addAttributes.value("directory").toString())); + FilePath includeDirectory + = m_pathMapper(FilePath::fromString(addAttributes.value("directory").toString())); // allow adding multiple times because order happens if (!includeDirectory.isEmpty()) @@ -417,8 +416,8 @@ void CMakeCbpParser::parseAdd() void CMakeCbpParser::parseUnit() { - FileName fileName = - m_pathMapper(FileName::fromUserInput(attributes().value("filename").toString())); + FilePath fileName = + m_pathMapper(FilePath::fromUserInput(attributes().value("filename").toString())); m_parsingCMakeUnit = false; m_unitTargets.clear(); @@ -429,7 +428,7 @@ void CMakeCbpParser::parseUnit() // Now check whether we found a virtual element beneath if (m_parsingCMakeUnit) { m_cmakeFileList.emplace_back( - std::make_unique<FileNode>(fileName, FileType::Project, false)); + std::make_unique<FileNode>(fileName, FileType::Project)); } else { bool generated = false; QString onlyFileName = fileName.fileName(); @@ -440,13 +439,12 @@ void CMakeCbpParser::parseUnit() if (fileName.endsWith(".qrc")) { m_fileList.emplace_back( - std::make_unique<FileNode>(fileName, FileType::Resource, - generated)); + std::make_unique<FileNode>(fileName, FileType::Resource)); } else { m_fileList.emplace_back( - std::make_unique<FileNode>(fileName, FileType::Source, - generated)); + std::make_unique<FileNode>(fileName, FileType::Source)); } + m_fileList.back()->setIsGenerated(generated); } m_unitTargetMap.insert(fileName, m_unitTargets); m_processedUnits.insert(fileName); diff --git a/src/plugins/cmakeprojectmanager/cmakecbpparser.h b/src/plugins/cmakeprojectmanager/cmakecbpparser.h index 44da473bcf..8a8d5fbe7f 100644 --- a/src/plugins/cmakeprojectmanager/cmakecbpparser.h +++ b/src/plugins/cmakeprojectmanager/cmakecbpparser.h @@ -46,8 +46,8 @@ namespace Internal { class CMakeCbpParser : public QXmlStreamReader { public: - bool parseCbpFile(CMakeTool::PathMapper mapper, const Utils::FileName &fileName, - const Utils::FileName &sourceDirectory); + bool parseCbpFile(CMakeTool::PathMapper mapper, const Utils::FilePath &fileName, + const Utils::FilePath &sourceDirectory); std::vector<std::unique_ptr<ProjectExplorer::FileNode>> && takeFileList() { return std::move(m_fileList); } std::vector<std::unique_ptr<ProjectExplorer::FileNode>> && @@ -74,19 +74,19 @@ private: void parseUnknownElement(); void sortFiles(); - QMap<Utils::FileName, QStringList> m_unitTargetMap; + QMap<Utils::FilePath, QStringList> m_unitTargetMap; CMakeTool::PathMapper m_pathMapper; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_fileList; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_cmakeFileList; - QSet<Utils::FileName> m_processedUnits; + QSet<Utils::FilePath> m_processedUnits; bool m_parsingCMakeUnit = false; CMakeBuildTarget m_buildTarget; QList<CMakeBuildTarget> m_buildTargets; QString m_projectName; QString m_compiler; - Utils::FileName m_sourceDirectory; - Utils::FileName m_buildDirectory; + Utils::FilePath m_sourceDirectory; + Utils::FilePath m_buildDirectory; QStringList m_unitTargets; }; diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp index 082b2816c9..c3e27c001b 100644 --- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp @@ -42,12 +42,6 @@ namespace CMakeProjectManager { CMakeConfigItem::CMakeConfigItem() = default; -CMakeConfigItem::CMakeConfigItem(const CMakeConfigItem &other) : // What about inCMakeCache? - key(other.key), type(other.type), isAdvanced(other.isAdvanced), - isUnset(other.isUnset), value(other.value), - documentation(other.documentation), values(other.values) -{} - CMakeConfigItem::CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v) : key(k), type(t), value(v), documentation(d) @@ -249,7 +243,7 @@ static QByteArrayList splitCMakeCacheLine(const QByteArray &line) { << line.mid(equalPos + 1); } -QList<CMakeConfigItem> CMakeConfigItem::itemsFromFile(const Utils::FileName &cacheFile, QString *errorMessage) +QList<CMakeConfigItem> CMakeConfigItem::itemsFromFile(const Utils::FilePath &cacheFile, QString *errorMessage) { CMakeConfig result; QFile cache(cacheFile.toString()); diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.h b/src/plugins/cmakeprojectmanager/cmakeconfigitem.h index 07409d9a36..16bc8acea3 100644 --- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.h +++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.h @@ -32,7 +32,7 @@ namespace ProjectExplorer { class Kit; } namespace Utils { -class FileName; +class FilePath; class MacroExpander; } // namespace Utils @@ -42,7 +42,6 @@ class CMakeConfigItem { public: enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC }; CMakeConfigItem(); - CMakeConfigItem(const CMakeConfigItem &other); CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v); CMakeConfigItem(const QByteArray &k, const QByteArray &v); @@ -58,7 +57,7 @@ public: static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator(); static CMakeConfigItem fromString(const QString &s); - static QList<CMakeConfigItem> itemsFromFile(const Utils::FileName &input, QString *errorMessage); + static QList<CMakeConfigItem> itemsFromFile(const Utils::FilePath &input, QString *errorMessage); QString toString(const Utils::MacroExpander *expander = nullptr) const; QString toArgument(const Utils::MacroExpander *expander = nullptr) const; diff --git a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp index 2a5cf769a8..07f350caf1 100644 --- a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp +++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp @@ -55,6 +55,7 @@ CMakeFileCompletionAssist::CMakeFileCompletionAssist() : KeywordsCompletionAssistProcessor(Keywords()) { setSnippetGroup(Constants::CMAKE_SNIPPETS_GROUP_ID); + setDynamicCompletionFunction(&TextEditor::pathComplete); } IAssistProposal *CMakeFileCompletionAssist::perform(const AssistInterface *interface) @@ -62,9 +63,9 @@ IAssistProposal *CMakeFileCompletionAssist::perform(const AssistInterface *inter Keywords kw; QString fileName = interface->fileName(); if (!fileName.isEmpty() && QFileInfo(fileName).isFile()) { - Project *p = SessionManager::projectForFile(Utils::FileName::fromString(fileName)); + Project *p = SessionManager::projectForFile(Utils::FilePath::fromString(fileName)); if (p && p->activeTarget()) { - CMakeTool *cmake = CMakeKitInformation::cmakeTool(p->activeTarget()->kit()); + CMakeTool *cmake = CMakeKitAspect::cmakeTool(p->activeTarget()->kit()); if (cmake && cmake->isValid()) kw = cmake->keywords(); } diff --git a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h index 387addeac1..220ed6ce26 100644 --- a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h +++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h @@ -31,7 +31,6 @@ namespace CMakeProjectManager { namespace Internal { - class CMakeFileCompletionAssist : public TextEditor::KeywordsCompletionAssistProcessor { public: diff --git a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp deleted file mode 100644 index d264f1324f..0000000000 --- a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Canonical Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "cmakeprojectconstants.h" -#include "cmakekitconfigwidget.h" -#include "cmakekitinformation.h" -#include "cmaketoolmanager.h" -#include "cmaketool.h" - -#include <coreplugin/icore.h> -#include <coreplugin/variablechooser.h> -#include <projectexplorer/kit.h> -#include <projectexplorer/projectexplorerconstants.h> - -#include <utils/algorithm.h> -#include <utils/elidinglabel.h> -#include <utils/qtcassert.h> - -#include <QBoxLayout> -#include <QComboBox> -#include <QDialog> -#include <QDialogButtonBox> -#include <QLabel> -#include <QLineEdit> -#include <QPlainTextEdit> -#include <QPointer> -#include <QPushButton> - -using namespace ProjectExplorer; - -namespace CMakeProjectManager { -namespace Internal { - -// -------------------------------------------------------------------- -// CMakeKitConfigWidget: -// -------------------------------------------------------------------- - -CMakeKitConfigWidget::CMakeKitConfigWidget(Kit *kit, - const KitInformation *ki) : - KitConfigWidget(kit, ki), - m_comboBox(new QComboBox), - m_manageButton(new QPushButton(KitConfigWidget::msgManage())) -{ - m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); - m_comboBox->setEnabled(false); - m_comboBox->setToolTip(toolTip()); - - foreach (CMakeTool *tool, CMakeToolManager::cmakeTools()) - cmakeToolAdded(tool->id()); - - updateComboBox(); - - refresh(); - connect(m_comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), - this, &CMakeKitConfigWidget::currentCMakeToolChanged); - - m_manageButton->setContentsMargins(0, 0, 0, 0); - connect(m_manageButton, &QPushButton::clicked, - this, &CMakeKitConfigWidget::manageCMakeTools); - - CMakeToolManager *cmakeMgr = CMakeToolManager::instance(); - connect(cmakeMgr, &CMakeToolManager::cmakeAdded, - this, &CMakeKitConfigWidget::cmakeToolAdded); - connect(cmakeMgr, &CMakeToolManager::cmakeRemoved, - this, &CMakeKitConfigWidget::cmakeToolRemoved); - connect(cmakeMgr, &CMakeToolManager::cmakeUpdated, - this, &CMakeKitConfigWidget::cmakeToolUpdated); -} - -CMakeKitConfigWidget::~CMakeKitConfigWidget() -{ - delete m_comboBox; - delete m_manageButton; -} - -QString CMakeKitConfigWidget::displayName() const -{ - return tr("CMake Tool"); -} - -void CMakeKitConfigWidget::makeReadOnly() -{ - m_comboBox->setEnabled(false); -} - -void CMakeKitConfigWidget::refresh() -{ - CMakeTool *tool = CMakeKitInformation::cmakeTool(m_kit); - m_comboBox->setCurrentIndex(tool ? indexOf(tool->id()) : -1); -} - -QWidget *CMakeKitConfigWidget::mainWidget() const -{ - return m_comboBox; -} - -QWidget *CMakeKitConfigWidget::buttonWidget() const -{ - return m_manageButton; -} - -QString CMakeKitConfigWidget::toolTip() const -{ - return tr("The CMake Tool to use when building a project with CMake.<br>" - "This setting is ignored when using other build systems."); -} - -int CMakeKitConfigWidget::indexOf(const Core::Id &id) -{ - for (int i = 0; i < m_comboBox->count(); ++i) { - if (id == Core::Id::fromSetting(m_comboBox->itemData(i))) - return i; - } - return -1; -} - -void CMakeKitConfigWidget::cmakeToolAdded(const Core::Id &id) -{ - const CMakeTool *tool = CMakeToolManager::findById(id); - QTC_ASSERT(tool, return); - - m_comboBox->addItem(tool->displayName(), tool->id().toSetting()); - updateComboBox(); - refresh(); -} - -void CMakeKitConfigWidget::cmakeToolUpdated(const Core::Id &id) -{ - const int pos = indexOf(id); - QTC_ASSERT(pos >= 0, return); - - const CMakeTool *tool = CMakeToolManager::findById(id); - QTC_ASSERT(tool, return); - - m_comboBox->setItemText(pos, tool->displayName()); -} - -void CMakeKitConfigWidget::cmakeToolRemoved(const Core::Id &id) -{ - const int pos = indexOf(id); - QTC_ASSERT(pos >= 0, return); - - // do not handle the current index changed signal - m_removingItem = true; - m_comboBox->removeItem(pos); - m_removingItem = false; - - // update the checkbox and set the current index - updateComboBox(); - refresh(); -} - -void CMakeKitConfigWidget::updateComboBox() -{ - // remove unavailable cmake tool: - int pos = indexOf(Core::Id()); - if (pos >= 0) - m_comboBox->removeItem(pos); - - if (m_comboBox->count() == 0) { - m_comboBox->addItem(tr("<No CMake Tool available>"), - Core::Id().toSetting()); - m_comboBox->setEnabled(false); - } else { - m_comboBox->setEnabled(true); - } -} - -void CMakeKitConfigWidget::currentCMakeToolChanged(int index) -{ - if (m_removingItem) - return; - - const Core::Id id = Core::Id::fromSetting(m_comboBox->itemData(index)); - CMakeKitInformation::setCMakeTool(m_kit, id); -} - -void CMakeKitConfigWidget::manageCMakeTools() -{ - Core::ICore::showOptionsDialog(Constants::CMAKE_SETTINGSPAGE_ID, - buttonWidget()); -} - -// -------------------------------------------------------------------- -// CMakeGeneratorKitConfigWidget: -// -------------------------------------------------------------------- - - -CMakeGeneratorKitConfigWidget::CMakeGeneratorKitConfigWidget(Kit *kit, - const KitInformation *ki) : - KitConfigWidget(kit, ki), - m_label(new QLabel), - m_changeButton(new QPushButton) -{ - m_label->setToolTip(toolTip()); - m_changeButton->setText(tr("Change...")); - - refresh(); - connect(m_changeButton, &QPushButton::clicked, - this, &CMakeGeneratorKitConfigWidget::changeGenerator); -} - -CMakeGeneratorKitConfigWidget::~CMakeGeneratorKitConfigWidget() -{ - delete m_label; - delete m_changeButton; -} - -QString CMakeGeneratorKitConfigWidget::displayName() const -{ - return tr("CMake generator"); -} - -void CMakeGeneratorKitConfigWidget::makeReadOnly() -{ - m_changeButton->setEnabled(false); -} - -void CMakeGeneratorKitConfigWidget::refresh() -{ - if (m_ignoreChange) - return; - - CMakeTool *const tool = CMakeKitInformation::cmakeTool(m_kit); - if (tool != m_currentTool) - m_currentTool = tool; - - m_changeButton->setEnabled(m_currentTool); - const QString generator = CMakeGeneratorKitInformation::generator(kit()); - const QString extraGenerator = CMakeGeneratorKitInformation::extraGenerator(kit()); - const QString platform = CMakeGeneratorKitInformation::platform(kit()); - const QString toolset = CMakeGeneratorKitInformation::toolset(kit()); - - const QString message = tr("%1 - %2, Platform: %3, Toolset: %4") - .arg(extraGenerator.isEmpty() ? tr("<none>") : extraGenerator) - .arg(generator.isEmpty() ? tr("<none>") : generator) - .arg(platform.isEmpty() ? tr("<none>") : platform) - .arg(toolset.isEmpty() ? tr("<none>") : toolset); - m_label->setText(message); -} - -QWidget *CMakeGeneratorKitConfigWidget::mainWidget() const -{ - return m_label; -} - -QWidget *CMakeGeneratorKitConfigWidget::buttonWidget() const -{ - return m_changeButton; -} - -QString CMakeGeneratorKitConfigWidget::toolTip() const -{ - return tr("CMake generator defines how a project is built when using CMake.<br>" - "This setting is ignored when using other build systems."); -} - -void CMakeGeneratorKitConfigWidget::changeGenerator() -{ - QPointer<QDialog> changeDialog = new QDialog(m_changeButton); - - // Disable help button in titlebar on windows: - Qt::WindowFlags flags = changeDialog->windowFlags(); - flags &= ~Qt::WindowContextHelpButtonHint; - flags |= Qt::MSWindowsFixedSizeDialogHint; - changeDialog->setWindowFlags(flags); - - changeDialog->setWindowTitle(tr("CMake Generator")); - - auto *layout = new QGridLayout(changeDialog); - layout->setSizeConstraint(QLayout::SetFixedSize); - - auto *cmakeLabel = new QLabel; - cmakeLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - - auto *generatorCombo = new QComboBox; - auto *extraGeneratorCombo = new QComboBox; - auto *platformEdit = new QLineEdit; - auto *toolsetEdit = new QLineEdit; - - int row = 0; - layout->addWidget(new QLabel(QLatin1String("Executable:"))); - layout->addWidget(cmakeLabel, row, 1); - - ++row; - layout->addWidget(new QLabel(tr("Generator:")), row, 0); - layout->addWidget(generatorCombo, row, 1); - - ++row; - layout->addWidget(new QLabel(tr("Extra generator:")), row, 0); - layout->addWidget(extraGeneratorCombo, row, 1); - - ++row; - layout->addWidget(new QLabel(tr("Platform:")), row, 0); - layout->addWidget(platformEdit, row, 1); - - ++row; - layout->addWidget(new QLabel(tr("Toolset:")), row, 0); - layout->addWidget(toolsetEdit, row, 1); - - ++row; - auto *bb = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); - layout->addWidget(bb, row, 0, 1, 2); - - connect(bb, &QDialogButtonBox::accepted, changeDialog.data(), &QDialog::accept); - connect(bb, &QDialogButtonBox::rejected, changeDialog.data(), &QDialog::reject); - - cmakeLabel->setText(m_currentTool->cmakeExecutable().toUserOutput()); - - QList<CMakeTool::Generator> generatorList = m_currentTool->supportedGenerators(); - Utils::sort(generatorList, &CMakeTool::Generator::name); - - for (auto it = generatorList.constBegin(); it != generatorList.constEnd(); ++it) - generatorCombo->addItem(it->name); - - auto updateDialog = [&generatorList, generatorCombo, extraGeneratorCombo, - platformEdit, toolsetEdit](const QString &name) { - auto it = std::find_if(generatorList.constBegin(), generatorList.constEnd(), - [name](const CMakeTool::Generator &g) { return g.name == name; }); - QTC_ASSERT(it != generatorList.constEnd(), return); - generatorCombo->setCurrentText(name); - - extraGeneratorCombo->clear(); - extraGeneratorCombo->addItem(tr("<none>"), QString()); - foreach (const QString &eg, it->extraGenerators) - extraGeneratorCombo->addItem(eg, eg); - extraGeneratorCombo->setEnabled(extraGeneratorCombo->count() > 1); - - platformEdit->setEnabled(it->supportsPlatform); - toolsetEdit->setEnabled(it->supportsToolset); - }; - - updateDialog(CMakeGeneratorKitInformation::generator(kit())); - - generatorCombo->setCurrentText(CMakeGeneratorKitInformation::generator(kit())); - extraGeneratorCombo->setCurrentText(CMakeGeneratorKitInformation::extraGenerator(kit())); - platformEdit->setText(platformEdit->isEnabled() ? CMakeGeneratorKitInformation::platform(kit()) : QLatin1String("<unsupported>")); - toolsetEdit->setText(toolsetEdit->isEnabled() ? CMakeGeneratorKitInformation::toolset(kit()) : QLatin1String("<unsupported>")); - - connect(generatorCombo, &QComboBox::currentTextChanged, updateDialog); - - if (changeDialog->exec() == QDialog::Accepted) { - if (!changeDialog) - return; - - CMakeGeneratorKitInformation::set(kit(), generatorCombo->currentText(), - extraGeneratorCombo->currentData().toString(), - platformEdit->isEnabled() ? platformEdit->text() : QString(), - toolsetEdit->isEnabled() ? toolsetEdit->text() : QString()); - } -} - -// -------------------------------------------------------------------- -// CMakeConfigurationKitConfigWidget: -// -------------------------------------------------------------------- - -CMakeConfigurationKitConfigWidget::CMakeConfigurationKitConfigWidget(Kit *kit, - const KitInformation *ki) : - KitConfigWidget(kit, ki), - m_summaryLabel(new Utils::ElidingLabel), - m_manageButton(new QPushButton) -{ - refresh(); - m_manageButton->setText(tr("Change...")); - connect(m_manageButton, &QAbstractButton::clicked, - this, &CMakeConfigurationKitConfigWidget::editConfigurationChanges); -} - -QString CMakeConfigurationKitConfigWidget::displayName() const -{ - return tr("CMake Configuration"); -} - -void CMakeConfigurationKitConfigWidget::makeReadOnly() -{ - m_manageButton->setEnabled(false); - if (m_dialog) - m_dialog->reject(); -} - -void CMakeConfigurationKitConfigWidget::refresh() -{ - const QStringList current = CMakeConfigurationKitInformation::toStringList(kit()); - - m_summaryLabel->setText(current.join("; ")); - if (m_editor) - m_editor->setPlainText(current.join('\n')); -} - -QWidget *CMakeConfigurationKitConfigWidget::mainWidget() const -{ - return m_summaryLabel; -} - -QWidget *CMakeConfigurationKitConfigWidget::buttonWidget() const -{ - return m_manageButton; -} - -QString CMakeConfigurationKitConfigWidget::toolTip() const -{ - return tr("Default configuration passed to CMake when setting up a project."); -} - -void CMakeConfigurationKitConfigWidget::editConfigurationChanges() -{ - if (m_dialog) { - m_dialog->activateWindow(); - m_dialog->raise(); - return; - } - - QTC_ASSERT(!m_editor, return); - - m_dialog = new QDialog(m_summaryLabel->window()); - m_dialog->setWindowTitle(tr("Edit CMake Configuration")); - auto layout = new QVBoxLayout(m_dialog); - m_editor = new QPlainTextEdit; - m_editor->setToolTip(tr("Enter one variable per line with the variable name " - "separated from the variable value by \"=\".<br>" - "You may provide a type hint by adding \":TYPE\" before the \"=\".")); - m_editor->setMinimumSize(800, 200); - - auto chooser = new Core::VariableChooser(m_dialog); - chooser->addSupportedWidget(m_editor); - chooser->addMacroExpanderProvider([this]() { return kit()->macroExpander(); }); - - auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Apply - |QDialogButtonBox::Reset|QDialogButtonBox::Cancel); - - layout->addWidget(m_editor); - layout->addWidget(buttons); - - connect(buttons, &QDialogButtonBox::accepted, m_dialog, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, m_dialog, &QDialog::reject); - connect(buttons, &QDialogButtonBox::clicked, m_dialog, [buttons, this](QAbstractButton *button) { - if (button != buttons->button(QDialogButtonBox::Reset)) - return; - CMakeConfigurationKitInformation::setConfiguration(kit(), - CMakeConfigurationKitInformation::defaultConfiguration(kit())); - }); - connect(m_dialog, &QDialog::accepted, this, &CMakeConfigurationKitConfigWidget::acceptChangesDialog); - connect(m_dialog, &QDialog::rejected, this, &CMakeConfigurationKitConfigWidget::closeChangesDialog); - connect(buttons->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, - this, &CMakeConfigurationKitConfigWidget::applyChanges); - - refresh(); - m_dialog->show(); -} - -void CMakeConfigurationKitConfigWidget::applyChanges() -{ - QTC_ASSERT(m_editor, return); - CMakeConfigurationKitInformation::fromStringList(kit(), m_editor->toPlainText().split(QLatin1Char('\n'))); -} - -void CMakeConfigurationKitConfigWidget::closeChangesDialog() -{ - m_dialog->deleteLater(); - m_dialog = nullptr; - m_editor = nullptr; -} - -void CMakeConfigurationKitConfigWidget::acceptChangesDialog() -{ - applyChanges(); - closeChangesDialog(); -} - -} // namespace Internal -} // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h deleted file mode 100644 index 3839750f66..0000000000 --- a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Canonical Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <projectexplorer/kitconfigwidget.h> - -QT_BEGIN_NAMESPACE -class QComboBox; -class QDialog; -class QLabel; -class QPlainTextEdit; -class QPushButton; -QT_END_NAMESPACE - -namespace ProjectExplorer { - class Kit; - class KitInformation; -} // namespace ProjectExplorer - -namespace CMakeProjectManager { - -class CMakeTool; - -namespace Internal { - -// -------------------------------------------------------------------- -// CMakeKitConfigWidget: -// -------------------------------------------------------------------- - -class CMakeKitConfigWidget : public ProjectExplorer::KitConfigWidget -{ - Q_OBJECT -public: - CMakeKitConfigWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki); - ~CMakeKitConfigWidget() override; - - // KitConfigWidget interface - QString displayName() const override; - void makeReadOnly() override; - void refresh() override; - QWidget *mainWidget() const override; - QWidget *buttonWidget() const override; - QString toolTip() const override; - -private: - int indexOf(const Core::Id &id); - void updateComboBox(); - void cmakeToolAdded(const Core::Id &id); - void cmakeToolUpdated(const Core::Id &id); - void cmakeToolRemoved(const Core::Id &id); - void currentCMakeToolChanged(int index); - void manageCMakeTools(); - - bool m_removingItem = false; - QComboBox *m_comboBox; - QPushButton *m_manageButton; -}; - -// -------------------------------------------------------------------- -// CMakeGeneratorKitConfigWidget: -// -------------------------------------------------------------------- - -class CMakeGeneratorKitConfigWidget : public ProjectExplorer::KitConfigWidget -{ - Q_OBJECT -public: - CMakeGeneratorKitConfigWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki); - ~CMakeGeneratorKitConfigWidget() override; - - // KitConfigWidget interface - QString displayName() const override; - void makeReadOnly() override; - void refresh() override; - QWidget *mainWidget() const override; - QWidget *buttonWidget() const override; - QString toolTip() const override; - -private: - void changeGenerator(); - - bool m_ignoreChange = false; - QLabel *m_label; - QPushButton *m_changeButton; - CMakeTool *m_currentTool = nullptr; -}; - -// -------------------------------------------------------------------- -// CMakeConfigurationKitConfigWidget: -// -------------------------------------------------------------------- - -class CMakeConfigurationKitConfigWidget : public ProjectExplorer::KitConfigWidget -{ - Q_OBJECT -public: - CMakeConfigurationKitConfigWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki); - - // KitConfigWidget interface - QString displayName() const override; - void makeReadOnly() override; - void refresh() override; - QWidget *mainWidget() const override; - QWidget *buttonWidget() const override; - QString toolTip() const override; - -private: - void editConfigurationChanges(); - - void applyChanges(); - void closeChangesDialog(); - void acceptChangesDialog(); - - QLabel *m_summaryLabel; - QPushButton *m_manageButton; - QDialog *m_dialog = nullptr; - QPlainTextEdit *m_editor = nullptr; -}; - -} // namespace Internal -} // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index 4dc49ce630..efe0dccc57 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -24,12 +24,13 @@ ****************************************************************************/ #include "cmakekitinformation.h" -#include "cmakekitconfigwidget.h" #include "cmakeprojectconstants.h" #include "cmaketoolmanager.h" #include "cmaketool.h" #include <app/app_version.h> +#include <coreplugin/icore.h> +#include <coreplugin/variablechooser.h> #include <projectexplorer/task.h> #include <projectexplorer/toolchain.h> #include <projectexplorer/kit.h> @@ -37,18 +38,28 @@ #include <qtsupport/baseqtversion.h> #include <qtsupport/qtkitinformation.h> #include <projectexplorer/projectexplorerconstants.h> - #include <utils/algorithm.h> +#include <utils/elidinglabel.h> #include <utils/environment.h> #include <utils/qtcassert.h> +#include <QComboBox> +#include <QDialog> +#include <QDialogButtonBox> +#include <QGridLayout> +#include <QLabel> +#include <QLineEdit> +#include <QPlainTextEdit> +#include <QPointer> +#include <QPushButton> #include <QVariant> using namespace ProjectExplorer; namespace CMakeProjectManager { +namespace Internal { // -------------------------------------------------------------------- -// CMakeKitInformation: +// CMakeKitAspect: // -------------------------------------------------------------------- static Core::Id defaultCMakeToolId() @@ -59,14 +70,145 @@ static Core::Id defaultCMakeToolId() static const char TOOL_ID[] = "CMakeProjectManager.CMakeKitInformation"; -// -------------------------------------------------------------------- -// CMakeKitInformation: -// -------------------------------------------------------------------- +class CMakeKitAspectWidget : public KitAspectWidget +{ + Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeKitAspect) +public: + CMakeKitAspectWidget(Kit *kit, const KitAspect *ki) : KitAspectWidget(kit, ki), + m_comboBox(new QComboBox), + m_manageButton(new QPushButton(KitAspectWidget::msgManage())) + { + m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); + m_comboBox->setEnabled(false); + m_comboBox->setToolTip(ki->description()); + + foreach (CMakeTool *tool, CMakeToolManager::cmakeTools()) + cmakeToolAdded(tool->id()); + + updateComboBox(); + refresh(); + connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), + this, &CMakeKitAspectWidget::currentCMakeToolChanged); + + m_manageButton->setContentsMargins(0, 0, 0, 0); + connect(m_manageButton, &QPushButton::clicked, + this, &CMakeKitAspectWidget::manageCMakeTools); + + CMakeToolManager *cmakeMgr = CMakeToolManager::instance(); + connect(cmakeMgr, &CMakeToolManager::cmakeAdded, + this, &CMakeKitAspectWidget::cmakeToolAdded); + connect(cmakeMgr, &CMakeToolManager::cmakeRemoved, + this, &CMakeKitAspectWidget::cmakeToolRemoved); + connect(cmakeMgr, &CMakeToolManager::cmakeUpdated, + this, &CMakeKitAspectWidget::cmakeToolUpdated); + } + + ~CMakeKitAspectWidget() override + { + delete m_comboBox; + delete m_manageButton; + } + +private: + // KitAspectWidget interface + void makeReadOnly() override { m_comboBox->setEnabled(false); } + QWidget *mainWidget() const override { return m_comboBox; } + QWidget *buttonWidget() const override { return m_manageButton; } + + void refresh() override + { + CMakeTool *tool = CMakeKitAspect::cmakeTool(m_kit); + m_comboBox->setCurrentIndex(tool ? indexOf(tool->id()) : -1); + } + + int indexOf(const Core::Id &id) + { + for (int i = 0; i < m_comboBox->count(); ++i) { + if (id == Core::Id::fromSetting(m_comboBox->itemData(i))) + return i; + } + return -1; + } + + void updateComboBox() + { + // remove unavailable cmake tool: + int pos = indexOf(Core::Id()); + if (pos >= 0) + m_comboBox->removeItem(pos); + + if (m_comboBox->count() == 0) { + m_comboBox->addItem(tr("<No CMake Tool available>"), + Core::Id().toSetting()); + m_comboBox->setEnabled(false); + } else { + m_comboBox->setEnabled(true); + } + } + + void cmakeToolAdded(const Core::Id &id) + { + const CMakeTool *tool = CMakeToolManager::findById(id); + QTC_ASSERT(tool, return); + + m_comboBox->addItem(tool->displayName(), tool->id().toSetting()); + updateComboBox(); + refresh(); + } + + void cmakeToolUpdated(const Core::Id &id) + { + const int pos = indexOf(id); + QTC_ASSERT(pos >= 0, return); + + const CMakeTool *tool = CMakeToolManager::findById(id); + QTC_ASSERT(tool, return); + + m_comboBox->setItemText(pos, tool->displayName()); + } -CMakeKitInformation::CMakeKitInformation() + void cmakeToolRemoved(const Core::Id &id) + { + const int pos = indexOf(id); + QTC_ASSERT(pos >= 0, return); + + // do not handle the current index changed signal + m_removingItem = true; + m_comboBox->removeItem(pos); + m_removingItem = false; + + // update the checkbox and set the current index + updateComboBox(); + refresh(); + } + + void currentCMakeToolChanged(int index) + { + if (m_removingItem) + return; + + const Core::Id id = Core::Id::fromSetting(m_comboBox->itemData(index)); + CMakeKitAspect::setCMakeTool(m_kit, id); + } + + void manageCMakeTools() + { + Core::ICore::showOptionsDialog(Constants::CMAKE_SETTINGSPAGE_ID, + buttonWidget()); + } + + bool m_removingItem = false; + QComboBox *m_comboBox; + QPushButton *m_manageButton; +}; + +CMakeKitAspect::CMakeKitAspect() { - setObjectName(QLatin1String("CMakeKitInformation")); + setObjectName(QLatin1String("CMakeKitAspect")); setId(TOOL_ID); + setDisplayName(tr("CMake Tool")); + setDescription(tr("The CMake Tool to use when building a project with CMake.<br>" + "This setting is ignored when using other build systems.")); setPriority(20000); //make sure the default value is set if a selected CMake is removed @@ -78,24 +220,24 @@ CMakeKitInformation::CMakeKitInformation() [this]() { foreach (Kit *k, KitManager::kits()) fix(k); }); } -Core::Id CMakeKitInformation::id() +Core::Id CMakeKitAspect::id() { return TOOL_ID; } -Core::Id CMakeKitInformation::cmakeToolId(const Kit *k) +Core::Id CMakeKitAspect::cmakeToolId(const Kit *k) { if (!k) return {}; return Core::Id::fromSetting(k->value(TOOL_ID)); } -CMakeTool *CMakeKitInformation::cmakeTool(const Kit *k) +CMakeTool *CMakeKitAspect::cmakeTool(const Kit *k) { return CMakeToolManager::findById(cmakeToolId(k)); } -void CMakeKitInformation::setCMakeTool(Kit *k, const Core::Id id) +void CMakeKitAspect::setCMakeTool(Kit *k, const Core::Id id) { const Core::Id toSet = id.isValid() ? id : defaultCMakeToolId(); QTC_ASSERT(!id.isValid() || CMakeToolManager::findById(toSet), return); @@ -103,63 +245,56 @@ void CMakeKitInformation::setCMakeTool(Kit *k, const Core::Id id) k->setValue(TOOL_ID, toSet.toSetting()); } -QVariant CMakeKitInformation::defaultValue(const Kit *k) const -{ - const Core::Id id = k ? defaultCMakeToolId() : Core::Id(); - return id.toSetting(); -} - -QList<Task> CMakeKitInformation::validate(const Kit *k) const +Tasks CMakeKitAspect::validate(const Kit *k) const { - QList<Task> result; - CMakeTool *tool = CMakeKitInformation::cmakeTool(k); + Tasks result; + CMakeTool *tool = CMakeKitAspect::cmakeTool(k); if (tool) { CMakeTool::Version version = tool->version(); if (version.major < 3) { result << Task(Task::Warning, tr("CMake version %1 is unsupported. Please update to " "version 3.0 or later.").arg(QString::fromUtf8(version.fullVersion)), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } return result; } -void CMakeKitInformation::setup(Kit *k) +void CMakeKitAspect::setup(Kit *k) { - CMakeTool *tool = CMakeKitInformation::cmakeTool(k); + CMakeTool *tool = CMakeKitAspect::cmakeTool(k); if (!tool) setCMakeTool(k, defaultCMakeToolId()); } -void CMakeKitInformation::fix(Kit *k) +void CMakeKitAspect::fix(Kit *k) { - if (!CMakeKitInformation::cmakeTool(k)) - setup(k); + setup(k); } -KitInformation::ItemList CMakeKitInformation::toUserOutput(const Kit *k) const +KitAspect::ItemList CMakeKitAspect::toUserOutput(const Kit *k) const { const CMakeTool *const tool = cmakeTool(k); - return ItemList() << qMakePair(tr("CMake"), tool ? tool->displayName() : tr("Unconfigured")); + return {{tr("CMake"), tool ? tool->displayName() : tr("Unconfigured")}}; } -KitConfigWidget *CMakeKitInformation::createConfigWidget(Kit *k) const +KitAspectWidget *CMakeKitAspect::createConfigWidget(Kit *k) const { QTC_ASSERT(k, return nullptr); - return new Internal::CMakeKitConfigWidget(k, this); + return new CMakeKitAspectWidget(k, this); } -void CMakeKitInformation::addToMacroExpander(Kit *k, Utils::MacroExpander *expander) const +void CMakeKitAspect::addToMacroExpander(Kit *k, Utils::MacroExpander *expander) const { QTC_ASSERT(k, return); expander->registerFileVariables("CMake:Executable", tr("Path to the cmake executable"), [k]() -> QString { - CMakeTool *tool = CMakeKitInformation::cmakeTool(k); + CMakeTool *tool = CMakeKitAspect::cmakeTool(k); return tool ? tool->cmakeExecutable().toString() : QString(); }); } -QSet<Core::Id> CMakeKitInformation::availableFeatures(const Kit *k) const +QSet<Core::Id> CMakeKitAspect::availableFeatures(const Kit *k) const { if (cmakeTool(k)) return { CMakeProjectManager::Constants::CMAKE_FEATURE_ID }; @@ -167,7 +302,7 @@ QSet<Core::Id> CMakeKitInformation::availableFeatures(const Kit *k) const } // -------------------------------------------------------------------- -// CMakeGeneratorKitInformation: +// CMakeGeneratorKitAspect: // -------------------------------------------------------------------- static const char GENERATOR_ID[] = "CMake.GeneratorKitInformation"; @@ -177,6 +312,158 @@ static const char EXTRA_GENERATOR_KEY[] = "ExtraGenerator"; static const char PLATFORM_KEY[] = "Platform"; static const char TOOLSET_KEY[] = "Toolset"; +class CMakeGeneratorKitAspectWidget : public KitAspectWidget +{ + Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeGeneratorKitAspect) +public: + CMakeGeneratorKitAspectWidget(Kit *kit, const ::KitAspect *ki) + : KitAspectWidget(kit, ki), + m_label(new QLabel), + m_changeButton(new QPushButton) + { + m_label->setToolTip(ki->description()); + m_changeButton->setText(tr("Change...")); + refresh(); + connect(m_changeButton, &QPushButton::clicked, + this, &CMakeGeneratorKitAspectWidget::changeGenerator); + } + + ~CMakeGeneratorKitAspectWidget() override + { + delete m_label; + delete m_changeButton; + } + +private: + // KitAspectWidget interface + void makeReadOnly() override { m_changeButton->setEnabled(false); } + QWidget *mainWidget() const override { return m_label; } + QWidget *buttonWidget() const override { return m_changeButton; } + + void refresh() override + { + if (m_ignoreChange) + return; + + CMakeTool *const tool = CMakeKitAspect::cmakeTool(m_kit); + if (tool != m_currentTool) + m_currentTool = tool; + + m_changeButton->setEnabled(m_currentTool); + const QString generator = CMakeGeneratorKitAspect::generator(kit()); + const QString extraGenerator = CMakeGeneratorKitAspect::extraGenerator(kit()); + const QString platform = CMakeGeneratorKitAspect::platform(kit()); + const QString toolset = CMakeGeneratorKitAspect::toolset(kit()); + + const QString message = tr("%1 - %2, Platform: %3, Toolset: %4") + .arg(extraGenerator.isEmpty() ? tr("<none>") : extraGenerator) + .arg(generator.isEmpty() ? tr("<none>") : generator) + .arg(platform.isEmpty() ? tr("<none>") : platform) + .arg(toolset.isEmpty() ? tr("<none>") : toolset); + m_label->setText(message); + } + + void changeGenerator() + { + QPointer<QDialog> changeDialog = new QDialog(m_changeButton); + + // Disable help button in titlebar on windows: + Qt::WindowFlags flags = changeDialog->windowFlags(); + flags &= ~Qt::WindowContextHelpButtonHint; + flags |= Qt::MSWindowsFixedSizeDialogHint; + changeDialog->setWindowFlags(flags); + + changeDialog->setWindowTitle(tr("CMake Generator")); + + auto *layout = new QGridLayout(changeDialog); + layout->setSizeConstraint(QLayout::SetFixedSize); + + auto *cmakeLabel = new QLabel; + cmakeLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + auto *generatorCombo = new QComboBox; + auto *extraGeneratorCombo = new QComboBox; + auto *platformEdit = new QLineEdit; + auto *toolsetEdit = new QLineEdit; + + int row = 0; + layout->addWidget(new QLabel(QLatin1String("Executable:"))); + layout->addWidget(cmakeLabel, row, 1); + + ++row; + layout->addWidget(new QLabel(tr("Generator:")), row, 0); + layout->addWidget(generatorCombo, row, 1); + + ++row; + layout->addWidget(new QLabel(tr("Extra generator:")), row, 0); + layout->addWidget(extraGeneratorCombo, row, 1); + + ++row; + layout->addWidget(new QLabel(tr("Platform:")), row, 0); + layout->addWidget(platformEdit, row, 1); + + ++row; + layout->addWidget(new QLabel(tr("Toolset:")), row, 0); + layout->addWidget(toolsetEdit, row, 1); + + ++row; + auto *bb = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + layout->addWidget(bb, row, 0, 1, 2); + + connect(bb, &QDialogButtonBox::accepted, changeDialog.data(), &QDialog::accept); + connect(bb, &QDialogButtonBox::rejected, changeDialog.data(), &QDialog::reject); + + cmakeLabel->setText(m_currentTool->cmakeExecutable().toUserOutput()); + + QList<CMakeTool::Generator> generatorList = m_currentTool->supportedGenerators(); + Utils::sort(generatorList, &CMakeTool::Generator::name); + + for (auto it = generatorList.constBegin(); it != generatorList.constEnd(); ++it) + generatorCombo->addItem(it->name); + + auto updateDialog = [&generatorList, generatorCombo, extraGeneratorCombo, + platformEdit, toolsetEdit](const QString &name) { + auto it = std::find_if(generatorList.constBegin(), generatorList.constEnd(), + [name](const CMakeTool::Generator &g) { return g.name == name; }); + QTC_ASSERT(it != generatorList.constEnd(), return); + generatorCombo->setCurrentText(name); + + extraGeneratorCombo->clear(); + extraGeneratorCombo->addItem(tr("<none>"), QString()); + foreach (const QString &eg, it->extraGenerators) + extraGeneratorCombo->addItem(eg, eg); + extraGeneratorCombo->setEnabled(extraGeneratorCombo->count() > 1); + + platformEdit->setEnabled(it->supportsPlatform); + toolsetEdit->setEnabled(it->supportsToolset); + }; + + updateDialog(CMakeGeneratorKitAspect::generator(kit())); + + generatorCombo->setCurrentText(CMakeGeneratorKitAspect::generator(kit())); + extraGeneratorCombo->setCurrentText(CMakeGeneratorKitAspect::extraGenerator(kit())); + platformEdit->setText(platformEdit->isEnabled() ? CMakeGeneratorKitAspect::platform(kit()) : QLatin1String("<unsupported>")); + toolsetEdit->setText(toolsetEdit->isEnabled() ? CMakeGeneratorKitAspect::toolset(kit()) : QLatin1String("<unsupported>")); + + connect(generatorCombo, &QComboBox::currentTextChanged, updateDialog); + + if (changeDialog->exec() == QDialog::Accepted) { + if (!changeDialog) + return; + + CMakeGeneratorKitAspect::set(kit(), generatorCombo->currentText(), + extraGeneratorCombo->currentData().toString(), + platformEdit->isEnabled() ? platformEdit->text() : QString(), + toolsetEdit->isEnabled() ? toolsetEdit->text() : QString()); + } + } + + bool m_ignoreChange = false; + QLabel *m_label; + QPushButton *m_changeButton; + CMakeTool *m_currentTool = nullptr; +}; + namespace { struct GeneratorInfo { @@ -222,62 +509,65 @@ static void setGeneratorInfo(Kit *k, const GeneratorInfo &info) k->setValue(GENERATOR_ID, info.toVariant()); } -CMakeGeneratorKitInformation::CMakeGeneratorKitInformation() +CMakeGeneratorKitAspect::CMakeGeneratorKitAspect() { - setObjectName(QLatin1String("CMakeGeneratorKitInformation")); + setObjectName(QLatin1String("CMakeGeneratorKitAspect")); setId(GENERATOR_ID); + setDisplayName(tr("CMake generator")); + setDescription(tr("CMake generator defines how a project is built when using CMake.<br>" + "This setting is ignored when using other build systems.")); setPriority(19000); } -QString CMakeGeneratorKitInformation::generator(const Kit *k) +QString CMakeGeneratorKitAspect::generator(const Kit *k) { return generatorInfo(k).generator; } -QString CMakeGeneratorKitInformation::extraGenerator(const Kit *k) +QString CMakeGeneratorKitAspect::extraGenerator(const Kit *k) { return generatorInfo(k).extraGenerator; } -QString CMakeGeneratorKitInformation::platform(const Kit *k) +QString CMakeGeneratorKitAspect::platform(const Kit *k) { return generatorInfo(k).platform; } -QString CMakeGeneratorKitInformation::toolset(const Kit *k) +QString CMakeGeneratorKitAspect::toolset(const Kit *k) { return generatorInfo(k).toolset; } -void CMakeGeneratorKitInformation::setGenerator(Kit *k, const QString &generator) +void CMakeGeneratorKitAspect::setGenerator(Kit *k, const QString &generator) { GeneratorInfo info = generatorInfo(k); info.generator = generator; setGeneratorInfo(k, info); } -void CMakeGeneratorKitInformation::setExtraGenerator(Kit *k, const QString &extraGenerator) +void CMakeGeneratorKitAspect::setExtraGenerator(Kit *k, const QString &extraGenerator) { GeneratorInfo info = generatorInfo(k); info.extraGenerator = extraGenerator; setGeneratorInfo(k, info); } -void CMakeGeneratorKitInformation::setPlatform(Kit *k, const QString &platform) +void CMakeGeneratorKitAspect::setPlatform(Kit *k, const QString &platform) { GeneratorInfo info = generatorInfo(k); info.platform = platform; setGeneratorInfo(k, info); } -void CMakeGeneratorKitInformation::setToolset(Kit *k, const QString &toolset) +void CMakeGeneratorKitAspect::setToolset(Kit *k, const QString &toolset) { GeneratorInfo info = generatorInfo(k); info.toolset = toolset; setGeneratorInfo(k, info); } -void CMakeGeneratorKitInformation::set(Kit *k, +void CMakeGeneratorKitAspect::set(Kit *k, const QString &generator, const QString &extraGenerator, const QString &platform, const QString &toolset) { @@ -285,7 +575,7 @@ void CMakeGeneratorKitInformation::set(Kit *k, setGeneratorInfo(k, info); } -QStringList CMakeGeneratorKitInformation::generatorArguments(const Kit *k) +QStringList CMakeGeneratorKitAspect::generatorArguments(const Kit *k) { QStringList result; GeneratorInfo info = generatorInfo(k); @@ -307,11 +597,11 @@ QStringList CMakeGeneratorKitInformation::generatorArguments(const Kit *k) return result; } -QVariant CMakeGeneratorKitInformation::defaultValue(const Kit *k) const +QVariant CMakeGeneratorKitAspect::defaultValue(const Kit *k) const { QTC_ASSERT(k, return QVariant()); - CMakeTool *tool = CMakeKitInformation::cmakeTool(k); + CMakeTool *tool = CMakeKitAspect::cmakeTool(k); if (!tool) return QVariant(); @@ -325,14 +615,14 @@ QVariant CMakeGeneratorKitInformation::defaultValue(const Kit *k) const if (it != known.constEnd()) { Utils::Environment env = Utils::Environment::systemEnvironment(); k->addToEnvironment(env); - const Utils::FileName ninjaExec = env.searchInPath(QLatin1String("ninja")); + const Utils::FilePath ninjaExec = env.searchInPath(QLatin1String("ninja")); if (!ninjaExec.isEmpty()) return GeneratorInfo({QString("Ninja"), extraGenerator, QString(), QString()}).toVariant(); } if (Utils::HostOsInfo::isWindowsHost()) { // *sigh* Windows with its zoo of incompatible stuff again... - ToolChain *tc = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); if (tc && tc->typeId() == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) { it = std::find_if(known.constBegin(), known.constEnd(), [extraGenerator](const CMakeTool::Generator &g) { @@ -360,16 +650,16 @@ QVariant CMakeGeneratorKitInformation::defaultValue(const Kit *k) const return GeneratorInfo({it->name, extraGenerator, QString(), QString()}).toVariant(); } -QList<Task> CMakeGeneratorKitInformation::validate(const Kit *k) const +Tasks CMakeGeneratorKitAspect::validate(const Kit *k) const { - CMakeTool *tool = CMakeKitInformation::cmakeTool(k); + CMakeTool *tool = CMakeKitAspect::cmakeTool(k); GeneratorInfo info = generatorInfo(k); - QList<Task> result; + Tasks result; if (tool) { if (!tool->isValid()) { result << Task(Task::Warning, tr("CMake Tool is unconfigured, CMake generator will be ignored."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } else { QList<CMakeTool::Generator> known = tool->supportedGenerators(); auto it = std::find_if(known.constBegin(), known.constEnd(), [info](const CMakeTool::Generator &g) { @@ -377,15 +667,15 @@ QList<Task> CMakeGeneratorKitInformation::validate(const Kit *k) const }); if (it == known.constEnd()) { result << Task(Task::Warning, tr("CMake Tool does not support the configured generator."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } else { if (!it->supportsPlatform && !info.platform.isEmpty()) { result << Task(Task::Warning, tr("Platform is not supported by the selected CMake generator."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } if (!it->supportsToolset && !info.toolset.isEmpty()) { result << Task(Task::Warning, tr("Toolset is not supported by the selected CMake generator."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } if (!tool->hasServerMode() && info.extraGenerator != "CodeBlocks") { @@ -393,23 +683,25 @@ QList<Task> CMakeGeneratorKitInformation::validate(const Kit *k) const "generator does not generate a CodeBlocks file. " "%1 will not be able to parse CMake projects.") .arg(Core::Constants::IDE_DISPLAY_NAME), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } } return result; } -void CMakeGeneratorKitInformation::setup(Kit *k) +void CMakeGeneratorKitAspect::setup(Kit *k) { + if (!k || k->hasValue(id())) + return; GeneratorInfo info; info.fromVariant(defaultValue(k)); setGeneratorInfo(k, info); } -void CMakeGeneratorKitInformation::fix(Kit *k) +void CMakeGeneratorKitAspect::fix(Kit *k) { - const CMakeTool *tool = CMakeKitInformation::cmakeTool(k); + const CMakeTool *tool = CMakeKitAspect::cmakeTool(k); const GeneratorInfo info = generatorInfo(k); if (!tool) @@ -431,7 +723,7 @@ void CMakeGeneratorKitInformation::fix(Kit *k) } } -void CMakeGeneratorKitInformation::upgrade(Kit *k) +void CMakeGeneratorKitAspect::upgrade(Kit *k) { QTC_ASSERT(k, return); @@ -450,7 +742,7 @@ void CMakeGeneratorKitInformation::upgrade(Kit *k) } } -KitInformation::ItemList CMakeGeneratorKitInformation::toUserOutput(const Kit *k) const +KitAspect::ItemList CMakeGeneratorKitAspect::toUserOutput(const Kit *k) const { const GeneratorInfo info = generatorInfo(k); QString message; @@ -463,16 +755,16 @@ KitInformation::ItemList CMakeGeneratorKitInformation::toUserOutput(const Kit *k if (!info.toolset.isEmpty()) message += "<br/>" + tr("Toolset: %1").arg(info.toolset); } - return ItemList() << qMakePair(tr("CMake Generator"), message); + return {{tr("CMake Generator"), message}}; } -KitConfigWidget *CMakeGeneratorKitInformation::createConfigWidget(Kit *k) const +KitAspectWidget *CMakeGeneratorKitAspect::createConfigWidget(Kit *k) const { - return new Internal::CMakeGeneratorKitConfigWidget(k, this); + return new CMakeGeneratorKitAspectWidget(k, this); } // -------------------------------------------------------------------- -// CMakeConfigurationKitInformation: +// CMakeConfigurationKitAspect: // -------------------------------------------------------------------- static const char CONFIGURATION_ID[] = "CMake.ConfigurationKitInformation"; @@ -482,14 +774,122 @@ static const char CMAKE_CXX_TOOLCHAIN_KEY[] = "CMAKE_CXX_COMPILER"; static const char CMAKE_QMAKE_KEY[] = "QT_QMAKE_EXECUTABLE"; static const char CMAKE_PREFIX_PATH_KEY[] = "CMAKE_PREFIX_PATH"; -CMakeConfigurationKitInformation::CMakeConfigurationKitInformation() +class CMakeConfigurationKitAspectWidget : public KitAspectWidget +{ + Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeConfigurationKitAspect) +public: + CMakeConfigurationKitAspectWidget(Kit *kit, const KitAspect *ki) + : KitAspectWidget(kit, ki), + m_summaryLabel(new Utils::ElidingLabel), + m_manageButton(new QPushButton) + { + refresh(); + m_manageButton->setText(tr("Change...")); + connect(m_manageButton, &QAbstractButton::clicked, + this, &CMakeConfigurationKitAspectWidget::editConfigurationChanges); + } + +private: + // KitAspectWidget interface + QWidget *mainWidget() const override { return m_summaryLabel; } + QWidget *buttonWidget() const override { return m_manageButton; } + + void makeReadOnly() override + { + m_manageButton->setEnabled(false); + if (m_dialog) + m_dialog->reject(); + } + + void refresh() override + { + const QStringList current = CMakeConfigurationKitAspect::toStringList(kit()); + + m_summaryLabel->setText(current.join("; ")); + if (m_editor) + m_editor->setPlainText(current.join('\n')); + } + + void editConfigurationChanges() + { + if (m_dialog) { + m_dialog->activateWindow(); + m_dialog->raise(); + return; + } + + QTC_ASSERT(!m_editor, return); + + m_dialog = new QDialog(m_summaryLabel->window()); + m_dialog->setWindowTitle(tr("Edit CMake Configuration")); + auto layout = new QVBoxLayout(m_dialog); + m_editor = new QPlainTextEdit; + m_editor->setToolTip(tr("Enter one variable per line with the variable name " + "separated from the variable value by \"=\".<br>" + "You may provide a type hint by adding \":TYPE\" before the \"=\".")); + m_editor->setMinimumSize(800, 200); + + auto chooser = new Core::VariableChooser(m_dialog); + chooser->addSupportedWidget(m_editor); + chooser->addMacroExpanderProvider([this]() { return kit()->macroExpander(); }); + + auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Apply + |QDialogButtonBox::Reset|QDialogButtonBox::Cancel); + + layout->addWidget(m_editor); + layout->addWidget(buttons); + + connect(buttons, &QDialogButtonBox::accepted, m_dialog, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, m_dialog, &QDialog::reject); + connect(buttons, &QDialogButtonBox::clicked, m_dialog, [buttons, this](QAbstractButton *button) { + if (button != buttons->button(QDialogButtonBox::Reset)) + return; + CMakeConfigurationKitAspect::setConfiguration(kit(), + CMakeConfigurationKitAspect::defaultConfiguration(kit())); + }); + connect(m_dialog, &QDialog::accepted, this, &CMakeConfigurationKitAspectWidget::acceptChangesDialog); + connect(m_dialog, &QDialog::rejected, this, &CMakeConfigurationKitAspectWidget::closeChangesDialog); + connect(buttons->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, + this, &CMakeConfigurationKitAspectWidget::applyChanges); + + refresh(); + m_dialog->show(); + } + + void applyChanges() + { + QTC_ASSERT(m_editor, return); + CMakeConfigurationKitAspect::fromStringList(kit(), m_editor->toPlainText().split(QLatin1Char('\n'))); + } + void closeChangesDialog() + { + m_dialog->deleteLater(); + m_dialog = nullptr; + m_editor = nullptr; + } + void acceptChangesDialog() + { + applyChanges(); + closeChangesDialog(); + } + + QLabel *m_summaryLabel; + QPushButton *m_manageButton; + QDialog *m_dialog = nullptr; + QPlainTextEdit *m_editor = nullptr; +}; + + +CMakeConfigurationKitAspect::CMakeConfigurationKitAspect() { - setObjectName(QLatin1String("CMakeConfigurationKitInformation")); + setObjectName(QLatin1String("CMakeConfigurationKitAspect")); setId(CONFIGURATION_ID); + setDisplayName(tr("CMake Configuration")); + setDescription(tr("Default configuration passed to CMake when setting up a project.")); setPriority(18000); } -CMakeConfig CMakeConfigurationKitInformation::configuration(const Kit *k) +CMakeConfig CMakeConfigurationKitAspect::configuration(const Kit *k) { if (!k) return CMakeConfig(); @@ -497,7 +897,7 @@ CMakeConfig CMakeConfigurationKitInformation::configuration(const Kit *k) return Utils::transform(tmp, &CMakeConfigItem::fromString); } -void CMakeConfigurationKitInformation::setConfiguration(Kit *k, const CMakeConfig &config) +void CMakeConfigurationKitAspect::setConfiguration(Kit *k, const CMakeConfig &config) { if (!k) return; @@ -505,17 +905,17 @@ void CMakeConfigurationKitInformation::setConfiguration(Kit *k, const CMakeConfi k->setValue(CONFIGURATION_ID, tmp); } -QStringList CMakeConfigurationKitInformation::toStringList(const Kit *k) +QStringList CMakeConfigurationKitAspect::toStringList(const Kit *k) { QStringList current - = Utils::transform(CMakeConfigurationKitInformation::configuration(k), + = Utils::transform(CMakeConfigurationKitAspect::configuration(k), [](const CMakeConfigItem &i) { return i.toString(); }); current = Utils::filtered(current, [](const QString &s) { return !s.isEmpty(); }); Utils::sort(current); return current; } -void CMakeConfigurationKitInformation::fromStringList(Kit *k, const QStringList &in) +void CMakeConfigurationKitAspect::fromStringList(Kit *k, const QStringList &in) { CMakeConfig result; foreach (const QString &s, in) { @@ -526,7 +926,7 @@ void CMakeConfigurationKitInformation::fromStringList(Kit *k, const QStringList setConfiguration(k, result); } -CMakeConfig CMakeConfigurationKitInformation::defaultConfiguration(const Kit *k) +CMakeConfig CMakeConfigurationKitAspect::defaultConfiguration(const Kit *k) { Q_UNUSED(k); CMakeConfig config; @@ -541,7 +941,7 @@ CMakeConfig CMakeConfigurationKitInformation::defaultConfiguration(const Kit *k) return config; } -QVariant CMakeConfigurationKitInformation::defaultValue(const Kit *k) const +QVariant CMakeConfigurationKitAspect::defaultValue(const Kit *k) const { Q_UNUSED(k); @@ -552,24 +952,24 @@ QVariant CMakeConfigurationKitInformation::defaultValue(const Kit *k) const return tmp; } -QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const +Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const { - QTC_ASSERT(k, return QList<Task>()); + QTC_ASSERT(k, return Tasks()); - const QtSupport::BaseQtVersion *const version = QtSupport::QtKitInformation::qtVersion(k); - const ToolChain *const tcC = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID); - const ToolChain *const tcCxx = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + const QtSupport::BaseQtVersion *const version = QtSupport::QtKitAspect::qtVersion(k); + const ToolChain *const tcC = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID); + const ToolChain *const tcCxx = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); const CMakeConfig config = configuration(k); const bool isQt4 = version && version->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0); - Utils::FileName qmakePath; + Utils::FilePath qmakePath; QStringList qtInstallDirs; - Utils::FileName tcCPath; - Utils::FileName tcCxxPath; + Utils::FilePath tcCPath; + Utils::FilePath tcCxxPath; foreach (const CMakeConfigItem &i, config) { // Do not use expand(QByteArray) as we cannot be sure the input is latin1 - const Utils::FileName expandedValue - = Utils::FileName::fromString(k->macroExpander()->expand(QString::fromUtf8(i.value))); + const Utils::FilePath expandedValue + = Utils::FilePath::fromString(k->macroExpander()->expand(QString::fromUtf8(i.value))); if (i.key == CMAKE_QMAKE_KEY) qmakePath = expandedValue; else if (i.key == CMAKE_C_TOOLCHAIN_KEY) @@ -580,31 +980,31 @@ QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const qtInstallDirs = CMakeConfigItem::cmakeSplitValue(expandedValue.toString()); } - QList<Task> result; + Tasks result; // Validate Qt: if (qmakePath.isEmpty()) { if (version && version->isValid() && isQt4) { result << Task(Task::Warning, tr("CMake configuration has no path to qmake binary set, " "even though the kit has a valid Qt version."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } else { if (!version || !version->isValid()) { result << Task(Task::Warning, tr("CMake configuration has a path to a qmake binary set, " "even though the kit has no valid Qt version."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } else if (qmakePath != version->qmakeCommand() && isQt4) { result << Task(Task::Warning, tr("CMake configuration has a path to a qmake binary set " "that does not match the qmake binary path " "configured in the Qt version."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } if (version && !qtInstallDirs.contains(version->qmakeProperty("QT_INSTALL_PREFIX")) && !isQt4) { if (version->isValid()) { result << Task(Task::Warning, tr("CMake configuration has no CMAKE_PREFIX_PATH set " "that points to the kit Qt version."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } @@ -613,18 +1013,18 @@ QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const if (tcC && tcC->isValid()) { result << Task(Task::Warning, tr("CMake configuration has no path to a C compiler set, " "even though the kit has a valid tool chain."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } else { if (!tcC || !tcC->isValid()) { result << Task(Task::Warning, tr("CMake configuration has a path to a C compiler set, " "even though the kit has no valid tool chain."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } else if (tcCPath != tcC->compilerCommand()) { result << Task(Task::Warning, tr("CMake configuration has a path to a C compiler set " "that does not match the compiler path " "configured in the tool chain of the kit."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } @@ -632,46 +1032,46 @@ QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const if (tcCxx && tcCxx->isValid()) { result << Task(Task::Warning, tr("CMake configuration has no path to a C++ compiler set, " "even though the kit has a valid tool chain."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } else { if (!tcCxx || !tcCxx->isValid()) { result << Task(Task::Warning, tr("CMake configuration has a path to a C++ compiler set, " "even though the kit has no valid tool chain."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } else if (tcCxxPath != tcCxx->compilerCommand()) { result << Task(Task::Warning, tr("CMake configuration has a path to a C++ compiler set " "that does not match the compiler path " "configured in the tool chain of the kit."), - Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); } } return result; } -void CMakeConfigurationKitInformation::setup(Kit *k) +void CMakeConfigurationKitAspect::setup(Kit *k) { if (k && !k->hasValue(CONFIGURATION_ID)) k->setValue(CONFIGURATION_ID, defaultValue(k)); } -void CMakeConfigurationKitInformation::fix(Kit *k) +void CMakeConfigurationKitAspect::fix(Kit *k) { Q_UNUSED(k); } -KitInformation::ItemList CMakeConfigurationKitInformation::toUserOutput(const Kit *k) const +KitAspect::ItemList CMakeConfigurationKitAspect::toUserOutput(const Kit *k) const { - const QStringList current = toStringList(k); - return ItemList() << qMakePair(tr("CMake Configuration"), current.join(QLatin1String("<br>"))); + return {{tr("CMake Configuration"), toStringList(k).join("<br>")}}; } -KitConfigWidget *CMakeConfigurationKitInformation::createConfigWidget(Kit *k) const +KitAspectWidget *CMakeConfigurationKitAspect::createConfigWidget(Kit *k) const { if (!k) return nullptr; - return new Internal::CMakeConfigurationKitConfigWidget(k, this); + return new CMakeConfigurationKitAspectWidget(k, this); } +} // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.h b/src/plugins/cmakeprojectmanager/cmakekitinformation.h index 3da3f7d7b2..7920cc1a27 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.h +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.h @@ -25,21 +25,20 @@ #pragma once -#include "cmake_global.h" - #include "cmakeconfigitem.h" #include <projectexplorer/kitmanager.h> namespace CMakeProjectManager { - class CMakeTool; -class CMAKE_EXPORT CMakeKitInformation : public ProjectExplorer::KitInformation +namespace Internal { + +class CMakeKitAspect : public ProjectExplorer::KitAspect { Q_OBJECT public: - CMakeKitInformation(); + CMakeKitAspect(); static Core::Id id(); @@ -47,24 +46,23 @@ public: static CMakeTool *cmakeTool(const ProjectExplorer::Kit *k); static void setCMakeTool(ProjectExplorer::Kit *k, const Core::Id id); - // KitInformation interface - QVariant defaultValue(const ProjectExplorer::Kit *k) const final; - QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const final; + // KitAspect interface + ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const final; void setup(ProjectExplorer::Kit *k) final; void fix(ProjectExplorer::Kit *k) final; ItemList toUserOutput(const ProjectExplorer::Kit *k) const final; - ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const final; + ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const final; void addToMacroExpander(ProjectExplorer::Kit *k, Utils::MacroExpander *expander) const final; QSet<Core::Id> availableFeatures(const ProjectExplorer::Kit *k) const final; }; -class CMAKE_EXPORT CMakeGeneratorKitInformation : public ProjectExplorer::KitInformation +class CMakeGeneratorKitAspect : public ProjectExplorer::KitAspect { Q_OBJECT public: - CMakeGeneratorKitInformation(); + CMakeGeneratorKitAspect(); static QString generator(const ProjectExplorer::Kit *k); static QString extraGenerator(const ProjectExplorer::Kit *k); @@ -78,21 +76,23 @@ public: const QString &extraGenerator, const QString &platform, const QString &toolset); static QStringList generatorArguments(const ProjectExplorer::Kit *k); - // KitInformation interface - QVariant defaultValue(const ProjectExplorer::Kit *k) const final; - QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const final; + // KitAspect interface + ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const final; void setup(ProjectExplorer::Kit *k) final; void fix(ProjectExplorer::Kit *k) final; void upgrade(ProjectExplorer::Kit *k) final; ItemList toUserOutput(const ProjectExplorer::Kit *k) const final; - ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const final; + ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const final; + +private: + QVariant defaultValue(const ProjectExplorer::Kit *k) const; }; -class CMAKE_EXPORT CMakeConfigurationKitInformation : public ProjectExplorer::KitInformation +class CMakeConfigurationKitAspect : public ProjectExplorer::KitAspect { Q_OBJECT public: - CMakeConfigurationKitInformation(); + CMakeConfigurationKitAspect(); static CMakeConfig configuration(const ProjectExplorer::Kit *k); static void setConfiguration(ProjectExplorer::Kit *k, const CMakeConfig &config); @@ -102,13 +102,16 @@ public: static CMakeConfig defaultConfiguration(const ProjectExplorer::Kit *k); - // KitInformation interface - QVariant defaultValue(const ProjectExplorer::Kit *k) const final; - QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const final; + // KitAspect interface + ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const final; void setup(ProjectExplorer::Kit *k) final; void fix(ProjectExplorer::Kit *k) final; ItemList toUserOutput(const ProjectExplorer::Kit *k) const final; - ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const final; + ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const final; + +private: + QVariant defaultValue(const ProjectExplorer::Kit *k) const; }; +} // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp b/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp index 19f80d66cc..47c8219c06 100644 --- a/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp @@ -70,7 +70,7 @@ void CMakeLocatorFilter::prepareSearch(const QString &entry) const int index = title.indexOf(entry); if (index >= 0) { Core::LocatorFilterEntry filterEntry(this, title, cmakeProject->projectFilePath().toString()); - filterEntry.extraInfo = FileUtils::shortNativePath(cmakeProject->projectFilePath()); + filterEntry.extraInfo = cmakeProject->projectFilePath().shortNativePath(); filterEntry.highlightInfo = {index, entry.length()}; m_result.append(filterEntry); } diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.cpp b/src/plugins/cmakeprojectmanager/cmakeparser.cpp index a06a68f684..be67db464f 100644 --- a/src/plugins/cmakeprojectmanager/cmakeparser.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeparser.cpp @@ -67,12 +67,12 @@ void CMakeParser::stdError(const QString &line) m_skippedFirstEmptyLine = false; if (m_commonError.indexIn(trimmedLine) != -1) { - m_lastTask = Task(Task::Error, QString(), Utils::FileName::fromUserInput(m_commonError.cap(1)), + m_lastTask = Task(Task::Error, QString(), Utils::FilePath::fromUserInput(m_commonError.cap(1)), m_commonError.cap(2).toInt(), Constants::TASK_CATEGORY_BUILDSYSTEM); m_lines = 1; return; } else if (m_nextSubError.indexIn(trimmedLine) != -1) { - m_lastTask = Task(Task::Error, QString(), Utils::FileName::fromUserInput(m_nextSubError.cap(1)), -1, + m_lastTask = Task(Task::Error, QString(), Utils::FilePath::fromUserInput(m_nextSubError.cap(1)), -1, Constants::TASK_CATEGORY_BUILDSYSTEM); m_lines = 1; return; @@ -86,11 +86,11 @@ void CMakeParser::stdError(const QString &line) m_expectTripleLineErrorData = LINE_LOCATION; doFlush(); m_lastTask = Task(trimmedLine.contains(QLatin1String("Error")) ? Task::Error : Task::Warning, - QString(), Utils::FileName(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM); + QString(), Utils::FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM); return; } else if (trimmedLine.startsWith("CMake Error: ")) { m_lastTask = Task(Task::Error, trimmedLine.mid(13), - Utils::FileName(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM); + Utils::FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM); m_lines = 1; return; } @@ -100,7 +100,7 @@ void CMakeParser::stdError(const QString &line) { QRegularExpressionMatch m = m_locationLine.match(trimmedLine); QTC_CHECK(m.hasMatch()); - m_lastTask.file = Utils::FileName::fromUserInput(trimmedLine.mid(0, m.capturedStart())); + m_lastTask.file = Utils::FilePath::fromUserInput(trimmedLine.mid(0, m.capturedStart())); m_lastTask.line = m.captured(1).toInt(); m_expectTripleLineErrorData = LINE_DESCRIPTION; } @@ -146,7 +146,7 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() QTest::addColumn<OutputParserTester::Channel>("inputChannel"); QTest::addColumn<QString>("childStdOutLines"); QTest::addColumn<QString>("childStdErrLines"); - QTest::addColumn<QList<ProjectExplorer::Task> >("tasks"); + QTest::addColumn<Tasks>("tasks"); QTest::addColumn<QString>("outputLines"); const Core::Id categoryBuild = Constants::TASK_CATEGORY_BUILDSYSTEM; @@ -155,12 +155,12 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() QTest::newRow("pass-through stdout") << QString::fromLatin1("Sometext") << OutputParserTester::STDOUT << QString::fromLatin1("Sometext\n") << QString() - << QList<ProjectExplorer::Task>() + << Tasks() << QString(); QTest::newRow("pass-through stderr") << QString::fromLatin1("Sometext") << OutputParserTester::STDERR << QString() << QString::fromLatin1("Sometext\n") - << QList<ProjectExplorer::Task>() + << Tasks() << QString(); // positive tests @@ -177,14 +177,14 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() " .hxx .in .txx\n\n") << OutputParserTester::STDERR << QString() << QString() - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Error, QLatin1String("Cannot find source file: unknownFile.qml Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx"), - Utils::FileName::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), 70, + Utils::FilePath::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), 70, categoryBuild) << Task(Task::Error, QLatin1String("Cannot find source file: CMakeLists.txt2 Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx"), - Utils::FileName::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), -1, + Utils::FilePath::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), -1, categoryBuild)) << QString(); @@ -193,10 +193,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() " add_subdirectory given source \"app1\" which is not an existing directory.\n\n") << OutputParserTester::STDERR << QString() << QString() - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Error, QLatin1String("add_subdirectory given source \"app1\" which is not an existing directory."), - Utils::FileName::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8, + Utils::FilePath::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8, categoryBuild)) << QString(); @@ -205,10 +205,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() " Unknown CMake command \"i_am_wrong_command\".\n\n") << OutputParserTester::STDERR << QString() << QString() - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Error, QLatin1String("Unknown CMake command \"i_am_wrong_command\"."), - Utils::FileName::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8, + Utils::FilePath::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8, categoryBuild)) << QString(); @@ -217,10 +217,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() " message called with incorrect number of arguments\n\n") << OutputParserTester::STDERR << QString() << QString() - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Error, QLatin1String("message called with incorrect number of arguments"), - Utils::FileName::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8, + Utils::FilePath::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8, categoryBuild)) << QString(); @@ -231,10 +231,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() "\".") << OutputParserTester::STDERR << QString() << QString() - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Error, QLatin1String("Parse error. Expected \"(\", got newline with text \"\n\"."), - Utils::FileName::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9, + Utils::FilePath::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9, categoryBuild)) << QString(); @@ -244,10 +244,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() "CMAKE_MAKE_PROGRAM\n") << OutputParserTester::STDERR << QString() << QString::fromLatin1("Missing variable is:\nCMAKE_MAKE_PROGRAM\n") - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Error, QLatin1String("Error required internal CMake variable not set, cmake may be not be built correctly."), - Utils::FileName(), -1, categoryBuild)) + Utils::FilePath(), -1, categoryBuild)) << QString(); QTest::newRow("cmake error at") @@ -257,10 +257,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() " \".\n") << OutputParserTester::STDERR << QString() << QString() - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Error, QLatin1String("Parse error. Expected \"(\", got newline with text \" \"."), - Utils::FileName::fromUserInput(QLatin1String("CMakeLists.txt")), 4, + Utils::FilePath::fromUserInput(QLatin1String("CMakeLists.txt")), 4, categoryBuild)) << QString(); @@ -270,10 +270,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data() "Argument not separated from preceding token by whitespace.") << OutputParserTester::STDERR << QString() << QString() - << (QList<ProjectExplorer::Task>() + << (Tasks() << Task(Task::Warning, QLatin1String("Argument not separated from preceding token by whitespace."), - Utils::FileName::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9, + Utils::FilePath::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9, categoryBuild)) << QString(); } @@ -284,7 +284,7 @@ void Internal::CMakeProjectPlugin::testCMakeParser() testbench.appendOutputParser(new CMakeParser); QFETCH(QString, input); QFETCH(OutputParserTester::Channel, inputChannel); - QFETCH(QList<Task>, tasks); + QFETCH(Tasks, tasks); QFETCH(QString, childStdOutLines); QFETCH(QString, childStdErrLines); QFETCH(QString, outputLines); diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index a9d4d76b96..a3e7ca3c37 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -26,6 +26,7 @@ #include "cmakeproject.h" #include "cmakebuildconfiguration.h" +#include "cmakebuildstep.h" #include "cmakekitinformation.h" #include "cmakeprojectconstants.h" #include "cmakeprojectnodes.h" @@ -37,6 +38,7 @@ #include <cpptools/generatedcodemodelsupport.h> #include <cpptools/projectinfo.h> #include <cpptools/cpptoolsconstants.h> +#include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildtargetinfo.h> #include <projectexplorer/deploymentdata.h> #include <projectexplorer/headerpath.h> @@ -52,6 +54,7 @@ #include <utils/algorithm.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <utils/stringutils.h> #include <utils/hostosinfo.h> @@ -78,7 +81,7 @@ static CMakeBuildConfiguration *activeBc(const CMakeProject *p) /*! \class CMakeProject */ -CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEMIMETYPE, fileName), +CMakeProject::CMakeProject(const FilePath &fileName) : Project(Constants::CMAKEMIMETYPE, fileName), m_cppCodeModelUpdater(new CppTools::CppProjectUpdater) { setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID); @@ -211,7 +214,7 @@ CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEM // TreeScanner: connect(&m_treeScanner, &TreeScanner::finished, this, &CMakeProject::handleTreeScanningFinished); - m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FileName &fn) { + m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FilePath &fn) { // Mime checks requires more resources, so keep it last in check list auto isIgnored = fn.toString().startsWith(projectFilePath().toString() + ".user") || @@ -231,7 +234,7 @@ CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEM return isIgnored; }); - m_treeScanner.setTypeFactory([](const Utils::MimeType &mimeType, const Utils::FileName &fn) { + m_treeScanner.setTypeFactory([](const Utils::MimeType &mimeType, const Utils::FilePath &fn) { auto type = TreeScanner::genericFileType(mimeType, fn); if (type == FileType::Unknown) { if (mimeType.isValid()) { @@ -265,13 +268,57 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc) QTC_ASSERT(bc == aBc, return); QTC_ASSERT(m_treeScanner.isFinished() && !m_buildDirManager.isParsing(), return); - bc->setBuildTargets(m_buildDirManager.takeBuildTargets()); - bc->setConfigurationFromCMake(m_buildDirManager.takeCMakeConfiguration()); + const QList<CMakeBuildTarget> buildTargets = m_buildDirManager.takeBuildTargets(); + bc->setBuildTargets(buildTargets); + const CMakeConfig cmakeConfig = m_buildDirManager.takeCMakeConfiguration(); + bc->setConfigurationFromCMake(cmakeConfig); + + CMakeConfig patchedConfig = cmakeConfig; + { + CMakeConfigItem settingFileItem; + settingFileItem.key = "ANDROID_DEPLOYMENT_SETTINGS_FILE"; + settingFileItem.value = bc->buildDirectory() + .pathAppended("android_deployment_settings.json").toString().toUtf8(); + patchedConfig.append(settingFileItem); + } + + QSet<QString> res; + QStringList apps; + for (const auto &target : bc->buildTargets()) { + if (target.targetType == CMakeProjectManager::DynamicLibraryType) { + res.insert(target.executable.parentDir().toString()); + apps.push_back(target.executable.toUserOutput()); + } + // ### shall we add also the ExecutableType ? + } + { + CMakeConfigItem paths; + paths.key = "ANDROID_SO_LIBS_PATHS"; + paths.values = res.toList(); + patchedConfig.append(paths); + } + + apps.sort(); + { + CMakeConfigItem appsPaths; + appsPaths.key = "TARGETS_BUILD_PATH"; + appsPaths.values = apps; + patchedConfig.append(appsPaths); + } + auto newRoot = generateProjectTree(m_allFiles); if (newRoot) { setDisplayName(newRoot->displayName()); setRootProjectNode(std::move(newRoot)); + + for (const CMakeBuildTarget &bt : buildTargets) { + const QString buildKey = CMakeTargetNode::generateId(bt.sourceDirectory, bt.title); + if (ProjectNode *node = findNodeForBuildKey(buildKey)) { + if (auto targetNode = dynamic_cast<CMakeTargetNode *>(node)) + targetNode->setConfig(patchedConfig); + } + } } Target *t = bc->target(); @@ -334,7 +381,7 @@ void CMakeProject::updateQmlJSCodeModel() } foreach (const QString &cmakeImport, CMakeConfigItem::cmakeSplitValue(cmakeImports)) - projectInfo.importPaths.maybeInsert(FileName::fromString(cmakeImport), QmlJS::Dialect::Qml); + projectInfo.importPaths.maybeInsert(FilePath::fromString(cmakeImport), QmlJS::Dialect::Qml); modelManager->updateProjectInfo(projectInfo, this); } @@ -355,13 +402,13 @@ bool CMakeProject::knowsAllBuildExecutables() const return false; } -QList<Task> CMakeProject::projectIssues(const Kit *k) const +Tasks CMakeProject::projectIssues(const Kit *k) const { - QList<Task> result = Project::projectIssues(k); + Tasks result = Project::projectIssues(k); - if (!CMakeKitInformation::cmakeTool(k)) + if (!CMakeKitAspect::cmakeTool(k)) result.append(createProjectTask(Task::TaskType::Error, tr("No cmake tool set."))); - if (ToolChainKitInformation::toolChains(k).isEmpty()) + if (ToolChainKitAspect::toolChains(k).isEmpty()) result.append(createProjectTask(Task::TaskType::Warning, tr("No compilers set in kit."))); return result; @@ -541,17 +588,16 @@ QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const if (!activeTarget()) return QStringList(); QFileInfo fi(sourceFile); - FileName project = projectDirectory(); - FileName baseDirectory = FileName::fromString(fi.absolutePath()); + FilePath project = projectDirectory(); + FilePath baseDirectory = FilePath::fromString(fi.absolutePath()); while (baseDirectory.isChildOf(project)) { - FileName cmakeListsTxt = baseDirectory; - cmakeListsTxt.appendPath("CMakeLists.txt"); + const FilePath cmakeListsTxt = baseDirectory.pathAppended("CMakeLists.txt"); if (cmakeListsTxt.exists()) break; QDir dir(baseDirectory.toString()); dir.cdUp(); - baseDirectory = FileName::fromString(dir.absolutePath()); + baseDirectory = FilePath::fromString(dir.absolutePath()); } QDir srcDirRoot = QDir(project.toString()); @@ -575,6 +621,29 @@ QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const } } +ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const +{ + return contains(files(AllFiles), [](const FilePath &f) { + return f.fileName() == "QtCreatorDeployment.txt"; + }) ? DeploymentKnowledge::Approximative : DeploymentKnowledge::Bad; +} + +MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target, + const QString &installRoot) +{ + MakeInstallCommand cmd; + if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) { + if (const auto cmakeStep = bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD) + ->firstOfType<CMakeBuildStep>()) { + if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target->kit())) + cmd.command = tool->cmakeExecutable(); + } + } + cmd.arguments << "--build" << "." << "--target" << "install"; + cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot)); + return cmd; +} + bool CMakeProject::mustUpdateCMakeStateBeforeBuild() { return m_delayedParsingTimer.isActive(); @@ -590,7 +659,7 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeProject::findExtraCompilers() const = Utils::transform<QSet>(factories, &ExtraCompilerFactory::sourceTag); // Find all files generated by any of the extra compilers, in a rather crude way. - const FileNameList fileList = files([&fileExtensions](const Node *n) { + const FilePathList fileList = files([&fileExtensions](const Node *n) { if (!SourceFiles(n)) return false; const QString fp = n->filePath().toString(); @@ -599,7 +668,7 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeProject::findExtraCompilers() const }); // Generate the necessary information: - for (const FileName &file : fileList) { + for (const FilePath &file : fileList) { ExtraCompilerFactory *factory = Utils::findOrDefault(factories, [&file](const ExtraCompilerFactory *f) { return file.endsWith('.' + f->sourceTag()); }); @@ -609,9 +678,9 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeProject::findExtraCompilers() const if (generated.isEmpty()) continue; - const FileNameList fileNames + const FilePathList fileNames = transform(generated, - [](const QString &s) { return FileName::fromString(s); }); + [](const QString &s) { return FilePath::fromString(s); }); extraCompilers.append(factory->create(this, file, fileNames)); } diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 686d93996f..3af409f1b6 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -30,11 +30,11 @@ #include "builddirmanager.h" #include "cmakebuildtarget.h" #include "cmakeprojectimporter.h" -#include "treescanner.h" #include <projectexplorer/extracompiler.h> -#include <projectexplorer/projectmacro.h> #include <projectexplorer/project.h> +#include <projectexplorer/projectmacro.h> +#include <projectexplorer/treescanner.h> #include <utils/fileutils.h> @@ -60,14 +60,14 @@ class CMAKE_EXPORT CMakeProject : public ProjectExplorer::Project Q_OBJECT public: - explicit CMakeProject(const Utils::FileName &filename); + explicit CMakeProject(const Utils::FilePath &filename); ~CMakeProject() final; QStringList buildTargetTitles() const; bool knowsAllBuildExecutables() const final; - QList<ProjectExplorer::Task> projectIssues(const ProjectExplorer::Kit *k) const final; + ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final; void runCMake(); void runCMakeAndScanProjectTree(); @@ -103,12 +103,17 @@ private: QList<ProjectExplorer::ExtraCompiler *> findExtraCompilers() const; QStringList filesGeneratedFrom(const QString &sourceFile) const final; + ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override; + bool hasMakeInstallEquivalent() const override { return true; } + ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target, + const QString &installRoot) override; + // TODO probably need a CMake specific node structure QList<CMakeBuildTarget> m_buildTargets; CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr; QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers; - Internal::TreeScanner m_treeScanner; + ProjectExplorer::TreeScanner m_treeScanner; Internal::BuildDirManager m_buildDirManager; bool m_waitingForScan = false; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h index e1e1a0114e..8714f04111 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h @@ -38,6 +38,8 @@ const char RUNCMAKE[] = "CMakeProject.RunCMake"; const char CLEARCMAKECACHE[] = "CMakeProject.ClearCache"; const char RESCANPROJECT[] = "CMakeProject.RescanProject"; const char RUNCMAKECONTEXTMENU[] = "CMakeProject.RunCMakeContextMenu"; +const char BUILDFILECONTEXTMENU[] = "CMakeProject.BuildFileContextMenu"; +const char BUILDFILE[] = "CMakeProject.BuildFile"; // Project const char CMAKEPROJECT_ID[] = "CMakeProjectManager.CMakeProject"; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp index 170e52e933..e647692439 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp @@ -47,6 +47,7 @@ using namespace ProjectExplorer; using namespace QtSupport; +using namespace Utils; namespace { @@ -55,7 +56,7 @@ Q_LOGGING_CATEGORY(cmInputLog, "qtc.cmake.import", QtWarningMsg); struct CMakeToolChainData { QByteArray languageId; - Utils::FileName compilerPath; + Utils::FilePath compilerPath; Core::Id mapLanguageIdToQtC() const { const QByteArray li = languageId.toLower(); @@ -72,10 +73,10 @@ struct DirectoryData { // Project Stuff: QByteArray cmakeBuildType; - Utils::FileName buildDirectory; + Utils::FilePath buildDirectory; // Kit Stuff - Utils::FileName cmakeBinary; + Utils::FilePath cmakeBinary; QByteArray generator; QByteArray extraGenerator; QByteArray platform; @@ -105,9 +106,9 @@ static QStringList scanDirectory(const QString &path, const QString &prefix) namespace CMakeProjectManager { namespace Internal { -CMakeProjectImporter::CMakeProjectImporter(const Utils::FileName &path) : QtProjectImporter(path) +CMakeProjectImporter::CMakeProjectImporter(const Utils::FilePath &path) : QtProjectImporter(path) { - useTemporaryKitInformation(CMakeKitInformation::id(), + useTemporaryKitAspect(CMakeKitAspect::id(), [this](Kit *k, const QVariantList &vl) { cleanupTemporaryCMake(k, vl); }, [this](Kit *k, const QVariantList &vl) { persistTemporaryCMake(k, vl); }); @@ -130,24 +131,24 @@ QStringList CMakeProjectImporter::importCandidates() return finalists; } -static Utils::FileName qmakeFromCMakeCache(const CMakeConfig &config) +static Utils::FilePath qmakeFromCMakeCache(const CMakeConfig &config) { // Qt4 way to define things (more convenient for us, so try this first;-) - Utils::FileName qmake - = Utils::FileName::fromUtf8(CMakeConfigItem::valueOf(QByteArray("QT_QMAKE_EXECUTABLE"), config)); + Utils::FilePath qmake + = Utils::FilePath::fromUtf8(CMakeConfigItem::valueOf(QByteArray("QT_QMAKE_EXECUTABLE"), config)); qCDebug(cmInputLog()) << "QT_QMAKE_EXECUTABLE=" << qmake.toUserOutput(); if (!qmake.isEmpty()) return qmake; // Check Qt5 settings: oh, the horror! - const Utils::FileName qtCMakeDir - = Utils::FileName::fromUtf8(CMakeConfigItem::valueOf(QByteArray("Qt5Core_DIR"), config)); + const Utils::FilePath qtCMakeDir + = Utils::FilePath::fromUtf8(CMakeConfigItem::valueOf(QByteArray("Qt5Core_DIR"), config)); qCDebug(cmInputLog()) << "Qt5Core_DIR=" << qtCMakeDir.toUserOutput(); - const Utils::FileName canQtCMakeDir = Utils::FileName::fromString(qtCMakeDir.toFileInfo().canonicalFilePath()); + const Utils::FilePath canQtCMakeDir = Utils::FilePath::fromString(qtCMakeDir.toFileInfo().canonicalFilePath()); qCInfo(cmInputLog()) << "Qt5Core_DIR (canonical)=" << canQtCMakeDir.toUserOutput(); if (qtCMakeDir.isEmpty()) - return Utils::FileName(); - const Utils::FileName baseQtDir = canQtCMakeDir.parentDir().parentDir().parentDir(); // Up 3 levels... + return Utils::FilePath(); + const Utils::FilePath baseQtDir = canQtCMakeDir.parentDir().parentDir().parentDir(); // Up 3 levels... qCDebug(cmInputLog()) << "BaseQtDir:" << baseQtDir.toUserOutput(); // "Parse" Qt5Core/Qt5CoreConfigExtras.cmake: @@ -166,7 +167,7 @@ static Utils::FileName qmakeFromCMakeCache(const CMakeConfig &config) QFile extras(qtCMakeDir.toString() + "/Qt5CoreConfigExtras.cmake"); if (!extras.open(QIODevice::ReadOnly)) - return Utils::FileName(); + return Utils::FilePath(); QByteArray data; bool inQmakeSection = false; @@ -201,22 +202,20 @@ static Utils::FileName qmakeFromCMakeCache(const CMakeConfig &config) const int sp = origLine.indexOf('}'); const int ep = origLine.lastIndexOf('"'); - QTC_ASSERT(sp > 0, return Utils::FileName()); - QTC_ASSERT(ep > sp + 2, return Utils::FileName()); - QTC_ASSERT(ep < origLine.count(), return Utils::FileName()); + QTC_ASSERT(sp > 0, return Utils::FilePath()); + QTC_ASSERT(ep > sp + 2, return Utils::FilePath()); + QTC_ASSERT(ep < origLine.count(), return Utils::FilePath()); // Eat the leading "}/" and trailing " const QByteArray locationPart = origLine.mid(sp + 2, ep - 2 - sp); - Utils::FileName result = baseQtDir; - result.appendPath(QString::fromUtf8(locationPart)); - return result; + return baseQtDir.pathAppended(QString::fromUtf8(locationPart)); } } } } // Now try to make sense of .../Qt5CoreConfig.cmake: - return Utils::FileName(); + return Utils::FilePath(); } QVector<CMakeToolChainData> extractToolChainsFromCache(const CMakeConfig &config) @@ -226,16 +225,15 @@ QVector<CMakeToolChainData> extractToolChainsFromCache(const CMakeConfig &config if (!i.key.startsWith("CMAKE_") || !i.key.endsWith("_COMPILER")) continue; const QByteArray language = i.key.mid(6, i.key.count() - 6 - 9); // skip "CMAKE_" and "_COMPILER" - result.append({language, Utils::FileName::fromUtf8(i.value)}); + result.append({language, Utils::FilePath::fromUtf8(i.value)}); } return result; } -QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &importPath) const +QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FilePath &importPath) const { qCInfo(cmInputLog()) << "Examining directory:" << importPath.toUserOutput(); - Utils::FileName cacheFile = importPath; - cacheFile.appendPath("CMakeCache.txt"); + const FilePath cacheFile = importPath.pathAppended("CMakeCache.txt"); if (!cacheFile.exists()) { qCDebug(cmInputLog()) << cacheFile.toUserOutput() << "does not exist, returning."; @@ -249,8 +247,8 @@ QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &impo return { }; } const auto homeDir - = Utils::FileName::fromUserInput(QString::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", config))); - const Utils::FileName canonicalProjectDirectory = Utils::FileUtils::canonicalPath(projectDirectory()); + = Utils::FilePath::fromUserInput(QString::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", config))); + const Utils::FilePath canonicalProjectDirectory = projectDirectory().canonicalPath(); if (homeDir != canonicalProjectDirectory) { qCDebug(cmInputLog()) << "Wrong source directory:" << homeDir.toUserOutput() << "expected:" << canonicalProjectDirectory.toUserOutput(); @@ -262,7 +260,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &impo data->cmakeBuildType = CMakeConfigItem::valueOf("CMAKE_BUILD_TYPE", config); data->cmakeBinary - = Utils::FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_COMMAND", config)); + = Utils::FilePath::fromUtf8(CMakeConfigItem::valueOf("CMAKE_COMMAND", config)); data->generator = CMakeConfigItem::valueOf("CMAKE_GENERATOR", config); data->extraGenerator = CMakeConfigItem::valueOf("CMAKE_EXTRA_GENERATOR", config); data->platform = CMakeConfigItem::valueOf("CMAKE_GENERATOR_PLATFORM", config); @@ -271,7 +269,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &impo data->sysroot = CMakeConfigItem::valueOf("CMAKE_SYSROOT", config); // Qt: - const Utils::FileName qmake = qmakeFromCMakeCache(config); + const Utils::FilePath qmake = qmakeFromCMakeCache(config); if (!qmake.isEmpty()) data->qt = findOrCreateQtVersion(qmake); @@ -286,24 +284,24 @@ bool CMakeProjectImporter::matchKit(void *directoryData, const Kit *k) const { const DirectoryData *data = static_cast<DirectoryData *>(directoryData); - CMakeTool *cm = CMakeKitInformation::cmakeTool(k); + CMakeTool *cm = CMakeKitAspect::cmakeTool(k); if (!cm || cm->cmakeExecutable() != data->cmakeBinary) return false; - if (CMakeGeneratorKitInformation::generator(k) != QString::fromUtf8(data->generator) - || CMakeGeneratorKitInformation::extraGenerator(k) != QString::fromUtf8(data->extraGenerator) - || CMakeGeneratorKitInformation::platform(k) != QString::fromUtf8(data->platform) - || CMakeGeneratorKitInformation::toolset(k) != QString::fromUtf8(data->toolset)) + if (CMakeGeneratorKitAspect::generator(k) != QString::fromUtf8(data->generator) + || CMakeGeneratorKitAspect::extraGenerator(k) != QString::fromUtf8(data->extraGenerator) + || CMakeGeneratorKitAspect::platform(k) != QString::fromUtf8(data->platform) + || CMakeGeneratorKitAspect::toolset(k) != QString::fromUtf8(data->toolset)) return false; - if (SysRootKitInformation::sysRoot(k) != Utils::FileName::fromUtf8(data->sysroot)) + if (SysRootKitAspect::sysRoot(k) != Utils::FilePath::fromUtf8(data->sysroot)) return false; - if (data->qt.qt && QtSupport::QtKitInformation::qtVersionId(k) != data->qt.qt->uniqueId()) + if (data->qt.qt && QtSupport::QtKitAspect::qtVersionId(k) != data->qt.qt->uniqueId()) return false; for (const CMakeToolChainData &tcd : data->toolChains) { - ToolChain *tc = ToolChainKitInformation::toolChain(k, tcd.mapLanguageIdToQtC()); + ToolChain *tc = ToolChainKitAspect::toolChain(k, tcd.mapLanguageIdToQtC()); if (!tc || tc->compilerCommand() != tcd.compilerPath) return false; } @@ -321,14 +319,14 @@ Kit *CMakeProjectImporter::createKit(void *directoryData) const const CMakeToolData cmtd = findOrCreateCMakeTool(data->cmakeBinary); QTC_ASSERT(cmtd.cmakeTool, return); if (cmtd.isTemporary) - addTemporaryData(CMakeKitInformation::id(), cmtd.cmakeTool->id().toSetting(), k); + addTemporaryData(CMakeKitAspect::id(), cmtd.cmakeTool->id().toSetting(), k); - CMakeGeneratorKitInformation::setGenerator(k, QString::fromUtf8(data->generator)); - CMakeGeneratorKitInformation::setExtraGenerator(k, QString::fromUtf8(data->extraGenerator)); - CMakeGeneratorKitInformation::setPlatform(k, QString::fromUtf8(data->platform)); - CMakeGeneratorKitInformation::setToolset(k, QString::fromUtf8(data->toolset)); + CMakeGeneratorKitAspect::setGenerator(k, QString::fromUtf8(data->generator)); + CMakeGeneratorKitAspect::setExtraGenerator(k, QString::fromUtf8(data->extraGenerator)); + CMakeGeneratorKitAspect::setPlatform(k, QString::fromUtf8(data->platform)); + CMakeGeneratorKitAspect::setToolset(k, QString::fromUtf8(data->toolset)); - SysRootKitInformation::setSysRoot(k, Utils::FileName::fromUtf8(data->sysroot)); + SysRootKitAspect::setSysRoot(k, Utils::FilePath::fromUtf8(data->sysroot)); for (const CMakeToolChainData &cmtcd : data->toolChains) { const ToolChainData tcd @@ -337,10 +335,10 @@ Kit *CMakeProjectImporter::createKit(void *directoryData) const if (tcd.areTemporary) { for (ToolChain *tc : tcd.tcs) - addTemporaryData(ToolChainKitInformation::id(), tc->id(), k); + addTemporaryData(ToolChainKitAspect::id(), tc->id(), k); } - ToolChainKitInformation::setToolChain(k, tcd.tcs.at(0)); + ToolChainKitAspect::setToolChain(k, tcd.tcs.at(0)); } qCInfo(cmInputLog()) << "Temporary Kit created."; @@ -366,7 +364,7 @@ const QList<BuildInfo> CMakeProjectImporter::buildInfoListForKit(const Kit *k, v } CMakeProjectImporter::CMakeToolData -CMakeProjectImporter::findOrCreateCMakeTool(const Utils::FileName &cmakeToolPath) const +CMakeProjectImporter::findOrCreateCMakeTool(const Utils::FilePath &cmakeToolPath) const { CMakeToolData result; result.cmakeTool = CMakeToolManager::findByCommand(cmakeToolPath); @@ -388,7 +386,7 @@ void CMakeProjectImporter::cleanupTemporaryCMake(Kit *k, const QVariantList &vl) if (vl.isEmpty()) return; // No temporary CMake QTC_ASSERT(vl.count() == 1, return); - CMakeKitInformation::setCMakeTool(k, Core::Id()); // Always mark Kit as not using this Qt + CMakeKitAspect::setCMakeTool(k, Core::Id()); // Always mark Kit as not using this Qt CMakeToolManager::deregisterCMakeTool(Core::Id::fromSetting(vl.at(0))); qCDebug(cmInputLog()) << "Temporary CMake tool cleaned up."; } @@ -400,7 +398,7 @@ void CMakeProjectImporter::persistTemporaryCMake(Kit *k, const QVariantList &vl) QTC_ASSERT(vl.count() == 1, return); const QVariant data = vl.at(0); CMakeTool *tmpCmake = CMakeToolManager::findById(Core::Id::fromSetting(data)); - CMakeTool *actualCmake = CMakeKitInformation::cmakeTool(k); + CMakeTool *actualCmake = CMakeKitAspect::cmakeTool(k); // User changed Kit away from temporary CMake that was set up: if (tmpCmake && actualCmake != tmpCmake) @@ -450,7 +448,7 @@ void CMakeProjectPlugin::testCMakeProjectImporterQt() config.append(CMakeConfigItem(key.toUtf8(), value.toUtf8())); } - Utils::FileName realQmake = qmakeFromCMakeCache(config); + Utils::FilePath realQmake = qmakeFromCMakeCache(config); QCOMPARE(realQmake.toString(), expectedQmake); } void CMakeProjectPlugin::testCMakeProjectImporterToolChain_data() diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h index c86fe77041..9940da3723 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h @@ -36,12 +36,12 @@ namespace Internal { class CMakeProjectImporter : public QtSupport::QtProjectImporter { public: - CMakeProjectImporter(const Utils::FileName &path); + CMakeProjectImporter(const Utils::FilePath &path); QStringList importCandidates() final; private: - QList<void *> examineDirectory(const Utils::FileName &importPath) const final; + QList<void *> examineDirectory(const Utils::FilePath &importPath) const final; bool matchKit(void *directoryData, const ProjectExplorer::Kit *k) const final; ProjectExplorer::Kit *createKit(void *directoryData) const final; const QList<ProjectExplorer::BuildInfo> buildInfoListForKit(const ProjectExplorer::Kit *k, @@ -51,7 +51,7 @@ private: bool isTemporary = false; CMakeTool *cmakeTool = nullptr; }; - CMakeToolData findOrCreateCMakeTool(const Utils::FileName &cmakeToolPath) const; + CMakeToolData findOrCreateCMakeTool(const Utils::FilePath &cmakeToolPath) const; void deleteDirectoryData(void *directoryData) const final; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index 63fe9c5fbb..21be7d1995 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -30,11 +30,14 @@ #include "cmakeproject.h" #include "cmakesettingspage.h" #include "cmaketoolmanager.h" +#include "cmakeprojectnodes.h" #include <coreplugin/icore.h> +#include <coreplugin/messagemanager.h> #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/editormanager/editormanager.h> #include <projectexplorer/buildmanager.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorerconstants.h> @@ -42,6 +45,8 @@ #include <projectexplorer/session.h> #include <projectexplorer/target.h> +#include <utils/parameteraction.h> + #include <QAction> #include <QDateTime> #include <QIcon> @@ -61,6 +66,8 @@ CMakeManager::CMakeManager() : Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT); Core::ActionContainer *msubproject = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT); + Core::ActionContainer *mfile = + Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FILECONTEXT); const Core::Context projectContext(CMakeProjectManager::Constants::CMAKEPROJECT_ID); const Core::Context globalContext(Core::Constants::C_GLOBAL); @@ -90,6 +97,14 @@ CMakeManager::CMakeManager() : runCMake(ProjectTree::currentProject()); }); + m_buildFileContextMenu = new QAction(tr("Build"), this); + command = Core::ActionManager::registerAction(m_buildFileContextMenu, + Constants::BUILDFILECONTEXTMENU, projectContext); + command->setAttribute(Core::Command::CA_Hide); + mfile->addAction(command, ProjectExplorer::Constants::G_FILE_OTHER); + connect(m_buildFileContextMenu, &QAction::triggered, + this, &CMakeManager::buildFileContextMenu); + command = Core::ActionManager::registerAction(m_rescanProjectAction, Constants::RESCANPROJECT, globalContext); command->setAttribute(Core::Command::CA_Hide); @@ -98,10 +113,24 @@ CMakeManager::CMakeManager() : rescanProject(ProjectTree::currentProject()); }); + m_buildFileAction = new Utils::ParameterAction(tr("Build File"), tr("Build File \"%1\""), + Utils::ParameterAction::AlwaysEnabled, this); + command = Core::ActionManager::registerAction(m_buildFileAction, Constants::BUILDFILE); + command->setAttribute(Core::Command::CA_Hide); + command->setAttribute(Core::Command::CA_UpdateText); + command->setDescription(m_buildFileAction->text()); + command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+B"))); + mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD); + connect(m_buildFileAction, &QAction::triggered, this, [this] { buildFile(); }); + connect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, &CMakeManager::updateCmakeActions); connect(BuildManager::instance(), &BuildManager::buildStateChanged, this, &CMakeManager::updateCmakeActions); + connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, + this, &CMakeManager::updateBuildFileAction); + connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged, + this, &CMakeManager::updateCmakeActions); updateCmakeActions(); } @@ -113,6 +142,7 @@ void CMakeManager::updateCmakeActions() m_runCMakeAction->setVisible(visible); m_clearCMakeCacheAction->setVisible(visible); m_rescanProjectAction->setVisible(visible); + enableBuildFileMenus(ProjectTree::currentNode()); } void CMakeManager::clearCMakeCache(Project *project) @@ -144,3 +174,89 @@ void CMakeManager::rescanProject(Project *project) cmakeProject->runCMakeAndScanProjectTree();// by my experience: every rescan run requires cmake run too } + +void CMakeManager::updateBuildFileAction() +{ + Node *node = nullptr; + if (Core::IDocument *currentDocument = Core::EditorManager::currentDocument()) + node = ProjectTree::nodeForFile(currentDocument->filePath()); + enableBuildFileMenus(node); +} + +void CMakeManager::enableBuildFileMenus(Node *node) +{ + m_buildFileAction->setVisible(false); + m_buildFileAction->setEnabled(false); + m_buildFileAction->setParameter(QString()); + m_buildFileContextMenu->setEnabled(false); + + if (!node) + return; + Project *project = ProjectTree::projectForNode(node); + if (!project) + return; + Target *target = project->activeTarget(); + if (!target) + return; + const QString generator = CMakeGeneratorKitAspect::generator(target->kit()); + if (generator != "Ninja" && !generator.contains("Makefiles")) + return; + + if (const FileNode *fileNode = node->asFileNode()) { + const FileType type = fileNode->fileType(); + const bool visible = qobject_cast<CMakeProject *>(project) + && dynamic_cast<CMakeTargetNode *>(node->parentProjectNode()) + && (type == FileType::Source || type == FileType::Header); + + const bool enabled = visible && !BuildManager::isBuilding(project); + m_buildFileAction->setVisible(visible); + m_buildFileAction->setEnabled(enabled); + m_buildFileAction->setParameter(node->filePath().fileName()); + m_buildFileContextMenu->setEnabled(enabled); + } +} + +void CMakeManager::buildFile(Node *node) +{ + if (!node) { + Core::IDocument *currentDocument= Core::EditorManager::currentDocument(); + if (!currentDocument) + return; + const Utils::FilePath file = currentDocument->filePath(); + node = ProjectTree::nodeForFile(file); + } + FileNode *fileNode = node ? node->asFileNode() : nullptr; + if (!fileNode) + return; + Project *project = ProjectTree::projectForNode(fileNode); + if (!project) + return; + CMakeTargetNode *targetNode = dynamic_cast<CMakeTargetNode *>(fileNode->parentProjectNode()); + if (!targetNode) + return; + auto cmakeProject = static_cast<CMakeProject *>(project); + Target *target = cmakeProject->activeTarget(); + const QString generator = CMakeGeneratorKitAspect::generator(target->kit()); + const QString relativeSource = fileNode->filePath().relativeChildPath(targetNode->filePath()).toString(); + const QString objExtension = Utils::HostOsInfo::isWindowsHost() ? QString(".obj") : QString(".o"); + Utils::FilePath targetBase; + if (generator == "Ninja") { + BuildConfiguration *bc = target->activeBuildConfiguration(); + const Utils::FilePath relativeBuildDir = targetNode->buildDirectory().relativeChildPath( + bc->buildDirectory()); + targetBase = relativeBuildDir + .pathAppended("CMakeFiles") + .pathAppended(targetNode->displayName() + ".dir"); + } else if (!generator.contains("Makefiles")) { + Core::MessageManager::write(tr("Build File is not supported for generator \"%1\"") + .arg(generator)); + return; + } + cmakeProject->buildCMakeTarget(targetBase.pathAppended(relativeSource).toString() + objExtension); +} + +void CMakeManager::buildFileContextMenu() +{ + if (Node *node = ProjectTree::currentNode()) + buildFile(node); +} diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h index 0a045c19c0..eab78b190a 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h @@ -27,6 +27,8 @@ #include <projectexplorer/project.h> +namespace Utils { class ParameterAction; } + QT_BEGIN_NAMESPACE class QAction; QT_END_NAMESPACE @@ -34,7 +36,6 @@ QT_END_NAMESPACE namespace CMakeProjectManager { namespace Internal { - class CMakeManager : public QObject { Q_OBJECT @@ -47,11 +48,17 @@ private: void clearCMakeCache(ProjectExplorer::Project *project); void runCMake(ProjectExplorer::Project *project); void rescanProject(ProjectExplorer::Project *project); + void buildFileContextMenu(); + void buildFile(ProjectExplorer::Node *node = nullptr); + void updateBuildFileAction(); + void enableBuildFileMenus(ProjectExplorer::Node *node); QAction *m_runCMakeAction; QAction *m_clearCMakeCacheAction; QAction *m_runCMakeActionContextMenu; QAction *m_rescanProjectAction; + QAction *m_buildFileContextMenu; + Utils::ParameterAction *m_buildFileAction; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro index 641c53bb25..dc4e30223b 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro @@ -25,7 +25,6 @@ HEADERS = builddirmanager.h \ cmaketoolmanager.h \ cmake_global.h \ cmakekitinformation.h \ - cmakekitconfigwidget.h \ cmakecbpparser.h \ cmakebuildsettingswidget.h \ cmakeindenter.h \ @@ -36,14 +35,12 @@ HEADERS = builddirmanager.h \ configmodelitemdelegate.h \ servermode.h \ servermodereader.h \ - tealeafreader.h \ - treescanner.h + tealeafreader.h SOURCES = builddirmanager.cpp \ builddirparameters.cpp \ builddirreader.cpp \ cmakebuildstep.cpp \ - cmakebuildtarget.cpp \ cmakeconfigitem.cpp \ cmakeproject.cpp \ cmakeprojectimporter.cpp \ @@ -61,7 +58,6 @@ SOURCES = builddirmanager.cpp \ cmakesettingspage.cpp \ cmaketoolmanager.cpp \ cmakekitinformation.cpp \ - cmakekitconfigwidget.cpp \ cmakecbpparser.cpp \ cmakebuildsettingswidget.cpp \ cmakeindenter.cpp \ @@ -72,8 +68,7 @@ SOURCES = builddirmanager.cpp \ configmodelitemdelegate.cpp \ servermode.cpp \ servermodereader.cpp \ - tealeafreader.cpp \ - treescanner.cpp \ + tealeafreader.cpp RESOURCES += cmakeproject.qrc diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs index cfa9b36e30..e31c42886a 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs @@ -32,7 +32,6 @@ QtcPlugin { "cmakebuildsettingswidget.h", "cmakebuildstep.cpp", "cmakebuildstep.h", - "cmakebuildtarget.cpp", "cmakebuildtarget.h", "cmakecbpparser.cpp", "cmakecbpparser.h", @@ -42,8 +41,6 @@ QtcPlugin { "cmakeeditor.h", "cmakefilecompletionassist.cpp", "cmakefilecompletionassist.h", - "cmakekitconfigwidget.h", - "cmakekitconfigwidget.cpp", "cmakekitinformation.h", "cmakekitinformation.cpp", "cmakelocatorfilter.cpp", @@ -90,8 +87,6 @@ QtcPlugin { "servermodereader.cpp", "servermodereader.h", "tealeafreader.cpp", - "tealeafreader.h", - "treescanner.cpp", - "treescanner.h" + "tealeafreader.h" ] } diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp index 64541593b9..f14f627b34 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp @@ -25,22 +25,31 @@ #include "cmakeprojectnodes.h" +#include "cmakeconfigitem.h" #include "cmakeprojectconstants.h" #include "cmakeprojectplugin.h" + +#include <android/androidconstants.h> + #include <coreplugin/fileiconprovider.h> #include <coreplugin/icore.h> #include <cpptools/cpptoolsconstants.h> + +#include <projectexplorer/target.h> + #include <utils/algorithm.h> #include <utils/checkablemessagebox.h> #include <utils/mimetypes/mimedatabase.h> #include <utils/optional.h> - +#include <utils/qtcassert.h> #include <QClipboard> #include <QDir> #include <QGuiApplication> #include <QMessageBox> +using namespace ProjectExplorer; + using namespace CMakeProjectManager; using namespace CMakeProjectManager::Internal; @@ -106,8 +115,8 @@ void noAutoAdditionNotify(const QStringList &filePaths, const ProjectExplorer::P } -CMakeInputsNode::CMakeInputsNode(const Utils::FileName &cmakeLists) : - ProjectExplorer::ProjectNode(cmakeLists, generateId(cmakeLists)) +CMakeInputsNode::CMakeInputsNode(const Utils::FilePath &cmakeLists) : + ProjectExplorer::ProjectNode(cmakeLists) { setPriority(Node::DefaultPriority - 10); // Bottom most! setDisplayName(QCoreApplication::translate("CMakeFilesProjectNode", "CMake Modules")); @@ -115,17 +124,7 @@ CMakeInputsNode::CMakeInputsNode(const Utils::FileName &cmakeLists) : setListInProject(false); } -QByteArray CMakeInputsNode::generateId(const Utils::FileName &inputFile) -{ - return inputFile.toString().toUtf8() + "/cmakeInputs"; -} - -bool CMakeInputsNode::showInSimpleTree() const -{ - return true; -} - -CMakeListsNode::CMakeListsNode(const Utils::FileName &cmakeListPath) : +CMakeListsNode::CMakeListsNode(const Utils::FilePath &cmakeListPath) : ProjectExplorer::ProjectNode(cmakeListPath) { static QIcon folderIcon = Core::FileIconProvider::directoryIcon(Constants::FILEOVERLAY_CMAKE); @@ -143,13 +142,12 @@ bool CMakeListsNode::supportsAction(ProjectExplorer::ProjectAction action, const return action == ProjectExplorer::ProjectAction::AddNewFile; } -Utils::optional<Utils::FileName> CMakeListsNode::visibleAfterAddFileAction() const +Utils::optional<Utils::FilePath> CMakeListsNode::visibleAfterAddFileAction() const { - Utils::FileName projFile{filePath()}; - return projFile.appendPath("CMakeLists.txt"); + return filePath().pathAppended("CMakeLists.txt"); } -CMakeProjectNode::CMakeProjectNode(const Utils::FileName &directory) : +CMakeProjectNode::CMakeProjectNode(const Utils::FilePath &directory) : ProjectExplorer::ProjectNode(directory) { setPriority(Node::DefaultProjectPriority + 1000); @@ -157,11 +155,6 @@ CMakeProjectNode::CMakeProjectNode(const Utils::FileName &directory) : setListInProject(false); } -bool CMakeProjectNode::showInSimpleTree() const -{ - return true; -} - QString CMakeProjectNode::tooltip() const { return QString(); @@ -173,22 +166,19 @@ bool CMakeProjectNode::addFiles(const QStringList &filePaths, QStringList *) return true; // Return always true as autoadd is not supported! } -CMakeTargetNode::CMakeTargetNode(const Utils::FileName &directory, const QString &target) : - ProjectExplorer::ProjectNode(directory, generateId(directory, target)) +CMakeTargetNode::CMakeTargetNode(const Utils::FilePath &directory, const QString &target) : + ProjectExplorer::ProjectNode(directory) { + m_target = target; setPriority(Node::DefaultProjectPriority + 900); setIcon(QIcon(":/projectexplorer/images/build.png")); // TODO: Use proper icon! setListInProject(false); + setIsProduct(); } -QByteArray CMakeTargetNode::generateId(const Utils::FileName &directory, const QString &target) +QString CMakeTargetNode::generateId(const Utils::FilePath &directory, const QString &target) { - return directory.toString().toUtf8() + "///::///" + target.toUtf8(); -} - -bool CMakeTargetNode::showInSimpleTree() const -{ - return true; + return directory.toString() + "///::///" + target; } QString CMakeTargetNode::tooltip() const @@ -198,7 +188,63 @@ QString CMakeTargetNode::tooltip() const QString CMakeTargetNode::buildKey() const { - return QString::fromUtf8(id()); + return generateId(filePath(), m_target); +} + +Utils::FilePath CMakeTargetNode::buildDirectory() const +{ + return m_buildDirectory; +} + +void CMakeTargetNode::setBuildDirectory(const Utils::FilePath &directory) +{ + m_buildDirectory = directory; +} + +QVariant CMakeTargetNode::data(Core::Id role) const +{ + auto value = [this](const QByteArray &key) -> QVariant { + for (const CMakeConfigItem &configItem : m_config) { + if (configItem.key == key) + return configItem.value; + } + return {}; + }; + + auto values = [this](const QByteArray &key) -> QVariant { + for (const CMakeConfigItem &configItem : m_config) { + if (configItem.key == key) + return configItem.values; + } + return {}; + }; + + if (role == Android::Constants::AndroidPackageSourceDir) + return value("ANDROID_PACKAGE_SOURCE_DIR"); + + if (role == Android::Constants::AndroidDeploySettingsFile) + return value("ANDROID_DEPLOYMENT_SETTINGS_FILE"); + + if (role == Android::Constants::AndroidExtraLibs) + return value("ANDROID_EXTRA_LIBS"); + + if (role == Android::Constants::AndroidArch) + return value("ANDROID_ABI"); + + if (role == Android::Constants::AndroidSoLibPath) + return values("ANDROID_SO_LIBS_PATHS"); + + if (role == Android::Constants::AndroidTargets) + return values("TARGETS_BUILD_PATH"); + + QTC_CHECK(false); + // Better guess than "not present". + return value(role.toString().toUtf8()); +} + +void CMakeTargetNode::setConfig(const CMakeConfig &config) +{ + m_config = config; } bool CMakeTargetNode::supportsAction(ProjectExplorer::ProjectAction action, @@ -213,20 +259,19 @@ bool CMakeTargetNode::addFiles(const QStringList &filePaths, QStringList *) return true; // Return always true as autoadd is not supported! } -Utils::optional<Utils::FileName> CMakeTargetNode::visibleAfterAddFileAction() const +Utils::optional<Utils::FilePath> CMakeTargetNode::visibleAfterAddFileAction() const { - Utils::FileName projFile{filePath()}; - return projFile.appendPath("CMakeLists.txt"); + return filePath().pathAppended("CMakeLists.txt"); } -void CMakeTargetNode::setTargetInformation(const QList<Utils::FileName> &artifacts, +void CMakeTargetNode::setTargetInformation(const QList<Utils::FilePath> &artifacts, const QString &type) { m_tooltip = QCoreApplication::translate("CMakeTargetNode", "Target type: ") + type + "<br>"; if (artifacts.isEmpty()) { m_tooltip += QCoreApplication::translate("CMakeTargetNode", "No build artifacts"); } else { - const QStringList tmp = Utils::transform(artifacts, &Utils::FileName::toUserOutput); + const QStringList tmp = Utils::transform(artifacts, &Utils::FilePath::toUserOutput); m_tooltip += QCoreApplication::translate("CMakeTargetNode", "Build artifacts:") + "<br>" + tmp.join("<br>"); } diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h index 0c8174c10e..5a61737925 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h @@ -25,6 +25,8 @@ #pragma once +#include "cmakeconfigitem.h" + #include <projectexplorer/projectnodes.h> namespace CMakeProjectManager { @@ -33,29 +35,24 @@ namespace Internal { class CMakeInputsNode : public ProjectExplorer::ProjectNode { public: - CMakeInputsNode(const Utils::FileName &cmakeLists); - - static QByteArray generateId(const Utils::FileName &inputFile); - - bool showInSimpleTree() const final; + CMakeInputsNode(const Utils::FilePath &cmakeLists); }; class CMakeListsNode : public ProjectExplorer::ProjectNode { public: - CMakeListsNode(const Utils::FileName &cmakeListPath); + CMakeListsNode(const Utils::FilePath &cmakeListPath); bool showInSimpleTree() const final; bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override; - Utils::optional<Utils::FileName> visibleAfterAddFileAction() const override; + Utils::optional<Utils::FilePath> visibleAfterAddFileAction() const override; }; class CMakeProjectNode : public ProjectExplorer::ProjectNode { public: - CMakeProjectNode(const Utils::FileName &directory); + CMakeProjectNode(const Utils::FilePath &directory); - bool showInSimpleTree() const final; QString tooltip() const final; bool addFiles(const QStringList &filePaths, QStringList *notAdded) override; @@ -64,22 +61,28 @@ public: class CMakeTargetNode : public ProjectExplorer::ProjectNode { public: - CMakeTargetNode(const Utils::FileName &directory, const QString &target); + CMakeTargetNode(const Utils::FilePath &directory, const QString &target); - static QByteArray generateId(const Utils::FileName &directory, const QString &target); + static QString generateId(const Utils::FilePath &directory, const QString &target); - void setTargetInformation(const QList<Utils::FileName> &artifacts, const QString &type); + void setTargetInformation(const QList<Utils::FilePath> &artifacts, const QString &type); - bool showInSimpleTree() const final; QString tooltip() const final; QString buildKey() const final; + Utils::FilePath buildDirectory() const; + void setBuildDirectory(const Utils::FilePath &directory); bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override; bool addFiles(const QStringList &filePaths, QStringList *notAdded) override; - Utils::optional<Utils::FileName> visibleAfterAddFileAction() const override; + Utils::optional<Utils::FilePath> visibleAfterAddFileAction() const override; + + QVariant data(Core::Id role) const override; + void setConfig(const CMakeConfig &config); private: QString m_tooltip; + Utils::FilePath m_buildDirectory; + CMakeConfig m_config; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp index ebd5d44d42..53825f4d7c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp @@ -43,9 +43,12 @@ #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/fileiconprovider.h> #include <coreplugin/icore.h> + #include <projectexplorer/kitmanager.h> #include <projectexplorer/projectmanager.h> #include <projectexplorer/projecttree.h> +#include <projectexplorer/runcontrol.h> + #include <texteditor/snippets/snippetprovider.h> #include <utils/parameteraction.h> @@ -59,6 +62,8 @@ namespace Internal { class CMakeProjectPluginPrivate { public: + CMakeToolManager cmakeToolManager; // have that before the first CMakeKitAspect + Utils::ParameterAction *m_buildTargetContextAction = nullptr; QMetaObject::Connection m_actionConnect; @@ -67,9 +72,14 @@ public: CMakeManager manager; CMakeBuildStepFactory buildStepFactory; CMakeRunConfigurationFactory runConfigFactory; + SimpleRunWorkerFactory<SimpleTargetRunner, CMakeRunConfiguration> runWorkerFactory; CMakeBuildConfigurationFactory buildConfigFactory; CMakeEditorFactory editorFactor; CMakeLocatorFilter locatorFiler; + + CMakeKitAspect cmakeKitAspect; + CMakeGeneratorKitAspect cmakeGeneratorKitAspect; + CMakeConfigurationKitAspect cmakeConfigurationKitAspect; }; const std::unique_ptr<CMakeSpecificSettings> @@ -104,12 +114,6 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString * tr("CMake", "SnippetProvider")); ProjectManager::registerProjectType<CMakeProject>(Constants::CMAKEPROJECTMIMETYPE); - new CMakeToolManager(this); - - KitManager::registerKitInformation<CMakeKitInformation>(); - KitManager::registerKitInformation<CMakeGeneratorKitInformation>(); - KitManager::registerKitInformation<CMakeConfigurationKitInformation>(); - //menus ActionContainer *msubproject = ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT); @@ -143,7 +147,7 @@ void CMakeProjectPlugin::extensionsInitialized() void CMakeProjectPlugin::updateContextActions() { Project *project = ProjectTree::currentProject(); - const Node *node = ProjectTree::findCurrentNode(); + const Node *node = ProjectTree::currentNode(); auto targetNode = dynamic_cast<const CMakeTargetNode *>(node); // as targetNode can be deleted while the menu is open, we keep only the const QString targetDisplayName = targetNode ? targetNode->displayName() : QString(); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h index 4652078d74..c8a50219f4 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h @@ -26,8 +26,9 @@ #pragma once #include "cmakespecificsettingspage.h" + #include <extensionsystem/iplugin.h> -#include <memory> + namespace CMakeProjectManager { namespace Internal { diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index 3872fe90f4..30514b70a5 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -33,9 +33,11 @@ #include <projectexplorer/localenvironmentaspect.h> #include <projectexplorer/project.h> #include <projectexplorer/runconfigurationaspects.h> +#include <projectexplorer/runcontrol.h> #include <projectexplorer/target.h> using namespace ProjectExplorer; +using namespace Utils; namespace CMakeProjectManager { namespace Internal { @@ -43,27 +45,28 @@ namespace Internal { CMakeRunConfiguration::CMakeRunConfiguration(Target *target, Core::Id id) : RunConfiguration(target, id) { - // Workaround for QTCREATORBUG-19354: - auto cmakeRunEnvironmentModifier = [target](Utils::Environment &env) { - if (!Utils::HostOsInfo::isWindowsHost()) - return; + auto envAspect = addAspect<LocalEnvironmentAspect>(target); - const Kit *k = target->kit(); - const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(k); - if (qt) - env.prependOrSetPath(qt->qmakeProperty("QT_INSTALL_BINS")); - }; - auto envAspect = addAspect<LocalEnvironmentAspect>(target, cmakeRunEnvironmentModifier); + // Workaround for QTCREATORBUG-19354: + if (HostOsInfo::isWindowsHost()) { + envAspect->addModifier([target](Environment &env) { + const Kit *k = target->kit(); + if (const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(k)) { + const QString installBinPath = qt->qmakeProperty("QT_INSTALL_BINS"); + env.prependOrSetPath(installBinPath); + } + }); + } addAspect<ExecutableAspect>(); addAspect<ArgumentsAspect>(); - addAspect<WorkingDirectoryAspect>(envAspect); + addAspect<WorkingDirectoryAspect>(); addAspect<TerminalAspect>(); connect(target->project(), &Project::parsingFinished, this, &CMakeRunConfiguration::updateTargetInformation); - if (QtSupport::QtKitInformation::qtVersion(target->kit())) + if (QtSupport::QtKitAspect::qtVersion(target->kit())) setOutputFormatter<QtSupport::QtOutputFormatter>(); } @@ -75,7 +78,7 @@ void CMakeRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo bool CMakeRunConfiguration::isBuildTargetValid() const { - return Utils::anyOf(target()->applicationTargets().list, [this](const BuildTargetInfo &bti) { + return Utils::anyOf(target()->applicationTargets(), [this](const BuildTargetInfo &bti) { return bti.buildKey == buildKey(); }); } @@ -97,14 +100,13 @@ QString CMakeRunConfiguration::disabledReason() const void CMakeRunConfiguration::updateTargetInformation() { - BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(buildKey()); + BuildTargetInfo bti = buildTargetInfo(); aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath); aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory); aspect<LocalEnvironmentAspect>()->buildEnvironmentHasChanged(); auto terminalAspect = aspect<TerminalAspect>(); - if (!terminalAspect->isUserSet()) - terminalAspect->setUseTerminal(bti.usesTerminal); + terminalAspect->setUseTerminalHint(bti.usesTerminal); } // Factory @@ -113,8 +115,6 @@ CMakeRunConfigurationFactory::CMakeRunConfigurationFactory() registerRunConfiguration<CMakeRunConfiguration>("CMakeProjectManager.CMakeRunConfiguration."); addSupportedProjectType(CMakeProjectManager::Constants::CMAKEPROJECT_ID); addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE); - - addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE); } } // Internal diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp index 0f125ba6e4..991eb274c4 100644 --- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp +++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp @@ -67,12 +67,12 @@ public: CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const; CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const; - QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected); + QModelIndex addCMakeTool(const QString &name, const FilePath &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected); void addCMakeTool(const CMakeTool *item, bool changed); TreeItem *autoGroupItem() const; TreeItem *manualGroupItem() const; void reevaluateChangedFlag(CMakeToolTreeItem *item) const; - void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable, + void updateCMakeTool(const Core::Id &id, const QString &displayName, const FilePath &executable, bool autoRun, bool autoCreate); void removeCMakeTool(const Core::Id &id); void apply(); @@ -101,7 +101,7 @@ public: m_changed(changed) {} - CMakeToolTreeItem(const QString &name, const Utils::FileName &executable, + CMakeToolTreeItem(const QString &name, const Utils::FilePath &executable, bool autoRun, bool autoCreate, bool autodetected) : m_id(Core::Id::fromString(QUuid::createUuid().toString())), m_name(name), @@ -143,7 +143,7 @@ public: Core::Id m_id; QString m_name; - FileName m_executable; + FilePath m_executable; bool m_isAutoRun = true; bool m_autoCreateBuildDirectory = false; bool m_autodetected = false; @@ -168,7 +168,7 @@ CMakeToolItemModel::CMakeToolItemModel() } -QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable, +QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FilePath &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected) { @@ -223,7 +223,7 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const } void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName, - const FileName &executable, bool autoRun, + const FilePath &executable, bool autoRun, bool autoCreate) { CMakeToolTreeItem *treeItem = cmakeToolItem(id); @@ -519,7 +519,7 @@ void CMakeToolConfigWidget::cloneCMakeTool() void CMakeToolConfigWidget::addCMakeTool() { QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")), - FileName(), true, false, false); + FilePath(), true, false, false); m_cmakeToolsView->setCurrentIndex(newItem); } diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index 795f2dc7cb..ac0ac0999e 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -102,7 +102,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : if (!fromSdk) m_isAutoDetected = map.value(CMAKE_INFORMATION_AUTODETECTED, false).toBool(); - setCMakeExecutable(Utils::FileName::fromString(map.value(CMAKE_INFORMATION_COMMAND).toString())); + setCMakeExecutable(Utils::FilePath::fromString(map.value(CMAKE_INFORMATION_COMMAND).toString())); } CMakeTool::~CMakeTool() = default; @@ -112,7 +112,7 @@ Core::Id CMakeTool::createId() return Core::Id::fromString(QUuid::createUuid().toString()); } -void CMakeTool::setCMakeExecutable(const Utils::FileName &executable) +void CMakeTool::setCMakeExecutable(const Utils::FilePath &executable) { if (m_executable == executable) return; @@ -187,11 +187,10 @@ QVariantMap CMakeTool::toMap() const return data; } -Utils::FileName CMakeTool::cmakeExecutable() const +Utils::FilePath CMakeTool::cmakeExecutable() const { if (Utils::HostOsInfo::isMacHost() && m_executable.endsWith(".app")) { - Utils::FileName toTest = m_executable; - toTest = toTest.appendPath("Contents/bin/cmake"); + const Utils::FilePath toTest = m_executable.pathAppended("Contents/bin/cmake"); if (toTest.exists()) return toTest; } @@ -280,7 +279,7 @@ CMakeTool::PathMapper CMakeTool::pathMapper() const { if (m_pathMapper) return m_pathMapper; - return [](const Utils::FileName &fn) { return fn; }; + return [](const Utils::FilePath &fn) { return fn; }; } void CMakeTool::readInformation(CMakeTool::QueryType type) const diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index 052722d89f..85feaf41e5 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -76,7 +76,7 @@ public: bool matches(const QString &n, const QString &ex) const; }; - using PathMapper = std::function<Utils::FileName (const Utils::FileName &)>; + using PathMapper = std::function<Utils::FilePath (const Utils::FilePath &)>; explicit CMakeTool(Detection d, const Core::Id &id); explicit CMakeTool(const QVariantMap &map, bool fromSdk); @@ -89,11 +89,11 @@ public: Core::Id id() const { return m_id; } QVariantMap toMap () const; - void setCMakeExecutable(const Utils::FileName &executable); + void setCMakeExecutable(const Utils::FilePath &executable); void setAutorun(bool autoRun); void setAutoCreateBuildDirectory(bool autoBuildDir); - Utils::FileName cmakeExecutable() const; + Utils::FilePath cmakeExecutable() const; bool isAutoRun() const; bool autoCreateBuildDirectory() const; QList<Generator> supportedGenerators() const; @@ -129,7 +129,7 @@ private: Core::Id m_id; QString m_displayName; - Utils::FileName m_executable; + Utils::FilePath m_executable; bool m_isAutoRun = true; bool m_isAutoDetected = false; diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp index a90fe59c81..b9b70c5352 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp @@ -57,7 +57,7 @@ static CMakeToolManagerPrivate *d = nullptr; CMakeToolManager *CMakeToolManager::m_instance = nullptr; -CMakeToolManager::CMakeToolManager(QObject *parent) : QObject(parent) +CMakeToolManager::CMakeToolManager() { QTC_ASSERT(!m_instance, return); m_instance = this; @@ -86,7 +86,7 @@ QList<CMakeTool *> CMakeToolManager::cmakeTools() return Utils::toRawPointer<QList>(d->m_cmakeTools); } -Id CMakeToolManager::registerOrFindCMakeTool(const FileName &command) +Id CMakeToolManager::registerOrFindCMakeTool(const FilePath &command) { if (CMakeTool *cmake = findByCommand(command)) return cmake->id(); @@ -149,7 +149,7 @@ void CMakeToolManager::setDefaultCMakeTool(const Id &id) ensureDefaultCMakeToolIsValid(); } -CMakeTool *CMakeToolManager::findByCommand(const FileName &command) +CMakeTool *CMakeToolManager::findByCommand(const FilePath &command) { return Utils::findOrDefault(d->m_cmakeTools, Utils::equal(&CMakeTool::cmakeExecutable, command)); } diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h index bd7f232553..49308e616b 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h +++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h @@ -40,20 +40,20 @@ class CMAKE_EXPORT CMakeToolManager : public QObject { Q_OBJECT public: - CMakeToolManager(QObject *parent); + CMakeToolManager(); ~CMakeToolManager() override; static CMakeToolManager *instance(); static QList<CMakeTool *> cmakeTools(); - static Core::Id registerOrFindCMakeTool(const Utils::FileName &command); + static Core::Id registerOrFindCMakeTool(const Utils::FilePath &command); static bool registerCMakeTool(std::unique_ptr<CMakeTool> &&tool); static void deregisterCMakeTool(const Core::Id &id); static CMakeTool *defaultCMakeTool(); static void setDefaultCMakeTool(const Core::Id &id); - static CMakeTool *findByCommand(const Utils::FileName &command); + static CMakeTool *findByCommand(const Utils::FilePath &command); static CMakeTool *findById(const Core::Id &id); static void notifyAboutUpdate(CMakeTool *); diff --git a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp index 2f2d40b91d..a34f463318 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp @@ -72,30 +72,30 @@ static std::vector<std::unique_ptr<CMakeTool>> autoDetectCMakeTools() { Utils::Environment env = Environment::systemEnvironment(); - Utils::FileNameList path = env.path(); + Utils::FilePathList path = env.path(); path = Utils::filteredUnique(path); if (HostOsInfo::isWindowsHost()) { const QString progFiles = QLatin1String(qgetenv("ProgramFiles")); - path.append(Utils::FileName::fromString(progFiles + "/CMake")); - path.append(Utils::FileName::fromString(progFiles + "/CMake/bin")); + path.append(Utils::FilePath::fromString(progFiles + "/CMake")); + path.append(Utils::FilePath::fromString(progFiles + "/CMake/bin")); const QString progFilesX86 = QLatin1String(qgetenv("ProgramFiles(x86)")); if (!progFilesX86.isEmpty()) { - path.append(Utils::FileName::fromString(progFilesX86 + "/CMake")); - path.append(Utils::FileName::fromString(progFilesX86 + "/CMake/bin")); + path.append(Utils::FilePath::fromString(progFilesX86 + "/CMake")); + path.append(Utils::FilePath::fromString(progFilesX86 + "/CMake/bin")); } } if (HostOsInfo::isMacHost()) { - path.append(Utils::FileName::fromString("/Applications/CMake.app/Contents/bin")); - path.append(Utils::FileName::fromString("/usr/local/bin")); - path.append(Utils::FileName::fromString("/opt/local/bin")); + path.append(Utils::FilePath::fromString("/Applications/CMake.app/Contents/bin")); + path.append(Utils::FilePath::fromString("/usr/local/bin")); + path.append(Utils::FilePath::fromString("/opt/local/bin")); } const QStringList execs = env.appendExeExtensions(QLatin1String("cmake")); - FileNameList suspects; - foreach (const Utils::FileName &base, path) { + FilePathList suspects; + foreach (const Utils::FilePath &base, path) { if (base.isEmpty()) continue; @@ -103,12 +103,12 @@ static std::vector<std::unique_ptr<CMakeTool>> autoDetectCMakeTools() for (const QString &exec : execs) { fi.setFile(QDir(base.toString()), exec); if (fi.exists() && fi.isFile() && fi.isExecutable()) - suspects << FileName::fromString(fi.absoluteFilePath()); + suspects << FilePath::fromString(fi.absoluteFilePath()); } } std::vector<std::unique_ptr<CMakeTool>> found; - foreach (const FileName &command, suspects) { + foreach (const FilePath &command, suspects) { auto item = std::make_unique<CMakeTool>(CMakeTool::AutoDetection, CMakeTool::createId()); item->setCMakeExecutable(command); item->setDisplayName(CMakeToolManager::tr("System CMake at %1").arg(command.toUserOutput())); @@ -166,7 +166,7 @@ CMakeToolSettingsAccessor::CMakeToolSettingsAccessor() : QCoreApplication::translate("CMakeProjectManager::CMakeToolManager", "CMake"), Core::Constants::IDE_DISPLAY_NAME) { - setBaseFilePath(FileName::fromString(Core::ICore::userResourcePath() + CMAKE_TOOL_FILENAME)); + setBaseFilePath(FilePath::fromString(Core::ICore::userResourcePath() + CMAKE_TOOL_FILENAME)); addVersionUpgrader(std::make_unique<CMakeToolSettingsUpgraderV0>()); } @@ -175,7 +175,7 @@ CMakeToolSettingsAccessor::CMakeTools CMakeToolSettingsAccessor::restoreCMakeToo { CMakeTools result; - const FileName sdkSettingsFile = FileName::fromString(Core::ICore::installerResourcePath() + const FilePath sdkSettingsFile = FilePath::fromString(Core::ICore::installerResourcePath() + CMAKE_TOOL_FILENAME); CMakeTools sdkTools = cmakeTools(restoreSettings(sdkSettingsFile, parent), true); diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp index 90a3c40f24..588855d345 100644 --- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp +++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp @@ -28,7 +28,7 @@ namespace CMakeProjectManager { -ConfigModelItemDelegate::ConfigModelItemDelegate(const Utils::FileName &base, QObject* parent) +ConfigModelItemDelegate::ConfigModelItemDelegate(const Utils::FilePath &base, QObject* parent) : QStyledItemDelegate(parent) , m_base(base) { } @@ -78,7 +78,7 @@ void ConfigModelItemDelegate::setEditorData(QWidget *editor, const QModelIndex & ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index); if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) { auto edit = static_cast<Utils::PathChooser *>(editor); - edit->setFileName(Utils::FileName::fromUserInput(data.value)); + edit->setFileName(Utils::FilePath::fromUserInput(data.value)); return; } else if (!data.values.isEmpty()) { auto edit = static_cast<QComboBox *>(editor); diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h index ce5571b6be..d33fb48c7a 100644 --- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h +++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h @@ -30,7 +30,7 @@ class ConfigModelItemDelegate : public QStyledItemDelegate Q_OBJECT public: - ConfigModelItemDelegate(const Utils::FileName &base, QObject *parent = nullptr); + ConfigModelItemDelegate(const Utils::FilePath &base, QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const final; @@ -40,7 +40,7 @@ public: QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const final; private: - Utils::FileName m_base; + Utils::FilePath m_base; QComboBox m_measurement; }; diff --git a/src/plugins/cmakeprojectmanager/servermode.cpp b/src/plugins/cmakeprojectmanager/servermode.cpp index 8e21749927..bd37c4f6fe 100644 --- a/src/plugins/cmakeprojectmanager/servermode.cpp +++ b/src/plugins/cmakeprojectmanager/servermode.cpp @@ -78,8 +78,8 @@ bool isValid(const QVariant &v) ServerMode::ServerMode(const Environment &env, - const FileName &sourceDirectory, const FileName &buildDirectory, - const FileName &cmakeExecutable, + const FilePath &sourceDirectory, const FilePath &buildDirectory, + const FilePath &cmakeExecutable, const QString &generator, const QString &extraGenerator, const QString &platform, const QString &toolset, bool experimental, int major, int minor, @@ -92,7 +92,7 @@ ServerMode::ServerMode(const Environment &env, m_socketDir("/tmp/cmake-"), #endif m_sourceDirectory(sourceDirectory), m_buildDirectory(buildDirectory), - m_cmakeExecutable(cmakeExecutable), + m_cmakeCommand(cmakeExecutable, {}), m_generator(generator), m_extraGenerator(extraGenerator), m_platform(platform), m_toolset(toolset), m_useExperimental(experimental), m_majorProtocol(major), m_minorProtocol(minor) @@ -114,28 +114,24 @@ ServerMode::ServerMode(const Environment &env, m_socketName = QString::fromLatin1("\\\\.\\pipe\\") + QUuid::createUuid().toString(); #endif - const QStringList args = QStringList({"-E", "server", "--pipe=" + m_socketName}); - connect(m_cmakeProcess.get(), &QtcProcess::started, this, [this]() { m_connectionTimer.start(); }); connect(m_cmakeProcess.get(), - static_cast<void(QtcProcess::*)(int, QProcess::ExitStatus)>(&QtcProcess::finished), + QOverload<int, QProcess::ExitStatus>::of(&QtcProcess::finished), this, &ServerMode::handleCMakeFinished); - QString argumentString; - QtcProcess::addArgs(&argumentString, args); + m_cmakeCommand.addArgs({"-E", "server", "--pipe=" + m_socketName}); if (m_useExperimental) - QtcProcess::addArg(&argumentString, "--experimental"); + m_cmakeCommand.addArg("--experimental"); qCInfo(cmakeServerMode) - << "Preparing cmake:" << cmakeExecutable.toString() << argumentString + << "Preparing cmake:" << m_cmakeCommand.toUserOutput() << "in" << m_buildDirectory.toString(); - m_cmakeProcess->setCommand(cmakeExecutable.toString(), argumentString); + m_cmakeProcess->setCommand(m_cmakeCommand); // Delay start: - QTimer::singleShot(0, this, [argumentString, this] { - emit message(tr("Running \"%1 %2\" in %3.") - .arg(m_cmakeExecutable.toUserOutput()) - .arg(argumentString) + QTimer::singleShot(0, this, [this] { + emit message(tr("Running \"%1\" in %2.") + .arg(m_cmakeCommand.toUserOutput()) .arg(m_buildDirectory.toUserOutput())); m_cmakeProcess->start(); @@ -199,7 +195,7 @@ void ServerMode::connectToServer() m_cmakeProcess->disconnect(); qCInfo(cmakeServerMode) << "Timeout waiting for pipe" << m_socketName; reportError(tr("Running \"%1\" failed: Timeout waiting for pipe \"%2\".") - .arg(m_cmakeExecutable.toUserOutput()) + .arg(m_cmakeCommand.toUserOutput()) .arg(m_socketName)); Core::Reaper::reap(m_cmakeProcess.release()); @@ -211,7 +207,7 @@ void ServerMode::connectToServer() auto socket = new QLocalSocket(m_cmakeProcess.get()); connect(socket, &QLocalSocket::readyRead, this, &ServerMode::handleRawCMakeServerData); - connect(socket, static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), + connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), this, [this, socket]() { reportError(socket->errorString()); m_cmakeSocket = nullptr; @@ -236,14 +232,14 @@ void ServerMode::handleCMakeFinished(int code, QProcess::ExitStatus status) qCInfo(cmakeServerMode) << "CMake has finished" << code << status; QString msg; if (status != QProcess::NormalExit) - msg = tr("CMake process \"%1\" crashed.").arg(m_cmakeExecutable.toUserOutput()); + msg = tr("CMake process \"%1\" crashed.").arg(m_cmakeCommand.toUserOutput()); else if (code != 0) - msg = tr("CMake process \"%1\" quit with exit code %2.").arg(m_cmakeExecutable.toUserOutput()).arg(code); + msg = tr("CMake process \"%1\" quit with exit code %2.").arg(m_cmakeCommand.toUserOutput()).arg(code); if (!msg.isEmpty()) { reportError(msg); } else { - emit message(tr("CMake process \"%1\" quit normally.").arg(m_cmakeExecutable.toUserOutput())); + emit message(tr("CMake process \"%1\" quit normally.").arg(m_cmakeCommand.toUserOutput())); } if (m_cmakeSocket) { diff --git a/src/plugins/cmakeprojectmanager/servermode.h b/src/plugins/cmakeprojectmanager/servermode.h index e7b645623a..2a4ccbf232 100644 --- a/src/plugins/cmakeprojectmanager/servermode.h +++ b/src/plugins/cmakeprojectmanager/servermode.h @@ -47,8 +47,8 @@ class ServerMode : public QObject public: ServerMode(const Utils::Environment &env, - const Utils::FileName &sourceDirectory, const Utils::FileName &buildDirectory, - const Utils::FileName &cmakeExecutable, + const Utils::FilePath &sourceDirectory, const Utils::FilePath &buildDirectory, + const Utils::FilePath &cmakeExecutable, const QString &generator, const QString &extraGenerator, const QString &platform, const QString &toolset, bool experimental, int major, int minor = -1, @@ -92,9 +92,9 @@ private: QLocalSocket *m_cmakeSocket = nullptr; QTimer m_connectionTimer; - Utils::FileName m_sourceDirectory; - Utils::FileName m_buildDirectory; - Utils::FileName m_cmakeExecutable; + Utils::FilePath m_sourceDirectory; + Utils::FilePath m_buildDirectory; + Utils::CommandLine m_cmakeCommand; QByteArray m_buffer; diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index 9b293d0ff8..a0a70a8d85 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -85,7 +85,7 @@ ServerModeReader::ServerModeReader() Task editable(t); if (!editable.file.isEmpty()) { QDir srcDir(m_parameters.sourceDirectory.toString()); - editable.file = FileName::fromString(srcDir.absoluteFilePath(editable.file.toString())); + editable.file = FilePath::fromString(srcDir.absoluteFilePath(editable.file.toString())); } TaskHub::addTask(editable); }); @@ -228,7 +228,7 @@ QList<CMakeBuildTarget> ServerModeReader::takeBuildTargets() const QList<CMakeBuildTarget> result = transform(m_targets, [](const Target *t) -> CMakeBuildTarget { CMakeBuildTarget ct; ct.title = t->name; - ct.executable = t->artifacts.isEmpty() ? FileName() : t->artifacts.at(0); + ct.executable = t->artifacts.isEmpty() ? FilePath() : t->artifacts.at(0); TargetType type = UtilityType; if (t->type == "EXECUTABLE") type = ExecutableType; @@ -245,7 +245,7 @@ QList<CMakeBuildTarget> ServerModeReader::takeBuildTargets() if (t->artifacts.isEmpty()) { ct.workingDirectory = t->buildDirectory; } else { - ct.workingDirectory = Utils::FileName::fromString(t->artifacts.at(0).toFileInfo().absolutePath()); + ct.workingDirectory = Utils::FilePath::fromString(t->artifacts.at(0).toFileInfo().absolutePath()); } ct.sourceDirectory = t->sourceDirectory; return ct; @@ -261,7 +261,7 @@ CMakeConfig ServerModeReader::takeParsedConfiguration() return config; } -static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, int priority, +static void addCMakeVFolder(FolderNode *base, const Utils::FilePath &basePath, int priority, const QString &displayName, std::vector<std::unique_ptr<FileNode>> &&files) { @@ -269,7 +269,8 @@ static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, i return; FolderNode *folder = base; if (!displayName.isEmpty()) { - auto newFolder = std::make_unique<VirtualFolderNode>(basePath, priority); + auto newFolder = std::make_unique<VirtualFolderNode>(basePath); + newFolder->setPriority(priority); newFolder->setDisplayName(displayName); folder = newFolder.get(); base->addNode(std::move(newFolder)); @@ -280,7 +281,7 @@ static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, i } static std::vector<std::unique_ptr<FileNode>> && -removeKnownNodes(const QSet<Utils::FileName> &knownFiles, +removeKnownNodes(const QSet<Utils::FilePath> &knownFiles, std::vector<std::unique_ptr<FileNode>> &&files) { Utils::erase(files, [&knownFiles](const std::unique_ptr<FileNode> &n) { @@ -290,15 +291,15 @@ removeKnownNodes(const QSet<Utils::FileName> &knownFiles, } static void addCMakeInputs(FolderNode *root, - const Utils::FileName &sourceDir, - const Utils::FileName &buildDir, + const Utils::FilePath &sourceDir, + const Utils::FilePath &buildDir, std::vector<std::unique_ptr<FileNode>> &&sourceInputs, std::vector<std::unique_ptr<FileNode>> &&buildInputs, std::vector<std::unique_ptr<FileNode>> &&rootInputs) { std::unique_ptr<ProjectNode> cmakeVFolder = std::make_unique<CMakeInputsNode>(root->filePath()); - QSet<Utils::FileName> knownFiles; + QSet<Utils::FilePath> knownFiles; root->forEachGenericNode([&knownFiles](const Node *n) { if (n->listInProject()) knownFiles.insert(n->filePath()); @@ -308,7 +309,7 @@ static void addCMakeInputs(FolderNode *root, addCMakeVFolder(cmakeVFolder.get(), buildDir, 100, QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Build Directory>"), removeKnownNodes(knownFiles, std::move(buildInputs))); - addCMakeVFolder(cmakeVFolder.get(), Utils::FileName(), 10, + addCMakeVFolder(cmakeVFolder.get(), Utils::FilePath(), 10, QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Other Locations>"), removeKnownNodes(knownFiles, std::move(rootInputs))); @@ -325,7 +326,7 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root, std::vector<std::unique_ptr<FileNode>> cmakeLists; for (std::unique_ptr<FileNode> &fn : m_cmakeInputsFileNodes) { - const FileName path = fn->filePath(); + const FilePath path = fn->filePath(); if (path.fileName().compare("CMakeLists.txt", HostOsInfo::fileNameCaseSensitivity()) == 0) cmakeLists.emplace_back(std::move(fn)); else if (path.isChildOf(m_parameters.workDirectory)) @@ -343,7 +344,7 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root, if (topLevel) root->setDisplayName(topLevel->name); - QHash<Utils::FileName, ProjectNode *> cmakeListsNodes + QHash<Utils::FilePath, ProjectNode *> cmakeListsNodes = addCMakeLists(root, std::move(cmakeLists)); QList<FileNode *> knownHeaders; addProjects(cmakeListsNodes, m_projects, knownHeaders); @@ -368,7 +369,7 @@ CppTools::RawProjectParts ServerModeReader::createRawProjectParts() const if (fg->macros.isEmpty() && fg->includePaths.isEmpty() && !fg->isGenerated - && Utils::allOf(fg->sources, [](const Utils::FileName &source) { + && Utils::allOf(fg->sources, [](const Utils::FilePath &source) { return Node::fileTypeForFileName(source) == FileType::Header; })) { qWarning() << "Not reporting all-header file group of target" << fg->target << "to code model."; @@ -381,7 +382,7 @@ CppTools::RawProjectParts ServerModeReader::createRawProjectParts() const CppTools::RawProjectPart rpp; rpp.setProjectFileLocation(fg->target->sourceDirectory.toString() + "/CMakeLists.txt"); - rpp.setBuildSystemTarget(fg->target->name + QChar('\n') + fg->target->sourceDirectory.toString() + QChar('/')); + rpp.setBuildSystemTarget(CMakeTargetNode::generateId(fg->target->sourceDirectory, fg->target->name)); rpp.setDisplayName(fg->target->name + QString::number(counter)); rpp.setMacros(fg->macros); rpp.setIncludePaths(includes); @@ -394,7 +395,7 @@ CppTools::RawProjectParts ServerModeReader::createRawProjectParts() const cxxProjectFlags.commandLineFlags = flags; rpp.setFlagsForCxx(cxxProjectFlags); - rpp.setFiles(transform(fg->sources, &FileName::toString)); + rpp.setFiles(transform(fg->sources, &FilePath::toString)); const bool isExecutable = fg->target->type == "EXECUTABLE"; rpp.setBuildTargetType(isExecutable ? CppTools::ProjectPart::Executable @@ -456,7 +457,7 @@ void ServerModeReader::handleReply(const QVariantMap &data, const QString &inRep void ServerModeReader::handleError(const QString &message) { TaskHub::addTask(Task::Error, message, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM, - Utils::FileName(), -1); + Utils::FilePath(), -1); if (!m_delayedErrorMessage.isEmpty()) { reportError(); return; @@ -534,7 +535,7 @@ ServerModeReader::Project *ServerModeReader::extractProjectData(const QVariantMa { auto project = new Project; project->name = data.value(NAME_KEY).toString(); - project->sourceDirectory = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString()); + project->sourceDirectory = FilePath::fromString(data.value(SOURCE_DIRECTORY_KEY).toString()); const QVariantList targets = data.value("targets").toList(); for (const QVariant &t : targets) { @@ -561,8 +562,8 @@ ServerModeReader::Target *ServerModeReader::extractTargetData(const QVariantMap auto target = new Target; target->project = p; target->name = targetName; - target->sourceDirectory = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString()); - target->buildDirectory = FileName::fromString(data.value("buildDirectory").toString()); + target->sourceDirectory = FilePath::fromString(data.value(SOURCE_DIRECTORY_KEY).toString()); + target->buildDirectory = FilePath::fromString(data.value("buildDirectory").toString()); target->crossReferences = extractCrossReferences(data.value("crossReferences").toMap()); @@ -570,7 +571,7 @@ ServerModeReader::Target *ServerModeReader::extractTargetData(const QVariantMap target->type = data.value("type").toString(); const QStringList artifacts = data.value("artifacts").toStringList(); - target->artifacts = transform(artifacts, [&srcDir](const QString &a) { return FileName::fromString(srcDir.absoluteFilePath(a)); }); + target->artifacts = transform(artifacts, [&srcDir](const QString &a) { return FilePath::fromString(srcDir.absoluteFilePath(a)); }); const QVariantList fileGroups = data.value("fileGroups").toList(); for (const QVariant &fg : fileGroups) { @@ -598,14 +599,14 @@ ServerModeReader::FileGroup *ServerModeReader::extractFileGroupData(const QVaria [](const QVariant &i) -> IncludePath* { const QVariantMap iData = i.toMap(); auto result = new IncludePath; - result->path = FileName::fromString(iData.value("path").toString()); + result->path = FilePath::fromString(iData.value("path").toString()); result->isSystem = iData.value("isSystem", false).toBool(); return result; }); fileGroup->isGenerated = data.value("isGenerated", false).toBool(); fileGroup->sources = transform(data.value(SOURCES_KEY).toStringList(), [&srcDir](const QString &s) { - return FileName::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s))); + return FilePath::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s))); }); m_fileGroups.append(fileGroup); @@ -680,7 +681,7 @@ QList<ServerModeReader::BacktraceItem *> ServerModeReader::extractBacktrace(cons void ServerModeReader::extractCMakeInputsData(const QVariantMap &data) { - const FileName src = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString()); + const FilePath src = FilePath::fromString(data.value(SOURCE_DIRECTORY_KEY).toString()); QTC_ASSERT(src == m_parameters.sourceDirectory, return); QDir srcDir(src.toString()); @@ -691,18 +692,28 @@ void ServerModeReader::extractCMakeInputsData(const QVariantMap &data) const QVariantMap §ion = bf.toMap(); const QStringList sources = section.value(SOURCES_KEY).toStringList(); - const bool isTemporary = section.value("isTemporary").toBool(); - const bool isCMake = section.value("isCMake").toBool(); + const bool isTemporary = section.value("isTemporary").toBool(); // generated file + const bool isCMake = section.value("isCMake").toBool(); // part of the cmake installation for (const QString &s : sources) { - const FileName sfn = FileName::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s))); + const FilePath sfn = FilePath::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s))); const int oldCount = m_cmakeFiles.count(); m_cmakeFiles.insert(sfn); - if (oldCount < m_cmakeFiles.count() && (!isCMake || sfn.toString().endsWith("/CMakeLists.txt"))) { - // Always include CMakeLists.txt files, even when cmake things these are part of its - // stuff. This unbreaks cmake binaries running from their own build directory. - m_cmakeInputsFileNodes.emplace_back( - std::make_unique<FileNode>(sfn, FileType::Project, isTemporary)); + if (oldCount < m_cmakeFiles.count()) { + const bool isCMakeListsFile = sfn.toString().endsWith("/CMakeLists.txt"); + + if (isCMake && !isCMakeListsFile) + // Skip files that cmake considers to be part of the installation -- but include + // CMakeLists.txt files. This unbreaks cmake binaries running from their own + // build directory. + continue; + + auto node = std::make_unique<FileNode>(sfn, FileType::Project); + node->setIsGenerated(isTemporary && !isCMakeListsFile); // CMakeLists.txt are never + // generated, independent + // what cmake thinks:-) + + m_cmakeInputsFileNodes.emplace_back(std::move(node)); } } } @@ -770,24 +781,24 @@ void ServerModeReader::fixTarget(ServerModeReader::Target *target) const } } -QHash<Utils::FileName, ProjectNode *> +QHash<Utils::FilePath, ProjectNode *> ServerModeReader::addCMakeLists(CMakeProjectNode *root, std::vector<std::unique_ptr<FileNode>> &&cmakeLists) { - QHash<Utils::FileName, ProjectNode *> cmakeListsNodes; + QHash<Utils::FilePath, ProjectNode *> cmakeListsNodes; cmakeListsNodes.insert(root->filePath(), root); - const QSet<Utils::FileName> cmakeDirs + const QSet<Utils::FilePath> cmakeDirs = Utils::transform<QSet>(cmakeLists, [](const std::unique_ptr<FileNode> &n) { return n->filePath().parentDir(); }); - root->addNestedNodes(std::move(cmakeLists), Utils::FileName(), - [&cmakeDirs, &cmakeListsNodes](const Utils::FileName &fp) + root->addNestedNodes(std::move(cmakeLists), Utils::FilePath(), + [&cmakeDirs, &cmakeListsNodes](const Utils::FilePath &fp) -> std::unique_ptr<ProjectExplorer::FolderNode> { if (cmakeDirs.contains(fp)) { auto fn = std::make_unique<CMakeListsNode>(fp); cmakeListsNodes.insert(fp, fn.get()); - return std::move(fn); + return fn; } return std::make_unique<FolderNode>(fp); @@ -796,14 +807,13 @@ ServerModeReader::addCMakeLists(CMakeProjectNode *root, return cmakeListsNodes; } -static void createProjectNode(const QHash<Utils::FileName, ProjectNode *> &cmakeListsNodes, - const Utils::FileName &dir, const QString &displayName) +static void createProjectNode(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNodes, + const Utils::FilePath &dir, const QString &displayName) { ProjectNode *cmln = cmakeListsNodes.value(dir); QTC_ASSERT(cmln, qDebug() << dir.toUserOutput(); return); - Utils::FileName projectName = dir; - projectName.appendPath(".project::" + displayName); + const Utils::FilePath projectName = dir.pathAppended(".project::" + displayName); ProjectNode *pn = cmln->projectNode(projectName); if (!pn) { @@ -814,7 +824,7 @@ static void createProjectNode(const QHash<Utils::FileName, ProjectNode *> &cmake pn->setDisplayName(displayName); } -void ServerModeReader::addProjects(const QHash<Utils::FileName, ProjectNode *> &cmakeListsNodes, +void ServerModeReader::addProjects(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNodes, const QList<Project *> &projects, QList<FileNode *> &knownHeaderNodes) { @@ -824,16 +834,16 @@ void ServerModeReader::addProjects(const QHash<Utils::FileName, ProjectNode *> & } } -static CMakeTargetNode *createTargetNode(const QHash<Utils::FileName, ProjectNode *> &cmakeListsNodes, - const Utils::FileName &dir, const QString &displayName) +static CMakeTargetNode *createTargetNode(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNodes, + const Utils::FilePath &dir, const QString &displayName) { ProjectNode *cmln = cmakeListsNodes.value(dir); QTC_ASSERT(cmln, return nullptr); - QByteArray targetId = CMakeTargetNode::generateId(dir, displayName); + QString targetId = CMakeTargetNode::generateId(dir, displayName); CMakeTargetNode *tn = static_cast<CMakeTargetNode *>(cmln->findNode([&targetId](const Node *n) { - return n->id() == targetId; + return n->buildKey() == targetId; })); if (!tn) { auto newNode = std::make_unique<CMakeTargetNode>(dir, displayName); @@ -844,7 +854,7 @@ static CMakeTargetNode *createTargetNode(const QHash<Utils::FileName, ProjectNod return tn; } -void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer::ProjectNode *> &cmakeListsNodes, +void ServerModeReader::addTargets(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes, const QList<Target *> &targets, QList<ProjectExplorer::FileNode *> &knownHeaderNodes) { @@ -852,15 +862,15 @@ void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer:: CMakeTargetNode *tNode = createTargetNode(cmakeListsNodes, t->sourceDirectory, t->name); QTC_ASSERT(tNode, qDebug() << "No target node for" << t->sourceDirectory << t->name; continue); tNode->setTargetInformation(t->artifacts, t->type); + tNode->setBuildDirectory(t->buildDirectory); QList<FolderNode::LocationInfo> info; // Set up a default target path: - FileName targetPath = t->sourceDirectory; - targetPath.appendPath("CMakeLists.txt"); + FilePath targetPath = t->sourceDirectory.pathAppended("CMakeLists.txt"); for (CrossReference *cr : qAsConst(t->crossReferences)) { BacktraceItem *bt = cr->backtrace.isEmpty() ? nullptr : cr->backtrace.at(0); if (bt) { const QString btName = bt->name.toLower(); - const FileName path = Utils::FileName::fromUserInput(bt->path); + const FilePath path = Utils::FilePath::fromUserInput(bt->path); QString dn; if (cr->type != CrossReference::TARGET) { if (path == targetPath) { @@ -887,29 +897,29 @@ void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer:: } void ServerModeReader::addFileGroups(ProjectNode *targetRoot, - const Utils::FileName &sourceDirectory, - const Utils::FileName &buildDirectory, + const Utils::FilePath &sourceDirectory, + const Utils::FilePath &buildDirectory, const QList<ServerModeReader::FileGroup *> &fileGroups, QList<FileNode *> &knownHeaderNodes) { std::vector<std::unique_ptr<FileNode>> toList; - QSet<Utils::FileName> alreadyListed; + QSet<Utils::FilePath> alreadyListed; // Files already added by other configurations: targetRoot->forEachGenericNode([&alreadyListed](const Node *n) { alreadyListed.insert(n->filePath()); }); for (const FileGroup *f : fileGroups) { - const QList<FileName> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FileName &fn) { + const QList<FilePath> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FilePath &fn) { const int count = alreadyListed.count(); alreadyListed.insert(fn); return count != alreadyListed.count(); }); std::vector<std::unique_ptr<FileNode>> newFileNodes = Utils::transform<std::vector>(newSources, - [f, &knownHeaderNodes](const Utils::FileName &fn) { - auto node - = std::make_unique<FileNode>(fn, Node::fileTypeForFileName(fn), f->isGenerated); + [f, &knownHeaderNodes](const Utils::FilePath &fn) { + auto node = std::make_unique<FileNode>(fn, Node::fileTypeForFileName(fn)); + node->setIsGenerated(f->isGenerated); if (node->fileType() == FileType::Header) knownHeaderNodes.append(node.get()); return node; @@ -933,7 +943,7 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot, addCMakeVFolder(targetRoot, sourceDirectory, 1000, QString(), std::move(sourceFileNodes)); addCMakeVFolder(targetRoot, buildDirectory, 100, tr("<Build Directory>"), std::move(buildFileNodes)); - addCMakeVFolder(targetRoot, Utils::FileName(), 10, tr("<Other Locations>"), std::move(otherFileNodes)); + addCMakeVFolder(targetRoot, Utils::FilePath(), 10, tr("<Other Locations>"), std::move(otherFileNodes)); } void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *> knownHeaders, @@ -944,13 +954,13 @@ void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *> static QIcon headerNodeIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_H); - auto headerNode - = std::make_unique<VirtualFolderNode>(root->filePath(), Node::DefaultPriority - 5); + auto headerNode = std::make_unique<VirtualFolderNode>(root->filePath()); + headerNode->setPriority(Node::DefaultPriority - 5); headerNode->setDisplayName(tr("<Headers>")); headerNode->setIcon(headerNodeIcon); // knownHeaders are already listed in their targets: - QSet<Utils::FileName> seenHeaders = Utils::transform<QSet>(knownHeaders, &FileNode::filePath); + QSet<Utils::FilePath> seenHeaders = Utils::transform<QSet>(knownHeaders, &FileNode::filePath); // Add scanned headers: for (const FileNode *fn : allFiles) { diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h index a8e998c68c..b362b15b3f 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.h +++ b/src/plugins/cmakeprojectmanager/servermodereader.h @@ -78,7 +78,7 @@ private: struct Project; struct IncludePath { - Utils::FileName path; + Utils::FilePath path; bool isSystem; }; @@ -90,7 +90,7 @@ private: ProjectExplorer::Macros macros; QList<IncludePath *> includePaths; QString language; - QList<Utils::FileName> sources; + QList<Utils::FilePath> sources; bool isGenerated; }; @@ -118,9 +118,9 @@ private: Project *project = nullptr; QString name; QString type; - QList<Utils::FileName> artifacts; - Utils::FileName sourceDirectory; - Utils::FileName buildDirectory; + QList<Utils::FilePath> artifacts; + Utils::FilePath sourceDirectory; + Utils::FilePath buildDirectory; QList<FileGroup *> fileGroups; QList<CrossReference *> crossReferences; }; @@ -128,7 +128,7 @@ private: struct Project { ~Project() { qDeleteAll(targets); targets.clear(); } QString name; - Utils::FileName sourceDirectory; + Utils::FilePath sourceDirectory; QList<Target *> targets; }; @@ -145,17 +145,17 @@ private: void fixTarget(Target *target) const; - QHash<Utils::FileName, ProjectExplorer::ProjectNode *> + QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> addCMakeLists(CMakeProjectNode *root, std::vector<std::unique_ptr<ProjectExplorer::FileNode> > &&cmakeLists); - void addProjects(const QHash<Utils::FileName, ProjectExplorer::ProjectNode *> &cmakeListsNodes, + void addProjects(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes, const QList<Project *> &projects, QList<ProjectExplorer::FileNode *> &knownHeaderNodes); - void addTargets(const QHash<Utils::FileName, ProjectExplorer::ProjectNode *> &cmakeListsNodes, + void addTargets(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes, const QList<Target *> &targets, QList<ProjectExplorer::FileNode *> &knownHeaderNodes); void addFileGroups(ProjectExplorer::ProjectNode *targetRoot, - const Utils::FileName &sourceDirectory, - const Utils::FileName &buildDirectory, const QList<FileGroup *> &fileGroups, + const Utils::FilePath &sourceDirectory, + const Utils::FilePath &buildDirectory, const QList<FileGroup *> &fileGroups, QList<ProjectExplorer::FileNode *> &knowHeaderNodes); void addHeaderNodes(ProjectExplorer::ProjectNode *root, @@ -172,7 +172,7 @@ private: CMakeConfig m_cmakeConfiguration; - QSet<Utils::FileName> m_cmakeFiles; + QSet<Utils::FilePath> m_cmakeFiles; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_cmakeInputsFileNodes; QList<Project *> m_projects; diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index 320b470e45..d336d9e8cf 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -70,7 +70,7 @@ namespace Internal { class CMakeFile : public IDocument { public: - CMakeFile(TeaLeafReader *r, const FileName &fileName); + CMakeFile(TeaLeafReader *r, const FilePath &fileName); ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override; bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; @@ -79,7 +79,7 @@ private: TeaLeafReader *m_reader; }; -CMakeFile::CMakeFile(TeaLeafReader *r, const FileName &fileName) : m_reader(r) +CMakeFile::CMakeFile(TeaLeafReader *r, const FilePath &fileName) : m_reader(r) { setId("Cmake.ProjectFile"); setMimeType(Constants::CMAKEPROJECTMIMETYPE); @@ -200,7 +200,7 @@ void TeaLeafReader::parse(bool forceConfiguration) } const bool mustUpdate = m_cmakeFiles.isEmpty() - || anyOf(m_cmakeFiles, [&cbpFileFi](const FileName &f) { + || anyOf(m_cmakeFiles, [&cbpFileFi](const FilePath &f) { return f.toFileInfo().lastModified() > cbpFileFi.lastModified(); }); if (mustUpdate) { @@ -235,8 +235,7 @@ QList<CMakeBuildTarget> TeaLeafReader::takeBuildTargets() CMakeConfig TeaLeafReader::takeParsedConfiguration() { - FileName cacheFile = m_parameters.workDirectory; - cacheFile.appendPath(QLatin1String("CMakeCache.txt")); + const FilePath cacheFile = m_parameters.workDirectory.pathAppended("CMakeCache.txt"); if (!cacheFile.exists()) return { }; @@ -249,10 +248,10 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration() return { }; } - const FileName sourceOfBuildDir - = FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", result)); - const FileName canonicalSourceOfBuildDir = FileUtils::canonicalPath(sourceOfBuildDir); - const FileName canonicalSourceDirectory = FileUtils::canonicalPath(m_parameters.sourceDirectory); + const FilePath sourceOfBuildDir + = FilePath::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", result)); + const FilePath canonicalSourceOfBuildDir = sourceOfBuildDir.canonicalPath(); + const FilePath canonicalSourceDirectory = m_parameters.sourceDirectory.canonicalPath(); if (canonicalSourceOfBuildDir != canonicalSourceDirectory) { // Uses case-insensitive compare where appropriate emit errorOccured(tr("The build directory is not for %1 but for %2") .arg(canonicalSourceOfBuildDir.toUserOutput(), @@ -270,10 +269,10 @@ void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<cons root->setDisplayName(m_projectName); // Delete no longer necessary file watcher based on m_cmakeFiles: - const QSet<FileName> currentWatched + const QSet<FilePath> currentWatched = transform(m_watchedFiles, &CMakeFile::filePath); - const QSet<FileName> toWatch = m_cmakeFiles; - QSet<FileName> toDelete = currentWatched; + const QSet<FilePath> toWatch = m_cmakeFiles; + QSet<FilePath> toDelete = currentWatched; toDelete.subtract(toWatch); m_watchedFiles = filtered(m_watchedFiles, [&toDelete](Internal::CMakeFile *cmf) { if (toDelete.contains(cmf->filePath())) { @@ -284,30 +283,30 @@ void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<cons }); // Add new file watchers: - QSet<FileName> toAdd = toWatch; + QSet<FilePath> toAdd = toWatch; toAdd.subtract(currentWatched); - foreach (const FileName &fn, toAdd) { + foreach (const FilePath &fn, toAdd) { auto cm = new CMakeFile(this, fn); DocumentManager::addDocument(cm); m_watchedFiles.insert(cm); } - QSet<FileName> allIncludePathSet; + QSet<FilePath> allIncludePathSet; for (const CMakeBuildTarget &bt : m_buildTargets) { - const QList<Utils::FileName> targetIncludePaths - = Utils::filtered(bt.includeFiles, [this](const Utils::FileName &fn) { + const QList<Utils::FilePath> targetIncludePaths + = Utils::filtered(bt.includeFiles, [this](const Utils::FilePath &fn) { return fn.isChildOf(m_parameters.sourceDirectory); }); - allIncludePathSet.unite(QSet<FileName>::fromList(targetIncludePaths)); + allIncludePathSet.unite(QSet<FilePath>::fromList(targetIncludePaths)); } - const QList<FileName> allIncludePaths = allIncludePathSet.toList(); + const QList<FilePath> allIncludePaths = allIncludePathSet.toList(); const QList<const FileNode *> missingHeaders = Utils::filtered(allFiles, [&allIncludePaths](const FileNode *fn) -> bool { if (fn->fileType() != FileType::Header) return false; - return Utils::contains(allIncludePaths, [fn](const FileName &inc) { return fn->filePath().isChildOf(inc); }); + return Utils::contains(allIncludePaths, [fn](const FilePath &inc) { return fn->filePath().isChildOf(inc); }); }); // filter duplicates: @@ -328,15 +327,15 @@ void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<cons } static void processCMakeIncludes(const CMakeBuildTarget &cbt, const ToolChain *tc, - const QStringList& flags, const FileName &sysroot, - QSet<FileName> &tcIncludes, QStringList &includePaths) + const QStringList& flags, const FilePath &sysroot, + QSet<FilePath> &tcIncludes, QStringList &includePaths) { if (!tc) return; foreach (const HeaderPath &hp, tc->builtInHeaderPaths(flags, sysroot)) - tcIncludes.insert(FileName::fromString(hp.path)); - foreach (const FileName &i, cbt.includeFiles) { + tcIncludes.insert(FilePath::fromString(hp.path)); + foreach (const FilePath &i, cbt.includeFiles) { if (!tcIncludes.contains(i)) includePaths.append(i.toString()); } @@ -346,7 +345,7 @@ CppTools::RawProjectParts TeaLeafReader::createRawProjectParts() const { const ToolChain *tcCxx = ToolChainManager::findToolChain(m_parameters.cxxToolChainId); const ToolChain *tcC = ToolChainManager::findToolChain(m_parameters.cToolChainId); - const FileName sysroot = m_parameters.sysRoot; + const FilePath sysroot = m_parameters.sysRoot; CppTools::RawProjectParts rpps; QHash<QString, QStringList> targetDataCacheCxx; @@ -360,18 +359,18 @@ CppTools::RawProjectParts TeaLeafReader::createRawProjectParts() const // place. auto cxxflags = getFlagsFor(cbt, targetDataCacheCxx, ProjectExplorer::Constants::CXX_LANGUAGE_ID); auto cflags = getFlagsFor(cbt, targetDataCacheC, ProjectExplorer::Constants::C_LANGUAGE_ID); - QSet<FileName> tcIncludes; + QSet<FilePath> tcIncludes; QStringList includePaths; if (tcCxx || tcC) { processCMakeIncludes(cbt, tcCxx, cxxflags, sysroot, tcIncludes, includePaths); processCMakeIncludes(cbt, tcC, cflags, sysroot, tcIncludes, includePaths); } else { - includePaths = transform(cbt.includeFiles, &FileName::toString); + includePaths = transform(cbt.includeFiles, &FilePath::toString); } includePaths += m_parameters.workDirectory.toString(); CppTools::RawProjectPart rpp; rpp.setProjectFileLocation(cbt.sourceDirectory.toString() + "/CMakeLists.txt"); - rpp.setBuildSystemTarget(cbt.title + QChar('\n') + cbt.sourceDirectory.toString() + QChar('/')); + rpp.setBuildSystemTarget(CMakeTargetNode::generateId(cbt.sourceDirectory, cbt.title)); rpp.setIncludePaths(includePaths); CppTools::RawProjectPartFlags cProjectFlags; @@ -384,7 +383,7 @@ CppTools::RawProjectParts TeaLeafReader::createRawProjectParts() const rpp.setMacros(cbt.macros); rpp.setDisplayName(cbt.title); - rpp.setFiles(transform(cbt.files, &FileName::toString)); + rpp.setFiles(transform(cbt.files, &FilePath::toString)); const bool isExecutable = cbt.targetType == ExecutableType; rpp.setBuildTargetType(isExecutable ? CppTools::ProjectPart::Executable @@ -415,26 +414,25 @@ void TeaLeafReader::extractData() CMakeTool *cmake = m_parameters.cmakeTool(); QTC_ASSERT(m_parameters.isValid() && cmake, return); - const FileName srcDir = m_parameters.sourceDirectory; - const FileName bldDir = m_parameters.workDirectory; - const FileName topCMake = Utils::FileName(srcDir).appendPath("CMakeLists.txt"); + const FilePath srcDir = m_parameters.sourceDirectory; + const FilePath bldDir = m_parameters.workDirectory; + const FilePath topCMake = srcDir.pathAppended("CMakeLists.txt"); resetData(); m_projectName = m_parameters.projectName; - m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project, false)); + m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project)); // Do not insert topCMake into m_cmakeFiles: The project already watches that! // Find cbp file - FileName cbpFile = FileName::fromString(findCbpFile(bldDir.toString())); + FilePath cbpFile = FilePath::fromString(findCbpFile(bldDir.toString())); if (cbpFile.isEmpty()) return; m_cmakeFiles.insert(cbpFile); // Add CMakeCache.txt file: - FileName cacheFile = m_parameters.workDirectory; - cacheFile.appendPath(QLatin1String("CMakeCache.txt")); - if (cacheFile.toFileInfo().exists()) + const FilePath cacheFile = m_parameters.workDirectory.pathAppended("CMakeCache.txt"); + if (cacheFile.exists()) m_cmakeFiles.insert(cacheFile); // setFolderName @@ -458,7 +456,7 @@ void TeaLeafReader::extractData() if (!contains(m_files, [topCMake](const std::unique_ptr<FileNode> &fn) { return fn->filePath() == topCMake; })) - m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project, false)); + m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project)); m_buildTargets = cbpparser.buildTargets(); } @@ -468,7 +466,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments) CMakeTool *cmake = m_parameters.cmakeTool(); QTC_ASSERT(m_parameters.isValid() && cmake, return); - const FileName workDirectory = m_parameters.workDirectory; + const FilePath workDirectory = m_parameters.workDirectory; QTC_ASSERT(!m_cmakeProcess, return); QTC_ASSERT(!m_parser, return); QTC_ASSERT(!m_future, return); @@ -484,7 +482,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments) TaskHub::addTask(task); } else { Task t = task; - t.file = FileName::fromString(source.absoluteFilePath(task.file.toString())); + t.file = FilePath::fromString(source.absoluteFilePath(task.file.toString())); TaskHub::addTask(t); } }); @@ -500,7 +498,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments) this, &TeaLeafReader::processCMakeOutput); connect(m_cmakeProcess, &QProcess::readyReadStandardError, this, &TeaLeafReader::processCMakeError); - connect(m_cmakeProcess, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), + connect(m_cmakeProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &TeaLeafReader::cmakeFinished); QString args; @@ -521,7 +519,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments) tr("Configuring \"%1\"").arg(m_parameters.projectName), "CMake.Configure"); - m_cmakeProcess->setCommand(cmake->cmakeExecutable().toString(), args); + m_cmakeProcess->setCommand(CommandLine(cmake->cmakeExecutable(), args)); emit configurationStarted(); m_cmakeProcess->start(); } diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.h b/src/plugins/cmakeprojectmanager/tealeafreader.h index 142ea4b5af..356adc8110 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.h +++ b/src/plugins/cmakeprojectmanager/tealeafreader.h @@ -79,7 +79,7 @@ private: ProjectExplorer::IOutputParser *m_parser = nullptr; QFutureInterface<void> *m_future = nullptr; - QSet<Utils::FileName> m_cmakeFiles; + QSet<Utils::FilePath> m_cmakeFiles; QString m_projectName; QList<CMakeBuildTarget> m_buildTargets; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_files; diff --git a/src/plugins/cmakeprojectmanager/treescanner.cpp b/src/plugins/cmakeprojectmanager/treescanner.cpp deleted file mode 100644 index 7a25e9e266..0000000000 --- a/src/plugins/cmakeprojectmanager/treescanner.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Alexander Drozdov. -** Contact: Alexander Drozdov (adrozdoff@gmail.com) -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "treescanner.h" - -#include <coreplugin/iversioncontrol.h> -#include <coreplugin/vcsmanager.h> -#include <projectexplorer/projectexplorerconstants.h> - -#include <cpptools/cpptoolsconstants.h> - -#include <utils/qtcassert.h> -#include <utils/algorithm.h> -#include <utils/runextensions.h> - -#include <memory> - -using namespace ProjectExplorer; - -namespace CMakeProjectManager { -namespace Internal { - -TreeScanner::TreeScanner(QObject *parent) : QObject(parent) -{ - m_factory = TreeScanner::genericFileType; - m_filter = [](const Utils::MimeType &mimeType, const Utils::FileName &fn) { - return isWellKnownBinary(mimeType, fn) && isMimeBinary(mimeType, fn); - }; - - connect(&m_futureWatcher, &FutureWatcher::finished, this, &TreeScanner::finished); -} - -TreeScanner::~TreeScanner() -{ - if (!m_futureWatcher.isFinished()) { - m_futureWatcher.cancel(); - m_futureWatcher.waitForFinished(); - } -} - -bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory) -{ - if (!m_futureWatcher.isFinished()) - return false; - - auto fi = new FutureInterface(); - m_scanFuture = fi->future(); - m_futureWatcher.setFuture(m_scanFuture); - - Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); }); - - return true; -} - -void TreeScanner::setFilter(TreeScanner::FileFilter filter) -{ - if (isFinished()) - m_filter = filter; -} - -void TreeScanner::setTypeFactory(TreeScanner::FileTypeFactory factory) -{ - if (isFinished()) - m_factory = factory; -} - -TreeScanner::Future TreeScanner::future() const -{ - return m_scanFuture; -} - -bool TreeScanner::isFinished() const -{ - return m_futureWatcher.isFinished(); -} - -TreeScanner::Result TreeScanner::result() const -{ - if (isFinished()) - return m_scanFuture.result(); - return Result(); -} - -TreeScanner::Result TreeScanner::release() -{ - if (isFinished()) { - auto result = m_scanFuture.result(); - m_scanFuture = Future(); - return result; - } - return Result(); -} - -void TreeScanner::reset() -{ - if (isFinished()) - m_scanFuture = Future(); -} - -bool TreeScanner::isWellKnownBinary(const Utils::MimeType & /*mdb*/, const Utils::FileName &fn) -{ - return fn.endsWith(QLatin1String(".a")) || - fn.endsWith(QLatin1String(".o")) || - fn.endsWith(QLatin1String(".d")) || - fn.endsWith(QLatin1String(".exe")) || - fn.endsWith(QLatin1String(".dll")) || - fn.endsWith(QLatin1String(".obj")) || - fn.endsWith(QLatin1String(".elf")); -} - -bool TreeScanner::isMimeBinary(const Utils::MimeType &mimeType, const Utils::FileName &/*fn*/) -{ - bool isBinary = false; - if (mimeType.isValid()) { - QStringList mimes; - mimes << mimeType.name() << mimeType.allAncestors(); - isBinary = !mimes.contains(QLatin1String("text/plain")); - } - return isBinary; -} - -FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Utils::FileName &/*fn*/) -{ - return Node::fileTypeForMimeType(mimeType); -} - -void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory, - const FileFilter &filter, const FileTypeFactory &factory) -{ - std::unique_ptr<FutureInterface> fip(fi); - fip->reportStarted(); - - Result nodes = FileNode::scanForFiles( - directory, - [&filter, &factory](const Utils::FileName &fn) -> FileNode * { - const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString()); - - // Skip some files during scan. - if (filter && filter(mimeType, fn)) - return nullptr; - - // Type detection - FileType type = FileType::Unknown; - if (factory) - type = factory(mimeType, fn); - - return new FileNode(fn, type, false); - }, fip.get()); - - Utils::sort(nodes, ProjectExplorer::Node::sortByPath); - - fip->setProgressValue(fip->progressMaximum()); - fip->reportResult(nodes); - fip->reportFinished(); -} - -} // namespace Internal -} // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/treescanner.h b/src/plugins/cmakeprojectmanager/treescanner.h deleted file mode 100644 index bf9872f6df..0000000000 --- a/src/plugins/cmakeprojectmanager/treescanner.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Alexander Drozdov. -** Contact: Alexander Drozdov (adrozdoff@gmail.com) -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "projectexplorer/projectnodes.h" - -#include <utils/mimetypes/mimedatabase.h> -#include <utils/fileutils.h> - -#include <QObject> -#include <QFuture> -#include <QFutureWatcher> - -#include <functional> - -namespace Core { class IVersionControl; } - -namespace CMakeProjectManager { -namespace Internal { - -class TreeScanner : public QObject -{ - Q_OBJECT - -public: - using Result = QList<ProjectExplorer::FileNode *>; - using Future = QFuture<Result>; - using FutureWatcher = QFutureWatcher<Result>; - using FutureInterface = QFutureInterface<Result>; - - using FileFilter = std::function<bool(const Utils::MimeType &, const Utils::FileName &)>; - using FileTypeFactory = std::function<ProjectExplorer::FileType(const Utils::MimeType &, const Utils::FileName &)>; - - explicit TreeScanner(QObject *parent = nullptr); - ~TreeScanner() override; - - // Start scanning in given directory - bool asyncScanForFiles(const Utils::FileName& directory); - - // Setup filter for ignored files - void setFilter(FileFilter filter); - - // Setup factory for file types - void setTypeFactory(FileTypeFactory factory); - - Future future() const; - bool isFinished() const; - - // Takes not-owning result - Result result() const; - // Takes owning of result - Result release(); - // Clear scan results - void reset(); - - // Standard filters helpers - static bool isWellKnownBinary(const Utils::MimeType &mimeType, const Utils::FileName &fn); - static bool isMimeBinary(const Utils::MimeType &mimeType, const Utils::FileName &fn); - - // Standard file factory - static ProjectExplorer::FileType genericFileType(const Utils::MimeType &mdb, const Utils::FileName& fn); - -signals: - void finished(); - -private: - static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory, - const FileFilter &filter, const FileTypeFactory &factory); - -private: - FileFilter m_filter; - FileTypeFactory m_factory; - - FutureWatcher m_futureWatcher; - Future m_scanFuture; -}; - -} // namespace Internal -} // namespace CMakeProjectManager - - |