/**************************************************************************** ** ** 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 "qbsrunconfiguration.h" #include "qbsprojectmanagerconstants.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ProjectExplorer; using namespace Utils; namespace QbsProjectManager { namespace Internal { const char QBS_RC_PREFIX[] = "Qbs.RunConfiguration:"; static QString rcNameSeparator() { return QLatin1String("---Qbs.RC.NameSeparator---"); } static QString usingLibraryPathsKey() { return QString("Qbs.RunConfiguration.UsingLibraryPaths"); } // -------------------------------------------------------------------- // QbsRunConfiguration: // -------------------------------------------------------------------- QbsRunConfiguration::QbsRunConfiguration(Target *target) : RunConfiguration(target, QBS_RC_PREFIX) { auto envAspect = new LocalEnvironmentAspect(this, [](RunConfiguration *rc, Environment &env) { static_cast(rc)->addToBaseEnvironment(env); }); addExtraAspect(envAspect); connect(project(), &Project::parsingFinished, this, [envAspect]() { envAspect->buildEnvironmentHasChanged(); }); addExtraAspect(new ArgumentsAspect(this, "Qbs.RunConfiguration.CommandLineArguments")); addExtraAspect(new WorkingDirectoryAspect(this, "Qbs.RunConfiguration.WorkingDirectory")); addExtraAspect(new TerminalAspect(this, "Qbs.RunConfiguration.UseTerminal", isConsoleApplication())); connect(project(), &Project::parsingFinished, this, [this](bool success) { auto terminalAspect = extraAspect(); if (success && !terminalAspect->isUserSet()) terminalAspect->setUseTerminal(isConsoleApplication()); }); connect(BuildManager::instance(), &BuildManager::buildStateChanged, this, [this](Project *p) { if (p == project() && !BuildManager::isBuilding(p)) { const QString defaultWorkingDir = baseWorkingDirectory(); if (!defaultWorkingDir.isEmpty()) { extraAspect()->setDefaultWorkingDirectory( Utils::FileName::fromString(defaultWorkingDir)); } emit enabledChanged(); } } ); connect(target, &Target::deploymentDataChanged, this, &QbsRunConfiguration::handleBuildSystemDataUpdated); connect(target, &Target::applicationTargetsChanged, this, &QbsRunConfiguration::handleBuildSystemDataUpdated); // Handles device changes, etc. connect(target, &Target::kitChanged, this, &QbsRunConfiguration::handleBuildSystemDataUpdated); } QbsRunConfiguration::~QbsRunConfiguration() { } QVariantMap QbsRunConfiguration::toMap() const { QVariantMap map = RunConfiguration::toMap(); map.insert(usingLibraryPathsKey(), usingLibraryPaths()); return map; } bool QbsRunConfiguration::fromMap(const QVariantMap &map) { if (!RunConfiguration::fromMap(map)) return false; m_buildKey = ProjectExplorer::idFromMap(map).suffixAfter(id()); m_usingLibraryPaths = map.value(usingLibraryPathsKey(), true).toBool(); const int sepPos = m_buildKey.indexOf(rcNameSeparator()); m_productDisplayName = sepPos == -1 ? QString() : m_buildKey.mid(sepPos + rcNameSeparator().size()); m_uniqueProductName = m_buildKey.left(sepPos); setDefaultDisplayName(defaultDisplayName()); return true; } QString QbsRunConfiguration::extraId() const { return m_uniqueProductName + rcNameSeparator() + m_productDisplayName; } void QbsRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo &rci) { m_buildKey = rci.buildKey; const int sepPos = m_buildKey.indexOf(rcNameSeparator()); m_productDisplayName = sepPos == -1 ? QString() : m_buildKey.mid(sepPos + rcNameSeparator().size()); m_uniqueProductName = m_buildKey.left(sepPos); setDefaultDisplayName(defaultDisplayName()); } QWidget *QbsRunConfiguration::createConfigurationWidget() { return new QbsRunConfigurationWidget(this); } Runnable QbsRunConfiguration::runnable() const { StandardRunnable r; r.executable = executable(); r.workingDirectory = extraAspect()->workingDirectory().toString(); r.commandLineArguments = extraAspect()->arguments(); r.runMode = extraAspect()->runMode(); r.environment = extraAspect()->environment(); return r; } QString QbsRunConfiguration::executable() const { BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(m_buildKey); return bti.targetFilePath.toString(); } bool QbsRunConfiguration::isConsoleApplication() const { BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(m_buildKey); return bti.usesTerminal; } void QbsRunConfiguration::setUsingLibraryPaths(bool useLibPaths) { m_usingLibraryPaths = useLibPaths; extraAspect()->environmentChanged(); } QString QbsRunConfiguration::baseWorkingDirectory() const { const QString exe = executable(); if (!exe.isEmpty()) return QFileInfo(exe).absolutePath(); return QString(); } void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const { BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(m_buildKey); if (bti.runEnvModifier) bti.runEnvModifier(env, m_usingLibraryPaths); } QString QbsRunConfiguration::buildSystemTarget() const { return m_buildKey; } QString QbsRunConfiguration::uniqueProductName() const { return m_uniqueProductName; } QString QbsRunConfiguration::defaultDisplayName() { QString defaultName = m_productDisplayName; if (defaultName.isEmpty()) defaultName = tr("Qbs Run Configuration"); return defaultName; } Utils::OutputFormatter *QbsRunConfiguration::createOutputFormatter() const { return new QtSupport::QtOutputFormatter(target()->project()); } void QbsRunConfiguration::handleBuildSystemDataUpdated() { emit targetInformationChanged(); emit enabledChanged(); } // -------------------------------------------------------------------- // QbsRunConfigurationWidget: // -------------------------------------------------------------------- class QbsRunConfigurationWidgetPrivate { public: QbsRunConfiguration *runConfiguration = nullptr; QLabel *executableLineLabel = nullptr; }; QbsRunConfigurationWidget::QbsRunConfigurationWidget(QbsRunConfiguration *rc) : d(new QbsRunConfigurationWidgetPrivate) { d->runConfiguration = rc; auto mainLayout = new QVBoxLayout(this); mainLayout->setMargin(0); auto detailsContainer = new Utils::DetailsWidget(this); detailsContainer->setState(Utils::DetailsWidget::NoSummary); mainLayout->addWidget(detailsContainer); auto detailsWidget = new QWidget(detailsContainer); detailsContainer->setWidget(detailsWidget); auto toplayout = new QFormLayout(detailsWidget); toplayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); toplayout->setMargin(0); d->executableLineLabel = new QLabel(this); d->executableLineLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); toplayout->addRow(tr("Executable:"), d->executableLineLabel); d->runConfiguration->extraAspect()->addToMainConfigurationWidget(this, toplayout); d->runConfiguration->extraAspect()->addToMainConfigurationWidget(this, toplayout); d->runConfiguration->extraAspect()->addToMainConfigurationWidget(this, toplayout); auto usingLibPathsCheckBox = new QCheckBox(tr("Add library paths to run environment")); usingLibPathsCheckBox->setChecked(d->runConfiguration->usingLibraryPaths()); connect(usingLibPathsCheckBox, &QCheckBox::toggled, d->runConfiguration, &QbsRunConfiguration::setUsingLibraryPaths); toplayout->addRow(QString(), usingLibPathsCheckBox); connect(d->runConfiguration, &QbsRunConfiguration::targetInformationChanged, this, &QbsRunConfigurationWidget::targetInformationHasChanged, Qt::QueuedConnection); connect(d->runConfiguration, &RunConfiguration::enabledChanged, this, &QbsRunConfigurationWidget::targetInformationHasChanged); Core::VariableChooser::addSupportForChildWidgets(this, rc->macroExpander()); targetInformationHasChanged(); } void QbsRunConfigurationWidget::targetInformationHasChanged() { WorkingDirectoryAspect *aspect = d->runConfiguration->extraAspect(); aspect->pathChooser()->setBaseFileName(d->runConfiguration->target()->project()->projectDirectory()); QString text = d->runConfiguration->executable(); d->executableLineLabel->setText(text.isEmpty() ? tr("") : text); } QbsRunConfigurationWidget::~QbsRunConfigurationWidget() { delete d; } // -------------------------------------------------------------------- // QbsRunConfigurationFactory: // -------------------------------------------------------------------- QbsRunConfigurationFactory::QbsRunConfigurationFactory() { registerRunConfiguration(QBS_RC_PREFIX); addSupportedProjectType(Constants::PROJECT_ID); addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE); } } // namespace Internal } // namespace QbsProjectManager