Compare commits

..

No commits in common. "5c5efb50299c6bd47da700168f7fbb7a4a5786be" and "d36d5e563a69d486ae3978efaff5d2572f9d5d9c" have entirely different histories.

9 changed files with 180 additions and 300 deletions

View file

@ -1,50 +1,35 @@
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.14)
project(eismuliplexer-qt) # Set the project name
project(eismultiplexer-qt)
set(CMAKE_PROJECT_VERSION_MAJOR 0)
set(CMAKE_PROJECT_VERSION_MINOR 9)
set(CMAKE_PROJECT_VERSION_PATCH 0)
add_compile_definitions(VERSION_MAJOR=${CMAKE_PROJECT_VERSION_MAJOR})
add_compile_definitions(VERSION_MINOR=${CMAKE_PROJECT_VERSION_MINOR})
add_compile_definitions(VERSION_PATCH=${CMAKE_PROJECT_VERSION_PATCH})
if(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
message(FATAL_ERROR "Windows builds have to be cross compiled on UNIX")
endif()
message("Platform " ${CMAKE_SYSTEM_NAME})
if(WIN32)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/release-win.sh ${CMAKE_CURRENT_BINARY_DIR}/release.sh @ONLY)
add_custom_target(package
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/release.sh
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Createing release archive"
VERBATIM)
endif(WIN32)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(PkgConfig REQUIRED) # Find Qt6
pkg_check_modules(EISMULIPLEXER REQUIRED eismuliplexer)
find_package(Qt6 REQUIRED COMPONENTS Widgets) find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package(Qt6 REQUIRED COMPONENTS Core)
# Enable automoc for Qt meta-object compiler
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
add_executable(${PROJECT_NAME} # Include the libeismultiplexer library
include_directories(/workspace/libeismultiplexer)
link_directories(/workspace/libeismultiplexer/build)
# Add the application executable
add_executable(eismultiplexer-qt
main.cpp main.cpp
mainwindow.cpp
mainwindow.h
channelwidget.cpp channelwidget.cpp
channelwidget.h channelwidget.h
mainwindow.h
mainwindow.cpp
mainwindow.ui
multiplexer.h
multiplexer.cpp
) )
target_compile_options(${PROJECT_NAME} PUBLIC "-Wall") target_compile_options(eismultiplexer-qt PUBLIC "-Wall")
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets Qt6::Core ${EISMULIPLEXER_LIBRARIES})
#target_include_directories(${PROJECT_NAME} PUBLIC ${EISMULIPLEXER_INCLUDE_DIRS}) # Link Qt Widgets
target_link_libraries(eismultiplexer-qt Qt6::Widgets eismultiplexer)
# Include directories
target_include_directories(eismultiplexer-qt PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

View file

@ -1,43 +1,30 @@
#include "channelwidget.h" #include "channelwidget.h"
#include <QDebug> #include <QDebug>
#include <QMessageBox> #include <QMessageBox>
ChannelWidget::ChannelWidget(uint16_t deviceSerial, uint16_t channelNumber, ChannelWidget::ChannelWidget(uint16_t deviceSerial, uint16_t channelNumber, struct eismultiplexer* multiplexer,
std::shared_ptr<struct eismultiplexer> multiplexer,
QWidget *parent) QWidget *parent)
: : QWidget(parent), deviceSerial(deviceSerial), channelNumber(channelNumber), multiplexer(multiplexer)
QWidget(parent),
deviceSerial(deviceSerial),
channelNumber(channelNumber),
multiplexer(multiplexer),
checkbox("Enable"),
devicelabel(QString::asprintf("Device %04u", deviceSerial)),
channellabel(QString::asprintf("Channel %u", channelNumber)),
ganglabel("Ganged:")
{ {
hlayout.addLayout(&labellayout); // Create layout
vlayout.addLayout(&hlayout); QHBoxLayout* layout = new QHBoxLayout(this);
labellayout.addWidget(&devicelabel); // Create label with device serial and channel number
labellayout.addWidget(&channellabel); label = new QLabel(QString("Device %1, Channel %2").arg(deviceSerial).arg(channelNumber), this);
layout->addWidget(label);
line.setGeometry(QRect(320, 150, 118, 3)); // Create checkbox
line.setFrameShape(QFrame::HLine); checkbox = new QCheckBox(this);
line.setFrameShadow(QFrame::Sunken); layout->addWidget(checkbox);
vlayout.addWidget(&line);
gangcombo.addItem("Unganged"); // Connect checkbox signal
connect(checkbox, &QCheckBox::toggled, this, &ChannelWidget::onChannelToggled);
hlayout.addStretch(); // Set layout
hlayout.addWidget(&ganglabel); setLayout(layout);
hlayout.addWidget(&gangcombo);
hlayout.addWidget(&checkbox);
connect(&checkbox, &QCheckBox::toggled, this, &ChannelWidget::onChannelToggled);
setFixedHeight(96);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setLayout(&vlayout);
} }
ChannelWidget::~ChannelWidget() ChannelWidget::~ChannelWidget()
@ -57,39 +44,33 @@ uint16_t ChannelWidget::getChannelNumber() const
bool ChannelWidget::isChecked() const bool ChannelWidget::isChecked() const
{ {
return checkbox.isChecked(); return checkbox->isChecked();
} }
void ChannelWidget::onChannelToggled(bool checked) void ChannelWidget::onChannelToggled(bool checked)
{ {
if (checked) if (checked) {
{
// Emit signal before actually turning on the channel // Emit signal before actually turning on the channel
emit channelAboutToBeTurnedOn(deviceSerial, channelNumber); emit channelAboutToBeTurnedOn(deviceSerial, channelNumber);
} }
channel_t channelFlag = static_cast<channel_t>(1 << channelNumber); channel_t channelFlag = static_cast<channel_t>(1 << channelNumber);
if (checked) if (checked) {
{ if (eismultiplexer_connect_channel(multiplexer.get(), channelFlag) < 0) {
if (eismultiplexer_connect_channel(multiplexer.get(), channelFlag) < 0)
{
QMessageBox::warning(this, tr("Connection Failed"), QMessageBox::warning(this, tr("Connection Failed"),
tr("Failed to connect channel %1 on device %2").arg(channelNumber).arg(deviceSerial)); tr("Failed to connect channel %1 on device %2").arg(channelNumber).arg(deviceSerial));
qWarning() << "Failed to connect channel" << channelNumber << "on device" << deviceSerial; qWarning() << "Failed to connect channel" << channelNumber << "on device" << deviceSerial;
checkbox.blockSignals(true); checkbox->blockSignals(true);
checkbox.setChecked(false); checkbox->setChecked(false);
setEnabled(false); // Gray out the widget setEnabled(false); // Gray out the widget
} }
} } else {
else if (eismultiplexer_disconnect_channel(multiplexer.get(), channelFlag) < 0) {
{
if (eismultiplexer_disconnect_channel(multiplexer.get(), channelFlag) < 0)
{
QMessageBox::warning(this, tr("Disconnection Failed"), QMessageBox::warning(this, tr("Disconnection Failed"),
tr("Failed to disconnect channel %1 on device %2").arg(channelNumber).arg(deviceSerial)); tr("Failed to disconnect channel %1 on device %2").arg(channelNumber).arg(deviceSerial));
qWarning() << "Failed to disconnect channel" << channelNumber << "on device" << deviceSerial; qWarning() << "Failed to disconnect channel" << channelNumber << "on device" << deviceSerial;
checkbox.blockSignals(true); checkbox->blockSignals(true);
checkbox.setChecked(true); checkbox->setChecked(true);
setEnabled(false); // Gray out the widget setEnabled(false); // Gray out the widget
} }
} }

View file

@ -5,7 +5,6 @@
#include <QCheckBox> #include <QCheckBox>
#include <QLabel> #include <QLabel>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QComboBox>
#include <eismultiplexer.h> #include <eismultiplexer.h>
#include <memory> #include <memory>
@ -14,8 +13,7 @@ class ChannelWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit ChannelWidget(uint16_t deviceSerial, uint16_t channelNumber, explicit ChannelWidget(uint16_t deviceSerial, uint16_t channelNumber, struct eismultiplexer* multiplexer,
std::shared_ptr<struct eismultiplexer> multiplexer,
QWidget *parent = nullptr); QWidget *parent = nullptr);
~ChannelWidget() override; ~ChannelWidget() override;
@ -33,15 +31,8 @@ private:
uint16_t deviceSerial; uint16_t deviceSerial;
uint16_t channelNumber; uint16_t channelNumber;
std::shared_ptr<struct eismultiplexer> multiplexer; std::shared_ptr<struct eismultiplexer> multiplexer;
QCheckBox checkbox; QCheckBox* checkbox;
QLabel devicelabel; QLabel* label;
QLabel channellabel;
QLabel ganglabel;
QComboBox gangcombo;
QFrame line;
QVBoxLayout vlayout;
QHBoxLayout hlayout;
QVBoxLayout labellayout;
}; };
#endif // CHANNELWIDGET_H #endif // CHANNELWIDGET_H

View file

@ -1,3 +1,4 @@
#include <QApplication> #include <QApplication>
#include "mainwindow.h" #include "mainwindow.h"

View file

@ -1,68 +1,85 @@
#include <eismultiplexer.h>
#include <QMessageBox>
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include <QDebug>
#include <QMessageBox>
#include <eismultiplexer.h>
#include <memory>
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
, ui(new Ui::MainWindow)
{ {
ui->setupUi(this); setupUi();
enumerateDevices(); enumerateDevices();
connect(ui->actionQuit, &QAction::triggered, this, [this]()
{
close();
});
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
delete ui; // Clean up all channel widgets
for (auto widget : channelWidgets) {
delete widget;
}
} }
void MainWindow::setupUi()
{
// Create central widget and main layout
centralWidget = new QWidget(this);
mainLayout = new QVBoxLayout(centralWidget);
// Create scroll area
scrollArea = new QScrollArea(this);
scrollContent = new QWidget();
scrollLayout = new QVBoxLayout(scrollContent);
// Set up scroll area properties
scrollArea->setWidget(scrollContent);
scrollArea->setWidgetResizable(true);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Add scroll area to main layout
mainLayout->addWidget(scrollArea);
// Set central widget
setCentralWidget(centralWidget);
setWindowTitle("EIS Multiplexer Controller");
}
void MainWindow::onChannelAboutToBeTurnedOn(uint16_t deviceSerial, uint16_t channelNumber)
{}
void MainWindow::enumerateDevices() 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 (!serials || count == 0) if (!serials || count == 0) {
{ QMessageBox::warning(this, tr("No Devices Found"),
QMessageBox::warning(nullptr, tr("No Devices Found"),
tr("No EIS multiplexer devices were found. Please connect a device and try again.")); tr("No EIS multiplexer devices were found. Please connect a device and try again."));
qWarning() << "No EIS multiplexer devices found"; qWarning() << "No EIS multiplexer devices found";
exit(0); close();
return; return;
} }
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++) {
{
uint16_t serial = serials[i]; uint16_t serial = serials[i];
std::shared_ptr<struct eismultiplexer> multiplexer(new struct eismultiplexer); std::shared_ptr<struct eismultiplexer> multiplexer(new struct eismultiplexer);
if (eismultiplexer_connect(multiplexer.get(), serial) >= 0) if (eismultiplexer_connect(multiplexer.get(), serial) >= 0) {
{
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) {
{ for (uint16_t channel = 0; channel < channelCount; channel++) {
for (uint16_t channel = 0; channel < channelCount; channel++) ChannelWidget* widget = new ChannelWidget(serial, channel, multiplexer.get());
{
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); channelWidgets.push_back(widget);
ui->channelLayout->addWidget(widget.get()); scrollLayout->addWidget(widget);
} }
} }
} } else {
else
{
QMessageBox::warning(this, tr("Connection Failed"), QMessageBox::warning(this, tr("Connection Failed"),
tr("Failed to connect to device with serial %1").arg(serial)); tr("Failed to connect to device with serial %1").arg(serial));
qWarning() << "Failed to connect to device with serial" << serial; qWarning() << "Failed to connect to device with serial" << serial;
} }
ui->channelLayout->addStretch();
} }
ui->statusbar->showMessage("Ready");
free(serials); free(serials);
} }

View file

@ -1,31 +1,42 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow> #include <QMainWindow>
#include <memory> #include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
#include <vector>
#include "channelwidget.h" #include "channelwidget.h"
namespace Ui QT_BEGIN_NAMESPACE
{ namespace Ui { class MainWindow; }
class MainWindow; QT_END_NAMESPACE
}
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
std::vector<std::shared_ptr<ChannelWidget>> channels;
Ui::MainWindow *ui;
signals:
void channelStateChanged(uint16_t device, uint16_t channel);
public: public:
explicit MainWindow(QWidget *parent = nullptr); explicit MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow() override;
private slots:
void onChannelAboutToBeTurnedOn(uint16_t deviceSerial, uint16_t channelNumber);
private: private:
void enumerateDevices(); void enumerateDevices();
void setupUi();
QWidget *centralWidget;
QVBoxLayout *mainLayout;
QScrollArea *scrollArea;
QWidget *scrollContent;
QVBoxLayout *scrollLayout;
std::vector<ChannelWidget*> channelWidgets;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View file

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>EisMultiplexer-Qt</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<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>788</width>
<height>537</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QVBoxLayout" name="channelLayout"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>29</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionQuit"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionQuit">
<property name="text">
<string>Quit</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -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()
{
}

View file

@ -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