Compare commits

..

2 commits

Author SHA1 Message Date
Carl Philipp Klemm
b7e323603c Fix python include issue 2025-10-13 16:53:56 +02:00
a3fbd2877b cpython attempt 2025-10-13 16:45:50 +02:00
15 changed files with 241 additions and 238 deletions

View file

@ -28,7 +28,7 @@ find_package(PkgConfig REQUIRED)
pkg_check_modules(EISMULIPLEXER REQUIRED eismuliplexer) pkg_check_modules(EISMULIPLEXER REQUIRED eismuliplexer)
find_package(Qt6 REQUIRED COMPONENTS Widgets) find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package(Qt6 REQUIRED COMPONENTS Core) find_package(Qt6 REQUIRED COMPONENTS Core)
# find_package(Python3 REQUIRED) - Removed since we're using QProcess instead of embedding Python find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
@ -42,17 +42,19 @@ add_executable(${PROJECT_NAME}
mainwindow.h mainwindow.h
mainwindow.cpp mainwindow.cpp
mainwindow.ui mainwindow.ui
multiplexer.h
multiplexer.cpp
triggerwidget.cpp triggerwidget.cpp
triggerwidget.h triggerwidget.h
pythonrunner.cpp pythonrunner.cpp
pythonrunner.h pythonrunner.h
pythonembed.cpp
) )
set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE ON) set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE ON)
target_compile_options(${PROJECT_NAME} PUBLIC "-Wall") target_compile_options(${PROJECT_NAME} PUBLIC "-Wall")
target_include_directories(${PROJECT_NAME} PUBLIC QCodeEditor) target_include_directories(${PROJECT_NAME} PUBLIC QCodeEditor)
# target_include_directories(${PROJECT_NAME} PRIVATE ${Python3_INCLUDE_DIRS}) - Removed since we're using QProcess instead of embedding Python target_include_directories(${PROJECT_NAME} PRIVATE ${Python3_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets Qt6::Core ${EISMULIPLEXER_LIBRARIES} QCodeEditor) target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets Qt6::Core ${EISMULIPLEXER_LIBRARIES} QCodeEditor ${Python3_LIBRARIES})
# ${Python3_LIBRARIES} - Removed since we're using QProcess instead of embedding Python
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/eismultiplexerqt.png PROPERTIES QT_RESOURCE_ALIAS eismultiplexerqt.png) set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/eismultiplexerqt.png PROPERTIES QT_RESOURCE_ALIAS eismultiplexerqt.png)
qt_add_resources(${PROJECT_NAME} "resources" PREFIX "/" FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/eismultiplexerqt.png ) qt_add_resources(${PROJECT_NAME} "resources" PREFIX "/" FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/eismultiplexerqt.png )
install(TARGETS ${PROJECT_NAME} DESTINATION bin) install(TARGETS ${PROJECT_NAME} DESTINATION bin)

View file

@ -108,6 +108,7 @@ void ChannelWidget::onGangComboChanged(int index)
gangedChannelNumber = -1; gangedChannelNumber = -1;
checkbox.setEnabled(true); checkbox.setEnabled(true);
checkbox.setChecked(false); checkbox.setChecked(false);
checkbox.setChecked(false);
} else { } else {
// A ganged channel was selected // A ganged channel was selected
QString currentText = gangcombo.currentText(); QString currentText = gangcombo.currentText();
@ -127,7 +128,7 @@ void ChannelWidget::onGangComboChanged(int index)
void ChannelWidget::onOtherChannelStateChanged(uint16_t deviceSerial, uint16_t channelNumber, bool checked) void ChannelWidget::onOtherChannelStateChanged(uint16_t deviceSerial, uint16_t channelNumber, bool checked)
{ {
// If this channel is ganged to the channel that changed state // If this channel is ganged to the channel that changed state
if (this->deviceSerial == deviceSerial && this->channelNumber == channelNumber) { if (gangedDeviceSerial == deviceSerial && gangedChannelNumber == channelNumber) {
// Update our checkbox state to follow the ganged channel // Update our checkbox state to follow the ganged channel
checkbox.blockSignals(true); checkbox.blockSignals(true);
checkbox.setChecked(checked); checkbox.setChecked(checked);
@ -162,9 +163,3 @@ void ChannelWidget::setGangedChannel(uint16_t gangedDeviceSerial, uint16_t gange
updateCheckboxState(); updateCheckboxState();
} }
void ChannelWidget::replaceMultiplexer(std::shared_ptr<struct eismultiplexer> multiplexer, int serial)
{
if(serial == deviceSerial || serial == -1)
this->multiplexer = multiplexer;
}

View file

@ -33,7 +33,6 @@ public slots:
private slots: private slots:
void onChannelToggled(bool checked); void onChannelToggled(bool checked);
void onGangComboChanged(int index); void onGangComboChanged(int index);
void replaceMultiplexer(std::shared_ptr<struct eismultiplexer> multiplexer, int serial = -1);
signals: signals:
void channelAboutToBeTurnedOn(uint16_t deviceSerial, uint16_t channelNumber); void channelAboutToBeTurnedOn(uint16_t deviceSerial, uint16_t channelNumber);

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.6)
project(QCodeEditor) project(QCodeEditor)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)

View file

@ -1,3 +1,4 @@
#include <eismultiplexer.h>
#include <QMessageBox> #include <QMessageBox>
#include <QMessageBox> #include <QMessageBox>
#include <set> #include <set>
@ -13,11 +14,12 @@ MainWindow::MainWindow(QWidget *parent):
ui(new Ui::MainWindow), ui(new Ui::MainWindow),
codeEditor(this), codeEditor(this),
pythonOutput(this), pythonOutput(this),
pythonRunner(&pythonOutput),
currentFilePath(""), currentFilePath(""),
isFileModified(false) isFileModified(false),
pythonRunner(nullptr)
{ {
ui->setupUi(this); ui->setupUi(this);
enumerateDevices();
codeEditor.setAutoIndentation(true); codeEditor.setAutoIndentation(true);
codeEditor.setAutoParentheses(true); codeEditor.setAutoParentheses(true);
@ -50,11 +52,9 @@ MainWindow::MainWindow(QWidget *parent):
}); });
// Connect Run and Stop buttons // Connect Run and Stop buttons
connect(ui->pushButtonRun, &QPushButton::clicked, this, &MainWindow::runScript); pythonRunner = new PythonRunner(&pythonOutput, this);
connect(ui->pushButtonStop, &QPushButton::clicked, this, &MainWindow::stopScript); connect(ui->pushButtonRun, &QPushButton::clicked, this, &MainWindow::onPushButtonRunClicked);
connect(&pythonRunner, &PythonRunner::scriptFinished, this, &MainWindow::stopScript); connect(ui->pushButtonStop, &QPushButton::clicked, this, &MainWindow::onPushButtonStopClicked);
enumerateDevices();
generateExample();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -62,30 +62,6 @@ MainWindow::~MainWindow()
delete ui; delete ui;
} }
void MainWindow::readState()
{
for (auto& multiplexer : multiplexers) {
channel_t channelstate = eismultiplexer_get_connected(multiplexer.second.get());
for (auto& channel : channels) {
for(size_t i = 0; i < 16; ++i) {
channel_t mask = static_cast<channel_t>(1 << i);
channel->onOtherChannelStateChanged(multiplexer.first, i, channelstate & mask);
}
}
int triggerCount = eismultiplexer_get_trigger_count(multiplexer.second.get());
for(int i = 0; i < triggerCount; ++i) {
bool level;
trigger_state_t state;
int ret = eismultiplexer_get_trigger_state(multiplexer.second.get(), i, &state, &level);
if (ret < 0) {
for (auto& trigger : triggers)
trigger->updateSate(multiplexer.first, i, state);
}
}
}
}
void MainWindow::updateStatus() void MainWindow::updateStatus()
{ {
if (!currentFilePath.isEmpty()) { if (!currentFilePath.isEmpty()) {
@ -174,9 +150,6 @@ void MainWindow::enumerateDevices()
{ {
size_t count = 0; size_t count = 0;
uint16_t* serials = eismultiplexer_list_available_devices(&count); uint16_t* serials = eismultiplexer_list_available_devices(&count);
if (ui->scrollArea->layout())
delete ui->scrollArea->layout();
QVBoxLayout* channelLayout = new QVBoxLayout(ui->scrollArea);
if (!serials || count == 0) if (!serials || count == 0)
{ {
@ -195,7 +168,6 @@ void MainWindow::enumerateDevices()
int ret = eismultiplexer_connect(multiplexer.get(), serial); int ret = eismultiplexer_connect(multiplexer.get(), serial);
if (ret == 0) if (ret == 0)
{ {
multiplexers.push_back({serial, multiplexer});
uint16_t channelCount = 0; uint16_t channelCount = 0;
qDebug()<<"Adding channels from device "<<serial; qDebug()<<"Adding channels from device "<<serial;
if (eismultiplexer_get_channel_count(multiplexer.get(), &channelCount) >= 0) if (eismultiplexer_get_channel_count(multiplexer.get(), &channelCount) >= 0)
@ -205,7 +177,7 @@ void MainWindow::enumerateDevices()
std::shared_ptr<ChannelWidget> widget(new ChannelWidget(serial, channel, multiplexer)); std::shared_ptr<ChannelWidget> widget(new ChannelWidget(serial, channel, multiplexer));
qDebug()<<"Added widget from device "<<serial<<" channel "<<channel; qDebug()<<"Added widget from device "<<serial<<" channel "<<channel;
channels.push_back(widget); channels.push_back(widget);
channelLayout->addWidget(widget.get()); ui->channelLayout->addWidget(widget.get());
} }
} }
@ -219,7 +191,7 @@ void MainWindow::enumerateDevices()
std::shared_ptr<TriggerWidget> triggerWidget(new TriggerWidget(serial, trigger, multiplexer)); std::shared_ptr<TriggerWidget> triggerWidget(new TriggerWidget(serial, trigger, multiplexer));
qDebug()<<"Added trigger widget from device "<<serial<<" trigger "<<trigger; qDebug()<<"Added trigger widget from device "<<serial<<" trigger "<<trigger;
triggers.push_back(triggerWidget); triggers.push_back(triggerWidget);
channelLayout->addWidget(triggerWidget.get()); ui->channelLayout->addWidget(triggerWidget.get());
} }
} }
} }
@ -230,8 +202,7 @@ void MainWindow::enumerateDevices()
qWarning()<<"Failed to connect to device with serial"<<serial<<"eismultiplexer_connect returned"<<ret; qWarning()<<"Failed to connect to device with serial"<<serial<<"eismultiplexer_connect returned"<<ret;
} }
} }
ui->channelLayout->addStretch();
channelLayout->addStretch();
// Second pass: populate gang combos and connect signals for channels // Second pass: populate gang combos and connect signals for channels
for (const auto& widget : channels) { for (const auto& widget : channels) {
@ -255,39 +226,23 @@ void MainWindow::enumerateDevices()
} }
} }
readState();
ui->statusbar->showMessage("Ready"); ui->statusbar->showMessage("Ready");
free(serials); free(serials);
generateExample();
} }
void MainWindow::runScript() { void MainWindow::onPushButtonRunClicked() {
QString scriptContent = codeEditor.toPlainText(); QString scriptContent = codeEditor.toPlainText();
pythonRunner.runScript(scriptContent); pythonRunner->runScript(scriptContent);
ui->pushButtonRun->setEnabled(false); ui->pushButtonRun->setEnabled(false);
ui->pushButtonStop->setEnabled(true); ui->pushButtonStop->setEnabled(true);
codeEditor.setEnabled(false);
ui->scrollArea->setEnabled(false);
disconnectDevices();
} }
void MainWindow::stopScript() { void MainWindow::onPushButtonStopClicked() {
pythonRunner.stopScript(); pythonRunner->stopScript();
channels.clear();
triggers.clear();
ui->pushButtonRun->setEnabled(true); ui->pushButtonRun->setEnabled(true);
ui->pushButtonStop->setEnabled(false); ui->pushButtonStop->setEnabled(false);
codeEditor.setEnabled(true);
ui->scrollArea->setEnabled(true);
enumerateDevices();
}
void MainWindow::disconnectDevices()
{
for(auto& multiplexer : multiplexers)
eismultiplexer_disconnect(multiplexer.second.get());
multiplexers.clear();
} }
void MainWindow::generateExample() void MainWindow::generateExample()
@ -305,7 +260,7 @@ void MainWindow::generateExample()
size_t i = 0; size_t i = 0;
for (uint16_t serial : serials) for (uint16_t serial : serials)
{ {
example.append(QString("multiplexer_") + QString::number(i) + " = multi.Multiplexer(serial=" + QString::number(serial) + ")\n"); example.append(QString("multiplexer_") + QString::number(i) + " multi.Multiplexer(serial=" + QString::number(serial) + ")\n");
++i; ++i;
} }

View file

@ -1,13 +1,14 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include <eismultiplexer.h>
#include <QMainWindow> #include <QMainWindow>
#include <memory> #include <memory>
#include <QCodeEditor> #include <QCodeEditor>
#include <QPythonCompleter> #include <QPythonCompleter>
#include <QPythonHighlighter> #include <QPythonHighlighter>
#include <QProgressBar>
#include "channelwidget.h" #include "channelwidget.h"
#include "triggerwidget.h" #include "triggerwidget.h"
#include "pythonrunner.h" #include "pythonrunner.h"
@ -20,15 +21,14 @@ class MainWindow;
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
std::vector<std::shared_ptr<TriggerWidget>> triggers;
std::vector<std::shared_ptr<ChannelWidget>> channels; std::vector<std::shared_ptr<ChannelWidget>> channels;
std::vector<std::pair<uint16_t, std::shared_ptr<struct eismultiplexer>>> multiplexers; std::vector<std::shared_ptr<TriggerWidget>> triggers;
Ui::MainWindow *ui; Ui::MainWindow *ui;
QCodeEditor codeEditor; QCodeEditor codeEditor;
QPythonHighlighter highligter; QPythonHighlighter highligter;
QPythonCompleter completer; QPythonCompleter completer;
QTextEdit pythonOutput; QTextEdit pythonOutput;
PythonRunner pythonRunner; PythonRunner* pythonRunner;
signals: signals:
void channelStateChanged(uint16_t device, uint16_t channel); void channelStateChanged(uint16_t device, uint16_t channel);
@ -41,15 +41,13 @@ private slots:
void onActionOpenTriggered(); void onActionOpenTriggered();
void onActionSaveTriggered(); void onActionSaveTriggered();
void onActionSaveAsTriggered(); void onActionSaveAsTriggered();
void runScript(); void onPushButtonRunClicked();
void stopScript(); void onPushButtonStopClicked();
void readState();
private: private:
void enumerateDevices(); void enumerateDevices();
void generateExample(); void generateExample();
void updateStatus(); void updateStatus();
void disconnectDevices();
QString currentFilePath; QString currentFilePath;
bool isFileModified; bool isFileModified;
}; };

View file

@ -16,14 +16,9 @@
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<widget class="QWidget" name="">
<layout class="QVBoxLayout" name="codeLayout"> <layout class="QVBoxLayout" name="codeLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>10</number>
</property> </property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
@ -53,14 +48,9 @@
</layout> </layout>
</item> </item>
</layout> </layout>
</widget> </item>
<item>
<widget class="QScrollArea" name="scrollArea"> <widget class="QScrollArea" name="scrollArea">
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="widgetResizable"> <property name="widgetResizable">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -69,12 +59,15 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>504</width> <width>591</width>
<height>537</height> <height>533</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"/> <layout class="QVBoxLayout" name="verticalLayout_3">
</widget> <item>
<layout class="QVBoxLayout" name="channelLayout"/>
</item>
</layout>
</widget> </widget>
</widget> </widget>
</item> </item>

16
multiplexer.cpp Normal file
View file

@ -0,0 +1,16 @@
#include "multiplexer.h"
Multiplexer::Multiplexer(QObject *parent)
: QObject{parent}
{}
Multiplexer::~Multiplexer()
{
for(auto& multiplexer : multiplexers)
eismultiplexer_disconnect(multiplexer.get());
}
void Multiplexer::probe()
{
}

22
multiplexer.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef MULTIPLEXER_H
#define MULTIPLEXER_H
#include <QObject>
#include "eismultiplexer.h"
class Multiplexer : public QObject
{
Q_OBJECT
std::vector<std::shared_ptr<struct eismultiplexer>> multiplexers;
std::vector<channel_t> channelStates;
public:
explicit Multiplexer(QObject *parent = nullptr);
~Multiplexer();
void probe();
signals:
void foundDevice(std::shared_ptr<struct eismultiplexer>);
};
#endif // MULTIPLEXER_H

73
pythonembed.cpp Normal file
View file

@ -0,0 +1,73 @@
#include "pythonembed.h"
#pragma push_macro("slots")
#undef slots
#include <Python.h>
#pragma pop_macro("slots")
#include <QDebug>
PythonEmbed::PythonEmbed(QTextEdit* outputWidget, QObject* parent)
: QObject(parent), m_outputWidget(outputWidget) {
// Initialize Python
Py_Initialize();
m_initialized = true;
// Initialize the output widget with Python prompt
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_outputWidget->append(">>> ");
}
PythonEmbed::~PythonEmbed() {
if (m_initialized) {
Py_Finalize();
}
}
void PythonEmbed::runScript(const QString& scriptContent) {
if (!m_initialized) {
m_outputWidget->append("Python not initialized\n");
return;
}
// Convert QString to const char*
QByteArray scriptBytes = scriptContent.toUtf8();
const char* script = scriptBytes.constData();
// Run the script
PyRun_SimpleString(script);
// Check for any errors
if (PyErr_Occurred()) {
handlePythonError("Script execution error");
} else {
m_outputWidget->append("\n>>> ");
}
}
void PythonEmbed::stopScript() {
// In this simple implementation, we don't have a running Python thread
// to stop, but we could add that functionality later
}
void PythonEmbed::handlePythonError(const char* context) {
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
if (type) {
PyObject *str = PyObject_Str(value);
PyObject *bytes = PyUnicode_AsEncodedString(str, "utf-8", "strict");
const char *error_msg = PyBytes_AS_STRING(bytes);
QString errorString = QString::fromUtf8(context) + ": " + QString::fromUtf8(error_msg);
m_outputWidget->append(errorString);
Py_DecRef(str);
Py_DecRef(bytes);
Py_DecRef(type);
Py_DecRef(value);
Py_DecRef(traceback);
} else {
m_outputWidget->append(QString::fromUtf8(context) + ": No error information available");
}
}

25
pythonembed.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef PYTHONEMBED_H
#define PYTHONEMBED_H
#include <QTextEdit>
#include <QObject>
class PythonEmbed : public QObject {
Q_OBJECT
public:
PythonEmbed(QTextEdit* outputWidget, QObject* parent = nullptr);
~PythonEmbed();
void runScript(const QString& scriptContent);
void stopScript();
private:
void handlePythonError(const char* context);
QTextEdit* m_outputWidget;
bool m_initialized = false;
};
#endif // PYTHONEMBED_H

View file

@ -1,56 +1,24 @@
#include "pythonrunner.h" #include "pythonrunner.h"
#include <QDebug> #include "pythonembed.h"
PythonRunner::PythonRunner(QTextEdit* outputWidget, QObject* parent) PythonRunner::PythonRunner(QTextEdit* outputWidget, QObject* parent)
: QObject(parent), m_outputWidget(outputWidget), m_process(nullptr) { : QObject(parent), m_outputWidget(outputWidget), m_pythonEmbed(nullptr) {
m_process = new QProcess(this); m_pythonEmbed = new PythonEmbed(m_outputWidget, 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() { PythonRunner::~PythonRunner() {
if (m_process) { delete m_pythonEmbed;
m_process->terminate();
m_process->waitForFinished(1000);
}
} }
bool PythonRunner::runScript(const QString& scriptContent) { void PythonRunner::runScript(const QString& scriptContent) {
if (m_process->state() == QProcess::Running) { if (m_pythonEmbed) {
m_process->terminate(); m_pythonEmbed->runScript(scriptContent);
m_process->waitForFinished(1000);
} }
m_outputWidget->clear();
m_process->start("python3", QStringList() << "-u" << "-c" << scriptContent);
return true;
} }
void PythonRunner::stopScript() { void PythonRunner::stopScript() {
if (m_process && m_process->state() == QProcess::Running) { if (m_pythonEmbed) {
m_process->terminate(); m_pythonEmbed->stopScript();
} }
} }
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,31 +1,26 @@
#pragma once
#include <QTextEdit> #ifndef PYTHONRUNNER_H
#include <QProcess> #define PYTHONRUNNER_H
#include <QObject> #include <QObject>
#include <QTemporaryDir> #include <QTextEdit>
class PythonEmbed;
class PythonRunner : public QObject { class PythonRunner : public QObject {
Q_OBJECT Q_OBJECT
public: public:
PythonRunner(QTextEdit* outputWidget, QObject* parent = nullptr); explicit PythonRunner(QTextEdit* outputWidget, QObject* parent = nullptr);
~PythonRunner(); ~PythonRunner();
bool runScript(const QString& scriptContent); public slots:
void runScript(const QString& scriptContent);
void stopScript(); void stopScript();
private slots:
void onOutputAvailable();
void onErrorAvailable();
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
signals:
void scriptFinished(int code);
private: private:
QTextEdit* m_outputWidget; QTextEdit* m_outputWidget;
QProcess* m_process; PythonEmbed* m_pythonEmbed;
bool ready;
QTemporaryDir dir;
}; };
#endif // PYTHONRUNNER_H

View file

@ -70,46 +70,9 @@ void TriggerWidget::onLevelToggled(bool checked)
updateTriggerState(); updateTriggerState();
} }
void TriggerWidget::updateSate(uint16_t serial, uint16_t trigger, trigger_state_t state)
{
if (serial == deviceSerial && trigger == triggerNumber) {
switch (state)
{
case TRIGGER_INPUT:
levelCheckbox.blockSignals(true);
levelCheckbox.setChecked(false);
levelCheckbox.setEnabled(false);
levelCheckbox.blockSignals(false);
inputCheckbox.blockSignals(true);
inputCheckbox.setChecked(true);
inputCheckbox.blockSignals(false);
break;
case TRIGGER_HIGH:
inputCheckbox.blockSignals(true);
inputCheckbox.setChecked(false);
inputCheckbox.blockSignals(false);
levelCheckbox.blockSignals(true);
levelCheckbox.setChecked(true);
levelCheckbox.setEnabled(true);
levelCheckbox.blockSignals(false);
break;
case TRIGGER_LOW:
inputCheckbox.blockSignals(true);
inputCheckbox.setChecked(false);
inputCheckbox.blockSignals(false);
levelCheckbox.blockSignals(true);
levelCheckbox.setChecked(true);
levelCheckbox.setEnabled(false);
levelCheckbox.blockSignals(false);
default:
break;
}
}
}
void TriggerWidget::updateTriggerState() void TriggerWidget::updateTriggerState()
{ {
trigger_state_t state = TRIGGER_INPUT; trigger_state_t state;
if(inputCheckbox.isChecked()) if(inputCheckbox.isChecked())
{ {
levelCheckbox.blockSignals(true); levelCheckbox.blockSignals(true);

View file

@ -22,7 +22,6 @@ public:
uint16_t getDeviceSerial() const; uint16_t getDeviceSerial() const;
uint16_t getTriggerNumber() const; uint16_t getTriggerNumber() const;
void updateSate(uint16_t serial, uint16_t trigger, trigger_state_t state);
private slots: private slots:
void onInputToggled(bool checked); void onInputToggled(bool checked);