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 | |
15 | static QString kSupportArgs[] = {"clean" , "compiler:compile" , "compiler:testCompile" , |
16 | "package" , "install" , "validate" , "dependency:tree" , |
17 | "dependency:analyze" , "site:site" , "compile" , "verify" }; |
18 | |
19 | class MavenAsynParsePrivate |
20 | { |
21 | friend class MavenAsynParse; |
22 | QDomDocument xmlDoc; |
23 | QThread *thread {nullptr}; |
24 | QString rootPath; |
25 | QList<QStandardItem *> rows {}; |
26 | }; |
27 | |
28 | MavenAsynParse::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 | |
40 | MavenAsynParse::~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 | |
54 | void 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 | |
72 | void 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. |
79 | void 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 | |
105 | void 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 | |
117 | void 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 | |
170 | QList<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 | |
179 | QStandardItem *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 | |
219 | int MavenAsynParse::separatorSize() const |
220 | { |
221 | return QString(QDir::separator()).size(); |
222 | } |
223 | |
224 | QString MavenAsynParse::itemDisplayName(const QStandardItem *item) const |
225 | { |
226 | if (!item) |
227 | return "" ; |
228 | return item->data(Qt::DisplayRole).toString(); |
229 | } |
230 | |