EnvironmentDialog.cxx 6.3 KB

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