Use desinger form for main window, add ganged combo box

This commit is contained in:
Carl Philipp Klemm 2025-07-03 11:55:32 +02:00
parent d36d5e563a
commit 9e0d7a5d9d
7 changed files with 141 additions and 92 deletions

View file

@ -11,8 +11,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Find Qt6
find_package(Qt6 REQUIRED COMPONENTS Widgets)
# Enable automoc for Qt meta-object compiler
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
# Include the libeismultiplexer library
include_directories(/workspace/libeismultiplexer)
@ -21,10 +21,11 @@ link_directories(/workspace/libeismultiplexer/build)
# Add the application executable
add_executable(eismultiplexer-qt
main.cpp
mainwindow.cpp
mainwindow.h
channelwidget.cpp
channelwidget.h
mainwindow.h
mainwindow.cpp
mainwindow.ui
)
target_compile_options(eismultiplexer-qt PUBLIC "-Wall")

View file

@ -1,30 +1,42 @@
#include "channelwidget.h"
#include <QDebug>
#include <QMessageBox>
ChannelWidget::ChannelWidget(uint16_t deviceSerial, uint16_t channelNumber, struct eismultiplexer* multiplexer,
ChannelWidget::ChannelWidget(uint16_t deviceSerial, uint16_t channelNumber, std::shared_ptr<struct eismultiplexer> multiplexer,
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:")
{
// Create layout
QHBoxLayout* layout = new QHBoxLayout(this);
hlayout.addLayout(&labellayout);
vlayout.addLayout(&hlayout);
// Create label with device serial and channel number
label = new QLabel(QString("Device %1, Channel %2").arg(deviceSerial).arg(channelNumber), this);
layout->addWidget(label);
labellayout.addWidget(&devicelabel);
labellayout.addWidget(&channellabel);
// Create checkbox
checkbox = new QCheckBox(this);
layout->addWidget(checkbox);
line.setGeometry(QRect(320, 150, 118, 3));
line.setFrameShape(QFrame::HLine);
line.setFrameShadow(QFrame::Sunken);
vlayout.addWidget(&line);
// Connect checkbox signal
connect(checkbox, &QCheckBox::toggled, this, &ChannelWidget::onChannelToggled);
gangcombo.addItem("Unganged");
// Set layout
setLayout(layout);
hlayout.addStretch();
hlayout.addWidget(&ganglabel);
hlayout.addWidget(&gangcombo);
hlayout.addWidget(&checkbox);
connect(&checkbox, &QCheckBox::toggled, this, &ChannelWidget::onChannelToggled);
setFixedHeight(96);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setLayout(&vlayout);
}
ChannelWidget::~ChannelWidget()
@ -44,7 +56,7 @@ uint16_t ChannelWidget::getChannelNumber() const
bool ChannelWidget::isChecked() const
{
return checkbox->isChecked();
return checkbox.isChecked();
}
void ChannelWidget::onChannelToggled(bool checked)
@ -60,8 +72,8 @@ void ChannelWidget::onChannelToggled(bool checked)
QMessageBox::warning(this, tr("Connection Failed"),
tr("Failed to connect channel %1 on device %2").arg(channelNumber).arg(deviceSerial));
qWarning() << "Failed to connect channel" << channelNumber << "on device" << deviceSerial;
checkbox->blockSignals(true);
checkbox->setChecked(false);
checkbox.blockSignals(true);
checkbox.setChecked(false);
setEnabled(false); // Gray out the widget
}
} else {
@ -69,8 +81,8 @@ void ChannelWidget::onChannelToggled(bool checked)
QMessageBox::warning(this, tr("Disconnection Failed"),
tr("Failed to disconnect channel %1 on device %2").arg(channelNumber).arg(deviceSerial));
qWarning() << "Failed to disconnect channel" << channelNumber << "on device" << deviceSerial;
checkbox->blockSignals(true);
checkbox->setChecked(true);
checkbox.blockSignals(true);
checkbox.setChecked(true);
setEnabled(false); // Gray out the widget
}
}

View file

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

View file

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

View file

@ -1,50 +1,22 @@
#include "mainwindow.h"
#include <QDebug>
#include <QMessageBox>
#include <eismultiplexer.h>
#include <memory>
#include <QMessageBox>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
setupUi();
ui->setupUi(this);
enumerateDevices();
connect(ui->actionQuit, &QAction::triggered, this, [this](){close();});
}
MainWindow::~MainWindow()
{
// Clean up all channel widgets
for (auto widget : channelWidgets) {
delete widget;
delete ui;
}
}
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()
{
@ -67,10 +39,10 @@ void MainWindow::enumerateDevices()
qDebug()<<"Adding channels from device "<<serial;
if (eismultiplexer_get_channel_count(multiplexer.get(), &channelCount) >= 0) {
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;
channelWidgets.push_back(widget);
scrollLayout->addWidget(widget);
channels.push_back(widget);
ui->channelLayout->addWidget(widget.get());
}
}
} else {
@ -78,8 +50,9 @@ void MainWindow::enumerateDevices()
tr("Failed to connect to device with serial %1").arg(serial));
qWarning() << "Failed to connect to device with serial" << serial;
}
ui->channelLayout->addStretch();
}
ui->statusbar->showMessage("Ready");
free(serials);
}

View file

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

68
mainwindow.ui Normal file
View file

@ -0,0 +1,68 @@
<?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>