- enhancement: Export FPS (free problem set) files.

This commit is contained in:
Roy Qu 2022-12-16 15:54:02 +08:00
parent f4ca71803f
commit d60febaac8
10 changed files with 749 additions and 551 deletions

View File

@ -1713,6 +1713,7 @@ void MainWindow::updateActionIcons()
pIconsManager->setIcon(ui->btnSaveProblemSet, IconsManager::ACTION_FILE_SAVE_AS);
pIconsManager->setIcon(ui->btnLoadProblemSet, IconsManager::ACTION_FILE_OPEN_FOLDER);
pIconsManager->setIcon(ui->btnImportFPS, IconsManager::ACTION_CODE_BACK);
pIconsManager->setIcon(ui->btnExportFPS, IconsManager::ACTION_CODE_FORWARD);
pIconsManager->setIcon(ui->btnAddProblemCase, IconsManager::ACTION_MISC_ADD);
pIconsManager->setIcon(ui->btnRemoveProblemCase, IconsManager::ACTION_MISC_REMOVE);
@ -8977,3 +8978,21 @@ void MainWindow::on_actionTrim_trailing_spaces_triggered()
}
}
void MainWindow::on_btnExportFPS_clicked()
{
QString fileName = QFileDialog::getSaveFileName(
this,
tr("Export FPS Problem Set"),
QString(),
tr("FPS Problem Set Files (*.fps)"));
if (!fileName.isEmpty()) {
try {
exportFreeProblemSet(mOJProblemSetModel.problems(),fileName);
} catch (FileError& error) {
QMessageBox::critical(this,tr("Export Error"),
error.reason());
}
}
}

View File

@ -755,6 +755,8 @@ private slots:
void on_actionTrim_trailing_spaces_triggered();
void on_btnExportFPS_clicked();
private:
Ui::MainWindow *ui;
EditorList *mEditorList;

View File

@ -120,7 +120,7 @@
<x>0</x>
<y>0</y>
<width>955</width>
<height>29</height>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -850,6 +850,17 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnExportFPS">
<property name="text">
<string>Export FPS Problem Set</string>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/052-next.png</normaloff>:/icons/images/newlook24/052-next.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">

View File

@ -1,5 +1,5 @@
#include "freeprojectsetformat.h"
#include "../utils.h"
#include <QFile>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
@ -8,8 +8,9 @@ QList<POJProblem> importFreeProblemSet(const QString &filename)
{
QFile file(filename);
QList<POJProblem> problems;
if (!file.open(QFile::ReadOnly))
return problems;
if (!file.open(QFile::ReadOnly)) {
throw FileError(QObject::tr("Can't open file \"%1\" for read.").arg(filename));
}
QXmlStreamReader xml;
xml.setDevice(&file);
POJProblem currentProblem;
@ -97,10 +98,93 @@ QList<POJProblem> importFreeProblemSet(const QString &filename)
void exportFreeProblemSet(const QList<POJProblem> &problems, const QString &filename)
{
QFile file(filename);
if (!file.open(QFile::WriteOnly|QFile::Truncate))
return;
if (!file.open(QFile::WriteOnly|QFile::Truncate)) {
throw FileError(QObject::tr("Can't open file \"%1\" for write.").arg(filename));
}
QXmlStreamWriter writer(&file);
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeEndDocument();
//fps
{
writer.writeStartElement("fps");
writer.writeAttribute("version","1.4");
writer.writeAttribute("url","https://github.com/zhblue/freeproblemset/");
{
writer.writeStartElement("generator");
writer.writeAttribute("name","RedPanda-C++");
writer.writeAttribute("url","https://royqh1979.gitee.io/redpandacpp/");
writer.writeEndElement(); // generator
}
foreach(const POJProblem& problem,problems) {
writer.writeStartElement("item");
{
writer.writeStartElement("title");
writer.writeCDATA(problem->name);
writer.writeEndElement(); //title
}
{
writer.writeStartElement("url");
writer.writeCDATA(problem->url);
writer.writeEndElement();//url
}
{
QString unit;
switch(problem->timeLimitUnit) {
case ProblemTimeLimitUnit::Milliseconds:
unit = "ms";
break;
case ProblemTimeLimitUnit::Seconds:
unit = "s";
break;
}
writer.writeStartElement("time_limit");
writer.writeAttribute("unit",unit);
writer.writeCDATA(QString("%1").arg(problem->timeLimit));
writer.writeEndElement(); //time_limit
}
{
QString unit;
switch(problem->memoryLimitUnit) {
case ProblemMemoryLimitUnit::MB:
unit = "mb";
break;
case ProblemMemoryLimitUnit::KB:
unit = "kb";
break;
case ProblemMemoryLimitUnit::GB:
unit = "gb";
break;
}
writer.writeStartElement("memory_limit");
writer.writeAttribute("unit",unit);
writer.writeCDATA(QString("%1").arg(problem->memoryLimit));
writer.writeEndElement(); //memory_limit
}
{
writer.writeStartElement("description");
writer.writeCDATA(problem->description);
writer.writeEndElement(); //description
}
foreach(const POJProblemCase& pCase, problem->cases) {
writer.writeStartElement("test_input");
writer.writeAttribute("name",pCase->name);
writer.writeCDATA(pCase->input);
writer.writeEndElement(); //test_input
writer.writeStartElement("test_output");
writer.writeCDATA(pCase->expected);
writer.writeEndElement(); //test_output
}
{
writer.writeStartElement("hint");
writer.writeCDATA(problem->hint);
writer.writeEndElement(); //hint
}
writer.writeEndElement(); //item
}
writer.writeEndElement(); //fps
}
writer.writeEndDocument();
if (writer.hasError()) {
throw FileError(QObject::tr("Error when writing file \"%1\".").arg(filename));
}
}

View File

@ -19,6 +19,7 @@
#include <QString>
#include <memory>
#include <QVector>
#include <QList>
enum class ProblemCaseTestState {
NotTested,
@ -82,7 +83,7 @@ using POJProblem = std::shared_ptr<OJProblem>;
struct OJProblemSet {
QString name;
QVector<POJProblem> problems;
QList<POJProblem> problems;
QString exportFilename;
};

View File

@ -4860,6 +4860,18 @@
<source>Trim trailing spaces</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Export FPS Problem Set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>FPS Problem Set Files (*.fps)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Export Error</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NewClassDialog</name>
@ -6347,6 +6359,18 @@
<source>Problem Case %1</source>
<translation type="unfinished">Caso do problema %1</translation>
</message>
<message>
<source>Can&apos;t open file &quot;%1&quot; for read.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Can&apos;t open file &quot;%1&quot; for write.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Error when writing file &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RegisterModel</name>

File diff suppressed because it is too large Load Diff

View File

@ -4677,6 +4677,18 @@
<source>Trim trailing spaces</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Export FPS Problem Set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>FPS Problem Set Files (*.fps)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Export Error</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NewClassDialog</name>
@ -6004,6 +6016,18 @@
<source>Problem Case %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Can&apos;t open file &quot;%1&quot; for read.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Can&apos;t open file &quot;%1&quot; for write.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Error when writing file &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RegisterModel</name>

View File

@ -85,7 +85,12 @@ void OJProblemSetModel::addProblems(const QList<POJProblem> &problems)
endInsertRows();
}
POJProblem OJProblemSetModel::problem(int index)
const QList<POJProblem> &OJProblemSetModel::problems() const
{
return mProblemSet.problems;
}
POJProblem OJProblemSetModel::problem(int index) const
{
return mProblemSet.problems[index];
}

View File

@ -82,7 +82,8 @@ public:
QString exportFilename() const;
void addProblem(const POJProblem& problem);
void addProblems(const QList<POJProblem> &problems);
POJProblem problem(int index);
const QList<POJProblem> &problems() const;
POJProblem problem(int index) const;
void removeProblem(int index);
bool problemNameUsed(const QString& name);
void removeAllProblems();