- enhancement: Show memory usage for problem cases.

This commit is contained in:
Roy Qu 2022-12-13 08:49:20 +08:00
parent 325fe71567
commit 2520ddf8f5
22 changed files with 1015 additions and 475 deletions

View File

@ -10,6 +10,8 @@ Red Panda C++ Version 2.6
- enhancement: When current file is the project's makefile, show project's compiler set in the toolbar.
- enhancement: Prevent error of "del" to stop make when rebuild project.
- enhancement: Import FPS (free problem set) files.
- enhancement: Show current problem's description in the problem list's mouse tip.
- enhancement: Show memory usage for problem cases.
Red Panda C++ Version 2.5

View File

@ -316,27 +316,40 @@ void CompilerManager::run(
}
void CompilerManager::runProblem(const QString &filename, const QString &arguments, const QString &workDir, POJProblemCase problemCase)
void CompilerManager::runProblem(const QString &filename, const QString &arguments, const QString &workDir, POJProblemCase problemCase,
const POJProblem& problem
)
{
QMutexLocker locker(&mRunnerMutex);
doRunProblem(filename, arguments, workDir, QVector<POJProblemCase> {problemCase});
doRunProblem(filename, arguments, workDir, QVector<POJProblemCase> {problemCase}, problem);
}
void CompilerManager::runProblem(const QString &filename, const QString &arguments, const QString &workDir, const QVector<POJProblemCase>& problemCases)
void CompilerManager::runProblem(const QString &filename, const QString &arguments, const QString &workDir, const QVector<POJProblemCase>& problemCases,
const POJProblem& problem
)
{
QMutexLocker locker(&mRunnerMutex);
doRunProblem(filename, arguments, workDir, problemCases);
doRunProblem(filename, arguments, workDir, problemCases, problem);
}
void CompilerManager::doRunProblem(const QString &filename, const QString &arguments, const QString &workDir, const QVector<POJProblemCase>& problemCases)
void CompilerManager::doRunProblem(const QString &filename, const QString &arguments, const QString &workDir, const QVector<POJProblemCase>& problemCases,
const POJProblem& problem)
{
if (mRunner!=nullptr) {
return;
}
OJProblemCasesRunner * execRunner = new OJProblemCasesRunner(filename,arguments,workDir,problemCases);
mRunner = execRunner;
if (pSettings->executor().enableCaseTimeout())
if (pSettings->executor().enableCaseLimit()) {
execRunner->setExecTimeout(pSettings->executor().caseTimeout());
execRunner->setMemoryLimit(pSettings->executor().caseMemoryLimit()*1024); //convert kb to bytes
}
size_t timeLimit = problem->getTimeLimit();
size_t memoryLimit = problem->getMemoryLimit();
if (timeLimit>0)
execRunner->setExecTimeout(timeLimit);
if (memoryLimit)
execRunner->setMemoryLimit(memoryLimit);
connect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
connect(mRunner, &Runner::finished, mRunner ,&Runner::deleteLater);
connect(mRunner, &Runner::finished, pMainWindow ,&MainWindow::onRunProblemFinished);

View File

@ -25,6 +25,8 @@
class Runner;
class Project;
class Compiler;
struct OJProblem;
using POJProblem = std::shared_ptr<OJProblem>;
struct OJProblemCase;
using POJProblemCase = std::shared_ptr<OJProblemCase>;
class CompilerManager : public QObject
@ -47,8 +49,13 @@ public:
const QString& arguments,
const QString& workDir,
const QStringList& extraBinDir);
void runProblem(const QString& filename, const QString& arguments, const QString& workDir, POJProblemCase problemCase);
void runProblem(const QString& filename, const QString& arguments, const QString& workDir, const QVector<POJProblemCase> &problemCases);
void runProblem(
const QString& filename, const QString& arguments, const QString& workDir, POJProblemCase problemCase,
const POJProblem& problem
);
void runProblem(const QString& filename, const QString& arguments, const QString& workDir, const QVector<POJProblemCase> &problemCases,
const POJProblem& problem
);
void stopRun();
void stopAllRunners();
void stopPausing();
@ -67,7 +74,9 @@ signals:
void signalStopAllRunners();
private slots:
void doRunProblem(const QString& filename, const QString& arguments, const QString& workDir, const QVector<POJProblemCase> &problemCases);
void doRunProblem(const QString& filename, const QString& arguments, const QString& workDir, const QVector<POJProblemCase> &problemCases,
const POJProblem& problem
);
void onRunnerTerminated();
void onRunnerPausing();
void onCompileFinished();

View File

@ -21,12 +21,16 @@
#include "../widgets/ojproblemsetmodel.h"
#include <QElapsedTimer>
#include <QProcess>
#ifdef Q_OS_WINDOWS
#include <psapi.h>
#endif
OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
const QVector<POJProblemCase>& problemCases, QObject *parent):
Runner(filename,arguments,workDir,parent),
mExecTimeout(-1)
mExecTimeout(0),
mMemoryLimit(0)
{
mProblemCases = problemCases;
mBufferSize = 8192;
@ -37,7 +41,8 @@ OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QStrin
OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
POJProblemCase problemCase, QObject *parent):
Runner(filename,arguments,workDir,parent),
mExecTimeout(-1)
mExecTimeout(0),
mMemoryLimit(0)
{
mProblemCases.append(problemCase);
mBufferSize = 8192;
@ -88,6 +93,12 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase)
problemCase->output.clear();
process.start();
process.waitForStarted(5000);
#ifdef Q_OS_WIN
HANDLE hProcess = NULL;
if (process.processId()!=0) {
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,process.processId());
}
#endif
if (process.state()==QProcess::Running) {
if (fileExists(problemCase->inputFileName))
process.write(readFileToByteArray(problemCase->inputFileName));
@ -133,8 +144,22 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase)
}
}
problemCase->runningTime=elapsedTimer.elapsed();
problemCase->runningMemory = 0;
#ifdef Q_OS_WIN
if (hProcess!=NULL) {
PROCESS_MEMORY_COUNTERS counter{0};
counter.cb = sizeof(counter);
if (GetProcessMemoryInfo(hProcess,&counter,
sizeof(counter))){
problemCase->runningMemory = counter.PeakWorkingSetSize;
}
}
#endif
if (execTimeouted) {
problemCase->output = tr("Case Timeout");
problemCase->output = tr("Time limit exceeded!");
emit resetOutput(problemCase->getId(), problemCase->output);
} else if (mMemoryLimit>0 && problemCase->runningMemory>mMemoryLimit) {
problemCase->output = tr("Memory limit exceeded!");
emit resetOutput(problemCase->getId(), problemCase->output);
} else {
if (process.state() == QProcess::ProcessState::NotRunning)
@ -142,6 +167,7 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase)
emit newOutputGetted(problemCase->getId(),QString::fromLocal8Bit(buffer));
output.append(buffer);
problemCase->output = QString::fromLocal8Bit(output);
if (errorOccurred) {
//qDebug()<<"process error:"<<process.error();
switch (process.error()) {
@ -192,6 +218,11 @@ void OJProblemCasesRunner::setExecTimeout(int newExecTimeout)
mExecTimeout = newExecTimeout;
}
void OJProblemCasesRunner::setMemoryLimit(size_t limit)
{
mMemoryLimit = limit;
}
int OJProblemCasesRunner::waitForFinishTime() const
{
return mWaitForFinishTime;

View File

@ -26,9 +26,11 @@ class OJProblemCasesRunner : public Runner
Q_OBJECT
public:
explicit OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
const QVector<POJProblemCase>& problemCases, QObject *parent = nullptr);
const QVector<POJProblemCase>& problemCases,
QObject *parent = nullptr);
explicit OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
POJProblemCase problemCase, QObject *parent = nullptr);
POJProblemCase problemCase,
QObject *parent = nullptr);
//max size of output buffer
int bufferSize() const;
void setBufferSize(int newBufferSize);
@ -43,6 +45,8 @@ public:
int execTimeout() const;
void setExecTimeout(int newExecTimeout);
void setMemoryLimit(size_t limit);
signals:
void caseStarted(const QString &caseId, int current, int total);
void caseFinished(const QString &caseId, int current, int total);
@ -60,6 +64,7 @@ private:
int mBufferSize;
int mOutputRefreshTime;
int mExecTimeout;
size_t mMemoryLimit;
};
#endif // OJPROBLEMCASESRUNNER_H

View File

@ -94,6 +94,7 @@
#ifdef Q_OS_WIN
#include <QMimeDatabase>
#include <QMimeType>
#include <QToolTip>
#include <windows.h>
#endif
@ -1933,7 +1934,8 @@ void MainWindow::runExecutable(
POJProblem problem = mOJProblemModel.problem();
if (problem) {
mCompilerManager->runProblem(exeName,params,QFileInfo(exeName).absolutePath(),
problem->cases);
problem->cases,
problem);
stretchMessagesPanel(true);
ui->tabMessages->setCurrentWidget(ui->tabProblem);
}
@ -1941,8 +1943,10 @@ void MainWindow::runExecutable(
QModelIndex index = ui->tblProblemCases->currentIndex();
if (index.isValid()) {
POJProblemCase problemCase =mOJProblemModel.getCase(index.row());
POJProblem problem = mOJProblemModel.problem();
mCompilerManager->runProblem(exeName,params,QFileInfo(exeName).absolutePath(),
problemCase);
problemCase,
problem);
stretchMessagesPanel(true);
ui->tabMessages->setCurrentWidget(ui->tabProblem);
}
@ -2675,6 +2679,20 @@ void MainWindow::buildContextMenus()
connect(mProblem_OpenSource, &QAction::triggered, this,
&MainWindow::onProblemOpenSource);
mProblem_Rename=createActionFor(
tr("Rename Problem"),
ui->lstProblemSet
);
connect(mProblem_Rename, &QAction::triggered, this,
&MainWindow::onProblemRename);
mProblem_GotoUrl=createActionFor(
tr("Goto Url"),
ui->lstProblemSet
);
connect(mProblem_GotoUrl, &QAction::triggered, this,
&MainWindow::onProblemGotoUrl);
//context menu signal for the problem list view
ui->tblProblemCases->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->tblProblemCases, &QWidget::customContextMenuRequested,
@ -3558,6 +3576,9 @@ void MainWindow::onLstProblemSetContextMenu(const QPoint &pos)
QMenu menu(this);
QModelIndex idx = ui->lstProblemSet->currentIndex();
mProblem_Properties->setEnabled(idx.isValid());
mProblem_Rename->setEnabled(idx.isValid());
menu.addAction(mProblem_Rename);
menu.addAction(mProblem_GotoUrl);
if (idx.isValid()) {
POJProblem problem = mOJProblemSetModel.problem(idx.row());
QMenu * menuSetAnswer = new QMenu(&menu);
@ -3614,7 +3635,11 @@ void MainWindow::onLstProblemSetContextMenu(const QPoint &pos)
});
menuSetAnswer->addAction(action);
menu.addMenu(menuSetAnswer);
mProblem_GotoUrl->setEnabled(!problem->url.isEmpty());
mProblem_OpenSource->setEnabled(!problem->answerProgram.isEmpty());
} else {
mProblem_GotoUrl->setEnabled(false);
mProblem_OpenSource->setEnabled(false);
}
menu.addAction(mProblem_OpenSource);
menu.addAction(mProblem_Properties);
@ -4044,15 +4069,9 @@ void MainWindow::onProblemProperties()
if (!problem)
return;
OJProblemPropertyWidget dialog;
dialog.setName(problem->name);
dialog.setUrl(problem->url);
dialog.setDescription(problem->description);
dialog.loadFromProblem(problem);
if (dialog.exec() == QDialog::Accepted) {
problem->url = dialog.url();
problem->description = dialog.description();
if (problem == mOJProblemModel.problem()) {
updateProblemTitle();
}
dialog.saveToProblem(problem);
}
}
@ -4069,6 +4088,27 @@ void MainWindow::onProblemOpenSource()
}
}
void MainWindow::onProblemRename()
{
QModelIndex idx = ui->lstProblemSet->currentIndex();
if (!idx.isValid())
return;
ui->lstProblemSet->edit(idx);
}
void MainWindow::onProblemGotoUrl()
{
QModelIndex idx = ui->lstProblemSet->currentIndex();
if (!idx.isValid())
return;
POJProblem problem=mOJProblemSetModel.problem(idx.row());
if (!problem)
return;
if (!problem->url.isEmpty()) {
QDesktopServices::openUrl(problem->url);
}
}
void MainWindow::onLableProblemSetContextMenuRequested()
{
QString newName = QInputDialog::getText(
@ -8920,12 +8960,13 @@ void MainWindow::on_btnImportFPS_clicked()
try {
QList<POJProblem> problems = importFreeProblemSet(fileName);
mOJProblemSetModel.addProblems(problems);
ui->lblProblemSet->setText(mOJProblemSetModel.name());
ui->lstProblemSet->setCurrentIndex(mOJProblemSetModel.index(0,0));
} catch (FileError& error) {
QMessageBox::critical(this,tr("Load Error"),
error.reason());
}
}
ui->lblProblemSet->setText(mOJProblemSetModel.name());
ui->lstProblemSet->setCurrentIndex(mOJProblemSetModel.index(0,0));
}

View File

@ -348,6 +348,9 @@ private slots:
void onFilesViewRename();
void onProblemProperties();
void onProblemOpenSource();
void onProblemRename();
void onProblemGotoUrl();
void onLableProblemSetContextMenuRequested();
void onBookmarkRemove();
void onBookmarkRemoveAll();
@ -881,6 +884,9 @@ private:
//action for problem set
QAction * mProblem_OpenSource;
QAction * mProblem_Properties;
QAction * mProblem_Rename;
QAction * mProblem_GotoUrl;
//action for problem
QAction * mProblem_RunCurrentCase;

View File

@ -912,7 +912,7 @@
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>2</number>
<number>6</number>
</property>
<property name="iconSize">
<size>

View File

@ -35,17 +35,27 @@ QList<POJProblem> importFreeProblemSet(const QString &filename)
currentCase->name = QObject::tr("Problem Case %1").arg(currentProblem->cases.count()+1);
} else if (currentProblem &&
xml.name()=="time_limit") {
currentEleName = xml.name().toString();
foreach (const QXmlStreamAttribute& attr, xml.attributes()) {
if (attr.name() == "unit" && attr.value()=="ms") {
currentEleName = attr.name().toString();
if (attr.name() == "unit") {
if (attr.value()=="ms")
currentProblem->timeLimitUnit = ProblemTimeLimitUnit::Milliseconds;
else if (attr.value()=="s")
currentProblem->timeLimitUnit = ProblemTimeLimitUnit::Seconds;
break;
}
}
} else if (currentProblem &&
xml.name()=="memory_limit") {
currentEleName = xml.name().toString();
foreach (const QXmlStreamAttribute& attr, xml.attributes()) {
if (attr.name() == "unit" && attr.value()=="mb") {
currentEleName = attr.name().toString();
if (attr.name() == "unit") {
if (attr.value()=="mb")
currentProblem->memoryLimitUnit = ProblemMemoryLimitUnit::MB;
else if (attr.value()=="kb")
currentProblem->memoryLimitUnit = ProblemMemoryLimitUnit::KB;
else if (attr.value()=="gb")
currentProblem->memoryLimitUnit = ProblemMemoryLimitUnit::GB;
break;
}
}
@ -70,7 +80,7 @@ QList<POJProblem> importFreeProblemSet(const QString &filename)
} else if (currentProblem && currentEleName=="hint") {
currentProblem->hint = xml.text().toString();
} else if (currentProblem && currentEleName=="title") {
currentProblem->name = xml.text().toString().trimmed();
currentProblem->name = xml.text().toString().trimmed().replace("&nbsp;"," ");
} else if (currentProblem && currentEleName=="url") {
currentProblem->url = xml.text().toString().trimmed();
} else if (currentProblem && currentEleName=="time_limit") {

View File

@ -28,3 +28,34 @@ const QString &OJProblemCase::getId() const
{
return id;
}
size_t OJProblem::getTimeLimit()
{
switch(timeLimitUnit) {
case ProblemTimeLimitUnit::Seconds:
return timeLimit*1000;
default:
return timeLimit;
}
}
size_t OJProblem::getMemoryLimit()
{
switch(memoryLimitUnit) {
case ProblemMemoryLimitUnit::KB:
return memoryLimit*1024;
case ProblemMemoryLimitUnit::MB:
return memoryLimit*1024*1024;
default:
return memoryLimit*1024*1024*1024;
}
}
OJProblem::OJProblem() :
timeLimit(0),
memoryLimit(0),
timeLimitUnit(ProblemTimeLimitUnit::Milliseconds),
memoryLimitUnit(ProblemMemoryLimitUnit::MB)
{
}

View File

@ -27,6 +27,17 @@ enum class ProblemCaseTestState {
Failed
};
enum class ProblemTimeLimitUnit {
Seconds,
Milliseconds
};
enum class ProblemMemoryLimitUnit {
KB,
MB,
GB
};
struct OJProblemCase {
QString name;
QString input;
@ -35,9 +46,10 @@ struct OJProblemCase {
QString expectedOutputFileName;
ProblemCaseTestState testState; // no persistence
QString output; // no persistence
int runningTime;
int firstDiffLine;
int outputLineCounts;
size_t runningTime; // no persistence
size_t runningMemory; // no persistence;
int firstDiffLine; // no persistence
int outputLineCounts; // no persistence
int expectedLineCounts;
OJProblemCase();
@ -56,9 +68,14 @@ struct OJProblem {
QString description;
QString hint;
QString answerProgram;
int timeLimit; // ms
int memoryLimit; // mb
size_t timeLimit;
size_t memoryLimit;
ProblemTimeLimitUnit timeLimitUnit;
ProblemMemoryLimitUnit memoryLimitUnit;
QVector<POJProblemCase> cases;
size_t getTimeLimit();
size_t getMemoryLimit();
OJProblem();
};
using POJProblem = std::shared_ptr<OJProblem>;

View File

@ -26,8 +26,6 @@
#include <QStandardPaths>
#include <QScreen>
#include <QDesktopWidget>
#include <QHash>
#include <iterator>
#ifdef Q_OS_LINUX
#include <sys/sysinfo.h>
#endif
@ -334,6 +332,11 @@ int Settings::_Base::intValue(const QString &key, int defaultValue)
return value(key,defaultValue).toInt();
}
unsigned int Settings::_Base::uintValue(const QString &key, unsigned int defaultValue)
{
return value(key,defaultValue).toUInt();
}
QStringList Settings::_Base::stringListValue(const QString &key, const QStringList &defaultValue)
{
return value(key,defaultValue).toStringList();
@ -3478,24 +3481,34 @@ void Settings::Executor::setCaseEditorFontOnlyMonospaced(bool newCaseEditorFontO
mCaseEditorFontOnlyMonospaced = newCaseEditorFontOnlyMonospaced;
}
int Settings::Executor::caseTimeout() const
size_t Settings::Executor::caseTimeout() const
{
return mCaseTimeout;
}
void Settings::Executor::setCaseTimeout(int newCaseTimeout)
void Settings::Executor::setCaseTimeout(size_t newCaseTimeout)
{
mCaseTimeout = newCaseTimeout;
}
bool Settings::Executor::enableCaseTimeout() const
size_t Settings::Executor::caseMemoryLimit() const
{
return mEnableCaseTimeout;
return mCaseMemoryLimit;
}
void Settings::Executor::setEnableCaseTimeout(bool newEnableCaseTimeout)
void Settings::Executor::setCaseMemoryLimit(size_t newCaseMemoryLimit)
{
mEnableCaseTimeout = newEnableCaseTimeout;
mCaseMemoryLimit = newCaseMemoryLimit;
}
bool Settings::Executor::enableCaseLimit() const
{
return mEnableCaseLimit;
}
void Settings::Executor::setEnableCaseLimit(bool newValue)
{
mEnableCaseLimit = newValue;
}
int Settings::Executor::caseEditorFontSize() const
@ -3555,8 +3568,9 @@ void Settings::Executor::doSave()
saveValue("case_editor_font_size",mCaseEditorFontSize);
saveValue("case_editor_font_only_monospaced",mCaseEditorFontOnlyMonospaced);
saveValue("case_timeout_ms", mCaseTimeout);
saveValue("case_memory_limit",mCaseMemoryLimit);
remove("case_timeout");
saveValue("enable_case_timeout", mEnableCaseTimeout);
saveValue("enable_case_limit", mEnableCaseLimit);
}
bool Settings::Executor::pauseConsole() const
@ -3595,8 +3609,14 @@ void Settings::Executor::doLoad()
if (case_timeout>0)
mCaseTimeout = case_timeout*1000;
else
mCaseTimeout = intValue("case_timeout_ms", 2000);
mEnableCaseTimeout = boolValue("enable_case_timeout", true);
mCaseTimeout = uintValue("case_timeout_ms", 2000); //2000ms
mCaseMemoryLimit = uintValue("case_memory_limit",0); // kb
mEnableCaseLimit = boolValue("enable_case_limit", true);
//compatibility
if (boolValue("enable_time_limit", true)) {
mEnableCaseLimit=true;
}
}

View File

@ -69,6 +69,7 @@ private:
bool boolValue(const QString &key, bool defaultValue);
QSize sizeValue(const QString &key);
int intValue(const QString &key, int defaultValue);
unsigned int uintValue(const QString &key, unsigned int defaultValue);
QStringList stringListValue(const QString &key, const QStringList& defaultValue=QStringList());
QSet<QString> stringSetValue(const QString &key);
QColor colorValue(const QString &key, const QColor& defaultValue);
@ -874,11 +875,14 @@ public:
bool caseEditorFontOnlyMonospaced() const;
void setCaseEditorFontOnlyMonospaced(bool newCaseEditorFontOnlyMonospaced);
bool enableCaseTimeout() const;
void setEnableCaseTimeout(bool newEnableCaseTimeout);
bool enableCaseLimit() const;
void setEnableCaseLimit(bool newValue);
int caseTimeout() const;
void setCaseTimeout(int newCaseTimeout);
size_t caseTimeout() const;
void setCaseTimeout(size_t newCaseTimeout);
size_t caseMemoryLimit() const;
void setCaseMemoryLimit(size_t newCaseMemoryLimit);
private:
// general
@ -897,8 +901,9 @@ public:
QString mCaseEditorFontName;
int mCaseEditorFontSize;
bool mCaseEditorFontOnlyMonospaced;
bool mEnableCaseTimeout;
int mCaseTimeout;
bool mEnableCaseLimit;
size_t mCaseTimeout; //ms
size_t mCaseMemoryLimit; //kb
protected:
void doSave() override;

View File

@ -41,9 +41,10 @@ void ExecutorProblemSetWidget::doLoad()
ui->cbFont->setCurrentFont(QFont(pSettings->executor().caseEditorFontName()));
ui->spinFontSize->setValue(pSettings->executor().caseEditorFontSize());
ui->chkOnlyMonospaced->setChecked(pSettings->executor().caseEditorFontOnlyMonospaced());
ui->grpEnableTimeout->setChecked(pSettings->executor().enableCaseTimeout());
ui->grpEnableTimeout->setChecked(pSettings->executor().enableCaseLimit());
ui->spinCaseTimeout->setValue(pSettings->executor().caseTimeout());
ui->spinMemoryLimit->setValue(pSettings->executor().caseMemoryLimit());
}
void ExecutorProblemSetWidget::doSave()
@ -55,8 +56,10 @@ void ExecutorProblemSetWidget::doSave()
pSettings->executor().setCaseEditorFontName(ui->cbFont->currentFont().family());
pSettings->executor().setCaseEditorFontOnlyMonospaced(ui->chkOnlyMonospaced->isChecked());
pSettings->executor().setCaseEditorFontSize(ui->spinFontSize->value());
pSettings->executor().setEnableCaseTimeout(ui->grpEnableTimeout->isChecked());
pSettings->executor().setEnableCaseLimit(ui->grpEnableTimeout->isChecked());
pSettings->executor().setCaseTimeout(ui->spinCaseTimeout->value());
pSettings->executor().setCaseMemoryLimit(ui->spinMemoryLimit->value());
pSettings->executor().save();
pMainWindow->applySettings();
}

View File

@ -75,13 +75,20 @@
<item>
<widget class="QGroupBox" name="grpEnableTimeout">
<property name="title">
<string>Timeout for Case Valdation</string>
<string>Case Valdation Limit</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Time Limit</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinCaseTimeout">
<property name="specialValueText">
<string/>
@ -90,7 +97,7 @@
<string>ms</string>
</property>
<property name="minimum">
<number>100</number>
<number>0</number>
</property>
<property name="maximum">
<number>1000000</number>
@ -100,7 +107,7 @@
</property>
</widget>
</item>
<item>
<item row="0" column="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -113,6 +120,23 @@
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Memory Limit</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinMemoryLimit">
<property name="suffix">
<string>kb</string>
</property>
<property name="maximum">
<number>999999</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -1867,7 +1867,7 @@
</message>
<message>
<source>Timeout for Case Valdation</source>
<translation>Tempo limite para validação de caso</translation>
<translation type="vanished">Tempo limite para validação de caso</translation>
</message>
<message>
<source>Case Editor Font</source>
@ -1889,6 +1889,22 @@
<source>ms</source>
<translation>ms</translation>
</message>
<message>
<source>Case Valdation Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Time Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Memory Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>kb</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FileAssociationModel</name>
@ -4737,7 +4753,15 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>FPS Problem Set Files (*.fps)</source>
<source>Rename Problem</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Goto Url</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>FPS Problem Set Files (*.fps;*.xml)</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -4932,7 +4956,7 @@
<name>OJProblemCasesRunner</name>
<message>
<source>Case Timeout</source>
<translation>Tempo esgotado para o caso</translation>
<translation type="vanished">Tempo esgotado para o caso</translation>
</message>
<message>
<source>The runner process &apos;%1&apos; failed to start.</source>
@ -4950,6 +4974,14 @@
<source>An error occurred when attempting to read from the runner process.</source>
<translation>Falhar ao tentar ler a execução do processo.</translation>
</message>
<message>
<source>Time limit exceeded!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Memory limit exceeded!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OJProblemModel</name>
@ -4961,6 +4993,10 @@
<source>Time(ms)</source>
<translation>Tempo(ms)</translation>
</message>
<message>
<source>Memory(kb)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OJProblemPropertyWidget</name>
@ -4988,6 +5024,34 @@
<source>Cancel</source>
<translation>Cancelar</translation>
</message>
<message>
<source>Time Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Memory Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>sec</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>ms</source>
<translation type="unfinished">ms</translation>
</message>
<message>
<source>KB</source>
<translation type="unfinished">KB</translation>
</message>
<message>
<source>MB</source>
<translation type="unfinished">MB</translation>
</message>
<message>
<source>GB</source>
<translation type="unfinished">GB</translation>
</message>
</context>
<context>
<name>Project</name>

File diff suppressed because it is too large Load Diff

View File

@ -1754,10 +1754,6 @@
<source>Ignore spaces when validating problem cases</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Timeout for Case Valdation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Case Editor Font</source>
<translation type="unfinished"></translation>
@ -1778,6 +1774,22 @@
<source>ms</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Case Valdation Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Time Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Memory Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>kb</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FileAssociationModel</name>
@ -4578,7 +4590,15 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>FPS Problem Set Files (*.fps)</source>
<source>Rename Problem</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Goto Url</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>FPS Problem Set Files (*.fps;*.xml)</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -4759,10 +4779,6 @@
</context>
<context>
<name>OJProblemCasesRunner</name>
<message>
<source>Case Timeout</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The runner process &apos;%1&apos; failed to start.</source>
<translation type="unfinished"></translation>
@ -4779,6 +4795,14 @@
<source>An error occurred when attempting to read from the runner process.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Time limit exceeded!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Memory limit exceeded!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OJProblemModel</name>
@ -4790,6 +4814,10 @@
<source>Time(ms)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Memory(kb)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OJProblemPropertyWidget</name>
@ -4817,6 +4845,34 @@
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Time Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Memory Limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>sec</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>ms</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>KB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MB</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>GB</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Project</name>

View File

@ -16,12 +16,22 @@
*/
#include "ojproblempropertywidget.h"
#include "ui_ojproblempropertywidget.h"
#include "../problems/ojproblemset.h"
OJProblemPropertyWidget::OJProblemPropertyWidget(QWidget *parent) :
QDialog(parent),
ui(new Ui::OJProblemPropertyWidget)
{
ui->setupUi(this);
QFont f = ui->lbName->font();
f.setPixelSize(f.pixelSize()+2);
f.setBold(true);
ui->lbName->setFont(f);
ui->cbTimeLimitUnit->addItem(tr("sec"));
ui->cbTimeLimitUnit->addItem(tr("ms"));
ui->cbMemoryLimitUnit->addItem(tr("KB"));
ui->cbMemoryLimitUnit->addItem(tr("MB"));
ui->cbMemoryLimitUnit->addItem(tr("GB"));
}
OJProblemPropertyWidget::~OJProblemPropertyWidget()
@ -29,38 +39,55 @@ OJProblemPropertyWidget::~OJProblemPropertyWidget()
delete ui;
}
void OJProblemPropertyWidget::setName(const QString &name)
void OJProblemPropertyWidget::loadFromProblem(POJProblem problem)
{
QFont f = ui->lbName->font();
f.setPixelSize(f.pixelSize()+2);
f.setBold(true);
ui->lbName->setFont(f);
ui->lbName->setText(name);
if (!problem)
return;
ui->lbName->setText(problem->name);
ui->txtURL->setText(problem->url);
ui->txtDescription->setHtml(problem->description);
ui->spinMemoryLimit->setValue(problem->memoryLimit);
ui->spinTimeLimit->setValue(problem->timeLimit);
switch(problem->timeLimitUnit) {
case ProblemTimeLimitUnit::Seconds:
ui->cbTimeLimitUnit->setCurrentText(tr("sec"));
break;
case ProblemTimeLimitUnit::Milliseconds:
ui->cbTimeLimitUnit->setCurrentText(tr("ms"));
break;
}
switch(problem->memoryLimitUnit) {
case ProblemMemoryLimitUnit::KB:
ui->cbTimeLimitUnit->setCurrentText(tr("KB"));
break;
case ProblemMemoryLimitUnit::MB:
ui->cbTimeLimitUnit->setCurrentText(tr("MB"));
break;
case ProblemMemoryLimitUnit::GB:
ui->cbTimeLimitUnit->setCurrentText(tr("GB"));
break;
}
}
void OJProblemPropertyWidget::setUrl(const QString &url)
void OJProblemPropertyWidget::saveToProblem(POJProblem problem)
{
ui->txtURL->setText(url);
}
void OJProblemPropertyWidget::setDescription(const QString &description)
{
ui->txtDescription->setHtml(description);
}
QString OJProblemPropertyWidget::name()
{
return ui->lbName->text();
}
QString OJProblemPropertyWidget::url()
{
return ui->txtURL->text();
}
QString OJProblemPropertyWidget::description()
{
return ui->txtDescription->toHtml();
if (!problem)
return;
problem->name = ui->lbName->text();
problem->url = ui->txtURL->text();
problem->description = ui->txtDescription->toHtml();
problem->memoryLimit = ui->spinMemoryLimit->value();
problem->timeLimit = ui->spinTimeLimit->value();
if (ui->cbTimeLimitUnit->currentText()=="sec")
problem->timeLimitUnit = ProblemTimeLimitUnit::Seconds;
else
problem->timeLimitUnit = ProblemTimeLimitUnit::Milliseconds;
if (ui->cbTimeLimitUnit->currentText()=="KB")
problem->memoryLimitUnit = ProblemMemoryLimitUnit::KB;
else if (ui->cbTimeLimitUnit->currentText()=="MB")
problem->memoryLimitUnit = ProblemMemoryLimitUnit::MB;
else
problem->memoryLimitUnit = ProblemMemoryLimitUnit::GB;
}
void OJProblemPropertyWidget::on_btnOk_clicked()

View File

@ -18,11 +18,14 @@
#define OJPROBLEMPROPERTYWIDGET_H
#include <QDialog>
#include <memory>
namespace Ui {
class OJProblemPropertyWidget;
}
class OJProblem;
using POJProblem = std::shared_ptr<OJProblem>;
class OJProblemPropertyWidget : public QDialog
{
Q_OBJECT
@ -30,12 +33,8 @@ class OJProblemPropertyWidget : public QDialog
public:
explicit OJProblemPropertyWidget(QWidget *parent = nullptr);
~OJProblemPropertyWidget();
void setName(const QString& name);
void setUrl(const QString& url);
void setDescription(const QString& description);
QString name();
QString url();
QString description();
void loadFromProblem(POJProblem problem);
void saveToProblem(POJProblem problem);
private slots:
void on_btnOk_clicked();

View File

@ -6,39 +6,107 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<width>460</width>
<height>364</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0" columnminimumwidth="0,0">
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>URL</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<item row="4" column="1">
<widget class="QLineEdit" name="txtURL"/>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="lbName">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="txtURL"/>
</item>
<item row="2" column="0" colspan="3">
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<item row="2" column="0" colspan="2">
<widget class="QTextEdit" name="txtDescription"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="2" column="2">
<widget class="QComboBox" name="cbMemoryLimitUnit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Time Limit</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Memory Limit</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinTimeLimit">
<property name="maximum">
<number>9999999</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spinMemoryLimit">
<property name="maximum">
<number>9999999</number>
</property>
</widget>
</item>
<item row="1" column="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="cbTimeLimitUnit"/>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
@ -83,9 +151,6 @@
</layout>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QTextEdit" name="txtDescription"/>
</item>
</layout>
</widget>
<resources/>

View File

@ -125,6 +125,10 @@ void OJProblemSetModel::saveToFile(const QString &fileName, int currentIndex)
problemObj["name"]=problem->name;
problemObj["url"]=problem->url;
problemObj["description"]=problem->description;
problemObj["time_limit"]=(int)problem->timeLimit;
problemObj["memory_limit"]=(int)problem->memoryLimit;
problemObj["time_limit_unit"]=(int)problem->timeLimitUnit;
problemObj["memory_limit_unit"]=(int)problem->memoryLimitUnit;
if (fileExists(problem->answerProgram))
problemObj["answer_program"] = problem->answerProgram;
QJsonArray cases;
@ -184,6 +188,11 @@ void OJProblemSetModel::loadFromFile(const QString &fileName, int& currentIndex)
POJProblem problem = std::make_shared<OJProblem>();
problem->name = problemObj["name"].toString();
problem->url = problemObj["url"].toString();
problem->timeLimit = problemObj["time_limit"].toInt();
problem->memoryLimit = problemObj["memory_limit"].toInt();
problem->timeLimitUnit = (ProblemTimeLimitUnit)problemObj["time_limit_unit"].toInt();
problem->memoryLimitUnit = (ProblemMemoryLimitUnit)problemObj["memory_limit_unit"].toInt();
problem->description = problemObj["description"].toString();
problem->answerProgram = problemObj["answer_program"].toString();
QJsonArray casesArray = problemObj["cases"].toArray();
@ -252,6 +261,15 @@ QVariant OJProblemSetModel::data(const QModelIndex &index, int role) const
return QVariant();
if (role == Qt::DisplayRole || role == Qt::EditRole) {
return mProblemSet.problems[index.row()]->name;
} else if (role == Qt::ToolTipRole) {
POJProblem problem = mProblemSet.problems[index.row()];
QString s;
s=QString("<h3>%1</h3>").arg(problem->name);
if (!problem->description.isEmpty())
s+=problem->description;
return s;
}
return QVariant();
}
@ -479,6 +497,16 @@ QVariant OJProblemModel::data(const QModelIndex &index, int role) const
return "";
}
break;
case 2:
if (role == Qt::DisplayRole) {
POJProblemCase problemCase = mProblem->cases[index.row()];
if (problemCase->testState == ProblemCaseTestState::Passed
|| problemCase->testState == ProblemCaseTestState::Failed)
return problemCase->runningMemory/1024;
else
return "";
}
break;
}
return QVariant();
@ -515,7 +543,7 @@ Qt::ItemFlags OJProblemModel::flags(const QModelIndex &idx) const
int OJProblemModel::columnCount(const QModelIndex &/*parent*/) const
{
return 2;
return 3;
}
QVariant OJProblemModel::headerData(int section, Qt::Orientation orientation, int role) const
@ -526,6 +554,8 @@ QVariant OJProblemModel::headerData(int section, Qt::Orientation orientation, in
return tr("Name");
case 1:
return tr("Time(ms)");
case 2:
return tr("Memory(kb)");
}
}
return QVariant();