ProjectExplorer: Introduce BuildDirectoryAspect

Change-Id: Id57d0a7901d2cec7b2d4f1fbeed6a1ecb41642cc
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2019-11-25 17:55:39 +01:00
parent 684d3e40a7
commit dd7f4890a2
6 changed files with 184 additions and 18 deletions

View File

@@ -25,8 +25,108 @@
#include "buildaspects.h" #include "buildaspects.h"
#include <utils/fileutils.h>
#include <utils/utilsicons.h>
#include <QLabel>
#include <QLayout>
using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
class BuildDirectoryAspect::Private
{
public:
FilePath sourceDir;
FilePath savedShadowBuildDir;
QString problem;
QPointer<QLabel> warningLabel;
QPointer<QLabel> problemLabel;
};
BuildDirectoryAspect::BuildDirectoryAspect() : d(new Private)
{
setSettingsKey("ProjectExplorer.BuildConfiguration.BuildDirectory");
setLabelText(tr("Build directory:"));
setDisplayStyle(PathChooserDisplay);
setExpectedKind(Utils::PathChooser::Directory);
setUncheckedSemantics(UncheckedSemantics::ReadOnly);
}
BuildDirectoryAspect::~BuildDirectoryAspect()
{
delete d;
}
void BuildDirectoryAspect::allowInSourceBuilds(const FilePath &sourceDir)
{
d->sourceDir = sourceDir;
makeCheckable(tr("Shadow Build"), QString());
}
bool BuildDirectoryAspect::isShadowBuild() const
{
return !d->sourceDir.isEmpty() && d->sourceDir != filePath();
}
void BuildDirectoryAspect::setProblem(const QString &description)
{
d->problem = description;
updateProblemLabel();
}
void BuildDirectoryAspect::toMap(QVariantMap &map) const
{
BaseStringAspect::toMap(map);
if (!d->sourceDir.isEmpty()) {
const FilePath shadowDir = isChecked() ? filePath() : d->savedShadowBuildDir;
map.insert(settingsKey() + ".shadowDir", shadowDir.toString());
}
}
void BuildDirectoryAspect::fromMap(const QVariantMap &map)
{
BaseStringAspect::fromMap(map);
if (!d->sourceDir.isEmpty()) {
d->savedShadowBuildDir = FilePath::fromString(map.value(settingsKey() + ".shadowDir")
.toString());
setChecked(d->sourceDir != filePath());
}
}
void BuildDirectoryAspect::addToLayout(LayoutBuilder &builder)
{
BaseStringAspect::addToLayout(builder);
d->warningLabel = new QLabel;
d->warningLabel->setAlignment(Qt::AlignTop);
d->warningLabel->setPixmap(Icons::WARNING.pixmap());
d->problemLabel = new QLabel;
d->problemLabel->setAlignment(Qt::AlignTop);
builder.startNewRow().addItems(QString(), d->warningLabel.data(), d->problemLabel.data());
updateProblemLabel();
if (!d->sourceDir.isEmpty()) {
connect(this, &BaseStringAspect::checkedChanged, builder.layout(), [this] {
if (isChecked()) {
setFilePath(d->savedShadowBuildDir);
} else {
d->savedShadowBuildDir = filePath();
setFilePath(d->sourceDir);
}
});
}
}
void BuildDirectoryAspect::updateProblemLabel()
{
if (!d->warningLabel)
return;
QTC_ASSERT(d->problemLabel, return);
d->problemLabel->setText(d->problem);
d->problemLabel->setVisible(!d->problem.isEmpty());
d->warningLabel->setVisible(!d->problem.isEmpty());
}
SeparateDebugInfoAspect::SeparateDebugInfoAspect() SeparateDebugInfoAspect::SeparateDebugInfoAspect()
{ {
setDisplayName(tr("Separate Debug Info")); setDisplayName(tr("Separate Debug Info"));

View File

@@ -28,8 +28,32 @@
#include "projectexplorer_export.h" #include "projectexplorer_export.h"
#include "projectconfigurationaspects.h" #include "projectconfigurationaspects.h"
namespace Utils { class FilePath; }
namespace ProjectExplorer { namespace ProjectExplorer {
class PROJECTEXPLORER_EXPORT BuildDirectoryAspect : public BaseStringAspect
{
Q_OBJECT
public:
BuildDirectoryAspect();
~BuildDirectoryAspect() override;
void allowInSourceBuilds(const Utils::FilePath &sourceDir);
bool isShadowBuild() const;
void setProblem(const QString &description);
private:
void toMap(QVariantMap &map) const override;
void fromMap(const QVariantMap &map) override;
void addToLayout(LayoutBuilder &builder) override;
void updateProblemLabel();
class Private;
Private * const d;
};
class PROJECTEXPLORER_EXPORT SeparateDebugInfoAspect : public BaseTriStateAspect class PROJECTEXPLORER_EXPORT SeparateDebugInfoAspect : public BaseTriStateAspect
{ {
Q_OBJECT Q_OBJECT

View File

@@ -25,6 +25,7 @@
#include "buildconfiguration.h" #include "buildconfiguration.h"
#include "buildaspects.h"
#include "buildenvironmentwidget.h" #include "buildenvironmentwidget.h"
#include "buildinfo.h" #include "buildinfo.h"
#include "buildsteplist.h" #include "buildsteplist.h"
@@ -35,7 +36,6 @@
#include "kitinformation.h" #include "kitinformation.h"
#include "kitmanager.h" #include "kitmanager.h"
#include "project.h" #include "project.h"
#include "projectconfigurationaspects.h"
#include "projectexplorer.h" #include "projectexplorer.h"
#include "projectexplorerconstants.h" #include "projectexplorerconstants.h"
#include "projectmacroexpander.h" #include "projectmacroexpander.h"
@@ -44,6 +44,7 @@
#include "session.h" #include "session.h"
#include <coreplugin/idocument.h> #include <coreplugin/idocument.h>
#include <coreplugin/variablechooser.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/detailswidget.h> #include <utils/detailswidget.h>
@@ -61,7 +62,6 @@ static const char BUILD_STEP_LIST_COUNT[] = "ProjectExplorer.BuildConfiguration.
static const char BUILD_STEP_LIST_PREFIX[] = "ProjectExplorer.BuildConfiguration.BuildStepList."; static const char BUILD_STEP_LIST_PREFIX[] = "ProjectExplorer.BuildConfiguration.BuildStepList.";
static const char CLEAR_SYSTEM_ENVIRONMENT_KEY[] = "ProjectExplorer.BuildConfiguration.ClearSystemEnvironment"; static const char CLEAR_SYSTEM_ENVIRONMENT_KEY[] = "ProjectExplorer.BuildConfiguration.ClearSystemEnvironment";
static const char USER_ENVIRONMENT_CHANGES_KEY[] = "ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"; static const char USER_ENVIRONMENT_CHANGES_KEY[] = "ProjectExplorer.BuildConfiguration.UserEnvironmentChanges";
static const char BUILDDIRECTORY_KEY[] = "ProjectExplorer.BuildConfiguration.BuildDirectory";
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
@@ -72,7 +72,7 @@ public:
bool m_clearSystemEnvironment = false; bool m_clearSystemEnvironment = false;
Utils::EnvironmentItems m_userEnvironmentChanges; Utils::EnvironmentItems m_userEnvironmentChanges;
QList<BuildStepList *> m_stepLists; QList<BuildStepList *> m_stepLists;
ProjectExplorer::BaseStringAspect *m_buildDirectoryAspect = nullptr; BuildDirectoryAspect *m_buildDirectoryAspect = nullptr;
Utils::FilePath m_lastEmittedBuildDirectory; Utils::FilePath m_lastEmittedBuildDirectory;
mutable Utils::Environment m_cachedEnvironment; mutable Utils::Environment m_cachedEnvironment;
QString m_configWidgetDisplayName; QString m_configWidgetDisplayName;
@@ -116,16 +116,12 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged, connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &BuildConfiguration::updateCacheAndEmitEnvironmentChanged); this, &BuildConfiguration::updateCacheAndEmitEnvironmentChanged);
d->m_buildDirectoryAspect = addAspect<BaseStringAspect>(); d->m_buildDirectoryAspect = addAspect<BuildDirectoryAspect>();
d->m_buildDirectoryAspect->setSettingsKey(BUILDDIRECTORY_KEY);
d->m_buildDirectoryAspect->setLabelText(tr("Build directory:"));
d->m_buildDirectoryAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
d->m_buildDirectoryAspect->setExpectedKind(Utils::PathChooser::Directory);
d->m_buildDirectoryAspect->setBaseFileName(target->project()->projectDirectory()); d->m_buildDirectoryAspect->setBaseFileName(target->project()->projectDirectory());
d->m_buildDirectoryAspect->setEnvironment(environment()); d->m_buildDirectoryAspect->setEnvironment(environment());
d->m_buildDirectoryAspect->setMacroExpanderProvider([this] { return macroExpander(); });
connect(d->m_buildDirectoryAspect, &BaseStringAspect::changed, connect(d->m_buildDirectoryAspect, &BaseStringAspect::changed,
this, &BuildConfiguration::buildDirectoryChanged); this, &BuildConfiguration::buildDirectoryChanged);
connect(this, &BuildConfiguration::environmentChanged, this, [this] { connect(this, &BuildConfiguration::environmentChanged, this, [this] {
d->m_buildDirectoryAspect->setEnvironment(environment()); d->m_buildDirectoryAspect->setEnvironment(environment());
this->target()->buildEnvironmentChanged(this); this->target()->buildEnvironmentChanged(this);
@@ -133,7 +129,6 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
connect(target, &Target::parsingStarted, this, &BuildConfiguration::enabledChanged); connect(target, &Target::parsingStarted, this, &BuildConfiguration::enabledChanged);
connect(target, &Target::parsingFinished, this, &BuildConfiguration::enabledChanged); connect(target, &Target::parsingFinished, this, &BuildConfiguration::enabledChanged);
connect(this, &BuildConfiguration::enabledChanged, this, [this] { connect(this, &BuildConfiguration::enabledChanged, this, [this] {
if (isActive() && project() == SessionManager::startupProject()) { if (isActive() && project() == SessionManager::startupProject()) {
ProjectExplorerPlugin::updateActions(); ProjectExplorerPlugin::updateActions();
@@ -309,7 +304,7 @@ QVariant BuildConfiguration::extraInfo() const
return d->m_extraInfo; return d->m_extraInfo;
} }
ProjectExplorer::BaseStringAspect *BuildConfiguration::buildDirectoryAspect() const ProjectExplorer::BuildDirectoryAspect *BuildConfiguration::buildDirectoryAspect() const
{ {
return d->m_buildDirectoryAspect; return d->m_buildDirectoryAspect;
} }

View File

@@ -36,7 +36,7 @@ namespace ProjectExplorer {
namespace Internal { class BuildConfigurationPrivate; } namespace Internal { class BuildConfigurationPrivate; }
class BaseStringAspect; class BuildDirectoryAspect;
class BuildInfo; class BuildInfo;
class BuildSystem; class BuildSystem;
class BuildStepList; class BuildStepList;
@@ -107,7 +107,7 @@ public:
static void prependCompilerPathToEnvironment(Kit *k, Utils::Environment &env); static void prependCompilerPathToEnvironment(Kit *k, Utils::Environment &env);
void updateCacheAndEmitEnvironmentChanged(); void updateCacheAndEmitEnvironmentChanged();
ProjectExplorer::BaseStringAspect *buildDirectoryAspect() const; ProjectExplorer::BuildDirectoryAspect *buildDirectoryAspect() const;
void setConfigWidgetDisplayName(const QString &display); void setConfigWidgetDisplayName(const QString &display);
void setBuildDirectoryHistoryCompleter(const QString &history); void setBuildDirectoryHistoryCompleter(const QString &history);
void setConfigWidgetHasFrame(bool configWidgetHasFrame); void setConfigWidgetHasFrame(bool configWidgetHasFrame);

View File

@@ -32,6 +32,7 @@
#include "runconfiguration.h" #include "runconfiguration.h"
#include "target.h" #include "target.h"
#include <coreplugin/variablechooser.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <utils/fancylineedit.h> #include <utils/fancylineedit.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
@@ -84,6 +85,8 @@ class BaseStringAspectPrivate
{ {
public: public:
BaseStringAspect::DisplayStyle m_displayStyle = BaseStringAspect::LabelDisplay; BaseStringAspect::DisplayStyle m_displayStyle = BaseStringAspect::LabelDisplay;
BaseStringAspect::UncheckedSemantics m_uncheckedSemantics
= BaseStringAspect::UncheckedSemantics::ReadOnly;
QString m_labelText; QString m_labelText;
std::function<QString(const QString &)> m_displayFilter; std::function<QString(const QString &)> m_displayFilter;
std::unique_ptr<BaseBoolAspect> m_checker; std::unique_ptr<BaseBoolAspect> m_checker;
@@ -98,10 +101,20 @@ public:
QPointer<FancyLineEdit> m_lineEditDisplay; QPointer<FancyLineEdit> m_lineEditDisplay;
QPointer<PathChooser> m_pathChooserDisplay; QPointer<PathChooser> m_pathChooserDisplay;
QPointer<QTextEdit> m_textEditDisplay; QPointer<QTextEdit> m_textEditDisplay;
Utils::MacroExpanderProvider m_expanderProvider;
QPixmap m_labelPixmap; QPixmap m_labelPixmap;
Utils::FilePath m_baseFileName; Utils::FilePath m_baseFileName;
bool m_readOnly = false; bool m_readOnly = false;
bool m_showToolTipOnLabel = false; bool m_showToolTipOnLabel = false;
template<class Widget> void updateWidgetFromCheckStatus(Widget *w)
{
const bool enabled = !m_checker || m_checker->value();
if (m_uncheckedSemantics == BaseStringAspect::UncheckedSemantics::Disabled)
w->setEnabled(enabled);
else
w->setReadOnly(!enabled);
}
}; };
class BaseIntegerAspectPrivate class BaseIntegerAspectPrivate
@@ -205,6 +218,12 @@ bool BaseStringAspect::isChecked() const
return !d->m_checker || d->m_checker->value(); return !d->m_checker || d->m_checker->value();
} }
void BaseStringAspect::setChecked(bool checked)
{
QTC_ASSERT(d->m_checker, return);
d->m_checker->setValue(checked);
}
void BaseStringAspect::setDisplayStyle(DisplayStyle displayStyle) void BaseStringAspect::setDisplayStyle(DisplayStyle displayStyle)
{ {
d->m_displayStyle = displayStyle; d->m_displayStyle = displayStyle;
@@ -260,6 +279,16 @@ void BaseStringAspect::setReadOnly(bool readOnly)
d->m_textEditDisplay->setReadOnly(readOnly); d->m_textEditDisplay->setReadOnly(readOnly);
} }
void BaseStringAspect::setMacroExpanderProvider(const MacroExpanderProvider &expanderProvider)
{
d->m_expanderProvider = expanderProvider;
}
void BaseStringAspect::setUncheckedSemantics(BaseStringAspect::UncheckedSemantics semantics)
{
d->m_uncheckedSemantics = semantics;
}
void BaseStringAspect::addToLayout(LayoutBuilder &builder) void BaseStringAspect::addToLayout(LayoutBuilder &builder)
{ {
QTC_CHECK(!d->m_label); QTC_CHECK(!d->m_label);
@@ -270,6 +299,14 @@ void BaseStringAspect::addToLayout(LayoutBuilder &builder)
d->m_label->setPixmap(d->m_labelPixmap); d->m_label->setPixmap(d->m_labelPixmap);
builder.addItem(d->m_label.data()); builder.addItem(d->m_label.data());
const auto useMacroExpander = [this, &builder](QWidget *w) {
if (!d->m_expanderProvider)
return;
const auto chooser = new Core::VariableChooser(builder.layout()->parentWidget());
chooser->addSupportedWidget(w);
chooser->addMacroExpanderProvider(d->m_expanderProvider);
};
switch (d->m_displayStyle) { switch (d->m_displayStyle) {
case PathChooserDisplay: case PathChooserDisplay:
d->m_pathChooserDisplay = new PathChooser; d->m_pathChooserDisplay = new PathChooser;
@@ -279,6 +316,7 @@ void BaseStringAspect::addToLayout(LayoutBuilder &builder)
d->m_pathChooserDisplay->setEnvironment(d->m_environment); d->m_pathChooserDisplay->setEnvironment(d->m_environment);
d->m_pathChooserDisplay->setBaseFileName(d->m_baseFileName); d->m_pathChooserDisplay->setBaseFileName(d->m_baseFileName);
d->m_pathChooserDisplay->setReadOnly(d->m_readOnly); d->m_pathChooserDisplay->setReadOnly(d->m_readOnly);
useMacroExpander(d->m_pathChooserDisplay->lineEdit());
connect(d->m_pathChooserDisplay, &PathChooser::pathChanged, connect(d->m_pathChooserDisplay, &PathChooser::pathChanged,
this, &BaseStringAspect::setValue); this, &BaseStringAspect::setValue);
builder.addItem(d->m_pathChooserDisplay.data()); builder.addItem(d->m_pathChooserDisplay.data());
@@ -289,6 +327,7 @@ void BaseStringAspect::addToLayout(LayoutBuilder &builder)
if (!d->m_historyCompleterKey.isEmpty()) if (!d->m_historyCompleterKey.isEmpty())
d->m_lineEditDisplay->setHistoryCompleter(d->m_historyCompleterKey); d->m_lineEditDisplay->setHistoryCompleter(d->m_historyCompleterKey);
d->m_lineEditDisplay->setReadOnly(d->m_readOnly); d->m_lineEditDisplay->setReadOnly(d->m_readOnly);
useMacroExpander(d->m_lineEditDisplay);
connect(d->m_lineEditDisplay, &FancyLineEdit::textEdited, connect(d->m_lineEditDisplay, &FancyLineEdit::textEdited,
this, &BaseStringAspect::setValue); this, &BaseStringAspect::setValue);
builder.addItem(d->m_lineEditDisplay.data()); builder.addItem(d->m_lineEditDisplay.data());
@@ -297,6 +336,7 @@ void BaseStringAspect::addToLayout(LayoutBuilder &builder)
d->m_textEditDisplay = new QTextEdit; d->m_textEditDisplay = new QTextEdit;
d->m_textEditDisplay->setPlaceholderText(d->m_placeHolderText); d->m_textEditDisplay->setPlaceholderText(d->m_placeHolderText);
d->m_textEditDisplay->setReadOnly(d->m_readOnly); d->m_textEditDisplay->setReadOnly(d->m_readOnly);
useMacroExpander(d->m_textEditDisplay);
connect(d->m_textEditDisplay, &QTextEdit::textChanged, this, [this] { connect(d->m_textEditDisplay, &QTextEdit::textChanged, this, [this] {
const QString value = d->m_textEditDisplay->document()->toPlainText(); const QString value = d->m_textEditDisplay->document()->toPlainText();
if (value != d->m_value) { if (value != d->m_value) {
@@ -324,21 +364,19 @@ void BaseStringAspect::update()
const QString displayedString = d->m_displayFilter ? d->m_displayFilter(d->m_value) const QString displayedString = d->m_displayFilter ? d->m_displayFilter(d->m_value)
: d->m_value; : d->m_value;
const bool enabled = !d->m_checker || d->m_checker->value();
if (d->m_pathChooserDisplay) { if (d->m_pathChooserDisplay) {
d->m_pathChooserDisplay->setFileName(FilePath::fromString(displayedString)); d->m_pathChooserDisplay->setFileName(FilePath::fromString(displayedString));
d->m_pathChooserDisplay->setEnabled(enabled); d->updateWidgetFromCheckStatus(d->m_pathChooserDisplay.data());
} }
if (d->m_lineEditDisplay) { if (d->m_lineEditDisplay) {
d->m_lineEditDisplay->setTextKeepingActiveCursor(displayedString); d->m_lineEditDisplay->setTextKeepingActiveCursor(displayedString);
d->m_lineEditDisplay->setEnabled(enabled); d->updateWidgetFromCheckStatus(d->m_lineEditDisplay.data());
} }
if (d->m_textEditDisplay) { if (d->m_textEditDisplay) {
d->m_textEditDisplay->setText(displayedString); d->m_textEditDisplay->setText(displayedString);
d->m_textEditDisplay->setEnabled(enabled); d->updateWidgetFromCheckStatus(d->m_textEditDisplay.data());
} }
if (d->m_labelDisplay) { if (d->m_labelDisplay) {
@@ -362,6 +400,7 @@ void BaseStringAspect::makeCheckable(const QString &checkerLabel, const QString
connect(d->m_checker.get(), &BaseBoolAspect::changed, this, &BaseStringAspect::update); connect(d->m_checker.get(), &BaseBoolAspect::changed, this, &BaseStringAspect::update);
connect(d->m_checker.get(), &BaseBoolAspect::changed, this, &BaseStringAspect::changed); connect(d->m_checker.get(), &BaseBoolAspect::changed, this, &BaseStringAspect::changed);
connect(d->m_checker.get(), &BaseBoolAspect::changed, this, &BaseStringAspect::checkedChanged);
update(); update();
} }

View File

@@ -29,6 +29,7 @@
#include "environmentaspect.h" #include "environmentaspect.h"
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/macroexpander.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <memory> #include <memory>
@@ -128,8 +129,12 @@ public:
void setEnvironment(const Utils::Environment &env); void setEnvironment(const Utils::Environment &env);
void setBaseFileName(const Utils::FilePath &baseFileName); void setBaseFileName(const Utils::FilePath &baseFileName);
void setReadOnly(bool readOnly); void setReadOnly(bool readOnly);
void setMacroExpanderProvider(const Utils::MacroExpanderProvider &expanderProvider);
enum class UncheckedSemantics { Disabled, ReadOnly };
void setUncheckedSemantics(UncheckedSemantics semantics);
bool isChecked() const; bool isChecked() const;
void setChecked(bool checked);
void makeCheckable(const QString &optionalLabel, const QString &optionalBaseKey); void makeCheckable(const QString &optionalLabel, const QString &optionalBaseKey);
enum DisplayStyle { enum DisplayStyle {
@@ -146,6 +151,9 @@ public:
Utils::FilePath filePath() const; Utils::FilePath filePath() const;
void setFilePath(const Utils::FilePath &val); void setFilePath(const Utils::FilePath &val);
signals:
void checkedChanged();
private: private:
void update(); void update();