From 1eac3f6a83cf23916ec197e42b25720f680b6f8c Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Mon, 13 Oct 2025 18:12:32 +0200 Subject: [PATCH] Cleanup python script running --- CMakeLists.txt | 1 - mainwindow.cpp | 22 ++++++++++------- mainwindow.h | 9 ++++--- pythonembed.cpp | 61 ------------------------------------------------ pythonembed.h | 31 ------------------------ pythonrunner.cpp | 48 +++++++++++++++++++++++++++++-------- pythonrunner.h | 24 ++++++++++--------- 7 files changed, 68 insertions(+), 128 deletions(-) delete mode 100644 pythonembed.cpp delete mode 100644 pythonembed.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 32b9cc7..a1ce0a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/mainwindow.cpp b/mainwindow.cpp index 05cc234..ed4f5b4 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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() diff --git a/mainwindow.h b/mainwindow.h index df74472..0c60a8f 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,5 +1,3 @@ - - #ifndef MAINWINDOW_H #define MAINWINDOW_H @@ -8,6 +6,7 @@ #include #include #include +#include #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(); diff --git a/pythonembed.cpp b/pythonembed.cpp deleted file mode 100644 index f6df212..0000000 --- a/pythonembed.cpp +++ /dev/null @@ -1,61 +0,0 @@ - - -#include "pythonembed.h" -#include - -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::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" - diff --git a/pythonembed.h b/pythonembed.h deleted file mode 100644 index b48bded..0000000 --- a/pythonembed.h +++ /dev/null @@ -1,31 +0,0 @@ - - -#ifndef PYTHONEMBED_H -#define PYTHONEMBED_H - -#include -#include -#include - -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 - diff --git a/pythonrunner.cpp b/pythonrunner.cpp index e2f09ca..8f7e126 100644 --- a/pythonrunner.cpp +++ b/pythonrunner.cpp @@ -1,26 +1,54 @@ - #include "pythonrunner.h" -#include "pythonembed.h" +#include 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::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); +} diff --git a/pythonrunner.h b/pythonrunner.h index b5067cb..3855486 100644 --- a/pythonrunner.h +++ b/pythonrunner.h @@ -1,26 +1,28 @@ +#pragma once -#ifndef PYTHONRUNNER_H -#define PYTHONRUNNER_H - -#include #include - -class PythonEmbed; +#include +#include 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