pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls import QtQuick.Layouts import Xpl2 ApplicationWindow { id: root height: 600 title: "XPL2 Demo" visible: true width: 800 Connections { function onConnectedChanged() { debugConsole.appendLog(Xpl2Client.connected ? "Connected" : "Disconnected"); } function onErrorOccurred(error: string) { debugConsole.appendLog("ERROR: " + error); } function onResponseReceived(response: string) { debugConsole.appendLog("Received: " + response); responseModel.append({ text: response }); } function onStatusMessage(message: string) { debugConsole.appendLog(message); } target: Xpl2Client } ColumnLayout { anchors.fill: parent spacing: 0 ColumnLayout { Layout.fillHeight: true Layout.fillWidth: true Layout.margins: 16 spacing: 12 // --- Connection --- GroupBox { Layout.fillWidth: true title: "Connection" GridLayout { anchors.fill: parent columns: 2 Label { text: "Host:" } TextField { id: hostField Layout.fillWidth: true text: Xpl2Client.host onEditingFinished: Xpl2Client.host = text } Label { text: "Command port:" } TextField { id: commandPortField Layout.fillWidth: true text: Xpl2Client.commandPort validator: IntValidator { bottom: 1 top: 65535 } onEditingFinished: Xpl2Client.commandPort = parseInt( text) } Label { text: "Imaging port:" } TextField { id: imagingPortField Layout.fillWidth: true text: Xpl2Client.imagingPort validator: IntValidator { bottom: 1 top: 65535 } onEditingFinished: Xpl2Client.imagingPort = parseInt( text) } Label { text: "Status port:" } TextField { id: statusPortField Layout.fillWidth: true text: Xpl2Client.statusPort validator: IntValidator { bottom: 1 top: 65535 } onEditingFinished: Xpl2Client.statusPort = parseInt( text) } Button { Layout.alignment: Qt.AlignRight Layout.columnSpan: 2 text: Xpl2Client.connected ? "Disconnect" : "Connect" onClicked: { if (Xpl2Client.connected) Xpl2Client.disconnectFromServer(); else Xpl2Client.connectToServer(); } } } } // --- Send Command --- GroupBox { Layout.fillWidth: true enabled: Xpl2Client.connected title: "Command" RowLayout { anchors.fill: parent TextField { id: cmdField Layout.fillWidth: true placeholderText: "Enter command…" onAccepted: sendBtn.clicked() } Button { id: sendBtn text: "Send" onClicked: { if (cmdField.text.length > 0) { Xpl2Client.sendCommand(cmdField.text); cmdField.text = ""; } } } } } // --- Responses --- GroupBox { Layout.fillHeight: true Layout.fillWidth: true title: "Responses" ListView { id: responseView anchors.fill: parent clip: true delegate: Text { id: responseDelegate required property string text font.family: "monospace" font.pixelSize: 13 text: responseDelegate.text width: responseView.width wrapMode: Text.Wrap } model: ListModel { id: responseModel } } } } // --- Debug Console --- Rectangle { id: debugConsole function appendLog(msg) { let ts = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss"); debugLog.text += "[" + ts + "] " + msg + "\n"; debugLog.cursorPosition = debugLog.text.length; } Layout.fillWidth: true Layout.preferredHeight: 120 border.color: "#444" color: "#1e1e1e" radius: 4 ScrollView { anchors.fill: parent anchors.margins: 4 TextArea { id: debugLog background: null color: "#cccccc" font.family: "monospace" font.pointSize: 9 readOnly: true wrapMode: TextEdit.Wrap } } } } }