- enhancement: enable run/debug/compile when console program finished but pausing.
This commit is contained in:
parent
a50c6af5de
commit
b956dbbcab
3
NEWS.md
3
NEWS.md
|
@ -1,3 +1,6 @@
|
|||
Version 0.12.0 For Dev-C++ 7 Beta
|
||||
- enhancement: enable run/debug/compile when console program finished but pausing.
|
||||
|
||||
Version 0.11.5 For Dev-C++ 7 Beta
|
||||
- fix: step into instruction and step over instruction not correctly disabled when cpu dialog is created
|
||||
- enhancement: icons in all dialogs auto change size with fonts
|
||||
|
|
|
@ -42,7 +42,7 @@ bool CompilerManager::backgroundSyntaxChecking()
|
|||
bool CompilerManager::running()
|
||||
{
|
||||
QMutexLocker locker(&mRunnerMutex);
|
||||
return mRunner!=nullptr;
|
||||
return (mRunner!=nullptr && !mRunner->pausing());
|
||||
}
|
||||
|
||||
void CompilerManager::compile(const QString& filename, const QByteArray& encoding, bool rebuild, bool silent, bool onlyCheckSyntax)
|
||||
|
@ -199,7 +199,7 @@ void CompilerManager::checkSyntax(const QString &filename, const QString &conten
|
|||
void CompilerManager::run(const QString &filename, const QString &arguments, const QString &workDir)
|
||||
{
|
||||
QMutexLocker locker(&mRunnerMutex);
|
||||
if (mRunner!=nullptr) {
|
||||
if (mRunner!=nullptr && !mRunner->pausing()) {
|
||||
return;
|
||||
}
|
||||
QString redirectInputFilename;
|
||||
|
@ -234,7 +234,9 @@ void CompilerManager::run(const QString &filename, const QString &arguments, con
|
|||
}
|
||||
mRunner = execRunner;
|
||||
connect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
|
||||
connect(mRunner, &Runner::finished, mRunner ,&Runner::deleteLater);
|
||||
connect(mRunner, &Runner::finished, pMainWindow ,&MainWindow::onRunFinished);
|
||||
connect(mRunner, &Runner::pausingForFinish, pMainWindow ,&MainWindow::onRunPausingForFinish);
|
||||
connect(mRunner, &Runner::runErrorOccurred, pMainWindow ,&MainWindow::onRunErrorOccured);
|
||||
mRunner->start();
|
||||
}
|
||||
|
@ -249,6 +251,7 @@ void CompilerManager::runProblem(const QString &filename, const QString &argumen
|
|||
OJProblemCasesRunner * execRunner = new OJProblemCasesRunner(filename,arguments,workDir,problemCase);
|
||||
mRunner = execRunner;
|
||||
connect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
|
||||
connect(mRunner, &Runner::finished, mRunner ,&Runner::deleteLater);
|
||||
connect(mRunner, &Runner::finished, pMainWindow ,&MainWindow::onRunProblemFinished);
|
||||
connect(mRunner, &Runner::runErrorOccurred, pMainWindow ,&MainWindow::onRunErrorOccured);
|
||||
connect(execRunner, &OJProblemCasesRunner::caseStarted, pMainWindow, &MainWindow::onOJProblemCaseStarted);
|
||||
|
@ -276,8 +279,22 @@ void CompilerManager::runProblem(const QString &filename, const QString &argumen
|
|||
void CompilerManager::stopRun()
|
||||
{
|
||||
QMutexLocker locker(&mRunnerMutex);
|
||||
if (mRunner!=nullptr)
|
||||
if (mRunner!=nullptr) {
|
||||
mRunner->stop();
|
||||
disconnect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
|
||||
mRunner=nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerManager::stopPausing()
|
||||
{
|
||||
QMutexLocker locker(&mRunnerMutex);
|
||||
if (mRunner!=nullptr && mRunner->pausing()) {
|
||||
disconnect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
|
||||
mRunner->stop();
|
||||
disconnect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
|
||||
mRunner=nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerManager::stopCompile()
|
||||
|
@ -309,9 +326,7 @@ void CompilerManager::onCompileFinished()
|
|||
void CompilerManager::onRunnerTerminated()
|
||||
{
|
||||
QMutexLocker locker(&mRunnerMutex);
|
||||
Runner* p=mRunner;
|
||||
mRunner=nullptr;
|
||||
p->deleteLater();
|
||||
}
|
||||
|
||||
void CompilerManager::onCompileIssue(PCompileIssue issue)
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
void runProblem(const QString& filename, const QString& arguments, const QString& workDir, POJProblemCase problemCase);
|
||||
void runProblem(const QString& filename, const QString& arguments, const QString& workDir, QVector<POJProblemCase> problemCases);
|
||||
void stopRun();
|
||||
void stopPausing();
|
||||
void stopCompile();
|
||||
void stopCheckSyntax();
|
||||
bool canCompile(const QString& filename);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "executablerunner.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <windows.h>
|
||||
#include <QDebug>
|
||||
#include "compilermanager.h"
|
||||
|
@ -50,15 +49,17 @@ void ExecutableRunner::run()
|
|||
{
|
||||
emit started();
|
||||
auto action = finally([this]{
|
||||
mProcess.reset();
|
||||
setPausing(false);
|
||||
emit terminated();
|
||||
});
|
||||
QProcess process;
|
||||
mStop = false;
|
||||
bool errorOccurred = false;
|
||||
|
||||
process.setProgram(mFilename);
|
||||
process.setArguments(QProcess::splitCommand(mArguments));
|
||||
process.setWorkingDirectory(mWorkDir);
|
||||
mProcess = std::make_shared<QProcess>();
|
||||
mProcess->setProgram(mFilename);
|
||||
mProcess->setArguments(QProcess::splitCommand(mArguments));
|
||||
mProcess->setWorkingDirectory(mWorkDir);
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString path = env.value("PATH");
|
||||
QStringList pathAdded;
|
||||
|
@ -74,8 +75,8 @@ void ExecutableRunner::run()
|
|||
path = pathAdded.join(PATH_SEPARATOR);
|
||||
}
|
||||
env.insert("PATH",path);
|
||||
process.setProcessEnvironment(env);
|
||||
process.setCreateProcessArgumentsModifier([this](QProcess::CreateProcessArguments * args){
|
||||
mProcess->setProcessEnvironment(env);
|
||||
mProcess->setCreateProcessArgumentsModifier([this](QProcess::CreateProcessArguments * args){
|
||||
if (mStartConsole) {
|
||||
args->flags |= CREATE_NEW_CONSOLE;
|
||||
args->flags &= ~CREATE_NO_WINDOW;
|
||||
|
@ -84,56 +85,96 @@ void ExecutableRunner::run()
|
|||
args->startupInfo -> dwFlags &= ~STARTF_USESTDHANDLES;
|
||||
}
|
||||
});
|
||||
process.connect(
|
||||
&process, &QProcess::errorOccurred,
|
||||
[&](){
|
||||
connect(
|
||||
mProcess.get(), &QProcess::errorOccurred,
|
||||
[&errorOccurred](){
|
||||
errorOccurred= true;
|
||||
});
|
||||
// if (!redirectInput()) {
|
||||
// process.closeWriteChannel();
|
||||
// }
|
||||
process.start();
|
||||
process.waitForStarted(5000);
|
||||
if (process.state()==QProcess::Running && redirectInput()) {
|
||||
process.write(readFileToByteArray(redirectInputFilename()));
|
||||
process.closeWriteChannel();
|
||||
mProcess->start();
|
||||
mProcess->waitForStarted(5000);
|
||||
if (mProcess->state()==QProcess::Running && redirectInput()) {
|
||||
mProcess->write(readFileToByteArray(redirectInputFilename()));
|
||||
mProcess->closeWriteChannel();
|
||||
}
|
||||
HANDLE hSharedMemory=INVALID_HANDLE_VALUE;
|
||||
int BUF_SIZE=1024;
|
||||
char* pBuf=nullptr;
|
||||
if (mStartConsole) {
|
||||
hSharedMemory = CreateFileMappingA(
|
||||
INVALID_HANDLE_VALUE,
|
||||
NULL,
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
100,
|
||||
"RED_PANDA_IDE_CONSOLE_PAUSER20211223"
|
||||
);
|
||||
if (hSharedMemory != NULL)
|
||||
{
|
||||
pBuf = (char*) MapViewOfFile(hSharedMemory, // handle to map object
|
||||
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||
0,
|
||||
0,
|
||||
BUF_SIZE);
|
||||
if (pBuf) {
|
||||
pBuf[0]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
process.waitForFinished(1000);
|
||||
if (process.state()!=QProcess::Running) {
|
||||
mProcess->waitForFinished(1000);
|
||||
if (mProcess->state()!=QProcess::Running) {
|
||||
break;
|
||||
}
|
||||
if (mStop) {
|
||||
process.closeReadChannel(QProcess::StandardOutput);
|
||||
process.closeReadChannel(QProcess::StandardError);
|
||||
process.closeWriteChannel();
|
||||
#ifdef Q_OS_WIN
|
||||
if (!mStartConsole) {
|
||||
process.terminate();
|
||||
if (process.waitForFinished(1000)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
process.terminate();
|
||||
if (process.waitForFinished(1000)) {
|
||||
qDebug()<<"??1";
|
||||
mProcess->closeReadChannel(QProcess::StandardOutput);
|
||||
mProcess->closeReadChannel(QProcess::StandardError);
|
||||
mProcess->closeWriteChannel();
|
||||
qDebug()<<"??2";
|
||||
#ifdef Q_OS_WIN
|
||||
qDebug()<<"??3";
|
||||
mProcess->terminate();
|
||||
qDebug()<<"??4";
|
||||
if (mProcess->waitForFinished(1000)) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
process->terminate();
|
||||
if (process->waitForFinished(1000)) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
for (int i=0;i<10;i++) {
|
||||
process.kill();
|
||||
if (process.waitForFinished(100)) {
|
||||
qDebug()<<"??5";
|
||||
mProcess->kill();
|
||||
qDebug()<<"??6";
|
||||
if (mProcess->waitForFinished(500)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (mStartConsole && !mPausing && pBuf) {
|
||||
if (strncmp(pBuf,"FINISHED",sizeof("FINISHED"))==0) {
|
||||
setPausing(true);
|
||||
emit pausingForFinish();
|
||||
}
|
||||
}
|
||||
|
||||
if (errorOccurred)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pBuf)
|
||||
UnmapViewOfFile(pBuf);
|
||||
if (hSharedMemory!=INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hSharedMemory);
|
||||
if (errorOccurred) {
|
||||
//qDebug()<<"process error:"<<process.error();
|
||||
switch (process.error()) {
|
||||
switch (mProcess->error()) {
|
||||
case QProcess::FailedToStart:
|
||||
emit runErrorOccurred(tr("The runner process '%1' failed to start.").arg(mFilename));
|
||||
break;
|
||||
|
@ -155,3 +196,38 @@ void ExecutableRunner::run()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutableRunner::doStop()
|
||||
{
|
||||
std::shared_ptr<QProcess> process = mProcess;
|
||||
if (process) {
|
||||
// qDebug()<<"??1";
|
||||
// process->closeReadChannel(QProcess::StandardOutput);
|
||||
// process->closeReadChannel(QProcess::StandardError);
|
||||
// process->closeWriteChannel();
|
||||
// qDebug()<<"??2";
|
||||
// #ifdef Q_OS_WIN
|
||||
// if (!mStartConsole) {
|
||||
// qDebug()<<"??3";
|
||||
// process->terminate();
|
||||
// qDebug()<<"??4";
|
||||
// if (process->waitForFinished(1000)) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// #else
|
||||
// process->terminate();
|
||||
// if (process->waitForFinished(1000)) {
|
||||
// break;
|
||||
// }
|
||||
// #endif
|
||||
// for (int i=0;i<10;i++) {
|
||||
// qDebug()<<"??5";
|
||||
// process->kill();
|
||||
// qDebug()<<"??6";
|
||||
// if (process->waitForFinished(100)) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define EXECUTABLERUNNER_H
|
||||
|
||||
#include "runner.h"
|
||||
#include <QProcess>
|
||||
|
||||
class ExecutableRunner : public Runner
|
||||
{
|
||||
|
@ -23,10 +24,15 @@ private:
|
|||
QString mRedirectInputFilename;
|
||||
bool mRedirectInput;
|
||||
bool mStartConsole;
|
||||
std::shared_ptr<QProcess> mProcess;
|
||||
|
||||
// QThread interface
|
||||
protected:
|
||||
void run() override;
|
||||
|
||||
// Runner interface
|
||||
protected:
|
||||
void doStop() override;
|
||||
};
|
||||
|
||||
#endif // EXECUTABLERUNNER_H
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../widgets/ojproblemsetmodel.h"
|
||||
#include <QProcess>
|
||||
|
||||
|
||||
OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
|
||||
const QVector<POJProblemCase>& problemCases, QObject *parent):
|
||||
Runner(filename,arguments,workDir,parent)
|
||||
|
|
|
@ -25,6 +25,7 @@ private:
|
|||
// QThread interface
|
||||
protected:
|
||||
void run() override;
|
||||
|
||||
};
|
||||
|
||||
#endif // OJPROBLEMCASESRUNNER_H
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
Runner::Runner(const QString &filename, const QString &arguments, const QString &workDir
|
||||
,QObject *parent) : QThread(parent),
|
||||
mPausing(false),
|
||||
mStop(false),
|
||||
mFilename(filename),
|
||||
mArguments(arguments),
|
||||
|
@ -13,5 +14,21 @@ Runner::Runner(const QString &filename, const QString &arguments, const QString
|
|||
void Runner::stop()
|
||||
{
|
||||
mStop = true;
|
||||
doStop();
|
||||
}
|
||||
|
||||
void Runner::doStop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Runner::pausing() const
|
||||
{
|
||||
return mPausing;
|
||||
}
|
||||
|
||||
void Runner::setPausing(bool newCanFinish)
|
||||
{
|
||||
mPausing = newCanFinish;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,15 +9,22 @@ class Runner : public QThread
|
|||
public:
|
||||
explicit Runner(const QString& filename, const QString& arguments, const QString& workDir, QObject *parent = nullptr);
|
||||
|
||||
bool pausing() const;
|
||||
|
||||
|
||||
signals:
|
||||
void started();
|
||||
void terminated();
|
||||
void runErrorOccurred(const QString& reason);
|
||||
void pausingForFinish(); // finish but pausing
|
||||
|
||||
public slots:
|
||||
void stop();
|
||||
|
||||
protected:
|
||||
virtual void doStop();
|
||||
void setPausing(bool newCanFinish);
|
||||
protected:
|
||||
bool mPausing;
|
||||
bool mStop;
|
||||
QString mFilename;
|
||||
QString mArguments;
|
||||
|
|
|
@ -1312,6 +1312,7 @@ void MainWindow::checkSyntaxInBack(Editor *e)
|
|||
|
||||
bool MainWindow::compile(bool rebuild)
|
||||
{
|
||||
mCompilerManager->stopPausing();
|
||||
CompileTarget target =getCompileTarget();
|
||||
if (target == CompileTarget::Project) {
|
||||
if (mProject->modified())
|
||||
|
@ -1355,6 +1356,7 @@ bool MainWindow::compile(bool rebuild)
|
|||
|
||||
void MainWindow::runExecutable(const QString &exeName,const QString &filename,RunType runType)
|
||||
{
|
||||
mCompilerManager->stopPausing();
|
||||
// Check if it exists
|
||||
if (!fileExists(exeName)) {
|
||||
if (ui->actionCompile_Run->isEnabled()) {
|
||||
|
@ -1452,6 +1454,7 @@ void MainWindow::debug()
|
|||
{
|
||||
if (mCompilerManager->compiling())
|
||||
return;
|
||||
mCompilerManager->stopPausing();
|
||||
Settings::PCompilerSet compilerSet = pSettings->compilerSets().defaultSet();
|
||||
if (!compilerSet) {
|
||||
QMessageBox::critical(pMainWindow,
|
||||
|
@ -3910,6 +3913,11 @@ void MainWindow::onRunFinished()
|
|||
updateAppTitle();
|
||||
}
|
||||
|
||||
void MainWindow::onRunPausingForFinish()
|
||||
{
|
||||
updateCompileActions();
|
||||
}
|
||||
|
||||
void MainWindow::onRunProblemFinished()
|
||||
{
|
||||
ui->pbProblemCases->setVisible(false);
|
||||
|
|
|
@ -172,6 +172,7 @@ public slots:
|
|||
void onCompileErrorOccured(const QString& reason);
|
||||
void onRunErrorOccured(const QString& reason);
|
||||
void onRunFinished();
|
||||
void onRunPausingForFinish();
|
||||
void onRunProblemFinished();
|
||||
void onOJProblemCaseStarted(const QString& id, int current, int total);
|
||||
void onOJProblemCaseFinished(const QString& id, int current, int total);
|
||||
|
|
|
@ -28,7 +28,7 @@ CustomMakefile =
|
|||
IncludeVersionInfo = 0
|
||||
SupportXPThemes = 0
|
||||
CompilerSet = 0
|
||||
CompilerSettings = 000000a000110000000001000
|
||||
CompilerSettings = 000000a000000000000010001
|
||||
UnitCount = 1
|
||||
UsePrecompiledHeader = 0
|
||||
PrecompiledHeader =
|
||||
|
|
|
@ -181,6 +181,25 @@ int main(int argc, char** argv) {
|
|||
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
|
||||
}
|
||||
|
||||
HANDLE hSharedMemory=INVALID_HANDLE_VALUE;
|
||||
int BUF_SIZE=1024;
|
||||
char* pBuf=nullptr;
|
||||
hSharedMemory = OpenFileMappingA(
|
||||
FILE_MAP_ALL_ACCESS,
|
||||
FALSE,
|
||||
"RED_PANDA_IDE_CONSOLE_PAUSER20211223"
|
||||
);
|
||||
if (hSharedMemory != NULL)
|
||||
{
|
||||
pBuf = (char*) MapViewOfFile(hSharedMemory, // handle to map object
|
||||
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||
0,
|
||||
0,
|
||||
BUF_SIZE);
|
||||
} else {
|
||||
printf("can't open shared memory!");
|
||||
}
|
||||
|
||||
// Save starting timestamp
|
||||
LONGLONG starttime = GetClockTick();
|
||||
|
||||
|
@ -191,6 +210,10 @@ int main(int argc, char** argv) {
|
|||
LONGLONG endtime = GetClockTick();
|
||||
double seconds = (endtime - starttime) / (double)GetClockFrequency();
|
||||
|
||||
if (pBuf) {
|
||||
strcpy(pBuf,"FINISHED");
|
||||
}
|
||||
|
||||
// Done? Print return value of executed program
|
||||
printf("\n--------------------------------");
|
||||
printf("\nProcess exited after %.4g seconds with return value %lu\n",seconds,returnvalue);
|
||||
|
|
Loading…
Reference in New Issue