blob: 846456c8e34e25b1af7a55d5593955502d495bb8 [file] [log] [blame]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "EnvironmentDialog.h"
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QItemSelectionModel>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QStandardItem>
EnvironmentItemModel::EnvironmentItemModel(
const QProcessEnvironment& environment, QObject* parent)
: QStandardItemModel(parent)
{
this->clear();
for (auto const& key : environment.keys()) {
auto value = environment.value(key);
this->appendVariable(key, value);
}
}
QProcessEnvironment EnvironmentItemModel::environment() const
{
QProcessEnvironment env;
for (int i = 0; i < this->rowCount(); ++i) {
auto name = this->data(this->index(i, 0), Qt::DisplayRole).toString();
auto value = this->data(this->index(i, 1), Qt::DisplayRole).toString();
env.insert(name, value);
}
return env;
}
void EnvironmentItemModel::clear()
{
this->QStandardItemModel::clear();
QStringList labels;
labels << tr("Name") << tr("Value");
this->setHorizontalHeaderLabels(labels);
}
QModelIndex EnvironmentItemModel::buddy(const QModelIndex& index) const
{
if (index.column() == 0) {
return this->index(index.row(), index.column() + 1, index.parent());
}
return index;
}
void EnvironmentItemModel::appendVariable(const QString& key,
const QString& value)
{
this->insertVariable(this->rowCount(), key, value);
}
void EnvironmentItemModel::insertVariable(int row, const QString& key,
const QString& value)
{
for (int i = 0; i < this->rowCount(); ++i) {
if (this->data(this->index(i, 0), Qt::DisplayRole) == key) {
this->setData(this->index(i, 1), value, Qt::DisplayRole);
return;
}
}
auto* keyItem = new QStandardItem(key);
auto* valueItem = new QStandardItem(value);
this->insertRow(row, { keyItem, valueItem });
}
EnvironmentSearchFilter::EnvironmentSearchFilter(QObject* parent)
: QSortFilterProxyModel(parent)
{
}
bool EnvironmentSearchFilter::filterAcceptsRow(int row,
const QModelIndex& parent) const
{
auto* model = this->sourceModel();
auto key =
model->data(model->index(row, 0, parent), Qt::DisplayRole).toString();
return key.contains(this->filterRegExp());
}
EnvironmentDialog::EnvironmentDialog(const QProcessEnvironment& environment,
QWidget* parent)
: QDialog(parent)
{
this->setupUi(this);
this->RemoveEntry->setEnabled(false);
this->m_model = new EnvironmentItemModel(environment, this);
this->m_filter = new EnvironmentSearchFilter(this);
this->m_filter->setSourceModel(this->m_model);
this->Environment->setModel(this->m_filter);
this->Environment->setUniformRowHeights(true);
this->Environment->setRootIsDecorated(false);
this->Environment->setSelectionMode(QAbstractItemView::ExtendedSelection);
this->Environment->setSelectionBehavior(QAbstractItemView::SelectRows);
QObject::connect(this->AddEntry, &QToolButton::clicked, this,
&EnvironmentDialog::addEntry);
QObject::connect(this->RemoveEntry, &QToolButton::clicked, this,
&EnvironmentDialog::removeSelectedEntries);
QObject::connect(this->Search, &QLineEdit::textChanged, this->m_filter,
&EnvironmentSearchFilter::setFilterFixedString);
QObject::connect(this->Environment->selectionModel(),
&QItemSelectionModel::selectionChanged, this,
&EnvironmentDialog::selectionChanged);
}
QProcessEnvironment EnvironmentDialog::environment() const
{
return this->m_model->environment();
}
void EnvironmentDialog::addEntry()
{
// Build the dialog manually because it's simple enough
QDialog dialog(this);
dialog.setWindowTitle("Add Environment Variable");
auto* layout = new QGridLayout;
dialog.setLayout(layout);
auto* nameLabel = new QLabel;
nameLabel->setText("Name:");
layout->addWidget(nameLabel, 0, 0);
auto* nameEdit = new QLineEdit;
nameEdit->setObjectName("name");
layout->addWidget(nameEdit, 0, 1);
auto* valueLabel = new QLabel;
valueLabel->setText("Value:");
layout->addWidget(valueLabel, 1, 0);
auto* valueEdit = new QLineEdit;
valueEdit->setObjectName("value");
layout->addWidget(valueEdit, 1, 1);
auto* buttons = new QDialogButtonBox;
buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
QObject::connect(
buttons, &QDialogButtonBox::accepted, &dialog,
[this, &dialog, nameEdit]() {
auto text = nameEdit->text();
if (text.isEmpty()) {
QMessageBox::critical(&dialog, "Error", "Name must be non-empty.");
return;
}
auto* model = this->Environment->model();
for (int i = 0; i < model->rowCount(); ++i) {
if (model->data(model->index(i, 0), Qt::DisplayRole) == text) {
QMessageBox::critical(
&dialog, "Error",
tr("Environment variable \"%1\" already exists.").arg(text));
return;
}
}
dialog.accept();
});
QObject::connect(buttons, &QDialogButtonBox::rejected, &dialog,
&QDialog::reject);
layout->addWidget(buttons, 2, 0, 1, 2);
if (dialog.exec() == QDialog::Accepted) {
this->m_model->insertVariable(0, nameEdit->text(), valueEdit->text());
}
}
void EnvironmentDialog::removeSelectedEntries()
{
QModelIndexList idxs = this->Environment->selectionModel()->selectedRows();
QList<QPersistentModelIndex> pidxs;
foreach (QModelIndex const& i, idxs) {
pidxs.append(i);
}
foreach (QPersistentModelIndex const& pi, pidxs) {
this->Environment->model()->removeRow(pi.row(), pi.parent());
}
}
void EnvironmentDialog::selectionChanged()
{
auto selected = this->Environment->selectionModel()->selectedRows();
this->RemoveEntry->setEnabled(!selected.isEmpty());
}