From 6754c014c9c36c2ee32d02d14dfb3916048d5f17 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Tue, 29 Mar 2022 21:41:02 +0800 Subject: [PATCH] - enhancement: only tag the first inconstantency when running problem case, to greatly reduce compare & display time --- NEWS.md | 1 + RedPandaIDE/RedPandaIDE.pro | 2 + RedPandaIDE/RedPandaIDE_zh_CN.ts | 447 +++++++++--------- RedPandaIDE/mainwindow.cpp | 73 ++- RedPandaIDE/mainwindow.h | 4 + RedPandaIDE/mainwindow.ui | 62 ++- RedPandaIDE/problems/ojproblemset.h | 3 + RedPandaIDE/problems/problemcasevalidator.cpp | 16 +- RedPandaIDE/widgets/linenumbertexteditor.cpp | 97 ++++ RedPandaIDE/widgets/linenumbertexteditor.h | 50 ++ 10 files changed, 495 insertions(+), 260 deletions(-) create mode 100644 RedPandaIDE/widgets/linenumbertexteditor.cpp create mode 100644 RedPandaIDE/widgets/linenumbertexteditor.h diff --git a/NEWS.md b/NEWS.md index 1198aa61..0b8d843b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,7 @@ Red Panda C++ Version 1.0.2 - enhancement: display problem case running time - enhancement: set problem case input/expected output file - enhancement: auto position cursor in expected with output's cursor + - enhancement: only tag the first inconstantency when running problem case, to greatly reduce compare & display time Red Panda C++ Version 1.0.1 - fix: only convert project icon file when it's filename doesn't end with ".ico" diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 5ea238d5..52962611 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -170,6 +170,7 @@ SOURCES += \ widgets/issuestable.cpp \ widgets/labelwithmenu.cpp \ widgets/lightfusionstyle.cpp \ + widgets/linenumbertexteditor.cpp \ widgets/macroinfomodel.cpp \ widgets/newclassdialog.cpp \ widgets/newheaderdialog.cpp \ @@ -314,6 +315,7 @@ HEADERS += \ widgets/issuestable.h \ widgets/labelwithmenu.h \ widgets/lightfusionstyle.h \ + widgets/linenumbertexteditor.h \ widgets/macroinfomodel.h \ widgets/newclassdialog.h \ widgets/newheaderdialog.h \ diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.ts b/RedPandaIDE/RedPandaIDE_zh_CN.ts index 3f653502..26d64a72 100644 --- a/RedPandaIDE/RedPandaIDE_zh_CN.ts +++ b/RedPandaIDE/RedPandaIDE_zh_CN.ts @@ -3813,7 +3813,7 @@ Are you really want to continue? - + @@ -3827,48 +3827,48 @@ Are you really want to continue? 编译日志 - + File 文件 - + Tools 工具 - - + + Run 运行 - + Edit 编辑 - - + + Project 项目 - + Watch 监视 - + Structure 结构 - + Files 文件 @@ -3878,10 +3878,10 @@ Are you really want to continue? - - - - + + + + Debug 调试 @@ -3913,8 +3913,8 @@ Are you really want to continue? - - + + Search 查找 @@ -3939,23 +3939,23 @@ Are you really want to continue? 替换 - + Close 关闭 - + Execute 运行 - - + + Code 代码 - + Window 窗口 @@ -3973,59 +3973,59 @@ 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 @@ -4033,73 +4033,73 @@ Are you really want to continue? - + Tools Output 工具输出 - - + + Choose Input File 选择输入文件 - + ... ... - + Tool Panels 工具面板 - + Git Git - + F9 F9 - + F10 F10 - + Undo 恢复 - + Ctrl+Z Ctrl+Z - + Redo 重做 - + Ctrl+Y Ctrl+Y - + Cut 剪切 - + Ctrl+X Ctrl+X - + @@ -4107,144 +4107,144 @@ Are you really want to continue? 复制 - + 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 单步进入 - + Problem Set 试题集 @@ -4299,20 +4299,20 @@ Are you really want to continue? - + TODO TODO - + Bookmark 书签 - + Problem 试题 @@ -4353,32 +4353,32 @@ Are you really want to continue? %v/%m - + Output 输出 - + Input 输入 - + Expected 期望输出 - + Help 帮助 - + Refactor 重构 - + View 视图 @@ -4387,306 +4387,306 @@ Are you really want to continue? 工具窗口 - + Main 主工具栏 - + Compiler Set 编译器配置集 - - + + New Source File 新建源代码文件 - + Tab Tab - + Shift+Tab Shift+Tab - + 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 Watches 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 跳转到声明处 - + Ctrl+Shift+G Ctrl+Shift+G - + Goto Definition 跳转到定义处 - + Ctrl+G Ctrl+G - + Find references 查找符号的引用 - + Open containing folder 打开所在的文件夹 - + Ctrl+B Ctrl+B - + Open a terminal here 打开命令行窗口 - + File Properties... 文件属性... - + Close Project 关闭项目 - + Project options 项目属性 - + New Project... 新建项目... - - + + New Project File 新建项目文件 @@ -4696,194 +4696,194 @@ Are you really want to continue? 新建文件 - + Add to project... 添加到项目... - + Remove from project 从项目删除 - + View Makefile 查看Makefile - + Clean 清理构建文件 - + Open Folder in Explorer 在浏览器中打开 - + Open In Terminal 在终端中打开 - + About 关于 - + Rename Symbol 重命名符号 - + Shift+F6 Shift+F6 - + Print... 打印... - + Ctrl+P Ctrl+P - + Export As RTF 导出为RTF - + Export As HTML 导出为HTML - + Move To Other View 移动到其他视图 - + Ctrl+M Ctrl+M - - + + C++ Reference C++参考手册 - + C Reference C参考手册 - + Show Tool Panels 显示全部工具面板 - + Create Git Repository Create Repository 创建Git仓库 - + Commit 提交(Commit) - + Revert 撤销(Revert) - + Reset 回滚(Reset) - + Add Files 添加文件 - + Restore 还原(Restore) - + Website 官方网站 - + Branch/Switch 分支切换(Switch) - + Merge 合并(Merge) - - + + Show Log Log 显示日志(Log) - + Remotes... 远程仓库... - + Fetch 取回(Fetch) - + Pull 拉取(Pull) - + Push 推送(Push) - + Hide Non Support Files 隐藏不支持的文件 - + Toggle Block Comment 切换块注释 - + Alt+Shift+A Alt+Shift+A - + Match Bracket 匹配当前括号 - + Ctrl+] Ctrl+] @@ -4892,50 +4892,50 @@ Are you really want to continue? 工具窗口栏 - + Status Bar 状态栏 - + Ctrl+Backspace Ctrl+Backspace - + Interrupt 中断 - - + + Delete To Word Begin 删除到单词开头 - + Ctrl+Shift+B Ctrl+Shift+B - + Delete to Word End 删除到单词结尾 - + Ctrl+Shift+E Ctrl+Shift+E - + New Class... Add Class... 新建类... - - + + New Header... New Header 新建头文件... @@ -4945,47 +4945,47 @@ Are you really want to continue? 插入行 - + Delete Line 删除当前行 - + Ctrl+D Ctrl+D - + Duplicate Line 复制当前行 - + Ctrl+E Ctrl+E - + Delete Word 删除当前单词 - + Ctrl+Shift+D Ctrl+Shift+D - + Delete to EOL 删除到行尾 - + Ctrl+Del Ctrl+Del - + Delete to BOL 删除到行首 @@ -4994,27 +4994,27 @@ Are you really want to continue? C/C++参考 - + EGE Manual EGE图形库手册 - + Add Bookmark 添加书签 - + Remove Bookmark 删除书签 - + Modify Bookmark Description 修改书签说明 - + Locate in Files View 在文件视图中定位 @@ -5023,7 +5023,7 @@ Are you really want to continue? 打开文件夹 - + Running Parameters... 运行参数... @@ -5241,9 +5241,9 @@ Are you really want to continue? 全部复制 - - - + + + @@ -5698,8 +5698,15 @@ Are you really want to continue? 选择期望输出文件 - - + + + + Line %1 + 第%1行 + + + + Choose Working Folder 选择工作文件夹 diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 3c0751a9..33aaf8a2 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -69,6 +69,7 @@ #include #include "MainWindow.h" #include +#include #include "settingsdialog/settingsdialog.h" #include "compiler/compilermanager.h" @@ -646,8 +647,11 @@ void MainWindow::applySettings() caseEditorFont.setPixelSize(pointToPixel(pSettings->executor().caseEditorFontSize())); font.setStyleStrategy(QFont::PreferAntialias); ui->txtProblemCaseInput->setFont(caseEditorFont); + ui->lblProblemCaseInput->setFont(caseEditorFont); ui->txtProblemCaseOutput->setFont(caseEditorFont); + ui->lblProblemCaseOutput->setFont(caseEditorFont); ui->txtProblemCaseExpected->setFont(caseEditorFont); + ui->lblProblemCaseExpected->setFont(caseEditorFont); mTcpServer.close(); if (pSettings->executor().enableProblemSet()) { @@ -3170,25 +3174,23 @@ void MainWindow::onProblemCaseIndexChanged(const QModelIndex ¤t, const QMo POJProblemCase problemCase = mOJProblemModel.getCase(idx.row()); if (problemCase) { ui->btnProblemCaseInputFileName->setEnabled(false); - ui->txtProblemCaseInputFileName->setEnabled(false); ui->btnRemoveProblemCase->setEnabled(true); ui->btnProblemCaseInputFileName->setEnabled(true); fillProblemCaseInputAndExpected(problemCase); ui->txtProblemCaseOutput->clear(); ui->txtProblemCaseOutput->setPlainText(problemCase->output); updateProblemCaseOutput(problemCase); + return; } } ui->btnProblemCaseClearInputFileName->setVisible(false); ui->btnProblemCaseInputFileName->setEnabled(false); - ui->txtProblemCaseInputFileName->setEnabled(false); ui->txtProblemCaseInputFileName->clear(); ui->txtProblemCaseInputFileName->setToolTip(""); ui->btnProblemCaseClearExpectedOutputFileName->setVisible(false); ui->btnProblemCaseExpectedOutputFileName->setEnabled(false); - ui->txtProblemCaseExpectedOutputFileName->setEnabled(false); ui->txtProblemCaseExpectedOutputFileName->clear(); ui->txtProblemCaseExpectedOutputFileName->setToolTip(""); @@ -3200,6 +3202,10 @@ void MainWindow::onProblemCaseIndexChanged(const QModelIndex ¤t, const QMo ui->txtProblemCaseExpected->clear(); ui->txtProblemCaseExpected->setReadOnly(true); ui->txtProblemCaseOutput->clear(); + + ui->lblProblemCaseExpected->clear(); + ui->lblProblemCaseOutput->clear(); + ui->lblProblemCaseInput->clear(); } void MainWindow::onProblemNameChanged(int index) @@ -6217,31 +6223,33 @@ void MainWindow::doCompileRun(RunType runType) void MainWindow::updateProblemCaseOutput(POJProblemCase problemCase) { if (problemCase->testState == ProblemCaseTestState::Failed) { - QStringList output = textToLines(problemCase->output); - QStringList expected; - if (fileExists(problemCase->expectedOutputFileName)) - expected = readFileToLines(problemCase->expectedOutputFileName); - else - expected = textToLines(problemCase->expected); - for (int i=0;i=expected.count() || output[i]!=expected[i]) { - QTextBlock block = ui->txtProblemCaseOutput->document()->findBlockByLineNumber(i); - QTextCursor cur(block); - cur.select(QTextCursor::LineUnderCursor); - QTextCharFormat format = cur.charFormat(); - format.setUnderlineColor(mErrorColor); - format.setUnderlineStyle(QTextCharFormat::WaveUnderline); - cur.setCharFormat(format); - } + int diffLine; + if (problemCase->outputLineCounts > problemCase->expectedLineCounts) { + diffLine = problemCase->expectedLineCounts; + } else if (problemCase->outputLineCounts < problemCase->expectedLineCounts) { + diffLine = problemCase->outputLineCounts; + } else { + diffLine = problemCase->firstDiffLine; } - if (output.count()txtProblemCaseOutput->document()->findBlockByLineNumber(output.count()-1); + if (diffLine < problemCase->outputLineCounts) { + QTextBlock block = ui->txtProblemCaseOutput->document()->findBlockByLineNumber(diffLine); + if (!block.isValid()) + return; QTextCursor cur(block); - cur.select(QTextCursor::LineUnderCursor); + if (cur.isNull()) + return; + cur = QTextCursor(block); + QTextCharFormat oldFormat = cur.charFormat(); QTextCharFormat format = cur.charFormat(); + cur.select(QTextCursor::LineUnderCursor); format.setUnderlineColor(mErrorColor); format.setUnderlineStyle(QTextCharFormat::WaveUnderline); cur.setCharFormat(format); + cur.clearSelection(); + cur.setCharFormat(oldFormat); + ui->txtProblemCaseOutput->setTextCursor(cur); + } else if (diffLine < problemCase->expectedLineCounts) { + ui->txtProblemCaseOutput->moveCursor(QTextCursor::MoveOperation::End); } } } @@ -7446,7 +7454,28 @@ void MainWindow::on_txtProblemCaseOutput_cursorPositionChanged() { QTextCursor cursor = ui->txtProblemCaseOutput->textCursor(); int val = ui->txtProblemCaseOutput->verticalScrollBar()->value(); + int line = cursor.block().firstLineNumber(); + ui->lblProblemCaseOutput->setText(tr("Line %1").arg(cursor.block().firstLineNumber()+1)); + + QTextBlock block = ui->txtProblemCaseExpected->document()->findBlockByLineNumber(line); + if (!block.isValid()) + return; + cursor = QTextCursor(block); ui->txtProblemCaseExpected->setTextCursor(cursor); ui->txtProblemCaseExpected->verticalScrollBar()->setValue(val); } + +void MainWindow::on_txtProblemCaseExpected_cursorPositionChanged() +{ + QTextCursor cursor = ui->txtProblemCaseExpected->textCursor(); + ui->lblProblemCaseExpected->setText(tr("Line %1").arg(cursor.block().firstLineNumber()+1)); +} + + +void MainWindow::on_txtProblemCaseInput_cursorPositionChanged() +{ + QTextCursor cursor = ui->txtProblemCaseInput->textCursor(); + ui->lblProblemCaseInput->setText(tr("Line %1").arg(cursor.block().firstLineNumber()+1)); +} + diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 90479e7c..79b49ed3 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -657,6 +657,10 @@ private slots: void on_txtProblemCaseOutput_cursorPositionChanged(); + void on_txtProblemCaseExpected_cursorPositionChanged(); + + void on_txtProblemCaseInput_cursorPositionChanged(); + private: Ui::MainWindow *ui; EditorList *mEditorList; diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 7659eedc..26b5c116 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -1373,7 +1373,7 @@ 0 - + QPlainTextEdit::NoWrap @@ -1382,13 +1382,6 @@ - - - - QPlainTextEdit::NoWrap - - - @@ -1406,6 +1399,9 @@ + + false + true @@ -1453,13 +1449,6 @@ - - - - QPlainTextEdit::NoWrap - - - @@ -1484,6 +1473,9 @@ + + false + true @@ -1517,6 +1509,41 @@ + + + + QPlainTextEdit::NoWrap + + + + + + + QPlainTextEdit::NoWrap + + + + + + + + + + + + + + + + + + + + + + + + @@ -3010,6 +3037,11 @@
widgets/editorstabwidget.h
1 + + LineNumberTextEditor + QPlainTextEdit +
widgets/linenumbertexteditor.h
+
diff --git a/RedPandaIDE/problems/ojproblemset.h b/RedPandaIDE/problems/ojproblemset.h index d9a00a72..90389e65 100644 --- a/RedPandaIDE/problems/ojproblemset.h +++ b/RedPandaIDE/problems/ojproblemset.h @@ -36,6 +36,9 @@ struct OJProblemCase { ProblemCaseTestState testState; // no persistence QString output; // no persistence int runningTime; + int firstDiffLine; + int outputLineCounts; + int expectedLineCounts; OJProblemCase(); public: diff --git a/RedPandaIDE/problems/problemcasevalidator.cpp b/RedPandaIDE/problems/problemcasevalidator.cpp index bc1c9b7b..aaef0fe5 100644 --- a/RedPandaIDE/problems/problemcasevalidator.cpp +++ b/RedPandaIDE/problems/problemcasevalidator.cpp @@ -27,16 +27,26 @@ bool ProblemCaseValidator::validate(POJProblemCase problemCase, bool ignoreSpace if (!problemCase) return false; QStringList output = textToLines(problemCase->output); - QStringList expected = textToLines(problemCase->expected); + QStringList expected; + if (fileExists(problemCase->expectedOutputFileName)) + expected = readFileToLines(problemCase->expectedOutputFileName); + else + expected = textToLines(problemCase->expected); + problemCase->outputLineCounts = output.count(); + problemCase->expectedLineCounts = expected.count(); if (output.count()!=expected.count()) return false; for (int i=0;ifirstDiffLine = i; return false; + } } else { - if (output[i]!=expected[i]) + if (output[i]!=expected[i]) { + problemCase->firstDiffLine = i; return false; + } } } return true; diff --git a/RedPandaIDE/widgets/linenumbertexteditor.cpp b/RedPandaIDE/widgets/linenumbertexteditor.cpp new file mode 100644 index 00000000..6d6db9f2 --- /dev/null +++ b/RedPandaIDE/widgets/linenumbertexteditor.cpp @@ -0,0 +1,97 @@ +#include "linenumbertexteditor.h" + +#include +#include + +LineNumberTextEditor::LineNumberTextEditor(QWidget *parent) +{ + lineNumberArea = new LineNumberArea(this); + + connect(this, &LineNumberTextEditor::blockCountChanged, this, &LineNumberTextEditor::updateLineNumberAreaWidth); + connect(this, &LineNumberTextEditor::updateRequest, this, &LineNumberTextEditor::updateLineNumberArea); + //connect(this, &LineNumberTextEditor::cursorPositionChanged, this, &LineNumberTextEditor::highlightCurrentLine); + + updateLineNumberAreaWidth(0); + //highlightCurrentLine(); +} + +int LineNumberTextEditor::lineNumberAreaWidth() +{ + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) { + max /= 10; + ++digits; + } + + int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits; + + return space; +} + +void LineNumberTextEditor::updateLineNumberAreaWidth(int /* newBlockCount */) +{ + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + +void LineNumberTextEditor::updateLineNumberArea(const QRect &rect, int dy) +{ + if (dy) + lineNumberArea->scroll(0, dy); + else + lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + + if (rect.contains(viewport()->rect())) + updateLineNumberAreaWidth(0); +} + +void LineNumberTextEditor::resizeEvent(QResizeEvent *e) +{ + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); +} + +void LineNumberTextEditor::highlightCurrentLine() +{ + QList extraSelections; + + if (!isReadOnly()) { + QTextEdit::ExtraSelection selection; + + QColor lineColor = QColor(Qt::yellow).lighter(160); + + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + +void LineNumberTextEditor::lineNumberAreaPaintEvent(QPaintEvent *event) +{ + QPainter painter(lineNumberArea); + painter.setFont(font()); + painter.fillRect(event->rect(), palette().color(QPalette::Button)); + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = qRound(blockBoundingGeometry(block).translated(contentOffset()).top()); + int bottom = top + qRound(blockBoundingRect(block).height()); + while (block.isValid() && top <= event->rect().bottom()) { + if (block.isVisible() && bottom >= event->rect().top()) { + QString number = QString::number(blockNumber + 1); + painter.setPen(palette().color(QPalette::ButtonText)); + painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), + Qt::AlignRight, number); + } + + block = block.next(); + top = bottom; + bottom = top + qRound(blockBoundingRect(block).height()); + ++blockNumber; + } +} diff --git a/RedPandaIDE/widgets/linenumbertexteditor.h b/RedPandaIDE/widgets/linenumbertexteditor.h new file mode 100644 index 00000000..2ed08327 --- /dev/null +++ b/RedPandaIDE/widgets/linenumbertexteditor.h @@ -0,0 +1,50 @@ +#ifndef LINENUMBERTEXTEDITOR_H +#define LINENUMBERTEXTEDITOR_H + +#include + +class LineNumberTextEditor : public QPlainTextEdit +{ + Q_OBJECT +public: + LineNumberTextEditor(QWidget *parent = nullptr); + + void lineNumberAreaPaintEvent(QPaintEvent *event); + int lineNumberAreaWidth(); + +protected: + void resizeEvent(QResizeEvent *event) override; + +private slots: + void updateLineNumberAreaWidth(int newBlockCount); + void highlightCurrentLine(); + void updateLineNumberArea(const QRect &rect, int dy); + +private: + QWidget *lineNumberArea; +}; + +class LineNumberArea : public QWidget +{ +public: + LineNumberArea(LineNumberTextEditor *editor) : QWidget(editor), mParentEditor(editor) + {} + + QSize sizeHint() const override + { + return QSize(mParentEditor->lineNumberAreaWidth(), 0); + } + +protected: + void paintEvent(QPaintEvent *event) override + { + mParentEditor->lineNumberAreaPaintEvent(event); + } + +private: + LineNumberTextEditor *mParentEditor; +}; + + + +#endif // LINENUMBERTEXTEDITOR_H