From c7a9698c4b39f613317582bfb37a6a6cb700be20 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Tue, 8 Feb 2022 12:33:10 +0800 Subject: [PATCH] - enhancement: file system view mode for project --- NEWS.md | 3 + RedPandaIDE/RedPandaIDE.pro | 2 +- RedPandaIDE/RedPandaIDE_zh_CN.ts | 319 ++++++++++-------- RedPandaIDE/iconsmanager.cpp | 2 +- RedPandaIDE/mainwindow.cpp | 21 +- RedPandaIDE/mainwindow.h | 2 + RedPandaIDE/project.cpp | 211 ++++++++---- RedPandaIDE/project.h | 43 ++- RedPandaIDE/projecttemplate.cpp | 1 + .../settingsdialog/projectfileswidget.cpp | 1 - RedPandaIDE/utils.cpp | 2 +- Red_Panda_CPP.pro | 2 +- 12 files changed, 370 insertions(+), 239 deletions(-) diff --git a/NEWS.md b/NEWS.md index f727d225..3b27856f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,6 @@ +Red Panda C++ Version 0.14.2 + - enhancement: file system view mode for project + Red Panda C++ Version 0.14.1 - enhancement: custom theme - fix: failed to show function tip, when there are parameters having '[' and ']' diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index f4db34bf..e6cf01f8 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -10,7 +10,7 @@ isEmpty(APP_NAME) { } isEmpty(APP_VERSION) { - APP_VERSION=0.14.1 + APP_VERSION=0.14.2 } isEmpty(PREFIX) { diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.ts b/RedPandaIDE/RedPandaIDE_zh_CN.ts index d711cb72..47b2defd 100644 --- a/RedPandaIDE/RedPandaIDE_zh_CN.ts +++ b/RedPandaIDE/RedPandaIDE_zh_CN.ts @@ -3272,11 +3272,11 @@ Are you really want to continue? - - - - - + + + + + Issues 编译器 @@ -3688,7 +3688,7 @@ Are you really want to continue? - + New Problem Set 新建试题集 @@ -3707,14 +3707,14 @@ Are you really want to continue? - + Save Problem Set 保存试题集 - + Load Problem Set 载入试题集 @@ -4053,7 +4053,7 @@ Are you really want to continue? - + Clear all breakpoints 删除所有断点 @@ -4154,7 +4154,7 @@ Are you really want to continue? - + Rename Symbol 重命名符号 @@ -4175,13 +4175,13 @@ Are you really want to continue? - + Export As RTF 导出为RTF - + Export As HTML 导出为HTML @@ -4344,7 +4344,7 @@ Are you really want to continue? - + Open Folder 打开文件夹 @@ -4354,7 +4354,7 @@ Are you really want to continue? 运行参数... - + File Encoding 文件编码 @@ -4584,7 +4584,7 @@ Are you really want to continue? - + Problem Set %1 试题集%1 @@ -4658,15 +4658,15 @@ Are you really want to continue? - - + + Bookmark Description 书签描述 - - + + Description: 描述: @@ -4742,195 +4742,205 @@ Are you really want to continue? 删除文件夹 - + + Switch to normal view + 切换为普通视图 + + + + Switch to custom view + 切换为自定义视图 + + + Sort By Type 按类型排序 - + Sort alphabetically 按名称排序 - + Show inherited members 显示继承的成员 - + Goto declaration 跳转到声明处 - + Goto definition 跳转到定义处 - + Open in Editor 在编辑器中打开 - + Open in External Program 使用外部程序打开 - + Open in Terminal 在终端中打开 - + Open in Windows Explorer 在Windows浏览器中打开 - + Character sets 字符集 - + %1 files autosaved 已自动保存%1个文件 - + Set answer to... 设置答案源代码... - + select other file... 选择其他文件... - + Select Answer Source File 选择答案源代码文件 - + C/C++Source Files (*.c *.cpp *.cc *.cxx) C/C++Source Files (*.c *.cpp *.cc *.cxx C/C++源代码文件 (*.c *.cpp *.cc *.cxx) - + Save project 保存项目 - + The project '%1' has modifications. 项目'%1'有改动。 - - + + Do you want to save it? 需要保存吗? - - + + File Changed 文件已发生变化 - + New Project File? 新建项目文件? - + Do you want to add the new file to the project? 您是否要将新建的文件加入项目? - - - - + + + + Save Error 保存失败 - + Change Project Compiler Set 改变项目编译器配置集 - + Change the project's compiler set will lose all custom compiler set options. 改变项目的编译器配置集会导致所有的自定义编译器选项被重置。 - + Do you really want to do that? 你真的想要做那些吗? - + Do you really want to clear all breakpoints in this file? 您真的要清除该文件的所有断点吗? - + New project 新建项目 - + Close %1 and start new project? 关闭'%1'以打开新项目? - + Folder not exist 文件夹不存在 - + Folder '%1' doesn't exist. Create it now? 文件夹'%1'不存在。是否创建? - + Can't create folder 无法创建文件夹 - + Failed to create folder '%1'. 创建文件夹'%1'失败。 - + Save new project as - - + + Header Exists 头文件已存在 - - + + Header file "%1" already exists! 头文件"%1"已存在! - + Source Exists 源文件已存在! - + Source file "%1" already exists! 源文件"%1"已存在! @@ -4939,125 +4949,125 @@ Are you really want to continue? 小熊猫Dev-C++项目文件 (*.dev) - + New project fail 新建项目失败 - + Can't assign project template 无法使用模板创建项目 - + Remove file 删除文件 - + Remove the file from disk? 同时从硬盘上删除文件? - + untitled 无标题 - + New Project File Name 新的项目文件名 - + File Name: 文件名: - + File Already Exists! 文件已存在! - + File '%1' already exists! 文件'%1'已经存在! - + Add to project 添加到项目 - + Red Panda C++ project file (*.dev) 小熊猫C++项目文件(*.dev) - + Rename Error 重命名出错 - + Symbol '%1' is defined in system header. 符号'%1'在系统头文件中定义,无法修改。 - + New Name 新名称 - - + + Replace Error 替换出错 - + Can't open file '%1' for replace! 无法打开文件'%1'进行替换! - + Contents has changed since last search! 内容和上次查找时不一致。 - + Rich Text Format Files (*.rtf) RTF格式文件 (*.rtf) - + HTML Files (*.html) HTML文件 (*.html) - + The current problem set is not empty. 当前的试题集不是空的。 - + Problem %1 试题%1 - - + + Problem Set Files (*.pbs) 试题集文件 (*.pbs) - + Load Error 载入失败 - - + + Problem Case %1 试题案例%1 @@ -5070,13 +5080,13 @@ Are you really want to continue? - - - - - - - + + + + + + + Error 错误 @@ -5091,75 +5101,75 @@ Are you really want to continue? 载入主题失败 - + File '%1' was changed. 磁盘文件'%1'已被修改。 - + Reload its content from disk? 是否重新读取它的内容? - + File '%1' was removed. 磁盘文件'%1'已被删除。 - + Keep it open? 是否保持它在小熊猫C++中打开的编辑窗口? - + Open 打开 - + Compile Failed 编译失败 - + Run Failed 运行失败 - - + + Confirm Convertion 确认转换 - - + + The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue? 当前编辑器中的文件将会使用%1编码保存。<br />这项操作无法被撤回。<br />你确定要继续吗? - + New Watch Expression 新监视表达式 - + Enter Watch Expression (it is recommended to use 'this->' for class members): 输入监视表达式 - + Parsing file %1 of %2: "%3" (%1/%2)正在解析文件"%3" - - + + Done parsing %1 files in %2 seconds 完成%1个文件的解析,用时%2秒 - + (%1 files per second) (每秒%1个文件) @@ -5325,22 +5335,22 @@ Are you really want to continue? OJProblemCasesRunner - + The runner process '%1' failed to start. 无法启动程序运行进程'%1'。 - + The last waitFor...() function timed out. waitFor()函数等待超时。 - + An error occurred when attempting to write to the runner process. 在向程序运行进程写入内容时出错。 - + An error occurred when attempting to read from the runner process. 在从程序运行进程读取内容时出错。 @@ -5391,83 +5401,98 @@ Are you really want to continue? 找不到项目文件'%1'! - + untitled 无标题 - + Can't save file 无法保存文件 - + Can't save file '%1' 无法保存文件'%1'. - + Error Load File 载入文件错误 - + File Exists 文件已存在 - + File '%1' is already in the project 文件'%1'已在项目中 - + Project Updated 项目已升级 - + Your project was succesfully updated to a newer file format! 已成功将项目升级到新的格式 - + If something has gone wrong, we kept a backup-file: '%1'... 旧项目文件备份在'%1'。 - + + Headers + 头文件 + + + + Sources + 源文件 + + + + Others + 其他文件 + + + Settings need update 设置需要更新 - + The compiler settings format of Red Panda C++ has changed. The compiler settings format of Dev-C++ has changed. 小熊猫C++的编译器设置格式已发生改变。 - + Please update your settings at Project >> Project Options >> Compiler and save your project. 请在项目 >> 项目属性 >> 编译器设置中修改您的设置并保存您的项目 - + Compiler not found 未找到编译器 - + The compiler set you have selected for this project, no longer exists. 您为该项目设置的编译器不存在。 - + It will be substituted by the global compiler set. 它将会被全局编译器设置代替。 - + Developed using the Red Panda C++ IDE Developed using the Red Panda Dev-C++ IDE 使用小熊猫C++编辑器开发 @@ -5696,12 +5721,12 @@ Are you really want to continue? 自定义构建命令 - + Auto detect 自动检测 - + ANSI ANSI @@ -5710,7 +5735,7 @@ Are you really want to continue? ANSI - + UTF-8 @@ -5874,24 +5899,24 @@ Are you really want to continue? ProjectModel - + File exists 文件已存在 - + File '%1' already exists. Delete it now? 文件'%1'已存在。是否删除? - - + + Remove failed 删除失败 - - + + Failed to remove file '%1' 无法删除文件'%1' @@ -7273,7 +7298,7 @@ Are you really want to continue? 自动链接 - + @@ -7349,15 +7374,15 @@ Are you really want to continue? 杂项 - - + + Program Runner 程序运行 - + Problem Set 试题集 diff --git a/RedPandaIDE/iconsmanager.cpp b/RedPandaIDE/iconsmanager.cpp index 3bb14ded..a54c93f3 100644 --- a/RedPandaIDE/iconsmanager.cpp +++ b/RedPandaIDE/iconsmanager.cpp @@ -314,7 +314,7 @@ QList IconsManager::listIconSets() while(dirIter.hasNext()) { dirIter.next(); QFileInfo fileInfo = dirIter.fileInfo(); - if (!fileInfo.isHidden() && fileInfo.isDir()) { + if (!fileInfo.isHidden() && !fileInfo.fileName().startsWith('.') && fileInfo.isDir()) { PIconSet pSet = std::make_shared(); pSet->name = fileInfo.baseName(); pSet->displayName = pSet->name; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 6634df46..7ccea5f7 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -2520,6 +2520,20 @@ void MainWindow::buildContextMenus() mProject->removeFolder(folderNode); mProject->saveOptions(); }); + mProject_SwitchFileSystemViewMode = createActionFor( + tr("Switch to normal view"), + ui->projectView); + connect(mProject_SwitchFileSystemViewMode, &QAction::triggered, + [this](){ + mProject->setModelType(ProjectModelType::FileSystem); + }); + mProject_SwitchCustomViewMode = createActionFor( + tr("Switch to custom view"), + ui->projectView); + connect(mProject_SwitchCustomViewMode, &QAction::triggered, + [this](){ + mProject->setModelType(ProjectModelType::Custom); + }); //context menu signal for class browser ui->tabStructure->setContextMenuPolicy(Qt::CustomContextMenu); @@ -2928,7 +2942,7 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos) menu.addAction(mProject_Rename_Unit); } menu.addSeparator(); - if (onFolder) { + if (onFolder && mProject->modelType()==ProjectModelType::Custom) { menu.addAction(mProject_Add_Folder); if (!onRoot) { menu.addAction(mProject_Rename_Folder); @@ -2941,6 +2955,11 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos) menu.addAction(ui->actionProject_Open_Folder_In_Explorer); menu.addAction(ui->actionProject_Open_In_Terminal); menu.addSeparator(); + if (mProject->modelType() == ProjectModelType::Custom) { + menu.addAction(mProject_SwitchFileSystemViewMode); + } else { + menu.addAction(mProject_SwitchCustomViewMode); + } menu.addAction(ui->actionProject_options); menu.exec(ui->projectView->mapToGlobal(pos)); diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 757ef611..28e6f6de 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -650,6 +650,8 @@ private: QAction * mProject_Rename_Unit; QAction * mProject_Rename_Folder; QAction * mProject_Remove_Folder; + QAction * mProject_SwitchFileSystemViewMode; + QAction * mProject_SwitchCustomViewMode; //actions for class browser QAction * mClassBrowser_Sort_By_Type; diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index 49da4259..914b3806 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -56,7 +56,7 @@ Project::Project(const QString &filename, const QString &name, QObject *parent) ini.SetValue("Project","filename", toByteArray(extractRelativePath(directory(),mFilename))); ini.SetValue("Project","name", toByteArray(mName)); ini.SaveFile(mFilename.toLocal8Bit()); - mNode = makeProjectNode(); + mRootNode = makeProjectNode(); } resetCppParser(mParser,mOptions.compilerSet); } @@ -141,7 +141,7 @@ void Project::open() ini.LoadFile(mFilename.toLocal8Bit()); loadOptions(ini); - mNode = makeProjectNode(); + mRootNode = makeProjectNode(); checkProjectFileForUpdate(ini); int uCount = ini.GetLongValue("Project","UnitCount",0); @@ -211,7 +211,7 @@ PProjectModelNode Project::makeNewFileNode(const QString &s, bool isFolder, PPro { PProjectModelNode node = std::make_shared(); if (!newParent) { - newParent = mNode; + newParent = mRootNode; } newParent->children.append(node); node->parent = newParent; @@ -219,8 +219,10 @@ PProjectModelNode Project::makeNewFileNode(const QString &s, bool isFolder, PPro if (newParent) { node->level = newParent->level+1; } - if (isFolder) + if (isFolder) { node->unitIndex = -1; + node->priority = 0; + } return node; } @@ -239,10 +241,10 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo // Select folder to add unit to if (!parentNode) - parentNode = mNode; // project root node + parentNode = mRootNode; // project root node if (parentNode->unitIndex>=0) { //it's a file - parentNode = mNode; + parentNode = mRootNode; } QString s; QDir dir(directory()); @@ -309,10 +311,13 @@ Editor *Project::openUnit(int index) void Project::rebuildNodes() { - + qDebug()<<(int)mOptions.modelType; mModel.beginUpdate(); // Delete everything - mNode->children.clear(); + mRootNode->children.clear(); + mFolderNodes.clear(); + mSpecialNodes.clear(); + mFileSystemFolderNodes.clear(); // Recreate everything switch(mOptions.modelType) { @@ -320,20 +325,36 @@ void Project::rebuildNodes() createFolderNodes(); for (int idx=0;idxfileName()); mUnits[idx]->setNode( makeNewFileNode( - extractRelativePath(filename(),mUnits[idx]->fileName()), + fileInfo.fileName(), false, folderNodeFromName(mUnits[idx]->folder()) ) ); mUnits[idx]->node()->unitIndex = idx; + mUnits[idx]->node()->priority = mUnits[idx]->priority(); } break; case ProjectModelType::FileSystem: createFileSystemFolderNodes(); - } + for (int idx=0;idxfileName()); + mUnits[idx]->setNode( + makeNewFileNode( + fileInfo.fileName(), + false, + getParentFolderNode( + mUnits[idx]->fileName()) + ) + ); + mUnits[idx]->node()->unitIndex = idx; + mUnits[idx]->node()->priority = mUnits[idx]->priority(); + } + break; + } mModel.endUpdate(); emit nodesChanged(); @@ -617,7 +638,7 @@ void Project::setCompilerOption(const QString &optionString, char value) void Project::updateFolders() { mFolders.clear(); - updateFolderNode(mNode); + updateFolderNode(mRootNode); for (int idx = 0; idx < mUnits.count();idx++) mUnits[idx]->setFolder( getFolderPath( @@ -636,10 +657,10 @@ void Project::updateNodeIndexes() PProjectModelNode Project::pointerToNode(ProjectModelNode *p, PProjectModelNode parent) { if (!parent) { - parent = mNode; + parent = mRootNode; } - if (p==mNode.get()) - return mNode; + if (p==mRootNode.get()) + return mRootNode; foreach (const PProjectModelNode& node , parent->children) { if (node.get()==p) return node; @@ -693,16 +714,16 @@ bool Project::assignTemplate(const std::shared_ptr aTemplate, b QFile::copy( QDir(pSettings->dirs().templateDir()).absoluteFilePath(templateUnit->Source), includeTrailingPathDelimiter(this->directory())+target); - unit = newUnit(mNode, target); + unit = newUnit(mRootNode, target); } else { QString s; PProjectUnit unit; if (mOptions.isCpp) { s = templateUnit->CppText; - unit = newUnit(mNode, templateUnit->CppName); + unit = newUnit(mRootNode, templateUnit->CppName); } else { s = templateUnit->CText; - unit = newUnit(mNode,templateUnit->CName); + unit = newUnit(mRootNode,templateUnit->CName); } Editor * editor = pMainWindow->editorList()->newEditor( @@ -730,6 +751,7 @@ bool Project::assignTemplate(const std::shared_ptr aTemplate, b } } } + rebuildNodes(); return true; } @@ -1228,9 +1250,8 @@ void Project::closeUnit(int index) void Project::createFolderNodes() { - mFolderNodes.clear(); for (int idx=0;idx=0) { @@ -1255,17 +1276,39 @@ void Project::createFolderNodes() void Project::createFileSystemFolderNodes() { - mFolderNodes.clear(); - PProjectModelNode node = makeNewFileNode(tr("Headers"),true,mNode); - createFileSystemFolderNode(folder(),node); - mFolderNodes.append(node); - node = makeNewFileNode(tr("Sources"),true,mNode); - createFileSystemFolderNode(folder(),node); - mFolderNodes.append(node); - node = makeNewFileNode(tr("Sources"),true,mNode); - createFileSystemFolderNode(folder(),node); + PProjectModelNode node = makeNewFileNode(tr("Headers"),true,mRootNode); + createFileSystemFolderNode(ProjectSpecialFolderNode::HEADERS,folder(),node); + node->priority = 1000; mFolderNodes.append(node); + mSpecialNodes.insert(ProjectSpecialFolderNode::HEADERS,node); + node = makeNewFileNode(tr("Sources"),true,mRootNode); + createFileSystemFolderNode(ProjectSpecialFolderNode::SOURCES,folder(),node); + node->priority = 900; + mFolderNodes.append(node); + mSpecialNodes.insert(ProjectSpecialFolderNode::SOURCES,node); + + node = makeNewFileNode(tr("Others"),true,mRootNode); + createFileSystemFolderNode(ProjectSpecialFolderNode::OTHERS,folder(),node); + node->priority = 800; + mFolderNodes.append(node); + mSpecialNodes.insert(ProjectSpecialFolderNode::OTHERS,node); +} + +void Project::createFileSystemFolderNode(ProjectSpecialFolderNode folderType, const QString &folderName, PProjectModelNode parent) +{ + QDirIterator iter(folderName); + while (iter.hasNext()) { + iter.next(); + QFileInfo fileInfo = iter.fileInfo(); + if (fileInfo.isHidden() || fileInfo.fileName().startsWith('.')) + continue; + if (fileInfo.isDir()) { + PProjectModelNode node = makeNewFileNode(fileInfo.fileName(),true,parent); + mFileSystemFolderNodes.insert(QString("%1/%2").arg((int)folderType).arg(fileInfo.absolutePath()),node); + createFileSystemFolderNode(folderType,fileInfo.path(), node); + } + } } void Project::doAutoOpen() @@ -1282,13 +1325,25 @@ bool Project::fileAlreadyExists(const QString &s) return false; } +PProjectModelNode Project::findFolderNode(const QString &folderPath, ProjectSpecialFolderNode nodeType) +{ + PProjectModelNode node = mFileSystemFolderNodes.value(QString("%1/%2").arg((int)nodeType).arg(folderPath), + PProjectModelNode()); + if (node) + return node; + PProjectModelNode parentNode = mSpecialNodes.value(nodeType,PProjectModelNode()); + if (parentNode) + return parentNode; + return mRootNode; +} + PProjectModelNode Project::folderNodeFromName(const QString &name) { int index = mFolders.indexOf(name); if (index>=0) { return mFolderNodes[index]; } - return mNode; + return mRootNode; } char Project::getCompilerOption(const QString &optionString) @@ -1314,7 +1369,7 @@ QString Project::getFolderPath(PProjectModelNode node) return result; PProjectModelNode p = node; - while (p && p->unitIndex==-1 && p!=mNode) { + while (p && p->unitIndex==-1 && p!=mRootNode) { if (!result.isEmpty()) result = p->text + "/" + result; else @@ -1329,6 +1384,20 @@ int Project::getUnitFromString(const QString &s) return indexInUnits(s); } +PProjectModelNode Project::getParentFolderNode(const QString &filename) +{ + QFileInfo fileInfo(filename); + ProjectSpecialFolderNode folderNodeType; + if (isHfile(fileInfo.fileName())) { + folderNodeType = ProjectSpecialFolderNode::HEADERS; + } else if (isCfile(fileInfo.fileName())) { + folderNodeType = ProjectSpecialFolderNode::SOURCES; + } else { + folderNodeType = ProjectSpecialFolderNode::OTHERS; + } + return findFolderNode(fileInfo.absolutePath(),folderNodeType); +} + void Project::incrementBuildNumber() { mOptions.versionInfo.build++; @@ -1342,15 +1411,6 @@ void Project::incrementBuildNumber() setModified(true); } -QString Project::listUnitStr(const QChar &separator) -{ - QStringList units; - foreach (const PProjectUnit& unit, mUnits) { - units.append('"'+unit->fileName()+'"'); - } - return units.join(separator); -} - void Project::loadLayout() { SimpleIni layIni; @@ -1525,30 +1585,6 @@ PCppParser Project::cppParser() return mParser; } -void Project::sortUnitsByPriority() -{ - mModel.beginUpdate(); - auto action = finally([this]{ - mModel.endUpdate(); - }); - std::sort(mUnits.begin(),mUnits.end(),[](const PProjectUnit& u1, const PProjectUnit& u2)->bool{ - return (u1->priority()>u2->priority()); - }); - rebuildNodes(); -} - -void Project::sortUnitsByAlpha() -{ - mModel.beginUpdate(); - auto action = finally([this]{ - mModel.endUpdate(); - }); - std::sort(mUnits.begin(),mUnits.end(),[](const PProjectUnit& u1, const PProjectUnit& u2)->bool{ - return (extractFileName(u1->fileName())fileName())); - }); - rebuildNodes(); -} - int Project::indexInUnits(const QString &fileName) const { QDir dir(directory()); @@ -1621,6 +1657,19 @@ const QList &Project::units() const return mUnits; } +ProjectModelType Project::modelType() const +{ + return mOptions.modelType; +} + +void Project::setModelType(ProjectModelType type) +{ + if (type!=mOptions.modelType) { + mOptions.modelType = type; + rebuildNodes(); + } +} + ProjectOptions &Project::options() { return mOptions; @@ -1633,7 +1682,7 @@ ProjectModel *Project::model() const PProjectModelNode &Project::rootNode() const { - return mNode; + return mRootNode; } const QString &Project::name() const @@ -1645,7 +1694,7 @@ void Project::setName(const QString &newName) { if (newName != mName) { mName = newName; - mNode->text = newName; + mRootNode->text = newName; setModified(true); } } @@ -1775,7 +1824,11 @@ int ProjectUnit::priority() const void ProjectUnit::setPriority(int newPriority) { - mPriority = newPriority; + if (mPriority!=newPriority) { + mPriority = newPriority; + if (mNode) + mNode->priority = mPriority; + } } const QByteArray &ProjectUnit::encoding() const @@ -1946,12 +1999,19 @@ Qt::ItemFlags ProjectModel::flags(const QModelIndex &index) const return Qt::NoItemFlags; if (p==mProject->rootNode().get()) return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable; - Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; - if (p->unitIndex<0) { - flags.setFlag(Qt::ItemIsDropEnabled); - flags.setFlag(Qt::ItemIsDragEnabled,false); + if (mProject && mProject->modelType() == ProjectModelType::FileSystem) { + Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + if (p->unitIndex>=0) + flags.setFlag(Qt::ItemIsEditable); + return flags; + } else { + Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; + if (p->unitIndex<0) { + flags.setFlag(Qt::ItemIsDropEnabled); + flags.setFlag(Qt::ItemIsDragEnabled,false); + } + return flags; } - return flags; } bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int role) @@ -2036,7 +2096,12 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int // Add new filename to file minitor pMainWindow->fileSystemWatcher()->addPath(newName); - emit dataChanged(index,index); + //suffix changed + if (mProject && mProject->modelType() == ProjectModelType::FileSystem + && QFileInfo(oldName).suffix()!=QFileInfo(newName).suffix()) { + mProject->rebuildNodes(); + } else + emit dataChanged(index,index); return true; } else { //change folder name @@ -2225,5 +2290,7 @@ bool ProjectModelSortFilterProxy::lessThan(const QModelIndex &source_left, const return true; if (pLeft->unitIndex>=0 && pRight->unitIndex<0) return false; + if (pLeft->priority!=pRight->priority) + return pLeft->priority>pRight->priority; return QString::compare(pLeft->text, pRight->text)<0; } diff --git a/RedPandaIDE/project.h b/RedPandaIDE/project.h index b40fed8d..1739dbce 100644 --- a/RedPandaIDE/project.h +++ b/RedPandaIDE/project.h @@ -33,6 +33,7 @@ struct ProjectModelNode { QString text; std::weak_ptr parent; int unitIndex; + int priority; QList children; int level; }; @@ -132,6 +133,13 @@ protected: bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; }; +enum ProjectSpecialFolderNode { + HEADERS, + SOURCES, + OTHERS, + NonSpecial +}; + class ProjectTemplate; class Project : public QObject { @@ -152,27 +160,19 @@ public: bool rebuild); QString folder(); void buildPrivateResource(bool forceSave=false); - void checkProjectFileForUpdate(SimpleIni& ini); void closeUnit(int index); - void createFolderNodes(); void doAutoOpen(); bool fileAlreadyExists(const QString& s); - PProjectModelNode folderNodeFromName(const QString& name); char getCompilerOption(const QString& optionString); QString getFolderPath(PProjectModelNode node); int getUnitFromString(const QString& s); void incrementBuildNumber(); int indexInUnits(const QString& fileName) const; int indexInUnits(const Editor* editor) const; - QString listUnitStr(const QChar& separator); - void loadLayout(); // load all [UnitX] - void loadOptions(SimpleIni& ini); - void loadUnitLayout(Editor *e, int index); // load single [UnitX] cursor positions - PProjectModelNode makeNewFileNode(const QString& s, bool isFolder, PProjectModelNode newParent); - PProjectModelNode makeProjectNode(); PProjectUnit newUnit(PProjectModelNode parentNode, const QString& customFileName=""); Editor* openUnit(int index); + PProjectModelNode pointerToNode(ProjectModelNode * p, PProjectModelNode parent=PProjectModelNode()); void rebuildNodes(); bool removeUnit(int index, bool doClose, bool removeFile = false); bool removeFolder(PProjectModelNode node); @@ -181,17 +181,13 @@ public: void saveLayout(); // save all [UnitX] void saveOptions(); void saveUnitAs(int i, const QString& sFileName, bool syncEditor = true); // save single [UnitX] - void saveUnitLayout(Editor* e, int index); // save single [UnitX] cursor positions bool saveUnits(); PProjectUnit findUnitByFilename(const QString& filename); void associateEditor(Editor* editor); void associateEditorToUnit(Editor* editor, PProjectUnit unit); void setCompilerOption(const QString& optionString, char value); - void sortUnitsByPriority(); - void sortUnitsByAlpha(); void updateFolders(); void updateNodeIndexes(); - PProjectModelNode pointerToNode(ProjectModelNode * p, PProjectModelNode parent=PProjectModelNode()); void setCompilerSet(int compilerSetIndex); //void showOptions(); @@ -212,12 +208,29 @@ public: const QList &units() const; + ProjectModelType modelType() const; + void setModelType(ProjectModelType type); + signals: void nodesChanged(); void modifyChanged(bool value); private: + void checkProjectFileForUpdate(SimpleIni& ini); + void createFolderNodes(); + void createFileSystemFolderNodes(); + void createFileSystemFolderNode(ProjectSpecialFolderNode folderType, const QString& folderName, PProjectModelNode parent); + PProjectModelNode getParentFolderNode(const QString& filename); + PProjectModelNode findFolderNode(const QString& folderPath, ProjectSpecialFolderNode nodeType); + PProjectModelNode folderNodeFromName(const QString& name); + void loadOptions(SimpleIni& ini); + void loadLayout(); // load all [UnitX] + void loadUnitLayout(Editor *e, int index); // load single [UnitX] cursor positions + + PProjectModelNode makeNewFileNode(const QString& s, bool isFolder, PProjectModelNode newParent); + PProjectModelNode makeProjectNode(); void open(); void removeFolderRecurse(PProjectModelNode node); + void saveUnitLayout(Editor* e, int index); // save single [UnitX] cursor positions void updateFolderNode(PProjectModelNode node); void updateCompilerSetType(); @@ -230,7 +243,9 @@ private: QStringList mFolders; std::shared_ptr mParser; QList mFolderNodes; - PProjectModelNode mNode; + PProjectModelNode mRootNode; + QHash mSpecialNodes; + QHash mFileSystemFolderNodes; ProjectModel mModel; }; diff --git a/RedPandaIDE/projecttemplate.cpp b/RedPandaIDE/projecttemplate.cpp index f17f763d..b8cf3db0 100644 --- a/RedPandaIDE/projecttemplate.cpp +++ b/RedPandaIDE/projecttemplate.cpp @@ -148,6 +148,7 @@ void ProjectTemplate::readTemplateFile(const QString &fileName) } else { mOptions.encoding = fromByteArray(mIni->GetValue("Project","Encoding", ENCODING_AUTO_DETECT)); } + mOptions.modelType = (ProjectModelType)mIni->GetLongValue("Project", "ModelType", (int)ProjectModelType::FileSystem); } diff --git a/RedPandaIDE/settingsdialog/projectfileswidget.cpp b/RedPandaIDE/settingsdialog/projectfileswidget.cpp index 380b9d88..d160bbc4 100644 --- a/RedPandaIDE/settingsdialog/projectfileswidget.cpp +++ b/RedPandaIDE/settingsdialog/projectfileswidget.cpp @@ -56,7 +56,6 @@ void ProjectFilesWidget::doSave() unit->setBuildCmd(unitCopy->buildCmd()); unit->setEncoding(unitCopy->encoding()); } - pMainWindow->project()->sortUnitsByPriority(); pMainWindow->project()->saveUnits(); copyUnits(); ui->treeProject->expandAll(); diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index c2683509..5e6ef97c 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -1116,7 +1116,7 @@ void copyFolder(const QString &fromDir, const QString &toDir) while (it.hasNext()){ it.next(); const auto fileInfo = it.fileInfo(); - if(!fileInfo.isHidden()) { //filters dot and dotdot + if(!fileInfo.isHidden() && !fileInfo.fileName().startsWith('.')) { //filters dot and dotdot const QString subPathStructure = fileInfo.absoluteFilePath().mid(absSourcePathLength); const QString constructedAbsolutePath = targetDir.absolutePath() + subPathStructure; if(fileInfo.isDir()){ diff --git a/Red_Panda_CPP.pro b/Red_Panda_CPP.pro index 5e213ca5..2dd6616e 100644 --- a/Red_Panda_CPP.pro +++ b/Red_Panda_CPP.pro @@ -7,7 +7,7 @@ SUBDIRS += \ APP_NAME = RedPandaCPP -APP_VERSION = 0.14.1 +APP_VERSION = 0.14.2 linux: {