diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp index 5b4ca9d0513..939383672d5 100644 --- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp +++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp @@ -69,13 +69,22 @@ public: CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const; CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const; - QModelIndex addCMakeTool(const QString &name, const FilePath &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected); + QModelIndex addCMakeTool(const QString &name, + const FilePath &executable, + const FilePath &qchFile, + 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 FilePath &executable, - bool autoRun, bool autoCreate); + void updateCMakeTool(const Core::Id &id, + const QString &displayName, + const FilePath &executable, + const FilePath &qchFile, + bool autoRun, + bool autoCreate); void removeCMakeTool(const Core::Id &id); void apply(); @@ -97,6 +106,7 @@ public: : m_id(item->id()) , m_name(item->displayName()) , m_executable(item->filePath()) + , m_qchFile(item->qchFilePath()) , m_isAutoRun(item->isAutoRun()) , m_autoCreateBuildDirectory(item->autoCreateBuildDirectory()) , m_autodetected(item->isAutoDetected()) @@ -111,12 +121,14 @@ public: CMakeToolTreeItem(const QString &name, const Utils::FilePath &executable, + const FilePath &qchFile, bool autoRun, bool autoCreate, bool autodetected) : m_id(Core::Id::fromString(QUuid::createUuid().toString())) , m_name(name) , m_executable(executable) + , m_qchFile(qchFile) , m_isAutoRun(autoRun) , m_autoCreateBuildDirectory(autoCreate) , m_autodetected(autodetected) @@ -197,6 +209,7 @@ public: QString m_name; QString m_tooltip; FilePath m_executable; + FilePath m_qchFile; bool m_isAutoRun = true; bool m_pathExists = false; bool m_pathIsFile = false; @@ -224,11 +237,14 @@ CMakeToolItemModel::CMakeToolItemModel() } -QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FilePath &executable, - const bool autoRun, const bool autoCreate, +QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, + const FilePath &executable, + const FilePath &qchFile, + const bool autoRun, + const bool autoCreate, const bool isAutoDetected) { - auto item = new CMakeToolTreeItem(name, executable, autoRun, autoCreate, isAutoDetected); + auto item = new CMakeToolTreeItem(name, executable, qchFile, autoRun, autoCreate, isAutoDetected); if (isAutoDetected) autoGroupItem()->appendChild(item); else @@ -265,7 +281,8 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const { CMakeTool *orig = CMakeToolManager::findById(item->m_id); item->m_changed = !orig || orig->displayName() != item->m_name - || orig->filePath() != item->m_executable; + || orig->filePath() != item->m_executable + || orig->qchFilePath() != item->m_qchFile; //make sure the item is marked as changed when the default cmake was changed CMakeTool *origDefTool = CMakeToolManager::defaultCMakeTool(); @@ -278,8 +295,11 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const item->update(); // Notify views. } -void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName, - const FilePath &executable, bool autoRun, +void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, + const QString &displayName, + const FilePath &executable, + const FilePath &qchFile, + bool autoRun, bool autoCreate) { CMakeToolTreeItem *treeItem = cmakeToolItem(id); @@ -287,6 +307,7 @@ void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &disp treeItem->m_name = displayName; treeItem->m_executable = executable; + treeItem->m_qchFile = qchFile; treeItem->m_isAutoRun = autoRun; treeItem->m_autoCreateBuildDirectory = autoCreate; @@ -328,6 +349,7 @@ void CMakeToolItemModel::apply() if (CMakeTool *cmake = CMakeToolManager::findById(item->m_id)) { cmake->setDisplayName(item->m_name); cmake->setFilePath(item->m_executable); + cmake->setQchFilePath(item->m_qchFile); cmake->setAutorun(item->m_isAutoRun); cmake->setAutoCreateBuildDirectory(item->m_autoCreateBuildDirectory); } else { @@ -341,6 +363,7 @@ void CMakeToolItemModel::apply() auto cmake = std::make_unique(detection, item->m_id); cmake->setDisplayName(item->m_name); cmake->setFilePath(item->m_executable); + cmake->setQchFilePath(item->m_qchFile); if (!CMakeToolManager::registerCMakeTool(std::move(cmake))) item->m_changed = true; } @@ -392,11 +415,14 @@ public: void store() const; private: + void updateQchFilePath(); + CMakeToolItemModel *m_model; QLineEdit *m_displayNameLineEdit; QCheckBox *m_autoRunCheckBox; QCheckBox *m_autoCreateBuildDirectoryCheckBox; PathChooser *m_binaryChooser; + PathChooser *m_qchFileChooser; Core::Id m_id; bool m_loadingItem; }; @@ -412,6 +438,13 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) m_binaryChooser->setHistoryCompleter(QLatin1String("Cmake.Command.History")); m_binaryChooser->setCommandVersionArguments({"--version"}); + m_qchFileChooser = new PathChooser(this); + m_qchFileChooser->setExpectedKind(PathChooser::File); + m_qchFileChooser->setMinimumWidth(400); + m_qchFileChooser->setHistoryCompleter(QLatin1String("Cmake.qchFile.History")); + m_qchFileChooser->setPromptDialogFilter("*.qch"); + m_qchFileChooser->setPromptDialogTitle(tr("CMake .qch File")); + m_autoRunCheckBox = new QCheckBox; m_autoRunCheckBox->setText(tr("Autorun CMake")); m_autoRunCheckBox->setToolTip(tr("Automatically run CMake after changes to CMake project files.")); @@ -424,13 +457,17 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit); formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser); + formLayout->addRow(new QLabel(tr("Help File:")), m_qchFileChooser); formLayout->addRow(m_autoRunCheckBox); formLayout->addRow(m_autoCreateBuildDirectoryCheckBox); - connect(m_binaryChooser, &PathChooser::rawPathChanged, - this, &CMakeToolItemConfigWidget::store); - connect(m_displayNameLineEdit, &QLineEdit::textChanged, - this, &CMakeToolItemConfigWidget::store); + connect(m_binaryChooser, &PathChooser::rawPathChanged, this, [this]() { + updateQchFilePath(); + m_qchFileChooser->setBaseFileName(m_binaryChooser->fileName().parentDir()); + store(); + }); + connect(m_qchFileChooser, &PathChooser::rawPathChanged, this, &CMakeToolItemConfigWidget::store); + connect(m_displayNameLineEdit, &QLineEdit::textChanged, this, &CMakeToolItemConfigWidget::store); connect(m_autoRunCheckBox, &QCheckBox::toggled, this, &CMakeToolItemConfigWidget::store); connect(m_autoCreateBuildDirectoryCheckBox, &QCheckBox::toggled, @@ -440,11 +477,20 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) void CMakeToolItemConfigWidget::store() const { if (!m_loadingItem && m_id.isValid()) - m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(), + m_model->updateCMakeTool(m_id, + m_displayNameLineEdit->text(), + m_binaryChooser->fileName(), + m_qchFileChooser->fileName(), m_autoRunCheckBox->checkState() == Qt::Checked, m_autoCreateBuildDirectoryCheckBox->checkState() == Qt::Checked); } +void CMakeToolItemConfigWidget::updateQchFilePath() +{ + if (m_qchFileChooser->fileName().isEmpty()) + m_qchFileChooser->setFileName(CMakeTool::searchQchFile(m_binaryChooser->fileName())); +} + void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) { m_loadingItem = true; // avoid intermediate signal handling @@ -461,6 +507,10 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) m_binaryChooser->setReadOnly(item->m_autodetected); m_binaryChooser->setFileName(item->m_executable); + m_qchFileChooser->setReadOnly(item->m_autodetected); + m_qchFileChooser->setBaseFileName(item->m_executable.parentDir()); + m_qchFileChooser->setFileName(item->m_qchFile); + m_autoRunCheckBox->setChecked(item->m_isAutoRun); m_autoCreateBuildDirectoryCheckBox->setChecked(item->m_autoCreateBuildDirectory); @@ -568,8 +618,10 @@ void CMakeToolConfigWidget::cloneCMakeTool() QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name), m_currentItem->m_executable, + m_currentItem->m_qchFile, m_currentItem->m_isAutoRun, - m_currentItem->m_autoCreateBuildDirectory, false); + m_currentItem->m_autoCreateBuildDirectory, + false); m_cmakeToolsView->setCurrentIndex(newItem); } @@ -577,7 +629,11 @@ void CMakeToolConfigWidget::cloneCMakeTool() void CMakeToolConfigWidget::addCMakeTool() { QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")), - FilePath(), true, false, false); + FilePath(), + FilePath(), + true, + false, + false); m_cmakeToolsView->setCurrentIndex(newItem); } diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index 10c0b10fe12..411ec19e27c 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -46,6 +47,7 @@ const char CMAKE_INFORMATION_ID[] = "Id"; const char CMAKE_INFORMATION_COMMAND[] = "Binary"; const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName"; const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun"; +const char CMAKE_INFORMATION_QCH_FILE_PATH[] = "QchFile"; const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory"; const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected"; const char CMAKE_INFORMATION_READERTYPE[] = "ReaderType"; @@ -146,6 +148,11 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected = map.value(CMAKE_INFORMATION_AUTODETECTED, false).toBool(); setFilePath(Utils::FilePath::fromString(map.value(CMAKE_INFORMATION_COMMAND).toString())); + + m_qchFilePath = Utils::FilePath::fromVariant(map.value(CMAKE_INFORMATION_QCH_FILE_PATH)); + + if (m_qchFilePath.isEmpty()) + m_qchFilePath = searchQchFile(m_executable); } CMakeTool::~CMakeTool() = default; @@ -229,6 +236,7 @@ QVariantMap CMakeTool::toMap() const data.insert(CMAKE_INFORMATION_DISPLAYNAME, m_displayName); data.insert(CMAKE_INFORMATION_ID, m_id.toSetting()); data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString()); + data.insert(CMAKE_INFORMATION_QCH_FILE_PATH, m_qchFilePath.toString()); data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun); data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory); if (m_readerType.has_value()) @@ -243,6 +251,16 @@ Utils::FilePath CMakeTool::cmakeExecutable() const return cmakeExecutable(m_executable); } +void CMakeTool::setQchFilePath(const Utils::FilePath &path) +{ + m_qchFilePath = path; +} + +Utils::FilePath CMakeTool::qchFilePath() const +{ + return m_qchFilePath; +} + Utils::FilePath CMakeTool::cmakeExecutable(const Utils::FilePath &path) { if (Utils::HostOsInfo::isMacHost()) { @@ -376,6 +394,28 @@ CMakeTool::ReaderType CMakeTool::readerType() const return m_readerType.value(); } +Utils::FilePath CMakeTool::searchQchFile(const Utils::FilePath &executable) +{ + if (executable.isEmpty()) + return {}; + + Utils::FilePath prefixDir = executable.parentDir().parentDir(); + QDir docDir{prefixDir.pathAppended("doc/cmake").toString()}; + if (!docDir.exists()) + docDir.setPath(prefixDir.pathAppended("share/doc/cmake").toString()); + if (!docDir.exists()) + return {}; + + const QStringList files = docDir.entryList(QStringList("*.qch")); + for (const QString &docFile : files) { + if (docFile.startsWith("cmake", Qt::CaseInsensitive)) { + return Utils::FilePath::fromString(docDir.absoluteFilePath(docFile)); + } + } + + return {}; +} + void CMakeTool::readInformation(CMakeTool::QueryType type) const { if (!m_introspection->m_triedCapabilities) { diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index 579f6e4d722..1e305b2dd34 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -95,6 +95,8 @@ public: void setFilePath(const Utils::FilePath &executable); Utils::FilePath filePath() const; Utils::FilePath cmakeExecutable() const; + void setQchFilePath(const Utils::FilePath &path); + Utils::FilePath qchFilePath() const; static Utils::FilePath cmakeExecutable(const Utils::FilePath &path); bool isAutoRun() const; bool autoCreateBuildDirectory() const; @@ -114,6 +116,8 @@ public: ReaderType readerType() const; + static Utils::FilePath searchQchFile(const Utils::FilePath &executable); + private: enum class QueryType { GENERATORS, @@ -136,6 +140,7 @@ private: Core::Id m_id; QString m_displayName; Utils::FilePath m_executable; + Utils::FilePath m_qchFilePath; bool m_isAutoRun = true; bool m_isAutoDetected = false; diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp index 77f3e077a2f..fd7af452c76 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp @@ -27,6 +27,7 @@ #include "cmaketoolsettingsaccessor.h" +#include #include #include @@ -105,6 +106,8 @@ bool CMakeToolManager::registerCMakeTool(std::unique_ptr &&tool) ensureDefaultCMakeToolIsValid(); + updateDocumentation(); + return true; } @@ -112,9 +115,10 @@ void CMakeToolManager::deregisterCMakeTool(const Id &id) { auto toRemove = Utils::take(d->m_cmakeTools, Utils::equal(&CMakeTool::id, id)); if (toRemove.has_value()) { - ensureDefaultCMakeToolIsValid(); + updateDocumentation(); + emit m_instance->cmakeRemoved(id); } } @@ -152,9 +156,22 @@ void CMakeToolManager::restoreCMakeTools() d->m_cmakeTools = std::move(tools.cmakeTools); setDefaultCMakeTool(tools.defaultToolId); + updateDocumentation(); + emit m_instance->cmakeToolsLoaded(); } +void CMakeToolManager::updateDocumentation() +{ + const QList tools = cmakeTools(); + QStringList docs; + for (const auto tool : tools) { + if (!tool->qchFilePath().isEmpty()) + docs.append(tool->qchFilePath().toString()); + } + Core::HelpManager::registerDocumentation(docs); +} + void CMakeToolManager::notifyAboutUpdate(CMakeTool *tool) { if (!tool || !Utils::contains(d->m_cmakeTools, tool)) diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h index b5ea3221dd1..c91f6498501 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h +++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h @@ -58,6 +58,8 @@ public: static void notifyAboutUpdate(CMakeTool *); static void restoreCMakeTools(); + static void updateDocumentation(); + signals: void cmakeAdded (const Core::Id &id); void cmakeRemoved (const Core::Id &id);