Cleanup python script running

This commit is contained in:
Carl Philipp Klemm 2025-10-13 18:12:32 +02:00
parent 87db38b08e
commit 1eac3f6a83
7 changed files with 68 additions and 128 deletions

View file

@ -48,7 +48,6 @@ add_executable(${PROJECT_NAME}
triggerwidget.h
pythonrunner.cpp
pythonrunner.h
pythonembed.cpp
)
set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE ON)
target_compile_options(${PROJECT_NAME} PUBLIC "-Wall")

View file

@ -14,9 +14,9 @@ MainWindow::MainWindow(QWidget *parent):
ui(new Ui::MainWindow),
codeEditor(this),
pythonOutput(this),
pythonRunner(&pythonOutput),
currentFilePath(""),
isFileModified(false),
pythonRunner(nullptr)
isFileModified(false)
{
ui->setupUi(this);
enumerateDevices();
@ -52,9 +52,9 @@ MainWindow::MainWindow(QWidget *parent):
});
// Connect Run and Stop buttons
pythonRunner = new PythonRunner(&pythonOutput, this);
connect(ui->pushButtonRun, &QPushButton::clicked, this, &MainWindow::onPushButtonRunClicked);
connect(ui->pushButtonStop, &QPushButton::clicked, this, &MainWindow::onPushButtonStopClicked);
connect(ui->pushButtonRun, &QPushButton::clicked, this, &MainWindow::runScript);
connect(ui->pushButtonStop, &QPushButton::clicked, this, &MainWindow::stopScript);
connect(&pythonRunner, &PythonRunner::scriptFinished, this, &MainWindow::stopScript);
}
MainWindow::~MainWindow()
@ -232,17 +232,21 @@ void MainWindow::enumerateDevices()
generateExample();
}
void MainWindow::onPushButtonRunClicked() {
void MainWindow::runScript() {
QString scriptContent = codeEditor.toPlainText();
pythonRunner->runScript(scriptContent);
pythonRunner.runScript(scriptContent);
ui->pushButtonRun->setEnabled(false);
ui->pushButtonStop->setEnabled(true);
codeEditor.setEnabled(false);
ui->scrollArea->setEnabled(false);
}
void MainWindow::onPushButtonStopClicked() {
pythonRunner->stopScript();
void MainWindow::stopScript() {
pythonRunner.stopScript();
ui->pushButtonRun->setEnabled(true);
ui->pushButtonStop->setEnabled(false);
codeEditor.setEnabled(true);
ui->scrollArea->setEnabled(true);
}
void MainWindow::generateExample()

View file

@ -1,5 +1,3 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
@ -8,6 +6,7 @@
#include <QCodeEditor>
#include <QPythonCompleter>
#include <QPythonHighlighter>
#include <QProgressBar>
#include "channelwidget.h"
#include "triggerwidget.h"
@ -28,7 +27,7 @@ class MainWindow : public QMainWindow
QPythonHighlighter highligter;
QPythonCompleter completer;
QTextEdit pythonOutput;
PythonRunner* pythonRunner;
PythonRunner pythonRunner;
signals:
void channelStateChanged(uint16_t device, uint16_t channel);
@ -41,8 +40,8 @@ private slots:
void onActionOpenTriggered();
void onActionSaveTriggered();
void onActionSaveAsTriggered();
void onPushButtonRunClicked();
void onPushButtonStopClicked();
void runScript();
void stopScript();
private:
void enumerateDevices();

View file

@ -1,61 +0,0 @@
#include "pythonembed.h"
#include <QDebug>
PythonEmbed::PythonEmbed(QTextEdit* outputWidget, QObject* parent)
: QObject(parent), m_outputWidget(outputWidget), m_process(nullptr) {
m_process = new QProcess(this);
connect(m_process, &QProcess::readyReadStandardOutput, this, &PythonEmbed::onOutputAvailable);
connect(m_process, &QProcess::readyReadStandardError, this, &PythonEmbed::onErrorAvailable);
connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &PythonEmbed::onProcessFinished);
}
PythonEmbed::~PythonEmbed() {
if (m_process) {
m_process->terminate();
m_process->waitForFinished(1000);
}
}
void PythonEmbed::runScript(const QString& scriptContent) {
if (m_process->state() == QProcess::Running) {
m_process->terminate();
m_process->waitForFinished(1000);
}
m_outputWidget->clear();
m_outputWidget->append("Python 3.11.2 (main, Oct 5 2023, 17:20:59) [GCC 11.4.0] on linux\n");
m_outputWidget->append("Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n\n");
m_process->start("python3", QStringList() << "-c" << scriptContent);
}
void PythonEmbed::stopScript() {
if (m_process && m_process->state() == QProcess::Running) {
m_process->terminate();
}
}
void PythonEmbed::onOutputAvailable() {
QByteArray output = m_process->readAllStandardOutput();
m_outputWidget->append(output);
m_outputWidget->moveCursor(QTextCursor::End);
}
void PythonEmbed::onErrorAvailable() {
QByteArray error = m_process->readAllStandardError();
m_outputWidget->append(error);
m_outputWidget->moveCursor(QTextCursor::End);
}
void PythonEmbed::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) {
if (exitStatus == QProcess::NormalExit && exitCode != 0) {
m_outputWidget->append(QString("Process exited with code %1\n").arg(exitCode));
} else if (exitStatus == QProcess::CrashExit) {
m_outputWidget->append("Python process crashed\n");
}
}
#include "pythonembed.moc"

View file

@ -1,31 +0,0 @@
#ifndef PYTHONEMBED_H
#define PYTHONEMBED_H
#include <QTextEdit>
#include <QProcess>
#include <QObject>
class PythonEmbed : public QObject {
Q_OBJECT
public:
PythonEmbed(QTextEdit* outputWidget, QObject* parent = nullptr);
~PythonEmbed();
void runScript(const QString& scriptContent);
void stopScript();
private slots:
void onOutputAvailable();
void onErrorAvailable();
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
private:
QTextEdit* m_outputWidget;
QProcess* m_process;
};
#endif // PYTHONEMBED_H

View file

@ -1,26 +1,54 @@
#include "pythonrunner.h"
#include "pythonembed.h"
#include <QDebug>
PythonRunner::PythonRunner(QTextEdit* outputWidget, QObject* parent)
: QObject(parent), m_outputWidget(outputWidget), m_pythonEmbed(nullptr) {
m_pythonEmbed = new PythonEmbed(m_outputWidget, this);
: QObject(parent), m_outputWidget(outputWidget), m_process(nullptr) {
m_process = new QProcess(this);
connect(m_process, &QProcess::readyReadStandardOutput, this, &PythonRunner::onOutputAvailable);
connect(m_process, &QProcess::readyReadStandardError, this, &PythonRunner::onErrorAvailable);
connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &PythonRunner::onProcessFinished);
}
PythonRunner::~PythonRunner() {
delete m_pythonEmbed;
if (m_process) {
m_process->terminate();
m_process->waitForFinished(1000);
}
}
void PythonRunner::runScript(const QString& scriptContent) {
if (m_pythonEmbed) {
m_pythonEmbed->runScript(scriptContent);
if (m_process->state() == QProcess::Running) {
m_process->terminate();
m_process->waitForFinished(1000);
}
m_outputWidget->clear();
m_process->start("python3", QStringList() << "-u" << "-c" << scriptContent);
}
void PythonRunner::stopScript() {
if (m_pythonEmbed) {
m_pythonEmbed->stopScript();
if (m_process && m_process->state() == QProcess::Running) {
m_process->terminate();
}
}
#include "pythonrunner.moc"
void PythonRunner::onOutputAvailable() {
QByteArray output = m_process->readAllStandardOutput();
m_outputWidget->append(output);
m_outputWidget->moveCursor(QTextCursor::End);
}
void PythonRunner::onErrorAvailable() {
QByteArray error = m_process->readAllStandardError();
m_outputWidget->append(error);
m_outputWidget->moveCursor(QTextCursor::End);
}
void PythonRunner::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) {
if (exitStatus == QProcess::NormalExit && exitCode != 0) {
m_outputWidget->append(QString("Process exited with code %1\n").arg(exitCode));
} else if (exitStatus == QProcess::CrashExit) {
m_outputWidget->append("Python was stopped\n");
}
emit scriptFinished(exitCode);
}

View file

@ -1,26 +1,28 @@
#pragma once
#ifndef PYTHONRUNNER_H
#define PYTHONRUNNER_H
#include <QObject>
#include <QTextEdit>
class PythonEmbed;
#include <QProcess>
#include <QObject>
class PythonRunner : public QObject {
Q_OBJECT
public:
explicit PythonRunner(QTextEdit* outputWidget, QObject* parent = nullptr);
PythonRunner(QTextEdit* outputWidget, QObject* parent = nullptr);
~PythonRunner();
public slots:
void runScript(const QString& scriptContent);
void stopScript();
private slots:
void onOutputAvailable();
void onErrorAvailable();
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
signals:
void scriptFinished(int code);
private:
QTextEdit* m_outputWidget;
PythonEmbed* m_pythonEmbed;
QProcess* m_process;
};
#endif // PYTHONRUNNER_H