From 5ff9705937ffc1647587e1b228effd30c8a0e309 Mon Sep 17 00:00:00 2001 From: Thomas Vanbesien Date: Mon, 23 Mar 2026 14:55:32 +0100 Subject: Refactor Main.qml into separate components and add comments Extract ConnectionPage, CertTrustDialog, and DebugConsole from Main.qml into their own QML files. Add inline comments to OpcUaMonitoredNode::handleValueUpdated explaining the range write guard, value store, and timestamp update. --- demo/Main.qml | 446 +--------------------------------------------------------- 1 file changed, 5 insertions(+), 441 deletions(-) (limited to 'demo/Main.qml') diff --git a/demo/Main.qml b/demo/Main.qml index 28d59bc..908dcbd 100644 --- a/demo/Main.qml +++ b/demo/Main.qml @@ -5,15 +5,11 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls import QtQuick.Layouts -import QtQuick.Dialogs import Bobink ApplicationWindow { id: root - property bool autoConnectFailed: false - property bool showPkiSettings: false - height: 900 title: "Bobink Demo" visible: true @@ -28,7 +24,7 @@ ApplicationWindow { function onConnectedChanged() { debugConsole.appendLog("Connected: " + Bobink.connected); if (Bobink.connected) { - root.autoConnectFailed = false; + connectionPage.autoConnectFailed = false; Bobink.stopDiscovery(); stack.push("NodePage.qml", { stackRef: stack, @@ -41,7 +37,7 @@ ApplicationWindow { function onConnectionError(message) { debugConsole.appendLog("Connection error: " + message); - root.autoConnectFailed = true; + connectionPage.autoConnectFailed = true; } function onDiscoveringChanged() { @@ -59,24 +55,9 @@ ApplicationWindow { target: Bobink } - Dialog { + CertTrustDialog { id: certTrustDialog - property string certInfo - - anchors.centerIn: parent - implicitWidth: 400 - modal: true - standardButtons: Dialog.Yes | Dialog.No - title: "Certificate Trust" - - onAccepted: Bobink.acceptCertificate() - onRejected: Bobink.rejectCertificate() - - Label { - text: certTrustDialog.certInfo - wrapMode: Text.Wrap - } } ColumnLayout { @@ -89,401 +70,9 @@ ApplicationWindow { Layout.fillHeight: true Layout.fillWidth: true - initialItem: Page { + initialItem: ConnectionPage { id: connectionPage - Component.onCompleted: { - Bobink.discoveryUrl = discoveryUrlField.text; - Bobink.startDiscovery(); - } - - OpcUaAuth { - id: auth - - certPath: Bobink.certFile - keyPath: Bobink.keyFile - mode: authModeCombo.currentValue - password: passwordField.text - username: usernameField.text - } - - FileDialog { - id: certFileDialog - - currentFolder: "file://" + trustFolderField.text - nameFilters: ["DER certificates (*.der)", "All files (*)"] - title: "Select Certificate" - - onAccepted: certFileField.text = selectedFile.toString( - ).replace("file://", "") - } - - FileDialog { - id: keyFileDialog - - currentFolder: "file://" + trustFolderField.text - nameFilters: ["Key files (*.pem *.crt)", "All files (*)"] - title: "Select Private Key" - - onAccepted: keyFileField.text = selectedFile.toString( - ).replace("file://", "") - } - - FolderDialog { - id: trustFolderDialog - - currentFolder: "file://" + trustFolderField.text - title: "Select Trust Folder" - - onAccepted: trustFolderField.text = selectedFolder.toString( - ).replace("file://", "") - } - - ColumnLayout { - anchors.fill: parent - anchors.margins: 20 - spacing: 12 - - Label { - font.bold: true - text: "Discovery URL" - } - - RowLayout { - TextField { - id: discoveryUrlField - - Layout.fillWidth: true - text: "opc.tcp://localhost:4840" - } - - Button { - text: Bobink.discovering ? "Stop" : "Discover" - - onClicked: { - if (Bobink.discovering) { - Bobink.stopDiscovery(); - } else { - Bobink.discoveryUrl - = discoveryUrlField.text; - Bobink.startDiscovery(); - } - } - } - } - - Label { - font.italic: true - text: Bobink.discovering ? "Discovering... (" - + Bobink.servers.length - + " found)" : - Bobink.servers.length - + " server(s)" - } - - ListView { - id: serverListView - - Layout.fillWidth: true - Layout.preferredHeight: 100 - clip: true - model: Bobink.servers - - ScrollBar.vertical: ScrollBar { - policy: ScrollBar.AsNeeded - } - delegate: ItemDelegate { - id: serverDelegate - - required property var modelData - - width: ListView.view.width - - contentItem: ColumnLayout { - spacing: 2 - - Label { - text: serverDelegate.modelData.serverName - } - - Label { - Layout.fillWidth: true - color: "gray" - elide: Text.ElideRight - font.italic: true - font.pointSize: 8 - text: serverDelegate.modelData.applicationUri - } - } - - onClicked: { - if (modelData.discoveryUrls.length > 0) - serverUrlField.text - = modelData.discoveryUrls[0]; - } - } - } - - RowLayout { - Label { - font.bold: true - text: "PKI" - } - - Label { - color: Bobink.certFile ? "green" : "gray" - font.italic: true - text: Bobink.certFile ? " (" - + Bobink.certFile.split( - "/").pop() + ")" : - " (no certificate found)" - } - - Item { - Layout.fillWidth: true - } - - Button { - text: root.showPkiSettings ? "Hide" : "Configure" - - onClicked: root.showPkiSettings = - !root.showPkiSettings - } - } - - GridLayout { - Layout.fillWidth: true - columns: 3 - visible: root.showPkiSettings - - Label { - text: "Certificate:" - } - - TextField { - id: certFileField - - Layout.fillWidth: true - placeholderText: "Client certificate (.der)" - text: Bobink.certFile - } - - Button { - text: "Browse" - - onClicked: certFileDialog.open() - } - - Label { - text: "Private key:" - } - - TextField { - id: keyFileField - - Layout.fillWidth: true - placeholderText: "Private key (.pem, .crt)" - text: Bobink.keyFile - } - - Button { - text: "Browse" - - onClicked: keyFileDialog.open() - } - - Label { - text: "Trust folder:" - } - - TextField { - id: trustFolderField - - Layout.fillWidth: true - text: Bobink.pkiDir - } - - Button { - text: "Browse" - - onClicked: trustFolderDialog.open() - } - } - - Button { - Layout.fillWidth: true - text: "Apply PKI" - visible: root.showPkiSettings - - onClicked: { - Bobink.pkiDir = trustFolderField.text; - Bobink.certFile = certFileField.text; - Bobink.keyFile = keyFileField.text; - Bobink.applyPki(); - } - } - - Label { - font.bold: true - text: "Server URL" - } - - TextField { - id: serverUrlField - - Layout.fillWidth: true - placeholderText: "opc.tcp://..." - } - - Label { - font.bold: true - text: "Authentication" - } - - ComboBox { - id: authModeCombo - - Layout.fillWidth: true - model: [ - { - text: "Anonymous", - mode: OpcUaAuth.Anonymous - }, - { - text: "Username / Password", - mode: OpcUaAuth.UserPass - }, - { - text: "Certificate", - mode: OpcUaAuth.Certificate - } - ] - textRole: "text" - valueRole: "mode" - } - - GridLayout { - Layout.fillWidth: true - columns: 2 - visible: authModeCombo.currentValue - === OpcUaAuth.UserPass - - Label { - text: "Username:" - } - - TextField { - id: usernameField - - Layout.fillWidth: true - } - - Label { - text: "Password:" - } - - TextField { - id: passwordField - - Layout.fillWidth: true - echoMode: TextInput.Password - } - } - - Button { - Layout.fillWidth: true - text: "Connect" - - onClicked: { - root.autoConnectFailed = false; - Bobink.auth = auth; - Bobink.serverUrl = serverUrlField.text; - Bobink.connectToServer(); - } - } - - Label { - font.bold: true - text: "Direct Connect" - visible: root.autoConnectFailed - } - - GridLayout { - Layout.fillWidth: true - columns: 2 - visible: root.autoConnectFailed - - Label { - text: "Security policy:" - } - - ComboBox { - id: securityPolicyCombo - - Layout.fillWidth: true - model: [ - { - text: "Basic256Sha256", - policy: Bobink.Basic256Sha256 - }, - { - text: "Aes128-Sha256-RsaOaep", - policy: Bobink.Aes128_Sha256_RsaOaep - }, - { - text: "Aes256-Sha256-RsaPss", - policy: Bobink.Aes256_Sha256_RsaPss - } - ] - textRole: "text" - valueRole: "policy" - } - - Label { - text: "Security mode:" - } - - ComboBox { - id: securityModeCombo - - Layout.fillWidth: true - model: [ - { - text: "Sign & Encrypt", - mode: Bobink.SignAndEncrypt - }, - { - text: "Sign", - mode: Bobink.Sign - }, - { - text: "None", - mode: Bobink.None - } - ] - textRole: "text" - valueRole: "mode" - } - } - - Button { - Layout.fillWidth: true - text: "Direct Connect" - visible: root.autoConnectFailed - - onClicked: { - Bobink.auth = auth; - Bobink.serverUrl = serverUrlField.text; - Bobink.connectDirect( - securityPolicyCombo.currentValue, - securityModeCombo.currentValue); - } - } - - Item { - Layout.fillHeight: true - } - } } Connections { @@ -496,36 +85,11 @@ ApplicationWindow { } } - Rectangle { + DebugConsole { 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 - } - } } } } -- cgit v1.2.3