Add support for reading state
This commit is contained in:
parent
1eac3f6a83
commit
4c2a4790c0
|
@ -42,8 +42,6 @@ add_executable(${PROJECT_NAME}
|
|||
mainwindow.h
|
||||
mainwindow.cpp
|
||||
mainwindow.ui
|
||||
multiplexer.h
|
||||
multiplexer.cpp
|
||||
triggerwidget.cpp
|
||||
triggerwidget.h
|
||||
pythonrunner.cpp
|
||||
|
|
|
@ -108,7 +108,6 @@ void ChannelWidget::onGangComboChanged(int index)
|
|||
gangedChannelNumber = -1;
|
||||
checkbox.setEnabled(true);
|
||||
checkbox.setChecked(false);
|
||||
checkbox.setChecked(false);
|
||||
} else {
|
||||
// A ganged channel was selected
|
||||
QString currentText = gangcombo.currentText();
|
||||
|
@ -128,7 +127,7 @@ void ChannelWidget::onGangComboChanged(int index)
|
|||
void ChannelWidget::onOtherChannelStateChanged(uint16_t deviceSerial, uint16_t channelNumber, bool checked)
|
||||
{
|
||||
// If this channel is ganged to the channel that changed state
|
||||
if (gangedDeviceSerial == deviceSerial && gangedChannelNumber == channelNumber) {
|
||||
if (this->deviceSerial == deviceSerial && this->channelNumber == channelNumber) {
|
||||
// Update our checkbox state to follow the ganged channel
|
||||
checkbox.blockSignals(true);
|
||||
checkbox.setChecked(checked);
|
||||
|
@ -163,3 +162,9 @@ void ChannelWidget::setGangedChannel(uint16_t gangedDeviceSerial, uint16_t gange
|
|||
updateCheckboxState();
|
||||
}
|
||||
|
||||
void ChannelWidget::replaceMultiplexer(std::shared_ptr<struct eismultiplexer> multiplexer, int serial)
|
||||
{
|
||||
if(serial == deviceSerial || serial == -1)
|
||||
this->multiplexer = multiplexer;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ public slots:
|
|||
private slots:
|
||||
void onChannelToggled(bool checked);
|
||||
void onGangComboChanged(int index);
|
||||
void replaceMultiplexer(std::shared_ptr<struct eismultiplexer> multiplexer, int serial = -1);
|
||||
|
||||
signals:
|
||||
void channelAboutToBeTurnedOn(uint16_t deviceSerial, uint16_t channelNumber);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <eismultiplexer.h>
|
||||
#include <QMessageBox>
|
||||
#include <QMessageBox>
|
||||
#include <set>
|
||||
|
@ -19,7 +18,6 @@ MainWindow::MainWindow(QWidget *parent):
|
|||
isFileModified(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
enumerateDevices();
|
||||
|
||||
codeEditor.setAutoIndentation(true);
|
||||
codeEditor.setAutoParentheses(true);
|
||||
|
@ -55,6 +53,8 @@ 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);
|
||||
enumerateDevices();
|
||||
generateExample();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
@ -62,6 +62,30 @@ MainWindow::~MainWindow()
|
|||
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()
|
||||
{
|
||||
if (!currentFilePath.isEmpty()) {
|
||||
|
@ -150,6 +174,9 @@ void MainWindow::enumerateDevices()
|
|||
{
|
||||
size_t count = 0;
|
||||
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)
|
||||
{
|
||||
|
@ -168,6 +195,7 @@ void MainWindow::enumerateDevices()
|
|||
int ret = eismultiplexer_connect(multiplexer.get(), serial);
|
||||
if (ret == 0)
|
||||
{
|
||||
multiplexers.push_back({serial, multiplexer});
|
||||
uint16_t channelCount = 0;
|
||||
qDebug()<<"Adding channels from device "<<serial;
|
||||
if (eismultiplexer_get_channel_count(multiplexer.get(), &channelCount) >= 0)
|
||||
|
@ -177,7 +205,7 @@ void MainWindow::enumerateDevices()
|
|||
std::shared_ptr<ChannelWidget> widget(new ChannelWidget(serial, channel, multiplexer));
|
||||
qDebug()<<"Added widget from device "<<serial<<" channel "<<channel;
|
||||
channels.push_back(widget);
|
||||
ui->channelLayout->addWidget(widget.get());
|
||||
channelLayout->addWidget(widget.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +219,7 @@ void MainWindow::enumerateDevices()
|
|||
std::shared_ptr<TriggerWidget> triggerWidget(new TriggerWidget(serial, trigger, multiplexer));
|
||||
qDebug()<<"Added trigger widget from device "<<serial<<" trigger "<<trigger;
|
||||
triggers.push_back(triggerWidget);
|
||||
ui->channelLayout->addWidget(triggerWidget.get());
|
||||
channelLayout->addWidget(triggerWidget.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +230,8 @@ void MainWindow::enumerateDevices()
|
|||
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
|
||||
for (const auto& widget : channels) {
|
||||
|
@ -226,10 +255,11 @@ void MainWindow::enumerateDevices()
|
|||
}
|
||||
}
|
||||
|
||||
readState();
|
||||
|
||||
ui->statusbar->showMessage("Ready");
|
||||
|
||||
free(serials);
|
||||
generateExample();
|
||||
}
|
||||
|
||||
void MainWindow::runScript() {
|
||||
|
@ -239,14 +269,25 @@ void MainWindow::runScript() {
|
|||
ui->pushButtonStop->setEnabled(true);
|
||||
codeEditor.setEnabled(false);
|
||||
ui->scrollArea->setEnabled(false);
|
||||
disconnectDevices();
|
||||
}
|
||||
|
||||
void MainWindow::stopScript() {
|
||||
pythonRunner.stopScript();
|
||||
channels.clear();
|
||||
triggers.clear();
|
||||
ui->pushButtonRun->setEnabled(true);
|
||||
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()
|
||||
|
|
13
mainwindow.h
13
mainwindow.h
|
@ -1,13 +1,13 @@
|
|||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <eismultiplexer.h>
|
||||
#include <QMainWindow>
|
||||
#include <memory>
|
||||
#include <QCodeEditor>
|
||||
#include <QPythonCompleter>
|
||||
#include <QPythonHighlighter>
|
||||
#include <QProgressBar>
|
||||
|
||||
#include "channelwidget.h"
|
||||
#include "triggerwidget.h"
|
||||
#include "pythonrunner.h"
|
||||
|
@ -19,10 +19,11 @@ class MainWindow;
|
|||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
std::vector<std::shared_ptr<ChannelWidget>> channels;
|
||||
std::vector<std::shared_ptr<TriggerWidget>> triggers;
|
||||
Ui::MainWindow *ui;
|
||||
Q_OBJECT
|
||||
std::vector<std::shared_ptr<TriggerWidget>> triggers;
|
||||
std::vector<std::shared_ptr<ChannelWidget>> channels;
|
||||
std::vector<std::pair<uint16_t, std::shared_ptr<struct eismultiplexer>>> multiplexers;
|
||||
Ui::MainWindow *ui;
|
||||
QCodeEditor codeEditor;
|
||||
QPythonHighlighter highligter;
|
||||
QPythonCompleter completer;
|
||||
|
@ -42,11 +43,13 @@ private slots:
|
|||
void onActionSaveAsTriggered();
|
||||
void runScript();
|
||||
void stopScript();
|
||||
void readState();
|
||||
|
||||
private:
|
||||
void enumerateDevices();
|
||||
void generateExample();
|
||||
void updateStatus();
|
||||
void disconnectDevices();
|
||||
QString currentFilePath;
|
||||
bool isFileModified;
|
||||
};
|
||||
|
|
101
mainwindow.ui
101
mainwindow.ui
|
@ -16,58 +16,65 @@
|
|||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="codeLayout">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<widget class="QWidget" name="">
|
||||
<layout class="QVBoxLayout" name="codeLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonStop">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="QIcon::ThemeIcon::MediaPlaybackStop"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonRun">
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="QIcon::ThemeIcon::MediaPlaybackStart"/>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonStop">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="QIcon::ThemeIcon::MediaPlaybackStop"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonRun">
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="QIcon::ThemeIcon::MediaPlaybackStart"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>591</width>
|
||||
<height>533</height>
|
||||
</rect>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="channelLayout"/>
|
||||
</item>
|
||||
</layout>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>504</width>
|
||||
<height>537</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#include "multiplexer.h"
|
||||
|
||||
Multiplexer::Multiplexer(QObject *parent)
|
||||
: QObject{parent}
|
||||
{}
|
||||
|
||||
Multiplexer::~Multiplexer()
|
||||
{
|
||||
for(auto& multiplexer : multiplexers)
|
||||
eismultiplexer_disconnect(multiplexer.get());
|
||||
}
|
||||
|
||||
void Multiplexer::probe()
|
||||
{
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#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
|
|
@ -16,7 +16,7 @@ PythonRunner::~PythonRunner() {
|
|||
}
|
||||
}
|
||||
|
||||
void PythonRunner::runScript(const QString& scriptContent) {
|
||||
bool PythonRunner::runScript(const QString& scriptContent) {
|
||||
if (m_process->state() == QProcess::Running) {
|
||||
m_process->terminate();
|
||||
m_process->waitForFinished(1000);
|
||||
|
@ -24,6 +24,8 @@ void PythonRunner::runScript(const QString& scriptContent) {
|
|||
|
||||
m_outputWidget->clear();
|
||||
m_process->start("python3", QStringList() << "-u" << "-c" << scriptContent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PythonRunner::stopScript() {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <QTextEdit>
|
||||
#include <QProcess>
|
||||
#include <QObject>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
class PythonRunner : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -11,7 +12,7 @@ public:
|
|||
PythonRunner(QTextEdit* outputWidget, QObject* parent = nullptr);
|
||||
~PythonRunner();
|
||||
|
||||
void runScript(const QString& scriptContent);
|
||||
bool runScript(const QString& scriptContent);
|
||||
void stopScript();
|
||||
|
||||
private slots:
|
||||
|
@ -25,4 +26,6 @@ signals:
|
|||
private:
|
||||
QTextEdit* m_outputWidget;
|
||||
QProcess* m_process;
|
||||
bool ready;
|
||||
QTemporaryDir dir;
|
||||
};
|
||||
|
|
|
@ -70,9 +70,46 @@ void TriggerWidget::onLevelToggled(bool checked)
|
|||
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()
|
||||
{
|
||||
trigger_state_t state;
|
||||
trigger_state_t state = TRIGGER_INPUT;
|
||||
if(inputCheckbox.isChecked())
|
||||
{
|
||||
levelCheckbox.blockSignals(true);
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
|
||||
uint16_t getDeviceSerial() const;
|
||||
uint16_t getTriggerNumber() const;
|
||||
void updateSate(uint16_t serial, uint16_t trigger, trigger_state_t state);
|
||||
|
||||
private slots:
|
||||
void onInputToggled(bool checked);
|
||||
|
|
Loading…
Reference in a new issue