add qml demo app

This commit is contained in:
2026-07-25 16:58:01 -05:00
parent d6792bf0e0
commit 815c77decb
6 changed files with 148 additions and 6 deletions

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,33 @@
#pragma once
#include <QObject>
#include <QTimer>
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_;
};

View File

@@ -1,13 +1,23 @@
#include <iostream>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#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<TimerComponent>("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();
}

34
client/ui/Main.qml Normal file
View File

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