diff --git a/CMakeLists.txt b/CMakeLists.txt index 82b0ca4..defda8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,15 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(libconfig) +# qt setup +find_package(Qt6 REQUIRED COMPONENTS + Core + Gui + Qml + Quick + QuickControls2 +) + set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(common) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index f4e1ef0..396da3a 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,10 +1,15 @@ -add_executable(accordion-client +qt_standard_project_setup() + +qt_add_executable(accordion-client src/main.cpp # other client source files go here src/TcpClient.cpp + src/TimerComponent.cpp ) +set_target_properties(accordion-client PROPERTIES OUTPUT_NAME "accordion.out") + message(STATUS ${ROOT_DIR}) target_include_directories(accordion-client PRIVATE @@ -12,5 +17,20 @@ target_include_directories(accordion-client PRIVATE ) target_link_libraries(accordion-client PRIVATE + Qt6::Core + Qt6::Qml + Qt6::Gui + Qt6::Quick + Qt6::QuickControls2 accordion-common ) + +qt_add_qml_module(accordion-client + URI accordion + VERSION 1.0 + QML_FILES ui/Main.qml +) + +install(TARGETS accordion-client) + +# if you get lots of wsl warnings use QT_QUICK_BACKEND=software in your execution environment diff --git a/client/src/TimerComponent.cpp b/client/src/TimerComponent.cpp new file mode 100644 index 0000000..c1aa3db --- /dev/null +++ b/client/src/TimerComponent.cpp @@ -0,0 +1,24 @@ + +#include "TimerComponent.hpp" + +TimerComponent::TimerComponent(QObject* parent) : QObject(parent) { + + // QTimer attach callback + connect(&timer_, &QTimer::timeout, this, &TimerComponent::increment); + timer_.start(1000); + +} + +void TimerComponent::reset() { + + seconds_ = 0; + emit secondsChanged(); + +} + +void TimerComponent::increment() { + + seconds_++; + emit secondsChanged(); + +} diff --git a/client/src/TimerComponent.hpp b/client/src/TimerComponent.hpp new file mode 100644 index 0000000..6ab906e --- /dev/null +++ b/client/src/TimerComponent.hpp @@ -0,0 +1,33 @@ + +#pragma once + +#include +#include + +class TimerComponent : public QObject { + + Q_OBJECT + Q_PROPERTY(int seconds READ seconds NOTIFY secondsChanged) + + public: + + explicit TimerComponent(QObject* parent = nullptr); + + int seconds() const { return seconds_; } + + public slots: + + void reset(); + + signals: + + void secondsChanged(); + + private: + + void increment(); + + int seconds_ = 0; + QTimer timer_; + +}; diff --git a/client/src/main.cpp b/client/src/main.cpp index ffddb53..7ee24b7 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -1,13 +1,23 @@ #include +#include +#include +#include + +#include "TimerComponent.hpp" +#include "TcpClient.hpp" #include "common/config/ConfigService.hpp" #include "common/LoggerService.hpp" -#include "TcpClient.hpp" - int main(int argc, char* argv[]) { + // create application + QGuiApplication app(argc, argv); + QQmlApplicationEngine engine; + + + // instantiate app services std::string centralConfigPath = "client/config/main.cfg"; // default path if(argc > 1) { centralConfigPath = std::string(argv[1]); @@ -16,10 +26,22 @@ int main(int argc, char* argv[]) { ConfigService config { centralConfigPath }; LoggerService logger {&config, "main"}; - logger.log("main", LogFlag::Debug, "hello world from the client!"); + // attach backend gui components + qmlRegisterType("accordion", 1, 0, "TimerComponent"); + // alternative is engine.rootContext()->setContextProperty("timerComponent", &timerComponent); + // which basically gives qml access to a singleton reference (qmlRegisterSingletonType is preferred) - TcpClient client {&config, &logger}; + //TcpClient client {&config, &logger}; - return 0; + // load qml + engine.load(QUrl::fromLocalFile("client/ui/Main.qml")); // ugh + + if(engine.rootObjects().isEmpty()) { + logger.log("Main", LogFlag::Error, "GuiEngine is empty."); + return -1; + } + + // execute app + return app.exec(); } diff --git a/client/ui/Main.qml b/client/ui/Main.qml new file mode 100644 index 0000000..79d6698 --- /dev/null +++ b/client/ui/Main.qml @@ -0,0 +1,34 @@ + +import QtQuick +import QtQuick.Controls + +import accordion + +ApplicationWindow { + + visible: true + width: 1200 + height: 800 + title: "accordion" + + TimerComponent { + id: timerComponent + } + + Column { + anchors.centerIn: parent + spacing: 20 + + Label { + text: timerComponent.seconds + " s" + font.pixelSize: 32 + horizontalAlignment: Text.AlignHCenter + } + + Button { + text: "Reset" + onClicked: timerComponent.reset() + } + } + +} \ No newline at end of file