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 19e92242..d7b4c7e7 100644 Binary files a/RedPandaIDE/RedPandaIDE_zh_CN.qm and b/RedPandaIDE/RedPandaIDE_zh_CN.qm differ 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