diff --git a/addcompilerwizard.cpp b/addcompilerwizard.cpp index 96e81ff..36c4b13 100644 --- a/addcompilerwizard.cpp +++ b/addcompilerwizard.cpp @@ -1,503 +1,507 @@ -#include "addcompilerwizard.h" -#include "ui_addcompilerwizard.h" -#include "compiler.h" - -AddCompilerWizard::AddCompilerWizard(QWidget *parent) : - QWizard(parent), - ui(new Ui::AddCompilerWizard) -{ - ui->setupUi(this); - - ui->sourceFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->sourceFileExtensions)); - ui->bytecodeFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->bytecodeFileExtensions)); - ui->javaMemoryLimit->setValidator(new QIntValidator(128, 2048, ui->javaMemoryLimit)); - -#ifdef Q_OS_LINUX - if (QFileInfo("/usr/bin/gcc").exists()) - ui->gccPath->setText("/usr/bin/gcc"); - if (QFileInfo("/usr/bin/g++").exists()) - ui->gppPath->setText("/usr/bin/g++"); - if (QFileInfo("/usr/bin/fpc").exists()) - ui->fpcPath->setText("/usr/bin/fpc"); - if (QFileInfo("/usr/bin/python").exists()) - ui->pythonPath->setText("/usr/bin/python"); -#endif - - connect(ui->typeSelect, SIGNAL(currentIndexChanged(int)), - this, SLOT(compilerTypeChanged())); - connect(ui->compilerSelectButton, SIGNAL(clicked()), - this, SLOT(selectCompilerLocation())); - connect(ui->interpreterSelectButton, SIGNAL(clicked()), - this, SLOT(selectInterpreterLocation())); - connect(ui->gccSelectButton, SIGNAL(clicked()), - this, SLOT(selectGccPath())); - connect(ui->gppSelectButton, SIGNAL(clicked()), - this, SLOT(selectGppPath())); - connect(ui->fpcSelectButton, SIGNAL(clicked()), - this, SLOT(selectFpcPath())); - connect(ui->fbcSelectButton, SIGNAL(clicked()), - this, SLOT(selectFbcPath())); - connect(ui->javacSelectButton, SIGNAL(clicked()), - this, SLOT(selectJavacPath())); - connect(ui->javaSelectButton, SIGNAL(clicked()), - this, SLOT(selectJavaPath())); - connect(ui->pythonSelectButton, SIGNAL(clicked()), - this, SLOT(selectPythonPath())); -} - -AddCompilerWizard::~AddCompilerWizard() -{ - delete ui; -} - -const QList& AddCompilerWizard::getCompilerList() const -{ - return compilerList; -} - -int AddCompilerWizard::nextId() const -{ - if (currentId() == 0) { - if (ui->customRadioButton->isChecked()) - return 1; - else - return 2; - } else - if (currentId() == 3) return -1; else return 3; -} - -bool AddCompilerWizard::validateCurrentPage() -{ - if (currentId() == 1) { - if (ui->compilerName->text().isEmpty()) { - ui->compilerName->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty compiler name!"), QMessageBox::Close); - return false; - } - if (ui->compilerLocation->isEnabled() && ui->compilerLocation->text().isEmpty()) { - ui->compilerLocation->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty compiler location!"), QMessageBox::Close); - return false; - } - if (ui->interpreterLocation->isEnabled() && ui->interpreterLocation->text().isEmpty()) { - ui->interpreterLocation->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty interpreter location!"), QMessageBox::Close); - return false; - } - if (ui->sourceFileExtensions->text().isEmpty()) { - ui->sourceFileExtensions->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty source file extensions!"), QMessageBox::Close); - return false; - } - if (ui->bytecodeFileExtensions->isEnabled() && ui->bytecodeFileExtensions->text().isEmpty()) { - ui->bytecodeFileExtensions->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty byte-code file extensions!"), QMessageBox::Close); - return false; - } - - QString text; - text += tr("[Custom Compiler]") + "\n"; - text += tr("Compiler Name: ") + ui->compilerName->text() + "\n"; - text += tr("Compiler Type: ") + ui->typeSelect->currentText() + "\n"; - if (ui->compilerLocation->isEnabled()) - text += tr("Compiler\'s Location: ") + ui->compilerLocation->text() + "\n"; - if (ui->interpreterLocation->isEnabled()) - text += tr("Interpreter\'s Location: ") + ui->interpreterLocation->text() + "\n"; - text += tr("Source File Extensions: ") + ui->sourceFileExtensions->text() + "\n"; - if (ui->bytecodeFileExtensions->isEnabled()) - text += tr("Byte-code File Extensions: ") + ui->bytecodeFileExtensions->text() + "\n"; - if (ui->defaultCompilerArguments->isEnabled()) - text += tr("Default Compiler\'s Arguments: ") + ui->defaultCompilerArguments->text() + "\n"; - if (ui->defaultInterpreterArguments->isEnabled()) - text += tr("Default Interpreter\'s Arguments: ") + ui->defaultInterpreterArguments->text() + "\n"; - ui->logViewer->setPlainText(text); - } - - if (currentId() == 2) { - if (ui->gccGroupBox->isEnabled() && ui->gccPath->text().isEmpty()) { - ui->gccPath->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty gcc path!"), QMessageBox::Close); - return false; - } - if (ui->gppGroupBox->isEnabled() && ui->gppPath->text().isEmpty()) { - ui->gppPath->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty g++ path!"), QMessageBox::Close); - return false; - } - if (ui->fpcGroupBox->isEnabled() && ui->fpcPath->text().isEmpty()) { - ui->fpcPath->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty fpc path!"), QMessageBox::Close); - return false; - } - if (ui->fbcGroupBox->isEnabled() && ui->fbcPath->text().isEmpty()) { - ui->fbcPath->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty fbc path!"), QMessageBox::Close); - return false; - } - if (ui->javaGroupBox->isEnabled() && ui->javacPath->text().isEmpty()) { - ui->javacPath->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty javac path!"), QMessageBox::Close); - return false; - } - if (ui->javaGroupBox->isEnabled() && ui->javaPath->text().isEmpty()) { - ui->javaPath->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty java path!"), QMessageBox::Close); - return false; - } - if (ui->pythonGroupBox->isEnabled() && ui->pythonPath->text().isEmpty()) { - ui->pythonPath->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty python path!"), QMessageBox::Close); - return false; - } - - QString text; - if (ui->gccGroupBox->isEnabled()) { - text += tr("[gcc Compiler]") + "\n"; - text += tr("gcc Path: ") + ui->gccPath->text() + "\n"; - if (ui->gccO2Check->isChecked()) - text += tr("Enable O2 Optimization") + "\n"; - text += "\n"; - } - if (ui->gppGroupBox->isEnabled()) { - text += tr("[g++ Compiler]") + "\n"; - text += tr("g++ Path: ") + ui->gppPath->text() + "\n"; - if (ui->gppO2Check->isChecked()) - text += tr("Enable O2 Optimization") + "\n"; - text += "\n"; - } - if (ui->fpcGroupBox->isEnabled()) { - text += tr("[fpc Compiler]") + "\n"; - text += tr("fpc Path: ") + ui->fpcPath->text() + "\n"; - if (ui->fpcO2Check->isChecked()) - text += tr("Enable O2 Optimization") + "\n"; - text += "\n"; - } - if (ui->fbcGroupBox->isEnabled()) { - text += tr("[fbc Compiler]") + "\n"; - text += tr("fbc Path: ") + ui->fbcPath->text() + "\n\n"; - } - if (ui->javaGroupBox->isEnabled()) { - text += tr("[Java Compiler]") + "\n"; - text += tr("javac Path: ") + ui->javacPath->text() + "\n"; - text += tr("java Path: ") + ui->javaPath->text() + "\n"; - text += tr("Memory Limit: %1 MB").arg(ui->javaMemoryLimit->text()) + "\n"; - text += "\n"; - } - if (ui->pythonGroupBox->isEnabled()) { - text += tr("[Python Compiler]") + "\n"; - text += tr("python Path: ") + ui->pythonPath->text() + "\n"; - if (ui->pythonBytecodeCheck->isChecked()) - text += tr("Generate Optimized Byte-code") + "\n"; - text += "\n"; - } - ui->logViewer->setPlainText(text); - } - - return true; -} - -void AddCompilerWizard::compilerTypeChanged() -{ - if (ui->typeSelect->currentIndex() == 0) { - ui->interpreterLocationLabel->setEnabled(false); - ui->interpreterLocation->setEnabled(false); - ui->interpreterSelectButton->setEnabled(false); - ui->defaultInterpreterArgumentsLabel->setEnabled(false); - ui->defaultInterpreterArguments->setEnabled(false); - } else { - ui->interpreterLocationLabel->setEnabled(true); - ui->interpreterLocation->setEnabled(true); - ui->interpreterSelectButton->setEnabled(true); - ui->defaultInterpreterArgumentsLabel->setEnabled(true); - ui->defaultInterpreterArguments->setEnabled(true); - } - - if (ui->typeSelect->currentIndex() == 1) { - ui->bytecodeFileExtensionsLabel->setEnabled(true); - ui->bytecodeFileExtensions->setEnabled(true); - } else { - ui->bytecodeFileExtensionsLabel->setEnabled(false); - ui->bytecodeFileExtensions->setEnabled(false); - } - - if (ui->typeSelect->currentIndex() == 2) { - ui->compilerLocationLabel->setEnabled(false); - ui->compilerLocation->setEnabled(false); - ui->compilerSelectButton->setEnabled(false); - ui->defaultCompilerArgumentsLabel->setEnabled(false); - ui->defaultCompilerArguments->setEnabled(false); - } else { - ui->compilerLocationLabel->setEnabled(true); - ui->compilerLocation->setEnabled(true); - ui->compilerSelectButton->setEnabled(true); - ui->defaultCompilerArgumentsLabel->setEnabled(true); - ui->defaultCompilerArguments->setEnabled(true); - } -} - -void AddCompilerWizard::selectCompilerLocation() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), tr("Executable files (*.exe)")); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), tr("Executable files (*.*)")); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->compilerLocation->setText(location); - } -} - -void AddCompilerWizard::selectInterpreterLocation() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), tr("Executable files (*.exe)")); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), tr("Executable files (*.*)")); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->interpreterLocation->setText(location); - } -} - -void AddCompilerWizard::selectGccPath() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "gcc (gcc.exe)"); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "gcc (gcc)"); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->gccPath->setText(location); - } -} - -void AddCompilerWizard::selectGppPath() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "g++ (g++.exe)"); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "g++ (g++)"); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->gppPath->setText(location); - } -} - -void AddCompilerWizard::selectFpcPath() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "fpc (fpc.exe)"); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "fpc (fpc)"); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->fpcPath->setText(location); - } -} - -void AddCompilerWizard::selectFbcPath() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "fbc (fbc.exe)"); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "fbc (fbc)"); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->fbcPath->setText(location); - } -} - -void AddCompilerWizard::selectJavacPath() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "javac (javac.exe)"); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), "javac (javac)"); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->javacPath->setText(location); - } -} - -void AddCompilerWizard::selectJavaPath() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), "java (java.exe)"); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), "java (java)"); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->javaPath->setText(location); - } -} - -void AddCompilerWizard::selectPythonPath() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), "python (python.exe)"); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), "python (python)"); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->pythonPath->setText(location); - } -} - -void AddCompilerWizard::accept() -{ - if (ui->customRadioButton->isChecked()) { - Compiler *compiler = new Compiler; - compiler->setCompilerType((Compiler::CompilerType)ui->typeSelect->currentIndex()); - compiler->setCompilerName(ui->compilerName->text()); - compiler->setCompilerLocation(ui->compilerLocation->text()); - compiler->setInterpreterLocation(ui->interpreterLocation->text()); - compiler->setSourceExtensions(ui->sourceFileExtensions->text()); - compiler->setBytecodeExtensions(ui->bytecodeFileExtensions->text()); - compiler->addConfiguration("default", - ui->defaultCompilerArguments->text(), - ui->defaultInterpreterArguments->text()); - compilerList.append(compiler); - } - - if (ui->builtinRadioButton->isChecked()) { - if (ui->gccGroupBox->isEnabled()) { - Compiler *compiler = new Compiler; - compiler->setCompilerName("gcc"); - compiler->setCompilerLocation(ui->gccPath->text()); - compiler->setSourceExtensions("c"); - if (ui->gccO2Check->isChecked()) - compiler->addConfiguration("default", "-o %s %s.* -O2", ""); - else - compiler->addConfiguration("default", "-o %s %s.*", ""); -#ifdef Q_OS_WIN32 - QProcessEnvironment environment; - QString path = QFileInfo(ui->gccPath->text()).absolutePath(); - path.replace('/', QDir::separator()); - environment.insert("PATH", path); - compiler->setEnvironment(environment); -#endif - compilerList.append(compiler); - } - - if (ui->gppGroupBox->isEnabled()) { - Compiler *compiler = new Compiler; - compiler->setCompilerName("g++"); - compiler->setCompilerLocation(ui->gppPath->text()); - compiler->setSourceExtensions("cpp;cc;cxx"); - if (ui->gccO2Check->isChecked()) - compiler->addConfiguration("default", "-o %s %s.* -O2", ""); - else - compiler->addConfiguration("default", "-o %s %s.*", ""); -#ifdef Q_OS_WIN32 - QProcessEnvironment environment; - QString path = QFileInfo(ui->gccPath->text()).absolutePath(); - path.replace('/', QDir::separator()); - environment.insert("PATH", path); - compiler->setEnvironment(environment); -#endif - compilerList.append(compiler); - } - - if (ui->fpcGroupBox->isEnabled()) { - Compiler *compiler = new Compiler; - compiler->setCompilerName("fpc"); - compiler->setCompilerLocation(ui->fpcPath->text()); - compiler->setSourceExtensions("pas;pp;inc"); - if (ui->gccO2Check->isChecked()) - compiler->addConfiguration("default", "%s.* -O2", ""); - else - compiler->addConfiguration("default", "%s.*", ""); - compilerList.append(compiler); - } - - if (ui->fbcGroupBox->isEnabled()) { - Compiler *compiler = new Compiler; - compiler->setCompilerName("fbc"); - compiler->setCompilerLocation(ui->fbcPath->text()); - compiler->setSourceExtensions("bas"); - compiler->addConfiguration("default", "%s.*", ""); - compilerList.append(compiler); - } - - if (ui->javaGroupBox->isEnabled()) { - Compiler *compiler = new Compiler; - compiler->setCompilerName("jdk"); - compiler->setCompilerType(Compiler::InterpretiveWithByteCode); - compiler->setCompilerLocation(ui->javacPath->text()); - compiler->setInterpreterLocation(ui->javaPath->text()); - compiler->setSourceExtensions("java"); - compiler->setBytecodeExtensions("class"); - compiler->setTimeLimitRatio(5); - compiler->setDisableMemoryLimitCheck(true); - compiler->addConfiguration("default", "%s.*", QString("-Xmx%1m %s").arg(ui->javaMemoryLimit->text())); - compilerList.append(compiler); - } - - if (ui->pythonGroupBox->isEnabled()) { - Compiler *compiler = new Compiler; - compiler->setCompilerName("python"); - compiler->setSourceExtensions("py"); - compiler->setTimeLimitRatio(10); - compiler->setMemoryLimitRatio(5); - if (ui->pythonBytecodeCheck->isChecked()) { - compiler->setCompilerType(Compiler::InterpretiveWithByteCode); - compiler->setCompilerLocation(ui->pythonPath->text()); - compiler->setInterpreterLocation(ui->pythonPath->text()); - compiler->setBytecodeExtensions("pyo"); - compiler->addConfiguration("default", "-O -m py_compile %s.*", "%s.pyo"); - } else { - compiler->setCompilerType(Compiler::InterpretiveWithoutByteCode); - compiler->setInterpreterLocation(ui->pythonPath->text()); - compiler->addConfiguration("default", "", "%s.*"); - } - compilerList.append(compiler); - } - } - - QWizard::accept(); -} +#include "addcompilerwizard.h" +#include "ui_addcompilerwizard.h" +#include "compiler.h" + +AddCompilerWizard::AddCompilerWizard(QWidget *parent) : + QWizard(parent), + ui(new Ui::AddCompilerWizard) +{ + ui->setupUi(this); + + ui->sourceFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->sourceFileExtensions)); + ui->bytecodeFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->bytecodeFileExtensions)); + ui->javaMemoryLimit->setValidator(new QIntValidator(128, 2048, ui->javaMemoryLimit)); + +#ifdef Q_OS_LINUX + if (QFileInfo("/usr/bin/gcc").exists()) + ui->gccPath->setText("/usr/bin/gcc"); + if (QFileInfo("/usr/bin/g++").exists()) + ui->gppPath->setText("/usr/bin/g++"); + if (QFileInfo("/usr/bin/fpc").exists()) + ui->fpcPath->setText("/usr/bin/fpc"); + if (QFileInfo("/usr/bin/javac").exists()) + ui->javacPath->setText("/usr/bin/javac"); + if (QFileInfo("/usr/bin/java").exists()) + ui->javaPath->setText("/usr/bin/java"); + if (QFileInfo("/usr/bin/python").exists()) + ui->pythonPath->setText("/usr/bin/python"); +#endif + + connect(ui->typeSelect, SIGNAL(currentIndexChanged(int)), + this, SLOT(compilerTypeChanged())); + connect(ui->compilerSelectButton, SIGNAL(clicked()), + this, SLOT(selectCompilerLocation())); + connect(ui->interpreterSelectButton, SIGNAL(clicked()), + this, SLOT(selectInterpreterLocation())); + connect(ui->gccSelectButton, SIGNAL(clicked()), + this, SLOT(selectGccPath())); + connect(ui->gppSelectButton, SIGNAL(clicked()), + this, SLOT(selectGppPath())); + connect(ui->fpcSelectButton, SIGNAL(clicked()), + this, SLOT(selectFpcPath())); + connect(ui->fbcSelectButton, SIGNAL(clicked()), + this, SLOT(selectFbcPath())); + connect(ui->javacSelectButton, SIGNAL(clicked()), + this, SLOT(selectJavacPath())); + connect(ui->javaSelectButton, SIGNAL(clicked()), + this, SLOT(selectJavaPath())); + connect(ui->pythonSelectButton, SIGNAL(clicked()), + this, SLOT(selectPythonPath())); +} + +AddCompilerWizard::~AddCompilerWizard() +{ + delete ui; +} + +const QList& AddCompilerWizard::getCompilerList() const +{ + return compilerList; +} + +int AddCompilerWizard::nextId() const +{ + if (currentId() == 0) { + if (ui->customRadioButton->isChecked()) + return 1; + else + return 2; + } else + if (currentId() == 3) return -1; else return 3; +} + +bool AddCompilerWizard::validateCurrentPage() +{ + if (currentId() == 1) { + if (ui->compilerName->text().isEmpty()) { + ui->compilerName->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty compiler name!"), QMessageBox::Close); + return false; + } + if (ui->compilerLocation->isEnabled() && ui->compilerLocation->text().isEmpty()) { + ui->compilerLocation->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty compiler location!"), QMessageBox::Close); + return false; + } + if (ui->interpreterLocation->isEnabled() && ui->interpreterLocation->text().isEmpty()) { + ui->interpreterLocation->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty interpreter location!"), QMessageBox::Close); + return false; + } + if (ui->sourceFileExtensions->text().isEmpty()) { + ui->sourceFileExtensions->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty source file extensions!"), QMessageBox::Close); + return false; + } + if (ui->bytecodeFileExtensions->isEnabled() && ui->bytecodeFileExtensions->text().isEmpty()) { + ui->bytecodeFileExtensions->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty byte-code file extensions!"), QMessageBox::Close); + return false; + } + + QString text; + text += tr("[Custom Compiler]") + "\n"; + text += tr("Compiler Name: ") + ui->compilerName->text() + "\n"; + text += tr("Compiler Type: ") + ui->typeSelect->currentText() + "\n"; + if (ui->compilerLocation->isEnabled()) + text += tr("Compiler\'s Location: ") + ui->compilerLocation->text() + "\n"; + if (ui->interpreterLocation->isEnabled()) + text += tr("Interpreter\'s Location: ") + ui->interpreterLocation->text() + "\n"; + text += tr("Source File Extensions: ") + ui->sourceFileExtensions->text() + "\n"; + if (ui->bytecodeFileExtensions->isEnabled()) + text += tr("Byte-code File Extensions: ") + ui->bytecodeFileExtensions->text() + "\n"; + if (ui->defaultCompilerArguments->isEnabled()) + text += tr("Default Compiler\'s Arguments: ") + ui->defaultCompilerArguments->text() + "\n"; + if (ui->defaultInterpreterArguments->isEnabled()) + text += tr("Default Interpreter\'s Arguments: ") + ui->defaultInterpreterArguments->text() + "\n"; + ui->logViewer->setPlainText(text); + } + + if (currentId() == 2) { + if (ui->gccGroupBox->isEnabled() && ui->gccPath->text().isEmpty()) { + ui->gccPath->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty gcc path!"), QMessageBox::Close); + return false; + } + if (ui->gppGroupBox->isEnabled() && ui->gppPath->text().isEmpty()) { + ui->gppPath->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty g++ path!"), QMessageBox::Close); + return false; + } + if (ui->fpcGroupBox->isEnabled() && ui->fpcPath->text().isEmpty()) { + ui->fpcPath->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty fpc path!"), QMessageBox::Close); + return false; + } + if (ui->fbcGroupBox->isEnabled() && ui->fbcPath->text().isEmpty()) { + ui->fbcPath->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty fbc path!"), QMessageBox::Close); + return false; + } + if (ui->javaGroupBox->isEnabled() && ui->javacPath->text().isEmpty()) { + ui->javacPath->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty javac path!"), QMessageBox::Close); + return false; + } + if (ui->javaGroupBox->isEnabled() && ui->javaPath->text().isEmpty()) { + ui->javaPath->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty java path!"), QMessageBox::Close); + return false; + } + if (ui->pythonGroupBox->isEnabled() && ui->pythonPath->text().isEmpty()) { + ui->pythonPath->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty python path!"), QMessageBox::Close); + return false; + } + + QString text; + if (ui->gccGroupBox->isEnabled()) { + text += tr("[gcc Compiler]") + "\n"; + text += tr("gcc Path: ") + ui->gccPath->text() + "\n"; + if (ui->gccO2Check->isChecked()) + text += tr("Enable O2 Optimization") + "\n"; + text += "\n"; + } + if (ui->gppGroupBox->isEnabled()) { + text += tr("[g++ Compiler]") + "\n"; + text += tr("g++ Path: ") + ui->gppPath->text() + "\n"; + if (ui->gppO2Check->isChecked()) + text += tr("Enable O2 Optimization") + "\n"; + text += "\n"; + } + if (ui->fpcGroupBox->isEnabled()) { + text += tr("[fpc Compiler]") + "\n"; + text += tr("fpc Path: ") + ui->fpcPath->text() + "\n"; + if (ui->fpcO2Check->isChecked()) + text += tr("Enable O2 Optimization") + "\n"; + text += "\n"; + } + if (ui->fbcGroupBox->isEnabled()) { + text += tr("[fbc Compiler]") + "\n"; + text += tr("fbc Path: ") + ui->fbcPath->text() + "\n\n"; + } + if (ui->javaGroupBox->isEnabled()) { + text += tr("[Java Compiler]") + "\n"; + text += tr("javac Path: ") + ui->javacPath->text() + "\n"; + text += tr("java Path: ") + ui->javaPath->text() + "\n"; + text += tr("Memory Limit: %1 MB").arg(ui->javaMemoryLimit->text()) + "\n"; + text += "\n"; + } + if (ui->pythonGroupBox->isEnabled()) { + text += tr("[Python Compiler]") + "\n"; + text += tr("python Path: ") + ui->pythonPath->text() + "\n"; + if (ui->pythonBytecodeCheck->isChecked()) + text += tr("Generate Optimized Byte-code") + "\n"; + text += "\n"; + } + ui->logViewer->setPlainText(text); + } + + return true; +} + +void AddCompilerWizard::compilerTypeChanged() +{ + if (ui->typeSelect->currentIndex() == 0) { + ui->interpreterLocationLabel->setEnabled(false); + ui->interpreterLocation->setEnabled(false); + ui->interpreterSelectButton->setEnabled(false); + ui->defaultInterpreterArgumentsLabel->setEnabled(false); + ui->defaultInterpreterArguments->setEnabled(false); + } else { + ui->interpreterLocationLabel->setEnabled(true); + ui->interpreterLocation->setEnabled(true); + ui->interpreterSelectButton->setEnabled(true); + ui->defaultInterpreterArgumentsLabel->setEnabled(true); + ui->defaultInterpreterArguments->setEnabled(true); + } + + if (ui->typeSelect->currentIndex() == 1) { + ui->bytecodeFileExtensionsLabel->setEnabled(true); + ui->bytecodeFileExtensions->setEnabled(true); + } else { + ui->bytecodeFileExtensionsLabel->setEnabled(false); + ui->bytecodeFileExtensions->setEnabled(false); + } + + if (ui->typeSelect->currentIndex() == 2) { + ui->compilerLocationLabel->setEnabled(false); + ui->compilerLocation->setEnabled(false); + ui->compilerSelectButton->setEnabled(false); + ui->defaultCompilerArgumentsLabel->setEnabled(false); + ui->defaultCompilerArguments->setEnabled(false); + } else { + ui->compilerLocationLabel->setEnabled(true); + ui->compilerLocation->setEnabled(true); + ui->compilerSelectButton->setEnabled(true); + ui->defaultCompilerArgumentsLabel->setEnabled(true); + ui->defaultCompilerArguments->setEnabled(true); + } +} + +void AddCompilerWizard::selectCompilerLocation() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), tr("Executable files (*.exe)")); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), tr("Executable files (*.*)")); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->compilerLocation->setText(location); + } +} + +void AddCompilerWizard::selectInterpreterLocation() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), tr("Executable files (*.exe)")); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), tr("Executable files (*.*)")); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->interpreterLocation->setText(location); + } +} + +void AddCompilerWizard::selectGccPath() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "gcc (gcc.exe)"); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "gcc (gcc)"); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->gccPath->setText(location); + } +} + +void AddCompilerWizard::selectGppPath() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "g++ (g++.exe)"); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "g++ (g++)"); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->gppPath->setText(location); + } +} + +void AddCompilerWizard::selectFpcPath() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "fpc (fpc.exe)"); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "fpc (fpc)"); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->fpcPath->setText(location); + } +} + +void AddCompilerWizard::selectFbcPath() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "fbc (fbc.exe)"); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "fbc (fbc)"); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->fbcPath->setText(location); + } +} + +void AddCompilerWizard::selectJavacPath() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "javac (javac.exe)"); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), "javac (javac)"); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->javacPath->setText(location); + } +} + +void AddCompilerWizard::selectJavaPath() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), "java (java.exe)"); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), "java (java)"); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->javaPath->setText(location); + } +} + +void AddCompilerWizard::selectPythonPath() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), "python (python.exe)"); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), "python (python)"); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->pythonPath->setText(location); + } +} + +void AddCompilerWizard::accept() +{ + if (ui->customRadioButton->isChecked()) { + Compiler *compiler = new Compiler; + compiler->setCompilerType((Compiler::CompilerType)ui->typeSelect->currentIndex()); + compiler->setCompilerName(ui->compilerName->text()); + compiler->setCompilerLocation(ui->compilerLocation->text()); + compiler->setInterpreterLocation(ui->interpreterLocation->text()); + compiler->setSourceExtensions(ui->sourceFileExtensions->text()); + compiler->setBytecodeExtensions(ui->bytecodeFileExtensions->text()); + compiler->addConfiguration("default", + ui->defaultCompilerArguments->text(), + ui->defaultInterpreterArguments->text()); + compilerList.append(compiler); + } + + if (ui->builtinRadioButton->isChecked()) { + if (ui->gccGroupBox->isEnabled()) { + Compiler *compiler = new Compiler; + compiler->setCompilerName("gcc"); + compiler->setCompilerLocation(ui->gccPath->text()); + compiler->setSourceExtensions("c"); + if (ui->gccO2Check->isChecked()) + compiler->addConfiguration("default", "-o %s %s.* -O2", ""); + else + compiler->addConfiguration("default", "-o %s %s.*", ""); +#ifdef Q_OS_WIN32 + QProcessEnvironment environment; + QString path = QFileInfo(ui->gccPath->text()).absolutePath(); + path.replace('/', QDir::separator()); + environment.insert("PATH", path); + compiler->setEnvironment(environment); +#endif + compilerList.append(compiler); + } + + if (ui->gppGroupBox->isEnabled()) { + Compiler *compiler = new Compiler; + compiler->setCompilerName("g++"); + compiler->setCompilerLocation(ui->gppPath->text()); + compiler->setSourceExtensions("cpp;cc;cxx"); + if (ui->gccO2Check->isChecked()) + compiler->addConfiguration("default", "-o %s %s.* -O2", ""); + else + compiler->addConfiguration("default", "-o %s %s.*", ""); +#ifdef Q_OS_WIN32 + QProcessEnvironment environment; + QString path = QFileInfo(ui->gccPath->text()).absolutePath(); + path.replace('/', QDir::separator()); + environment.insert("PATH", path); + compiler->setEnvironment(environment); +#endif + compilerList.append(compiler); + } + + if (ui->fpcGroupBox->isEnabled()) { + Compiler *compiler = new Compiler; + compiler->setCompilerName("fpc"); + compiler->setCompilerLocation(ui->fpcPath->text()); + compiler->setSourceExtensions("pas;pp;inc"); + if (ui->gccO2Check->isChecked()) + compiler->addConfiguration("default", "%s.* -O2", ""); + else + compiler->addConfiguration("default", "%s.*", ""); + compilerList.append(compiler); + } + + if (ui->fbcGroupBox->isEnabled()) { + Compiler *compiler = new Compiler; + compiler->setCompilerName("fbc"); + compiler->setCompilerLocation(ui->fbcPath->text()); + compiler->setSourceExtensions("bas"); + compiler->addConfiguration("default", "%s.*", ""); + compilerList.append(compiler); + } + + if (ui->javaGroupBox->isEnabled()) { + Compiler *compiler = new Compiler; + compiler->setCompilerName("jdk"); + compiler->setCompilerType(Compiler::InterpretiveWithByteCode); + compiler->setCompilerLocation(ui->javacPath->text()); + compiler->setInterpreterLocation(ui->javaPath->text()); + compiler->setSourceExtensions("java"); + compiler->setBytecodeExtensions("class"); + compiler->setTimeLimitRatio(5); + compiler->setDisableMemoryLimitCheck(true); + compiler->addConfiguration("default", "%s.*", QString("-Xmx%1m %s").arg(ui->javaMemoryLimit->text())); + compilerList.append(compiler); + } + + if (ui->pythonGroupBox->isEnabled()) { + Compiler *compiler = new Compiler; + compiler->setCompilerName("python"); + compiler->setSourceExtensions("py"); + compiler->setTimeLimitRatio(10); + compiler->setMemoryLimitRatio(5); + if (ui->pythonBytecodeCheck->isChecked()) { + compiler->setCompilerType(Compiler::InterpretiveWithByteCode); + compiler->setCompilerLocation(ui->pythonPath->text()); + compiler->setInterpreterLocation(ui->pythonPath->text()); + compiler->setBytecodeExtensions("pyo"); + compiler->addConfiguration("default", "-O -m py_compile %s.*", "%s.pyo"); + } else { + compiler->setCompilerType(Compiler::InterpretiveWithoutByteCode); + compiler->setInterpreterLocation(ui->pythonPath->text()); + compiler->addConfiguration("default", "", "%s.*"); + } + compilerList.append(compiler); + } + } + + QWizard::accept(); +} diff --git a/addcompilerwizard.h b/addcompilerwizard.h index 274dd87..4f11091 100644 --- a/addcompilerwizard.h +++ b/addcompilerwizard.h @@ -1,43 +1,43 @@ -#ifndef ADDCOMPILERWIZARD_H -#define ADDCOMPILERWIZARD_H - -#include -#include -#include - -namespace Ui { - class AddCompilerWizard; -} - -class Compiler; - -class AddCompilerWizard : public QWizard -{ - Q_OBJECT - -public: - explicit AddCompilerWizard(QWidget *parent = 0); - ~AddCompilerWizard(); - void accept(); - const QList& getCompilerList() const; - -private: - Ui::AddCompilerWizard *ui; - QList compilerList; - int nextId() const; - bool validateCurrentPage(); - -private slots: - void compilerTypeChanged(); - void selectCompilerLocation(); - void selectInterpreterLocation(); - void selectGccPath(); - void selectGppPath(); - void selectFpcPath(); - void selectFbcPath(); - void selectJavacPath(); - void selectJavaPath(); - void selectPythonPath(); -}; - -#endif // ADDCOMPILERWIZARD_H +#ifndef ADDCOMPILERWIZARD_H +#define ADDCOMPILERWIZARD_H + +#include +#include +#include + +namespace Ui { + class AddCompilerWizard; +} + +class Compiler; + +class AddCompilerWizard : public QWizard +{ + Q_OBJECT + +public: + explicit AddCompilerWizard(QWidget *parent = 0); + ~AddCompilerWizard(); + void accept(); + const QList& getCompilerList() const; + +private: + Ui::AddCompilerWizard *ui; + QList compilerList; + int nextId() const; + bool validateCurrentPage(); + +private slots: + void compilerTypeChanged(); + void selectCompilerLocation(); + void selectInterpreterLocation(); + void selectGccPath(); + void selectGppPath(); + void selectFpcPath(); + void selectFbcPath(); + void selectJavacPath(); + void selectJavaPath(); + void selectPythonPath(); +}; + +#endif // ADDCOMPILERWIZARD_H diff --git a/addcompilerwizard.ui b/addcompilerwizard.ui index da77fc4..63fcad5 100644 --- a/addcompilerwizard.ui +++ b/addcompilerwizard.ui @@ -6,14 +6,14 @@ 0 0 - 457 - 415 + 470 + 450 - 457 - 415 + 470 + 450 @@ -259,6 +259,9 @@ font-weight: bold; 20 + + font-size:9pt; + @@ -279,6 +282,9 @@ font-weight: bold; 20 + + font-size:9pt; + Typical (Generate executable file) @@ -307,10 +313,17 @@ font-weight: bold; - + + + font-size:9pt; + + + + font-size:9pt; + ... @@ -334,6 +347,9 @@ font-weight: bold; false + + font-size:9pt; + @@ -341,6 +357,9 @@ font-weight: bold; false + + font-size:9pt; + ... @@ -361,15 +380,18 @@ font-weight: bold; 61 - 20 + 0 81 - 20 + 16777215 + + font-size:9pt; + @@ -393,15 +415,18 @@ font-weight: bold; 61 - 20 + 0 81 - 20 + 16777215 + + font-size:9pt; + @@ -415,7 +440,11 @@ font-weight: bold; - + + + font-size:9pt; + + @@ -435,6 +464,9 @@ font-weight: bold; false + + font-size:9pt; + @@ -495,7 +527,7 @@ font-weight: bold; 16777215 - 81 + 100 @@ -552,7 +584,7 @@ font-weight: bold; 16777215 - 81 + 100 @@ -603,13 +635,13 @@ font-weight: bold; 0 - 79 + 81 16777215 - 79 + 100 @@ -669,7 +701,7 @@ font-weight: bold; 16777215 - 81 + 100 @@ -732,7 +764,7 @@ font-weight: bold; 16777215 - 110 + 120 @@ -865,13 +897,13 @@ font-weight: bold; 0 - 111 + 110 16777215 - 111 + 120 diff --git a/addtaskdialog.cpp b/addtaskdialog.cpp index 4b37e6e..ac7cec3 100644 --- a/addtaskdialog.cpp +++ b/addtaskdialog.cpp @@ -1,99 +1,99 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "addtaskdialog.h" -#include "ui_addtaskdialog.h" - -AddTaskDialog::AddTaskDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::AddTaskDialog) -{ - ui->setupUi(this); - connect(ui->taskBox, SIGNAL(currentIndexChanged(int)), - this, SLOT(taskBoxIndexChanged())); - connect(ui->fullScore, SIGNAL(textChanged(QString)), - this, SLOT(fullScoreChanged())); - connect(ui->timeLimit, SIGNAL(textChanged(QString)), - this, SLOT(timeLimitChanged())); - connect(ui->memoryLimit, SIGNAL(textChanged(QString)), - this, SLOT(memoryLimitChanged())); -} - -AddTaskDialog::~AddTaskDialog() -{ - delete ui; -} - -void AddTaskDialog::addTask(const QString &title, int _fullScore, int _timeLimit, int _memoryLimit) -{ - fullScore.append(_fullScore); - timeLimit.append(_timeLimit); - memoryLimit.append(_memoryLimit); - ui->taskBox->addItem(title); - ui->taskBox->setCurrentIndex(0); -} - -int AddTaskDialog::getFullScore(int index) const -{ - if (0 <= index && index < fullScore.size()) - return fullScore[index]; - else - return 0; -} - -int AddTaskDialog::getTimeLimit(int index) const -{ - if (0 <= index && index < timeLimit.size()) - return timeLimit[index]; - else - return 0; -} - -int AddTaskDialog::getMemoryLimit(int index) const -{ - if (0 <= index && index < memoryLimit.size()) - return memoryLimit[index]; - else - return 0; -} - -void AddTaskDialog::taskBoxIndexChanged() -{ - int index = ui->taskBox->currentIndex(); - ui->fullScore->setText(QString("%1").arg(fullScore[index])); - ui->timeLimit->setText(QString("%1").arg(timeLimit[index])); - ui->memoryLimit->setText(QString("%1").arg(memoryLimit[index])); -} - -void AddTaskDialog::fullScoreChanged() -{ - int index = ui->taskBox->currentIndex(); - fullScore[index] = ui->fullScore->text().toInt(); -} - -void AddTaskDialog::timeLimitChanged() -{ - int index = ui->taskBox->currentIndex(); - timeLimit[index] = ui->timeLimit->text().toInt(); -} - -void AddTaskDialog::memoryLimitChanged() -{ - int index = ui->taskBox->currentIndex(); - memoryLimit[index] = ui->memoryLimit->text().toInt(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "addtaskdialog.h" +#include "ui_addtaskdialog.h" + +AddTaskDialog::AddTaskDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AddTaskDialog) +{ + ui->setupUi(this); + connect(ui->taskBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(taskBoxIndexChanged())); + connect(ui->fullScore, SIGNAL(textChanged(QString)), + this, SLOT(fullScoreChanged())); + connect(ui->timeLimit, SIGNAL(textChanged(QString)), + this, SLOT(timeLimitChanged())); + connect(ui->memoryLimit, SIGNAL(textChanged(QString)), + this, SLOT(memoryLimitChanged())); +} + +AddTaskDialog::~AddTaskDialog() +{ + delete ui; +} + +void AddTaskDialog::addTask(const QString &title, int _fullScore, int _timeLimit, int _memoryLimit) +{ + fullScore.append(_fullScore); + timeLimit.append(_timeLimit); + memoryLimit.append(_memoryLimit); + ui->taskBox->addItem(title); + ui->taskBox->setCurrentIndex(0); +} + +int AddTaskDialog::getFullScore(int index) const +{ + if (0 <= index && index < fullScore.size()) + return fullScore[index]; + else + return 0; +} + +int AddTaskDialog::getTimeLimit(int index) const +{ + if (0 <= index && index < timeLimit.size()) + return timeLimit[index]; + else + return 0; +} + +int AddTaskDialog::getMemoryLimit(int index) const +{ + if (0 <= index && index < memoryLimit.size()) + return memoryLimit[index]; + else + return 0; +} + +void AddTaskDialog::taskBoxIndexChanged() +{ + int index = ui->taskBox->currentIndex(); + ui->fullScore->setText(QString("%1").arg(fullScore[index])); + ui->timeLimit->setText(QString("%1").arg(timeLimit[index])); + ui->memoryLimit->setText(QString("%1").arg(memoryLimit[index])); +} + +void AddTaskDialog::fullScoreChanged() +{ + int index = ui->taskBox->currentIndex(); + fullScore[index] = ui->fullScore->text().toInt(); +} + +void AddTaskDialog::timeLimitChanged() +{ + int index = ui->taskBox->currentIndex(); + timeLimit[index] = ui->timeLimit->text().toInt(); +} + +void AddTaskDialog::memoryLimitChanged() +{ + int index = ui->taskBox->currentIndex(); + memoryLimit[index] = ui->memoryLimit->text().toInt(); +} diff --git a/addtaskdialog.h b/addtaskdialog.h index 9f9bc5b..93c3613 100644 --- a/addtaskdialog.h +++ b/addtaskdialog.h @@ -1,53 +1,53 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef ADDTASKDIALOG_H -#define ADDTASKDIALOG_H - -#include - -namespace Ui { - class AddTaskDialog; -} - -class AddTaskDialog : public QDialog -{ - Q_OBJECT - -public: - explicit AddTaskDialog(QWidget *parent = 0); - ~AddTaskDialog(); - void addTask(const QString&, int, int, int); - int getFullScore(int) const; - int getTimeLimit(int) const; - int getMemoryLimit(int) const; - -private: - Ui::AddTaskDialog *ui; - QList fullScore; - QList timeLimit; - QList memoryLimit; - -private slots: - void taskBoxIndexChanged(); - void fullScoreChanged(); - void timeLimitChanged(); - void memoryLimitChanged(); -}; - -#endif // ADDTASKDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef ADDTASKDIALOG_H +#define ADDTASKDIALOG_H + +#include + +namespace Ui { + class AddTaskDialog; +} + +class AddTaskDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AddTaskDialog(QWidget *parent = 0); + ~AddTaskDialog(); + void addTask(const QString&, int, int, int); + int getFullScore(int) const; + int getTimeLimit(int) const; + int getMemoryLimit(int) const; + +private: + Ui::AddTaskDialog *ui; + QList fullScore; + QList timeLimit; + QList memoryLimit; + +private slots: + void taskBoxIndexChanged(); + void fullScoreChanged(); + void timeLimitChanged(); + void memoryLimitChanged(); +}; + +#endif // ADDTASKDIALOG_H diff --git a/addtaskdialog.ui b/addtaskdialog.ui index 4ad212a..2282164 100644 --- a/addtaskdialog.ui +++ b/addtaskdialog.ui @@ -1,199 +1,212 @@ - - - AddTaskDialog - - - - 0 - 0 - 261 - 177 - - - - - 197 - 164 - - - - Add Task - - - - 9 - - - 10 - - - - - font-size: 10pt; -font-weight: bold; - - - Task - - - - - - - - - - font-size: 10pt; -font-weight: bold; - - - Full Score - - - - - - - - 75 - 22 - - - - - - - - font-size: 10pt; -font-weight: bold; - - - Time Limit - - - - - - - - 75 - 22 - - - - - - - - font-size: 10pt; - - - ms - - - - - - - font-size: 10pt; -font-weight: bold; - - - Memory Limit - - - - - - - - 75 - 22 - - - - - - - - font-size: 10pt; - - - MB - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Qt::Horizontal - - - - 33 - 20 - - - - - - - - Qt::Horizontal - - - - 33 - 20 - - - - - - - - - - buttonBox - accepted() - AddTaskDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AddTaskDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - + + + AddTaskDialog + + + + 0 + 0 + 261 + 177 + + + + + 197 + 164 + + + + Add Task + + + + 9 + + + 10 + + + + + font-size: 10pt; +font-weight: bold; + + + Task + + + + + + + font-size:9pt; + + + + + + + font-size: 10pt; +font-weight: bold; + + + Full Score + + + + + + + + 75 + 22 + + + + font-size:9pt; + + + + + + + font-size: 10pt; +font-weight: bold; + + + Time Limit + + + + + + + + 75 + 22 + + + + font-size:9pt; + + + + + + + font-size: 10pt; + + + ms + + + + + + + font-size: 10pt; +font-weight: bold; + + + Memory Limit + + + + + + + + 75 + 22 + + + + font-size:9pt; + + + + + + + font-size: 10pt; + + + MB + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + 33 + 20 + + + + + + + + Qt::Horizontal + + + + 33 + 20 + + + + + + + + + + buttonBox + accepted() + AddTaskDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AddTaskDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/addtestcaseswizard.cpp b/addtestcaseswizard.cpp index 7a7d9fa..f81883d 100644 --- a/addtestcaseswizard.cpp +++ b/addtestcaseswizard.cpp @@ -1,373 +1,373 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "addtestcaseswizard.h" -#include "ui_addtestcaseswizard.h" -#include "settings.h" - -AddTestCasesWizard::AddTestCasesWizard(QWidget *parent) : - QWizard(parent), - ui(new Ui::AddTestCasesWizard) -{ - ui->setupUi(this); - - ui->fullScore->setValidator(new QIntValidator(1, Settings::upperBoundForFullScore(), ui->fullScore)); - ui->timeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->timeLimit)); - ui->memoryLimit->setValidator(new QIntValidator(1, Settings::upperBoundForMemoryLimit(), ui->memoryLimit)); - - connect(ui->fullScore, SIGNAL(textChanged(QString)), - this, SLOT(fullScoreChanged(QString))); - connect(ui->timeLimit, SIGNAL(textChanged(QString)), - this, SLOT(timeLimitChanged(QString))); - connect(ui->memoryLimit, SIGNAL(textChanged(QString)), - this, SLOT(memoryLimitChanged(QString))); - - QHeaderView *header = ui->argumentList->horizontalHeader(); - for (int i = 0; i < 3; i ++) - header->resizeSection(i, header->sectionSizeHint(i)); - - connect(ui->inputFilesPattern, SIGNAL(textChanged(QString)), - this, SLOT(inputFilesPatternChanged(QString))); - connect(ui->outputFilesPattern, SIGNAL(textChanged(QString)), - this, SLOT(outputFilesPatternChanged(QString))); - connect(ui->addArgumentButton, SIGNAL(clicked()), - this, SLOT(addArgument())); - connect(ui->deleteArgumentButton, SIGNAL(clicked()), - this, SLOT(deleteArgument())); -} - -AddTestCasesWizard::~AddTestCasesWizard() -{ - delete ui; -} - -void AddTestCasesWizard::setSettings(Settings *_settings, bool check) -{ - settings = _settings; - ui->fullScore->setText(QString("%1").arg(settings->getDefaultFullScore())); - ui->timeLimit->setText(QString("%1").arg(settings->getDefaultTimeLimit())); - ui->memoryLimit->setText(QString("%1").arg(settings->getDefaultMemoryLimit())); - ui->timeLimit->setEnabled(check); - ui->timeLimitLabel->setEnabled(check); - ui->msLabel->setEnabled(check); - ui->memoryLimit->setEnabled(check); - ui->memoryLimitLabel->setEnabled(check); - ui->mbLabel->setEnabled(check); - refreshButtonState(); -} - -int AddTestCasesWizard::getFullScore() const -{ - return fullScore; -} - -int AddTestCasesWizard::getTimeLimit() const -{ - return timeLimit; -} - -int AddTestCasesWizard::getMemoryLimit() const -{ - return memoryLimit; -} - -const QList& AddTestCasesWizard::getMatchedInputFiles() const -{ - return matchedInputFiles; -} - -const QList& AddTestCasesWizard::getMatchedOutputFiles() const -{ - return matchedOutputFiles; -} - -void AddTestCasesWizard::fullScoreChanged(const QString &text) -{ - fullScore = text.toInt(); -} - -void AddTestCasesWizard::timeLimitChanged(const QString &text) -{ - timeLimit = text.toInt(); -} - -void AddTestCasesWizard::memoryLimitChanged(const QString &text) -{ - memoryLimit = text.toInt(); -} - -void AddTestCasesWizard::inputFilesPatternChanged(const QString &text) -{ - inputFilesPattern = text; -} - -void AddTestCasesWizard::outputFilesPatternChanged(const QString &text) -{ - outputFilesPattern = text; -} - -void AddTestCasesWizard::addArgument() -{ - ui->argumentList->setRowCount(ui->argumentList->rowCount() + 1); - int index = ui->argumentList->rowCount() - 1; - ui->argumentList->setItem(index, 0, new QTableWidgetItem(QString("<%1>").arg(index + 1))); - ui->argumentList->item(index, 0)->setTextAlignment(Qt::AlignCenter); - ui->argumentList->item(index, 0)->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - ui->argumentList->item(index, 0)->setCheckState(Qt::Checked); - ui->argumentList->setItem(index, 1, new QTableWidgetItem()); - ui->argumentList->setFocus(); - ui->argumentList->editItem(ui->argumentList->item(index, 1)); - refreshButtonState(); -} - -void AddTestCasesWizard::deleteArgument() -{ - int index = ui->argumentList->currentRow(); - for (int i = index; i + 1 < ui->argumentList->rowCount(); i ++) { - ui->argumentList->item(i, 0)->setCheckState(ui->argumentList->item(i + 1, 0)->checkState()); - delete ui->argumentList->item(i, 1); - ui->argumentList->setItem(i, 1, new QTableWidgetItem(ui->argumentList->item(i + 1, 1)->text())); - } - ui->argumentList->setRowCount(ui->argumentList->rowCount() - 1); - refreshButtonState(); -} - -void AddTestCasesWizard::refreshButtonState() -{ - if (ui->argumentList->rowCount() < 9) - ui->addArgumentButton->setEnabled(true); - else - ui->addArgumentButton->setEnabled(false); - if (ui->argumentList->currentRow() == -1) - ui->deleteArgumentButton->setEnabled(false); - else - ui->deleteArgumentButton->setEnabled(true); -} - -void AddTestCasesWizard::getFiles(const QString &curDir, const QString &prefix, const QStringList &filters, QStringList &files) -{ - QDir dir(curDir); - if (! filters.isEmpty()) - dir.setNameFilters(filters); - QStringList list = dir.entryList(QDir::Files); - for (int i = 0; i < list.size(); i ++) - list[i] = prefix + list[i]; - files.append(list); - list = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (int i = 0; i < list.size(); i ++) - getFiles(curDir + list[i] + QDir::separator(), - prefix + list[i] + QDir::separator(), - filters, files); -} - -QString AddTestCasesWizard::getFullRegExp(const QString &pattern) -{ - QString result = pattern; - result.replace("\\", "\\\\"); - result.replace("^", "\\^"); - result.replace("$", "\\$"); - result.replace("(", "\\("); - result.replace(")", "\\)"); - result.replace("*", "\\*"); - result.replace("+", "\\+"); - result.replace("?", "\\?"); - result.replace(".", "\\."); - result.replace("[", "\\["); - result.replace("{", "\\{"); - result.replace("|", "\\|"); - - for (int i = 0; i < ui->argumentList->rowCount(); i ++) { - QString text = ui->argumentList->item(i, 1)->text(); - result.replace(QString("<%1>").arg(i + 1), QString("(%1)").arg(text)); - } - return result; -} - -QStringList AddTestCasesWizard::getMatchedPart(const QString &str, const QString &pattern) -{ - QStringList result; - for (int i = 0; i < ui->argumentList->rowCount(); i ++) - result.append(""); - int pos = 0, i = 0; - for ( ; pos < pattern.length(); i ++, pos ++) { - if (pos + 2 < pattern.length()) - if (pattern[pos] == '<' && pattern[pos+1].isDigit() && pattern[pos+1] != '0' && pattern[pos+2] == '>') { - int index = pattern[pos+1].toAscii() - 49; - QString regExp = ui->argumentList->item(index, 1)->text(); - for (int j = i; j < str.length(); j ++) - if (QRegExp(regExp).exactMatch(str.mid(i, j - i + 1))) - if (QRegExp(getFullRegExp(pattern.mid(pos + 3))).exactMatch(str.mid(j + 1))) { - result[index] = str.mid(i, j - i + 1); - i = j; - break; - } - pos += 2; - } - } - return result; -} - -void AddTestCasesWizard::searchMatchedFiles() -{ - QStringList inputFiles, outputFiles; - QStringList filters; - filters = settings->getInputFileExtensions(); - for (int i = 0; i < filters.size(); i ++) - filters[i] = QString("*.") + filters[i]; - getFiles(Settings::dataPath(), "", filters, inputFiles); - filters = settings->getOutputFileExtensions(); - for (int i = 0; i < filters.size(); i ++) - filters[i] = QString("*.") + filters[i]; - getFiles(Settings::dataPath(), "", filters, outputFiles); - - QString regExp = getFullRegExp(inputFilesPattern); - for (int i = 0; i < inputFiles.size(); i ++) - if (! QRegExp(regExp).exactMatch(inputFiles[i])) { - inputFiles.removeAt(i); - i --; - } - regExp = getFullRegExp(outputFilesPattern); - for (int i = 0; i < outputFiles.size(); i ++) - if (! QRegExp(regExp).exactMatch(outputFiles[i])) { - outputFiles.removeAt(i); - i --; - } - - qSort(inputFiles.begin(), inputFiles.end(), compareFileName); - qSort(outputFiles.begin(), outputFiles.end(), compareFileName); - - QList inputFilesMatchedPart; - QList outputFilesMatchedPart; - for (int i = 0; i < inputFiles.size(); i ++) - inputFilesMatchedPart.append(getMatchedPart(inputFiles[i], inputFilesPattern)); - for (int i = 0; i < outputFiles.size(); i ++) - outputFilesMatchedPart.append(getMatchedPart(outputFiles[i], outputFilesPattern)); - - QMap loc; - QList< QPair > singleCases; - QList< QStringList > matchedPart; - for (int i = 0; i < inputFiles.size(); i ++) - loc[inputFilesMatchedPart[i].join("*")] = i; - for (int i = 0; i < outputFiles.size(); i ++) - if (loc.count(outputFilesMatchedPart[i].join("*")) > 0) { - int partner = loc[outputFilesMatchedPart[i].join("*")]; - singleCases.append(qMakePair(inputFiles[partner], outputFiles[i])); - matchedPart.append(outputFilesMatchedPart[i]); - } - - loc.clear(); - for (int i = 0; i < singleCases.size(); i ++) { - QStringList key; - for (int j = 0; j < ui->argumentList->rowCount(); j ++) - if (ui->argumentList->item(j, 0)->checkState() == Qt::Checked) - key.append(matchedPart[i][j]); - loc.insertMulti(key.join("*"), i); - } - - matchedInputFiles.clear(); - matchedOutputFiles.clear(); - ui->testCasesViewer->clear(); - - QList keys = loc.uniqueKeys(); - qSort(keys.begin(), keys.end(), compareFileName); - for (int i = 0; i < keys.size(); i ++) { - QList values = loc.values(keys[i]); - qSort(values.begin(), values.end()); - QStringList inputFiles, outputFiles; - QTreeWidgetItem *item = new QTreeWidgetItem(ui->testCasesViewer); - item->setText(0, tr("Test Case #%1").arg(i + 1)); - for (int j = 0; j < values.size(); j ++) { - inputFiles.append(singleCases[values[j]].first); - outputFiles.append(singleCases[values[j]].second); - QTreeWidgetItem *child = new QTreeWidgetItem(item); - child->setText(0, singleCases[values[j]].first); - child->setText(1, singleCases[values[j]].second); - } - matchedInputFiles.append(inputFiles); - matchedOutputFiles.append(outputFiles); - } - - ui->testCasesViewer->resizeColumnToContents(0); - ui->testCasesViewer->resizeColumnToContents(1); -} - -bool AddTestCasesWizard::validateCurrentPage() -{ - if (currentId() == 0) { - if (ui->fullScore->text().isEmpty()) { - ui->fullScore->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty full score!"), QMessageBox::Close); - return false; - } - if (ui->timeLimit->text().isEmpty()) { - ui->timeLimit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty time limit!"), QMessageBox::Close); - return false; - } - if (ui->memoryLimit->text().isEmpty()) { - ui->memoryLimit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty memory limit!"), QMessageBox::Close); - return false; - } - return true; - } - - if (currentId() == 1) { - if (ui->inputFilesPattern->text().isEmpty()) { - ui->inputFilesPattern->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty input files pattern!"), QMessageBox::Close); - return false; - } - if (ui->outputFilesPattern->text().isEmpty()) { - ui->outputFilesPattern->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty output files pattern!"), QMessageBox::Close); - return false; - } - for (int i = 0; i < ui->argumentList->rowCount(); i ++) { - if (inputFilesPattern.count(QString("<%1>").arg(i + 1)) > 1) { - ui->inputFilesPattern->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Argument <%1> appears more than once in input files pattern!").arg(i + 1), - QMessageBox::Close); - return false; - } - if (outputFilesPattern.count(QString("<%1>").arg(i + 1)) > 1) { - ui->outputFilesPattern->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Argument <%1> appears more than once in output files pattern!").arg(i + 1), - QMessageBox::Close); - return false; - } - QString regExp = ui->argumentList->item(i, 1)->text(); - if (! QRegExp(regExp).isValid()) { - ui->argumentList->setCurrentCell(i, 1); - QMessageBox::warning(this, tr("Error"), tr("Invalid regular expression!"), QMessageBox::Close); - return false; - } - } - QApplication::setOverrideCursor(Qt::WaitCursor); - searchMatchedFiles(); - QApplication::restoreOverrideCursor(); - return true; - } - - return true; -} - -bool AddTestCasesWizard::compareFileName(const QString &a, const QString &b) -{ - return a.length() < b.length() || a.length() == b.length() && QString::localeAwareCompare(a, b) < 0; -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "addtestcaseswizard.h" +#include "ui_addtestcaseswizard.h" +#include "settings.h" + +AddTestCasesWizard::AddTestCasesWizard(QWidget *parent) : + QWizard(parent), + ui(new Ui::AddTestCasesWizard) +{ + ui->setupUi(this); + + ui->fullScore->setValidator(new QIntValidator(1, Settings::upperBoundForFullScore(), ui->fullScore)); + ui->timeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->timeLimit)); + ui->memoryLimit->setValidator(new QIntValidator(1, Settings::upperBoundForMemoryLimit(), ui->memoryLimit)); + + connect(ui->fullScore, SIGNAL(textChanged(QString)), + this, SLOT(fullScoreChanged(QString))); + connect(ui->timeLimit, SIGNAL(textChanged(QString)), + this, SLOT(timeLimitChanged(QString))); + connect(ui->memoryLimit, SIGNAL(textChanged(QString)), + this, SLOT(memoryLimitChanged(QString))); + + QHeaderView *header = ui->argumentList->horizontalHeader(); + for (int i = 0; i < 3; i ++) + header->resizeSection(i, header->sectionSizeHint(i)); + + connect(ui->inputFilesPattern, SIGNAL(textChanged(QString)), + this, SLOT(inputFilesPatternChanged(QString))); + connect(ui->outputFilesPattern, SIGNAL(textChanged(QString)), + this, SLOT(outputFilesPatternChanged(QString))); + connect(ui->addArgumentButton, SIGNAL(clicked()), + this, SLOT(addArgument())); + connect(ui->deleteArgumentButton, SIGNAL(clicked()), + this, SLOT(deleteArgument())); +} + +AddTestCasesWizard::~AddTestCasesWizard() +{ + delete ui; +} + +void AddTestCasesWizard::setSettings(Settings *_settings, bool check) +{ + settings = _settings; + ui->fullScore->setText(QString("%1").arg(settings->getDefaultFullScore())); + ui->timeLimit->setText(QString("%1").arg(settings->getDefaultTimeLimit())); + ui->memoryLimit->setText(QString("%1").arg(settings->getDefaultMemoryLimit())); + ui->timeLimit->setEnabled(check); + ui->timeLimitLabel->setEnabled(check); + ui->msLabel->setEnabled(check); + ui->memoryLimit->setEnabled(check); + ui->memoryLimitLabel->setEnabled(check); + ui->mbLabel->setEnabled(check); + refreshButtonState(); +} + +int AddTestCasesWizard::getFullScore() const +{ + return fullScore; +} + +int AddTestCasesWizard::getTimeLimit() const +{ + return timeLimit; +} + +int AddTestCasesWizard::getMemoryLimit() const +{ + return memoryLimit; +} + +const QList& AddTestCasesWizard::getMatchedInputFiles() const +{ + return matchedInputFiles; +} + +const QList& AddTestCasesWizard::getMatchedOutputFiles() const +{ + return matchedOutputFiles; +} + +void AddTestCasesWizard::fullScoreChanged(const QString &text) +{ + fullScore = text.toInt(); +} + +void AddTestCasesWizard::timeLimitChanged(const QString &text) +{ + timeLimit = text.toInt(); +} + +void AddTestCasesWizard::memoryLimitChanged(const QString &text) +{ + memoryLimit = text.toInt(); +} + +void AddTestCasesWizard::inputFilesPatternChanged(const QString &text) +{ + inputFilesPattern = text; +} + +void AddTestCasesWizard::outputFilesPatternChanged(const QString &text) +{ + outputFilesPattern = text; +} + +void AddTestCasesWizard::addArgument() +{ + ui->argumentList->setRowCount(ui->argumentList->rowCount() + 1); + int index = ui->argumentList->rowCount() - 1; + ui->argumentList->setItem(index, 0, new QTableWidgetItem(QString("<%1>").arg(index + 1))); + ui->argumentList->item(index, 0)->setTextAlignment(Qt::AlignCenter); + ui->argumentList->item(index, 0)->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + ui->argumentList->item(index, 0)->setCheckState(Qt::Checked); + ui->argumentList->setItem(index, 1, new QTableWidgetItem()); + ui->argumentList->setFocus(); + ui->argumentList->editItem(ui->argumentList->item(index, 1)); + refreshButtonState(); +} + +void AddTestCasesWizard::deleteArgument() +{ + int index = ui->argumentList->currentRow(); + for (int i = index; i + 1 < ui->argumentList->rowCount(); i ++) { + ui->argumentList->item(i, 0)->setCheckState(ui->argumentList->item(i + 1, 0)->checkState()); + delete ui->argumentList->item(i, 1); + ui->argumentList->setItem(i, 1, new QTableWidgetItem(ui->argumentList->item(i + 1, 1)->text())); + } + ui->argumentList->setRowCount(ui->argumentList->rowCount() - 1); + refreshButtonState(); +} + +void AddTestCasesWizard::refreshButtonState() +{ + if (ui->argumentList->rowCount() < 9) + ui->addArgumentButton->setEnabled(true); + else + ui->addArgumentButton->setEnabled(false); + if (ui->argumentList->currentRow() == -1) + ui->deleteArgumentButton->setEnabled(false); + else + ui->deleteArgumentButton->setEnabled(true); +} + +void AddTestCasesWizard::getFiles(const QString &curDir, const QString &prefix, const QStringList &filters, QStringList &files) +{ + QDir dir(curDir); + if (! filters.isEmpty()) + dir.setNameFilters(filters); + QStringList list = dir.entryList(QDir::Files); + for (int i = 0; i < list.size(); i ++) + list[i] = prefix + list[i]; + files.append(list); + list = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (int i = 0; i < list.size(); i ++) + getFiles(curDir + list[i] + QDir::separator(), + prefix + list[i] + QDir::separator(), + filters, files); +} + +QString AddTestCasesWizard::getFullRegExp(const QString &pattern) +{ + QString result = pattern; + result.replace("\\", "\\\\"); + result.replace("^", "\\^"); + result.replace("$", "\\$"); + result.replace("(", "\\("); + result.replace(")", "\\)"); + result.replace("*", "\\*"); + result.replace("+", "\\+"); + result.replace("?", "\\?"); + result.replace(".", "\\."); + result.replace("[", "\\["); + result.replace("{", "\\{"); + result.replace("|", "\\|"); + + for (int i = 0; i < ui->argumentList->rowCount(); i ++) { + QString text = ui->argumentList->item(i, 1)->text(); + result.replace(QString("<%1>").arg(i + 1), QString("(%1)").arg(text)); + } + return result; +} + +QStringList AddTestCasesWizard::getMatchedPart(const QString &str, const QString &pattern) +{ + QStringList result; + for (int i = 0; i < ui->argumentList->rowCount(); i ++) + result.append(""); + int pos = 0, i = 0; + for ( ; pos < pattern.length(); i ++, pos ++) { + if (pos + 2 < pattern.length()) + if (pattern[pos] == '<' && pattern[pos+1].isDigit() && pattern[pos+1] != '0' && pattern[pos+2] == '>') { + int index = pattern[pos+1].toAscii() - 49; + QString regExp = ui->argumentList->item(index, 1)->text(); + for (int j = i; j < str.length(); j ++) + if (QRegExp(regExp).exactMatch(str.mid(i, j - i + 1))) + if (QRegExp(getFullRegExp(pattern.mid(pos + 3))).exactMatch(str.mid(j + 1))) { + result[index] = str.mid(i, j - i + 1); + i = j; + break; + } + pos += 2; + } + } + return result; +} + +void AddTestCasesWizard::searchMatchedFiles() +{ + QStringList inputFiles, outputFiles; + QStringList filters; + filters = settings->getInputFileExtensions(); + for (int i = 0; i < filters.size(); i ++) + filters[i] = QString("*.") + filters[i]; + getFiles(Settings::dataPath(), "", filters, inputFiles); + filters = settings->getOutputFileExtensions(); + for (int i = 0; i < filters.size(); i ++) + filters[i] = QString("*.") + filters[i]; + getFiles(Settings::dataPath(), "", filters, outputFiles); + + QString regExp = getFullRegExp(inputFilesPattern); + for (int i = 0; i < inputFiles.size(); i ++) + if (! QRegExp(regExp).exactMatch(inputFiles[i])) { + inputFiles.removeAt(i); + i --; + } + regExp = getFullRegExp(outputFilesPattern); + for (int i = 0; i < outputFiles.size(); i ++) + if (! QRegExp(regExp).exactMatch(outputFiles[i])) { + outputFiles.removeAt(i); + i --; + } + + qSort(inputFiles.begin(), inputFiles.end(), compareFileName); + qSort(outputFiles.begin(), outputFiles.end(), compareFileName); + + QList inputFilesMatchedPart; + QList outputFilesMatchedPart; + for (int i = 0; i < inputFiles.size(); i ++) + inputFilesMatchedPart.append(getMatchedPart(inputFiles[i], inputFilesPattern)); + for (int i = 0; i < outputFiles.size(); i ++) + outputFilesMatchedPart.append(getMatchedPart(outputFiles[i], outputFilesPattern)); + + QMap loc; + QList< QPair > singleCases; + QList< QStringList > matchedPart; + for (int i = 0; i < inputFiles.size(); i ++) + loc[inputFilesMatchedPart[i].join("*")] = i; + for (int i = 0; i < outputFiles.size(); i ++) + if (loc.count(outputFilesMatchedPart[i].join("*")) > 0) { + int partner = loc[outputFilesMatchedPart[i].join("*")]; + singleCases.append(qMakePair(inputFiles[partner], outputFiles[i])); + matchedPart.append(outputFilesMatchedPart[i]); + } + + loc.clear(); + for (int i = 0; i < singleCases.size(); i ++) { + QStringList key; + for (int j = 0; j < ui->argumentList->rowCount(); j ++) + if (ui->argumentList->item(j, 0)->checkState() == Qt::Checked) + key.append(matchedPart[i][j]); + loc.insertMulti(key.join("*"), i); + } + + matchedInputFiles.clear(); + matchedOutputFiles.clear(); + ui->testCasesViewer->clear(); + + QList keys = loc.uniqueKeys(); + qSort(keys.begin(), keys.end(), compareFileName); + for (int i = 0; i < keys.size(); i ++) { + QList values = loc.values(keys[i]); + qSort(values.begin(), values.end()); + QStringList inputFiles, outputFiles; + QTreeWidgetItem *item = new QTreeWidgetItem(ui->testCasesViewer); + item->setText(0, tr("Test Case #%1").arg(i + 1)); + for (int j = 0; j < values.size(); j ++) { + inputFiles.append(singleCases[values[j]].first); + outputFiles.append(singleCases[values[j]].second); + QTreeWidgetItem *child = new QTreeWidgetItem(item); + child->setText(0, singleCases[values[j]].first); + child->setText(1, singleCases[values[j]].second); + } + matchedInputFiles.append(inputFiles); + matchedOutputFiles.append(outputFiles); + } + + ui->testCasesViewer->resizeColumnToContents(0); + ui->testCasesViewer->resizeColumnToContents(1); +} + +bool AddTestCasesWizard::validateCurrentPage() +{ + if (currentId() == 0) { + if (ui->fullScore->text().isEmpty()) { + ui->fullScore->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty full score!"), QMessageBox::Close); + return false; + } + if (ui->timeLimit->text().isEmpty()) { + ui->timeLimit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty time limit!"), QMessageBox::Close); + return false; + } + if (ui->memoryLimit->text().isEmpty()) { + ui->memoryLimit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty memory limit!"), QMessageBox::Close); + return false; + } + return true; + } + + if (currentId() == 1) { + if (ui->inputFilesPattern->text().isEmpty()) { + ui->inputFilesPattern->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty input files pattern!"), QMessageBox::Close); + return false; + } + if (ui->outputFilesPattern->text().isEmpty()) { + ui->outputFilesPattern->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty output files pattern!"), QMessageBox::Close); + return false; + } + for (int i = 0; i < ui->argumentList->rowCount(); i ++) { + if (inputFilesPattern.count(QString("<%1>").arg(i + 1)) > 1) { + ui->inputFilesPattern->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Argument <%1> appears more than once in input files pattern!").arg(i + 1), + QMessageBox::Close); + return false; + } + if (outputFilesPattern.count(QString("<%1>").arg(i + 1)) > 1) { + ui->outputFilesPattern->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Argument <%1> appears more than once in output files pattern!").arg(i + 1), + QMessageBox::Close); + return false; + } + QString regExp = ui->argumentList->item(i, 1)->text(); + if (! QRegExp(regExp).isValid()) { + ui->argumentList->setCurrentCell(i, 1); + QMessageBox::warning(this, tr("Error"), tr("Invalid regular expression!"), QMessageBox::Close); + return false; + } + } + QApplication::setOverrideCursor(Qt::WaitCursor); + searchMatchedFiles(); + QApplication::restoreOverrideCursor(); + return true; + } + + return true; +} + +bool AddTestCasesWizard::compareFileName(const QString &a, const QString &b) +{ + return a.length() < b.length() || a.length() == b.length() && QString::localeAwareCompare(a, b) < 0; +} diff --git a/addtestcaseswizard.h b/addtestcaseswizard.h index 80a7b52..8a06ae0 100644 --- a/addtestcaseswizard.h +++ b/addtestcaseswizard.h @@ -1,74 +1,74 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef ADDTESTCASESWIZARD_H -#define ADDTESTCASESWIZARD_H - -#include -#include -#include - -namespace Ui { - class AddTestCasesWizard; -} - -class Settings; - -class AddTestCasesWizard : public QWizard -{ - Q_OBJECT - -public: - explicit AddTestCasesWizard(QWidget *parent = 0); - ~AddTestCasesWizard(); - void setSettings(Settings*, bool); - int getFullScore() const; - int getTimeLimit() const; - int getMemoryLimit() const; - const QList& getMatchedInputFiles() const; - const QList& getMatchedOutputFiles() const; - -private: - Ui::AddTestCasesWizard *ui; - Settings *settings; - int fullScore; - int timeLimit; - int memoryLimit; - QString inputFilesPattern; - QString outputFilesPattern; - QList matchedInputFiles; - QList matchedOutputFiles; - void refreshButtonState(); - void getFiles(const QString&, const QString&, const QStringList&, QStringList&); - QString getFullRegExp(const QString&); - QStringList getMatchedPart(const QString&, const QString&); - void searchMatchedFiles(); - bool validateCurrentPage(); - static bool compareFileName(const QString&, const QString&); - -private slots: - void fullScoreChanged(const QString&); - void timeLimitChanged(const QString&); - void memoryLimitChanged(const QString&); - void inputFilesPatternChanged(const QString&); - void outputFilesPatternChanged(const QString&); - void addArgument(); - void deleteArgument(); -}; - -#endif // ADDTESTCASESWIZARD_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef ADDTESTCASESWIZARD_H +#define ADDTESTCASESWIZARD_H + +#include +#include +#include + +namespace Ui { + class AddTestCasesWizard; +} + +class Settings; + +class AddTestCasesWizard : public QWizard +{ + Q_OBJECT + +public: + explicit AddTestCasesWizard(QWidget *parent = 0); + ~AddTestCasesWizard(); + void setSettings(Settings*, bool); + int getFullScore() const; + int getTimeLimit() const; + int getMemoryLimit() const; + const QList& getMatchedInputFiles() const; + const QList& getMatchedOutputFiles() const; + +private: + Ui::AddTestCasesWizard *ui; + Settings *settings; + int fullScore; + int timeLimit; + int memoryLimit; + QString inputFilesPattern; + QString outputFilesPattern; + QList matchedInputFiles; + QList matchedOutputFiles; + void refreshButtonState(); + void getFiles(const QString&, const QString&, const QStringList&, QStringList&); + QString getFullRegExp(const QString&); + QStringList getMatchedPart(const QString&, const QString&); + void searchMatchedFiles(); + bool validateCurrentPage(); + static bool compareFileName(const QString&, const QString&); + +private slots: + void fullScoreChanged(const QString&); + void timeLimitChanged(const QString&); + void memoryLimitChanged(const QString&); + void inputFilesPatternChanged(const QString&); + void outputFilesPatternChanged(const QString&); + void addArgument(); + void deleteArgument(); +}; + +#endif // ADDTESTCASESWIZARD_H diff --git a/addtestcaseswizard.ui b/addtestcaseswizard.ui index 06ca5e3..fd0942a 100644 --- a/addtestcaseswizard.ui +++ b/addtestcaseswizard.ui @@ -1,462 +1,479 @@ - - - AddTestCasesWizard - - - - 0 - 0 - 459 - 372 - - - - - 459 - 372 - - - - Add Test Cases - - - - - 12 - - - - - font-size: 10pt; -font-weight: bold; - - - Step I: Input the full score, time limit and memory limit for each new test case. - - - true - - - - - - - 12 - - - 10 - - - - - font-size: 9pt; - - - - Full Score - - - - - - - - - - 73 - 22 - - - - - 73 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - font-size: 9pt; - - - - Time Limit - - - - - - - 10 - - - - - - 58 - 22 - - - - - 58 - 22 - - - - - - - - font-size: 9pt; - - - - ms - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - font-size: 9pt; - - - - Memory Limit - - - - - - - 10 - - - - - - 58 - 22 - - - - - 58 - 22 - - - - - - - - font-size: 9pt; - - - - MB - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 141 - - - - - - - - - - 10 - - - - - font-size: 10pt; -font-weight: bold; - - - Step II: Input patterns for input files and output files. You can use argument <1>, <2>, etc. to represent a regular expression. Input and output files will in the same test case when their matched parts of checked expressions are identical. - - - true - - - - - - - 12 - - - 9 - - - - - font-size: 9pt; - - - - Input Files Pattern - - - - - - - - - - font-size: 9pt; - - - - Output Files Pattern - - - - - - - - - - - - 10 - - - - - font-size: 9pt; - - - QAbstractItemView::SingleSelection - - - false - - - 70 - - - true - - - false - - - 25 - - - 25 - - - - Argument - - - - 9 - - - - - - Regular Expression - - - - 9 - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 27 - 27 - - - - - 27 - 27 - - - - - - - - :/icon/add.ico:/icon/add.ico - - - - - - - - 27 - 27 - - - - - 27 - 27 - - - - - - - - :/icon/rod.ico:/icon/rod.ico - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - 10 - - - - - font-size: 10pt; -font-weight: bold; - - - Step III: Preview the result and finish the wizard. - - - true - - - - - - - 2 - - - false - - - - 1 - - - - - 2 - - - - - - - - - - - - + + + AddTestCasesWizard + + + + 0 + 0 + 459 + 372 + + + + + 459 + 372 + + + + Add Test Cases + + + + + 12 + + + + + font-size: 10pt; +font-weight: bold; + + + Step I: Input the full score, time limit and memory limit for each new test case. + + + true + + + + + + + 12 + + + 10 + + + + + font-size: 9pt; + + + + Full Score + + + + + + + + + + 73 + 22 + + + + + 73 + 22 + + + + font-size:9pt; + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + font-size: 9pt; + + + + Time Limit + + + + + + + 10 + + + + + + 58 + 22 + + + + + 58 + 22 + + + + font-size:9pt; + + + + + + + font-size: 9pt; + + + + ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + font-size: 9pt; + + + + Memory Limit + + + + + + + 10 + + + + + + 58 + 22 + + + + + 58 + 22 + + + + font-size:9pt; + + + + + + + font-size: 9pt; + + + + MB + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 141 + + + + + + + + + + 10 + + + + + font-size: 10pt; +font-weight: bold; + + + Step II: Input patterns for input files and output files. You can use argument <1>, <2>, etc. to represent a regular expression. Input and output files will in the same test case when their matched parts of checked expressions are identical. + + + true + + + + + + + 12 + + + 9 + + + + + font-size: 9pt; + + + + Input Files Pattern + + + + + + + font-size:9pt; + + + + + + + font-size: 9pt; + + + + Output Files Pattern + + + + + + + font-size:9pt; + + + + + + + + + 10 + + + + + font-size: 9pt; + + + QAbstractItemView::SingleSelection + + + false + + + 70 + + + true + + + false + + + 25 + + + 25 + + + + Argument + + + + 9 + + + + + + Regular Expression + + + + 9 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 27 + 27 + + + + + 27 + 27 + + + + + + + + :/icon/add.png:/icon/add.png + + + + + + + + 27 + 27 + + + + + 27 + 27 + + + + + + + + :/icon/rod.png:/icon/rod.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 10 + + + + + font-size: 10pt; +font-weight: bold; + + + Step III: Preview the result and finish the wizard. + + + true + + + + + + + 2 + + + false + + + + 1 + + + + + 2 + + + + + + + + + + + + diff --git a/advancedcompilersettingsdialog.cpp b/advancedcompilersettingsdialog.cpp index 2b9efaf..0b04b42 100644 --- a/advancedcompilersettingsdialog.cpp +++ b/advancedcompilersettingsdialog.cpp @@ -1,317 +1,318 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "advancedcompilersettingsdialog.h" -#include "ui_advancedcompilersettingsdialog.h" -#include "environmentvariablesdialog.h" -#include "compiler.h" - -AdvancedCompilerSettingsDialog::AdvancedCompilerSettingsDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::AdvancedCompilerSettingsDialog) -{ - ui->setupUi(this); - - editCompiler = new Compiler(this); - ui->bytecodeExtension->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->bytecodeExtension)); - ui->configurationSelect->setLineEdit(new QLineEdit(this)); - - connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), - this, SLOT(okayButtonClicked())); - connect(ui->typeSelect, SIGNAL(currentIndexChanged(int)), - this, SLOT(compilerTypeChanged())); - connect(ui->compilerLocation, SIGNAL(textChanged(QString)), - this, SLOT(compilerLocationChanged())); - connect(ui->interpreterLocation, SIGNAL(textChanged(QString)), - this, SLOT(interpreterLocationChanged())); - connect(ui->compilerSelectButton, SIGNAL(clicked()), - this, SLOT(selectCompilerLocation())); - connect(ui->interpreterSelectButton, SIGNAL(clicked()), - this, SLOT(selectInterpreterLocation())); - connect(ui->bytecodeExtension, SIGNAL(textChanged(QString)), - this, SLOT(bytecodeExtensionsChanged())); - connect(ui->timeLimitRatio, SIGNAL(valueChanged(double)), - this, SLOT(timeLimitRatioChanged())); - connect(ui->memoryLimitRatio, SIGNAL(valueChanged(double)), - this, SLOT(memoryLimitRatioChanged())); - connect(ui->disableMemoryLimit, SIGNAL(stateChanged(int)), - this, SLOT(disableMemoryLimitCheckChanged())); - connect(ui->configurationSelect, SIGNAL(currentIndexChanged(int)), - this, SLOT(configurationIndexChanged())); - connect(ui->configurationSelect, SIGNAL(editTextChanged(QString)), - this, SLOT(configurationTextChanged())); - connect(ui->deleteConfigurationButton, SIGNAL(clicked()), - this, SLOT(deleteConfiguration())); - connect(ui->compilerArguments, SIGNAL(textChanged(QString)), - this, SLOT(compilerArgumentsChanged())); - connect(ui->interpreterArguments, SIGNAL(textChanged(QString)), - this, SLOT(interpreterArgumentsChanged())); - connect(ui->environmentVariablesButton, SIGNAL(clicked()), - this, SLOT(environmentVariablesButtonClicked())); -} - -AdvancedCompilerSettingsDialog::~AdvancedCompilerSettingsDialog() -{ - delete ui; -} - -void AdvancedCompilerSettingsDialog::resetEditCompiler(Compiler *compiler) -{ - configCount = 0; - editCompiler->copyFrom(compiler); - ui->typeSelect->setCurrentIndex(int(editCompiler->getCompilerType())); - compilerTypeChanged(); - ui->compilerLocation->setText(editCompiler->getCompilerLocation()); - ui->interpreterLocation->setText(editCompiler->getInterpreterLocation()); - ui->bytecodeExtension->setText(editCompiler->getBytecodeExtensions().join(";")); - ui->timeLimitRatio->setValue(editCompiler->getTimeLimitRatio()); - ui->memoryLimitRatio->setValue(editCompiler->getMemoryLimitRatio()); - ui->disableMemoryLimit->setChecked(editCompiler->getDisableMemoryLimitCheck()); - ui->memoryLimitRatio->setEnabled(! editCompiler->getDisableMemoryLimitCheck()); - QStringList configurationNames = editCompiler->getConfigurationNames(); - ui->configurationSelect->setEnabled(false); - for (int i = 0; i < configurationNames.size(); i ++) - ui->configurationSelect->addItem(configurationNames[i]); - ui->configurationSelect->addItem(tr("Add new ...")); - ui->configurationSelect->setEnabled(true); - ui->configurationSelect->setCurrentIndex(0); - configurationIndexChanged(); -} - -Compiler* AdvancedCompilerSettingsDialog::getEditCompiler() const -{ - return editCompiler; -} - -void AdvancedCompilerSettingsDialog::okayButtonClicked() -{ - if (ui->compilerLocation->isEnabled() && ui->compilerLocation->text().isEmpty()) { - ui->compilerLocation->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty compiler\'s Location!"), QMessageBox::Close); - return; - } - if (ui->interpreterLocation->isEnabled() && ui->interpreterLocation->text().isEmpty()) { - ui->interpreterLocation->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty interpreter\'s Location!"), QMessageBox::Close); - return; - } - if (ui->bytecodeExtension->isEnabled() && ui->bytecodeExtension->text().isEmpty()) { - ui->bytecodeExtension->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty Byte-code Extensions!"), QMessageBox::Close); - return; - } - const QStringList &configurationNames = editCompiler->getConfigurationNames(); - for (int j = 0; j < configurationNames.size(); j ++) { - if (configurationNames[j].isEmpty()) { - ui->configurationSelect->setCurrentIndex(j); - ui->configurationSelect->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty configuration name!"), QMessageBox::Close); - return; - } - if (configurationNames.count(configurationNames[j]) > 1) { - ui->configurationSelect->setCurrentIndex(j); - ui->configurationSelect->setFocus(); - QMessageBox::warning(this, tr("Error"), - tr("Configuration %1 appears more than once!").arg(configurationNames[j]), - QMessageBox::Close); - return; - } - if (configurationNames[j] == "disable") { - ui->configurationSelect->setCurrentIndex(j); - ui->configurationSelect->setFocus(); - QMessageBox::warning(this, tr("Error"),tr("Invalid configuration name \"disable\"!"), QMessageBox::Close); - return; - } - } - accept(); -} - -void AdvancedCompilerSettingsDialog::compilerTypeChanged() -{ - editCompiler->setCompilerType((Compiler::CompilerType)ui->typeSelect->currentIndex()); - - if (editCompiler->getCompilerType() == Compiler::Typical) { - ui->interpreterLabel->setEnabled(false); - ui->interpreterLocation->setEnabled(false); - ui->interpreterSelectButton->setEnabled(false); - ui->interpreterArgumentsLabel->setEnabled(false); - ui->interpreterArguments->setEnabled(false); - } else { - ui->interpreterLabel->setEnabled(true); - ui->interpreterLocation->setEnabled(true); - ui->interpreterSelectButton->setEnabled(true); - ui->interpreterArgumentsLabel->setEnabled(true); - ui->interpreterArguments->setEnabled(true); - } - - if (editCompiler->getCompilerType() == Compiler::InterpretiveWithByteCode) { - ui->bytecodeExtensionLabel->setEnabled(true); - ui->bytecodeExtension->setEnabled(true); - } else { - ui->bytecodeExtensionLabel->setEnabled(false); - ui->bytecodeExtension->setEnabled(false); - } - - if (editCompiler->getCompilerType() == Compiler::InterpretiveWithoutByteCode) { - ui->compilerLabel->setEnabled(false); - ui->compilerLocation->setEnabled(false); - ui->compilerSelectButton->setEnabled(false); - ui->compilerArgumentsLabel->setEnabled(false); - ui->compilerArguments->setEnabled(false); - } else { - ui->compilerLabel->setEnabled(true); - ui->compilerLocation->setEnabled(true); - ui->compilerSelectButton->setEnabled(true); - ui->compilerArgumentsLabel->setEnabled(true); - ui->compilerArguments->setEnabled(true); - } -} - -void AdvancedCompilerSettingsDialog::compilerLocationChanged() -{ - editCompiler->setCompilerLocation(ui->compilerLocation->text()); -} - -void AdvancedCompilerSettingsDialog::interpreterLocationChanged() -{ - editCompiler->setInterpreterLocation(ui->interpreterLocation->text()); -} - -void AdvancedCompilerSettingsDialog::selectCompilerLocation() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), tr("Executable files (*.exe)")); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), - QDir::rootPath(), tr("Executable files (*.*)")); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->compilerLocation->setText(location); - } -} - -void AdvancedCompilerSettingsDialog::selectInterpreterLocation() -{ -#ifdef Q_OS_WIN32 - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), tr("Executable files (*.exe)")); -#endif - -#ifdef Q_OS_LINUX - QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), - QDir::rootPath(), tr("Executable files (*.*)")); -#endif - if (! location.isEmpty()) { - location = location.replace('/', QDir::separator()); - ui->interpreterLocation->setText(location); - } -} - -void AdvancedCompilerSettingsDialog::bytecodeExtensionsChanged() -{ - editCompiler->setBytecodeExtensions(ui->bytecodeExtension->text()); -} - -void AdvancedCompilerSettingsDialog::timeLimitRatioChanged() -{ - editCompiler->setTimeLimitRatio(ui->timeLimitRatio->value()); -} - -void AdvancedCompilerSettingsDialog::memoryLimitRatioChanged() -{ - editCompiler->setMemoryLimitRatio(ui->memoryLimitRatio->value()); -} - -void AdvancedCompilerSettingsDialog::disableMemoryLimitCheckChanged() -{ - bool check = ui->disableMemoryLimit->isChecked(); - editCompiler->setDisableMemoryLimitCheck(check); - ui->memoryLimitRatio->setEnabled(! check); -} - -void AdvancedCompilerSettingsDialog::configurationIndexChanged() -{ - if (! ui->configurationSelect->isEnabled()) return; - int index = ui->configurationSelect->currentIndex(); - if (index == -1) return; - if (index == ui->configurationSelect->count() - 1) { - ui->configurationSelect->setItemText(index, tr("New configuration %1").arg(++ configCount)); - editCompiler->addConfiguration(ui->configurationSelect->currentText(), "", ""); - ui->compilerArguments->clear(); - ui->interpreterArguments->clear(); - ui->configurationSelect->addItem(tr("Add new ...")); - ui->configurationSelect->lineEdit()->setSelection(0, ui->configurationSelect->currentText().length()); - } else { - ui->configurationSelect->lineEdit()->setText(ui->configurationSelect->itemText(index)); - ui->compilerArguments->setText(editCompiler->getCompilerArguments().at(index)); - ui->interpreterArguments->setText(editCompiler->getInterpreterArguments().at(index)); - } - ui->deleteConfigurationButton->setEnabled(index > 0); -} - -void AdvancedCompilerSettingsDialog::configurationTextChanged() -{ - if (! ui->configurationSelect->isEnabled()) return; - if (ui->configurationSelect->currentIndex() == 0) { - if (ui->configurationSelect->lineEdit()->text() != "default") - ui->configurationSelect->lineEdit()->setText("default"); - } else { - ui->configurationSelect->setItemText(ui->configurationSelect->currentIndex(), - ui->configurationSelect->lineEdit()->text()); - editCompiler->setConfigName(ui->configurationSelect->currentIndex(), - ui->configurationSelect->lineEdit()->text()); - } -} - -void AdvancedCompilerSettingsDialog::deleteConfiguration() -{ - int index = ui->configurationSelect->currentIndex(); - if (index + 1 < ui->configurationSelect->count() - 1) - ui->configurationSelect->setCurrentIndex(index + 1); - else - ui->configurationSelect->setCurrentIndex(index - 1); - editCompiler->deleteConfiguration(index); - ui->configurationSelect->removeItem(index); -} - -void AdvancedCompilerSettingsDialog::compilerArgumentsChanged() -{ - if (! ui->configurationSelect->isEnabled()) return; - int index = ui->configurationSelect->currentIndex(); - editCompiler->setCompilerArguments(index, ui->compilerArguments->text()); -} - -void AdvancedCompilerSettingsDialog::interpreterArgumentsChanged() -{ - if (! ui->configurationSelect->isEnabled()) return; - int index = ui->configurationSelect->currentIndex(); - editCompiler->setInterpreterArguments(index, ui->interpreterArguments->text()); -} - -void AdvancedCompilerSettingsDialog::environmentVariablesButtonClicked() -{ - EnvironmentVariablesDialog *dialog = new EnvironmentVariablesDialog(this); - dialog->setProcessEnvironment(editCompiler->getEnvironment()); - if (dialog->exec() == QDialog::Accepted) - editCompiler->setEnvironment(dialog->getProcessEnvironment()); - delete dialog; -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "advancedcompilersettingsdialog.h" +#include "ui_advancedcompilersettingsdialog.h" +#include "environmentvariablesdialog.h" +#include "compiler.h" + +AdvancedCompilerSettingsDialog::AdvancedCompilerSettingsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AdvancedCompilerSettingsDialog) +{ + ui->setupUi(this); + + editCompiler = new Compiler(this); + ui->bytecodeExtension->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->bytecodeExtension)); + ui->configurationSelect->setLineEdit(new QLineEdit(this)); + + connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), + this, SLOT(okayButtonClicked())); + connect(ui->typeSelect, SIGNAL(currentIndexChanged(int)), + this, SLOT(compilerTypeChanged())); + connect(ui->compilerLocation, SIGNAL(textChanged(QString)), + this, SLOT(compilerLocationChanged())); + connect(ui->interpreterLocation, SIGNAL(textChanged(QString)), + this, SLOT(interpreterLocationChanged())); + connect(ui->compilerSelectButton, SIGNAL(clicked()), + this, SLOT(selectCompilerLocation())); + connect(ui->interpreterSelectButton, SIGNAL(clicked()), + this, SLOT(selectInterpreterLocation())); + connect(ui->bytecodeExtension, SIGNAL(textChanged(QString)), + this, SLOT(bytecodeExtensionsChanged())); + connect(ui->timeLimitRatio, SIGNAL(valueChanged(double)), + this, SLOT(timeLimitRatioChanged())); + connect(ui->memoryLimitRatio, SIGNAL(valueChanged(double)), + this, SLOT(memoryLimitRatioChanged())); + connect(ui->disableMemoryLimit, SIGNAL(stateChanged(int)), + this, SLOT(disableMemoryLimitCheckChanged())); + connect(ui->configurationSelect, SIGNAL(currentIndexChanged(int)), + this, SLOT(configurationIndexChanged())); + connect(ui->configurationSelect, SIGNAL(editTextChanged(QString)), + this, SLOT(configurationTextChanged())); + connect(ui->deleteConfigurationButton, SIGNAL(clicked()), + this, SLOT(deleteConfiguration())); + connect(ui->compilerArguments, SIGNAL(textChanged(QString)), + this, SLOT(compilerArgumentsChanged())); + connect(ui->interpreterArguments, SIGNAL(textChanged(QString)), + this, SLOT(interpreterArgumentsChanged())); + connect(ui->environmentVariablesButton, SIGNAL(clicked()), + this, SLOT(environmentVariablesButtonClicked())); +} + +AdvancedCompilerSettingsDialog::~AdvancedCompilerSettingsDialog() +{ + delete ui; +} + +void AdvancedCompilerSettingsDialog::resetEditCompiler(Compiler *compiler) +{ + configCount = 0; + editCompiler->copyFrom(compiler); + ui->typeSelect->setCurrentIndex(int(editCompiler->getCompilerType())); + compilerTypeChanged(); + ui->compilerLocation->setText(editCompiler->getCompilerLocation()); + ui->interpreterLocation->setText(editCompiler->getInterpreterLocation()); + ui->bytecodeExtension->setText(editCompiler->getBytecodeExtensions().join(";")); + ui->timeLimitRatio->setValue(editCompiler->getTimeLimitRatio()); + ui->memoryLimitRatio->setValue(editCompiler->getMemoryLimitRatio()); + ui->disableMemoryLimit->setChecked(editCompiler->getDisableMemoryLimitCheck()); + ui->memoryLimitRatio->setEnabled(! editCompiler->getDisableMemoryLimitCheck()); + QStringList configurationNames = editCompiler->getConfigurationNames(); + ui->configurationSelect->setEnabled(false); + for (int i = 0; i < configurationNames.size(); i ++) + ui->configurationSelect->addItem(configurationNames[i]); + ui->configurationSelect->addItem(tr("Add new ...")); + ui->configurationSelect->setEnabled(true); + ui->configurationSelect->setCurrentIndex(0); + configurationIndexChanged(); +} + +Compiler* AdvancedCompilerSettingsDialog::getEditCompiler() const +{ + return editCompiler; +} + +void AdvancedCompilerSettingsDialog::okayButtonClicked() +{ + if (ui->compilerLocation->isEnabled() && ui->compilerLocation->text().isEmpty()) { + ui->compilerLocation->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty compiler\'s Location!"), QMessageBox::Close); + return; + } + if (ui->interpreterLocation->isEnabled() && ui->interpreterLocation->text().isEmpty()) { + ui->interpreterLocation->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty interpreter\'s Location!"), QMessageBox::Close); + return; + } + if (ui->bytecodeExtension->isEnabled() && ui->bytecodeExtension->text().isEmpty()) { + ui->bytecodeExtension->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty Byte-code Extensions!"), QMessageBox::Close); + return; + } + const QStringList &configurationNames = editCompiler->getConfigurationNames(); + for (int j = 0; j < configurationNames.size(); j ++) { + if (configurationNames[j].isEmpty()) { + ui->configurationSelect->setCurrentIndex(j); + ui->configurationSelect->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty configuration name!"), QMessageBox::Close); + return; + } + if (configurationNames.count(configurationNames[j]) > 1) { + ui->configurationSelect->setCurrentIndex(j); + ui->configurationSelect->setFocus(); + QMessageBox::warning(this, tr("Error"), + tr("Configuration %1 appears more than once!").arg(configurationNames[j]), + QMessageBox::Close); + return; + } + if (configurationNames[j] == "disable") { + ui->configurationSelect->setCurrentIndex(j); + ui->configurationSelect->setFocus(); + QMessageBox::warning(this, tr("Error"),tr("Invalid configuration name \"disable\"!"), QMessageBox::Close); + return; + } + } + accept(); +} + +void AdvancedCompilerSettingsDialog::compilerTypeChanged() +{ + editCompiler->setCompilerType((Compiler::CompilerType)ui->typeSelect->currentIndex()); + + if (editCompiler->getCompilerType() == Compiler::Typical) { + ui->interpreterLabel->setEnabled(false); + ui->interpreterLocation->setEnabled(false); + ui->interpreterSelectButton->setEnabled(false); + ui->interpreterArgumentsLabel->setEnabled(false); + ui->interpreterArguments->setEnabled(false); + } else { + ui->interpreterLabel->setEnabled(true); + ui->interpreterLocation->setEnabled(true); + ui->interpreterSelectButton->setEnabled(true); + ui->interpreterArgumentsLabel->setEnabled(true); + ui->interpreterArguments->setEnabled(true); + } + + if (editCompiler->getCompilerType() == Compiler::InterpretiveWithByteCode) { + ui->bytecodeExtensionLabel->setEnabled(true); + ui->bytecodeExtension->setEnabled(true); + } else { + ui->bytecodeExtensionLabel->setEnabled(false); + ui->bytecodeExtension->setEnabled(false); + } + + if (editCompiler->getCompilerType() == Compiler::InterpretiveWithoutByteCode) { + ui->compilerLabel->setEnabled(false); + ui->compilerLocation->setEnabled(false); + ui->compilerSelectButton->setEnabled(false); + ui->compilerArgumentsLabel->setEnabled(false); + ui->compilerArguments->setEnabled(false); + } else { + ui->compilerLabel->setEnabled(true); + ui->compilerLocation->setEnabled(true); + ui->compilerSelectButton->setEnabled(true); + ui->compilerArgumentsLabel->setEnabled(true); + ui->compilerArguments->setEnabled(true); + } +} + +void AdvancedCompilerSettingsDialog::compilerLocationChanged() +{ + editCompiler->setCompilerLocation(ui->compilerLocation->text()); +} + +void AdvancedCompilerSettingsDialog::interpreterLocationChanged() +{ + editCompiler->setInterpreterLocation(ui->interpreterLocation->text()); +} + +void AdvancedCompilerSettingsDialog::selectCompilerLocation() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), tr("Executable files (*.exe)")); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Compiler\'s Location"), + QDir::rootPath(), tr("Executable files (*.*)")); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->compilerLocation->setText(location); + } +} + +void AdvancedCompilerSettingsDialog::selectInterpreterLocation() +{ +#ifdef Q_OS_WIN32 + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), tr("Executable files (*.exe)")); +#endif + +#ifdef Q_OS_LINUX + QString location = QFileDialog::getOpenFileName(this, tr("Select Interpreter\'s Location"), + QDir::rootPath(), tr("Executable files (*.*)")); +#endif + if (! location.isEmpty()) { + location = location.replace('/', QDir::separator()); + ui->interpreterLocation->setText(location); + } +} + +void AdvancedCompilerSettingsDialog::bytecodeExtensionsChanged() +{ + editCompiler->setBytecodeExtensions(ui->bytecodeExtension->text()); +} + +void AdvancedCompilerSettingsDialog::timeLimitRatioChanged() +{ + editCompiler->setTimeLimitRatio(ui->timeLimitRatio->value()); +} + +void AdvancedCompilerSettingsDialog::memoryLimitRatioChanged() +{ + editCompiler->setMemoryLimitRatio(ui->memoryLimitRatio->value()); +} + +void AdvancedCompilerSettingsDialog::disableMemoryLimitCheckChanged() +{ + bool check = ui->disableMemoryLimit->isChecked(); + editCompiler->setDisableMemoryLimitCheck(check); + ui->memoryLimitRatioLabel->setEnabled(! check); + ui->memoryLimitRatio->setEnabled(! check); +} + +void AdvancedCompilerSettingsDialog::configurationIndexChanged() +{ + if (! ui->configurationSelect->isEnabled()) return; + int index = ui->configurationSelect->currentIndex(); + if (index == -1) return; + if (index == ui->configurationSelect->count() - 1) { + ui->configurationSelect->setItemText(index, tr("New configuration %1").arg(++ configCount)); + editCompiler->addConfiguration(ui->configurationSelect->currentText(), "", ""); + ui->compilerArguments->clear(); + ui->interpreterArguments->clear(); + ui->configurationSelect->addItem(tr("Add new ...")); + ui->configurationSelect->lineEdit()->setSelection(0, ui->configurationSelect->currentText().length()); + } else { + ui->configurationSelect->lineEdit()->setText(ui->configurationSelect->itemText(index)); + ui->compilerArguments->setText(editCompiler->getCompilerArguments().at(index)); + ui->interpreterArguments->setText(editCompiler->getInterpreterArguments().at(index)); + } + ui->deleteConfigurationButton->setEnabled(index > 0); +} + +void AdvancedCompilerSettingsDialog::configurationTextChanged() +{ + if (! ui->configurationSelect->isEnabled()) return; + if (ui->configurationSelect->currentIndex() == 0) { + if (ui->configurationSelect->lineEdit()->text() != "default") + ui->configurationSelect->lineEdit()->setText("default"); + } else { + ui->configurationSelect->setItemText(ui->configurationSelect->currentIndex(), + ui->configurationSelect->lineEdit()->text()); + editCompiler->setConfigName(ui->configurationSelect->currentIndex(), + ui->configurationSelect->lineEdit()->text()); + } +} + +void AdvancedCompilerSettingsDialog::deleteConfiguration() +{ + int index = ui->configurationSelect->currentIndex(); + if (index + 1 < ui->configurationSelect->count() - 1) + ui->configurationSelect->setCurrentIndex(index + 1); + else + ui->configurationSelect->setCurrentIndex(index - 1); + editCompiler->deleteConfiguration(index); + ui->configurationSelect->removeItem(index); +} + +void AdvancedCompilerSettingsDialog::compilerArgumentsChanged() +{ + if (! ui->configurationSelect->isEnabled()) return; + int index = ui->configurationSelect->currentIndex(); + editCompiler->setCompilerArguments(index, ui->compilerArguments->text()); +} + +void AdvancedCompilerSettingsDialog::interpreterArgumentsChanged() +{ + if (! ui->configurationSelect->isEnabled()) return; + int index = ui->configurationSelect->currentIndex(); + editCompiler->setInterpreterArguments(index, ui->interpreterArguments->text()); +} + +void AdvancedCompilerSettingsDialog::environmentVariablesButtonClicked() +{ + EnvironmentVariablesDialog *dialog = new EnvironmentVariablesDialog(this); + dialog->setProcessEnvironment(editCompiler->getEnvironment()); + if (dialog->exec() == QDialog::Accepted) + editCompiler->setEnvironment(dialog->getProcessEnvironment()); + delete dialog; +} diff --git a/advancedcompilersettingsdialog.h b/advancedcompilersettingsdialog.h index efb5909..4b2afa6 100644 --- a/advancedcompilersettingsdialog.h +++ b/advancedcompilersettingsdialog.h @@ -1,66 +1,66 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef ADVANCEDCOMPILERSETTINGSDIALOG_H -#define ADVANCEDCOMPILERSETTINGSDIALOG_H - -#include -#include -#include - -class Compiler; - -namespace Ui { - class AdvancedCompilerSettingsDialog; -} - -class AdvancedCompilerSettingsDialog : public QDialog -{ - Q_OBJECT - -public: - explicit AdvancedCompilerSettingsDialog(QWidget *parent = 0); - ~AdvancedCompilerSettingsDialog(); - void resetEditCompiler(Compiler*); - Compiler* getEditCompiler() const; - -private: - Ui::AdvancedCompilerSettingsDialog *ui; - Compiler *editCompiler; - int configCount; - -private slots: - void okayButtonClicked(); - void compilerTypeChanged(); - void compilerLocationChanged(); - void interpreterLocationChanged(); - void selectCompilerLocation(); - void selectInterpreterLocation(); - void bytecodeExtensionsChanged(); - void timeLimitRatioChanged(); - void memoryLimitRatioChanged(); - void disableMemoryLimitCheckChanged(); - void configurationIndexChanged(); - void configurationTextChanged(); - void deleteConfiguration(); - void compilerArgumentsChanged(); - void interpreterArgumentsChanged(); - void environmentVariablesButtonClicked(); -}; - -#endif // ADVANCEDCOMPILERSETTINGSDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef ADVANCEDCOMPILERSETTINGSDIALOG_H +#define ADVANCEDCOMPILERSETTINGSDIALOG_H + +#include +#include +#include + +class Compiler; + +namespace Ui { + class AdvancedCompilerSettingsDialog; +} + +class AdvancedCompilerSettingsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AdvancedCompilerSettingsDialog(QWidget *parent = 0); + ~AdvancedCompilerSettingsDialog(); + void resetEditCompiler(Compiler*); + Compiler* getEditCompiler() const; + +private: + Ui::AdvancedCompilerSettingsDialog *ui; + Compiler *editCompiler; + int configCount; + +private slots: + void okayButtonClicked(); + void compilerTypeChanged(); + void compilerLocationChanged(); + void interpreterLocationChanged(); + void selectCompilerLocation(); + void selectInterpreterLocation(); + void bytecodeExtensionsChanged(); + void timeLimitRatioChanged(); + void memoryLimitRatioChanged(); + void disableMemoryLimitCheckChanged(); + void configurationIndexChanged(); + void configurationTextChanged(); + void deleteConfiguration(); + void compilerArgumentsChanged(); + void interpreterArgumentsChanged(); + void environmentVariablesButtonClicked(); +}; + +#endif // ADVANCEDCOMPILERSETTINGSDIALOG_H diff --git a/advancedcompilersettingsdialog.ui b/advancedcompilersettingsdialog.ui index 0eeda40..1e95141 100644 --- a/advancedcompilersettingsdialog.ui +++ b/advancedcompilersettingsdialog.ui @@ -1,376 +1,379 @@ - - - AdvancedCompilerSettingsDialog - - - - 0 - 0 - 296 - 442 - - - - Compiler Settings - - - - - - - - - 211 - 20 - - - - - Typical (Generate executable file) - - - - - Interpretive (Generate byte-code file) - - - - - Interpretive (Run source code directly) - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - font-size:9pt; - - - Location - - - - 8 - - - 6 - - - - - font-size:9pt; -font-weight:bold; - - - Compiler - - - - - - - - - - ... - - - - - - - font-size:9pt; -font-weight:bold; - - - Interpreter - - - - - - - - - - ... - - - - - - - font-size:9pt; -font-weight:bold; - - - Byte-code File Extensions - - - - - - - - 50 - 20 - - - - - - - - - - - font-size:9pt; - - - Time and Memory Limit - - - - 8 - - - 6 - - - - - font-size:9pt; -font-weight:bold; - - - Time Limit Ration - - - - - - - 1 - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - Qt::Horizontal - - - - 57 - 20 - - - - - - - - font-size:9pt; -font-weight:bold; - - - Memory Limit Ration - - - - - - - 1 - - - 1.000000000000000 - - - 0.100000000000000 - - - - - - - Qt::Horizontal - - - - 57 - 20 - - - - - - - - font-size:8pt; - - - Disable Memory Limit - - - - - - - - - - font-size:9pt; - - - Arguments - - - - 8 - - - 6 - - - - - font-size:9pt; -font-weight:bold; - - - Configuration - - - - - - - - - - - 23 - 23 - - - - ... - - - - :/icon/cross.png:/icon/cross.png - - - - - - - font-size:9pt; -font-weight:bold; - - - Compiler's Arguments - - - - - - - - - - font-size:9pt; -font-weight:bold; - - - Interpreter's Arguments - - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Environment Variables - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - rejected() - AdvancedCompilerSettingsDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - + + + AdvancedCompilerSettingsDialog + + + + 0 + 0 + 296 + 442 + + + + Compiler Settings + + + + + + + + + 211 + 20 + + + + font-size:9pt; + + + + Typical (Generate executable file) + + + + + Interpretive (Generate byte-code file) + + + + + Interpretive (Run source code directly) + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + font-size:9pt; + + + Location + + + + 8 + + + 6 + + + + + font-size:9pt; +font-weight:bold; + + + Compiler + + + + + + + + + + ... + + + + + + + font-size:9pt; +font-weight:bold; + + + Interpreter + + + + + + + + + + ... + + + + + + + font-size:9pt; +font-weight:bold; + + + Byte-code File Extensions + + + + + + + + 50 + 20 + + + + + + + + + + + font-size:9pt; + + + Time and Memory Limit + + + + 8 + + + 6 + + + + + font-size:9pt; +font-weight:bold; + + + Time Limit Ration + + + + + + + 1 + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + Qt::Horizontal + + + + 57 + 20 + + + + + + + + font-size:9pt; +font-weight:bold; + + + Memory Limit Ration + + + + + + + 1 + + + 1.000000000000000 + + + 0.100000000000000 + + + + + + + Qt::Horizontal + + + + 57 + 20 + + + + + + + + font-size:8pt; + + + Disable Memory Limit + + + + + + + + + + font-size:9pt; + + + Arguments + + + + 8 + + + 6 + + + + + font-size:9pt; +font-weight:bold; + + + Configuration + + + + + + + + + + + 23 + 23 + + + + ... + + + + :/icon/cross.png:/icon/cross.png + + + + + + + font-size:9pt; +font-weight:bold; + + + Compiler's Arguments + + + + + + + + + + font-size:9pt; +font-weight:bold; + + + Interpreter's Arguments + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Environment Variables + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + rejected() + AdvancedCompilerSettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/assignmentthread.cpp b/assignmentthread.cpp index 7b50240..ad431aa 100644 --- a/assignmentthread.cpp +++ b/assignmentthread.cpp @@ -1,386 +1,386 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "assignmentthread.h" -#include "judgingthread.h" -#include "settings.h" -#include "compiler.h" -#include "task.h" -#include "testcase.h" - -AssignmentThread::AssignmentThread(QObject *parent) : - QThread(parent) -{ - moveToThread(this); - checkRejudgeMode = false; - curTestCaseIndex = 0; - curSingleCaseIndex = 0; - countFinished = 0; - totalSingleCase = 0; - stopJudging = false; -} - -void AssignmentThread::setCheckRejudgeMode(bool check) -{ - checkRejudgeMode = check; -} - -void AssignmentThread::setNeedRejudge(const QList > &list) -{ - needRejudge = list; -} - -void AssignmentThread::setSettings(Settings *_settings) -{ - settings = _settings; -} - -void AssignmentThread::setTask(Task *_task) -{ - task = _task; -} - -void AssignmentThread::setContestantName(const QString &name) -{ - contestantName = name; -} - -CompileState AssignmentThread::getCompileState() const -{ - return compileState; -} - -const QString& AssignmentThread::getCompileMessage() const -{ - return compileMessage; -} - -const QString& AssignmentThread::getSourceFile() const -{ - return sourceFile; -} - -const QList< QList >& AssignmentThread::getScore() const -{ - return score; -} - -const QList< QList >& AssignmentThread::getTimeUsed() const -{ - return timeUsed; -} - -const QList< QList >& AssignmentThread::getMemoryUsed() const -{ - return memoryUsed; -} - -const QList< QList >& AssignmentThread::getResult() const -{ - return result; -} - -const QList& AssignmentThread::getMessage() const -{ - return message; -} - -const QList& AssignmentThread::getInputFiles() const -{ - return inputFiles; -} - -const QList< QPair >& AssignmentThread::getNeedRejudge() const -{ - return needRejudge; -} - -bool AssignmentThread::traditionalTaskPrepare() -{ - compileState = NoValidSourceFile; - QDir contestantDir = QDir(Settings::sourcePath() + contestantName); - QList compilerList = settings->getCompilerList(); - - for (int i = 0; i < compilerList.size(); i ++) { - if (task->getCompilerConfiguration(compilerList[i]->getCompilerName()) == "disable") continue; - QStringList filters = compilerList[i]->getSourceExtensions(); - for (int j = 0; j < filters.size(); j ++) - filters[j] = task->getSourceFileName() + "." + filters[j]; - QStringList files = contestantDir.entryList(filters, QDir::Files); - sourceFile = ""; - for (int j = 0; j < files.size(); j ++) { - qint64 fileSize = QFileInfo(Settings::sourcePath() + contestantName + QDir::separator() + files[j]).size(); - if (fileSize <= settings->getFileSizeLimit() * 1024) { - sourceFile = files[j]; - break; - } - } - - if (! sourceFile.isEmpty()) { - QDir(Settings::temporaryPath()).mkdir(contestantName); - QFile::copy(Settings::sourcePath() + contestantName + QDir::separator() + sourceFile, - Settings::temporaryPath() + contestantName + QDir::separator() + sourceFile); - QStringList configurationNames = compilerList[i]->getConfigurationNames(); - QStringList compilerArguments = compilerList[i]->getCompilerArguments(); - QStringList interpreterArguments = compilerList[i]->getInterpreterArguments(); - QString currentConfiguration = task->getCompilerConfiguration(compilerList[i]->getCompilerName()); - for (int j = 0; j < configurationNames.size(); j ++) - if (configurationNames[j] == currentConfiguration) { - timeLimitRatio = compilerList[i]->getTimeLimitRatio(); - memoryLimitRatio = compilerList[i]->getMemoryLimitRatio(); - disableMemoryLimitCheck = compilerList[i]->getDisableMemoryLimitCheck(); - environment = compilerList[i]->getEnvironment(); - QStringList values = environment.toStringList(); - for (int k = 0; k < values.size(); k ++) { - int tmp = values[k].indexOf("="); - QString variable = values[k].mid(0, tmp); - environment.insert(variable, - environment.value(variable) + ";" - + QProcessEnvironment::systemEnvironment().value(variable)); - } - - if (compilerList[i]->getCompilerType() == Compiler::Typical) { -#ifdef Q_OS_WIN32 - executableFile = task->getSourceFileName() + ".exe"; -#endif -#ifdef Q_OS_LINUX - executableFile = task->getSourceFileName(); -#endif - } else { - executableFile = QString("\"") + compilerList[i]->getInterpreterLocation() + "\" "; - QString arguments = interpreterArguments[j]; - arguments.replace("%s.*", sourceFile); - arguments.replace("%s", task->getSourceFileName()); - executableFile += arguments; - } - - if (compilerList[i]->getCompilerType() != Compiler::InterpretiveWithoutByteCode) { - QString arguments = compilerArguments[j]; - arguments.replace("%s.*", sourceFile); - arguments.replace("%s", task->getSourceFileName()); - QProcess *compiler = new QProcess(this); - compiler->setProcessChannelMode(QProcess::MergedChannels); - compiler->setProcessEnvironment(environment); - compiler->setWorkingDirectory(Settings::temporaryPath() + contestantName); - compiler->start(QString("\"") + compilerList[i]->getCompilerLocation() + "\" " + arguments); - if (! compiler->waitForStarted(-1)) { - compileState = InvalidCompiler; - delete compiler; - break; - } - QElapsedTimer timer; - timer.start(); - bool flag = false; - while (timer.elapsed() < settings->getCompileTimeLimit()) { - if (compiler->state() != QProcess::Running) { - flag = true; - break; - } - QCoreApplication::processEvents(); - if (stopJudging) { - compiler->kill(); - delete compiler; - return false; - } - msleep(10); - } - if (! flag) { - compiler->kill(); - compileState = CompileTimeLimitExceeded; - } else - if (compiler->exitCode() != 0) { - compileState = CompileError; - compileMessage = QString::fromLocal8Bit(compiler->readAllStandardOutput().data()); - } else { - if (compilerList[i]->getCompilerType() == Compiler::Typical) { - if (! QDir(Settings::temporaryPath() + contestantName).exists(executableFile)) - compileState = InvalidCompiler; - else - compileState = CompileSuccessfully; - } else { - QStringList filters = compilerList[i]->getBytecodeExtensions(); - for (int k = 0; k < filters.size(); k ++) - filters[k] = QString("*.") + filters[k]; - if (QDir(Settings::temporaryPath() + contestantName).entryList(filters, QDir::Files).size() == 0) - compileState = InvalidCompiler; - else - compileState = CompileSuccessfully; - } - } - delete compiler; - } - - if (compilerList[i]->getCompilerType() == Compiler::InterpretiveWithoutByteCode) - compileState = CompileSuccessfully; - - break; - } - break; - } - } - - if (compileState != CompileSuccessfully) { - emit compileError(task->getTotalTimeLimit(), int(compileState)); - return false; - } - - return true; -} - -void AssignmentThread::run() -{ - if (task->getTaskType() == Task::Traditional) - if (! traditionalTaskPrepare()) return; - - if (stopJudging) return; - - for (int i = 0; i < task->getTestCaseList().size(); i ++) { - timeUsed.append(QList()); - memoryUsed.append(QList()); - score.append(QList()); - result.append(QList()); - message.append(QStringList()); - inputFiles.append(QStringList()); - for (int j = 0; j < task->getTestCase(i)->getInputFiles().size(); j ++) { - timeUsed[i].append(-1); - memoryUsed[i].append(-1); - score[i].append(0); - result[i].append(WrongAnswer); - message[i].append(""); - inputFiles[i].append(""); - } - } - - if (checkRejudgeMode) - assign(); - else - for (int i = 0; i < settings->getNumberOfThreads(); i ++) assign(); - - exec(); -} - -void AssignmentThread::assign() -{ - if (! checkRejudgeMode) { - if (curTestCaseIndex == task->getTestCaseList().size()) { - if (countFinished == totalSingleCase) quit(); - return; - } - - TestCase *curTestCase = task->getTestCase(curTestCaseIndex); - if (curSingleCaseIndex == curTestCase->getInputFiles().size()) { - curTestCaseIndex ++; - for ( ; curTestCaseIndex < task->getTestCaseList().size(); curTestCaseIndex ++) - if (task->getTestCase(curTestCaseIndex)->getInputFiles().size() > 0) break; - curSingleCaseIndex = 0; - if (curTestCaseIndex == task->getTestCaseList().size()) { - if (countFinished == totalSingleCase) quit(); - return; - } - curTestCase = task->getTestCase(curTestCaseIndex); - } - } else { - if (needRejudge.size() == 0) { - if (countFinished == totalSingleCase) quit(); - return; - } - curTestCaseIndex = needRejudge[0].first; - curSingleCaseIndex = needRejudge[0].second; - needRejudge.removeFirst(); - } - - totalSingleCase ++; - TestCase *curTestCase = task->getTestCase(curTestCaseIndex); - JudgingThread *thread = new JudgingThread(); - thread->setCheckRejudgeMode(checkRejudgeMode); - if (checkRejudgeMode) - thread->setExtraTimeRatio(0.2); - else - thread->setExtraTimeRatio(0.2 * settings->getNumberOfThreads()); - QString workingDirectory = QDir(Settings::temporaryPath() - + QString("_%1.%2").arg(curTestCaseIndex).arg(curSingleCaseIndex)) - .absolutePath() + QDir::separator(); - thread->setWorkingDirectory(workingDirectory); - QDir(Settings::temporaryPath()).mkdir(QString("_%1.%2").arg(curTestCaseIndex).arg(curSingleCaseIndex)); - QStringList entryList = QDir(Settings::temporaryPath() + contestantName).entryList(QDir::Files); - for (int i = 0; i < entryList.size(); i ++) - QFile::copy(Settings::temporaryPath() + contestantName + QDir::separator() + entryList[i], - workingDirectory + entryList[i]); - thread->setSpecialJudgeTimeLimit(settings->getSpecialJudgeTimeLimit()); - if (task->getTaskType() == Task::Traditional) - if (executableFile[0] == '\"') - thread->setExecutableFile(executableFile); - else - thread->setExecutableFile(workingDirectory + executableFile); - if (task->getTaskType() == Task::AnswersOnly) { - QString fileName; - fileName = QFileInfo(curTestCase->getInputFiles().at(curSingleCaseIndex)).completeBaseName(); - fileName += QString(".") + task->getAnswerFileExtension(); - thread->setAnswerFile(Settings::sourcePath() + contestantName + QDir::separator() + fileName); - } - thread->setTask(task); - - connect(thread, SIGNAL(finished()), this, SLOT(threadFinished())); - connect(this, SIGNAL(stopJudgingSignal()), thread, SLOT(stopJudgingSlot())); - - inputFiles[curTestCaseIndex][curSingleCaseIndex] = QFileInfo(curTestCase->getInputFiles().at(curSingleCaseIndex)).fileName(); - thread->setInputFile(Settings::dataPath() + curTestCase->getInputFiles().at(curSingleCaseIndex)); - thread->setOutputFile(Settings::dataPath() + curTestCase->getOutputFiles().at(curSingleCaseIndex)); - thread->setFullScore(curTestCase->getFullScore()); - if (task->getTaskType() == Task::Traditional) { - thread->setEnvironment(environment); - thread->setTimeLimit(qCeil(curTestCase->getTimeLimit() * timeLimitRatio)); - if (disableMemoryLimitCheck) - thread->setMemoryLimit(-1); - else - thread->setMemoryLimit(qCeil(curTestCase->getMemoryLimit() * memoryLimitRatio)); - } - running[thread] = qMakePair(curTestCaseIndex, curSingleCaseIndex ++); - thread->start(); -} - -void AssignmentThread::threadFinished() -{ - JudgingThread *thread = dynamic_cast(sender()); - if (stopJudging) { - running.remove(thread); - delete thread; - if (running.size() == 0) quit(); - return; - } - QPair cur = running[thread]; - timeUsed[cur.first][cur.second] = thread->getTimeUsed(); - memoryUsed[cur.first][cur.second] = thread->getMemoryUsed(); - score[cur.first][cur.second] = thread->getScore(); - result[cur.first][cur.second] = thread->getResult(); - message[cur.first][cur.second] = thread->getMessage(); - if (! checkRejudgeMode && thread->getNeedRejudge()) - needRejudge.append(cur); - running.remove(thread); - countFinished ++; - delete thread; - emit singleCaseFinished(task->getTestCase(cur.first)->getTimeLimit(), - cur.first, cur.second, int(result[cur.first][cur.second])); - assign(); -} - -void AssignmentThread::stopJudgingSlot() -{ - stopJudging = true; - emit stopJudgingSignal(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "assignmentthread.h" +#include "judgingthread.h" +#include "settings.h" +#include "compiler.h" +#include "task.h" +#include "testcase.h" + +AssignmentThread::AssignmentThread(QObject *parent) : + QThread(parent) +{ + moveToThread(this); + checkRejudgeMode = false; + curTestCaseIndex = 0; + curSingleCaseIndex = 0; + countFinished = 0; + totalSingleCase = 0; + stopJudging = false; +} + +void AssignmentThread::setCheckRejudgeMode(bool check) +{ + checkRejudgeMode = check; +} + +void AssignmentThread::setNeedRejudge(const QList > &list) +{ + needRejudge = list; +} + +void AssignmentThread::setSettings(Settings *_settings) +{ + settings = _settings; +} + +void AssignmentThread::setTask(Task *_task) +{ + task = _task; +} + +void AssignmentThread::setContestantName(const QString &name) +{ + contestantName = name; +} + +CompileState AssignmentThread::getCompileState() const +{ + return compileState; +} + +const QString& AssignmentThread::getCompileMessage() const +{ + return compileMessage; +} + +const QString& AssignmentThread::getSourceFile() const +{ + return sourceFile; +} + +const QList< QList >& AssignmentThread::getScore() const +{ + return score; +} + +const QList< QList >& AssignmentThread::getTimeUsed() const +{ + return timeUsed; +} + +const QList< QList >& AssignmentThread::getMemoryUsed() const +{ + return memoryUsed; +} + +const QList< QList >& AssignmentThread::getResult() const +{ + return result; +} + +const QList& AssignmentThread::getMessage() const +{ + return message; +} + +const QList& AssignmentThread::getInputFiles() const +{ + return inputFiles; +} + +const QList< QPair >& AssignmentThread::getNeedRejudge() const +{ + return needRejudge; +} + +bool AssignmentThread::traditionalTaskPrepare() +{ + compileState = NoValidSourceFile; + QDir contestantDir = QDir(Settings::sourcePath() + contestantName); + QList compilerList = settings->getCompilerList(); + + for (int i = 0; i < compilerList.size(); i ++) { + if (task->getCompilerConfiguration(compilerList[i]->getCompilerName()) == "disable") continue; + QStringList filters = compilerList[i]->getSourceExtensions(); + for (int j = 0; j < filters.size(); j ++) + filters[j] = task->getSourceFileName() + "." + filters[j]; + QStringList files = contestantDir.entryList(filters, QDir::Files); + sourceFile = ""; + for (int j = 0; j < files.size(); j ++) { + qint64 fileSize = QFileInfo(Settings::sourcePath() + contestantName + QDir::separator() + files[j]).size(); + if (fileSize <= settings->getFileSizeLimit() * 1024) { + sourceFile = files[j]; + break; + } + } + + if (! sourceFile.isEmpty()) { + QDir(Settings::temporaryPath()).mkdir(contestantName); + QFile::copy(Settings::sourcePath() + contestantName + QDir::separator() + sourceFile, + Settings::temporaryPath() + contestantName + QDir::separator() + sourceFile); + QStringList configurationNames = compilerList[i]->getConfigurationNames(); + QStringList compilerArguments = compilerList[i]->getCompilerArguments(); + QStringList interpreterArguments = compilerList[i]->getInterpreterArguments(); + QString currentConfiguration = task->getCompilerConfiguration(compilerList[i]->getCompilerName()); + for (int j = 0; j < configurationNames.size(); j ++) + if (configurationNames[j] == currentConfiguration) { + timeLimitRatio = compilerList[i]->getTimeLimitRatio(); + memoryLimitRatio = compilerList[i]->getMemoryLimitRatio(); + disableMemoryLimitCheck = compilerList[i]->getDisableMemoryLimitCheck(); + environment = compilerList[i]->getEnvironment(); + QStringList values = environment.toStringList(); + for (int k = 0; k < values.size(); k ++) { + int tmp = values[k].indexOf("="); + QString variable = values[k].mid(0, tmp); + environment.insert(variable, + environment.value(variable) + ";" + + QProcessEnvironment::systemEnvironment().value(variable)); + } + + if (compilerList[i]->getCompilerType() == Compiler::Typical) { +#ifdef Q_OS_WIN32 + executableFile = task->getSourceFileName() + ".exe"; +#endif +#ifdef Q_OS_LINUX + executableFile = task->getSourceFileName(); +#endif + } else { + executableFile = QString("\"") + compilerList[i]->getInterpreterLocation() + "\" "; + QString arguments = interpreterArguments[j]; + arguments.replace("%s.*", sourceFile); + arguments.replace("%s", task->getSourceFileName()); + executableFile += arguments; + } + + if (compilerList[i]->getCompilerType() != Compiler::InterpretiveWithoutByteCode) { + QString arguments = compilerArguments[j]; + arguments.replace("%s.*", sourceFile); + arguments.replace("%s", task->getSourceFileName()); + QProcess *compiler = new QProcess(this); + compiler->setProcessChannelMode(QProcess::MergedChannels); + compiler->setProcessEnvironment(environment); + compiler->setWorkingDirectory(Settings::temporaryPath() + contestantName); + compiler->start(QString("\"") + compilerList[i]->getCompilerLocation() + "\" " + arguments); + if (! compiler->waitForStarted(-1)) { + compileState = InvalidCompiler; + delete compiler; + break; + } + QElapsedTimer timer; + timer.start(); + bool flag = false; + while (timer.elapsed() < settings->getCompileTimeLimit()) { + if (compiler->state() != QProcess::Running) { + flag = true; + break; + } + QCoreApplication::processEvents(); + if (stopJudging) { + compiler->kill(); + delete compiler; + return false; + } + msleep(10); + } + if (! flag) { + compiler->kill(); + compileState = CompileTimeLimitExceeded; + } else + if (compiler->exitCode() != 0) { + compileState = CompileError; + compileMessage = QString::fromLocal8Bit(compiler->readAllStandardOutput().data()); + } else { + if (compilerList[i]->getCompilerType() == Compiler::Typical) { + if (! QDir(Settings::temporaryPath() + contestantName).exists(executableFile)) + compileState = InvalidCompiler; + else + compileState = CompileSuccessfully; + } else { + QStringList filters = compilerList[i]->getBytecodeExtensions(); + for (int k = 0; k < filters.size(); k ++) + filters[k] = QString("*.") + filters[k]; + if (QDir(Settings::temporaryPath() + contestantName).entryList(filters, QDir::Files).size() == 0) + compileState = InvalidCompiler; + else + compileState = CompileSuccessfully; + } + } + delete compiler; + } + + if (compilerList[i]->getCompilerType() == Compiler::InterpretiveWithoutByteCode) + compileState = CompileSuccessfully; + + break; + } + break; + } + } + + if (compileState != CompileSuccessfully) { + emit compileError(task->getTotalTimeLimit(), int(compileState)); + return false; + } + + return true; +} + +void AssignmentThread::run() +{ + if (task->getTaskType() == Task::Traditional) + if (! traditionalTaskPrepare()) return; + + if (stopJudging) return; + + for (int i = 0; i < task->getTestCaseList().size(); i ++) { + timeUsed.append(QList()); + memoryUsed.append(QList()); + score.append(QList()); + result.append(QList()); + message.append(QStringList()); + inputFiles.append(QStringList()); + for (int j = 0; j < task->getTestCase(i)->getInputFiles().size(); j ++) { + timeUsed[i].append(-1); + memoryUsed[i].append(-1); + score[i].append(0); + result[i].append(WrongAnswer); + message[i].append(""); + inputFiles[i].append(""); + } + } + + if (checkRejudgeMode) + assign(); + else + for (int i = 0; i < settings->getNumberOfThreads(); i ++) assign(); + + exec(); +} + +void AssignmentThread::assign() +{ + if (! checkRejudgeMode) { + if (curTestCaseIndex == task->getTestCaseList().size()) { + if (countFinished == totalSingleCase) quit(); + return; + } + + TestCase *curTestCase = task->getTestCase(curTestCaseIndex); + if (curSingleCaseIndex == curTestCase->getInputFiles().size()) { + curTestCaseIndex ++; + for ( ; curTestCaseIndex < task->getTestCaseList().size(); curTestCaseIndex ++) + if (task->getTestCase(curTestCaseIndex)->getInputFiles().size() > 0) break; + curSingleCaseIndex = 0; + if (curTestCaseIndex == task->getTestCaseList().size()) { + if (countFinished == totalSingleCase) quit(); + return; + } + curTestCase = task->getTestCase(curTestCaseIndex); + } + } else { + if (needRejudge.size() == 0) { + if (countFinished == totalSingleCase) quit(); + return; + } + curTestCaseIndex = needRejudge[0].first; + curSingleCaseIndex = needRejudge[0].second; + needRejudge.removeFirst(); + } + + totalSingleCase ++; + TestCase *curTestCase = task->getTestCase(curTestCaseIndex); + JudgingThread *thread = new JudgingThread(); + thread->setCheckRejudgeMode(checkRejudgeMode); + if (checkRejudgeMode) + thread->setExtraTimeRatio(0.2); + else + thread->setExtraTimeRatio(0.2 * settings->getNumberOfThreads()); + QString workingDirectory = QDir(Settings::temporaryPath() + + QString("_%1.%2").arg(curTestCaseIndex).arg(curSingleCaseIndex)) + .absolutePath() + QDir::separator(); + thread->setWorkingDirectory(workingDirectory); + QDir(Settings::temporaryPath()).mkdir(QString("_%1.%2").arg(curTestCaseIndex).arg(curSingleCaseIndex)); + QStringList entryList = QDir(Settings::temporaryPath() + contestantName).entryList(QDir::Files); + for (int i = 0; i < entryList.size(); i ++) + QFile::copy(Settings::temporaryPath() + contestantName + QDir::separator() + entryList[i], + workingDirectory + entryList[i]); + thread->setSpecialJudgeTimeLimit(settings->getSpecialJudgeTimeLimit()); + if (task->getTaskType() == Task::Traditional) + if (executableFile[0] == '\"') + thread->setExecutableFile(executableFile); + else + thread->setExecutableFile(workingDirectory + executableFile); + if (task->getTaskType() == Task::AnswersOnly) { + QString fileName; + fileName = QFileInfo(curTestCase->getInputFiles().at(curSingleCaseIndex)).completeBaseName(); + fileName += QString(".") + task->getAnswerFileExtension(); + thread->setAnswerFile(Settings::sourcePath() + contestantName + QDir::separator() + fileName); + } + thread->setTask(task); + + connect(thread, SIGNAL(finished()), this, SLOT(threadFinished())); + connect(this, SIGNAL(stopJudgingSignal()), thread, SLOT(stopJudgingSlot())); + + inputFiles[curTestCaseIndex][curSingleCaseIndex] = QFileInfo(curTestCase->getInputFiles().at(curSingleCaseIndex)).fileName(); + thread->setInputFile(Settings::dataPath() + curTestCase->getInputFiles().at(curSingleCaseIndex)); + thread->setOutputFile(Settings::dataPath() + curTestCase->getOutputFiles().at(curSingleCaseIndex)); + thread->setFullScore(curTestCase->getFullScore()); + if (task->getTaskType() == Task::Traditional) { + thread->setEnvironment(environment); + thread->setTimeLimit(qCeil(curTestCase->getTimeLimit() * timeLimitRatio)); + if (disableMemoryLimitCheck) + thread->setMemoryLimit(-1); + else + thread->setMemoryLimit(qCeil(curTestCase->getMemoryLimit() * memoryLimitRatio)); + } + running[thread] = qMakePair(curTestCaseIndex, curSingleCaseIndex ++); + thread->start(); +} + +void AssignmentThread::threadFinished() +{ + JudgingThread *thread = dynamic_cast(sender()); + if (stopJudging) { + running.remove(thread); + delete thread; + if (running.size() == 0) quit(); + return; + } + QPair cur = running[thread]; + timeUsed[cur.first][cur.second] = thread->getTimeUsed(); + memoryUsed[cur.first][cur.second] = thread->getMemoryUsed(); + score[cur.first][cur.second] = thread->getScore(); + result[cur.first][cur.second] = thread->getResult(); + message[cur.first][cur.second] = thread->getMessage(); + if (! checkRejudgeMode && thread->getNeedRejudge()) + needRejudge.append(cur); + running.remove(thread); + countFinished ++; + delete thread; + emit singleCaseFinished(task->getTestCase(cur.first)->getTimeLimit(), + cur.first, cur.second, int(result[cur.first][cur.second])); + assign(); +} + +void AssignmentThread::stopJudgingSlot() +{ + stopJudging = true; + emit stopJudgingSignal(); +} diff --git a/assignmentthread.h b/assignmentthread.h index 29cefdf..f4576c9 100644 --- a/assignmentthread.h +++ b/assignmentthread.h @@ -1,93 +1,93 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef ASSIGNMENTTHREAD_H -#define ASSIGNMENTTHREAD_H - -#include -#include -#include "globaltype.h" - -class Settings; -class Task; -class JudgingThread; - -class AssignmentThread : public QThread -{ - Q_OBJECT -public: - explicit AssignmentThread(QObject *parent = 0); - void setCheckRejudgeMode(bool); - void setNeedRejudge(const QList< QPair >&); - void setSettings(Settings*); - void setTask(Task*); - void setContestantName(const QString&); - CompileState getCompileState() const; - const QString& getCompileMessage() const; - const QString& getSourceFile() const; - const QList< QList >& getScore() const; - const QList< QList >& getTimeUsed() const; - const QList< QList >& getMemoryUsed() const; - const QList< QList >& getResult() const; - const QList& getMessage() const; - const QList& getInputFiles() const; - const QList< QPair >& getNeedRejudge() const; - void run(); - -private: - bool checkRejudgeMode; - Settings *settings; - Task* task; - QString contestantName; - CompileState compileState; - QString compileMessage; - QString sourceFile; - QString executableFile; - double timeLimitRatio; - double memoryLimitRatio; - bool disableMemoryLimitCheck; - QProcessEnvironment environment; - QList< QList > timeUsed; - QList< QList > memoryUsed; - QList< QList > score; - QList< QList > result; - QList message; - QList inputFiles; - QList< QPair > needRejudge; - int curTestCaseIndex; - int curSingleCaseIndex; - int countFinished; - int totalSingleCase; - QMap< JudgingThread*, QPair > running; - bool stopJudging; - bool traditionalTaskPrepare(); - void assign(); - -private slots: - void threadFinished(); - -public slots: - void stopJudgingSlot(); - -signals: - void singleCaseFinished(int, int, int, int); - void compileError(int, int); - void stopJudgingSignal(); -}; - -#endif // ASSIGNMENTTHREAD_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef ASSIGNMENTTHREAD_H +#define ASSIGNMENTTHREAD_H + +#include +#include +#include "globaltype.h" + +class Settings; +class Task; +class JudgingThread; + +class AssignmentThread : public QThread +{ + Q_OBJECT +public: + explicit AssignmentThread(QObject *parent = 0); + void setCheckRejudgeMode(bool); + void setNeedRejudge(const QList< QPair >&); + void setSettings(Settings*); + void setTask(Task*); + void setContestantName(const QString&); + CompileState getCompileState() const; + const QString& getCompileMessage() const; + const QString& getSourceFile() const; + const QList< QList >& getScore() const; + const QList< QList >& getTimeUsed() const; + const QList< QList >& getMemoryUsed() const; + const QList< QList >& getResult() const; + const QList& getMessage() const; + const QList& getInputFiles() const; + const QList< QPair >& getNeedRejudge() const; + void run(); + +private: + bool checkRejudgeMode; + Settings *settings; + Task* task; + QString contestantName; + CompileState compileState; + QString compileMessage; + QString sourceFile; + QString executableFile; + double timeLimitRatio; + double memoryLimitRatio; + bool disableMemoryLimitCheck; + QProcessEnvironment environment; + QList< QList > timeUsed; + QList< QList > memoryUsed; + QList< QList > score; + QList< QList > result; + QList message; + QList inputFiles; + QList< QPair > needRejudge; + int curTestCaseIndex; + int curSingleCaseIndex; + int countFinished; + int totalSingleCase; + QMap< JudgingThread*, QPair > running; + bool stopJudging; + bool traditionalTaskPrepare(); + void assign(); + +private slots: + void threadFinished(); + +public slots: + void stopJudgingSlot(); + +signals: + void singleCaseFinished(int, int, int, int); + void compileError(int, int); + void stopJudgingSignal(); +}; + +#endif // ASSIGNMENTTHREAD_H diff --git a/compiler.cpp b/compiler.cpp index df5eaed..41c9560 100644 --- a/compiler.cpp +++ b/compiler.cpp @@ -1,194 +1,194 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "compiler.h" - -Compiler::Compiler(QObject *parent) : - QObject(parent) -{ - compilerType = Typical; - timeLimitRatio = 1; - memoryLimitRatio = 1; - disableMemoryLimitCheck = false; -} - -Compiler::CompilerType Compiler::getCompilerType() const -{ - return compilerType; -} - -const QString& Compiler::getCompilerName() const -{ - return compilerName; -} - -const QStringList& Compiler::getSourceExtensions() const -{ - return sourceExtensions; -} - -const QString& Compiler::getCompilerLocation() const -{ - return compilerLocation; -} - -const QString& Compiler::getInterpreterLocation() const -{ - return interpreterLocation; -} - -const QStringList& Compiler::getBytecodeExtensions() const -{ - return bytecodeExtensions; -} - -const QStringList& Compiler::getConfigurationNames() const -{ - return configurationNames; -} - -const QStringList& Compiler::getCompilerArguments() const -{ - return compilerArguments; -} - -const QStringList& Compiler::getInterpreterArguments() const -{ - return interpreterArguments; -} - -const QProcessEnvironment& Compiler::getEnvironment() const -{ - return environment; -} - -double Compiler::getTimeLimitRatio() const -{ - return timeLimitRatio; -} - -double Compiler::getMemoryLimitRatio() const -{ - return memoryLimitRatio; -} - -bool Compiler::getDisableMemoryLimitCheck() const -{ - return disableMemoryLimitCheck; -} - -void Compiler::setCompilerType(Compiler::CompilerType type) -{ - compilerType = type; -} - -void Compiler::setCompilerName(const QString &name) -{ - compilerName = name; -} - -void Compiler::setSourceExtensions(const QString &extensions) -{ - sourceExtensions = extensions.split(";", QString::SkipEmptyParts); -} - -void Compiler::setCompilerLocation(const QString &location) -{ - compilerLocation = location; -} - -void Compiler::setInterpreterLocation(const QString &location) -{ - interpreterLocation = location; -} - -void Compiler::setBytecodeExtensions(const QString &extensions) -{ - bytecodeExtensions = extensions.split(";", QString::SkipEmptyParts); -} - -void Compiler::setEnvironment(const QProcessEnvironment &env) -{ - environment = env; -} - -void Compiler::setTimeLimitRatio(double ratio) -{ - timeLimitRatio = ratio; -} - -void Compiler::setMemoryLimitRatio(double ratio) -{ - memoryLimitRatio = ratio; -} - -void Compiler::setDisableMemoryLimitCheck(bool check) -{ - disableMemoryLimitCheck = check; -} - -void Compiler::addConfiguration(const QString &name, const QString &arguments1, const QString &arguments2) -{ - configurationNames.append(name); - compilerArguments.append(arguments1); - interpreterArguments.append(arguments2); -} - -void Compiler::setConfigName(int index, const QString &name) -{ - if (0 <= index && index < configurationNames.size()) - configurationNames[index] = name; -} - -void Compiler::setCompilerArguments(int index, const QString &arguments) -{ - if (0 <= index && index < compilerArguments.size()) - compilerArguments[index] = arguments; -} - -void Compiler::setInterpreterArguments(int index, const QString &arguments) -{ - if (0 <= index && index < interpreterArguments.size()) - interpreterArguments[index] = arguments; -} - -void Compiler::deleteConfiguration(int index) -{ - if (0 <= index && index < configurationNames.size()) { - configurationNames.removeAt(index); - compilerArguments.removeAt(index); - interpreterArguments.removeAt(index); - } -} - -void Compiler::copyFrom(Compiler *other) -{ - compilerType = other->getCompilerType(); - compilerName = other->getCompilerName(); - sourceExtensions = other->getSourceExtensions(); - compilerLocation = other->getCompilerLocation(); - interpreterLocation = other->getInterpreterLocation(); - bytecodeExtensions = other->getBytecodeExtensions(); - configurationNames = other->getConfigurationNames(); - compilerArguments = other->getCompilerArguments(); - interpreterArguments = other->getInterpreterArguments(); - environment = other->getEnvironment(); - timeLimitRatio = other->getTimeLimitRatio(); - memoryLimitRatio = other->getMemoryLimitRatio(); - disableMemoryLimitCheck = other->getDisableMemoryLimitCheck(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "compiler.h" + +Compiler::Compiler(QObject *parent) : + QObject(parent) +{ + compilerType = Typical; + timeLimitRatio = 1; + memoryLimitRatio = 1; + disableMemoryLimitCheck = false; +} + +Compiler::CompilerType Compiler::getCompilerType() const +{ + return compilerType; +} + +const QString& Compiler::getCompilerName() const +{ + return compilerName; +} + +const QStringList& Compiler::getSourceExtensions() const +{ + return sourceExtensions; +} + +const QString& Compiler::getCompilerLocation() const +{ + return compilerLocation; +} + +const QString& Compiler::getInterpreterLocation() const +{ + return interpreterLocation; +} + +const QStringList& Compiler::getBytecodeExtensions() const +{ + return bytecodeExtensions; +} + +const QStringList& Compiler::getConfigurationNames() const +{ + return configurationNames; +} + +const QStringList& Compiler::getCompilerArguments() const +{ + return compilerArguments; +} + +const QStringList& Compiler::getInterpreterArguments() const +{ + return interpreterArguments; +} + +const QProcessEnvironment& Compiler::getEnvironment() const +{ + return environment; +} + +double Compiler::getTimeLimitRatio() const +{ + return timeLimitRatio; +} + +double Compiler::getMemoryLimitRatio() const +{ + return memoryLimitRatio; +} + +bool Compiler::getDisableMemoryLimitCheck() const +{ + return disableMemoryLimitCheck; +} + +void Compiler::setCompilerType(Compiler::CompilerType type) +{ + compilerType = type; +} + +void Compiler::setCompilerName(const QString &name) +{ + compilerName = name; +} + +void Compiler::setSourceExtensions(const QString &extensions) +{ + sourceExtensions = extensions.split(";", QString::SkipEmptyParts); +} + +void Compiler::setCompilerLocation(const QString &location) +{ + compilerLocation = location; +} + +void Compiler::setInterpreterLocation(const QString &location) +{ + interpreterLocation = location; +} + +void Compiler::setBytecodeExtensions(const QString &extensions) +{ + bytecodeExtensions = extensions.split(";", QString::SkipEmptyParts); +} + +void Compiler::setEnvironment(const QProcessEnvironment &env) +{ + environment = env; +} + +void Compiler::setTimeLimitRatio(double ratio) +{ + timeLimitRatio = ratio; +} + +void Compiler::setMemoryLimitRatio(double ratio) +{ + memoryLimitRatio = ratio; +} + +void Compiler::setDisableMemoryLimitCheck(bool check) +{ + disableMemoryLimitCheck = check; +} + +void Compiler::addConfiguration(const QString &name, const QString &arguments1, const QString &arguments2) +{ + configurationNames.append(name); + compilerArguments.append(arguments1); + interpreterArguments.append(arguments2); +} + +void Compiler::setConfigName(int index, const QString &name) +{ + if (0 <= index && index < configurationNames.size()) + configurationNames[index] = name; +} + +void Compiler::setCompilerArguments(int index, const QString &arguments) +{ + if (0 <= index && index < compilerArguments.size()) + compilerArguments[index] = arguments; +} + +void Compiler::setInterpreterArguments(int index, const QString &arguments) +{ + if (0 <= index && index < interpreterArguments.size()) + interpreterArguments[index] = arguments; +} + +void Compiler::deleteConfiguration(int index) +{ + if (0 <= index && index < configurationNames.size()) { + configurationNames.removeAt(index); + compilerArguments.removeAt(index); + interpreterArguments.removeAt(index); + } +} + +void Compiler::copyFrom(Compiler *other) +{ + compilerType = other->getCompilerType(); + compilerName = other->getCompilerName(); + sourceExtensions = other->getSourceExtensions(); + compilerLocation = other->getCompilerLocation(); + interpreterLocation = other->getInterpreterLocation(); + bytecodeExtensions = other->getBytecodeExtensions(); + configurationNames = other->getConfigurationNames(); + compilerArguments = other->getCompilerArguments(); + interpreterArguments = other->getInterpreterArguments(); + environment = other->getEnvironment(); + timeLimitRatio = other->getTimeLimitRatio(); + memoryLimitRatio = other->getMemoryLimitRatio(); + disableMemoryLimitCheck = other->getDisableMemoryLimitCheck(); +} diff --git a/compiler.h b/compiler.h index 7ff244f..cc8f426 100644 --- a/compiler.h +++ b/compiler.h @@ -1,82 +1,82 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef COMPILER_H -#define COMPILER_H - -#include -#include - -class Compiler : public QObject -{ - Q_OBJECT -public: - enum CompilerType { Typical, InterpretiveWithByteCode, InterpretiveWithoutByteCode }; - - explicit Compiler(QObject *parent = 0); - - CompilerType getCompilerType() const; - const QString& getCompilerName() const; - const QStringList& getSourceExtensions() const; - const QString& getCompilerLocation() const; - const QString& getInterpreterLocation() const; - const QStringList& getBytecodeExtensions() const; - const QStringList& getConfigurationNames() const; - const QStringList& getCompilerArguments() const; - const QStringList& getInterpreterArguments() const; - const QProcessEnvironment& getEnvironment() const; - double getTimeLimitRatio() const; - double getMemoryLimitRatio() const; - bool getDisableMemoryLimitCheck() const; - - void setCompilerType(CompilerType); - void setCompilerName(const QString&); - void setSourceExtensions(const QString&); - void setCompilerLocation(const QString&); - void setInterpreterLocation(const QString&); - void setBytecodeExtensions(const QString&); - void setEnvironment(const QProcessEnvironment&); - void setTimeLimitRatio(double); - void setMemoryLimitRatio(double); - void setDisableMemoryLimitCheck(bool); - - void addConfiguration(const QString&, const QString&, const QString&); - void setConfigName(int, const QString&); - void setCompilerArguments(int, const QString&); - void setInterpreterArguments(int, const QString&); - void deleteConfiguration(int); - - void copyFrom(Compiler*); - -private: - CompilerType compilerType; - QString compilerName; - QStringList sourceExtensions; - QString compilerLocation; - QString interpreterLocation; - QStringList bytecodeExtensions; - QStringList configurationNames; - QStringList compilerArguments; - QStringList interpreterArguments; - QProcessEnvironment environment; - double timeLimitRatio; - double memoryLimitRatio; - bool disableMemoryLimitCheck; -}; - -#endif // COMPILER_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef COMPILER_H +#define COMPILER_H + +#include +#include + +class Compiler : public QObject +{ + Q_OBJECT +public: + enum CompilerType { Typical, InterpretiveWithByteCode, InterpretiveWithoutByteCode }; + + explicit Compiler(QObject *parent = 0); + + CompilerType getCompilerType() const; + const QString& getCompilerName() const; + const QStringList& getSourceExtensions() const; + const QString& getCompilerLocation() const; + const QString& getInterpreterLocation() const; + const QStringList& getBytecodeExtensions() const; + const QStringList& getConfigurationNames() const; + const QStringList& getCompilerArguments() const; + const QStringList& getInterpreterArguments() const; + const QProcessEnvironment& getEnvironment() const; + double getTimeLimitRatio() const; + double getMemoryLimitRatio() const; + bool getDisableMemoryLimitCheck() const; + + void setCompilerType(CompilerType); + void setCompilerName(const QString&); + void setSourceExtensions(const QString&); + void setCompilerLocation(const QString&); + void setInterpreterLocation(const QString&); + void setBytecodeExtensions(const QString&); + void setEnvironment(const QProcessEnvironment&); + void setTimeLimitRatio(double); + void setMemoryLimitRatio(double); + void setDisableMemoryLimitCheck(bool); + + void addConfiguration(const QString&, const QString&, const QString&); + void setConfigName(int, const QString&); + void setCompilerArguments(int, const QString&); + void setInterpreterArguments(int, const QString&); + void deleteConfiguration(int); + + void copyFrom(Compiler*); + +private: + CompilerType compilerType; + QString compilerName; + QStringList sourceExtensions; + QString compilerLocation; + QString interpreterLocation; + QStringList bytecodeExtensions; + QStringList configurationNames; + QStringList compilerArguments; + QStringList interpreterArguments; + QProcessEnvironment environment; + double timeLimitRatio; + double memoryLimitRatio; + bool disableMemoryLimitCheck; +}; + +#endif // COMPILER_H diff --git a/compilersettings.cpp b/compilersettings.cpp index 5c2cc81..2087a49 100644 --- a/compilersettings.cpp +++ b/compilersettings.cpp @@ -1,247 +1,247 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "compilersettings.h" -#include "ui_compilersettings.h" -#include "advancedcompilersettingsdialog.h" -#include "addcompilerwizard.h" -#include "settings.h" -#include "compiler.h" - -CompilerSettings::CompilerSettings(QWidget *parent) : - QWidget(parent), - ui(new Ui::CompilerSettings) -{ - ui->setupUi(this); - - ui->sourceExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->sourceExtensions)); - deleteCompilerKeyAction = new QAction(ui->compilerList); - deleteCompilerKeyAction->setShortcutContext(Qt::WidgetShortcut); - deleteCompilerKeyAction->setShortcut(QKeySequence::Delete); - deleteCompilerKeyAction->setEnabled(false); - ui->compilerList->addAction(deleteCompilerKeyAction); - - connect(ui->moveUpButton, SIGNAL(clicked()), - this, SLOT(moveUpCompiler())); - connect(ui->moveDownButton, SIGNAL(clicked()), - this, SLOT(moveDownCompiler())); - connect(ui->addCompilerButton, SIGNAL(clicked()), - this, SLOT(addCompiler())); - connect(ui->deleteCompilerButton, SIGNAL(clicked()), - this, SLOT(deleteCompiler())); - connect(ui->compilerName, SIGNAL(textChanged(QString)), - this, SLOT(compilerNameChanged(QString))); - connect(ui->sourceExtensions, SIGNAL(textChanged(QString)), - this, SLOT(sourceExtensionsChanged(QString))); - connect(ui->compilerList, SIGNAL(currentRowChanged(int)), - this, SLOT(compilerListCurrentRowChanged())); - connect(ui->advancedButton, SIGNAL(clicked()), - this, SLOT(advancedButtonClicked())); - connect(deleteCompilerKeyAction, SIGNAL(triggered()), - this, SLOT(deleteCompiler())); -} - -CompilerSettings::~CompilerSettings() -{ - delete ui; -} - -void CompilerSettings::resetEditSettings(Settings *settings) -{ - editSettings = settings; - - const QList &compilerList = editSettings->getCompilerList(); - ui->compilerList->clear(); - for (int i = 0; i < compilerList.size(); i ++) - ui->compilerList->addItem(compilerList[i]->getCompilerName()); - if (compilerList.size() > 0) { - ui->compilerList->setCurrentRow(0); - setCurrentCompiler(compilerList[0]); - } else - setCurrentCompiler(0); - refreshItemState(); -} - -bool CompilerSettings::checkValid() -{ - const QList &compilerList = editSettings->getCompilerList(); - QStringList compilerNames; - for (int i = 0; i < compilerList.size(); i ++) - compilerNames.append(compilerList[i]->getCompilerName()); - for (int i = 0; i < compilerList.size(); i ++) - if (compilerNames.count(compilerNames[i]) > 1) { - ui->compilerList->setFocus(); - ui->compilerList->setCurrentRow(i); - QMessageBox::warning(this, tr("Error"), - tr("Compiler %1 appears more than once!").arg(compilerNames[i]), - QMessageBox::Close); - return false; - } - for (int i = 0; i < compilerList.size(); i ++) { - if (compilerList[i]->getCompilerName().isEmpty()) { - ui->compilerList->setCurrentRow(i); - ui->compilerName->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty compiler name!"), QMessageBox::Close); - return false; - } - if (compilerList[i]->getSourceExtensions().isEmpty()) { - ui->compilerList->setCurrentRow(i); - ui->sourceExtensions->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty source file extensions!"), QMessageBox::Close); - return false; - } - } - return true; -} - -void CompilerSettings::moveUpCompiler() -{ - int index = ui->compilerList->currentRow(); - QString curCompilerName = ui->compilerList->currentItem()->text(); - QString upCompilerName = ui->compilerList->item(index - 1)->text(); - ui->compilerList->currentItem()->setText(upCompilerName); - ui->compilerList->item(index - 1)->setText(curCompilerName); - editSettings->swapCompiler(index - 1, index); - ui->compilerList->setCurrentRow(index - 1); -} - -void CompilerSettings::moveDownCompiler() -{ - int index = ui->compilerList->currentRow(); - QString curCompilerName = ui->compilerList->currentItem()->text(); - QString downCompilerName = ui->compilerList->item(index + 1)->text(); - ui->compilerList->currentItem()->setText(downCompilerName); - ui->compilerList->item(index + 1)->setText(curCompilerName); - editSettings->swapCompiler(index + 1, index); - ui->compilerList->setCurrentRow(index + 1); -} - -void CompilerSettings::addCompiler() -{ - AddCompilerWizard *wizard = new AddCompilerWizard(this); - if (wizard->exec() == QDialog::Accepted) { - QList compilerList = editSettings->getCompilerList(); - QStringList compilerNames; - for (int i = 0; i < compilerList.size(); i ++) - compilerNames.append(compilerList[i]->getCompilerName()); - compilerList = wizard->getCompilerList(); - for (int i = 0; i < compilerList.size(); i ++) { - if (compilerNames.contains(compilerList[i]->getCompilerName())) { - int cnt = 2; - QString name = compilerList[i]->getCompilerName(); - while (compilerNames.contains(QString("%1 (%2)").arg(name).arg(cnt))) - cnt ++; - compilerList[i]->setCompilerName(QString("%1 (%2)").arg(name).arg(cnt)); - } - editSettings->addCompiler(compilerList[i]); - ui->compilerList->addItem(new QListWidgetItem(compilerList[i]->getCompilerName())); - ui->compilerList->setCurrentRow(ui->compilerList->count() - 1); - refreshItemState(); - } - } - delete wizard; -} - -void CompilerSettings::deleteCompiler() -{ - if (QMessageBox::question(this, tr("Lemon"), tr("Are you sure to delete compiler %1?") - .arg(curCompiler->getCompilerName()), - QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) - return; - int index = ui->compilerList->currentRow(); - delete ui->compilerList->item(index); - editSettings->deleteCompiler(index); - refreshItemState(); -} - -void CompilerSettings::setCurrentCompiler(Compiler *compiler) -{ - curCompiler = compiler; - if (! compiler) { - ui->compilerName->clear(); - ui->sourceExtensions->clear(); - return; - } - ui->compilerName->setText(curCompiler->getCompilerName()); - ui->sourceExtensions->setText(curCompiler->getSourceExtensions().join(";")); -} - -void CompilerSettings::refreshItemState() -{ - if (ui->compilerList->count() == 0) { - ui->moveUpButton->setEnabled(false); - ui->moveDownButton->setEnabled(false); - ui->addCompilerButton->setEnabled(true); - ui->deleteCompilerButton->setEnabled(false); - ui->compilerName->setEnabled(false); - ui->sourceExtensions->setEnabled(false); - ui->compilerNameLabel->setEnabled(false); - ui->sourceExtensionsLabel->setEnabled(false); - ui->advancedButton->setEnabled(false); - deleteCompilerKeyAction->setEnabled(false); - } else { - if (ui->compilerList->currentRow() > 0) - ui->moveUpButton->setEnabled(true); - else - ui->moveUpButton->setEnabled(false); - if (ui->compilerList->currentRow() + 1 < ui->compilerList->count()) - ui->moveDownButton->setEnabled(true); - else - ui->moveDownButton->setEnabled(false); - ui->addCompilerButton->setEnabled(true); - ui->deleteCompilerButton->setEnabled(true); - ui->compilerName->setEnabled(true); - ui->sourceExtensions->setEnabled(true); - ui->compilerNameLabel->setEnabled(true); - ui->sourceExtensionsLabel->setEnabled(true); - ui->advancedButton->setEnabled(true); - deleteCompilerKeyAction->setEnabled(true); - } -} - -void CompilerSettings::compilerNameChanged(const QString &text) -{ - if (curCompiler) { - curCompiler->setCompilerName(text); - ui->compilerList->currentItem()->setText(text); - } -} - -void CompilerSettings::sourceExtensionsChanged(const QString &text) -{ - if (curCompiler) curCompiler->setSourceExtensions(text); -} - -void CompilerSettings::compilerListCurrentRowChanged() -{ - if (ui->compilerList->currentItem()) { - int index = ui->compilerList->currentRow(); - setCurrentCompiler(editSettings->getCompiler(index)); - } else - setCurrentCompiler(0); - refreshItemState(); -} - -void CompilerSettings::advancedButtonClicked() -{ - AdvancedCompilerSettingsDialog *dialog = new AdvancedCompilerSettingsDialog(this); - dialog->resetEditCompiler(curCompiler); - if (dialog->exec() == QDialog::Accepted) - curCompiler->copyFrom(dialog->getEditCompiler()); - delete dialog; -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "compilersettings.h" +#include "ui_compilersettings.h" +#include "advancedcompilersettingsdialog.h" +#include "addcompilerwizard.h" +#include "settings.h" +#include "compiler.h" + +CompilerSettings::CompilerSettings(QWidget *parent) : + QWidget(parent), + ui(new Ui::CompilerSettings) +{ + ui->setupUi(this); + + ui->sourceExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->sourceExtensions)); + deleteCompilerKeyAction = new QAction(ui->compilerList); + deleteCompilerKeyAction->setShortcutContext(Qt::WidgetShortcut); + deleteCompilerKeyAction->setShortcut(QKeySequence::Delete); + deleteCompilerKeyAction->setEnabled(false); + ui->compilerList->addAction(deleteCompilerKeyAction); + + connect(ui->moveUpButton, SIGNAL(clicked()), + this, SLOT(moveUpCompiler())); + connect(ui->moveDownButton, SIGNAL(clicked()), + this, SLOT(moveDownCompiler())); + connect(ui->addCompilerButton, SIGNAL(clicked()), + this, SLOT(addCompiler())); + connect(ui->deleteCompilerButton, SIGNAL(clicked()), + this, SLOT(deleteCompiler())); + connect(ui->compilerName, SIGNAL(textChanged(QString)), + this, SLOT(compilerNameChanged(QString))); + connect(ui->sourceExtensions, SIGNAL(textChanged(QString)), + this, SLOT(sourceExtensionsChanged(QString))); + connect(ui->compilerList, SIGNAL(currentRowChanged(int)), + this, SLOT(compilerListCurrentRowChanged())); + connect(ui->advancedButton, SIGNAL(clicked()), + this, SLOT(advancedButtonClicked())); + connect(deleteCompilerKeyAction, SIGNAL(triggered()), + this, SLOT(deleteCompiler())); +} + +CompilerSettings::~CompilerSettings() +{ + delete ui; +} + +void CompilerSettings::resetEditSettings(Settings *settings) +{ + editSettings = settings; + + const QList &compilerList = editSettings->getCompilerList(); + ui->compilerList->clear(); + for (int i = 0; i < compilerList.size(); i ++) + ui->compilerList->addItem(compilerList[i]->getCompilerName()); + if (compilerList.size() > 0) { + ui->compilerList->setCurrentRow(0); + setCurrentCompiler(compilerList[0]); + } else + setCurrentCompiler(0); + refreshItemState(); +} + +bool CompilerSettings::checkValid() +{ + const QList &compilerList = editSettings->getCompilerList(); + QStringList compilerNames; + for (int i = 0; i < compilerList.size(); i ++) + compilerNames.append(compilerList[i]->getCompilerName()); + for (int i = 0; i < compilerList.size(); i ++) + if (compilerNames.count(compilerNames[i]) > 1) { + ui->compilerList->setFocus(); + ui->compilerList->setCurrentRow(i); + QMessageBox::warning(this, tr("Error"), + tr("Compiler %1 appears more than once!").arg(compilerNames[i]), + QMessageBox::Close); + return false; + } + for (int i = 0; i < compilerList.size(); i ++) { + if (compilerList[i]->getCompilerName().isEmpty()) { + ui->compilerList->setCurrentRow(i); + ui->compilerName->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty compiler name!"), QMessageBox::Close); + return false; + } + if (compilerList[i]->getSourceExtensions().isEmpty()) { + ui->compilerList->setCurrentRow(i); + ui->sourceExtensions->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty source file extensions!"), QMessageBox::Close); + return false; + } + } + return true; +} + +void CompilerSettings::moveUpCompiler() +{ + int index = ui->compilerList->currentRow(); + QString curCompilerName = ui->compilerList->currentItem()->text(); + QString upCompilerName = ui->compilerList->item(index - 1)->text(); + ui->compilerList->currentItem()->setText(upCompilerName); + ui->compilerList->item(index - 1)->setText(curCompilerName); + editSettings->swapCompiler(index - 1, index); + ui->compilerList->setCurrentRow(index - 1); +} + +void CompilerSettings::moveDownCompiler() +{ + int index = ui->compilerList->currentRow(); + QString curCompilerName = ui->compilerList->currentItem()->text(); + QString downCompilerName = ui->compilerList->item(index + 1)->text(); + ui->compilerList->currentItem()->setText(downCompilerName); + ui->compilerList->item(index + 1)->setText(curCompilerName); + editSettings->swapCompiler(index + 1, index); + ui->compilerList->setCurrentRow(index + 1); +} + +void CompilerSettings::addCompiler() +{ + AddCompilerWizard *wizard = new AddCompilerWizard(this); + if (wizard->exec() == QDialog::Accepted) { + QList compilerList = editSettings->getCompilerList(); + QStringList compilerNames; + for (int i = 0; i < compilerList.size(); i ++) + compilerNames.append(compilerList[i]->getCompilerName()); + compilerList = wizard->getCompilerList(); + for (int i = 0; i < compilerList.size(); i ++) { + if (compilerNames.contains(compilerList[i]->getCompilerName())) { + int cnt = 2; + QString name = compilerList[i]->getCompilerName(); + while (compilerNames.contains(QString("%1 (%2)").arg(name).arg(cnt))) + cnt ++; + compilerList[i]->setCompilerName(QString("%1 (%2)").arg(name).arg(cnt)); + } + editSettings->addCompiler(compilerList[i]); + ui->compilerList->addItem(new QListWidgetItem(compilerList[i]->getCompilerName())); + ui->compilerList->setCurrentRow(ui->compilerList->count() - 1); + refreshItemState(); + } + } + delete wizard; +} + +void CompilerSettings::deleteCompiler() +{ + if (QMessageBox::question(this, tr("Lemon"), tr("Are you sure to delete compiler %1?") + .arg(curCompiler->getCompilerName()), + QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) + return; + int index = ui->compilerList->currentRow(); + delete ui->compilerList->item(index); + editSettings->deleteCompiler(index); + refreshItemState(); +} + +void CompilerSettings::setCurrentCompiler(Compiler *compiler) +{ + curCompiler = compiler; + if (! compiler) { + ui->compilerName->clear(); + ui->sourceExtensions->clear(); + return; + } + ui->compilerName->setText(curCompiler->getCompilerName()); + ui->sourceExtensions->setText(curCompiler->getSourceExtensions().join(";")); +} + +void CompilerSettings::refreshItemState() +{ + if (ui->compilerList->count() == 0) { + ui->moveUpButton->setEnabled(false); + ui->moveDownButton->setEnabled(false); + ui->addCompilerButton->setEnabled(true); + ui->deleteCompilerButton->setEnabled(false); + ui->compilerName->setEnabled(false); + ui->sourceExtensions->setEnabled(false); + ui->compilerNameLabel->setEnabled(false); + ui->sourceExtensionsLabel->setEnabled(false); + ui->advancedButton->setEnabled(false); + deleteCompilerKeyAction->setEnabled(false); + } else { + if (ui->compilerList->currentRow() > 0) + ui->moveUpButton->setEnabled(true); + else + ui->moveUpButton->setEnabled(false); + if (ui->compilerList->currentRow() + 1 < ui->compilerList->count()) + ui->moveDownButton->setEnabled(true); + else + ui->moveDownButton->setEnabled(false); + ui->addCompilerButton->setEnabled(true); + ui->deleteCompilerButton->setEnabled(true); + ui->compilerName->setEnabled(true); + ui->sourceExtensions->setEnabled(true); + ui->compilerNameLabel->setEnabled(true); + ui->sourceExtensionsLabel->setEnabled(true); + ui->advancedButton->setEnabled(true); + deleteCompilerKeyAction->setEnabled(true); + } +} + +void CompilerSettings::compilerNameChanged(const QString &text) +{ + if (curCompiler) { + curCompiler->setCompilerName(text); + ui->compilerList->currentItem()->setText(text); + } +} + +void CompilerSettings::sourceExtensionsChanged(const QString &text) +{ + if (curCompiler) curCompiler->setSourceExtensions(text); +} + +void CompilerSettings::compilerListCurrentRowChanged() +{ + if (ui->compilerList->currentItem()) { + int index = ui->compilerList->currentRow(); + setCurrentCompiler(editSettings->getCompiler(index)); + } else + setCurrentCompiler(0); + refreshItemState(); +} + +void CompilerSettings::advancedButtonClicked() +{ + AdvancedCompilerSettingsDialog *dialog = new AdvancedCompilerSettingsDialog(this); + dialog->resetEditCompiler(curCompiler); + if (dialog->exec() == QDialog::Accepted) + curCompiler->copyFrom(dialog->getEditCompiler()); + delete dialog; +} diff --git a/compilersettings.h b/compilersettings.h index 1c9cc3c..9a73816 100644 --- a/compilersettings.h +++ b/compilersettings.h @@ -1,62 +1,62 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef COMPILERSETTINGS_H -#define COMPILERSETTINGS_H - -#include -#include -#include - -namespace Ui { - class CompilerSettings; -} - -class Settings; -class Compiler; - -class CompilerSettings : public QWidget -{ - Q_OBJECT - -public: - explicit CompilerSettings(QWidget *parent = 0); - ~CompilerSettings(); - void resetEditSettings(Settings*); - bool checkValid(); - -private: - Ui::CompilerSettings *ui; - Settings *editSettings; - Compiler *curCompiler; - QAction *deleteCompilerKeyAction; - void setCurrentCompiler(Compiler*); - void refreshItemState(); - -private slots: - void moveUpCompiler(); - void moveDownCompiler(); - void addCompiler(); - void deleteCompiler(); - void compilerNameChanged(const QString&); - void sourceExtensionsChanged(const QString&); - void compilerListCurrentRowChanged(); - void advancedButtonClicked(); -}; - -#endif // COMPILERSETTINGS_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef COMPILERSETTINGS_H +#define COMPILERSETTINGS_H + +#include +#include +#include + +namespace Ui { + class CompilerSettings; +} + +class Settings; +class Compiler; + +class CompilerSettings : public QWidget +{ + Q_OBJECT + +public: + explicit CompilerSettings(QWidget *parent = 0); + ~CompilerSettings(); + void resetEditSettings(Settings*); + bool checkValid(); + +private: + Ui::CompilerSettings *ui; + Settings *editSettings; + Compiler *curCompiler; + QAction *deleteCompilerKeyAction; + void setCurrentCompiler(Compiler*); + void refreshItemState(); + +private slots: + void moveUpCompiler(); + void moveDownCompiler(); + void addCompiler(); + void deleteCompiler(); + void compilerNameChanged(const QString&); + void sourceExtensionsChanged(const QString&); + void compilerListCurrentRowChanged(); + void advancedButtonClicked(); +}; + +#endif // COMPILERSETTINGS_H diff --git a/compilersettings.ui b/compilersettings.ui index f08febb..88799d5 100644 --- a/compilersettings.ui +++ b/compilersettings.ui @@ -1,257 +1,265 @@ - - - CompilerSettings - - - - 0 - 0 - 325 - 352 - - - - - 325 - 352 - - - - Form - - - - 8 - - - - - 10 - - - - - font-size: 9pt; - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::SingleSelection - - - - - - - - - Qt::Vertical - - - - 17 - 13 - - - - - - - - - 27 - 27 - - - - - 27 - 27 - - - - - - - - :/icon/uparrow.png:/icon/uparrow.png - - - false - - - Qt::NoArrow - - - - - - - - 27 - 27 - - - - - 27 - 27 - - - - - - - - :/icon/downarrow.png:/icon/downarrow.png - - - false - - - Qt::NoArrow - - - - - - - - 27 - 27 - - - - - 27 - 27 - - - - - - - - :/icon/add.png:/icon/add.png - - - false - - - Qt::NoArrow - - - - - - - - 27 - 27 - - - - - 27 - 27 - - - - - - - - :/icon/rod.png:/icon/rod.png - - - false - - - Qt::NoArrow - - - - - - - Qt::Vertical - - - - 17 - 13 - - - - - - - - - - - - 8 - - - - - font-size: 9pt; -font-weight: bold; - - - Compiler Name - - - - - - - - - - font-size: 9pt; -font-weight: bold; - - - Source Extensions - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - &Advanced - - - - - - - - - - - - + + + CompilerSettings + + + + 0 + 0 + 325 + 352 + + + + + 325 + 352 + + + + Form + + + + 8 + + + + + 10 + + + + + font-size: 9pt; + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + + + + + + + Qt::Vertical + + + + 17 + 13 + + + + + + + + + 27 + 27 + + + + + 27 + 27 + + + + + + + + :/icon/uparrow.png:/icon/uparrow.png + + + false + + + Qt::NoArrow + + + + + + + + 27 + 27 + + + + + 27 + 27 + + + + + + + + :/icon/downarrow.png:/icon/downarrow.png + + + false + + + Qt::NoArrow + + + + + + + + 27 + 27 + + + + + 27 + 27 + + + + + + + + :/icon/add.png:/icon/add.png + + + false + + + Qt::NoArrow + + + + + + + + 27 + 27 + + + + + 27 + 27 + + + + + + + + :/icon/rod.png:/icon/rod.png + + + false + + + Qt::NoArrow + + + + + + + Qt::Vertical + + + + 17 + 13 + + + + + + + + + + + + 8 + + + + + font-size: 9pt; +font-weight: bold; + + + Compiler Name + + + + + + + font-size:9pt; + + + + + + + font-size: 9pt; +font-weight: bold; + + + Source Extensions + + + + + + + font-size:9pt; + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Advanced + + + + + + + + + + + + diff --git a/contest.cpp b/contest.cpp index 5b5d040..ebfdc23 100644 --- a/contest.cpp +++ b/contest.cpp @@ -1,420 +1,420 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include -#include "contest.h" -#include "task.h" -#include "testcase.h" -#include "settings.h" -#include "compiler.h" -#include "contestant.h" -#include "judgingthread.h" -#include "assignmentthread.h" - -Contest::Contest(QObject *parent) : - QObject(parent) -{ -} - -void Contest::setSettings(Settings *_settings) -{ - settings = _settings; -} - -void Contest::setContestTitle(const QString &title) -{ - contestTitle = title; -} - -const QString& Contest::getContestTitle() const -{ - return contestTitle; -} - -Task* Contest::getTask(int index) const -{ - if (0 <= index && index < taskList.size()) - return taskList[index]; - else - return 0; -} - -const QList& Contest::getTaskList() const -{ - return taskList; -} - -Contestant* Contest::getContestant(const QString &name) const -{ - if (contestantList.contains(name)) - return contestantList.value(name); - else - return 0; -} - -QList Contest::getContestantList() const -{ - return contestantList.values(); -} - -int Contest::getTotalTimeLimit() const -{ - int total = 0; - for (int i = 0; i < taskList.size(); i ++) { - QList testCaseList = taskList[i]->getTestCaseList(); - for (int j = 0; j < testCaseList.size(); j ++) - total += testCaseList[j]->getTimeLimit() * testCaseList[j]->getInputFiles().size(); - } - return total; -} - -void Contest::addTask(Task *task) -{ - task->setParent(this); - taskList.append(task); - connect(task, SIGNAL(problemTitleChanged(QString)), - this, SIGNAL(problemTitleChanged())); - emit taskAddedForContestant(); - emit taskAddedForViewer(); -} - -void Contest::deleteTask(int index) -{ - if (0 <= index && index < taskList.size()) { - delete taskList[index]; - taskList.removeAt(index); - } - emit taskDeletedForContestant(index); - emit taskDeletedForViewer(index); -} - -void Contest::refreshContestantList() -{ - QStringList nameList = QDir(Settings::sourcePath()).entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot); - QStringList curNameList = contestantList.keys(); - for (int i = 0; i < curNameList.size(); i ++) - if (! nameList.contains(curNameList[i])) { - delete contestantList[curNameList[i]]; - contestantList.remove(curNameList[i]); - } - for (int i = 0; i < nameList.size(); i ++) - if (! contestantList.contains(nameList[i])) { - Contestant *newContestant = new Contestant(this); - newContestant->setContestantName(nameList[i]); - for (int j = 0; j < taskList.size(); j ++) - newContestant->addTask(); - contestantList.insert(nameList[i], newContestant); - connect(this, SIGNAL(taskAddedForContestant()), - newContestant, SLOT(addTask())); - connect(this, SIGNAL(taskDeletedForContestant(int)), - newContestant, SLOT(deleteTask(int))); - } -} - -void Contest::deleteContestant(const QString &name) -{ - if (! contestantList.contains(name)) return; - delete contestantList[name]; - contestantList.remove(name); -} - -void Contest::clearPath(const QString &curDir) -{ - QDir dir(curDir); - QStringList fileList = dir.entryList(QDir::Files); - for (int i = 0; i < fileList.size(); i ++) - dir.remove(fileList[i]); - QStringList dirList = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (int i = 0; i < dirList.size(); i ++) { - clearPath(curDir + dirList[i] + QDir::separator()); - dir.rmdir(dirList[i]); - } -} - -void Contest::judge(Contestant *contestant) -{ - emit contestantJudgingStart(contestant->getContestantName()); - QDir(QDir::current()).mkdir(Settings::temporaryPath()); - for (int i = 0; i < taskList.size(); i ++) { - emit taskJudgingStarted(taskList[i]->getProblemTile()); - - AssignmentThread *thread = new AssignmentThread(); - connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), - this, SIGNAL(singleCaseFinished(int, int, int, int))); - connect(thread, SIGNAL(compileError(int, int)), - this, SIGNAL(compileError(int, int))); - connect(this, SIGNAL(stopJudgingSignal()), - thread, SLOT(stopJudgingSlot())); - thread->setSettings(settings); - thread->setTask(taskList[i]); - thread->setContestantName(contestant->getContestantName()); - QEventLoop *eventLoop = new QEventLoop(this); - connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); - thread->start(); - eventLoop->exec(); - delete eventLoop; - - if (stopJudging) { - delete thread; - clearPath(Settings::temporaryPath()); - QDir().rmdir(Settings::temporaryPath()); - return; - } - - contestant->setCompileState(i, thread->getCompileState()); - contestant->setCompileMessage(i, thread->getCompileMessage()); - contestant->setSourceFile(i, thread->getSourceFile()); - contestant->setInputFiles(i, thread->getInputFiles()); - contestant->setResult(i, thread->getResult()); - contestant->setMessage(i, thread->getMessage()); - contestant->setScore(i, thread->getScore()); - contestant->setTimeUsed(i, thread->getTimeUsed()); - contestant->setMemoryUsed(i, thread->getMemoryUsed()); - QList< QPair > needRejudge = thread->getNeedRejudge(); - - delete thread; - clearPath(Settings::temporaryPath()); - - if (needRejudge.size() > 0) { - AssignmentThread *thread = new AssignmentThread(); - connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), - this, SIGNAL(singleCaseFinished(int, int, int, int))); - connect(thread, SIGNAL(compileError(int, int)), - this, SIGNAL(compileError(int, int))); - connect(this, SIGNAL(stopJudgingSignal()), - thread, SLOT(stopJudgingSlot())); - thread->setCheckRejudgeMode(true); - thread->setNeedRejudge(needRejudge); - thread->setSettings(settings); - thread->setTask(taskList[i]); - thread->setContestantName(contestant->getContestantName()); - QEventLoop *eventLoop = new QEventLoop(this); - connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); - thread->start(); - eventLoop->exec(); - delete eventLoop; - - if (stopJudging) { - delete thread; - clearPath(Settings::temporaryPath()); - QDir().rmdir(Settings::temporaryPath()); - return; - } - - QList< QList > result = contestant->getResult(i); - QList message = contestant->getMessage(i); - QList< QList > score = contestant->getSocre(i); - QList< QList > timeUsed = contestant->getTimeUsed(i); - QList< QList > memoryUsed = contestant->getMemoryUsed(i); - - for (int j = 0; j < needRejudge.size(); j ++) { - int a = needRejudge[j].first, b = needRejudge[j].second; - result[a][b] = thread->getResult()[a][b]; - message[a][b] = thread->getMessage()[a][b]; - score[a][b] = thread->getScore()[a][b]; - timeUsed[a][b] = thread->getTimeUsed()[a][b]; - memoryUsed[a][b] = thread->getMemoryUsed()[a][b]; - } - - contestant->setResult(i, result); - contestant->setMessage(i, message); - contestant->setScore(i, score); - contestant->setTimeUsed(i, timeUsed); - contestant->setMemoryUsed(i, memoryUsed); - - delete thread; - clearPath(Settings::temporaryPath()); - } - - contestant->setCheckJudged(i, true); - emit taskJudgingFinished(); - } - contestant->setJudgingTime(QDateTime::currentDateTime()); - QDir().rmdir(Settings::temporaryPath()); - emit contestantJudgingFinished(); -} - -void Contest::judge(Contestant *contestant, int index) -{ - emit contestantJudgingStart(contestant->getContestantName()); - QDir(QDir::current()).mkdir(Settings::temporaryPath()); - - emit taskJudgingStarted(taskList[index]->getProblemTile()); - - AssignmentThread *thread = new AssignmentThread(); - connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), - this, SIGNAL(singleCaseFinished(int, int, int, int))); - connect(thread, SIGNAL(compileError(int, int)), - this, SIGNAL(compileError(int, int))); - connect(this, SIGNAL(stopJudgingSignal()), - thread, SLOT(stopJudgingSlot())); - thread->setSettings(settings); - thread->setTask(taskList[index]); - thread->setContestantName(contestant->getContestantName()); - QEventLoop *eventLoop = new QEventLoop(this); - connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); - thread->start(); - eventLoop->exec(); - delete eventLoop; - - if (stopJudging) { - delete thread; - clearPath(Settings::temporaryPath()); - QDir().rmdir(Settings::temporaryPath()); - return; - } - - contestant->setCompileState(index, thread->getCompileState()); - contestant->setCompileMessage(index, thread->getCompileMessage()); - contestant->setSourceFile(index, thread->getSourceFile()); - contestant->setInputFiles(index, thread->getInputFiles()); - contestant->setResult(index, thread->getResult()); - contestant->setMessage(index, thread->getMessage()); - contestant->setScore(index, thread->getScore()); - contestant->setTimeUsed(index, thread->getTimeUsed()); - contestant->setMemoryUsed(index, thread->getMemoryUsed()); - QList< QPair > needRejudge = thread->getNeedRejudge(); - - delete thread; - clearPath(Settings::temporaryPath()); - - if (needRejudge.size() > 0) { - AssignmentThread *thread = new AssignmentThread(); - connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), - this, SIGNAL(singleCaseFinished(int, int, int, int))); - connect(thread, SIGNAL(compileError(int, int)), - this, SIGNAL(compileError(int, int))); - connect(this, SIGNAL(stopJudgingSignal()), - thread, SLOT(stopJudgingSlot())); - thread->setCheckRejudgeMode(true); - thread->setNeedRejudge(needRejudge); - thread->setSettings(settings); - thread->setTask(taskList[index]); - thread->setContestantName(contestant->getContestantName()); - QEventLoop *eventLoop = new QEventLoop(this); - connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); - thread->start(); - eventLoop->exec(); - delete eventLoop; - - if (stopJudging) { - delete thread; - clearPath(Settings::temporaryPath()); - QDir().rmdir(Settings::temporaryPath()); - return; - } - - QList< QList > result = contestant->getResult(index); - QList message = contestant->getMessage(index); - QList< QList > score = contestant->getSocre(index); - QList< QList > timeUsed = contestant->getTimeUsed(index); - QList< QList > memoryUsed = contestant->getMemoryUsed(index); - - for (int i = 0; i < needRejudge.size(); i ++) { - int a = needRejudge[i].first, b = needRejudge[i].second; - result[a][b] = thread->getResult()[a][b]; - message[a][b] = thread->getMessage()[a][b]; - score[a][b] = thread->getScore()[a][b]; - timeUsed[a][b] = thread->getTimeUsed()[a][b]; - memoryUsed[a][b] = thread->getMemoryUsed()[a][b]; - } - - contestant->setResult(index, result); - contestant->setMessage(index, message); - contestant->setScore(index, score); - contestant->setTimeUsed(index, timeUsed); - contestant->setMemoryUsed(index, memoryUsed); - - delete thread; - clearPath(Settings::temporaryPath()); - } - - contestant->setCheckJudged(index, true); - emit taskJudgingFinished(); - - contestant->setJudgingTime(QDateTime::currentDateTime()); - QDir().rmdir(Settings::temporaryPath()); - emit contestantJudgingFinished(); -} - -void Contest::judge(const QString &name) -{ - clearPath(Settings::temporaryPath()); - stopJudging = false; - judge(contestantList.value(name)); -} - -void Contest::judge(const QString &name, int index) -{ - clearPath(Settings::temporaryPath()); - stopJudging = false; - judge(contestantList.value(name), index); -} - -void Contest::judgeAll() -{ - clearPath(Settings::temporaryPath()); - stopJudging = false; - QList contestants = contestantList.values(); - for (int i = 0; i < contestants.size(); i ++) { - judge(contestants[i]); - if (stopJudging) break; - } -} - -void Contest::stopJudgingSlot() -{ - stopJudging = true; - emit stopJudgingSignal(); -} - -void Contest::writeToStream(QDataStream &out) -{ - out << signed(MagicNumber); - out << contestTitle; - out << taskList.size(); - for (int i = 0; i < taskList.size(); i ++) - taskList[i]->writeToStream(out); - out << contestantList.size(); - QList list = contestantList.values(); - for (int i = 0; i < list.size(); i ++) - list[i]->writeToStream(out); -} - -void Contest::readFromStream(QDataStream &in) -{ - int count; - in >> contestTitle; - in >> count; - for (int i = 0; i < count; i ++) { - Task *newTask = new Task(this); - newTask->readFromStream(in); - newTask->refreshCompilerConfiguration(settings); - taskList.append(newTask); - } - in >> count; - for (int i = 0; i < count; i ++) { - Contestant *newContestant = new Contestant(this); - newContestant->readFromStream(in); - connect(this, SIGNAL(taskAddedForContestant()), - newContestant, SLOT(addTask())); - connect(this, SIGNAL(taskDeletedForContestant(int)), - newContestant, SLOT(deleteTask(int))); - contestantList.insert(newContestant->getContestantName(), newContestant); - } -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include +#include "contest.h" +#include "task.h" +#include "testcase.h" +#include "settings.h" +#include "compiler.h" +#include "contestant.h" +#include "judgingthread.h" +#include "assignmentthread.h" + +Contest::Contest(QObject *parent) : + QObject(parent) +{ +} + +void Contest::setSettings(Settings *_settings) +{ + settings = _settings; +} + +void Contest::setContestTitle(const QString &title) +{ + contestTitle = title; +} + +const QString& Contest::getContestTitle() const +{ + return contestTitle; +} + +Task* Contest::getTask(int index) const +{ + if (0 <= index && index < taskList.size()) + return taskList[index]; + else + return 0; +} + +const QList& Contest::getTaskList() const +{ + return taskList; +} + +Contestant* Contest::getContestant(const QString &name) const +{ + if (contestantList.contains(name)) + return contestantList.value(name); + else + return 0; +} + +QList Contest::getContestantList() const +{ + return contestantList.values(); +} + +int Contest::getTotalTimeLimit() const +{ + int total = 0; + for (int i = 0; i < taskList.size(); i ++) { + QList testCaseList = taskList[i]->getTestCaseList(); + for (int j = 0; j < testCaseList.size(); j ++) + total += testCaseList[j]->getTimeLimit() * testCaseList[j]->getInputFiles().size(); + } + return total; +} + +void Contest::addTask(Task *task) +{ + task->setParent(this); + taskList.append(task); + connect(task, SIGNAL(problemTitleChanged(QString)), + this, SIGNAL(problemTitleChanged())); + emit taskAddedForContestant(); + emit taskAddedForViewer(); +} + +void Contest::deleteTask(int index) +{ + if (0 <= index && index < taskList.size()) { + delete taskList[index]; + taskList.removeAt(index); + } + emit taskDeletedForContestant(index); + emit taskDeletedForViewer(index); +} + +void Contest::refreshContestantList() +{ + QStringList nameList = QDir(Settings::sourcePath()).entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot); + QStringList curNameList = contestantList.keys(); + for (int i = 0; i < curNameList.size(); i ++) + if (! nameList.contains(curNameList[i])) { + delete contestantList[curNameList[i]]; + contestantList.remove(curNameList[i]); + } + for (int i = 0; i < nameList.size(); i ++) + if (! contestantList.contains(nameList[i])) { + Contestant *newContestant = new Contestant(this); + newContestant->setContestantName(nameList[i]); + for (int j = 0; j < taskList.size(); j ++) + newContestant->addTask(); + contestantList.insert(nameList[i], newContestant); + connect(this, SIGNAL(taskAddedForContestant()), + newContestant, SLOT(addTask())); + connect(this, SIGNAL(taskDeletedForContestant(int)), + newContestant, SLOT(deleteTask(int))); + } +} + +void Contest::deleteContestant(const QString &name) +{ + if (! contestantList.contains(name)) return; + delete contestantList[name]; + contestantList.remove(name); +} + +void Contest::clearPath(const QString &curDir) +{ + QDir dir(curDir); + QStringList fileList = dir.entryList(QDir::Files); + for (int i = 0; i < fileList.size(); i ++) + dir.remove(fileList[i]); + QStringList dirList = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (int i = 0; i < dirList.size(); i ++) { + clearPath(curDir + dirList[i] + QDir::separator()); + dir.rmdir(dirList[i]); + } +} + +void Contest::judge(Contestant *contestant) +{ + emit contestantJudgingStart(contestant->getContestantName()); + QDir(QDir::current()).mkdir(Settings::temporaryPath()); + for (int i = 0; i < taskList.size(); i ++) { + emit taskJudgingStarted(taskList[i]->getProblemTile()); + + AssignmentThread *thread = new AssignmentThread(); + connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), + this, SIGNAL(singleCaseFinished(int, int, int, int))); + connect(thread, SIGNAL(compileError(int, int)), + this, SIGNAL(compileError(int, int))); + connect(this, SIGNAL(stopJudgingSignal()), + thread, SLOT(stopJudgingSlot())); + thread->setSettings(settings); + thread->setTask(taskList[i]); + thread->setContestantName(contestant->getContestantName()); + QEventLoop *eventLoop = new QEventLoop(this); + connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); + thread->start(); + eventLoop->exec(); + delete eventLoop; + + if (stopJudging) { + delete thread; + clearPath(Settings::temporaryPath()); + QDir().rmdir(Settings::temporaryPath()); + return; + } + + contestant->setCompileState(i, thread->getCompileState()); + contestant->setCompileMessage(i, thread->getCompileMessage()); + contestant->setSourceFile(i, thread->getSourceFile()); + contestant->setInputFiles(i, thread->getInputFiles()); + contestant->setResult(i, thread->getResult()); + contestant->setMessage(i, thread->getMessage()); + contestant->setScore(i, thread->getScore()); + contestant->setTimeUsed(i, thread->getTimeUsed()); + contestant->setMemoryUsed(i, thread->getMemoryUsed()); + QList< QPair > needRejudge = thread->getNeedRejudge(); + + delete thread; + clearPath(Settings::temporaryPath()); + + if (needRejudge.size() > 0) { + AssignmentThread *thread = new AssignmentThread(); + connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), + this, SIGNAL(singleCaseFinished(int, int, int, int))); + connect(thread, SIGNAL(compileError(int, int)), + this, SIGNAL(compileError(int, int))); + connect(this, SIGNAL(stopJudgingSignal()), + thread, SLOT(stopJudgingSlot())); + thread->setCheckRejudgeMode(true); + thread->setNeedRejudge(needRejudge); + thread->setSettings(settings); + thread->setTask(taskList[i]); + thread->setContestantName(contestant->getContestantName()); + QEventLoop *eventLoop = new QEventLoop(this); + connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); + thread->start(); + eventLoop->exec(); + delete eventLoop; + + if (stopJudging) { + delete thread; + clearPath(Settings::temporaryPath()); + QDir().rmdir(Settings::temporaryPath()); + return; + } + + QList< QList > result = contestant->getResult(i); + QList message = contestant->getMessage(i); + QList< QList > score = contestant->getSocre(i); + QList< QList > timeUsed = contestant->getTimeUsed(i); + QList< QList > memoryUsed = contestant->getMemoryUsed(i); + + for (int j = 0; j < needRejudge.size(); j ++) { + int a = needRejudge[j].first, b = needRejudge[j].second; + result[a][b] = thread->getResult()[a][b]; + message[a][b] = thread->getMessage()[a][b]; + score[a][b] = thread->getScore()[a][b]; + timeUsed[a][b] = thread->getTimeUsed()[a][b]; + memoryUsed[a][b] = thread->getMemoryUsed()[a][b]; + } + + contestant->setResult(i, result); + contestant->setMessage(i, message); + contestant->setScore(i, score); + contestant->setTimeUsed(i, timeUsed); + contestant->setMemoryUsed(i, memoryUsed); + + delete thread; + clearPath(Settings::temporaryPath()); + } + + contestant->setCheckJudged(i, true); + emit taskJudgingFinished(); + } + contestant->setJudgingTime(QDateTime::currentDateTime()); + QDir().rmdir(Settings::temporaryPath()); + emit contestantJudgingFinished(); +} + +void Contest::judge(Contestant *contestant, int index) +{ + emit contestantJudgingStart(contestant->getContestantName()); + QDir(QDir::current()).mkdir(Settings::temporaryPath()); + + emit taskJudgingStarted(taskList[index]->getProblemTile()); + + AssignmentThread *thread = new AssignmentThread(); + connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), + this, SIGNAL(singleCaseFinished(int, int, int, int))); + connect(thread, SIGNAL(compileError(int, int)), + this, SIGNAL(compileError(int, int))); + connect(this, SIGNAL(stopJudgingSignal()), + thread, SLOT(stopJudgingSlot())); + thread->setSettings(settings); + thread->setTask(taskList[index]); + thread->setContestantName(contestant->getContestantName()); + QEventLoop *eventLoop = new QEventLoop(this); + connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); + thread->start(); + eventLoop->exec(); + delete eventLoop; + + if (stopJudging) { + delete thread; + clearPath(Settings::temporaryPath()); + QDir().rmdir(Settings::temporaryPath()); + return; + } + + contestant->setCompileState(index, thread->getCompileState()); + contestant->setCompileMessage(index, thread->getCompileMessage()); + contestant->setSourceFile(index, thread->getSourceFile()); + contestant->setInputFiles(index, thread->getInputFiles()); + contestant->setResult(index, thread->getResult()); + contestant->setMessage(index, thread->getMessage()); + contestant->setScore(index, thread->getScore()); + contestant->setTimeUsed(index, thread->getTimeUsed()); + contestant->setMemoryUsed(index, thread->getMemoryUsed()); + QList< QPair > needRejudge = thread->getNeedRejudge(); + + delete thread; + clearPath(Settings::temporaryPath()); + + if (needRejudge.size() > 0) { + AssignmentThread *thread = new AssignmentThread(); + connect(thread, SIGNAL(singleCaseFinished(int, int, int, int)), + this, SIGNAL(singleCaseFinished(int, int, int, int))); + connect(thread, SIGNAL(compileError(int, int)), + this, SIGNAL(compileError(int, int))); + connect(this, SIGNAL(stopJudgingSignal()), + thread, SLOT(stopJudgingSlot())); + thread->setCheckRejudgeMode(true); + thread->setNeedRejudge(needRejudge); + thread->setSettings(settings); + thread->setTask(taskList[index]); + thread->setContestantName(contestant->getContestantName()); + QEventLoop *eventLoop = new QEventLoop(this); + connect(thread, SIGNAL(finished()), eventLoop, SLOT(quit())); + thread->start(); + eventLoop->exec(); + delete eventLoop; + + if (stopJudging) { + delete thread; + clearPath(Settings::temporaryPath()); + QDir().rmdir(Settings::temporaryPath()); + return; + } + + QList< QList > result = contestant->getResult(index); + QList message = contestant->getMessage(index); + QList< QList > score = contestant->getSocre(index); + QList< QList > timeUsed = contestant->getTimeUsed(index); + QList< QList > memoryUsed = contestant->getMemoryUsed(index); + + for (int i = 0; i < needRejudge.size(); i ++) { + int a = needRejudge[i].first, b = needRejudge[i].second; + result[a][b] = thread->getResult()[a][b]; + message[a][b] = thread->getMessage()[a][b]; + score[a][b] = thread->getScore()[a][b]; + timeUsed[a][b] = thread->getTimeUsed()[a][b]; + memoryUsed[a][b] = thread->getMemoryUsed()[a][b]; + } + + contestant->setResult(index, result); + contestant->setMessage(index, message); + contestant->setScore(index, score); + contestant->setTimeUsed(index, timeUsed); + contestant->setMemoryUsed(index, memoryUsed); + + delete thread; + clearPath(Settings::temporaryPath()); + } + + contestant->setCheckJudged(index, true); + emit taskJudgingFinished(); + + contestant->setJudgingTime(QDateTime::currentDateTime()); + QDir().rmdir(Settings::temporaryPath()); + emit contestantJudgingFinished(); +} + +void Contest::judge(const QString &name) +{ + clearPath(Settings::temporaryPath()); + stopJudging = false; + judge(contestantList.value(name)); +} + +void Contest::judge(const QString &name, int index) +{ + clearPath(Settings::temporaryPath()); + stopJudging = false; + judge(contestantList.value(name), index); +} + +void Contest::judgeAll() +{ + clearPath(Settings::temporaryPath()); + stopJudging = false; + QList contestants = contestantList.values(); + for (int i = 0; i < contestants.size(); i ++) { + judge(contestants[i]); + if (stopJudging) break; + } +} + +void Contest::stopJudgingSlot() +{ + stopJudging = true; + emit stopJudgingSignal(); +} + +void Contest::writeToStream(QDataStream &out) +{ + out << signed(MagicNumber); + out << contestTitle; + out << taskList.size(); + for (int i = 0; i < taskList.size(); i ++) + taskList[i]->writeToStream(out); + out << contestantList.size(); + QList list = contestantList.values(); + for (int i = 0; i < list.size(); i ++) + list[i]->writeToStream(out); +} + +void Contest::readFromStream(QDataStream &in) +{ + int count; + in >> contestTitle; + in >> count; + for (int i = 0; i < count; i ++) { + Task *newTask = new Task(this); + newTask->readFromStream(in); + newTask->refreshCompilerConfiguration(settings); + taskList.append(newTask); + } + in >> count; + for (int i = 0; i < count; i ++) { + Contestant *newContestant = new Contestant(this); + newContestant->readFromStream(in); + connect(this, SIGNAL(taskAddedForContestant()), + newContestant, SLOT(addTask())); + connect(this, SIGNAL(taskDeletedForContestant(int)), + newContestant, SLOT(deleteTask(int))); + contestantList.insert(newContestant->getContestantName(), newContestant); + } +} diff --git a/contest.h b/contest.h index 2a995d6..aa27b26 100644 --- a/contest.h +++ b/contest.h @@ -1,82 +1,82 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef CONTEST_H -#define CONTEST_H - -#include -#include -#include "globaltype.h" -#define MagicNumber 0x20101231 - -class Task; -class Settings; -class Contestant; - -class Contest : public QObject -{ - Q_OBJECT -public: - explicit Contest(QObject *parent = 0); - void setSettings(Settings*); - void setContestTitle(const QString&); - const QString& getContestTitle() const; - Task* getTask(int) const; - const QList& getTaskList() const; - Contestant* getContestant(const QString&) const; - QList getContestantList() const; - int getTotalTimeLimit() const; - void addTask(Task*); - void deleteTask(int); - void refreshContestantList(); - void deleteContestant(const QString&); - void writeToStream(QDataStream&); - void readFromStream(QDataStream&); - -private: - QString contestTitle; - Settings *settings; - QList taskList; - QMap contestantList; - bool stopJudging; - void judge(Contestant*); - void judge(Contestant*, int); - void clearPath(const QString&); - -public slots: - void judge(const QString&); - void judge(const QString&, int); - void judgeAll(); - void stopJudgingSlot(); - -signals: - void taskAddedForContestant(); - void taskDeletedForContestant(int); - void taskAddedForViewer(); - void taskDeletedForViewer(int); - void problemTitleChanged(); - void singleCaseFinished(int, int, int, int); - void taskJudgingStarted(QString); - void taskJudgingFinished(); - void contestantJudgingStart(QString); - void contestantJudgingFinished(); - void compileError(int, int); - void stopJudgingSignal(); -}; - -#endif // CONTEST_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef CONTEST_H +#define CONTEST_H + +#include +#include +#include "globaltype.h" +#define MagicNumber 0x20101231 + +class Task; +class Settings; +class Contestant; + +class Contest : public QObject +{ + Q_OBJECT +public: + explicit Contest(QObject *parent = 0); + void setSettings(Settings*); + void setContestTitle(const QString&); + const QString& getContestTitle() const; + Task* getTask(int) const; + const QList& getTaskList() const; + Contestant* getContestant(const QString&) const; + QList getContestantList() const; + int getTotalTimeLimit() const; + void addTask(Task*); + void deleteTask(int); + void refreshContestantList(); + void deleteContestant(const QString&); + void writeToStream(QDataStream&); + void readFromStream(QDataStream&); + +private: + QString contestTitle; + Settings *settings; + QList taskList; + QMap contestantList; + bool stopJudging; + void judge(Contestant*); + void judge(Contestant*, int); + void clearPath(const QString&); + +public slots: + void judge(const QString&); + void judge(const QString&, int); + void judgeAll(); + void stopJudgingSlot(); + +signals: + void taskAddedForContestant(); + void taskDeletedForContestant(int); + void taskAddedForViewer(); + void taskDeletedForViewer(int); + void problemTitleChanged(); + void singleCaseFinished(int, int, int, int); + void taskJudgingStarted(QString); + void taskJudgingFinished(); + void contestantJudgingStart(QString); + void contestantJudgingFinished(); + void compileError(int, int); + void stopJudgingSignal(); +}; + +#endif // CONTEST_H diff --git a/contestant.cpp b/contestant.cpp index a70d2e2..d4ef409 100644 --- a/contestant.cpp +++ b/contestant.cpp @@ -1,271 +1,271 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "contestant.h" -#include "contest.h" - -Contestant::Contestant(QObject *parent) : - QObject(parent) -{ -} - -const QString& Contestant::getContestantName() const -{ - return contestantName; -} - -bool Contestant::getCheckJudged(int index) const -{ - return checkJudged[index]; -} - -CompileState Contestant::getCompileState(int index) const -{ - return compileState[index]; -} - -const QString& Contestant::getSourceFile(int index) const -{ - return sourceFile[index]; -} - -const QString& Contestant::getCompileMessage(int index) const -{ - return compileMesaage[index]; -} - -const QList& Contestant::getInputFiles(int index) const -{ - return inputFiles[index]; -} - -const QList< QList >& Contestant::getResult(int index) const -{ - return result[index]; -} - -const QList& Contestant::getMessage(int index) const -{ - return message[index]; -} - -const QList< QList >& Contestant::getSocre(int index) const -{ - return score[index]; -} - -const QList< QList >& Contestant::getTimeUsed(int index) const -{ - return timeUsed[index]; -} - -const QList< QList >& Contestant::getMemoryUsed(int index) const -{ - return memoryUsed[index]; -} - -QDateTime Contestant::getJudingTime() const -{ - return judgingTime; -} - -void Contestant::setContestantName(const QString &name) -{ - contestantName = name; -} - -void Contestant::setCheckJudged(int index, bool check) -{ - checkJudged[index] = check; -} - -void Contestant::setCompileState(int index, CompileState state) -{ - compileState[index] = state; -} - -void Contestant::setSourceFile(int index, const QString &fileName) -{ - sourceFile[index] = fileName; -} - -void Contestant::setCompileMessage(int index, const QString &text) -{ - compileMesaage[index] = text; -} - -void Contestant::setInputFiles(int index, const QList &files) -{ - inputFiles[index] = files; -} - -void Contestant::setResult(int index, const QList< QList > &_result) -{ - result[index] = _result; -} - -void Contestant::setMessage(int index, const QList&_message) -{ - message[index] = _message; -} - -void Contestant::setScore(int index, const QList< QList > &_score) -{ - score[index] = _score; -} - -void Contestant::setTimeUsed(int index, const QList< QList > &_timeUsed) -{ - timeUsed[index] = _timeUsed; -} - -void Contestant::setMemoryUsed(int index, const QList< QList > &_memoryUsed) -{ - memoryUsed[index] = _memoryUsed; -} - -void Contestant::setJudgingTime(QDateTime time) -{ - judgingTime = time; -} - -void Contestant::addTask() -{ - checkJudged.append(false); - compileState.append(NoValidSourceFile); - sourceFile.append(""); - compileMesaage.append(""); - inputFiles.append(QList()); - result.append(QList< QList >()); - message.append(QList()); - score.append(QList< QList >()); - timeUsed.append(QList< QList >()); - memoryUsed.append(QList< QList >()); -} - -void Contestant::deleteTask(int index) -{ - checkJudged.removeAt(index); - compileState.removeAt(index); - sourceFile.removeAt(index); - compileMesaage.removeAt(index); - inputFiles.removeAt(index); - result.removeAt(index); - message.removeAt(index); - score.removeAt(index); - timeUsed.removeAt(index); - memoryUsed.removeAt(index); -} - -int Contestant::getTaskScore(int index) const -{ - if (0 > index || index >= checkJudged.size()) return -1; - if (! checkJudged[index]) return -1; - int total = 0; - for (int i = 0; i < score[index].size(); i ++) { - int minv = 1000000000; - for (int j = 0; j < score[index][i].size(); j ++) - if (score[index][i][j] < minv) minv = score[index][i][j]; - if (minv == 1000000000) minv = 0; - total += minv; - } - return total; -} - -int Contestant::getTotalScore() const -{ - if (checkJudged.size() == 0) return -1; - for (int i = 0; i < checkJudged.size(); i ++) - if (! checkJudged[i]) return -1; - int total = 0; - for (int i = 0; i < score.size(); i ++) - total += getTaskScore(i); - return total; -} - -int Contestant::getTotalUsedTime() const -{ - if (checkJudged.size() == 0) return -1; - for (int i = 0; i < checkJudged.size(); i ++) - if (! checkJudged[i]) return -1; - int total = 0; - for (int i = 0; i < timeUsed.size(); i ++) - for (int j = 0; j < timeUsed[i].size(); j ++) - for (int k = 0; k < timeUsed[i][j].size(); k ++) - if (timeUsed[i][j][k] >= 0) total += timeUsed[i][j][k]; - return total; -} - -void Contestant::writeToStream(QDataStream &out) -{ - out << contestantName; - out << checkJudged; - out << sourceFile; - out << compileMesaage; - out << inputFiles; - out << message; - out << score; - out << timeUsed; - out << memoryUsed; - out << judgingTime; - out << compileState.size(); - for (int i = 0; i < compileState.size(); i ++) - out << int(compileState[i]); - out << result.size(); - for (int i = 0; i < result.size(); i ++) { - out << result[i].size(); - for (int j = 0; j < result[i].size(); j ++) { - out << result[i][j].size(); - for (int k = 0; k < result[i][j].size(); k ++) - out << int(result[i][j][k]); - } - } -} - -void Contestant::readFromStream(QDataStream &in) -{ - in >> contestantName; - in >> checkJudged; - in >> sourceFile; - in >> compileMesaage; - in >> inputFiles; - in >> message; - in >> score; - in >> timeUsed; - in >> memoryUsed; - in >> judgingTime; - int count, _count, __count, tmp; - in >> count; - for (int i = 0; i < count; i ++) { - in >> tmp; - compileState.append(CompileState(tmp)); - } - in >> count; - for (int i = 0; i < count; i ++) { - result.append(QList< QList >()); - in >> _count; - for (int j = 0; j < _count; j ++) { - result[i].append(QList()); - in >> __count; - for (int k = 0; k < __count; k ++) { - in >> tmp; - result[i][j].append(ResultState(tmp)); - } - } - } -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "contestant.h" +#include "contest.h" + +Contestant::Contestant(QObject *parent) : + QObject(parent) +{ +} + +const QString& Contestant::getContestantName() const +{ + return contestantName; +} + +bool Contestant::getCheckJudged(int index) const +{ + return checkJudged[index]; +} + +CompileState Contestant::getCompileState(int index) const +{ + return compileState[index]; +} + +const QString& Contestant::getSourceFile(int index) const +{ + return sourceFile[index]; +} + +const QString& Contestant::getCompileMessage(int index) const +{ + return compileMesaage[index]; +} + +const QList& Contestant::getInputFiles(int index) const +{ + return inputFiles[index]; +} + +const QList< QList >& Contestant::getResult(int index) const +{ + return result[index]; +} + +const QList& Contestant::getMessage(int index) const +{ + return message[index]; +} + +const QList< QList >& Contestant::getSocre(int index) const +{ + return score[index]; +} + +const QList< QList >& Contestant::getTimeUsed(int index) const +{ + return timeUsed[index]; +} + +const QList< QList >& Contestant::getMemoryUsed(int index) const +{ + return memoryUsed[index]; +} + +QDateTime Contestant::getJudingTime() const +{ + return judgingTime; +} + +void Contestant::setContestantName(const QString &name) +{ + contestantName = name; +} + +void Contestant::setCheckJudged(int index, bool check) +{ + checkJudged[index] = check; +} + +void Contestant::setCompileState(int index, CompileState state) +{ + compileState[index] = state; +} + +void Contestant::setSourceFile(int index, const QString &fileName) +{ + sourceFile[index] = fileName; +} + +void Contestant::setCompileMessage(int index, const QString &text) +{ + compileMesaage[index] = text; +} + +void Contestant::setInputFiles(int index, const QList &files) +{ + inputFiles[index] = files; +} + +void Contestant::setResult(int index, const QList< QList > &_result) +{ + result[index] = _result; +} + +void Contestant::setMessage(int index, const QList&_message) +{ + message[index] = _message; +} + +void Contestant::setScore(int index, const QList< QList > &_score) +{ + score[index] = _score; +} + +void Contestant::setTimeUsed(int index, const QList< QList > &_timeUsed) +{ + timeUsed[index] = _timeUsed; +} + +void Contestant::setMemoryUsed(int index, const QList< QList > &_memoryUsed) +{ + memoryUsed[index] = _memoryUsed; +} + +void Contestant::setJudgingTime(QDateTime time) +{ + judgingTime = time; +} + +void Contestant::addTask() +{ + checkJudged.append(false); + compileState.append(NoValidSourceFile); + sourceFile.append(""); + compileMesaage.append(""); + inputFiles.append(QList()); + result.append(QList< QList >()); + message.append(QList()); + score.append(QList< QList >()); + timeUsed.append(QList< QList >()); + memoryUsed.append(QList< QList >()); +} + +void Contestant::deleteTask(int index) +{ + checkJudged.removeAt(index); + compileState.removeAt(index); + sourceFile.removeAt(index); + compileMesaage.removeAt(index); + inputFiles.removeAt(index); + result.removeAt(index); + message.removeAt(index); + score.removeAt(index); + timeUsed.removeAt(index); + memoryUsed.removeAt(index); +} + +int Contestant::getTaskScore(int index) const +{ + if (0 > index || index >= checkJudged.size()) return -1; + if (! checkJudged[index]) return -1; + int total = 0; + for (int i = 0; i < score[index].size(); i ++) { + int minv = 1000000000; + for (int j = 0; j < score[index][i].size(); j ++) + if (score[index][i][j] < minv) minv = score[index][i][j]; + if (minv == 1000000000) minv = 0; + total += minv; + } + return total; +} + +int Contestant::getTotalScore() const +{ + if (checkJudged.size() == 0) return -1; + for (int i = 0; i < checkJudged.size(); i ++) + if (! checkJudged[i]) return -1; + int total = 0; + for (int i = 0; i < score.size(); i ++) + total += getTaskScore(i); + return total; +} + +int Contestant::getTotalUsedTime() const +{ + if (checkJudged.size() == 0) return -1; + for (int i = 0; i < checkJudged.size(); i ++) + if (! checkJudged[i]) return -1; + int total = 0; + for (int i = 0; i < timeUsed.size(); i ++) + for (int j = 0; j < timeUsed[i].size(); j ++) + for (int k = 0; k < timeUsed[i][j].size(); k ++) + if (timeUsed[i][j][k] >= 0) total += timeUsed[i][j][k]; + return total; +} + +void Contestant::writeToStream(QDataStream &out) +{ + out << contestantName; + out << checkJudged; + out << sourceFile; + out << compileMesaage; + out << inputFiles; + out << message; + out << score; + out << timeUsed; + out << memoryUsed; + out << judgingTime; + out << compileState.size(); + for (int i = 0; i < compileState.size(); i ++) + out << int(compileState[i]); + out << result.size(); + for (int i = 0; i < result.size(); i ++) { + out << result[i].size(); + for (int j = 0; j < result[i].size(); j ++) { + out << result[i][j].size(); + for (int k = 0; k < result[i][j].size(); k ++) + out << int(result[i][j][k]); + } + } +} + +void Contestant::readFromStream(QDataStream &in) +{ + in >> contestantName; + in >> checkJudged; + in >> sourceFile; + in >> compileMesaage; + in >> inputFiles; + in >> message; + in >> score; + in >> timeUsed; + in >> memoryUsed; + in >> judgingTime; + int count, _count, __count, tmp; + in >> count; + for (int i = 0; i < count; i ++) { + in >> tmp; + compileState.append(CompileState(tmp)); + } + in >> count; + for (int i = 0; i < count; i ++) { + result.append(QList< QList >()); + in >> _count; + for (int j = 0; j < _count; j ++) { + result[i].append(QList()); + in >> __count; + for (int k = 0; k < __count; k ++) { + in >> tmp; + result[i][j].append(ResultState(tmp)); + } + } + } +} diff --git a/contestant.h b/contestant.h index 01743b7..1bfe9f9 100644 --- a/contestant.h +++ b/contestant.h @@ -1,85 +1,85 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef CONTESTANT_H -#define CONTESTANT_H - -#include -#include -#include "globaltype.h" - -class Contestant : public QObject -{ - Q_OBJECT -public: - explicit Contestant(QObject *parent = 0); - - const QString& getContestantName() const; - bool getCheckJudged(int) const; - CompileState getCompileState(int) const; - const QString& getSourceFile(int) const; - const QString& getCompileMessage(int) const; - const QList& getInputFiles(int) const; - const QList< QList >& getResult(int) const; - const QList& getMessage(int) const; - const QList< QList >& getSocre(int) const; - const QList< QList >& getTimeUsed(int) const; - const QList< QList >& getMemoryUsed(int) const; - QDateTime getJudingTime() const; - int getTaskScore(int) const; - int getTotalScore() const; - int getTotalUsedTime() const; - - void setContestantName(const QString&); - void setCheckJudged(int, bool); - void setCompileState(int, CompileState); - void setSourceFile(int, const QString&); - void setCompileMessage(int, const QString&); - void setInputFiles(int, const QList&); - void setResult(int, const QList< QList >&); - void setMessage(int, const QList&); - void setScore(int, const QList< QList >&); - void setTimeUsed(int, const QList< QList >&); - void setMemoryUsed(int, const QList< QList >&); - void setJudgingTime(QDateTime); - - void writeToStream(QDataStream&); - void readFromStream(QDataStream&); - -private: - QString contestantName; - QList checkJudged; - QList compileState; - QStringList sourceFile; - QStringList compileMesaage; - QList< QList > inputFiles; - QList< QList< QList > > result; - QList< QList > message; - QList< QList< QList > > score; - QList< QList< QList > > timeUsed; - QList< QList< QList > > memoryUsed; - QDateTime judgingTime; - -signals: - -public slots: - void addTask(); - void deleteTask(int); -}; - -#endif // CONTESTANT_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef CONTESTANT_H +#define CONTESTANT_H + +#include +#include +#include "globaltype.h" + +class Contestant : public QObject +{ + Q_OBJECT +public: + explicit Contestant(QObject *parent = 0); + + const QString& getContestantName() const; + bool getCheckJudged(int) const; + CompileState getCompileState(int) const; + const QString& getSourceFile(int) const; + const QString& getCompileMessage(int) const; + const QList& getInputFiles(int) const; + const QList< QList >& getResult(int) const; + const QList& getMessage(int) const; + const QList< QList >& getSocre(int) const; + const QList< QList >& getTimeUsed(int) const; + const QList< QList >& getMemoryUsed(int) const; + QDateTime getJudingTime() const; + int getTaskScore(int) const; + int getTotalScore() const; + int getTotalUsedTime() const; + + void setContestantName(const QString&); + void setCheckJudged(int, bool); + void setCompileState(int, CompileState); + void setSourceFile(int, const QString&); + void setCompileMessage(int, const QString&); + void setInputFiles(int, const QList&); + void setResult(int, const QList< QList >&); + void setMessage(int, const QList&); + void setScore(int, const QList< QList >&); + void setTimeUsed(int, const QList< QList >&); + void setMemoryUsed(int, const QList< QList >&); + void setJudgingTime(QDateTime); + + void writeToStream(QDataStream&); + void readFromStream(QDataStream&); + +private: + QString contestantName; + QList checkJudged; + QList compileState; + QStringList sourceFile; + QStringList compileMesaage; + QList< QList > inputFiles; + QList< QList< QList > > result; + QList< QList > message; + QList< QList< QList > > score; + QList< QList< QList > > timeUsed; + QList< QList< QList > > memoryUsed; + QDateTime judgingTime; + +signals: + +public slots: + void addTask(); + void deleteTask(int); +}; + +#endif // CONTESTANT_H diff --git a/detaildialog.cpp b/detaildialog.cpp index 4419e9d..f140b51 100644 --- a/detaildialog.cpp +++ b/detaildialog.cpp @@ -1,415 +1,415 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "detaildialog.h" -#include "ui_detaildialog.h" -#include "task.h" -#include "testcase.h" -#include "contest.h" -#include "contestant.h" -#include "globaltype.h" -#include "judgingdialog.h" - -DetailDialog::DetailDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::DetailDialog) -{ - ui->setupUi(this); - connect(ui->detailViewer, SIGNAL(anchorClicked(QUrl)), - this, SLOT(anchorClicked(QUrl))); -} - -DetailDialog::~DetailDialog() -{ - delete ui; -} - -QString DetailDialog::getCode(Contest *contest, Contestant *contestant) -{ - QString htmlCode; - - QList taskList = contest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) { - htmlCode += "

"; - htmlCode += QString("%1 %2
").arg(tr("Task")).arg(taskList[i]->getProblemTile()); - - if (! contestant->getCheckJudged(i)) { - htmlCode += QString("  %1

").arg(tr("Not judged")); - continue; - } - - if (taskList[i]->getTaskType() == Task::Traditional) { - if (contestant->getCompileState(i) != CompileSuccessfully) { - switch (contestant->getCompileState(i)) { - case NoValidSourceFile: { - htmlCode += QString("  %1

").arg(tr("Cannot find valid source file")); - break; - } - case CompileTimeLimitExceeded: { - htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); - htmlCode += QString("  %1

").arg(tr("Compile time limit exceeded")); - break; - } - case InvalidCompiler: { - htmlCode += QString("  %1

").arg(tr("Cannot run given compiler")); - break; - } - case CompileError: { - htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); - htmlCode += QString("  %1").arg(tr("Compile error")); - if (! contestant->getCompileMessage(i).isEmpty()) { - QString compileMessage = contestant->getCompileMessage(i); - compileMessage.replace("\r\n", "
"); - compileMessage.replace("\n", "
"); - compileMessage.replace("\r", "
"); - if (compileMessage.endsWith("
")) - compileMessage.chop(4); - htmlCode += ""; - htmlCode += "
"; - htmlCode += compileMessage; - htmlCode += "
"; - } - htmlCode += "

"; - break; - } - } - continue; - } - htmlCode += QString("  %1%2").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); - } - - htmlCode += ""; - htmlCode += QString("").arg(tr("Test Case")); - htmlCode += QString("").arg(tr("Input File")); - htmlCode += QString("").arg(tr("Result")); - htmlCode += QString("").arg(tr("Time Used")); - htmlCode += QString("").arg(tr("Memory Used")); - htmlCode += QString("").arg(tr("Score")); - - QList inputFiles = contestant->getInputFiles(i); - QList< QList > result = contestant->getResult(i); - QList message = contestant->getMessage(i); - QList< QList > timeUsed = contestant->getTimeUsed(i); - QList< QList > memoryUsed = contestant->getMemoryUsed(i); - QList< QList > score = contestant->getSocre(i); - - for (int j = 0; j < inputFiles.size(); j ++) { - for (int k = 0; k < inputFiles[j].size(); k ++) { - htmlCode += ""; - if (k == 0) { - htmlCode += QString("") - .arg(inputFiles[j].size()).arg(j + 1); - } - - htmlCode += QString("").arg(inputFiles[j][k]); - - QString text; - switch (result[j][k]) { - case CorrectAnswer: { - text = tr("Correct Answer"); - break; - } - case WrongAnswer: { - text = tr("Wrong Answer"); - break; - } - case PartlyCorrect: { - text = tr("Partly Correct"); - break; - } - case TimeLimitExceeded: { - text = tr("Time Limit Exceeded"); - break; - } - case MemoryLimitExceeded: { - text = tr("Memory Limit Exceeded"); - break; - } - case CannotStartProgram: { - text = tr("Cannot Start Program"); - break; - } - case FileError: { - text = tr("File Error"); - break; - } - case RunTimeError: { - text = tr("Run Time Error"); - break; - } - case InvalidSpecialJudge: { - text = tr("Invalid Special Judge"); - break; - } - case SpecialJudgeTimeLimitExceeded: { - text = tr("Special Judge Time Limit Exceeded"); - break; - } - case SpecialJudgeRunTimeError: { - text = tr("Special Judge Run Time Error"); - break; - } - } - - htmlCode += QString(""; - - htmlCode += ""; - - htmlCode += ""; - - if (k == 0) { - htmlCode += QString("").arg(minv); - } - - htmlCode += ""; - } - } - - htmlCode += "
%1%1%1%1%1%1
#%2%1%1").arg(text); - if (! message[j][k].isEmpty()) { - QString tmp = message[j][k]; - tmp.replace("\n", "\\n"); - tmp.replace("\"", "\\"); - htmlCode += QString(" (...)") - .arg(tmp); - } - htmlCode += ""; - if (timeUsed[j][k] != -1) - htmlCode += QString("").sprintf("%.3lf s", double(timeUsed[j][k]) / 1000); - else - htmlCode += tr("Invalid"); - htmlCode += ""; - if (memoryUsed[j][k] != -1) - htmlCode += QString("").sprintf("%.3lf MB", double(memoryUsed[j][k]) / 1024 / 1024); - else - htmlCode += tr("Invalid"); - htmlCode += "").arg(inputFiles[j].size()); - int minv = 1000000000; - for (int t = 0; t < inputFiles[j].size(); t ++) - if (score[j][t] < minv) minv = score[j][t]; - htmlCode += QString("%1

"; - } - - htmlCode += QString("

%1

").arg(tr("Return to top")); - - return htmlCode; -} - -void DetailDialog::refreshViewer(Contest *_contest, Contestant *_contestant) -{ - contest = _contest; - contestant = _contestant; - - setWindowTitle(tr("Contestant: %1").arg(contestant->getContestantName())); - ui->detailViewer->clear(); - QString htmlCode; - - htmlCode += ""; - htmlCode += ""; - htmlCode += ""; - - QList taskList = contest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) { - htmlCode += "

"; - htmlCode += QString("%1 %2 (%4)
") - .arg(tr("Task")).arg(taskList[i]->getProblemTile()).arg(i).arg(tr("Rejudge")); - - if (! contestant->getCheckJudged(i)) { - htmlCode += QString("  %1

").arg(tr("Not judged")); - continue; - } - - if (taskList[i]->getTaskType() == Task::Traditional) { - if (contestant->getCompileState(i) != CompileSuccessfully) { - switch (contestant->getCompileState(i)) { - case NoValidSourceFile: { - htmlCode += QString("  %1

").arg(tr("Cannot find valid source file")); - break; - } - case CompileTimeLimitExceeded: { - htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); - htmlCode += QString("  %1

").arg(tr("Compile time limit exceeded")); - break; - } - case InvalidCompiler: { - htmlCode += QString("  %1

").arg(tr("Cannot run given compiler")); - break; - } - case CompileError: { - htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); - htmlCode += QString("  %1").arg(tr("Compile error")); - if (! contestant->getCompileMessage(i).isEmpty()) - htmlCode += QString("
(...)").arg(i); - htmlCode += "

"; - break; - } - } - continue; - } - htmlCode += QString("  %1%2").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); - } - - htmlCode += ""; - htmlCode += QString("").arg(tr("Test Case")); - htmlCode += QString("").arg(tr("Input File")); - htmlCode += QString("").arg(tr("Result")); - htmlCode += QString("").arg(tr("Time Used")); - htmlCode += QString("").arg(tr("Memory Used")); - htmlCode += QString("").arg(tr("Score")); - - QList inputFiles = contestant->getInputFiles(i); - QList< QList > result = contestant->getResult(i); - QList message = contestant->getMessage(i); - QList< QList > timeUsed = contestant->getTimeUsed(i); - QList< QList > memoryUsed = contestant->getMemoryUsed(i); - QList< QList > score = contestant->getSocre(i); - - for (int j = 0; j < inputFiles.size(); j ++) { - for (int k = 0; k < inputFiles[j].size(); k ++) { - htmlCode += ""; - if (k == 0) { - htmlCode += QString("") - .arg(inputFiles[j].size()).arg(j + 1); - } - - htmlCode += QString("").arg(inputFiles[j][k]); - - QString text; - switch (result[j][k]) { - case CorrectAnswer: { - text = tr("Correct Answer"); - break; - } - case WrongAnswer: { - text = tr("Wrong Answer"); - break; - } - case PartlyCorrect: { - text = tr("Partly Correct"); - break; - } - case TimeLimitExceeded: { - text = tr("Time Limit Exceeded"); - break; - } - case MemoryLimitExceeded: { - text = tr("Memory Limit Exceeded"); - break; - } - case CannotStartProgram: { - text = tr("Cannot Start Program"); - break; - } - case FileError: { - text = tr("File Error"); - break; - } - case RunTimeError: { - text = tr("Run Time Error"); - break; - } - case InvalidSpecialJudge: { - text = tr("Invalid Special Judge"); - break; - } - case SpecialJudgeTimeLimitExceeded: { - text = tr("Special Judge Time Limit Exceeded"); - break; - } - case SpecialJudgeRunTimeError: { - text = tr("Special Judge Run Time Error"); - break; - } - } - - htmlCode += QString(""; - - htmlCode += ""; - - htmlCode += ""; - - if (k == 0) { - htmlCode += QString("").arg(minv); - } - - htmlCode += ""; - } - } - - htmlCode += "
%1%1%1%1%1%1
#%2%1%1").arg(text); - if (! message[j][k].isEmpty()) - htmlCode += QString(" (...)").arg(i).arg(j).arg(k); - htmlCode += ""; - if (timeUsed[j][k] != -1) - htmlCode += QString("").sprintf("%.3lf s", double(timeUsed[j][k]) / 1000); - else - htmlCode += tr("Invalid"); - htmlCode += ""; - if (memoryUsed[j][k] != -1) - htmlCode += QString("").sprintf("%.3lf MB", double(memoryUsed[j][k]) / 1024 / 1024); - else - htmlCode += tr("Invalid"); - htmlCode += "").arg(inputFiles[j].size()); - int minv = 1000000000; - for (int t = 0; t < inputFiles[j].size(); t ++) - if (score[j][t] < minv) minv = score[j][t]; - htmlCode += QString("%1

"; - } - - htmlCode += ""; - ui->detailViewer->setHtml(htmlCode); -} - -void DetailDialog::showDialog() -{ - show(); - QScrollBar *bar = ui->detailViewer->verticalScrollBar(); - bar->setValue(bar->minimum()); - bar = ui->detailViewer->horizontalScrollBar(); - bar->setValue(bar->minimum()); - exec(); -} - -void DetailDialog::anchorClicked(const QUrl &url) -{ - QStringList list = url.path().split(' ', QString::SkipEmptyParts); - - if (list[0] == "Rejudge") { - JudgingDialog *dialog = new JudgingDialog(this); - dialog->setModal(true); - dialog->setContest(contest); - dialog->show(); - dialog->judge(contestant->getContestantName(), list[1].toInt()); - delete dialog; - emit rejudgeSignal(); - refreshViewer(contest, contestant); - } - - if (list[0] == "CompileMessage") { - QMessageBox(QMessageBox::NoIcon, tr("Compile Message"), - QString("%1").arg(contestant->getCompileMessage(list[1].toInt())), - QMessageBox::Close, this).exec(); - } - - if (list[0] == "Message") { - QList message = contestant->getMessage(list[1].toInt()); - QMessageBox(QMessageBox::NoIcon, tr("Message"), - QString("%1").arg(message[list[2].toInt()][list[3].toInt()]), - QMessageBox::Close, this).exec(); - } -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "detaildialog.h" +#include "ui_detaildialog.h" +#include "task.h" +#include "testcase.h" +#include "contest.h" +#include "contestant.h" +#include "globaltype.h" +#include "judgingdialog.h" + +DetailDialog::DetailDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::DetailDialog) +{ + ui->setupUi(this); + connect(ui->detailViewer, SIGNAL(anchorClicked(QUrl)), + this, SLOT(anchorClicked(QUrl))); +} + +DetailDialog::~DetailDialog() +{ + delete ui; +} + +QString DetailDialog::getCode(Contest *contest, Contestant *contestant) +{ + QString htmlCode; + + QList taskList = contest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) { + htmlCode += "

"; + htmlCode += QString("%1 %2
").arg(tr("Task")).arg(taskList[i]->getProblemTile()); + + if (! contestant->getCheckJudged(i)) { + htmlCode += QString("  %1

").arg(tr("Not judged")); + continue; + } + + if (taskList[i]->getTaskType() == Task::Traditional) { + if (contestant->getCompileState(i) != CompileSuccessfully) { + switch (contestant->getCompileState(i)) { + case NoValidSourceFile: { + htmlCode += QString("  %1

").arg(tr("Cannot find valid source file")); + break; + } + case CompileTimeLimitExceeded: { + htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); + htmlCode += QString("  %1

").arg(tr("Compile time limit exceeded")); + break; + } + case InvalidCompiler: { + htmlCode += QString("  %1

").arg(tr("Cannot run given compiler")); + break; + } + case CompileError: { + htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); + htmlCode += QString("  %1").arg(tr("Compile error")); + if (! contestant->getCompileMessage(i).isEmpty()) { + QString compileMessage = contestant->getCompileMessage(i); + compileMessage.replace("\r\n", "
"); + compileMessage.replace("\n", "
"); + compileMessage.replace("\r", "
"); + if (compileMessage.endsWith("
")) + compileMessage.chop(4); + htmlCode += ""; + htmlCode += "
"; + htmlCode += compileMessage; + htmlCode += "
"; + } + htmlCode += "

"; + break; + } + } + continue; + } + htmlCode += QString("  %1%2").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); + } + + htmlCode += ""; + htmlCode += QString("").arg(tr("Test Case")); + htmlCode += QString("").arg(tr("Input File")); + htmlCode += QString("").arg(tr("Result")); + htmlCode += QString("").arg(tr("Time Used")); + htmlCode += QString("").arg(tr("Memory Used")); + htmlCode += QString("").arg(tr("Score")); + + QList inputFiles = contestant->getInputFiles(i); + QList< QList > result = contestant->getResult(i); + QList message = contestant->getMessage(i); + QList< QList > timeUsed = contestant->getTimeUsed(i); + QList< QList > memoryUsed = contestant->getMemoryUsed(i); + QList< QList > score = contestant->getSocre(i); + + for (int j = 0; j < inputFiles.size(); j ++) { + for (int k = 0; k < inputFiles[j].size(); k ++) { + htmlCode += ""; + if (k == 0) { + htmlCode += QString("") + .arg(inputFiles[j].size()).arg(j + 1); + } + + htmlCode += QString("").arg(inputFiles[j][k]); + + QString text; + switch (result[j][k]) { + case CorrectAnswer: { + text = tr("Correct Answer"); + break; + } + case WrongAnswer: { + text = tr("Wrong Answer"); + break; + } + case PartlyCorrect: { + text = tr("Partly Correct"); + break; + } + case TimeLimitExceeded: { + text = tr("Time Limit Exceeded"); + break; + } + case MemoryLimitExceeded: { + text = tr("Memory Limit Exceeded"); + break; + } + case CannotStartProgram: { + text = tr("Cannot Start Program"); + break; + } + case FileError: { + text = tr("File Error"); + break; + } + case RunTimeError: { + text = tr("Run Time Error"); + break; + } + case InvalidSpecialJudge: { + text = tr("Invalid Special Judge"); + break; + } + case SpecialJudgeTimeLimitExceeded: { + text = tr("Special Judge Time Limit Exceeded"); + break; + } + case SpecialJudgeRunTimeError: { + text = tr("Special Judge Run Time Error"); + break; + } + } + + htmlCode += QString(""; + + htmlCode += ""; + + htmlCode += ""; + + if (k == 0) { + htmlCode += QString("").arg(minv); + } + + htmlCode += ""; + } + } + + htmlCode += "
%1%1%1%1%1%1
#%2%1%1").arg(text); + if (! message[j][k].isEmpty()) { + QString tmp = message[j][k]; + tmp.replace("\n", "\\n"); + tmp.replace("\"", "\\"); + htmlCode += QString(" (...)") + .arg(tmp); + } + htmlCode += ""; + if (timeUsed[j][k] != -1) + htmlCode += QString("").sprintf("%.3lf s", double(timeUsed[j][k]) / 1000); + else + htmlCode += tr("Invalid"); + htmlCode += ""; + if (memoryUsed[j][k] != -1) + htmlCode += QString("").sprintf("%.3lf MB", double(memoryUsed[j][k]) / 1024 / 1024); + else + htmlCode += tr("Invalid"); + htmlCode += "").arg(inputFiles[j].size()); + int minv = 1000000000; + for (int t = 0; t < inputFiles[j].size(); t ++) + if (score[j][t] < minv) minv = score[j][t]; + htmlCode += QString("%1

"; + } + + htmlCode += QString("

%1

").arg(tr("Return to top")); + + return htmlCode; +} + +void DetailDialog::refreshViewer(Contest *_contest, Contestant *_contestant) +{ + contest = _contest; + contestant = _contestant; + + setWindowTitle(tr("Contestant: %1").arg(contestant->getContestantName())); + ui->detailViewer->clear(); + QString htmlCode; + + htmlCode += ""; + htmlCode += ""; + htmlCode += ""; + + QList taskList = contest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) { + htmlCode += "

"; + htmlCode += QString("%1 %2 (%4)
") + .arg(tr("Task")).arg(taskList[i]->getProblemTile()).arg(i).arg(tr("Rejudge")); + + if (! contestant->getCheckJudged(i)) { + htmlCode += QString("  %1

").arg(tr("Not judged")); + continue; + } + + if (taskList[i]->getTaskType() == Task::Traditional) { + if (contestant->getCompileState(i) != CompileSuccessfully) { + switch (contestant->getCompileState(i)) { + case NoValidSourceFile: { + htmlCode += QString("  %1

").arg(tr("Cannot find valid source file")); + break; + } + case CompileTimeLimitExceeded: { + htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); + htmlCode += QString("  %1

").arg(tr("Compile time limit exceeded")); + break; + } + case InvalidCompiler: { + htmlCode += QString("  %1

").arg(tr("Cannot run given compiler")); + break; + } + case CompileError: { + htmlCode += QString("  %1%2
").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); + htmlCode += QString("  %1").arg(tr("Compile error")); + if (! contestant->getCompileMessage(i).isEmpty()) + htmlCode += QString("
(...)").arg(i); + htmlCode += "

"; + break; + } + } + continue; + } + htmlCode += QString("  %1%2").arg(tr("Source file: ")).arg(contestant->getSourceFile(i)); + } + + htmlCode += ""; + htmlCode += QString("").arg(tr("Test Case")); + htmlCode += QString("").arg(tr("Input File")); + htmlCode += QString("").arg(tr("Result")); + htmlCode += QString("").arg(tr("Time Used")); + htmlCode += QString("").arg(tr("Memory Used")); + htmlCode += QString("").arg(tr("Score")); + + QList inputFiles = contestant->getInputFiles(i); + QList< QList > result = contestant->getResult(i); + QList message = contestant->getMessage(i); + QList< QList > timeUsed = contestant->getTimeUsed(i); + QList< QList > memoryUsed = contestant->getMemoryUsed(i); + QList< QList > score = contestant->getSocre(i); + + for (int j = 0; j < inputFiles.size(); j ++) { + for (int k = 0; k < inputFiles[j].size(); k ++) { + htmlCode += ""; + if (k == 0) { + htmlCode += QString("") + .arg(inputFiles[j].size()).arg(j + 1); + } + + htmlCode += QString("").arg(inputFiles[j][k]); + + QString text; + switch (result[j][k]) { + case CorrectAnswer: { + text = tr("Correct Answer"); + break; + } + case WrongAnswer: { + text = tr("Wrong Answer"); + break; + } + case PartlyCorrect: { + text = tr("Partly Correct"); + break; + } + case TimeLimitExceeded: { + text = tr("Time Limit Exceeded"); + break; + } + case MemoryLimitExceeded: { + text = tr("Memory Limit Exceeded"); + break; + } + case CannotStartProgram: { + text = tr("Cannot Start Program"); + break; + } + case FileError: { + text = tr("File Error"); + break; + } + case RunTimeError: { + text = tr("Run Time Error"); + break; + } + case InvalidSpecialJudge: { + text = tr("Invalid Special Judge"); + break; + } + case SpecialJudgeTimeLimitExceeded: { + text = tr("Special Judge Time Limit Exceeded"); + break; + } + case SpecialJudgeRunTimeError: { + text = tr("Special Judge Run Time Error"); + break; + } + } + + htmlCode += QString(""; + + htmlCode += ""; + + htmlCode += ""; + + if (k == 0) { + htmlCode += QString("").arg(minv); + } + + htmlCode += ""; + } + } + + htmlCode += "
%1%1%1%1%1%1
#%2%1%1").arg(text); + if (! message[j][k].isEmpty()) + htmlCode += QString(" (...)").arg(i).arg(j).arg(k); + htmlCode += ""; + if (timeUsed[j][k] != -1) + htmlCode += QString("").sprintf("%.3lf s", double(timeUsed[j][k]) / 1000); + else + htmlCode += tr("Invalid"); + htmlCode += ""; + if (memoryUsed[j][k] != -1) + htmlCode += QString("").sprintf("%.3lf MB", double(memoryUsed[j][k]) / 1024 / 1024); + else + htmlCode += tr("Invalid"); + htmlCode += "").arg(inputFiles[j].size()); + int minv = 1000000000; + for (int t = 0; t < inputFiles[j].size(); t ++) + if (score[j][t] < minv) minv = score[j][t]; + htmlCode += QString("%1

"; + } + + htmlCode += ""; + ui->detailViewer->setHtml(htmlCode); +} + +void DetailDialog::showDialog() +{ + show(); + QScrollBar *bar = ui->detailViewer->verticalScrollBar(); + bar->setValue(bar->minimum()); + bar = ui->detailViewer->horizontalScrollBar(); + bar->setValue(bar->minimum()); + exec(); +} + +void DetailDialog::anchorClicked(const QUrl &url) +{ + QStringList list = url.path().split(' ', QString::SkipEmptyParts); + + if (list[0] == "Rejudge") { + JudgingDialog *dialog = new JudgingDialog(this); + dialog->setModal(true); + dialog->setContest(contest); + dialog->show(); + dialog->judge(contestant->getContestantName(), list[1].toInt()); + delete dialog; + emit rejudgeSignal(); + refreshViewer(contest, contestant); + } + + if (list[0] == "CompileMessage") { + QMessageBox(QMessageBox::NoIcon, tr("Compile Message"), + QString("%1").arg(contestant->getCompileMessage(list[1].toInt())), + QMessageBox::Close, this).exec(); + } + + if (list[0] == "Message") { + QList message = contestant->getMessage(list[1].toInt()); + QMessageBox(QMessageBox::NoIcon, tr("Message"), + QString("%1").arg(message[list[2].toInt()][list[3].toInt()]), + QMessageBox::Close, this).exec(); + } +} diff --git a/detaildialog.h b/detaildialog.h index c2eaf75..541f0f5 100644 --- a/detaildialog.h +++ b/detaildialog.h @@ -1,56 +1,56 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef DETAILDIALOG_H -#define DETAILDIALOG_H - -#include -#include -#include - -class Contestant; -class Contest; - -namespace Ui { - class DetailDialog; -} - -class DetailDialog : public QDialog -{ - Q_OBJECT - -public: - explicit DetailDialog(QWidget *parent = 0); - ~DetailDialog(); - void refreshViewer(Contest*, Contestant*); - void showDialog(); - static QString getCode(Contest*, Contestant*); - -private: - Ui::DetailDialog *ui; - Contest *contest; - Contestant *contestant; - -private slots: - void anchorClicked(const QUrl&); - -signals: - void rejudgeSignal(); -}; - -#endif // DETAILDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef DETAILDIALOG_H +#define DETAILDIALOG_H + +#include +#include +#include + +class Contestant; +class Contest; + +namespace Ui { + class DetailDialog; +} + +class DetailDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DetailDialog(QWidget *parent = 0); + ~DetailDialog(); + void refreshViewer(Contest*, Contestant*); + void showDialog(); + static QString getCode(Contest*, Contestant*); + +private: + Ui::DetailDialog *ui; + Contest *contest; + Contestant *contestant; + +private slots: + void anchorClicked(const QUrl&); + +signals: + void rejudgeSignal(); +}; + +#endif // DETAILDIALOG_H diff --git a/detaildialog.ui b/detaildialog.ui index 56a0dbd..7cc12dc 100644 --- a/detaildialog.ui +++ b/detaildialog.ui @@ -1,72 +1,72 @@ - - - DetailDialog - - - - 0 - 0 - 709 - 520 - - - - Details - - - - - - Qt::LinksAccessibleByMouse - - - false - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - &Close - - - - - - - - - - - closeButton - clicked() - DetailDialog - accept() - - - 650 - 493 - - - 354 - 259 - - - - - + + + DetailDialog + + + + 0 + 0 + 709 + 520 + + + + Details + + + + + + Qt::LinksAccessibleByMouse + + + false + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Close + + + + + + + + + + + closeButton + clicked() + DetailDialog + accept() + + + 650 + 493 + + + 354 + 259 + + + + + diff --git a/editvariabledialog.cpp b/editvariabledialog.cpp index 81c4b94..b96c33a 100644 --- a/editvariabledialog.cpp +++ b/editvariabledialog.cpp @@ -1,66 +1,66 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "editvariabledialog.h" -#include "ui_editvariabledialog.h" - -EditVariableDialog::EditVariableDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::EditVariableDialog) -{ - ui->setupUi(this); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - - connect(ui->variableName, SIGNAL(textChanged(QString)), - this, SLOT(textChanged())); - connect(ui->variableValue, SIGNAL(textChanged(QString)), - this, SLOT(textChanged())); -} - -EditVariableDialog::~EditVariableDialog() -{ - delete ui; -} - -void EditVariableDialog::setVariableName(const QString &variable) -{ - ui->variableName->setText(variable); -} - -void EditVariableDialog::setVariableValue(const QString &value) -{ - ui->variableValue->setText(value); -} - -QString EditVariableDialog::getVariableName() const -{ - return ui->variableName->text(); -} - -QString EditVariableDialog::getVariableValue() const -{ - return ui->variableValue->text(); -} - -void EditVariableDialog::textChanged() -{ - if (! ui->variableName->text().isEmpty() && ! ui->variableValue->text().isEmpty()) - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - else - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "editvariabledialog.h" +#include "ui_editvariabledialog.h" + +EditVariableDialog::EditVariableDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::EditVariableDialog) +{ + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + connect(ui->variableName, SIGNAL(textChanged(QString)), + this, SLOT(textChanged())); + connect(ui->variableValue, SIGNAL(textChanged(QString)), + this, SLOT(textChanged())); +} + +EditVariableDialog::~EditVariableDialog() +{ + delete ui; +} + +void EditVariableDialog::setVariableName(const QString &variable) +{ + ui->variableName->setText(variable); +} + +void EditVariableDialog::setVariableValue(const QString &value) +{ + ui->variableValue->setText(value); +} + +QString EditVariableDialog::getVariableName() const +{ + return ui->variableName->text(); +} + +QString EditVariableDialog::getVariableValue() const +{ + return ui->variableValue->text(); +} + +void EditVariableDialog::textChanged() +{ + if (! ui->variableName->text().isEmpty() && ! ui->variableValue->text().isEmpty()) + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + else + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); +} diff --git a/editvariabledialog.h b/editvariabledialog.h index ebf3146..fc55e85 100644 --- a/editvariabledialog.h +++ b/editvariabledialog.h @@ -1,49 +1,49 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef EDITVARIABLEDIALOG_H -#define EDITVARIABLEDIALOG_H - -#include -#include -#include - -namespace Ui { - class EditVariableDialog; -} - -class EditVariableDialog : public QDialog -{ - Q_OBJECT - -public: - explicit EditVariableDialog(QWidget *parent = 0); - ~EditVariableDialog(); - void setVariableName(const QString&); - void setVariableValue(const QString&); - QString getVariableName() const; - QString getVariableValue() const; - -private: - Ui::EditVariableDialog *ui; - -private slots: - void textChanged(); -}; - -#endif // EDITVARIABLEDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef EDITVARIABLEDIALOG_H +#define EDITVARIABLEDIALOG_H + +#include +#include +#include + +namespace Ui { + class EditVariableDialog; +} + +class EditVariableDialog : public QDialog +{ + Q_OBJECT + +public: + explicit EditVariableDialog(QWidget *parent = 0); + ~EditVariableDialog(); + void setVariableName(const QString&); + void setVariableValue(const QString&); + QString getVariableName() const; + QString getVariableValue() const; + +private: + Ui::EditVariableDialog *ui; + +private slots: + void textChanged(); +}; + +#endif // EDITVARIABLEDIALOG_H diff --git a/editvariabledialog.ui b/editvariabledialog.ui index bba58f9..c9243b3 100644 --- a/editvariabledialog.ui +++ b/editvariabledialog.ui @@ -1,115 +1,123 @@ - - - EditVariableDialog - - - - 0 - 0 - 321 - 106 - - - - - 321 - 106 - - - - - 321 - 106 - - - - Dialog - - - - 8 - - - - - 10 - - - 8 - - - - - font-size:9pt; - - - Variable Name - - - - - - - - - - font-size:9pt; - - - Variable Value - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - EditVariableDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - EditVariableDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - + + + EditVariableDialog + + + + 0 + 0 + 321 + 106 + + + + + 321 + 106 + + + + + 321 + 106 + + + + Dialog + + + + 8 + + + + + 10 + + + 8 + + + + + font-size:9pt; + + + Variable Name + + + + + + + font-size:9pt; + + + + + + + font-size:9pt; + + + Variable Value + + + + + + + font-size:9pt; + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + EditVariableDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + EditVariableDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/environmentvariablesdialog.cpp b/environmentvariablesdialog.cpp index 86f1679..90d397b 100644 --- a/environmentvariablesdialog.cpp +++ b/environmentvariablesdialog.cpp @@ -1,123 +1,123 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "environmentvariablesdialog.h" -#include "ui_environmentvariablesdialog.h" -#include "editvariabledialog.h" - -EnvironmentVariablesDialog::EnvironmentVariablesDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::EnvironmentVariablesDialog) -{ - ui->setupUi(this); - - connect(ui->addButton, SIGNAL(clicked()), - this, SLOT(addButtonClicked())); - connect(ui->editButton, SIGNAL(clicked()), - this, SLOT(editButtonClicked())); - connect(ui->deleteButton, SIGNAL(clicked()), - this, SLOT(deleteButtonClicked())); - connect(ui->valueViewer, SIGNAL(itemSelectionChanged()), - this, SLOT(viewerSelectionChanged())); -} - -EnvironmentVariablesDialog::~EnvironmentVariablesDialog() -{ - delete ui; -} - -void EnvironmentVariablesDialog::setProcessEnvironment(const QProcessEnvironment &environment) -{ - QStringList values = environment.toStringList(); - ui->valueViewer->setRowCount(values.size()); - for (int i = 0; i < values.size(); i ++) { - int tmp = values[i].indexOf('='); - QString variable = values[i].mid(0, tmp); - QString value = values[i].mid(tmp + 1); - ui->valueViewer->setItem(i, 0, new QTableWidgetItem(variable)); - ui->valueViewer->setItem(i, 1, new QTableWidgetItem(value)); - } -} - -QProcessEnvironment EnvironmentVariablesDialog::getProcessEnvironment() const -{ - QProcessEnvironment environment; - for (int i = 0; i < ui->valueViewer->rowCount(); i ++) { - QString variable = ui->valueViewer->item(i, 0)->text(); - QString value = ui->valueViewer->item(i, 1)->text(); - environment.insert(variable, value); - } - return environment; -} - -void EnvironmentVariablesDialog::addButtonClicked() -{ - EditVariableDialog *dialog = new EditVariableDialog(this); - dialog->setWindowTitle(tr("Add New Variable")); - if (dialog->exec() == QDialog::Accepted) { - ui->valueViewer->setRowCount(ui->valueViewer->rowCount() + 1); - ui->valueViewer->setItem(ui->valueViewer->rowCount() - 1, 0, - new QTableWidgetItem(dialog->getVariableName())); - ui->valueViewer->setItem(ui->valueViewer->rowCount() - 1, 1, - new QTableWidgetItem(dialog->getVariableValue())); - } - delete dialog; -} - -void EnvironmentVariablesDialog::editButtonClicked() -{ - int index = ui->valueViewer->currentRow(); - EditVariableDialog *dialog = new EditVariableDialog(this); - dialog->setWindowTitle(tr("Edit Variable")); - dialog->setVariableName(ui->valueViewer->item(index, 0)->text()); - dialog->setVariableValue(ui->valueViewer->item(index, 1)->text()); - if (dialog->exec() == QDialog::Accepted) { - ui->valueViewer->setItem(index, 0, new QTableWidgetItem(dialog->getVariableName())); - ui->valueViewer->setItem(index, 1, new QTableWidgetItem(dialog->getVariableValue())); - } - delete dialog; -} - -void EnvironmentVariablesDialog::deleteButtonClicked() -{ - int index = ui->valueViewer->currentRow(); - QString variable = ui->valueViewer->item(index, 0)->text(); - - if (QMessageBox::question(this, tr("Lemon"), tr("Are you sure to delete variable %1?").arg(variable), - QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok) { - return; - } - - for (int i = index + 1; i < ui->valueViewer->rowCount(); i ++) { - ui->valueViewer->setItem(i - 1, 0, new QTableWidgetItem(ui->valueViewer->item(i, 0)->text())); - ui->valueViewer->setItem(i - 1, 1, new QTableWidgetItem(ui->valueViewer->item(i, 1)->text())); - } - ui->valueViewer->setRowCount(ui->valueViewer->rowCount() - 1); -} - -void EnvironmentVariablesDialog::viewerSelectionChanged() -{ - QList range = ui->valueViewer->selectedRanges(); - if (range.size() > 0) { - ui->editButton->setEnabled(true); - ui->deleteButton->setEnabled(true); - } else { - ui->editButton->setEnabled(false); - ui->deleteButton->setEnabled(false); - } -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "environmentvariablesdialog.h" +#include "ui_environmentvariablesdialog.h" +#include "editvariabledialog.h" + +EnvironmentVariablesDialog::EnvironmentVariablesDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::EnvironmentVariablesDialog) +{ + ui->setupUi(this); + + connect(ui->addButton, SIGNAL(clicked()), + this, SLOT(addButtonClicked())); + connect(ui->editButton, SIGNAL(clicked()), + this, SLOT(editButtonClicked())); + connect(ui->deleteButton, SIGNAL(clicked()), + this, SLOT(deleteButtonClicked())); + connect(ui->valueViewer, SIGNAL(itemSelectionChanged()), + this, SLOT(viewerSelectionChanged())); +} + +EnvironmentVariablesDialog::~EnvironmentVariablesDialog() +{ + delete ui; +} + +void EnvironmentVariablesDialog::setProcessEnvironment(const QProcessEnvironment &environment) +{ + QStringList values = environment.toStringList(); + ui->valueViewer->setRowCount(values.size()); + for (int i = 0; i < values.size(); i ++) { + int tmp = values[i].indexOf('='); + QString variable = values[i].mid(0, tmp); + QString value = values[i].mid(tmp + 1); + ui->valueViewer->setItem(i, 0, new QTableWidgetItem(variable)); + ui->valueViewer->setItem(i, 1, new QTableWidgetItem(value)); + } +} + +QProcessEnvironment EnvironmentVariablesDialog::getProcessEnvironment() const +{ + QProcessEnvironment environment; + for (int i = 0; i < ui->valueViewer->rowCount(); i ++) { + QString variable = ui->valueViewer->item(i, 0)->text(); + QString value = ui->valueViewer->item(i, 1)->text(); + environment.insert(variable, value); + } + return environment; +} + +void EnvironmentVariablesDialog::addButtonClicked() +{ + EditVariableDialog *dialog = new EditVariableDialog(this); + dialog->setWindowTitle(tr("Add New Variable")); + if (dialog->exec() == QDialog::Accepted) { + ui->valueViewer->setRowCount(ui->valueViewer->rowCount() + 1); + ui->valueViewer->setItem(ui->valueViewer->rowCount() - 1, 0, + new QTableWidgetItem(dialog->getVariableName())); + ui->valueViewer->setItem(ui->valueViewer->rowCount() - 1, 1, + new QTableWidgetItem(dialog->getVariableValue())); + } + delete dialog; +} + +void EnvironmentVariablesDialog::editButtonClicked() +{ + int index = ui->valueViewer->currentRow(); + EditVariableDialog *dialog = new EditVariableDialog(this); + dialog->setWindowTitle(tr("Edit Variable")); + dialog->setVariableName(ui->valueViewer->item(index, 0)->text()); + dialog->setVariableValue(ui->valueViewer->item(index, 1)->text()); + if (dialog->exec() == QDialog::Accepted) { + ui->valueViewer->setItem(index, 0, new QTableWidgetItem(dialog->getVariableName())); + ui->valueViewer->setItem(index, 1, new QTableWidgetItem(dialog->getVariableValue())); + } + delete dialog; +} + +void EnvironmentVariablesDialog::deleteButtonClicked() +{ + int index = ui->valueViewer->currentRow(); + QString variable = ui->valueViewer->item(index, 0)->text(); + + if (QMessageBox::question(this, tr("Lemon"), tr("Are you sure to delete variable %1?").arg(variable), + QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok) { + return; + } + + for (int i = index + 1; i < ui->valueViewer->rowCount(); i ++) { + ui->valueViewer->setItem(i - 1, 0, new QTableWidgetItem(ui->valueViewer->item(i, 0)->text())); + ui->valueViewer->setItem(i - 1, 1, new QTableWidgetItem(ui->valueViewer->item(i, 1)->text())); + } + ui->valueViewer->setRowCount(ui->valueViewer->rowCount() - 1); +} + +void EnvironmentVariablesDialog::viewerSelectionChanged() +{ + QList range = ui->valueViewer->selectedRanges(); + if (range.size() > 0) { + ui->editButton->setEnabled(true); + ui->deleteButton->setEnabled(true); + } else { + ui->editButton->setEnabled(false); + ui->deleteButton->setEnabled(false); + } +} diff --git a/environmentvariablesdialog.h b/environmentvariablesdialog.h index 74fb687..c7fa8f7 100644 --- a/environmentvariablesdialog.h +++ b/environmentvariablesdialog.h @@ -1,50 +1,50 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef ENVIRONMENTVARIABLESDIALOG_H -#define ENVIRONMENTVARIABLESDIALOG_H - -#include -#include -#include - -namespace Ui { - class EnvironmentVariablesDialog; -} - -class EnvironmentVariablesDialog : public QDialog -{ - Q_OBJECT - -public: - explicit EnvironmentVariablesDialog(QWidget *parent = 0); - ~EnvironmentVariablesDialog(); - void setProcessEnvironment(const QProcessEnvironment&); - QProcessEnvironment getProcessEnvironment() const; - -private: - Ui::EnvironmentVariablesDialog *ui; - -private slots: - void addButtonClicked(); - void editButtonClicked(); - void deleteButtonClicked(); - void viewerSelectionChanged(); -}; - -#endif // ENVIRONMENTVARIABLESDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef ENVIRONMENTVARIABLESDIALOG_H +#define ENVIRONMENTVARIABLESDIALOG_H + +#include +#include +#include + +namespace Ui { + class EnvironmentVariablesDialog; +} + +class EnvironmentVariablesDialog : public QDialog +{ + Q_OBJECT + +public: + explicit EnvironmentVariablesDialog(QWidget *parent = 0); + ~EnvironmentVariablesDialog(); + void setProcessEnvironment(const QProcessEnvironment&); + QProcessEnvironment getProcessEnvironment() const; + +private: + Ui::EnvironmentVariablesDialog *ui; + +private slots: + void addButtonClicked(); + void editButtonClicked(); + void deleteButtonClicked(); + void viewerSelectionChanged(); +}; + +#endif // ENVIRONMENTVARIABLESDIALOG_H diff --git a/environmentvariablesdialog.ui b/environmentvariablesdialog.ui index 3515918..417ffcb 100644 --- a/environmentvariablesdialog.ui +++ b/environmentvariablesdialog.ui @@ -1,161 +1,161 @@ - - - EnvironmentVariablesDialog - - - - 0 - 0 - 298 - 196 - - - - - 298 - 196 - - - - Extra Environment Variables - - - - 8 - - - - - font-size: 9pt; - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - 80 - - - false - - - true - - - false - - - 25 - - - 25 - - - - Variable - - - - - Value - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - &Add - - - - - - - false - - - &Edit - - - - - - - false - - - &Delete - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - EnvironmentVariablesDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - EnvironmentVariablesDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - + + + EnvironmentVariablesDialog + + + + 0 + 0 + 298 + 196 + + + + + 298 + 196 + + + + Extra Environment Variables + + + + 8 + + + + + font-size: 9pt; + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + 80 + + + false + + + true + + + false + + + 25 + + + 25 + + + + Variable + + + + + Value + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Add + + + + + + + false + + + &Edit + + + + + + + false + + + &Delete + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + EnvironmentVariablesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + EnvironmentVariablesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/filelineedit.cpp b/filelineedit.cpp index 320c128..08e08d5 100644 --- a/filelineedit.cpp +++ b/filelineedit.cpp @@ -1,63 +1,63 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "filelineedit.h" -#include "settings.h" - -FileLineEdit::FileLineEdit(QWidget *parent) : - QLineEdit(parent) -{ - completer = 0; -} - -void FileLineEdit::getFiles(const QString &curDir, const QString &prefix, QStringList &files) -{ - QDir dir(curDir); - if (! nameFilters.isEmpty()) - dir.setNameFilters(nameFilters); - QStringList list = dir.entryList(filters); - for (int i = 0; i < list.size(); i ++) - list[i] = prefix + list[i]; - files.append(list); - list = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (int i = 0; i < list.size(); i ++) - getFiles(curDir + list[i] + QDir::separator(), - prefix + list[i] + QDir::separator(), files); -} - -void FileLineEdit::setFilters(QDir::Filters _filters) -{ - filters = _filters; -} - -void FileLineEdit::setFileExtensions(const QStringList &extensions) -{ - nameFilters.clear(); - for (int i = 0; i < extensions.size(); i ++) - nameFilters.append("*." + extensions[i]); - refreshFileList(); -} - -void FileLineEdit::refreshFileList() -{ - QStringList files; - getFiles(Settings::dataPath(), "", files); - if (completer) delete completer; - completer = new QCompleter(files, this); - setCompleter(completer); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "filelineedit.h" +#include "settings.h" + +FileLineEdit::FileLineEdit(QWidget *parent) : + QLineEdit(parent) +{ + completer = 0; +} + +void FileLineEdit::getFiles(const QString &curDir, const QString &prefix, QStringList &files) +{ + QDir dir(curDir); + if (! nameFilters.isEmpty()) + dir.setNameFilters(nameFilters); + QStringList list = dir.entryList(filters); + for (int i = 0; i < list.size(); i ++) + list[i] = prefix + list[i]; + files.append(list); + list = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (int i = 0; i < list.size(); i ++) + getFiles(curDir + list[i] + QDir::separator(), + prefix + list[i] + QDir::separator(), files); +} + +void FileLineEdit::setFilters(QDir::Filters _filters) +{ + filters = _filters; +} + +void FileLineEdit::setFileExtensions(const QStringList &extensions) +{ + nameFilters.clear(); + for (int i = 0; i < extensions.size(); i ++) + nameFilters.append("*." + extensions[i]); + refreshFileList(); +} + +void FileLineEdit::refreshFileList() +{ + QStringList files; + getFiles(Settings::dataPath(), "", files); + if (completer) delete completer; + completer = new QCompleter(files, this); + setCompleter(completer); +} diff --git a/filelineedit.h b/filelineedit.h index 5273f46..5eb8237 100644 --- a/filelineedit.h +++ b/filelineedit.h @@ -1,44 +1,44 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef FILELINEEDIT_H -#define FILELINEEDIT_H - -#include -#include -#include - -class FileLineEdit : public QLineEdit -{ - Q_OBJECT -public: - explicit FileLineEdit(QWidget *parent = 0); - void setFilters(QDir::Filters); - void setFileExtensions(const QStringList&); - void getFiles(const QString&, const QString&, QStringList&); - -private: - QCompleter *completer; - QStringList nameFilters; - QDir::Filters filters; - -public slots: - void refreshFileList(); -}; - -#endif // FILELINEEDIT_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef FILELINEEDIT_H +#define FILELINEEDIT_H + +#include +#include +#include + +class FileLineEdit : public QLineEdit +{ + Q_OBJECT +public: + explicit FileLineEdit(QWidget *parent = 0); + void setFilters(QDir::Filters); + void setFileExtensions(const QStringList&); + void getFiles(const QString&, const QString&, QStringList&); + +private: + QCompleter *completer; + QStringList nameFilters; + QDir::Filters filters; + +public slots: + void refreshFileList(); +}; + +#endif // FILELINEEDIT_H diff --git a/generalsettings.cpp b/generalsettings.cpp index 7fca34f..4114a44 100644 --- a/generalsettings.cpp +++ b/generalsettings.cpp @@ -1,162 +1,162 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "generalsettings.h" -#include "ui_generalsettings.h" -#include "settings.h" - -GeneralSettings::GeneralSettings(QWidget *parent) : - QWidget(parent), - ui(new Ui::GeneralSettings) -{ - ui->setupUi(this); - - ui->defaultFullScore->setValidator(new QIntValidator(1, Settings::upperBoundForFullScore(), ui->defaultFullScore)); - ui->defaultTimeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->defaultTimeLimit)); - ui->defaultMemoryLimit->setValidator(new QIntValidator(1, Settings::upperBoundForMemoryLimit(), ui->defaultMemoryLimit)); - ui->compileTimeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->compileTimeLimit)); - ui->specialJudgeTimeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->specialJudgeTimeLimit)); - ui->fileSizeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForFileSizeLimit(), ui->fileSizeLimit)); - ui->numberOfThreads->setValidator(new QIntValidator(1, Settings::upperBoundForNumberOfThreads(), ui->defaultFullScore)); - ui->inputFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->inputFileExtensions)); - ui->outputFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->outputFileExtensions)); - - connect(ui->defaultFullScore, SIGNAL(textChanged(QString)), - this, SLOT(defaultFullScoreChanged(QString))); - connect(ui->defaultTimeLimit, SIGNAL(textChanged(QString)), - this, SLOT(defaultTimeLimitChanged(QString))); - connect(ui->defaultMemoryLimit, SIGNAL(textChanged(QString)), - this, SLOT(defaultMemoryLimitChanged(QString))); - connect(ui->compileTimeLimit, SIGNAL(textChanged(QString)), - this, SLOT(compileTimeLimitChanged(QString))); - connect(ui->specialJudgeTimeLimit, SIGNAL(textChanged(QString)), - this, SLOT(specialJudgeTimeLimitChanged(QString))); - connect(ui->fileSizeLimit, SIGNAL(textChanged(QString)), - this, SLOT(fileSizeLimitChanged(QString))); - connect(ui->numberOfThreads, SIGNAL(textChanged(QString)), - this, SLOT(numberOfThreadsChanged(QString))); - connect(ui->inputFileExtensions, SIGNAL(textChanged(QString)), - this, SLOT(inputFileExtensionsChanged(QString))); - connect(ui->outputFileExtensions, SIGNAL(textChanged(QString)), - this, SLOT(outputFileExtensionsChanged(QString))); -} - -GeneralSettings::~GeneralSettings() -{ - delete ui; -} - -void GeneralSettings::resetEditSettings(Settings *settings) -{ - editSettings = settings; - - ui->defaultFullScore->setText(QString("%1").arg(editSettings->getDefaultFullScore())); - ui->defaultTimeLimit->setText(QString("%1").arg(editSettings->getDefaultTimeLimit())); - ui->defaultMemoryLimit->setText(QString("%1").arg(editSettings->getDefaultMemoryLimit())); - ui->compileTimeLimit->setText(QString("%1").arg(editSettings->getCompileTimeLimit())); - ui->specialJudgeTimeLimit->setText(QString("%1").arg(editSettings->getSpecialJudgeTimeLimit())); - ui->fileSizeLimit->setText(QString("%1").arg(editSettings->getFileSizeLimit())); - ui->numberOfThreads->setText(QString("%1").arg(editSettings->getNumberOfThreads())); - ui->inputFileExtensions->setText(editSettings->getInputFileExtensions().join(";")); - ui->outputFileExtensions->setText(editSettings->getOutputFileExtensions().join(";")); -} - -bool GeneralSettings::checkValid() -{ - if (ui->defaultFullScore->text().isEmpty()) { - ui->defaultFullScore->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty default full score!"), QMessageBox::Close); - return false; - } - if (ui->defaultTimeLimit->text().isEmpty()) { - ui->defaultTimeLimit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty default time limit!"), QMessageBox::Close); - return false; - } - if (ui->defaultMemoryLimit->text().isEmpty()) { - ui->defaultMemoryLimit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty default memory limit!"), QMessageBox::Close); - return false; - } - if (ui->compileTimeLimit->text().isEmpty()) { - ui->compileTimeLimit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty compile time limit!"), QMessageBox::Close); - return false; - } - if (ui->specialJudgeTimeLimit->text().isEmpty()) { - ui->specialJudgeTimeLimit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty special judge time limit!"), QMessageBox::Close); - return false; - } - if (ui->fileSizeLimit->text().isEmpty()) { - ui->fileSizeLimit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty source file size limit!"), QMessageBox::Close); - return false; - } - if (ui->numberOfThreads->text().isEmpty()) { - ui->numberOfThreads->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty number of threads!"), QMessageBox::Close); - return false; - } - return true; -} - -void GeneralSettings::defaultFullScoreChanged(const QString &text) -{ - editSettings->setDefaultFullScore(text.toInt()); -} - -void GeneralSettings::defaultTimeLimitChanged(const QString &text) -{ - editSettings->setDefaultTimeLimit(text.toInt()); -} - -void GeneralSettings::defaultMemoryLimitChanged(const QString &text) -{ - editSettings->setDefaultMemoryLimit(text.toInt()); -} - -void GeneralSettings::compileTimeLimitChanged(const QString &text) -{ - editSettings->setCompileTimeLimit(text.toInt()); -} - -void GeneralSettings::specialJudgeTimeLimitChanged(const QString &text) -{ - editSettings->setSpecialJudgeTimeLimit(text.toInt()); -} - -void GeneralSettings::fileSizeLimitChanged(const QString &text) -{ - editSettings->setFileSizeLimit(text.toInt()); -} - -void GeneralSettings::numberOfThreadsChanged(const QString &text) -{ - editSettings->setNumberOfThreads(text.toInt()); -} - -void GeneralSettings::inputFileExtensionsChanged(const QString &text) -{ - editSettings->setInputFileExtensions(text); -} - -void GeneralSettings::outputFileExtensionsChanged(const QString &text) -{ - editSettings->setOutputFileExtensions(text); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "generalsettings.h" +#include "ui_generalsettings.h" +#include "settings.h" + +GeneralSettings::GeneralSettings(QWidget *parent) : + QWidget(parent), + ui(new Ui::GeneralSettings) +{ + ui->setupUi(this); + + ui->defaultFullScore->setValidator(new QIntValidator(1, Settings::upperBoundForFullScore(), ui->defaultFullScore)); + ui->defaultTimeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->defaultTimeLimit)); + ui->defaultMemoryLimit->setValidator(new QIntValidator(1, Settings::upperBoundForMemoryLimit(), ui->defaultMemoryLimit)); + ui->compileTimeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->compileTimeLimit)); + ui->specialJudgeTimeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->specialJudgeTimeLimit)); + ui->fileSizeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForFileSizeLimit(), ui->fileSizeLimit)); + ui->numberOfThreads->setValidator(new QIntValidator(1, Settings::upperBoundForNumberOfThreads(), ui->defaultFullScore)); + ui->inputFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->inputFileExtensions)); + ui->outputFileExtensions->setValidator(new QRegExpValidator(QRegExp("(\\w+;)*\\w+"), ui->outputFileExtensions)); + + connect(ui->defaultFullScore, SIGNAL(textChanged(QString)), + this, SLOT(defaultFullScoreChanged(QString))); + connect(ui->defaultTimeLimit, SIGNAL(textChanged(QString)), + this, SLOT(defaultTimeLimitChanged(QString))); + connect(ui->defaultMemoryLimit, SIGNAL(textChanged(QString)), + this, SLOT(defaultMemoryLimitChanged(QString))); + connect(ui->compileTimeLimit, SIGNAL(textChanged(QString)), + this, SLOT(compileTimeLimitChanged(QString))); + connect(ui->specialJudgeTimeLimit, SIGNAL(textChanged(QString)), + this, SLOT(specialJudgeTimeLimitChanged(QString))); + connect(ui->fileSizeLimit, SIGNAL(textChanged(QString)), + this, SLOT(fileSizeLimitChanged(QString))); + connect(ui->numberOfThreads, SIGNAL(textChanged(QString)), + this, SLOT(numberOfThreadsChanged(QString))); + connect(ui->inputFileExtensions, SIGNAL(textChanged(QString)), + this, SLOT(inputFileExtensionsChanged(QString))); + connect(ui->outputFileExtensions, SIGNAL(textChanged(QString)), + this, SLOT(outputFileExtensionsChanged(QString))); +} + +GeneralSettings::~GeneralSettings() +{ + delete ui; +} + +void GeneralSettings::resetEditSettings(Settings *settings) +{ + editSettings = settings; + + ui->defaultFullScore->setText(QString("%1").arg(editSettings->getDefaultFullScore())); + ui->defaultTimeLimit->setText(QString("%1").arg(editSettings->getDefaultTimeLimit())); + ui->defaultMemoryLimit->setText(QString("%1").arg(editSettings->getDefaultMemoryLimit())); + ui->compileTimeLimit->setText(QString("%1").arg(editSettings->getCompileTimeLimit())); + ui->specialJudgeTimeLimit->setText(QString("%1").arg(editSettings->getSpecialJudgeTimeLimit())); + ui->fileSizeLimit->setText(QString("%1").arg(editSettings->getFileSizeLimit())); + ui->numberOfThreads->setText(QString("%1").arg(editSettings->getNumberOfThreads())); + ui->inputFileExtensions->setText(editSettings->getInputFileExtensions().join(";")); + ui->outputFileExtensions->setText(editSettings->getOutputFileExtensions().join(";")); +} + +bool GeneralSettings::checkValid() +{ + if (ui->defaultFullScore->text().isEmpty()) { + ui->defaultFullScore->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty default full score!"), QMessageBox::Close); + return false; + } + if (ui->defaultTimeLimit->text().isEmpty()) { + ui->defaultTimeLimit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty default time limit!"), QMessageBox::Close); + return false; + } + if (ui->defaultMemoryLimit->text().isEmpty()) { + ui->defaultMemoryLimit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty default memory limit!"), QMessageBox::Close); + return false; + } + if (ui->compileTimeLimit->text().isEmpty()) { + ui->compileTimeLimit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty compile time limit!"), QMessageBox::Close); + return false; + } + if (ui->specialJudgeTimeLimit->text().isEmpty()) { + ui->specialJudgeTimeLimit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty special judge time limit!"), QMessageBox::Close); + return false; + } + if (ui->fileSizeLimit->text().isEmpty()) { + ui->fileSizeLimit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty source file size limit!"), QMessageBox::Close); + return false; + } + if (ui->numberOfThreads->text().isEmpty()) { + ui->numberOfThreads->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty number of threads!"), QMessageBox::Close); + return false; + } + return true; +} + +void GeneralSettings::defaultFullScoreChanged(const QString &text) +{ + editSettings->setDefaultFullScore(text.toInt()); +} + +void GeneralSettings::defaultTimeLimitChanged(const QString &text) +{ + editSettings->setDefaultTimeLimit(text.toInt()); +} + +void GeneralSettings::defaultMemoryLimitChanged(const QString &text) +{ + editSettings->setDefaultMemoryLimit(text.toInt()); +} + +void GeneralSettings::compileTimeLimitChanged(const QString &text) +{ + editSettings->setCompileTimeLimit(text.toInt()); +} + +void GeneralSettings::specialJudgeTimeLimitChanged(const QString &text) +{ + editSettings->setSpecialJudgeTimeLimit(text.toInt()); +} + +void GeneralSettings::fileSizeLimitChanged(const QString &text) +{ + editSettings->setFileSizeLimit(text.toInt()); +} + +void GeneralSettings::numberOfThreadsChanged(const QString &text) +{ + editSettings->setNumberOfThreads(text.toInt()); +} + +void GeneralSettings::inputFileExtensionsChanged(const QString &text) +{ + editSettings->setInputFileExtensions(text); +} + +void GeneralSettings::outputFileExtensionsChanged(const QString &text) +{ + editSettings->setOutputFileExtensions(text); +} diff --git a/generalsettings.h b/generalsettings.h index e34c360..706baff 100644 --- a/generalsettings.h +++ b/generalsettings.h @@ -1,58 +1,58 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef GENERALSETTINGS_H -#define GENERALSETTINGS_H - -#include -#include -#include - -namespace Ui { - class GeneralSettings; -} - -class Settings; - -class GeneralSettings : public QWidget -{ - Q_OBJECT - -public: - explicit GeneralSettings(QWidget *parent = 0); - ~GeneralSettings(); - void resetEditSettings(Settings*); - bool checkValid(); - -private: - Ui::GeneralSettings *ui; - Settings *editSettings; - -private slots: - void defaultFullScoreChanged(const QString&); - void defaultTimeLimitChanged(const QString&); - void defaultMemoryLimitChanged(const QString&); - void compileTimeLimitChanged(const QString&); - void specialJudgeTimeLimitChanged(const QString&); - void fileSizeLimitChanged(const QString&); - void numberOfThreadsChanged(const QString&); - void inputFileExtensionsChanged(const QString&); - void outputFileExtensionsChanged(const QString&); -}; - -#endif // GENERALSETTINGS_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef GENERALSETTINGS_H +#define GENERALSETTINGS_H + +#include +#include +#include + +namespace Ui { + class GeneralSettings; +} + +class Settings; + +class GeneralSettings : public QWidget +{ + Q_OBJECT + +public: + explicit GeneralSettings(QWidget *parent = 0); + ~GeneralSettings(); + void resetEditSettings(Settings*); + bool checkValid(); + +private: + Ui::GeneralSettings *ui; + Settings *editSettings; + +private slots: + void defaultFullScoreChanged(const QString&); + void defaultTimeLimitChanged(const QString&); + void defaultMemoryLimitChanged(const QString&); + void compileTimeLimitChanged(const QString&); + void specialJudgeTimeLimitChanged(const QString&); + void fileSizeLimitChanged(const QString&); + void numberOfThreadsChanged(const QString&); + void inputFileExtensionsChanged(const QString&); + void outputFileExtensionsChanged(const QString&); +}; + +#endif // GENERALSETTINGS_H diff --git a/generalsettings.ui b/generalsettings.ui index 1e92d8e..32d2f04 100644 --- a/generalsettings.ui +++ b/generalsettings.ui @@ -1,606 +1,606 @@ - - - GeneralSettings - - - - 0 - 0 - 325 - 352 - - - - - 325 - 352 - - - - Form - - - - 12 - - - 10 - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Default Full Score - - - - - - - - - - 0 - 0 - - - - - 81 - 22 - - - - - 81 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Default Time Limit - - - - - - - 12 - - - - - - 0 - 0 - - - - - 81 - 22 - - - - - 81 - 22 - - - - - - - - - 0 - 0 - - - - font-size: 9pt; - - - ms - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Default Memory Limit - - - - - - - 12 - - - - - - 0 - 0 - - - - - 81 - 22 - - - - - 81 - 22 - - - - - - - - - 0 - 0 - - - - font-size: 9pt; - - - MB - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Compile Time Limit - - - - - - - 12 - - - - - - 0 - 0 - - - - - 81 - 22 - - - - - 81 - 22 - - - - - - - - - 0 - 0 - - - - font-size: 9pt; - - - ms - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Special Judge Time Limit - - - - - - - 12 - - - - - - 0 - 0 - - - - - 81 - 22 - - - - - 81 - 22 - - - - - - - - - 0 - 0 - - - - font-size: 9pt; - - - ms - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Source File Size Limit - - - - - - - 12 - - - - - - 0 - 0 - - - - - 81 - 22 - - - - - 81 - 22 - - - - - - - - - 0 - 0 - - - - font-size: 9pt; - - - KB - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Number of Threads - - - - - - - 12 - - - - - - 81 - 22 - - - - - 81 - 22 - - - - - - - - Qt::Horizontal - - - - 201 - 20 - - - - - - - - - - font-size: 9pt; -font-weight: bold; - - - Input File Extensions - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - font-size: 9pt; -font-weight: bold; - - - Output File Extensions - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - font-size: 9pt; - - - - (separated by ";". Empty means no limitation.) - - - Qt::AlignCenter - - - - - - - Qt::Vertical - - - - 20 - 3 - - - - - - - - - + + + GeneralSettings + + + + 0 + 0 + 325 + 352 + + + + + 325 + 352 + + + + Form + + + + 12 + + + 10 + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Default Full Score + + + + + + + + + + 0 + 0 + + + + + 81 + 22 + + + + + 81 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Default Time Limit + + + + + + + 12 + + + + + + 0 + 0 + + + + + 81 + 22 + + + + + 81 + 22 + + + + + + + + + 0 + 0 + + + + font-size: 9pt; + + + ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Default Memory Limit + + + + + + + 12 + + + + + + 0 + 0 + + + + + 81 + 22 + + + + + 81 + 22 + + + + + + + + + 0 + 0 + + + + font-size: 9pt; + + + MB + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Compile Time Limit + + + + + + + 12 + + + + + + 0 + 0 + + + + + 81 + 22 + + + + + 81 + 22 + + + + + + + + + 0 + 0 + + + + font-size: 9pt; + + + ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Special Judge Time Limit + + + + + + + 12 + + + + + + 0 + 0 + + + + + 81 + 22 + + + + + 81 + 22 + + + + + + + + + 0 + 0 + + + + font-size: 9pt; + + + ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Source File Size Limit + + + + + + + 12 + + + + + + 0 + 0 + + + + + 81 + 22 + + + + + 81 + 22 + + + + + + + + + 0 + 0 + + + + font-size: 9pt; + + + KB + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Number of Threads + + + + + + + 12 + + + + + + 81 + 22 + + + + + 81 + 22 + + + + + + + + Qt::Horizontal + + + + 201 + 20 + + + + + + + + + + font-size: 9pt; +font-weight: bold; + + + Input File Extensions + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + font-size: 9pt; +font-weight: bold; + + + Output File Extensions + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + font-size: 9pt; + + + + (separated by ";". Empty means no limitation.) + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 3 + + + + + + + + + diff --git a/globaltype.h b/globaltype.h index 68ac699..ebf0fef 100644 --- a/globaltype.h +++ b/globaltype.h @@ -1,31 +1,31 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef GLOBALTYPE_H -#define GLOBALTYPE_H - -enum CompileState { CompileSuccessfully, NoValidSourceFile, CompileError, - CompileTimeLimitExceeded, InvalidCompiler }; - -enum ResultState { CorrectAnswer, WrongAnswer, PartlyCorrect, - TimeLimitExceeded, MemoryLimitExceeded, - CannotStartProgram, FileError, RunTimeError, - InvalidSpecialJudge, SpecialJudgeTimeLimitExceeded, - SpecialJudgeRunTimeError }; - -#endif // GLOBALTYPE_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef GLOBALTYPE_H +#define GLOBALTYPE_H + +enum CompileState { CompileSuccessfully, NoValidSourceFile, CompileError, + CompileTimeLimitExceeded, InvalidCompiler }; + +enum ResultState { CorrectAnswer, WrongAnswer, PartlyCorrect, + TimeLimitExceeded, MemoryLimitExceeded, + CannotStartProgram, FileError, RunTimeError, + InvalidSpecialJudge, SpecialJudgeTimeLimitExceeded, + SpecialJudgeRunTimeError }; + +#endif // GLOBALTYPE_H diff --git a/judgingdialog.cpp b/judgingdialog.cpp index 9ee7e80..9078577 100644 --- a/judgingdialog.cpp +++ b/judgingdialog.cpp @@ -1,238 +1,238 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "judgingdialog.h" -#include "ui_judgingdialog.h" -#include "contest.h" -#include "task.h" - -JudgingDialog::JudgingDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::JudgingDialog) -{ - ui->setupUi(this); - cursor = new QTextCursor(ui->logViewer->document()); - connect(ui->cancelButton, SIGNAL(clicked()), - this, SLOT(stopJudgingSlot())); -} - -JudgingDialog::~JudgingDialog() -{ - delete ui; - delete cursor; -} - -void JudgingDialog::setContest(Contest *contest) -{ - curContest = contest; - connect(curContest, SIGNAL(singleCaseFinished(int, int, int, int)), - this, SLOT(singleCaseFinished(int, int, int, int))); - connect(curContest, SIGNAL(taskJudgingStarted(QString)), - this, SLOT(taskJudgingStarted(QString))); - connect(curContest, SIGNAL(contestantJudgingStart(QString)), - this, SLOT(contestantJudgingStart(QString))); - connect(curContest, SIGNAL(contestantJudgingFinished()), - this, SLOT(contestantJudgingFinished())); - connect(curContest, SIGNAL(compileError(int, int)), - this, SLOT(compileError(int, int))); - connect(this, SIGNAL(stopJudgingSignal()), - curContest, SLOT(stopJudgingSlot())); -} - -void JudgingDialog::judge(const QStringList &nameList) -{ - stopJudging = false; - ui->progressBar->setMaximum(curContest->getTotalTimeLimit() * nameList.size()); - for (int i = 0; i < nameList.size(); i ++) { - curContest->judge(nameList[i]); - if (stopJudging) break; - } - accept(); -} - -void JudgingDialog::judge(const QString &name, int index) -{ - stopJudging = false; - ui->progressBar->setMaximum(curContest->getTask(index)->getTotalTimeLimit()); - curContest->judge(name, index); - accept(); -} - -void JudgingDialog::judgeAll() -{ - stopJudging = false; - ui->progressBar->setMaximum(curContest->getTotalTimeLimit() * curContest->getContestantList().size()); - curContest->judgeAll(); - accept(); -} - -void JudgingDialog::singleCaseFinished(int progress, int x, int y, int result) -{ - QTextBlockFormat blockFormat; - blockFormat.setLeftMargin(30); - cursor->insertBlock(blockFormat); - QTextCharFormat charFormat; - charFormat.setFontPointSize(9); - cursor->insertText(tr("Test case %1.%2: ").arg(x + 1).arg(y + 1), charFormat); - - QString text; - switch (ResultState(result)) { - case CorrectAnswer: { - text = tr("Correct answer"); - charFormat.setForeground(QBrush(Qt::darkGreen)); - break; - } - case WrongAnswer: { - text = tr("Wrong answer"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case PartlyCorrect: { - text = tr("Partly correct"); - charFormat.setForeground(QBrush(Qt::darkYellow)); - break; - } - case TimeLimitExceeded: { - text = tr("Time limit exceeded"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case MemoryLimitExceeded: { - text = tr("Memory limit exceeded"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case CannotStartProgram: { - text = tr("Cannot start program"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case FileError: { - text = tr("File error"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case RunTimeError: { - text = tr("Run time error"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case InvalidSpecialJudge: { - text = tr("Invalid special judge"); - charFormat.setForeground(QBrush(Qt::darkBlue)); - break; - } - case SpecialJudgeTimeLimitExceeded: { - text = tr("Special judge time limit exceeded"); - charFormat.setForeground(QBrush(Qt::darkBlue)); - break; - } - case SpecialJudgeRunTimeError: { - text = tr("Special judge run time error"); - charFormat.setForeground(QBrush(Qt::darkBlue)); - break; - } - } - - cursor->insertText(text, charFormat); - ui->progressBar->setValue(ui->progressBar->value() + progress); - - QScrollBar *bar = ui->logViewer->verticalScrollBar(); - bar->setValue(bar->maximum()); -} - -void JudgingDialog::taskJudgingStarted(const QString &taskName) -{ - QTextBlockFormat blockFormat; - blockFormat.setLeftMargin(15); - cursor->insertBlock(blockFormat); - QTextCharFormat charFormat; - charFormat.setFontPointSize(9); - cursor->insertText(tr("Start judging task %1").arg(taskName), charFormat); - QScrollBar *bar = ui->logViewer->verticalScrollBar(); - bar->setValue(bar->maximum()); -} - -void JudgingDialog::contestantJudgingStart(const QString &contestantName) -{ - QTextCharFormat charFormat; - charFormat.setFontPointSize(10); - charFormat.setFontWeight(QFont::Bold); - cursor->insertText(tr("Start judging contestant %1").arg(contestantName), charFormat); - QScrollBar *bar = ui->logViewer->verticalScrollBar(); - bar->setValue(bar->maximum()); -} - -void JudgingDialog::contestantJudgingFinished() -{ - QTextBlockFormat blockFormat; - cursor->insertBlock(blockFormat); - cursor->insertBlock(blockFormat); - QScrollBar *bar = ui->logViewer->verticalScrollBar(); - bar->setValue(bar->maximum()); -} - -void JudgingDialog::compileError(int progress, int compileState) -{ - QTextBlockFormat blockFormat; - blockFormat.setLeftMargin(30); - cursor->insertBlock(blockFormat); - QTextCharFormat charFormat; - charFormat.setFontPointSize(9); - - QString text; - switch (CompileState(compileState)) { - case NoValidSourceFile: { - text = tr("Cannot find valid source file"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case CompileError: { - text = tr("Compile error"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case CompileTimeLimitExceeded: { - text = tr("Compile time limit exceeded"); - charFormat.setForeground(QBrush(Qt::red)); - break; - } - case InvalidCompiler: { - text = tr("Invalid compiler"); - charFormat.setForeground(QBrush(Qt::blue)); - break; - } - } - - cursor->insertText(text, charFormat); - ui->progressBar->setValue(ui->progressBar->value() + progress); - - QScrollBar *bar = ui->logViewer->verticalScrollBar(); - bar->setValue(bar->maximum()); -} - -void JudgingDialog::stopJudgingSlot() -{ - stopJudging = true; - emit stopJudgingSignal(); -} - -void JudgingDialog::reject() -{ - stopJudgingSlot(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "judgingdialog.h" +#include "ui_judgingdialog.h" +#include "contest.h" +#include "task.h" + +JudgingDialog::JudgingDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::JudgingDialog) +{ + ui->setupUi(this); + cursor = new QTextCursor(ui->logViewer->document()); + connect(ui->cancelButton, SIGNAL(clicked()), + this, SLOT(stopJudgingSlot())); +} + +JudgingDialog::~JudgingDialog() +{ + delete ui; + delete cursor; +} + +void JudgingDialog::setContest(Contest *contest) +{ + curContest = contest; + connect(curContest, SIGNAL(singleCaseFinished(int, int, int, int)), + this, SLOT(singleCaseFinished(int, int, int, int))); + connect(curContest, SIGNAL(taskJudgingStarted(QString)), + this, SLOT(taskJudgingStarted(QString))); + connect(curContest, SIGNAL(contestantJudgingStart(QString)), + this, SLOT(contestantJudgingStart(QString))); + connect(curContest, SIGNAL(contestantJudgingFinished()), + this, SLOT(contestantJudgingFinished())); + connect(curContest, SIGNAL(compileError(int, int)), + this, SLOT(compileError(int, int))); + connect(this, SIGNAL(stopJudgingSignal()), + curContest, SLOT(stopJudgingSlot())); +} + +void JudgingDialog::judge(const QStringList &nameList) +{ + stopJudging = false; + ui->progressBar->setMaximum(curContest->getTotalTimeLimit() * nameList.size()); + for (int i = 0; i < nameList.size(); i ++) { + curContest->judge(nameList[i]); + if (stopJudging) break; + } + accept(); +} + +void JudgingDialog::judge(const QString &name, int index) +{ + stopJudging = false; + ui->progressBar->setMaximum(curContest->getTask(index)->getTotalTimeLimit()); + curContest->judge(name, index); + accept(); +} + +void JudgingDialog::judgeAll() +{ + stopJudging = false; + ui->progressBar->setMaximum(curContest->getTotalTimeLimit() * curContest->getContestantList().size()); + curContest->judgeAll(); + accept(); +} + +void JudgingDialog::singleCaseFinished(int progress, int x, int y, int result) +{ + QTextBlockFormat blockFormat; + blockFormat.setLeftMargin(30); + cursor->insertBlock(blockFormat); + QTextCharFormat charFormat; + charFormat.setFontPointSize(9); + cursor->insertText(tr("Test case %1.%2: ").arg(x + 1).arg(y + 1), charFormat); + + QString text; + switch (ResultState(result)) { + case CorrectAnswer: { + text = tr("Correct answer"); + charFormat.setForeground(QBrush(Qt::darkGreen)); + break; + } + case WrongAnswer: { + text = tr("Wrong answer"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case PartlyCorrect: { + text = tr("Partly correct"); + charFormat.setForeground(QBrush(Qt::darkYellow)); + break; + } + case TimeLimitExceeded: { + text = tr("Time limit exceeded"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case MemoryLimitExceeded: { + text = tr("Memory limit exceeded"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case CannotStartProgram: { + text = tr("Cannot start program"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case FileError: { + text = tr("File error"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case RunTimeError: { + text = tr("Run time error"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case InvalidSpecialJudge: { + text = tr("Invalid special judge"); + charFormat.setForeground(QBrush(Qt::darkBlue)); + break; + } + case SpecialJudgeTimeLimitExceeded: { + text = tr("Special judge time limit exceeded"); + charFormat.setForeground(QBrush(Qt::darkBlue)); + break; + } + case SpecialJudgeRunTimeError: { + text = tr("Special judge run time error"); + charFormat.setForeground(QBrush(Qt::darkBlue)); + break; + } + } + + cursor->insertText(text, charFormat); + ui->progressBar->setValue(ui->progressBar->value() + progress); + + QScrollBar *bar = ui->logViewer->verticalScrollBar(); + bar->setValue(bar->maximum()); +} + +void JudgingDialog::taskJudgingStarted(const QString &taskName) +{ + QTextBlockFormat blockFormat; + blockFormat.setLeftMargin(15); + cursor->insertBlock(blockFormat); + QTextCharFormat charFormat; + charFormat.setFontPointSize(9); + cursor->insertText(tr("Start judging task %1").arg(taskName), charFormat); + QScrollBar *bar = ui->logViewer->verticalScrollBar(); + bar->setValue(bar->maximum()); +} + +void JudgingDialog::contestantJudgingStart(const QString &contestantName) +{ + QTextCharFormat charFormat; + charFormat.setFontPointSize(10); + charFormat.setFontWeight(QFont::Bold); + cursor->insertText(tr("Start judging contestant %1").arg(contestantName), charFormat); + QScrollBar *bar = ui->logViewer->verticalScrollBar(); + bar->setValue(bar->maximum()); +} + +void JudgingDialog::contestantJudgingFinished() +{ + QTextBlockFormat blockFormat; + cursor->insertBlock(blockFormat); + cursor->insertBlock(blockFormat); + QScrollBar *bar = ui->logViewer->verticalScrollBar(); + bar->setValue(bar->maximum()); +} + +void JudgingDialog::compileError(int progress, int compileState) +{ + QTextBlockFormat blockFormat; + blockFormat.setLeftMargin(30); + cursor->insertBlock(blockFormat); + QTextCharFormat charFormat; + charFormat.setFontPointSize(9); + + QString text; + switch (CompileState(compileState)) { + case NoValidSourceFile: { + text = tr("Cannot find valid source file"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case CompileError: { + text = tr("Compile error"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case CompileTimeLimitExceeded: { + text = tr("Compile time limit exceeded"); + charFormat.setForeground(QBrush(Qt::red)); + break; + } + case InvalidCompiler: { + text = tr("Invalid compiler"); + charFormat.setForeground(QBrush(Qt::blue)); + break; + } + } + + cursor->insertText(text, charFormat); + ui->progressBar->setValue(ui->progressBar->value() + progress); + + QScrollBar *bar = ui->logViewer->verticalScrollBar(); + bar->setValue(bar->maximum()); +} + +void JudgingDialog::stopJudgingSlot() +{ + stopJudging = true; + emit stopJudgingSignal(); +} + +void JudgingDialog::reject() +{ + stopJudgingSlot(); +} diff --git a/judgingdialog.h b/judgingdialog.h index 08ccb92..81b5d0a 100644 --- a/judgingdialog.h +++ b/judgingdialog.h @@ -1,66 +1,66 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef JUDGINGDIALOG_H -#define JUDGINGDIALOG_H - -#include -#include -#include -#include "globaltype.h" - -class Contest; - -namespace Ui { - class JudgingDialog; -} - -class JudgingDialog : public QDialog -{ - Q_OBJECT - -public: - explicit JudgingDialog(QWidget *parent = 0); - ~JudgingDialog(); - void setContest(Contest*); - void judge(const QStringList&); - void judge(const QString&, int); - void judgeAll(); - void reject(); - -private slots: - void stopJudgingSlot(); - -private: - Ui::JudgingDialog *ui; - Contest *curContest; - QTextCursor *cursor; - bool stopJudging; - -public slots: - void singleCaseFinished(int, int, int, int); - void taskJudgingStarted(const QString&); - void contestantJudgingStart(const QString&); - void contestantJudgingFinished(); - void compileError(int, int); - -signals: - void stopJudgingSignal(); -}; - -#endif // JUDGINGDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef JUDGINGDIALOG_H +#define JUDGINGDIALOG_H + +#include +#include +#include +#include "globaltype.h" + +class Contest; + +namespace Ui { + class JudgingDialog; +} + +class JudgingDialog : public QDialog +{ + Q_OBJECT + +public: + explicit JudgingDialog(QWidget *parent = 0); + ~JudgingDialog(); + void setContest(Contest*); + void judge(const QStringList&); + void judge(const QString&, int); + void judgeAll(); + void reject(); + +private slots: + void stopJudgingSlot(); + +private: + Ui::JudgingDialog *ui; + Contest *curContest; + QTextCursor *cursor; + bool stopJudging; + +public slots: + void singleCaseFinished(int, int, int, int); + void taskJudgingStarted(const QString&); + void contestantJudgingStart(const QString&); + void contestantJudgingFinished(); + void compileError(int, int); + +signals: + void stopJudgingSignal(); +}; + +#endif // JUDGINGDIALOG_H diff --git a/judgingdialog.ui b/judgingdialog.ui index 2d727d2..efbf6a9 100644 --- a/judgingdialog.ui +++ b/judgingdialog.ui @@ -1,64 +1,64 @@ - - - JudgingDialog - - - Qt::WindowModal - - - - 0 - 0 - 448 - 263 - - - - - 448 - 263 - - - - Judging - - - - - - - - - false - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Cancel - - - - - - - - - - + + + JudgingDialog + + + Qt::WindowModal + + + + 0 + 0 + 448 + 263 + + + + + 448 + 263 + + + + Judging + + + + + + + + + false + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + + + + diff --git a/judgingthread.cpp b/judgingthread.cpp index bee9899..5be757b 100644 --- a/judgingthread.cpp +++ b/judgingthread.cpp @@ -1,754 +1,754 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include -#include -#include "judgingthread.h" -#include "settings.h" -#include "task.h" - -#ifdef Q_OS_WIN32 -#include "windows.h" -#include "psapi.h" -#endif - -#ifdef Q_OS_LINUX -#include "unistd.h" -#include "time.h" -#include "linux_proc.h" -#endif - -JudgingThread::JudgingThread(QObject *parent) : - QThread(parent) -{ - moveToThread(this); - checkRejudgeMode = false; - needRejudge = false; - stopJudging = false; - timeUsed = -1; - memoryUsed = -1; -} - -void JudgingThread::setCheckRejudgeMode(bool check) -{ - checkRejudgeMode = check; -} - -void JudgingThread::setExtraTimeRatio(double ratio) -{ - extraTimeRatio = ratio; -} - -void JudgingThread::setEnvironment(const QProcessEnvironment &env) -{ - environment = env; -} - -void JudgingThread::setWorkingDirectory(const QString &directory) -{ - workingDirectory = directory; -} - -void JudgingThread::setSpecialJudgeTimeLimit(int limit) -{ - specialJudgeTimeLimit = limit; -} - -void JudgingThread::setExecutableFile(const QString &fileName) -{ - executableFile = fileName; -} - -void JudgingThread::setAnswerFile(const QString &fileName) -{ - answerFile = fileName; -} - -void JudgingThread::setInputFile(const QString &fileName) -{ - inputFile = fileName; -} - -void JudgingThread::setOutputFile(const QString &fileName) -{ - outputFile = fileName; -} - -void JudgingThread::setTask(Task *_task) -{ - task = _task; -} - -void JudgingThread::setFullScore(int score) -{ - fullScore = score; -} - -void JudgingThread::setTimeLimit(int limit) -{ - timeLimit = limit; -} - -void JudgingThread::setMemoryLimit(int limit) -{ - memoryLimit = limit; -} - -int JudgingThread::getTimeUsed() const -{ - return timeUsed; -} - -int JudgingThread::getMemoryUsed() const -{ - return memoryUsed; -} - -int JudgingThread::getScore() const -{ - return score; -} - -ResultState JudgingThread::getResult() const -{ - return result; -} - -const QString& JudgingThread::getMessage() const -{ - return message; -} - -bool JudgingThread::getNeedRejudge() const -{ - return needRejudge; -} - -void JudgingThread::stopJudgingSlot() -{ - stopJudging = true; -} - -void JudgingThread::compareLineByLine(const QString &contestantOutput) -{ - FILE *contestantOutputFile = fopen(contestantOutput.toLocal8Bit().data(), "r"); - if (contestantOutputFile == NULL) { - score = 0; - result = FileError; - message = tr("Cannot open contestant\'s output file"); - return; - } - FILE *standardOutputFile = fopen(outputFile.toLocal8Bit().data(), "r"); - if (standardOutputFile == NULL) { - score = 0; - result = FileError; - message = tr("Cannot open standard output file"); - fclose(contestantOutputFile); - return; - } - - char str1[20], str2[20], ch; - bool chk1 = false, chk2 = false; - bool chkEof1 = false, chkEof2 = false; - int len1, len2; - while (true) { - len1 = 0; - while (len1 < 10) { - ch = fgetc(contestantOutputFile); - if (ch == EOF) break; - if (! chk1 && ch == '\n') break; - if (chk1 && ch == '\n') { - chk1 = false; - continue; - } - if (ch == '\r') { - chk1 = true; - break; - } - if (chk1) chk1 = false; - str1[len1 ++] = ch; - } - str1[len1 ++] = '\0'; - if (ch == EOF) chkEof1 = true; else chkEof1 = false; - - len2 = 0; - while (len2 < 10) { - ch = fgetc(standardOutputFile); - if (ch == EOF) break; - if (! chk2 && ch == '\n') break; - if (chk2 && ch == '\n') { - chk2 = false; - continue; - } - if (ch == '\r') { - chk2 = true; - break; - } - if (chk2) chk2 = false; - str2[len2 ++] = ch; - } - str2[len2 ++] = '\0'; - if (ch == EOF) chkEof2 = true; else chkEof2 = false; - - if (chkEof1 && ! chkEof2) { - score = 0; - result = WrongAnswer; - message = tr("Shorter than standard output"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - - if (! chkEof1 && chkEof2) { - score = 0; - result = WrongAnswer; - message = tr("Longer than standard output"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - - if (len1 != len2 || strcmp(str1, str2) != 0) { - score = 0; - result = WrongAnswer; - message = tr("Read %1 but expect %2").arg(str1).arg(str2); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (chkEof1 && chkEof2) break; - QCoreApplication::processEvents(); - if (stopJudging) { - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - } - - score = fullScore; - result = CorrectAnswer; - fclose(contestantOutputFile); - fclose(standardOutputFile); -} - -void JudgingThread::compareRealNumbers(const QString &contestantOutput) -{ - FILE *contestantOutputFile = fopen(contestantOutput.toLocal8Bit().data(), "r"); - if (contestantOutputFile == NULL) { - score = 0; - result = FileError; - message = tr("Cannot open contestant\'s output file"); - return; - } - FILE *standardOutputFile = fopen(outputFile.toLocal8Bit().data(), "r"); - if (standardOutputFile == NULL) { - score = 0; - result = FileError; - message = tr("Cannot open standard output file"); - fclose(contestantOutputFile); - return; - } - - double eps = 1; - for (int i = 0; i < task->getRealPrecision(); i ++) - eps *= 0.1; - - double a, b; - while (true) { - int cnt1 = fscanf(contestantOutputFile, "%lf", &a); - int cnt2 = fscanf(standardOutputFile, "%lf", &b); - if (cnt1 == 0) { - score = 0; - result = WrongAnswer; - message = tr("Invalid characters found"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (cnt2 == 0) { - score = 0; - result = FileError; - message = tr("Invalid characters in standard output file"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (cnt1 == EOF && cnt2 == EOF) break; - if (cnt1 == EOF && cnt2 == 1) { - score = 0; - result = WrongAnswer; - message = tr("Shorter than standard output"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (cnt1 == 1 && cnt2 == EOF) { - score = 0; - result = WrongAnswer; - message = tr("Longer than standard output"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (fabs(a - b) > eps) { - score = 0; - result = WrongAnswer; - message = tr("Read %1 but expect %2").arg(a, 0, 'g', 18).arg(b, 0, 'g', 18); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - QCoreApplication::processEvents(); - if (stopJudging) { - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - } - - score = fullScore; - result = CorrectAnswer; - fclose(contestantOutputFile); - fclose(standardOutputFile); -} - -void JudgingThread::specialJudge(const QString &fileName) -{ - if (! QFileInfo(inputFile).exists()) { - score = 0; - result = FileError; - message = tr("Cannot find standard input file"); - return; - } - - if (! QFileInfo(fileName).exists()) { - score = 0; - result = FileError; - message = tr("Cannot find contestant\'s output file"); - return; - } - - if (! QFileInfo(outputFile).exists()) { - score = 0; - result = FileError; - message = tr("Cannot find standard output file"); - return; - } - - QProcess *judge = new QProcess(this); - QStringList arguments; - arguments << inputFile << fileName << outputFile << QString("%1").arg(fullScore); - arguments << workingDirectory + "_score"; - arguments << workingDirectory + "_message"; - judge->start(Settings::dataPath() + task->getSpecialJudge(), arguments); - if (! judge->waitForStarted(-1)) { - score = 0; - result = InvalidSpecialJudge; - delete judge; - return; - } - - QElapsedTimer timer; - timer.start(); - bool flag = false; - while (timer.elapsed() < specialJudgeTimeLimit) { - if (judge->state() != QProcess::Running) { - flag = true; - break; - } - QCoreApplication::processEvents(); - if (stopJudging) { - judge->kill(); - delete judge; - return; - } - msleep(10); - } - if (! flag) { - judge->kill(); - score = 0; - result = SpecialJudgeTimeLimitExceeded; - delete judge; - return; - } else - if (judge->exitCode() != 0) { - score = 0; - result = SpecialJudgeRunTimeError; - delete judge; - return; - } - delete judge; - - QFile scoreFile(workingDirectory + "_score"); - if (! scoreFile.open(QFile::ReadOnly)) { - score = 0; - result = InvalidSpecialJudge; - return; - } - - QTextStream scoreStream(&scoreFile); - scoreStream >> score; - if (scoreStream.status() == QTextStream::ReadCorruptData) { - score = 0; - result = InvalidSpecialJudge; - return; - } - scoreFile.close(); - - if (score < 0) { - score = 0; - result = InvalidSpecialJudge; - return; - } - - QFile messageFile(workingDirectory + "_message"); - if (messageFile.open(QFile::ReadOnly)) { - QTextStream messageStream(&messageFile); - message = messageStream.readAll(); - messageFile.close(); - } - - if (score == 0) result = WrongAnswer; - if (0 < score && score < fullScore) result = PartlyCorrect; - if (score >= fullScore) result = CorrectAnswer; - - scoreFile.remove(); - messageFile.remove(); -} - -void JudgingThread::runProgram() -{ - result = CorrectAnswer; - -#ifdef Q_OS_WIN32 - SetErrorMode(SEM_NOGPFAULTERRORBOX); - - STARTUPINFO si; - PROCESS_INFORMATION pi; - SECURITY_ATTRIBUTES sa; - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES; - ZeroMemory(&pi, sizeof(pi)); - ZeroMemory(&sa, sizeof(sa)); - sa.bInheritHandle = TRUE; - - if (task->getStandardInputCheck()) - si.hStdInput = CreateFile((const WCHAR*)(inputFile.utf16()), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (task->getStandardOutputCheck()) - si.hStdOutput = CreateFile((const WCHAR*)((workingDirectory + "_tmpout").utf16()), GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - si.hStdError = CreateFile((const WCHAR*)((workingDirectory + "_tmperr").utf16()), GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - QString values = environment.toStringList().join('\0') + '\0'; - if (! CreateProcess(NULL, (WCHAR*)(executableFile.utf16()), NULL, &sa, - TRUE, HIGH_PRIORITY_CLASS | CREATE_NO_WINDOW, (LPVOID)(values.toLocal8Bit().data()), - (const WCHAR*)(workingDirectory.utf16()), &si, &pi)) { - if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); - if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); - score = 0; - result = CannotStartProgram; - return; - } - SetProcessWorkingSetSize(pi.hProcess, memoryLimit * 1024 * 1024 / 4, memoryLimit * 1024 * 1024); - - bool flag = false; - QElapsedTimer timer; - timer.start(); - - while (timer.elapsed() < timeLimit * (1 + extraTimeRatio * 2)) { - if (WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0) { - flag = true; - break; - } - if (memoryLimit != -1) { - PROCESS_MEMORY_COUNTERS info; - GetProcessMemoryInfo(pi.hProcess, &info, sizeof(info)); - memoryUsed = info.PeakWorkingSetSize; - if (memoryUsed > memoryLimit * 1024 * 1024) { - TerminateProcess(pi.hProcess, 0); - if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); - if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - score = 0; - result = MemoryLimitExceeded; - timeUsed = -1; - return; - } - } - QCoreApplication::processEvents(); - if (stopJudging) { - TerminateProcess(pi.hProcess, 0); - if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); - if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return; - } - Sleep(10); - } - - if (! flag) { - TerminateProcess(pi.hProcess, 0); - if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); - if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - score = 0; - result = TimeLimitExceeded; - timeUsed = -1; - return; - } - - unsigned long exitCode; - GetExitCodeProcess(pi.hProcess, &exitCode); - if (exitCode != 0) { - if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); - if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - score = 0; - result = RunTimeError; - QFile file(workingDirectory + "_tmperr"); - if (file.open(QFile::ReadOnly)) { - QTextStream stream(&file); - message = stream.readAll(); - } - timeUsed = -1; - return; - } - - FILETIME creationTime, exitTime, kernelTime, userTime; - GetProcessTimes(pi.hProcess, &creationTime, &exitTime, &kernelTime, &userTime); - - SYSTEMTIME realTime; - FileTimeToSystemTime(&userTime, &realTime); - - timeUsed = realTime.wMilliseconds - + realTime.wSecond * 1000 - + realTime.wMinute * 60 * 1000 - + realTime.wHour * 60 * 60 * 1000; - - PROCESS_MEMORY_COUNTERS info; - GetProcessMemoryInfo(pi.hProcess, &info, sizeof(info)); - memoryUsed = info.PeakWorkingSetSize; - - if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); - if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); - CloseHandle(si.hStdError); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); -#endif - -#ifdef Q_OS_LINUX - QProcess *program = new QProcess(this); - if (task->getStandardInputCheck()) - program->setStandardInputFile(inputFile); - if (task->getStandardOutputCheck()) - program->setStandardOutputFile(workingDirectory + "_tmpout"); - program->setWorkingDirectory(workingDirectory); - program->setProcessEnvironment(environment); - program->start(executableFile); - if (! program->waitForStarted(-1)) { - delete program; - score = 0; - result = CannotStartProgram; - return; - } - - proc_info info; - bool flag = false; - QElapsedTimer timer; - timer.start(); - - while (timer.elapsed() < timeLimit * (1 + extraTimeRatio * 2)) { - if (program->state() != QProcess::Running) { - flag = true; - break; - } - - if (get_pid_stat(int(program->pid()), &info)) { - memoryUsed = qMax(memoryUsed, int(info.rss * sysconf(_SC_PAGESIZE))); - timeUsed = info.utime * 1000 / sysconf(_SC_CLK_TCK); - if (memoryUsed > memoryLimit * 1024 * 1024) { - program->kill(); - delete program; - score = 0; - result = MemoryLimitExceeded; - timeUsed = -1; - return; - } - } - QCoreApplication::processEvents(); - if (stopJudging) { - program->kill(); - delete program; - return; - } - msleep(1); - } - - if (! flag) { - program->kill(); - delete program; - score = 0; - result = TimeLimitExceeded; - timeUsed = -1; - return; - } - - if (program->exitCode() != 0) { - score = 0; - result = RunTimeError; - message = QString::fromLocal8Bit(program->readAllStandardError().data()); - timeUsed = -1; - delete program; - return; - } - - delete program; -#endif -} - -void JudgingThread::judgeOutput() -{ - if (task->getComparisonMode() == Task::LineByLineMode) { - if (task->getStandardOutputCheck()) - compareLineByLine(workingDirectory + "_tmpout"); - else - compareLineByLine(workingDirectory + task->getOutputFileName()); - } - - if (task->getComparisonMode() == Task::RealNumberMode) { - if (task->getStandardOutputCheck()) - compareRealNumbers(workingDirectory + "_tmpout"); - else - compareRealNumbers(workingDirectory + task->getOutputFileName()); - } - - if (task->getComparisonMode() == Task::SpecialJudgeMode) { - if (task->getStandardOutputCheck()) - specialJudge(workingDirectory + "_tmpout"); - else - specialJudge(workingDirectory + task->getOutputFileName()); - } -} - -void JudgingThread::judgeTraditionalTask() -{ - if (! QFileInfo(inputFile).exists()) { - score = 0; - result = FileError; - message = tr("Cannot find standard input file"); - return; - } - if (! task->getStandardInputCheck()) - if (! QFile::copy(inputFile, workingDirectory + task->getInputFileName())) { - score = 0; - result = FileError; - message = tr("Cannot copy standard input file"); - return; - } - - runProgram(); - if (stopJudging) return; - - if (result != CorrectAnswer) { - if (! task->getStandardInputCheck()) - QFile::remove(workingDirectory + task->getInputFileName()); - if (! task->getStandardOutputCheck()) - QFile::remove(workingDirectory + task->getOutputFileName()); - else - QFile::remove(workingDirectory + "_tmpout"); - return; - } - - judgeOutput(); - if (stopJudging) return; - - if (timeUsed > timeLimit) - if (checkRejudgeMode && score > 0 && (timeUsed <= timeLimit * (1 + extraTimeRatio) - || timeUsed <= timeLimit + 1000 * extraTimeRatio)) { - int minTimeUsed = timeUsed, curMemoryUsed = memoryUsed; - bool flag = true; - for (int i = 0; i < 10; i ++) { - runProgram(); - if (stopJudging) return; - if (result != CorrectAnswer) { - flag = false; - break; - } - if (timeUsed < minTimeUsed) { - minTimeUsed = timeUsed; - curMemoryUsed = memoryUsed; - judgeOutput(); - if (stopJudging) return; - if (timeUsed <= timeLimit) break; - } - } - timeUsed = minTimeUsed; - memoryUsed = curMemoryUsed; - if (! flag || timeUsed > timeLimit) { - score = 0; - result = TimeLimitExceeded; - message = ""; - } - } else { - if (! checkRejudgeMode && score > 0 && (timeUsed <= timeLimit * (1 + extraTimeRatio) - || timeUsed <= timeLimit + 1000 * extraTimeRatio)) { - needRejudge = true; - } - score = 0; - result = TimeLimitExceeded; - message = ""; - } - - if (! task->getStandardInputCheck()) - QFile::remove(workingDirectory + task->getInputFileName()); - if (! task->getStandardOutputCheck()) - QFile::remove(workingDirectory + task->getOutputFileName()); - else - QFile::remove(workingDirectory + "_tmpout"); -} - -void JudgingThread::judgeAnswersOnlyTask() -{ - if (task->getComparisonMode() == Task::LineByLineMode) - compareLineByLine(answerFile); - if (task->getComparisonMode() == Task::RealNumberMode) - compareRealNumbers(answerFile); - if (task->getComparisonMode() == Task::SpecialJudgeMode) - specialJudge(answerFile); -} - -void JudgingThread::run() -{ - if (task->getTaskType() == Task::Traditional) - judgeTraditionalTask(); - if (task->getTaskType() == Task::AnswersOnly) - judgeAnswersOnlyTask(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include +#include +#include "judgingthread.h" +#include "settings.h" +#include "task.h" + +#ifdef Q_OS_WIN32 +#include "windows.h" +#include "psapi.h" +#endif + +#ifdef Q_OS_LINUX +#include "unistd.h" +#include "time.h" +#include "linux_proc.h" +#endif + +JudgingThread::JudgingThread(QObject *parent) : + QThread(parent) +{ + moveToThread(this); + checkRejudgeMode = false; + needRejudge = false; + stopJudging = false; + timeUsed = -1; + memoryUsed = -1; +} + +void JudgingThread::setCheckRejudgeMode(bool check) +{ + checkRejudgeMode = check; +} + +void JudgingThread::setExtraTimeRatio(double ratio) +{ + extraTimeRatio = ratio; +} + +void JudgingThread::setEnvironment(const QProcessEnvironment &env) +{ + environment = env; +} + +void JudgingThread::setWorkingDirectory(const QString &directory) +{ + workingDirectory = directory; +} + +void JudgingThread::setSpecialJudgeTimeLimit(int limit) +{ + specialJudgeTimeLimit = limit; +} + +void JudgingThread::setExecutableFile(const QString &fileName) +{ + executableFile = fileName; +} + +void JudgingThread::setAnswerFile(const QString &fileName) +{ + answerFile = fileName; +} + +void JudgingThread::setInputFile(const QString &fileName) +{ + inputFile = fileName; +} + +void JudgingThread::setOutputFile(const QString &fileName) +{ + outputFile = fileName; +} + +void JudgingThread::setTask(Task *_task) +{ + task = _task; +} + +void JudgingThread::setFullScore(int score) +{ + fullScore = score; +} + +void JudgingThread::setTimeLimit(int limit) +{ + timeLimit = limit; +} + +void JudgingThread::setMemoryLimit(int limit) +{ + memoryLimit = limit; +} + +int JudgingThread::getTimeUsed() const +{ + return timeUsed; +} + +int JudgingThread::getMemoryUsed() const +{ + return memoryUsed; +} + +int JudgingThread::getScore() const +{ + return score; +} + +ResultState JudgingThread::getResult() const +{ + return result; +} + +const QString& JudgingThread::getMessage() const +{ + return message; +} + +bool JudgingThread::getNeedRejudge() const +{ + return needRejudge; +} + +void JudgingThread::stopJudgingSlot() +{ + stopJudging = true; +} + +void JudgingThread::compareLineByLine(const QString &contestantOutput) +{ + FILE *contestantOutputFile = fopen(contestantOutput.toLocal8Bit().data(), "r"); + if (contestantOutputFile == NULL) { + score = 0; + result = FileError; + message = tr("Cannot open contestant\'s output file"); + return; + } + FILE *standardOutputFile = fopen(outputFile.toLocal8Bit().data(), "r"); + if (standardOutputFile == NULL) { + score = 0; + result = FileError; + message = tr("Cannot open standard output file"); + fclose(contestantOutputFile); + return; + } + + char str1[20], str2[20], ch; + bool chk1 = false, chk2 = false; + bool chkEof1 = false, chkEof2 = false; + int len1, len2; + while (true) { + len1 = 0; + while (len1 < 10) { + ch = fgetc(contestantOutputFile); + if (ch == EOF) break; + if (! chk1 && ch == '\n') break; + if (chk1 && ch == '\n') { + chk1 = false; + continue; + } + if (ch == '\r') { + chk1 = true; + break; + } + if (chk1) chk1 = false; + str1[len1 ++] = ch; + } + str1[len1 ++] = '\0'; + if (ch == EOF) chkEof1 = true; else chkEof1 = false; + + len2 = 0; + while (len2 < 10) { + ch = fgetc(standardOutputFile); + if (ch == EOF) break; + if (! chk2 && ch == '\n') break; + if (chk2 && ch == '\n') { + chk2 = false; + continue; + } + if (ch == '\r') { + chk2 = true; + break; + } + if (chk2) chk2 = false; + str2[len2 ++] = ch; + } + str2[len2 ++] = '\0'; + if (ch == EOF) chkEof2 = true; else chkEof2 = false; + + if (chkEof1 && ! chkEof2) { + score = 0; + result = WrongAnswer; + message = tr("Shorter than standard output"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + + if (! chkEof1 && chkEof2) { + score = 0; + result = WrongAnswer; + message = tr("Longer than standard output"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + + if (len1 != len2 || strcmp(str1, str2) != 0) { + score = 0; + result = WrongAnswer; + message = tr("Read %1 but expect %2").arg(str1).arg(str2); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (chkEof1 && chkEof2) break; + QCoreApplication::processEvents(); + if (stopJudging) { + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + } + + score = fullScore; + result = CorrectAnswer; + fclose(contestantOutputFile); + fclose(standardOutputFile); +} + +void JudgingThread::compareRealNumbers(const QString &contestantOutput) +{ + FILE *contestantOutputFile = fopen(contestantOutput.toLocal8Bit().data(), "r"); + if (contestantOutputFile == NULL) { + score = 0; + result = FileError; + message = tr("Cannot open contestant\'s output file"); + return; + } + FILE *standardOutputFile = fopen(outputFile.toLocal8Bit().data(), "r"); + if (standardOutputFile == NULL) { + score = 0; + result = FileError; + message = tr("Cannot open standard output file"); + fclose(contestantOutputFile); + return; + } + + double eps = 1; + for (int i = 0; i < task->getRealPrecision(); i ++) + eps *= 0.1; + + double a, b; + while (true) { + int cnt1 = fscanf(contestantOutputFile, "%lf", &a); + int cnt2 = fscanf(standardOutputFile, "%lf", &b); + if (cnt1 == 0) { + score = 0; + result = WrongAnswer; + message = tr("Invalid characters found"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (cnt2 == 0) { + score = 0; + result = FileError; + message = tr("Invalid characters in standard output file"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (cnt1 == EOF && cnt2 == EOF) break; + if (cnt1 == EOF && cnt2 == 1) { + score = 0; + result = WrongAnswer; + message = tr("Shorter than standard output"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (cnt1 == 1 && cnt2 == EOF) { + score = 0; + result = WrongAnswer; + message = tr("Longer than standard output"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (fabs(a - b) > eps) { + score = 0; + result = WrongAnswer; + message = tr("Read %1 but expect %2").arg(a, 0, 'g', 18).arg(b, 0, 'g', 18); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + QCoreApplication::processEvents(); + if (stopJudging) { + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + } + + score = fullScore; + result = CorrectAnswer; + fclose(contestantOutputFile); + fclose(standardOutputFile); +} + +void JudgingThread::specialJudge(const QString &fileName) +{ + if (! QFileInfo(inputFile).exists()) { + score = 0; + result = FileError; + message = tr("Cannot find standard input file"); + return; + } + + if (! QFileInfo(fileName).exists()) { + score = 0; + result = FileError; + message = tr("Cannot find contestant\'s output file"); + return; + } + + if (! QFileInfo(outputFile).exists()) { + score = 0; + result = FileError; + message = tr("Cannot find standard output file"); + return; + } + + QProcess *judge = new QProcess(this); + QStringList arguments; + arguments << inputFile << fileName << outputFile << QString("%1").arg(fullScore); + arguments << workingDirectory + "_score"; + arguments << workingDirectory + "_message"; + judge->start(Settings::dataPath() + task->getSpecialJudge(), arguments); + if (! judge->waitForStarted(-1)) { + score = 0; + result = InvalidSpecialJudge; + delete judge; + return; + } + + QElapsedTimer timer; + timer.start(); + bool flag = false; + while (timer.elapsed() < specialJudgeTimeLimit) { + if (judge->state() != QProcess::Running) { + flag = true; + break; + } + QCoreApplication::processEvents(); + if (stopJudging) { + judge->kill(); + delete judge; + return; + } + msleep(10); + } + if (! flag) { + judge->kill(); + score = 0; + result = SpecialJudgeTimeLimitExceeded; + delete judge; + return; + } else + if (judge->exitCode() != 0) { + score = 0; + result = SpecialJudgeRunTimeError; + delete judge; + return; + } + delete judge; + + QFile scoreFile(workingDirectory + "_score"); + if (! scoreFile.open(QFile::ReadOnly)) { + score = 0; + result = InvalidSpecialJudge; + return; + } + + QTextStream scoreStream(&scoreFile); + scoreStream >> score; + if (scoreStream.status() == QTextStream::ReadCorruptData) { + score = 0; + result = InvalidSpecialJudge; + return; + } + scoreFile.close(); + + if (score < 0) { + score = 0; + result = InvalidSpecialJudge; + return; + } + + QFile messageFile(workingDirectory + "_message"); + if (messageFile.open(QFile::ReadOnly)) { + QTextStream messageStream(&messageFile); + message = messageStream.readAll(); + messageFile.close(); + } + + if (score == 0) result = WrongAnswer; + if (0 < score && score < fullScore) result = PartlyCorrect; + if (score >= fullScore) result = CorrectAnswer; + + scoreFile.remove(); + messageFile.remove(); +} + +void JudgingThread::runProgram() +{ + result = CorrectAnswer; + +#ifdef Q_OS_WIN32 + SetErrorMode(SEM_NOGPFAULTERRORBOX); + + STARTUPINFO si; + PROCESS_INFORMATION pi; + SECURITY_ATTRIBUTES sa; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + ZeroMemory(&pi, sizeof(pi)); + ZeroMemory(&sa, sizeof(sa)); + sa.bInheritHandle = TRUE; + + if (task->getStandardInputCheck()) + si.hStdInput = CreateFile((const WCHAR*)(inputFile.utf16()), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (task->getStandardOutputCheck()) + si.hStdOutput = CreateFile((const WCHAR*)((workingDirectory + "_tmpout").utf16()), GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + si.hStdError = CreateFile((const WCHAR*)((workingDirectory + "_tmperr").utf16()), GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + QString values = environment.toStringList().join('\0') + '\0'; + if (! CreateProcess(NULL, (WCHAR*)(executableFile.utf16()), NULL, &sa, + TRUE, HIGH_PRIORITY_CLASS | CREATE_NO_WINDOW, (LPVOID)(values.toLocal8Bit().data()), + (const WCHAR*)(workingDirectory.utf16()), &si, &pi)) { + if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); + if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); + score = 0; + result = CannotStartProgram; + return; + } + SetProcessWorkingSetSize(pi.hProcess, memoryLimit * 1024 * 1024 / 4, memoryLimit * 1024 * 1024); + + bool flag = false; + QElapsedTimer timer; + timer.start(); + + while (timer.elapsed() < timeLimit * (1 + extraTimeRatio * 2)) { + if (WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0) { + flag = true; + break; + } + if (memoryLimit != -1) { + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo(pi.hProcess, &info, sizeof(info)); + memoryUsed = info.PeakWorkingSetSize; + if (memoryUsed > memoryLimit * 1024 * 1024) { + TerminateProcess(pi.hProcess, 0); + if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); + if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + score = 0; + result = MemoryLimitExceeded; + timeUsed = -1; + return; + } + } + QCoreApplication::processEvents(); + if (stopJudging) { + TerminateProcess(pi.hProcess, 0); + if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); + if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return; + } + Sleep(10); + } + + if (! flag) { + TerminateProcess(pi.hProcess, 0); + if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); + if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + score = 0; + result = TimeLimitExceeded; + timeUsed = -1; + return; + } + + unsigned long exitCode; + GetExitCodeProcess(pi.hProcess, &exitCode); + if (exitCode != 0) { + if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); + if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + score = 0; + result = RunTimeError; + QFile file(workingDirectory + "_tmperr"); + if (file.open(QFile::ReadOnly)) { + QTextStream stream(&file); + message = stream.readAll(); + } + timeUsed = -1; + return; + } + + FILETIME creationTime, exitTime, kernelTime, userTime; + GetProcessTimes(pi.hProcess, &creationTime, &exitTime, &kernelTime, &userTime); + + SYSTEMTIME realTime; + FileTimeToSystemTime(&userTime, &realTime); + + timeUsed = realTime.wMilliseconds + + realTime.wSecond * 1000 + + realTime.wMinute * 60 * 1000 + + realTime.wHour * 60 * 60 * 1000; + + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo(pi.hProcess, &info, sizeof(info)); + memoryUsed = info.PeakWorkingSetSize; + + if (task->getStandardInputCheck()) CloseHandle(si.hStdInput); + if (task->getStandardOutputCheck()) CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); +#endif + +#ifdef Q_OS_LINUX + QProcess *program = new QProcess(this); + if (task->getStandardInputCheck()) + program->setStandardInputFile(inputFile); + if (task->getStandardOutputCheck()) + program->setStandardOutputFile(workingDirectory + "_tmpout"); + program->setWorkingDirectory(workingDirectory); + program->setProcessEnvironment(environment); + program->start(executableFile); + if (! program->waitForStarted(-1)) { + delete program; + score = 0; + result = CannotStartProgram; + return; + } + + proc_info info; + bool flag = false; + QElapsedTimer timer; + timer.start(); + + while (timer.elapsed() < timeLimit * (1 + extraTimeRatio * 2)) { + if (program->state() != QProcess::Running) { + flag = true; + break; + } + + if (get_pid_stat(int(program->pid()), &info)) { + memoryUsed = qMax(memoryUsed, int(info.rss * sysconf(_SC_PAGESIZE))); + timeUsed = info.utime * 1000 / sysconf(_SC_CLK_TCK); + if (memoryLimit != -1 && memoryUsed > memoryLimit * 1024 * 1024) { + program->kill(); + delete program; + score = 0; + result = MemoryLimitExceeded; + timeUsed = -1; + return; + } + } + QCoreApplication::processEvents(); + if (stopJudging) { + program->kill(); + delete program; + return; + } + msleep(1); + } + + if (! flag) { + program->kill(); + delete program; + score = 0; + result = TimeLimitExceeded; + timeUsed = -1; + return; + } + + if (program->exitCode() != 0) { + score = 0; + result = RunTimeError; + message = QString::fromLocal8Bit(program->readAllStandardError().data()); + timeUsed = -1; + delete program; + return; + } + + delete program; +#endif +} + +void JudgingThread::judgeOutput() +{ + if (task->getComparisonMode() == Task::LineByLineMode) { + if (task->getStandardOutputCheck()) + compareLineByLine(workingDirectory + "_tmpout"); + else + compareLineByLine(workingDirectory + task->getOutputFileName()); + } + + if (task->getComparisonMode() == Task::RealNumberMode) { + if (task->getStandardOutputCheck()) + compareRealNumbers(workingDirectory + "_tmpout"); + else + compareRealNumbers(workingDirectory + task->getOutputFileName()); + } + + if (task->getComparisonMode() == Task::SpecialJudgeMode) { + if (task->getStandardOutputCheck()) + specialJudge(workingDirectory + "_tmpout"); + else + specialJudge(workingDirectory + task->getOutputFileName()); + } +} + +void JudgingThread::judgeTraditionalTask() +{ + if (! QFileInfo(inputFile).exists()) { + score = 0; + result = FileError; + message = tr("Cannot find standard input file"); + return; + } + if (! task->getStandardInputCheck()) + if (! QFile::copy(inputFile, workingDirectory + task->getInputFileName())) { + score = 0; + result = FileError; + message = tr("Cannot copy standard input file"); + return; + } + + runProgram(); + if (stopJudging) return; + + if (result != CorrectAnswer) { + if (! task->getStandardInputCheck()) + QFile::remove(workingDirectory + task->getInputFileName()); + if (! task->getStandardOutputCheck()) + QFile::remove(workingDirectory + task->getOutputFileName()); + else + QFile::remove(workingDirectory + "_tmpout"); + return; + } + + judgeOutput(); + if (stopJudging) return; + + if (timeUsed > timeLimit) + if (checkRejudgeMode && score > 0 && (timeUsed <= timeLimit * (1 + extraTimeRatio) + || timeUsed <= timeLimit + 1000 * extraTimeRatio)) { + int minTimeUsed = timeUsed, curMemoryUsed = memoryUsed; + bool flag = true; + for (int i = 0; i < 10; i ++) { + runProgram(); + if (stopJudging) return; + if (result != CorrectAnswer) { + flag = false; + break; + } + if (timeUsed < minTimeUsed) { + minTimeUsed = timeUsed; + curMemoryUsed = memoryUsed; + judgeOutput(); + if (stopJudging) return; + if (timeUsed <= timeLimit) break; + } + } + timeUsed = minTimeUsed; + memoryUsed = curMemoryUsed; + if (! flag || timeUsed > timeLimit) { + score = 0; + result = TimeLimitExceeded; + message = ""; + } + } else { + if (! checkRejudgeMode && score > 0 && (timeUsed <= timeLimit * (1 + extraTimeRatio) + || timeUsed <= timeLimit + 1000 * extraTimeRatio)) { + needRejudge = true; + } + score = 0; + result = TimeLimitExceeded; + message = ""; + } + + if (! task->getStandardInputCheck()) + QFile::remove(workingDirectory + task->getInputFileName()); + if (! task->getStandardOutputCheck()) + QFile::remove(workingDirectory + task->getOutputFileName()); + else + QFile::remove(workingDirectory + "_tmpout"); +} + +void JudgingThread::judgeAnswersOnlyTask() +{ + if (task->getComparisonMode() == Task::LineByLineMode) + compareLineByLine(answerFile); + if (task->getComparisonMode() == Task::RealNumberMode) + compareRealNumbers(answerFile); + if (task->getComparisonMode() == Task::SpecialJudgeMode) + specialJudge(answerFile); +} + +void JudgingThread::run() +{ + if (task->getTaskType() == Task::Traditional) + judgeTraditionalTask(); + if (task->getTaskType() == Task::AnswersOnly) + judgeAnswersOnlyTask(); +} diff --git a/judgingthread.h b/judgingthread.h index 80f8354..a08149f 100644 --- a/judgingthread.h +++ b/judgingthread.h @@ -1,87 +1,87 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef JUDGINGTHREAD_H -#define JUDGINGTHREAD_H - -#include -#include -#include "globaltype.h" - -class Task; - -class JudgingThread : public QThread -{ - Q_OBJECT -public: - explicit JudgingThread(QObject *parent = 0); - void setCheckRejudgeMode(bool); - void setExtraTimeRatio(double); - void setEnvironment(const QProcessEnvironment&); - void setWorkingDirectory(const QString&); - void setSpecialJudgeTimeLimit(int); - void setExecutableFile(const QString&); - void setAnswerFile(const QString&); - void setInputFile(const QString&); - void setOutputFile(const QString&); - void setTask(Task*); - void setFullScore(int); - void setTimeLimit(int); - void setMemoryLimit(int); - int getTimeUsed() const; - int getMemoryUsed() const; - int getScore() const; - ResultState getResult() const; - const QString& getMessage() const; - bool getNeedRejudge() const; - void run(); - -private: - bool checkRejudgeMode; - bool needRejudge; - double extraTimeRatio; - QProcessEnvironment environment; - QString workingDirectory; - QString executableFile; - QString answerFile; - QString inputFile; - QString outputFile; - Task *task; - int specialJudgeTimeLimit; - int fullScore; - int timeLimit; - int memoryLimit; - int timeUsed; - int memoryUsed; - int score; - ResultState result; - QString message; - bool stopJudging; - void compareLineByLine(const QString&); - void compareRealNumbers(const QString&); - void specialJudge(const QString&); - void runProgram(); - void judgeOutput(); - void judgeTraditionalTask(); - void judgeAnswersOnlyTask(); - -public slots: - void stopJudgingSlot(); -}; - -#endif // JUDGINGTHREAD_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef JUDGINGTHREAD_H +#define JUDGINGTHREAD_H + +#include +#include +#include "globaltype.h" + +class Task; + +class JudgingThread : public QThread +{ + Q_OBJECT +public: + explicit JudgingThread(QObject *parent = 0); + void setCheckRejudgeMode(bool); + void setExtraTimeRatio(double); + void setEnvironment(const QProcessEnvironment&); + void setWorkingDirectory(const QString&); + void setSpecialJudgeTimeLimit(int); + void setExecutableFile(const QString&); + void setAnswerFile(const QString&); + void setInputFile(const QString&); + void setOutputFile(const QString&); + void setTask(Task*); + void setFullScore(int); + void setTimeLimit(int); + void setMemoryLimit(int); + int getTimeUsed() const; + int getMemoryUsed() const; + int getScore() const; + ResultState getResult() const; + const QString& getMessage() const; + bool getNeedRejudge() const; + void run(); + +private: + bool checkRejudgeMode; + bool needRejudge; + double extraTimeRatio; + QProcessEnvironment environment; + QString workingDirectory; + QString executableFile; + QString answerFile; + QString inputFile; + QString outputFile; + Task *task; + int specialJudgeTimeLimit; + int fullScore; + int timeLimit; + int memoryLimit; + int timeUsed; + int memoryUsed; + int score; + ResultState result; + QString message; + bool stopJudging; + void compareLineByLine(const QString&); + void compareRealNumbers(const QString&); + void specialJudge(const QString&); + void runProgram(); + void judgeOutput(); + void judgeTraditionalTask(); + void judgeAnswersOnlyTask(); + +public slots: + void stopJudgingSlot(); +}; + +#endif // JUDGINGTHREAD_H diff --git a/lemon.cpp b/lemon.cpp index 6ad3f37..1b5a467 100644 --- a/lemon.cpp +++ b/lemon.cpp @@ -1,1039 +1,1039 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "lemon.h" -#include "ui_lemon.h" -#include "task.h" -#include "testcase.h" -#include "contest.h" -#include "compiler.h" -#include "contestant.h" -#include "settings.h" -#include "optionsdialog.h" -#include "addcompilerwizard.h" -#include "newcontestdialog.h" -#include "opencontestdialog.h" -#include "welcomedialog.h" -#include "addtaskdialog.h" -#include "detaildialog.h" -#include "time.h" - -Lemon::Lemon(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::Lemon) -{ - ui->setupUi(this); - - curContest = 0; - settings = new Settings(this); - - ui->tabWidget->setVisible(false); - ui->closeAction->setEnabled(false); - - dataDirWatcher = 0; - settings->loadSettings(); - - ui->summary->setSettings(settings); - ui->taskEdit->setSettings(settings); - ui->testCaseEdit->setSettings(settings); - - connect(this, SIGNAL(dataPathChanged()), - ui->taskEdit, SIGNAL(dataPathChanged())); - connect(this, SIGNAL(dataPathChanged()), - ui->testCaseEdit, SIGNAL(dataPathChanged())); - - connect(ui->summary, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), - this, SLOT(summarySelectionChanged())); - connect(ui->optionsAction, SIGNAL(triggered()), - this, SLOT(showOptionsDialog())); - connect(ui->refreshButton, SIGNAL(clicked()), - this, SLOT(refreshButtonClicked())); - connect(ui->judgeButton, SIGNAL(clicked()), - ui->resultViewer, SLOT(judgeSelected())); - connect(ui->judgeAllButton, SIGNAL(clicked()), - ui->resultViewer, SLOT(judgeAll())); - connect(ui->judgeAction, SIGNAL(triggered()), - ui->resultViewer, SLOT(judgeSelected())); - connect(ui->judgeAllAction, SIGNAL(triggered()), - ui->resultViewer, SLOT(judgeAll())); - connect(ui->tabWidget, SIGNAL(currentChanged(int)), - this, SLOT(tabIndexChanged(int))); - connect(ui->resultViewer, SIGNAL(itemSelectionChanged()), - this, SLOT(viewerSelectionChanged())); - connect(ui->resultViewer, SIGNAL(contestantDeleted()), - this, SLOT(contestantDeleted())); - connect(ui->newAction, SIGNAL(triggered()), - this, SLOT(newAction())); - connect(ui->openAction, SIGNAL(triggered()), - this, SLOT(loadAction())); - connect(ui->closeAction, SIGNAL(triggered()), - this, SLOT(closeAction())); - connect(ui->addTasksAction, SIGNAL(triggered()), - this, SLOT(addTasksAction())); - connect(ui->makeSelfTestAction, SIGNAL(triggered()), - this, SLOT(makeSelfTest())); - connect(ui->exportAction, SIGNAL(triggered()), - this, SLOT(exportResult())); - connect(ui->aboutAction, SIGNAL(triggered()), - this, SLOT(aboutLemon())); - connect(ui->exitAction, SIGNAL(triggered()), - this, SLOT(close())); - - appTranslator = new QTranslator(this); - qtTranslator = new QTranslator(this); - QApplication::installTranslator(appTranslator); - QApplication::installTranslator(qtTranslator); - - QStringList fileList = QDir(":/translation").entryList(QStringList() << "lemon_*.qm", QDir::Files); - for (int i = 0; i < fileList.size(); i ++) { - appTranslator->load(QString(":/translation/%1").arg(fileList[i])); - QAction *newLanguage = new QAction(appTranslator->translate("Lemon", "English"), this); - newLanguage->setCheckable(true); - QString language = QFileInfo(fileList[i]).baseName(); - language.remove(0, language.indexOf('_') + 1); - newLanguage->setData(language); - connect(newLanguage, SIGNAL(triggered()), - this, SLOT(setUiLanguage())); - languageActions.append(newLanguage); - } - ui->languageMenu->addActions(languageActions); - ui->setEnglishAction->setData("en"); - ui->setEnglishAction->setCheckable(true); - connect(ui->setEnglishAction, SIGNAL(triggered()), - this, SLOT(setUiLanguage())); - loadUiLanguage(); - - QSettings settings("Crash", "Lemon"); - QSize _size = settings.value("WindowSize", size()).toSize(); - resize(_size); -} - -Lemon::~Lemon() -{ - delete ui; -} - -void Lemon::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::LanguageChange) { - ui->retranslateUi(this); - ui->resultViewer->refreshViewer(); - } -} - -void Lemon::closeEvent(QCloseEvent *event) -{ - if (curContest) saveContest(curFile); - settings->saveSettings(); - QSettings settings("Crash", "Lemon"); - settings.setValue("WindowSize", size()); -} - -void Lemon::welcome() -{ - if (settings->getCompilerList().size() == 0) { - AddCompilerWizard *wizard = new AddCompilerWizard(this); - if (wizard->exec() == QDialog::Accepted) { - QList compilerList = wizard->getCompilerList(); - for (int i = 0; i < compilerList.size(); i ++) - settings->addCompiler(compilerList[i]); - } - delete wizard; - } - - WelcomeDialog *dialog = new WelcomeDialog(this); - dialog->setRecentContest(settings->getRecentContest()); - if (dialog->exec() == QDialog::Accepted) { - settings->setRecentContest(dialog->getRecentContest()); - if (dialog->getCurrentTab() == 0) - loadContest(dialog->getSelectedContest()); - else - newContest(dialog->getContestTitle(), dialog->getSavingName(), dialog->getContestPath()); - } else - settings->setRecentContest(dialog->getRecentContest()); - delete dialog; -} - -void Lemon::loadUiLanguage() -{ - ui->setEnglishAction->setChecked(false); - for (int i = 0; i < languageActions.size(); i ++) - languageActions[i]->setChecked(false); - for (int i = 0; i < languageActions.size(); i ++) - if (languageActions[i]->data().toString() == settings->getUiLanguage()) { - languageActions[i]->setChecked(true); - appTranslator->load(QString(":/translation/lemon_%1.qm").arg(settings->getUiLanguage())); - qtTranslator->load(QString(":/translation/qt_%1.qm").arg(settings->getUiLanguage())); - return; - } - settings->setUiLanguage("en"); - appTranslator->load(""); - qtTranslator->load(""); - ui->setEnglishAction->setChecked(true); -} - -void Lemon::insertWatchPath(const QString &curDir, QFileSystemWatcher *watcher) -{ - watcher->addPath(curDir); - QDir dir(curDir); - QStringList list = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (int i = 0; i < list.size(); i ++) - insertWatchPath(curDir + list[i] + QDir::separator(), watcher); -} - -void Lemon::resetDataWatcher() -{ - if (dataDirWatcher) delete dataDirWatcher; - dataDirWatcher = new QFileSystemWatcher(this); - insertWatchPath(Settings::dataPath(), dataDirWatcher); - connect(dataDirWatcher, SIGNAL(directoryChanged(QString)), - this, SLOT(resetDataWatcher())); - connect(dataDirWatcher, SIGNAL(fileChanged(QString)), - this, SIGNAL(dataPathChanged())); - connect(dataDirWatcher, SIGNAL(directoryChanged(QString)), - this, SIGNAL(dataPathChanged())); - emit dataPathChanged(); -} - -void Lemon::summarySelectionChanged() -{ - if (! ui->summary->isEnabled()) return; - - QTreeWidgetItem *curItem = ui->summary->currentItem(); - if (! curItem) { - ui->taskEdit->setEditTask(0); - ui->editWidget->setCurrentIndex(0); - return; - } - - int index = ui->summary->indexOfTopLevelItem(curItem); - if (index != -1) { - ui->taskEdit->setEditTask(curContest->getTask(index)); - ui->editWidget->setCurrentIndex(1); - - } else { - QTreeWidgetItem *parentItem = curItem->parent(); - int taskIndex = ui->summary->indexOfTopLevelItem(parentItem); - int testCaseIndex = parentItem->indexOfChild(curItem); - Task *curTask = curContest->getTask(taskIndex); - TestCase *curTestCase = curTask->getTestCase(testCaseIndex); - - ui->testCaseEdit->setEditTestCase(curTestCase, curTask->getTaskType() == Task::Traditional); - ui->editWidget->setCurrentIndex(2); - } -} - -void Lemon::showOptionsDialog() -{ - OptionsDialog *dialog = new OptionsDialog(this); - dialog->resetEditSettings(settings); - if (dialog->exec() == QDialog::Accepted) { - settings->copyFrom(dialog->getEditSettings()); - ui->testCaseEdit->setSettings(settings); - if (curContest) { - const QList &taskList = curContest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) - taskList[i]->refreshCompilerConfiguration(settings); - } - } - delete dialog; -} - -void Lemon::refreshButtonClicked() -{ - curContest->refreshContestantList(); - ui->resultViewer->refreshViewer(); - if (ui->resultViewer->rowCount() > 0) { - ui->judgeAllButton->setEnabled(true); - ui->judgeAllAction->setEnabled(true); - } else { - ui->judgeAllButton->setEnabled(false); - ui->judgeAllAction->setEnabled(false); - } -} - -void Lemon::tabIndexChanged(int index) -{ - if (index == 0) { - ui->judgeAction->setEnabled(false); - ui->judgeButton->setEnabled(false); - ui->judgeAllAction->setEnabled(false); - ui->judgeAllButton->setEnabled(false); - } else { - QList selectionRange = ui->resultViewer->selectedRanges(); - if (selectionRange.size() > 0) { - ui->judgeAction->setEnabled(true); - ui->judgeButton->setEnabled(true); - } else { - ui->judgeAction->setEnabled(false); - ui->judgeButton->setEnabled(false); - } - if (ui->resultViewer->rowCount() > 0) { - ui->judgeAllAction->setEnabled(true); - ui->judgeAllButton->setEnabled(true); - } else { - ui->judgeAllAction->setEnabled(false); - ui->judgeAllButton->setEnabled(false); - } - } -} - -void Lemon::viewerSelectionChanged() -{ - QList selectionRange = ui->resultViewer->selectedRanges(); - if (selectionRange.size() > 0) { - ui->judgeButton->setEnabled(true); - ui->judgeAction->setEnabled(true); - } else { - ui->judgeButton->setEnabled(false); - ui->judgeAction->setEnabled(false); - } -} - -void Lemon::contestantDeleted() -{ - if (ui->resultViewer->rowCount() > 0) { - ui->judgeAllButton->setEnabled(true); - ui->judgeAllAction->setEnabled(true); - } else { - ui->judgeAllButton->setEnabled(false); - ui->judgeAllAction->setEnabled(false); - } -} - -void Lemon::saveContest(const QString &fileName) -{ - QFile file(fileName); - if (! file.open(QFile::WriteOnly)) { - QMessageBox::warning(this, tr("Error"), tr("Cannot open file %1").arg(fileName), - QMessageBox::Close); - return; - } - - QApplication::setOverrideCursor(Qt::WaitCursor); - QDataStream out(&file); - curContest->writeToStream(out); - QApplication::restoreOverrideCursor(); -} - -void Lemon::loadContest(const QString &filePath) -{ - if (curContest) closeAction(); - - QFile file(filePath); - if (! file.open(QFile::ReadOnly)) { - QMessageBox::warning(this, tr("Error"), tr("Cannot open file %1").arg(QFileInfo(filePath).fileName()), - QMessageBox::Close); - return; - } - - QDataStream in(&file); - signed checkNumber; - in >> checkNumber; - if (checkNumber != signed(MagicNumber)) { - QMessageBox::warning(this, tr("Error"), tr("File %1 is broken").arg(QFileInfo(filePath).fileName()), - QMessageBox::Close); - return; - } - - QApplication::setOverrideCursor(Qt::WaitCursor); - - curContest = new Contest(this); - curContest->setSettings(settings); - curContest->readFromStream(in); - - curFile = QFileInfo(filePath).fileName(); - QDir::setCurrent(QFileInfo(filePath).path()); - QDir().mkdir(Settings::dataPath()); - QDir().mkdir(Settings::sourcePath()); - ui->summary->setContest(curContest); - ui->resultViewer->setContest(curContest); - ui->resultViewer->refreshViewer(); - ui->tabWidget->setVisible(true); - resetDataWatcher(); - ui->closeAction->setEnabled(true); - ui->addTasksAction->setEnabled(true); - ui->makeSelfTestAction->setEnabled(true); - ui->exportAction->setEnabled(true); - setWindowTitle(tr("Lemon - %1").arg(curContest->getContestTitle())); - - QApplication::restoreOverrideCursor(); - ui->tabWidget->setCurrentIndex(0); -} - -void Lemon::newContest(const QString &title, const QString &savingName, const QString &path) -{ - if (! QDir(path).exists() && ! QDir().mkpath(path)) { - QMessageBox::warning(this, tr("Error"), tr("Cannot make contest path"), - QMessageBox::Close); - return; - } - - if (curContest) closeAction(); - curContest = new Contest(this); - curContest->setSettings(settings); - curContest->setContestTitle(title); - setWindowTitle(tr("Lemon - %1").arg(title)); - QDir::setCurrent(path); - QDir().mkdir(Settings::dataPath()); - QDir().mkdir(Settings::sourcePath()); - curFile = savingName + ".cdf"; - saveContest(curFile); - ui->summary->setContest(curContest); - ui->resultViewer->setContest(curContest); - ui->resultViewer->refreshViewer(); - ui->tabWidget->setVisible(true); - resetDataWatcher(); - ui->closeAction->setEnabled(true); - ui->addTasksAction->setEnabled(true); - ui->makeSelfTestAction->setEnabled(true); - ui->exportAction->setEnabled(true); - QStringList recentContest = settings->getRecentContest(); - recentContest.append(QDir::toNativeSeparators((QDir().absoluteFilePath(curFile)))); - settings->setRecentContest(recentContest); - ui->tabWidget->setCurrentIndex(0); -} - -void Lemon::newAction() -{ - NewContestDialog *dialog = new NewContestDialog(this); - if (dialog->exec() == QDialog::Accepted) - newContest(dialog->getContestTitle(), dialog->getSavingName(), dialog->getContestPath()); - delete dialog; -} - -void Lemon::closeAction() -{ - saveContest(curFile); - ui->summary->setContest(0); - ui->taskEdit->setEditTask(0); - ui->resultViewer->setContest(0); - delete curContest; - curContest = 0; - ui->tabWidget->setCurrentIndex(0); - ui->tabWidget->setVisible(false); - ui->closeAction->setEnabled(false); - ui->addTasksAction->setEnabled(false); - ui->makeSelfTestAction->setEnabled(false); - ui->exportAction->setEnabled(false); - setWindowTitle(tr("Lemon")); -} - -void Lemon::loadAction() -{ - OpenContestDialog *dialog = new OpenContestDialog(this); - dialog->setRecentContest(settings->getRecentContest()); - if (dialog->exec() == QDialog::Accepted) - loadContest(dialog->getSelectedContest()); - settings->setRecentContest(dialog->getRecentContest()); - delete dialog; -} - -void Lemon::getFiles(const QString &path, const QStringList &filters, QMap &files) -{ - QDir dir(path); - if (! filters.isEmpty()) dir.setNameFilters(filters); - QFileInfoList list = dir.entryInfoList(QDir::Files); - for (int i = 0; i < list.size(); i ++) - files.insert(list[i].completeBaseName(), list[i].fileName()); -} - -void Lemon::addTask(const QString &title, const QList > &testCases, - int fullScore, int timeLimit, int memoryLimit) -{ - Task *newTask = new Task; - newTask->setProblemTitle(title); - newTask->setSourceFileName(title); - newTask->setInputFileName(title + ".in"); - newTask->setOutputFileName(title + ".out"); - newTask->refreshCompilerConfiguration(settings); - newTask->setAnswerFileExtension(settings->getDefaultOutputFileExtension()); - curContest->addTask(newTask); - for (int i = 0; i < testCases.size(); i ++) { - TestCase *newTestCase = new TestCase; - newTestCase->setFullScore(fullScore); - newTestCase->setTimeLimit(timeLimit); - newTestCase->setMemoryLimit(memoryLimit); - newTestCase->addSingleCase(title + QDir::separator() + testCases[i].first, - title + QDir::separator() + testCases[i].second); - newTask->addTestCase(newTestCase); - } -} - -bool Lemon::compareFileName(const QPair &a, const QPair &b) -{ - return a.first.length() < b.first.length() - || a.first.length() == b.first.length() && QString::localeAwareCompare(a.first, b.first) < 0; -} - -void Lemon::addTasksAction() -{ - QStringList list = QDir(Settings::dataPath()).entryList(QDir::Dirs | QDir::NoDotAndDotDot); - QSet nameSet; - QList taskList = curContest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) - nameSet.insert(taskList[i]->getSourceFileName()); - QStringList nameList; - QList< QList< QPair > > testCases; - for (int i = 0; i < list.size(); i ++) - if (! nameSet.contains(list[i])) { - QStringList filters; - filters = settings->getInputFileExtensions(); - if (filters.isEmpty()) filters << "in"; - for (int j = 0; j < filters.size(); j ++) - filters[j] = QString("*.") + filters[j]; - QMap inputFiles; - getFiles(Settings::dataPath() + list[i], filters, inputFiles); - - filters = settings->getOutputFileExtensions(); - if (filters.isEmpty()) filters << "out" << "ans"; - for (int j = 0; j < filters.size(); j ++) - filters[j] = QString("*.") + filters[j]; - QMap outputFiles; - getFiles(Settings::dataPath() + list[i], filters, outputFiles); - - QList< QPair > cases; - QStringList baseNameList = inputFiles.keys(); - for (int j = 0; j < baseNameList.size(); j ++) - if (outputFiles.contains(baseNameList[j])) - cases.append(qMakePair(inputFiles[baseNameList[j]], outputFiles[baseNameList[j]])); - - qSort(cases.begin(), cases.end(), compareFileName); - if (! cases.isEmpty()) { - nameList.append(list[i]); - testCases.append(cases); - } - } - - if (nameList.isEmpty()) { - QMessageBox::warning(this, tr("Lemon"), tr("No task found"), QMessageBox::Ok); - return; - } - - AddTaskDialog *dialog = new AddTaskDialog(this); - dialog->resize(dialog->sizeHint()); - dialog->setMaximumSize(dialog->sizeHint()); - dialog->setMinimumSize(dialog->sizeHint()); - for (int i = 0; i < nameList.size(); i ++) - dialog->addTask(nameList[i], 100, settings->getDefaultTimeLimit(), settings->getDefaultMemoryLimit()); - if (dialog->exec() == QDialog::Accepted) - for (int i = 0; i < nameList.size(); i ++) - addTask(nameList[i], testCases[i], dialog->getFullScore(i) / testCases[i].size(), - dialog->getTimeLimit(i), dialog->getMemoryLimit(i)); - - ui->summary->setContest(curContest); -} - -void Lemon::clearPath(const QString &curDir) -{ - QDir dir(curDir); - QStringList fileList = dir.entryList(QDir::Files); - for (int i = 0; i < fileList.size(); i ++) - dir.remove(fileList[i]); - QStringList dirList = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (int i = 0; i < dirList.size(); i ++) { - clearPath(curDir + dirList[i] + QDir::separator()); - dir.rmdir(dirList[i]); - } -} - -void Lemon::makeSelfTest() -{ - QApplication::setOverrideCursor(Qt::WaitCursor); - if (QDir(Settings::selfTestPath()).exists()) - clearPath(Settings::selfTestPath()); - if (! QDir(Settings::selfTestPath()).exists() && ! QDir().mkdir(Settings::selfTestPath())) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(this, tr("Lemon"), tr("Cannot make directory"), QMessageBox::Ok); - return; - } - QList taskList = curContest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) { - QDir(Settings::selfTestPath()).mkdir(taskList[i]->getSourceFileName()); - QList testCaseList = taskList[i]->getTestCaseList(); -#ifdef Q_OS_WIN32 - QFile file(Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "check.bat"); - if (! file.open(QFile::WriteOnly | QFile::Text)) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(this, tr("Lemon"), tr("Cannot write check.bat"), QMessageBox::Ok); - return; - } - QFile dummy(Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "enter"); - if (! dummy.open(QFile::WriteOnly | QFile::Text)) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(this, tr("Lemon"), tr("Cannot write enter"), QMessageBox::Ok); - return; - } - QTextStream dummyStream(&dummy); - dummyStream << endl; - dummy.close(); -#endif -#ifdef Q_OS_LINUX - QFile file(Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "check.sh"); - if (! file.open(QFile::WriteOnly | QFile::Text)) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(this, tr("Lemon"), tr("Cannot write check.sh"), QMessageBox::Ok); - return; - } -#endif - QTextStream out(&file); -#ifdef Q_OS_WIN32 - out << "@echo off" << endl; -#endif -#ifdef Q_OS_LINUX - out << "#!/bin/bash" << endl; -#endif - if (taskList[i]->getComparisonMode() == Task::RealNumberMode) { -#ifdef Q_OS_WIN32 - QFile::copy(":/realjudge/realjudge_win32.exe", - Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "realjudge.exe"); -#endif -#ifdef Q_OS_LINUX - QFile::copy(":/realjudge/realjudge_linux", - Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "realjudge"); - QProcess::execute(QString("chmod +wx \"") + Settings::selfTestPath() + taskList[i]->getSourceFileName() - + QDir::separator() + "realjudge" + "\""); -#endif - } - if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) { - if (! QFile::copy(Settings::dataPath() + taskList[i]->getSpecialJudge(), - Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() - + QFileInfo(taskList[i]->getSpecialJudge()).fileName())) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(this, tr("Lemon"), tr("Cannot copy %1").arg(QFileInfo(taskList[i]->getSpecialJudge()).fileName()), - QMessageBox::Ok); - return; - } - } - for (int j = 0; j < testCaseList.size(); j ++) { - QStringList inputFiles = testCaseList[j]->getInputFiles(); - QStringList outputFiles = testCaseList[j]->getOutputFiles(); - for (int k = 0; k < inputFiles.size(); k ++) { - if (! QFile::copy(Settings::dataPath() + inputFiles[k], - Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() - + QFileInfo(inputFiles[k]).fileName())) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(this, tr("Lemon"), tr("Cannot copy %1").arg(QFileInfo(inputFiles[k]).fileName()), - QMessageBox::Ok); - return; - } - if (! QFile::copy(Settings::dataPath() + outputFiles[k], - Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() - + QFileInfo(outputFiles[k]).fileName())) { - QApplication::restoreOverrideCursor(); - QMessageBox::warning(this, tr("Lemon"), tr("Cannot copy %1").arg(QFileInfo(outputFiles[k]).fileName()), - QMessageBox::Ok); - return; - } -#ifdef Q_OS_WIN32 - if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) - out << QString("copy \"%1\" \"%2\" >nul").arg(QFileInfo(inputFiles[k]).fileName(), - taskList[i]->getInputFileName()) << endl; - out << QString("echo Input file: %1").arg(QFileInfo(outputFiles[k]).fileName()) << endl; - if (taskList[i]->getTaskType() == Task::Traditional) { - out << "timegetSourceFileName() + ".exe" + "\""; - if (taskList[i]->getStandardInputCheck()) - cmd += QString(" <\"%1\"").arg(QFileInfo(inputFiles[k]).fileName()); - if (taskList[i]->getStandardOutputCheck()) - cmd += QString(" >\"%1\"").arg("_tmpout"); - out << cmd << endl; - out << "timegetTaskType() == Task::Traditional) { - if (taskList[i]->getStandardOutputCheck()) - outputFileName = "_tmpout"; - else - outputFileName = taskList[i]->getOutputFileName(); - } else { - outputFileName = QFileInfo(inputFiles[k]).completeBaseName() + "." - + taskList[i]->getAnswerFileExtension(); - } - if (taskList[i]->getComparisonMode() == Task::LineByLineMode) { - out << QString("fc \"%1\" \"%2\"").arg(outputFileName, QFileInfo(outputFiles[k]).fileName()) << endl; - } - if (taskList[i]->getComparisonMode() == Task::RealNumberMode) { - out << QString("realjudge.exe \"%1\" \"%2\" \"%3\"") - .arg(outputFileName, QFileInfo(outputFiles[k]).fileName(), - QString("%1").arg(taskList[i]->getRealPrecision())) << endl; - } - if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) { - out << QString("%1 \"%2\" \"%3\" \"%4\" \"%5\" \"%6\" \"%7\"") - .arg(QFileInfo(taskList[i]->getSpecialJudge()).fileName(), - QFileInfo(inputFiles[k]).fileName(), outputFileName, - QFileInfo(outputFiles[k]).fileName(), QString("%1").arg(testCaseList[j]->getFullScore()), - "_score", "_message") << endl; - out << "echo Your score:" << endl << "type _score" << endl; - out << "if exist _message (" << endl; - out << "echo Message:" << endl << "type _message" << endl << ")" << endl; - } - out << "pause" << endl; - if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) - out << QString("del \"%1\"").arg(taskList[i]->getInputFileName()) << endl; - if (taskList[i]->getTaskType() == Task::Traditional) { - if (! taskList[i]->getStandardOutputCheck()) - out << QString("del \"%1\"").arg(taskList[i]->getOutputFileName()) << endl; - else - out << "del _tmpout" << endl; - } - if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) - out << "del _score" << endl << "del _message" << endl; - out << "echo." << endl; -#endif -#ifdef Q_OS_LINUX - if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) - out << QString("cp %1 %2").arg(QFileInfo(inputFiles[k]).fileName(), - taskList[i]->getInputFileName()) << endl; - out << QString("echo \"Input file: %1\"").arg(QFileInfo(outputFiles[k]).fileName()) << endl; - if (taskList[i]->getTaskType() == Task::Traditional) { - QString cmd = QString("\"") + taskList[i]->getSourceFileName() + "\""; - if (taskList[i]->getStandardInputCheck()) - cmd += QString(" <\"%1\"").arg(QFileInfo(inputFiles[k]).fileName()); - if (taskList[i]->getStandardOutputCheck()) - cmd += QString(" >\"%1\"").arg("_tmpout"); - out << QString("time ./") << cmd << endl; - } - QString outputFileName; - if (taskList[i]->getTaskType() == Task::Traditional) { - if (taskList[i]->getStandardOutputCheck()) - outputFileName = "_tmpout"; - else - outputFileName = taskList[i]->getOutputFileName(); - } else { - outputFileName = QFileInfo(inputFiles[k]).completeBaseName() + "." - + taskList[i]->getAnswerFileExtension(); - } - if (taskList[i]->getComparisonMode() == Task::LineByLineMode) { - QString arg = QString("\"%1\" \"%2\"").arg(outputFileName, QFileInfo(outputFiles[k]).fileName()); - out << "if ! diff " << arg << " --strip-trailing-cr -q;then" << endl; - out << "diff " << arg << " --strip-trailing-cr -y" << endl; - out << QString("echo \"Wrong answer\"") << endl; - out << "else" << endl; - out << QString("echo \"Correct answer\"") << endl; - out << "fi" << endl; - } - if (taskList[i]->getComparisonMode() == Task::RealNumberMode) { - out << QString("./realjudge \"%1\" \"%2\" \"%3\"") - .arg(outputFileName, QFileInfo(outputFiles[k]).fileName(), - QString("%1").arg(taskList[i]->getRealPrecision())) << endl; - } - if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) { - out << QString("./%1 \"%2\" \"%3\" \"%4\" \"%5\" \"%6\" \"%7\"") - .arg(QFileInfo(taskList[i]->getSpecialJudge()).fileName(), - QFileInfo(inputFiles[k]).fileName(), outputFileName, - QFileInfo(outputFiles[k]).fileName(), QString("%1").arg(testCaseList[j]->getFullScore()), - "_score", "_message") << endl; - out << "echo \"Your score:\"" << endl << "cat _score" << endl; - out << "if [ -e _message ];then" << endl; - out << "echo \"Message:\"" << endl << "cat _message" << endl << "fi" << endl; - } - out << "read -n1 -p \"Press enter to continue...\"" << endl; - if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) - out << QString("rm \"%1\"").arg(taskList[i]->getInputFileName()) << endl; - if (taskList[i]->getTaskType() == Task::Traditional) - if (! taskList[i]->getStandardOutputCheck()) - out << QString("rm \"%1\"").arg(taskList[i]->getOutputFileName()) << endl; - else - out << "rm _tmpout" << endl; - if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) - out << "rm _score" << endl << "rm _message" << endl; - out << "echo" << endl; -#endif - } - } - file.close(); -#ifdef Q_OS_LINUX - QProcess::execute(QString("chmod +x \"") + Settings::selfTestPath() + taskList[i]->getSourceFileName() - + QDir::separator() + "check.sh" + "\""); -#endif - } - - QApplication::restoreOverrideCursor(); - QMessageBox::information(this, tr("Lemon"), tr("Self-test folder has been made"), QMessageBox::Ok); -} - -void Lemon::exportHtml(const QString &fileName) -{ - QFile file(fileName); - if (! file.open(QFile::WriteOnly)) { - QMessageBox::warning(this, tr("Lemon"), tr("Cannot open file %1").arg(QFileInfo(file).fileName()), - QMessageBox::Ok); - return; - } - - QApplication::setOverrideCursor(Qt::WaitCursor); - QTextStream out(&file); - - QList contestantList = curContest->getContestantList(); - QList taskList = curContest->getTaskList(); - - out.setCodec("UTF-8"); - out << ""; - out << ""; - out << ""; - out << "" << tr("Contest Result") << ""; - out << ""; - - QList< QPair > sortList; - for (int i = 0; i < contestantList.size(); i ++) { - int totalScore = contestantList[i]->getTotalScore(); - if (totalScore != -1) - sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); - else - sortList.append(qMakePair(1, contestantList[i]->getContestantName())); - } - qSort(sortList); - QMap rankList; - for (int i = 0; i < sortList.size(); i ++) - if (i > 0 && sortList[i].first == sortList[i-1].first) - rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); - else - rankList.insert(sortList[i].second, i); - - QMap loc; - for (int i = 0; i < contestantList.size(); i ++) - loc.insert(contestantList[i], i); - - out << "

"; - out << "" << tr("Rank List") << "

"; - out << "

"; - out << QString("").arg(tr("Rank")); - out << QString("").arg(tr("Name")); - for (int i = 0; i < taskList.size(); i ++) - out << QString("").arg(taskList[i]->getProblemTile()); - out << QString("").arg(tr("Total Score")); - - for (int i = 0; i < sortList.size(); i ++) { - Contestant *contestant = curContest->getContestant(sortList[i].second); - out << QString("") - .arg(rankList[contestant->getContestantName()] + 1); - out << QString("") - .arg(loc[contestant]).arg(sortList[i].second); - for (int j = 0; j < taskList.size(); j ++) { - int score = contestant->getTaskScore(j); - if (score != -1) - out << QString("").arg(score); - else - out << QString("").arg(tr("Invalid")); - } - int score = contestant->getTotalScore(); - if (score != -1) - out << QString("").arg(score); - else - out << QString("").arg(tr("Invalid")); - } - out << "
%1%1%1%1
%1%2%1%1%1%1

"; - - for (int i = 0; i < contestantList.size(); i ++) { - out << QString("
").arg(i) << ""; - out << tr("Contestant: %1").arg(contestantList[i]->getContestantName()) << ""; - out << DetailDialog::getCode(curContest, contestantList[i]); - } - out << ""; - - QApplication::restoreOverrideCursor(); - QMessageBox::information(this, tr("Lemon"), tr("Export is done"), QMessageBox::Ok); -} - -void Lemon::exportCsv(const QString &fileName) -{ - QFile file(fileName); - if (! file.open(QFile::WriteOnly)) { - QMessageBox::warning(this, tr("Lemon"), tr("Cannot open file %1").arg(QFileInfo(file).fileName()), - QMessageBox::Ok); - return; - } - - QApplication::setOverrideCursor(Qt::WaitCursor); - QTextStream out(&file); - - QList contestantList = curContest->getContestantList(); - QList taskList = curContest->getTaskList(); - QList< QPair > sortList; - for (int i = 0; i < contestantList.size(); i ++) { - int totalScore = contestantList[i]->getTotalScore(); - if (totalScore != -1) - sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); - else - sortList.append(qMakePair(1, contestantList[i]->getContestantName())); - } - qSort(sortList); - QMap rankList; - for (int i = 0; i < sortList.size(); i ++) - if (i > 0 && sortList[i].first == sortList[i-1].first) - rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); - else - rankList.insert(sortList[i].second, i); - - QMap loc; - for (int i = 0; i < contestantList.size(); i ++) - loc.insert(contestantList[i], i); - - out << "\"" << tr("Rank") << "\"" << "," << "\"" << tr("Name") << "\"" << ","; - for (int i = 0; i < taskList.size(); i ++) - out << "\"" << taskList[i]->getProblemTile() << "\"" << ","; - out << "\"" << tr("Total Score") << "\"" << endl; - - for (int i = 0; i < sortList.size(); i ++) { - Contestant *contestant = curContest->getContestant(sortList[i].second); - out << "\"" << rankList[contestant->getContestantName()] + 1 << "\"" << ","; - out << "\"" << sortList[i].second << "\"" << ","; - for (int j = 0; j < taskList.size(); j ++) { - int score = contestant->getTaskScore(j); - if (score != -1) - out << "\"" << score << "\"" << ","; - else - out << "\"" << tr("Invalid") << "\"" << ","; - } - int score = contestant->getTotalScore(); - if (score != -1) - out << "\"" << score << "\"" << endl; - else - out << "\"" << tr("Invalid") << "\"" << endl; - } - - QApplication::restoreOverrideCursor(); - QMessageBox::information(this, tr("Lemon"), tr("Export is done"), QMessageBox::Ok); -} - -void Lemon::exportXls(const QString &fileName) -{ -#ifdef Q_OS_WIN32 - if (QFile(fileName).exists()) - if (! QFile(fileName).remove()) { - QMessageBox::warning(this, tr("Lemon"), tr("Cannot open file %1").arg(QFileInfo(fileName).fileName()), - QMessageBox::Ok); - return; - } - - QApplication::setOverrideCursor(Qt::WaitCursor); - - QList contestantList = curContest->getContestantList(); - QList taskList = curContest->getTaskList(); - QList< QPair > sortList; - for (int i = 0; i < contestantList.size(); i ++) { - int totalScore = contestantList[i]->getTotalScore(); - if (totalScore != -1) - sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); - else - sortList.append(qMakePair(1, contestantList[i]->getContestantName())); - } - qSort(sortList); - QMap rankList; - for (int i = 0; i < sortList.size(); i ++) - if (i > 0 && sortList[i].first == sortList[i-1].first) - rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); - else - rankList.insert(sortList[i].second, i); - - QMap loc; - for (int i = 0; i < contestantList.size(); i ++) - loc.insert(contestantList[i], i); - - QAxObject *excel = new QAxObject("Excel.Application", this); - QAxObject *workbook = excel->querySubObject("Workbooks")->querySubObject("Add"); - QAxObject *sheet = workbook->querySubObject("ActiveSheet"); - sheet->setProperty("Name", QDate::currentDate().toString("yyyy-MM-dd")); - - sheet->querySubObject("Cells(int, int)", 1, 1)->setProperty("Value", tr("Rank")); - sheet->querySubObject("Cells(int, int)", 1, 2)->setProperty("Value", tr("Name")); - for (int i = 0; i < taskList.size(); i ++) - sheet->querySubObject("Cells(int, int)", 1, 3 + i)->setProperty("Value", taskList[i]->getProblemTile()); - sheet->querySubObject("Cells(int, int)", 1, 3 + taskList.size())->setProperty("Value", tr("Total Score")); - for (int i = 0; i < taskList.size() + 3; i ++) - sheet->querySubObject("Cells(int, int)", 1, i + 1)->querySubObject("Font")->setProperty("Bold", true); - - for (int i = 0; i < sortList.size(); i ++) { - Contestant *contestant = curContest->getContestant(sortList[i].second); - sheet->querySubObject("Cells(int, int)", 2 + i, 1)->setProperty("Value", rankList[contestant->getContestantName()] + 1); - sheet->querySubObject("Cells(int, int)", 2 + i, 2)->setProperty("Value", sortList[i].second); - for (int j = 0; j < taskList.size(); j ++) { - int score = contestant->getTaskScore(j); - if (score != -1) - sheet->querySubObject("Cells(int, int)", 2 + i, 3 + j)->setProperty("Value", score); - else - sheet->querySubObject("Cells(int, int)", 2 + i, 3 + j)->setProperty("Value", tr("Invalid")); - } - int score = contestant->getTotalScore(); - if (score != -1) - sheet->querySubObject("Cells(int, int)", 2 + i, 3 + taskList.size())->setProperty("Value", score); - else - sheet->querySubObject("Cells(int, int)", 2 + i, 3 + taskList.size())->setProperty("Value", tr("Invalid")); - } - - workbook->dynamicCall("SaveAs(const QString&, int)", QDir::toNativeSeparators(fileName), -4143); - excel->dynamicCall("Quit()"); - delete excel; - - QApplication::restoreOverrideCursor(); - QMessageBox::information(this, tr("Lemon"), tr("Export is done"), QMessageBox::Ok); -#endif -} - -void Lemon::exportResult() -{ - QList contestantList = curContest->getContestantList(); - QList taskList = curContest->getTaskList(); - if (contestantList.isEmpty()) { - QMessageBox::warning(this, tr("Lemon"), tr("No contestant in current contest"), QMessageBox::Ok); - return; - } - if (taskList.isEmpty()) { - QMessageBox::warning(this, tr("Lemon"), tr("No task in current contest"), QMessageBox::Ok); - return; - } - - QString filter = tr("HTML Document (*.html);;CSV (*.csv)"); - -#ifdef Q_OS_WIN32 - QAxObject *excel = new QAxObject("Excel.Application", this); - if (! excel->isNull()) - filter = filter + tr(";;Excel Workbook (*.xls)"); - delete excel; -#endif - - QString fileName = QFileDialog::getSaveFileName(this, tr("Export Result"), - QDir::currentPath() + QDir::separator() + "result", filter); - if (fileName.isEmpty()) return; - - if (QFileInfo(fileName).suffix() == "html") exportHtml(fileName); - if (QFileInfo(fileName).suffix() == "csv") exportCsv(fileName); - if (QFileInfo(fileName).suffix() == "xls") exportXls(fileName); -} - -void Lemon::aboutLemon() -{ - QString text; - text += "

Project Lemon

"; - text += tr("A tiny judging environment for OI contest") + "
"; - text += tr("Version 1.0 Release") + "
"; - text += tr("Build Date: %1").arg(__DATE__) + "
"; - text += tr("Copyright (c) 2011 Zhipeng Jia") + "
"; - text += tr("This program is under the
GPLv3 license") + "
"; - text += QString("") + tr("Author\'s blog") + "
"; - text += QString("") + tr("Google Code Page") + ""; - QMessageBox::about(this, tr("About Lemon"), text); -} - -void Lemon::setUiLanguage() -{ - QAction *language = dynamic_cast(sender()); - settings->setUiLanguage(language->data().toString()); - loadUiLanguage(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "lemon.h" +#include "ui_lemon.h" +#include "task.h" +#include "testcase.h" +#include "contest.h" +#include "compiler.h" +#include "contestant.h" +#include "settings.h" +#include "optionsdialog.h" +#include "addcompilerwizard.h" +#include "newcontestdialog.h" +#include "opencontestdialog.h" +#include "welcomedialog.h" +#include "addtaskdialog.h" +#include "detaildialog.h" +#include "time.h" + +Lemon::Lemon(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::Lemon) +{ + ui->setupUi(this); + + curContest = 0; + settings = new Settings(this); + + ui->tabWidget->setVisible(false); + ui->closeAction->setEnabled(false); + + dataDirWatcher = 0; + settings->loadSettings(); + + ui->summary->setSettings(settings); + ui->taskEdit->setSettings(settings); + ui->testCaseEdit->setSettings(settings); + + connect(this, SIGNAL(dataPathChanged()), + ui->taskEdit, SIGNAL(dataPathChanged())); + connect(this, SIGNAL(dataPathChanged()), + ui->testCaseEdit, SIGNAL(dataPathChanged())); + + connect(ui->summary, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + this, SLOT(summarySelectionChanged())); + connect(ui->optionsAction, SIGNAL(triggered()), + this, SLOT(showOptionsDialog())); + connect(ui->refreshButton, SIGNAL(clicked()), + this, SLOT(refreshButtonClicked())); + connect(ui->judgeButton, SIGNAL(clicked()), + ui->resultViewer, SLOT(judgeSelected())); + connect(ui->judgeAllButton, SIGNAL(clicked()), + ui->resultViewer, SLOT(judgeAll())); + connect(ui->judgeAction, SIGNAL(triggered()), + ui->resultViewer, SLOT(judgeSelected())); + connect(ui->judgeAllAction, SIGNAL(triggered()), + ui->resultViewer, SLOT(judgeAll())); + connect(ui->tabWidget, SIGNAL(currentChanged(int)), + this, SLOT(tabIndexChanged(int))); + connect(ui->resultViewer, SIGNAL(itemSelectionChanged()), + this, SLOT(viewerSelectionChanged())); + connect(ui->resultViewer, SIGNAL(contestantDeleted()), + this, SLOT(contestantDeleted())); + connect(ui->newAction, SIGNAL(triggered()), + this, SLOT(newAction())); + connect(ui->openAction, SIGNAL(triggered()), + this, SLOT(loadAction())); + connect(ui->closeAction, SIGNAL(triggered()), + this, SLOT(closeAction())); + connect(ui->addTasksAction, SIGNAL(triggered()), + this, SLOT(addTasksAction())); + connect(ui->makeSelfTestAction, SIGNAL(triggered()), + this, SLOT(makeSelfTest())); + connect(ui->exportAction, SIGNAL(triggered()), + this, SLOT(exportResult())); + connect(ui->aboutAction, SIGNAL(triggered()), + this, SLOT(aboutLemon())); + connect(ui->exitAction, SIGNAL(triggered()), + this, SLOT(close())); + + appTranslator = new QTranslator(this); + qtTranslator = new QTranslator(this); + QApplication::installTranslator(appTranslator); + QApplication::installTranslator(qtTranslator); + + QStringList fileList = QDir(":/translation").entryList(QStringList() << "lemon_*.qm", QDir::Files); + for (int i = 0; i < fileList.size(); i ++) { + appTranslator->load(QString(":/translation/%1").arg(fileList[i])); + QAction *newLanguage = new QAction(appTranslator->translate("Lemon", "English"), this); + newLanguage->setCheckable(true); + QString language = QFileInfo(fileList[i]).baseName(); + language.remove(0, language.indexOf('_') + 1); + newLanguage->setData(language); + connect(newLanguage, SIGNAL(triggered()), + this, SLOT(setUiLanguage())); + languageActions.append(newLanguage); + } + ui->languageMenu->addActions(languageActions); + ui->setEnglishAction->setData("en"); + ui->setEnglishAction->setCheckable(true); + connect(ui->setEnglishAction, SIGNAL(triggered()), + this, SLOT(setUiLanguage())); + loadUiLanguage(); + + QSettings settings("Crash", "Lemon"); + QSize _size = settings.value("WindowSize", size()).toSize(); + resize(_size); +} + +Lemon::~Lemon() +{ + delete ui; +} + +void Lemon::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + ui->resultViewer->refreshViewer(); + } +} + +void Lemon::closeEvent(QCloseEvent *event) +{ + if (curContest) saveContest(curFile); + settings->saveSettings(); + QSettings settings("Crash", "Lemon"); + settings.setValue("WindowSize", size()); +} + +void Lemon::welcome() +{ + if (settings->getCompilerList().size() == 0) { + AddCompilerWizard *wizard = new AddCompilerWizard(this); + if (wizard->exec() == QDialog::Accepted) { + QList compilerList = wizard->getCompilerList(); + for (int i = 0; i < compilerList.size(); i ++) + settings->addCompiler(compilerList[i]); + } + delete wizard; + } + + WelcomeDialog *dialog = new WelcomeDialog(this); + dialog->setRecentContest(settings->getRecentContest()); + if (dialog->exec() == QDialog::Accepted) { + settings->setRecentContest(dialog->getRecentContest()); + if (dialog->getCurrentTab() == 0) + loadContest(dialog->getSelectedContest()); + else + newContest(dialog->getContestTitle(), dialog->getSavingName(), dialog->getContestPath()); + } else + settings->setRecentContest(dialog->getRecentContest()); + delete dialog; +} + +void Lemon::loadUiLanguage() +{ + ui->setEnglishAction->setChecked(false); + for (int i = 0; i < languageActions.size(); i ++) + languageActions[i]->setChecked(false); + for (int i = 0; i < languageActions.size(); i ++) + if (languageActions[i]->data().toString() == settings->getUiLanguage()) { + languageActions[i]->setChecked(true); + appTranslator->load(QString(":/translation/lemon_%1.qm").arg(settings->getUiLanguage())); + qtTranslator->load(QString(":/translation/qt_%1.qm").arg(settings->getUiLanguage())); + return; + } + settings->setUiLanguage("en"); + appTranslator->load(""); + qtTranslator->load(""); + ui->setEnglishAction->setChecked(true); +} + +void Lemon::insertWatchPath(const QString &curDir, QFileSystemWatcher *watcher) +{ + watcher->addPath(curDir); + QDir dir(curDir); + QStringList list = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (int i = 0; i < list.size(); i ++) + insertWatchPath(curDir + list[i] + QDir::separator(), watcher); +} + +void Lemon::resetDataWatcher() +{ + if (dataDirWatcher) delete dataDirWatcher; + dataDirWatcher = new QFileSystemWatcher(this); + insertWatchPath(Settings::dataPath(), dataDirWatcher); + connect(dataDirWatcher, SIGNAL(directoryChanged(QString)), + this, SLOT(resetDataWatcher())); + connect(dataDirWatcher, SIGNAL(fileChanged(QString)), + this, SIGNAL(dataPathChanged())); + connect(dataDirWatcher, SIGNAL(directoryChanged(QString)), + this, SIGNAL(dataPathChanged())); + emit dataPathChanged(); +} + +void Lemon::summarySelectionChanged() +{ + if (! ui->summary->isEnabled()) return; + + QTreeWidgetItem *curItem = ui->summary->currentItem(); + if (! curItem) { + ui->taskEdit->setEditTask(0); + ui->editWidget->setCurrentIndex(0); + return; + } + + int index = ui->summary->indexOfTopLevelItem(curItem); + if (index != -1) { + ui->taskEdit->setEditTask(curContest->getTask(index)); + ui->editWidget->setCurrentIndex(1); + + } else { + QTreeWidgetItem *parentItem = curItem->parent(); + int taskIndex = ui->summary->indexOfTopLevelItem(parentItem); + int testCaseIndex = parentItem->indexOfChild(curItem); + Task *curTask = curContest->getTask(taskIndex); + TestCase *curTestCase = curTask->getTestCase(testCaseIndex); + + ui->testCaseEdit->setEditTestCase(curTestCase, curTask->getTaskType() == Task::Traditional); + ui->editWidget->setCurrentIndex(2); + } +} + +void Lemon::showOptionsDialog() +{ + OptionsDialog *dialog = new OptionsDialog(this); + dialog->resetEditSettings(settings); + if (dialog->exec() == QDialog::Accepted) { + settings->copyFrom(dialog->getEditSettings()); + ui->testCaseEdit->setSettings(settings); + if (curContest) { + const QList &taskList = curContest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) + taskList[i]->refreshCompilerConfiguration(settings); + } + } + delete dialog; +} + +void Lemon::refreshButtonClicked() +{ + curContest->refreshContestantList(); + ui->resultViewer->refreshViewer(); + if (ui->resultViewer->rowCount() > 0) { + ui->judgeAllButton->setEnabled(true); + ui->judgeAllAction->setEnabled(true); + } else { + ui->judgeAllButton->setEnabled(false); + ui->judgeAllAction->setEnabled(false); + } +} + +void Lemon::tabIndexChanged(int index) +{ + if (index == 0) { + ui->judgeAction->setEnabled(false); + ui->judgeButton->setEnabled(false); + ui->judgeAllAction->setEnabled(false); + ui->judgeAllButton->setEnabled(false); + } else { + QList selectionRange = ui->resultViewer->selectedRanges(); + if (selectionRange.size() > 0) { + ui->judgeAction->setEnabled(true); + ui->judgeButton->setEnabled(true); + } else { + ui->judgeAction->setEnabled(false); + ui->judgeButton->setEnabled(false); + } + if (ui->resultViewer->rowCount() > 0) { + ui->judgeAllAction->setEnabled(true); + ui->judgeAllButton->setEnabled(true); + } else { + ui->judgeAllAction->setEnabled(false); + ui->judgeAllButton->setEnabled(false); + } + } +} + +void Lemon::viewerSelectionChanged() +{ + QList selectionRange = ui->resultViewer->selectedRanges(); + if (selectionRange.size() > 0) { + ui->judgeButton->setEnabled(true); + ui->judgeAction->setEnabled(true); + } else { + ui->judgeButton->setEnabled(false); + ui->judgeAction->setEnabled(false); + } +} + +void Lemon::contestantDeleted() +{ + if (ui->resultViewer->rowCount() > 0) { + ui->judgeAllButton->setEnabled(true); + ui->judgeAllAction->setEnabled(true); + } else { + ui->judgeAllButton->setEnabled(false); + ui->judgeAllAction->setEnabled(false); + } +} + +void Lemon::saveContest(const QString &fileName) +{ + QFile file(fileName); + if (! file.open(QFile::WriteOnly)) { + QMessageBox::warning(this, tr("Error"), tr("Cannot open file %1").arg(fileName), + QMessageBox::Close); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + QDataStream out(&file); + curContest->writeToStream(out); + QApplication::restoreOverrideCursor(); +} + +void Lemon::loadContest(const QString &filePath) +{ + if (curContest) closeAction(); + + QFile file(filePath); + if (! file.open(QFile::ReadOnly)) { + QMessageBox::warning(this, tr("Error"), tr("Cannot open file %1").arg(QFileInfo(filePath).fileName()), + QMessageBox::Close); + return; + } + + QDataStream in(&file); + signed checkNumber; + in >> checkNumber; + if (checkNumber != signed(MagicNumber)) { + QMessageBox::warning(this, tr("Error"), tr("File %1 is broken").arg(QFileInfo(filePath).fileName()), + QMessageBox::Close); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + + curContest = new Contest(this); + curContest->setSettings(settings); + curContest->readFromStream(in); + + curFile = QFileInfo(filePath).fileName(); + QDir::setCurrent(QFileInfo(filePath).path()); + QDir().mkdir(Settings::dataPath()); + QDir().mkdir(Settings::sourcePath()); + ui->summary->setContest(curContest); + ui->resultViewer->setContest(curContest); + ui->resultViewer->refreshViewer(); + ui->tabWidget->setVisible(true); + resetDataWatcher(); + ui->closeAction->setEnabled(true); + ui->addTasksAction->setEnabled(true); + ui->makeSelfTestAction->setEnabled(true); + ui->exportAction->setEnabled(true); + setWindowTitle(tr("Lemon - %1").arg(curContest->getContestTitle())); + + QApplication::restoreOverrideCursor(); + ui->tabWidget->setCurrentIndex(0); +} + +void Lemon::newContest(const QString &title, const QString &savingName, const QString &path) +{ + if (! QDir(path).exists() && ! QDir().mkpath(path)) { + QMessageBox::warning(this, tr("Error"), tr("Cannot make contest path"), + QMessageBox::Close); + return; + } + + if (curContest) closeAction(); + curContest = new Contest(this); + curContest->setSettings(settings); + curContest->setContestTitle(title); + setWindowTitle(tr("Lemon - %1").arg(title)); + QDir::setCurrent(path); + QDir().mkdir(Settings::dataPath()); + QDir().mkdir(Settings::sourcePath()); + curFile = savingName + ".cdf"; + saveContest(curFile); + ui->summary->setContest(curContest); + ui->resultViewer->setContest(curContest); + ui->resultViewer->refreshViewer(); + ui->tabWidget->setVisible(true); + resetDataWatcher(); + ui->closeAction->setEnabled(true); + ui->addTasksAction->setEnabled(true); + ui->makeSelfTestAction->setEnabled(true); + ui->exportAction->setEnabled(true); + QStringList recentContest = settings->getRecentContest(); + recentContest.append(QDir::toNativeSeparators((QDir().absoluteFilePath(curFile)))); + settings->setRecentContest(recentContest); + ui->tabWidget->setCurrentIndex(0); +} + +void Lemon::newAction() +{ + NewContestDialog *dialog = new NewContestDialog(this); + if (dialog->exec() == QDialog::Accepted) + newContest(dialog->getContestTitle(), dialog->getSavingName(), dialog->getContestPath()); + delete dialog; +} + +void Lemon::closeAction() +{ + saveContest(curFile); + ui->summary->setContest(0); + ui->taskEdit->setEditTask(0); + ui->resultViewer->setContest(0); + delete curContest; + curContest = 0; + ui->tabWidget->setCurrentIndex(0); + ui->tabWidget->setVisible(false); + ui->closeAction->setEnabled(false); + ui->addTasksAction->setEnabled(false); + ui->makeSelfTestAction->setEnabled(false); + ui->exportAction->setEnabled(false); + setWindowTitle(tr("Lemon")); +} + +void Lemon::loadAction() +{ + OpenContestDialog *dialog = new OpenContestDialog(this); + dialog->setRecentContest(settings->getRecentContest()); + if (dialog->exec() == QDialog::Accepted) + loadContest(dialog->getSelectedContest()); + settings->setRecentContest(dialog->getRecentContest()); + delete dialog; +} + +void Lemon::getFiles(const QString &path, const QStringList &filters, QMap &files) +{ + QDir dir(path); + if (! filters.isEmpty()) dir.setNameFilters(filters); + QFileInfoList list = dir.entryInfoList(QDir::Files); + for (int i = 0; i < list.size(); i ++) + files.insert(list[i].completeBaseName(), list[i].fileName()); +} + +void Lemon::addTask(const QString &title, const QList > &testCases, + int fullScore, int timeLimit, int memoryLimit) +{ + Task *newTask = new Task; + newTask->setProblemTitle(title); + newTask->setSourceFileName(title); + newTask->setInputFileName(title + ".in"); + newTask->setOutputFileName(title + ".out"); + newTask->refreshCompilerConfiguration(settings); + newTask->setAnswerFileExtension(settings->getDefaultOutputFileExtension()); + curContest->addTask(newTask); + for (int i = 0; i < testCases.size(); i ++) { + TestCase *newTestCase = new TestCase; + newTestCase->setFullScore(fullScore); + newTestCase->setTimeLimit(timeLimit); + newTestCase->setMemoryLimit(memoryLimit); + newTestCase->addSingleCase(title + QDir::separator() + testCases[i].first, + title + QDir::separator() + testCases[i].second); + newTask->addTestCase(newTestCase); + } +} + +bool Lemon::compareFileName(const QPair &a, const QPair &b) +{ + return a.first.length() < b.first.length() + || a.first.length() == b.first.length() && QString::localeAwareCompare(a.first, b.first) < 0; +} + +void Lemon::addTasksAction() +{ + QStringList list = QDir(Settings::dataPath()).entryList(QDir::Dirs | QDir::NoDotAndDotDot); + QSet nameSet; + QList taskList = curContest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) + nameSet.insert(taskList[i]->getSourceFileName()); + QStringList nameList; + QList< QList< QPair > > testCases; + for (int i = 0; i < list.size(); i ++) + if (! nameSet.contains(list[i])) { + QStringList filters; + filters = settings->getInputFileExtensions(); + if (filters.isEmpty()) filters << "in"; + for (int j = 0; j < filters.size(); j ++) + filters[j] = QString("*.") + filters[j]; + QMap inputFiles; + getFiles(Settings::dataPath() + list[i], filters, inputFiles); + + filters = settings->getOutputFileExtensions(); + if (filters.isEmpty()) filters << "out" << "ans"; + for (int j = 0; j < filters.size(); j ++) + filters[j] = QString("*.") + filters[j]; + QMap outputFiles; + getFiles(Settings::dataPath() + list[i], filters, outputFiles); + + QList< QPair > cases; + QStringList baseNameList = inputFiles.keys(); + for (int j = 0; j < baseNameList.size(); j ++) + if (outputFiles.contains(baseNameList[j])) + cases.append(qMakePair(inputFiles[baseNameList[j]], outputFiles[baseNameList[j]])); + + qSort(cases.begin(), cases.end(), compareFileName); + if (! cases.isEmpty()) { + nameList.append(list[i]); + testCases.append(cases); + } + } + + if (nameList.isEmpty()) { + QMessageBox::warning(this, tr("Lemon"), tr("No task found"), QMessageBox::Ok); + return; + } + + AddTaskDialog *dialog = new AddTaskDialog(this); + dialog->resize(dialog->sizeHint()); + dialog->setMaximumSize(dialog->sizeHint()); + dialog->setMinimumSize(dialog->sizeHint()); + for (int i = 0; i < nameList.size(); i ++) + dialog->addTask(nameList[i], 100, settings->getDefaultTimeLimit(), settings->getDefaultMemoryLimit()); + if (dialog->exec() == QDialog::Accepted) + for (int i = 0; i < nameList.size(); i ++) + addTask(nameList[i], testCases[i], dialog->getFullScore(i) / testCases[i].size(), + dialog->getTimeLimit(i), dialog->getMemoryLimit(i)); + + ui->summary->setContest(curContest); +} + +void Lemon::clearPath(const QString &curDir) +{ + QDir dir(curDir); + QStringList fileList = dir.entryList(QDir::Files); + for (int i = 0; i < fileList.size(); i ++) + dir.remove(fileList[i]); + QStringList dirList = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (int i = 0; i < dirList.size(); i ++) { + clearPath(curDir + dirList[i] + QDir::separator()); + dir.rmdir(dirList[i]); + } +} + +void Lemon::makeSelfTest() +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + if (QDir(Settings::selfTestPath()).exists()) + clearPath(Settings::selfTestPath()); + if (! QDir(Settings::selfTestPath()).exists() && ! QDir().mkdir(Settings::selfTestPath())) { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(this, tr("Lemon"), tr("Cannot make directory"), QMessageBox::Ok); + return; + } + QList taskList = curContest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) { + QDir(Settings::selfTestPath()).mkdir(taskList[i]->getSourceFileName()); + QList testCaseList = taskList[i]->getTestCaseList(); +#ifdef Q_OS_WIN32 + QFile file(Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "check.bat"); + if (! file.open(QFile::WriteOnly | QFile::Text)) { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(this, tr("Lemon"), tr("Cannot write check.bat"), QMessageBox::Ok); + return; + } + QFile dummy(Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "enter"); + if (! dummy.open(QFile::WriteOnly | QFile::Text)) { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(this, tr("Lemon"), tr("Cannot write enter"), QMessageBox::Ok); + return; + } + QTextStream dummyStream(&dummy); + dummyStream << endl; + dummy.close(); +#endif +#ifdef Q_OS_LINUX + QFile file(Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "check.sh"); + if (! file.open(QFile::WriteOnly | QFile::Text)) { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(this, tr("Lemon"), tr("Cannot write check.sh"), QMessageBox::Ok); + return; + } +#endif + QTextStream out(&file); +#ifdef Q_OS_WIN32 + out << "@echo off" << endl; +#endif +#ifdef Q_OS_LINUX + out << "#!/bin/bash" << endl; +#endif + if (taskList[i]->getComparisonMode() == Task::RealNumberMode) { +#ifdef Q_OS_WIN32 + QFile::copy(":/realjudge/realjudge_win32.exe", + Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "realjudge.exe"); +#endif +#ifdef Q_OS_LINUX + QFile::copy(":/realjudge/realjudge_linux", + Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + "realjudge"); + QProcess::execute(QString("chmod +wx \"") + Settings::selfTestPath() + taskList[i]->getSourceFileName() + + QDir::separator() + "realjudge" + "\""); +#endif + } + if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) { + if (! QFile::copy(Settings::dataPath() + taskList[i]->getSpecialJudge(), + Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + + QFileInfo(taskList[i]->getSpecialJudge()).fileName())) { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(this, tr("Lemon"), tr("Cannot copy %1").arg(QFileInfo(taskList[i]->getSpecialJudge()).fileName()), + QMessageBox::Ok); + return; + } + } + for (int j = 0; j < testCaseList.size(); j ++) { + QStringList inputFiles = testCaseList[j]->getInputFiles(); + QStringList outputFiles = testCaseList[j]->getOutputFiles(); + for (int k = 0; k < inputFiles.size(); k ++) { + if (! QFile::copy(Settings::dataPath() + inputFiles[k], + Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + + QFileInfo(inputFiles[k]).fileName())) { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(this, tr("Lemon"), tr("Cannot copy %1").arg(QFileInfo(inputFiles[k]).fileName()), + QMessageBox::Ok); + return; + } + if (! QFile::copy(Settings::dataPath() + outputFiles[k], + Settings::selfTestPath() + taskList[i]->getSourceFileName() + QDir::separator() + + QFileInfo(outputFiles[k]).fileName())) { + QApplication::restoreOverrideCursor(); + QMessageBox::warning(this, tr("Lemon"), tr("Cannot copy %1").arg(QFileInfo(outputFiles[k]).fileName()), + QMessageBox::Ok); + return; + } +#ifdef Q_OS_WIN32 + if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) + out << QString("copy \"%1\" \"%2\" >nul").arg(QFileInfo(inputFiles[k]).fileName(), + taskList[i]->getInputFileName()) << endl; + out << QString("echo Input file: %1").arg(QFileInfo(outputFiles[k]).fileName()) << endl; + if (taskList[i]->getTaskType() == Task::Traditional) { + out << "timegetSourceFileName() + ".exe" + "\""; + if (taskList[i]->getStandardInputCheck()) + cmd += QString(" <\"%1\"").arg(QFileInfo(inputFiles[k]).fileName()); + if (taskList[i]->getStandardOutputCheck()) + cmd += QString(" >\"%1\"").arg("_tmpout"); + out << cmd << endl; + out << "timegetTaskType() == Task::Traditional) { + if (taskList[i]->getStandardOutputCheck()) + outputFileName = "_tmpout"; + else + outputFileName = taskList[i]->getOutputFileName(); + } else { + outputFileName = QFileInfo(inputFiles[k]).completeBaseName() + "." + + taskList[i]->getAnswerFileExtension(); + } + if (taskList[i]->getComparisonMode() == Task::LineByLineMode) { + out << QString("fc \"%1\" \"%2\"").arg(outputFileName, QFileInfo(outputFiles[k]).fileName()) << endl; + } + if (taskList[i]->getComparisonMode() == Task::RealNumberMode) { + out << QString("realjudge.exe \"%1\" \"%2\" \"%3\"") + .arg(outputFileName, QFileInfo(outputFiles[k]).fileName(), + QString("%1").arg(taskList[i]->getRealPrecision())) << endl; + } + if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) { + out << QString("%1 \"%2\" \"%3\" \"%4\" \"%5\" \"%6\" \"%7\"") + .arg(QFileInfo(taskList[i]->getSpecialJudge()).fileName(), + QFileInfo(inputFiles[k]).fileName(), outputFileName, + QFileInfo(outputFiles[k]).fileName(), QString("%1").arg(testCaseList[j]->getFullScore()), + "_score", "_message") << endl; + out << "echo Your score:" << endl << "type _score" << endl; + out << "if exist _message (" << endl; + out << "echo Message:" << endl << "type _message" << endl << ")" << endl; + } + out << "pause" << endl; + if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) + out << QString("del \"%1\"").arg(taskList[i]->getInputFileName()) << endl; + if (taskList[i]->getTaskType() == Task::Traditional) { + if (! taskList[i]->getStandardOutputCheck()) + out << QString("del \"%1\"").arg(taskList[i]->getOutputFileName()) << endl; + else + out << "del _tmpout" << endl; + } + if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) + out << "del _score" << endl << "del _message" << endl; + out << "echo." << endl; +#endif +#ifdef Q_OS_LINUX + if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) + out << QString("cp %1 %2").arg(QFileInfo(inputFiles[k]).fileName(), + taskList[i]->getInputFileName()) << endl; + out << QString("echo \"Input file: %1\"").arg(QFileInfo(outputFiles[k]).fileName()) << endl; + if (taskList[i]->getTaskType() == Task::Traditional) { + QString cmd = QString("\"") + taskList[i]->getSourceFileName() + "\""; + if (taskList[i]->getStandardInputCheck()) + cmd += QString(" <\"%1\"").arg(QFileInfo(inputFiles[k]).fileName()); + if (taskList[i]->getStandardOutputCheck()) + cmd += QString(" >\"%1\"").arg("_tmpout"); + out << QString("time ./") << cmd << endl; + } + QString outputFileName; + if (taskList[i]->getTaskType() == Task::Traditional) { + if (taskList[i]->getStandardOutputCheck()) + outputFileName = "_tmpout"; + else + outputFileName = taskList[i]->getOutputFileName(); + } else { + outputFileName = QFileInfo(inputFiles[k]).completeBaseName() + "." + + taskList[i]->getAnswerFileExtension(); + } + if (taskList[i]->getComparisonMode() == Task::LineByLineMode) { + QString arg = QString("\"%1\" \"%2\"").arg(outputFileName, QFileInfo(outputFiles[k]).fileName()); + out << "if ! diff " << arg << " --strip-trailing-cr -q;then" << endl; + out << "diff " << arg << " --strip-trailing-cr -y" << endl; + out << QString("echo \"Wrong answer\"") << endl; + out << "else" << endl; + out << QString("echo \"Correct answer\"") << endl; + out << "fi" << endl; + } + if (taskList[i]->getComparisonMode() == Task::RealNumberMode) { + out << QString("./realjudge \"%1\" \"%2\" \"%3\"") + .arg(outputFileName, QFileInfo(outputFiles[k]).fileName(), + QString("%1").arg(taskList[i]->getRealPrecision())) << endl; + } + if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) { + out << QString("./%1 \"%2\" \"%3\" \"%4\" \"%5\" \"%6\" \"%7\"") + .arg(QFileInfo(taskList[i]->getSpecialJudge()).fileName(), + QFileInfo(inputFiles[k]).fileName(), outputFileName, + QFileInfo(outputFiles[k]).fileName(), QString("%1").arg(testCaseList[j]->getFullScore()), + "_score", "_message") << endl; + out << "echo \"Your score:\"" << endl << "cat _score" << endl; + out << "if [ -e _message ];then" << endl; + out << "echo \"Message:\"" << endl << "cat _message" << endl << "fi" << endl; + } + out << "read -n1 -p \"Press enter to continue...\"" << endl; + if (! taskList[i]->getStandardInputCheck() && taskList[i]->getTaskType() == Task::Traditional) + out << QString("rm \"%1\"").arg(taskList[i]->getInputFileName()) << endl; + if (taskList[i]->getTaskType() == Task::Traditional) + if (! taskList[i]->getStandardOutputCheck()) + out << QString("rm \"%1\"").arg(taskList[i]->getOutputFileName()) << endl; + else + out << "rm _tmpout" << endl; + if (taskList[i]->getComparisonMode() == Task::SpecialJudgeMode) + out << "rm _score" << endl << "rm _message" << endl; + out << "echo" << endl; +#endif + } + } + file.close(); +#ifdef Q_OS_LINUX + QProcess::execute(QString("chmod +x \"") + Settings::selfTestPath() + taskList[i]->getSourceFileName() + + QDir::separator() + "check.sh" + "\""); +#endif + } + + QApplication::restoreOverrideCursor(); + QMessageBox::information(this, tr("Lemon"), tr("Self-test folder has been made"), QMessageBox::Ok); +} + +void Lemon::exportHtml(const QString &fileName) +{ + QFile file(fileName); + if (! file.open(QFile::WriteOnly)) { + QMessageBox::warning(this, tr("Lemon"), tr("Cannot open file %1").arg(QFileInfo(file).fileName()), + QMessageBox::Ok); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + QTextStream out(&file); + + QList contestantList = curContest->getContestantList(); + QList taskList = curContest->getTaskList(); + + out.setCodec("UTF-8"); + out << ""; + out << ""; + out << ""; + out << "" << tr("Contest Result") << ""; + out << ""; + + QList< QPair > sortList; + for (int i = 0; i < contestantList.size(); i ++) { + int totalScore = contestantList[i]->getTotalScore(); + if (totalScore != -1) + sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); + else + sortList.append(qMakePair(1, contestantList[i]->getContestantName())); + } + qSort(sortList); + QMap rankList; + for (int i = 0; i < sortList.size(); i ++) + if (i > 0 && sortList[i].first == sortList[i-1].first) + rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); + else + rankList.insert(sortList[i].second, i); + + QMap loc; + for (int i = 0; i < contestantList.size(); i ++) + loc.insert(contestantList[i], i); + + out << "

"; + out << "" << tr("Rank List") << "

"; + out << "

"; + out << QString("").arg(tr("Rank")); + out << QString("").arg(tr("Name")); + for (int i = 0; i < taskList.size(); i ++) + out << QString("").arg(taskList[i]->getProblemTile()); + out << QString("").arg(tr("Total Score")); + + for (int i = 0; i < sortList.size(); i ++) { + Contestant *contestant = curContest->getContestant(sortList[i].second); + out << QString("") + .arg(rankList[contestant->getContestantName()] + 1); + out << QString("") + .arg(loc[contestant]).arg(sortList[i].second); + for (int j = 0; j < taskList.size(); j ++) { + int score = contestant->getTaskScore(j); + if (score != -1) + out << QString("").arg(score); + else + out << QString("").arg(tr("Invalid")); + } + int score = contestant->getTotalScore(); + if (score != -1) + out << QString("").arg(score); + else + out << QString("").arg(tr("Invalid")); + } + out << "
%1%1%1%1
%1%2%1%1%1%1

"; + + for (int i = 0; i < contestantList.size(); i ++) { + out << QString("
").arg(i) << ""; + out << tr("Contestant: %1").arg(contestantList[i]->getContestantName()) << ""; + out << DetailDialog::getCode(curContest, contestantList[i]); + } + out << ""; + + QApplication::restoreOverrideCursor(); + QMessageBox::information(this, tr("Lemon"), tr("Export is done"), QMessageBox::Ok); +} + +void Lemon::exportCsv(const QString &fileName) +{ + QFile file(fileName); + if (! file.open(QFile::WriteOnly)) { + QMessageBox::warning(this, tr("Lemon"), tr("Cannot open file %1").arg(QFileInfo(file).fileName()), + QMessageBox::Ok); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + QTextStream out(&file); + + QList contestantList = curContest->getContestantList(); + QList taskList = curContest->getTaskList(); + QList< QPair > sortList; + for (int i = 0; i < contestantList.size(); i ++) { + int totalScore = contestantList[i]->getTotalScore(); + if (totalScore != -1) + sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); + else + sortList.append(qMakePair(1, contestantList[i]->getContestantName())); + } + qSort(sortList); + QMap rankList; + for (int i = 0; i < sortList.size(); i ++) + if (i > 0 && sortList[i].first == sortList[i-1].first) + rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); + else + rankList.insert(sortList[i].second, i); + + QMap loc; + for (int i = 0; i < contestantList.size(); i ++) + loc.insert(contestantList[i], i); + + out << "\"" << tr("Rank") << "\"" << "," << "\"" << tr("Name") << "\"" << ","; + for (int i = 0; i < taskList.size(); i ++) + out << "\"" << taskList[i]->getProblemTile() << "\"" << ","; + out << "\"" << tr("Total Score") << "\"" << endl; + + for (int i = 0; i < sortList.size(); i ++) { + Contestant *contestant = curContest->getContestant(sortList[i].second); + out << "\"" << rankList[contestant->getContestantName()] + 1 << "\"" << ","; + out << "\"" << sortList[i].second << "\"" << ","; + for (int j = 0; j < taskList.size(); j ++) { + int score = contestant->getTaskScore(j); + if (score != -1) + out << "\"" << score << "\"" << ","; + else + out << "\"" << tr("Invalid") << "\"" << ","; + } + int score = contestant->getTotalScore(); + if (score != -1) + out << "\"" << score << "\"" << endl; + else + out << "\"" << tr("Invalid") << "\"" << endl; + } + + QApplication::restoreOverrideCursor(); + QMessageBox::information(this, tr("Lemon"), tr("Export is done"), QMessageBox::Ok); +} + +void Lemon::exportXls(const QString &fileName) +{ +#ifdef Q_OS_WIN32 + if (QFile(fileName).exists()) + if (! QFile(fileName).remove()) { + QMessageBox::warning(this, tr("Lemon"), tr("Cannot open file %1").arg(QFileInfo(fileName).fileName()), + QMessageBox::Ok); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + + QList contestantList = curContest->getContestantList(); + QList taskList = curContest->getTaskList(); + QList< QPair > sortList; + for (int i = 0; i < contestantList.size(); i ++) { + int totalScore = contestantList[i]->getTotalScore(); + if (totalScore != -1) + sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); + else + sortList.append(qMakePair(1, contestantList[i]->getContestantName())); + } + qSort(sortList); + QMap rankList; + for (int i = 0; i < sortList.size(); i ++) + if (i > 0 && sortList[i].first == sortList[i-1].first) + rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); + else + rankList.insert(sortList[i].second, i); + + QMap loc; + for (int i = 0; i < contestantList.size(); i ++) + loc.insert(contestantList[i], i); + + QAxObject *excel = new QAxObject("Excel.Application", this); + QAxObject *workbook = excel->querySubObject("Workbooks")->querySubObject("Add"); + QAxObject *sheet = workbook->querySubObject("ActiveSheet"); + sheet->setProperty("Name", QDate::currentDate().toString("yyyy-MM-dd")); + + sheet->querySubObject("Cells(int, int)", 1, 1)->setProperty("Value", tr("Rank")); + sheet->querySubObject("Cells(int, int)", 1, 2)->setProperty("Value", tr("Name")); + for (int i = 0; i < taskList.size(); i ++) + sheet->querySubObject("Cells(int, int)", 1, 3 + i)->setProperty("Value", taskList[i]->getProblemTile()); + sheet->querySubObject("Cells(int, int)", 1, 3 + taskList.size())->setProperty("Value", tr("Total Score")); + for (int i = 0; i < taskList.size() + 3; i ++) + sheet->querySubObject("Cells(int, int)", 1, i + 1)->querySubObject("Font")->setProperty("Bold", true); + + for (int i = 0; i < sortList.size(); i ++) { + Contestant *contestant = curContest->getContestant(sortList[i].second); + sheet->querySubObject("Cells(int, int)", 2 + i, 1)->setProperty("Value", rankList[contestant->getContestantName()] + 1); + sheet->querySubObject("Cells(int, int)", 2 + i, 2)->setProperty("Value", sortList[i].second); + for (int j = 0; j < taskList.size(); j ++) { + int score = contestant->getTaskScore(j); + if (score != -1) + sheet->querySubObject("Cells(int, int)", 2 + i, 3 + j)->setProperty("Value", score); + else + sheet->querySubObject("Cells(int, int)", 2 + i, 3 + j)->setProperty("Value", tr("Invalid")); + } + int score = contestant->getTotalScore(); + if (score != -1) + sheet->querySubObject("Cells(int, int)", 2 + i, 3 + taskList.size())->setProperty("Value", score); + else + sheet->querySubObject("Cells(int, int)", 2 + i, 3 + taskList.size())->setProperty("Value", tr("Invalid")); + } + + workbook->dynamicCall("SaveAs(const QString&, int)", QDir::toNativeSeparators(fileName), -4143); + excel->dynamicCall("Quit()"); + delete excel; + + QApplication::restoreOverrideCursor(); + QMessageBox::information(this, tr("Lemon"), tr("Export is done"), QMessageBox::Ok); +#endif +} + +void Lemon::exportResult() +{ + QList contestantList = curContest->getContestantList(); + QList taskList = curContest->getTaskList(); + if (contestantList.isEmpty()) { + QMessageBox::warning(this, tr("Lemon"), tr("No contestant in current contest"), QMessageBox::Ok); + return; + } + if (taskList.isEmpty()) { + QMessageBox::warning(this, tr("Lemon"), tr("No task in current contest"), QMessageBox::Ok); + return; + } + + QString filter = tr("HTML Document (*.html);;CSV (*.csv)"); + +#ifdef Q_OS_WIN32 + QAxObject *excel = new QAxObject("Excel.Application", this); + if (! excel->isNull()) + filter = filter + tr(";;Excel Workbook (*.xls)"); + delete excel; +#endif + + QString fileName = QFileDialog::getSaveFileName(this, tr("Export Result"), + QDir::currentPath() + QDir::separator() + "result", filter); + if (fileName.isEmpty()) return; + + if (QFileInfo(fileName).suffix() == "html") exportHtml(fileName); + if (QFileInfo(fileName).suffix() == "csv") exportCsv(fileName); + if (QFileInfo(fileName).suffix() == "xls") exportXls(fileName); +} + +void Lemon::aboutLemon() +{ + QString text; + text += "

Project Lemon

"; + text += tr("A tiny judging environment for OI contest") + "
"; + text += tr("Version 1.1 Beta") + "
"; + text += tr("Build Date: %1").arg(__DATE__) + "
"; + text += tr("Copyright (c) 2011 Zhipeng Jia") + "
"; + text += tr("This program is under the
GPLv3 license") + "
"; + text += QString("") + tr("Author\'s blog") + "
"; + text += QString("") + tr("Google Code Page") + ""; + QMessageBox::about(this, tr("About Lemon"), text); +} + +void Lemon::setUiLanguage() +{ + QAction *language = dynamic_cast(sender()); + settings->setUiLanguage(language->data().toString()); + loadUiLanguage(); +} diff --git a/lemon.h b/lemon.h index 9d7683f..2fdd00b 100644 --- a/lemon.h +++ b/lemon.h @@ -1,92 +1,92 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef LEMON_H -#define LEMON_H - -#include -#include -#include - -#ifdef Q_OS_WIN32 -#include -#endif - -namespace Ui { - class Lemon; -} - -class Contest; -class Settings; -class OptionsDialog; - -class Lemon : public QMainWindow -{ - Q_OBJECT - -public: - explicit Lemon(QWidget *parent = 0); - ~Lemon(); - void changeEvent(QEvent*); - void closeEvent(QCloseEvent*); - void welcome(); - -private: - Ui::Lemon *ui; - Contest *curContest; - Settings *settings; - QFileSystemWatcher *dataDirWatcher; - QString curFile; - QList languageActions; - QTranslator *appTranslator; - QTranslator *qtTranslator; - void loadUiLanguage(); - void insertWatchPath(const QString&, QFileSystemWatcher*); - void newContest(const QString&, const QString&, const QString&); - void saveContest(const QString&); - void loadContest(const QString&); - void getFiles(const QString&, const QStringList&, QMap&); - void addTask(const QString&, const QList< QPair >&, int, int, int); - void clearPath(const QString&); - void exportHtml(const QString&); - void exportCsv(const QString&); - void exportXls(const QString&); - static bool compareFileName(const QPair&, const QPair&); - -private slots: - void summarySelectionChanged(); - void resetDataWatcher(); - void showOptionsDialog(); - void refreshButtonClicked(); - void tabIndexChanged(int); - void viewerSelectionChanged(); - void contestantDeleted(); - void newAction(); - void closeAction(); - void loadAction(); - void addTasksAction(); - void makeSelfTest(); - void exportResult(); - void aboutLemon(); - void setUiLanguage(); - -signals: - void dataPathChanged(); -}; - -#endif // LEMON_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef LEMON_H +#define LEMON_H + +#include +#include +#include + +#ifdef Q_OS_WIN32 +#include +#endif + +namespace Ui { + class Lemon; +} + +class Contest; +class Settings; +class OptionsDialog; + +class Lemon : public QMainWindow +{ + Q_OBJECT + +public: + explicit Lemon(QWidget *parent = 0); + ~Lemon(); + void changeEvent(QEvent*); + void closeEvent(QCloseEvent*); + void welcome(); + +private: + Ui::Lemon *ui; + Contest *curContest; + Settings *settings; + QFileSystemWatcher *dataDirWatcher; + QString curFile; + QList languageActions; + QTranslator *appTranslator; + QTranslator *qtTranslator; + void loadUiLanguage(); + void insertWatchPath(const QString&, QFileSystemWatcher*); + void newContest(const QString&, const QString&, const QString&); + void saveContest(const QString&); + void loadContest(const QString&); + void getFiles(const QString&, const QStringList&, QMap&); + void addTask(const QString&, const QList< QPair >&, int, int, int); + void clearPath(const QString&); + void exportHtml(const QString&); + void exportCsv(const QString&); + void exportXls(const QString&); + static bool compareFileName(const QPair&, const QPair&); + +private slots: + void summarySelectionChanged(); + void resetDataWatcher(); + void showOptionsDialog(); + void refreshButtonClicked(); + void tabIndexChanged(int); + void viewerSelectionChanged(); + void contestantDeleted(); + void newAction(); + void closeAction(); + void loadAction(); + void addTasksAction(); + void makeSelfTest(); + void exportResult(); + void aboutLemon(); + void setUiLanguage(); + +signals: + void dataPathChanged(); +}; + +#endif // LEMON_H diff --git a/lemon.pro b/lemon.pro index 14bbe6d..171bdb5 100644 --- a/lemon.pro +++ b/lemon.pro @@ -1,132 +1,132 @@ -# -# Project Lemon - A tiny judging environment for OI contest -# Copyright (C) 2011 Zhipeng Jia -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -QT += core gui network - -TARGET = lemon -TEMPLATE = app - -SOURCES += main.cpp \ - lemon.cpp \ - contest.cpp \ - task.cpp \ - testcase.cpp \ - settings.cpp \ - compiler.cpp \ - filelineedit.cpp \ - summarytree.cpp \ - taskeditwidget.cpp \ - testcaseeditwidget.cpp \ - generalsettings.cpp \ - compilersettings.cpp \ - addtestcaseswizard.cpp \ - contestant.cpp \ - judgingdialog.cpp \ - judgingthread.cpp \ - optionsdialog.cpp \ - resultviewer.cpp \ - assignmentthread.cpp \ - detaildialog.cpp \ - newcontestwidget.cpp \ - opencontestwidget.cpp \ - newcontestdialog.cpp \ - opencontestdialog.cpp \ - welcomedialog.cpp \ - addtaskdialog.cpp \ - qtlockedfile/qtlockedfile.cpp \ - qtsingleapplication/qtsinglecoreapplication.cpp \ - qtsingleapplication/qtsingleapplication.cpp \ - qtsingleapplication/qtlocalpeer.cpp \ - advancedcompilersettingsdialog.cpp \ - environmentvariablesdialog.cpp \ - editvariabledialog.cpp \ - addcompilerwizard.cpp - -win32:SOURCES += qtlockedfile/qtlockedfile_win.cpp -unix:SOURCES += qtlockedfile/qtlockedfile_unix.cpp - -HEADERS += lemon.h \ - contest.h \ - task.h \ - testcase.h \ - settings.h \ - compiler.h \ - filelineedit.h \ - summarytree.h \ - taskeditwidget.h \ - testcaseeditwidget.h \ - generalsettings.h \ - compilersettings.h \ - addtestcaseswizard.h \ - contestant.h \ - judgingdialog.h \ - judgingthread.h \ - optionsdialog.h \ - resultviewer.h \ - assignmentthread.h \ - globaltype.h \ - detaildialog.h \ - newcontestwidget.h \ - opencontestwidget.h \ - newcontestdialog.h \ - opencontestdialog.h \ - welcomedialog.h \ - linux_proc.h \ - addtaskdialog.h \ - qtlockedfile/qtlockedfile.h \ - qtsingleapplication/qtsinglecoreapplication.h \ - qtsingleapplication/qtsingleapplication.h \ - qtsingleapplication/qtlocalpeer.h \ - advancedcompilersettingsdialog.h \ - environmentvariablesdialog.h \ - editvariabledialog.h \ - addcompilerwizard.h - -FORMS += lemon.ui \ - taskeditwidget.ui \ - testcaseeditwidget.ui \ - generalsettings.ui \ - compilersettings.ui \ - addtestcaseswizard.ui \ - judgingdialog.ui \ - optionsdialog.ui \ - detaildialog.ui \ - newcontestwidget.ui \ - opencontestwidget.ui \ - newcontestdialog.ui \ - opencontestdialog.ui \ - welcomedialog.ui \ - addtaskdialog.ui \ - advancedcompilersettingsdialog.ui \ - environmentvariablesdialog.ui \ - editvariabledialog.ui \ - addcompilerwizard.ui - - -TRANSLATIONS += lemon_zh_CN.ts - -win32:RC_FILE = lemon.rc - -win32:LIBS += -lpsapi - -win32:CONFIG += qaxcontainer - -RESOURCES += resource.qrc - - - +# +# Project Lemon - A tiny judging environment for OI contest +# Copyright (C) 2011 Zhipeng Jia +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +QT += core gui network + +TARGET = lemon +TEMPLATE = app + +SOURCES += main.cpp \ + lemon.cpp \ + contest.cpp \ + task.cpp \ + testcase.cpp \ + settings.cpp \ + compiler.cpp \ + filelineedit.cpp \ + summarytree.cpp \ + taskeditwidget.cpp \ + testcaseeditwidget.cpp \ + generalsettings.cpp \ + compilersettings.cpp \ + addtestcaseswizard.cpp \ + contestant.cpp \ + judgingdialog.cpp \ + judgingthread.cpp \ + optionsdialog.cpp \ + resultviewer.cpp \ + assignmentthread.cpp \ + detaildialog.cpp \ + newcontestwidget.cpp \ + opencontestwidget.cpp \ + newcontestdialog.cpp \ + opencontestdialog.cpp \ + welcomedialog.cpp \ + addtaskdialog.cpp \ + qtlockedfile/qtlockedfile.cpp \ + qtsingleapplication/qtsinglecoreapplication.cpp \ + qtsingleapplication/qtsingleapplication.cpp \ + qtsingleapplication/qtlocalpeer.cpp \ + advancedcompilersettingsdialog.cpp \ + environmentvariablesdialog.cpp \ + editvariabledialog.cpp \ + addcompilerwizard.cpp + +win32:SOURCES += qtlockedfile/qtlockedfile_win.cpp +unix:SOURCES += qtlockedfile/qtlockedfile_unix.cpp + +HEADERS += lemon.h \ + contest.h \ + task.h \ + testcase.h \ + settings.h \ + compiler.h \ + filelineedit.h \ + summarytree.h \ + taskeditwidget.h \ + testcaseeditwidget.h \ + generalsettings.h \ + compilersettings.h \ + addtestcaseswizard.h \ + contestant.h \ + judgingdialog.h \ + judgingthread.h \ + optionsdialog.h \ + resultviewer.h \ + assignmentthread.h \ + globaltype.h \ + detaildialog.h \ + newcontestwidget.h \ + opencontestwidget.h \ + newcontestdialog.h \ + opencontestdialog.h \ + welcomedialog.h \ + linux_proc.h \ + addtaskdialog.h \ + qtlockedfile/qtlockedfile.h \ + qtsingleapplication/qtsinglecoreapplication.h \ + qtsingleapplication/qtsingleapplication.h \ + qtsingleapplication/qtlocalpeer.h \ + advancedcompilersettingsdialog.h \ + environmentvariablesdialog.h \ + editvariabledialog.h \ + addcompilerwizard.h + +FORMS += lemon.ui \ + taskeditwidget.ui \ + testcaseeditwidget.ui \ + generalsettings.ui \ + compilersettings.ui \ + addtestcaseswizard.ui \ + judgingdialog.ui \ + optionsdialog.ui \ + detaildialog.ui \ + newcontestwidget.ui \ + opencontestwidget.ui \ + newcontestdialog.ui \ + opencontestdialog.ui \ + welcomedialog.ui \ + addtaskdialog.ui \ + advancedcompilersettingsdialog.ui \ + environmentvariablesdialog.ui \ + editvariabledialog.ui \ + addcompilerwizard.ui + + +TRANSLATIONS += lemon_zh_CN.ts + +win32:RC_FILE = lemon.rc + +win32:LIBS += -lpsapi + +win32:CONFIG += qaxcontainer + +RESOURCES += resource.qrc + + + diff --git a/lemon.rc b/lemon.rc index 2f55423..fc7a538 100644 --- a/lemon.rc +++ b/lemon.rc @@ -1 +1 @@ -IDI_ICON1 ICON DISCARDABLE "icon.ico" +IDI_ICON1 ICON DISCARDABLE "icon.ico" diff --git a/lemon.ui b/lemon.ui index a9c771c..65e66f9 100644 --- a/lemon.ui +++ b/lemon.ui @@ -1,391 +1,391 @@ - - - Lemon - - - - 0 - 0 - 725 - 510 - - - - - 725 - 510 - - - - Lemon - - - - :/icon/icon.png:/icon/icon.png - - - - - - - true - - - font-size: 9pt; - - - 0 - - - - Tasks - - - - - - - 1 - 0 - - - - - 176 - 387 - - - - font-size: 9pt; - - - Summary - - - - - - Qt::DefaultContextMenu - - - font-size: 10pt; - - - false - - - - 1 - - - - - - - - - - - - 3 - 0 - - - - font-size: 9pt; - - - Detail - - - - - - Qt::NoContextMenu - - - 2 - - - - - - - - - - - - - - Contestants - - - - - - font-size: 9pt; - - - - QAbstractItemView::NoEditTriggers - - - false - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - - - false - - - true - - - false - - - false - - - false - - - 25 - - - 25 - - - - - - - - - Qt::Horizontal - - - - 468 - 20 - - - - - - - - &Refresh - - - - - - - false - - - &Judge - - - - - - - false - - - Judge &All - - - - - - - - - - - - - - - 0 - 0 - 725 - 21 - - - - font-size: 9pt; - - - - &File - - - - - - - - - - &Control - - - - - - - - - - - &Tools - - - - UI Language - - - - - - - - - &Help - - - - - - - - - - - &New Contest - - - - - &Open Existing Contest - - - - - E&xit - - - - - &Options - - - - - &About - - - - - false - - - &Judge Selected - - - - - false - - - Judge &All - - - - - &Close Current Contest - - - - - English - - - - - false - - - Add &Tasks Automatically - - - - - false - - - &Make Self-testing Folder - - - - - false - - - &Export Result - - - - - - - SummaryTree - QTreeWidget -
summarytree.h
-
- - TaskEditWidget - QWidget -
taskeditwidget.h
- 1 -
- - TestCaseEditWidget - QWidget -
testcaseeditwidget.h
- 1 -
- - ResultViewer - QTableWidget -
resultviewer.h
-
-
- - tabWidget - summary - refreshButton - judgeButton - judgeAllButton - resultViewer - - - - - -
+ + + Lemon + + + + 0 + 0 + 725 + 510 + + + + + 725 + 510 + + + + Lemon + + + + :/icon/icon.png:/icon/icon.png + + + + + + + true + + + font-size: 9pt; + + + 0 + + + + Tasks + + + + + + + 1 + 0 + + + + + 176 + 387 + + + + font-size: 9pt; + + + Summary + + + + + + Qt::DefaultContextMenu + + + font-size: 10pt; + + + false + + + + 1 + + + + + + + + + + + + 3 + 0 + + + + font-size: 9pt; + + + Detail + + + + + + Qt::NoContextMenu + + + 2 + + + + + + + + + + + + + + Contestants + + + + + + font-size: 9pt; + + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + false + + + true + + + false + + + false + + + false + + + 25 + + + 25 + + + + + + + + + Qt::Horizontal + + + + 468 + 20 + + + + + + + + &Refresh + + + + + + + false + + + &Judge + + + + + + + false + + + Judge &All + + + + + + + + + + + + + + + 0 + 0 + 725 + 21 + + + + font-size: 9pt; + + + + &File + + + + + + + + + + &Control + + + + + + + + + + + &Tools + + + + UI Language + + + + + + + + + &Help + + + + + + + + + + + &New Contest + + + + + &Open Existing Contest + + + + + E&xit + + + + + &Options + + + + + &About + + + + + false + + + &Judge Selected + + + + + false + + + Judge &All + + + + + &Close Current Contest + + + + + English + + + + + false + + + Add &Tasks Automatically + + + + + false + + + &Make Self-testing Folder + + + + + false + + + &Export Result + + + + + + + SummaryTree + QTreeWidget +
summarytree.h
+
+ + TaskEditWidget + QWidget +
taskeditwidget.h
+ 1 +
+ + TestCaseEditWidget + QWidget +
testcaseeditwidget.h
+ 1 +
+ + ResultViewer + QTableWidget +
resultviewer.h
+
+
+ + tabWidget + summary + refreshButton + judgeButton + judgeAllButton + resultViewer + + + + + +
diff --git a/lemon_zh_CN.qm b/lemon_zh_CN.qm index e1d325c..c22254a 100644 Binary files a/lemon_zh_CN.qm and b/lemon_zh_CN.qm differ diff --git a/lemon_zh_CN.ts b/lemon_zh_CN.ts index cf8877f..fa9054b 100644 --- a/lemon_zh_CN.ts +++ b/lemon_zh_CN.ts @@ -34,317 +34,317 @@ 编译器名称 - + Compiler Type 编译器类型 - + Typical (Generate executable file) 传统型(生成可执行文件) - + Interpretive (Generate byte-code file) 解释型(生成中间字节码) - + Interpretive (Run source code directly) 解释型(直接运行源代码) - + Compiler's Location 编译器位置 - + Interpreter's Location 解释器位置 - + Source File Extensions 源程序后缀名 - + Byte-code File Extensions 中间字节码后缀名 - + Default Compiler's Arguments 默认编译器参数 - + Default Interpreter's Arguments 默认解释器参数 - + Step II: Select compilers' locations to configure them. 步骤二:选择编译器路径进行配置。 - - - - - - + + + + + + Enable O2 Optimization - 开始O2优化 + 开启O2优化 - + Memory Limit 空间限制 - + MB MB - - + + Generate Optimized Byte-code 生成优化的字节码 - + Step III: Check the result and finish the wizard. 步骤三:检查结果并完成向导。 - - - - - - - - - - - - + + + + + + + + + + + + Error 错误 - + Empty compiler name! 编译器名称为空! - + Empty compiler location! 编译器位置为空! - + Empty interpreter location! 解释器位置为空! - + Empty source file extensions! 源程序扩展名为空! - + Empty byte-code file extensions! 中间字节码扩展名为空! - + [Custom Compiler] 【自定义编译器】 - + Compiler Name: 编译器名称: - + Compiler Type: 编译器类型: - + Compiler's Location: 编译器位置: - + Interpreter's Location: 解释器位置: - + Source File Extensions: 源程序后缀名: - + Byte-code File Extensions: 中间字节码后缀名: - + Default Compiler's Arguments: 默认编译器参数: - + Default Interpreter's Arguments: 默认解释器参数: - + Empty gcc path! gcc路径为空! - + Empty g++ path! g++路径为空! - + Empty fpc path! fpc路径为空! - + Empty fbc path! fbc路径为空! - + Empty javac path! javac路径为空! - + Empty java path! java路径为空! - + Empty python path! python路径为空! - + [gcc Compiler] 【gcc编译器】 - + gcc Path: gcc路径: - + [g++ Compiler] 【g++编译器】 - + g++ Path: g++路径: - + [fpc Compiler] 【fpc编译器】 - + fpc Path: fpc路径: - + [fbc Compiler] 【fbc编译器】 - + fbc Path: fbc路径: - + [Java Compiler] 【Java编译器】 - + javac Path: javac路径: - + java Path: java路径: - + Memory Limit: %1 MB 内存限制:%1 MB - + [Python Compiler] 【Python编译器】 - + python Path: python路径: - - - - - - - - - - - - + + + + + + + + + + + + Select Compiler's Location 选择编译器位置 - - + + Executable files (*.exe) 可执行文件 (*.exe) - - + + Executable files (*.*) 可执行文件 (*.*) - - - - - - + + + + + + Select Interpreter's Location 选择解释器位置 @@ -362,27 +362,27 @@ 试题 - + Full Score 试题分值 - + Time Limit 时间限制 - + ms ms - + Memory Limit 空间限制 - + MB MB @@ -405,52 +405,52 @@ 分值 - + Time Limit 时间限制 - + ms ms - + Memory Limit 空间限制 - + MB MB - + Step II: Input patterns for input files and output files. You can use argument <1>, <2>, etc. to represent a regular expression. Input and output files will in the same test case when their matched parts of checked expressions are identical. 步骤二:为输入输出文件指定格式。你可以使用诸如<1>, <2>...这样的参数来表示一个正则表达式。打钩的表达式匹配内容相同的输入输出文件将会在一个测试点中。 - + Step III: Preview the result and finish the wizard. 步骤三:预览结果,并结束向导。 - + Input Files Pattern 输入文件格式 - + Output Files Pattern 输出文件格式 - + Argument 参数 - + Regular Expression 正则表达式 @@ -520,93 +520,93 @@ 编译器设置 - + Typical (Generate executable file) 传统型(生成可执行文件) - + Interpretive (Generate byte-code file) 解释型(生成中间字节码) - + Interpretive (Run source code directly) 解释型(直接运行源代码) - + Location 位置 - + Compiler 编译器 - + Interpreter 解释器 - + Byte-code File Extensions 中间字节码后缀名 - + Time and Memory Limit 时间、内存限制 - + Time Limit Ration 时间限制比率 - + Memory Limit Ration 内存限制比率 - + Disable Memory Limit 取消内存限制 - + Arguments 参数 - + Configuration 配置 - + ... ... - + Compiler's Arguments 编译器参数 - + Interpreter's Arguments 解释器参数 - + Environment Variables 环境变量 - + Add new ... 添加... @@ -675,7 +675,7 @@ 选择解释器位置 - + New configuration %1 新建配置%1 @@ -693,12 +693,12 @@ 编译器名称 - + Source Extensions 源程序扩展名 - + &Advanced 高级 @@ -719,34 +719,34 @@ (用%s表示源程序文件名,%e表示可执行文件名。) - - - + + + Error 错误 - + Compiler %1 appears more than once! 编译器%1出现多次! - + Empty compiler name! 编译器名称为空! - + Empty source file extensions! 源程序扩展名为空! - + Lemon Lemon - + Are you sure to delete compiler %1? 确定删除编译器%1吗? @@ -999,7 +999,7 @@ 变量名称 - + Variable Value 变量的值 @@ -1645,8 +1645,8 @@ - Version 1.0 Release - v1.0 正式版 + Version 1.1 Beta + v1.1 测试版 @@ -2005,7 +2005,7 @@ 配置: - + Extension of Contestant's Answer File 选手答案文件扩展名 diff --git a/linux_proc.h b/linux_proc.h index 05f431f..affa5c5 100644 --- a/linux_proc.h +++ b/linux_proc.h @@ -1,133 +1,133 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef LINUX_PROC_H -#define LINUX_PROC_H - -#include -#include "stdio.h" - -#ifdef Q_OS_LINUX - -struct proc_info { - int pid; - char comm[100]; - char state[10]; - int ppid; - int pgrp; - int session; - int tty_nr; - int tpgid; - unsigned flags; - unsigned long minflt; - unsigned long cminflt; - unsigned long majflt; - unsigned long cmajflt; - unsigned long utime; - unsigned long stime; - long cutime; - long cstime; - long priority; - long nice; - long num_threads; - long itrealvalue; - unsigned long long starttime; - unsigned long vsize; - long rss; - unsigned long rsslim; - unsigned long startcode; - unsigned long endcode; - unsigned long startstack; - unsigned long kstkesp; - unsigned long kstkeip; - unsigned long signal; - unsigned long blocked; - unsigned long sigignore; - unsigned long sigcatch; - unsigned long wchan; - unsigned long nswap; - unsigned long cnswap; - int exit_signal; - int processor; - unsigned rt_priority; - unsigned policy; - unsigned long long delayacct_blkio_ticks; - unsigned long guest_time; - long cguest_time; -}; - -bool get_pid_stat(int pid, proc_info *info) -{ - char buf[100]; - sprintf(buf, "/proc/%d/stat", pid); - FILE *in = fopen(buf, "r"); - - if (in == NULL) return false; - - fscanf(in, "%d", &info->pid); - fscanf(in, "%s", &info->comm); - fscanf(in, "%s", &info->state); - fscanf(in, "%d", &info->ppid); - fscanf(in, "%d", &info->pgrp); - fscanf(in, "%d", &info->session); - fscanf(in, "%d", &info->tty_nr); - fscanf(in, "%d", &info->tpgid); - fscanf(in, "%u", &info->flags); - fscanf(in, "%lu", &info->minflt); - fscanf(in, "%lu", &info->cminflt); - fscanf(in, "%lu", &info->majflt); - fscanf(in, "%lu", &info->cmajflt); - fscanf(in, "%lu", &info->utime); - fscanf(in, "%lu", &info->stime); - fscanf(in, "%ld", &info->cutime); - fscanf(in, "%ld", &info->cstime); - fscanf(in, "%ld", &info->priority); - fscanf(in, "%ld", &info->nice); - fscanf(in, "%ld", &info->num_threads); - fscanf(in, "%ld", &info->itrealvalue); - fscanf(in, "%llu", &info->starttime); - fscanf(in, "%lu", &info->vsize); - fscanf(in, "%ld", &info->rss); - fscanf(in, "%lu", &info->rsslim); - fscanf(in, "%lu", &info->startcode); - fscanf(in, "%lu", &info->endcode); - fscanf(in, "%lu", &info->startstack); - fscanf(in, "%lu", &info->kstkesp); - fscanf(in, "%lu", &info->kstkeip); - fscanf(in, "%lu", &info->signal); - fscanf(in, "%lu", &info->blocked); - fscanf(in, "%lu", &info->sigignore); - fscanf(in, "%lu", &info->sigcatch); - fscanf(in, "%lu", &info->wchan); - fscanf(in, "%lu", &info->nswap); - fscanf(in, "%lu", &info->cnswap); - fscanf(in, "%d", &info->exit_signal); - fscanf(in, "%d", &info->processor); - fscanf(in, "%u", &info->rt_priority); - fscanf(in, "%u", &info->policy); - fscanf(in, "%llu", &info->delayacct_blkio_ticks); - fscanf(in, "%lu", &info->guest_time); - fscanf(in, "%ld", &info->cguest_time); - - fclose(in); - - return true; -} - -#endif // Q_OS_LINUX -#endif // LINUX_PROC_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef LINUX_PROC_H +#define LINUX_PROC_H + +#include +#include "stdio.h" + +#ifdef Q_OS_LINUX + +struct proc_info { + int pid; + char comm[100]; + char state[10]; + int ppid; + int pgrp; + int session; + int tty_nr; + int tpgid; + unsigned flags; + unsigned long minflt; + unsigned long cminflt; + unsigned long majflt; + unsigned long cmajflt; + unsigned long utime; + unsigned long stime; + long cutime; + long cstime; + long priority; + long nice; + long num_threads; + long itrealvalue; + unsigned long long starttime; + unsigned long vsize; + long rss; + unsigned long rsslim; + unsigned long startcode; + unsigned long endcode; + unsigned long startstack; + unsigned long kstkesp; + unsigned long kstkeip; + unsigned long signal; + unsigned long blocked; + unsigned long sigignore; + unsigned long sigcatch; + unsigned long wchan; + unsigned long nswap; + unsigned long cnswap; + int exit_signal; + int processor; + unsigned rt_priority; + unsigned policy; + unsigned long long delayacct_blkio_ticks; + unsigned long guest_time; + long cguest_time; +}; + +bool get_pid_stat(int pid, proc_info *info) +{ + char buf[100]; + sprintf(buf, "/proc/%d/stat", pid); + FILE *in = fopen(buf, "r"); + + if (in == NULL) return false; + + fscanf(in, "%d", &info->pid); + fscanf(in, "%s", &info->comm); + fscanf(in, "%s", &info->state); + fscanf(in, "%d", &info->ppid); + fscanf(in, "%d", &info->pgrp); + fscanf(in, "%d", &info->session); + fscanf(in, "%d", &info->tty_nr); + fscanf(in, "%d", &info->tpgid); + fscanf(in, "%u", &info->flags); + fscanf(in, "%lu", &info->minflt); + fscanf(in, "%lu", &info->cminflt); + fscanf(in, "%lu", &info->majflt); + fscanf(in, "%lu", &info->cmajflt); + fscanf(in, "%lu", &info->utime); + fscanf(in, "%lu", &info->stime); + fscanf(in, "%ld", &info->cutime); + fscanf(in, "%ld", &info->cstime); + fscanf(in, "%ld", &info->priority); + fscanf(in, "%ld", &info->nice); + fscanf(in, "%ld", &info->num_threads); + fscanf(in, "%ld", &info->itrealvalue); + fscanf(in, "%llu", &info->starttime); + fscanf(in, "%lu", &info->vsize); + fscanf(in, "%ld", &info->rss); + fscanf(in, "%lu", &info->rsslim); + fscanf(in, "%lu", &info->startcode); + fscanf(in, "%lu", &info->endcode); + fscanf(in, "%lu", &info->startstack); + fscanf(in, "%lu", &info->kstkesp); + fscanf(in, "%lu", &info->kstkeip); + fscanf(in, "%lu", &info->signal); + fscanf(in, "%lu", &info->blocked); + fscanf(in, "%lu", &info->sigignore); + fscanf(in, "%lu", &info->sigcatch); + fscanf(in, "%lu", &info->wchan); + fscanf(in, "%lu", &info->nswap); + fscanf(in, "%lu", &info->cnswap); + fscanf(in, "%d", &info->exit_signal); + fscanf(in, "%d", &info->processor); + fscanf(in, "%u", &info->rt_priority); + fscanf(in, "%u", &info->policy); + fscanf(in, "%llu", &info->delayacct_blkio_ticks); + fscanf(in, "%lu", &info->guest_time); + fscanf(in, "%ld", &info->cguest_time); + + fclose(in); + + return true; +} + +#endif // Q_OS_LINUX +#endif // LINUX_PROC_H diff --git a/main.cpp b/main.cpp index d3e0d7b..f5ad579 100644 --- a/main.cpp +++ b/main.cpp @@ -1,41 +1,41 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include -#include -#include "qtsingleapplication/qtsingleapplication.h" -#include "lemon.h" - -int main(int argc, char *argv[]) -{ - QApplication::addLibraryPath("./plugins"); - QtSingleApplication a(argc, argv); - - if (a.sendMessage("ok")) { - a.activateWindow(); - return 0; - } - - Lemon w; - a.setActivationWindow(&w); - - w.show(); - w.welcome(); - - return a.exec(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include +#include +#include "qtsingleapplication/qtsingleapplication.h" +#include "lemon.h" + +int main(int argc, char *argv[]) +{ + QApplication::addLibraryPath("./plugins"); + QtSingleApplication a(argc, argv); + + if (a.sendMessage("ok")) { + a.activateWindow(); + return 0; + } + + Lemon w; + a.setActivationWindow(&w); + + w.show(); + w.welcome(); + + return a.exec(); +} diff --git a/newcontestdialog.cpp b/newcontestdialog.cpp index 832a8fd..f9b16d2 100644 --- a/newcontestdialog.cpp +++ b/newcontestdialog.cpp @@ -1,55 +1,55 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "newcontestdialog.h" -#include "ui_newcontestdialog.h" - -NewContestDialog::NewContestDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::NewContestDialog) -{ - ui->setupUi(this); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - connect(ui->newContestWidget, SIGNAL(informationChanged()), - this, SLOT(informationChanged())); -} - -NewContestDialog::~NewContestDialog() -{ - delete ui; -} - -QString NewContestDialog::getContestTitle() -{ - return ui->newContestWidget->getContestTitle(); -} - -QString NewContestDialog::getSavingName() -{ - return ui->newContestWidget->getSavingName(); -} - -QString NewContestDialog::getContestPath() -{ - return ui->newContestWidget->getContestPath(); -} - -void NewContestDialog::informationChanged() -{ - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ui->newContestWidget->checkReady()); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "newcontestdialog.h" +#include "ui_newcontestdialog.h" + +NewContestDialog::NewContestDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::NewContestDialog) +{ + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + connect(ui->newContestWidget, SIGNAL(informationChanged()), + this, SLOT(informationChanged())); +} + +NewContestDialog::~NewContestDialog() +{ + delete ui; +} + +QString NewContestDialog::getContestTitle() +{ + return ui->newContestWidget->getContestTitle(); +} + +QString NewContestDialog::getSavingName() +{ + return ui->newContestWidget->getSavingName(); +} + +QString NewContestDialog::getContestPath() +{ + return ui->newContestWidget->getContestPath(); +} + +void NewContestDialog::informationChanged() +{ + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ui->newContestWidget->checkReady()); +} diff --git a/newcontestdialog.h b/newcontestdialog.h index dc4c81c..bb87df9 100644 --- a/newcontestdialog.h +++ b/newcontestdialog.h @@ -1,48 +1,48 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef NEWCONTESTDIALOG_H -#define NEWCONTESTDIALOG_H - -#include -#include -#include - -namespace Ui { - class NewContestDialog; -} - -class NewContestDialog : public QDialog -{ - Q_OBJECT - -public: - explicit NewContestDialog(QWidget *parent = 0); - ~NewContestDialog(); - QString getContestTitle(); - QString getSavingName(); - QString getContestPath(); - -private: - Ui::NewContestDialog *ui; - -private slots: - void informationChanged(); -}; - -#endif // NEWCONTESTDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef NEWCONTESTDIALOG_H +#define NEWCONTESTDIALOG_H + +#include +#include +#include + +namespace Ui { + class NewContestDialog; +} + +class NewContestDialog : public QDialog +{ + Q_OBJECT + +public: + explicit NewContestDialog(QWidget *parent = 0); + ~NewContestDialog(); + QString getContestTitle(); + QString getSavingName(); + QString getContestPath(); + +private: + Ui::NewContestDialog *ui; + +private slots: + void informationChanged(); +}; + +#endif // NEWCONTESTDIALOG_H diff --git a/newcontestdialog.ui b/newcontestdialog.ui index 2216ba5..32e5a1c 100644 --- a/newcontestdialog.ui +++ b/newcontestdialog.ui @@ -1,78 +1,78 @@ - - - NewContestDialog - - - - 0 - 0 - 450 - 320 - - - - - 450 - 320 - - - - New Contest - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - NewContestWidget - QWidget -
newcontestwidget.h
- 1 -
-
- - - - buttonBox - accepted() - NewContestDialog - accept() - - - 224 - 294 - - - 224 - 159 - - - - - buttonBox - rejected() - NewContestDialog - reject() - - - 224 - 294 - - - 224 - 159 - - - - -
+ + + NewContestDialog + + + + 0 + 0 + 450 + 320 + + + + + 450 + 320 + + + + New Contest + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + NewContestWidget + QWidget +
newcontestwidget.h
+ 1 +
+
+ + + + buttonBox + accepted() + NewContestDialog + accept() + + + 224 + 294 + + + 224 + 159 + + + + + buttonBox + rejected() + NewContestDialog + reject() + + + 224 + 294 + + + 224 + 159 + + + + +
diff --git a/newcontestwidget.cpp b/newcontestwidget.cpp index 45f6a36..bc77282 100644 --- a/newcontestwidget.cpp +++ b/newcontestwidget.cpp @@ -1,77 +1,77 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "newcontestwidget.h" -#include "ui_newcontestwidget.h" - -NewContestWidget::NewContestWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::NewContestWidget) -{ - ui->setupUi(this); - connect(ui->selectButton, SIGNAL(clicked()), - this, SLOT(selectContestPath())); - connect(ui->savingName, SIGNAL(textChanged(QString)), - this, SLOT(savingNameChanged())); - connect(ui->contestTitle, SIGNAL(textChanged(QString)), - this, SIGNAL(informationChanged())); - connect(ui->savingName, SIGNAL(textChanged(QString)), - this, SIGNAL(informationChanged())); - connect(ui->contestPath, SIGNAL(textChanged(QString)), - this, SIGNAL(informationChanged())); -} - -NewContestWidget::~NewContestWidget() -{ - delete ui; -} - -QString NewContestWidget::getContestTitle() -{ - return ui->contestTitle->text(); -} - -QString NewContestWidget::getSavingName() -{ - return ui->savingName->text(); -} - -QString NewContestWidget::getContestPath() -{ - return ui->contestPath->text(); -} - -bool NewContestWidget::checkReady() const -{ - return ! ui->contestTitle->text().isEmpty() && ! ui->contestPath->text().isEmpty() && ! ui->savingName->text().isEmpty(); -} - -void NewContestWidget::selectContestPath() -{ - QString path = QFileDialog::getExistingDirectory(this, tr("Select Contest Path"), QDir::homePath()); - if (! path.isEmpty()) ui->contestPath->setText(QDir::toNativeSeparators(path)); -} - -void NewContestWidget::savingNameChanged() -{ - QString path = QDir::homePath(); - path = QDir::toNativeSeparators(path); - path += QDir::separator(); - path += ui->savingName->text(); - ui->contestPath->setText(path); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "newcontestwidget.h" +#include "ui_newcontestwidget.h" + +NewContestWidget::NewContestWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::NewContestWidget) +{ + ui->setupUi(this); + connect(ui->selectButton, SIGNAL(clicked()), + this, SLOT(selectContestPath())); + connect(ui->savingName, SIGNAL(textChanged(QString)), + this, SLOT(savingNameChanged())); + connect(ui->contestTitle, SIGNAL(textChanged(QString)), + this, SIGNAL(informationChanged())); + connect(ui->savingName, SIGNAL(textChanged(QString)), + this, SIGNAL(informationChanged())); + connect(ui->contestPath, SIGNAL(textChanged(QString)), + this, SIGNAL(informationChanged())); +} + +NewContestWidget::~NewContestWidget() +{ + delete ui; +} + +QString NewContestWidget::getContestTitle() +{ + return ui->contestTitle->text(); +} + +QString NewContestWidget::getSavingName() +{ + return ui->savingName->text(); +} + +QString NewContestWidget::getContestPath() +{ + return ui->contestPath->text(); +} + +bool NewContestWidget::checkReady() const +{ + return ! ui->contestTitle->text().isEmpty() && ! ui->contestPath->text().isEmpty() && ! ui->savingName->text().isEmpty(); +} + +void NewContestWidget::selectContestPath() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Select Contest Path"), QDir::homePath()); + if (! path.isEmpty()) ui->contestPath->setText(QDir::toNativeSeparators(path)); +} + +void NewContestWidget::savingNameChanged() +{ + QString path = QDir::homePath(); + path = QDir::toNativeSeparators(path); + path += QDir::separator(); + path += ui->savingName->text(); + ui->contestPath->setText(path); +} diff --git a/newcontestwidget.h b/newcontestwidget.h index f24ce47..eb0dc3b 100644 --- a/newcontestwidget.h +++ b/newcontestwidget.h @@ -1,53 +1,53 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef NEWCONTESTWIDGET_H -#define NEWCONTESTWIDGET_H - -#include -#include -#include - -namespace Ui { - class NewContestWidget; -} - -class NewContestWidget : public QWidget -{ - Q_OBJECT - -public: - explicit NewContestWidget(QWidget *parent = 0); - ~NewContestWidget(); - QString getContestTitle(); - QString getSavingName(); - QString getContestPath(); - bool checkReady() const; - -private: - Ui::NewContestWidget *ui; - -signals: - void informationChanged(); - -private slots: - void selectContestPath(); - void savingNameChanged(); -}; - -#endif // NEWCONTESTWIDGET_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef NEWCONTESTWIDGET_H +#define NEWCONTESTWIDGET_H + +#include +#include +#include + +namespace Ui { + class NewContestWidget; +} + +class NewContestWidget : public QWidget +{ + Q_OBJECT + +public: + explicit NewContestWidget(QWidget *parent = 0); + ~NewContestWidget(); + QString getContestTitle(); + QString getSavingName(); + QString getContestPath(); + bool checkReady() const; + +private: + Ui::NewContestWidget *ui; + +signals: + void informationChanged(); + +private slots: + void selectContestPath(); + void savingNameChanged(); +}; + +#endif // NEWCONTESTWIDGET_H diff --git a/newcontestwidget.ui b/newcontestwidget.ui index 2c69165..594fb68 100644 --- a/newcontestwidget.ui +++ b/newcontestwidget.ui @@ -1,100 +1,100 @@ - - - NewContestWidget - - - - 0 - 0 - 392 - 290 - - - - Form - - - - - - 12 - - - 15 - - - - - font-size: 10pt; -font-weight: bold; - - - Contest Title - - - - - - - - - - font-size: 10pt; -font-weight: bold; - - - Saving Name - - - - - - - - - - font-size: 10pt; -font-weight: bold; - - - Contest Path - - - - - - - 10 - - - - - - - - ... - - - - - - - - - - - Qt::Vertical - - - - 20 - 168 - - - - - - - - - + + + NewContestWidget + + + + 0 + 0 + 392 + 290 + + + + Form + + + + + + 12 + + + 15 + + + + + font-size: 10pt; +font-weight: bold; + + + Contest Title + + + + + + + + + + font-size: 10pt; +font-weight: bold; + + + Saving Name + + + + + + + + + + font-size: 10pt; +font-weight: bold; + + + Contest Path + + + + + + + 10 + + + + + + + + ... + + + + + + + + + + + Qt::Vertical + + + + 20 + 168 + + + + + + + + + diff --git a/opencontestdialog.cpp b/opencontestdialog.cpp index 33a2b37..3751a65 100644 --- a/opencontestdialog.cpp +++ b/opencontestdialog.cpp @@ -1,60 +1,60 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "opencontestdialog.h" -#include "ui_opencontestdialog.h" - -OpenContestDialog::OpenContestDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::OpenContestDialog) -{ - ui->setupUi(this); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - connect(ui->openContestWidget, SIGNAL(selectionChanged()), - this, SLOT(selectionChanged())); - connect(ui->openContestWidget, SIGNAL(rowDoubleClicked()), - this, SLOT(accept())); -} - -OpenContestDialog::~OpenContestDialog() -{ - delete ui; -} - -void OpenContestDialog::setRecentContest(const QStringList &list) -{ - ui->openContestWidget->setRecentContest(list); -} - -void OpenContestDialog::selectionChanged() -{ - if (ui->openContestWidget->getCurrentRow() != -1) - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - else - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); -} - -const QStringList& OpenContestDialog::getRecentContest() const -{ - return ui->openContestWidget->getRecentContest(); -} - -QString OpenContestDialog::getSelectedContest() -{ - return ui->openContestWidget->getRecentContest().at(ui->openContestWidget->getCurrentRow()); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "opencontestdialog.h" +#include "ui_opencontestdialog.h" + +OpenContestDialog::OpenContestDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::OpenContestDialog) +{ + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + connect(ui->openContestWidget, SIGNAL(selectionChanged()), + this, SLOT(selectionChanged())); + connect(ui->openContestWidget, SIGNAL(rowDoubleClicked()), + this, SLOT(accept())); +} + +OpenContestDialog::~OpenContestDialog() +{ + delete ui; +} + +void OpenContestDialog::setRecentContest(const QStringList &list) +{ + ui->openContestWidget->setRecentContest(list); +} + +void OpenContestDialog::selectionChanged() +{ + if (ui->openContestWidget->getCurrentRow() != -1) + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + else + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); +} + +const QStringList& OpenContestDialog::getRecentContest() const +{ + return ui->openContestWidget->getRecentContest(); +} + +QString OpenContestDialog::getSelectedContest() +{ + return ui->openContestWidget->getRecentContest().at(ui->openContestWidget->getCurrentRow()); +} diff --git a/opencontestdialog.h b/opencontestdialog.h index 729ba68..5ed0fb8 100644 --- a/opencontestdialog.h +++ b/opencontestdialog.h @@ -1,48 +1,48 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef OPENCONTESTDIALOG_H -#define OPENCONTESTDIALOG_H - -#include -#include -#include - -namespace Ui { - class OpenContestDialog; -} - -class OpenContestDialog : public QDialog -{ - Q_OBJECT - -public: - explicit OpenContestDialog(QWidget *parent = 0); - ~OpenContestDialog(); - void setRecentContest(const QStringList&); - const QStringList& getRecentContest() const; - QString getSelectedContest(); - -private: - Ui::OpenContestDialog *ui; - -private slots: - void selectionChanged(); -}; - -#endif // OPENCONTESTDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef OPENCONTESTDIALOG_H +#define OPENCONTESTDIALOG_H + +#include +#include +#include + +namespace Ui { + class OpenContestDialog; +} + +class OpenContestDialog : public QDialog +{ + Q_OBJECT + +public: + explicit OpenContestDialog(QWidget *parent = 0); + ~OpenContestDialog(); + void setRecentContest(const QStringList&); + const QStringList& getRecentContest() const; + QString getSelectedContest(); + +private: + Ui::OpenContestDialog *ui; + +private slots: + void selectionChanged(); +}; + +#endif // OPENCONTESTDIALOG_H diff --git a/opencontestdialog.ui b/opencontestdialog.ui index 58faf3e..80526ef 100644 --- a/opencontestdialog.ui +++ b/opencontestdialog.ui @@ -1,78 +1,78 @@ - - - OpenContestDialog - - - - 0 - 0 - 450 - 320 - - - - - 450 - 320 - - - - Open an Existing Contest - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - OpenContestWidget - QWidget -
opencontestwidget.h
- 1 -
-
- - - - buttonBox - accepted() - OpenContestDialog - accept() - - - 224 - 294 - - - 224 - 159 - - - - - buttonBox - rejected() - OpenContestDialog - reject() - - - 224 - 294 - - - 224 - 159 - - - - -
+ + + OpenContestDialog + + + + 0 + 0 + 450 + 320 + + + + + 450 + 320 + + + + Open an Existing Contest + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + OpenContestWidget + QWidget +
opencontestwidget.h
+ 1 +
+
+ + + + buttonBox + accepted() + OpenContestDialog + accept() + + + 224 + 294 + + + 224 + 159 + + + + + buttonBox + rejected() + OpenContestDialog + reject() + + + 224 + 294 + + + 224 + 159 + + + + +
diff --git a/opencontestwidget.cpp b/opencontestwidget.cpp index 25faf14..5fa0aa7 100644 --- a/opencontestwidget.cpp +++ b/opencontestwidget.cpp @@ -1,125 +1,125 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "opencontestwidget.h" -#include "ui_opencontestwidget.h" -#include "contest.h" - -OpenContestWidget::OpenContestWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::OpenContestWidget) -{ - ui->setupUi(this); - connect(ui->recentContest, SIGNAL(itemSelectionChanged()), - this, SIGNAL(selectionChanged())); - connect(ui->recentContest, SIGNAL(cellDoubleClicked(int, int)), - this, SIGNAL(rowDoubleClicked())); - connect(ui->addButton, SIGNAL(clicked()), - this, SLOT(addContest())); - connect(ui->deleteButton, SIGNAL(clicked()), - this, SLOT(deleteContest())); - connect(ui->recentContest, SIGNAL(currentCellChanged(int,int,int,int)), - this, SLOT(currentRowChanged())); -} - -OpenContestWidget::~OpenContestWidget() -{ - delete ui; -} - -void OpenContestWidget::setRecentContest(const QStringList &list) -{ - recentContest = list; - refreshContestList(); -} - -void OpenContestWidget::refreshContestList() -{ - ui->recentContest->setRowCount(0); - for (int i = 0; i < recentContest.size(); ) { - QFile file(recentContest[i]); - if (! file.open(QFile::ReadOnly)) { - recentContest.removeAt(i); - continue; - } - QDataStream in(&file); - signed checkNumber; - in >> checkNumber; - if (checkNumber != signed(MagicNumber)) { - recentContest.removeAt(i); - continue; - } - QString title; - in >> title; - ui->recentContest->setRowCount(i + 1); - ui->recentContest->setItem(i, 0, new QTableWidgetItem(title)); - ui->recentContest->setItem(i, 1, new QTableWidgetItem(recentContest[i])); - ui->recentContest->item(i, 0)->setTextAlignment(Qt::AlignCenter); - i ++; - } - QHeaderView *header = ui->recentContest->horizontalHeader(); - header->setResizeMode(QHeaderView::ResizeToContents); -} - -void OpenContestWidget::addContest() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Add Contest"), QDir::homePath(), - tr("Lemon contest data file (*.cdf)")); - if (fileName.isEmpty()) return; - fileName = fileName.replace('/', QDir::separator()); - QFile file(fileName); - if (! file.open(QFile::ReadOnly)) { - QMessageBox::warning(this, tr("Error"), tr("Cannot open selected file"), QMessageBox::Close); - return; - } - QDataStream in(&file); - signed checkNumber; - in >> checkNumber; - if (checkNumber != signed(MagicNumber)) { - QMessageBox::warning(this, tr("Error"), tr("Broken contest data file"), QMessageBox::Close); - return; - } - recentContest.append(fileName); - refreshContestList(); -} - -void OpenContestWidget::deleteContest() -{ - int index = ui->recentContest->currentRow(); - recentContest.removeAt(index); - refreshContestList(); -} - -void OpenContestWidget::currentRowChanged() -{ - int index = ui->recentContest->currentRow(); - if (index != -1) - ui->deleteButton->setEnabled(true); - else - ui->deleteButton->setEnabled(false); -} - -const QStringList& OpenContestWidget::getRecentContest() const -{ - return recentContest; -} - -int OpenContestWidget::getCurrentRow() const -{ - return ui->recentContest->currentRow(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "opencontestwidget.h" +#include "ui_opencontestwidget.h" +#include "contest.h" + +OpenContestWidget::OpenContestWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::OpenContestWidget) +{ + ui->setupUi(this); + connect(ui->recentContest, SIGNAL(itemSelectionChanged()), + this, SIGNAL(selectionChanged())); + connect(ui->recentContest, SIGNAL(cellDoubleClicked(int, int)), + this, SIGNAL(rowDoubleClicked())); + connect(ui->addButton, SIGNAL(clicked()), + this, SLOT(addContest())); + connect(ui->deleteButton, SIGNAL(clicked()), + this, SLOT(deleteContest())); + connect(ui->recentContest, SIGNAL(currentCellChanged(int,int,int,int)), + this, SLOT(currentRowChanged())); +} + +OpenContestWidget::~OpenContestWidget() +{ + delete ui; +} + +void OpenContestWidget::setRecentContest(const QStringList &list) +{ + recentContest = list; + refreshContestList(); +} + +void OpenContestWidget::refreshContestList() +{ + ui->recentContest->setRowCount(0); + for (int i = 0; i < recentContest.size(); ) { + QFile file(recentContest[i]); + if (! file.open(QFile::ReadOnly)) { + recentContest.removeAt(i); + continue; + } + QDataStream in(&file); + signed checkNumber; + in >> checkNumber; + if (checkNumber != signed(MagicNumber)) { + recentContest.removeAt(i); + continue; + } + QString title; + in >> title; + ui->recentContest->setRowCount(i + 1); + ui->recentContest->setItem(i, 0, new QTableWidgetItem(title)); + ui->recentContest->setItem(i, 1, new QTableWidgetItem(recentContest[i])); + ui->recentContest->item(i, 0)->setTextAlignment(Qt::AlignCenter); + i ++; + } + QHeaderView *header = ui->recentContest->horizontalHeader(); + header->setResizeMode(QHeaderView::ResizeToContents); +} + +void OpenContestWidget::addContest() +{ + QString fileName = QFileDialog::getOpenFileName(this, tr("Add Contest"), QDir::homePath(), + tr("Lemon contest data file (*.cdf)")); + if (fileName.isEmpty()) return; + fileName = fileName.replace('/', QDir::separator()); + QFile file(fileName); + if (! file.open(QFile::ReadOnly)) { + QMessageBox::warning(this, tr("Error"), tr("Cannot open selected file"), QMessageBox::Close); + return; + } + QDataStream in(&file); + signed checkNumber; + in >> checkNumber; + if (checkNumber != signed(MagicNumber)) { + QMessageBox::warning(this, tr("Error"), tr("Broken contest data file"), QMessageBox::Close); + return; + } + recentContest.append(fileName); + refreshContestList(); +} + +void OpenContestWidget::deleteContest() +{ + int index = ui->recentContest->currentRow(); + recentContest.removeAt(index); + refreshContestList(); +} + +void OpenContestWidget::currentRowChanged() +{ + int index = ui->recentContest->currentRow(); + if (index != -1) + ui->deleteButton->setEnabled(true); + else + ui->deleteButton->setEnabled(false); +} + +const QStringList& OpenContestWidget::getRecentContest() const +{ + return recentContest; +} + +int OpenContestWidget::getCurrentRow() const +{ + return ui->recentContest->currentRow(); +} diff --git a/opencontestwidget.h b/opencontestwidget.h index 8574d2c..b52eaad 100644 --- a/opencontestwidget.h +++ b/opencontestwidget.h @@ -1,56 +1,56 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef OPENCONTESTWIDGET_H -#define OPENCONTESTWIDGET_H - -#include -#include -#include - -namespace Ui { - class OpenContestWidget; -} - -class OpenContestWidget : public QWidget -{ - Q_OBJECT - -public: - explicit OpenContestWidget(QWidget *parent = 0); - ~OpenContestWidget(); - void setRecentContest(const QStringList&); - const QStringList& getRecentContest() const; - int getCurrentRow() const; - -private: - Ui::OpenContestWidget *ui; - QStringList recentContest; - void refreshContestList(); - -private slots: - void addContest(); - void deleteContest(); - void currentRowChanged(); - -signals: - void selectionChanged(); - void rowDoubleClicked(); -}; - -#endif // OPENCONTESTWIDGET_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef OPENCONTESTWIDGET_H +#define OPENCONTESTWIDGET_H + +#include +#include +#include + +namespace Ui { + class OpenContestWidget; +} + +class OpenContestWidget : public QWidget +{ + Q_OBJECT + +public: + explicit OpenContestWidget(QWidget *parent = 0); + ~OpenContestWidget(); + void setRecentContest(const QStringList&); + const QStringList& getRecentContest() const; + int getCurrentRow() const; + +private: + Ui::OpenContestWidget *ui; + QStringList recentContest; + void refreshContestList(); + +private slots: + void addContest(); + void deleteContest(); + void currentRowChanged(); + +signals: + void selectionChanged(); + void rowDoubleClicked(); +}; + +#endif // OPENCONTESTWIDGET_H diff --git a/opencontestwidget.ui b/opencontestwidget.ui index dfbdbc1..d12e0f2 100644 --- a/opencontestwidget.ui +++ b/opencontestwidget.ui @@ -1,142 +1,142 @@ - - - OpenContestWidget - - - - 0 - 0 - 400 - 300 - - - - Form - - - - - - font-size: 9pt; - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - false - - - 80 - - - true - - - false - - - 25 - - - 25 - - - - Title - - - - 9 - 75 - true - - - - - - Location - - - - 9 - 75 - true - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 27 - 27 - - - - - :/icon/add.png:/icon/add.png - - - - - - - false - - - - 27 - 27 - - - - - :/icon/rod.png:/icon/rod.png - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - + + + OpenContestWidget + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + font-size: 9pt; + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + 80 + + + true + + + false + + + 25 + + + 25 + + + + Title + + + + 9 + 75 + true + + + + + + Location + + + + 9 + 75 + true + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 27 + 27 + + + + + :/icon/add.png:/icon/add.png + + + + + + + false + + + + 27 + 27 + + + + + :/icon/rod.png:/icon/rod.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + diff --git a/optionsdialog.cpp b/optionsdialog.cpp index 216b279..a27a88a 100644 --- a/optionsdialog.cpp +++ b/optionsdialog.cpp @@ -1,58 +1,58 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "optionsdialog.h" -#include "ui_optionsdialog.h" -#include "settings.h" - -OptionsDialog::OptionsDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::OptionsDialog) -{ - ui->setupUi(this); - editSettings = new Settings(this); - connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), - this, SLOT(okayButtonClicked())); -} - -OptionsDialog::~OptionsDialog() -{ - delete ui; -} - -Settings* OptionsDialog::getEditSettings() -{ - return editSettings; -} - -void OptionsDialog::resetEditSettings(Settings *settings) -{ - editSettings->copyFrom(settings); - ui->generalSettings->resetEditSettings(editSettings); - ui->compilerSettings->resetEditSettings(editSettings); - ui->tabWidget->setCurrentIndex(0); -} - -void OptionsDialog::okayButtonClicked() -{ - ui->tabWidget->setCurrentIndex(0); - if (! ui->generalSettings->checkValid()) return; - ui->tabWidget->setCurrentIndex(1); - if (! ui->compilerSettings->checkValid()) return; - accept(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "optionsdialog.h" +#include "ui_optionsdialog.h" +#include "settings.h" + +OptionsDialog::OptionsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::OptionsDialog) +{ + ui->setupUi(this); + editSettings = new Settings(this); + connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), + this, SLOT(okayButtonClicked())); +} + +OptionsDialog::~OptionsDialog() +{ + delete ui; +} + +Settings* OptionsDialog::getEditSettings() +{ + return editSettings; +} + +void OptionsDialog::resetEditSettings(Settings *settings) +{ + editSettings->copyFrom(settings); + ui->generalSettings->resetEditSettings(editSettings); + ui->compilerSettings->resetEditSettings(editSettings); + ui->tabWidget->setCurrentIndex(0); +} + +void OptionsDialog::okayButtonClicked() +{ + ui->tabWidget->setCurrentIndex(0); + if (! ui->generalSettings->checkValid()) return; + ui->tabWidget->setCurrentIndex(1); + if (! ui->compilerSettings->checkValid()) return; + accept(); +} diff --git a/optionsdialog.h b/optionsdialog.h index f13fd40..4e28be4 100644 --- a/optionsdialog.h +++ b/optionsdialog.h @@ -1,50 +1,50 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef OPTIONSDIALOG_H -#define OPTIONSDIALOG_H - -#include -#include -#include - -namespace Ui { - class OptionsDialog; -} - -class Settings; - -class OptionsDialog : public QDialog -{ - Q_OBJECT - -public: - explicit OptionsDialog(QWidget *parent = 0); - ~OptionsDialog(); - void resetEditSettings(Settings*); - Settings* getEditSettings(); - -private: - Ui::OptionsDialog *ui; - Settings *editSettings; - -private slots: - void okayButtonClicked(); -}; - -#endif // OPTIONSDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef OPTIONSDIALOG_H +#define OPTIONSDIALOG_H + +#include +#include +#include + +namespace Ui { + class OptionsDialog; +} + +class Settings; + +class OptionsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit OptionsDialog(QWidget *parent = 0); + ~OptionsDialog(); + void resetEditSettings(Settings*); + Settings* getEditSettings(); + +private: + Ui::OptionsDialog *ui; + Settings *editSettings; + +private slots: + void okayButtonClicked(); +}; + +#endif // OPTIONSDIALOG_H diff --git a/optionsdialog.ui b/optionsdialog.ui index ee258d1..320752f 100644 --- a/optionsdialog.ui +++ b/optionsdialog.ui @@ -1,88 +1,88 @@ - - - OptionsDialog - - - - 0 - 0 - 362 - 437 - - - - - 362 - 437 - - - - Options - - - - - - font-size: 9pt; - - - 0 - - - - General - - - - - Compiler - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - GeneralSettings - QWidget -
generalsettings.h
- 1 -
- - CompilerSettings - QWidget -
compilersettings.h
- 1 -
-
- - tabWidget - - - - - buttonBox - rejected() - OptionsDialog - reject() - - - 176 - 414 - - - 176 - 219 - - - - -
+ + + OptionsDialog + + + + 0 + 0 + 362 + 437 + + + + + 362 + 437 + + + + Options + + + + + + font-size: 9pt; + + + 0 + + + + General + + + + + Compiler + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + GeneralSettings + QWidget +
generalsettings.h
+ 1 +
+ + CompilerSettings + QWidget +
compilersettings.h
+ 1 +
+
+ + tabWidget + + + + + buttonBox + rejected() + OptionsDialog + reject() + + + 176 + 414 + + + 176 + 219 + + + + +
diff --git a/qtlockedfile/qtlockedfile.cpp b/qtlockedfile/qtlockedfile.cpp index 3e73ba6..8f4fa4f 100644 --- a/qtlockedfile/qtlockedfile.cpp +++ b/qtlockedfile/qtlockedfile.cpp @@ -1,192 +1,192 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - -#include "qtlockedfile.h" - -/*! - \class QtLockedFile - - \brief The QtLockedFile class extends QFile with advisory locking - functions. - - A file may be locked in read or write mode. Multiple instances of - \e QtLockedFile, created in multiple processes running on the same - machine, may have a file locked in read mode. Exactly one instance - may have it locked in write mode. A read and a write lock cannot - exist simultaneously on the same file. - - The file locks are advisory. This means that nothing prevents - another process from manipulating a locked file using QFile or - file system functions offered by the OS. Serialization is only - guaranteed if all processes that access the file use - QLockedFile. Also, while holding a lock on a file, a process - must not open the same file again (through any API), or locks - can be unexpectedly lost. - - The lock provided by an instance of \e QtLockedFile is released - whenever the program terminates. This is true even when the - program crashes and no destructors are called. -*/ - -/*! \enum QtLockedFile::LockMode - - This enum describes the available lock modes. - - \value ReadLock A read lock. - \value WriteLock A write lock. - \value NoLock Neither a read lock nor a write lock. -*/ - -/*! - Constructs an unlocked \e QtLockedFile object. This constructor - behaves in the same way as \e QFile::QFile(). - - \sa QFile::QFile() -*/ -QtLockedFile::QtLockedFile() - : QFile() -{ -#ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; -#endif - m_lock_mode = NoLock; -} - -/*! - Constructs an unlocked QtLockedFile object with file \a name. This - constructor behaves in the same way as \e QFile::QFile(const - QString&). - - \sa QFile::QFile() -*/ -QtLockedFile::QtLockedFile(const QString &name) - : QFile(name) -{ -#ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; -#endif - m_lock_mode = NoLock; -} - -/*! - Opens the file in OpenMode \a mode. - - This is identical to QFile::open(), with the one exception that the - Truncate mode flag is disallowed. Truncation would conflict with the - advisory file locking, since the file would be modified before the - write lock is obtained. If truncation is required, use resize(0) - after obtaining the write lock. - - Returns true if successful; otherwise false. - - \sa QFile::open(), QFile::resize() -*/ -bool QtLockedFile::open(OpenMode mode) -{ - if (mode & QIODevice::Truncate) { - qWarning("QtLockedFile::open(): Truncate mode not allowed."); - return false; - } - return QFile::open(mode); -} - -/*! - Returns \e true if this object has a in read or write lock; - otherwise returns \e false. - - \sa lockMode() -*/ -bool QtLockedFile::isLocked() const -{ - return m_lock_mode != NoLock; -} - -/*! - Returns the type of lock currently held by this object, or \e - QtLockedFile::NoLock. - - \sa isLocked() -*/ -QtLockedFile::LockMode QtLockedFile::lockMode() const -{ - return m_lock_mode; -} - -/*! - \fn bool QtLockedFile::lock(LockMode mode, bool block = true) - - Obtains a lock of type \a mode. The file must be opened before it - can be locked. - - If \a block is true, this function will block until the lock is - aquired. If \a block is false, this function returns \e false - immediately if the lock cannot be aquired. - - If this object already has a lock of type \a mode, this function - returns \e true immediately. If this object has a lock of a - different type than \a mode, the lock is first released and then a - new lock is obtained. - - This function returns \e true if, after it executes, the file is - locked by this object, and \e false otherwise. - - \sa unlock(), isLocked(), lockMode() -*/ - -/*! - \fn bool QtLockedFile::unlock() - - Releases a lock. - - If the object has no lock, this function returns immediately. - - This function returns \e true if, after it executes, the file is - not locked by this object, and \e false otherwise. - - \sa lock(), isLocked(), lockMode() -*/ - -/*! - \fn QtLockedFile::~QtLockedFile() - - Destroys the \e QtLockedFile object. If any locks were held, they - are released. -*/ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "qtlockedfile.h" + +/*! + \class QtLockedFile + + \brief The QtLockedFile class extends QFile with advisory locking + functions. + + A file may be locked in read or write mode. Multiple instances of + \e QtLockedFile, created in multiple processes running on the same + machine, may have a file locked in read mode. Exactly one instance + may have it locked in write mode. A read and a write lock cannot + exist simultaneously on the same file. + + The file locks are advisory. This means that nothing prevents + another process from manipulating a locked file using QFile or + file system functions offered by the OS. Serialization is only + guaranteed if all processes that access the file use + QLockedFile. Also, while holding a lock on a file, a process + must not open the same file again (through any API), or locks + can be unexpectedly lost. + + The lock provided by an instance of \e QtLockedFile is released + whenever the program terminates. This is true even when the + program crashes and no destructors are called. +*/ + +/*! \enum QtLockedFile::LockMode + + This enum describes the available lock modes. + + \value ReadLock A read lock. + \value WriteLock A write lock. + \value NoLock Neither a read lock nor a write lock. +*/ + +/*! + Constructs an unlocked \e QtLockedFile object. This constructor + behaves in the same way as \e QFile::QFile(). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile() + : QFile() +{ +#ifdef Q_OS_WIN + wmutex = 0; + rmutex = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Constructs an unlocked QtLockedFile object with file \a name. This + constructor behaves in the same way as \e QFile::QFile(const + QString&). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile(const QString &name) + : QFile(name) +{ +#ifdef Q_OS_WIN + wmutex = 0; + rmutex = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Opens the file in OpenMode \a mode. + + This is identical to QFile::open(), with the one exception that the + Truncate mode flag is disallowed. Truncation would conflict with the + advisory file locking, since the file would be modified before the + write lock is obtained. If truncation is required, use resize(0) + after obtaining the write lock. + + Returns true if successful; otherwise false. + + \sa QFile::open(), QFile::resize() +*/ +bool QtLockedFile::open(OpenMode mode) +{ + if (mode & QIODevice::Truncate) { + qWarning("QtLockedFile::open(): Truncate mode not allowed."); + return false; + } + return QFile::open(mode); +} + +/*! + Returns \e true if this object has a in read or write lock; + otherwise returns \e false. + + \sa lockMode() +*/ +bool QtLockedFile::isLocked() const +{ + return m_lock_mode != NoLock; +} + +/*! + Returns the type of lock currently held by this object, or \e + QtLockedFile::NoLock. + + \sa isLocked() +*/ +QtLockedFile::LockMode QtLockedFile::lockMode() const +{ + return m_lock_mode; +} + +/*! + \fn bool QtLockedFile::lock(LockMode mode, bool block = true) + + Obtains a lock of type \a mode. The file must be opened before it + can be locked. + + If \a block is true, this function will block until the lock is + aquired. If \a block is false, this function returns \e false + immediately if the lock cannot be aquired. + + If this object already has a lock of type \a mode, this function + returns \e true immediately. If this object has a lock of a + different type than \a mode, the lock is first released and then a + new lock is obtained. + + This function returns \e true if, after it executes, the file is + locked by this object, and \e false otherwise. + + \sa unlock(), isLocked(), lockMode() +*/ + +/*! + \fn bool QtLockedFile::unlock() + + Releases a lock. + + If the object has no lock, this function returns immediately. + + This function returns \e true if, after it executes, the file is + not locked by this object, and \e false otherwise. + + \sa lock(), isLocked(), lockMode() +*/ + +/*! + \fn QtLockedFile::~QtLockedFile() + + Destroys the \e QtLockedFile object. If any locks were held, they + are released. +*/ diff --git a/qtlockedfile/qtlockedfile.h b/qtlockedfile/qtlockedfile.h index 07a42bf..809575f 100644 --- a/qtlockedfile/qtlockedfile.h +++ b/qtlockedfile/qtlockedfile.h @@ -1,96 +1,96 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - -#ifndef QTLOCKEDFILE_H -#define QTLOCKEDFILE_H - -#include -#ifdef Q_OS_WIN -#include -#endif - -#if defined(Q_WS_WIN) -# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) -# define QT_QTLOCKEDFILE_EXPORT -# elif defined(QT_QTLOCKEDFILE_IMPORT) -# if defined(QT_QTLOCKEDFILE_EXPORT) -# undef QT_QTLOCKEDFILE_EXPORT -# endif -# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) -# elif defined(QT_QTLOCKEDFILE_EXPORT) -# undef QT_QTLOCKEDFILE_EXPORT -# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTLOCKEDFILE_EXPORT -#endif - -namespace QtLP_Private { - -class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile -{ -public: - enum LockMode { NoLock = 0, ReadLock, WriteLock }; - - QtLockedFile(); - QtLockedFile(const QString &name); - ~QtLockedFile(); - - bool open(OpenMode mode); - - bool lock(LockMode mode, bool block = true); - bool unlock(); - bool isLocked() const; - LockMode lockMode() const; - -private: -#ifdef Q_OS_WIN - Qt::HANDLE wmutex; - Qt::HANDLE rmutex; - QVector rmutexes; - QString mutexname; - - Qt::HANDLE getMutexHandle(int idx, bool doCreate); - bool waitMutex(Qt::HANDLE mutex, bool doBlock); - -#endif - LockMode m_lock_mode; -}; -} -#endif +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTLOCKEDFILE_H +#define QTLOCKEDFILE_H + +#include +#ifdef Q_OS_WIN +#include +#endif + +#if defined(Q_WS_WIN) +# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) +# define QT_QTLOCKEDFILE_EXPORT +# elif defined(QT_QTLOCKEDFILE_IMPORT) +# if defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# endif +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) +# elif defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTLOCKEDFILE_EXPORT +#endif + +namespace QtLP_Private { + +class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile +{ +public: + enum LockMode { NoLock = 0, ReadLock, WriteLock }; + + QtLockedFile(); + QtLockedFile(const QString &name); + ~QtLockedFile(); + + bool open(OpenMode mode); + + bool lock(LockMode mode, bool block = true); + bool unlock(); + bool isLocked() const; + LockMode lockMode() const; + +private: +#ifdef Q_OS_WIN + Qt::HANDLE wmutex; + Qt::HANDLE rmutex; + QVector rmutexes; + QString mutexname; + + Qt::HANDLE getMutexHandle(int idx, bool doCreate); + bool waitMutex(Qt::HANDLE mutex, bool doBlock); + +#endif + LockMode m_lock_mode; +}; +} +#endif diff --git a/qtlockedfile/qtlockedfile_unix.cpp b/qtlockedfile/qtlockedfile_unix.cpp index 715c7d9..fff0b06 100644 --- a/qtlockedfile/qtlockedfile_unix.cpp +++ b/qtlockedfile/qtlockedfile_unix.cpp @@ -1,114 +1,114 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - -#include -#include -#include -#include - -#include "qtlockedfile.h" - -bool QtLockedFile::lock(LockMode mode, bool block) -{ - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } - - if (mode == NoLock) - return unlock(); - - if (mode == m_lock_mode) - return true; - - if (m_lock_mode != NoLock) - unlock(); - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; - int cmd = block ? F_SETLKW : F_SETLK; - int ret = fcntl(handle(), cmd, &fl); - - if (ret == -1) { - if (errno != EINTR && errno != EAGAIN) - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } - - - m_lock_mode = mode; - return true; -} - - -bool QtLockedFile::unlock() -{ - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - int ret = fcntl(handle(), F_SETLKW, &fl); - - if (ret == -1) { - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } - - m_lock_mode = NoLock; - return true; -} - -QtLockedFile::~QtLockedFile() -{ - if (isOpen()) - unlock(); -} - +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "qtlockedfile.h" + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; + int cmd = block ? F_SETLKW : F_SETLK; + int ret = fcntl(handle(), cmd, &fl); + + if (ret == -1) { + if (errno != EINTR && errno != EAGAIN) + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + + m_lock_mode = mode; + return true; +} + + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_UNLCK; + int ret = fcntl(handle(), F_SETLKW, &fl); + + if (ret == -1) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + m_lock_mode = NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); +} + diff --git a/qtlockedfile/qtlockedfile_win.cpp b/qtlockedfile/qtlockedfile_win.cpp index 4cd2003..b1baf14 100644 --- a/qtlockedfile/qtlockedfile_win.cpp +++ b/qtlockedfile/qtlockedfile_win.cpp @@ -1,206 +1,206 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - -#include "qtlockedfile.h" -#include -#include - -#define MUTEX_PREFIX "QtLockedFile mutex " -// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS -#define MAX_READERS MAXIMUM_WAIT_OBJECTS - -Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) -{ - if (mutexname.isEmpty()) { - QFileInfo fi(*this); - mutexname = QString::fromLatin1(MUTEX_PREFIX) - + fi.absoluteFilePath().toLower(); - } - QString mname(mutexname); - if (idx >= 0) - mname += QString::number(idx); - - Qt::HANDLE mutex; - if (doCreate) { - QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, - { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); - return 0; - } - } - else { - QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, - { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) - qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); - return 0; - } - } - return mutex; -} - -bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) -{ - Q_ASSERT(mutex); - DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); - switch (res) { - case WAIT_OBJECT_0: - case WAIT_ABANDONED: - return true; - break; - case WAIT_TIMEOUT: - break; - default: - qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); - } - return false; -} - - - -bool QtLockedFile::lock(LockMode mode, bool block) -{ - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } - - if (mode == NoLock) - return unlock(); - - if (mode == m_lock_mode) - return true; - - if (m_lock_mode != NoLock) - unlock(); - - if (!wmutex && !(wmutex = getMutexHandle(-1, true))) - return false; - - if (!waitMutex(wmutex, block)) - return false; - - if (mode == ReadLock) { - int idx = 0; - for (; idx < MAX_READERS; idx++) { - rmutex = getMutexHandle(idx, false); - if (!rmutex || waitMutex(rmutex, false)) - break; - CloseHandle(rmutex); - } - bool ok = true; - if (idx >= MAX_READERS) { - qWarning("QtLockedFile::lock(): too many readers"); - rmutex = 0; - ok = false; - } - else if (!rmutex) { - rmutex = getMutexHandle(idx, true); - if (!rmutex || !waitMutex(rmutex, false)) - ok = false; - } - if (!ok && rmutex) { - CloseHandle(rmutex); - rmutex = 0; - } - ReleaseMutex(wmutex); - if (!ok) - return false; - } - else { - Q_ASSERT(rmutexes.isEmpty()); - for (int i = 0; i < MAX_READERS; i++) { - Qt::HANDLE mutex = getMutexHandle(i, false); - if (mutex) - rmutexes.append(mutex); - } - if (rmutexes.size()) { - DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), - TRUE, block ? INFINITE : 0); - if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { - if (res != WAIT_TIMEOUT) - qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); - m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky - unlock(); - return false; - } - } - } - - m_lock_mode = mode; - return true; -} - -bool QtLockedFile::unlock() -{ - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - if (m_lock_mode == ReadLock) { - ReleaseMutex(rmutex); - CloseHandle(rmutex); - rmutex = 0; - } - else { - foreach(Qt::HANDLE mutex, rmutexes) { - ReleaseMutex(mutex); - CloseHandle(mutex); - } - rmutexes.clear(); - ReleaseMutex(wmutex); - } - - m_lock_mode = QtLockedFile::NoLock; - return true; -} - -QtLockedFile::~QtLockedFile() -{ - if (isOpen()) - unlock(); - if (wmutex) - CloseHandle(wmutex); -} +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "qtlockedfile.h" +#include +#include + +#define MUTEX_PREFIX "QtLockedFile mutex " +// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS +#define MAX_READERS MAXIMUM_WAIT_OBJECTS + +Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) +{ + if (mutexname.isEmpty()) { + QFileInfo fi(*this); + mutexname = QString::fromLatin1(MUTEX_PREFIX) + + fi.absoluteFilePath().toLower(); + } + QString mname(mutexname); + if (idx >= 0) + mname += QString::number(idx); + + Qt::HANDLE mutex; + if (doCreate) { + QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); + if (!mutex) { + qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); + return 0; + } + } + else { + QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); + if (!mutex) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); + return 0; + } + } + return mutex; +} + +bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) +{ + Q_ASSERT(mutex); + DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); + switch (res) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return true; + break; + case WAIT_TIMEOUT: + break; + default: + qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); + } + return false; +} + + + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + if (!wmutex && !(wmutex = getMutexHandle(-1, true))) + return false; + + if (!waitMutex(wmutex, block)) + return false; + + if (mode == ReadLock) { + int idx = 0; + for (; idx < MAX_READERS; idx++) { + rmutex = getMutexHandle(idx, false); + if (!rmutex || waitMutex(rmutex, false)) + break; + CloseHandle(rmutex); + } + bool ok = true; + if (idx >= MAX_READERS) { + qWarning("QtLockedFile::lock(): too many readers"); + rmutex = 0; + ok = false; + } + else if (!rmutex) { + rmutex = getMutexHandle(idx, true); + if (!rmutex || !waitMutex(rmutex, false)) + ok = false; + } + if (!ok && rmutex) { + CloseHandle(rmutex); + rmutex = 0; + } + ReleaseMutex(wmutex); + if (!ok) + return false; + } + else { + Q_ASSERT(rmutexes.isEmpty()); + for (int i = 0; i < MAX_READERS; i++) { + Qt::HANDLE mutex = getMutexHandle(i, false); + if (mutex) + rmutexes.append(mutex); + } + if (rmutexes.size()) { + DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), + TRUE, block ? INFINITE : 0); + if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { + if (res != WAIT_TIMEOUT) + qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); + m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky + unlock(); + return false; + } + } + } + + m_lock_mode = mode; + return true; +} + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + if (m_lock_mode == ReadLock) { + ReleaseMutex(rmutex); + CloseHandle(rmutex); + rmutex = 0; + } + else { + foreach(Qt::HANDLE mutex, rmutexes) { + ReleaseMutex(mutex); + CloseHandle(mutex); + } + rmutexes.clear(); + ReleaseMutex(wmutex); + } + + m_lock_mode = QtLockedFile::NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); + if (wmutex) + CloseHandle(wmutex); +} diff --git a/qtsingleapplication/qtlocalpeer.cpp b/qtsingleapplication/qtlocalpeer.cpp index eb127ee..4ca6ab1 100644 --- a/qtsingleapplication/qtlocalpeer.cpp +++ b/qtsingleapplication/qtlocalpeer.cpp @@ -1,199 +1,199 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - - -#include "qtlocalpeer.h" -#include -#include - -#if defined(Q_OS_WIN) -#include -#include -typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); -static PProcessIdToSessionId pProcessIdToSessionId = 0; -#endif -#if defined(Q_OS_UNIX) -#include -#endif - -namespace QtLP_Private { -#include "qtlockedfile/qtlockedfile.cpp" -#if defined(Q_OS_WIN) -#include "qtlockedfile/qtlockedfile_win.cpp" -#else -#include "qtlockedfile/qtlockedfile_unix.cpp" -#endif -} - -const char* QtLocalPeer::ack = "ack"; - -QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) - : QObject(parent), id(appId) -{ - QString prefix = id; - if (id.isEmpty()) { - id = QCoreApplication::applicationFilePath(); -#if defined(Q_OS_WIN) - id = id.toLower(); -#endif - prefix = id.section(QLatin1Char('/'), -1); - } - prefix.remove(QRegExp("[^a-zA-Z]")); - prefix.truncate(6); - - QByteArray idc = id.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); - socketName = QLatin1String("qtsingleapp-") + prefix - + QLatin1Char('-') + QString::number(idNum, 16); - -#if defined(Q_OS_WIN) - if (!pProcessIdToSessionId) { - QLibrary lib("kernel32"); - pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); - } - if (pProcessIdToSessionId) { - DWORD sessionId = 0; - pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - socketName += QLatin1Char('-') + QString::number(sessionId, 16); - } -#else - socketName += QLatin1Char('-') + QString::number(::getuid(), 16); -#endif - - server = new QLocalServer(this); - QString lockName = QDir(QDir::tempPath()).absolutePath() - + QLatin1Char('/') + socketName - + QLatin1String("-lockfile"); - lockFile.setFileName(lockName); - lockFile.open(QIODevice::ReadWrite); -} - - - -bool QtLocalPeer::isClient() -{ - if (lockFile.isLocked()) - return false; - - if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) - return true; - - bool res = server->listen(socketName); -#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) - // ### Workaround - if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); - res = server->listen(socketName); - } -#endif - if (!res) - qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); - QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); - return false; -} - - -bool QtLocalPeer::sendMessage(const QString &message, int timeout) -{ - if (!isClient()) - return false; - - QLocalSocket socket; - bool connOk = false; - for(int i = 0; i < 2; i++) { - // Try twice, in case the other instance is just starting up - socket.connectToServer(socketName); - connOk = socket.waitForConnected(timeout/2); - if (connOk || i) - break; - int ms = 250; -#if defined(Q_OS_WIN) - Sleep(DWORD(ms)); -#else - struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; - nanosleep(&ts, NULL); -#endif - } - if (!connOk) - return false; - - QByteArray uMsg(message.toUtf8()); - QDataStream ds(&socket); - ds.writeBytes(uMsg.constData(), uMsg.size()); - bool res = socket.waitForBytesWritten(timeout); - if (res) { - res &= socket.waitForReadyRead(timeout); // wait for ack - if (res) - res &= (socket.read(qstrlen(ack)) == ack); - } - return res; -} - - -void QtLocalPeer::receiveConnection() -{ - QLocalSocket* socket = server->nextPendingConnection(); - if (!socket) - return; - - while (socket->bytesAvailable() < (int)sizeof(quint32)) - socket->waitForReadyRead(); - QDataStream ds(socket); - QByteArray uMsg; - quint32 remaining; - ds >> remaining; - uMsg.resize(remaining); - int got = 0; - char* uMsgBuf = uMsg.data(); - do { - got = ds.readRawData(uMsgBuf, remaining); - remaining -= got; - uMsgBuf += got; - } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); - if (got < 0) { - qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); - delete socket; - return; - } - QString message(QString::fromUtf8(uMsg)); - socket->write(ack, qstrlen(ack)); - socket->waitForBytesWritten(1000); - delete socket; - emit messageReceived(message); //### (might take a long time to return) -} +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "qtlocalpeer.h" +#include +#include + +#if defined(Q_OS_WIN) +#include +#include +typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); +static PProcessIdToSessionId pProcessIdToSessionId = 0; +#endif +#if defined(Q_OS_UNIX) +#include +#endif + +namespace QtLP_Private { +#include "qtlockedfile/qtlockedfile.cpp" +#if defined(Q_OS_WIN) +#include "qtlockedfile/qtlockedfile_win.cpp" +#else +#include "qtlockedfile/qtlockedfile_unix.cpp" +#endif +} + +const char* QtLocalPeer::ack = "ack"; + +QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) + : QObject(parent), id(appId) +{ + QString prefix = id; + if (id.isEmpty()) { + id = QCoreApplication::applicationFilePath(); +#if defined(Q_OS_WIN) + id = id.toLower(); +#endif + prefix = id.section(QLatin1Char('/'), -1); + } + prefix.remove(QRegExp("[^a-zA-Z]")); + prefix.truncate(6); + + QByteArray idc = id.toUtf8(); + quint16 idNum = qChecksum(idc.constData(), idc.size()); + socketName = QLatin1String("qtsingleapp-") + prefix + + QLatin1Char('-') + QString::number(idNum, 16); + +#if defined(Q_OS_WIN) + if (!pProcessIdToSessionId) { + QLibrary lib("kernel32"); + pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); + } + if (pProcessIdToSessionId) { + DWORD sessionId = 0; + pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + socketName += QLatin1Char('-') + QString::number(sessionId, 16); + } +#else + socketName += QLatin1Char('-') + QString::number(::getuid(), 16); +#endif + + server = new QLocalServer(this); + QString lockName = QDir(QDir::tempPath()).absolutePath() + + QLatin1Char('/') + socketName + + QLatin1String("-lockfile"); + lockFile.setFileName(lockName); + lockFile.open(QIODevice::ReadWrite); +} + + + +bool QtLocalPeer::isClient() +{ + if (lockFile.isLocked()) + return false; + + if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) + return true; + + bool res = server->listen(socketName); +#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) + // ### Workaround + if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { + QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); + res = server->listen(socketName); + } +#endif + if (!res) + qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); + QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); + return false; +} + + +bool QtLocalPeer::sendMessage(const QString &message, int timeout) +{ + if (!isClient()) + return false; + + QLocalSocket socket; + bool connOk = false; + for(int i = 0; i < 2; i++) { + // Try twice, in case the other instance is just starting up + socket.connectToServer(socketName); + connOk = socket.waitForConnected(timeout/2); + if (connOk || i) + break; + int ms = 250; +#if defined(Q_OS_WIN) + Sleep(DWORD(ms)); +#else + struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; + nanosleep(&ts, NULL); +#endif + } + if (!connOk) + return false; + + QByteArray uMsg(message.toUtf8()); + QDataStream ds(&socket); + ds.writeBytes(uMsg.constData(), uMsg.size()); + bool res = socket.waitForBytesWritten(timeout); + if (res) { + res &= socket.waitForReadyRead(timeout); // wait for ack + if (res) + res &= (socket.read(qstrlen(ack)) == ack); + } + return res; +} + + +void QtLocalPeer::receiveConnection() +{ + QLocalSocket* socket = server->nextPendingConnection(); + if (!socket) + return; + + while (socket->bytesAvailable() < (int)sizeof(quint32)) + socket->waitForReadyRead(); + QDataStream ds(socket); + QByteArray uMsg; + quint32 remaining; + ds >> remaining; + uMsg.resize(remaining); + int got = 0; + char* uMsgBuf = uMsg.data(); + do { + got = ds.readRawData(uMsgBuf, remaining); + remaining -= got; + uMsgBuf += got; + } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); + if (got < 0) { + qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); + delete socket; + return; + } + QString message(QString::fromUtf8(uMsg)); + socket->write(ack, qstrlen(ack)); + socket->waitForBytesWritten(1000); + delete socket; + emit messageReceived(message); //### (might take a long time to return) +} diff --git a/qtsingleapplication/qtlocalpeer.h b/qtsingleapplication/qtlocalpeer.h index 31d4c41..b0f8526 100644 --- a/qtsingleapplication/qtlocalpeer.h +++ b/qtsingleapplication/qtlocalpeer.h @@ -1,76 +1,76 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - -#ifndef QTLOCALPEER_H -#define QTLOCALPEER_H - -#include -#include -#include - -#include "qtlockedfile/qtlockedfile.h" - -class QtLocalPeer : public QObject -{ - Q_OBJECT - -public: - QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); - bool isClient(); - bool sendMessage(const QString &message, int timeout); - QString applicationId() const - { return id; } - -Q_SIGNALS: - void messageReceived(const QString &message); - -protected Q_SLOTS: - void receiveConnection(); - -protected: - QString id; - QString socketName; - QLocalServer* server; - QtLP_Private::QtLockedFile lockFile; - -private: - static const char* ack; -}; - -#endif // QTLOCALPEER_H +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTLOCALPEER_H +#define QTLOCALPEER_H + +#include +#include +#include + +#include "qtlockedfile/qtlockedfile.h" + +class QtLocalPeer : public QObject +{ + Q_OBJECT + +public: + QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); + bool isClient(); + bool sendMessage(const QString &message, int timeout); + QString applicationId() const + { return id; } + +Q_SIGNALS: + void messageReceived(const QString &message); + +protected Q_SLOTS: + void receiveConnection(); + +protected: + QString id; + QString socketName; + QLocalServer* server; + QtLP_Private::QtLockedFile lockFile; + +private: + static const char* ack; +}; + +#endif // QTLOCALPEER_H diff --git a/qtsingleapplication/qtsingleapplication.cpp b/qtsingleapplication/qtsingleapplication.cpp index 5a8f1b0..a748ebe 100644 --- a/qtsingleapplication/qtsingleapplication.cpp +++ b/qtsingleapplication/qtsingleapplication.cpp @@ -1,344 +1,344 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - - -#include "qtsingleapplication.h" -#include "qtlocalpeer.h" -#include - - -/*! - \class QtSingleApplication qtsingleapplication.h - \brief The QtSingleApplication class provides an API to detect and - communicate with running instances of an application. - - This class allows you to create applications where only one - instance should be running at a time. I.e., if the user tries to - launch another instance, the already running instance will be - activated instead. Another usecase is a client-server system, - where the first started instance will assume the role of server, - and the later instances will act as clients of that server. - - By default, the full path of the executable file is used to - determine whether two processes are instances of the same - application. You can also provide an explicit identifier string - that will be compared instead. - - The application should create the QtSingleApplication object early - in the startup phase, and call isRunning() to find out if another - instance of this application is already running. If isRunning() - returns false, it means that no other instance is running, and - this instance has assumed the role as the running instance. In - this case, the application should continue with the initialization - of the application user interface before entering the event loop - with exec(), as normal. - - The messageReceived() signal will be emitted when the running - application receives messages from another instance of the same - application. When a message is received it might be helpful to the - user to raise the application so that it becomes visible. To - facilitate this, QtSingleApplication provides the - setActivationWindow() function and the activateWindow() slot. - - If isRunning() returns true, another instance is already - running. It may be alerted to the fact that another instance has - started by using the sendMessage() function. Also data such as - startup parameters (e.g. the name of the file the user wanted this - new instance to open) can be passed to the running instance with - this function. Then, the application should terminate (or enter - client mode). - - If isRunning() returns true, but sendMessage() fails, that is an - indication that the running instance is frozen. - - Here's an example that shows how to convert an existing - application to use QtSingleApplication. It is very simple and does - not make use of all QtSingleApplication's functionality (see the - examples for that). - - \code - // Original - int main(int argc, char **argv) - { - QApplication app(argc, argv); - - MyMainWidget mmw; - mmw.show(); - return app.exec(); - } - - // Single instance - int main(int argc, char **argv) - { - QtSingleApplication app(argc, argv); - - if (app.isRunning()) - return !app.sendMessage(someDataString); - - MyMainWidget mmw; - app.setActivationWindow(&mmw); - mmw.show(); - return app.exec(); - } - \endcode - - Once this QtSingleApplication instance is destroyed (normally when - the process exits or crashes), when the user next attempts to run the - application this instance will not, of course, be encountered. The - next instance to call isRunning() or sendMessage() will assume the - role as the new running instance. - - For console (non-GUI) applications, QtSingleCoreApplication may be - used instead of this class, to avoid the dependency on the QtGui - library. - - \sa QtSingleCoreApplication -*/ - - -void QtSingleApplication::sysInit(const QString &appId) -{ - actWin = 0; - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -} - - -/*! - Creates a QtSingleApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc, \a - argv, and \a GUIenabled are passed on to the QAppliation constructor. - - If you are creating a console application (i.e. setting \a - GUIenabled to false), you may consider using - QtSingleCoreApplication instead. -*/ - -QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) - : QApplication(argc, argv, GUIenabled) -{ - sysInit(); -} - - -/*! - Creates a QtSingleApplication object with the application - identifier \a appId. \a argc and \a argv are passed on to the - QAppliation constructor. -*/ - -QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) - : QApplication(argc, argv) -{ - sysInit(appId); -} - - -/*! - Creates a QtSingleApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc, \a - argv, and \a type are passed on to the QAppliation constructor. -*/ -QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) - : QApplication(argc, argv, type) -{ - sysInit(); -} - - -#if defined(Q_WS_X11) -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, - and \a cmap are passed on to the QApplication constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be \a appId. \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(appId); -} -#endif - - -/*! - Returns true if another instance of this application is running; - otherwise false. - - This function does not find instances of this application that are - being run by a different user (on Windows: that are running in - another session). - - \sa sendMessage() -*/ - -bool QtSingleApplication::isRunning() -{ - return peer->isClient(); -} - - -/*! - Tries to send the text \a message to the currently running - instance. The QtSingleApplication object in the running instance - will emit the messageReceived() signal when it receives the - message. - - This function returns true if the message has been sent to, and - processed by, the current instance. If there is no instance - currently running, or if the running instance fails to process the - message within \a timeout milliseconds, this function return false. - - \sa isRunning(), messageReceived() -*/ -bool QtSingleApplication::sendMessage(const QString &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - - -/*! - Returns the application identifier. Two processes with the same - identifier will be regarded as instances of the same application. -*/ -QString QtSingleApplication::id() const -{ - return peer->applicationId(); -} - - -/*! - Sets the activation window of this application to \a aw. The - activation window is the widget that will be activated by - activateWindow(). This is typically the application's main window. - - If \a activateOnMessage is true (the default), the window will be - activated automatically every time a message is received, just prior - to the messageReceived() signal being emitted. - - \sa activateWindow(), messageReceived() -*/ - -void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) -{ - actWin = aw; - if (activateOnMessage) - connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); - else - disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); -} - - -/*! - Returns the applications activation window if one has been set by - calling setActivationWindow(), otherwise returns 0. - - \sa setActivationWindow() -*/ -QWidget* QtSingleApplication::activationWindow() const -{ - return actWin; -} - - -/*! - De-minimizes, raises, and activates this application's activation window. - This function does nothing if no activation window has been set. - - This is a convenience function to show the user that this - application instance has been activated when he has tried to start - another instance. - - This function should typically be called in response to the - messageReceived() signal. By default, that will happen - automatically, if an activation window has been set. - - \sa setActivationWindow(), messageReceived(), initialize() -*/ -void QtSingleApplication::activateWindow() -{ - if (actWin) { - actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); - actWin->raise(); - actWin->activateWindow(); - } -} - - -/*! - \fn void QtSingleApplication::messageReceived(const QString& message) - - This signal is emitted when the current instance receives a \a - message from another instance of this application. - - \sa sendMessage(), setActivationWindow(), activateWindow() -*/ - - -/*! - \fn void QtSingleApplication::initialize(bool dummy = true) - - \obsolete -*/ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "qtsingleapplication.h" +#include "qtlocalpeer.h" +#include + + +/*! + \class QtSingleApplication qtsingleapplication.h + \brief The QtSingleApplication class provides an API to detect and + communicate with running instances of an application. + + This class allows you to create applications where only one + instance should be running at a time. I.e., if the user tries to + launch another instance, the already running instance will be + activated instead. Another usecase is a client-server system, + where the first started instance will assume the role of server, + and the later instances will act as clients of that server. + + By default, the full path of the executable file is used to + determine whether two processes are instances of the same + application. You can also provide an explicit identifier string + that will be compared instead. + + The application should create the QtSingleApplication object early + in the startup phase, and call isRunning() to find out if another + instance of this application is already running. If isRunning() + returns false, it means that no other instance is running, and + this instance has assumed the role as the running instance. In + this case, the application should continue with the initialization + of the application user interface before entering the event loop + with exec(), as normal. + + The messageReceived() signal will be emitted when the running + application receives messages from another instance of the same + application. When a message is received it might be helpful to the + user to raise the application so that it becomes visible. To + facilitate this, QtSingleApplication provides the + setActivationWindow() function and the activateWindow() slot. + + If isRunning() returns true, another instance is already + running. It may be alerted to the fact that another instance has + started by using the sendMessage() function. Also data such as + startup parameters (e.g. the name of the file the user wanted this + new instance to open) can be passed to the running instance with + this function. Then, the application should terminate (or enter + client mode). + + If isRunning() returns true, but sendMessage() fails, that is an + indication that the running instance is frozen. + + Here's an example that shows how to convert an existing + application to use QtSingleApplication. It is very simple and does + not make use of all QtSingleApplication's functionality (see the + examples for that). + + \code + // Original + int main(int argc, char **argv) + { + QApplication app(argc, argv); + + MyMainWidget mmw; + mmw.show(); + return app.exec(); + } + + // Single instance + int main(int argc, char **argv) + { + QtSingleApplication app(argc, argv); + + if (app.isRunning()) + return !app.sendMessage(someDataString); + + MyMainWidget mmw; + app.setActivationWindow(&mmw); + mmw.show(); + return app.exec(); + } + \endcode + + Once this QtSingleApplication instance is destroyed (normally when + the process exits or crashes), when the user next attempts to run the + application this instance will not, of course, be encountered. The + next instance to call isRunning() or sendMessage() will assume the + role as the new running instance. + + For console (non-GUI) applications, QtSingleCoreApplication may be + used instead of this class, to avoid the dependency on the QtGui + library. + + \sa QtSingleCoreApplication +*/ + + +void QtSingleApplication::sysInit(const QString &appId) +{ + actWin = 0; + peer = new QtLocalPeer(this, appId); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +/*! + Creates a QtSingleApplication object. The application identifier + will be QCoreApplication::applicationFilePath(). \a argc, \a + argv, and \a GUIenabled are passed on to the QAppliation constructor. + + If you are creating a console application (i.e. setting \a + GUIenabled to false), you may consider using + QtSingleCoreApplication instead. +*/ + +QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) + : QApplication(argc, argv, GUIenabled) +{ + sysInit(); +} + + +/*! + Creates a QtSingleApplication object with the application + identifier \a appId. \a argc and \a argv are passed on to the + QAppliation constructor. +*/ + +QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) + : QApplication(argc, argv) +{ + sysInit(appId); +} + + +/*! + Creates a QtSingleApplication object. The application identifier + will be QCoreApplication::applicationFilePath(). \a argc, \a + argv, and \a type are passed on to the QAppliation constructor. +*/ +QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) + : QApplication(argc, argv, type) +{ + sysInit(); +} + + +#if defined(Q_WS_X11) +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, + and \a cmap are passed on to the QApplication constructor. +*/ +QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, visual, cmap) +{ + sysInit(); +} + +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. +*/ +QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, argc, argv, visual, cmap) +{ + sysInit(); +} + +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be \a appId. \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. +*/ +QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, argc, argv, visual, cmap) +{ + sysInit(appId); +} +#endif + + +/*! + Returns true if another instance of this application is running; + otherwise false. + + This function does not find instances of this application that are + being run by a different user (on Windows: that are running in + another session). + + \sa sendMessage() +*/ + +bool QtSingleApplication::isRunning() +{ + return peer->isClient(); +} + + +/*! + Tries to send the text \a message to the currently running + instance. The QtSingleApplication object in the running instance + will emit the messageReceived() signal when it receives the + message. + + This function returns true if the message has been sent to, and + processed by, the current instance. If there is no instance + currently running, or if the running instance fails to process the + message within \a timeout milliseconds, this function return false. + + \sa isRunning(), messageReceived() +*/ +bool QtSingleApplication::sendMessage(const QString &message, int timeout) +{ + return peer->sendMessage(message, timeout); +} + + +/*! + Returns the application identifier. Two processes with the same + identifier will be regarded as instances of the same application. +*/ +QString QtSingleApplication::id() const +{ + return peer->applicationId(); +} + + +/*! + Sets the activation window of this application to \a aw. The + activation window is the widget that will be activated by + activateWindow(). This is typically the application's main window. + + If \a activateOnMessage is true (the default), the window will be + activated automatically every time a message is received, just prior + to the messageReceived() signal being emitted. + + \sa activateWindow(), messageReceived() +*/ + +void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) +{ + actWin = aw; + if (activateOnMessage) + connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); + else + disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); +} + + +/*! + Returns the applications activation window if one has been set by + calling setActivationWindow(), otherwise returns 0. + + \sa setActivationWindow() +*/ +QWidget* QtSingleApplication::activationWindow() const +{ + return actWin; +} + + +/*! + De-minimizes, raises, and activates this application's activation window. + This function does nothing if no activation window has been set. + + This is a convenience function to show the user that this + application instance has been activated when he has tried to start + another instance. + + This function should typically be called in response to the + messageReceived() signal. By default, that will happen + automatically, if an activation window has been set. + + \sa setActivationWindow(), messageReceived(), initialize() +*/ +void QtSingleApplication::activateWindow() +{ + if (actWin) { + actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); + actWin->raise(); + actWin->activateWindow(); + } +} + + +/*! + \fn void QtSingleApplication::messageReceived(const QString& message) + + This signal is emitted when the current instance receives a \a + message from another instance of this application. + + \sa sendMessage(), setActivationWindow(), activateWindow() +*/ + + +/*! + \fn void QtSingleApplication::initialize(bool dummy = true) + + \obsolete +*/ diff --git a/qtsingleapplication/qtsingleapplication.h b/qtsingleapplication/qtsingleapplication.h index d1613a4..246e886 100644 --- a/qtsingleapplication/qtsingleapplication.h +++ b/qtsingleapplication/qtsingleapplication.h @@ -1,102 +1,102 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - -#ifndef QTSINGLEAPPLICATION_H -#define QTSINGLEAPPLICATION_H - -#include - -class QtLocalPeer; - -#if defined(Q_WS_WIN) -# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) -# define QT_QTSINGLEAPPLICATION_EXPORT -# elif defined(QT_QTSINGLEAPPLICATION_IMPORT) -# if defined(QT_QTSINGLEAPPLICATION_EXPORT) -# undef QT_QTSINGLEAPPLICATION_EXPORT -# endif -# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) -# elif defined(QT_QTSINGLEAPPLICATION_EXPORT) -# undef QT_QTSINGLEAPPLICATION_EXPORT -# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTSINGLEAPPLICATION_EXPORT -#endif - -class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication -{ - Q_OBJECT - -public: - QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); - QtSingleApplication(const QString &id, int &argc, char **argv); - QtSingleApplication(int &argc, char **argv, Type type); -#if defined(Q_WS_X11) - QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); - QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); - QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); -#endif - - bool isRunning(); - QString id() const; - - void setActivationWindow(QWidget* aw, bool activateOnMessage = true); - QWidget* activationWindow() const; - - // Obsolete: - void initialize(bool dummy = true) - { isRunning(); Q_UNUSED(dummy) } - -public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); - void activateWindow(); - - -Q_SIGNALS: - void messageReceived(const QString &message); - - -private: - void sysInit(const QString &appId = QString()); - QtLocalPeer *peer; - QWidget *actWin; -}; - -#endif // QTSINGLEAPPLICATION_H +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTSINGLEAPPLICATION_H +#define QTSINGLEAPPLICATION_H + +#include + +class QtLocalPeer; + +#if defined(Q_WS_WIN) +# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) +# define QT_QTSINGLEAPPLICATION_EXPORT +# elif defined(QT_QTSINGLEAPPLICATION_IMPORT) +# if defined(QT_QTSINGLEAPPLICATION_EXPORT) +# undef QT_QTSINGLEAPPLICATION_EXPORT +# endif +# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) +# elif defined(QT_QTSINGLEAPPLICATION_EXPORT) +# undef QT_QTSINGLEAPPLICATION_EXPORT +# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTSINGLEAPPLICATION_EXPORT +#endif + +class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication +{ + Q_OBJECT + +public: + QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); + QtSingleApplication(const QString &id, int &argc, char **argv); + QtSingleApplication(int &argc, char **argv, Type type); +#if defined(Q_WS_X11) + QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); + QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); + QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); +#endif + + bool isRunning(); + QString id() const; + + void setActivationWindow(QWidget* aw, bool activateOnMessage = true); + QWidget* activationWindow() const; + + // Obsolete: + void initialize(bool dummy = true) + { isRunning(); Q_UNUSED(dummy) } + +public Q_SLOTS: + bool sendMessage(const QString &message, int timeout = 5000); + void activateWindow(); + + +Q_SIGNALS: + void messageReceived(const QString &message); + + +private: + void sysInit(const QString &appId = QString()); + QtLocalPeer *peer; + QWidget *actWin; +}; + +#endif // QTSINGLEAPPLICATION_H diff --git a/qtsingleapplication/qtsinglecoreapplication.cpp b/qtsingleapplication/qtsinglecoreapplication.cpp index cf60771..8646873 100644 --- a/qtsingleapplication/qtsinglecoreapplication.cpp +++ b/qtsingleapplication/qtsinglecoreapplication.cpp @@ -1,148 +1,148 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - - -#include "qtsinglecoreapplication.h" -#include "qtlocalpeer.h" - -/*! - \class QtSingleCoreApplication qtsinglecoreapplication.h - \brief A variant of the QtSingleApplication class for non-GUI applications. - - This class is a variant of QtSingleApplication suited for use in - console (non-GUI) applications. It is an extension of - QCoreApplication (instead of QApplication). It does not require - the QtGui library. - - The API and usage is identical to QtSingleApplication, except that - functions relating to the "activation window" are not present, for - obvious reasons. Please refer to the QtSingleApplication - documentation for explanation of the usage. - - A QtSingleCoreApplication instance can communicate to a - QtSingleApplication instance if they share the same application - id. Hence, this class can be used to create a light-weight - command-line tool that sends commands to a GUI application. - - \sa QtSingleApplication -*/ - -/*! - Creates a QtSingleCoreApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc and \a - argv are passed on to the QCoreAppliation constructor. -*/ - -QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) - : QCoreApplication(argc, argv) -{ - peer = new QtLocalPeer(this); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -} - - -/*! - Creates a QtSingleCoreApplication object with the application - identifier \a appId. \a argc and \a argv are passed on to the - QCoreAppliation constructor. -*/ -QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) - : QCoreApplication(argc, argv) -{ - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -} - - -/*! - Returns true if another instance of this application is running; - otherwise false. - - This function does not find instances of this application that are - being run by a different user (on Windows: that are running in - another session). - - \sa sendMessage() -*/ - -bool QtSingleCoreApplication::isRunning() -{ - return peer->isClient(); -} - - -/*! - Tries to send the text \a message to the currently running - instance. The QtSingleCoreApplication object in the running instance - will emit the messageReceived() signal when it receives the - message. - - This function returns true if the message has been sent to, and - processed by, the current instance. If there is no instance - currently running, or if the running instance fails to process the - message within \a timeout milliseconds, this function return false. - - \sa isRunning(), messageReceived() -*/ - -bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - - -/*! - Returns the application identifier. Two processes with the same - identifier will be regarded as instances of the same application. -*/ - -QString QtSingleCoreApplication::id() const -{ - return peer->applicationId(); -} - - -/*! - \fn void QtSingleCoreApplication::messageReceived(const QString& message) - - This signal is emitted when the current instance receives a \a - message from another instance of this application. - - \sa sendMessage() -*/ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "qtsinglecoreapplication.h" +#include "qtlocalpeer.h" + +/*! + \class QtSingleCoreApplication qtsinglecoreapplication.h + \brief A variant of the QtSingleApplication class for non-GUI applications. + + This class is a variant of QtSingleApplication suited for use in + console (non-GUI) applications. It is an extension of + QCoreApplication (instead of QApplication). It does not require + the QtGui library. + + The API and usage is identical to QtSingleApplication, except that + functions relating to the "activation window" are not present, for + obvious reasons. Please refer to the QtSingleApplication + documentation for explanation of the usage. + + A QtSingleCoreApplication instance can communicate to a + QtSingleApplication instance if they share the same application + id. Hence, this class can be used to create a light-weight + command-line tool that sends commands to a GUI application. + + \sa QtSingleApplication +*/ + +/*! + Creates a QtSingleCoreApplication object. The application identifier + will be QCoreApplication::applicationFilePath(). \a argc and \a + argv are passed on to the QCoreAppliation constructor. +*/ + +QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) + : QCoreApplication(argc, argv) +{ + peer = new QtLocalPeer(this); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +/*! + Creates a QtSingleCoreApplication object with the application + identifier \a appId. \a argc and \a argv are passed on to the + QCoreAppliation constructor. +*/ +QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) + : QCoreApplication(argc, argv) +{ + peer = new QtLocalPeer(this, appId); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +/*! + Returns true if another instance of this application is running; + otherwise false. + + This function does not find instances of this application that are + being run by a different user (on Windows: that are running in + another session). + + \sa sendMessage() +*/ + +bool QtSingleCoreApplication::isRunning() +{ + return peer->isClient(); +} + + +/*! + Tries to send the text \a message to the currently running + instance. The QtSingleCoreApplication object in the running instance + will emit the messageReceived() signal when it receives the + message. + + This function returns true if the message has been sent to, and + processed by, the current instance. If there is no instance + currently running, or if the running instance fails to process the + message within \a timeout milliseconds, this function return false. + + \sa isRunning(), messageReceived() +*/ + +bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) +{ + return peer->sendMessage(message, timeout); +} + + +/*! + Returns the application identifier. Two processes with the same + identifier will be regarded as instances of the same application. +*/ + +QString QtSingleCoreApplication::id() const +{ + return peer->applicationId(); +} + + +/*! + \fn void QtSingleCoreApplication::messageReceived(const QString& message) + + This signal is emitted when the current instance receives a \a + message from another instance of this application. + + \sa sendMessage() +*/ diff --git a/qtsingleapplication/qtsinglecoreapplication.h b/qtsingleapplication/qtsinglecoreapplication.h index 7cde4b8..581e481 100644 --- a/qtsingleapplication/qtsinglecoreapplication.h +++ b/qtsingleapplication/qtsinglecoreapplication.h @@ -1,70 +1,70 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -****************************************************************************/ - -#ifndef QTSINGLECOREAPPLICATION_H -#define QTSINGLECOREAPPLICATION_H - -#include - -class QtLocalPeer; - -class QtSingleCoreApplication : public QCoreApplication -{ - Q_OBJECT - -public: - QtSingleCoreApplication(int &argc, char **argv); - QtSingleCoreApplication(const QString &id, int &argc, char **argv); - - bool isRunning(); - QString id() const; - -public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); - - -Q_SIGNALS: - void messageReceived(const QString &message); - - -private: - QtLocalPeer* peer; -}; - -#endif // QTSINGLECOREAPPLICATION_H +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTSINGLECOREAPPLICATION_H +#define QTSINGLECOREAPPLICATION_H + +#include + +class QtLocalPeer; + +class QtSingleCoreApplication : public QCoreApplication +{ + Q_OBJECT + +public: + QtSingleCoreApplication(int &argc, char **argv); + QtSingleCoreApplication(const QString &id, int &argc, char **argv); + + bool isRunning(); + QString id() const; + +public Q_SLOTS: + bool sendMessage(const QString &message, int timeout = 5000); + + +Q_SIGNALS: + void messageReceived(const QString &message); + + +private: + QtLocalPeer* peer; +}; + +#endif // QTSINGLECOREAPPLICATION_H diff --git a/realjudge.c b/realjudge.c index 574b2ab..4792497 100644 --- a/realjudge.c +++ b/realjudge.c @@ -1,81 +1,81 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include -#include - -int main(int argc, char **argv) { - FILE *contestantOutputFile = fopen(argv[1], "r"); - if (contestantOutputFile == NULL) { - printf("Cannot open contestant\'s output file\n"); - return; - } - FILE *standardOutputFile = fopen(argv[2], "r"); - if (standardOutputFile == NULL) { - printf("Cannot open standard output file\n"); - fclose(contestantOutputFile); - return; - } - - int realPrecision, i; - sscanf(argv[3], "%d", &realPrecision); - double eps = 1; - for (i = 0; i < realPrecision; i ++) - eps *= 0.1; - - double a, b; - while (1) { - int cnt1 = fscanf(contestantOutputFile, "%lf", &a); - int cnt2 = fscanf(standardOutputFile, "%lf", &b); - if (cnt1 == 0) { - printf("Wrong answer\nInvalid characters found\n"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (cnt2 == 0) { - printf("Invalid characters in standard output file\n"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (cnt1 == EOF && cnt2 == EOF) break; - if (cnt1 == EOF && cnt2 == 1) { - printf("Wrong answer\nShorter than standard output\n"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (cnt1 == 1 && cnt2 == EOF) { - printf("Wrong answer\nLonger than standard output\n"); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - if (fabs(a - b) > eps) { - printf("Wrong answer\nRead %.10lf but expect %.10lf\n", a, b); - fclose(contestantOutputFile); - fclose(standardOutputFile); - return; - } - } - - printf("Correct answer\n"); - fclose(contestantOutputFile); - fclose(standardOutputFile); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include +#include + +int main(int argc, char **argv) { + FILE *contestantOutputFile = fopen(argv[1], "r"); + if (contestantOutputFile == NULL) { + printf("Cannot open contestant\'s output file\n"); + return; + } + FILE *standardOutputFile = fopen(argv[2], "r"); + if (standardOutputFile == NULL) { + printf("Cannot open standard output file\n"); + fclose(contestantOutputFile); + return; + } + + int realPrecision, i; + sscanf(argv[3], "%d", &realPrecision); + double eps = 1; + for (i = 0; i < realPrecision; i ++) + eps *= 0.1; + + double a, b; + while (1) { + int cnt1 = fscanf(contestantOutputFile, "%lf", &a); + int cnt2 = fscanf(standardOutputFile, "%lf", &b); + if (cnt1 == 0) { + printf("Wrong answer\nInvalid characters found\n"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (cnt2 == 0) { + printf("Invalid characters in standard output file\n"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (cnt1 == EOF && cnt2 == EOF) break; + if (cnt1 == EOF && cnt2 == 1) { + printf("Wrong answer\nShorter than standard output\n"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (cnt1 == 1 && cnt2 == EOF) { + printf("Wrong answer\nLonger than standard output\n"); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + if (fabs(a - b) > eps) { + printf("Wrong answer\nRead %.10lf but expect %.10lf\n", a, b); + fclose(contestantOutputFile); + fclose(standardOutputFile); + return; + } + } + + printf("Correct answer\n"); + fclose(contestantOutputFile); + fclose(standardOutputFile); +} diff --git a/resource.qrc b/resource.qrc index e67374a..92ffb26 100644 --- a/resource.qrc +++ b/resource.qrc @@ -1,18 +1,18 @@ - - - rod.png - downarrow.png - uparrow.png - add.png - cross.png - icon.png - - - lemon_zh_CN.qm - qt_zh_CN.qm - - - realjudge_win32.exe - realjudge_linux - - + + + rod.png + downarrow.png + uparrow.png + add.png + cross.png + icon.png + + + lemon_zh_CN.qm + qt_zh_CN.qm + + + realjudge_win32.exe + realjudge_linux + + diff --git a/resultviewer.cpp b/resultviewer.cpp index 057bc3b..c2cef47 100644 --- a/resultviewer.cpp +++ b/resultviewer.cpp @@ -1,250 +1,250 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "resultviewer.h" -#include "judgingdialog.h" -#include "contestant.h" -#include "settings.h" -#include "contest.h" -#include "task.h" -#include "detaildialog.h" - -ResultViewer::ResultViewer(QWidget *parent) : - QTableWidget(parent) -{ - curContest = 0; - - deleteContestantAction = new QAction(tr("Delete"), this); - detailInformationAction = new QAction(tr("Details"), this); - judgeSelectedAction = new QAction(tr("Judge"), this); - deleteContestantKeyAction = new QAction(this); - deleteContestantKeyAction->setShortcut(QKeySequence::Delete); - deleteContestantKeyAction->setShortcutContext(Qt::WidgetShortcut); - addAction(deleteContestantKeyAction); - connect(deleteContestantAction, SIGNAL(triggered()), - this, SLOT(deleteContestant())); - connect(detailInformationAction, SIGNAL(triggered()), - this, SLOT(detailInformation())); - connect(judgeSelectedAction, SIGNAL(triggered()), - this, SLOT(judgeSelected())); - connect(deleteContestantKeyAction, SIGNAL(triggered()), - this, SLOT(deleteContestant())); - connect(this, SIGNAL(cellDoubleClicked(int, int)), - this, SLOT(detailInformation())); -} - -void ResultViewer::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::LanguageChange) { - deleteContestantAction->setText(QApplication::translate("ResultViewer", "Delete", - 0, QApplication::UnicodeUTF8)); - detailInformationAction->setText(QApplication::translate("ResultViewer", "Details", - 0, QApplication::UnicodeUTF8)); - judgeSelectedAction->setText(QApplication::translate("ResultViewer", "Judge", - 0, QApplication::UnicodeUTF8)); - } -} - -void ResultViewer::contextMenuEvent(QContextMenuEvent *event) -{ - QList selectionRange = selectedRanges(); - if (selectionRange.size() == 0) return; - QMenu *contextMenu = new QMenu(this); - if (selectionRange.size() == 1 && selectionRange[0].rowCount() == 1) { - contextMenu->addAction(detailInformationAction); - contextMenu->setDefaultAction(detailInformationAction); - } - if (selectionRange.size() > 0) - contextMenu->addAction(judgeSelectedAction); - contextMenu->addAction(deleteContestantAction); - contextMenu->exec(QCursor::pos()); - delete contextMenu; -} - -void ResultViewer::setContest(Contest *contest) -{ - if (curContest) { - disconnect(curContest, SIGNAL(taskAddedForViewer()), - this, SLOT(refreshViewer())); - disconnect(curContest, SIGNAL(taskDeletedForViewer(int)), - this, SLOT(refreshViewer())); - disconnect(curContest, SIGNAL(problemTitleChanged()), - this, SLOT(refreshViewer())); - disconnect(curContest, SIGNAL(taskJudgingFinished()), - this, SLOT(refreshViewer())); - } - curContest = contest; - if (! curContest) return; - connect(curContest, SIGNAL(taskAddedForViewer()), - this, SLOT(refreshViewer())); - connect(curContest, SIGNAL(taskDeletedForViewer(int)), - this, SLOT(refreshViewer())); - connect(curContest, SIGNAL(problemTitleChanged()), - this, SLOT(refreshViewer())); - connect(curContest, SIGNAL(taskJudgingFinished()), - this, SLOT(refreshViewer())); -} - -void ResultViewer::refreshViewer() -{ - clear(); - setRowCount(0); - setColumnCount(0); - if (! curContest) return; - - QStringList headerList; - headerList << tr("Name") << tr("Rank"); - QList taskList = curContest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) - headerList << taskList[i]->getProblemTile(); - headerList << tr("Total Score") << tr("Total Used Time (s)") << tr("Judging Time"); - setColumnCount(taskList.size() + 5); - setHorizontalHeaderLabels(headerList); - horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); - - QList contestantList = curContest->getContestantList(); - QList< QPair > sortList; - setRowCount(contestantList.size()); - for (int i = 0; i < contestantList.size(); i ++) { - setItem(i, 0, new QTableWidgetItem(contestantList[i]->getContestantName())); - setItem(i, 1, new QTableWidgetItem()); - for (int j = 0; j < taskList.size(); j ++) { - setItem(i, j + 2, new QTableWidgetItem()); - int score = contestantList[i]->getTaskScore(j); - if (score != -1) - item(i, j + 2)->setData(Qt::DisplayRole, score); - else - item(i, j + 2)->setText(tr("Invalid")); - } - setItem(i, taskList.size() + 2, new QTableWidgetItem()); - setItem(i, taskList.size() + 3, new QTableWidgetItem()); - setItem(i, taskList.size() + 4, new QTableWidgetItem()); - int totalScore = contestantList[i]->getTotalScore(); - int totalUsedTime = contestantList[i]->getTotalUsedTime(); - QDateTime judgingTime = contestantList[i]->getJudingTime(); - if (totalScore != -1) { - item(i, taskList.size() + 2)->setData(Qt::DisplayRole, totalScore); - item(i, taskList.size() + 3)->setData(Qt::DisplayRole, double(totalUsedTime) / 1000); - item(i, taskList.size() + 4)->setData(Qt::DisplayRole, judgingTime); - sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); - } else { - item(i, taskList.size() + 2)->setText(tr("Invalid")); - item(i, taskList.size() + 3)->setText(tr("Invalid")); - item(i, taskList.size() + 4)->setText(tr("Invalid")); - } - } - - qSort(sortList); - QMap rankList; - for (int i = 0; i < sortList.size(); i ++) - if (i > 0 && sortList[i].first == sortList[i-1].first) - rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); - else - rankList.insert(sortList[i].second, i); - for (int i = 0; i < rowCount(); i ++) - if (rankList.contains(contestantList[i]->getContestantName())) - item(i, 1)->setData(Qt::DisplayRole, rankList[contestantList[i]->getContestantName()] + 1); - else - item(i, 1)->setText(tr("Invalid")); - - for (int i = 0; i < rowCount(); i ++) - for (int j = 0; j < columnCount(); j ++) - item(i, j)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); -} - -void ResultViewer::judgeSelected() -{ - QStringList nameList; - QList selectionRange = selectedRanges(); - for (int i = 0; i < selectionRange.size(); i ++) - for (int j = selectionRange[i].topRow(); j <= selectionRange[i].bottomRow(); j ++) - nameList.append(item(j, 0)->text()); - JudgingDialog *dialog = new JudgingDialog(this); - dialog->setModal(true); - dialog->setContest(curContest); - dialog->show(); - dialog->judge(nameList); - delete dialog; - refreshViewer(); -} - -void ResultViewer::judgeAll() -{ - JudgingDialog *dialog = new JudgingDialog(this); - dialog->setModal(true); - dialog->setContest(curContest); - dialog->show(); - dialog->judgeAll(); - delete dialog; - refreshViewer(); -} - -void ResultViewer::clearPath(const QString &curDir) -{ - QDir dir(curDir); - QStringList fileList = dir.entryList(QDir::Files); - for (int i = 0; i < fileList.size(); i ++) - dir.remove(fileList[i]); - QStringList dirList = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (int i = 0; i < dirList.size(); i ++) { - clearPath(curDir + dirList[i] + QDir::separator()); - dir.rmdir(dirList[i]); - } -} - -void ResultViewer::deleteContestant() -{ - QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning, tr("Lemon"), - QString("") - + tr("Are you sure to delete selected contestant(s)?") + "", - QMessageBox::Ok | QMessageBox::Cancel, this); - QHBoxLayout *layout = new QHBoxLayout; - QCheckBox *checkBox = new QCheckBox(tr("Delete directories in the hard disk as well")); - layout->addWidget(checkBox); - layout->setAlignment(checkBox, Qt::AlignHCenter); - dynamic_cast(messageBox->layout())->addLayout(layout, 1, 1); - dynamic_cast(messageBox->layout())->setVerticalSpacing(10); - if (messageBox->exec() != QMessageBox::Ok) return; - - QList selectionRange = selectedRanges(); - for (int i = 0; i < selectionRange.size(); i ++) - for (int j = selectionRange[i].topRow(); j <= selectionRange[i].bottomRow(); j ++) { - curContest->deleteContestant(item(j, 0)->text()); - if (checkBox->isChecked()) { - clearPath(Settings::sourcePath() + item(j, 0)->text() + QDir::separator()); - QDir(Settings::sourcePath()).rmdir(item(j, 0)->text()); - } - } - - delete checkBox; - delete messageBox; - refreshViewer(); - emit contestantDeleted(); -} - -void ResultViewer::detailInformation() -{ - QList selectionRange = selectedRanges(); - int index = selectionRange[0].topRow(); - DetailDialog *dialog = new DetailDialog(this); - dialog->setModal(true); - dialog->refreshViewer(curContest, curContest->getContestant(item(index, 0)->text())); - connect(dialog, SIGNAL(rejudgeSignal()), this, SLOT(refreshViewer())); - dialog->showDialog(); - delete dialog; -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "resultviewer.h" +#include "judgingdialog.h" +#include "contestant.h" +#include "settings.h" +#include "contest.h" +#include "task.h" +#include "detaildialog.h" + +ResultViewer::ResultViewer(QWidget *parent) : + QTableWidget(parent) +{ + curContest = 0; + + deleteContestantAction = new QAction(tr("Delete"), this); + detailInformationAction = new QAction(tr("Details"), this); + judgeSelectedAction = new QAction(tr("Judge"), this); + deleteContestantKeyAction = new QAction(this); + deleteContestantKeyAction->setShortcut(QKeySequence::Delete); + deleteContestantKeyAction->setShortcutContext(Qt::WidgetShortcut); + addAction(deleteContestantKeyAction); + connect(deleteContestantAction, SIGNAL(triggered()), + this, SLOT(deleteContestant())); + connect(detailInformationAction, SIGNAL(triggered()), + this, SLOT(detailInformation())); + connect(judgeSelectedAction, SIGNAL(triggered()), + this, SLOT(judgeSelected())); + connect(deleteContestantKeyAction, SIGNAL(triggered()), + this, SLOT(deleteContestant())); + connect(this, SIGNAL(cellDoubleClicked(int, int)), + this, SLOT(detailInformation())); +} + +void ResultViewer::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) { + deleteContestantAction->setText(QApplication::translate("ResultViewer", "Delete", + 0, QApplication::UnicodeUTF8)); + detailInformationAction->setText(QApplication::translate("ResultViewer", "Details", + 0, QApplication::UnicodeUTF8)); + judgeSelectedAction->setText(QApplication::translate("ResultViewer", "Judge", + 0, QApplication::UnicodeUTF8)); + } +} + +void ResultViewer::contextMenuEvent(QContextMenuEvent *event) +{ + QList selectionRange = selectedRanges(); + if (selectionRange.size() == 0) return; + QMenu *contextMenu = new QMenu(this); + if (selectionRange.size() == 1 && selectionRange[0].rowCount() == 1) { + contextMenu->addAction(detailInformationAction); + contextMenu->setDefaultAction(detailInformationAction); + } + if (selectionRange.size() > 0) + contextMenu->addAction(judgeSelectedAction); + contextMenu->addAction(deleteContestantAction); + contextMenu->exec(QCursor::pos()); + delete contextMenu; +} + +void ResultViewer::setContest(Contest *contest) +{ + if (curContest) { + disconnect(curContest, SIGNAL(taskAddedForViewer()), + this, SLOT(refreshViewer())); + disconnect(curContest, SIGNAL(taskDeletedForViewer(int)), + this, SLOT(refreshViewer())); + disconnect(curContest, SIGNAL(problemTitleChanged()), + this, SLOT(refreshViewer())); + disconnect(curContest, SIGNAL(taskJudgingFinished()), + this, SLOT(refreshViewer())); + } + curContest = contest; + if (! curContest) return; + connect(curContest, SIGNAL(taskAddedForViewer()), + this, SLOT(refreshViewer())); + connect(curContest, SIGNAL(taskDeletedForViewer(int)), + this, SLOT(refreshViewer())); + connect(curContest, SIGNAL(problemTitleChanged()), + this, SLOT(refreshViewer())); + connect(curContest, SIGNAL(taskJudgingFinished()), + this, SLOT(refreshViewer())); +} + +void ResultViewer::refreshViewer() +{ + clear(); + setRowCount(0); + setColumnCount(0); + if (! curContest) return; + + QStringList headerList; + headerList << tr("Name") << tr("Rank"); + QList taskList = curContest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) + headerList << taskList[i]->getProblemTile(); + headerList << tr("Total Score") << tr("Total Used Time (s)") << tr("Judging Time"); + setColumnCount(taskList.size() + 5); + setHorizontalHeaderLabels(headerList); + horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + + QList contestantList = curContest->getContestantList(); + QList< QPair > sortList; + setRowCount(contestantList.size()); + for (int i = 0; i < contestantList.size(); i ++) { + setItem(i, 0, new QTableWidgetItem(contestantList[i]->getContestantName())); + setItem(i, 1, new QTableWidgetItem()); + for (int j = 0; j < taskList.size(); j ++) { + setItem(i, j + 2, new QTableWidgetItem()); + int score = contestantList[i]->getTaskScore(j); + if (score != -1) + item(i, j + 2)->setData(Qt::DisplayRole, score); + else + item(i, j + 2)->setText(tr("Invalid")); + } + setItem(i, taskList.size() + 2, new QTableWidgetItem()); + setItem(i, taskList.size() + 3, new QTableWidgetItem()); + setItem(i, taskList.size() + 4, new QTableWidgetItem()); + int totalScore = contestantList[i]->getTotalScore(); + int totalUsedTime = contestantList[i]->getTotalUsedTime(); + QDateTime judgingTime = contestantList[i]->getJudingTime(); + if (totalScore != -1) { + item(i, taskList.size() + 2)->setData(Qt::DisplayRole, totalScore); + item(i, taskList.size() + 3)->setData(Qt::DisplayRole, double(totalUsedTime) / 1000); + item(i, taskList.size() + 4)->setData(Qt::DisplayRole, judgingTime); + sortList.append(qMakePair(-totalScore, contestantList[i]->getContestantName())); + } else { + item(i, taskList.size() + 2)->setText(tr("Invalid")); + item(i, taskList.size() + 3)->setText(tr("Invalid")); + item(i, taskList.size() + 4)->setText(tr("Invalid")); + } + } + + qSort(sortList); + QMap rankList; + for (int i = 0; i < sortList.size(); i ++) + if (i > 0 && sortList[i].first == sortList[i-1].first) + rankList.insert(sortList[i].second, rankList[sortList[i-1].second]); + else + rankList.insert(sortList[i].second, i); + for (int i = 0; i < rowCount(); i ++) + if (rankList.contains(contestantList[i]->getContestantName())) + item(i, 1)->setData(Qt::DisplayRole, rankList[contestantList[i]->getContestantName()] + 1); + else + item(i, 1)->setText(tr("Invalid")); + + for (int i = 0; i < rowCount(); i ++) + for (int j = 0; j < columnCount(); j ++) + item(i, j)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); +} + +void ResultViewer::judgeSelected() +{ + QStringList nameList; + QList selectionRange = selectedRanges(); + for (int i = 0; i < selectionRange.size(); i ++) + for (int j = selectionRange[i].topRow(); j <= selectionRange[i].bottomRow(); j ++) + nameList.append(item(j, 0)->text()); + JudgingDialog *dialog = new JudgingDialog(this); + dialog->setModal(true); + dialog->setContest(curContest); + dialog->show(); + dialog->judge(nameList); + delete dialog; + refreshViewer(); +} + +void ResultViewer::judgeAll() +{ + JudgingDialog *dialog = new JudgingDialog(this); + dialog->setModal(true); + dialog->setContest(curContest); + dialog->show(); + dialog->judgeAll(); + delete dialog; + refreshViewer(); +} + +void ResultViewer::clearPath(const QString &curDir) +{ + QDir dir(curDir); + QStringList fileList = dir.entryList(QDir::Files); + for (int i = 0; i < fileList.size(); i ++) + dir.remove(fileList[i]); + QStringList dirList = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (int i = 0; i < dirList.size(); i ++) { + clearPath(curDir + dirList[i] + QDir::separator()); + dir.rmdir(dirList[i]); + } +} + +void ResultViewer::deleteContestant() +{ + QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning, tr("Lemon"), + QString("") + + tr("Are you sure to delete selected contestant(s)?") + "", + QMessageBox::Ok | QMessageBox::Cancel, this); + QHBoxLayout *layout = new QHBoxLayout; + QCheckBox *checkBox = new QCheckBox(tr("Delete directories in the hard disk as well")); + layout->addWidget(checkBox); + layout->setAlignment(checkBox, Qt::AlignHCenter); + dynamic_cast(messageBox->layout())->addLayout(layout, 1, 1); + dynamic_cast(messageBox->layout())->setVerticalSpacing(10); + if (messageBox->exec() != QMessageBox::Ok) return; + + QList selectionRange = selectedRanges(); + for (int i = 0; i < selectionRange.size(); i ++) + for (int j = selectionRange[i].topRow(); j <= selectionRange[i].bottomRow(); j ++) { + curContest->deleteContestant(item(j, 0)->text()); + if (checkBox->isChecked()) { + clearPath(Settings::sourcePath() + item(j, 0)->text() + QDir::separator()); + QDir(Settings::sourcePath()).rmdir(item(j, 0)->text()); + } + } + + delete checkBox; + delete messageBox; + refreshViewer(); + emit contestantDeleted(); +} + +void ResultViewer::detailInformation() +{ + QList selectionRange = selectedRanges(); + int index = selectionRange[0].topRow(); + DetailDialog *dialog = new DetailDialog(this); + dialog->setModal(true); + dialog->refreshViewer(curContest, curContest->getContestant(item(index, 0)->text())); + connect(dialog, SIGNAL(rejudgeSignal()), this, SLOT(refreshViewer())); + dialog->showDialog(); + delete dialog; +} diff --git a/resultviewer.h b/resultviewer.h index 6a983b7..823c107 100644 --- a/resultviewer.h +++ b/resultviewer.h @@ -1,58 +1,58 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef RESULTVIEWER_H -#define RESULTVIEWER_H - -#include -#include -#include - -class Contest; - -class ResultViewer : public QTableWidget -{ - Q_OBJECT -public: - explicit ResultViewer(QWidget *parent = 0); - void changeEvent(QEvent*); - void contextMenuEvent(QContextMenuEvent*); - void setContest(Contest*); - -public slots: - void refreshViewer(); - void judgeSelected(); - void judgeAll(); - -private: - Contest *curContest; - QAction *deleteContestantAction; - QAction *detailInformationAction; - QAction *judgeSelectedAction; - QAction *deleteContestantKeyAction; - void clearPath(const QString&); - -private slots: - void deleteContestant(); - void detailInformation(); - -signals: - void contestantDeleted(); -}; - -#endif // RESULTVIEWER_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef RESULTVIEWER_H +#define RESULTVIEWER_H + +#include +#include +#include + +class Contest; + +class ResultViewer : public QTableWidget +{ + Q_OBJECT +public: + explicit ResultViewer(QWidget *parent = 0); + void changeEvent(QEvent*); + void contextMenuEvent(QContextMenuEvent*); + void setContest(Contest*); + +public slots: + void refreshViewer(); + void judgeSelected(); + void judgeAll(); + +private: + Contest *curContest; + QAction *deleteContestantAction; + QAction *detailInformationAction; + QAction *judgeSelectedAction; + QAction *deleteContestantKeyAction; + void clearPath(const QString&); + +private slots: + void deleteContestant(); + void detailInformation(); + +signals: + void contestantDeleted(); +}; + +#endif // RESULTVIEWER_H diff --git a/settings.cpp b/settings.cpp index ec305b0..d2f1f5d 100644 --- a/settings.cpp +++ b/settings.cpp @@ -1,381 +1,381 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "settings.h" -#include "compiler.h" - -Settings::Settings(QObject *parent) : - QObject(parent) -{ -} - -int Settings::getDefaultFullScore() const -{ - return defaultFullScore; -} - -int Settings::getDefaultTimeLimit() const -{ - return defaultTimeLimit; -} - -int Settings::getDefaultMemoryLimit() const -{ - return defaultMemoryLimit; -} - -int Settings::getCompileTimeLimit() const -{ - return compileTimeLimit; -} - -int Settings::getSpecialJudgeTimeLimit() const -{ - return specialJudgeTimeLimit; -} - -int Settings::getFileSizeLimit() const -{ - return fileSizeLimit; -} - -int Settings::getNumberOfThreads() const -{ - return numberOfThreads; -} - -const QString& Settings::getDefaultInputFileExtension() const -{ - return defaultInputFileExtension; -} - -const QString& Settings::getDefaultOutputFileExtension() const -{ - return defaultOutputFileExtension; -} - -const QStringList& Settings::getInputFileExtensions() const -{ - return inputFileExtensions; -} - -const QStringList& Settings::getOutputFileExtensions() const -{ - return outputFileExtensions; -} - -const QStringList& Settings::getRecentContest() const -{ - return recentContest; -} - -const QList& Settings::getCompilerList() const -{ - return compilerList; -} - -const QString& Settings::getUiLanguage() const -{ - return uiLanguage; -} - -void Settings::setDefaultFullScore(int score) -{ - defaultFullScore = score; -} - -void Settings::setDefaultTimeLimit(int limit) -{ - defaultTimeLimit = limit; -} - -void Settings::setDefaultMemoryLimit(int limit) -{ - defaultMemoryLimit = limit; -} - -void Settings::setCompileTimeLimit(int limit) -{ - compileTimeLimit = limit; -} - -void Settings::setSpecialJudgeTimeLimit(int limit) -{ - specialJudgeTimeLimit = limit; -} - -void Settings::setFileSizeLimit(int limit) -{ - fileSizeLimit = limit; -} - -void Settings::setNumberOfThreads(int number) -{ - numberOfThreads = number; -} - -void Settings::setDefaultInputFileExtension(const QString &extension) -{ - defaultInputFileExtension = extension; -} - -void Settings::setDefaultOutputFileExtension(const QString &extension) -{ - defaultOutputFileExtension = extension; -} - -void Settings::setInputFileExtensions(const QString &extensions) -{ - inputFileExtensions = extensions.split(";", QString::SkipEmptyParts); -} - -void Settings::setOutputFileExtensions(const QString &extensions) -{ - outputFileExtensions = extensions.split(";", QString::SkipEmptyParts); -} - -void Settings::setRecentContest(const QStringList &list) -{ - recentContest = list; -} - -void Settings::setUiLanguage(const QString &language) -{ - uiLanguage = language; -} - -void Settings::addCompiler(Compiler *compiler) -{ - compiler->setParent(this); - compilerList.append(compiler); -} - -void Settings::deleteCompiler(int index) -{ - if (0 <= index && index < compilerList.size()) { - delete compilerList[index]; - compilerList.removeAt(index); - } -} - -Compiler* Settings::getCompiler(int index) -{ - if (0 <= index && index < compilerList.size()) - return compilerList[index]; - else - return 0; -} - -void Settings::swapCompiler(int a, int b) -{ - if (0 <= a && a < compilerList.size()) - if (0 <= b && b < compilerList.size()) - compilerList.swap(a, b); -} - -void Settings::copyFrom(Settings *other) -{ - setDefaultFullScore(other->getDefaultFullScore()); - setDefaultTimeLimit(other->getDefaultTimeLimit()); - setDefaultMemoryLimit(other->getDefaultMemoryLimit()); - setCompileTimeLimit(other->getCompileTimeLimit()); - setSpecialJudgeTimeLimit(other->getSpecialJudgeTimeLimit()); - setFileSizeLimit(other->getFileSizeLimit()); - setNumberOfThreads(other->getNumberOfThreads()); - setDefaultInputFileExtension(other->getDefaultInputFileExtension()); - setDefaultOutputFileExtension(other->getDefaultOutputFileExtension()); - setInputFileExtensions(other->getInputFileExtensions().join(";")); - setOutputFileExtensions(other->getOutputFileExtensions().join(";")); - - for (int i = 0; i < compilerList.size(); i ++) - delete compilerList[i]; - compilerList.clear(); - const QList &list = other->getCompilerList(); - for (int i = 0; i < list.size(); i ++) { - Compiler *compiler = new Compiler; - compiler->copyFrom(list[i]); - addCompiler(compiler); - } -} - -void Settings::saveSettings() -{ - QSettings settings("Crash", "Lemon"); - - settings.setValue("UiLanguage", uiLanguage); - - settings.beginGroup("GeneralSettings"); - settings.setValue("DefaultFullScore", defaultFullScore); - settings.setValue("DefaultTimeLimit", defaultTimeLimit); - settings.setValue("DefaultMemoryLimit", defaultMemoryLimit); - settings.setValue("CompileTimeLimit", compileTimeLimit); - settings.setValue("SpecialJudgeTimeLimit", specialJudgeTimeLimit); - settings.setValue("FileSizeLimit", fileSizeLimit); - settings.setValue("NumberOfThreads", numberOfThreads); - settings.setValue("DefaultInputFileExtension", defaultInputFileExtension); - settings.setValue("DefaultOutputFileExtension", defaultOutputFileExtension); - settings.setValue("InputFileExtensions", inputFileExtensions); - settings.setValue("OutputFileExtensions", outputFileExtensions); - settings.endGroup(); - - settings.beginWriteArray("CompilerSettings"); - for (int i = 0; i < compilerList.size(); i ++) { - settings.setArrayIndex(i); - settings.setValue("CompilerType", (int)compilerList[i]->getCompilerType()); - settings.setValue("CompilerName", compilerList[i]->getCompilerName()); - settings.setValue("SourceExtensions", compilerList[i]->getSourceExtensions()); - settings.setValue("CompilerLocation", compilerList[i]->getCompilerLocation()); - settings.setValue("InterpreterLocation", compilerList[i]->getInterpreterLocation()); - settings.setValue("BytecodeExtensions", compilerList[i]->getBytecodeExtensions()); - settings.setValue("TimeLimitRatio", compilerList[i]->getTimeLimitRatio()); - settings.setValue("MemoryLimitRatio", compilerList[i]->getMemoryLimitRatio()); - settings.setValue("DisableMemoryLimitCheck", compilerList[i]->getDisableMemoryLimitCheck()); - QStringList configurationNames = compilerList[i]->getConfigurationNames(); - QStringList compilerArguments = compilerList[i]->getCompilerArguments(); - QStringList interpreterArguments = compilerList[i]->getInterpreterArguments(); - settings.beginWriteArray("Configuration"); - for (int j = 0; j < configurationNames.size(); j ++) { - settings.setArrayIndex(j); - settings.setValue("Name", configurationNames[j]); - settings.setValue("CompilerArguments", compilerArguments[j]); - settings.setValue("InterpreterArguments", interpreterArguments[j]); - } - settings.setValue("EnvironmentVariables", compilerList[i]->getEnvironment().toStringList()); - settings.endArray(); - } - settings.endArray(); - - settings.beginWriteArray("RecentContest"); - for (int i = 0; i < recentContest.size(); i ++) { - settings.setArrayIndex(i); - settings.setValue("Location", recentContest[i]); - } - settings.endArray(); -} - -void Settings::loadSettings() -{ - for (int i = 0; i < compilerList.size(); i ++) - delete compilerList[i]; - compilerList.clear(); - recentContest.clear(); - - QSettings settings("Crash", "Lemon"); - - uiLanguage = settings.value("UiLanguage", QLocale::system().name()).toString(); - - settings.beginGroup("GeneralSettings"); - defaultFullScore = settings.value("DefaultFullScore", 10).toInt(); - defaultTimeLimit = settings.value("DefaultTimeLimit", 1000).toInt(); - defaultMemoryLimit = settings.value("DefaultMemoryLimit", 64).toInt(); - compileTimeLimit = settings.value("CompileTimeLimit", 10000).toInt(); - specialJudgeTimeLimit = settings.value("SpecialJudgeTimeLimit", 10000).toInt(); - fileSizeLimit = settings.value("FileSizeLimit", 50).toInt(); - numberOfThreads = settings.value("NumberOfThreads", 1).toInt(); - defaultInputFileExtension = settings.value("DefaultInputFileExtension", "in").toString(); - defaultOutputFileExtension = settings.value("DefaultOuputFileExtension", "out").toString(); - inputFileExtensions = settings.value("InputFileExtensions", QStringList() << "in").toStringList(); - outputFileExtensions = settings.value("OutputFileExtensions", QStringList() << "out" << "ans").toStringList(); - settings.endGroup(); - - int compilerCount = settings.beginReadArray("CompilerSettings"); - for (int i = 0; i < compilerCount; i ++) { - settings.setArrayIndex(i); - Compiler *compiler = new Compiler; - compiler->setCompilerType((Compiler::CompilerType)settings.value("CompilerType").toInt()); - compiler->setCompilerName(settings.value("CompilerName").toString()); - compiler->setSourceExtensions(settings.value("SourceExtensions").toStringList().join(";")); - compiler->setCompilerLocation(settings.value("CompilerLocation").toString()); - compiler->setInterpreterLocation(settings.value("InterpreterLocation").toString()); - compiler->setBytecodeExtensions(settings.value("BytecodeExtensions").toStringList().join(";")); - compiler->setTimeLimitRatio(settings.value("TimeLimitRatio").toDouble()); - compiler->setMemoryLimitRatio(settings.value("MemoryLimitRatio").toDouble()); - compiler->setDisableMemoryLimitCheck(settings.value("DisableMemoryLimitCheck").toBool()); - int configurationCount = settings.beginReadArray("Configuration"); - for (int j = 0; j < configurationCount; j ++) { - settings.setArrayIndex(j); - compiler->addConfiguration(settings.value("Name").toString(), - settings.value("CompilerArguments").toString(), - settings.value("InterpreterArguments").toString()); - } - QStringList values = settings.value("EnvironmentVariables").toStringList(); - QProcessEnvironment environment; - for (int i = 0; i < values.size(); i ++) { - int tmp = values[i].indexOf('='); - QString variable = values[i].mid(0, tmp); - QString value = values[i].mid(tmp + 1); - environment.insert(variable, value); - } - compiler->setEnvironment(environment); - settings.endArray(); - addCompiler(compiler); - } - settings.endArray(); - - int listCount = settings.beginReadArray("RecentContest"); - for (int i = 0; i < listCount; i ++) { - settings.setArrayIndex(i); - recentContest.append(settings.value("Location").toString()); - } - settings.endArray(); -} - -int Settings::upperBoundForFullScore() -{ - return 100; -} - -int Settings::upperBoundForTimeLimit() -{ - return 1000 * 60 * 10; -} - -int Settings::upperBoundForMemoryLimit() -{ - return 1024; -} - -int Settings::upperBoundForFileSizeLimit() -{ - return 10 * 1024; -} - -int Settings::upperBoundForNumberOfThreads() -{ - return 8; -} - -QString Settings::dataPath() -{ - return QString("data") + QDir::separator(); -} - -QString Settings::sourcePath() -{ - return QString("source") + QDir::separator(); -} - -QString Settings::temporaryPath() -{ - return QString("temp") + QDir::separator(); -} - -QString Settings::selfTestPath() -{ - return QString("selftest") + QDir::separator(); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "settings.h" +#include "compiler.h" + +Settings::Settings(QObject *parent) : + QObject(parent) +{ +} + +int Settings::getDefaultFullScore() const +{ + return defaultFullScore; +} + +int Settings::getDefaultTimeLimit() const +{ + return defaultTimeLimit; +} + +int Settings::getDefaultMemoryLimit() const +{ + return defaultMemoryLimit; +} + +int Settings::getCompileTimeLimit() const +{ + return compileTimeLimit; +} + +int Settings::getSpecialJudgeTimeLimit() const +{ + return specialJudgeTimeLimit; +} + +int Settings::getFileSizeLimit() const +{ + return fileSizeLimit; +} + +int Settings::getNumberOfThreads() const +{ + return numberOfThreads; +} + +const QString& Settings::getDefaultInputFileExtension() const +{ + return defaultInputFileExtension; +} + +const QString& Settings::getDefaultOutputFileExtension() const +{ + return defaultOutputFileExtension; +} + +const QStringList& Settings::getInputFileExtensions() const +{ + return inputFileExtensions; +} + +const QStringList& Settings::getOutputFileExtensions() const +{ + return outputFileExtensions; +} + +const QStringList& Settings::getRecentContest() const +{ + return recentContest; +} + +const QList& Settings::getCompilerList() const +{ + return compilerList; +} + +const QString& Settings::getUiLanguage() const +{ + return uiLanguage; +} + +void Settings::setDefaultFullScore(int score) +{ + defaultFullScore = score; +} + +void Settings::setDefaultTimeLimit(int limit) +{ + defaultTimeLimit = limit; +} + +void Settings::setDefaultMemoryLimit(int limit) +{ + defaultMemoryLimit = limit; +} + +void Settings::setCompileTimeLimit(int limit) +{ + compileTimeLimit = limit; +} + +void Settings::setSpecialJudgeTimeLimit(int limit) +{ + specialJudgeTimeLimit = limit; +} + +void Settings::setFileSizeLimit(int limit) +{ + fileSizeLimit = limit; +} + +void Settings::setNumberOfThreads(int number) +{ + numberOfThreads = number; +} + +void Settings::setDefaultInputFileExtension(const QString &extension) +{ + defaultInputFileExtension = extension; +} + +void Settings::setDefaultOutputFileExtension(const QString &extension) +{ + defaultOutputFileExtension = extension; +} + +void Settings::setInputFileExtensions(const QString &extensions) +{ + inputFileExtensions = extensions.split(";", QString::SkipEmptyParts); +} + +void Settings::setOutputFileExtensions(const QString &extensions) +{ + outputFileExtensions = extensions.split(";", QString::SkipEmptyParts); +} + +void Settings::setRecentContest(const QStringList &list) +{ + recentContest = list; +} + +void Settings::setUiLanguage(const QString &language) +{ + uiLanguage = language; +} + +void Settings::addCompiler(Compiler *compiler) +{ + compiler->setParent(this); + compilerList.append(compiler); +} + +void Settings::deleteCompiler(int index) +{ + if (0 <= index && index < compilerList.size()) { + delete compilerList[index]; + compilerList.removeAt(index); + } +} + +Compiler* Settings::getCompiler(int index) +{ + if (0 <= index && index < compilerList.size()) + return compilerList[index]; + else + return 0; +} + +void Settings::swapCompiler(int a, int b) +{ + if (0 <= a && a < compilerList.size()) + if (0 <= b && b < compilerList.size()) + compilerList.swap(a, b); +} + +void Settings::copyFrom(Settings *other) +{ + setDefaultFullScore(other->getDefaultFullScore()); + setDefaultTimeLimit(other->getDefaultTimeLimit()); + setDefaultMemoryLimit(other->getDefaultMemoryLimit()); + setCompileTimeLimit(other->getCompileTimeLimit()); + setSpecialJudgeTimeLimit(other->getSpecialJudgeTimeLimit()); + setFileSizeLimit(other->getFileSizeLimit()); + setNumberOfThreads(other->getNumberOfThreads()); + setDefaultInputFileExtension(other->getDefaultInputFileExtension()); + setDefaultOutputFileExtension(other->getDefaultOutputFileExtension()); + setInputFileExtensions(other->getInputFileExtensions().join(";")); + setOutputFileExtensions(other->getOutputFileExtensions().join(";")); + + for (int i = 0; i < compilerList.size(); i ++) + delete compilerList[i]; + compilerList.clear(); + const QList &list = other->getCompilerList(); + for (int i = 0; i < list.size(); i ++) { + Compiler *compiler = new Compiler; + compiler->copyFrom(list[i]); + addCompiler(compiler); + } +} + +void Settings::saveSettings() +{ + QSettings settings("Crash", "Lemon"); + + settings.setValue("UiLanguage", uiLanguage); + + settings.beginGroup("GeneralSettings"); + settings.setValue("DefaultFullScore", defaultFullScore); + settings.setValue("DefaultTimeLimit", defaultTimeLimit); + settings.setValue("DefaultMemoryLimit", defaultMemoryLimit); + settings.setValue("CompileTimeLimit", compileTimeLimit); + settings.setValue("SpecialJudgeTimeLimit", specialJudgeTimeLimit); + settings.setValue("FileSizeLimit", fileSizeLimit); + settings.setValue("NumberOfThreads", numberOfThreads); + settings.setValue("DefaultInputFileExtension", defaultInputFileExtension); + settings.setValue("DefaultOutputFileExtension", defaultOutputFileExtension); + settings.setValue("InputFileExtensions", inputFileExtensions); + settings.setValue("OutputFileExtensions", outputFileExtensions); + settings.endGroup(); + + settings.beginWriteArray("CompilerSettings"); + for (int i = 0; i < compilerList.size(); i ++) { + settings.setArrayIndex(i); + settings.setValue("CompilerType", (int)compilerList[i]->getCompilerType()); + settings.setValue("CompilerName", compilerList[i]->getCompilerName()); + settings.setValue("SourceExtensions", compilerList[i]->getSourceExtensions()); + settings.setValue("CompilerLocation", compilerList[i]->getCompilerLocation()); + settings.setValue("InterpreterLocation", compilerList[i]->getInterpreterLocation()); + settings.setValue("BytecodeExtensions", compilerList[i]->getBytecodeExtensions()); + settings.setValue("TimeLimitRatio", compilerList[i]->getTimeLimitRatio()); + settings.setValue("MemoryLimitRatio", compilerList[i]->getMemoryLimitRatio()); + settings.setValue("DisableMemoryLimitCheck", compilerList[i]->getDisableMemoryLimitCheck()); + QStringList configurationNames = compilerList[i]->getConfigurationNames(); + QStringList compilerArguments = compilerList[i]->getCompilerArguments(); + QStringList interpreterArguments = compilerList[i]->getInterpreterArguments(); + settings.beginWriteArray("Configuration"); + for (int j = 0; j < configurationNames.size(); j ++) { + settings.setArrayIndex(j); + settings.setValue("Name", configurationNames[j]); + settings.setValue("CompilerArguments", compilerArguments[j]); + settings.setValue("InterpreterArguments", interpreterArguments[j]); + } + settings.setValue("EnvironmentVariables", compilerList[i]->getEnvironment().toStringList()); + settings.endArray(); + } + settings.endArray(); + + settings.beginWriteArray("RecentContest"); + for (int i = 0; i < recentContest.size(); i ++) { + settings.setArrayIndex(i); + settings.setValue("Location", recentContest[i]); + } + settings.endArray(); +} + +void Settings::loadSettings() +{ + for (int i = 0; i < compilerList.size(); i ++) + delete compilerList[i]; + compilerList.clear(); + recentContest.clear(); + + QSettings settings("Crash", "Lemon"); + + uiLanguage = settings.value("UiLanguage", QLocale::system().name()).toString(); + + settings.beginGroup("GeneralSettings"); + defaultFullScore = settings.value("DefaultFullScore", 10).toInt(); + defaultTimeLimit = settings.value("DefaultTimeLimit", 1000).toInt(); + defaultMemoryLimit = settings.value("DefaultMemoryLimit", 64).toInt(); + compileTimeLimit = settings.value("CompileTimeLimit", 10000).toInt(); + specialJudgeTimeLimit = settings.value("SpecialJudgeTimeLimit", 10000).toInt(); + fileSizeLimit = settings.value("FileSizeLimit", 50).toInt(); + numberOfThreads = settings.value("NumberOfThreads", 1).toInt(); + defaultInputFileExtension = settings.value("DefaultInputFileExtension", "in").toString(); + defaultOutputFileExtension = settings.value("DefaultOuputFileExtension", "out").toString(); + inputFileExtensions = settings.value("InputFileExtensions", QStringList() << "in").toStringList(); + outputFileExtensions = settings.value("OutputFileExtensions", QStringList() << "out" << "ans").toStringList(); + settings.endGroup(); + + int compilerCount = settings.beginReadArray("CompilerSettings"); + for (int i = 0; i < compilerCount; i ++) { + settings.setArrayIndex(i); + Compiler *compiler = new Compiler; + compiler->setCompilerType((Compiler::CompilerType)settings.value("CompilerType").toInt()); + compiler->setCompilerName(settings.value("CompilerName").toString()); + compiler->setSourceExtensions(settings.value("SourceExtensions").toStringList().join(";")); + compiler->setCompilerLocation(settings.value("CompilerLocation").toString()); + compiler->setInterpreterLocation(settings.value("InterpreterLocation").toString()); + compiler->setBytecodeExtensions(settings.value("BytecodeExtensions").toStringList().join(";")); + compiler->setTimeLimitRatio(settings.value("TimeLimitRatio").toDouble()); + compiler->setMemoryLimitRatio(settings.value("MemoryLimitRatio").toDouble()); + compiler->setDisableMemoryLimitCheck(settings.value("DisableMemoryLimitCheck").toBool()); + int configurationCount = settings.beginReadArray("Configuration"); + for (int j = 0; j < configurationCount; j ++) { + settings.setArrayIndex(j); + compiler->addConfiguration(settings.value("Name").toString(), + settings.value("CompilerArguments").toString(), + settings.value("InterpreterArguments").toString()); + } + QStringList values = settings.value("EnvironmentVariables").toStringList(); + QProcessEnvironment environment; + for (int i = 0; i < values.size(); i ++) { + int tmp = values[i].indexOf('='); + QString variable = values[i].mid(0, tmp); + QString value = values[i].mid(tmp + 1); + environment.insert(variable, value); + } + compiler->setEnvironment(environment); + settings.endArray(); + addCompiler(compiler); + } + settings.endArray(); + + int listCount = settings.beginReadArray("RecentContest"); + for (int i = 0; i < listCount; i ++) { + settings.setArrayIndex(i); + recentContest.append(settings.value("Location").toString()); + } + settings.endArray(); +} + +int Settings::upperBoundForFullScore() +{ + return 100; +} + +int Settings::upperBoundForTimeLimit() +{ + return 1000 * 60 * 10; +} + +int Settings::upperBoundForMemoryLimit() +{ + return 1024; +} + +int Settings::upperBoundForFileSizeLimit() +{ + return 10 * 1024; +} + +int Settings::upperBoundForNumberOfThreads() +{ + return 8; +} + +QString Settings::dataPath() +{ + return QString("data") + QDir::separator(); +} + +QString Settings::sourcePath() +{ + return QString("source") + QDir::separator(); +} + +QString Settings::temporaryPath() +{ + return QString("temp") + QDir::separator(); +} + +QString Settings::selfTestPath() +{ + return QString("selftest") + QDir::separator(); +} diff --git a/settings.h b/settings.h index f2eebec..76df28c 100644 --- a/settings.h +++ b/settings.h @@ -1,97 +1,97 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef SETTINGS_H -#define SETTINGS_H - -#include -#include - -class Compiler; - -class Settings : public QObject -{ - Q_OBJECT -public: - explicit Settings(QObject *parent = 0); - - int getDefaultFullScore() const; - int getDefaultTimeLimit() const; - int getDefaultMemoryLimit() const; - int getCompileTimeLimit() const; - int getSpecialJudgeTimeLimit() const; - int getFileSizeLimit() const; - int getNumberOfThreads() const; - const QString& getDefaultInputFileExtension() const; - const QString& getDefaultOutputFileExtension() const; - const QStringList& getInputFileExtensions() const; - const QStringList& getOutputFileExtensions() const; - const QStringList& getRecentContest() const; - const QList& getCompilerList() const; - const QString& getUiLanguage() const; - - void setDefaultFullScore(int); - void setDefaultTimeLimit(int); - void setDefaultMemoryLimit(int); - void setCompileTimeLimit(int); - void setSpecialJudgeTimeLimit(int); - void setFileSizeLimit(int); - void setNumberOfThreads(int); - void setDefaultInputFileExtension(const QString&); - void setDefaultOutputFileExtension(const QString&); - void setInputFileExtensions(const QString&); - void setOutputFileExtensions(const QString&); - void setRecentContest(const QStringList&); - void setUiLanguage(const QString&); - - void addCompiler(Compiler*); - void deleteCompiler(int); - Compiler* getCompiler(int); - void swapCompiler(int, int); - void copyFrom(Settings*); - void saveSettings(); - void loadSettings(); - - static int upperBoundForFullScore(); - static int upperBoundForTimeLimit(); - static int upperBoundForMemoryLimit(); - static int upperBoundForFileSizeLimit(); - static int upperBoundForNumberOfThreads(); - static QString dataPath(); - static QString sourcePath(); - static QString temporaryPath(); - static QString selfTestPath(); - -private: - QList compilerList; - int defaultFullScore; - int defaultTimeLimit; - int defaultMemoryLimit; - int compileTimeLimit; - int specialJudgeTimeLimit; - int fileSizeLimit; - int numberOfThreads; - QString defaultInputFileExtension; - QString defaultOutputFileExtension; - QStringList inputFileExtensions; - QStringList outputFileExtensions; - QStringList recentContest; - QString uiLanguage; -}; - -#endif // SETTINGS_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef SETTINGS_H +#define SETTINGS_H + +#include +#include + +class Compiler; + +class Settings : public QObject +{ + Q_OBJECT +public: + explicit Settings(QObject *parent = 0); + + int getDefaultFullScore() const; + int getDefaultTimeLimit() const; + int getDefaultMemoryLimit() const; + int getCompileTimeLimit() const; + int getSpecialJudgeTimeLimit() const; + int getFileSizeLimit() const; + int getNumberOfThreads() const; + const QString& getDefaultInputFileExtension() const; + const QString& getDefaultOutputFileExtension() const; + const QStringList& getInputFileExtensions() const; + const QStringList& getOutputFileExtensions() const; + const QStringList& getRecentContest() const; + const QList& getCompilerList() const; + const QString& getUiLanguage() const; + + void setDefaultFullScore(int); + void setDefaultTimeLimit(int); + void setDefaultMemoryLimit(int); + void setCompileTimeLimit(int); + void setSpecialJudgeTimeLimit(int); + void setFileSizeLimit(int); + void setNumberOfThreads(int); + void setDefaultInputFileExtension(const QString&); + void setDefaultOutputFileExtension(const QString&); + void setInputFileExtensions(const QString&); + void setOutputFileExtensions(const QString&); + void setRecentContest(const QStringList&); + void setUiLanguage(const QString&); + + void addCompiler(Compiler*); + void deleteCompiler(int); + Compiler* getCompiler(int); + void swapCompiler(int, int); + void copyFrom(Settings*); + void saveSettings(); + void loadSettings(); + + static int upperBoundForFullScore(); + static int upperBoundForTimeLimit(); + static int upperBoundForMemoryLimit(); + static int upperBoundForFileSizeLimit(); + static int upperBoundForNumberOfThreads(); + static QString dataPath(); + static QString sourcePath(); + static QString temporaryPath(); + static QString selfTestPath(); + +private: + QList compilerList; + int defaultFullScore; + int defaultTimeLimit; + int defaultMemoryLimit; + int compileTimeLimit; + int specialJudgeTimeLimit; + int fileSizeLimit; + int numberOfThreads; + QString defaultInputFileExtension; + QString defaultOutputFileExtension; + QStringList inputFileExtensions; + QStringList outputFileExtensions; + QStringList recentContest; + QString uiLanguage; +}; + +#endif // SETTINGS_H diff --git a/summarytree.cpp b/summarytree.cpp index e4ec72b..17a2441 100644 --- a/summarytree.cpp +++ b/summarytree.cpp @@ -1,291 +1,291 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "summarytree.h" -#include "addtestcaseswizard.h" -#include "settings.h" -#include "contest.h" -#include "task.h" -#include "testcase.h" - -SummaryTree::SummaryTree(QWidget *parent) : - QTreeWidget(parent) -{ - curContest = 0; - addCount = 0; - - addTaskAction = new QAction(tr("Add a New Task"), this); - addTestCaseAction = new QAction(tr("Add a Test Case"), this); - addTestCasesAction = new QAction(tr("Add Test Cases ..."), this); - deleteTaskAction = new QAction(tr("Delete Current Task"), this); - deleteTestCaseAction = new QAction(tr("Delete Current Test Case"), this); - deleteTaskKeyAction = new QAction(this); - deleteTestCaseKeyAction = new QAction(this); - - deleteTaskKeyAction->setShortcutContext(Qt::WidgetShortcut); - deleteTestCaseKeyAction->setShortcutContext(Qt::WidgetShortcut); - deleteTaskKeyAction->setShortcut(QKeySequence::Delete); - deleteTestCaseKeyAction->setShortcut(QKeySequence::Delete); - deleteTaskKeyAction->setEnabled(false); - deleteTestCaseKeyAction->setEnabled(false); - addAction(deleteTaskKeyAction); - addAction(deleteTestCaseKeyAction); - - connect(addTaskAction, SIGNAL(triggered()), - this, SLOT(addTask())); - connect(addTestCaseAction, SIGNAL(triggered()), - this, SLOT(addTestCase())); - connect(addTestCasesAction, SIGNAL(triggered()), - this, SLOT(addTestCases())); - connect(deleteTaskAction, SIGNAL(triggered()), - this, SLOT(deleteTask())); - connect(deleteTestCaseAction, SIGNAL(triggered()), - this, SLOT(deleteTestCase())); - connect(deleteTaskKeyAction, SIGNAL(triggered()), - this, SLOT(deleteTask())); - connect(deleteTestCaseKeyAction, SIGNAL(triggered()), - this, SLOT(deleteTestCase())); - connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), - this, SLOT(selectionChanged())); - connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)), - this, SLOT(itemChanged(QTreeWidgetItem*))); -} - -void SummaryTree::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::LanguageChange) { - addTaskAction->setText(QApplication::translate("SummaryTree", "Add a New Task", - 0, QApplication::UnicodeUTF8)); - addTestCaseAction->setText(QApplication::translate("SummaryTree", "Add a Test Case", - 0, QApplication::UnicodeUTF8)); - addTestCasesAction->setText(QApplication::translate("SummaryTree", "Add Test Cases ...", - 0, QApplication::UnicodeUTF8)); - deleteTaskAction->setText(QApplication::translate("SummaryTree", "Delete Current Task", - 0, QApplication::UnicodeUTF8)); - deleteTestCaseAction->setText(QApplication::translate("SummaryTree", "Delete Current Test Case", - 0, QApplication::UnicodeUTF8)); - for (int i = 0; i < topLevelItemCount(); i ++) { - QTreeWidgetItem *taskItem = topLevelItem(i); - for (int j = 0; j < taskItem->childCount(); j ++) { - taskItem->child(j)->setText(0, QApplication::translate("SummaryTree", "Test Case #%1", - 0, QApplication::UnicodeUTF8).arg(j + 1)); - } - } - } -} - -void SummaryTree::setContest(Contest *contest) -{ - if (curContest) { - QList taskList = curContest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) - disconnect(taskList[i], SIGNAL(problemTitleChanged(QString)), - this, SLOT(titleChanged(QString))); - } - curContest = contest; - if (! curContest) return; - setEnabled(false); - clear(); - QList taskList = curContest->getTaskList(); - for (int i = 0; i < taskList.size(); i ++) { - connect(taskList[i], SIGNAL(problemTitleChanged(QString)), - this, SLOT(titleChanged(QString))); - QTreeWidgetItem *newTaskItem = new QTreeWidgetItem(this); - newTaskItem->setText(0, taskList[i]->getProblemTile()); - newTaskItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); - for (int j = 0; j < taskList[i]->getTestCaseList().size(); j ++) { - QTreeWidgetItem *newTestCaseItem = new QTreeWidgetItem(newTaskItem); - newTestCaseItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - newTestCaseItem->setText(0, tr("Test Case #%1").arg(newTaskItem->childCount())); - } - } - if (taskList.size() > 0) setCurrentItem(topLevelItem(0)); - setEnabled(true); - emit currentItemChanged(0, 0); -} - -void SummaryTree::setSettings(Settings *_settings) -{ - settings = _settings; -} - -void SummaryTree::contextMenuEvent(QContextMenuEvent *event) -{ - QMenu *contextMenu = new QMenu(this); - - QTreeWidgetItem *curItem = currentItem(); - if (! curItem) { - contextMenu->addAction(addTaskAction); - contextMenu->exec(QCursor::pos()); - delete contextMenu; - return; - } - - int index = indexOfTopLevelItem(curItem); - if (index != -1) { - contextMenu->addAction(addTaskAction); - contextMenu->addAction(deleteTaskAction); - contextMenu->addSeparator(); - contextMenu->addAction(addTestCaseAction); - contextMenu->addAction(addTestCasesAction); - contextMenu->exec(QCursor::pos()); - delete contextMenu; - } else { - contextMenu->addAction(addTaskAction); - contextMenu->addAction(deleteTaskAction); - contextMenu->addSeparator(); - contextMenu->addAction(addTestCaseAction); - contextMenu->addAction(addTestCasesAction); - contextMenu->addAction(deleteTestCaseAction); - contextMenu->exec(QCursor::pos()); - delete contextMenu; - } -} - -void SummaryTree::addTask() -{ - Task *newTask = new Task; - newTask->setAnswerFileExtension(settings->getDefaultOutputFileExtension()); - curContest->addTask(newTask); - newTask->refreshCompilerConfiguration(settings); - connect(newTask, SIGNAL(problemTitleChanged(QString)), - this, SLOT(titleChanged(QString))); - QTreeWidgetItem *newItem = new QTreeWidgetItem(this); - setCurrentItem(newItem); - newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); - newItem->setText(0, tr("Problem %1").arg(++ addCount)); - editItem(newItem); -} - -void SummaryTree::addTestCase() -{ - QTreeWidgetItem *curItem = currentItem(); - if (indexOfTopLevelItem(curItem) == -1) - curItem = curItem->parent(); - int index = indexOfTopLevelItem(curItem); - Task *curTask = curContest->getTask(index); - TestCase *newTestCase = new TestCase; - newTestCase->setFullScore(settings->getDefaultFullScore()); - newTestCase->setTimeLimit(settings->getDefaultTimeLimit()); - newTestCase->setMemoryLimit(settings->getDefaultMemoryLimit()); - curTask->addTestCase(newTestCase); - QTreeWidgetItem *newItem = new QTreeWidgetItem(curItem); - newItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - newItem->setText(0, tr("Test Case #%1").arg(curItem->childCount())); - setCurrentItem(newItem); -} - -void SummaryTree::addTestCases() -{ - QTreeWidgetItem *curItem = currentItem(); - if (indexOfTopLevelItem(curItem) == -1) - curItem = curItem->parent(); - int index = indexOfTopLevelItem(curItem); - Task *curTask = curContest->getTask(index); - AddTestCasesWizard *wizard = new AddTestCasesWizard(this); - wizard->setSettings(settings, curTask->getTaskType() == Task::Traditional); - if (wizard->exec() == QDialog::Accepted) { - QList inputFiles = wizard->getMatchedInputFiles(); - QList outputFiles = wizard->getMatchedOutputFiles(); - for (int i = 0; i < inputFiles.size(); i ++) { - addTestCase(); - QTreeWidgetItem *curItem = currentItem(); - QTreeWidgetItem *parentItem = curItem->parent(); - int taskIndex = indexOfTopLevelItem(parentItem); - int testCaseIndex = parentItem->indexOfChild(curItem); - Task *curTask = curContest->getTask(taskIndex); - TestCase *curTestCase = curTask->getTestCase(testCaseIndex); - curTestCase->setFullScore(wizard->getFullScore()); - curTestCase->setTimeLimit(wizard->getTimeLimit()); - curTestCase->setMemoryLimit(wizard->getMemoryLimit()); - for (int j = 0; j < inputFiles[i].size(); j ++) - curTestCase->addSingleCase(inputFiles[i][j], outputFiles[i][j]); - setCurrentItem(parentItem); - setCurrentItem(curItem); - } - } - delete wizard; -} - -void SummaryTree::deleteTask() -{ - if (QMessageBox::warning(this, tr("Lemon"), tr("Are you sure to delete this task?"), - QMessageBox::Yes, QMessageBox::Cancel) == QMessageBox::Cancel) - return; - QTreeWidgetItem *curItem = currentItem(); - if (indexOfTopLevelItem(curItem) == -1) - curItem = curItem->parent(); - int index = indexOfTopLevelItem(curItem); - if (index + 1 < topLevelItemCount()) - setCurrentItem(topLevelItem(index + 1)); - else - if (index - 1 >= 0) - setCurrentItem(topLevelItem(index - 1)); - else - setCurrentItem(0); - delete curItem; - curContest->deleteTask(index); -} - -void SummaryTree::deleteTestCase() -{ - QTreeWidgetItem *curItem = currentItem(); - QTreeWidgetItem *parentItem = curItem->parent(); - int taskIndex = indexOfTopLevelItem(parentItem); - int testCaseIndex = parentItem->indexOfChild(curItem); - Task *curTask = curContest->getTask(taskIndex); - delete curItem; - curTask->deleteTestCase(testCaseIndex); - for (int i = 0; i < parentItem->childCount(); i ++) - parentItem->child(i)->setText(0, tr("Test Case #%1").arg(i + 1)); -} - -void SummaryTree::selectionChanged() -{ - if (! isEnabled()) return; - QTreeWidgetItem *curItem = currentItem(); - if (! curItem) { - deleteTaskKeyAction->setEnabled(false); - deleteTestCaseKeyAction->setEnabled(false); - return; - } - - int index = indexOfTopLevelItem(curItem); - if (index != -1) { - deleteTaskKeyAction->setEnabled(true); - deleteTestCaseKeyAction->setEnabled(false); - } else { - deleteTaskKeyAction->setEnabled(false); - deleteTestCaseKeyAction->setEnabled(true); - } -} - -void SummaryTree::itemChanged(QTreeWidgetItem *item) -{ - int index = indexOfTopLevelItem(item); - if (index != -1) { - Task *curTask = curContest->getTask(index); - curTask->setProblemTitle(item->text(0)); - } -} - -void SummaryTree::titleChanged(const QString &title) -{ - QTreeWidgetItem *curItem = currentItem(); - if (curItem) curItem->setText(0, title); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "summarytree.h" +#include "addtestcaseswizard.h" +#include "settings.h" +#include "contest.h" +#include "task.h" +#include "testcase.h" + +SummaryTree::SummaryTree(QWidget *parent) : + QTreeWidget(parent) +{ + curContest = 0; + addCount = 0; + + addTaskAction = new QAction(tr("Add a New Task"), this); + addTestCaseAction = new QAction(tr("Add a Test Case"), this); + addTestCasesAction = new QAction(tr("Add Test Cases ..."), this); + deleteTaskAction = new QAction(tr("Delete Current Task"), this); + deleteTestCaseAction = new QAction(tr("Delete Current Test Case"), this); + deleteTaskKeyAction = new QAction(this); + deleteTestCaseKeyAction = new QAction(this); + + deleteTaskKeyAction->setShortcutContext(Qt::WidgetShortcut); + deleteTestCaseKeyAction->setShortcutContext(Qt::WidgetShortcut); + deleteTaskKeyAction->setShortcut(QKeySequence::Delete); + deleteTestCaseKeyAction->setShortcut(QKeySequence::Delete); + deleteTaskKeyAction->setEnabled(false); + deleteTestCaseKeyAction->setEnabled(false); + addAction(deleteTaskKeyAction); + addAction(deleteTestCaseKeyAction); + + connect(addTaskAction, SIGNAL(triggered()), + this, SLOT(addTask())); + connect(addTestCaseAction, SIGNAL(triggered()), + this, SLOT(addTestCase())); + connect(addTestCasesAction, SIGNAL(triggered()), + this, SLOT(addTestCases())); + connect(deleteTaskAction, SIGNAL(triggered()), + this, SLOT(deleteTask())); + connect(deleteTestCaseAction, SIGNAL(triggered()), + this, SLOT(deleteTestCase())); + connect(deleteTaskKeyAction, SIGNAL(triggered()), + this, SLOT(deleteTask())); + connect(deleteTestCaseKeyAction, SIGNAL(triggered()), + this, SLOT(deleteTestCase())); + connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + this, SLOT(selectionChanged())); + connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)), + this, SLOT(itemChanged(QTreeWidgetItem*))); +} + +void SummaryTree::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) { + addTaskAction->setText(QApplication::translate("SummaryTree", "Add a New Task", + 0, QApplication::UnicodeUTF8)); + addTestCaseAction->setText(QApplication::translate("SummaryTree", "Add a Test Case", + 0, QApplication::UnicodeUTF8)); + addTestCasesAction->setText(QApplication::translate("SummaryTree", "Add Test Cases ...", + 0, QApplication::UnicodeUTF8)); + deleteTaskAction->setText(QApplication::translate("SummaryTree", "Delete Current Task", + 0, QApplication::UnicodeUTF8)); + deleteTestCaseAction->setText(QApplication::translate("SummaryTree", "Delete Current Test Case", + 0, QApplication::UnicodeUTF8)); + for (int i = 0; i < topLevelItemCount(); i ++) { + QTreeWidgetItem *taskItem = topLevelItem(i); + for (int j = 0; j < taskItem->childCount(); j ++) { + taskItem->child(j)->setText(0, QApplication::translate("SummaryTree", "Test Case #%1", + 0, QApplication::UnicodeUTF8).arg(j + 1)); + } + } + } +} + +void SummaryTree::setContest(Contest *contest) +{ + if (curContest) { + QList taskList = curContest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) + disconnect(taskList[i], SIGNAL(problemTitleChanged(QString)), + this, SLOT(titleChanged(QString))); + } + curContest = contest; + if (! curContest) return; + setEnabled(false); + clear(); + QList taskList = curContest->getTaskList(); + for (int i = 0; i < taskList.size(); i ++) { + connect(taskList[i], SIGNAL(problemTitleChanged(QString)), + this, SLOT(titleChanged(QString))); + QTreeWidgetItem *newTaskItem = new QTreeWidgetItem(this); + newTaskItem->setText(0, taskList[i]->getProblemTile()); + newTaskItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); + for (int j = 0; j < taskList[i]->getTestCaseList().size(); j ++) { + QTreeWidgetItem *newTestCaseItem = new QTreeWidgetItem(newTaskItem); + newTestCaseItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + newTestCaseItem->setText(0, tr("Test Case #%1").arg(newTaskItem->childCount())); + } + } + if (taskList.size() > 0) setCurrentItem(topLevelItem(0)); + setEnabled(true); + emit currentItemChanged(0, 0); +} + +void SummaryTree::setSettings(Settings *_settings) +{ + settings = _settings; +} + +void SummaryTree::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu *contextMenu = new QMenu(this); + + QTreeWidgetItem *curItem = currentItem(); + if (! curItem) { + contextMenu->addAction(addTaskAction); + contextMenu->exec(QCursor::pos()); + delete contextMenu; + return; + } + + int index = indexOfTopLevelItem(curItem); + if (index != -1) { + contextMenu->addAction(addTaskAction); + contextMenu->addAction(deleteTaskAction); + contextMenu->addSeparator(); + contextMenu->addAction(addTestCaseAction); + contextMenu->addAction(addTestCasesAction); + contextMenu->exec(QCursor::pos()); + delete contextMenu; + } else { + contextMenu->addAction(addTaskAction); + contextMenu->addAction(deleteTaskAction); + contextMenu->addSeparator(); + contextMenu->addAction(addTestCaseAction); + contextMenu->addAction(addTestCasesAction); + contextMenu->addAction(deleteTestCaseAction); + contextMenu->exec(QCursor::pos()); + delete contextMenu; + } +} + +void SummaryTree::addTask() +{ + Task *newTask = new Task; + newTask->setAnswerFileExtension(settings->getDefaultOutputFileExtension()); + curContest->addTask(newTask); + newTask->refreshCompilerConfiguration(settings); + connect(newTask, SIGNAL(problemTitleChanged(QString)), + this, SLOT(titleChanged(QString))); + QTreeWidgetItem *newItem = new QTreeWidgetItem(this); + setCurrentItem(newItem); + newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); + newItem->setText(0, tr("Problem %1").arg(++ addCount)); + editItem(newItem); +} + +void SummaryTree::addTestCase() +{ + QTreeWidgetItem *curItem = currentItem(); + if (indexOfTopLevelItem(curItem) == -1) + curItem = curItem->parent(); + int index = indexOfTopLevelItem(curItem); + Task *curTask = curContest->getTask(index); + TestCase *newTestCase = new TestCase; + newTestCase->setFullScore(settings->getDefaultFullScore()); + newTestCase->setTimeLimit(settings->getDefaultTimeLimit()); + newTestCase->setMemoryLimit(settings->getDefaultMemoryLimit()); + curTask->addTestCase(newTestCase); + QTreeWidgetItem *newItem = new QTreeWidgetItem(curItem); + newItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + newItem->setText(0, tr("Test Case #%1").arg(curItem->childCount())); + setCurrentItem(newItem); +} + +void SummaryTree::addTestCases() +{ + QTreeWidgetItem *curItem = currentItem(); + if (indexOfTopLevelItem(curItem) == -1) + curItem = curItem->parent(); + int index = indexOfTopLevelItem(curItem); + Task *curTask = curContest->getTask(index); + AddTestCasesWizard *wizard = new AddTestCasesWizard(this); + wizard->setSettings(settings, curTask->getTaskType() == Task::Traditional); + if (wizard->exec() == QDialog::Accepted) { + QList inputFiles = wizard->getMatchedInputFiles(); + QList outputFiles = wizard->getMatchedOutputFiles(); + for (int i = 0; i < inputFiles.size(); i ++) { + addTestCase(); + QTreeWidgetItem *curItem = currentItem(); + QTreeWidgetItem *parentItem = curItem->parent(); + int taskIndex = indexOfTopLevelItem(parentItem); + int testCaseIndex = parentItem->indexOfChild(curItem); + Task *curTask = curContest->getTask(taskIndex); + TestCase *curTestCase = curTask->getTestCase(testCaseIndex); + curTestCase->setFullScore(wizard->getFullScore()); + curTestCase->setTimeLimit(wizard->getTimeLimit()); + curTestCase->setMemoryLimit(wizard->getMemoryLimit()); + for (int j = 0; j < inputFiles[i].size(); j ++) + curTestCase->addSingleCase(inputFiles[i][j], outputFiles[i][j]); + setCurrentItem(parentItem); + setCurrentItem(curItem); + } + } + delete wizard; +} + +void SummaryTree::deleteTask() +{ + if (QMessageBox::warning(this, tr("Lemon"), tr("Are you sure to delete this task?"), + QMessageBox::Yes, QMessageBox::Cancel) == QMessageBox::Cancel) + return; + QTreeWidgetItem *curItem = currentItem(); + if (indexOfTopLevelItem(curItem) == -1) + curItem = curItem->parent(); + int index = indexOfTopLevelItem(curItem); + if (index + 1 < topLevelItemCount()) + setCurrentItem(topLevelItem(index + 1)); + else + if (index - 1 >= 0) + setCurrentItem(topLevelItem(index - 1)); + else + setCurrentItem(0); + delete curItem; + curContest->deleteTask(index); +} + +void SummaryTree::deleteTestCase() +{ + QTreeWidgetItem *curItem = currentItem(); + QTreeWidgetItem *parentItem = curItem->parent(); + int taskIndex = indexOfTopLevelItem(parentItem); + int testCaseIndex = parentItem->indexOfChild(curItem); + Task *curTask = curContest->getTask(taskIndex); + delete curItem; + curTask->deleteTestCase(testCaseIndex); + for (int i = 0; i < parentItem->childCount(); i ++) + parentItem->child(i)->setText(0, tr("Test Case #%1").arg(i + 1)); +} + +void SummaryTree::selectionChanged() +{ + if (! isEnabled()) return; + QTreeWidgetItem *curItem = currentItem(); + if (! curItem) { + deleteTaskKeyAction->setEnabled(false); + deleteTestCaseKeyAction->setEnabled(false); + return; + } + + int index = indexOfTopLevelItem(curItem); + if (index != -1) { + deleteTaskKeyAction->setEnabled(true); + deleteTestCaseKeyAction->setEnabled(false); + } else { + deleteTaskKeyAction->setEnabled(false); + deleteTestCaseKeyAction->setEnabled(true); + } +} + +void SummaryTree::itemChanged(QTreeWidgetItem *item) +{ + int index = indexOfTopLevelItem(item); + if (index != -1) { + Task *curTask = curContest->getTask(index); + curTask->setProblemTitle(item->text(0)); + } +} + +void SummaryTree::titleChanged(const QString &title) +{ + QTreeWidgetItem *curItem = currentItem(); + if (curItem) curItem->setText(0, title); +} diff --git a/summarytree.h b/summarytree.h index cd0441d..792c8b6 100644 --- a/summarytree.h +++ b/summarytree.h @@ -1,62 +1,62 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef SUMMARYTREE_H -#define SUMMARYTREE_H - -#include -#include -#include - -class Settings; -class Contest; - -class SummaryTree : public QTreeWidget -{ - Q_OBJECT -public: - explicit SummaryTree(QWidget *parent = 0); - void changeEvent(QEvent*); - void setContest(Contest*); - void setSettings(Settings*); - void contextMenuEvent(QContextMenuEvent*); - -private: - int addCount; - Contest *curContest; - Settings *settings; - QAction *addTaskAction; - QAction *addTestCaseAction; - QAction *addTestCasesAction; - QAction *deleteTaskAction; - QAction *deleteTestCaseAction; - QAction *deleteTaskKeyAction; - QAction *deleteTestCaseKeyAction; - -private slots: - void addTask(); - void addTestCase(); - void addTestCases(); - void deleteTask(); - void deleteTestCase(); - void selectionChanged(); - void itemChanged(QTreeWidgetItem*); - void titleChanged(const QString&); -}; - -#endif // SUMMARYTREE_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef SUMMARYTREE_H +#define SUMMARYTREE_H + +#include +#include +#include + +class Settings; +class Contest; + +class SummaryTree : public QTreeWidget +{ + Q_OBJECT +public: + explicit SummaryTree(QWidget *parent = 0); + void changeEvent(QEvent*); + void setContest(Contest*); + void setSettings(Settings*); + void contextMenuEvent(QContextMenuEvent*); + +private: + int addCount; + Contest *curContest; + Settings *settings; + QAction *addTaskAction; + QAction *addTestCaseAction; + QAction *addTestCasesAction; + QAction *deleteTaskAction; + QAction *deleteTestCaseAction; + QAction *deleteTaskKeyAction; + QAction *deleteTestCaseKeyAction; + +private slots: + void addTask(); + void addTestCase(); + void addTestCases(); + void deleteTask(); + void deleteTestCase(); + void selectionChanged(); + void itemChanged(QTreeWidgetItem*); + void titleChanged(const QString&); +}; + +#endif // SUMMARYTREE_H diff --git a/task.cpp b/task.cpp index 45d92fc..e8070c8 100644 --- a/task.cpp +++ b/task.cpp @@ -1,256 +1,256 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "task.h" -#include "testcase.h" -#include "settings.h" -#include "compiler.h" - -Task::Task(QObject *parent) : - QObject(parent) -{ - taskType = Traditional; - comparisonMode = LineByLineMode; - realPrecision = 3; - standardInputCheck = false; - standardOutputCheck = false; -} - -const QList& Task::getTestCaseList() const -{ - return testCaseList; -} - -const QString& Task::getProblemTile() const -{ - return problemTitle; -} - -const QString& Task::getSourceFileName() const -{ - return sourceFileName; -} - -const QString& Task::getInputFileName() const -{ - return inputFileName; -} - -const QString& Task::getOutputFileName() const -{ - return outputFileName; -} - -bool Task::getStandardInputCheck() const -{ - return standardInputCheck; -} - -bool Task::getStandardOutputCheck() const -{ - return standardOutputCheck; -} - -Task::TaskType Task::getTaskType() const -{ - return taskType; -} - -Task::ComparisonMode Task::getComparisonMode() const -{ - return comparisonMode; -} - -int Task::getRealPrecision() const -{ - return realPrecision; -} - -const QString& Task::getSpecialJudge() const -{ - return specialJudge; -} - -QString Task::getCompilerConfiguration(const QString &compilerName) const -{ - return compilerConfiguration.value(compilerName); -} - -const QString& Task::getAnswerFileExtension() const -{ - return answerFileExtension; -} - -void Task::setProblemTitle(const QString &title) -{ - bool changed = problemTitle != title; - problemTitle = title; - if (changed) emit problemTitleChanged(title); -} - -void Task::setSourceFileName(const QString &fileName) -{ - sourceFileName = fileName; -} - -void Task::setInputFileName(const QString &fileName) -{ - inputFileName = fileName; -} - -void Task::setOutputFileName(const QString &fileName) -{ - outputFileName = fileName; -} - -void Task::setStandardInputCheck(bool check) -{ - standardInputCheck = check; -} - -void Task::setStandardOutputCheck(bool check) -{ - standardOutputCheck = check; -} - -void Task::setTaskType(Task::TaskType type) -{ - taskType = type; -} - -void Task::setComparisonMode(Task::ComparisonMode mode) -{ - comparisonMode = mode; -} - -void Task::setRealPrecision(int precision) -{ - realPrecision = precision; -} - -void Task::setSpecialJudge(const QString &fileName) -{ - specialJudge = fileName; -} - -void Task::setCompilerConfiguration(const QString &compiler, const QString &configuration) -{ - compilerConfiguration.insert(compiler, configuration); -} - -void Task::setAnswerFileExtension(const QString &extension) -{ - answerFileExtension = extension; -} - -void Task::addTestCase(TestCase *testCase) -{ - testCase->setParent(this); - testCaseList.append(testCase); -} - -TestCase* Task::getTestCase(int index) const -{ - if (0 <= index && index < testCaseList.size()) - return testCaseList[index]; - else - return 0; -} - -void Task::deleteTestCase(int index) -{ - if (0 <= index && index < testCaseList.size()) { - delete testCaseList[index]; - testCaseList.removeAt(index); - } -} - -void Task::refreshCompilerConfiguration(Settings *settings) -{ - QList compilerList = settings->getCompilerList(); - QStringList compilerNames; - for (int i = 0; i < compilerList.size(); i ++) - compilerNames.append(compilerList[i]->getCompilerName()); - QMap::iterator p; - for (p = compilerConfiguration.begin(); p != compilerConfiguration.end(); ) - if (! compilerNames.contains(p.key())) - p = compilerConfiguration.erase(p); - else - p ++; - for (int i = 0; i < compilerList.size(); i ++) - if (compilerConfiguration.contains(compilerList[i]->getCompilerName())) { - const QString &config = compilerConfiguration.value(compilerList[i]->getCompilerName()); - const QStringList &configurationNames = compilerList[i]->getConfigurationNames(); - if (! configurationNames.contains(config)) - compilerConfiguration.insert(compilerList[i]->getCompilerName(), "default"); - } else - compilerConfiguration.insert(compilerList[i]->getCompilerName(), "default"); - emit compilerConfigurationRefreshed(); -} - -int Task::getTotalTimeLimit() const -{ - int total = 0; - for (int i = 0; i < testCaseList.size(); i ++) - total += testCaseList[i]->getTimeLimit() * testCaseList[i]->getInputFiles().size(); - return total; -} - -void Task::writeToStream(QDataStream &out) -{ - out << problemTitle; - out << sourceFileName; - out << inputFileName; - out << outputFileName; - out << standardInputCheck; - out << standardOutputCheck; - out << int(taskType); - out << int(comparisonMode); - out << realPrecision; - out << specialJudge; - out << compilerConfiguration; - out << answerFileExtension; - out << testCaseList.size(); - for (int i = 0; i < testCaseList.size(); i ++) - testCaseList[i]->writeToStream(out); -} - -void Task::readFromStream(QDataStream &in) -{ - int tmp, count; - in >> problemTitle; - in >> sourceFileName; - in >> inputFileName; - in >> outputFileName; - in >> standardInputCheck; - in >> standardOutputCheck; - in >> tmp; - taskType = TaskType(tmp); - in >> tmp; - comparisonMode = ComparisonMode(tmp); - in >> realPrecision; - in >> specialJudge; - in >> compilerConfiguration; - in >> answerFileExtension; - in >> count; - for (int i = 0; i < count; i ++) { - TestCase *newTestCase = new TestCase(this); - newTestCase->readFromStream(in); - testCaseList.append(newTestCase); - } -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "task.h" +#include "testcase.h" +#include "settings.h" +#include "compiler.h" + +Task::Task(QObject *parent) : + QObject(parent) +{ + taskType = Traditional; + comparisonMode = LineByLineMode; + realPrecision = 3; + standardInputCheck = false; + standardOutputCheck = false; +} + +const QList& Task::getTestCaseList() const +{ + return testCaseList; +} + +const QString& Task::getProblemTile() const +{ + return problemTitle; +} + +const QString& Task::getSourceFileName() const +{ + return sourceFileName; +} + +const QString& Task::getInputFileName() const +{ + return inputFileName; +} + +const QString& Task::getOutputFileName() const +{ + return outputFileName; +} + +bool Task::getStandardInputCheck() const +{ + return standardInputCheck; +} + +bool Task::getStandardOutputCheck() const +{ + return standardOutputCheck; +} + +Task::TaskType Task::getTaskType() const +{ + return taskType; +} + +Task::ComparisonMode Task::getComparisonMode() const +{ + return comparisonMode; +} + +int Task::getRealPrecision() const +{ + return realPrecision; +} + +const QString& Task::getSpecialJudge() const +{ + return specialJudge; +} + +QString Task::getCompilerConfiguration(const QString &compilerName) const +{ + return compilerConfiguration.value(compilerName); +} + +const QString& Task::getAnswerFileExtension() const +{ + return answerFileExtension; +} + +void Task::setProblemTitle(const QString &title) +{ + bool changed = problemTitle != title; + problemTitle = title; + if (changed) emit problemTitleChanged(title); +} + +void Task::setSourceFileName(const QString &fileName) +{ + sourceFileName = fileName; +} + +void Task::setInputFileName(const QString &fileName) +{ + inputFileName = fileName; +} + +void Task::setOutputFileName(const QString &fileName) +{ + outputFileName = fileName; +} + +void Task::setStandardInputCheck(bool check) +{ + standardInputCheck = check; +} + +void Task::setStandardOutputCheck(bool check) +{ + standardOutputCheck = check; +} + +void Task::setTaskType(Task::TaskType type) +{ + taskType = type; +} + +void Task::setComparisonMode(Task::ComparisonMode mode) +{ + comparisonMode = mode; +} + +void Task::setRealPrecision(int precision) +{ + realPrecision = precision; +} + +void Task::setSpecialJudge(const QString &fileName) +{ + specialJudge = fileName; +} + +void Task::setCompilerConfiguration(const QString &compiler, const QString &configuration) +{ + compilerConfiguration.insert(compiler, configuration); +} + +void Task::setAnswerFileExtension(const QString &extension) +{ + answerFileExtension = extension; +} + +void Task::addTestCase(TestCase *testCase) +{ + testCase->setParent(this); + testCaseList.append(testCase); +} + +TestCase* Task::getTestCase(int index) const +{ + if (0 <= index && index < testCaseList.size()) + return testCaseList[index]; + else + return 0; +} + +void Task::deleteTestCase(int index) +{ + if (0 <= index && index < testCaseList.size()) { + delete testCaseList[index]; + testCaseList.removeAt(index); + } +} + +void Task::refreshCompilerConfiguration(Settings *settings) +{ + QList compilerList = settings->getCompilerList(); + QStringList compilerNames; + for (int i = 0; i < compilerList.size(); i ++) + compilerNames.append(compilerList[i]->getCompilerName()); + QMap::iterator p; + for (p = compilerConfiguration.begin(); p != compilerConfiguration.end(); ) + if (! compilerNames.contains(p.key())) + p = compilerConfiguration.erase(p); + else + p ++; + for (int i = 0; i < compilerList.size(); i ++) + if (compilerConfiguration.contains(compilerList[i]->getCompilerName())) { + const QString &config = compilerConfiguration.value(compilerList[i]->getCompilerName()); + const QStringList &configurationNames = compilerList[i]->getConfigurationNames(); + if (! configurationNames.contains(config)) + compilerConfiguration.insert(compilerList[i]->getCompilerName(), "default"); + } else + compilerConfiguration.insert(compilerList[i]->getCompilerName(), "default"); + emit compilerConfigurationRefreshed(); +} + +int Task::getTotalTimeLimit() const +{ + int total = 0; + for (int i = 0; i < testCaseList.size(); i ++) + total += testCaseList[i]->getTimeLimit() * testCaseList[i]->getInputFiles().size(); + return total; +} + +void Task::writeToStream(QDataStream &out) +{ + out << problemTitle; + out << sourceFileName; + out << inputFileName; + out << outputFileName; + out << standardInputCheck; + out << standardOutputCheck; + out << int(taskType); + out << int(comparisonMode); + out << realPrecision; + out << specialJudge; + out << compilerConfiguration; + out << answerFileExtension; + out << testCaseList.size(); + for (int i = 0; i < testCaseList.size(); i ++) + testCaseList[i]->writeToStream(out); +} + +void Task::readFromStream(QDataStream &in) +{ + int tmp, count; + in >> problemTitle; + in >> sourceFileName; + in >> inputFileName; + in >> outputFileName; + in >> standardInputCheck; + in >> standardOutputCheck; + in >> tmp; + taskType = TaskType(tmp); + in >> tmp; + comparisonMode = ComparisonMode(tmp); + in >> realPrecision; + in >> specialJudge; + in >> compilerConfiguration; + in >> answerFileExtension; + in >> count; + for (int i = 0; i < count; i ++) { + TestCase *newTestCase = new TestCase(this); + newTestCase->readFromStream(in); + testCaseList.append(newTestCase); + } +} diff --git a/task.h b/task.h index 02518b5..5aa901c 100644 --- a/task.h +++ b/task.h @@ -1,92 +1,92 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef TASK_H -#define TASK_H - -#include -#include - -class TestCase; -class Settings; - -class Task : public QObject -{ - Q_OBJECT -public: - enum TaskType { Traditional, AnswersOnly }; - enum ComparisonMode { LineByLineMode, RealNumberMode, SpecialJudgeMode }; - - explicit Task(QObject *parent = 0); - - const QList& getTestCaseList() const; - const QString& getProblemTile() const; - const QString& getSourceFileName() const; - const QString& getInputFileName() const; - const QString& getOutputFileName() const; - bool getStandardInputCheck() const; - bool getStandardOutputCheck() const; - TaskType getTaskType() const; - ComparisonMode getComparisonMode() const; - int getRealPrecision() const; - const QString& getSpecialJudge() const; - QString getCompilerConfiguration(const QString&) const; - const QString& getAnswerFileExtension() const; - - void setProblemTitle(const QString&); - void setSourceFileName(const QString&); - void setInputFileName(const QString&); - void setOutputFileName(const QString&); - void setStandardInputCheck(bool); - void setStandardOutputCheck(bool); - void setTaskType(TaskType); - void setComparisonMode(ComparisonMode); - void setRealPrecision(int); - void setSpecialJudge(const QString&); - void setCompilerConfiguration(const QString&, const QString&); - void setAnswerFileExtension(const QString&); - - void addTestCase(TestCase*); - TestCase* getTestCase(int) const; - void deleteTestCase(int); - void refreshCompilerConfiguration(Settings*); - int getTotalTimeLimit() const; - void writeToStream(QDataStream&); - void readFromStream(QDataStream&); - -private: - QList testCaseList; - QString problemTitle; - QString sourceFileName; - QString inputFileName; - QString outputFileName; - bool standardInputCheck; - bool standardOutputCheck; - TaskType taskType; - ComparisonMode comparisonMode; - int realPrecision; - QString specialJudge; - QMap compilerConfiguration; - QString answerFileExtension; - -signals: - void problemTitleChanged(const QString&); - void compilerConfigurationRefreshed(); -}; - -#endif // TASK_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef TASK_H +#define TASK_H + +#include +#include + +class TestCase; +class Settings; + +class Task : public QObject +{ + Q_OBJECT +public: + enum TaskType { Traditional, AnswersOnly }; + enum ComparisonMode { LineByLineMode, RealNumberMode, SpecialJudgeMode }; + + explicit Task(QObject *parent = 0); + + const QList& getTestCaseList() const; + const QString& getProblemTile() const; + const QString& getSourceFileName() const; + const QString& getInputFileName() const; + const QString& getOutputFileName() const; + bool getStandardInputCheck() const; + bool getStandardOutputCheck() const; + TaskType getTaskType() const; + ComparisonMode getComparisonMode() const; + int getRealPrecision() const; + const QString& getSpecialJudge() const; + QString getCompilerConfiguration(const QString&) const; + const QString& getAnswerFileExtension() const; + + void setProblemTitle(const QString&); + void setSourceFileName(const QString&); + void setInputFileName(const QString&); + void setOutputFileName(const QString&); + void setStandardInputCheck(bool); + void setStandardOutputCheck(bool); + void setTaskType(TaskType); + void setComparisonMode(ComparisonMode); + void setRealPrecision(int); + void setSpecialJudge(const QString&); + void setCompilerConfiguration(const QString&, const QString&); + void setAnswerFileExtension(const QString&); + + void addTestCase(TestCase*); + TestCase* getTestCase(int) const; + void deleteTestCase(int); + void refreshCompilerConfiguration(Settings*); + int getTotalTimeLimit() const; + void writeToStream(QDataStream&); + void readFromStream(QDataStream&); + +private: + QList testCaseList; + QString problemTitle; + QString sourceFileName; + QString inputFileName; + QString outputFileName; + bool standardInputCheck; + bool standardOutputCheck; + TaskType taskType; + ComparisonMode comparisonMode; + int realPrecision; + QString specialJudge; + QMap compilerConfiguration; + QString answerFileExtension; + +signals: + void problemTitleChanged(const QString&); + void compilerConfigurationRefreshed(); +}; + +#endif // TASK_H diff --git a/taskeditwidget.cpp b/taskeditwidget.cpp index 9e42974..ec48704 100644 --- a/taskeditwidget.cpp +++ b/taskeditwidget.cpp @@ -1,276 +1,276 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "taskeditwidget.h" -#include "ui_taskeditwidget.h" -#include "settings.h" -#include "compiler.h" -#include "task.h" - -TaskEditWidget::TaskEditWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::TaskEditWidget) -{ - ui->setupUi(this); - - editTask = 0; - - ui->specialJudge->setFilters(QDir::Files | QDir::Executable); - connect(this, SIGNAL(dataPathChanged()), - ui->specialJudge, SLOT(refreshFileList())); - - ui->sourceFileName->setValidator(new QRegExpValidator(QRegExp("\\w+"), ui->sourceFileName)); - ui->inputFileName->setValidator(new QRegExpValidator(QRegExp("(\\w+)(\\.\\w+)?"), ui->inputFileName)); - ui->outputFileName->setValidator(new QRegExpValidator(QRegExp("(\\w+)(\\.\\w+)?"), ui->outputFileName)); - ui->answerFileExtension->setValidator(new QRegExpValidator(QRegExp("\\w+"), ui->answerFileExtension)); - - connect(ui->problemTitle, SIGNAL(textChanged(QString)), - this, SLOT(problemTitleChanged(QString))); - connect(ui->traditionalButton, SIGNAL(toggled(bool)), - this, SLOT(setToTraditional(bool))); - connect(ui->answersOnlyButton, SIGNAL(toggled(bool)), - this, SLOT(setToAnswersOnly(bool))); - connect(ui->sourceFileName, SIGNAL(textChanged(QString)), - this, SLOT(sourceFileNameChanged(QString))); - connect(ui->inputFileName, SIGNAL(textChanged(QString)), - this, SLOT(inputFileNameChanged(QString))); - connect(ui->outputFileName, SIGNAL(textChanged(QString)), - this, SLOT(outputFileNameChanged(QString))); - connect(ui->standardInputCheck, SIGNAL(stateChanged(int)), - this, SLOT(standardInputCheckChanged())); - connect(ui->standardOutputCheck, SIGNAL(stateChanged(int)), - this, SLOT(standardOutputCheckChanged())); - connect(ui->comparisonMode, SIGNAL(currentIndexChanged(int)), - this, SLOT(comparisonModeChanged())); - connect(ui->realPrecision, SIGNAL(valueChanged(int)), - this, SLOT(realPrecisionChanged(int))); - connect(ui->specialJudge, SIGNAL(textChanged(QString)), - this, SLOT(specialJudgeChanged(QString))); - connect(ui->compilersList, SIGNAL(currentRowChanged(int)), - this, SLOT(compilerSelectionChanged())); - connect(ui->configurationSelect, SIGNAL(currentIndexChanged(int)), - this, SLOT(configurationSelectionChanged())); - connect(ui->answerFileExtension, SIGNAL(textChanged(QString)), - this, SLOT(answerFileExtensionChanged(QString))); -} - -TaskEditWidget::~TaskEditWidget() -{ - delete ui; -} - -void TaskEditWidget::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::LanguageChange) { - Task *bak = editTask; - setEditTask(0); - ui->retranslateUi(this); - setEditTask(bak); - } -} - -void TaskEditWidget::setEditTask(Task *task) -{ - if (editTask) { - disconnect(editTask, SIGNAL(problemTitleChanged(QString)), - this, SLOT(refreshProblemTitle(QString))); - disconnect(editTask, SIGNAL(compilerConfigurationRefreshed()), - this, SLOT(refreshCompilerConfiguration())); - } - editTask = task; - if (! task) return; - connect(editTask, SIGNAL(problemTitleChanged(QString)), - this, SLOT(refreshProblemTitle(QString))); - connect(editTask, SIGNAL(compilerConfigurationRefreshed()), - this, SLOT(refreshCompilerConfiguration())); - ui->problemTitle->setText(editTask->getProblemTile()); - ui->sourceFileName->setEnabled(false); - ui->sourceFileName->setText(editTask->getSourceFileName()); - ui->sourceFileName->setEnabled(true); - ui->inputFileName->setText(editTask->getInputFileName()); - ui->outputFileName->setText(editTask->getOutputFileName()); - ui->comparisonMode->setCurrentIndex(int(editTask->getComparisonMode())); - ui->realPrecision->setValue(editTask->getRealPrecision()); - ui->specialJudge->setText(editTask->getSpecialJudge()); - ui->standardInputCheck->setChecked(editTask->getStandardInputCheck()); - ui->standardOutputCheck->setChecked(editTask->getStandardOutputCheck()); - ui->answerFileExtension->setText(editTask->getAnswerFileExtension()); - refreshCompilerConfiguration(); - if (editTask->getTaskType() == Task::Traditional) - ui->traditionalButton->setChecked(true); - if (editTask->getTaskType() == Task::AnswersOnly) - ui->answersOnlyButton->setChecked(true); - refreshWidgetState(); -} - -void TaskEditWidget::setSettings(Settings *_settings) -{ - settings = _settings; -} - -void TaskEditWidget::refreshWidgetState() -{ - if (! editTask) return; - bool check = editTask->getTaskType() == Task::Traditional; - ui->sourceFileName->setEnabled(check); - ui->sourceFileNameLabel->setEnabled(check); - ui->inputFileName->setEnabled(check && ! editTask->getStandardInputCheck()); - ui->inputFileNameLabel->setEnabled(check); - ui->standardInputCheck->setEnabled(check); - ui->outputFileName->setEnabled(check && ! editTask->getStandardOutputCheck()); - ui->outputFileNameLabel->setEnabled(check); - ui->standardOutputCheck->setEnabled(check); - ui->compilerSettingsLabel->setEnabled(check); - ui->compilersList->setEnabled(check); - ui->configurationLabel->setEnabled(check); - ui->configurationSelect->setEditable(check); - ui->answerFileExtension->setEnabled(! check); - ui->answerFileExtensionLabel->setEnabled(! check); -} - -void TaskEditWidget::problemTitleChanged(const QString &text) -{ - if (! editTask) return; - editTask->setProblemTitle(text); -} - -void TaskEditWidget::setToTraditional(bool check) -{ - if (! check || ! editTask) return; - editTask->setTaskType(Task::Traditional); - refreshWidgetState(); -} - -void TaskEditWidget::setToAnswersOnly(bool check) -{ - if (! check || ! editTask) return; - editTask->setTaskType(Task::AnswersOnly); - refreshWidgetState(); -} - -void TaskEditWidget::sourceFileNameChanged(const QString &text) -{ - if (! editTask) return; - if (! ui->sourceFileName->isEnabled()) return; - editTask->setSourceFileName(text); - if (ui->inputFileName->isEnabled()) - ui->inputFileName->setText(text + "." + settings->getDefaultInputFileExtension()); - if (ui->outputFileName->isEnabled()) - ui->outputFileName->setText(text + "." + settings->getDefaultOutputFileExtension()); -} - -void TaskEditWidget::inputFileNameChanged(const QString &text) -{ - if (! editTask) return; - editTask->setInputFileName(text); -} - -void TaskEditWidget::outputFileNameChanged(const QString &text) -{ - if (! editTask) return; - editTask->setOutputFileName(text); -} - -void TaskEditWidget::standardInputCheckChanged() -{ - if (! editTask) return; - bool check = ui->standardInputCheck->isChecked(); - editTask->setStandardInputCheck(check); - ui->inputFileName->setEnabled(! check); -} - -void TaskEditWidget::standardOutputCheckChanged() -{ - if (! editTask) return; - bool check = ui->standardOutputCheck->isChecked(); - editTask->setStandardOutputCheck(check); - ui->outputFileName->setEnabled(! check); -} - -void TaskEditWidget::comparisonModeChanged() -{ - if (! editTask) return; - editTask->setComparisonMode(Task::ComparisonMode(ui->comparisonMode->currentIndex())); -} - -void TaskEditWidget::realPrecisionChanged(int precision) -{ - if (! editTask) return; - editTask->setRealPrecision(precision); -} - -void TaskEditWidget::specialJudgeChanged(const QString &text) -{ - if (! editTask) return; - editTask->setSpecialJudge(text); -} - -void TaskEditWidget::refreshProblemTitle(const QString &title) -{ - if (! editTask) return; - ui->problemTitle->setText(title); -} - -void TaskEditWidget::refreshCompilerConfiguration() -{ - if (! editTask) return; - ui->compilersList->setEnabled(false); - ui->configurationSelect->setEnabled(false); - ui->configurationLabel->setEnabled(false); - ui->compilersList->clear(); - ui->configurationSelect->clear(); - const QList &compilerList = settings->getCompilerList(); - if (compilerList.isEmpty()) return; - for (int i = 0; i < compilerList.size(); i ++) - ui->compilersList->addItem(compilerList[i]->getCompilerName()); - ui->compilersList->setEnabled(true); - ui->configurationSelect->setEnabled(true); - ui->configurationLabel->setEnabled(true); - ui->compilersList->setCurrentRow(0); - compilerSelectionChanged(); -} - -void TaskEditWidget::compilerSelectionChanged() -{ - if (! editTask) return; - if (! ui->compilersList->isEnabled()) return; - ui->configurationSelect->setEnabled(false); - ui->configurationSelect->clear(); - ui->configurationSelect->addItem("disable"); - const QList &compilerList = settings->getCompilerList(); - for (int i = 0; i < compilerList.size(); i ++) - if (compilerList[i]->getCompilerName() == ui->compilersList->currentItem()->text()) - ui->configurationSelect->addItems(compilerList[i]->getConfigurationNames()); - QString config = editTask->getCompilerConfiguration(ui->compilersList->currentItem()->text()); - ui->configurationSelect->setCurrentIndex(ui->configurationSelect->findText(config)); - ui->configurationSelect->setEnabled(true); -} - -void TaskEditWidget::configurationSelectionChanged() -{ - if (! editTask) return; - if (! ui->configurationSelect->isEnabled()) return; - editTask->setCompilerConfiguration(ui->compilersList->currentItem()->text(), - ui->configurationSelect->currentText()); -} - -void TaskEditWidget::answerFileExtensionChanged(const QString &extension) -{ - if (! editTask) return; - editTask->setAnswerFileExtension(extension); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "taskeditwidget.h" +#include "ui_taskeditwidget.h" +#include "settings.h" +#include "compiler.h" +#include "task.h" + +TaskEditWidget::TaskEditWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::TaskEditWidget) +{ + ui->setupUi(this); + + editTask = 0; + + ui->specialJudge->setFilters(QDir::Files | QDir::Executable); + connect(this, SIGNAL(dataPathChanged()), + ui->specialJudge, SLOT(refreshFileList())); + + ui->sourceFileName->setValidator(new QRegExpValidator(QRegExp("\\w+"), ui->sourceFileName)); + ui->inputFileName->setValidator(new QRegExpValidator(QRegExp("(\\w+)(\\.\\w+)?"), ui->inputFileName)); + ui->outputFileName->setValidator(new QRegExpValidator(QRegExp("(\\w+)(\\.\\w+)?"), ui->outputFileName)); + ui->answerFileExtension->setValidator(new QRegExpValidator(QRegExp("\\w+"), ui->answerFileExtension)); + + connect(ui->problemTitle, SIGNAL(textChanged(QString)), + this, SLOT(problemTitleChanged(QString))); + connect(ui->traditionalButton, SIGNAL(toggled(bool)), + this, SLOT(setToTraditional(bool))); + connect(ui->answersOnlyButton, SIGNAL(toggled(bool)), + this, SLOT(setToAnswersOnly(bool))); + connect(ui->sourceFileName, SIGNAL(textChanged(QString)), + this, SLOT(sourceFileNameChanged(QString))); + connect(ui->inputFileName, SIGNAL(textChanged(QString)), + this, SLOT(inputFileNameChanged(QString))); + connect(ui->outputFileName, SIGNAL(textChanged(QString)), + this, SLOT(outputFileNameChanged(QString))); + connect(ui->standardInputCheck, SIGNAL(stateChanged(int)), + this, SLOT(standardInputCheckChanged())); + connect(ui->standardOutputCheck, SIGNAL(stateChanged(int)), + this, SLOT(standardOutputCheckChanged())); + connect(ui->comparisonMode, SIGNAL(currentIndexChanged(int)), + this, SLOT(comparisonModeChanged())); + connect(ui->realPrecision, SIGNAL(valueChanged(int)), + this, SLOT(realPrecisionChanged(int))); + connect(ui->specialJudge, SIGNAL(textChanged(QString)), + this, SLOT(specialJudgeChanged(QString))); + connect(ui->compilersList, SIGNAL(currentRowChanged(int)), + this, SLOT(compilerSelectionChanged())); + connect(ui->configurationSelect, SIGNAL(currentIndexChanged(int)), + this, SLOT(configurationSelectionChanged())); + connect(ui->answerFileExtension, SIGNAL(textChanged(QString)), + this, SLOT(answerFileExtensionChanged(QString))); +} + +TaskEditWidget::~TaskEditWidget() +{ + delete ui; +} + +void TaskEditWidget::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) { + Task *bak = editTask; + setEditTask(0); + ui->retranslateUi(this); + setEditTask(bak); + } +} + +void TaskEditWidget::setEditTask(Task *task) +{ + if (editTask) { + disconnect(editTask, SIGNAL(problemTitleChanged(QString)), + this, SLOT(refreshProblemTitle(QString))); + disconnect(editTask, SIGNAL(compilerConfigurationRefreshed()), + this, SLOT(refreshCompilerConfiguration())); + } + editTask = task; + if (! task) return; + connect(editTask, SIGNAL(problemTitleChanged(QString)), + this, SLOT(refreshProblemTitle(QString))); + connect(editTask, SIGNAL(compilerConfigurationRefreshed()), + this, SLOT(refreshCompilerConfiguration())); + ui->problemTitle->setText(editTask->getProblemTile()); + ui->sourceFileName->setEnabled(false); + ui->sourceFileName->setText(editTask->getSourceFileName()); + ui->sourceFileName->setEnabled(true); + ui->inputFileName->setText(editTask->getInputFileName()); + ui->outputFileName->setText(editTask->getOutputFileName()); + ui->comparisonMode->setCurrentIndex(int(editTask->getComparisonMode())); + ui->realPrecision->setValue(editTask->getRealPrecision()); + ui->specialJudge->setText(editTask->getSpecialJudge()); + ui->standardInputCheck->setChecked(editTask->getStandardInputCheck()); + ui->standardOutputCheck->setChecked(editTask->getStandardOutputCheck()); + ui->answerFileExtension->setText(editTask->getAnswerFileExtension()); + refreshCompilerConfiguration(); + if (editTask->getTaskType() == Task::Traditional) + ui->traditionalButton->setChecked(true); + if (editTask->getTaskType() == Task::AnswersOnly) + ui->answersOnlyButton->setChecked(true); + refreshWidgetState(); +} + +void TaskEditWidget::setSettings(Settings *_settings) +{ + settings = _settings; +} + +void TaskEditWidget::refreshWidgetState() +{ + if (! editTask) return; + bool check = editTask->getTaskType() == Task::Traditional; + ui->sourceFileName->setEnabled(check); + ui->sourceFileNameLabel->setEnabled(check); + ui->inputFileName->setEnabled(check && ! editTask->getStandardInputCheck()); + ui->inputFileNameLabel->setEnabled(check); + ui->standardInputCheck->setEnabled(check); + ui->outputFileName->setEnabled(check && ! editTask->getStandardOutputCheck()); + ui->outputFileNameLabel->setEnabled(check); + ui->standardOutputCheck->setEnabled(check); + ui->compilerSettingsLabel->setEnabled(check); + ui->compilersList->setEnabled(check); + ui->configurationLabel->setEnabled(check); + ui->configurationSelect->setEditable(check); + ui->answerFileExtension->setEnabled(! check); + ui->answerFileExtensionLabel->setEnabled(! check); +} + +void TaskEditWidget::problemTitleChanged(const QString &text) +{ + if (! editTask) return; + editTask->setProblemTitle(text); +} + +void TaskEditWidget::setToTraditional(bool check) +{ + if (! check || ! editTask) return; + editTask->setTaskType(Task::Traditional); + refreshWidgetState(); +} + +void TaskEditWidget::setToAnswersOnly(bool check) +{ + if (! check || ! editTask) return; + editTask->setTaskType(Task::AnswersOnly); + refreshWidgetState(); +} + +void TaskEditWidget::sourceFileNameChanged(const QString &text) +{ + if (! editTask) return; + if (! ui->sourceFileName->isEnabled()) return; + editTask->setSourceFileName(text); + if (ui->inputFileName->isEnabled()) + ui->inputFileName->setText(text + "." + settings->getDefaultInputFileExtension()); + if (ui->outputFileName->isEnabled()) + ui->outputFileName->setText(text + "." + settings->getDefaultOutputFileExtension()); +} + +void TaskEditWidget::inputFileNameChanged(const QString &text) +{ + if (! editTask) return; + editTask->setInputFileName(text); +} + +void TaskEditWidget::outputFileNameChanged(const QString &text) +{ + if (! editTask) return; + editTask->setOutputFileName(text); +} + +void TaskEditWidget::standardInputCheckChanged() +{ + if (! editTask) return; + bool check = ui->standardInputCheck->isChecked(); + editTask->setStandardInputCheck(check); + ui->inputFileName->setEnabled(! check); +} + +void TaskEditWidget::standardOutputCheckChanged() +{ + if (! editTask) return; + bool check = ui->standardOutputCheck->isChecked(); + editTask->setStandardOutputCheck(check); + ui->outputFileName->setEnabled(! check); +} + +void TaskEditWidget::comparisonModeChanged() +{ + if (! editTask) return; + editTask->setComparisonMode(Task::ComparisonMode(ui->comparisonMode->currentIndex())); +} + +void TaskEditWidget::realPrecisionChanged(int precision) +{ + if (! editTask) return; + editTask->setRealPrecision(precision); +} + +void TaskEditWidget::specialJudgeChanged(const QString &text) +{ + if (! editTask) return; + editTask->setSpecialJudge(text); +} + +void TaskEditWidget::refreshProblemTitle(const QString &title) +{ + if (! editTask) return; + ui->problemTitle->setText(title); +} + +void TaskEditWidget::refreshCompilerConfiguration() +{ + if (! editTask) return; + ui->compilersList->setEnabled(false); + ui->configurationSelect->setEnabled(false); + ui->configurationLabel->setEnabled(false); + ui->compilersList->clear(); + ui->configurationSelect->clear(); + const QList &compilerList = settings->getCompilerList(); + if (compilerList.isEmpty()) return; + for (int i = 0; i < compilerList.size(); i ++) + ui->compilersList->addItem(compilerList[i]->getCompilerName()); + ui->compilersList->setEnabled(true); + ui->configurationSelect->setEnabled(true); + ui->configurationLabel->setEnabled(true); + ui->compilersList->setCurrentRow(0); + compilerSelectionChanged(); +} + +void TaskEditWidget::compilerSelectionChanged() +{ + if (! editTask) return; + if (! ui->compilersList->isEnabled()) return; + ui->configurationSelect->setEnabled(false); + ui->configurationSelect->clear(); + ui->configurationSelect->addItem("disable"); + const QList &compilerList = settings->getCompilerList(); + for (int i = 0; i < compilerList.size(); i ++) + if (compilerList[i]->getCompilerName() == ui->compilersList->currentItem()->text()) + ui->configurationSelect->addItems(compilerList[i]->getConfigurationNames()); + QString config = editTask->getCompilerConfiguration(ui->compilersList->currentItem()->text()); + ui->configurationSelect->setCurrentIndex(ui->configurationSelect->findText(config)); + ui->configurationSelect->setEnabled(true); +} + +void TaskEditWidget::configurationSelectionChanged() +{ + if (! editTask) return; + if (! ui->configurationSelect->isEnabled()) return; + editTask->setCompilerConfiguration(ui->compilersList->currentItem()->text(), + ui->configurationSelect->currentText()); +} + +void TaskEditWidget::answerFileExtensionChanged(const QString &extension) +{ + if (! editTask) return; + editTask->setAnswerFileExtension(extension); +} diff --git a/taskeditwidget.h b/taskeditwidget.h index 843bfcb..dd7f565 100644 --- a/taskeditwidget.h +++ b/taskeditwidget.h @@ -1,72 +1,72 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef TASKEDITWIDGET_H -#define TASKEDITWIDGET_H - -#include -#include -#include - -namespace Ui { - class TaskEditWidget; -} - -class Settings; -class Task; - -class TaskEditWidget : public QWidget -{ - Q_OBJECT - -public: - explicit TaskEditWidget(QWidget *parent = 0); - ~TaskEditWidget(); - void changeEvent(QEvent*); - void setEditTask(Task*); - void setSettings(Settings*); - -private: - Ui::TaskEditWidget *ui; - Settings *settings; - Task *editTask; - void refreshWidgetState(); - -private slots: - void problemTitleChanged(const QString&); - void setToTraditional(bool); - void setToAnswersOnly(bool); - void sourceFileNameChanged(const QString&); - void inputFileNameChanged(const QString&); - void outputFileNameChanged(const QString&); - void standardInputCheckChanged(); - void standardOutputCheckChanged(); - void comparisonModeChanged(); - void realPrecisionChanged(int); - void specialJudgeChanged(const QString&); - void refreshProblemTitle(const QString&); - void refreshCompilerConfiguration(); - void compilerSelectionChanged(); - void configurationSelectionChanged(); - void answerFileExtensionChanged(const QString&); - -signals: - void dataPathChanged(); -}; - -#endif // TASKEDITWIDGET_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef TASKEDITWIDGET_H +#define TASKEDITWIDGET_H + +#include +#include +#include + +namespace Ui { + class TaskEditWidget; +} + +class Settings; +class Task; + +class TaskEditWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TaskEditWidget(QWidget *parent = 0); + ~TaskEditWidget(); + void changeEvent(QEvent*); + void setEditTask(Task*); + void setSettings(Settings*); + +private: + Ui::TaskEditWidget *ui; + Settings *settings; + Task *editTask; + void refreshWidgetState(); + +private slots: + void problemTitleChanged(const QString&); + void setToTraditional(bool); + void setToAnswersOnly(bool); + void sourceFileNameChanged(const QString&); + void inputFileNameChanged(const QString&); + void outputFileNameChanged(const QString&); + void standardInputCheckChanged(); + void standardOutputCheckChanged(); + void comparisonModeChanged(); + void realPrecisionChanged(int); + void specialJudgeChanged(const QString&); + void refreshProblemTitle(const QString&); + void refreshCompilerConfiguration(); + void compilerSelectionChanged(); + void configurationSelectionChanged(); + void answerFileExtensionChanged(const QString&); + +signals: + void dataPathChanged(); +}; + +#endif // TASKEDITWIDGET_H diff --git a/taskeditwidget.ui b/taskeditwidget.ui index 3e7b714..d1e9bf2 100644 --- a/taskeditwidget.ui +++ b/taskeditwidget.ui @@ -1,483 +1,486 @@ - - - TaskEditWidget - - - - 0 - 0 - 443 - 438 - - - - Form - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Problem Title - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Task Type - - - - - - - 12 - - - - - font-size: 9pt; - - - Traditional - - - - - - - font-size: 9pt; - - - Answers Only - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Source File Name - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Input File Name - - - - - - - - - - font-size: 9pt; - - - Standard input - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Output File Name - - - - - - - - - - font-size: 9pt; - - - Standard output - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Comparison Mode - - - - - - - font-size: 9pt; - - - - Line-by-line mode - - - - - Real number mode - - - - - Special judge mode - - - - - - - - - 0 - 0 - - - - 0 - - - - - - - - - 0 - 0 - - - - font: 8pt "MS Shell Dlg 2"; - - - Real Number Precision: - - - - - - - 18 - - - 3 - - - - - - - - 0 - 0 - - - - font: 8pt "MS Shell Dlg 2"; - - - - digits - - - - - - - Qt::Horizontal - - - - 96 - 20 - - - - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - - 143 - 18 - - - - - 143 - 18 - - - - font-size: 9pt; -font-weight: bold; - - - Compiler Settings - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - 12 - - - - - - - - 15 - - - - - false - - - - 0 - 0 - - - - font-size: 9pt; - - - Configuration: - - - - - - - false - - - - - - - - - - - 10 - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Extension of Contestant's Answer File - - - - - - - - 0 - 0 - - - - - 61 - 22 - - - - - 61 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - FileLineEdit - QLineEdit -
filelineedit.h
-
-
- - problemTitle - sourceFileName - inputFileName - standardInputCheck - outputFileName - standardOutputCheck - comparisonMode - compilersList - configurationSelect - specialJudge - realPrecision - - - - - comparisonMode - currentIndexChanged(int) - comparisonSetting - setCurrentIndex(int) - - - 329 - 202 - - - 329 - 245 - - - - -
+ + + TaskEditWidget + + + + 0 + 0 + 443 + 438 + + + + Form + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Problem Title + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Task Type + + + + + + + 12 + + + + + font-size: 9pt; + + + Traditional + + + + + + + font-size: 9pt; + + + Answers Only + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Source File Name + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Input File Name + + + + + + + + + + font-size: 9pt; + + + Standard input + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Output File Name + + + + + + + + + + font-size: 9pt; + + + Standard output + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Comparison Mode + + + + + + + font-size: 9pt; + + + + Line-by-line mode + + + + + Real number mode + + + + + Special judge mode + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + + 0 + 0 + + + + font: 8pt "MS Shell Dlg 2"; + + + Real Number Precision: + + + + + + + 18 + + + 3 + + + + + + + + 0 + 0 + + + + font: 8pt "MS Shell Dlg 2"; + + + + digits + + + + + + + Qt::Horizontal + + + + 96 + 20 + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 143 + 18 + + + + + 143 + 18 + + + + font-size: 9pt; +font-weight: bold; + + + Compiler Settings + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 12 + + + + + + + + 15 + + + + + false + + + + 0 + 0 + + + + font-size: 9pt; + + + Configuration: + + + + + + + false + + + font-size:9pt; + + + + + + + + + + + 10 + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Extension of Contestant's Answer File + + + + + + + + 0 + 0 + + + + + 61 + 22 + + + + + 61 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + FileLineEdit + QLineEdit +
filelineedit.h
+
+
+ + problemTitle + sourceFileName + inputFileName + standardInputCheck + outputFileName + standardOutputCheck + comparisonMode + compilersList + configurationSelect + specialJudge + realPrecision + + + + + comparisonMode + currentIndexChanged(int) + comparisonSetting + setCurrentIndex(int) + + + 329 + 202 + + + 329 + 245 + + + + +
diff --git a/testcase.cpp b/testcase.cpp index e84f97f..cf3b877 100644 --- a/testcase.cpp +++ b/testcase.cpp @@ -1,107 +1,107 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "testcase.h" -#include "settings.h" - -TestCase::TestCase(QObject *parent) : - QObject(parent) -{ -} - -int TestCase::getFullScore() const -{ - return fullScore; -} - -int TestCase::getTimeLimit() const -{ - return timeLimit; -} - -int TestCase::getMemoryLimit() const -{ - return memoryLimit; -} - -const QStringList& TestCase::getInputFiles() const -{ - return inputFiles; -} - -const QStringList& TestCase::getOutputFiles() const -{ - return outputFiles; -} - -void TestCase::setFullScore(int score) -{ - fullScore = score; -} - -void TestCase::setTimeLimit(int limit) -{ - timeLimit = limit; -} - -void TestCase::setMemoryLimit(int limit) -{ - memoryLimit = limit; -} - -void TestCase::setInputFiles(int index, const QString &fileName) -{ - if (0 <= index && index < inputFiles.size()) - inputFiles[index] = fileName; -} - -void TestCase::setOutputFiles(int index, const QString &fileName) -{ - if (0 <= index && index < outputFiles.size()) - outputFiles[index] = fileName; -} - -void TestCase::addSingleCase(const QString &inputFile, const QString &outputFile) -{ - inputFiles.append(inputFile); - outputFiles.append(outputFile); -} - -void TestCase::deleteSingleCase(int index) -{ - inputFiles.removeAt(index); - outputFiles.removeAt(index); -} - -void TestCase::writeToStream(QDataStream &out) -{ - out << fullScore; - out << timeLimit; - out << memoryLimit; - out << inputFiles; - out << outputFiles; -} - -void TestCase::readFromStream(QDataStream &in) -{ - in >> fullScore; - in >> timeLimit; - in >> memoryLimit; - in >> inputFiles; - in >> outputFiles; -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "testcase.h" +#include "settings.h" + +TestCase::TestCase(QObject *parent) : + QObject(parent) +{ +} + +int TestCase::getFullScore() const +{ + return fullScore; +} + +int TestCase::getTimeLimit() const +{ + return timeLimit; +} + +int TestCase::getMemoryLimit() const +{ + return memoryLimit; +} + +const QStringList& TestCase::getInputFiles() const +{ + return inputFiles; +} + +const QStringList& TestCase::getOutputFiles() const +{ + return outputFiles; +} + +void TestCase::setFullScore(int score) +{ + fullScore = score; +} + +void TestCase::setTimeLimit(int limit) +{ + timeLimit = limit; +} + +void TestCase::setMemoryLimit(int limit) +{ + memoryLimit = limit; +} + +void TestCase::setInputFiles(int index, const QString &fileName) +{ + if (0 <= index && index < inputFiles.size()) + inputFiles[index] = fileName; +} + +void TestCase::setOutputFiles(int index, const QString &fileName) +{ + if (0 <= index && index < outputFiles.size()) + outputFiles[index] = fileName; +} + +void TestCase::addSingleCase(const QString &inputFile, const QString &outputFile) +{ + inputFiles.append(inputFile); + outputFiles.append(outputFile); +} + +void TestCase::deleteSingleCase(int index) +{ + inputFiles.removeAt(index); + outputFiles.removeAt(index); +} + +void TestCase::writeToStream(QDataStream &out) +{ + out << fullScore; + out << timeLimit; + out << memoryLimit; + out << inputFiles; + out << outputFiles; +} + +void TestCase::readFromStream(QDataStream &in) +{ + in >> fullScore; + in >> timeLimit; + in >> memoryLimit; + in >> inputFiles; + in >> outputFiles; +} diff --git a/testcase.h b/testcase.h index ee42004..15a003b 100644 --- a/testcase.h +++ b/testcase.h @@ -1,53 +1,53 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef TESTCASE_H -#define TESTCASE_H - -#include -#include - -class TestCase : public QObject -{ - Q_OBJECT -public: - explicit TestCase(QObject *parent = 0); - int getFullScore() const; - int getTimeLimit() const; - int getMemoryLimit() const; - const QStringList& getInputFiles() const; - const QStringList& getOutputFiles() const; - void setFullScore(int); - void setTimeLimit(int); - void setMemoryLimit(int); - void setInputFiles(int, const QString&); - void setOutputFiles(int, const QString&); - void addSingleCase(const QString&, const QString&); - void deleteSingleCase(int); - void writeToStream(QDataStream&); - void readFromStream(QDataStream&); - -private: - QStringList inputFiles; - QStringList outputFiles; - int fullScore; - int timeLimit; - int memoryLimit; -}; - -#endif // TESTCASE_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef TESTCASE_H +#define TESTCASE_H + +#include +#include + +class TestCase : public QObject +{ + Q_OBJECT +public: + explicit TestCase(QObject *parent = 0); + int getFullScore() const; + int getTimeLimit() const; + int getMemoryLimit() const; + const QStringList& getInputFiles() const; + const QStringList& getOutputFiles() const; + void setFullScore(int); + void setTimeLimit(int); + void setMemoryLimit(int); + void setInputFiles(int, const QString&); + void setOutputFiles(int, const QString&); + void addSingleCase(const QString&, const QString&); + void deleteSingleCase(int); + void writeToStream(QDataStream&); + void readFromStream(QDataStream&); + +private: + QStringList inputFiles; + QStringList outputFiles; + int fullScore; + int timeLimit; + int memoryLimit; +}; + +#endif // TESTCASE_H diff --git a/testcaseeditwidget.cpp b/testcaseeditwidget.cpp index 486923c..f8041a8 100644 --- a/testcaseeditwidget.cpp +++ b/testcaseeditwidget.cpp @@ -1,188 +1,188 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "testcaseeditwidget.h" -#include "ui_testcaseeditwidget.h" -#include "settings.h" -#include "testcase.h" - -TestCaseEditWidget::TestCaseEditWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::TestCaseEditWidget) -{ - ui->setupUi(this); - - editTestCase = 0; - - deleteAction = new QAction(this); - deleteAction->setShortcutContext(Qt::WidgetShortcut); - deleteAction->setShortcut(QKeySequence::Delete); - deleteAction->setEnabled(false); - ui->fileList->addAction(deleteAction); - - ui->fullScore->setValidator(new QIntValidator(1, Settings::upperBoundForFullScore(), ui->fullScore)); - ui->timeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->timeLimit)); - ui->memoryLimit->setValidator(new QIntValidator(1, Settings::upperBoundForMemoryLimit(), ui->memoryLimit)); - ui->fileList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); - - ui->inputFileEdit->setFilters(QDir::Files); - ui->outputFileEdit->setFilters(QDir::Files); - connect(this, SIGNAL(dataPathChanged()), - ui->inputFileEdit, SLOT(refreshFileList())); - connect(this, SIGNAL(dataPathChanged()), - ui->outputFileEdit, SLOT(refreshFileList())); - - connect(ui->addButton, SIGNAL(clicked()), - this, SLOT(addSingleCase())); - connect(deleteAction, SIGNAL(triggered()), - this, SLOT(deleteSingleCase())); - connect(ui->fullScore, SIGNAL(textChanged(QString)), - this, SLOT(fullScoreChanged(QString))); - connect(ui->timeLimit, SIGNAL(textChanged(QString)), - this, SLOT(timeLimitChanged(QString))); - connect(ui->memoryLimit, SIGNAL(textChanged(QString)), - this, SLOT(memoryLimitChanged(QString))); - connect(ui->fileList, SIGNAL(itemSelectionChanged()), - this, SLOT(fileListSelectionChanged())); - connect(ui->fileList, SIGNAL(itemChanged(QTableWidgetItem*)), - this, SLOT(fileListItemChanged(QTableWidgetItem*))); -} - -TestCaseEditWidget::~TestCaseEditWidget() -{ - delete ui; -} - -void TestCaseEditWidget::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::LanguageChange) { - TestCase *bak = editTestCase; - setEditTestCase(0, true); - ui->retranslateUi(this); - setEditTestCase(bak, true); - } -} - -void TestCaseEditWidget::refreshFileList() -{ - if (! editTestCase) return; - ui->fileList->setRowCount(0); - QStringList inputFiles = editTestCase->getInputFiles(); - QStringList outputFiles = editTestCase->getOutputFiles(); - ui->fileList->setRowCount(inputFiles.size()); - for (int i = 0; i < ui->fileList->rowCount(); i ++) { - QTableWidgetItem *inputFile = new QTableWidgetItem(inputFiles[i]); - QTableWidgetItem *outputFile = new QTableWidgetItem(outputFiles[i]); - ui->fileList->setItem(i, 0, inputFile); - ui->fileList->setItem(i, 1, outputFile); - } -} - -void TestCaseEditWidget::setEditTestCase(TestCase *testCase, bool check) -{ - editTestCase = testCase; - if (! editTestCase) return; - ui->fullScore->setText(QString("%1").arg(editTestCase->getFullScore())); - ui->timeLimit->setText(QString("%1").arg(editTestCase->getTimeLimit())); - ui->memoryLimit->setText(QString("%1").arg(editTestCase->getMemoryLimit())); - refreshFileList(); - ui->timeLimit->setEnabled(check); - ui->timeLimitLabel->setEnabled(check); - ui->msLabel->setEnabled(check); - ui->memoryLimit->setEnabled(check); - ui->memoryLimitLabel->setEnabled(check); - ui->mbLabel->setEnabled(check); -} - -void TestCaseEditWidget::setSettings(Settings *_settings) -{ - settings = _settings; - ui->inputFileEdit->setFileExtensions(settings->getInputFileExtensions()); - ui->outputFileEdit->setFileExtensions(settings->getOutputFileExtensions()); -} - -void TestCaseEditWidget::addSingleCase() -{ - if (ui->inputFileEdit->text().isEmpty()) { - ui->inputFileEdit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty input file name!"), QMessageBox::Close); - return; - } - - if (ui->outputFileEdit->text().isEmpty()) { - ui->outputFileEdit->setFocus(); - QMessageBox::warning(this, tr("Error"), tr("Empty output file name!"), QMessageBox::Close); - return; - } - - ui->fileList->setRowCount(ui->fileList->rowCount() + 1); - editTestCase->addSingleCase(ui->inputFileEdit->text(), ui->outputFileEdit->text()); - ui->fileList->setItem(ui->fileList->rowCount() - 1, 0, - new QTableWidgetItem(ui->inputFileEdit->text())); - ui->fileList->setItem(ui->fileList->rowCount() - 1, 1, - new QTableWidgetItem(ui->outputFileEdit->text())); - ui->inputFileEdit->clear(); - ui->outputFileEdit->clear(); -} - -void TestCaseEditWidget::deleteSingleCase() -{ - QTableWidgetSelectionRange range = ui->fileList->selectedRanges().at(0); - for (int i = range.topRow(); i <= range.bottomRow(); i ++) - editTestCase->deleteSingleCase(i); - refreshFileList(); -} - -void TestCaseEditWidget::fileListSelectionChanged() -{ - if (! editTestCase) return; - QList range = ui->fileList->selectedRanges(); - if (range.size() == 1 && range[0].columnCount() == 2) - deleteAction->setEnabled(true); - else - deleteAction->setEnabled(false); -} - -void TestCaseEditWidget::fileListItemChanged(QTableWidgetItem *item) -{ - if (! editTestCase) return; - if (item) { - if (item->column() == 0) - editTestCase->setInputFiles(item->row(), item->text()); - else - editTestCase->setOutputFiles(item->row(), item->text()); - } -} - -void TestCaseEditWidget::fullScoreChanged(const QString &text) -{ - if (! editTestCase) return; - editTestCase->setFullScore(text.toInt()); -} - -void TestCaseEditWidget::timeLimitChanged(const QString &text) -{ - if (! editTestCase) return; - editTestCase->setTimeLimit(text.toInt()); -} - -void TestCaseEditWidget::memoryLimitChanged(const QString &text) -{ - if (! editTestCase) return; - editTestCase->setMemoryLimit(text.toInt()); -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "testcaseeditwidget.h" +#include "ui_testcaseeditwidget.h" +#include "settings.h" +#include "testcase.h" + +TestCaseEditWidget::TestCaseEditWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::TestCaseEditWidget) +{ + ui->setupUi(this); + + editTestCase = 0; + + deleteAction = new QAction(this); + deleteAction->setShortcutContext(Qt::WidgetShortcut); + deleteAction->setShortcut(QKeySequence::Delete); + deleteAction->setEnabled(false); + ui->fileList->addAction(deleteAction); + + ui->fullScore->setValidator(new QIntValidator(1, Settings::upperBoundForFullScore(), ui->fullScore)); + ui->timeLimit->setValidator(new QIntValidator(1, Settings::upperBoundForTimeLimit(), ui->timeLimit)); + ui->memoryLimit->setValidator(new QIntValidator(1, Settings::upperBoundForMemoryLimit(), ui->memoryLimit)); + ui->fileList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + + ui->inputFileEdit->setFilters(QDir::Files); + ui->outputFileEdit->setFilters(QDir::Files); + connect(this, SIGNAL(dataPathChanged()), + ui->inputFileEdit, SLOT(refreshFileList())); + connect(this, SIGNAL(dataPathChanged()), + ui->outputFileEdit, SLOT(refreshFileList())); + + connect(ui->addButton, SIGNAL(clicked()), + this, SLOT(addSingleCase())); + connect(deleteAction, SIGNAL(triggered()), + this, SLOT(deleteSingleCase())); + connect(ui->fullScore, SIGNAL(textChanged(QString)), + this, SLOT(fullScoreChanged(QString))); + connect(ui->timeLimit, SIGNAL(textChanged(QString)), + this, SLOT(timeLimitChanged(QString))); + connect(ui->memoryLimit, SIGNAL(textChanged(QString)), + this, SLOT(memoryLimitChanged(QString))); + connect(ui->fileList, SIGNAL(itemSelectionChanged()), + this, SLOT(fileListSelectionChanged())); + connect(ui->fileList, SIGNAL(itemChanged(QTableWidgetItem*)), + this, SLOT(fileListItemChanged(QTableWidgetItem*))); +} + +TestCaseEditWidget::~TestCaseEditWidget() +{ + delete ui; +} + +void TestCaseEditWidget::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) { + TestCase *bak = editTestCase; + setEditTestCase(0, true); + ui->retranslateUi(this); + setEditTestCase(bak, true); + } +} + +void TestCaseEditWidget::refreshFileList() +{ + if (! editTestCase) return; + ui->fileList->setRowCount(0); + QStringList inputFiles = editTestCase->getInputFiles(); + QStringList outputFiles = editTestCase->getOutputFiles(); + ui->fileList->setRowCount(inputFiles.size()); + for (int i = 0; i < ui->fileList->rowCount(); i ++) { + QTableWidgetItem *inputFile = new QTableWidgetItem(inputFiles[i]); + QTableWidgetItem *outputFile = new QTableWidgetItem(outputFiles[i]); + ui->fileList->setItem(i, 0, inputFile); + ui->fileList->setItem(i, 1, outputFile); + } +} + +void TestCaseEditWidget::setEditTestCase(TestCase *testCase, bool check) +{ + editTestCase = testCase; + if (! editTestCase) return; + ui->fullScore->setText(QString("%1").arg(editTestCase->getFullScore())); + ui->timeLimit->setText(QString("%1").arg(editTestCase->getTimeLimit())); + ui->memoryLimit->setText(QString("%1").arg(editTestCase->getMemoryLimit())); + refreshFileList(); + ui->timeLimit->setEnabled(check); + ui->timeLimitLabel->setEnabled(check); + ui->msLabel->setEnabled(check); + ui->memoryLimit->setEnabled(check); + ui->memoryLimitLabel->setEnabled(check); + ui->mbLabel->setEnabled(check); +} + +void TestCaseEditWidget::setSettings(Settings *_settings) +{ + settings = _settings; + ui->inputFileEdit->setFileExtensions(settings->getInputFileExtensions()); + ui->outputFileEdit->setFileExtensions(settings->getOutputFileExtensions()); +} + +void TestCaseEditWidget::addSingleCase() +{ + if (ui->inputFileEdit->text().isEmpty()) { + ui->inputFileEdit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty input file name!"), QMessageBox::Close); + return; + } + + if (ui->outputFileEdit->text().isEmpty()) { + ui->outputFileEdit->setFocus(); + QMessageBox::warning(this, tr("Error"), tr("Empty output file name!"), QMessageBox::Close); + return; + } + + ui->fileList->setRowCount(ui->fileList->rowCount() + 1); + editTestCase->addSingleCase(ui->inputFileEdit->text(), ui->outputFileEdit->text()); + ui->fileList->setItem(ui->fileList->rowCount() - 1, 0, + new QTableWidgetItem(ui->inputFileEdit->text())); + ui->fileList->setItem(ui->fileList->rowCount() - 1, 1, + new QTableWidgetItem(ui->outputFileEdit->text())); + ui->inputFileEdit->clear(); + ui->outputFileEdit->clear(); +} + +void TestCaseEditWidget::deleteSingleCase() +{ + QTableWidgetSelectionRange range = ui->fileList->selectedRanges().at(0); + for (int i = range.topRow(); i <= range.bottomRow(); i ++) + editTestCase->deleteSingleCase(i); + refreshFileList(); +} + +void TestCaseEditWidget::fileListSelectionChanged() +{ + if (! editTestCase) return; + QList range = ui->fileList->selectedRanges(); + if (range.size() == 1 && range[0].columnCount() == 2) + deleteAction->setEnabled(true); + else + deleteAction->setEnabled(false); +} + +void TestCaseEditWidget::fileListItemChanged(QTableWidgetItem *item) +{ + if (! editTestCase) return; + if (item) { + if (item->column() == 0) + editTestCase->setInputFiles(item->row(), item->text()); + else + editTestCase->setOutputFiles(item->row(), item->text()); + } +} + +void TestCaseEditWidget::fullScoreChanged(const QString &text) +{ + if (! editTestCase) return; + editTestCase->setFullScore(text.toInt()); +} + +void TestCaseEditWidget::timeLimitChanged(const QString &text) +{ + if (! editTestCase) return; + editTestCase->setTimeLimit(text.toInt()); +} + +void TestCaseEditWidget::memoryLimitChanged(const QString &text) +{ + if (! editTestCase) return; + editTestCase->setMemoryLimit(text.toInt()); +} diff --git a/testcaseeditwidget.h b/testcaseeditwidget.h index e489e1c..c767bee 100644 --- a/testcaseeditwidget.h +++ b/testcaseeditwidget.h @@ -1,64 +1,64 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef TESTCASEEDITWIDGET_H -#define TESTCASEEDITWIDGET_H - -#include -#include -#include - -namespace Ui { - class TestCaseEditWidget; -} - -class Settings; -class TestCase; - -class TestCaseEditWidget : public QWidget -{ - Q_OBJECT - -public: - explicit TestCaseEditWidget(QWidget *parent = 0); - ~TestCaseEditWidget(); - void changeEvent(QEvent*); - void setEditTestCase(TestCase*, bool); - void setSettings(Settings*); - -private: - Ui::TestCaseEditWidget *ui; - TestCase *editTestCase; - Settings *settings; - QAction *deleteAction; - void refreshFileList(); - -private slots: - void addSingleCase(); - void deleteSingleCase(); - void fullScoreChanged(const QString&); - void timeLimitChanged(const QString&); - void memoryLimitChanged(const QString&); - void fileListSelectionChanged(); - void fileListItemChanged(QTableWidgetItem*); - -signals: - void dataPathChanged(); -}; - -#endif // TESTCASEEDITWIDGET_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef TESTCASEEDITWIDGET_H +#define TESTCASEEDITWIDGET_H + +#include +#include +#include + +namespace Ui { + class TestCaseEditWidget; +} + +class Settings; +class TestCase; + +class TestCaseEditWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TestCaseEditWidget(QWidget *parent = 0); + ~TestCaseEditWidget(); + void changeEvent(QEvent*); + void setEditTestCase(TestCase*, bool); + void setSettings(Settings*); + +private: + Ui::TestCaseEditWidget *ui; + TestCase *editTestCase; + Settings *settings; + QAction *deleteAction; + void refreshFileList(); + +private slots: + void addSingleCase(); + void deleteSingleCase(); + void fullScoreChanged(const QString&); + void timeLimitChanged(const QString&); + void memoryLimitChanged(const QString&); + void fileListSelectionChanged(); + void fileListItemChanged(QTableWidgetItem*); + +signals: + void dataPathChanged(); +}; + +#endif // TESTCASEEDITWIDGET_H diff --git a/testcaseeditwidget.ui b/testcaseeditwidget.ui index ae9b47b..286baf6 100644 --- a/testcaseeditwidget.ui +++ b/testcaseeditwidget.ui @@ -1,354 +1,354 @@ - - - TestCaseEditWidget - - - - 0 - 0 - 440 - 337 - - - - Form - - - - 10 - - - - - 10 - - - - - font-size: 9pt; - - - QAbstractItemView::ContiguousSelection - - - 2 - - - false - - - 25 - - - false - - - 25 - - - - Input Files - - - - 9 - - - - - - Output Files - - - - 9 - - - - - - - - - - - - 0 - 0 - - - - font-size: 8pt; - - - Input File Name - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 60 - 20 - - - - - - - - - 0 - 0 - - - - font-size: 8pt; - - - Output File Name - - - - - - - - - - - 0 - 0 - - - - - 60 - 0 - - - - - 60 - 16777215 - - - - &Add - - - - - - - - - - - 12 - - - 7 - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Full Score - - - - - - - - 51 - 22 - - - - - 81 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Time Limit - - - - - - - - 51 - 22 - - - - - 81 - 22 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; - - - ms - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; -font-weight: bold; - - - Memory Limit - - - - - - - - 51 - 22 - - - - - 81 - 22 - - - - - - - - - - - 0 - 0 - - - - font-size: 9pt; - - - MB - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - FileLineEdit - QLineEdit -
filelineedit.h
-
-
- - -
+ + + TestCaseEditWidget + + + + 0 + 0 + 440 + 337 + + + + Form + + + + 10 + + + + + 10 + + + + + font-size: 9pt; + + + QAbstractItemView::ContiguousSelection + + + 2 + + + false + + + 25 + + + false + + + 25 + + + + Input Files + + + + 9 + + + + + + Output Files + + + + 9 + + + + + + + + + + + + 0 + 0 + + + + font-size: 8pt; + + + Input File Name + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 60 + 20 + + + + + + + + + 0 + 0 + + + + font-size: 8pt; + + + Output File Name + + + + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + &Add + + + + + + + + + + + 12 + + + 7 + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Full Score + + + + + + + + 51 + 22 + + + + + 81 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Time Limit + + + + + + + + 51 + 22 + + + + + 81 + 22 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; + + + ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; +font-weight: bold; + + + Memory Limit + + + + + + + + 51 + 22 + + + + + 81 + 22 + + + + + + + + + + + 0 + 0 + + + + font-size: 9pt; + + + MB + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + FileLineEdit + QLineEdit +
filelineedit.h
+
+
+ + +
diff --git a/welcomedialog.cpp b/welcomedialog.cpp index 41ec246..3b2554d 100644 --- a/welcomedialog.cpp +++ b/welcomedialog.cpp @@ -1,101 +1,101 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#include "welcomedialog.h" -#include "ui_welcomedialog.h" - -WelcomeDialog::WelcomeDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::WelcomeDialog) -{ - ui->setupUi(this); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - connect(ui->openContestWidget, SIGNAL(selectionChanged()), - this, SLOT(selectionChanged())); - connect(ui->newContestWidget, SIGNAL(informationChanged()), - this, SLOT(informationChanged())); - connect(ui->tabWidget, SIGNAL(currentChanged(int)), - this, SLOT(tabIndexChanged(int))); - connect(ui->openContestWidget, SIGNAL(rowDoubleClicked()), - this, SLOT(accept())); -} - -WelcomeDialog::~WelcomeDialog() -{ - delete ui; -} - -void WelcomeDialog::setRecentContest(const QStringList &list) -{ - ui->openContestWidget->setRecentContest(list); -} - -QString WelcomeDialog::getContestTitle() -{ - return ui->newContestWidget->getContestTitle(); -} - -QString WelcomeDialog::getSavingName() -{ - return ui->newContestWidget->getSavingName(); -} - -QString WelcomeDialog::getContestPath() -{ - return ui->newContestWidget->getContestPath(); -} - -const QStringList& WelcomeDialog::getRecentContest() const -{ - return ui->openContestWidget->getRecentContest(); -} - -QString WelcomeDialog::getSelectedContest() -{ - return ui->openContestWidget->getRecentContest().at(ui->openContestWidget->getCurrentRow()); -} - -int WelcomeDialog::getCurrentTab() const -{ - return ui->tabWidget->currentIndex(); -} - -void WelcomeDialog::selectionChanged() -{ - if (ui->openContestWidget->getCurrentRow() != -1) - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - else - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); -} - -void WelcomeDialog::informationChanged() -{ - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ui->newContestWidget->checkReady()); -} - -void WelcomeDialog::tabIndexChanged(int index) -{ - if (index == 0) { - if (ui->openContestWidget->getCurrentRow() != -1) - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - else - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - } else { - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ui->newContestWidget->checkReady()); - } -} +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#include "welcomedialog.h" +#include "ui_welcomedialog.h" + +WelcomeDialog::WelcomeDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::WelcomeDialog) +{ + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + connect(ui->openContestWidget, SIGNAL(selectionChanged()), + this, SLOT(selectionChanged())); + connect(ui->newContestWidget, SIGNAL(informationChanged()), + this, SLOT(informationChanged())); + connect(ui->tabWidget, SIGNAL(currentChanged(int)), + this, SLOT(tabIndexChanged(int))); + connect(ui->openContestWidget, SIGNAL(rowDoubleClicked()), + this, SLOT(accept())); +} + +WelcomeDialog::~WelcomeDialog() +{ + delete ui; +} + +void WelcomeDialog::setRecentContest(const QStringList &list) +{ + ui->openContestWidget->setRecentContest(list); +} + +QString WelcomeDialog::getContestTitle() +{ + return ui->newContestWidget->getContestTitle(); +} + +QString WelcomeDialog::getSavingName() +{ + return ui->newContestWidget->getSavingName(); +} + +QString WelcomeDialog::getContestPath() +{ + return ui->newContestWidget->getContestPath(); +} + +const QStringList& WelcomeDialog::getRecentContest() const +{ + return ui->openContestWidget->getRecentContest(); +} + +QString WelcomeDialog::getSelectedContest() +{ + return ui->openContestWidget->getRecentContest().at(ui->openContestWidget->getCurrentRow()); +} + +int WelcomeDialog::getCurrentTab() const +{ + return ui->tabWidget->currentIndex(); +} + +void WelcomeDialog::selectionChanged() +{ + if (ui->openContestWidget->getCurrentRow() != -1) + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + else + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); +} + +void WelcomeDialog::informationChanged() +{ + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ui->newContestWidget->checkReady()); +} + +void WelcomeDialog::tabIndexChanged(int index) +{ + if (index == 0) { + if (ui->openContestWidget->getCurrentRow() != -1) + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + else + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } else { + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ui->newContestWidget->checkReady()); + } +} diff --git a/welcomedialog.h b/welcomedialog.h index 20f64ce..5b57e9b 100644 --- a/welcomedialog.h +++ b/welcomedialog.h @@ -1,54 +1,54 @@ -/*************************************************************************** - This file is part of Project Lemon - Copyright (C) 2011 Zhipeng Jia - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***************************************************************************/ - -#ifndef WELCOMEDIALOG_H -#define WELCOMEDIALOG_H - -#include -#include -#include - -namespace Ui { - class WelcomeDialog; -} - -class WelcomeDialog : public QDialog -{ - Q_OBJECT - -public: - explicit WelcomeDialog(QWidget *parent = 0); - ~WelcomeDialog(); - void setRecentContest(const QStringList&); - QString getContestTitle(); - QString getSavingName(); - QString getContestPath(); - const QStringList& getRecentContest() const; - QString getSelectedContest(); - int getCurrentTab() const; - -private: - Ui::WelcomeDialog *ui; - -private slots: - void selectionChanged(); - void informationChanged(); - void tabIndexChanged(int); -}; - -#endif // WELCOMEDIALOG_H +/*************************************************************************** + This file is part of Project Lemon + Copyright (C) 2011 Zhipeng Jia + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***************************************************************************/ + +#ifndef WELCOMEDIALOG_H +#define WELCOMEDIALOG_H + +#include +#include +#include + +namespace Ui { + class WelcomeDialog; +} + +class WelcomeDialog : public QDialog +{ + Q_OBJECT + +public: + explicit WelcomeDialog(QWidget *parent = 0); + ~WelcomeDialog(); + void setRecentContest(const QStringList&); + QString getContestTitle(); + QString getSavingName(); + QString getContestPath(); + const QStringList& getRecentContest() const; + QString getSelectedContest(); + int getCurrentTab() const; + +private: + Ui::WelcomeDialog *ui; + +private slots: + void selectionChanged(); + void informationChanged(); + void tabIndexChanged(int); +}; + +#endif // WELCOMEDIALOG_H diff --git a/welcomedialog.ui b/welcomedialog.ui index b9fa769..e2f279d 100644 --- a/welcomedialog.ui +++ b/welcomedialog.ui @@ -1,105 +1,105 @@ - - - WelcomeDialog - - - - 0 - 0 - 470 - 350 - - - - Welcome - - - - - - font-size: 9pt; - - - 0 - - - - Open - - - - - - - - - - New - - - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - OpenContestWidget - QWidget -
opencontestwidget.h
- 1 -
- - NewContestWidget - QWidget -
newcontestwidget.h
- 1 -
-
- - - - buttonBox - accepted() - WelcomeDialog - accept() - - - 234 - 324 - - - 234 - 174 - - - - - buttonBox - rejected() - WelcomeDialog - reject() - - - 234 - 324 - - - 234 - 174 - - - - -
+ + + WelcomeDialog + + + + 0 + 0 + 470 + 350 + + + + Welcome + + + + + + font-size: 9pt; + + + 0 + + + + Open + + + + + + + + + + New + + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + OpenContestWidget + QWidget +
opencontestwidget.h
+ 1 +
+ + NewContestWidget + QWidget +
newcontestwidget.h
+ 1 +
+
+ + + + buttonBox + accepted() + WelcomeDialog + accept() + + + 234 + 324 + + + 234 + 174 + + + + + buttonBox + rejected() + WelcomeDialog + reject() + + + 234 + 324 + + + 234 + 174 + + + + +