work save: problem set ui done

This commit is contained in:
royqh1979 2021-11-01 00:40:11 +08:00
parent bb10a83942
commit 46b95c03ae
7 changed files with 1097 additions and 525 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -205,6 +205,18 @@ MainWindow::MainWindow(QWidget *parent)
ui->searchView,&QTreeView::expandAll); ui->searchView,&QTreeView::expandAll);
ui->replacePanel->setVisible(false); 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 //files view
ui->treeFiles->setModel(&mFileSystemModel); ui->treeFiles->setModel(&mFileSystemModel);
mFileSystemModel.setReadOnly(true); mFileSystemModel.setReadOnly(true);
@ -2503,6 +2515,63 @@ void MainWindow::onFilesViewContextMenu(const QPoint &pos)
menu.exec(ui->treeFiles->mapToGlobal(pos)); menu.exec(ui->treeFiles->mapToGlobal(pos));
} }
void MainWindow::onProblemSetIndexChanged(const QModelIndex &current, 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 &current, 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() void MainWindow::onShowInsertCodeSnippetMenu()
{ {
mMenuInsertCodeSnippet->clear(); 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<OJProblem>();
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<OJProblemCase>();
problemCase->name = name;
problemCase->testState = ProblemCaseTestState::NoTested;
mOJProblemModel.addCase(problemCase);
ui->lstProblemCases->setCurrentIndex(mOJProblemModel.index(mOJProblemModel.count()-1));
}

View File

@ -18,6 +18,7 @@
#include "toolsmanager.h" #include "toolsmanager.h"
#include "widgets/labelwithmenu.h" #include "widgets/labelwithmenu.h"
#include "widgets/bookmarkmodel.h" #include "widgets/bookmarkmodel.h"
#include "widgets/ojproblemsetmodel.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -211,6 +212,8 @@ private slots:
void onDebugConsoleContextMenu(const QPoint& pos); void onDebugConsoleContextMenu(const QPoint& pos);
void onFileEncodingContextMenu(const QPoint& pos); void onFileEncodingContextMenu(const QPoint& pos);
void onFilesViewContextMenu(const QPoint& pos); void onFilesViewContextMenu(const QPoint& pos);
void onProblemSetIndexChanged(const QModelIndex &current, const QModelIndex &previous);
void onProblemCaseIndexChanged(const QModelIndex &current, const QModelIndex &previous);
void onShowInsertCodeSnippetMenu(); void onShowInsertCodeSnippetMenu();
@ -433,6 +436,18 @@ private slots:
void on_actionRun_Parameters_triggered(); 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: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
EditorList *mEditorList; EditorList *mEditorList;
@ -473,6 +488,9 @@ private:
PTodoParser mTodoParser; PTodoParser mTodoParser;
PToolsManager mToolsManager; PToolsManager mToolsManager;
QFileSystemModel mFileSystemModel; QFileSystemModel mFileSystemModel;
OJProblemSetModel mOJProblemSetModel;
OJProblemModel mOJProblemModel;
int mOJProblemSetNameCounter;
bool mCheckSyntaxInBack; bool mCheckSyntaxInBack;
bool mOpenClosingBottomPanel; bool mOpenClosingBottomPanel;

View File

@ -306,8 +306,11 @@
</property> </property>
<item> <item>
<widget class="QToolButton" name="btnNewProblemSet"> <widget class="QToolButton" name="btnNewProblemSet">
<property name="toolTip">
<string>New Problem Set</string>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>New Problem Set</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -317,8 +320,11 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="btnAddProblem"> <widget class="QToolButton" name="btnAddProblem">
<property name="toolTip">
<string>Add Problem</string>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>Add Problem</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -328,8 +334,11 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="btnRemoveProblem"> <widget class="QToolButton" name="btnRemoveProblem">
<property name="toolTip">
<string>Remove Problem</string>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>Remove Problem</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -339,8 +348,11 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="btnSaveProblemSet"> <widget class="QToolButton" name="btnSaveProblemSet">
<property name="toolTip">
<string>Save Problem Set</string>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>Save Problem Set</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -350,8 +362,11 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="btnLoadProblemSet"> <widget class="QToolButton" name="btnLoadProblemSet">
<property name="toolTip">
<string>Load Problem Set</string>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>Load Problem Set</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -1099,7 +1114,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="lblProblem">
<property name="text"> <property name="text">
<string>Problem</string> <string>Problem</string>
</property> </property>
@ -1146,8 +1161,11 @@
</property> </property>
<item> <item>
<widget class="QToolButton" name="btnAddProblemCase"> <widget class="QToolButton" name="btnAddProblemCase">
<property name="toolTip">
<string>Add Probem Case</string>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>Add Probem Case</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -1157,8 +1175,11 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="btnRemoveProblemCase"> <widget class="QToolButton" name="btnRemoveProblemCase">
<property name="toolTip">
<string>Remove Problem Case</string>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>Remove Problem Case</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -1166,6 +1187,41 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnRunCurrentProblemCase">
<property name="toolTip">
<string>Run Current Case</string>
</property>
<property name="text">
<string>Run Current Case</string>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/069-run.png</normaloff>:/icons/images/newlook24/069-run.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnRunAllProblemCases">
<property name="toolTip">
<string>Run All Cases</string>
</property>
<property name="text">
<string>Run All Cases</string>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/021-Debug-Continue.png</normaloff>:/icons/images/newlook24/021-Debug-Continue.png</iconset>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_4"> <spacer name="horizontalSpacer_4">
<property name="orientation"> <property name="orientation">

View File

@ -1,26 +1,240 @@
#include "ojproblemsetmodel.h" #include "ojproblemsetmodel.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include "../utils.h"
OJProblemSetModel::OJProblemSetModel(QObject *parent) : QAbstractListModel(parent) 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<OJProblem>();
problem->name = problemObj["name"].toString();
QJsonArray casesArray = problemObj["cases"].toArray();
foreach (const QJsonValue& caseVal, casesArray) {
QJsonObject caseObj = caseVal.toObject();
POJProblemCase problemCase = std::make_shared<OJProblemCase>();
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; 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();
} }

View File

@ -14,7 +14,9 @@ struct OJProblemCase {
QString name; QString name;
QString input; QString input;
QString expected; QString expected;
ProblemCaseTestState testState;
QString output; // no persistence
ProblemCaseTestState testState; // no persistence
}; };
using POJProblemCase = std::shared_ptr<OJProblemCase>; using POJProblemCase = std::shared_ptr<OJProblemCase>;
@ -24,17 +26,27 @@ struct OJProblem {
QVector<POJProblemCase> cases; QVector<POJProblemCase> cases;
}; };
using POJProbelm = std::shared_ptr<OJProblem>; using POJProblem = std::shared_ptr<OJProblem>;
class OJProblemCaseModel: public QAbstractListModel { struct OJProblemSet {
QString name;
QVector<POJProblem> problems;
};
class OJProblemModel: public QAbstractListModel {
Q_OBJECT Q_OBJECT
public: public:
explicit OJProblemCaseModel(QObject *parent = nullptr); explicit OJProblemModel(QObject *parent = nullptr);
const POJProbelm &problem() const; const POJProblem &problem() const;
void setProblem(const POJProbelm &newProblem); void setProblem(const POJProblem &newProblem);
void addCase(POJProblemCase problemCase);
void removeCase(int index);
POJProblemCase getCase(int index);
void clear();
int count();
private: private:
POJProbelm mProblem; POJProblem mProblem;
// QAbstractItemModel interface // QAbstractItemModel interface
public: public:
@ -47,6 +59,25 @@ class OJProblemSetModel : public QAbstractListModel
Q_OBJECT Q_OBJECT
public: public:
explicit OJProblemSetModel(QObject *parent = nullptr); 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 #endif // OJPROBLEMSETMODEL_H