From eb740bdd95a115873e63e8bf50c733c8b1d54a23 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 29 Nov 2023 15:08:48 +0100 Subject: [PATCH] Debugger: add python debugger setting in run configuration Change-Id: Ifa5d72566007e0bb006523433dcef97689677fbf Reviewed-by: hjk Reviewed-by: --- src/libs/utils/algorithm.h | 6 + src/plugins/debugger/debuggerconstants.h | 1 - src/plugins/debugger/debuggerengine.cpp | 18 +- src/plugins/debugger/debuggerengine.h | 5 +- src/plugins/debugger/debuggeritem.cpp | 4 - .../debuggerrunconfigurationaspect.cpp | 36 +++- .../debugger/debuggerrunconfigurationaspect.h | 3 + src/plugins/debugger/debuggerruncontrol.cpp | 183 ++++++++---------- src/plugins/debugger/debuggerruncontrol.h | 3 +- src/plugins/debugger/qml/qmlengine.cpp | 8 +- src/plugins/python/pythonbuildsystem.cpp | 7 + 11 files changed, 143 insertions(+), 131 deletions(-) diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index 551fed85ddb..26c0ff1b903 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -395,6 +395,12 @@ bool allOf(const T &container, F predicate) return std::all_of(std::begin(container), std::end(container), predicate); } +template +bool allOf(const std::initializer_list &initializerList, F predicate) +{ + return std::all_of(std::begin(initializerList), std::end(initializerList), predicate); +} + // allOf taking a member function pointer template bool allOf(const T &container, R (S::*predicate)() const) diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index b071713a844..d1f70644f6d 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -97,7 +97,6 @@ enum DebuggerEngineType NoEngineType = 0, GdbEngineType = 0x001, CdbEngineType = 0x004, - PdbEngineType = 0x008, LldbEngineType = 0x100, UvscEngineType = 0x1000 }; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 72bdb341a3e..1612f3751a0 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -267,8 +267,8 @@ public: connect(&settings().enableReverseDebugging, &BaseAspect::changed, this, [this] { updateState(); - if (m_companionEngine) - m_companionEngine->d->updateState(); + for (const QPointer &companion : std::as_const(m_companionEngines)) + companion->d->updateState(); }); static int contextCount = 0; m_context = Context(Id("Debugger.Engine.").withSuffix(++contextCount)); @@ -445,7 +445,7 @@ public: DebuggerRunParameters m_runParameters; IDevice::ConstPtr m_device; - QPointer m_companionEngine; + QList> m_companionEngines; bool m_isPrimaryEngine = true; // The current state. @@ -1134,9 +1134,9 @@ IDevice::ConstPtr DebuggerEngine::device() const return d->m_device; } -DebuggerEngine *DebuggerEngine::companionEngine() const +QList DebuggerEngine::companionEngines() const { - return d->m_companionEngine; + return Utils::transform(d->m_companionEngines, &QPointer::get); } DebuggerState DebuggerEngine::state() const @@ -1849,8 +1849,8 @@ void DebuggerEngine::setState(DebuggerState state, bool forced) showMessage(msg, LogDebug); d->updateState(); - if (d->m_companionEngine) - d->m_companionEngine->d->updateState(); + for (const QPointer &companion : std::as_const(d->m_companionEngines)) + companion->d->updateState(); if (oldState != d->m_state) emit EngineManager::instance()->engineStateChanged(this); @@ -2037,9 +2037,9 @@ void DebuggerEngine::progressPing() d->m_progress.setProgressValue(progress); } -void DebuggerEngine::setCompanionEngine(DebuggerEngine *engine) +void DebuggerEngine::addCompanionEngine(DebuggerEngine *engine) { - d->m_companionEngine = engine; + d->m_companionEngines << engine; } void DebuggerEngine::setSecondaryEngine() diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index aed61bbc2e4..dfb623b4bc5 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -149,6 +149,7 @@ public: QString version; bool isQmlDebugging = false; + bool isPythonDebugging = false; bool breakOnMain = false; bool multiProcess = false; // Whether to set detach-on-fork off. bool useTerminal = false; @@ -269,7 +270,7 @@ public: QString runId() const; const DebuggerRunParameters &runParameters() const; - void setCompanionEngine(DebuggerEngine *engine); + void addCompanionEngine(DebuggerEngine *engine); void setSecondaryEngine(); void start(); @@ -553,7 +554,7 @@ protected: void startDying() const; ProjectExplorer::IDeviceConstPtr device() const; - DebuggerEngine *companionEngine() const; + QList companionEngines() const; private: friend class DebuggerPluginPrivate; diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp index ba4a564a102..591b4bd38bc 100644 --- a/src/plugins/debugger/debuggeritem.cpp +++ b/src/plugins/debugger/debuggeritem.cpp @@ -243,10 +243,6 @@ void DebuggerItem::reinitializeFromFile(QString *error, Utils::Environment *cust m_version = output.section(' ', 2); return; } - if (output.startsWith("Python")) { - m_engineType = PdbEngineType; - return; - } if (error) *error = output; m_engineType = NoEngineType; diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp index 173b6b1a5e5..e5a8aeb5eb6 100644 --- a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp +++ b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp @@ -40,6 +40,12 @@ namespace Debugger { \class Debugger::DebuggerRunConfigurationAspect */ +static bool isDisabled(TriStateAspect *aspect) +{ + QTC_ASSERT(aspect, return false); + return aspect->value() == TriState::Disabled; +} + DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target) : m_target(target) { @@ -49,6 +55,7 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target) setConfigWidgetCreator([this] { Layouting::Grid builder; builder.addRow({m_cppAspect}); + builder.addRow({m_pythonAspect}); auto info = new QLabel( Tr::tr("setLabelText(Tr::tr("QML debugger:")); m_qmlAspect->setSettingsKey("RunConfiguration.UseQmlDebugger"); + m_pythonAspect = new TriStateAspect(nullptr, Tr::tr("Enabled"), Tr::tr("Disabled"), Tr::tr("Automatic")); + m_pythonAspect->setLabelText(Tr::tr("Python debugger:")); + m_pythonAspect->setSettingsKey("RunConfiguration.UsePythonDebugger"); + // Make sure at least one of the debuggers is set to be active. connect(m_cppAspect, &TriStateAspect::changed, this, [this]{ - if (m_cppAspect->value() == TriState::Disabled && m_qmlAspect->value() == TriState::Disabled) + if (Utils::allOf({m_cppAspect, m_qmlAspect, m_pythonAspect}, &isDisabled)) m_qmlAspect->setValue(TriState::Default); }); connect(m_qmlAspect, &TriStateAspect::changed, this, [this]{ - if (m_qmlAspect->value() == TriState::Disabled && m_cppAspect->value() == TriState::Disabled) + if (Utils::allOf({m_cppAspect, m_qmlAspect, m_pythonAspect}, &isDisabled)) + m_cppAspect->setValue(TriState::Default); + }); + connect(m_qmlAspect, &TriStateAspect::changed, this, [this] { + if (Utils::allOf({m_cppAspect, m_qmlAspect, m_pythonAspect}, &isDisabled)) m_cppAspect->setValue(TriState::Default); }); - m_multiProcessAspect = new BoolAspect; m_multiProcessAspect->setSettingsKey("RunConfiguration.UseMultiProcess"); @@ -177,8 +192,8 @@ bool DebuggerRunConfigurationAspect::useQmlDebugger() const // // Try to find a build configuration to check whether qml debugging is enabled there if (BuildConfiguration *bc = m_target->activeBuildConfiguration()) { - const auto aspect = bc->aspect(); - return aspect && aspect->value() == TriState::Enabled; + if (const auto aspect = bc->aspect()) + return aspect->value() == TriState::Enabled; } return !languages.contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID); @@ -186,6 +201,15 @@ bool DebuggerRunConfigurationAspect::useQmlDebugger() const return m_qmlAspect->value() == TriState::Enabled; } +bool DebuggerRunConfigurationAspect::usePythonDebugger() const +{ + if (m_pythonAspect->value() == TriState::Default) { + const Core::Context languages = m_target->project()->projectLanguages(); + return languages.contains(ProjectExplorer::Constants::PYTHON_LANGUAGE_ID); + } + return m_pythonAspect->value() == TriState::Enabled; +} + bool DebuggerRunConfigurationAspect::useMultiProcess() const { return m_multiProcessAspect->value(); @@ -215,6 +239,7 @@ void DebuggerRunConfigurationAspect::toMap(Store &map) const { m_cppAspect->toMap(map); m_qmlAspect->toMap(map); + m_pythonAspect->toMap(map); m_multiProcessAspect->toMap(map); m_overrideStartupAspect->toMap(map); @@ -227,6 +252,7 @@ void DebuggerRunConfigurationAspect::fromMap(const Store &map) { m_cppAspect->fromMap(map); m_qmlAspect->fromMap(map); + m_pythonAspect->fromMap(map); // respect old project settings if (map.value("RunConfiguration.UseCppDebuggerAuto", false).toBool()) diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.h b/src/plugins/debugger/debuggerrunconfigurationaspect.h index c6357cf4a31..16bcce9f5de 100644 --- a/src/plugins/debugger/debuggerrunconfigurationaspect.h +++ b/src/plugins/debugger/debuggerrunconfigurationaspect.h @@ -22,6 +22,7 @@ public: bool useCppDebugger() const; bool useQmlDebugger() const; + bool usePythonDebugger() const; void setUseQmlDebugger(bool value); bool useMultiProcess() const; void setUseMultiProcess(bool on); @@ -33,6 +34,7 @@ public: { bool useCppDebugger; bool useQmlDebugger; + bool usePythonDebugger; bool useMultiProcess; QString overrideStartup; }; @@ -40,6 +42,7 @@ public: private: Utils::TriStateAspect *m_cppAspect; Utils::TriStateAspect *m_qmlAspect; + Utils::TriStateAspect *m_pythonAspect; Utils::BoolAspect *m_multiProcessAspect; Utils::StringAspect *m_overrideStartupAspect; ProjectExplorer::Target *m_target; diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 5c67d0d138a..d43a7af990e 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -481,31 +481,27 @@ void DebuggerRunTool::start() runControl()->setDisplayName(m_runParameters.displayName); - if (!m_engine) - m_engine = createDapEngine(runControl()->runMode()); + if (auto dapEngine = createDapEngine(runControl()->runMode())) + m_engines << dapEngine; - if (!m_engine) { + if (m_engines.isEmpty()) { if (m_runParameters.isCppDebugging()) { switch (m_runParameters.cppEngineType) { case GdbEngineType: - m_engine = createGdbEngine(); + m_engines << createGdbEngine(); break; case CdbEngineType: if (!HostOsInfo::isWindowsHost()) { reportFailure(Tr::tr("Unsupported CDB host system.")); return; } - m_engine = createCdbEngine(); + m_engines << createCdbEngine(); break; case LldbEngineType: - m_engine = createLldbEngine(); - break; - case PdbEngineType: // FIXME: Yes, Python counts as C++... - QTC_CHECK(false); // Called from DebuggerRunTool constructor already. -// m_engine = createPdbEngine(); + m_engines << createLldbEngine(); break; case UvscEngineType: - m_engine = createUvscEngine(); + m_engines << createUvscEngine(); break; default: if (!m_runParameters.isQmlDebugging) { @@ -518,16 +514,14 @@ void DebuggerRunTool::start() } } - if (m_runParameters.isQmlDebugging) { - if (m_engine) { - m_engine2 = createQmlEngine(); - } else { - m_engine = createQmlEngine(); - } - } + if (m_runParameters.isPythonDebugging) + m_engines << createPdbEngine(); + + if (m_runParameters.isQmlDebugging) + m_engines << createQmlEngine(); } - if (!m_engine) { + if (m_engines.isEmpty()) { QString msg = noEngineMessage(); if (!DebuggerKitAspect::debugger(runControl()->kit())) msg += '\n' + noDebuggerInKitMessage(); @@ -535,55 +529,59 @@ void DebuggerRunTool::start() return; } - m_engine->setRunParameters(m_runParameters); - m_engine->setRunId(d->runId); - m_engine->setRunTool(this); - m_engine->setCompanionEngine(m_engine2); - auto rc = runControl(); - connect(m_engine, &DebuggerEngine::requestRunControlFinish, rc, [rc] { - rc->setAutoDeleteOnStop(true); - rc->initiateStop(); - }, Qt::QueuedConnection); - connect(m_engine, &DebuggerEngine::requestRunControlStop, rc, &RunControl::initiateStop); - connect(m_engine, &DebuggerEngine::engineStarted, - this, [this] { handleEngineStarted(m_engine); }); - connect(m_engine, &DebuggerEngine::engineFinished, - this, [this] { handleEngineFinished(m_engine); }); - connect(m_engine, &DebuggerEngine::appendMessageRequested, - this, &DebuggerRunTool::appendMessage); - ++d->engineStartsNeeded; - ++d->engineStopsNeeded; + if (auto interpreterAspect = runControl()->aspect()) { + if (auto mainScriptAspect = runControl()->aspect()) { + const FilePath mainScript = mainScriptAspect->filePath; + const FilePath interpreter = interpreterAspect->filePath; + if (!interpreter.isEmpty() && mainScript.endsWith(".py")) { + m_runParameters.mainScript = mainScript; + m_runParameters.interpreter = interpreter; + if (auto args = runControl()->aspect()) + m_runParameters.inferior.command.addArgs(args->arguments, CommandLine::Raw); + } + } + } - connect(m_engine, &DebuggerEngine::attachToCoreRequested, this, [this](const QString &coreFile) { - auto rc = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE); - rc->copyDataFromRunControl(runControl()); - auto name = QString(Tr::tr("%1 - Snapshot %2").arg(runControl()->displayName()).arg(++d->snapshotCounter)); - auto debugger = new DebuggerRunTool(rc); - debugger->setStartMode(AttachToCore); - debugger->setRunControlName(name); - debugger->setCoreFilePath(FilePath::fromString(coreFile), true); - debugger->startRunControl(); - }); - - if (m_engine2) { - m_engine2->setRunParameters(m_runParameters); - m_engine2->setRunId(d->runId); - m_engine2->setRunTool(this); - m_engine2->setCompanionEngine(m_engine); - m_engine2->setSecondaryEngine(); - connect(m_engine2, &DebuggerEngine::requestRunControlFinish, rc, [rc] { - rc->setAutoDeleteOnStop(true); - rc->initiateStop(); - }, Qt::QueuedConnection); - connect(m_engine2, &DebuggerEngine::requestRunControlStop, rc, &RunControl::initiateStop); - connect(m_engine2, &DebuggerEngine::engineStarted, - this, [this] { handleEngineStarted(m_engine2); }); - connect(m_engine2, &DebuggerEngine::engineFinished, - this, [this] { handleEngineFinished(m_engine2); }); - connect(m_engine2, &DebuggerEngine::appendMessageRequested, + bool first = true; + for (auto engine : m_engines) { + engine->setRunParameters(m_runParameters); + engine->setRunId(d->runId); + engine->setRunTool(this); + for (auto companion : m_engines) { + if (companion != engine) + engine->addCompanionEngine(companion); + } + if (!first) + engine->setSecondaryEngine(); + auto rc = runControl(); + connect(engine, &DebuggerEngine::requestRunControlFinish, rc, [rc] { + rc->setAutoDeleteOnStop(true); + rc->initiateStop(); + }, Qt::QueuedConnection); + connect(engine, &DebuggerEngine::requestRunControlStop, rc, &RunControl::initiateStop); + connect(engine, &DebuggerEngine::engineStarted, + this, [this, engine] { handleEngineStarted(engine); }); + connect(engine, &DebuggerEngine::engineFinished, + this, [this, engine] { handleEngineFinished(engine); }); + connect(engine, &DebuggerEngine::appendMessageRequested, this, &DebuggerRunTool::appendMessage); ++d->engineStartsNeeded; ++d->engineStopsNeeded; + + if (first) { + connect(engine, &DebuggerEngine::attachToCoreRequested, this, [this](const QString &coreFile) { + auto rc = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE); + rc->copyDataFromRunControl(runControl()); + auto name = QString(Tr::tr("%1 - Snapshot %2").arg(runControl()->displayName()).arg(++d->snapshotCounter)); + auto debugger = new DebuggerRunTool(rc); + debugger->setStartMode(AttachToCore); + debugger->setRunControlName(name); + debugger->setCoreFilePath(FilePath::fromString(coreFile), true); + debugger->startRunControl(); + }); + + first = false; + } } if (m_runParameters.startMode != AttachToCore) { @@ -593,10 +591,11 @@ void DebuggerRunTool::start() if (gbp->isEnabled()) { const BreakpointParameters &bp = gbp->requestedParameters(); hasQmlBreakpoints = hasQmlBreakpoints || bp.isQmlFileAndLineBreakpoint(); - if (!m_engine->acceptsBreakpoint(bp)) { - if (!m_engine2 || !m_engine2->acceptsBreakpoint(bp)) - unhandledIds.append(gbp->displayName()); - } + auto engineAcceptsBp = [bp](const DebuggerEngine *engine) { + return engine->acceptsBreakpoint(bp); + }; + if (!Utils::anyOf(m_engines, engineAcceptsBp)) + unhandledIds.append(gbp->displayName()); } } if (!unhandledIds.isEmpty()) { @@ -624,28 +623,22 @@ void DebuggerRunTool::start() appendMessage(Tr::tr("Debugging %1 ...").arg(m_runParameters.inferior.command.toUserOutput()), NormalMessageFormat); - QString debuggerName = m_engine->objectName(); - if (m_engine2) - debuggerName += ' ' + m_engine2->objectName(); + const QString debuggerName = Utils::transform(m_engines, &DebuggerEngine::objectName).join(" "); const QString message = Tr::tr("Starting debugger \"%1\" for ABI \"%2\"...") .arg(debuggerName).arg(m_runParameters.toolChainAbi.toString()); DebuggerMainWindow::showStatusMessage(message, 10000); - showMessage(m_engine->formatStartParameters(), LogDebug); + showMessage(m_engines.first()->formatStartParameters(), LogDebug); showMessage(DebuggerSettings::dump(), LogDebug); - if (m_engine2) - m_engine2->start(); - m_engine->start(); + Utils::reverseForeach(m_engines, [](DebuggerEngine *engine) { engine->start(); }); } void DebuggerRunTool::stop() { - QTC_ASSERT(m_engine, reportStopped(); return); - if (m_engine2) - m_engine2->quitDebugger(); - m_engine->quitDebugger(); + QTC_ASSERT(!m_engines.isEmpty(), reportStopped(); return); + Utils::reverseForeach(m_engines, [](DebuggerEngine *engine) { engine->quitDebugger(); }); } void DebuggerRunTool::handleEngineStarted(DebuggerEngine *engine) @@ -657,7 +650,7 @@ void DebuggerRunTool::handleEngineStarted(DebuggerEngine *engine) // } // Feels better, as the QML Engine might attach late or not at all. - if (engine == m_engine) { + if (engine == m_engines.first()) { EngineManager::activateDebugMode(); reportStarted(); } @@ -865,6 +858,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm if (!aspect->useCppDebugger) m_runParameters.cppEngineType = NoEngineType; m_runParameters.isQmlDebugging = aspect->useQmlDebugger; + m_runParameters.isPythonDebugging = aspect->usePythonDebugger; m_runParameters.multiProcess = aspect->useMultiProcess; m_runParameters.additionalStartupCommands = aspect->overrideStartup; @@ -907,22 +901,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm if (ok) m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride); - - if (auto interpreterAspect = runControl->aspect()) { - if (auto mainScriptAspect = runControl->aspect()) { - const FilePath mainScript = mainScriptAspect->filePath; - const FilePath interpreter = interpreterAspect->filePath; - if (!interpreter.isEmpty() && mainScript.endsWith(".py")) { - m_runParameters.mainScript = mainScript; - m_runParameters.interpreter = interpreter; - if (auto args = runControl->aspect()) - m_runParameters.inferior.command.addArgs(args->arguments, CommandLine::Raw); - if (runControl->runMode() == ProjectExplorer::Constants::DEBUG_RUN_MODE) - m_engine = createPdbEngine(); - } - } - } - if (QtSupport::QtVersion *baseQtVersion = QtSupport::QtKitAspect::qtVersion(kit)) { const QVersionNumber qtVersion = baseQtVersion->qtVersion(); m_runParameters.fallbackQtVersion = 0x10000 * qtVersion.majorVersion() @@ -948,10 +926,8 @@ DebuggerRunTool::~DebuggerRunTool() if (m_runParameters.isSnapshot && !m_runParameters.coreFile.isEmpty()) m_runParameters.coreFile.removeFile(); - delete m_engine2; - m_engine2 = nullptr; - delete m_engine; - m_engine = nullptr; + qDeleteAll(m_engines); + m_engines.clear(); delete d; } @@ -961,11 +937,10 @@ void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout) if (channel == ConsoleOutput) debuggerConsole()->printItem(ConsoleItem::DefaultType, msg); - QTC_ASSERT(m_engine, qDebug() << msg; return); + QTC_ASSERT(!m_engines.isEmpty(), qDebug() << msg; return); - m_engine->showMessage(msg, channel, timeout); - if (m_engine2) - m_engine->showMessage(msg, channel, timeout); + for (auto engine : m_engines) + engine->showMessage(msg, channel, timeout); switch (channel) { case AppOutput: appendMessage(msg, StdOutFormat); diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h index fdba73c83e2..49db615b09d 100644 --- a/src/plugins/debugger/debuggerruncontrol.h +++ b/src/plugins/debugger/debuggerruncontrol.h @@ -115,8 +115,7 @@ private: void handleEngineFinished(Internal::DebuggerEngine *engine); Internal::DebuggerRunToolPrivate *d; - QPointer m_engine; - QPointer m_engine2; + QList> m_engines; Internal::DebuggerRunParameters m_runParameters; }; diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 3f18b5f5fc8..7ba162a28f8 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -405,7 +405,9 @@ void QmlEngine::appStartupFailed(const QString &errorMessage) { QString error = Tr::tr("Could not connect to the in-process QML debugger. %1").arg(errorMessage); - if (companionEngine()) { + if (companionEngines().isEmpty()) { + debuggerConsole()->printItem(ConsoleItem::WarningType, error); + } else { auto infoBox = new QMessageBox(ICore::dialogParent()); infoBox->setIcon(QMessageBox::Critical); infoBox->setWindowTitle(QGuiApplication::applicationDisplayName()); @@ -415,8 +417,6 @@ void QmlEngine::appStartupFailed(const QString &errorMessage) connect(infoBox, &QDialog::finished, this, &QmlEngine::errorMessageBoxFinished); infoBox->show(); - } else { - debuggerConsole()->printItem(ConsoleItem::WarningType, error); } notifyEngineRunFailed(); @@ -1029,7 +1029,7 @@ bool QmlEngine::companionPreventsActions() const { // We need a C++ Engine in a Running state to do anything sensible // as otherwise the debugger services in the debuggee are unresponsive. - if (DebuggerEngine *companion = companionEngine()) + if (DebuggerEngine *companion = companionEngines().value(0)) return companion->state() != InferiorRunOk; return false; diff --git a/src/plugins/python/pythonbuildsystem.cpp b/src/plugins/python/pythonbuildsystem.cpp index 717395e6aa4..b2263811a25 100644 --- a/src/plugins/python/pythonbuildsystem.cpp +++ b/src/plugins/python/pythonbuildsystem.cpp @@ -13,6 +13,7 @@ #include #include +#include #include @@ -186,10 +187,14 @@ void PythonBuildSystem::triggerParsing() newRoot->addNestedNode( std::make_unique(projectFile, displayName, FileType::Project)); + bool hasQmlFiles = false; + for (const FileEntry &entry : std::as_const(m_files)) { const QString displayName = entry.filePath.relativePathFrom(projectDirectory()).toUserOutput(); const FileType fileType = getFileType(entry.filePath); + hasQmlFiles |= fileType == FileType::QML; + newRoot->addNestedNode(std::make_unique(entry.filePath, displayName, fileType)); const MimeType mt = mimeTypeForFile(entry.filePath, MimeMatchMode::MatchExtension); if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE) @@ -204,6 +209,8 @@ void PythonBuildSystem::triggerParsing() appTargets.append(bti); } } + project()->setProjectLanguage(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID, hasQmlFiles); + setRootProjectNode(std::move(newRoot)); setApplicationTargets(appTargets);