// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "debuggerrunconfigurationaspect.h" #include "debuggertr.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Debugger::Internal; using namespace ProjectExplorer; using namespace Utils; namespace Debugger { namespace Internal { enum DebuggerLanguageStatus { DisabledLanguage = 0, EnabledLanguage, AutoEnabledLanguage }; class DebuggerLanguageAspect : public BaseAspect { public: DebuggerLanguageAspect() = default; void addToLayout(Layouting::LayoutBuilder &builder) override; bool value() const; void setValue(bool val); void setAutoSettingsKey(const QString &settingsKey); void setLabel(const QString &label); void setInfoLabelText(const QString &text) { m_infoLabelText = text; } void setClickCallBack(const std::function &clickCallBack) { m_clickCallBack = clickCallBack; } void fromMap(const QVariantMap &map) override; void toMap(QVariantMap &map) const override; public: DebuggerLanguageStatus m_value = AutoEnabledLanguage; bool m_defaultValue = false; QString m_label; QString m_infoLabelText; QPointer m_checkBox; // Owned by configuration widget QPointer m_infoLabel; // Owned by configuration widget QString m_autoSettingsKey; std::function m_clickCallBack; }; void DebuggerLanguageAspect::addToLayout(Layouting::LayoutBuilder &builder) { QTC_CHECK(!m_checkBox); m_checkBox = new QCheckBox(m_label); m_checkBox->setChecked(m_value); m_checkBox->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); QTC_CHECK(m_clickCallBack); connect(m_checkBox, &QAbstractButton::clicked, this, m_clickCallBack, Qt::QueuedConnection); connect(m_checkBox.data(), &QAbstractButton::clicked, this, [this] { m_value = m_checkBox->isChecked() ? EnabledLanguage : DisabledLanguage; emit changed(); }); builder.addItem(QString()); builder.addItem(m_checkBox.data()); if (!m_infoLabelText.isEmpty()) { QTC_CHECK(!m_infoLabel); m_infoLabel = new QLabel(m_infoLabelText); connect(m_infoLabel, &QLabel::linkActivated, [](const QString &link) { Core::HelpManager::showHelpUrl(link); }); builder.addItem(m_infoLabel.data()); } } void DebuggerLanguageAspect::setAutoSettingsKey(const QString &settingsKey) { m_autoSettingsKey = settingsKey; } void DebuggerLanguageAspect::fromMap(const QVariantMap &map) { const bool val = map.value(settingsKey(), false).toBool(); const bool autoVal = map.value(m_autoSettingsKey, false).toBool(); m_value = autoVal ? AutoEnabledLanguage : val ? EnabledLanguage : DisabledLanguage; } void DebuggerLanguageAspect::toMap(QVariantMap &data) const { data.insert(settingsKey(), m_value == EnabledLanguage); data.insert(m_autoSettingsKey, m_value == AutoEnabledLanguage); } bool DebuggerLanguageAspect::value() const { return m_value; } void DebuggerLanguageAspect::setValue(bool value) { m_value = value ? EnabledLanguage : DisabledLanguage; if (m_checkBox) m_checkBox->setChecked(m_value); } void DebuggerLanguageAspect::setLabel(const QString &label) { m_label = label; } } // Internal /*! \class Debugger::DebuggerRunConfigurationAspect */ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target) : m_target(target) { setId("DebuggerAspect"); setDisplayName(Tr::tr("Debugger settings")); setConfigWidgetCreator([this] { Layouting::Form builder; builder.addRow(m_cppAspect); builder.addRow(m_qmlAspect); builder.addRow(m_overrideStartupAspect); static const QString env = qtcEnvironmentVariable("QTC_DEBUGGER_MULTIPROCESS"); if (env.toInt()) builder.addRow(m_multiProcessAspect); return builder.emerge(Layouting::WithoutMargins); }); addDataExtractor(this, &DebuggerRunConfigurationAspect::useCppDebugger, &Data::useCppDebugger); addDataExtractor(this, &DebuggerRunConfigurationAspect::useQmlDebugger, &Data::useQmlDebugger); addDataExtractor(this, &DebuggerRunConfigurationAspect::useMultiProcess, &Data::useMultiProcess); addDataExtractor(this, &DebuggerRunConfigurationAspect::overrideStartup, &Data::overrideStartup); m_cppAspect = new DebuggerLanguageAspect; m_cppAspect->setLabel(Tr::tr("Enable C++")); m_cppAspect->setSettingsKey("RunConfiguration.UseCppDebugger"); m_cppAspect->setAutoSettingsKey("RunConfiguration.UseCppDebuggerAuto"); m_qmlAspect = new DebuggerLanguageAspect; m_qmlAspect->setLabel(Tr::tr("Enable QML")); m_qmlAspect->setSettingsKey("RunConfiguration.UseQmlDebugger"); m_qmlAspect->setAutoSettingsKey("RunConfiguration.UseQmlDebuggerAuto"); m_qmlAspect->setInfoLabelText(Tr::tr("What are the prerequisites?")); // Make sure at least one of the debuggers is set to be active. m_cppAspect->setClickCallBack([this](bool on) { if (!on && !m_qmlAspect->value()) m_qmlAspect->setValue(true); }); m_qmlAspect->setClickCallBack([this](bool on) { if (!on && !m_cppAspect->value()) m_cppAspect->setValue(true); }); m_multiProcessAspect = new BoolAspect; m_multiProcessAspect->setSettingsKey("RunConfiguration.UseMultiProcess"); m_multiProcessAspect->setLabel(Tr::tr("Enable Debugging of Subprocesses"), BoolAspect::LabelPlacement::AtCheckBox); m_overrideStartupAspect = new StringAspect; m_overrideStartupAspect->setSettingsKey("RunConfiguration.OverrideDebuggerStartup"); m_overrideStartupAspect->setDisplayStyle(StringAspect::TextEditDisplay); m_overrideStartupAspect->setLabelText(Tr::tr("Additional startup commands:")); } DebuggerRunConfigurationAspect::~DebuggerRunConfigurationAspect() { delete m_cppAspect; delete m_qmlAspect; delete m_multiProcessAspect; delete m_overrideStartupAspect; } void DebuggerRunConfigurationAspect::setUseQmlDebugger(bool value) { m_qmlAspect->setValue(value); } bool DebuggerRunConfigurationAspect::useCppDebugger() const { if (m_cppAspect->m_value == AutoEnabledLanguage) return m_target->project()->projectLanguages().contains( ProjectExplorer::Constants::CXX_LANGUAGE_ID); return m_cppAspect->m_value == EnabledLanguage; } bool DebuggerRunConfigurationAspect::useQmlDebugger() const { if (m_qmlAspect->m_value == AutoEnabledLanguage) { const Core::Context languages = m_target->project()->projectLanguages(); if (!languages.contains(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID)) return false; // // 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; } return !languages.contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID); } return m_qmlAspect->m_value == EnabledLanguage; } bool DebuggerRunConfigurationAspect::useMultiProcess() const { return m_multiProcessAspect->value(); } void DebuggerRunConfigurationAspect::setUseMultiProcess(bool value) { m_multiProcessAspect->setValue(value); } QString DebuggerRunConfigurationAspect::overrideStartup() const { return m_overrideStartupAspect->value(); } int DebuggerRunConfigurationAspect::portsUsedByDebugger() const { int ports = 0; if (useQmlDebugger()) ++ports; if (useCppDebugger()) ++ports; return ports; } void DebuggerRunConfigurationAspect::toMap(QVariantMap &map) const { m_cppAspect->toMap(map); m_qmlAspect->toMap(map); m_multiProcessAspect->toMap(map); m_overrideStartupAspect->toMap(map); } void DebuggerRunConfigurationAspect::fromMap(const QVariantMap &map) { m_cppAspect->fromMap(map); m_qmlAspect->fromMap(map); m_multiProcessAspect->fromMap(map); m_overrideStartupAspect->fromMap(map); } } // namespace Debugger