Files
CuboBmsTool/qml/MainWindow.qml
2023-03-26 23:45:49 +03:00

608 lines
20 KiB
QML

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import Controls 1.0 as Controls
import Screens 1.0 as Screens
import Cubo 1.0
import Utils 1.0
ApplicationWindow {
id: window
title: qsTr("Cubo Verde BMS")
width: 1366
height: 768
visible: true
RowLayout {
anchors.fill: parent
spacing: 0
Rectangle {
id: pane
color: Palette.alternativeBackgroundColor
implicitWidth: 300
property bool minimized: false
ColumnLayout {
anchors.fill: parent
spacing: 0
Item {
Layout.preferredHeight: 40
}
Image {
source: "qrc:/Icons/cubo-logo.svg"
sourceSize.width: pane.minimized ? 70 : 115
sourceSize.height: pane.minimized ? 70 : 115
Layout.alignment: Qt.AlignCenter
}
Item {
Layout.preferredHeight: pane.minimized ? 85 : 40
}
Controls.MenuItemDelegate {
text: qsTr("Hide menu")
font.weight: Font.Normal
icon.source: "qrc:/Icons/hide-menu.svg"
minimized: pane.minimized
mirroredIcon: pane.minimized
onClicked: if (pane.implicitWidth === 300) {
animation.from = 300
animation.to = 100
animation.running = true
pane.minimized = true
} else {
animation.from = 100
animation.to = 300
animation.running = true
pane.minimized = false
}
Layout.fillWidth: true
}
Item {
Layout.preferredHeight: 40
}
ListView {
id: menuView
clip: true
boundsBehavior: Flickable.StopAtBounds
property var menuModel: [
{"text": qsTr("AKB monitor"), "icon": "qrc:/Icons/akb-monitor.svg"},
{"text": qsTr("Cell monitor"), "icon": "qrc:/Icons/cell-monitor.svg"},
{"text": qsTr("Temperature monitor"), "icon": "qrc:/Icons/temperature.svg"},
{"text": qsTr("Configuration"), "icon": "qrc:/Icons/bms-configuration.svg"},
{"text": qsTr("Visualization"), "icon": "qrc:/Icons/visualization.svg"},
{"text": qsTr("History"), "icon": "qrc:/Icons/history.svg"},
{"text": qsTr("BMS service"), "icon": "qrc:/Icons/bms-service.svg"}
]
model: menuModel.length
delegate: Controls.MenuItemDelegate {
width: ListView.view.width
text: menuView.menuModel[modelData].text
icon.source: menuView.menuModel[modelData].icon
icon.color: "white"
highlighted: ListView.isCurrentItem
minimized: pane.minimized
onClicked: menuView.currentIndex = index
}
Layout.fillHeight: true
Layout.fillWidth: true
}
Controls.MenuItemDelegate {
text: qsTr("Connection")
icon.source: "qrc:/Icons/connection.svg"
icon.color: "#FFFFFF"
minimized: pane.minimized
onClicked: connectionDialog.open()
Layout.fillWidth: true
}
Item {
Layout.preferredHeight: 40
}
}
PropertyAnimation {
id: animation
target: pane
property: "implicitWidth"
duration: 200
easing.type: Easing.InQuad
}
Layout.preferredWidth: implicitWidth
Layout.fillHeight: true
}
ColumnLayout {
spacing: 0
RowLayout {
id: topBar
Label {
text: stack.itemAt(stack.currentIndex).title
font.pixelSize: 38
font.weight: Font.Bold
color: Palette.textColor
}
Item {
Layout.fillWidth: true
}
RowLayout {
spacing: 20
ColumnLayout {
spacing: 5
RowLayout {
spacing: 7
Controls.ContentLabel {
id: connectionStatusLabel
text: qsTr("Disconnected")
Layout.alignment: Qt.AlignRight
}
Controls.AvailabilityIndicator {
id: connectionStatusIndicator
enabled: false
neutral: false
Layout.alignment: Qt.AlignCenter
}
Controls.ContentLabel {
id: firmwareLabel
text: "-"
Layout.alignment: Qt.AlignRight
}
Layout.alignment: Qt.AlignRight
}
RowLayout {
spacing: 5
Controls.ContentLabel {
text: qsTr("Serial number") + ":"
Layout.alignment: Qt.AlignRight
}
Controls.SubtitleLabel {
id: serialLabel
text: "-"
Layout.alignment: Qt.AlignRight
}
Layout.alignment: Qt.AlignRight
}
Layout.topMargin: 15
Layout.bottomMargin: 15
Layout.fillHeight: true
}
Controls.LineSeparator {
horizontal: false
Layout.fillHeight: true
Layout.topMargin: 15
Layout.bottomMargin: 15
}
Item {
RowLayout {
id: languagesLayout
anchors.fill: parent
spacing: 10
Controls.ContentLabel {
text: Translator.currentLanguageName
}
Image {
source: Translator.currentLanguageIcon
sourceSize.width: 30
sourceSize.height: 26
}
}
MouseArea {
anchors.fill: parent
onClicked: languagesPopup.open()
}
Popup {
id: languagesPopup
width: 90
contentHeight: languagesList.contentHeight
padding: 1
x: -(width - languagesLayout.width) / 2
y: languagesLayout.height + 2
background: Rectangle {
color: Palette.backgroundColor
radius: 6
border.width: 1
border.color: Palette.borderColor
}
contentItem: ListView {
id: languagesList
model: [Translator.Russian, Translator.English, Translator.Italian]
width: languagesPopup.width
height: 120
clip: true
spacing: 0
delegate: Rectangle {
width: ListView.view.width
height: 40
color: Palette.backgroundColor
RowLayout {
anchors.fill: parent
spacing: 10
Controls.ContentLabel {
text: Translator.languageName(modelData)
Layout.fillWidth: true
Layout.leftMargin: 10
}
Image {
source: Translator.languageIcon(modelData)
sourceSize.width: 30
sourceSize.height: 26
Layout.rightMargin: 10
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: parent.color = Palette.selectedBackgroundColor
onReleased: parent.color = Palette.backgroundColor
onEntered: parent.color = Palette.hoveredBackgroundColor
onExited: parent.color = Palette.backgroundColor
onClicked: {
languagesPopup.close()
Translator.currentLanguage = modelData
}
}
}
}
}
Layout.preferredWidth: languagesLayout.implicitWidth
Layout.preferredHeight: languagesLayout.implicitHeight
}
}
Layout.leftMargin: 45
Layout.rightMargin: 45
Layout.maximumHeight: 90
}
StackLayout {
id: stack
currentIndex: menuView.currentIndex
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 45
Layout.rightMargin: 45
Layout.bottomMargin: 30
Screens.AkbMonitorScreen {
property string title: qsTr("AKB monitor")
}
Screens.CellMonitorScreen {
property string title: qsTr("Cell monitor")
}
Screens.TemperatureMonitorScreen {
property string title: qsTr("Temperature monitor")
}
Screens.BmsSettingsScreen {
property string title: qsTr("BMS settings")
onNeedWait: {
if (active) {
busyPopup.text = text
busyPopup.open()
} else {
busyPopup.close()
}
}
}
Screens.VisualizationScreen {
property string title: qsTr("Visualization")
}
Screens.DebugInformationScreen {
id: debugScreen
property string title: qsTr("Information output")
}
Screens.BmsServiceScreen {
}
}
}
}
Connections {
target: BmsInterface
onPortConnectedChanged: {
connectionStatusLabel.text = Qt.binding(function(){ return BmsInterface.isPortConnected() ? qsTr("Connected") : qsTr("Disconnected") })
connectionStatusIndicator.enabled = BmsInterface.isPortConnected()
faultStateTimer.running = BmsInterface.isPortConnected()
if (BmsInterface.isPortConnected()) {
BmsInterface.commands().getBMSconf()
BmsInterface.commands().getFaultState()
} else {
serialLabel.text = "-"
firmwareLabel.text = "-"
statusPopup.queue = []
faultStatePopup.lastState = ""
}
}
onMessageDialog: {
if (!messageDialog.visible) {
messageDialog.title = title
messageDialog.description = msg
messageDialog.good = isGood
messageDialog.open()
} else {
messageDialog.queue.push({"title": title, "description": msg, "good": isGood})
}
}
onStatusMessage: {
for (var i = 0; i < statusPopup.filteredStatuses.length; ++i) {
if (msg === statusPopup.filteredStatuses[i]) {
return
}
}
if (!statusPopup.visible) {
statusPopup.text = msg
statusPopup.good = isGood
statusPopup.open()
} else {
if (statusPopup.text !== msg) {
statusPopup.queue.push({"text": msg, "good": isGood})
}
}
}
onFwUploadStatus: {
if (isOngoing) {
if (!progressPopup.opened) {
progressPopup.open()
}
progressPopup.text = status
progressPopup.progress = progress
} else {
progressPopup.close()
BmsInterface.emitMessageDialog(qsTr("Firmware update"), status, true)
}
}
onBmsConfigurationStored: busyPopup.close()
}
Connections {
target: BmsInterface.bmsConfig()
onUpdated: {
serialLabel.text = Number(BmsInterface.bmsConfig().getParamDouble("notUsedCurrentThreshold")).toFixed()
}
}
Connections {
target: BmsInterface.commands()
onFwVersionReceived: {
firmwareLabel.text = major + "." + minor
}
onFaultStateReceived: {
if (faultStatePopup.lastState != faultString) {
faultStatePopup.close()
faultStatePopup.lastState = faultString
faultStatePopup.text = faultString
faultStatePopup.type = faultType
faultStatePopup.open()
Qt.callLater(debugScreen.printMessage, faultString, faultStatePopup.color)
}
}
}
Screens.ConnectionDialog {
id: connectionDialog
}
Screens.MessageDialog {
id: messageDialog
property var queue: []
onClosed: {
if (queue.length > 0) {
var message = queue.pop()
messageDialog.title = message.title
messageDialog.description = message.description
messageDialog.good = message.good
messageDialog.open()
}
}
}
Screens.StatusPopup {
id: statusPopup
property var filteredStatuses: []
property var queue: []
onClosed: {
if (queue.length > 0) {
var message = queue.pop()
statusPopup.text = message.text
statusPopup.good = message.good
statusPopup.open()
}
}
onOpened: {
hideStatusTimer.start()
}
Timer {
id: hideStatusTimer
interval: 3000
onTriggered: statusPopup.close()
}
}
Popup {
id: busyPopup
x: (parent.width - width) / 2
y: (parent.height - height) / 2
modal: true
closePolicy: Popup.NoAutoClose
property string text: ""
background: Rectangle {
color: "transparent"
}
ColumnLayout {
Controls.BusyIndicator {
running: true
Layout.alignment: Qt.AlignCenter
}
Controls.SubtitleLabel {
text: busyPopup.text
color: Palette.alternativeTextColor
maximumLineCount: 3
wrapMode: Text.Wrap
font.pixelSize: 20
Layout.alignment: Qt.AlignCenter
horizontalAlignment: Text.AlignHCenter
leftPadding: 10
rightPadding: 10
background: Rectangle {
color: Palette.textColor
opacity: 0.3
radius: 6
}
}
}
onOpened: hideBusyTimer.start()
onClosed: hideBusyTimer.stop()
Timer {
id: hideBusyTimer
interval: 30000
onTriggered: busyPopup.close()
}
}
Popup {
id: progressPopup
x: (parent.width - width) / 2
y: (parent.height - height) / 2
modal: true
closePolicy: Popup.NoAutoClose
property alias text: progressText.text
property alias progress: progressBar.value
background: Rectangle {
color: "transparent"
}
ColumnLayout {
Controls.ProgressBar {
id: progressBar
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: 500
}
Controls.SubtitleLabel {
text: "asdfzasdf"
id: progressText
color: Palette.alternativeTextColor
maximumLineCount: 3
wrapMode: Text.Wrap
font.pixelSize: 20
Layout.alignment: Qt.AlignCenter
horizontalAlignment: Text.AlignHCenter
leftPadding: 10
rightPadding: 10
background: Rectangle {
color: Palette.textColor
opacity: 0.3
radius: 6
}
}
}
}
Screens.StatePopup {
id: faultStatePopup
x: parent.width - width - 45
y: 18
property var lastState: ""
onOpened: {
hideStateTimer.start()
}
Timer {
id: hideStateTimer
interval: 3000
onTriggered: faultStatePopup.close()
}
Timer {
id: faultStateTimer
interval: 50000
repeat: true
onTriggered: BmsInterface.commands().getFaultState()
}
}
background: Rectangle {
color: Palette.screenBackgroundColor
}
Component.onCompleted: {
connectionDialog.open()
Qt.callLater(debugScreen.printMessage, qsTr("Tool started"))
}
}