forked from qt-creator/qt-creator
ProjectExplorer: Introduce and use a new MultiSelectionAspect
Only provide the minimum functionality to make it usable for the target selection in Make steps. Task-number: QTCREATORBUG-25088 Change-Id: I6458a0bd544d2fff596df3240c69e05d7bdea14b Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QListWidget>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
@@ -250,6 +251,23 @@ public:
|
|||||||
QString m_tooltip;
|
QString m_tooltip;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MultiSelectionAspectPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QStringList m_value;
|
||||||
|
QStringList m_allValues;
|
||||||
|
MultiSelectionAspect::DisplayStyle m_displayStyle
|
||||||
|
= MultiSelectionAspect::DisplayStyle::ListView;
|
||||||
|
QString m_labelText;
|
||||||
|
|
||||||
|
// These are all owned by the configuration widget.
|
||||||
|
QPointer<QListWidget> m_listView;
|
||||||
|
QPointer<QLabel> m_label;
|
||||||
|
|
||||||
|
void updateListView();
|
||||||
|
bool setValueSelectedHelper(const QString &value, bool on);
|
||||||
|
};
|
||||||
|
|
||||||
class StringAspectPrivate
|
class StringAspectPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1033,6 +1051,129 @@ void SelectionAspect::addOption(const QString &displayName, const QString &toolT
|
|||||||
d->m_options.append({displayName, toolTip});
|
d->m_options.append({displayName, toolTip});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class Utils::MultiSelectionAspect
|
||||||
|
\inmodule QtCreator
|
||||||
|
|
||||||
|
\brief A multi-selection aspect represents one or more choices out of
|
||||||
|
several.
|
||||||
|
|
||||||
|
The multi-selection aspect is displayed using a QListWidget with
|
||||||
|
checkable items.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MultiSelectionAspect::MultiSelectionAspect()
|
||||||
|
: d(new Internal::MultiSelectionAspectPrivate)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
MultiSelectionAspect::~MultiSelectionAspect() = default;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void MultiSelectionAspect::addToLayout(LayoutBuilder &builder)
|
||||||
|
{
|
||||||
|
QTC_CHECK(d->m_listView == nullptr);
|
||||||
|
if (d->m_allValues.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (d->m_displayStyle) {
|
||||||
|
case DisplayStyle::ListView:
|
||||||
|
d->m_label = new QLabel(d->m_labelText);
|
||||||
|
d->m_listView = new QListWidget;
|
||||||
|
for (const QString &value : qAsConst(d->m_allValues)) {
|
||||||
|
auto item = new QListWidgetItem(value, d->m_listView);
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
|
item->setCheckState(d->m_value.contains(item->text()) ? Qt::Checked : Qt::Unchecked);
|
||||||
|
}
|
||||||
|
connect(d->m_listView, &QListWidget::itemChanged, this,
|
||||||
|
[this](QListWidgetItem *item) {
|
||||||
|
if (d->setValueSelectedHelper(item->text(), item->checkState() & Qt::Checked))
|
||||||
|
emit changed();
|
||||||
|
});
|
||||||
|
builder.addItems({d->m_label.data(), d->m_listView.data()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Internal::MultiSelectionAspectPrivate::setValueSelectedHelper(const QString &value, bool on)
|
||||||
|
{
|
||||||
|
if (on && !m_value.contains(value)) {
|
||||||
|
m_value.append(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!on && m_value.contains(value)) {
|
||||||
|
m_value.removeOne(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList MultiSelectionAspect::allValues() const
|
||||||
|
{
|
||||||
|
return d->m_allValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiSelectionAspect::setAllValues(const QStringList &val)
|
||||||
|
{
|
||||||
|
d->m_allValues = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiSelectionAspect::setLabelText(const QString &labelText)
|
||||||
|
{
|
||||||
|
d->m_labelText = labelText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Internal::MultiSelectionAspectPrivate::updateListView()
|
||||||
|
{
|
||||||
|
if (!m_listView)
|
||||||
|
return;
|
||||||
|
const int n = m_listView->count();
|
||||||
|
QTC_CHECK(n == m_allValues.size());
|
||||||
|
for (int i = 0; i != n; ++i) {
|
||||||
|
auto item = m_listView->item(i);
|
||||||
|
item->setCheckState(m_value.contains(item->text()) ? Qt::Checked : Qt::Unchecked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void MultiSelectionAspect::fromMap(const QVariantMap &map)
|
||||||
|
{
|
||||||
|
d->m_value = map.value(settingsKey(), QStringList()).toStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void MultiSelectionAspect::toMap(QVariantMap &data) const
|
||||||
|
{
|
||||||
|
saveToMap(data, d->m_value, QStringList());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiSelectionAspect::setDisplayStyle(MultiSelectionAspect::DisplayStyle style)
|
||||||
|
{
|
||||||
|
d->m_displayStyle = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList MultiSelectionAspect::value() const
|
||||||
|
{
|
||||||
|
return d->m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiSelectionAspect::setValue(const QStringList &value)
|
||||||
|
{
|
||||||
|
if (d->m_value == value)
|
||||||
|
return;
|
||||||
|
d->m_value = value;
|
||||||
|
d->updateListView();
|
||||||
|
emit changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class Utils::IntegerAspect
|
\class Utils::IntegerAspect
|
||||||
\inmodule QtCreator
|
\inmodule QtCreator
|
||||||
|
@@ -44,6 +44,7 @@ namespace Internal {
|
|||||||
class AspectContainerPrivate;
|
class AspectContainerPrivate;
|
||||||
class BoolAspectPrivate;
|
class BoolAspectPrivate;
|
||||||
class IntegerAspectPrivate;
|
class IntegerAspectPrivate;
|
||||||
|
class MultiSelectionAspectPrivate;
|
||||||
class SelectionAspectPrivate;
|
class SelectionAspectPrivate;
|
||||||
class StringAspectPrivate;
|
class StringAspectPrivate;
|
||||||
class StringListAspectPrivate;
|
class StringListAspectPrivate;
|
||||||
@@ -97,7 +98,6 @@ protected:
|
|||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT BaseAspects
|
class QTCREATOR_UTILS_EXPORT BaseAspects
|
||||||
{
|
{
|
||||||
|
|
||||||
BaseAspects(const BaseAspects &) = delete;
|
BaseAspects(const BaseAspects &) = delete;
|
||||||
BaseAspects &operator=(const BaseAspects &) = delete;
|
BaseAspects &operator=(const BaseAspects &) = delete;
|
||||||
|
|
||||||
@@ -202,6 +202,34 @@ private:
|
|||||||
std::unique_ptr<Internal::SelectionAspectPrivate> d;
|
std::unique_ptr<Internal::SelectionAspectPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT MultiSelectionAspect : public BaseAspect
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MultiSelectionAspect();
|
||||||
|
~MultiSelectionAspect() override;
|
||||||
|
|
||||||
|
void addToLayout(LayoutBuilder &builder) override;
|
||||||
|
|
||||||
|
enum class DisplayStyle { ListView };
|
||||||
|
void setDisplayStyle(DisplayStyle style);
|
||||||
|
|
||||||
|
QStringList value() const;
|
||||||
|
void setValue(const QStringList &val);
|
||||||
|
|
||||||
|
QStringList allValues() const;
|
||||||
|
void setAllValues(const QStringList &val);
|
||||||
|
|
||||||
|
void setLabelText(const QString &labelText);
|
||||||
|
|
||||||
|
void fromMap(const QVariantMap &map) override;
|
||||||
|
void toMap(QVariantMap &map) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Internal::MultiSelectionAspectPrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT StringAspect : public BaseAspect
|
class QTCREATOR_UTILS_EXPORT StringAspect : public BaseAspect
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@@ -49,10 +49,10 @@ MakeStep::MakeStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id)
|
|||||||
{
|
{
|
||||||
setAvailableBuildTargets({"all", "clean"});
|
setAvailableBuildTargets({"all", "clean"});
|
||||||
if (bsl->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
|
if (bsl->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
|
||||||
setBuildTarget("clean", true);
|
setSelectedBuildTarget("clean");
|
||||||
setIgnoreReturnValue(true);
|
setIgnoreReturnValue(true);
|
||||||
} else {
|
} else {
|
||||||
setBuildTarget("all", true);
|
setSelectedBuildTarget("all");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,13 +43,13 @@ public:
|
|||||||
GenericMakeStep::GenericMakeStep(BuildStepList *parent, Utils::Id id)
|
GenericMakeStep::GenericMakeStep(BuildStepList *parent, Utils::Id id)
|
||||||
: MakeStep(parent, id)
|
: MakeStep(parent, id)
|
||||||
{
|
{
|
||||||
|
setAvailableBuildTargets({"all", "clean"});
|
||||||
if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_BUILD) {
|
if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_BUILD) {
|
||||||
setBuildTarget("all");
|
setSelectedBuildTarget("all");
|
||||||
} else if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
|
} else if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
|
||||||
setBuildTarget("clean");
|
setSelectedBuildTarget("clean");
|
||||||
setIgnoreReturnValue(true);
|
setIgnoreReturnValue(true);
|
||||||
}
|
}
|
||||||
setAvailableBuildTargets({"all", "clean"});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericMakeStepFactory::GenericMakeStepFactory()
|
GenericMakeStepFactory::GenericMakeStepFactory()
|
||||||
|
@@ -49,8 +49,6 @@
|
|||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QListWidget>
|
|
||||||
#include <QSpinBox>
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
@@ -105,8 +103,9 @@ MakeStep::MakeStep(BuildStepList *parent, Id id)
|
|||||||
.arg(text) + "</p></body></html>");
|
.arg(text) + "</p></body></html>");
|
||||||
m_nonOverrideWarning->setIconType(InfoLabel::Warning);
|
m_nonOverrideWarning->setIconType(InfoLabel::Warning);
|
||||||
|
|
||||||
m_buildTargetsAspect = addAspect<StringListAspect>();
|
m_buildTargetsAspect = addAspect<MultiSelectionAspect>();
|
||||||
m_buildTargetsAspect->setSettingsKey(id.withSuffix(BUILD_TARGETS_SUFFIX).toString());
|
m_buildTargetsAspect->setSettingsKey(id.withSuffix(BUILD_TARGETS_SUFFIX).toString());
|
||||||
|
m_buildTargetsAspect->setLabelText(tr("Targets:"));
|
||||||
|
|
||||||
const auto updateMakeLabel = [this] {
|
const auto updateMakeLabel = [this] {
|
||||||
const QString defaultMake = defaultMakeCommand().toString();
|
const QString defaultMake = defaultMakeCommand().toString();
|
||||||
@@ -121,15 +120,14 @@ MakeStep::MakeStep(BuildStepList *parent, Id id)
|
|||||||
connect(m_makeCommandAspect, &StringAspect::changed, this, updateMakeLabel);
|
connect(m_makeCommandAspect, &StringAspect::changed, this, updateMakeLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeStep::setBuildTarget(const QString &buildTarget)
|
void MakeStep::setSelectedBuildTarget(const QString &buildTarget)
|
||||||
{
|
{
|
||||||
if (!buildTarget.isEmpty())
|
m_buildTargetsAspect->setValue({buildTarget});
|
||||||
setBuildTarget(buildTarget, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeStep::setAvailableBuildTargets(const QStringList &buildTargets)
|
void MakeStep::setAvailableBuildTargets(const QStringList &buildTargets)
|
||||||
{
|
{
|
||||||
m_availableTargets = buildTargets;
|
m_buildTargetsAspect->setAllValues(buildTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MakeStep::init()
|
bool MakeStep::init()
|
||||||
@@ -342,11 +340,6 @@ QWidget *MakeStep::createConfigWidget()
|
|||||||
{
|
{
|
||||||
auto widget = new QWidget;
|
auto widget = new QWidget;
|
||||||
|
|
||||||
auto targetsLabel = new QLabel(widget);
|
|
||||||
targetsLabel->setText(tr("Targets:"));
|
|
||||||
|
|
||||||
auto targetsList = new QListWidget(widget);
|
|
||||||
|
|
||||||
auto disableInSubDirsLabel = new QLabel(tr("Disable in subdirectories:"), widget);
|
auto disableInSubDirsLabel = new QLabel(tr("Disable in subdirectories:"), widget);
|
||||||
auto disableInSubDirsCheckBox = new QCheckBox(widget);
|
auto disableInSubDirsCheckBox = new QCheckBox(widget);
|
||||||
disableInSubDirsCheckBox->setToolTip(tr("Runs this step only for a top-level build."));
|
disableInSubDirsCheckBox->setToolTip(tr("Runs this step only for a top-level build."));
|
||||||
@@ -356,7 +349,7 @@ QWidget *MakeStep::createConfigWidget()
|
|||||||
builder.addRow(m_userArgumentsAspect);
|
builder.addRow(m_userArgumentsAspect);
|
||||||
builder.addRow(m_jobCountContainer);
|
builder.addRow(m_jobCountContainer);
|
||||||
builder.addRow({disableInSubDirsLabel, disableInSubDirsCheckBox});
|
builder.addRow({disableInSubDirsLabel, disableInSubDirsCheckBox});
|
||||||
builder.addRow({targetsLabel, targetsList});
|
builder.addRow(m_buildTargetsAspect);
|
||||||
|
|
||||||
if (!m_disablingForSubDirsSupported) {
|
if (!m_disablingForSubDirsSupported) {
|
||||||
disableInSubDirsLabel->hide();
|
disableInSubDirsLabel->hide();
|
||||||
@@ -367,16 +360,6 @@ QWidget *MakeStep::createConfigWidget()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QString &target : qAsConst(m_availableTargets)) {
|
|
||||||
auto item = new QListWidgetItem(target, targetsList);
|
|
||||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
|
||||||
item->setCheckState(buildsTarget(item->text()) ? Qt::Checked : Qt::Unchecked);
|
|
||||||
}
|
|
||||||
if (m_availableTargets.isEmpty()) {
|
|
||||||
targetsLabel->hide();
|
|
||||||
targetsList->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableChooser::addSupportForChildWidgets(widget, macroExpander());
|
VariableChooser::addSupportForChildWidgets(widget, macroExpander());
|
||||||
|
|
||||||
setSummaryUpdater([this] {
|
setSummaryUpdater([this] {
|
||||||
@@ -420,12 +403,7 @@ QWidget *MakeStep::createConfigWidget()
|
|||||||
connect(m_userArgumentsAspect, &StringAspect::changed, widget, updateDetails);
|
connect(m_userArgumentsAspect, &StringAspect::changed, widget, updateDetails);
|
||||||
connect(m_userJobCountAspect, &IntegerAspect::changed, widget, updateDetails);
|
connect(m_userJobCountAspect, &IntegerAspect::changed, widget, updateDetails);
|
||||||
connect(m_overrideMakeflagsAspect, &BoolAspect::changed, widget, updateDetails);
|
connect(m_overrideMakeflagsAspect, &BoolAspect::changed, widget, updateDetails);
|
||||||
|
connect(m_buildTargetsAspect, &BaseAspect::changed, widget, updateDetails);
|
||||||
connect(targetsList, &QListWidget::itemChanged, this,
|
|
||||||
[this, updateDetails](QListWidgetItem *item) {
|
|
||||||
setBuildTarget(item->text(), item->checkState() & Qt::Checked);
|
|
||||||
updateDetails();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
|
||||||
widget, updateDetails);
|
widget, updateDetails);
|
||||||
@@ -439,25 +417,9 @@ QWidget *MakeStep::createConfigWidget()
|
|||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MakeStep::buildsTarget(const QString &target) const
|
|
||||||
{
|
|
||||||
return m_buildTargetsAspect->value().contains(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MakeStep::setBuildTarget(const QString &target, bool on)
|
|
||||||
{
|
|
||||||
QStringList old = m_buildTargetsAspect->value();
|
|
||||||
if (on && !old.contains(target))
|
|
||||||
old << target;
|
|
||||||
else if (!on && old.contains(target))
|
|
||||||
old.removeOne(target);
|
|
||||||
|
|
||||||
m_buildTargetsAspect->setValue(old);
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList MakeStep::availableTargets() const
|
QStringList MakeStep::availableTargets() const
|
||||||
{
|
{
|
||||||
return m_availableTargets;
|
return m_buildTargetsAspect->allValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -45,14 +45,13 @@ public:
|
|||||||
};
|
};
|
||||||
explicit MakeStep(ProjectExplorer::BuildStepList *parent, Utils::Id id);
|
explicit MakeStep(ProjectExplorer::BuildStepList *parent, Utils::Id id);
|
||||||
|
|
||||||
void setBuildTarget(const QString &buildTarget);
|
|
||||||
void setAvailableBuildTargets(const QStringList &buildTargets);
|
void setAvailableBuildTargets(const QStringList &buildTargets);
|
||||||
|
void setSelectedBuildTarget(const QString &buildTarget);
|
||||||
|
|
||||||
bool init() override;
|
bool init() override;
|
||||||
void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
|
void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
|
||||||
QWidget *createConfigWidget() override;
|
QWidget *createConfigWidget() override;
|
||||||
bool buildsTarget(const QString &target) const;
|
|
||||||
void setBuildTarget(const QString &target, bool on);
|
|
||||||
QStringList availableTargets() const;
|
QStringList availableTargets() const;
|
||||||
QString userArguments() const;
|
QString userArguments() const;
|
||||||
void setUserArguments(const QString &args);
|
void setUserArguments(const QString &args);
|
||||||
@@ -87,8 +86,7 @@ private:
|
|||||||
static int defaultJobCount();
|
static int defaultJobCount();
|
||||||
QStringList jobArguments() const;
|
QStringList jobArguments() const;
|
||||||
|
|
||||||
Utils::StringListAspect *m_buildTargetsAspect = nullptr;
|
Utils::MultiSelectionAspect *m_buildTargetsAspect = nullptr;
|
||||||
QStringList m_availableTargets;
|
|
||||||
Utils::StringAspect *m_makeCommandAspect = nullptr;
|
Utils::StringAspect *m_makeCommandAspect = nullptr;
|
||||||
Utils::StringAspect *m_userArgumentsAspect = nullptr;
|
Utils::StringAspect *m_userArgumentsAspect = nullptr;
|
||||||
Utils::AspectContainer *m_jobCountContainer = nullptr;
|
Utils::AspectContainer *m_jobCountContainer = nullptr;
|
||||||
|
Reference in New Issue
Block a user