Skip to content

Commit

Permalink
fix: [DirectoryAsynParse] Program crash
Browse files Browse the repository at this point in the history
QStandItem is not thread-safe, and operating on the QStandItem object in the thread causes the program to crash

Log: fix bug
Bug: https://pms.uniontech.com/bug-view-298511.html
  • Loading branch information
Kakueeen authored and deepin-mozart committed Jan 6, 2025
1 parent e693d5e commit 645bb7a
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 30 deletions.
30 changes: 13 additions & 17 deletions src/services/project/directoryasynparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@ class DirectoryAsynParsePrivate
{
friend class DirectoryAsynParse;
QString rootPath;
QStandardItem *rootItem { nullptr };
QList<QStandardItem *> itemList;
QSet<QString> fileList {};
};

DirectoryAsynParse::DirectoryAsynParse(QStandardItem *root)
DirectoryAsynParse::DirectoryAsynParse()
: d(new DirectoryAsynParsePrivate)
{
d->rootItem = root;
QObject::connect(this, &QFileSystemWatcher::directoryChanged,
this, &DirectoryAsynParse::doDirectoryChanged);
}
Expand All @@ -38,7 +37,7 @@ DirectoryAsynParse::~DirectoryAsynParse()
void DirectoryAsynParse::parseProject(const dpfservice::ProjectInfo &info)
{
createRows(info.workspaceFolder());
emit itemsModified();
emit itemsCreated(d->itemList);
}

QSet<QString> DirectoryAsynParse::getFilelist()
Expand All @@ -51,11 +50,11 @@ void DirectoryAsynParse::doDirectoryChanged(const QString &path)
if (!path.startsWith(d->rootPath))
return;

auto item = findItem(path);
if (!item)
item = d->rootItem;
updateItem(item);
Q_EMIT itemUpdated(item);
// auto item = findItem(path);
// if (!item)
// item = d->rootItem;
// updateItem(item);
Q_EMIT reqUpdateItem(path);
}

void DirectoryAsynParse::createRows(const QString &path)
Expand All @@ -69,7 +68,6 @@ void DirectoryAsynParse::createRows(const QString &path)

// 缓存当前工程目录
d->rootPath = rootPath;
d->rootItem->setData(rootPath, Project::FilePathRole);
QFileSystemWatcher::addPath(d->rootPath);

QDir dir;
Expand All @@ -83,7 +81,7 @@ void DirectoryAsynParse::createRows(const QString &path)
item->setData(iter.filePath(), Project::FileIconRole);
item->setData(iter.filePath(), Project::FilePathRole);
item->setToolTip(iter.filePath());
parent ? parent->appendRow(item) : d->rootItem->appendRow(item);
parent ? parent->appendRow(item) : d->itemList.append(item);
if (iter.fileInfo().isFile())
d->fileList.insert(iter.filePath());
else
Expand Down Expand Up @@ -118,7 +116,7 @@ QStandardItem *DirectoryAsynParse::findItem(const QString &path, QStandardItem *
if (path.isEmpty())
return nullptr;

const auto &itemRows = parent ? rows(parent) : rows(d->rootItem);
const auto &itemRows = parent ? rows(parent) : d->itemList;
for (const auto item : itemRows) {
const auto &itemPath = item->data(Project::FilePathRole).toString();
if (path == itemPath) {
Expand All @@ -140,7 +138,7 @@ QStandardItem *DirectoryAsynParse::findParentItem(const QString &path, QStandard
return nullptr;

QFileInfo fileInfo(path);
const auto &itemRows = parent ? rows(parent) : rows(d->rootItem);
const auto &itemRows = parent ? rows(parent) : d->itemList;
for (const auto item : itemRows) {
const auto &itemPath = item->data(Project::FilePathRole).toString();
if (!path.startsWith(itemPath))
Expand Down Expand Up @@ -218,12 +216,10 @@ void DirectoryAsynParse::updateItem(QStandardItem *item)
void DirectoryAsynParse::sortItems()
{
// Sort root level items
auto itemList = takeAll(d->rootItem);
std::sort(itemList.begin(), itemList.end(), std::bind(&DirectoryAsynParse::compareItems, this, _1, _2));
std::sort(d->itemList.begin(), d->itemList.end(), std::bind(&DirectoryAsynParse::compareItems, this, _1, _2));

// Sort children of each root item
for (auto *item : itemList) {
d->rootItem->appendRow(item);
for (auto *item : d->itemList) {
sortChildren(item);
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/services/project/directoryasynparse.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ class DirectoryAsynParse : public QFileSystemWatcher
bool isNormal = true;
};

explicit DirectoryAsynParse(QStandardItem *root);
explicit DirectoryAsynParse();
virtual ~DirectoryAsynParse();

QSet<QString> getFilelist();
QStandardItem *findItem(const QString &path, QStandardItem *parent = nullptr) const;
void updateItem(QStandardItem *item);

signals:
void itemsModified();
void itemUpdated(QStandardItem *item);
void itemsCreated(QList<QStandardItem *> itemList);
void reqUpdateItem(const QString &path);
void parsedError(const ParseInfo<QString> &info);

public slots:
Expand All @@ -45,11 +47,9 @@ private slots:

private:
void createRows(const QString &path);
QStandardItem *findItem(const QString &path, QStandardItem *parent = nullptr) const;
QStandardItem *findParentItem(const QString &path, QStandardItem *parent = nullptr) const;
QList<QStandardItem *> rows(const QStandardItem *item) const;
QList<QStandardItem *> takeAll(QStandardItem *item);
void updateItem(QStandardItem *item);

void sortItems();
void sortChildren(QStandardItem *parentItem);
Expand Down
27 changes: 21 additions & 6 deletions src/services/project/directorygenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ QStandardItem *DirectoryGenerator::createRootItem(const dpfservice::ProjectInfo

QStandardItem *rootItem = ProjectGenerator::createRootItem(info);
d->configureRootItem = rootItem;
auto parser = new DirectoryAsynParse(rootItem);
auto parser = new DirectoryAsynParse();
d->projectParses[rootItem] = parser;
QObject::connect(d->projectParses[rootItem],
&DirectoryAsynParse::itemsModified,
this, &DirectoryGenerator::doProjectChildsModified,
&DirectoryAsynParse::itemsCreated,
this, &DirectoryGenerator::projectItemsCreated,
Qt::UniqueConnection);
QObject::connect(d->projectParses[rootItem],
&DirectoryAsynParse::itemUpdated,
&DirectoryAsynParse::reqUpdateItem,
this, &DirectoryGenerator::handleItemUpdated,
Qt::UniqueConnection);
QtConcurrent::run(parser, &DirectoryAsynParse::parseProject, info);
Expand All @@ -101,7 +101,7 @@ void DirectoryGenerator::removeRootItem(QStandardItem *root)
delete parser;
}

void DirectoryGenerator::doProjectChildsModified()
void DirectoryGenerator::projectItemsCreated(QList<QStandardItem *> itemList)
{
auto sourceFiles = d->projectParses[d->configureRootItem]->getFilelist();
ProjectInfo tempInfo = prjInfo;
Expand All @@ -110,13 +110,28 @@ void DirectoryGenerator::doProjectChildsModified()
project.activeProject(tempInfo.kitName(), tempInfo.language(), tempInfo.workspaceFolder());

auto rootItem = d->projectParses.key(qobject_cast<DirectoryAsynParse *>(sender()));
if (rootItem) {
while (rootItem->hasChildren()) {
rootItem->removeRow(0);
}
rootItem->appendRows(itemList);
}

rootItem->setData(Project::Done, Project::ParsingStateRole);
}

void DirectoryGenerator::handleItemUpdated(QStandardItem *item)
void DirectoryGenerator::handleItemUpdated(const QString &path)
{
ProjectService *prjSrv = dpfGetService(ProjectService);
Q_ASSERT(prjSrv);

auto parser = qobject_cast<DirectoryAsynParse *>(sender());
auto rootItem = d->projectParses.key(parser);
auto item = parser->findItem(path, rootItem);
if (!item)
item = rootItem;
parser->updateItem(item);
if (auto model = rootItem->model())
Q_EMIT model->layoutChanged();
prjSrv->restoreExpandState(item);
}
4 changes: 2 additions & 2 deletions src/services/project/directorygenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class DirectoryGenerator : public ProjectGenerator
protected:
dpfservice::ProjectInfo prjInfo;
public slots:
void doProjectChildsModified();
void handleItemUpdated(QStandardItem *item);
void projectItemsCreated(QList<QStandardItem *> itemList);
void handleItemUpdated(const QString &path);
};

}
Expand Down
1 change: 1 addition & 0 deletions src/services/project/projectgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ QStandardItem *dpfservice::ProjectGenerator::createRootItem(const dpfservice::Pr
QString displyName = QFileInfo(info.workspaceFolder()).fileName();
QString tooltip = info.workspaceFolder();
auto rootItem = new QStandardItem(icon, displyName);
rootItem->setData(info.workspaceFolder(), Project::FilePathRole);
rootItem->setToolTip(tooltip);
return rootItem;
}
Expand Down

0 comments on commit 645bb7a

Please sign in to comment.