Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b7e323603c | ||
|
a3fbd2877b | ||
|
66937e2cfc |
|
@ -28,6 +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 COMPONENTS Interpreter Development REQUIRED)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
@ -45,11 +46,15 @@ add_executable(${PROJECT_NAME}
|
||||||
multiplexer.cpp
|
multiplexer.cpp
|
||||||
triggerwidget.cpp
|
triggerwidget.cpp
|
||||||
triggerwidget.h
|
triggerwidget.h
|
||||||
|
pythonrunner.cpp
|
||||||
|
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_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets Qt6::Core ${EISMULIPLEXER_LIBRARIES} QCodeEditor)
|
target_include_directories(${PROJECT_NAME} PRIVATE ${Python3_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets Qt6::Core ${EISMULIPLEXER_LIBRARIES} QCodeEditor ${Python3_LIBRARIES})
|
||||||
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)
|
||||||
|
|
|
@ -15,7 +15,8 @@ MainWindow::MainWindow(QWidget *parent):
|
||||||
codeEditor(this),
|
codeEditor(this),
|
||||||
pythonOutput(this),
|
pythonOutput(this),
|
||||||
currentFilePath(""),
|
currentFilePath(""),
|
||||||
isFileModified(false)
|
isFileModified(false),
|
||||||
|
pythonRunner(nullptr)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
enumerateDevices();
|
enumerateDevices();
|
||||||
|
@ -49,6 +50,11 @@ MainWindow::MainWindow(QWidget *parent):
|
||||||
isFileModified = true;
|
isFileModified = true;
|
||||||
updateStatus();
|
updateStatus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
|
@ -226,6 +232,19 @@ void MainWindow::enumerateDevices()
|
||||||
generateExample();
|
generateExample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onPushButtonRunClicked() {
|
||||||
|
QString scriptContent = codeEditor.toPlainText();
|
||||||
|
pythonRunner->runScript(scriptContent);
|
||||||
|
ui->pushButtonRun->setEnabled(false);
|
||||||
|
ui->pushButtonStop->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onPushButtonStopClicked() {
|
||||||
|
pythonRunner->stopScript();
|
||||||
|
ui->pushButtonRun->setEnabled(true);
|
||||||
|
ui->pushButtonStop->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::generateExample()
|
void MainWindow::generateExample()
|
||||||
{
|
{
|
||||||
QString example =
|
QString example =
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "channelwidget.h"
|
#include "channelwidget.h"
|
||||||
#include "triggerwidget.h"
|
#include "triggerwidget.h"
|
||||||
|
#include "pythonrunner.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
|
@ -27,6 +28,7 @@ class MainWindow : public QMainWindow
|
||||||
QPythonHighlighter highligter;
|
QPythonHighlighter highligter;
|
||||||
QPythonCompleter completer;
|
QPythonCompleter completer;
|
||||||
QTextEdit pythonOutput;
|
QTextEdit pythonOutput;
|
||||||
|
PythonRunner* pythonRunner;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void channelStateChanged(uint16_t device, uint16_t channel);
|
void channelStateChanged(uint16_t device, uint16_t channel);
|
||||||
|
@ -39,6 +41,8 @@ private slots:
|
||||||
void onActionOpenTriggered();
|
void onActionOpenTriggered();
|
||||||
void onActionSaveTriggered();
|
void onActionSaveTriggered();
|
||||||
void onActionSaveAsTriggered();
|
void onActionSaveAsTriggered();
|
||||||
|
void onPushButtonRunClicked();
|
||||||
|
void onPushButtonStopClicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void enumerateDevices();
|
void enumerateDevices();
|
||||||
|
|
73
pythonembed.cpp
Normal file
73
pythonembed.cpp
Normal 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
25
pythonembed.h
Normal 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
|
||||||
|
|
24
pythonrunner.cpp
Normal file
24
pythonrunner.cpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
#include "pythonrunner.h"
|
||||||
|
#include "pythonembed.h"
|
||||||
|
|
||||||
|
PythonRunner::PythonRunner(QTextEdit* outputWidget, QObject* parent)
|
||||||
|
: QObject(parent), m_outputWidget(outputWidget), m_pythonEmbed(nullptr) {
|
||||||
|
m_pythonEmbed = new PythonEmbed(m_outputWidget, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PythonRunner::~PythonRunner() {
|
||||||
|
delete m_pythonEmbed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonRunner::runScript(const QString& scriptContent) {
|
||||||
|
if (m_pythonEmbed) {
|
||||||
|
m_pythonEmbed->runScript(scriptContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonRunner::stopScript() {
|
||||||
|
if (m_pythonEmbed) {
|
||||||
|
m_pythonEmbed->stopScript();
|
||||||
|
}
|
||||||
|
}
|
26
pythonrunner.h
Normal file
26
pythonrunner.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#ifndef PYTHONRUNNER_H
|
||||||
|
#define PYTHONRUNNER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
class PythonEmbed;
|
||||||
|
|
||||||
|
class PythonRunner : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PythonRunner(QTextEdit* outputWidget, QObject* parent = nullptr);
|
||||||
|
~PythonRunner();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void runScript(const QString& scriptContent);
|
||||||
|
void stopScript();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTextEdit* m_outputWidget;
|
||||||
|
PythonEmbed* m_pythonEmbed;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PYTHONRUNNER_H
|
Loading…
Reference in a new issue