1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "mavenprojectgenerator.h"
6#include "mavenasynparse.h"
7#include "maven/project/properties/mavenconfigpropertywidget.h"
8
9#include "services/window/windowservice.h"
10#include "services/builder/builderservice.h"
11
12#include "common/dialog/propertiesdialog.h"
13#include "properties/mavenconfigutil.h"
14#include "common/util/custompaths.h"
15#include "common/util/environment.h"
16#include "common/supportfile/dapconfig.h"
17#include "services/project/projectservice.h"
18
19#include <QtXml>
20#include <QFileIconProvider>
21
22using namespace mavenConfig;
23using namespace dpfservice;
24class MavenProjectGeneratorPrivate
25{
26 friend class MavenProjectGenerator;
27 QStandardItem* configureRootItem {nullptr};
28 QMenu *mavenMenu {nullptr};
29 QHash<QStandardItem*, MavenAsynParse*> projectParses {};
30};
31
32MavenProjectGenerator::MavenProjectGenerator()
33 : d(new MavenProjectGeneratorPrivate())
34{
35 using namespace dpfservice;
36 auto &ctx = dpfInstance.serviceContext();
37 BuilderService *builderService = ctx.service<BuilderService>(BuilderService::name());
38 if (!builderService) {
39 qCritical() << "Failed, not found service : builderService";
40 abort();
41 }
42}
43
44MavenProjectGenerator::~MavenProjectGenerator()
45{
46 qInfo() << __FUNCTION__;
47
48 if (d)
49 delete d;
50}
51
52QStringList MavenProjectGenerator::supportLanguages()
53{
54 return {dpfservice::MWMFA_JAVA};
55}
56
57QStringList MavenProjectGenerator::supportFileNames()
58{
59 return {"pom.xml"};
60}
61
62QDialog *MavenProjectGenerator::configureWidget(const QString &language,
63 const QString &workspace)
64{
65 // get config result.
66 ProjectInfo projectInfo;
67 projectInfo.setLanguage(language);
68 projectInfo.setKitName(MavenProjectGenerator::toolKitName());
69 projectInfo.setWorkspaceFolder(workspace);
70
71 // refresh config.
72 restoreRuntimeCfg(projectInfo);
73 configure(projectInfo);
74
75 return nullptr;
76}
77
78bool MavenProjectGenerator::configure(const dpfservice::ProjectInfo &info)
79{
80 dpfservice::ProjectGenerator::configure(info);
81
82 auto root = createRootItem(info);
83 using namespace dpfservice;
84 auto &ctx = dpfInstance.serviceContext();
85 ProjectService *projectService = ctx.service<ProjectService>(ProjectService::name());
86 if (projectService && root) {
87 projectService->projectView.addRootItem(root);
88 projectService->projectView.expandedDepth(root, 1);
89 }
90
91 return true;
92}
93
94QStandardItem *MavenProjectGenerator::createRootItem(const dpfservice::ProjectInfo &info)
95{
96 using namespace dpfservice;
97 QStandardItem *rootItem = ProjectGenerator::createRootItem(info);
98 dpfservice::ProjectInfo::set(rootItem, info);
99 d->projectParses[rootItem] = new MavenAsynParse();
100 QObject::connect(d->projectParses[rootItem], &MavenAsynParse::itemsModified,
101 this, &MavenProjectGenerator::itemModified);
102 QMetaObject::invokeMethod(d->projectParses[rootItem], "parseProject",
103 Q_ARG(const dpfservice::ProjectInfo &, info));
104 return rootItem;
105}
106
107void MavenProjectGenerator::removeRootItem(QStandardItem *root)
108{
109 if (!root)
110 return;
111 auto parser = d->projectParses[root];
112
113 while (root->hasChildren()) {
114 root->takeRow(0);
115 }
116 d->projectParses.remove(root);
117
118 delete root;
119
120 if (parser)
121 delete parser;
122}
123
124QMenu *MavenProjectGenerator::createItemMenu(const QStandardItem *item)
125{
126 if (item->parent())
127 return nullptr;
128
129 QMenu *menu = new QMenu();
130 if (!d->mavenMenu) {
131 d->mavenMenu = new QMenu("Maven", menu);
132 QObject::connect(d->mavenMenu, &QMenu::destroyed,
133 [=](){
134 d->mavenMenu = nullptr;
135 });
136 }
137
138 menu->addMenu(d->mavenMenu);
139
140 // asyn parse
141 using namespace dpfservice;
142
143 QStandardItem *itemTemp = const_cast<QStandardItem *>(item);
144 if (!itemTemp)
145 return d->mavenMenu;
146
147 auto parse = d->projectParses[itemTemp];
148 if (!parse)
149 return d->mavenMenu;
150
151 ProjectInfo info = ProjectInfo::get(item);
152 if (info.isEmpty())
153 return d->mavenMenu;
154
155 // add menu generat call back
156 QObject::connect(parse, &MavenAsynParse::parsedActions,
157 this, &MavenProjectGenerator::doAddMavenMeue,
158 Qt::UniqueConnection);
159 // execute logic
160 parse->parseActions(info);
161
162 QAction *action = new QAction(tr("Properties"));
163 menu->addAction(action);
164 QObject::connect(action, &QAction::triggered, [=](){
165 actionProperties(info, itemTemp);
166 });
167
168 return menu;
169}
170
171void MavenProjectGenerator::itemModified(const QList<QStandardItem *> &items)
172{
173 MavenAsynParse *parse = qobject_cast<MavenAsynParse*>(sender());
174 if (parse) {
175 auto root = d->projectParses.key(parse);
176 emit itemChanged(root, items);
177 }
178}
179
180void MavenProjectGenerator::doAddMavenMeue(const dpfservice::ProjectActionInfos &infos)
181{
182 if (d->mavenMenu) {
183 for (auto actionInfo : infos) {
184 QAction *action = new QAction(actionInfo.displyText, d->mavenMenu);
185 dpfservice::ProjectMenuActionInfo::set(action, actionInfo);
186 d->mavenMenu->addAction(action);
187 QObject::connect(action, &QAction::triggered,
188 this, &MavenProjectGenerator::doActionTriggered,
189 Qt::UniqueConnection);
190 }
191 }
192}
193
194void MavenProjectGenerator::doActionTriggered()
195{
196 QAction *action = qobject_cast<QAction*>(sender());
197 if (action) {
198 auto value = dpfservice::ProjectMenuActionInfo::get(action);
199
200 auto &ctx = dpfInstance.serviceContext();
201 auto builderService = ctx.service<dpfservice::BuilderService>(dpfservice::BuilderService::name());
202 if (builderService) {
203 BuildCommandInfo commandInfo;
204 commandInfo.kitName = toolKitName();
205 commandInfo.program = value.buildProgram;
206 commandInfo.arguments = value.buildArguments;
207 commandInfo.workingDir = QFileInfo(value.workingDirectory).path();
208 builderService->interface.builderCommand({commandInfo}, false);
209 }
210 }
211}
212
213void MavenProjectGenerator::actionProperties(const dpfservice::ProjectInfo &info, QStandardItem *item)
214{
215 PropertiesDialog dlg;
216 MavenConfigPropertyWidget *property = new MavenConfigPropertyWidget(info, item);
217 dlg.insertPropertyPanel("Config", property);
218 dlg.exec();
219}
220
221void MavenProjectGenerator::restoreRuntimeCfg(dpfservice::ProjectInfo &projectInfo)
222{
223 // get project config.
224 ConfigureParam *cfgParams = ConfigUtil::instance()->getConfigureParamPointer();
225 ConfigUtil::instance()->readConfig(ConfigUtil::instance()->getConfigPath(projectInfo.workspaceFolder()), *cfgParams);
226
227 // get global config.
228 QString arch = ProcessUtil::localPlatform();
229 QString dapSupportFilePath = support_file::DapSupportConfig::globalPath();
230 QString configHomePath = env::pkg::native::path();// CustomPaths::user(CustomPaths::Configures) + QDir::separator();
231 support_file::JavaDapPluginConfig javaDapPluginConfig;
232 bool ret = support_file::DapSupportConfig::readFromSupportFile(dapSupportFilePath, arch, javaDapPluginConfig, configHomePath);
233 if (!ret) {
234 qDebug("Read dapconfig.support failed, please check the file and retry.");
235 return;
236 }
237
238 // use global config when project config is null.
239 auto setPropertyParams = [&](QString &projectProperty, const QString &key, const QString &globalPropery){
240 if (projectProperty.isEmpty()) {
241 // use global propery.
242 projectInfo.setProperty(key, globalPropery);
243 projectProperty = globalPropery;
244 } else {
245 // use project propery.
246 projectInfo.setProperty(key, projectProperty);
247 }
248 };
249 setPropertyParams(cfgParams->jrePath, kJrePath, javaDapPluginConfig.jrePath);
250 setPropertyParams(cfgParams->jreExecute, kJreExecute, javaDapPluginConfig.jreExecute);
251 setPropertyParams(cfgParams->launchConfigPath, kLaunchConfigPath, javaDapPluginConfig.launchConfigPath);
252 setPropertyParams(cfgParams->launchPackageFile, kLaunchPackageFile, javaDapPluginConfig.launchPackageFile);
253 setPropertyParams(cfgParams->dapPackageFile, kDapPackageFile, javaDapPluginConfig.dapPackageFile);
254 projectInfo.setDetailInformation(cfgParams->detailInfo);
255}
256