ProjectExplorer: Re-do the EnvironmentWidget

Editing in the item view was cumbersome and did not generally allow one
variable to refer to another, as there was no defined order on the
assignments.
Therefore, we make the item view read-only and promote the batch editing
widget to be the standard input method. User changes are not sorted
anymore, except in the summary text of the details widget.

Fixes: QTCREATORBUG-28480
Change-Id: I225cf86fff7b001a57d663e1fd267a4645e695c4
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2024-01-16 11:18:30 +01:00
parent 10ff747a0f
commit 8ef85e481a
6 changed files with 180 additions and 92 deletions

View File

@@ -179,7 +179,7 @@ QVariant NameValueModel::data(const QModelIndex &index, int role) const
Qt::ItemFlags NameValueModel::flags(const QModelIndex &index) const Qt::ItemFlags NameValueModel::flags(const QModelIndex &index) const
{ {
Q_UNUSED(index) Q_UNUSED(index)
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled; return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
} }
QVariant NameValueModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant NameValueModel::headerData(int section, Qt::Orientation orientation, int role) const
@@ -264,10 +264,7 @@ bool NameValueModel::setData(const QModelIndex &index, const QVariant &value, in
QModelIndex NameValueModel::addVariable() QModelIndex NameValueModel::addVariable()
{ {
//: Name when inserting a new variable return addVariable(NameValueItem("NEWVAR", "VALUE"));
return addVariable(NameValueItem(Tr::tr("<VARIABLE>"),
//: Value when inserting a new variable
Tr::tr("<VALUE>")));
} }
QModelIndex NameValueModel::addVariable(const NameValueItem &item) QModelIndex NameValueModel::addVariable(const NameValueItem &item)

View File

@@ -12,6 +12,8 @@
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QPushButton> #include <QPushButton>
#include <QSet> #include <QSet>
#include <QTextBlock>
#include <QTimer>
#include <QVBoxLayout> #include <QVBoxLayout>
namespace Utils { namespace Utils {
@@ -34,20 +36,21 @@ static EnvironmentItems cleanUp(const EnvironmentItems &items)
return uniqueItems; return uniqueItems;
} }
class NameValueItemsWidget : public QWidget class TextEditHelper : public QPlainTextEdit
{ {
Q_OBJECT
public: public:
explicit NameValueItemsWidget(QWidget *parent = nullptr); using QPlainTextEdit::QPlainTextEdit;
void setEnvironmentItems(const EnvironmentItems &items); signals:
EnvironmentItems environmentItems() const; void lostFocus();
void setPlaceholderText(const QString &text);
private: private:
QPlainTextEdit *m_editor; void focusOutEvent(QFocusEvent *) override { emit lostFocus(); }
}; };
} // namespace Internal
NameValueItemsWidget::NameValueItemsWidget(QWidget *parent) NameValueItemsWidget::NameValueItemsWidget(QWidget *parent)
: QWidget(parent) : QWidget(parent)
{ {
@@ -60,26 +63,41 @@ NameValueItemsWidget::NameValueItemsWidget(QWidget *parent)
"To clear a variable, put its name on a line with nothing else on it.\n" "To clear a variable, put its name on a line with nothing else on it.\n"
"To disable a variable, prefix the line with \"#\"."); "To disable a variable, prefix the line with \"#\".");
m_editor = new QPlainTextEdit(this); m_editor = new Internal::TextEditHelper(this);
auto layout = new QVBoxLayout(this); auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_editor); layout->addWidget(m_editor);
layout->addWidget(new QLabel(helpText, this)); layout->addWidget(new QLabel(helpText, this));
const auto checkForItemChange = [this] {
const NameValueItems newItems = environmentItems();
if (newItems != m_originalItems) {
m_originalItems = newItems;
emit userChangedItems(newItems);
}
};
const auto timer = new QTimer(this);
timer->setSingleShot(true);
timer->setInterval(1000);
connect(m_editor, &QPlainTextEdit::textChanged, timer, qOverload<>(&QTimer::start));
connect(timer, &QTimer::timeout, this, checkForItemChange);
connect(m_editor, &Internal::TextEditHelper::lostFocus, this, [timer, checkForItemChange] {
timer->stop();
checkForItemChange();
});
} }
void NameValueItemsWidget::setEnvironmentItems(const EnvironmentItems &items) void NameValueItemsWidget::setEnvironmentItems(const EnvironmentItems &items)
{ {
EnvironmentItems sortedItems = items; m_originalItems = items;
EnvironmentItem::sort(&sortedItems); m_editor->document()->setPlainText(EnvironmentItem::toStringList(items)
const QStringList list = EnvironmentItem::toStringList(sortedItems); .join(QLatin1Char('\n')));
m_editor->document()->setPlainText(list.join(QLatin1Char('\n')));
} }
EnvironmentItems NameValueItemsWidget::environmentItems() const EnvironmentItems NameValueItemsWidget::environmentItems() const
{ {
const QStringList list = m_editor->document()->toPlainText().split(QLatin1String("\n")); const QStringList list = m_editor->document()->toPlainText().split(QLatin1String("\n"));
EnvironmentItems items = EnvironmentItem::fromStringList(list); return Internal::cleanUp(EnvironmentItem::fromStringList(list));
return cleanUp(items);
} }
void NameValueItemsWidget::setPlaceholderText(const QString &text) void NameValueItemsWidget::setPlaceholderText(const QString &text)
@@ -87,13 +105,61 @@ void NameValueItemsWidget::setPlaceholderText(const QString &text)
m_editor->setPlaceholderText(text); m_editor->setPlaceholderText(text);
} }
} // namespace Internal bool NameValueItemsWidget::editVariable(const QString &name, Selection selection)
{
QTextDocument * const doc = m_editor->document();
for (QTextBlock b = doc->lastBlock(); b.isValid(); b = b.previous()) {
const QString &line = b.text();
qsizetype offset = 0;
const auto skipWhiteSpace = [&] {
for (; offset < line.length(); ++offset) {
if (!line.at(offset).isSpace())
return;
}
};
skipWhiteSpace();
if (line.mid(offset, name.size()) != name)
continue;
offset += name.size();
const auto updateCursor = [&](int anchor, int pos) {
QTextCursor newCursor(doc);
newCursor.setPosition(anchor);
newCursor.setPosition(pos, QTextCursor::KeepAnchor);
m_editor->setTextCursor(newCursor);
};
if (selection == Selection::Name) {
m_editor->setFocus();
updateCursor(b.position() + offset, b.position());
return true;
}
skipWhiteSpace();
if (offset < line.length()) {
QChar nextChar = line.at(offset);
if (nextChar.isLetterOrNumber())
continue;
if (nextChar == '=') {
if (++offset < line.length() && line.at(offset) == '+')
++offset;
} else if (nextChar == '+') {
if (++offset < line.length() && line.at(offset) == '=')
++offset;
}
}
m_editor->setFocus();
updateCursor(b.position() + b.length() - 1, b.position() + offset);
return true;
}
return false;
}
NameValuesDialog::NameValuesDialog(const QString &windowTitle, QWidget *parent) NameValuesDialog::NameValuesDialog(const QString &windowTitle, QWidget *parent)
: QDialog(parent) : QDialog(parent)
{ {
resize(640, 480); resize(640, 480);
m_editor = new Internal::NameValueItemsWidget(this); m_editor = new NameValueItemsWidget(this);
auto box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, auto box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, Qt::Horizontal,
this); this);
@@ -143,3 +209,5 @@ std::optional<NameValueItems> NameValuesDialog::getNameValueItems(QWidget *paren
} }
} // namespace Utils } // namespace Utils
#include <namevaluesdialog.moc>

View File

@@ -3,19 +3,39 @@
#pragma once #pragma once
#include "utils_global.h"
#include "namevalueitem.h" #include "namevalueitem.h"
#include "utils_global.h"
#include <QDialog> #include <QDialog>
#include <functional> #include <functional>
#include <memory>
#include <optional> #include <optional>
namespace Utils { namespace Utils {
namespace Internal { class NameValueItemsWidget; } namespace Internal { class TextEditHelper; }
class QTCREATOR_UTILS_EXPORT NameValueItemsWidget : public QWidget
{
Q_OBJECT
public:
explicit NameValueItemsWidget(QWidget *parent = nullptr);
void setEnvironmentItems(const EnvironmentItems &items);
EnvironmentItems environmentItems() const;
void setPlaceholderText(const QString &text);
enum class Selection { Name, Value };
bool editVariable(const QString &name, Selection selection);
signals:
void userChangedItems(const EnvironmentItems &items);
private:
Internal::TextEditHelper *m_editor;
NameValueItems m_originalItems;
};
class QTCREATOR_UTILS_EXPORT NameValuesDialog : public QDialog class QTCREATOR_UTILS_EXPORT NameValuesDialog : public QDialog
{ {
@@ -36,7 +56,7 @@ protected:
QWidget *parent = {}); QWidget *parent = {});
private: private:
Internal::NameValueItemsWidget *m_editor; NameValueItemsWidget *m_editor;
}; };
} // namespace Utils } // namespace Utils

View File

@@ -125,38 +125,19 @@ private:
PathTreeWidget m_view; PathTreeWidget m_view;
}; };
class EnvironmentDelegate : public QStyledItemDelegate
{
public:
EnvironmentDelegate(Utils::EnvironmentModel *model,
QTreeView *view)
: QStyledItemDelegate(view), m_model(model), m_view(view)
{}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
QWidget *w = QStyledItemDelegate::createEditor(parent, option, index);
if (index.column() != 0)
return w;
if (auto edit = qobject_cast<QLineEdit *>(w))
edit->setValidator(new Utils::NameValueValidator(
edit, m_model, m_view, index, Tr::tr("Variable already exists.")));
return w;
}
private:
Utils::EnvironmentModel *m_model;
QTreeView *m_view;
};
//// ////
// EnvironmentWidget::EnvironmentWidget // EnvironmentWidget::EnvironmentWidget
//// ////
class EnvironmentWidgetPrivate class EnvironmentWidget::Private
{ {
public: public:
Private(EnvironmentWidget *q) : q(q) {}
void handleEditRequest(NameValueItemsWidget::Selection selection);
EnvironmentWidget * const q;
Utils::NameValueItemsWidget m_editor;
Utils::EnvironmentModel *m_model; Utils::EnvironmentModel *m_model;
EnvironmentWidget::Type m_type = EnvironmentWidget::TypeLocal; EnvironmentWidget::Type m_type = EnvironmentWidget::TypeLocal;
QString m_baseEnvironmentText; QString m_baseEnvironmentText;
@@ -168,14 +149,13 @@ public:
QPushButton *m_resetButton; QPushButton *m_resetButton;
QPushButton *m_unsetButton; QPushButton *m_unsetButton;
QPushButton *m_toggleButton; QPushButton *m_toggleButton;
QPushButton *m_batchEditButton;
QPushButton *m_appendPathButton = nullptr; QPushButton *m_appendPathButton = nullptr;
QPushButton *m_prependPathButton = nullptr; QPushButton *m_prependPathButton = nullptr;
QPushButton *m_terminalButton; QPushButton *m_terminalButton;
}; };
EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additionalDetailsWidget) EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additionalDetailsWidget)
: QWidget(parent), d(std::make_unique<EnvironmentWidgetPrivate>()) : QWidget(parent), d(std::make_unique<Private>(this))
{ {
d->m_model = new Utils::EnvironmentModel(); d->m_model = new Utils::EnvironmentModel();
d->m_type = type; d->m_type = type;
@@ -183,14 +163,27 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
this, &EnvironmentWidget::userChangesChanged); this, &EnvironmentWidget::userChangesChanged);
connect(d->m_model, &QAbstractItemModel::modelReset, connect(d->m_model, &QAbstractItemModel::modelReset,
this, &EnvironmentWidget::invalidateCurrentIndex); this, &EnvironmentWidget::invalidateCurrentIndex);
connect(d->m_model, &Utils::EnvironmentModel::focusIndex, connect(d->m_model, &Utils::EnvironmentModel::focusIndex,
this, &EnvironmentWidget::focusIndex); this, &EnvironmentWidget::focusIndex);
// The text edit represents the raw, unexpanded user changes.
// There are two possible data flows:
// a) text edit -> model -> view for when the user types in the text edit
// b) top level widget
// -> text edit
// -> model -> view
// for when convenience functionality is used via the buttons.
// So the model is always updated from the text edit or text edit and model
// are updated in sync from this widget.
connect(&d->m_editor, &NameValueItemsWidget::userChangedItems,
d->m_model, &EnvironmentModel::setUserChanges);
auto vbox = new QVBoxLayout(this); auto vbox = new QVBoxLayout(this);
vbox->setContentsMargins(0, 0, 0, 0); vbox->setContentsMargins(0, 0, 0, 0);
d->m_detailsContainer = new Utils::DetailsWidget(this); d->m_detailsContainer = new Utils::DetailsWidget(this);
connect(d->m_detailsContainer, &DetailsWidget::expanded,
this, &EnvironmentWidget::updateSummaryText);
auto details = new QWidget(d->m_detailsContainer); auto details = new QWidget(d->m_detailsContainer);
d->m_detailsContainer->setWidget(details); d->m_detailsContainer->setWidget(details);
@@ -209,7 +202,6 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
tree, [tree](const QModelIndex &idx) { tree->edit(idx); }); tree, [tree](const QModelIndex &idx) { tree->edit(idx); });
d->m_environmentView = tree; d->m_environmentView = tree;
d->m_environmentView->setModel(d->m_model); d->m_environmentView->setModel(d->m_model);
d->m_environmentView->setItemDelegate(new EnvironmentDelegate(d->m_model, d->m_environmentView));
d->m_environmentView->setMinimumHeight(400); d->m_environmentView->setMinimumHeight(400);
d->m_environmentView->setRootIsDecorated(false); d->m_environmentView->setRootIsDecorated(false);
const auto stretcher = new HeaderViewStretcher(d->m_environmentView->header(), 1); const auto stretcher = new HeaderViewStretcher(d->m_environmentView->header(), 1);
@@ -218,7 +210,7 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
connect(d->m_model, &EnvironmentModel::userChangesChanged, connect(d->m_model, &EnvironmentModel::userChangesChanged,
stretcher, &HeaderViewStretcher::softStretch); stretcher, &HeaderViewStretcher::softStretch);
d->m_environmentView->setSelectionMode(QAbstractItemView::SingleSelection); d->m_environmentView->setSelectionMode(QAbstractItemView::SingleSelection);
d->m_environmentView->setSelectionBehavior(QAbstractItemView::SelectItems); d->m_environmentView->setSelectionBehavior(QAbstractItemView::SelectRows);
d->m_environmentView->setFrameShape(QFrame::NoFrame); d->m_environmentView->setFrameShape(QFrame::NoFrame);
QFrame *findWrapper = Core::ItemViewFind::createSearchableWrapper(d->m_environmentView, Core::ItemViewFind::LightColored); QFrame *findWrapper = Core::ItemViewFind::createSearchableWrapper(d->m_environmentView, Core::ItemViewFind::LightColored);
findWrapper->setFrameStyle(QFrame::StyledPanel); findWrapper->setFrameStyle(QFrame::StyledPanel);
@@ -266,10 +258,6 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
this, &EnvironmentWidget::prependPathButtonClicked); this, &EnvironmentWidget::prependPathButtonClicked);
} }
d->m_batchEditButton = new QPushButton(this);
d->m_batchEditButton->setText(Tr::tr("&Batch Edit..."));
buttonLayout->addWidget(d->m_batchEditButton);
d->m_terminalButton = new QPushButton(this); d->m_terminalButton = new QPushButton(this);
d->m_terminalButton->setText(Tr::tr("Open &Terminal")); d->m_terminalButton->setText(Tr::tr("Open &Terminal"));
d->m_terminalButton->setToolTip(Tr::tr("Open a terminal with this environment set up.")); d->m_terminalButton->setToolTip(Tr::tr("Open a terminal with this environment set up."));
@@ -278,6 +266,7 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
buttonLayout->addStretch(); buttonLayout->addStretch();
horizontalLayout->addLayout(buttonLayout); horizontalLayout->addLayout(buttonLayout);
horizontalLayout->addWidget(&d->m_editor);
vbox2->addLayout(horizontalLayout); vbox2->addLayout(horizontalLayout);
vbox->addWidget(d->m_detailsContainer); vbox->addWidget(d->m_detailsContainer);
@@ -293,8 +282,6 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
this, &EnvironmentWidget::removeEnvironmentButtonClicked); this, &EnvironmentWidget::removeEnvironmentButtonClicked);
connect(d->m_unsetButton, &QAbstractButton::clicked, connect(d->m_unsetButton, &QAbstractButton::clicked,
this, &EnvironmentWidget::unsetEnvironmentButtonClicked); this, &EnvironmentWidget::unsetEnvironmentButtonClicked);
connect(d->m_batchEditButton, &QAbstractButton::clicked,
this, &EnvironmentWidget::batchEditEnvironmentButtonClicked);
connect(d->m_environmentView->selectionModel(), &QItemSelectionModel::currentChanged, connect(d->m_environmentView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &EnvironmentWidget::environmentCurrentIndexChanged); this, &EnvironmentWidget::environmentCurrentIndexChanged);
connect(d->m_terminalButton, &QAbstractButton::clicked, connect(d->m_terminalButton, &QAbstractButton::clicked,
@@ -354,7 +341,7 @@ Utils::EnvironmentItems EnvironmentWidget::userChanges() const
void EnvironmentWidget::setUserChanges(const Utils::EnvironmentItems &list) void EnvironmentWidget::setUserChanges(const Utils::EnvironmentItems &list)
{ {
d->m_model->setUserChanges(list); d->m_model->setUserChanges(list);
updateSummaryText(); d->m_editor.setEnvironmentItems(list);
} }
void EnvironmentWidget::setOpenTerminalFunc(const EnvironmentWidget::OpenTerminalFunc &func) void EnvironmentWidget::setOpenTerminalFunc(const EnvironmentWidget::OpenTerminalFunc &func)
@@ -370,6 +357,12 @@ void EnvironmentWidget::expand()
void EnvironmentWidget::updateSummaryText() void EnvironmentWidget::updateSummaryText()
{ {
// The summary is redundant with the text edit, so we hide it on expansion.
if (d->m_detailsContainer->state() == DetailsWidget::Expanded) {
d->m_detailsContainer->setSummaryText({});
return;
}
Utils::EnvironmentItems list = d->m_model->userChanges(); Utils::EnvironmentItems list = d->m_model->userChanges();
Utils::EnvironmentItem::sort(&list); Utils::EnvironmentItem::sort(&list);
@@ -428,30 +421,52 @@ void EnvironmentWidget::updateButtons()
void EnvironmentWidget::editEnvironmentButtonClicked() void EnvironmentWidget::editEnvironmentButtonClicked()
{ {
const QModelIndex current = d->m_environmentView->currentIndex(); d->handleEditRequest(NameValueItemsWidget::Selection::Value);
if (current.column() == 1 }
&& d->m_type == TypeLocal
&& d->m_model->currentEntryIsPathList(current)) { void EnvironmentWidget::Private::handleEditRequest(NameValueItemsWidget::Selection selection)
PathListDialog dlg(d->m_model->indexToVariable(current), {
d->m_model->data(current).toString(), this); QModelIndex current = m_environmentView->currentIndex();
if (dlg.exec() == QDialog::Accepted) if (current.column() == 0)
d->m_model->setData(current, dlg.paths()); current = current.siblingAtColumn(1);
} else { const QString varName = m_model->indexToVariable(current);
d->m_environmentView->edit(current);
// Known path lists are edited via a dedicated widget.
if (m_type == TypeLocal && m_model->currentEntryIsPathList(current)) {
PathListDialog dlg(varName, m_model->data(current).toString(), q);
if (dlg.exec() == QDialog::Accepted) {
m_model->setData(current, dlg.paths());
m_editor.setEnvironmentItems(m_model->userChanges());
}
return;
} }
if (m_editor.editVariable(varName, selection))
return;
// The variable does not appear on an LHS in the text edit. This means it is not
// set or unset in any of the user changes. Therefore, we have to create a new
// change item for the user to edit.
EnvironmentItems items = m_model->userChanges();
items.append({varName, "NEWVALUE"});
q->setUserChanges(items);
const bool editable = m_editor.editVariable(varName, NameValueItemsWidget::Selection::Value);
QTC_CHECK(editable);
} }
void EnvironmentWidget::addEnvironmentButtonClicked() void EnvironmentWidget::addEnvironmentButtonClicked()
{ {
QModelIndex index = d->m_model->addVariable(); QModelIndex index = d->m_model->addVariable();
d->m_editor.setEnvironmentItems(d->m_model->userChanges());
d->m_environmentView->setCurrentIndex(index); d->m_environmentView->setCurrentIndex(index);
d->m_environmentView->edit(index); d->handleEditRequest(NameValueItemsWidget::Selection::Name);
} }
void EnvironmentWidget::removeEnvironmentButtonClicked() void EnvironmentWidget::removeEnvironmentButtonClicked()
{ {
const QString &name = d->m_model->indexToVariable(d->m_environmentView->currentIndex()); const QString &name = d->m_model->indexToVariable(d->m_environmentView->currentIndex());
d->m_model->resetVariable(name); d->m_model->resetVariable(name);
d->m_editor.setEnvironmentItems(d->m_model->userChanges());
} }
// unset in Merged Environment Mode means, unset if it comes from the base environment // unset in Merged Environment Mode means, unset if it comes from the base environment
@@ -463,6 +478,7 @@ void EnvironmentWidget::unsetEnvironmentButtonClicked()
d->m_model->resetVariable(name); d->m_model->resetVariable(name);
else else
d->m_model->unsetVariable(name); d->m_model->unsetVariable(name);
d->m_editor.setEnvironmentItems(d->m_model->userChanges());
} }
void EnvironmentWidget::amendPathList(Utils::NameValueItem::Operation op) void EnvironmentWidget::amendPathList(Utils::NameValueItem::Operation op)
@@ -473,7 +489,7 @@ void EnvironmentWidget::amendPathList(Utils::NameValueItem::Operation op)
return; return;
Utils::NameValueItems changes = d->m_model->userChanges(); Utils::NameValueItems changes = d->m_model->userChanges();
changes.append({varName, dir.toUserOutput(), op}); changes.append({varName, dir.toUserOutput(), op});
d->m_model->setUserChanges(changes); setUserChanges(changes);
} }
void EnvironmentWidget::appendPathButtonClicked() void EnvironmentWidget::appendPathButtonClicked()
@@ -486,16 +502,6 @@ void EnvironmentWidget::prependPathButtonClicked()
amendPathList(Utils::NameValueItem::Prepend); amendPathList(Utils::NameValueItem::Prepend);
} }
void EnvironmentWidget::batchEditEnvironmentButtonClicked()
{
const Utils::EnvironmentItems changes = d->m_model->userChanges();
const auto newChanges = Utils::EnvironmentDialog::getEnvironmentItems(this, changes);
if (newChanges)
d->m_model->setUserChanges(*newChanges);
}
void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &current) void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &current)
{ {
if (current.isValid()) { if (current.isValid()) {

View File

@@ -17,8 +17,6 @@ QT_FORWARD_DECLARE_CLASS(QModelIndex)
namespace ProjectExplorer { namespace ProjectExplorer {
class EnvironmentWidgetPrivate;
class PROJECTEXPLORER_EXPORT EnvironmentWidget : public QWidget class PROJECTEXPLORER_EXPORT EnvironmentWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@@ -51,7 +49,6 @@ private:
void unsetEnvironmentButtonClicked(); void unsetEnvironmentButtonClicked();
void appendPathButtonClicked(); void appendPathButtonClicked();
void prependPathButtonClicked(); void prependPathButtonClicked();
void batchEditEnvironmentButtonClicked();
void environmentCurrentIndexChanged(const QModelIndex &current); void environmentCurrentIndexChanged(const QModelIndex &current);
void invalidateCurrentIndex(); void invalidateCurrentIndex();
void updateSummaryText(); void updateSummaryText();
@@ -62,7 +59,8 @@ private:
using PathListModifier = std::function<QString(const QString &oldList, const QString &newDir)>; using PathListModifier = std::function<QString(const QString &oldList, const QString &newDir)>;
void amendPathList(Utils::NameValueItem::Operation op); void amendPathList(Utils::NameValueItem::Operation op);
const std::unique_ptr<EnvironmentWidgetPrivate> d; class Private;
const std::unique_ptr<Private> d;
}; };
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -1480,8 +1480,7 @@ private:
if (HostOsInfo::isWindowsHost()) if (HostOsInfo::isWindowsHost())
changes.removeAll(forceMSVCEnglishItem()); changes.removeAll(forceMSVCEnglishItem());
return sorted(std::move(changes), [](const EnvironmentItem &lhs, const EnvironmentItem &rhs) return changes;
{ return QString::localeAwareCompare(lhs.name, rhs.name) < 0; });
} }
void initMSVCOutputSwitch(QVBoxLayout *layout) void initMSVCOutputSwitch(QVBoxLayout *layout)