From 08d1006ae0ebd60ba74ef3e7cf383f80d5136888 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Sun, 3 Oct 2021 17:18:43 +0800 Subject: [PATCH] - enhancement: todo view --- NEWS.md | 1 + RedPandaIDE/RedPandaIDE.pro | 2 + RedPandaIDE/RedPandaIDE_zh_CN.qm | Bin 83205 -> 83447 bytes RedPandaIDE/RedPandaIDE_zh_CN.ts | 630 +++++++++++++----------- RedPandaIDE/editor.cpp | 9 + RedPandaIDE/editor.h | 1 + RedPandaIDE/mainwindow.cpp | 53 ++ RedPandaIDE/mainwindow.h | 14 + RedPandaIDE/mainwindow.ui | 8 +- RedPandaIDE/qsynedit/highlighter/base.h | 3 +- RedPandaIDE/todoparser.cpp | 159 ++++++ RedPandaIDE/todoparser.h | 75 +++ 12 files changed, 651 insertions(+), 304 deletions(-) create mode 100644 RedPandaIDE/todoparser.cpp create mode 100644 RedPandaIDE/todoparser.h diff --git a/NEWS.md b/NEWS.md index 1fc731cc..cdd9a8ae 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,7 @@ Version 0.6.0 - fix: can't save code snippets modifications - fix: errors in code snippet processing - change: auto open a new editor at start + - enhancement: todo view Version 0.5.0 - enhancement: support C++ using type alias; diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 2cdc45e1..75769746 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -60,6 +60,7 @@ SOURCES += \ settingsdialog/projectprecompilewidget.cpp \ settingsdialog/projectversioninfowidget.cpp \ symbolusagemanager.cpp \ + todoparser.cpp \ widgets/classbrowser.cpp \ widgets/codecompletionlistview.cpp \ widgets/codecompletionpopup.cpp \ @@ -161,6 +162,7 @@ HEADERS += \ settingsdialog/projectprecompilewidget.h \ settingsdialog/projectversioninfowidget.h \ symbolusagemanager.h \ + todoparser.h \ widgets/classbrowser.h \ widgets/codecompletionlistview.h \ widgets/codecompletionpopup.h \ diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.qm b/RedPandaIDE/RedPandaIDE_zh_CN.qm index 19e92242b1bb9a91b0a7dddb4feb543402939c15..d7b4c7e78b02b4ca38c82b92350eefa44b098e71 100644 GIT binary patch delta 4233 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 delta 4001 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 Lp~TUfozeUsDR|K5 diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.ts b/RedPandaIDE/RedPandaIDE_zh_CN.ts index 3ff65832..796afadb 100644 --- a/RedPandaIDE/RedPandaIDE_zh_CN.ts +++ b/RedPandaIDE/RedPandaIDE_zh_CN.ts @@ -205,44 +205,46 @@ CodeSnippetsManager - + + Load default code snippets failed 载入缺省代码模板失败 - + + Can't copy default code snippets '%1' to '%2'. 无法将缺省代码模板'%1'复制到'%2'。 - - + + Read code snippets failed 读取代码模板失败 - + Can't open code snippet file '%1' for read. 无法读入代码模板文件'%1' - + Read code snippet file '%1' failed:%2 读取代码模板文件'%1'失败:%2 - - + + Save code snippets failed 保存代码模板失败 - + Can't open code snippet file '%1' for write. - + Write to code snippet file '%1' failed. 写入代码片段文件'%1'失败。 @@ -250,22 +252,22 @@ CodeSnippetsModel - + Caption 名称 - + Completion Prefix 代码补全前缀 - + Description 描述 - + Menu Section 菜单节 @@ -827,71 +829,71 @@ Are you really want to continue? 失败 - - - - - - - + + + + + + + Error 错误 - + File %1 is not writable! 无法写入文件"%1" - + Save As 另存为 - + The text to be copied exceeds count limit! 要复制的内容超过了行数限制! - + The text to be copied exceeds character limit! 要复制的内容超过了字符数限制! - + The text to be cut exceeds count limit! 要剪切的内容超过了行数限制! - + The text to be cut exceeds character limit! 要剪切的内容超过了字符数限制! - - - + + + Ctrl+click for more info Ctrl+单击以获取更多信息 - - + + Symbol '%1' not found! 未找到符号'%1'! - + Break point condition 断点条件 - + Enter the condition of the breakpoint: 输入当前断点的生效条件: - + Readonly 只读 @@ -2405,7 +2407,7 @@ Are you really want to continue? - + Issues 编译器 @@ -2415,29 +2417,29 @@ Are you really want to continue? 编译日志 - + File 文件 - + Tools 工具 - - + + Run 运行 - + Edit 编辑 - + Project 项目 @@ -2462,9 +2464,9 @@ Are you really want to continue? - - - + + + Debug 调试 @@ -2495,7 +2497,7 @@ Are you really want to continue? - + Search 查找 @@ -2520,23 +2522,23 @@ Are you really want to continue? 替换 - + Close 关闭 - + Execute 运行 - - + + Code 代码 - + Window 窗口 @@ -2554,244 +2556,244 @@ Are you really want to continue? 新建 - + Ctrl+N Ctrl+N - + Open... 打开... - + Ctrl+O Ctrl+O - + Save 保存 - + Ctrl+S Ctrl+S - + Save As... 另存为... - + Save As 另存为 - + Save All 全部保存 - + Ctrl+Shift+S Ctrl+Shift+S - + Options 选项 - - - - - - - + + + + + + + Compile 编译 - + F9 F9 - + F10 F10 - + Undo 恢复 - + Ctrl+Z Ctrl+Z - + Redo 重做 - + Ctrl+Y Ctrl+Y - + Cut 剪切 - + Ctrl+X Ctrl+X - - - + + + Copy 复制 - + Ctrl+C Ctrl+C - - + + Paste 粘贴 - + Ctrl+V Ctrl+V - - + + Select All 选择全部 - + Ctrl+A Ctrl+A - + Indent 缩进 - + UnIndent 取消缩进 - + Toggle Comment 切换注释 - + Ctrl+/ Ctrl+/ - + Collapse All 全部收起 - + Uncollapse All 全部展开 - + Encode in ANSI 使用ANSI编码 - + Encode in UTF-8 使用UTF-8编码 - + Auto Detect 自动检测 - + Convert to ANSI 转换为ANSI编码 - + Convert to UTF-8 转换为UTF-8编码 - - + + Compile & Run 编译运行 - + F11 F11 - - + + Rebuild All 全部重编译 - + F12 F12 - + Stop Execution 停止执行 - + F6 F6 - + F5 F5 - + Step Over 单步跳过 - + F7 F7 - + Step Into 单步进入 @@ -2807,319 +2809,324 @@ Are you really want to continue? 地址表达式: - + + TODO + TODO + + + Main 主工具栏 - + Compiler Set 编译器配置集 - - + + New Source File 新建源代码文件 - + F8 F8 - + Step Out 单步跳出 - + Ctrl+F8 Ctrl+F8 - + Run To Cursor 执行到光标处 - + Ctrl+F5 Ctrl+F5 - + Continue 继续执行 - + F4 F4 - + Add Watch... 添加监视 - + View CPU Window... 打开CPU信息窗口... - + Exit 退出 - + Find... 查找... - + Ctrl+F Ctrl+F - + Find in Files... 在文件中查找... - + Ctrl+Shift+F Ctrl+Shift+F - + Replace... 替换 - + Ctrl+R Ctrl+R - + Find Next 查找下一个 - + F3 F3 - + Find Previous 查找前一个 - + Shift+F3 Shift+F3 - + Remove Watch 删除监视 - + Remove All 清除全部监视 - + Modify Watch... 修改监视值 - + Reformat Code 对代码重新排版 - + Ctrl+Shift+A Ctrl+Shift+A - + Go back 前一次编辑位置 - + Ctrl+Alt+Left Ctrl+Alt+Left - + Forward 后一次编辑位置 - + Ctrl+Alt+Right Ctrl+Alt+Right - + Ctrl+W Ctrl+W - + Close All 全部关闭 - + Ctrl+Shift+W Ctrl+Shift+W - + Maximize Editor 最大化编辑器 - + Ctrl+F11 Ctrl+F11 - + Next 下一窗口 - + Ctrl+Tab Ctrl+Tab - + Previous 前一窗口 - + Ctrl+Shift+Tab Ctrl+Shift+Tab - + Toggle breakpoint 切换断点 - + Ctrl+F4 Ctrl+F4 - - + + Clear all breakpoints 删除所有断点 - + Breakpoint property... 设置断点条件... - + Goto Declaration 跳转到声明处 - + Goto Definition 跳转到定义处 - + Find references 查找符号的引用 - + Open containing folder 打开所在的文件夹 - + Ctrl+B Ctrl+B - + Open a terminal here 打开命令行窗口 - + File Properties... 文件属性... - + Close Project 关闭项目 - + Project options 项目属性 - + New Project... 新建项目... - + New File 新建项目文件 - + Add to project... 添加到项目... - + Remove from project 从项目删除 - + View Makefile 查看Makefile - + Clean 清理构建文件 - + Open Folder in Explorer 在浏览器中打开 - + Open In Terminal 在终端中打开 - + File Encoding 文件编码 @@ -3129,32 +3136,32 @@ Are you really want to continue? 文件历史 - - - - - - + + + + + + Debugging 正在调试 - - - - - - + + + + + + Running 正在运行 - - - - - - + + + + + + Compiling 正在编译 @@ -3163,355 +3170,355 @@ Are you really want to continue? 行:%1 列:%2 已选择:%3 总行数:%4 总长度:%5 - + Line:%1 Col:%2 Selected:%3 Lines:%4 Length:%5 行:%1 列:%2 已选择:%3 总行数:%4 总长度:%5 - + Read Only 只读 - + Insert 插入 - + Overwrite 覆写 - + Close project 关闭项目 - + Are you sure you want to close %1? 你确定要关闭'%1'吗? - - + + Confirm 确认 - - - + + + Source file is not compiled. 源文件尚未编译。 - - + + Compile now? 现在编译? - - + + Source file is more recent than executable. 源文件比可执行程序新。 - + Recompile now? 重新编译? - + No compiler set 无编译器设置 - + No compiler set is configured. 没有配置编译器设置。 - + Can't start debugging. 无法启动调试器 - - + + Enable debugging 启用调试参数 - - + + You have not enabled debugging info (-g3) and/or stripped it from the executable (-s) in Compiler Options.<BR /><BR />Do you want to correct this now? 当前编译设置中未启用调试选项(-g3),或启用了信息剥除选项(-s)<br /><br/>是否纠正这一问题? - + Project not built 项目尚未构建 - + Project hasn't been built. Build it now? 项目尚未构建。是否构建? - + Host applcation missing 宿主程序不存在 - + DLL project needs a host application to run. 动态链接库(DLL)需要一个宿主程序来运行。 - + But it's missing. 但它不存在。 - + Host application not exists 宿主程序不存在 - + Host application file '%1' doesn't exist. 宿主程序'%1'不存在。 - + Recompile? 重新编译? - - + + Save last open info error 保存上次打开信息失败 - + Can't remove old last open information file '%1' 无法删除旧上次打开信息文件'%1' - + Can't save last open info file '%1' 无法保存上次打开信息文件'%1' - + Load last open info error 载入上次打开信息失败 - + Can't load last open info file '%1' 无法载入上次打开信息文件'%1' - + Copy all 全部复制 - - + + Clear 清除 - + Show debug logs in the debug console 在调试主控台中显示调试器输出 - + Remove this search 清除这次搜索 - + Clear all searches 删除所有搜索 - + Breakpoint condition... 断点条件... - + Break point condition 断点条件 - + Enter the condition of the breakpoint: 输入当前断点的生效条件: - + Remove all breakpoints 清除所有断点 - + Rename File 重命名文件 - - + + Add Folder 添加文件夹 - + New folder 新文件夹 - + Folder name: 文件夹: - + Rename Folder 重命名 - + Remove Folder 删除文件夹 - + Sort By Type 按类型排序 - + Sort alphabetically 按名称排序 - + Show inherited members 显示继承的成员 - + Goto declaration 跳转到声明处 - + Goto definition 跳转到定义处 - + Character sets 字符集 - + %1 files autosaved 已自动保存%1个文件 - + Save project 保存项目 - + The project '%1' has modifications. 项目'%1'有改动。 - + Do you want to save it? 需要保存吗? - + 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 - + Red panda Dev-C++ project file (*.dev) 小熊猫Dev-C++项目文件 (*.dev) - + New project fail 新建项目失败 - + Can't assign project template 无法使用模板创建项目 - + Add to project 添加到项目 - - - - - - - - - + + + + + + + + + Error 错误 @@ -3521,75 +3528,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个文件) @@ -4348,7 +4355,7 @@ Are you really want to continue? QApplication - + Error 错误 @@ -4402,23 +4409,23 @@ Are you really want to continue? - - + + Error 错误 - + Can't create configuration folder %1 无法创建配置文件夹"%1" - + Can't write to configuration file %1 无法写入配置文件夹"%1" - + Can't load autolink settings 无法载入自动链接设置 @@ -5608,6 +5615,29 @@ Are you really want to continue? 无法写入文件'%2'! + + TodoModel + + + Filename + 文件名 + + + + Line + + + + + Column + + + + + Content + 内容 + + WatchModel diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 665423d5..86b3652c 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -182,6 +182,7 @@ void Editor::loadFile(const QString& filename) { if (pSettings->editor().syntaxCheckWhenLineChanged()) { checkSyntaxInBack(); } + reparseTodo(); } mLastIdCharPressed = 0; } @@ -192,6 +193,7 @@ void Editor::saveFile(const QString &filename) { pMainWindow->updateForEncodingInfo(); if (pSettings->editor().syntaxCheckWhenSave()) checkSyntaxInBack(); + reparseTodo(); } void Editor::convertToEncoding(const QByteArray &encoding) @@ -1279,6 +1281,7 @@ void Editor::onStatusChanged(SynStatusChanges changes) reparse(); if (pSettings->editor().syntaxCheckWhenLineChanged()) checkSyntaxInBack(); + reparseTodo(); } mLineCount = lines()->count(); if (changes.testFlag(scModified)) { @@ -1899,6 +1902,11 @@ void Editor::reparse() parseFile(mParser,mFilename,mInProject); } +void Editor::reparseTodo() +{ + pMainWindow->todoParser()->parseFile(mFilename); +} + void Editor::insertString(const QString &value, bool moveCursor) { beginUpdate(); @@ -3150,6 +3158,7 @@ void Editor::reformat() setSelText(QString::fromUtf8(newContent)); reparse(); checkSyntaxInBack(); + reparseTodo(); pMainWindow->updateEditorActions(); } diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 22a510ec..138932d5 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -155,6 +155,7 @@ public: void gotoDeclaration(const BufferCoord& pos); void gotoDefinition(const BufferCoord& pos); void reparse(); + void reparseTodo(); void insertString(const QString& value, bool moveCursor); void insertCodeSnippet(const QString& code); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index ca8ade2c..4d2ba673 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -130,6 +130,7 @@ MainWindow::MainWindow(QWidget *parent) connect(ui->cbMemoryAddress->lineEdit(), &QLineEdit::returnPressed, this, &MainWindow::onDebugMemoryAddressInput); + mTodoParser = std::make_shared(); mSymbolUsageManager = std::make_shared(); mSymbolUsageManager->load(); mCodeSnippetManager = std::make_shared(); @@ -140,6 +141,7 @@ MainWindow::MainWindow(QWidget *parent) ui->cbSearchHistory->setModel(mSearchResultListModel.get()); ui->searchView->setModel(mSearchResultTreeModel.get()); ui->searchView->setItemDelegate(mSearchViewDelegate.get()); + ui->tableTODO->setModel(&mTodoModel); connect(mSearchResultTreeModel.get() , &QAbstractItemModel::modelReset, ui->searchView,&QTreeView::expandAll); ui->replacePanel->setVisible(false); @@ -2276,6 +2278,21 @@ void MainWindow::enableDebugActions() ui->cbMemoryAddress->setEnabled(true); } +void MainWindow::onTodoParseStarted() +{ + mTodoModel.clear(); +} + +void MainWindow::onTodoParsing(const QString &filename, int lineNo, int ch, const QString &line) +{ + mTodoModel.addItem(filename,lineNo,ch,line); +} + +void MainWindow::onTodoParseFinished() +{ + +} + void MainWindow::prepareProjectForCompile() { if (!mProject) @@ -3875,6 +3892,11 @@ void MainWindow::on_classBrowser_doubleClicked(const QModelIndex &index) } } +const PTodoParser &MainWindow::todoParser() const +{ + return mTodoParser; +} + PCodeSnippetManager &MainWindow::codeSnippetManager() { return mCodeSnippetManager; @@ -3884,3 +3906,34 @@ PSymbolUsageManager &MainWindow::symbolUsageManager() { return mSymbolUsageManager; } + +void MainWindow::on_EditorTabsLeft_currentChanged(int index) +{ + Editor * editor = mEditorList->getEditor(); + if (editor) { + editor->reparseTodo(); + } +} + + +void MainWindow::on_EditorTabsRight_currentChanged(int index) +{ + Editor * editor = mEditorList->getEditor(); + if (editor) { + editor->reparseTodo(); + } +} + + +void MainWindow::on_tableTODO_doubleClicked(const QModelIndex &index) +{ + PTodoItem item = mTodoModel.getItem(index); + if (item) { + Editor * editor = mEditorList->getOpenedEditorByFilename(item->filename); + if (editor) { + editor->setCaretPositionAndActivate(item->lineNo,item->ch+1); + } + } + +} + diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 8a8c9a34..87974eb1 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -13,6 +13,7 @@ #include "caretlist.h" #include "symbolusagemanager.h" #include "codesnippetsmanager.h" +#include "todoparser.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -121,6 +122,8 @@ public: PCodeSnippetManager &codeSnippetManager(); + const PTodoParser &todoParser() const; + public slots: void onCompileLog(const QString& msg); void onCompileIssue(PCompileIssue issue); @@ -143,6 +146,9 @@ public slots: void onEditorTabContextMenu(const QPoint& pos); void disableDebugActions(); void enableDebugActions(); + void onTodoParseStarted(); + void onTodoParsing(const QString& filename, int lineNo, int ch, const QString& line); + void onTodoParseFinished(); private: void prepareProjectForCompile(); @@ -357,6 +363,12 @@ private slots: void on_classBrowser_doubleClicked(const QModelIndex &index); + void on_EditorTabsLeft_currentChanged(int index); + + void on_EditorTabsRight_currentChanged(int index); + + void on_tableTODO_doubleClicked(const QModelIndex &index); + private: Ui::MainWindow *ui; EditorList *mEditorList; @@ -385,6 +397,7 @@ private: std::shared_ptr mHeaderCompletionPopup; std::shared_ptr mFunctionTip; + TodoModel mTodoModel; SearchResultModel mSearchResultModel; PSearchResultListModel mSearchResultListModel; PSearchResultTreeModel mSearchResultTreeModel; @@ -393,6 +406,7 @@ private: std::shared_ptr> mStatementColors; PSymbolUsageManager mSymbolUsageManager; PCodeSnippetManager mCodeSnippetManager; + PTodoParser mTodoParser; bool mCheckSyntaxInBack; bool mOpenClosingBottomPanel; diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index f3ff4471..2bfdea1f 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -806,13 +806,17 @@ - + TODO - + + + true + + diff --git a/RedPandaIDE/qsynedit/highlighter/base.h b/RedPandaIDE/qsynedit/highlighter/base.h index 66ee7ad6..a5b69601 100644 --- a/RedPandaIDE/qsynedit/highlighter/base.h +++ b/RedPandaIDE/qsynedit/highlighter/base.h @@ -118,6 +118,7 @@ public: virtual bool isWordBreakChar(const QChar& ch); bool enabled() const; void setEnabled(bool value); + virtual PSynHighlighterAttribute getAttribute(const QString& name) const; protected: PSynHighlighterAttribute mCommentAttribute; @@ -131,8 +132,6 @@ protected: void clearAttributes(); virtual int attributesCount() const; - virtual PSynHighlighterAttribute getAttribute(const QString& name) const; - private: QMap mAttributes; bool mEnabled; diff --git a/RedPandaIDE/todoparser.cpp b/RedPandaIDE/todoparser.cpp new file mode 100644 index 00000000..25c1f48d --- /dev/null +++ b/RedPandaIDE/todoparser.cpp @@ -0,0 +1,159 @@ +#include "todoparser.h" +#include "mainwindow.h" +#include "editor.h" +#include "editorlist.h" +#include "HighlighterManager.h" +#include "qsynedit/Constants.h" + +TodoParser::TodoParser(QObject *parent) : QObject(parent) +{ + mThread = nullptr; +} + +void TodoParser::parseFile(const QString &filename) +{ + QMutexLocker locker(&mMutex); + if (mThread) { + return; + } + mThread = new TodoThread(filename); + connect(mThread,&QThread::finished, + [this] { + QMutexLocker locker(&mMutex); + if (mThread) { + mThread->deleteLater(); + mThread = nullptr; + } + }); + connect(mThread, &TodoThread::parseStarted, + pMainWindow, &MainWindow::onTodoParseStarted); + connect(mThread, &TodoThread::todoFound, + pMainWindow, &MainWindow::onTodoParsing); + connect(mThread, &TodoThread::parseFinished, + pMainWindow, &MainWindow::onTodoParseFinished); + mThread->start(); +} + +bool TodoParser::parsing() const +{ + return (mThread!=nullptr); +} + +TodoThread::TodoThread(const QString& filename, QObject *parent): QThread(parent) +{ + mFilename = filename; +} + +void TodoThread::run() +{ + PSynHighlighter highlighter = highlighterManager.getCppHighlighter(); + emit parseStarted(); + auto action = finally([this]{ + emit parseFinished(); + }); + QStringList lines; + if (!pMainWindow->editorList()->getContentFromOpenedEditor(mFilename,lines)) { + return; + } + PSynHighlighterAttribute commentAttr = highlighter->getAttribute(SYNS_AttrComment); + + highlighter->resetState(); + for (int i =0;isetLine(lines[i],i); + while (!highlighter->eol()) { + PSynHighlighterAttribute attr; + attr = highlighter->getTokenAttribute(); + if (attr == commentAttr) { + QString token = highlighter->getToken(); + int pos = token.indexOf("TODO:",Qt::CaseInsensitive); + if (pos>=0) { + emit todoFound( + mFilename, + i+1, + pos+highlighter->getTokenPos(), + lines[i].trimmed() + ); + } + } + highlighter->next(); + } + } +} + +TodoModel::TodoModel(QObject *parent) : QAbstractListModel(parent) +{ + +} + +void TodoModel::addItem(const QString &filename, int lineNo, int ch, const QString &line) +{ + beginInsertRows(QModelIndex(),mItems.count(),mItems.count()); + PTodoItem item = std::make_shared(); + item->filename = filename; + item->lineNo = lineNo; + item->ch = ch; + item->line = line; + mItems.append(item); + endInsertRows(); +} + +void TodoModel::clear() +{ + beginResetModel(); + mItems.clear(); + endResetModel(); +} + +PTodoItem TodoModel::getItem(const QModelIndex &index) +{ + if (!index.isValid()) + return PTodoItem(); + return mItems[index.row()]; +} + +int TodoModel::rowCount(const QModelIndex &parent) const +{ + return mItems.count(); +} + +QVariant TodoModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + if (role==Qt::DisplayRole) { + PTodoItem item = mItems[index.row()]; + switch(index.column()) { + case 0: + return item->filename; + case 1: + return item->lineNo; + case 2: + return item->ch; + case 3: + return item->line; + } + } + return QVariant(); +} + +QVariant TodoModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch(section) { + case 0: + return tr("Filename"); + case 1: + return tr("Line"); + case 2: + return tr("Column"); + case 3: + return tr("Content"); + } + } + return QVariant(); +} + +int TodoModel::columnCount(const QModelIndex &parent) const +{ + return 4; +} diff --git a/RedPandaIDE/todoparser.h b/RedPandaIDE/todoparser.h new file mode 100644 index 00000000..25dfaff2 --- /dev/null +++ b/RedPandaIDE/todoparser.h @@ -0,0 +1,75 @@ +#ifndef TODOPARSER_H +#define TODOPARSER_H + +#include +#include +#include +#include + +struct TodoItem { + QString filename; + int lineNo; + int ch; + QString line; +}; + +using PTodoItem = std::shared_ptr; + +class TodoModel : public QAbstractListModel { + Q_OBJECT +public: + explicit TodoModel(QObject* parent=nullptr); + void addItem(const QString& filename, int lineNo, + int ch, const QString& line); + void clear(); + PTodoItem getItem(const QModelIndex& index); +private: + QList mItems; + + // QAbstractItemModel interface +public: + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + // QAbstractItemModel interface +public: + int columnCount(const QModelIndex &parent) const override; +}; + +class TodoThread: public QThread +{ + Q_OBJECT +public: + explicit TodoThread(const QString& filename, QObject* parent = nullptr); +signals: + void parseStarted(); + void todoFound(const QString& filename, int lineNo, int ch, const QString& line); + void parseFinished(); +private: + QString mFilename; + + // QThread interface +protected: + void run() override; +}; + +using PTodoThread = std::shared_ptr; + +class TodoParser : public QObject +{ + Q_OBJECT +public: + explicit TodoParser(QObject *parent = nullptr); + void parseFile(const QString& filename); + bool parsing() const; + +signals: +private: + TodoThread* mThread; + QRecursiveMutex mMutex; +}; + +using PTodoParser = std::shared_ptr; + +#endif // TODOPARSER_H