From e0c4ba201dda549388bd9641e821bde3785c73b5 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Mon, 7 Nov 2022 21:44:12 +0800 Subject: [PATCH] - fix: Crash when editing a function at the end of file without ; or { - enhancement: Add the "parsing TODOs" option in Options Dialog / Editor / Misc - enhancement: Remove todos/bookmarks/breakpoints when deleting file from project - enhancement: Rename filenames in todos/bookmarks/breakpoints when renaming project file --- NEWS.md | 4 ++ RedPandaIDE/debugger.cpp | 23 +++++++ RedPandaIDE/debugger.h | 2 + RedPandaIDE/editor.cpp | 12 ++-- RedPandaIDE/mainwindow.cpp | 61 +++++++++++++++++-- RedPandaIDE/mainwindow.h | 8 ++- RedPandaIDE/parser/cppparser.cpp | 5 +- RedPandaIDE/project.cpp | 47 +------------- RedPandaIDE/project.h | 4 +- RedPandaIDE/settings.cpp | 13 ++++ RedPandaIDE/settings.h | 4 ++ .../settingsdialog/editormiscwidget.cpp | 3 + .../settingsdialog/editormiscwidget.ui | 11 +++- RedPandaIDE/widgets/bookmarkmodel.cpp | 19 ++++++ RedPandaIDE/widgets/bookmarkmodel.h | 1 + 15 files changed, 155 insertions(+), 62 deletions(-) diff --git a/NEWS.md b/NEWS.md index bc228de6..216e954f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,10 @@ Red Panda C++ Version 2.4 - fix: Contents in class browser not correctly updated when close the last editor for project. - fix: When all editors closed, switch browser mode dosen't correct update the class browser; - fix: "check when open/save" and "check when caret line changed" in Options Dialog / Editor / Syntax Check don't work + - fix: Crash when editing a function at the end of file without ; or { + - enhancement: Add the "parsing TODOs" option in Options Dialog / Editor / Misc + - enhancement: Remove todos/bookmarks/breakpoints when deleting file from project + - enhancement: Rename filenames in todos/bookmarks/breakpoints when renaming project file Red Panda C++ Version 2.3 diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index a10b97dd..4ef4f574 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -1843,6 +1843,29 @@ void BreakpointModel::removeBreakpoint(int row, bool forProject) endRemoveRows(); } +void BreakpointModel::removeBreakpointsInFile(const QString &fileName, bool forProject) +{ + QList & lst=forProject?mProjectBreakpoints:mBreakpoints; + for (int i=lst.count()-1;i>=0;i--) { + if (lst[i]->filename==fileName) + removeBreakpoint(i,forProject); + } +} + +void BreakpointModel::renameBreakpointFilenames(const QString &oldFileName, const QString &newFileName, bool forProject) +{ + QList & lst=forProject?mProjectBreakpoints:mBreakpoints; + for (int i=lst.count()-1;i>=0;i--) { + if (lst[i]->filename==oldFileName) { + lst[i]->filename=newFileName; + if (forProject == mIsForProject) { + QModelIndex index=createIndex(i,0); + emit dataChanged(index,index); + } + } + } +} + void BreakpointModel::invalidateAllBreakpointNumbers() { foreach (PBreakpoint bp,mBreakpoints) { diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index cd709d9d..6f9bbcb1 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -130,6 +130,8 @@ public: void addBreakpoint(PBreakpoint p, bool forProject); void clear(bool forProject); void removeBreakpoint(int index, bool forProject); + void removeBreakpointsInFile(const QString& fileName, bool forProject); + void renameBreakpointFilenames(const QString& oldFileName,const QString& newFileName, bool forProject); PBreakpoint setBreakPointCondition(int index, const QString& condition, bool forProject); const QList& breakpoints(bool forProject) const { return forProject?mProjectBreakpoints:mBreakpoints; diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 6262a270..4a3acdf8 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -350,7 +350,7 @@ bool Editor::saveAs(const QString &name, bool fromProject){ clearSyntaxIssues(); pMainWindow->fileSystemWatcher()->removePath(mFilename); - if (pSettings->codeCompletion().enabled() && mParser) { + if (pSettings->codeCompletion().enabled() && mParser && !inProject()) { mParser->invalidateFile(mFilename); } @@ -395,11 +395,14 @@ bool Editor::saveAs(const QString &name, bool fromProject){ } applyColorScheme(pSettings->editor().colorScheme()); - reparse(false); + if (!inProject()) + reparse(false); if (pSettings->editor().syntaxCheckWhenSave()) checkSyntaxInBack(); - reparseTodo(); + + if (!inProject()) + reparseTodo(); if (!shouldOpenInReadonly()) { setReadOnly(false); @@ -2775,7 +2778,8 @@ void Editor::reparseTodo() return; if (!highlighter()) return; - pMainWindow->todoParser()->parseFile(mFilename, inProject()); + if (pSettings->editor().parseTodos()) + pMainWindow->todoParser()->parseFile(mFilename, inProject()); } void Editor::insertString(const QString &value, bool moveCursor) diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index ee86e38b..59a350a6 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1127,7 +1127,7 @@ void MainWindow::rebuildOpenedFileHisotryMenu() //menu takes the ownership QAction* action = new QAction(filename,mMenuRecentProjects); connect(action, &QAction::triggered, [filename,this](bool){ - this->openProject(filename); + openProject(filename); }); mMenuRecentProjects->addAction(action); } @@ -1430,7 +1430,8 @@ void MainWindow::openProject(const QString &filename, bool openFiles) changeFileExt(mProject->filename(), PROJECT_DEBUG_EXT), mProject->directory()); mTodoModel.setIsForProject(true); - mTodoParser->parseFiles(mProject->unitFiles()); + if (pSettings->editor().parseTodos()) + mTodoParser->parseFiles(mProject->unitFiles()); if (openFiles) { PProjectUnit unit = mProject->doAutoOpen(); @@ -1455,6 +1456,7 @@ void MainWindow::openProject(const QString &filename, bool openFiles) mClassBrowserModel.endUpdate(); if (oldEditor) mEditorList->closeEditor(oldEditor); + setupSlotsForProject(); //updateForEncodingInfo(); } @@ -4565,6 +4567,7 @@ void MainWindow::onTodoParsingFile(const QString& filename) { mTodoModel.removeTodosForFile(filename); } + void MainWindow::onTodoParseStarted() { mTodoModel.clear(); @@ -6295,8 +6298,6 @@ void MainWindow::on_actionNew_Project_triggered() } mProject->saveAll(); updateProjectView(); - mTodoParser->parseFiles(mProject->unitFiles()); - scanActiveProject(true); Editor* editor = mEditorList->getEditor(); updateClassBrowserForEditor(editor); if (editor) { @@ -6308,8 +6309,12 @@ void MainWindow::on_actionNew_Project_triggered() ui->projectView->setCurrentIndex(index); } } + scanActiveProject(true); + if (pSettings->editor().parseTodos()) + mTodoParser->parseFiles(mProject->unitFiles()); if (pSettings->ui().showProject()) ui->tabExplorer->setCurrentWidget(ui->tabProject); + setupSlotsForProject(); } pSettings->ui().setNewProjectDialogWidth(dialog.width()); pSettings->ui().setNewProjectDialogHeight(dialog.height()); @@ -6842,6 +6847,49 @@ QString MainWindow::switchHeaderSourceTarget(Editor *editor) return QString(); } +void MainWindow::setupSlotsForProject() +{ + connect(mProject.get(), &Project::unitAdded, + this, &MainWindow::onProjectUnitAdded); + connect(mProject.get(), &Project::unitRemoved, + this, &MainWindow::onProjectUnitRemoved); + connect(mProject.get(), &Project::unitRenamed, + this, &MainWindow::onProjectUnitRenamed); +} + +void MainWindow::onProjectUnitAdded(const QString &filename) +{ + mProject->cppParser()->addProjectFile(filename,true); + if (pSettings->editor().parseTodos()) { + mTodoParser->parseFile(filename,true); + } +} + +void MainWindow::onProjectUnitRemoved(const QString &filename) +{ + mProject->cppParser()->invalidateFile(filename); + mProject->cppParser()->removeProjectFile(filename); + if (pSettings->editor().parseTodos()) { + mTodoModel.removeTodosForFile(filename); + } + mDebugger->breakpointModel()->removeBreakpointsInFile(filename,true); + mBookmarkModel->removeBookmarks(filename,true); +} + +void MainWindow::onProjectUnitRenamed(const QString &oldFilename, const QString &newFilename) +{ + mProject->cppParser()->invalidateFile(oldFilename); + mProject->cppParser()->removeProjectFile(oldFilename); + mProject->cppParser()->addProjectFile(newFilename,true); + parseFileList(mProject->cppParser()); + if (pSettings->editor().parseTodos()) { + mTodoModel.removeTodosForFile(oldFilename); + mTodoParser->parseFile(newFilename,true); + } + mBookmarkModel->renameBookmarkFile(oldFilename,newFilename,true); + mDebugger->breakpointModel()->renameBreakpointFilenames(oldFilename,newFilename,true); +} + void MainWindow::onProjectViewNodeRenamed() { updateProjectView(); @@ -7023,6 +7071,11 @@ void MainWindow::onEditorRenamed(const QString &oldFilename, const QString &newF { if (firstSave) mOJProblemSetModel.updateProblemAnswerFilename(oldFilename, newFilename); + Editor * editor=mEditorList->getOpenedEditorByFilename(newFilename); + if (editor && !editor->inProject()) { + mBookmarkModel->renameBookmarkFile(oldFilename,newFilename,false); + mDebugger->breakpointModel()->renameBreakpointFilenames(oldFilename,newFilename,false); + } } void MainWindow::on_EditorTabsLeft_currentChanged(int) diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 889850be..382431d6 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -293,14 +293,18 @@ private: QString switchHeaderSourceTarget(Editor *editor); private slots: + void setupSlotsForProject(); + void onProjectUnitAdded(const QString &filename); + void onProjectUnitRemoved(const QString &filename); + void onProjectUnitRenamed(const QString &oldFilename, const QString& newFilename); void onProjectViewNodeRenamed(); void setDockExplorerToArea(const Qt::DockWidgetArea &area); void setDockMessagesToArea(const Qt::DockWidgetArea &area); void updateVCSActions(); void invalidateProjectProxyModel(); - void onEditorRenamed(const QString& oldFilename, const QString& newFilename, bool firstSave); + void onEditorRenamed(const QString &oldFilename, const QString &newFilename, bool firstSave); void onAutoSaveTimeout(); - void onFileChanged(const QString& path); + void onFileChanged(const QString &path); void onFilesViewPathChanged(); void onWatchViewContextMenu(const QPoint& pos); void onBookmarkContextMenu(const QPoint& pos); diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index c3de053d..a5d42719 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -2619,10 +2619,11 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co } else mIndex++; } - - } + if (mIndex>=mTokenizer.tokenCount()) + return; + // Check if this is a prototype if (mTokenizer[mIndex]->text.startsWith(';') || mTokenizer[mIndex]->text.startsWith('}')) {// prototype diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index 851b1514..d8ae9745 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -329,8 +329,6 @@ PProjectModelNode Project::makeProjectNode() PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& customFileName) { - PProjectUnit newUnit = std::make_shared(this); - // Select folder to add unit to if (!parentNode) parentNode = mRootNode; // project root node @@ -348,47 +346,7 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo } else { s = cleanPath(dir.absoluteFilePath(customFileName)); } - if (mOptions.modelType == ProjectModelType::FileSystem) { - // in file system mode, parentNode is determined by file's path - parentNode = getParentFileSystemFolderNode(s); - } - // Add - - // Set all properties - newUnit->setFileName(s); - newUnit->setFolder(getNodePath(parentNode)); - PProjectModelNode node = makeNewFileNode(newUnit,newUnit->priority(),parentNode); - newUnit->setNode(node); - mUnits.insert(newUnit->fileName(), newUnit); - - //parentNode.Expand(True); - switch(getFileType(customFileName)) { - case FileType::CSource: - newUnit->setCompile(true); - newUnit->setCompileCpp(false); - newUnit->setLink(true); - break; - case FileType::CppSource: - newUnit->setCompile(true); - newUnit->setCompileCpp(true); - newUnit->setLink(true); - break; - case FileType::WindowsResourceSource: - newUnit->setCompile(true); - newUnit->setCompileCpp(mOptions.isCpp); - newUnit->setLink(false); - break; - default: - newUnit->setCompile(false); - newUnit->setCompileCpp(false); - newUnit->setLink(false); - } - newUnit->setPriority(1000); - newUnit->setOverrideBuildCmd(false); - newUnit->setBuildCmd(""); - newUnit->setEncoding(toByteArray(mOptions.encoding)); - - mParser->addProjectFile(newUnit->fileName(),true); + PProjectUnit newUnit = internalAddUnit(s,parentNode); emit unitAdded(newUnit->fileName()); return newUnit; } @@ -533,8 +491,6 @@ bool Project::removeUnit(PProjectUnit& unit, bool doClose , bool removeFile) bool result=internalRemoveUnit(unit,doClose,removeFile); if (result) { - mParser->invalidateFile(unit->fileName()); - mParser->removeProjectFile(unit->fileName()); emit unitRemoved(unit->fileName()); } return result; @@ -1225,7 +1181,6 @@ PProjectUnit Project::addUnit(const QString &inFileName, PProjectModelNode paren { PProjectUnit newUnit=internalAddUnit(inFileName, parentNode); if (newUnit) { - mParser->addProjectFile(newUnit->fileName(),true); emit unitAdded(newUnit->fileName()); } return newUnit; diff --git a/RedPandaIDE/project.h b/RedPandaIDE/project.h index 6ff073bd..80a2a0fe 100644 --- a/RedPandaIDE/project.h +++ b/RedPandaIDE/project.h @@ -216,6 +216,8 @@ public: void setModified(bool value); PProjectModelNode addFolder(PProjectModelNode parentFolder, const QString& s); + PProjectUnit newUnit(PProjectModelNode parentNode, + const QString& customFileName=""); PProjectUnit addUnit(const QString& inFileName, PProjectModelNode parentNode); QString folder(); @@ -227,8 +229,6 @@ public: QString getNodePath(PProjectModelNode node); void incrementBuildNumber(); - PProjectUnit newUnit(PProjectModelNode parentNode, - const QString& customFileName=""); Editor* openUnit(PProjectUnit& unit, bool forceOpen=true); Editor* openUnit(PProjectUnit& unit, const PProjectEditorLayout& layout); Editor* unitEditor(const PProjectUnit& unit) const; diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index f7efd6a2..0876653b 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -665,6 +665,16 @@ void Settings::Editor::setAutoFormatWhenSaved(bool newAutoFormatWhenSaved) mAutoFormatWhenSaved = newAutoFormatWhenSaved; } +bool Settings::Editor::parseTodos() const +{ + return mParseTodos; +} + +void Settings::Editor::setParseTodos(bool newParseTodos) +{ + mParseTodos = newParseTodos; +} + bool Settings::Editor::highlightCurrentWord() const { return mHighlightCurrentWord; @@ -1246,6 +1256,7 @@ void Settings::Editor::doSave() saveValue("undo_limit",mUndoLimit); saveValue("undo_memory_usage", mUndoMemoryUsage); saveValue("auto_format_when_saved", mAutoFormatWhenSaved); + saveValue("parse_todos",mParseTodos); //tooltips saveValue("enable_tooltips",mEnableTooltips); @@ -1389,6 +1400,8 @@ void Settings::Editor::doLoad() mUndoLimit = intValue("undo_limit",0); mUndoMemoryUsage = intValue("undo_memory_usage", 10); mAutoFormatWhenSaved = boolValue("auto_format_when_saved", false); + mParseTodos = boolValue("parse_todos",true); + //tooltips mEnableTooltips = boolValue("enable_tooltips",true); diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h index dc7c485e..92dd3d99 100644 --- a/RedPandaIDE/settings.h +++ b/RedPandaIDE/settings.h @@ -367,6 +367,9 @@ public: bool autoFormatWhenSaved() const; void setAutoFormatWhenSaved(bool newAutoFormatWhenSaved); + bool parseTodos() const; + void setParseTodos(bool newParseTodos); + private: //General // indents @@ -476,6 +479,7 @@ public: int mUndoLimit; int mUndoMemoryUsage; bool mAutoFormatWhenSaved; + bool mParseTodos; //hints tooltip diff --git a/RedPandaIDE/settingsdialog/editormiscwidget.cpp b/RedPandaIDE/settingsdialog/editormiscwidget.cpp index 4830eaeb..16204a86 100644 --- a/RedPandaIDE/settingsdialog/editormiscwidget.cpp +++ b/RedPandaIDE/settingsdialog/editormiscwidget.cpp @@ -67,6 +67,7 @@ void EditorMiscWidget::doLoad() ui->spinMaxUndo->setValue(pSettings->editor().undoLimit()); ui->spinMaxUndoMemory->setValue(pSettings->editor().undoMemoryUsage()); ui->chkAutoReformat->setChecked(pSettings->editor().autoFormatWhenSaved()); + ui->chkParseTodos->setChecked(pSettings->editor().parseTodos()); } void EditorMiscWidget::doSave() @@ -84,6 +85,8 @@ void EditorMiscWidget::doSave() pSettings->editor().setUndoLimit(ui->spinMaxUndo->value()); pSettings->editor().setUndoMemoryUsage(ui->spinMaxUndoMemory->value()); pSettings->editor().setAutoFormatWhenSaved(ui->chkAutoReformat->isChecked()); + pSettings->editor().setParseTodos(ui->chkParseTodos->isChecked()); + pSettings->editor().save(); pMainWindow->updateEditorSettings(); diff --git a/RedPandaIDE/settingsdialog/editormiscwidget.ui b/RedPandaIDE/settingsdialog/editormiscwidget.ui index 50972ca8..7315cda6 100644 --- a/RedPandaIDE/settingsdialog/editormiscwidget.ui +++ b/RedPandaIDE/settingsdialog/editormiscwidget.ui @@ -29,9 +29,9 @@ - + - Auto detect encoding when openning files + Parse TODOs @@ -147,6 +147,13 @@ + + + + Auto detect encoding when openning files + + + diff --git a/RedPandaIDE/widgets/bookmarkmodel.cpp b/RedPandaIDE/widgets/bookmarkmodel.cpp index 83f15a0a..9c4271f7 100644 --- a/RedPandaIDE/widgets/bookmarkmodel.cpp +++ b/RedPandaIDE/widgets/bookmarkmodel.cpp @@ -138,6 +138,25 @@ void BookmarkModel::removeBookmarks(const QString &filename, bool forProject) } } +void BookmarkModel::renameBookmarkFile(const QString& oldFilename, const QString& newFilename, bool forProject) +{ + QList bookmarks; + if (forProject) + bookmarks = mProjectBookmarks; + else + bookmarks = mBookmarks; + for (int i=bookmarks.count()-1;i>=0;i--) { + PBookmark bookmark = bookmarks[i]; + if (bookmark->filename.compare(oldFilename, PATH_SENSITIVITY) == 0) { + bookmark->filename=newFilename; + if (forProject==mIsForProject) { + QModelIndex index=createIndex(i,2); + emit dataChanged(index,index); + } + } + } +} + void BookmarkModel::clear(bool forProject) { if (forProject==mIsForProject) diff --git a/RedPandaIDE/widgets/bookmarkmodel.h b/RedPandaIDE/widgets/bookmarkmodel.h index 405e15c6..c669b386 100644 --- a/RedPandaIDE/widgets/bookmarkmodel.h +++ b/RedPandaIDE/widgets/bookmarkmodel.h @@ -43,6 +43,7 @@ public: PBookmark bookmark(const QString&filename, int line); bool removeBookmark(const QString&filename, int line, bool forProject); void removeBookmarks(const QString& filename, bool forProject); + void renameBookmarkFile(const QString& oldFilename, const QString& newFilename, bool forProject); void clear(bool forProject); bool updateDescription(const QString&filename, int line, const QString& description, bool forProject); bool updateDescription(const QString&filename, int line, const QString& description);