Files
qt-creator/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp
Tobias Hunger 2a3cb8d7cb Qmake: Add variable chooser to build directory path chooser
Task-number: QTCREATORBUG-17160
Change-Id: I11974b04f1ab7f757fddb7a62bff787a977838ba
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
2016-10-25 08:10:04 +00:00

293 lines
11 KiB
C++

/****************************************************************************
**
** 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 "qmakeprojectconfigwidget.h"
#include "qmakeproject.h"
#include "qmakebuildconfiguration.h"
#include "qmakenodes.h"
#include "ui_qmakeprojectconfigwidget.h"
#include <coreplugin/coreicons.h>
#include <coreplugin/variablechooser.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/algorithm.h>
#include <utils/detailswidget.h>
#include <utils/utilsicons.h>
using namespace QmakeProjectManager;
using namespace QmakeProjectManager::Internal;
using namespace ProjectExplorer;
QmakeProjectConfigWidget::QmakeProjectConfigWidget(QmakeBuildConfiguration *bc)
: NamedWidget(),
m_buildConfiguration(bc)
{
m_defaultShadowBuildDir
= QmakeBuildConfiguration::shadowBuildDirectory(bc->target()->project()->projectFilePath().toString(),
bc->target()->kit(),
Utils::FileUtils::qmakeFriendlyName(bc->displayName()),
bc->buildType());
QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->setMargin(0);
m_detailsContainer = new Utils::DetailsWidget(this);
m_detailsContainer->setState(Utils::DetailsWidget::NoSummary);
vbox->addWidget(m_detailsContainer);
QWidget *details = new QWidget(m_detailsContainer);
m_detailsContainer->setWidget(details);
m_ui = new Ui::QmakeProjectConfigWidget();
m_ui->setupUi(details);
m_browseButton = m_ui->shadowBuildDirEdit->buttonAtIndex(0);
m_ui->warningLabel->setPixmap(Utils::Icons::WARNING.pixmap());
m_ui->shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory"));
m_ui->shadowBuildDirEdit->setExpectedKind(Utils::PathChooser::ExistingDirectory);
m_ui->shadowBuildDirEdit->setHistoryCompleter(QLatin1String("Qmake.BuildDir.History"));
m_ui->shadowBuildDirEdit->setEnvironment(bc->environment());
m_ui->shadowBuildDirEdit->setBaseFileName(bc->target()->project()->projectDirectory());
bool isShadowBuild = bc->isShadowBuild();
if (isShadowBuild) {
m_ui->shadowBuildDirEdit->setPath(bc->rawBuildDirectory().toString());
m_ui->inSourceBuildDirEdit->setVisible(false);
} else {
m_ui->shadowBuildDirEdit->setPath(m_defaultShadowBuildDir);
m_ui->shadowBuildDirEdit->setVisible(false);
}
m_ui->inSourceBuildDirEdit->setFileName(bc->target()->project()->projectDirectory());
m_ui->inSourceBuildDirEdit->setReadOnly(true);
m_ui->inSourceBuildDirEdit->setEnabled(false);
auto chooser = new Core::VariableChooser(this);
chooser->addSupportedWidget(m_ui->shadowBuildDirEdit->lineEdit());
m_ui->shadowBuildCheckBox->setChecked(isShadowBuild);
connect(m_ui->shadowBuildCheckBox, &QAbstractButton::clicked,
this, &QmakeProjectConfigWidget::shadowBuildClicked);
connect(m_ui->shadowBuildDirEdit, &Utils::PathChooser::beforeBrowsing,
this, &QmakeProjectConfigWidget::onBeforeBeforeShadowBuildDirBrowsed);
connect(m_ui->shadowBuildDirEdit, &Utils::PathChooser::rawPathChanged,
this, &QmakeProjectConfigWidget::shadowBuildEdited);
QmakeProject *project = static_cast<QmakeProject *>(bc->target()->project());
connect(project, &QmakeProject::environmentChanged,
this, &QmakeProjectConfigWidget::environmentChanged);
connect(project, &QmakeProject::buildDirectoryInitialized,
this, &QmakeProjectConfigWidget::updateProblemLabel);
connect(project, &QmakeProject::proFilesEvaluated,
this, &QmakeProjectConfigWidget::updateProblemLabel);
connect(bc->target(), &Target::kitChanged, this, &QmakeProjectConfigWidget::updateProblemLabel);
connect(m_buildConfiguration, &BuildConfiguration::buildDirectoryChanged,
this, &QmakeProjectConfigWidget::buildDirectoryChanged);
connect(m_buildConfiguration, &QmakeBuildConfiguration::qmakeBuildConfigurationChanged,
this, &QmakeProjectConfigWidget::updateProblemLabel);
setDisplayName(tr("General"));
updateDetails();
updateProblemLabel();
}
QmakeProjectConfigWidget::~QmakeProjectConfigWidget()
{
delete m_ui;
}
void QmakeProjectConfigWidget::updateDetails()
{
m_detailsContainer->setSummaryText(
tr("building in <b>%1</b>")
.arg(m_buildConfiguration->buildDirectory().toUserOutput()));
}
void QmakeProjectConfigWidget::setProblemLabel(const QString &text)
{
m_ui->warningLabel->setVisible(!text.isEmpty());
m_ui->problemLabel->setVisible(!text.isEmpty());
m_ui->problemLabel->setText(text);
}
void QmakeProjectConfigWidget::environmentChanged()
{
m_ui->shadowBuildDirEdit->setEnvironment(m_buildConfiguration->environment());
}
void QmakeProjectConfigWidget::buildDirectoryChanged()
{
if (m_ignoreChange)
return;
bool shadowBuild = m_ui->shadowBuildCheckBox->isChecked();
m_ui->inSourceBuildDirEdit->setVisible(!shadowBuild);
m_ui->shadowBuildDirEdit->setVisible(shadowBuild);
m_ui->shadowBuildDirEdit->setEnabled(shadowBuild);
m_browseButton->setEnabled(shadowBuild);
m_ui->shadowBuildDirEdit->setPath(m_buildConfiguration->rawBuildDirectory().toString());
updateDetails();
updateProblemLabel();
}
void QmakeProjectConfigWidget::onBeforeBeforeShadowBuildDirBrowsed()
{
Utils::FileName initialDirectory = m_buildConfiguration->target()->project()->projectDirectory();
if (!initialDirectory.isEmpty())
m_ui->shadowBuildDirEdit->setInitialBrowsePathBackup(initialDirectory.toString());
}
void QmakeProjectConfigWidget::shadowBuildClicked(bool checked)
{
m_ui->shadowBuildDirEdit->setEnabled(checked);
m_browseButton->setEnabled(checked);
m_ui->shadowBuildDirEdit->setVisible(checked);
m_ui->inSourceBuildDirEdit->setVisible(!checked);
m_ignoreChange = true;
if (checked)
m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_ui->shadowBuildDirEdit->rawPath()));
else
m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_ui->inSourceBuildDirEdit->rawPath()));
m_ignoreChange = false;
updateDetails();
updateProblemLabel();
}
void QmakeProjectConfigWidget::shadowBuildEdited()
{
if (m_buildConfiguration->rawBuildDirectory().toString() == m_ui->shadowBuildDirEdit->rawPath())
return;
m_ignoreChange = true;
m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_ui->shadowBuildDirEdit->rawPath()));
m_ignoreChange = false;
}
void QmakeProjectConfigWidget::updateProblemLabel()
{
m_ui->shadowBuildDirEdit->triggerChanged();
ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit();
const QString proFileName = m_buildConfiguration->target()->project()->projectFilePath().toString();
// Check for Qt version:
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
if (!version) {
setProblemLabel(tr("This kit cannot build this project since it does not define a Qt version."));
return;
}
QmakeProject *p = static_cast<QmakeProject *>(m_buildConfiguration->target()->project());
if (p->rootProjectNode()->parseInProgress() || !p->rootProjectNode()->validParse()) {
setProblemLabel(QString());
return;
}
bool targetMismatch = false;
bool incompatibleBuild = false;
bool allGood = false;
// we only show if we actually have a qmake and makestep
QString errorString;
if (m_buildConfiguration->qmakeStep() && m_buildConfiguration->makeStep()) {
QString makefile = m_buildConfiguration->buildDirectory().toString() + QLatin1Char('/');
if (m_buildConfiguration->makefile().isEmpty())
makefile.append(QLatin1String("Makefile"));
else
makefile.append(m_buildConfiguration->makefile());
switch (m_buildConfiguration->compareToImportFrom(makefile, &errorString)) {
case QmakeBuildConfiguration::MakefileMatches:
allGood = true;
break;
case QmakeBuildConfiguration::MakefileMissing:
allGood = true;
break;
case QmakeBuildConfiguration::MakefileIncompatible:
incompatibleBuild = true;
break;
case QmakeBuildConfiguration::MakefileForWrongProject:
targetMismatch = true;
break;
}
}
if (allGood) {
QString buildDirectory = m_buildConfiguration->target()->project()->projectDirectory().toString();
if (m_buildConfiguration->isShadowBuild())
buildDirectory = m_buildConfiguration->buildDirectory().toString();
QList<ProjectExplorer::Task> issues;
issues = version->reportIssues(proFileName, buildDirectory);
Utils::sort(issues);
if (!issues.isEmpty()) {
QString text = QLatin1String("<nobr>");
foreach (const ProjectExplorer::Task &task, issues) {
QString type;
switch (task.type) {
case ProjectExplorer::Task::Error:
type = tr("Error:");
type += QLatin1Char(' ');
break;
case ProjectExplorer::Task::Warning:
type = tr("Warning:");
type += QLatin1Char(' ');
break;
case ProjectExplorer::Task::Unknown:
default:
break;
}
if (!text.endsWith(QLatin1String("br>")))
text.append(QLatin1String("<br>"));
text.append(type + task.description);
}
setProblemLabel(text);
return;
}
} else if (targetMismatch) {
setProblemLabel(tr("A build for a different project exists in %1, which will be overwritten.",
"%1 build directory")
.arg(m_buildConfiguration->buildDirectory().toUserOutput()));
return;
} else if (incompatibleBuild) {
setProblemLabel(tr("%1 The build in %2 will be overwritten.",
"%1 error message, %2 build directory")
.arg(errorString)
.arg(m_buildConfiguration->buildDirectory().toUserOutput()));
return;
}
setProblemLabel(QString());
}