diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.qm b/RedPandaIDE/RedPandaIDE_zh_CN.qm
index 5fd850f7..d3f0fb8f 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 96e86334..2fdc02bf 100644
--- a/RedPandaIDE/RedPandaIDE_zh_CN.ts
+++ b/RedPandaIDE/RedPandaIDE_zh_CN.ts
@@ -430,62 +430,62 @@
Compiler
-
+
重编译前的清理准备工作失败!
-
+
编译结果:
-
+
- 错误数: %1
-
+
- 警告数: %1
-
+
- 输出文件名: %1
-
+
- 输出文件大小: %1
-
+
- 编译时间: %1 秒
-
+
[错误]
-
+
[警告]
-
+
[信息]
-
+
[说明]
-
+
无法启动编译器进程'%1'。
@@ -494,27 +494,27 @@
无法启动编译进程。
-
+
编译进程启动后崩溃。
-
+
waitFor()函数等待超时。
-
+
在向编译进程输入内容时出错。
-
+
在从编译进程读取内容时出错。
-
+
发生了未知错误。
@@ -549,45 +549,45 @@
CompilerManager
+
+
+
+
+
+
+
+ 无编译器设置
+
-
- 无编译器设置
-
-
-
-
-
-
-
没有配置编译器设置。
-
-
-
-
-
+
+
+
+
+
无法启动调试器
-
+
不支持字符编码
-
+
Clang只支持UTF-8编码
-
+
程序中的文字内容可能无法被正确处理和显示。
@@ -1065,35 +1065,35 @@ Are you really want to continue?
要剪切的内容超过了字符数限制!
-
+
打印文档
-
-
-
+
+
+
Ctrl+单击以获取更多信息
-
-
+
+
未找到符号'%1'!
-
+
断点条件
-
+
输入当前断点的生效条件:
-
+
只读
@@ -2806,44 +2806,44 @@ Are you really want to continue?
小熊猫C++
-
-
-
-
-
-
+
+
+
+
+
+
编译器
-
+
编译日志
-
+
文件
-
+
工具
-
-
+
+
运行
-
+
编辑
-
+
项目
@@ -2867,82 +2867,82 @@ Are you really want to continue?
资源
-
-
-
-
+
+
+
+
调试
-
+
求值
-
+
调试主控台
-
+
调用栈
-
+
断点
-
+
本地变量
-
-
+
+
查找
-
+
历史:
-
+
重新查找
-
+
替换为:
-
+
替换
-
+
关闭
-
+
运行
-
-
+
+
代码
-
+
窗口
@@ -2955,737 +2955,802 @@ Are you really want to continue?
工具栏2
-
+
新建
-
+
Ctrl+N
-
+
打开...
-
+
Ctrl+O
-
+
保存
-
+
Ctrl+S
-
+
另存为...
-
+
另存为
-
+
全部保存
-
+
Ctrl+Shift+S
-
+
选项
-
-
-
-
-
-
-
+
+
+
+
+
+
+
编译
-
+
F9
-
+
F10
-
+
恢复
-
+
Ctrl+Z
-
+
重做
-
+
Ctrl+Y
-
+
剪切
-
+
Ctrl+X
-
-
-
+
+
+
复制
-
+
Ctrl+C
-
-
+
+
粘贴
-
+
Ctrl+V
-
-
+
+
选择全部
-
+
Ctrl+A
-
+
缩进
-
+
取消缩进
-
+
切换注释
-
+
Ctrl+/
-
+
全部收起
-
+
全部展开
-
+
使用ANSI编码
-
+
使用UTF-8编码
-
+
自动检测
-
+
转换为ANSI编码
-
+
转换为UTF-8编码
-
-
+
+
编译运行
-
+
F11
-
-
+
+
全部重编译
-
+
F12
-
+
停止执行
-
+
F6
-
+
F5
-
+
单步跳过
-
+
F7
-
+
单步进入
-
+
+
+
+ 试题集
+
+
+
+
+ 新建试题集
+
+
+
+
+ 添加试题
+
+
+
+
+ 删除试题
+
+
+
+
+
+ 保存试题集
+
+
+
+
+
+ 载入试题集
+
+
+
内存
-
+
Address:
地址表达式:
-
+
取消
-
+
TODO
-
+
书签
-
+
+
+
+ 试题
+
+
+
+
+ 添加试题案例
+
+
+
+
+ Remove Problem Set
+ 删除试题集
+
+
+
+
+ 输出
+
+
+
+
+ 输入
+
+
+
+
+ 期望输出
+
+
+
帮助
-
+
重构
-
+
主工具栏
-
+
编译器配置集
-
-
+
+
新建源代码文件
-
+
Tab
-
+
Shift+Tab
-
+
F8
-
+
单步跳出
-
+
Ctrl+F8
-
+
执行到光标处
-
+
Ctrl+F5
-
+
继续执行
-
+
F4
-
+
添加监视
-
+
打开CPU信息窗口...
-
+
退出
-
+
查找...
-
+
Ctrl+F
-
+
在文件中查找...
-
+
Ctrl+Shift+F
-
+
替换
-
+
Ctrl+R
-
+
查找下一个
-
+
F3
-
+
查找前一个
-
+
Shift+F3
-
+
删除监视值
-
+
Remove All
删除全部监视值
-
+
修改监视值
-
+
对代码重新排版
-
+
Ctrl+Shift+A
-
+
前一次编辑位置
-
+
Ctrl+Alt+Left
-
+
后一次编辑位置
-
+
Ctrl+Alt+Right
-
+
Ctrl+W
-
+
全部关闭
-
+
Ctrl+Shift+W
-
+
最大化编辑器
-
+
Ctrl+F11
-
+
下一窗口
-
+
Ctrl+Tab
-
+
前一窗口
-
+
Ctrl+Shift+Tab
-
+
切换断点
-
+
Ctrl+F4
-
-
+
+
删除所有断点
-
+
设置断点条件...
-
+
跳转到声明处
-
+
跳转到定义处
-
+
查找符号的引用
-
+
打开所在的文件夹
-
+
Ctrl+B
-
+
打开命令行窗口
-
+
文件属性...
-
+
关闭项目
-
+
项目属性
-
+
新建项目...
-
+
新建项目文件
-
+
添加到项目...
-
+
从项目删除
-
+
查看Makefile
-
+
清理构建文件
-
+
在浏览器中打开
-
+
在终端中打开
-
+
关于
-
-
+
+
重命名符号
-
+
Shift+F6
-
+
打印...
-
+
Ctrl+P
-
-
+
+
导出为RTF
-
-
+
+
导出为HTML
-
+
移动到其他视图
-
+
Ctrl+M
-
+
C/C++参考
-
+
EGE图形库手册
-
+
添加书签
-
+
删除书签
-
+
修改书签说明
-
+
在文件视图中定位
-
-
+
+
打开文件夹
-
+
运行参数...
-
+
文件编码
-
+
文件历史
-
-
-
-
-
-
+
+
+
+
+
+
正在调试
-
-
-
-
-
-
+
+
+
+
+
+
正在运行
-
-
-
-
+
+
+
-
+
+
正在编译
@@ -3694,599 +3759,627 @@ 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
-
+
只读
-
+
插入
-
+
覆写
-
+
关闭项目
-
+
你确定要关闭'%1'吗?
-
-
+
+
确认
-
-
-
+
+
+
源文件尚未编译。
-
-
+
+
现在编译?
-
-
-
+
+
+
源文件比可执行程序新。
-
+
重新编译?
-
+
无编译器设置
-
+
没有配置编译器设置。
-
+
无法启动调试器
-
-
+
+
启用调试参数
-
-
+
+
当前编译设置中未启用调试选项(-g3),或启用了信息剥除选项(-s)<br /><br/>是否纠正这一问题?
-
+
项目尚未构建
-
+
项目尚未构建。是否构建?
-
+
宿主程序不存在
-
+
动态链接库(DLL)需要一个宿主程序来运行。
-
+
但它不存在。
-
+
宿主程序不存在
-
+
宿主程序'%1'不存在。
-
+
重新编译?
-
-
+
+
保存上次打开信息失败
-
+
无法删除旧上次打开信息文件'%1'
-
+
无法保存上次打开信息文件'%1'
-
+
载入上次打开信息失败
-
+
无法载入上次打开信息文件'%1'
-
+
全部复制
-
-
+
+
清除
-
+
导出
-
+
插入代码段
-
+
+
+
+ 试题集%1
+
+
+
小熊猫Dev-C++
-
+
删除
-
+
删除全部书签
-
+
修改描述
-
-
-
+
+
+
书签描述
-
-
-
+
+
+
描述:
-
+
在调试主控台中显示调试器输出
-
+
清除这次搜索
-
+
删除所有搜索
-
+
断点条件...
-
+
断点条件
-
+
输入当前断点的生效条件:
-
+
Remove all breakpoints
删除所有断点
-
+
- 删除当前断点
+ 删除当前断点
-
+
重命名文件
-
-
+
+
添加文件夹
-
+
新文件夹
-
+
文件夹:
-
+
重命名
-
+
删除文件夹
-
+
按类型排序
-
+
按名称排序
-
+
显示继承的成员
-
+
跳转到声明处
-
+
跳转到定义处
-
+
在编辑器中打开
-
+
使用外部程序打开
-
+
在终端中打开
-
+
在Windows浏览器中打开
-
+
字符集
-
+
已自动保存%1个文件
-
+
保存项目
-
+
项目'%1'有改动。
-
+
需要保存吗?
-
-
-
+
+
+
+
保存失败
-
+
改变项目编译器配置集
-
+
改变项目的编译器配置集会导致所有的自定义编译器选项被重置。
-
+
你真的想要做那些吗?
-
+
您真的要清除该文件的所有断点吗?
-
+
新建项目
-
+
关闭'%1'以打开新项目?
-
+
文件夹不存在
-
+
文件夹'%1'不存在。是否创建?
-
+
无法创建文件夹
-
+
创建文件夹'%1'失败。
-
+
-
+
小熊猫Dev-C++项目文件 (*.dev)
-
+
新建项目失败
-
+
无法使用模板创建项目
-
+
无标题
-
+
新的项目文件名
-
+
文件名:
-
+
文件已存在!
-
+
文件'%1'已经存在!
-
+
添加到项目
-
+
重命名出错
-
+
符号'%1'在系统头文件中定义,无法修改。
-
+
新名称
-
-
+
+
替换出错
-
+
无法打开文件'%1'进行替换!
-
+
内容和上次查找时不一致。
-
+
RTF格式文件 (*.rtf)
-
+
HTML文件 (*.html)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ 试题%1
+
+
+
+
+
+ 试题集文件 (*.pbs)
+
+
+
+
+ 载入失败
+
+
+
+
+ 试题案例%1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
错误
-
+
项目历史
-
+
磁盘文件'%1'已被修改。
-
+
是否重新读取它的内容?
-
+
磁盘文件'%1'已被删除。
-
+
是否保持它在小熊猫C++中打开的编辑窗口?
-
+
打开
-
+
编译失败
-
+
运行失败
-
-
+
+
确认转换
-
-
+
+
当前编辑器中的文件将会使用%1编码保存。<br />这项操作无法被撤回。<br />你确定要继续吗?
-
+
新监视表达式
-
+
输入监视表达式
-
+
(%1/%2)正在解析文件"%3"
-
-
+
+
完成%1个文件的解析,用时%2秒
-
+
(每秒%1个文件)
@@ -4343,92 +4436,92 @@ Are you really want to continue?
Project
-
+
未找到文件
-
+
找不到项目文件'%1'!
-
+
无标题
-
+
无法保存文件
-
+
无法保存文件'%1'.
-
+
载入文件错误
-
+
文件已存在
-
+
文件'%1'已在项目中
-
+
项目已升级
-
+
已成功将项目升级到新的格式
-
+
旧项目文件备份在'%1'。
-
+
设置需要更新
-
+
Dev-C++的编译器设置格式已发生改变。
-
+
请在项目 >> 项目属性 >> 编译器设置中修改您的设置并保存您的项目
-
+
未找到编译器
-
+
您为该项目设置的编译器不存在。
-
+
它将会被全局编译器设置代替。
-
+
使用小熊猫Dev-C++编辑器开发
@@ -4819,24 +4912,24 @@ Are you really want to continue?
ProjectModel
-
+
文件已存在
-
+
文件'%1'已存在。是否删除?
-
-
+
+
删除失败
-
-
+
+
无法删除文件'%1'
@@ -5055,7 +5148,7 @@ Are you really want to continue?
QApplication
-
+
错误
@@ -5109,196 +5202,196 @@ Are you really want to continue?
-
-
+
+
错误
-
+
无法创建配置文件夹"%1"
-
+
无法写入配置文件夹"%1"
-
+
无法载入自动链接设置
-
+
+
-
下列%1文件夹不存在:
-
-
+
+
二进制
-
+
未指定%1文件夹
-
+
C包含
+
-
C++包含
-
-
-
-
+
+
+
+
无法找到%1程序"%2"
-
+
C语言选项
-
+
支持所有ANSI标准C程序(-ansi)
-
+
不支持将asm、inline和typeof作为关键字(-fno-asm)
-
+
模仿传统C预处理器行为(-traditional-cpp)
-
+
代码生成
-
+
生成特定机器的专用指令(-march)
-
+
完整兼容特定机器,较少优化(-tune)
-
+
启用特定指令集(-mx)
-
+
优化级别(-Ox)
-
+
使用下列指针大小编译(-mx)
-
+
语言标准(-std)
-
+
性能分析
-
+
生成调试信息(-g3)
-
+
生成性能分析信息(-pg)
-
+
代码警告
-
+
忽略所有警告信息(-w)
-
+
启用常见问题警告(-Wall)
-
+
启用更多问题警告(-Wextra)
-
+
检查ISO C/C++/C++0x语法一致性(-pedantic)
-
+
只进行语法检查(不编译)(-fsyntax-only)
-
+
将警告作为错误处理(-Werror)
-
+
遇到第一个错误后立即中止编译(-Wfatal-errors)
-
+
链接器
-
+
链接Objective-C程序 (-lobjc)
-
+
不使用标准库和系统启动文件(-nostdlib)
-
+
不产生控制台窗口(-mwindows)
-
+
剥除附加信息(-s)
@@ -5307,43 +5400,43 @@ Are you really want to continue?
链接Ojbective C程序(-lobjc)
-
+
输出
-
+
在生成的汇编代码中加入注释(-fverbose-asm)
-
+
编译时使用管道而不是临时文件(-pipe)
-
+
只生成汇编代码(-S)
-
-
+
+
确认
-
+
在验证编译器设置"%1"时遇到了下列问题:
-
+
未配置编译器设置。
-
+
您需要小熊猫C++在下列位置搜索编译器吗:<br />%1<br />%2
@@ -5677,18 +5770,20 @@ Are you really want to continue?
无标题
-
+
构造函数
-
+
析构函数
+
+
无法读取文件'%1'.
@@ -5698,6 +5793,11 @@ Are you really want to continue?
无法写入文件'%1'.
+
+
+
+ 无法解析试题集文件"%1":%2
+
RegisterModel
@@ -6095,7 +6195,7 @@ Are you really want to continue?
自动链接
-
+
@@ -6171,7 +6271,7 @@ Are you really want to continue?
杂项
-
+
程序运行
@@ -6394,12 +6494,12 @@ Are you really want to continue?
SynEditStringList
-
+
无法读取文件'%1'!
-
+
无法写入文件'%2'!
@@ -6608,122 +6708,121 @@ Are you really want to continue?
自动计算缩进
-
- 在{和:的下一行添加缩进
+ 在{和:的下一行添加缩进
-
+
自动使用空格代替制表符(Tab)
-
+
制表符(Tab)宽度
-
+
显示缩进提示线
-
+
缩进提示线颜色
-
+
填充缩进区域
-
+
光标
-
+
按下HOME键时,光标定位在本行的第一个非空格字符处
-
+
按下End键时,光标定位在本行的最后一个非空格字符处
-
+
在上下移动光标时,记住起始时光标所在栏数
-
+
插入状态下的光标
-
+
使用文字颜色作为光标颜色
-
+
滚动条
-
+
自动隐藏滚动条
-
+
可以将每行末尾字符滚动到编辑器最左侧
-
+
可以将最后一行滚动到编辑器最上方
-
+
翻页键只滚动半页
-
+
在滚动页时少滚动一行
-
+
鼠标滚轮卷轴速度(行)
-
+
显示右边缘线
-
+
右边缘宽度
-
+
右边缘颜色
-
+
覆写状态下的光标
-
+
光标颜色
diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp
index 2ca0458b..8331362a 100644
--- a/RedPandaIDE/mainwindow.cpp
+++ b/RedPandaIDE/mainwindow.cpp
@@ -205,6 +205,18 @@ MainWindow::MainWindow(QWidget *parent)
ui->searchView,&QTreeView::expandAll);
ui->replacePanel->setVisible(false);
+ mOJProblemSetNameCounter++;
+ mOJProblemSetModel.rename(tr("Problem Set %1").arg(mOJProblemSetNameCounter));
+ ui->lstProblemSet->setModel(&mOJProblemSetModel);
+ ui->lstProblemCases->setModel(&mOJProblemModel);
+ connect(ui->lstProblemSet->selectionModel(),
+ &QItemSelectionModel::currentRowChanged,
+ this, &MainWindow::onProblemSetIndexChanged);
+ connect(ui->lstProblemCases->selectionModel(),
+ &QItemSelectionModel::currentRowChanged,
+ this, &MainWindow::onProblemCaseIndexChanged);
+ ui->tabProblem->setVisible(false);
+
//files view
ui->treeFiles->setModel(&mFileSystemModel);
mFileSystemModel.setReadOnly(true);
@@ -2503,6 +2515,63 @@ void MainWindow::onFilesViewContextMenu(const QPoint &pos)
menu.exec(ui->treeFiles->mapToGlobal(pos));
}
+void MainWindow::onProblemSetIndexChanged(const QModelIndex ¤t, const QModelIndex &previous)
+{
+ QModelIndex idx = current;
+// if (previous.isValid()) {
+// QModelIndex caseIdx = ui->lstProblemCases->currentIndex();
+// if (caseIdx.isValid()) {
+// POJProblemCase problemCase = mOJProblemModel.getCase(caseIdx.row());
+// problemCase->input = ui->txtProblemCaseInput->toPlainText();
+// problemCase->expected = ui->txtProblemCaseExpected->toPlainText();
+// problemCase->output = ui->txtProblemCaseOutput->toPlainText();
+// }
+// }
+ if (!idx.isValid()) {
+ ui->btnRemoveProblem->setEnabled(false);
+ ui->tabProblem->setVisible(false);
+ } else {
+ ui->btnRemoveProblem->setEnabled(true);
+ POJProblem problem = mOJProblemSetModel.problem(idx.row());
+ mOJProblemModel.setProblem(problem);
+ ui->lblProblem->setText(problem->name);
+ ui->tabProblem->setVisible(true);
+ openCloseBottomPanel(true);
+ ui->tabMessages->setCurrentWidget(ui->tabProblem);
+ }
+}
+
+void MainWindow::onProblemCaseIndexChanged(const QModelIndex ¤t, const QModelIndex &previous)
+{
+ QModelIndex idx = current;
+ if (previous.isValid()) {
+ POJProblemCase problemCase = mOJProblemModel.getCase(previous.row());
+ problemCase->input = ui->txtProblemCaseInput->toPlainText();
+ problemCase->expected = ui->txtProblemCaseExpected->toPlainText();
+ problemCase->output = ui->txtProblemCaseOutput->toPlainText();
+ }
+ if (idx.isValid()) {
+ POJProblemCase problemCase = mOJProblemModel.getCase(idx.row());
+ if (problemCase) {
+ ui->btnRemoveProblemCase->setEnabled(true);
+ ui->txtProblemCaseInput->setText(problemCase->input);
+ ui->txtProblemCaseInput->setReadOnly(false);
+ ui->txtProblemCaseExpected->setText(problemCase->expected);
+ ui->txtProblemCaseExpected->setReadOnly(false);
+ ui->txtProblemCaseOutput->setText(problemCase->output);
+ ui->txtProblemCaseOutput->setReadOnly(true);
+ return;
+ }
+ }
+ ui->btnRemoveProblemCase->setEnabled(false);
+ ui->txtProblemCaseInput->clear();
+ ui->txtProblemCaseInput->setReadOnly(true);
+ ui->txtProblemCaseExpected->clear();
+ ui->txtProblemCaseExpected->setReadOnly(true);
+ ui->txtProblemCaseOutput->clear();
+ ui->txtProblemCaseOutput->setReadOnly(true);
+}
+
void MainWindow::onShowInsertCodeSnippetMenu()
{
mMenuInsertCodeSnippet->clear();
@@ -4819,3 +4888,88 @@ void MainWindow::on_actionRun_Parameters_triggered()
);
}
+
+void MainWindow::on_btnNewProblemSet_clicked()
+{
+ mOJProblemSetNameCounter++;
+ mOJProblemSetModel.create(tr("Problem Set %1").arg(mOJProblemSetNameCounter));
+}
+
+
+void MainWindow::on_btnAddProblem_clicked()
+{
+ int startCount = mOJProblemSetModel.count();
+ QString name;
+ while (true) {
+ name = tr("Problem %1").arg(startCount);
+ if (!mOJProblemSetModel.problemNameUsed(name))
+ break;
+ }
+ POJProblem problem = std::make_shared();
+ problem->name = name;
+ mOJProblemSetModel.addProblem(problem);
+ ui->lstProblemSet->setCurrentIndex(mOJProblemSetModel.index(mOJProblemSetModel.count()-1));
+}
+
+
+void MainWindow::on_btnRemoveProblem_clicked()
+{
+ QModelIndex idx = ui->lstProblemSet->currentIndex();
+ if (!idx.isValid())
+ return;
+ mOJProblemSetModel.removeProblem(idx.row());
+}
+
+
+void MainWindow::on_btnSaveProblemSet_clicked()
+{
+ QString fileName = QFileDialog::getSaveFileName(
+ this,
+ tr("Save Problem Set"),
+ QDir().absolutePath(),
+ tr("Problem Set Files (*.pbs)"));
+ if (!fileName.isEmpty()) {
+ try {
+ mOJProblemSetModel.saveToFile(fileName);
+ } catch (FileError& error) {
+ QMessageBox::critical(this,tr("Save Error"),
+ error.reason());
+ }
+ }
+}
+
+
+void MainWindow::on_btnLoadProblemSet_clicked()
+{
+ QString fileName = QFileDialog::getOpenFileName(
+ this,
+ tr("Load Problem Set"),
+ QDir().absolutePath(),
+ tr("Problem Set Files (*.pbs)"));
+ if (!fileName.isEmpty()) {
+ try {
+ mOJProblemSetModel.loadFromFile(fileName);
+ } catch (FileError& error) {
+ QMessageBox::critical(this,tr("Load Error"),
+ error.reason());
+ }
+ }
+}
+
+
+void MainWindow::on_btnAddProblemCase_clicked()
+{
+ int startCount = mOJProblemModel.count();
+ QString name;
+ while (true) {
+ name = tr("Problem Case %1").arg(startCount);
+ if (!mOJProblemSetModel.problemNameUsed(name))
+ break;
+ }
+ POJProblemCase problemCase = std::make_shared();
+ problemCase->name = name;
+ problemCase->testState = ProblemCaseTestState::NoTested;
+ mOJProblemModel.addCase(problemCase);
+ ui->lstProblemCases->setCurrentIndex(mOJProblemModel.index(mOJProblemModel.count()-1));
+}
+
diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h
index ac69a54b..da52071b 100644
--- a/RedPandaIDE/mainwindow.h
+++ b/RedPandaIDE/mainwindow.h
@@ -18,6 +18,7 @@
#include "toolsmanager.h"
#include "widgets/labelwithmenu.h"
#include "widgets/bookmarkmodel.h"
+#include "widgets/ojproblemsetmodel.h"
QT_BEGIN_NAMESPACE
@@ -211,6 +212,8 @@ private slots:
void onDebugConsoleContextMenu(const QPoint& pos);
void onFileEncodingContextMenu(const QPoint& pos);
void onFilesViewContextMenu(const QPoint& pos);
+ void onProblemSetIndexChanged(const QModelIndex ¤t, const QModelIndex &previous);
+ void onProblemCaseIndexChanged(const QModelIndex ¤t, const QModelIndex &previous);
void onShowInsertCodeSnippetMenu();
@@ -433,6 +436,18 @@ private slots:
void on_actionRun_Parameters_triggered();
+ void on_btnNewProblemSet_clicked();
+
+ void on_btnAddProblem_clicked();
+
+ void on_btnRemoveProblem_clicked();
+
+ void on_btnSaveProblemSet_clicked();
+
+ void on_btnLoadProblemSet_clicked();
+
+ void on_btnAddProblemCase_clicked();
+
private:
Ui::MainWindow *ui;
EditorList *mEditorList;
@@ -473,6 +488,9 @@ private:
PTodoParser mTodoParser;
PToolsManager mToolsManager;
QFileSystemModel mFileSystemModel;
+ OJProblemSetModel mOJProblemSetModel;
+ OJProblemModel mOJProblemModel;
+ int mOJProblemSetNameCounter;
bool mCheckSyntaxInBack;
bool mOpenClosingBottomPanel;
diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui
index 84ef4751..86554a78 100644
--- a/RedPandaIDE/mainwindow.ui
+++ b/RedPandaIDE/mainwindow.ui
@@ -306,8 +306,11 @@
-
+
+ New Problem Set
+
- ...
+ New Problem Set
@@ -317,8 +320,11 @@
-
+
+ Add Problem
+
- ...
+ Add Problem
@@ -328,8 +334,11 @@
-
+
+ Remove Problem
+
- ...
+ Remove Problem
@@ -339,8 +348,11 @@
-
+
+ Save Problem Set
+
- ...
+ Save Problem Set
@@ -350,8 +362,11 @@
-
+
+ Load Problem Set
+
- ...
+ Load Problem Set
@@ -1099,7 +1114,7 @@
0
-
-
+
Problem
@@ -1146,8 +1161,11 @@
-
+
+ Add Probem Case
+
- ...
+ Add Probem Case
@@ -1157,8 +1175,11 @@
-
+
+ Remove Problem Case
+
- ...
+ Remove Problem Case
@@ -1166,6 +1187,41 @@
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+ Run Current Case
+
+
+ Run Current Case
+
+
+
+ :/icons/images/newlook24/069-run.png:/icons/images/newlook24/069-run.png
+
+
+
+ -
+
+
+ Run All Cases
+
+
+ Run All Cases
+
+
+
+ :/icons/images/newlook24/021-Debug-Continue.png:/icons/images/newlook24/021-Debug-Continue.png
+
+
+
-
diff --git a/RedPandaIDE/widgets/ojproblemsetmodel.cpp b/RedPandaIDE/widgets/ojproblemsetmodel.cpp
index e4b37925..7f6650ea 100644
--- a/RedPandaIDE/widgets/ojproblemsetmodel.cpp
+++ b/RedPandaIDE/widgets/ojproblemsetmodel.cpp
@@ -1,26 +1,240 @@
#include "ojproblemsetmodel.h"
+#include
+#include
+#include
+#include
+#include "../utils.h"
+
OJProblemSetModel::OJProblemSetModel(QObject *parent) : QAbstractListModel(parent)
{
}
-OJProblemCaseModel::OJProblemCaseModel(QObject *parent): QAbstractListModel(parent)
+void OJProblemSetModel::clear()
+{
+ beginRemoveRows(QModelIndex(),0,mProblemSet.problems.count()-1);
+ mProblemSet.problems.clear();
+ endRemoveRows();
+}
+
+int OJProblemSetModel::count()
+{
+ return mProblemSet.problems.count();
+}
+
+void OJProblemSetModel::create(const QString& name)
+{
+ mProblemSet.name = name;
+ clear();
+}
+
+void OJProblemSetModel::rename(const QString &newName)
+{
+ if (mProblemSet.name!=newName)
+ mProblemSet.name = newName;
+}
+
+QString OJProblemSetModel::name()
+{
+ return mProblemSet.name;
+}
+
+void OJProblemSetModel::addProblem(POJProblem problem)
+{
+ beginInsertRows(QModelIndex(), mProblemSet.problems.count(), mProblemSet.problems.count());
+ mProblemSet.problems.append(problem);
+ endInsertRows();
+}
+
+POJProblem OJProblemSetModel::problem(int index)
+{
+ return mProblemSet.problems[index];
+}
+
+void OJProblemSetModel::removeProblem(int index)
+{
+ Q_ASSERT(index>=0 && index < mProblemSet.problems.count());
+ mProblemSet.problems.removeAt(index);
+}
+
+bool OJProblemSetModel::problemNameUsed(const QString &name)
+{
+ foreach (const POJProblem& problem, mProblemSet.problems) {
+ if (name == problem->name)
+ return true;
+ }
+ return false;
+}
+
+void OJProblemSetModel::removeAllProblems()
+{
+ clear();
+}
+
+void OJProblemSetModel::saveToFile(const QString &fileName)
+{
+ QFile file(fileName);
+ if (file.open(QFile::WriteOnly | QFile::Truncate)) {
+ QJsonObject obj;
+ obj["name"]=mProblemSet.name;
+ QJsonArray problemsArray;
+ foreach (const POJProblem& problem, mProblemSet.problems) {
+ QJsonObject problemObj;
+ problemObj["name"]=problem->name;
+ QJsonArray cases;
+ foreach (const POJProblemCase& problemCase, problem->cases) {
+ QJsonObject caseObj;
+ caseObj["name"]=problemCase->name;
+ caseObj["input"]=problemCase->input;
+ caseObj["expected"]=problemCase->expected;
+ cases.append(caseObj);
+ }
+ problemObj["cases"]=cases;
+ problemsArray.append(problemObj);
+ }
+ obj["problems"]=problemsArray;
+ QJsonDocument doc;
+ doc.setObject(obj);
+ file.write(doc.toJson());
+ file.close();
+ } else {
+ throw FileError(QObject::tr("Can't open file '%1' for read.")
+ .arg(fileName));
+ }
+}
+
+void OJProblemSetModel::loadFromFile(const QString &fileName)
+{
+ QFile file(fileName);
+ if (file.open(QFile::ReadOnly)) {
+ QByteArray content = file.readAll();
+ QJsonParseError error;
+ QJsonDocument doc(QJsonDocument::fromJson(content,&error));
+ if (error.error!=QJsonParseError::NoError) {
+ throw FileError(QObject::tr("Can't parse problem set file '%1':%2")
+ .arg(fileName)
+ .arg(error.errorString()));
+ }
+ beginResetModel();
+ QJsonObject obj = doc.object();
+ mProblemSet.name = obj["name"].toString();
+ mProblemSet.problems.clear();
+ QJsonArray problemsArray = obj["problems"].toArray();
+ foreach (const QJsonValue& problemVal, problemsArray) {
+ QJsonObject problemObj = problemVal.toObject();
+ POJProblem problem = std::make_shared();
+ problem->name = problemObj["name"].toString();
+ QJsonArray casesArray = problemObj["cases"].toArray();
+ foreach (const QJsonValue& caseVal, casesArray) {
+ QJsonObject caseObj = caseVal.toObject();
+ POJProblemCase problemCase = std::make_shared();
+ problemCase->name = caseObj["name"].toString();
+ problemCase->input = caseObj["input"].toString();
+ problemCase->expected = caseObj["expected"].toString();
+ problemCase->testState = ProblemCaseTestState::NoTested;
+ problem->cases.append(problemCase);
+ }
+ mProblemSet.problems.append(problem);
+ }
+ endResetModel();
+ } else {
+ throw FileError(QObject::tr("Can't open file '%1' for read.")
+ .arg(fileName));
+ }
+}
+
+int OJProblemSetModel::rowCount(const QModelIndex &parent) const
+{
+ return mProblemSet.problems.count();
+}
+
+QVariant OJProblemSetModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+ if (role == Qt::DisplayRole) {
+ return mProblemSet.problems[index.row()]->name;
+ }
+ return QVariant();
+}
+
+OJProblemModel::OJProblemModel(QObject *parent): QAbstractListModel(parent)
{
}
-const POJProbelm &OJProblemCaseModel::problem() const
+const POJProblem &OJProblemModel::problem() const
{
return mProblem;
}
-void OJProblemCaseModel::setProblem(const POJProbelm &newProblem)
+void OJProblemModel::setProblem(const POJProblem &newProblem)
{
- mProblem = newProblem;
+ if (newProblem!=mProblem) {
+ beginResetModel();
+ mProblem = newProblem;
+ endResetModel();
+ }
}
-int OJProblemCaseModel::rowCount(const QModelIndex &parent) const
+void OJProblemModel::addCase(POJProblemCase problemCase)
{
-
+ if (mProblem==nullptr)
+ return;
+ beginInsertRows(QModelIndex(),mProblem->cases.count(),mProblem->cases.count());
+ mProblem->cases.append(problemCase);
+ endInsertRows();
+}
+
+void OJProblemModel::removeCase(int index)
+{
+ if (mProblem==nullptr)
+ return;
+ Q_ASSERT(index >= 0 && index < mProblem->cases.count());
+ beginRemoveRows(QModelIndex(),index,index);
+ mProblem->cases.removeAt(index);
+ endRemoveRows();
+}
+
+POJProblemCase OJProblemModel::getCase(int index)
+{
+ if (mProblem==nullptr)
+ return POJProblemCase();
+ return mProblem->cases[index];
+}
+
+void OJProblemModel::clear()
+{
+ if (mProblem==nullptr)
+ return;
+ beginRemoveRows(QModelIndex(),0,mProblem->cases.count()-1);
+ mProblem->cases.clear();
+ endRemoveRows();
+}
+
+int OJProblemModel::count()
+{
+ if (mProblem == nullptr)
+ return 0;
+ return mProblem->cases.count();
+}
+
+int OJProblemModel::rowCount(const QModelIndex &) const
+{
+ if (mProblem==nullptr)
+ return 0;
+ return mProblem->cases.count();
+}
+
+QVariant OJProblemModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+ if (mProblem==nullptr)
+ return QVariant();
+ if (role == Qt::DisplayRole) {
+ return mProblem->cases[index.row()]->name;
+ }
+ return QVariant();
}
diff --git a/RedPandaIDE/widgets/ojproblemsetmodel.h b/RedPandaIDE/widgets/ojproblemsetmodel.h
index 74e1208f..ea4934c5 100644
--- a/RedPandaIDE/widgets/ojproblemsetmodel.h
+++ b/RedPandaIDE/widgets/ojproblemsetmodel.h
@@ -14,7 +14,9 @@ struct OJProblemCase {
QString name;
QString input;
QString expected;
- ProblemCaseTestState testState;
+
+ QString output; // no persistence
+ ProblemCaseTestState testState; // no persistence
};
using POJProblemCase = std::shared_ptr;
@@ -24,17 +26,27 @@ struct OJProblem {
QVector cases;
};
-using POJProbelm = std::shared_ptr;
+using POJProblem = std::shared_ptr;
-class OJProblemCaseModel: public QAbstractListModel {
+struct OJProblemSet {
+ QString name;
+ QVector problems;
+};
+
+class OJProblemModel: public QAbstractListModel {
Q_OBJECT
public:
- explicit OJProblemCaseModel(QObject *parent = nullptr);
- const POJProbelm &problem() const;
- void setProblem(const POJProbelm &newProblem);
+ explicit OJProblemModel(QObject *parent = nullptr);
+ const POJProblem &problem() const;
+ void setProblem(const POJProblem &newProblem);
+ void addCase(POJProblemCase problemCase);
+ void removeCase(int index);
+ POJProblemCase getCase(int index);
+ void clear();
+ int count();
private:
- POJProbelm mProblem;
+ POJProblem mProblem;
// QAbstractItemModel interface
public:
@@ -47,6 +59,25 @@ class OJProblemSetModel : public QAbstractListModel
Q_OBJECT
public:
explicit OJProblemSetModel(QObject *parent = nullptr);
+ void clear();
+ int count();
+ void create(const QString& name);
+ void rename(const QString& newName);
+ QString name();
+ void addProblem(POJProblem problem);
+ POJProblem problem(int index);
+ void removeProblem(int index);
+ bool problemNameUsed(const QString& name);
+ void removeAllProblems();
+ void saveToFile(const QString& fileName);
+ void loadFromFile(const QString& fileName);
+private:
+ OJProblemSet mProblemSet;
+
+ // QAbstractItemModel interface
+public:
+ int rowCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
};
#endif // OJPROBLEMSETMODEL_H