1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "jsasynparse.h"
6#include "services/project/projectgenerator.h"
7
8#include "common/common.h"
9
10#include <QAction>
11#include <QDebug>
12#include <QtXml>
13
14class JSAsynParsePrivate
15{
16 friend class JSAsynParse;
17 QDomDocument xmlDoc;
18 QThread *thread {nullptr};
19 QString rootPath;
20 QList<QStandardItem *> rows {};
21};
22
23JSAsynParse::JSAsynParse()
24 : d(new JSAsynParsePrivate)
25{
26 QObject::connect(this, &QFileSystemWatcher::directoryChanged,
27 this, &JSAsynParse::doDirectoryChanged);
28 d->thread = new QThread();
29 this->moveToThread(d->thread);
30 d->thread->start();
31}
32
33JSAsynParse::~JSAsynParse()
34{
35 if (d) {
36 if (d->thread) {
37 if (d->thread->isRunning())
38 d->thread->quit();
39 d->thread->wait();
40 d->thread->deleteLater();
41 d->thread = nullptr;
42 }
43 delete d;
44 }
45}
46
47void JSAsynParse::parseProject(dpfservice::ProjectInfo &info)
48{
49 createRows(info.workspaceFolder());
50 QSet<QString> jsFiles;
51 for (auto row : d->rows) {
52 QString fileName = row->text();
53 if (fileName.endsWith(".js", Qt::CaseInsensitive)) {
54 jsFiles.insert(info.workspaceFolder() + "/" + fileName);
55 }
56 qInfo() << fileName;
57 }
58 info.setSourceFiles(jsFiles);
59 emit itemsModified(d->rows);
60}
61
62void JSAsynParse::doDirectoryChanged(const QString &path)
63{
64 if (!path.startsWith(d->rootPath))
65 return;
66
67 d->rows.clear();
68
69 createRows(d->rootPath);
70
71 emit itemsModified(d->rows);
72}
73
74QString JSAsynParse::itemDisplayName(const QStandardItem *item) const
75{
76 if (!item)
77 return "";
78 return item->data(Qt::DisplayRole).toString();
79}
80
81void JSAsynParse::iteratorDirectory(const QString &rootPath)
82{
83 QDir dir;
84 dir.setPath(rootPath);
85 dir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
86 dir.setSorting(QDir::Name);
87 QDirIterator dirItera(dir, QDirIterator::Subdirectories);
88 while (dirItera.hasNext()) {
89 QString childPath = dirItera.next().remove(0, rootPath.size());
90 QFileSystemWatcher::addPath(dirItera.filePath());
91 QStandardItem *item = findItem(childPath);
92 QIcon icon = CustomIcons::icon(dirItera.fileInfo());
93 auto newItem = new QStandardItem(icon, dirItera.fileName());
94 newItem->setToolTip(dirItera.filePath());
95 if (!item) {
96 d->rows.append(newItem);
97 } else {
98 item->appendRow(newItem);
99 }
100 }
101}
102
103void JSAsynParse::iteratorFiles(const QString &rootPath)
104{
105 QDir dir;
106 dir.setPath(rootPath);
107 dir.setFilter(QDir::NoDotAndDotDot | QDir::Files);
108 dir.setSorting(QDir::Name);
109 QDirIterator fileItera(dir, QDirIterator::Subdirectories);
110 while (fileItera.hasNext()) {
111 QString childPath = fileItera.next().remove(0, rootPath.size());
112 QStandardItem *item = findItem(childPath);
113 QIcon icon = CustomIcons::icon(fileItera.fileInfo());
114 auto newItem = new QStandardItem(icon, fileItera.fileName());
115 newItem->setToolTip(fileItera.filePath());
116 if (!item) {
117 d->rows.append(newItem);
118 } else {
119 item->appendRow(newItem);
120 }
121 }
122}
123
124void JSAsynParse::createRows(const QString &path)
125{
126 QString rootPath = path;
127 if (rootPath.endsWith(QDir::separator())) {
128 int separatorSize = QString(QDir::separator()).size();
129 rootPath = rootPath.remove(rootPath.size() - separatorSize, separatorSize);
130 }
131 d->rootPath = rootPath;
132 QFileSystemWatcher::addPath(d->rootPath);
133
134 iteratorDirectory(rootPath);
135 iteratorFiles(rootPath);
136}
137
138QList<QStandardItem *> JSAsynParse::rows(const QStandardItem *item) const
139{
140 QList<QStandardItem *> result;
141 for (int i = 0; i < item->rowCount(); i++) {
142 result << item->child(i);
143 }
144 return result;
145}
146
147QStandardItem *JSAsynParse::findItem(const QString &path,
148 QStandardItem *parent) const
149{
150 QString pathTemp = path;
151 if (pathTemp.endsWith(QDir::separator())) {
152 pathTemp = pathTemp.remove(pathTemp.size() - separatorSize(), separatorSize());
153 }
154
155 if (pathTemp.startsWith(QDir::separator()))
156 pathTemp.remove(0, separatorSize());
157
158 if (pathTemp.endsWith(QDir::separator()))
159 pathTemp.remove(pathTemp.size() - separatorSize(), separatorSize());
160
161 if (pathTemp.isEmpty())
162 return parent;
163
164 QStringList splitPaths = pathTemp.split(QDir::separator());
165 QString name = splitPaths.takeFirst();
166
167 QList<QStandardItem*> currRows{};
168 if (parent) {
169 currRows = rows(parent);
170 } else {
171 currRows = d->rows;
172 }
173
174 for (int i = 0; i < currRows.size(); i++) {
175 QStandardItem *child = currRows[i];
176 if (name == itemDisplayName(child)) {
177 if (splitPaths.isEmpty()) {
178 return child;
179 } else {
180 return findItem(splitPaths.join(QDir::separator()), child);
181 }
182 }
183 }
184 return parent;
185}
186
187int JSAsynParse::separatorSize() const
188{
189 return QString(QDir::separator()).size();
190}
191