1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "environmentview.h"
6
7#include <QVBoxLayout>
8#include <QCheckBox>
9#include <QHeaderView>
10#include <QTableView>
11#include <QProcessEnvironment>
12
13class EnvironmentModelPrivate
14{
15 friend class EnvironmentModel;
16 QMap<QString, QVariant> envs;
17};
18
19EnvironmentModel::EnvironmentModel(QObject *parent)
20 : QAbstractTableModel(parent)
21 , d (new EnvironmentModelPrivate())
22{
23
24}
25
26EnvironmentModel::~EnvironmentModel()
27{
28 if (d)
29 delete d;
30}
31
32int EnvironmentModel::rowCount(const QModelIndex &) const
33{
34 return d->envs.keys().size();
35}
36
37int EnvironmentModel::columnCount(const QModelIndex &) const
38{
39 return ColumnCount;
40}
41
42QVariant EnvironmentModel::data(const QModelIndex &index, int role) const
43{
44 if (role == Qt::DisplayRole || role == Qt::EditRole) {
45 auto var = d->envs.keys()[index.row()];
46 switch (index.column()) {
47 case Key:
48 return var;
49 case Value:
50 return d->envs.value(var);
51 default:
52 break;
53 }
54 }
55 return {};
56}
57
58bool EnvironmentModel::setData(const QModelIndex &index, const QVariant &value, int role)
59{
60 if (!index.isValid() || role != Qt::EditRole)
61 return false;
62
63 if (data(index, role) == value)
64 return true;
65
66 const QString oldName = data(this->index(index.row(), 0, QModelIndex())).toString();
67 const QString oldValue = data(this->index(index.row(), 1, QModelIndex()), Qt::EditRole).toString();
68 QMap<QString, QVariant> map = d->envs;
69 if (index.column() == Key) {
70 const QString newName = value.toString();
71 if (newName.isEmpty() || newName.contains("="))
72 return false;
73 if (map.contains(newName) || newName.isEmpty())
74 return false;
75 map.remove(oldName);
76 map.insert(value.toString(), oldValue);
77 } else if (index.column() == Value) {
78 const QString stringValue = value.toString();
79 auto var = map.keys()[index.row()];
80 map[var] = stringValue;
81 }
82 update(map);
83 emit dataChanged(index, index);
84 return true;
85}
86
87Qt::ItemFlags EnvironmentModel::flags(const QModelIndex &index) const
88{
89 Q_UNUSED(index);
90 return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
91}
92
93QVariant EnvironmentModel::headerData(int section, Qt::Orientation orientation, int role) const
94{
95 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
96 switch (section) {
97 case Key:
98 return QObject::tr("Variable");
99 case Value:
100 return QObject::tr("Value");
101 default:
102 break;
103 }
104 }
105 return {};
106}
107
108void EnvironmentModel::append(const QString &key, const QVariant &value)
109{
110 beginInsertRows({}, d->envs.keys().count(), d->envs.keys().count());
111 d->envs.insert(key, value);
112 endInsertRows();
113}
114
115void EnvironmentModel::remove(QModelIndex &index)
116{
117 if (d->envs.keys().isEmpty() || index.row() < 0)
118 return;
119
120 beginRemoveRows({}, d->envs.keys().count(), d->envs.keys().count());
121 QString key = d->envs.keys()[index.row()];
122 d->envs.remove(key);
123 endRemoveRows();
124}
125
126void EnvironmentModel::update(const QMap<QString, QVariant> &data)
127{
128 beginResetModel();
129 d->envs.clear();
130 d->envs = data;
131 endResetModel();
132}
133
134const QMap<QString, QVariant> EnvironmentModel::getEnvironment() const
135{
136 return d->envs;
137}
138
139class EnvironmentViewPrivate
140{
141 friend class EnvironmentView;
142
143 QVBoxLayout *vLayout = nullptr;
144 QTableView *tableView = nullptr;
145 EnvironmentModel *model = nullptr;
146};
147
148EnvironmentView::EnvironmentView(QWidget *parent)
149 : QWidget(parent)
150 , d(new EnvironmentViewPrivate)
151{
152 setAutoFillBackground(true);
153
154 if (!d->vLayout)
155 d->vLayout = new QVBoxLayout();
156 this->setLayout(d->vLayout);
157
158 if (!d->tableView) {
159 d->tableView = new QTableView();
160 d->tableView->setShowGrid(false);
161 QHeaderView* headerView = d->tableView->horizontalHeader();
162 headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
163 d->tableView->verticalHeader()->hide();
164 d->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
165 d->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
166 }
167
168 if (!d->model)
169 d->model = new EnvironmentModel();
170
171 d->tableView->setModel(d->model);
172
173 d->vLayout->setSpacing(0);
174 d->vLayout->setMargin(0);
175 d->vLayout->addWidget(d->tableView);
176
177 connect(d->tableView->selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex &current){
178 if (current.isValid() || d->tableView->selectionModel()->hasSelection()) {
179 emit deleteSignal(true);
180 } else {
181 emit deleteSignal(false);
182 }
183 });
184
185 initModel();
186}
187
188EnvironmentView::~EnvironmentView()
189{
190 if(d)
191 delete d;
192}
193
194const QMap<QString, QVariant> EnvironmentView::getEnvironment()
195{
196 return d->model->getEnvironment();
197}
198
199void EnvironmentView::appendRow()
200{
201 d->model->append("<KEY>", "<VALUE>");
202}
203
204void EnvironmentView::deleteRow()
205{
206 QModelIndex index = d->tableView->currentIndex();
207 d->model->remove(index);
208}
209
210void EnvironmentView::initModel()
211{
212 QMap<QString, QVariant> envs;
213 QStringList keys = QProcessEnvironment::systemEnvironment().keys();
214 for (auto key : keys) {
215 QString value = QProcessEnvironment::systemEnvironment().value(key);
216 envs.insert(key, value);
217 }
218
219 d->model->update(envs);
220 emit deleteSignal(false);
221}
222
223void EnvironmentView::setValue(const QMap<QString, QVariant> &map)
224{
225 d->model->update(map);
226}
227
228
229
230