now works on windows
This commit is contained in:
2026-02-14 14:32:50 +01:00
parent b493129184
commit 9765cd3e51
12 changed files with 127 additions and 49 deletions
+41 -35
View File
@@ -6,43 +6,17 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
file(GLOB_RECURSE ui "ui/*")
set(PROJECT_SOURCES
${ui}
helpers.cpp
helpers.hpp
IterableEnum.hpp
main.cpp
mainwindow.cpp
mainwindow.hpp
mainwindow.ui
ui_base.cpp
ui_base.hpp
web_socket_wrapper.cpp
web_socket_wrapper.hpp
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(unisim_client
MANUAL_FINALIZATION
${PROJECT_SOURCES}
$<$<BOOL:${EMSCRIPTEN}>:${sims}>
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET Simulator - CVS_I10 APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR } / android)
# For more information, see https: // doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
if(ANDROID)
add_library(unisim_client SHARED
${PROJECT_SOURCES}
)
# Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
add_executable(unisim_client
${PROJECT_SOURCES}
)
endif()
endif()
qt_add_executable(unisim_client
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
set_target_properties(
unisim_client
@@ -50,18 +24,16 @@ set_target_properties(
AUTOMOC ON
AUTORCC ON
AUTOUIC ON
LINK_FLAGS "-Wl,--export-dynamic"
)
target_include_directories(unisim_client
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/simulators
${CMAKE_CURRENT_LIST_DIR}/ui
${PROJECT_BINARY_DIR}/
)
target_link_libraries(unisim_client PRIVATE qwt spdlog Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::WebSockets magic_enum::magic_enum nlohmann_json::nlohmann_json git_tag)
target_link_libraries(unisim_client PUBLIC Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::WebSockets spdlog magic_enum::magic_enum nlohmann_json::nlohmann_json git_tag client_common)
include(GNUInstallDirs)
install(TARGETS unisim_client
@@ -74,6 +46,40 @@ if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(unisim_client)
endif()
add_library(client_common SHARED)
target_sources(client_common
PRIVATE
${ui}
helpers.cpp
helpers.hpp
ui_base.cpp
ui_base.hpp
web_socket_wrapper.cpp
web_socket_wrapper.hpp
)
target_compile_definitions(client_common PRIVATE
INTERNAL
)
target_link_libraries(client_common
PUBLIC
qwt Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::WebSockets magic_enum::magic_enum nlohmann_json::nlohmann_json
)
set_target_properties(
client_common
PROPERTIES
AUTOMOC ON
AUTORCC ON
AUTOUIC ON
)
target_include_directories(client_common
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/ui
${PROJECT_BINARY_DIR}
)
if (NOT EMSCRIPTEN)
file(GLOB_RECURSE sims "simulators/*.cpp")
# Loop through each .cpp file and create a library for it
@@ -83,8 +89,8 @@ if (NOT EMSCRIPTEN)
# Create a library for each .cpp file
add_library(ui_${LIB_NAME} SHARED ${CMAKE_CURRENT_SOURCE_DIR}/simulators/${LIB_NAME}.hpp ${CMAKE_CURRENT_SOURCE_DIR}/simulators/${LIB_NAME}.cpp ${CMAKE_CURRENT_SOURCE_DIR}/simulators/${LIB_NAME}.ui)
target_link_libraries(ui_${LIB_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets magic_enum::magic_enum nlohmann_json::nlohmann_json)
target_include_directories(ui_${LIB_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/ui ${CMAKE_SOURCE_DIR}/external/qwt/src ${PROJECT_BINARY_DIR}/)
target_link_libraries(ui_${LIB_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Widgets client_common)
target_include_directories(ui_${LIB_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/ui ${PROJECT_BINARY_DIR}/)
set_target_properties(
ui_${LIB_NAME}
+7 -1
View File
@@ -16,8 +16,14 @@ MainWindow::MainWindow(QUrl ws_url, QString sim, QWidget *parent)
m_web_socket(new Web_socket_wrapper(ws_url))
{
ui->setupUi(this);
connect(m_web_socket.get(), &Web_socket_wrapper::log_signal, this,
[](const char *filename_in, int line_in, const char *funcname_in, int level, QString msg) {
spdlog::default_logger_raw()->log(spdlog::source_loc{filename_in, line_in, funcname_in},
(spdlog::level::level_enum)level, msg.toStdString());
});
QLibrary lib;
QDirIterator it(QCoreApplication::applicationDirPath(), QStringList() << "*.so", QDir::Files,
QDirIterator it(QCoreApplication::applicationDirPath(), QStringList() << "*.so" << "*.dll", QDir::Files,
QDirIterator::Subdirectories);
while (it.hasNext())
{
+7 -1
View File
@@ -2,11 +2,17 @@
#include <QRadioButton>
#include <QVBoxLayout>
#ifdef INTERNAL
#define EXPORT Q_DECL_EXPORT
#else
#define EXPORT Q_DECL_IMPORT
#endif
/**
* @brief Class representing a better radiobutton group
*
*/
class Better_Radiobutton : public QWidget
class EXPORT Better_Radiobutton : public QWidget
{
Q_OBJECT
public:
+7 -1
View File
@@ -2,6 +2,12 @@
#include "hex_spinbox.hpp"
#include <QWidget>
#ifdef INTERNAL
#define EXPORT Q_DECL_EXPORT
#else
#define EXPORT Q_DECL_IMPORT
#endif
namespace Ui
{
class Can_Transceive;
@@ -11,7 +17,7 @@ class Can_Transceive;
* @brief Class representing a CAN transceive UI component
*
*/
class Can_Transceive : public QWidget
class EXPORT Can_Transceive : public QWidget
{
Q_OBJECT
+7 -1
View File
@@ -3,13 +3,19 @@
#include <QRegularExpressionValidator>
#include <QSpinBox>
#ifdef INTERNAL
#define EXPORT Q_DECL_EXPORT
#else
#define EXPORT Q_DECL_IMPORT
#endif
/**
* @brief Class representing a hexadecimal spin box
* @note Since QSpinBox uses int as the storage type, the effective editing range
* is +/- 0x7FFF FFFF, so it can't handle a full unsigned int.
* QDoubleSpinBox would be a more suitable base class if a wider range is needed.
*/
class HexSpinBox : public QSpinBox
class EXPORT HexSpinBox : public QSpinBox
{
Q_OBJECT
+7 -1
View File
@@ -1,11 +1,17 @@
#pragma once
#include "QPushButton"
#ifdef INTERNAL
#define EXPORT Q_DECL_EXPORT
#else
#define EXPORT Q_DECL_IMPORT
#endif
/**
* @brief Class representing an LED widget
*
*/
class Led : public QPushButton
class EXPORT Led : public QPushButton
{
Q_OBJECT
public:
+7 -1
View File
@@ -4,11 +4,17 @@
#include <qwt_plot_curve.h>
#include <qwt_text.h>
#ifdef INTERNAL
#define EXPORT Q_DECL_EXPORT
#else
#define EXPORT Q_DECL_IMPORT
#endif
/**
* @brief Class wrapping a QwtPlot for plotting data
*
*/
class Plot_wrapper : public QwtPlot
class EXPORT Plot_wrapper : public QwtPlot
{
Q_OBJECT
public:
+7 -1
View File
@@ -3,6 +3,12 @@
#include <QWidget>
#include <nlohmann/json.hpp>
#ifdef INTERNAL
#define EXPORT Q_DECL_EXPORT
#else
#define EXPORT Q_DECL_IMPORT
#endif
Q_FORWARD_DECLARE_OBJC_CLASS(Web_socket_wrapper);
Q_FORWARD_DECLARE_OBJC_CLASS(QTimer);
Q_FORWARD_DECLARE_OBJC_CLASS(QLabel);
@@ -28,7 +34,7 @@ using json = nlohmann::json;
/**
* @brief Base class for client UIs
*/
class UI_base : public QMainWindow
class EXPORT UI_base : public QMainWindow
{
Q_OBJECT
public:
+12 -4
View File
@@ -1,9 +1,16 @@
#include "web_socket_wrapper.hpp"
#include "spdlog/spdlog.h"
#include <QTimer>
#include <QtWebSockets/QWebSocket>
#include <magic_enum/magic_enum.hpp>
#define LOG_SRC_LOC(level, msg) emit log_signal(__FILE__, __LINE__, __FUNCTION__, (int)level, msg)
#define LOG_TRACE(msg) LOG_SRC_LOC(Log_level_enum::trace, msg)
#define LOG_DEBUG(msg) LOG_SRC_LOC(Log_level_enum::debug, msg)
#define LOG_INFO(msg) LOG_SRC_LOC(Log_level_enum::info, msg)
#define LOG_WARN(msg) LOG_SRC_LOC(Log_level_enum::warn, msg)
#define LOG_ERROR(msg) LOG_SRC_LOC(Log_level_enum::err, msg)
#define LOG_CRITICAL(msg) LOG_SRC_LOC(Log_level_enum::critical, msg)
Web_socket_wrapper::Web_socket_wrapper(const QUrl &url, QObject *parent)
: QObject(parent), m_web_socket(new QWebSocket("", QWebSocketProtocol::VersionLatest, this)),
m_ping_timer(new QTimer(this)), m_pong_timer(new QTimer(this))
@@ -11,8 +18,9 @@ Web_socket_wrapper::Web_socket_wrapper(const QUrl &url, QObject *parent)
connect(m_web_socket, &QWebSocket::connected, this, &Web_socket_wrapper::m_on_connected);
connect(m_web_socket, &QWebSocket::disconnected, this, &Web_socket_wrapper::on_closed);
connect(m_web_socket, &QWebSocket::pong, this, &Web_socket_wrapper::m_on_pong);
connect(m_web_socket, &QWebSocket::errorOccurred, this,
[=](QAbstractSocket::SocketError error) { SPDLOG_ERROR(magic_enum::enum_name(error)); });
connect(m_web_socket, &QWebSocket::errorOccurred, this, [this](QAbstractSocket::SocketError error) {
LOG_ERROR(QString::fromStdString(std::string(magic_enum::enum_name(error))));
});
connect(m_ping_timer, &QTimer::timeout, this, [=, this] {
m_web_socket->ping();
m_pong_timer->start(1000);
@@ -200,7 +208,7 @@ void Web_socket_wrapper::m_on_pong(quint64 elapsedTime)
void Web_socket_wrapper::m_on_pong_timeout()
{
SPDLOG_CRITICAL("Pong timeout");
LOG_CRITICAL("Pong timeout");
m_web_socket->close();
emit on_closed();
}
+23 -2
View File
@@ -1,6 +1,13 @@
#pragma once
#include <QObject>
#include <nlohmann/json.hpp>
#ifdef INTERNAL
#define EXPORT Q_DECL_EXPORT
#else
#define EXPORT Q_DECL_IMPORT
#endif
Q_FORWARD_DECLARE_OBJC_CLASS(QWebSocket);
Q_FORWARD_DECLARE_OBJC_CLASS(QTimer);
using json = nlohmann::json;
@@ -9,7 +16,7 @@ using json = nlohmann::json;
* @brief Class wrapping a WebSocket connection
*
*/
class Web_socket_wrapper : public QObject
class EXPORT Web_socket_wrapper : public QObject
{
Q_OBJECT
public:
@@ -27,6 +34,18 @@ class Web_socket_wrapper : public QObject
begin = 0
};
enum class Log_level_enum : int
{
trace,
debug,
info,
warn,
err,
critical,
off,
n_levels
};
/**
* @brief Enumeration of events
*
@@ -121,7 +140,7 @@ class Web_socket_wrapper : public QObject
*/
void inhibit_events(bool inhibit);
Q_SIGNALS:
signals:
/**
* @brief Signal emitted when the WebSocket is connected
*
@@ -145,6 +164,8 @@ class Web_socket_wrapper : public QObject
*/
void on_event_cb(json &data);
void log_signal(const char *filename_in, int line_in, const char *funcname_in, int level, QString msg);
private Q_SLOTS:
/**
* @brief Internal slot for handling WebSocket connection established