Skip to content

Commit

Permalink
refactor: [project] Optimize project tree icon loading and parsing
Browse files Browse the repository at this point in the history
Refactored project tree icon loading mechanism and parsing process to improve
performance and maintainability:

- Moved icon loading from individual items to ProjectModel data() method
- Added ProjectItemRole enum for icon name and file path roles
- Replaced direct icon setting with role-based data storage
- Implemented stop mechanism for cmake async parsing
- Moved cmake parser to separate thread for better responsiveness
- Unified parsing state role usage across project types
- Removed redundant icon loading code from various parsers
- Added sorting capability to project tree

Log: Optimize project tree icon loading and parsing mechanism
  • Loading branch information
Kakueeen authored and deepin-mozart committed Dec 6, 2024
1 parent 5430fa6 commit 7d53433
Show file tree
Hide file tree
Showing 15 changed files with 183 additions and 169 deletions.
76 changes: 37 additions & 39 deletions src/plugins/cxx/cmake/project/cmakeasynparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ enum_def(CDT_TARGETS_TYPE, QString)
enum_exp Exe = "[exe]";
};

QIcon cmakeFolderIcon()
{
static QIcon cmakeFolderIcon;
if (cmakeFolderIcon.isNull()) {
cmakeFolderIcon = CustomIcons::icon(QFileIconProvider::Folder);
}
return cmakeFolderIcon;
}

} // namespace

const QString kProjectFile = "CMakeLists.txt";
Expand Down Expand Up @@ -70,15 +61,14 @@ void sortParentItem(QStandardItem *parentItem)
return item1->text().toLower().localeAwareCompare(item2->text().toLower()) < 0;
});

for ( auto item : cmakeFileList )
for (auto item : cmakeFileList)
parentItem->appendRow(item);
for ( auto item : directoryList )
for (auto item : directoryList)
parentItem->appendRow(item);
for ( auto item : fileList )
for (auto item : fileList)
parentItem->appendRow(item);
for ( auto item : others )
for (auto item : others)
parentItem->appendRow(item);

}

CmakeAsynParse::CmakeAsynParse()
Expand All @@ -89,6 +79,11 @@ CmakeAsynParse::~CmakeAsynParse()
{
}

void CmakeAsynParse::stop()
{
isStop = true;
}

QString getTargetRootPath(const CMakeBuildTarget &target, const dpfservice::ProjectInfo &prjInfo)
{
auto srcFiles = target.srcfiles;
Expand All @@ -101,7 +96,7 @@ QString getTargetRootPath(const CMakeBuildTarget &target, const dpfservice::Proj
//get target root path by build-directory
auto workingDirectory = target.workingDirectory;
auto buildDirectory = prjInfo.buildFolder();
if(workingDirectory.startsWith(buildDirectory)) {
if (workingDirectory.startsWith(buildDirectory)) {
workingDirectory.remove(buildDirectory);
return topPath + workingDirectory;
}
Expand All @@ -111,7 +106,7 @@ QString getTargetRootPath(const CMakeBuildTarget &target, const dpfservice::Proj
QList<QList<QString>> pathPartsList;
for (const QString &filePath : srcFiles) {
// remove outter file.
if ((!topPath.isEmpty() && !filePath.startsWith(topPath))/* || QFileInfo(filePath).suffix() == "h" || QFileInfo(filePath).suffix() == "hpp"*/) {
if ((!topPath.isEmpty() && !filePath.startsWith(topPath)) /* || QFileInfo(filePath).suffix() == "h" || QFileInfo(filePath).suffix() == "hpp"*/) {
continue;
}

Expand Down Expand Up @@ -160,17 +155,21 @@ QString getTargetRootPath(const CMakeBuildTarget &target, const dpfservice::Proj
return rootPath;
}

QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfservice::ProjectInfo &prjInfo)
void CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfservice::ProjectInfo &prjInfo)
{
isStop = false;
if (!rootItem)
return nullptr;
return;

TargetsManager::instance()->readTargets(prjInfo.buildFolder(), prjInfo.workspaceFolder());
auto cbpParser = TargetsManager::instance()->cbpParser();
// add cmakefile to tree first.
auto cmakeList = cbpParser->getCmakeFileList();
QSet<QString> cmakeFiles {};
for (auto &cmakeFile : cmakeList) {
if (isStop)
return;

QString cmakeFilePath = cmakeFile.get()->getfilePath();
if (cmakeFilePath.endsWith("CMakeLists.txt"))
cmakeFiles.insert(cmakeFilePath);
Expand All @@ -187,22 +186,23 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
cmakeFileItem->setText(cmakeFileInfo.fileName());
cmakeFileItem->setToolTip(cmakeFileInfo.filePath());
cmakeParentItem->appendRow(cmakeFileItem);
QMetaObject::invokeMethod(this, [=](){
cmakeFileItem->setIcon(CustomIcons::icon(cmakeFileInfo));
});
cmakeFileItem->setData(cmakeFileInfo.absoluteFilePath(), ProjectItemRole::FileIconRole);

// monitor cmake file change to refresh project tree.
if (cmakeParentItem == rootItem) {
CmakeItemKeeper::instance()->addCmakeRootFile(rootItem, cmakeFilePath);
} else {
CmakeItemKeeper::instance()->addCmakeSubFiles(rootItem, {cmakeFilePath});
CmakeItemKeeper::instance()->addCmakeSubFiles(rootItem, { cmakeFilePath });
}
}
}

QSet<QString> commonFiles {};
const QList<CMakeBuildTarget> &targets = cbpParser->getBuildTargets();
for (auto target : targets) {
if (isStop)
return;

if (target.type == kUtility) {
continue;
}
Expand All @@ -222,12 +222,10 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
} else if (target.type == kStaticLibrary || target.type == kDynamicLibrary) {
prefix = CDT_TARGETS_TYPE::get()->Lib;
}
QMetaObject::invokeMethod(this, [=](){
if (target.type == kExecutable)
targetItem->setIcon(QIcon::fromTheme("project_executable"));
else if (target.type == kStaticLibrary || target.type == kDynamicLibrary)
targetItem->setIcon(QIcon::fromTheme("library"));
});
if (target.type == kExecutable)
targetItem->setData("project_executable", ProjectItemRole::IconNameRole);
else if (target.type == kStaticLibrary || target.type == kDynamicLibrary)
targetItem->setData("library", ProjectItemRole::IconNameRole);
QString title = prefix + target.title;
targetItem->setText(title);
targetItem->setToolTip(absolutePath);
Expand All @@ -237,6 +235,9 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
targetRootItem->appendRow(targetItem);

for (const auto &src : target.srcfiles) {
if (isStop)
return;

QFileInfo srcFileInfo(src);
relativePath = QDir(targetRootPath).relativeFilePath(srcFileInfo.dir().path());
absolutePath = QDir(targetRootPath).absoluteFilePath(srcFileInfo.dir().path());
Expand All @@ -258,9 +259,9 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
QStandardItem *srcItem = new QStandardItem();
srcItem->setText(srcFileInfo.fileName());
srcItem->setToolTip(srcFileInfo.filePath());
srcItem->setIcon(CustomIcons::icon(srcFileInfo));
srcItem->setData(srcFileInfo.absoluteFilePath(), ProjectItemRole::FileIconRole);
if (srcFileInfo.isDir())
emit directoryCreated(srcFileInfo.filePath());
emit directoryCreated(rootItem, srcFileInfo.filePath());

if (parentItem)
parentItem->appendRow(srcItem);
Expand All @@ -271,24 +272,21 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse

ProjectInfo tempInfo = prjInfo;
if (tempInfo.runProgram().isEmpty()) {
auto activeExecTarget = TargetsManager::instance()->
getActivedTargetByTargetType(dpfservice::TargetType::kActiveExecTarget);
auto activeExecTarget = TargetsManager::instance()->getActivedTargetByTargetType(dpfservice::TargetType::kActiveExecTarget);
tempInfo.setRunProgram(activeExecTarget.output);
tempInfo.setRunWorkspaceDir(activeExecTarget.workingDir);
}

tempInfo.setSourceFiles(commonFiles + cmakeFiles);
auto exePrograms = TargetsManager::instance()->getExeTargetNamesList();
qSort(exePrograms.begin(), exePrograms.end(), [](const QString &s1, const QString &s2){
qSort(exePrograms.begin(), exePrograms.end(), [](const QString &s1, const QString &s2) {
return s1.toLower() < s2.toLower();
});
tempInfo.setExePrograms(exePrograms);
tempInfo.setCurrentProgram(TargetsManager::instance()->getActivedTargetByTargetType(TargetType::kActiveExecTarget).name);
ProjectInfo::set(rootItem, tempInfo);
emit parseProjectEnd({ rootItem, true });
rootItem->setData(ParsingState::Done, Parsing_State_Role);

return rootItem;
rootItem->setData(ParsingState::Done, ProjectItemRole::ParsingStateRole);
}

QList<CmakeAsynParse::TargetBuild> CmakeAsynParse::parseActions(const QStandardItem *item)
Expand All @@ -312,7 +310,7 @@ QList<CmakeAsynParse::TargetBuild> CmakeAsynParse::parseActions(const QStandardI
build.buildTarget = QFileInfo(buildTarget.output).dir().path();
buildMenuList.push_back(build);

parseActionsEnd({ buildMenuList, true });
emit parseActionsEnd({ buildMenuList, true });
return buildMenuList;
}

Expand Down Expand Up @@ -347,10 +345,10 @@ QStandardItem *CmakeAsynParse::createParentItem(QStandardItem *rootItem, const Q
item = new QStandardItem();
item->setText(nameItem);
item->setToolTip(basePath + relative);
item->setIcon(::cmakeFolderIcon());
item->setData(basePath + relative, ProjectItemRole::FileIconRole);
// append to parent.
QStandardItem *parentItem = findParentItem(rootItem, relative);
emit directoryCreated(basePath+relative);
emit directoryCreated(rootItem, basePath + relative);
parentItem->appendRow(item);
sortParentItem(parentItem);
}
Expand Down
13 changes: 9 additions & 4 deletions src/plugins/cxx/cmake/project/cmakeasynparse.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class CMakeCbpParser;
namespace {
enum_def(CDT_PROJECT_KIT, QString)
{
enum_exp CBP_GENERATOR = "CodeBlocks - Unix Makefiles";
enum_exp CBP_GENERATOR = "CodeBlocks - Unix Makefiles";
enum_exp CBP_FILE = ".cbp";
};

Expand Down Expand Up @@ -53,25 +53,30 @@ class CmakeAsynParse : public QObject
QString stopOnError;
QString useDefaultCommand;
};

typedef QList<TargetBuild> TargetBuilds;

CmakeAsynParse();
virtual ~CmakeAsynParse();

void stop();

signals:
void parseProjectEnd(const ParseInfo<QStandardItem *> &info);
void parseActionsEnd(const ParseInfo<QList<TargetBuild>> &info);
void directoryCreated(const QString &path);
void directoryCreated(QStandardItem *rootItem, const QString &path);

public slots:
QStandardItem *parseProject(QStandardItem *rootItem, const dpfservice::ProjectInfo &info);
void parseProject(QStandardItem *rootItem, const dpfservice::ProjectInfo &info);
QList<TargetBuild> parseActions(const QStandardItem *item);

private:
QStandardItem *findParentItem(QStandardItem *rootItem, QString &name);
QStandardItem *createParentItem(QStandardItem *rootItem, const QString &relativeName, const QString &absolutePath);
QStandardItem *findItem(QStandardItem *rootItem, QString &name, QString &relativePath);

QAtomicInteger<bool> isStop { false };
};

Q_DECLARE_METATYPE(CmakeAsynParse::ParseInfo<QStandardItem *>)
Q_DECLARE_METATYPE(CmakeAsynParse::ParseInfo<QList<CmakeAsynParse::TargetBuild>>)
#endif // CMAKEASYNPARSE_H
Loading

0 comments on commit 7d53433

Please sign in to comment.