1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "mavenasynparse.h"
6#include "services/project/projectgenerator.h"
7#include "services/option/optionmanager.h"
8
9#include "common/common.h"
10
11#include <QAction>
12#include <QDebug>
13#include <QtXml>
14
15static QString kSupportArgs[] = {"clean", "compiler:compile", "compiler:testCompile",
16 "package", "install", "validate", "dependency:tree",
17 "dependency:analyze", "site:site", "compile", "verify"};
18
19class MavenAsynParsePrivate
20{
21 friend class MavenAsynParse;
22 QDomDocument xmlDoc;
23 QThread *thread {nullptr};
24 QString rootPath;
25 QList<QStandardItem *> rows {};
26};
27
28MavenAsynParse::MavenAsynParse()
29 : d(new MavenAsynParsePrivate)
30{
31
32 QObject::connect(this, &QFileSystemWatcher::directoryChanged,
33 this, &MavenAsynParse::doDirectoryChanged);
34
35 d->thread = new QThread();
36 this->moveToThread(d->thread);
37 d->thread->start();
38}
39
40MavenAsynParse::~MavenAsynParse()
41{
42 if (d) {
43 if (d->thread) {
44 if (d->thread->isRunning())
45 d->thread->quit();
46 d->thread->wait();
47 d->thread->deleteLater();
48 d->thread = nullptr;
49 }
50 delete d;
51 }
52}
53
54void MavenAsynParse::loadPoms(const dpfservice::ProjectInfo &info)
55{
56 QFile docFile(info.workspaceFolder() + QDir::separator() + "pom.xml");
57
58 if (!docFile.exists()) {
59 parsedError("Failed, maven pro not exists!: " + docFile.fileName());
60 }
61
62 if (!docFile.open(QFile::OpenModeFlag::ReadOnly)) {;
63 parsedError(docFile.errorString());
64 }
65
66 if (!d->xmlDoc.setContent(&docFile)) {
67 docFile.close();
68 }
69 docFile.close();
70}
71
72void MavenAsynParse::parseProject(const dpfservice::ProjectInfo &info)
73{
74 createRows(info.workspaceFolder());
75 emit itemsModified(d->rows);
76}
77
78// TODO(mozart):get from tool or config.
79void MavenAsynParse::parseActions(const dpfservice::ProjectInfo &info)
80{
81 using namespace dpfservice;
82 ProjectInfo proInfo = info;
83 if (proInfo.isEmpty()) {
84 return;
85 }
86
87 ProjectActionInfos actionInfos;
88 auto addAction = [&](QString &arg){
89 ProjectMenuActionInfo actionInfo;
90 actionInfo.buildProgram = OptionManager::getInstance()->getMavenToolPath();
91 actionInfo.workingDirectory = info.workspaceFolder() + QDir::separator() + "pom.xml";
92 actionInfo.buildArguments.append(arg);
93 actionInfo.displyText = arg;
94 actionInfo.tooltip = arg;
95 actionInfos.append(actionInfo);
96 };
97
98 for (auto arg : kSupportArgs) {
99 addAction(arg);
100 }
101
102 emit parsedActions(actionInfos);
103}
104
105void MavenAsynParse::doDirectoryChanged(const QString &path)
106{
107 if (!path.startsWith(d->rootPath))
108 return;
109
110 d->rows.clear();
111
112 createRows(d->rootPath);
113
114 emit itemsModified(d->rows);
115}
116
117void MavenAsynParse::createRows(const QString &path)
118{
119 QString rootPath = path;
120 if (rootPath.endsWith(QDir::separator())) {
121 int separatorSize = QString(QDir::separator()).size();
122 rootPath = rootPath.remove(rootPath.size() - separatorSize, separatorSize);
123 }
124
125 // 缓存当前工程目录
126 d->rootPath = rootPath;
127 QFileSystemWatcher::addPath(d->rootPath);
128
129 {// 避免变量冲突 迭代文件夹
130 QDir dir;
131 dir.setPath(rootPath);
132 dir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
133 dir.setSorting(QDir::Name);
134 QDirIterator dirItera(dir, QDirIterator::Subdirectories);
135 while (dirItera.hasNext()) {
136 QString childPath = dirItera.next().remove(0, rootPath.size());
137 QFileSystemWatcher::addPath(dirItera.filePath());
138 QStandardItem *item = findItem(childPath);
139 QIcon icon = CustomIcons::icon(dirItera.fileInfo());
140 auto newItem = new QStandardItem(icon, dirItera.fileName());
141 newItem->setToolTip(dirItera.filePath());
142 if (!item) {
143 d->rows.append(newItem);
144 } else {
145 item->appendRow(newItem);
146 }
147 }
148 }
149 {// 避免变量冲突 迭代文件
150 QDir dir;
151 dir.setPath(rootPath);
152 dir.setFilter(QDir::NoDotAndDotDot | QDir::Files);
153 dir.setSorting(QDir::Name);
154 QDirIterator fileItera(dir, QDirIterator::Subdirectories);
155 while (fileItera.hasNext()) {
156 QString childPath = fileItera.next().remove(0, rootPath.size());
157 QStandardItem *item = findItem(childPath);
158 QIcon icon = CustomIcons::icon(fileItera.fileInfo());
159 auto newItem = new QStandardItem(icon, fileItera.fileName());
160 newItem->setToolTip(fileItera.filePath());
161 if (!item) {
162 d->rows.append(newItem);
163 } else {
164 item->appendRow(newItem);
165 }
166 }
167 }
168}
169
170QList<QStandardItem *> MavenAsynParse::rows(const QStandardItem *item) const
171{
172 QList<QStandardItem *> result;
173 for (int i = 0; i < item->rowCount(); i++) {
174 result << item->child(i);
175 }
176 return result;
177}
178
179QStandardItem *MavenAsynParse::findItem(const QString &path,
180 QStandardItem *parent) const
181{
182 QString pathTemp = path;
183 if (pathTemp.endsWith(QDir::separator())) {
184 pathTemp = pathTemp.remove(pathTemp.size() - separatorSize(), separatorSize());
185 }
186
187 if (pathTemp.startsWith(QDir::separator()))
188 pathTemp.remove(0, separatorSize());
189
190 if (pathTemp.endsWith(QDir::separator()))
191 pathTemp.remove(pathTemp.size() - separatorSize(), separatorSize());
192
193 if (pathTemp.isEmpty())
194 return parent;
195
196 QStringList splitPaths = pathTemp.split(QDir::separator());
197 QString name = splitPaths.takeFirst();
198
199 QList<QStandardItem*> currRows{};
200 if (parent) {
201 currRows = rows(parent);
202 } else {
203 currRows = d->rows;
204 }
205
206 for (int i = 0; i < currRows.size(); i++) {
207 QStandardItem *child = currRows[i];
208 if (name == itemDisplayName(child)) {
209 if (splitPaths.isEmpty()) {
210 return child;
211 } else {
212 return findItem(splitPaths.join(QDir::separator()), child);
213 }
214 }
215 }
216 return parent;
217}
218
219int MavenAsynParse::separatorSize() const
220{
221 return QString(QDir::separator()).size();
222}
223
224QString MavenAsynParse::itemDisplayName(const QStandardItem *item) const
225{
226 if (!item)
227 return "";
228 return item->data(Qt::DisplayRole).toString();
229}
230