Files
CuboBmsTool/qml/MainWindow.qml

499 lines
16 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 tool")
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
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: 70
}
ListView {
id: menuView
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("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
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
property var labels: [
qsTr("AKB monitor"),
qsTr("Cell monitor"),
qsTr("BMS settings"),
qsTr("Visualization"),
qsTr("Information output"),
qsTr("Terminal"),
]
Label {
text: topBar.labels[stack.currentIndex]
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
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.fillHeight: true
}
}
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 {
}
Screens.CellMonitorScreen {
}
Screens.BmsSettingsScreen {
onNeedWait: {
if (active) {
busyPopup.text = text
busyPopup.open()
} else {
busyPopup.close()
}
}
}
Screens.VisualizationScreen {
}
Screens.DebugInformationScreen {
}
Screens.BmsServiceScreen {
}
}
}
}
Connections {
target: BmsInterface
onPortConnectedChanged: {
connectionStatusLabel.text = Qt.binding(function(){ return BmsInterface.isPortConnected() ? qsTr("Connected") : qsTr("Disconnected") })
connectionStatusIndicator.enabled = BmsInterface.isPortConnected()
if (BmsInterface.isPortConnected()) {
BmsInterface.commands().getBMSconf()
} else {
serialLabel.text = "-"
firmwareLabel.text = "-"
}
}
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})
}
}
}
}
Connections {
target: BmsInterface.bmsConfig()
onUpdated: {
serialLabel.text = Number(BmsInterface.bmsConfig().getParamDouble("notUsedCurrentThreshold")).toFixed()
}
}
Connections {
target: BmsInterface.commands()
onFwVersionReceived: {
firmwareLabel.text = major + "." + minor
}
}
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()
busyPopup.close()
}
}
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
background: Rectangle {
color: Palette.textColor
opacity: 0.3
radius: 6
}
}
}
onOpened: hideBusyTimer.start()
onClosed: hideBusyTimer.stop()
}
Timer {
id: hideBusyTimer
interval: 30000
onTriggered: busyPopup.close()
}
background: Rectangle {
color: Palette.screenBackgroundColor
}
Component.onCompleted: {
connectionDialog.open()
}
}