diff --git a/NEWS.md b/NEWS.md index 1562aed0..011136b5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,9 @@ Red Panda C++ Version 1.5 - fix: project files that lies in project include folder is wrongly openned in Read-only mode - - enhancement: add/new/remove project files won't rebuild project tree + - enhancement: add/new/remove/rename project files won't rebuild project tree + - fix: gliches in UI's left panel in some OS + - fix: correctly restore project layout when reopen it Red Panda C++ Version 1.4 diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 151891a2..f1137c4e 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -336,8 +336,8 @@ bool Editor::saveAs(const QString &name, bool fromProject){ } // Update project information if (mInProject && pMainWindow->project() && !fromProject) { - int unitId = pMainWindow->project()->findUnitId(newName); - if (unitId<0) { + PProjectUnit unit = pMainWindow->project()->findUnit(newName); + if (!unit) { mInProject = false; } } diff --git a/RedPandaIDE/editorlist.cpp b/RedPandaIDE/editorlist.cpp index 1d7c789e..860787f5 100644 --- a/RedPandaIDE/editorlist.cpp +++ b/RedPandaIDE/editorlist.cpp @@ -169,10 +169,8 @@ bool EditorList::closeEditor(Editor* editor, bool transferFocus, bool force) { // } if (editor->inProject() && pMainWindow->project()) { - int unitId = pMainWindow->project()->findUnitId(editor); - if (unitId>=0) { - pMainWindow->project()->closeUnit(unitId); - } + PProjectUnit unit = pMainWindow->project()->findUnit(editor); + pMainWindow->project()->closeUnit(unit); } else { if (pSettings->history().addToOpenedFiles(editor->filename())) { pMainWindow->rebuildOpenedFileHisotryMenu(); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 272579d3..9caa4618 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -2224,6 +2224,10 @@ void MainWindow::loadLastOpens() QByteArray encoding = unit ? unit->encoding() : (pSettings->editor().autoDetectFileEncoding()? ENCODING_AUTO_DETECT : pSettings->editor().defaultEncoding()); Editor * editor = mEditorList->newEditor(editorFilename, encoding, inProject,false,page); + + if (inProject && editor) { + mProject->loadUnitLayout(editor); + } // if (mProject) { // mProject->associateEditorToUnit(editor,unit); // } @@ -2943,15 +2947,13 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos) bool onRoot = false; bool folderEmpty = false; bool multiSelection = ui->projectView->selectionModel()->selectedRows().count()>1; - int unitIndex = -1; QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->selectionModel()->currentIndex()); if (current.isValid() && mProject) { ProjectModelNode * node = static_cast(current.internalPointer()); PProjectModelNode pNode = mProject->pointerToNode(node); if (pNode) { - unitIndex = pNode->unitIndex; - onFolder = (unitIndex<0); - onUnit = (unitIndex >= 0); + onFolder = (!pNode->isUnit); + onUnit = (pNode->isUnit); onRoot = false; if (onFolder && !onRoot) { folderEmpty = pNode->children.isEmpty(); @@ -3022,11 +3024,11 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos) } QModelIndex realIndex = mProjectProxyModel->mapToSource(index); ProjectModelNode * node = static_cast(realIndex.internalPointer()); - if (!node || node->unitIndex<0) { + if (!node || !node->isUnit) { shouldAdd=false; break; } - PProjectUnit pUnit=mProject->findUnitById(node->unitIndex); + PProjectUnit pUnit=node->pUnit.lock(); if (mProject->model()->iconProvider()->VCSRepository()->isFileInRepository( pUnit->fileName() ) @@ -3893,7 +3895,7 @@ void MainWindow::onProjectRemoveFolder() PProjectModelNode folderNode = mProject->pointerToNode(node); if (!folderNode) return; - if (folderNode->unitIndex>=0) + if (folderNode->isUnit) return; mProject->removeFolder(folderNode); mProject->saveOptions(); @@ -3919,7 +3921,7 @@ void MainWindow::onProjectAddFolder() PProjectModelNode folderNode = mProject->pointerToNode(node); if (!folderNode) folderNode = mProject->rootNode(); - if (folderNode->unitIndex>=0) + if (folderNode->isUnit) return; QString s=tr("New folder"); int i=1; @@ -4267,6 +4269,7 @@ void MainWindow::closeProject(bool refreshEditor) auto action3 = finally([this]{ mEditorList->endUpdate(); }); + mProject->closeAllUnits(); mProject.reset(); if (!mQuitting && refreshEditor) { @@ -4294,9 +4297,8 @@ void MainWindow::updateProjectView() if (mProjectProxyModel->sourceModel()!=mProject->model()) { mProjectProxyModel->setSourceModel(mProject->model()); mProjectProxyModel->sort(0); -// connect(mProject->model(), &ProjectModel::dataChanged, -// this, &MainWindow::invalidateProjectProxyModel); -// connect(mProject->model(), &ProjectModel::rowsRemoved, + connect(mProject.get(), &Project::nodeRenamed, + this, &MainWindow::onProjectViewNodeRenamed); // this, &MainWindow::invalidateProjectProxyModel); // connect(mProject->model(), &ProjectModel::rowsInserted, // this, &MainWindow::invalidateProjectProxyModel); @@ -5760,8 +5762,9 @@ void MainWindow::on_projectView_doubleClicked(const QModelIndex &index) ProjectModelNode * node = static_cast(sourceIndex.internalPointer()); if (!node) return; - if (node->unitIndex>=0) { - mProject->openUnit(node->unitIndex); + if (node->isUnit) { + PProjectUnit unit = node->pUnit.lock(); + mProject->openUnit(unit); } } @@ -5967,7 +5970,8 @@ void MainWindow::on_actionRemove_from_project_triggered() PProjectModelNode folderNode = mProject->pointerToNode(node); if (!folderNode) continue; - mProject->removeUnit(folderNode->unitIndex, true, removeFile); + PProjectUnit unit = folderNode->pUnit.lock(); + mProject->removeUnit(unit, true, removeFile); }; ui->projectView->selectionModel()->clearSelection(); mProject->saveAll(); @@ -6159,7 +6163,7 @@ void MainWindow::newProjectUnitFile() } PProjectModelNode pNode = mProject->pointerToNode(node); - while (pNode && pNode->unitIndex>0) { + while (pNode && pNode->isUnit) { pNode = pNode->parent.lock(); } @@ -6235,13 +6239,8 @@ void MainWindow::newProjectUnitFile() setProjectViewCurrentUnit(newUnit); -// mProject->rebuildNodes(); mProject->saveAll(); -// updateProjectView(); -// idx = newUnit->id; - Editor * editor = mProject->openUnit(newUnit->id(), false); - //editor->setUseCppSyntax(mProject->options().useGPP); - //editor->setModified(true); + Editor * editor = mProject->openUnit(newUnit, false); if (editor) editor->activate(); QString branch; @@ -6311,6 +6310,11 @@ void MainWindow::setProjectViewCurrentUnit(std::shared_ptr unit) { } } +void MainWindow::onProjectViewNodeRenamed() +{ + updateProjectView(); +} + void MainWindow::setProjectViewCurrentNode(PProjectModelNode node) { if (node) { @@ -7576,8 +7580,8 @@ void MainWindow::on_actionGit_Add_Files_triggered() PProjectModelNode folderNode = mProject->pointerToNode(node); if (!folderNode) continue; - if (folderNode->unitIndex>=0) { - PProjectUnit unit = mProject->findUnitById(folderNode->unitIndex); + if (folderNode->isUnit) { + PProjectUnit unit = folderNode->pUnit.lock(); QFileInfo info(unit->fileName()); QString output; vcsManager.add(info.absolutePath(),info.fileName(),output); diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index a673d77a..c1bce69a 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -276,6 +276,7 @@ private: void setProjectViewCurrentUnit(std::shared_ptr unit); private slots: + void onProjectViewNodeRenamed(); void setDockExplorerToArea(const Qt::DockWidgetArea &area); void setDockMessagesToArea(const Qt::DockWidgetArea &area); void updateVCSActions(); diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 301dca55..62977126 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -473,12 +473,15 @@ QTabWidget::West - 1 + 4 true + + true + :/icons/images/newlook24/018-copy.png:/icons/images/newlook24/018-copy.png @@ -561,6 +564,9 @@ + + true + :/icons/images/newlook24/049-newproj.png:/icons/images/newlook24/049-newproj.png @@ -612,6 +618,9 @@ + + true + :/icons/images/newlook24/088-watch.png:/icons/images/newlook24/088-watch.png @@ -654,6 +663,9 @@ + + true + :/icons/images/newlook24/087-update.png:/icons/images/newlook24/087-update.png @@ -693,6 +705,9 @@ + + true + :/icons/images/newlook24/014-compopt.png:/icons/images/newlook24/014-compopt.png diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index ae289e26..55c8126b 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include "customfileiconprovider.h" #include #include "settings.h" @@ -193,22 +196,19 @@ void Project::open() newUnit->setEncoding(ENCODING_AUTO_DETECT); } newUnit->setNew(false); - newUnit->setParent(this); PProjectModelNode parentNode; if (mOptions.modelType==ProjectModelType::FileSystem) { parentNode = getParentFileSystemFolderNode(newUnit->fileName()); } else { parentNode = getCustomeFolderNodeFromName(newUnit->folder()); } - PProjectModelNode node = makeNewFileNode(extractFileName(newUnit->fileName()), - newUnit->id(), + PProjectModelNode node = makeNewFileNode(newUnit, newUnit->priority(), parentNode ); newUnit->setNode(node); - mUnits.insert(newUnit->id(),newUnit); + mUnits.insert(newUnit->fileName(),newUnit); } - //rebuildNodes(); } void Project::setFileName(QString value) @@ -242,7 +242,7 @@ PProjectModelNode Project::makeNewFolderNode( if (newParent) { node->level = newParent->level+1; } - node->unitIndex = -1; + node->isUnit=false; node->priority = priority; node->folderNodeType = nodeType; QModelIndex parentIndex=mModel.getNodeIndex(newParent.get()); @@ -251,18 +251,19 @@ PProjectModelNode Project::makeNewFolderNode( return node; } -PProjectModelNode Project::makeNewFileNode(const QString &fileName, int unitId,int priority, PProjectModelNode newParent) +PProjectModelNode Project::makeNewFileNode(PProjectUnit unit,int priority, PProjectModelNode newParent) { PProjectModelNode node = std::make_shared(); if (!newParent) { newParent = mRootNode; } node->parent = newParent; - node->text = fileName; + node->text = extractFileName(unit->fileName()); if (newParent) { node->level = newParent->level+1; } - node->unitIndex = unitId; + node->isUnit = true; + node->pUnit = unit; node->priority = priority; node->folderNodeType = ProjectModelNodeType::File; @@ -277,7 +278,7 @@ PProjectModelNode Project::makeProjectNode() PProjectModelNode node = std::make_shared(); node->text = mName; node->level = 0; - node->unitIndex = -1; + node->isUnit = false; node->folderNodeType = ProjectModelNodeType::Folder; return node; } @@ -290,7 +291,7 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo if (!parentNode) parentNode = mRootNode; // project root node - if (parentNode->unitIndex>=0) { //it's a file + if (parentNode->isUnit) { //it's a file parentNode = mRootNode; } QString s; @@ -313,11 +314,9 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo newUnit->setFileName(s); newUnit->setNew(true); newUnit->setFolder(getNodePath(parentNode)); - PProjectModelNode node = makeNewFileNode(extractFileName(newUnit->fileName()), - newUnit->id(),newUnit->priority(),parentNode); - node->unitIndex = newUnit->id(); + PProjectModelNode node = makeNewFileNode(newUnit,newUnit->priority(),parentNode); newUnit->setNode(node); - mUnits.insert(newUnit->id(), newUnit); + mUnits.insert(newUnit->fileName(), newUnit); //parentNode.Expand(True); switch(getFileType(customFileName)) { @@ -349,12 +348,7 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo return newUnit; } -Editor *Project::openUnit(int index, bool forceOpen) -{ - - PProjectUnit unit = mUnits.value(index,PProjectUnit()); - if (!unit) - return nullptr; +Editor* Project::openUnit(PProjectUnit& unit, bool forceOpen) { if (!unit->fileName().isEmpty() && fileExists(unit->fileName())) { if (getFileType(unit->fileName())==FileType::Other) { @@ -375,22 +369,16 @@ Editor *Project::openUnit(int index, bool forceOpen) if (editor) { editor->setInProject(true); //unit->setEncoding(encoding); - editor->activate(); loadUnitLayout(editor); + editor->activate(); return editor; } } return nullptr; } -Editor *Project::openUnit(PProjectEditorLayout editorLayout) +Editor *Project::openUnit(PProjectUnit &unit, const PProjectEditorLayout &layout) { - if (!editorLayout) - return nullptr; - PProjectUnit unit = findUnit(editorLayout->filename); - if (!unit) - return nullptr; - if (!unit->fileName().isEmpty() && fileExists(unit->fileName())) { if (getFileType(unit->fileName())==FileType::Other) { return nullptr; @@ -407,26 +395,28 @@ Editor *Project::openUnit(PProjectEditorLayout editorLayout) editor = mEditorList->newEditor(unit->fileName(), encoding, true, unit->isNew()); if (editor) { editor->setInProject(true); - //unit->setEncoding(encoding); + editor->setCaretY(layout->caretY); + editor->setCaretX(layout->caretX); + editor->setTopLine(layout->topLine); + editor->setLeftChar(layout->leftChar); editor->activate(); - editor->setTopLine(editorLayout->topLine); - editor->setLeftChar(editorLayout->leftChar); - editor->setCaretX(editorLayout->caretX); - editor->setCaretY(editorLayout->caretY); return editor; } } return nullptr; - } Editor *Project::unitEditor(const PProjectUnit &unit) const { + if (!unit) + return nullptr; return mEditorList->getOpenedEditorByFilename(unit->fileName()); } Editor *Project::unitEditor(const ProjectUnit *unit) const { + if (!unit) + return nullptr; return mEditorList->getOpenedEditorByFilename(unit->fileName()); } @@ -456,13 +446,11 @@ void Project::rebuildNodes() QFileInfo fileInfo(pUnit->fileName()); pUnit->setNode( makeNewFileNode( - fileInfo.fileName(), - pUnit->id(), + pUnit, pUnit->priority(), getCustomeFolderNodeFromName(pUnit->folder()) ) ); - pUnit->node()->priority = pUnit->priority(); } break; case ProjectModelType::FileSystem: @@ -472,26 +460,22 @@ void Project::rebuildNodes() QFileInfo fileInfo(pUnit->fileName()); pUnit->setNode( makeNewFileNode( - fileInfo.fileName(), - pUnit->id(), + pUnit, pUnit->priority(), getParentFileSystemFolderNode( pUnit->fileName()) ) ); - pUnit->node()->priority = pUnit->priority(); } break; } mModel.endUpdate(); - emit nodesChanged(); } -bool Project::removeUnit(int id, bool doClose , bool removeFile) +bool Project::removeUnit(PProjectUnit& unit, bool doClose , bool removeFile) { - PProjectUnit unit = findUnitById(id); if (!unit) return false; @@ -514,20 +498,20 @@ bool Project::removeUnit(int id, bool doClose , bool removeFile) PProjectModelNode node = unit->node(); PProjectModelNode parentNode = node->parent.lock(); if (!parentNode) { - mUnits.remove(unit->id()); + mUnits.remove(unit->fileName()); return true; } int row = parentNode->children.indexOf(unit->node()); if (row<0) { - mUnits.remove(unit->id()); + mUnits.remove(unit->fileName()); return true; } QModelIndex parentIndex = mModel.getNodeIndex(parentNode.get()); mModel.removeRow(row,parentIndex); - mUnits.remove(unit->id()); + mUnits.remove(unit->fileName()); //remove empty parent node PProjectModelNode currentNode = parentNode; @@ -558,7 +542,7 @@ bool Project::removeFolder(PProjectModelNode node) return false; // Check if this is actually a folder - if (node->unitIndex>=0 || node->level<1) + if (node->isUnit || node->level<1) return false; // Let this function call itself @@ -594,7 +578,7 @@ void Project::saveAll() void Project::saveLayout() { - SimpleIni layIni; + QJsonObject jsonRoot; QHash editorOrderSet; // Write list of open project files int order=0; @@ -611,52 +595,61 @@ void Project::saveLayout() // Remember what files were visible mEditorList->getVisibleEditors(e, e2); if (e) - layIni.SetValue("Editors","Focused", e->filename().toUtf8()); + jsonRoot["focused"]=e->filename(); + + QJsonArray jsonLayouts; // save editor info foreach (const PProjectUnit& unit,mUnits) { Editor* editor = unitEditor(unit); if (editor) { - QByteArray groupName = QString("E_%1").arg(editor->filename()).toUtf8(); - layIni.SetLongValue(groupName,"CursorCol", editor->caretX()); - layIni.SetLongValue(groupName,"CursorRow", editor->caretY()); - layIni.SetLongValue(groupName,"TopLine", editor->topLine()); - layIni.SetLongValue(groupName,"LeftChar", editor->leftChar()); + QJsonObject jsonLayout; + jsonLayout["filename"]=unit->fileName(); + jsonLayout["caretX"]=editor->caretX(); + jsonLayout["caretY"]=editor->caretY(); + jsonLayout["topLine"]=editor->topLine(); + jsonLayout["leftChar"]=editor->leftChar(); int order=editorOrderSet.value(editor->filename(),-1); if (order>=0) { - layIni.SetLongValue(groupName,"Order",order); + jsonLayout["order"]=order; } + jsonLayouts.append(jsonLayout); } - // remove old data from project file -// SimpleIni ini; -// ini.LoadFile(filename().toLocal8Bit()); -// groupName = toByteArray(QString("Unit%1").arg(i+1)); -// ini.Delete(groupName,"Open"); -// ini.Delete(groupName,"Top"); -// ini.Delete(groupName,"CursorCol"); -// ini.Delete(groupName,"CursorRow"); -// ini.Delete(groupName,"TopLine"); -// ini.Delete(groupName,"LeftChar"); -// ini.SaveFile(filename().toLocal8Bit()); } - layIni.SaveFile(changeFileExt(filename(), "layout").toLocal8Bit()); + jsonRoot["editorLayouts"]=jsonLayouts; + QString jsonFilename=changeFileExt(filename(), "layout"); + QFile file(jsonFilename); + if (file.open(QFile::WriteOnly|QFile::Truncate)) { + QJsonDocument doc(jsonRoot); + file.write(doc.toJson(QJsonDocument::Indented)); + file.close(); + } else { + throw FileError(QObject::tr("Can't open file '%1' for write.") + .arg(jsonFilename)); + } } -void Project::renameUnit(int idx, const QString &sFileName) +void Project::renameUnit(PProjectUnit& unit, const QString &sFileName) { - PProjectUnit unit = findUnitById(idx); if (!unit) return; + if (sFileName.compare(unit->fileName(),PATH_SENSITIVITY)==0) + return; + if (fileExists(unit->fileName())) { unit->setNew(false); } + Editor * editor=unitEditor(unit); if (editor) { //prevent recurse editor->saveAs(sFileName,true); } - unit->setNew(false); - unit->setFileName(sFileName); + removeUnit(unit,false,false); + PProjectModelNode parentNode = unit->node()->parent.lock(); + unit = addUnit(sFileName,parentNode); setModified(true); + + emit nodeRenamed(); } bool Project::saveUnits() @@ -725,18 +718,9 @@ bool Project::saveUnits() return true; } -PProjectUnit Project::findUnitById(int id) -{ - return mUnits.value(id,PProjectUnit()); -} - PProjectUnit Project::findUnit(const QString &filename) { - foreach(PProjectUnit unit, mUnits) { - if (QString::compare(unit->fileName(),filename, PATH_SENSITIVITY)==0) - return unit; - } - return PProjectUnit(); + return mUnits.value(filename,PProjectUnit()); } PProjectUnit Project::findUnit(const Editor *editor) @@ -854,6 +838,9 @@ bool Project::assignTemplate(const std::shared_ptr aTemplate, b if (!aTemplate) { return true; } + mModel.beginUpdate(); + mRootNode = makeProjectNode(); + mOptions = aTemplate->options(); mOptions.compilerSet = pSettings->compilerSets().defaultIndex(); mOptions.isCpp = useCpp; @@ -921,7 +908,7 @@ bool Project::assignTemplate(const std::shared_ptr aTemplate, b } } } - rebuildNodes(); + mModel.endUpdate(); return true; } @@ -1188,17 +1175,16 @@ PProjectUnit Project::addUnit(const QString &inFileName, PProjectModelNode paren newUnit->setCompileCpp(false); newUnit->setLink(false); } - newUnit->setFolder(getNodePath(parentNode)); + if (mOptions.modelType == ProjectModelType::FileSystem) + newUnit->setFolder(getNodePath(parentNode)); newUnit->setPriority(1000); newUnit->setOverrideBuildCmd(false); newUnit->setBuildCmd(""); - PProjectModelNode node = makeNewFileNode(extractFileName(newUnit->fileName()), - newUnit->id(), + PProjectModelNode node = makeNewFileNode(newUnit, newUnit->priority(), parentNode); - node->unitIndex = newUnit->id(); newUnit->setNode(node); - mUnits.insert(newUnit->id(),newUnit); + mUnits.insert(newUnit->fileName(),newUnit); setModified(true); return newUnit; @@ -1487,6 +1473,17 @@ void Project::buildPrivateResource(bool forceSave) stringsToFile(contents,hFile); } +void Project::closeAllUnits() +{ + foreach (PProjectUnit unit, mUnits) { + Editor * editor = unitEditor(unit); + if (editor) { + editor->setInProject(false); + mEditorList->forceCloseEditor(editor); + } + } +} + void Project::checkProjectFileForUpdate(SimpleIni &ini) { bool cnvt = false; @@ -1537,10 +1534,10 @@ void Project::checkProjectFileForUpdate(SimpleIni &ini) QMessageBox::Ok); } -void Project::closeUnit(int id) +void Project::closeUnit(PProjectUnit& unit) { - PProjectUnit unit = findUnitById(id); - Editor * editor =unitEditor(unit); + saveLayout(); + Editor * editor = unitEditor(unit); if (editor) { editor->setInProject(false); mEditorList->forceCloseEditor(editor); @@ -1563,12 +1560,14 @@ void Project::createFolderNodes() node = makeNewFolderNode(s.mid(0,i),node); else node = findnode; - node->unitIndex = -1; + if (!node->isUnit) { + qDebug()<<"node "<text<<"is not a folder:"<unitIndex = -1; mCustomFolderNodes.append(node); } } @@ -1715,11 +1714,11 @@ QString Project::getNodePath(PProjectModelNode node) if (!node) return result; - if (node->unitIndex>=0) // not a folder + if (node->isUnit) // not a folder return result; PProjectModelNode p = node; - while (p && p->unitIndex==-1 && p!=mRootNode) { + while (p && !p->isUnit && p!=mRootNode) { if (!result.isEmpty()) result = p->text + "/" + result; else @@ -1729,11 +1728,6 @@ QString Project::getNodePath(PProjectModelNode node) return result; } -int Project::getUnitFromString(const QString &s) -{ - return findUnitId(s); -} - PProjectModelNode Project::getParentFileSystemFolderNode(const QString &filename) { QFileInfo fileInfo(filename); @@ -1763,47 +1757,59 @@ void Project::incrementBuildNumber() PProjectUnit Project::loadLayout() { - SimpleIni layIni; - SI_Error error = layIni.LoadFile(changeFileExt(filename(), "layout").toLocal8Bit()); - if (error!=SI_OK) + QString jsonFilename = changeFileExt(filename(), "layout"); + qDebug()<<"read file"< opennedMap; - SimpleIni::TNamesDepend sections; - layIni.GetAllSections(sections); - QSet sectionNames; - for(const SimpleIni::Entry& entry:sections) { - QString key(entry.pItem); - sectionNames.insert(key); - } - foreach (PProjectUnit unit,mUnits) { - QByteArray groupName = QString("E_%1").arg(unit->fileName()).toUtf8(); - if (sectionNames.contains(groupName)) { + for (int i=0;i(); - editorLayout->filename=unit->fileName(); - editorLayout->topLine=layIni.GetLongValue(groupName,"TopLine"); - editorLayout->leftChar=layIni.GetLongValue(groupName,"LeftChar"); - editorLayout->caretX=layIni.GetLongValue(groupName,"CursorCol"); - editorLayout->caretY=layIni.GetLongValue(groupName,"CursorRow"); - int order = layIni.GetLongValue(groupName,"Order",-1); + editorLayout->filename=unitFilename; + editorLayout->topLine=jsonLayout["topLine"].toInt(); + editorLayout->leftChar=jsonLayout["leftChar"].toInt(); + editorLayout->caretX=jsonLayout["caretX"].toInt(); + editorLayout->caretY=jsonLayout["caretY"].toInt(); + int order = jsonLayout["order"].toInt(-1); if (order>=0) opennedMap.insert(order,editorLayout); } } + for (int i=0;ifilename); + openUnit(unit,editorLayout); } } - PProjectUnit unit = findUnit(focusedFilename); - if (unit) { - Editor * editor = unitEditor(unit); - if (editor) - editor->activate(); + + QString focusedFilename = jsonRoot["focused"].toString(); + + if (!focusedFilename.isEmpty()) { + PProjectUnit unit = findUnit(focusedFilename); + if (unit) { + Editor * editor = unitEditor(unit); + if (editor) + editor->activate(); + } + return unit; } - return unit; + return PProjectUnit(); } void Project::loadOptions(SimpleIni& ini) @@ -2050,16 +2056,37 @@ void Project::loadUnitLayout(Editor *e) { if (!e) return; - SimpleIni layIni; - SI_Error error; - error = layIni.LoadFile(changeFileExt(filename(), "layout").toLocal8Bit()); - if (error != SI_Error::SI_OK) + + QString jsonFilename = changeFileExt(filename(), "layout"); + QFile file(jsonFilename); + if (!file.open(QIODevice::ReadOnly)) return; - QByteArray groupName = (QString("E_%1").arg(e->filename())).toUtf8(); - e->setCaretY(layIni.GetLongValue(groupName,"CursorRow",1)); - e->setCaretX(layIni.GetLongValue(groupName,"CursorCol",1)); - e->setTopLine(layIni.GetLongValue(groupName,"TopLine",1)); - e->setLeftChar(layIni.GetLongValue(groupName,"LeftChar",1)); + QByteArray content = file.readAll(); + QJsonParseError parseError; + QJsonDocument doc{QJsonDocument::fromJson(content,&parseError)}; + file.close(); + if (parseError.error!=QJsonParseError::NoError) + return; + + QJsonObject jsonRoot=doc.object(); + + QJsonArray jsonLayouts=jsonRoot["editorLayouts"].toArray(); + + QHash opennedMap; + for (int i=0;ifilename(),PATH_SENSITIVITY)==0) { + qDebug()<filename(); + e->setCaretY(jsonLayout["caretY"].toInt()); + e->setCaretX(jsonLayout["caretX"].toInt()); + e->setTopLine(jsonLayout["topLine"].toInt()); + e->setLeftChar(jsonLayout["leftChar"].toInt()); + return; + } + } + + } PCppParser Project::cppParser() @@ -2067,23 +2094,6 @@ PCppParser Project::cppParser() return mParser; } -int Project::findUnitId(const QString &fileName) const -{ - QDir dir(directory()); - foreach (const PProjectUnit& unit, mUnits) { - if (dir.absoluteFilePath(fileName) == dir.absoluteFilePath(unit->fileName())) - return unit->id(); - } - return -1; -} - -int Project::findUnitId(const Editor *editor) const -{ - if (!editor) - return -1; - return findUnitId(editor->filename()); -} - void Project::removeFolderRecurse(PProjectModelNode node) { if (!node) @@ -2092,13 +2102,13 @@ void Project::removeFolderRecurse(PProjectModelNode node) for (int i=node->children.count()-1;i>=0;i++) { PProjectModelNode childNode = node->children[i]; // Remove folder inside folder - if (childNode->unitIndex<0 && childNode->level>0) { + if (!childNode->isUnit && childNode->level>0) { removeFolderRecurse(childNode); // Or remove editors at this level - } else if (childNode->unitIndex >= 0 && childNode->level > 0) { + } else if (childNode->isUnit && childNode->level > 0) { // Remove editor in folder from project - int editorIndex = childNode->unitIndex; - if (!removeUnit(editorIndex,true)) + PProjectUnit unit = childNode->pUnit.lock(); + if (!removeUnit(unit,true)) return; } } @@ -2113,7 +2123,7 @@ void Project::updateFolderNode(PProjectModelNode node) { for (int i=0;ichildren.count();i++){ PProjectModelNode child = node->children[i]; - if (child->unitIndex<0) { + if (!child->isUnit) { mFolders.append(getNodePath(child)); updateFolderNode(child); } @@ -2162,6 +2172,18 @@ QStringList Project::binDirs() return lst; } +void Project::renameFolderNode(PProjectModelNode node, const QString newName) +{ + if (!node) + return; + if (node->isUnit) + return; + node->text = newName; + updateFolders(); + setModified(true); + emit nodeRenamed(); +} + EditorList *Project::editorList() const { return mEditorList; @@ -2214,14 +2236,11 @@ const QString &Project::filename() const return mFilename; } -int ProjectUnit::mIdGenerator=0; - ProjectUnit::ProjectUnit(Project* parent) { mNode = nullptr; mParent = parent; mFileMissing = false; - mId=mIdGenerator++; mPriority=0; } @@ -2230,11 +2249,6 @@ Project *ProjectUnit::parent() const return mParent; } -void ProjectUnit::setParent(Project* newParent) -{ - mParent = newParent; -} - const QString &ProjectUnit::fileName() const { return mFileName; @@ -2416,16 +2430,6 @@ void ProjectUnit::setFileMissing(bool newDontSave) mFileMissing = newDontSave; } -int ProjectUnit::id() const -{ - return mId; -} - -void ProjectUnit::setId(int newId) -{ - mId = newId; -} - ProjectModel::ProjectModel(Project *project, QObject *parent): QAbstractItemModel(parent), mProject(project) @@ -2547,8 +2551,10 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const return p->text; } else if (role == Qt::DecorationRole) { QIcon icon; - if (p->unitIndex>=0) { - icon = mIconProvider->icon(mProject->findUnitById(p->unitIndex)->fileName()); + if (p->isUnit) { + PProjectUnit unit = p->pUnit.lock(); + if (unit) + icon = mIconProvider->icon(unit->fileName()); } else { if (p == mProject->rootNode().get()) { QString branch; @@ -2585,12 +2591,12 @@ Qt::ItemFlags ProjectModel::flags(const QModelIndex &index) const return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable; if (mProject && mProject->modelType() == ProjectModelType::FileSystem) { Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; - if (p->unitIndex>=0) + if (p->isUnit) flags.setFlag(Qt::ItemIsEditable); return flags; } else { Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; - if (p->unitIndex<0) { + if (!p->isUnit) { flags.setFlag(Qt::ItemIsDropEnabled); flags.setFlag(Qt::ItemIsDragEnabled,false); } @@ -2615,10 +2621,10 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int emit dataChanged(index,index); return true; } - int idx = node->unitIndex; - if (idx >= 0) { + PProjectUnit unit = node->pUnit.lock(); + if (unit) { //change unit name - PProjectUnit unit = mProject->findUnitById(idx); + QString newName = value.toString().trimmed(); if (newName.isEmpty()) return false; @@ -2642,9 +2648,9 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int mProject->editorList()->closeEditor(e); // Remove it from the current project... - int projindex = mProject->findUnitId(newName); - if (projindex>=0) { - mProject->removeUnit(projindex,false); + PProjectUnit unit = mProject->findUnit(newName); + if (unit) { + mProject->removeUnit(unit,false); } // All references to the file are removed. Delete the file from disk @@ -2674,17 +2680,13 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int QMessageBox::Ok); return false; } - mProject->renameUnit(idx,newName); + mProject->renameUnit(unit,newName); // Add new filename to file minitor mProject->fileSystemWatcher()->addPath(newName); - //suffix changed - if (mProject && mProject->modelType() == ProjectModelType::FileSystem - && QFileInfo(oldName).suffix()!=QFileInfo(newName).suffix()) { - mProject->rebuildNodes(); - } else - emit dataChanged(index,index); + mProject->saveAll(); + return true; } else { //change folder name @@ -2693,10 +2695,11 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int return false; if (newName == node->text) return false; - node->text = newName; - mProject->updateFolders(); - mProject->saveAll(); + mProject->renameFolderNode(node,newName); + emit dataChanged(index,index); + + mProject->saveAll(); return true; } @@ -2767,7 +2770,7 @@ bool ProjectModel::canDropMimeData(const QMimeData * data, Qt::DropAction action // } ProjectModelNode* p= static_cast(idx.internalPointer()); PProjectModelNode node = mProject->pointerToNode(p); - if (node->unitIndex>=0) + if (node->isUnit) return false; QByteArray encoded = data->data(format); QDataStream stream(&encoded, QIODevice::ReadOnly); @@ -2835,8 +2838,8 @@ bool ProjectModel::dropMimeData(const QMimeData *data, Qt::DropAction action, in beginInsertRows(newParentIndex,node->children.count(),node->children.count()); droppedNode->parent = node; node->children.append(droppedNode); - if (droppedNode->unitIndex>=0) { - PProjectUnit unit = mProject->findUnitById(droppedNode->unitIndex); + if (droppedNode->isUnit) { + PProjectUnit unit = droppedNode->pUnit.lock(); unit->setFolder(mProject->getNodePath(node)); } endInsertRows(); @@ -2863,8 +2866,10 @@ QMimeData *ProjectModel::mimeData(const QModelIndexList &indexes) const for (; it != indexes.end(); ++it) { stream << (qint32)((*it).row()) << (qint32)((*it).column()) << (quintptr)((*it).internalPointer()); ProjectModelNode* p = static_cast((*it).internalPointer()); - if (p && p->unitIndex>=0) { - urls.append(QUrl::fromLocalFile(mProject->findUnitById(p->unitIndex)->fileName())); + if (p && p->isUnit) { + PProjectUnit unit = p->pUnit.lock(); + if (unit) + urls.append(QUrl::fromLocalFile(unit->fileName())); } } if (!urls.isEmpty()) @@ -2893,9 +2898,9 @@ bool ProjectModelSortFilterProxy::lessThan(const QModelIndex &source_left, const return true; if (!pRight) return false; - if (pLeft->unitIndex<0 && pRight->unitIndex>=0) + if (!pLeft->isUnit && pRight->isUnit) return true; - if (pLeft->unitIndex>=0 && pRight->unitIndex<0) + if (pLeft->isUnit && !pRight->isUnit) return false; if (pLeft->priority!=pRight->priority) return pLeft->priority>pRight->priority; diff --git a/RedPandaIDE/project.h b/RedPandaIDE/project.h index c6fe7f4a..cacbd7e0 100644 --- a/RedPandaIDE/project.h +++ b/RedPandaIDE/project.h @@ -44,12 +44,15 @@ struct ProjectModelItemRecord { QString fullPath; }; +class ProjectUnit; + struct ProjectModelNode; using PProjectModelNode = std::shared_ptr; struct ProjectModelNode { QString text; std::weak_ptr parent; - int unitIndex; + bool isUnit; + std::weak_ptr pUnit; int priority; QList children; ProjectModelNodeType folderNodeType; @@ -71,7 +74,6 @@ class ProjectUnit { public: explicit ProjectUnit(Project* parent); Project* parent() const; - void setParent(Project* newParent); const QString &fileName() const; void setFileName(QString newFileName); bool isNew() const; @@ -102,10 +104,6 @@ public: bool FileMissing() const; void setFileMissing(bool newDontSave); - int id() const; - - void setId(int newId); - private: Project* mParent; QString mFileName; @@ -120,8 +118,6 @@ private: QByteArray mEncoding; PProjectModelNode mNode; bool mFileMissing; - int mId; - static int mIdGenerator; }; using PProjectUnit = std::shared_ptr; @@ -206,46 +202,37 @@ public: PProjectModelNode parentNode); QString folder(); void buildPrivateResource(bool forceSave=false); - void closeUnit(int id); + void closeAllUnits(); + void closeUnit(PProjectUnit& unit); PProjectUnit doAutoOpen(); bool fileAlreadyExists(const QString& s); QString getNodePath(PProjectModelNode node); - int getUnitFromString(const QString& s); void incrementBuildNumber(); PProjectUnit newUnit(PProjectModelNode parentNode, const QString& customFileName=""); - Editor* openUnit(int index, bool forceOpen=true); - Editor* openUnit(PProjectEditorLayout editorLayout); + Editor* openUnit(PProjectUnit& unit, bool forceOpen=true); + Editor* openUnit(PProjectUnit& unit, const PProjectEditorLayout& layout); Editor* unitEditor(const PProjectUnit& unit) const; Editor* unitEditor(const ProjectUnit* unit) const; - Editor* unitEditor(int id) const { - PProjectUnit unit=mUnits.value(id,PProjectUnit()); - if (!unit) - return nullptr; - return unitEditor(unit); - } QList unitList(); PProjectModelNode pointerToNode(ProjectModelNode * p, PProjectModelNode parent=PProjectModelNode()); void rebuildNodes(); - bool removeUnit(int id, bool doClose, bool removeFile = false); + bool removeUnit(PProjectUnit& unit, bool doClose, bool removeFile = false); bool removeFolder(PProjectModelNode node); void resetParserProjectFiles(); void saveAll(); // save [Project] and all [UnitX] void saveLayout(); // save all [UnitX] void saveOptions(); - void renameUnit(int idx, const QString& sFileName); + void renameUnit(PProjectUnit& unit, const QString& sFileName); bool saveUnits(); - PProjectUnit findUnitById(int id); PProjectUnit findUnit(const QString& filename); PProjectUnit findUnit(const Editor* editor); - int findUnitId(const QString& fileName) const; - int findUnitId(const Editor* editor) const; void associateEditor(Editor* editor); void associateEditorToUnit(Editor* editor, PProjectUnit unit); bool setCompileOption(const QString &key, const QString &value); @@ -283,9 +270,12 @@ public: QStringList binDirs(); + void renameFolderNode(PProjectModelNode node, const QString newName); + void loadUnitLayout(Editor *e); signals: - void nodesChanged(); + void nodeRenamed(); void modifyChanged(bool value); + private: void checkProjectFileForUpdate(SimpleIni& ini); void createFolderNodes(); @@ -296,7 +286,6 @@ private: PProjectModelNode getCustomeFolderNodeFromName(const QString& name); void loadOptions(SimpleIni& ini); PProjectUnit loadLayout(); - void loadUnitLayout(Editor *e); PProjectModelNode makeNewFolderNode( const QString& folderName, @@ -304,8 +293,8 @@ private: ProjectModelNodeType nodeType=ProjectModelNodeType::Folder, int priority=0); PProjectModelNode makeNewFileNode( - const QString& fileName, - int unitId, + //const QString& fileName, + PProjectUnit unit, int priority, PProjectModelNode newParent); PProjectModelNode makeProjectNode(); @@ -315,7 +304,7 @@ private: void updateCompilerSetType(); private: - QHash mUnits; + QHash mUnits; ProjectOptions mOptions; QString mFilename; QString mName; diff --git a/RedPandaIDE/settingsdialog/projectfileswidget.cpp b/RedPandaIDE/settingsdialog/projectfileswidget.cpp index 494b2db1..cd96a9eb 100644 --- a/RedPandaIDE/settingsdialog/projectfileswidget.cpp +++ b/RedPandaIDE/settingsdialog/projectfileswidget.cpp @@ -47,7 +47,7 @@ void ProjectFilesWidget::doSave() { for (int i=0;iproject()->findUnitById(unitCopy->id()); + PProjectUnit unit = pMainWindow->project()->findUnit(unitCopy->fileName()); unit->setPriority(unitCopy->priority()); unit->setCompile(unitCopy->compile()); unit->setLink(unitCopy->link()); @@ -70,11 +70,13 @@ PProjectUnit ProjectFilesWidget::currentUnit() ProjectModelNode* node = static_cast(index.internalPointer()); if (!node) return PProjectUnit(); - int idx = node->unitIndex; - if (idx>=0) { - foreach (PProjectUnit unit, mUnits) { - if (unit->id() == idx) - return unit; + if (!node->isUnit) + return PProjectUnit(); + PProjectUnit unit=node->pUnit.lock(); + if (unit) { + foreach (PProjectUnit tmpUnit, mUnits) { + if (tmpUnit->fileName() == unit->fileName()) + return tmpUnit; } } return PProjectUnit(); @@ -88,7 +90,6 @@ void ProjectFilesWidget::copyUnits() mUnits.clear(); foreach (const PProjectUnit& unit, project->unitList()) { PProjectUnit unitCopy = std::make_shared(project.get()); - unitCopy->setId(unit->id()); unitCopy->setPriority(unit->priority()); unitCopy->setCompile(unit->compile()); unitCopy->setLink(unit->link()); @@ -145,9 +146,8 @@ void ProjectFilesWidget::on_treeProject_doubleClicked(const QModelIndex &index) disableFileOptions(); return; } - int i = node->unitIndex; - if (i>=0) { - PProjectUnit unit = mUnits[i]; + PProjectUnit unit = node->pUnit.lock(); + if (unit) { ui->grpFileOptions->setEnabled(true); ui->spinPriority->setValue(unit->priority()); ui->chkCompile->setChecked(unit->compile());