diff options
Diffstat (limited to 'demo')
| -rw-r--r-- | demo/CMakeLists.txt | 30 | ||||
| -rw-r--r-- | demo/Main.qml | 243 |
2 files changed, 173 insertions, 100 deletions
diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index a12e090..9fb3093 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -1,18 +1,20 @@ -qt_add_executable(bobink-demo main.cpp) +qt_add_executable(BobinkDemo main.cpp) -qt_add_qml_module(bobink-demo - URI BobinkDemo - VERSION 1.0 - QML_FILES - Main.qml - # LoginPage.qml - # NodePage.qml - NO_RESOURCE_TARGET_PATH -) +qt_add_qml_module( + BobinkDemo + URI + BobinkDemo + VERSION + 1.0 + QML_FILES + Main.qml) -target_link_libraries(bobink-demo PRIVATE Qt6::Quick bobink) +# Executable goes to bin/ to avoid clashing with the QML module directory +set_target_properties(BobinkDemo PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/bin") + +target_link_libraries(BobinkDemo PRIVATE Qt6::Quick BobinkQtOpcUa) # Tell the demo where to find the locally-built OpcUa plugin at runtime -target_compile_definitions(bobink-demo PRIVATE - QTOPCUA_PLUGIN_PATH="${QTOPCUA_BUILD_DIR}/plugins" -) +target_compile_definitions( + BobinkDemo PRIVATE QTOPCUA_PLUGIN_PATH="${QTOPCUA_BUILD_DIR}/plugins") diff --git a/demo/Main.qml b/demo/Main.qml index fe4f369..5bdf369 100644 --- a/demo/Main.qml +++ b/demo/Main.qml @@ -7,8 +7,9 @@ import QtQuick.Dialogs import Bobink ApplicationWindow { - width: 600 - height: 800 + id: root + width: 800 + height: 900 visible: true title: "Bobink Demo" @@ -16,30 +17,33 @@ ApplicationWindow { property bool showPkiSettings: false Component.onCompleted: { - BobinkClient.discoveryUrl = discoveryUrlField.text - BobinkClient.startDiscovery() + BobinkClient.discoveryUrl = discoveryUrlField.text; + BobinkClient.startDiscovery(); } Connections { target: BobinkClient function onServersChanged() { - console.log("Discovered server list updated") + debugConsole.appendLog("Discovered server list updated"); } function onConnectedChanged() { - console.log("Connected:", BobinkClient.connected) + debugConsole.appendLog("Connected: " + BobinkClient.connected); if (BobinkClient.connected) - autoConnectFailed = false + root.autoConnectFailed = false; } function onConnectionError(message) { - console.log("Connection error:", message) - autoConnectFailed = true + debugConsole.appendLog("ERROR: " + message); + root.autoConnectFailed = true; + } + function onStatusMessage(message) { + debugConsole.appendLog(message); } function onDiscoveringChanged() { - console.log("Discovering:", BobinkClient.discovering) + debugConsole.appendLog("Discovering: " + BobinkClient.discovering); } function onCertificateTrustRequested(certInfo) { - certTrustDialog.certInfo = certInfo - certTrustDialog.open() + certTrustDialog.certInfo = certInfo; + certTrustDialog.open(); } } @@ -50,7 +54,9 @@ ApplicationWindow { title: "Certificate Trust" modal: true standardButtons: Dialog.Yes | Dialog.No - Label { text: certTrustDialog.certInfo } + Label { + text: certTrustDialog.certInfo + } onAccepted: BobinkClient.acceptCertificate() onRejected: BobinkClient.rejectCertificate() } @@ -60,7 +66,10 @@ ApplicationWindow { anchors.margins: 20 spacing: 12 - Label { text: "Discovery URL"; font.bold: true } + Label { + text: "Discovery URL" + font.bold: true + } RowLayout { TextField { @@ -72,19 +81,17 @@ ApplicationWindow { text: BobinkClient.discovering ? "Stop" : "Discover" onClicked: { if (BobinkClient.discovering) { - BobinkClient.stopDiscovery() + BobinkClient.stopDiscovery(); } else { - BobinkClient.discoveryUrl = discoveryUrlField.text - BobinkClient.startDiscovery() + BobinkClient.discoveryUrl = discoveryUrlField.text; + BobinkClient.startDiscovery(); } } } } Label { - text: BobinkClient.discovering - ? "Discovering... (" + BobinkClient.servers.length + " found)" - : BobinkClient.servers.length + " server(s)" + text: BobinkClient.discovering ? "Discovering... (" + BobinkClient.servers.length + " found)" : BobinkClient.servers.length + " server(s)" font.italic: true } @@ -94,30 +101,34 @@ ApplicationWindow { clip: true model: BobinkClient.servers delegate: ItemDelegate { + required property var modelData width: ListView.view.width text: modelData.serverName + " — " + modelData.applicationUri onClicked: { if (modelData.discoveryUrls.length > 0) - serverUrlField.text = modelData.discoveryUrls[0] + serverUrlField.text = modelData.discoveryUrls[0]; } } ScrollBar.vertical: ScrollBar {} } RowLayout { - Label { text: "PKI"; font.bold: true } Label { - text: BobinkClient.certFile - ? " (" + BobinkClient.certFile.split("/").pop() + ")" - : " (no certificate found)" + text: "PKI" + font.bold: true + } + Label { + text: BobinkClient.certFile ? " (" + BobinkClient.certFile.split("/").pop() + ")" : " (no certificate found)" font.italic: true color: BobinkClient.certFile ? "green" : "gray" } - Item { Layout.fillWidth: true } + Item { + Layout.fillWidth: true + } Button { - text: showPkiSettings ? "Hide" : "Configure..." + text: root.showPkiSettings ? "Hide" : "Configure..." flat: true - onClicked: showPkiSettings = !showPkiSettings + onClicked: root.showPkiSettings = !root.showPkiSettings } } @@ -147,9 +158,11 @@ ApplicationWindow { GridLayout { columns: 3 Layout.fillWidth: true - visible: showPkiSettings + visible: root.showPkiSettings - Label { text: "Certificate:" } + Label { + text: "Certificate:" + } TextField { id: certFileField Layout.fillWidth: true @@ -161,7 +174,9 @@ ApplicationWindow { onClicked: certFileDialog.open() } - Label { text: "Private key:" } + Label { + text: "Private key:" + } TextField { id: keyFileField Layout.fillWidth: true @@ -173,7 +188,9 @@ ApplicationWindow { onClicked: keyFileDialog.open() } - Label { text: "Trust folder:" } + Label { + text: "Trust folder:" + } TextField { id: trustFolderField Layout.fillWidth: true @@ -188,16 +205,19 @@ ApplicationWindow { Button { text: "Apply PKI" Layout.fillWidth: true - visible: showPkiSettings + visible: root.showPkiSettings onClicked: { - BobinkClient.pkiDir = trustFolderField.text - BobinkClient.certFile = certFileField.text - BobinkClient.keyFile = keyFileField.text - BobinkClient.applyPki() + BobinkClient.pkiDir = trustFolderField.text; + BobinkClient.certFile = certFileField.text; + BobinkClient.keyFile = keyFileField.text; + BobinkClient.applyPki(); } } - Label { text: "Server URL"; font.bold: true } + Label { + text: "Server URL" + font.bold: true + } TextField { id: serverUrlField @@ -205,15 +225,18 @@ ApplicationWindow { placeholderText: "opc.tcp://..." } - Label { text: "Authentication"; font.bold: true } + Label { + text: "Authentication" + font.bold: true + } BobinkAuth { id: auth mode: authModeCombo.currentValue username: usernameField.text password: passwordField.text - certPath: certPathField.text - keyPath: keyPathField.text + certPath: BobinkClient.certFile + keyPath: BobinkClient.keyFile } ComboBox { @@ -222,9 +245,18 @@ ApplicationWindow { textRole: "text" valueRole: "mode" model: [ - { text: "Anonymous", mode: BobinkAuth.Anonymous }, - { text: "Username / Password", mode: BobinkAuth.UserPass }, - { text: "Certificate", mode: BobinkAuth.Certificate } + { + text: "Anonymous", + mode: BobinkAuth.Anonymous + }, + { + text: "Username / Password", + mode: BobinkAuth.UserPass + }, + { + text: "Certificate", + mode: BobinkAuth.Certificate + } ] } @@ -233,12 +265,16 @@ ApplicationWindow { visible: authModeCombo.currentValue === BobinkAuth.UserPass Layout.fillWidth: true - Label { text: "Username:" } + Label { + text: "Username:" + } TextField { id: usernameField Layout.fillWidth: true } - Label { text: "Password:" } + Label { + text: "Password:" + } TextField { id: passwordField Layout.fillWidth: true @@ -246,36 +282,17 @@ ApplicationWindow { } } - GridLayout { - columns: 2 - visible: authModeCombo.currentValue === BobinkAuth.Certificate - Layout.fillWidth: true - - Label { text: "Certificate:" } - TextField { - id: certPathField - Layout.fillWidth: true - placeholderText: "/path/to/cert.pem" - } - Label { text: "Private key:" } - TextField { - id: keyPathField - Layout.fillWidth: true - placeholderText: "/path/to/key.pem" - } - } - Button { text: BobinkClient.connected ? "Disconnect" : "Connect" Layout.fillWidth: true onClicked: { if (BobinkClient.connected) { - BobinkClient.disconnectFromServer() + BobinkClient.disconnectFromServer(); } else { - autoConnectFailed = false - BobinkClient.auth = auth - BobinkClient.serverUrl = serverUrlField.text - BobinkClient.connectToServer() + root.autoConnectFailed = false; + BobinkClient.auth = auth; + BobinkClient.serverUrl = serverUrlField.text; + BobinkClient.connectToServer(); } } } @@ -283,37 +300,59 @@ ApplicationWindow { Label { text: "Direct Connect" font.bold: true - visible: autoConnectFailed && !BobinkClient.connected + visible: root.autoConnectFailed && !BobinkClient.connected } GridLayout { columns: 2 Layout.fillWidth: true - visible: autoConnectFailed && !BobinkClient.connected + visible: root.autoConnectFailed && !BobinkClient.connected - Label { text: "Security policy:" } + Label { + text: "Security policy:" + } ComboBox { id: securityPolicyCombo Layout.fillWidth: true textRole: "text" valueRole: "policy" model: [ - { text: "Basic256Sha256", policy: BobinkClient.Basic256Sha256 }, - { text: "Aes128-Sha256-RsaOaep", policy: BobinkClient.Aes128_Sha256_RsaOaep }, - { text: "Aes256-Sha256-RsaPss", policy: BobinkClient.Aes256_Sha256_RsaPss } + { + text: "Basic256Sha256", + policy: BobinkClient.Basic256Sha256 + }, + { + text: "Aes128-Sha256-RsaOaep", + policy: BobinkClient.Aes128_Sha256_RsaOaep + }, + { + text: "Aes256-Sha256-RsaPss", + policy: BobinkClient.Aes256_Sha256_RsaPss + } ] } - Label { text: "Security mode:" } + Label { + text: "Security mode:" + } ComboBox { id: securityModeCombo Layout.fillWidth: true textRole: "text" valueRole: "mode" model: [ - { text: "Sign & Encrypt", mode: BobinkClient.SignAndEncrypt }, - { text: "Sign", mode: BobinkClient.Sign }, - { text: "None", mode: BobinkClient.None } + { + text: "Sign & Encrypt", + mode: BobinkClient.SignAndEncrypt + }, + { + text: "Sign", + mode: BobinkClient.Sign + }, + { + text: "None", + mode: BobinkClient.None + } ] } } @@ -321,12 +360,11 @@ ApplicationWindow { Button { text: "Direct Connect" Layout.fillWidth: true - visible: autoConnectFailed && !BobinkClient.connected + visible: root.autoConnectFailed && !BobinkClient.connected onClicked: { - BobinkClient.auth = auth - BobinkClient.serverUrl = serverUrlField.text - BobinkClient.connectDirect(securityPolicyCombo.currentValue, - securityModeCombo.currentValue) + BobinkClient.auth = auth; + BobinkClient.serverUrl = serverUrlField.text; + BobinkClient.connectDirect(securityPolicyCombo.currentValue, securityModeCombo.currentValue); } } @@ -335,6 +373,39 @@ ApplicationWindow { color: BobinkClient.connected ? "green" : "red" } - Item { Layout.fillHeight: true } + Item { + Layout.fillHeight: true + } + + Rectangle { + id: debugConsole + Layout.fillWidth: true + Layout.preferredHeight: 100 + color: "#1e1e1e" + border.color: "#444" + radius: 4 + + function appendLog(msg) { + let ts = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss"); + statusLog.text += "[" + ts + "] " + msg + "\n"; + statusLog.cursorPosition = statusLog.text.length; + } + + ScrollView { + anchors.fill: parent + anchors.margins: 4 + + TextArea { + id: statusLog + readOnly: true + color: "#cccccc" + font.family: "monospace" + font.pointSize: 9 + wrapMode: TextEdit.Wrap + background: null + } + } + } } + } |
