import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Controls.Material 2.15 import QtQuick.Layouts 1.15 import AntiClipSettings 1.0 ApplicationWindow { id: window width: 1000 height: 640 visible: true title: qsTr(Qt.application.name + " " + Qt.application.version) header: ToolBar { RowLayout { anchors.fill: parent Button { Layout.leftMargin: 5 Material.background: Material.Blue text: "搜索设备" onClicked: { deviceList.currentIndex = -1 App.startSearchDevice() App.collector.stop() // 停止数据采集 App.collector.path = "" } } Label { text: `设备总数: ${deviceList.count}` } Label { Layout.alignment: Qt.AlignRight Layout.preferredWidth: 280 text: App.currentFirmware.length > 0 ? `当前设备版本号: ${App.currentFirmware}` : "" } } } ListView { id: deviceList anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left width: 420 clip: true model: App.devices Label { id: emptyHint visible: false anchors.centerIn: parent text: qsTr("未搜索到设备") } delegate: Rectangle { width: deviceList.width height: 40 color: ListView.isCurrentItem ? "#aaddff" : (index % 2 == 0 ? "#ffffff" : "#eeeeee") Row { anchors.fill: parent spacing: 10 Text { anchors.verticalCenter: parent.verticalCenter text: deviceId } Item {} Text { anchors.verticalCenter: parent.verticalCenter text: ip } Rectangle { anchors.verticalCenter: parent.verticalCenter color: onlineStatus ? "green" : "black" width: 10 height: 10 radius: 5 } } MouseArea { anchors.fill: parent onClicked: { deviceList.currentIndex = index } onDoubleClicked: { if (!softwareVersion.includes("R003")) { showMessageDialog(2, "网络设置", "当前设备不支持有线网络设置!") } else if (onlineStatus) { networkPopup.open() } else { showMessageDialog(2, "网络设置", "设备已离线!") } } } } onCurrentIndexChanged: { App.connectToDevice(deviceList.currentIndex) App.collector.stop() // 停止数据采集 App.collector.path = "" } ProgressBar { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom visible: App.devices.isSearching from: 0 to: 100 value: App.devices.searchProgress height: 25 } } DeviceView { anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: deviceList.right anchors.right: parent.right enabled: App.currentDeviceConnected && (deviceList.currentIndex >= 0) openDoorAreaWay: App.currentOpenDoorAreaWay openDoorAreaPoints: App.currentOpenDoorAreaPoints shieldedAreaEnabled: App.currentShieldedAreaEnabled shieldedAreaPoints: App.currentShieldedAreaPoints antiClipAreaEnabled: App.currentAntiClipAreaEnabled antiClipAreaPoints: App.currentAntiClipAreaPoints } NetworkSettingPopup { id: networkPopup visible: false width: 500 } OtaPopup { id: otaPopup } footer: RowLayout { width: parent.width Button { Layout.leftMargin: 5 text: App.collector.enabled ? "停止采集" : "数据采集" onClicked: { if (App.collector.enabled) { App.collector.stop() } else { if (deviceList.currentIndex < 0) { showMessageDialog(2, "数据采集", "请先选择设备") return } else if (!App.currentDeviceConnected) { showMessageDialog(2, "数据采集", "设备已离线,请重新连接设备!") return } if (App.collector.path.length <= 0) { showFolderDialog(folder => { App.collector.path = folder App.collector.start(App.devices.get(deviceList.currentIndex).ip) }) } else { App.collector.start(App.devices.get( deviceList.currentIndex).ip) } } } } Item {} Button { text: "升级" onClicked: { if (deviceList.currentIndex < 0) { showMessageDialog(2, "OTA升级", "请先选择设备!") return } else if (!App.currentDeviceConnected) { showMessageDialog(2, "OTA升级", "设备已离线,请重新连接设备!") return } otaPopup.open() } } Item {} spacing: (parent.width - (2 * 100)) / 3 } function showMessageDialog(type, title, message) { let component = Qt.createComponent("MessageDialog.qml") if (component.status === Component.Ready) { let dialog = component.createObject(window, { "type": type, "titleText": title, "text": message }) dialog.open() } } function showFileDialog(nameFilters, onSelected) { let dialog = null if (isQt5) { dialog = Qt.createQmlObject("import QtQuick.Dialogs 1.3; FileDialog {}", window, "myDynamicSnippet") } else { dialog = Qt.createQmlObject("import QtQuick.Dialogs; FileDialog {}", window, "myDynamicSnippet") } if (dialog) { dialog.nameFilters = nameFilters; dialog.visible = true dialog.accepted.connect(function () { let fileUrl = isQt5 ? dialog.fileUrl.toString() : dialog.selectedFile.toString() let localFilePath = fileUrl.startsWith("file:///") ? fileUrl.substring(8) : fileUrl onSelected(localFilePath) dialog.destroy() }) dialog.rejected.connect(function () { dialog.destroy() }) } else { console.error("Failed to create FolderDialog object") } } function showFolderDialog(onSelected) { let dialog = null if (isQt5) { dialog = Qt.createQmlObject("import QtQuick.Dialogs 1.3; FileDialog {}", window, "myDynamicSnippet") dialog.selectExisting = true dialog.selectFolder = true } else { dialog = Qt.createQmlObject("import QtQuick.Dialogs; FolderDialog {}", window, "myDynamicSnippet") } if (dialog) { dialog.visible = true dialog.accepted.connect(function () { onSelected(isQt5 ? dialog.fileUrl : dialog.selectedFolder) dialog.destroy() }) dialog.rejected.connect(function () { dialog.destroy() }) } else { console.error("Failed to create FolderDialog object") } } Connections { target: App function onNewMessage(type, title, message) { showMessageDialog(type, title, message) } } Connections { target: App.devices function onIsSearchingChanged() { if (App.devices.isSearching) { emptyHint.visible = false } else if (!App.devices.isSearching && (App.devices.rowCount() <= 0)) { emptyHint.visible = true } } } }