diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 03fb769c..2e7aa2f1 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -22,6 +22,7 @@ SOURCES += \ compiler/executablerunner.cpp \ compiler/filecompiler.cpp \ compiler/stdincompiler.cpp \ + cpprefacter.cpp \ parser/cppparser.cpp \ parser/cpppreprocessor.cpp \ parser/cpptokenizer.cpp \ @@ -94,6 +95,7 @@ HEADERS += \ compiler/executablerunner.h \ compiler/filecompiler.h \ compiler/stdincompiler.h \ + cpprefacter.h \ parser/cppparser.h \ parser/cpppreprocessor.h \ parser/cpptokenizer.h \ @@ -195,6 +197,8 @@ RESOURCES += \ icons.qrc \ translations.qrc +RC_ICONS = images/devcpp.ico + #win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../QScintilla/src/release/ -lqscintilla2_qt5d #else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../QScintilla/src/debug/ -lqscintilla2_qt5d #else:unix: LIBS += -L$$OUT_PWD/../../QScintilla/src/ -lqscintilla2_qt5d diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.qm b/RedPandaIDE/RedPandaIDE_zh_CN.qm index 7bd5b8b7..eb769ff7 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 72ce78f8..34c3bda3 100644 --- a/RedPandaIDE/RedPandaIDE_zh_CN.ts +++ b/RedPandaIDE/RedPandaIDE_zh_CN.ts @@ -4,17 +4,17 @@ BacktraceModel - + Function 函数 - + Filename 文件名 - + Line @@ -22,17 +22,17 @@ BreakpointModel - + Filename 文件名 - + Line - + Condition 条件 @@ -132,32 +132,32 @@ [说明] - + The compiler process failed to start. 无法启动编译进程。 - + The compiler process crashed after starting successfully. 编译进程启动后崩溃。 - + The last waitFor...() function timed out. waitFor()函数等待超时。 - + An error occurred when attempting to write to the compiler process. 在向编译进程输入内容时出错。 - + An error occurred when attempting to read from the compiler process. 在从编译进程读取内容时出错。 - + An unknown error occurred. 发生了未知错误。 @@ -236,12 +236,12 @@ - - - - - - + + + + + + ... ... @@ -251,12 +251,12 @@ 基本选项 - + Add the following arguments when calling the compiler 编译时加入下列选项: - + Add the following arguments when calling the linker 链接时加入下列选项 @@ -266,92 +266,97 @@ 编译时自动加入字符编码选项 - + + Statically link libraries + 静态链接所有库 + + + Settings 编译/链接选项 - + Directories 文件夹 - + Programs 程序 - + TextLabel 选项 - + Resource Compiler(windres) 资源编辑器(winres) - + C++ Compiler(g++) C++编译器(g++) - + Choose C++ Compiler 选择C++编译器 - + Choose C Compiler 选择C编译器 - + C Compiler(gcc) C编译器(gcc) - + Debugger(gdb) 调试器(gdb) - + Profiler(gprof) 性能分析器(gprof) - + make - + Choose make 选择make - + Choose Debugger 选择调试器 - + Choose Resource Compiler 选择资源编译器 - + Choose Profiler 选择性能分析器 - + Confirm 确认 - + Red Panda C++ will clear current compiler list and search for compilers in the following locations: '%1' '%2' @@ -362,35 +367,35 @@ Are you really want to continue? 你确定要继续吗? - - + + Failed 失败 - - + + Can't find any compiler. 找不到编译器 - - + + Compiler Set Name 编译器配置名称 - + Name 名称 - + Compiler Set Folder 编译器所在文件夹 - + New name 新名称 @@ -490,28 +495,28 @@ Are you really want to continue? 找不到调试器程序"%1" - - + + Execute to evaluate 执行以求值 - + Not found in current context 不在当前语境中 - + Compile 编译 - + Source file is more recent than executable. 源文件比程序文件新。 - + Recompile? 重新编译? @@ -523,7 +528,7 @@ Are you really want to continue? 无标题 - + untitled%1 无标题%1 @@ -532,61 +537,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 只读 @@ -1879,22 +1894,22 @@ Are you really want to continue? IssuesModel - + Filename 文件名 - + Line - + Col - + Description 描述 @@ -1908,33 +1923,33 @@ Are you really want to continue? - + Issues 编译器 - + Compile Log 编译日志 - + File 文件 - + Tools 工具 - - + + Run 运行 - + Edit 编辑 @@ -1959,539 +1974,610 @@ Are you really want to continue? 文件 - + Resource 资源 - - - + + + Debug 调试 - + Evaluate: 求值 - + Debug Console 调试主控台 - + Call Stack 调用栈 - + Breakpoints 断点 - + Locals 本地变量 - - + + Search 查找 - + History: 历史: - + Search Again 重新查找 - + Replace with: 替换为: - + Replace 替换 - - + + Close 关闭 - + Execute - 执行 + 运行 - + Code 代码 - + Window 窗口 - - - - + + + + toolBar 工具栏 - + toolBar_2 工具栏2 - + New 新建 - + 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 单步进入 - + 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 Encoding 文件编码 - + Recent Files 文件历史 - - + + Debugging 正在调试 - - + + Running 正在运行 - - + + Compiling 正在编译 @@ -2500,172 +2586,177 @@ 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 覆写 - - + + 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/>是否纠正这一问题? - + Recompile? 重新编译? - + %1 files autosaved 已自动保存%1个文件 - - - - - - - - + + Do you really want to clear all breakpoints in this file? + 您真的要清除该文件的所有断点吗? + + + + + + + + + + Error 错误 - + 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个文件) @@ -2934,23 +3025,23 @@ Are you really want to continue? 只生成汇编代码(-S) - - + + Confirm 确认 - + The following problems were found during validation of compiler set "%1": 在验证编译器设置"%1"时遇到了下列问题: - + Compiler set not configuared. 未配置编译器设置。 - + Would you like Red Panda C++ to search for compilers in the following locations: <BR />'%1'<BR />'%2'? 您需要小熊猫C++在下列位置搜索编译器吗:<br />%1<br />%2 @@ -2986,7 +3077,7 @@ Are you really want to continue? - + untitled 无标题 @@ -3265,17 +3356,17 @@ Are you really want to continue? RegisterModel - + Register 寄存器 - + Value(Hex) 值(HEX) - + Value(Dec) 值(DEC) @@ -3420,25 +3511,30 @@ Are you really want to continue? SearchResultListModel - + Current File: 当前文件: - + Files In Project: 项目中的文件: - + Open Files: 打开的文件: + + + References to symbol '%1' at '%2':%3 + 符号'%1'出现在'%2':'%3' + SearchResultTreeModel - + Line @@ -3446,8 +3542,8 @@ Are you really want to continue? SearchResultTreeViewDelegate - - + + Line @@ -3764,12 +3860,12 @@ Are you really want to continue? SynEditStringList - + Can't open file '%1' for read! 无法读取文件'%1'! - + Can't open file '%1' for save! 无法写入文件'%2'! diff --git a/RedPandaIDE/cpprefacter.cpp b/RedPandaIDE/cpprefacter.cpp new file mode 100644 index 00000000..e93a90cb --- /dev/null +++ b/RedPandaIDE/cpprefacter.cpp @@ -0,0 +1,121 @@ +#include "cpprefacter.h" +#include "mainwindow.h" +#include "settings.h" +#include "editor.h" +#include "editorlist.h" +#include +#include "HighlighterManager.h" + +CppRefacter::CppRefacter(QObject *parent) : QObject(parent) +{ + +} + +bool CppRefacter::findOccurence(Editor *editor, const BufferCoord &pos) +{ + if (!editor->parser()->freeze()) + return false; + auto action = finally([&editor]{ + editor->parser()->unFreeze(); + }); + // get full phrase (such as s.name instead of name) + BufferCoord pBeginPos,pEndPos; + QString phrase = getWordAtPosition(editor,pos,pBeginPos,pEndPos,Editor::WordPurpose::wpInformation); + // Find it's definition + PStatement statement = editor->parser()->findStatementOf( + editor->filename(), + phrase, + pos.Line); + // definition of the symbol not found + if (!statement) + return false; + + PSearchResults results = pMainWindow->searchResultModel()->addSearchResults( + phrase, + editor->filename(), + pos.Line + ); + + + PSearchResultTreeItem item = findOccurenceInFile( + editor->filename(), + statement, + editor->parser()); + if (item && !(item->results.isEmpty())) { + results->results.append(item); + } + pMainWindow->searchResultModel()->notifySearchResultsUpdated(); + return true; +} + +PSearchResultTreeItem CppRefacter::findOccurenceInFile( + const QString &filename, + const PStatement &statement, + const PCppParser& parser) +{ + PSearchResultTreeItem parentItem = std::make_shared(); + parentItem->filename = filename; + parentItem->parent = nullptr; + QStringList buffer; + SynEdit editor; + if (pMainWindow->editorList()->getContentFromOpenedEditor( + filename,buffer)){ + editor.lines()->setContents(buffer); + } else { + QByteArray encoding; + QFile file(filename); + editor.lines()->LoadFromFile(file,ENCODING_AUTO_DETECT,encoding); + } + editor.setHighlighter(HighlighterManager().getCppHighlighter()); + int posY = 0; + while (posY < editor.lines()->count()) { + QString line = editor.lines()->getString(posY); + if (line.isEmpty()) { + posY++; + continue; + } + + if (posY == 0) { + editor.highlighter()->resetState(); + } else { + editor.highlighter()->setState( + editor.lines()->ranges(posY-1), + editor.lines()->braceLevels(posY-1), + editor.lines()->bracketLevels(posY-1), + editor.lines()->parenthesisLevels(posY-1) + ); + } + editor.highlighter()->setLine(line,posY); + while (!editor.highlighter()->eol()) { + int start = editor.highlighter()->getTokenPos() + 1; + QString token = editor.highlighter()->getToken(); + if (token == statement->command) { + //same name symbol , test if the same statement; + BufferCoord p,pBeginPos,pEndPos; + p.Line = posY+1; + p.Char = start; + QString phrase = getWordAtPosition(&editor, p, pBeginPos,pEndPos, + Editor::WordPurpose::wpInformation); + PStatement tokenStatement = parser->findStatementOf( + filename, + phrase, p.Line); + if (tokenStatement + && (tokenStatement->line == statement->line) + && (tokenStatement->fileName == statement->fileName)) { + PSearchResultTreeItem item = std::make_shared(); + item->filename = filename; + item->line = p.Line; + item->start = start; + item->len = phrase.length(); + item->parent = parentItem.get(); + item->text = line; + item->text.replace('\t',' '); + parentItem->results.append(item); + } + } + editor.highlighter()->next(); + } + posY++; + } + return parentItem; +} diff --git a/RedPandaIDE/cpprefacter.h b/RedPandaIDE/cpprefacter.h new file mode 100644 index 00000000..81cba0ab --- /dev/null +++ b/RedPandaIDE/cpprefacter.h @@ -0,0 +1,27 @@ +#ifndef CPPREFACTER_H +#define CPPREFACTER_H + +#include +#include "parser/parserutils.h" +#include "widgets/searchresultview.h" +#include "parser/cppparser.h" + +class Editor; +class BufferCoord; +class CppRefacter : public QObject +{ + Q_OBJECT +public: + explicit CppRefacter(QObject *parent = nullptr); + + bool findOccurence(Editor * editor, const BufferCoord& pos); +signals: +private: + PSearchResultTreeItem findOccurenceInFile( + const QString& filename, + const PStatement& statement, + const PCppParser& parser); + +}; + +#endif // CPPREFACTER_H diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index e10eac36..d6c3ac8c 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -647,7 +647,7 @@ void Editor::onPreparePaintHighlightToken(int line, int aChar, const QString &to if (mParser && mCompletionPopup && (attr->name() == SYNS_AttrIdentifier)) { BufferCoord p{aChar,line}; BufferCoord pBeginPos,pEndPos; - QString s= getWordAtPosition(p, pBeginPos,pEndPos, WordPurpose::wpInformation); + QString s= getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpInformation); // qDebug()<findStatementOf(mFilename, s , p.Line); @@ -702,11 +702,11 @@ bool Editor::event(QEvent *event) break; case TipType::Identifier: if (pMainWindow->debugger()->executing()) - s = getWordAtPosition(p, pBeginPos,pEndPos, WordPurpose::wpEvaluation); // debugging + s = getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpEvaluation); // debugging else if (//devEditor.ParserHints and !mCompletionPopup->isVisible() && !mHeaderCompletionPopup->isVisible()) - s = getWordAtPosition(p, pBeginPos,pEndPos, WordPurpose::wpInformation); // information during coding + s = getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpInformation); // information during coding break; case TipType::Selection: s = selText(); // when a selection is available, always only use that @@ -1669,13 +1669,13 @@ void Editor::showCompletion(bool autoComplete) BufferCoord{caretX() - 1, caretY()}, s, tokenFinished,tokenType, attr)) { if (tokenType == SynHighlighterTokenType::PreprocessDirective) {//Preprocessor - word = getWordAtPosition(caretXY(),pBeginPos,pEndPos, WordPurpose::wpDirective); + word = getWordAtPosition(this,caretXY(),pBeginPos,pEndPos, WordPurpose::wpDirective); if (!word.startsWith('#')) { //showTabnineCompletion(); return; } } else if (tokenType == SynHighlighterTokenType::Comment) { //Comment, javadoc tag - word = getWordAtPosition(caretXY(),pBeginPos,pEndPos, WordPurpose::wpJavadoc); + word = getWordAtPosition(this,caretXY(),pBeginPos,pEndPos, WordPurpose::wpJavadoc); if (!word.startsWith('@')) { return; } @@ -1721,7 +1721,7 @@ void Editor::showCompletion(bool autoComplete) ); if (word.isEmpty()) - word=getWordAtPosition(caretXY(),pBeginPos,pEndPos, WordPurpose::wpCompletion); + word=getWordAtPosition(this,caretXY(),pBeginPos,pEndPos, WordPurpose::wpCompletion); //if not fCompletionBox.Visible then mCompletionPopup->prepareSearch(word, mFilename, pBeginPos.Line); @@ -1760,7 +1760,7 @@ void Editor::showHeaderCompletion(bool autoComplete) mHeaderCompletionPopup->setParser(mParser); BufferCoord pBeginPos,pEndPos; - QString word = getWordAtPosition(caretXY(),pBeginPos,pEndPos, + QString word = getWordAtPosition(this,caretXY(),pBeginPos,pEndPos, WordPurpose::wpHeaderCompletionStart); if (word.isEmpty()) return; @@ -1943,7 +1943,7 @@ bool Editor::onCompletionKeyPressed(QKeyEvent *event) ExecuteCommand( SynEditorCommand::ecDeleteLastChar, QChar(), nullptr); // Simulate backspace in editor - phrase = getWordAtPosition(caretXY(), + phrase = getWordAtPosition(this,caretXY(), pBeginPos,pEndPos, purpose); mLastIdCharPressed = phrase.length(); @@ -1967,7 +1967,7 @@ bool Editor::onCompletionKeyPressed(QKeyEvent *event) QChar ch = event->text().front(); if (isIdentChar(ch)) { setSelText(ch); - phrase = getWordAtPosition(caretXY(), + phrase = getWordAtPosition(this,caretXY(), pBeginPos,pEndPos, purpose); mLastIdCharPressed = phrase.length(); @@ -1994,7 +1994,7 @@ bool Editor::onHeaderCompletionKeyPressed(QKeyEvent *event) ExecuteCommand( SynEditorCommand::ecDeleteLastChar, QChar(), nullptr); // Simulate backspace in editor - phrase = getWordAtPosition(caretXY(), + phrase = getWordAtPosition(this,caretXY(), pBeginPos,pEndPos, WordPurpose::wpHeaderCompletion); mLastIdCharPressed = phrase.length(); @@ -2019,7 +2019,7 @@ bool Editor::onHeaderCompletionKeyPressed(QKeyEvent *event) QChar ch = event->text().front(); if (isIdentChar(ch)) { setSelText(ch); - phrase = getWordAtPosition(caretXY(), + phrase = getWordAtPosition(this,caretXY(), pBeginPos,pEndPos, WordPurpose::wpHeaderCompletion); mLastIdCharPressed = phrase.length(); @@ -2177,7 +2177,7 @@ void Editor::gotoDeclaration(const BufferCoord &pos) { // Exit early, don't bother creating a stream (which is slow) BufferCoord pBeginPos, pEndPos; - QString phrase = getWordAtPosition(pos,pBeginPos,pEndPos, WordPurpose::wpInformation); + QString phrase = getWordAtPosition(this,pos,pBeginPos,pEndPos, WordPurpose::wpInformation); if (phrase.isEmpty()) return; @@ -2207,7 +2207,7 @@ void Editor::gotoDefinition(const BufferCoord &pos) { // Exit early, don't bother creating a stream (which is slow) BufferCoord pBeginPos, pEndPos; - QString phrase = getWordAtPosition(pos,pBeginPos,pEndPos, WordPurpose::wpInformation); + QString phrase = getWordAtPosition(this,pos,pBeginPos,pEndPos, WordPurpose::wpInformation); if (phrase.isEmpty()) return; @@ -2228,31 +2228,31 @@ void Editor::gotoDefinition(const BufferCoord &pos) } } -QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord &pWordEnd, WordPurpose purpose) +QString getWordAtPosition(SynEdit *editor, const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord &pWordEnd, Editor::WordPurpose purpose) { QString result = ""; QString s; - if ((p.Line<1) || (p.Line>lines()->count())) { + if ((p.Line<1) || (p.Line>editor->lines()->count())) { pWordBegin = p; pWordEnd = p; return ""; } - s = lines()->getString(p.Line - 1); + s = editor->lines()->getString(p.Line - 1); int len = s.length(); int wordBegin = p.Char - 1 - 1; //BufferCoord::Char starts with 1 int wordEnd = p.Char - 1 - 1; // Copy forward until end of word - if (purpose == WordPurpose::wpEvaluation - || purpose == WordPurpose::wpInformation) { + if (purpose == Editor::WordPurpose::wpEvaluation + || purpose == Editor::WordPurpose::wpInformation) { while (wordEnd + 1 < len) { - if ((purpose == WordPurpose::wpEvaluation) + if ((purpose == Editor::WordPurpose::wpEvaluation) && (s[wordEnd + 1] == '[')) { if (!findComplement(s, '[', ']', wordEnd, 1)) break; - } else if (isIdentChar(s[wordEnd + 1])) { + } else if (editor->isIdentChar(s[wordEnd + 1])) { wordEnd++; } else break; @@ -2260,9 +2260,9 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, } // Copy backward until # - if (purpose == WordPurpose::wpDirective) { + if (purpose == Editor::WordPurpose::wpDirective) { while ((wordBegin >= 0) && (wordBegin < len)) { - if (isIdentChar(s[wordBegin])) + if (editor->isIdentChar(s[wordBegin])) wordBegin--; else if (s[wordBegin] == '#') { wordBegin--; @@ -2273,9 +2273,9 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, } // Copy backward until @ - if (purpose == WordPurpose::wpJavadoc) { + if (purpose == Editor::WordPurpose::wpJavadoc) { while ((wordBegin >= 0) && (wordBegin < len)) { - if (isIdentChar(s[wordBegin])) + if (editor->isIdentChar(s[wordBegin])) wordBegin--; else if (s[wordBegin] == '@') { wordBegin--; @@ -2286,9 +2286,9 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, } // Copy backward until begin of path - if (purpose == WordPurpose::wpHeaderCompletion) { + if (purpose == Editor::WordPurpose::wpHeaderCompletion) { while ((wordBegin >= 0) && (wordBegin < len)) { - if (isIdentChar(s[wordBegin])) + if (editor->isIdentChar(s[wordBegin])) wordBegin--; else if (s[wordBegin] == '/' || s[wordBegin] == '\\' @@ -2300,7 +2300,7 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, } } - if (purpose == WordPurpose::wpHeaderCompletionStart) { + if (purpose == Editor::WordPurpose::wpHeaderCompletionStart) { while ((wordBegin >= 0) && (wordBegin < len)) { if (s[wordBegin] == '"' || s[wordBegin] == '<') { @@ -2310,7 +2310,7 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, || s[wordBegin] == '\\' || s[wordBegin] == '.') { wordBegin--; - } else if (isIdentChar(s[wordBegin])) + } else if (editor->isIdentChar(s[wordBegin])) wordBegin--; else break; @@ -2319,16 +2319,16 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, // && ( wordBegin < len) // Copy backward until begin of word - if (purpose == WordPurpose::wpCompletion - || purpose == WordPurpose::wpEvaluation - || purpose == WordPurpose::wpInformation) { + if (purpose == Editor::WordPurpose::wpCompletion + || purpose == Editor::WordPurpose::wpEvaluation + || purpose == Editor::WordPurpose::wpInformation) { while ((wordBegin >= 0) && (wordBeginisIdentChar(s[wordBegin])) { wordBegin--; } else if (s[wordBegin] == '.' || s[wordBegin] == ':' @@ -2375,9 +2375,9 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, && ( result[0] == '.' || result[0] == '-') - && (purpose == WordPurpose::wpCompletion - || purpose == WordPurpose::wpEvaluation - || purpose == WordPurpose::wpInformation)) { + && (purpose == Editor::WordPurpose::wpCompletion + || purpose == Editor::WordPurpose::wpEvaluation + || purpose == Editor::WordPurpose::wpInformation)) { int i = wordBegin; int line=p.Line; while (line>=1) { @@ -2391,7 +2391,7 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, if (i<0) { line--; if (line>=1) { - s=lines()->getString(line-1); + s=editor->lines()->getString(line-1); i=s.length(); continue; } else @@ -2401,7 +2401,7 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord pDummy; highlightPos.Line = line; highlightPos.Char = i+1; - result = getWordAtPosition(highlightPos,pWordBegin,pDummy,purpose)+result; + result = getWordAtPosition(editor, highlightPos,pWordBegin,pDummy,purpose)+result; break; } } @@ -2527,7 +2527,7 @@ void Editor::checkSyntaxInBack() pMainWindow->checkSyntaxInBack(this); } -const PCppParser &Editor::parser() const +const PCppParser &Editor::parser() { return mParser; } diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index aec3da4f..a22dd5e8 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -137,17 +137,13 @@ public: void removeBreakpointFocus(); void modifyBreakpointProperty(int line); void setActiveBreakpointFocus(int Line, bool setFocus=true); - QString getWordAtPosition(const BufferCoord& p, - BufferCoord& pWordBegin, - BufferCoord& pWordEnd, - WordPurpose purpose); QString getPreviousWordAtPositionForSuggestion(const BufferCoord& p); void reformat(); void checkSyntaxInBack(); void gotoDeclaration(const BufferCoord& pos); void gotoDefinition(const BufferCoord& pos); - const PCppParser &parser() const; + const PCppParser &parser(); private slots: void onModificationChanged(bool status) ; @@ -260,4 +256,11 @@ protected: void mouseReleaseEvent(QMouseEvent *event) override; }; +QString getWordAtPosition(SynEdit* editor, + const BufferCoord& p, + BufferCoord& pWordBegin, + BufferCoord& pWordEnd, + Editor::WordPurpose purpose); + + #endif // EDITOR_H diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 757bb27e..1958dc8c 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1,3 +1,4 @@ +#include #include "mainwindow.h" #include "ui_mainwindow.h" #include "editorlist.h" @@ -11,6 +12,7 @@ #include #include +#include #include #include #include @@ -24,6 +26,7 @@ #include #include #include +#include "cpprefacter.h" #include @@ -1102,6 +1105,39 @@ void MainWindow::maximizeEditor() } } +void MainWindow::openShell(const QString &folder, const QString &shellCommand) +{ + QProcess process; + process.setWorkingDirectory(folder); + process.setProgram(shellCommand); + process.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments * args){ + args->flags |= CREATE_NEW_CONSOLE; + args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES; // + }); + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString path = env.value("PATH"); + + if (pSettings->compilerSets().defaultSet()) { + foreach(const QString& dir, pSettings->compilerSets().defaultSet()->binDirs()) { +#ifdef Q_OS_WIN + path+=";"; +#else + path+=":"; +#endif + path+=dir; + } + } +#ifdef Q_OS_WIN + path+=";"; +#else + path+=":"; +#endif + path+=pSettings->dirs().app(); + env.insert("PATH",path); + process.setProcessEnvironment(env); + process.startDetached(); +} + void MainWindow::onAutoSaveTimeout() { if (!pSettings->editor().enableAutoSave()) @@ -1154,6 +1190,15 @@ void MainWindow::onEditorContextMenu(const QPoint &pos) menu.addAction(ui->actionGoto_Declaration); menu.addAction(ui->actionGoto_Definition); menu.addAction(ui->actionFind_references); + + menu.addSeparator(); + menu.addAction(ui->actionOpen_Containing_Folder); + menu.addAction(ui->actionOpen_Terminal); + + //these actions needs parser + ui->actionGoto_Declaration->setEnabled(!editor->parser()->parsing()); + ui->actionGoto_Definition->setEnabled(!editor->parser()->parsing()); + ui->actionFind_references->setEnabled(!editor->parser()->parsing()); } else { //mouse on gutter int line; @@ -1996,8 +2041,13 @@ void MainWindow::on_actionFind_Previous_triggered() void MainWindow::on_cbSearchHistory_currentIndexChanged(int index) { - ui->btnSearchAgin->setEnabled(!ui->cbSearchHistory->currentText().isEmpty()); mSearchResultModel.setCurrentIndex(index); + PSearchResults results = mSearchResultModel.results(index); + if (results && results->searchType == SearchType::Search) { + ui->btnSearchAgin->setEnabled(true); + } else { + ui->btnSearchAgin->setEnabled(false); + } } void MainWindow::on_btnSearchAgin_clicked() @@ -2206,3 +2256,41 @@ void MainWindow::on_actionGoto_Definition_triggered() } } + +void MainWindow::on_actionFind_references_triggered() +{ + Editor * editor = mEditorList->getEditor(); + BufferCoord pos; + if (editor && editor->PointToCharLine(mContextMenuPos,pos)) { + CppRefacter refactor; + refactor.findOccurence(editor,pos); + ui->tabMessages->setCurrentWidget(ui->tabSearch); + openCloseBottomPanel(true); + } +} + + +void MainWindow::on_actionOpen_Containing_Folder_triggered() +{ + Editor* editor = mEditorList->getEditor(); + if (editor) { + QFileInfo info(editor->filename()); + if (!info.path().isEmpty()) { + QDesktopServices::openUrl(info.path()); + } + } +} + + +void MainWindow::on_actionOpen_Terminal_triggered() +{ + Editor* editor = mEditorList->getEditor(); + if (editor) { + QFileInfo info(editor->filename()); + if (!info.path().isEmpty()) { + openShell(info.path(),"cmd.exe"); + } + } + +} + diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 40ca89de..7661f0af 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -132,6 +132,7 @@ private: void doAutoSave(Editor *e); void buildContextMenus(); void maximizeEditor(); + void openShell(const QString& folder, const QString& shellCommand); private slots: void onAutoSaveTimeout(); @@ -274,6 +275,12 @@ private slots: void on_actionGoto_Definition_triggered(); + void on_actionFind_references_triggered(); + + void on_actionOpen_Containing_Folder_triggered(); + + void on_actionOpen_Terminal_triggered(); + private: Ui::MainWindow *ui; EditorList *mEditorList; diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 853fb0b8..10005b9e 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -255,7 +255,7 @@ QTabWidget::South - 0 + 3 @@ -467,7 +467,7 @@ QTabWidget::North - 0 + 1 @@ -1552,6 +1552,29 @@ Find references + + + + :/icons/images/newlook24/090-explorer.png + + + + Open containing folder + + + Ctrl+B + + + + + + :/icons/images/newlook24/030-dos.png + + + + Open a terminal here + + diff --git a/RedPandaIDE/qsynedit/SynEdit.h b/RedPandaIDE/qsynedit/SynEdit.h index 95922afa..e08689b6 100644 --- a/RedPandaIDE/qsynedit/SynEdit.h +++ b/RedPandaIDE/qsynedit/SynEdit.h @@ -254,6 +254,7 @@ public: bool GetLineOfMouse(int& line); bool PointToCharLine(const QPoint& point, BufferCoord& coord); bool PointToLine(const QPoint& point, int& line); + bool isIdentChar(const QChar& ch); // setter && getters @@ -369,9 +370,6 @@ signals: void fontChanged(); void tabSizeChanged(); -protected: - bool isIdentChar(const QChar& ch); - protected: virtual bool onGetSpecialLineColors(int Line, QColor& foreground, QColor& backgroundColor) ; diff --git a/RedPandaIDE/qsynedit/TextBuffer.cpp b/RedPandaIDE/qsynedit/TextBuffer.cpp index d3bb9c7f..908b8ea1 100644 --- a/RedPandaIDE/qsynedit/TextBuffer.cpp +++ b/RedPandaIDE/qsynedit/TextBuffer.cpp @@ -217,6 +217,24 @@ void SynEditStringList::setText(const QString &text) PutTextStr(text); } +void SynEditStringList::setContents(const QStringList &text) +{ + beginUpdate(); + auto action = finally([this]{ + endUpdate(); + }); + clear(); + if (text.count() > 0) { + mIndexOfLongestLine = -1; + int FirstAdded = mList.count(); + + foreach (const QString& s,text) { + addItem(s); + } + emit inserted(FirstAdded,text.count()); + } +} + QStringList SynEditStringList::contents() { QStringList Result; @@ -288,8 +306,10 @@ void SynEditStringList::clear() { if (!mList.isEmpty()) { beginUpdate(); + int oldCount = mList.count(); mIndexOfLongestLine = -1; mList.clear(); + emit deleted(0,oldCount); endUpdate(); } } diff --git a/RedPandaIDE/qsynedit/TextBuffer.h b/RedPandaIDE/qsynedit/TextBuffer.h index 627c3e5e..46410b91 100644 --- a/RedPandaIDE/qsynedit/TextBuffer.h +++ b/RedPandaIDE/qsynedit/TextBuffer.h @@ -67,6 +67,7 @@ public: void* getObject(int Index); QString text(); void setText(const QString& text); + void setContents(const QStringList& text); QStringList contents(); void putString(int Index, const QString& s);