diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index 1a279e93adc..ea9fa55db01 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -277,9 +277,10 @@ void CMakeKitAspect::setup(Kit *k) return; // Look for a suitable auto-detected one: - const QString id = k->autoDetectionSource(); + const QString kitSource = k->autoDetectionSource(); for (CMakeTool *tool : CMakeToolManager::cmakeTools()) { - if (tool->detectionSource() == id) { + const QString toolSource = tool->detectionSource(); + if (!toolSource.isEmpty() && toolSource == kitSource) { setCMakeTool(k, tool->id()); return; } @@ -1043,8 +1044,6 @@ CMakeConfig CMakeConfigurationKitAspect::defaultConfiguration(const Kit *k) QVariant CMakeConfigurationKitAspect::defaultValue(const Kit *k) const { - Q_UNUSED(k) - // FIXME: Convert preload scripts CMakeConfig config = defaultConfiguration(k); const QStringList tmp diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp index 0d6430517bf..3e653c51405 100644 --- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp +++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp @@ -110,6 +110,7 @@ public: , m_executable(item->filePath()) , m_qchFile(item->qchFilePath()) , m_versionDisplay(item->versionDisplay()) + , m_detectionSource(item->detectionSource()) , m_isAutoRun(item->isAutoRun()) , m_autodetected(item->isAutoDetected()) , m_isSupported(item->hasFileApi()) @@ -145,9 +146,10 @@ public: cmake.setFilePath(m_executable); m_isSupported = cmake.hasFileApi(); - m_tooltip = tr("Version: %1
Supports fileApi: %2") - .arg(cmake.versionDisplay()) - .arg(cmake.hasFileApi() ? tr("yes") : tr("no")); + m_tooltip = tr("Version: %1").arg(cmake.versionDisplay()); + m_tooltip += "
" + tr("Supports fileApi: %1").arg(m_isSupported ? tr("yes") : tr("no")); + m_tooltip += "
" + tr("Detection source: \"%1\"").arg(m_detectionSource); + m_versionDisplay = cmake.versionDisplay(); } @@ -223,6 +225,7 @@ public: FilePath m_executable; FilePath m_qchFile; QString m_versionDisplay; + QString m_detectionSource; bool m_isAutoRun = true; bool m_pathExists = false; bool m_pathIsFile = false; @@ -362,6 +365,7 @@ void CMakeToolItemModel::apply() cmake->setDisplayName(item->m_name); cmake->setFilePath(item->m_executable); cmake->setQchFilePath(item->m_qchFile); + cmake->setDetectionSource(item->m_detectionSource); cmake->setAutorun(item->m_isAutoRun); } else { toRegister.append(item); @@ -375,6 +379,7 @@ void CMakeToolItemModel::apply() cmake->setDisplayName(item->m_name); cmake->setFilePath(item->m_executable); cmake->setQchFilePath(item->m_qchFile); + cmake->setDetectionSource(item->m_detectionSource); if (!CMakeToolManager::registerCMakeTool(std::move(cmake))) item->m_changed = true; } diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index cf9e83bf1ca..51daa1bb5f3 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -53,6 +53,7 @@ const char CMAKE_INFORMATION_QCH_FILE_PATH[] = "QchFile"; // obsolete since Qt Creator 5. Kept for backward compatibility const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory"; const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected"; +const char CMAKE_INFORMATION_DETECTIONSOURCE[] = "DetectionSource"; const char CMAKE_INFORMATION_READERTYPE[] = "ReaderType"; bool CMakeTool::Generator::matches(const QString &n, const QString &ex) const @@ -132,6 +133,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : //loading a CMakeTool from SDK is always autodetection if (!fromSdk) m_isAutoDetected = map.value(CMAKE_INFORMATION_AUTODETECTED, false).toBool(); + m_detectionSource = map.value(CMAKE_INFORMATION_DETECTIONSOURCE).toString(); setFilePath(FilePath::fromString(map.value(CMAKE_INFORMATION_COMMAND).toString())); @@ -209,6 +211,7 @@ QVariantMap CMakeTool::toMap() const data.insert(CMAKE_INFORMATION_READERTYPE, Internal::readerTypeToString(m_readerType.value())); data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected); + data.insert(CMAKE_INFORMATION_DETECTIONSOURCE, m_detectionSource); return data; } diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index 62b5c9964ce..c45fb7514db 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -122,6 +122,8 @@ private: void fetchFromCapabilities() const; void parseFromCapabilities(const QString &input) const; + // Note: New items here need also be handled in CMakeToolItemModel::apply() + // FIXME: Use a saner approach. Utils::Id m_id; QString m_displayName; Utils::FilePath m_executable; diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp index 348b1de7627..55b47891e4a 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp @@ -184,14 +184,14 @@ void CMakeToolManager::autoDetectCMakeForDevice(const FilePath &deviceRoot, const QString &detectionSource, QString *logMessage) { - QStringList messages; + QStringList messages{tr("Searching CMake binaries...")}; const FilePaths candidates = {FilePath::fromString("cmake").onDevice(deviceRoot)}; const Environment env = deviceRoot.deviceEnvironment(); for (const FilePath &candidate : candidates) { const FilePath cmake = candidate.searchOnDevice(env.path()); if (!cmake.isEmpty()) { registerCMakeByPath(cmake, detectionSource); - messages.append(tr("Found CMake binary: %1").arg(cmake.toUserOutput())); + messages.append(tr("Found \"%1\"").arg(cmake.toUserOutput())); } } if (logMessage) @@ -209,11 +209,28 @@ void CMakeToolManager::registerCMakeByPath(const FilePath &cmakePath, const QStr auto newTool = std::make_unique(CMakeTool::ManualDetection, id); newTool->setFilePath(cmakePath); - newTool->setDisplayName(cmakePath.toUserOutput()); newTool->setDetectionSource(detectionSource); + newTool->setDisplayName(cmakePath.toUserOutput()); registerCMakeTool(std::move(newTool)); } +void CMakeToolManager::removeDetectedCMake(const QString &detectionSource, QString *logMessage) +{ + QStringList logMessages{tr("Removing CMake entries...")}; + while (true) { + auto toRemove = Utils::take(d->m_cmakeTools, Utils::equal(&CMakeTool::detectionSource, detectionSource)); + if (!toRemove.has_value()) + break; + logMessages.append(tr("Removed \"%1\"").arg((*toRemove)->displayName())); + emit m_instance->cmakeRemoved((*toRemove)->id()); + } + + ensureDefaultCMakeToolIsValid(); + updateDocumentation(); + if (logMessage) + *logMessage = logMessages.join('\n'); +} + 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 9497192873d..3c3dfa8f84f 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h +++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h @@ -68,6 +68,7 @@ public slots: QString *logMessage); void registerCMakeByPath(const Utils::FilePath &cmakePath, const QString &detectionSource); + void removeDetectedCMake(const QString &detectionSource, QString *logMessage); signals: void cmakeAdded (const Utils::Id &id); diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index 33a04cf7c41..fd0bfd91178 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -92,7 +92,9 @@ public: QVariant registerDebugger(const DebuggerItem &item); void readDebuggers(const FilePath &fileName, bool isSystem); void autoDetectCdbDebuggers(); - void autoDetectGdbOrLldbDebuggers(const FilePath &deviceRoot, const QString &detectionSource); + void autoDetectGdbOrLldbDebuggers(const FilePath &deviceRoot, + const QString &detectionSource, + QString *logMessage = nullptr); void autoDetectUvscDebuggers(); QString uniqueDisplayName(const QString &base); @@ -715,7 +717,8 @@ static Utils::FilePaths searchGdbPathsFromRegistry() } void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers(const FilePath &deviceRoot, - const QString &detectionSource) + const QString &detectionSource, + QString *logMessage) { const QStringList filters = {"gdb-i686-pc-mingw32", "gdb-i686-pc-mingw32.exe", "gdb", "gdb.exe", "lldb", "lldb.exe", "lldb-[1-9]*", @@ -773,6 +776,7 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers(const FilePath &de suspects.append(device->directoryEntries(globalPath, filters, QDir::Files | QDir::Executable)); } + QStringList logMessages{tr("Searching debuggers...")}; for (const FilePath &command : qAsConst(suspects)) { const auto commandMatches = [command](const DebuggerTreeItem *titem) { return titem->m_item.command() == command; @@ -796,7 +800,10 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers(const FilePath &de const QString name = detectionSource.isEmpty() ? tr("System %1 at %2") : tr("Detected %1 at %2"); item.setUnexpandedDisplayName(name.arg(item.engineTypeName()).arg(command.toUserOutput())); m_model->addDebugger(item); + logMessages.append(tr("Found: \"%1\"").arg(name)); } + if (logMessage) + *logMessage = logMessages.join('\n'); } void DebuggerItemManagerPrivate::autoDetectUvscDebuggers() @@ -1030,9 +1037,31 @@ void DebuggerItemManager::deregisterDebugger(const QVariant &id) } void DebuggerItemManager::autoDetectDebuggersForDevice(const FilePath &deviceRoot, - const QString &detectionSource) + const QString &detectionSource, + QString *logMessage) { - d->autoDetectGdbOrLldbDebuggers(deviceRoot, detectionSource); + d->autoDetectGdbOrLldbDebuggers(deviceRoot, detectionSource, logMessage); +} + +void DebuggerItemManager::removeDetectedDebuggers(const QString &detectionSource, + QString *logMessage) +{ + QStringList logMessages{tr("Removing debugger entries...")}; + d->m_model->forItemsAtLevel<2>([detectionSource, &logMessages](DebuggerTreeItem *titem) { + if (titem->m_item.detectionSource() == detectionSource) { + logMessages.append(tr("Removed \"%1\"").arg(titem->m_item.displayName())); + d->m_model->destroyItem(titem); + return; + } + // FIXME: These items appeared in early docker development. Ok to remove for Creator 7.0. + FilePath filePath = titem->m_item.command(); + if (filePath.scheme() + ':' + filePath.host() == detectionSource) { + logMessages.append(tr("Removed \"%1\"").arg(titem->m_item.displayName())); + d->m_model->destroyItem(titem); + } + }); + if (logMessage) + *logMessage = logMessages.join('\n'); } } // namespace Debugger diff --git a/src/plugins/debugger/debuggeritemmanager.h b/src/plugins/debugger/debuggeritemmanager.h index 221ecf72bdb..e8d8cba42b1 100644 --- a/src/plugins/debugger/debuggeritemmanager.h +++ b/src/plugins/debugger/debuggeritemmanager.h @@ -53,7 +53,9 @@ public: static void deregisterDebugger(const QVariant &id); static void autoDetectDebuggersForDevice(const Utils::FilePath &deviceRoot, - const QString &detectionSource); + const QString &detectionSource, + QString *logMessage); + static void removeDetectedDebuggers(const QString &detectionSource, QString *logMessage); static const DebuggerItem *findByCommand(const Utils::FilePath &command); static const DebuggerItem *findById(const QVariant &id); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index e9a6c2d22ba..442fb2db24e 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -724,6 +724,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments) { qRegisterMetaType("ContextData"); qRegisterMetaType("DebuggerRunParameters"); + qRegisterMetaType(); // Menu groups ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING); @@ -1747,9 +1748,15 @@ void DebuggerPlugin::getEnginesState(QByteArray *json) const } void DebuggerPlugin::autoDetectDebuggersForDevice(const FilePath &deviceRoot, - const QString &detectionId) + const QString &detectionSource, + QString *logMessage) { - dd->m_debuggerItemManager.autoDetectDebuggersForDevice(deviceRoot, detectionId); + dd->m_debuggerItemManager.autoDetectDebuggersForDevice(deviceRoot, detectionSource, logMessage); +} + +void DebuggerPlugin::removeDetectedDebuggers(const QString &detectionSource, QString *logMessage) +{ + dd->m_debuggerItemManager.removeDetectedDebuggers(detectionSource, logMessage); } void DebuggerPluginPrivate::attachToQmlPort() diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h index 8ef79ed48fd..4d4efda0f38 100644 --- a/src/plugins/debugger/debuggerplugin.h +++ b/src/plugins/debugger/debuggerplugin.h @@ -59,10 +59,15 @@ private: Q_SLOT void getEnginesState(QByteArray *json) const; // Called from DockerDevice - Q_SLOT void autoDetectDebuggersForDevice(const Utils::FilePath &deviceRoot, const QString &detectionId); + Q_SLOT void autoDetectDebuggersForDevice(const Utils::FilePath &deviceRoot, + const QString &detectionId, + QString *logMessage); + Q_SLOT void removeDetectedDebuggers(const QString &detectionId, QString *logMessage); QVector createTestObjects() const override; }; } // namespace Internal } // namespace Debugger + +Q_DECLARE_METATYPE(QString *) diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 4f366fbe3fb..b533c67d335 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -471,26 +471,54 @@ DockerDeviceData &DockerDevice::data() void KitDetectorPrivate::undoAutoDetect() const { + emit q->logOutput(tr("Start removing auto-detected items associated with this docker image.")); + + emit q->logOutput('\n' + tr("Removing kits...")); for (Kit *kit : KitManager::kits()) { if (kit->autoDetectionSource() == m_sharedId) { - emit q->logOutput(tr("Removing kit: %1").arg(kit->displayName())); + emit q->logOutput(tr("Removed \"%1\"").arg(kit->displayName())); KitManager::deregisterKit(kit); } }; + + emit q->logOutput('\n' + tr("Removing Qt version entries...")); for (BaseQtVersion *qtVersion : QtVersionManager::versions()) { if (qtVersion->detectionSource() == m_sharedId) { - emit q->logOutput(tr("Removing Qt version: %1").arg(qtVersion->displayName())); + emit q->logOutput(tr("Removed \"%1\"").arg(qtVersion->displayName())); QtVersionManager::removeVersion(qtVersion); } }; - emit q->logOutput(tr("Tool chains not removed.")); - // for (ToolChain *toolChain : ToolChainManager::toolChains()) { - // if (toolChain->autoDetectionSource() == id.toString()) - // // FIXME: Implement - // }; + emit q->logOutput('\n' + tr("Removing toolchain entries...")); + for (ToolChain *toolChain : ToolChainManager::toolChains()) { + QString detectionSource = toolChain->detectionSource(); + if (toolChain->detectionSource() == m_sharedId) { + emit q->logOutput(tr("Removed \"%1\"").arg(toolChain->displayName())); + ToolChainManager::deregisterToolChain(toolChain); + } + }; - emit q->logOutput(tr("Removal of previously auto-detected kit items finished.") + '\n'); + if (QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager")) { + QString logMessage; + const bool res = QMetaObject::invokeMethod(cmakeManager, + "removeDetectedCMake", + Q_ARG(QString, m_sharedId), + Q_ARG(QString *, &logMessage)); + QTC_CHECK(res); + emit q->logOutput('\n' + logMessage); + } + + if (QObject *debuggerPlugin = ExtensionSystem::PluginManager::getObjectByName("DebuggerPlugin")) { + QString logMessage; + const bool res = QMetaObject::invokeMethod(debuggerPlugin, + "removeDetectedDebuggers", + Q_ARG(QString, m_sharedId), + Q_ARG(QString *, &logMessage)); + QTC_CHECK(res); + emit q->logOutput('\n' + logMessage); + } + + emit q->logOutput('\n' + tr("Removal of previously auto-detected kit items finished.") + "\n\n"); } QList KitDetectorPrivate::autoDetectQtVersions() const @@ -510,7 +538,7 @@ QList KitDetectorPrivate::autoDetectQtVersions() const continue; qtVersions.append(qtVersion); QtVersionManager::addVersion(qtVersion); - emit q->logOutput(tr("Found Qt: %1").arg(qtVersion->qmakeFilePath().toUserOutput())); + emit q->logOutput(tr("Found \"%1\"").arg(qtVersion->qmakeFilePath().toUserOutput())); } if (qtVersions.isEmpty()) emit q->logOutput(tr("No Qt installation found.")); @@ -521,21 +549,24 @@ QList KitDetectorPrivate::autoDetectToolChains() { const QList factories = ToolChainFactory::allToolChainFactories(); - QList toolChains; + QList alreadyKnown = ToolChainManager::toolChains(); + QList allNewToolChains; QApplication::processEvents(); - emit q->logOutput('\n' + tr("Searching tool chains...")); + emit q->logOutput('\n' + tr("Searching toolchains...")); for (ToolChainFactory *factory : factories) { - const QList newToolChains = factory->autoDetect(toolChains, m_device.constCast()); - emit q->logOutput(tr("Searching tool chains of type %1").arg(factory->displayName())); + emit q->logOutput(tr("Searching toolchains of type %1").arg(factory->displayName())); + const QList newToolChains = factory->autoDetect(alreadyKnown, m_device.constCast()); for (ToolChain *toolChain : newToolChains) { - emit q->logOutput(tr("Found tool chain: %1").arg(toolChain->compilerCommand().toUserOutput())); + emit q->logOutput(tr("Found \"%1\"").arg(toolChain->compilerCommand().toUserOutput())); + toolChain->setDetectionSource(m_sharedId); ToolChainManager::registerToolChain(toolChain); - toolChains.append(toolChain); + alreadyKnown.append(toolChain); } + allNewToolChains.append(newToolChains); } - emit q->logOutput(tr("%1 new tool chains found.").arg(toolChains.size())); + emit q->logOutput(tr("%1 new toolchains found.").arg(allNewToolChains.size())); - return toolChains; + return allNewToolChains; } void KitDetectorPrivate::autoDetectCMake() @@ -544,16 +575,15 @@ void KitDetectorPrivate::autoDetectCMake() if (!cmakeManager) return; - emit q->logOutput('\n' + tr("Searching CMake binary...")); const FilePath deviceRoot = m_device->mapToGlobalPath({}); - QString error; + QString logMessage; const bool res = QMetaObject::invokeMethod(cmakeManager, "autoDetectCMakeForDevice", Q_ARG(Utils::FilePath, deviceRoot), Q_ARG(QString, m_sharedId), - Q_ARG(QString *, &error)); + Q_ARG(QString *, &logMessage)); QTC_CHECK(res); - emit q->logOutput(error); + emit q->logOutput('\n' + logMessage); } void KitDetectorPrivate::autoDetectDebugger() @@ -562,13 +592,15 @@ void KitDetectorPrivate::autoDetectDebugger() if (!debuggerPlugin) return; - emit q->logOutput('\n' + tr("Searching debuggers...")); const FilePath deviceRoot = m_device->mapToGlobalPath({}); + QString logMessage; const bool res = QMetaObject::invokeMethod(debuggerPlugin, "autoDetectDebuggersForDevice", Q_ARG(Utils::FilePath, deviceRoot), - Q_ARG(QString, m_sharedId)); + Q_ARG(QString, m_sharedId), + Q_ARG(QString *, &logMessage)); QTC_CHECK(res); + emit q->logOutput('\n' + logMessage); } void KitDetectorPrivate::autoDetect()