Run user script in venv and install eismultiplexer
This commit is contained in:
parent
4c2a4790c0
commit
b5bd510f59
4 changed files with 155 additions and 3 deletions
|
|
@ -53,6 +53,12 @@ MainWindow::MainWindow(QWidget *parent):
|
|||
connect(ui->pushButtonRun, &QPushButton::clicked, this, &MainWindow::runScript);
|
||||
connect(ui->pushButtonStop, &QPushButton::clicked, this, &MainWindow::stopScript);
|
||||
connect(&pythonRunner, &PythonRunner::scriptFinished, this, &MainWindow::stopScript);
|
||||
connect(&pythonRunner, &PythonRunner::venvSetupProgress, this, &MainWindow::onVenvSetupProgress);
|
||||
|
||||
// Disable run button until venv is ready
|
||||
ui->pushButtonRun->setEnabled(false);
|
||||
ui->statusbar->showMessage("Setting up Python environment...");
|
||||
|
||||
enumerateDevices();
|
||||
generateExample();
|
||||
}
|
||||
|
|
@ -290,6 +296,18 @@ void MainWindow::disconnectDevices()
|
|||
multiplexers.clear();
|
||||
}
|
||||
|
||||
void MainWindow::onVenvSetupProgress(const QString& message) {
|
||||
ui->statusbar->showMessage(message);
|
||||
if (message.contains("completed successfully", Qt::CaseInsensitive) ||
|
||||
message.contains("already exists", Qt::CaseInsensitive)) {
|
||||
ui->pushButtonRun->setEnabled(true);
|
||||
ui->statusbar->showMessage("Ready");
|
||||
} else if (message.contains("failed", Qt::CaseInsensitive)) {
|
||||
ui->pushButtonRun->setEnabled(false);
|
||||
ui->statusbar->showMessage("Error: Python environment setup failed. Please check the output.");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::generateExample()
|
||||
{
|
||||
QString example =
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ private slots:
|
|||
void runScript();
|
||||
void stopScript();
|
||||
void readState();
|
||||
void onVenvSetupProgress(const QString& message);
|
||||
|
||||
private:
|
||||
void enumerateDevices();
|
||||
|
|
|
|||
122
pythonrunner.cpp
122
pythonrunner.cpp
|
|
@ -1,12 +1,18 @@
|
|||
#include "pythonrunner.h"
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QThread>
|
||||
|
||||
PythonRunner::PythonRunner(QTextEdit* outputWidget, QObject* parent)
|
||||
: QObject(parent), m_outputWidget(outputWidget), m_process(nullptr) {
|
||||
: QObject(parent), m_outputWidget(outputWidget), m_process(nullptr), m_venvProcess(nullptr), venvReady(false) {
|
||||
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);
|
||||
|
||||
// Start venv setup in background
|
||||
QThread::create([this]() { setupVenv(); });
|
||||
}
|
||||
|
||||
PythonRunner::~PythonRunner() {
|
||||
|
|
@ -14,6 +20,103 @@ PythonRunner::~PythonRunner() {
|
|||
m_process->terminate();
|
||||
m_process->waitForFinished(1000);
|
||||
}
|
||||
if (m_venvProcess) {
|
||||
m_venvProcess->terminate();
|
||||
m_venvProcess->waitForFinished(1000);
|
||||
}
|
||||
}
|
||||
|
||||
QString PythonRunner::venvPath() {
|
||||
return dir.path() + QDir::separator() + "venv";
|
||||
}
|
||||
|
||||
QString PythonRunner::pythonExePath() {
|
||||
QString venv = venvPath();
|
||||
#ifdef Q_OS_WIN
|
||||
return venv + "\\Scripts\\python.exe";
|
||||
#else
|
||||
return venv + "/bin/python";
|
||||
#endif
|
||||
}
|
||||
|
||||
void PythonRunner::ensureVenvReady() {
|
||||
QMutexLocker locker(&venvMutex);
|
||||
if (!venvReady) {
|
||||
venvCondition.wait(&venvMutex);
|
||||
}
|
||||
}
|
||||
|
||||
void PythonRunner::setupVenv() {
|
||||
QString venv = venvPath();
|
||||
QString pythonCmd = "python3";
|
||||
#ifdef Q_OS_WIN
|
||||
pythonCmd = "python";
|
||||
#endif
|
||||
|
||||
// Check if venv already exists
|
||||
QDir venvDir(venv);
|
||||
if (venvDir.exists()) {
|
||||
venvReady = true;
|
||||
emit venvSetupProgress("Virtual environment already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create virtual environment
|
||||
emit venvSetupProgress("Creating virtual environment...");
|
||||
|
||||
m_venvProcess = new QProcess();
|
||||
connect(m_venvProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &PythonRunner::onVenvProcessFinished);
|
||||
|
||||
QStringList args;
|
||||
#ifdef Q_OS_WIN
|
||||
args << "-m" << "venv" << "venv";
|
||||
#else
|
||||
args << "-m" << "venv" << venv;
|
||||
#endif
|
||||
|
||||
m_venvProcess->setWorkingDirectory(dir.path());
|
||||
m_venvProcess->start(pythonCmd, args);
|
||||
if (!m_venvProcess->waitForStarted()) {
|
||||
emit venvSetupProgress("Failed to start venv creation process");
|
||||
venvReady = false;
|
||||
m_venvProcess->deleteLater();
|
||||
m_venvProcess = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PythonRunner::onVenvProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
|
||||
// Install eismultiplexer package
|
||||
emit venvSetupProgress("Installing eismultiplexer package...");
|
||||
|
||||
QProcess installProcess;
|
||||
installProcess.setWorkingDirectory(dir.path());
|
||||
QStringList installArgs;
|
||||
installArgs << "-m" << "pip" << "install" << "eismultiplexer";
|
||||
|
||||
installProcess.start(pythonExePath(), installArgs);
|
||||
if (!installProcess.waitForFinished(30000)) { // 30 second timeout
|
||||
emit venvSetupProgress("Package installation timed out");
|
||||
venvReady = false;
|
||||
} else {
|
||||
QByteArray output = installProcess.readAllStandardOutput();
|
||||
QByteArray error = installProcess.readAllStandardError();
|
||||
if (!error.isEmpty()) {
|
||||
emit venvSetupProgress("Installation error: " + QString::fromLocal8Bit(error));
|
||||
venvReady = false;
|
||||
} else {
|
||||
emit venvSetupProgress("Package installed successfully");
|
||||
venvReady = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emit venvSetupProgress(QString("Virtual environment creation failed with code %1").arg(exitCode));
|
||||
venvReady = false;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
m_venvProcess->deleteLater();
|
||||
m_venvProcess = nullptr;
|
||||
}
|
||||
|
||||
bool PythonRunner::runScript(const QString& scriptContent) {
|
||||
|
|
@ -23,7 +126,18 @@ bool PythonRunner::runScript(const QString& scriptContent) {
|
|||
}
|
||||
|
||||
m_outputWidget->clear();
|
||||
m_process->start("python3", QStringList() << "-u" << "-c" << scriptContent);
|
||||
|
||||
// Check if venv is ready
|
||||
if (!venvReady) {
|
||||
m_outputWidget->append("Error: Virtual environment not ready. Please wait for the setup to complete.\n");
|
||||
emit scriptFinished(-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_outputWidget->append("Running script in virtual environment...\n");
|
||||
|
||||
QString pythonPath = pythonExePath();
|
||||
m_process->start(pythonPath, QStringList() << "-u" << "-c" << scriptContent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -54,3 +168,7 @@ void PythonRunner::onProcessFinished(int exitCode, QProcess::ExitStatus exitStat
|
|||
}
|
||||
emit scriptFinished(exitCode);
|
||||
}
|
||||
|
||||
void PythonRunner::onVenvSetupFinished() {
|
||||
// This slot can be used to handle venv setup completion if needed
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
#include <QProcess>
|
||||
#include <QObject>
|
||||
#include <QTemporaryDir>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
class PythonRunner : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
@ -19,13 +22,25 @@ private slots:
|
|||
void onOutputAvailable();
|
||||
void onErrorAvailable();
|
||||
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void onVenvSetupFinished();
|
||||
void setupVenv();
|
||||
|
||||
public slots:
|
||||
void onVenvProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
signals:
|
||||
void scriptFinished(int code);
|
||||
void venvSetupProgress(const QString& message);
|
||||
|
||||
private:
|
||||
QTextEdit* m_outputWidget;
|
||||
QProcess* m_process;
|
||||
bool ready;
|
||||
QProcess* m_venvProcess;
|
||||
QTemporaryDir dir;
|
||||
QString venvPath();
|
||||
QString pythonExePath();
|
||||
void ensureVenvReady();
|
||||
bool venvReady;
|
||||
QMutex venvMutex;
|
||||
QWaitCondition venvCondition;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue