From 35309337aacac2eac7d7215e526bddcf7647b8cf Mon Sep 17 00:00:00 2001 From: Thomas Vanbesien Date: Wed, 11 Mar 2026 11:02:24 +0100 Subject: Initial project setup: Qt 6.10.2 TCP client library for Alchemie XPL2 protocol - Static library (src/) with QML singleton Xpl2Client for TCP communication - Qt Quick demo app (demo/) with connection UI, command input, and response log --- demo/Main.qml | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 demo/Main.qml (limited to 'demo/Main.qml') diff --git a/demo/Main.qml b/demo/Main.qml new file mode 100644 index 0000000..82b2573 --- /dev/null +++ b/demo/Main.qml @@ -0,0 +1,177 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Xpl2 + +ApplicationWindow { + id: root + + width: 800 + height: 600 + visible: true + title: "XPL2 Demo" + + Connections { + target: Xpl2Client + + function onConnectedChanged() { + log(Xpl2Client.connected ? "Connected" : "Disconnected"); + } + + function onResponseReceived(response: string) { + log("← " + response); + responseModel.append({ + text: response + }); + } + + function onErrorOccurred(error: string) { + log("ERROR: " + error); + } + + function onStatusMessage(message: string) { + log(message); + } + } + + function log(msg: string) { + let ts = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss.zzz"); + logModel.append({ + text: "[" + ts + "] " + msg + }); + logView.positionViewAtEnd(); + } + + ColumnLayout { + anchors.fill: parent + anchors.margins: 16 + spacing: 12 + + // --- Connection --- + GroupBox { + title: "Connection" + Layout.fillWidth: true + + GridLayout { + columns: 4 + anchors.fill: parent + + Label { + text: "Host:" + } + TextField { + id: hostField + text: Xpl2Client.host + Layout.fillWidth: true + onEditingFinished: Xpl2Client.host = text + } + + Label { + text: "Port:" + } + TextField { + id: portField + text: Xpl2Client.port + implicitWidth: 80 + validator: IntValidator { + bottom: 1 + top: 65535 + } + onEditingFinished: Xpl2Client.port = parseInt(text) + } + + Button { + text: Xpl2Client.connected ? "Disconnect" : "Connect" + Layout.columnSpan: 4 + Layout.alignment: Qt.AlignRight + onClicked: { + if (Xpl2Client.connected) + Xpl2Client.disconnectFromServer(); + else + Xpl2Client.connectToServer(); + } + } + } + } + + // --- Send Command --- + GroupBox { + title: "Command" + Layout.fillWidth: true + enabled: Xpl2Client.connected + + RowLayout { + anchors.fill: parent + + TextField { + id: cmdField + placeholderText: "Enter command…" + Layout.fillWidth: true + onAccepted: sendBtn.clicked() + } + + Button { + id: sendBtn + text: "Send" + onClicked: { + if (cmdField.text.length > 0) { + Xpl2Client.sendCommand(cmdField.text); + cmdField.text = ""; + } + } + } + } + } + + // --- Responses --- + GroupBox { + title: "Responses" + Layout.fillWidth: true + Layout.fillHeight: true + + ListView { + id: responseView + anchors.fill: parent + clip: true + model: ListModel { + id: responseModel + } + + delegate: Text { + required property string text + width: responseView.width + wrapMode: Text.Wrap + font.family: "monospace" + font.pixelSize: 13 + text: model.text + } + } + } + + // --- Debug Log --- + GroupBox { + title: "Log" + Layout.fillWidth: true + Layout.preferredHeight: 160 + + ListView { + id: logView + anchors.fill: parent + clip: true + model: ListModel { + id: logModel + } + + delegate: Text { + required property string text + width: logView.width + wrapMode: Text.Wrap + font.family: "monospace" + font.pixelSize: 12 + color: "#555" + text: model.text + } + } + } + } +} -- cgit v1.2.3