1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "configwidget.h"
6#include "services/project/projectservice.h"
7#include "common/util/custompaths.h"
8
9#include <QtCore/QVariant>
10#include <QtWidgets/QApplication>
11#include <QtWidgets/QComboBox>
12#include <QtWidgets/QGridLayout>
13#include <QtWidgets/QHBoxLayout>
14#include <QtWidgets/QLabel>
15#include <QtWidgets/QPushButton>
16#include <QtWidgets/QSpacerItem>
17#include <QtWidgets/QVBoxLayout>
18#include <QtWidgets/QWidget>
19
20static const char *kConfigFileName = "codeporting.cfg";
21static const char *kSrcCPU = "Src CPU";
22static const char *kTargetCPU = "Target CPU";
23
24// TODO(mozart):These value should get from backend later.
25static const char *kX86_64 = "x86_64";
26static const char *kArm = "arm64";
27static const char *kMips = "mips64el";
28static const char *kSW_64 = "sw_64";
29static const char *kLoongarch64 = "loongarch64";
30
31static const char *kSupportKit [] = {"cmake"};
32
33using namespace dpfservice;
34
35struct ConfigParameter
36{
37 QString project;
38 QString srcCPU;
39 QString targetCPU;
40 QString reserve;
41};
42
43class ConfigWidgetPrivate
44{
45 friend ConfigWidget;
46 QVBoxLayout *verticalLayout = nullptr;
47 QGridLayout *gridLayout = nullptr;
48 QLabel *lbProject = nullptr;
49 QComboBox *combProject = nullptr;
50 QLabel *lbSrc = nullptr;
51 QComboBox *combSrc = nullptr;
52 QLabel *lbTarget = nullptr;
53 QComboBox *combTarget = nullptr;
54 QSpacerItem *verticalSpacer = nullptr;
55 QHBoxLayout *horizontalLayout = nullptr;
56 QSpacerItem *horizontalSpacer = nullptr;
57 QPushButton *btnPoting = nullptr;
58 QPushButton *btnCancel = nullptr;
59 QLabel *lbWarning = nullptr;
60
61 ConfigParameter cfgParam;
62};
63
64ConfigWidget::ConfigWidget(QWidget *parent)
65 : QDialog(parent)
66 , d(new ConfigWidgetPrivate)
67{
68 setupUi(this);
69
70 initializeUi();
71
72 if (!restore()) {
73 setDefaultValue();
74 }
75
76 connect(d->btnPoting, &QPushButton::clicked, this, &ConfigWidget::configDone);
77 connect(d->btnCancel, &QPushButton::clicked, this, &ConfigWidget::reject);
78}
79
80void ConfigWidget::configDone()
81{
82 d->cfgParam.project = d->combProject->currentText();
83 d->cfgParam.srcCPU = d->combSrc->currentText();
84 d->cfgParam.targetCPU = d->combTarget->currentText();
85
86 // empty parameter check.
87 if (d->cfgParam.project.isEmpty()
88 || d->cfgParam.srcCPU.isEmpty()
89 || d->cfgParam.targetCPU.isEmpty()) {
90 d->lbWarning->setText(tr("Warning: parameter is empty!"));
91 return;
92 }
93
94 // repeat paramter check.
95 if (d->cfgParam.srcCPU == d->cfgParam.targetCPU) {
96 d->lbWarning->setText(tr("Warning: source cpu and target cpu should not be the same!"));
97 return;
98 }
99
100 saveCfg();
101
102 accept();
103
104 d->lbWarning->clear();
105
106 emit sigStartPorting(d->cfgParam.project, d->cfgParam.srcCPU, d->cfgParam.targetCPU);
107}
108
109void ConfigWidget::showEvent(QShowEvent *e)
110{
111 refreshUi();
112
113 QDialog::showEvent(e);
114}
115
116void ConfigWidget::initializeUi()
117{
118 d->combSrc->addItem(kX86_64);
119 d->combSrc->addItem(kArm);
120 d->combSrc->addItem(kMips);
121 d->combSrc->addItem(kSW_64);
122 d->combSrc->addItem(kLoongarch64);
123
124 d->combTarget->addItem(kX86_64);
125 d->combTarget->addItem(kArm);
126 d->combTarget->addItem(kMips);
127 d->combTarget->addItem(kSW_64);
128 d->combTarget->addItem(kLoongarch64);
129}
130
131void ConfigWidget::setDefaultValue()
132{
133 d->cfgParam.srcCPU = "x86_64";
134 d->cfgParam.targetCPU = "arm64";
135}
136
137void ConfigWidget::setupUi(QWidget *Widget)
138{
139 Widget->setWindowTitle(tr("CodePorting config"));
140 Widget->resize(500, 200);
141 d->verticalLayout = new QVBoxLayout(Widget);
142 d->verticalLayout->setSpacing(6);
143 d->verticalLayout->setContentsMargins(11, 11, 11, 11);
144 d->verticalLayout->setContentsMargins(40, 20, 40, 20);
145 d->gridLayout = new QGridLayout();
146 d->gridLayout->setSpacing(6);
147 d->lbProject = new QLabel(Widget);
148 d->lbProject->setText(tr("Project:"));
149
150 d->gridLayout->addWidget(d->lbProject, 0, 0, 1, 1);
151
152 d->combProject = new QComboBox(Widget);
153
154 d->gridLayout->addWidget(d->combProject, 0, 1, 1, 1);
155
156 d->lbSrc = new QLabel(Widget);
157 d->lbSrc->setText(tr("Source CPU Architecture:"));
158
159 d->gridLayout->addWidget(d->lbSrc, 1, 0, 1, 1);
160
161 d->combSrc = new QComboBox(Widget);
162
163 d->gridLayout->addWidget(d->combSrc, 1, 1, 1, 1);
164
165 d->lbTarget = new QLabel(Widget);
166 d->lbTarget->setText(tr("Target CPU Architecture:"));
167
168 d->gridLayout->addWidget(d->lbTarget, 2, 0, 1, 1);
169
170 d->combTarget = new QComboBox(Widget);
171
172 d->gridLayout->addWidget(d->combTarget, 2, 1, 1, 1);
173
174 d->verticalLayout->addLayout(d->gridLayout);
175
176 d->lbWarning = new QLabel(Widget);
177 QPalette pe;
178 pe.setColor(QPalette::Text, Qt::yellow);
179 d->lbWarning->setPalette(pe);
180
181 d->verticalLayout->addWidget(d->lbWarning);
182
183 d->verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
184
185 d->verticalLayout->addItem(d->verticalSpacer);
186
187 d->horizontalLayout = new QHBoxLayout();
188 d->horizontalSpacer = new QSpacerItem(40, 30, QSizePolicy::Expanding, QSizePolicy::Minimum);
189
190 d->horizontalLayout->addItem(d->horizontalSpacer);
191
192 d->btnPoting = new QPushButton(Widget);
193 d->btnPoting->setText(tr("Porting"));
194 d->btnPoting->setDefault(true);
195
196 d->horizontalLayout->addWidget(d->btnPoting);
197
198 d->btnCancel = new QPushButton(Widget);
199 d->btnCancel->setText(tr("Cancel"));
200
201 d->horizontalLayout->addWidget(d->btnCancel);
202
203 d->verticalLayout->addLayout(d->horizontalLayout);
204}
205
206void ConfigWidget::resetUi()
207{
208 int emptyIndex = -1;
209 d->combProject->setCurrentIndex(emptyIndex);
210 d->combSrc->setCurrentIndex(emptyIndex);
211 d->combTarget->setCurrentIndex(emptyIndex);
212}
213
214void ConfigWidget::refreshDetail()
215{
216 d->combSrc->setCurrentText(d->cfgParam.srcCPU);
217 d->combTarget->setCurrentText(d->cfgParam.targetCPU);
218}
219
220bool ConfigWidget::saveCfg()
221{
222 QString cfgFilePath = configFilePath();
223
224 QJsonArray paramsArray;
225
226 QJsonObject valueObj;
227 valueObj.insert(kSrcCPU, d->cfgParam.srcCPU);
228 valueObj.insert(kTargetCPU, d->cfgParam.targetCPU);
229
230 paramsArray.append(valueObj);
231
232 QJsonObject rootObject;
233 rootObject.insert("Configure", paramsArray);
234 QJsonDocument doc;
235 doc.setObject(rootObject);
236 QString jsonStr(doc.toJson(QJsonDocument::Indented));
237
238 QFile file(cfgFilePath);
239 if (!file.open(QIODevice::WriteOnly))
240 return false;
241
242 file.write(jsonStr.toUtf8());
243 file.close();
244
245 return true;
246}
247
248bool ConfigWidget::restore()
249{
250 QString cfgFilePath = configFilePath();
251
252 QFile file(cfgFilePath);
253 if (!file.open(QIODevice::ReadOnly))
254 return false;
255
256 QByteArray data = file.readAll();
257 file.close();
258
259 QJsonParseError parseError;
260 QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
261 if (QJsonParseError::NoError != parseError.error) {
262 return false;
263 }
264
265 if (!doc.isObject())
266 return false;
267
268 QJsonObject rootObject = doc.object();
269 for (auto key : rootObject.keys()) {
270 if (!rootObject.value(key).isArray() || !rootObject.keys().contains("Configure"))
271 continue;
272
273 if (rootObject.keys().contains("Configure")) {
274 QJsonArray valueArray = rootObject.value("Configure").toArray();
275
276 for (QJsonValue value : valueArray) {
277 QJsonObject obj = value.toObject();
278 d->cfgParam.srcCPU = obj.value(kSrcCPU).toString();
279 d->cfgParam.targetCPU = obj.value(kTargetCPU).toString();
280 }
281 }
282 }
283 return true;
284}
285
286QString ConfigWidget::configFilePath()
287{
288 return CustomPaths::endSeparator(CustomPaths::user(CustomPaths::Configures)) + kConfigFileName;
289}
290
291void ConfigWidget::refreshUi()
292{
293 auto &ctx = dpfInstance.serviceContext();
294 ProjectService *projectService = ctx.service<ProjectService>(ProjectService::name());
295 d->combProject->clear();
296 if (projectService && projectService->getAllProjectInfo) {
297 auto allInfo = projectService->getAllProjectInfo();
298 if (allInfo.isEmpty()) {
299 resetUi();
300 return;
301 } else {
302 for (auto projInfo : allInfo) {
303 QString path = projInfo.workspaceFolder();
304 QString dirName = path.split("/").back();
305 QString kitName = projInfo.kitName();
306 int supportkitCount = sizeof(kSupportKit)/sizeof(kSupportKit[0]);
307 for (int i = 0; i < supportkitCount; ++i) {
308 if (kSupportKit[i] == projInfo.kitName()) {
309 d->combProject->addItem(dirName);
310 break;
311 }
312 }
313 }
314 }
315 }
316 refreshDetail();
317}
318