EnvironmentDialog.cxx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "EnvironmentDialog.h"
  4. #include "QCMakeWidgets.h"
  5. #include <QDialogButtonBox>
  6. #include <QGridLayout>
  7. #include <QItemSelectionModel>
  8. #include <QLabel>
  9. #include <QLineEdit>
  10. #include <QMessageBox>
  11. #include <QStandardItem>
  12. EnvironmentItemModel::EnvironmentItemModel(
  13. const QProcessEnvironment& environment, QObject* parent)
  14. : QStandardItemModel(parent)
  15. {
  16. this->clear();
  17. for (auto const& key : environment.keys()) {
  18. auto value = environment.value(key);
  19. this->appendVariable(key, value);
  20. }
  21. }
  22. QProcessEnvironment EnvironmentItemModel::environment() const
  23. {
  24. QProcessEnvironment env;
  25. for (int i = 0; i < this->rowCount(); ++i) {
  26. auto name = this->data(this->index(i, 0), Qt::DisplayRole).toString();
  27. auto value = this->data(this->index(i, 1), Qt::DisplayRole).toString();
  28. env.insert(name, value);
  29. }
  30. return env;
  31. }
  32. void EnvironmentItemModel::clear()
  33. {
  34. this->QStandardItemModel::clear();
  35. QStringList labels;
  36. labels << tr("Name") << tr("Value");
  37. this->setHorizontalHeaderLabels(labels);
  38. }
  39. QModelIndex EnvironmentItemModel::buddy(const QModelIndex& index) const
  40. {
  41. if (index.column() == 0) {
  42. return this->index(index.row(), index.column() + 1, index.parent());
  43. }
  44. return index;
  45. }
  46. void EnvironmentItemModel::appendVariable(const QString& key,
  47. const QString& value)
  48. {
  49. this->insertVariable(this->rowCount(), key, value);
  50. }
  51. void EnvironmentItemModel::insertVariable(int row, const QString& key,
  52. const QString& value)
  53. {
  54. for (int i = 0; i < this->rowCount(); ++i) {
  55. if (this->data(this->index(i, 0), Qt::DisplayRole) == key) {
  56. this->setData(this->index(i, 1), value, Qt::DisplayRole);
  57. return;
  58. }
  59. }
  60. auto* keyItem = new QStandardItem(key);
  61. auto* valueItem = new QStandardItem(value);
  62. this->insertRow(row, { keyItem, valueItem });
  63. }
  64. EnvironmentSearchFilter::EnvironmentSearchFilter(QObject* parent)
  65. : QSortFilterProxyModel(parent)
  66. {
  67. }
  68. bool EnvironmentSearchFilter::filterAcceptsRow(int row,
  69. const QModelIndex& parent) const
  70. {
  71. auto* model = this->sourceModel();
  72. auto key =
  73. model->data(model->index(row, 0, parent), Qt::DisplayRole).toString();
  74. #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
  75. return key.contains(this->filterRegularExpression());
  76. #else
  77. return key.contains(this->filterRegExp());
  78. #endif
  79. }
  80. EnvironmentDialog::EnvironmentDialog(const QProcessEnvironment& environment,
  81. QWidget* parent)
  82. : QDialog(parent)
  83. {
  84. this->setupUi(this);
  85. this->RemoveEntry->setEnabled(false);
  86. this->m_model = new EnvironmentItemModel(environment, this);
  87. this->m_filter = new EnvironmentSearchFilter(this);
  88. this->m_filter->setSourceModel(this->m_model);
  89. this->Environment->setModel(this->m_filter);
  90. this->Environment->setUniformRowHeights(true);
  91. this->Environment->setRootIsDecorated(false);
  92. this->Environment->setSelectionMode(QAbstractItemView::ExtendedSelection);
  93. this->Environment->setSelectionBehavior(QAbstractItemView::SelectRows);
  94. QObject::connect(this->AddEntry, &QAbstractButton::clicked, this,
  95. &EnvironmentDialog::addEntry);
  96. QObject::connect(this->RemoveEntry, &QAbstractButton::clicked, this,
  97. &EnvironmentDialog::removeSelectedEntries);
  98. QObject::connect(
  99. this->Search, &QLineEdit::textChanged, [this](const QString& text) {
  100. const bool valid = QtCMake::setSearchFilter(this->m_filter, text);
  101. QtCMake::setSearchFilterColor(this->Search, valid);
  102. });
  103. QObject::connect(this->Environment->selectionModel(),
  104. &QItemSelectionModel::selectionChanged, this,
  105. &EnvironmentDialog::selectionChanged);
  106. }
  107. QProcessEnvironment EnvironmentDialog::environment() const
  108. {
  109. return this->m_model->environment();
  110. }
  111. void EnvironmentDialog::addEntry()
  112. {
  113. // Build the dialog manually because it's simple enough
  114. QDialog dialog(this);
  115. dialog.setWindowTitle("Add Environment Variable");
  116. auto* layout = new QGridLayout;
  117. dialog.setLayout(layout);
  118. auto* nameLabel = new QLabel;
  119. nameLabel->setText("Name:");
  120. layout->addWidget(nameLabel, 0, 0);
  121. auto* nameEdit = new QLineEdit;
  122. nameEdit->setObjectName("name");
  123. layout->addWidget(nameEdit, 0, 1);
  124. auto* valueLabel = new QLabel;
  125. valueLabel->setText("Value:");
  126. layout->addWidget(valueLabel, 1, 0);
  127. auto* valueEdit = new QLineEdit;
  128. valueEdit->setObjectName("value");
  129. layout->addWidget(valueEdit, 1, 1);
  130. auto* buttons = new QDialogButtonBox;
  131. buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
  132. QObject::connect(
  133. buttons, &QDialogButtonBox::accepted, &dialog,
  134. [this, &dialog, nameEdit]() {
  135. auto text = nameEdit->text();
  136. if (text.isEmpty()) {
  137. QMessageBox::critical(&dialog, "Error", "Name must be non-empty.");
  138. return;
  139. }
  140. auto* model = this->Environment->model();
  141. for (int i = 0; i < model->rowCount(); ++i) {
  142. if (model->data(model->index(i, 0), Qt::DisplayRole) == text) {
  143. QMessageBox::critical(
  144. &dialog, "Error",
  145. tr("Environment variable \"%1\" already exists.").arg(text));
  146. return;
  147. }
  148. }
  149. dialog.accept();
  150. });
  151. QObject::connect(buttons, &QDialogButtonBox::rejected, &dialog,
  152. &QDialog::reject);
  153. layout->addWidget(buttons, 2, 0, 1, 2);
  154. if (dialog.exec() == QDialog::Accepted) {
  155. this->m_model->insertVariable(0, nameEdit->text(), valueEdit->text());
  156. }
  157. }
  158. void EnvironmentDialog::removeSelectedEntries()
  159. {
  160. QModelIndexList idxs = this->Environment->selectionModel()->selectedRows();
  161. QList<QPersistentModelIndex> pidxs;
  162. foreach (QModelIndex const& i, idxs) {
  163. pidxs.append(i);
  164. }
  165. foreach (QPersistentModelIndex const& pi, pidxs) {
  166. this->Environment->model()->removeRow(pi.row(), pi.parent());
  167. }
  168. }
  169. void EnvironmentDialog::selectionChanged()
  170. {
  171. auto selected = this->Environment->selectionModel()->selectedRows();
  172. this->RemoveEntry->setEnabled(!selected.isEmpty());
  173. }