diff --git a/qml/Controls/ComboBox.qml b/qml/Controls/ComboBox.qml
index 07cbab5..cd831f7 100644
--- a/qml/Controls/ComboBox.qml
+++ b/qml/Controls/ComboBox.qml
@@ -46,7 +46,8 @@ ComboBox {
}
onPaint: {
- context.reset();
+ var context = getContext("2d")
+ context.reset()
if (control.down) {
context.moveTo(0, height);
@@ -77,7 +78,10 @@ ComboBox {
background: Rectangle {
implicitWidth: 120
implicitHeight: 46
- color: control.down ? Palette.selectedBackgroundColor : Palette.backgroundColor
+ color: control.enabled
+ ? (control.down ? Palette.selectedBackgroundColor : Palette.backgroundColor)
+ : Palette.hoveredBackgroundColor
+
border.color: Palette.borderColor
border.width: 1
radius: 5
diff --git a/qml/Controls/DialogBackground.qml b/qml/Controls/DialogBackground.qml
new file mode 100644
index 0000000..2a0015e
--- /dev/null
+++ b/qml/Controls/DialogBackground.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.12
+
+import Utils 1.0
+
+Rectangle {
+ color: Palette.screenBackgroundColor
+ radius: 6
+}
diff --git a/qml/Controls/DialogHeader.qml b/qml/Controls/DialogHeader.qml
new file mode 100644
index 0000000..f7eddf6
--- /dev/null
+++ b/qml/Controls/DialogHeader.qml
@@ -0,0 +1,75 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Controls 1.0 as Controls
+import Utils 1.0
+
+Rectangle {
+ color: Qt.darker(Palette.hoveredBackgroundColor, 1.05)
+ height: 50
+ radius: 6
+
+ property Dialog dialog: undefined
+
+ RowLayout {
+ anchors.fill: parent
+
+ Controls.SubtitleLabel {
+ text: root.title
+ leftPadding: 20
+ topPadding: 0
+ bottomPadding: 0
+ verticalAlignment: Text.AlignVCenter
+ Layout.fillWidth: true
+ Layout.preferredHeight: parent.height
+
+ MouseArea {
+ anchors.fill: parent
+
+ property int lastX: 0
+ property int lastY: 0
+
+ onPressed: {
+ lastX = mouse.x
+ lastY = mouse.y
+ }
+
+ onPositionChanged:{
+ var deltaX = mouse.x - lastX
+ dialog.x += deltaX
+ lastX = mouse.x - deltaX
+
+ var deltaY = mouse.y - lastY
+ dialog.y += deltaY
+ lastY = mouse.y - deltaY
+ }
+ }
+ }
+
+ Image {
+ id: closeImage
+ source: "qrc:/Icons/close.svg"
+ sourceSize.width: 36
+ sourceSize.height: 36
+ Layout.rightMargin: 10
+
+ MouseArea {
+ anchors.fill: parent
+ propagateComposedEvents: true
+
+ onPressed: {
+ closeImage.sourceSize.width = 32
+ closeImage.sourceSize.height = 32
+ }
+ onReleased: {
+ closeImage.sourceSize.width = 36
+ closeImage.sourceSize.height = 36
+ }
+ onClicked: {
+ root.close()
+ }
+ }
+ }
+ }
+}
diff --git a/qml/Controls/qmldir b/qml/Controls/qmldir
index 0ebc71e..b0b9cb5 100644
--- a/qml/Controls/qmldir
+++ b/qml/Controls/qmldir
@@ -20,3 +20,5 @@ TabButton 1.0 TabButton.qml
TabBar 1.0 TabBar.qml
ChartView 1.0 ChartView.qml
TextArea 1.0 TextArea.qml
+DialogHeader 1.0 DialogHeader.qml
+DialogBackground 1.0 DialogBackground.qml
diff --git a/qml/Icons/close.svg b/qml/Icons/close.svg
new file mode 100644
index 0000000..f363dcc
--- /dev/null
+++ b/qml/Icons/close.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/qml/Icons/connection.svg b/qml/Icons/connection.svg
new file mode 100644
index 0000000..94da06a
--- /dev/null
+++ b/qml/Icons/connection.svg
@@ -0,0 +1,3 @@
+
diff --git a/qml/Icons/info.svg b/qml/Icons/info.svg
new file mode 100644
index 0000000..eebe6e9
--- /dev/null
+++ b/qml/Icons/info.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/qml/Icons/warning.svg b/qml/Icons/warning.svg
new file mode 100644
index 0000000..963664f
--- /dev/null
+++ b/qml/Icons/warning.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/qml/MainWindow.qml b/qml/MainWindow.qml
index bed6f63..2daeacb 100644
--- a/qml/MainWindow.qml
+++ b/qml/MainWindow.qml
@@ -1,6 +1,7 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
+import QtGraphicalEffects 1.0
import Controls 1.0 as Controls
import Screens 1.0 as Screens
@@ -106,7 +107,7 @@ ApplicationWindow {
{"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"},
- {"text": qsTr("Exit"), "icon": "qrc:/Icons/exit.svg"},
+// {"text": qsTr("Exit"), "icon": "qrc:/Icons/exit.svg"},
]
delegate: ItemDelegate {
@@ -151,6 +152,55 @@ ApplicationWindow {
Layout.fillHeight: true
Layout.fillWidth: true
}
+
+ ItemDelegate {
+ leftPadding: pane.minimized ? 0 : 40
+ onClicked: connectionDialog.open()
+
+ contentItem: RowLayout {
+ spacing: pane.minimized ? 0 : 25
+ height: 50
+
+ Item {
+ visible: pane.minimized
+ Layout.fillWidth: true
+ }
+
+ Image {
+ source: "qrc:/Icons/connection.svg"
+ sourceSize.width: 24
+ sourceSize.height: 24
+ Layout.alignment: Qt.AlignCenter
+
+ ColorOverlay {
+ anchors.fill: parent
+ source: parent
+ color: "#FFFFFF"
+ }
+ }
+
+ Label {
+ text: qsTr("Connection")
+ font.weight: Font.Bold
+ color: Palette.alternativeTextColor
+ visible: !pane.minimized
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+ }
+
+ background: Rectangle {
+ color: parent.down ? Palette.pressedButtonColor : Palette.buttonColor
+ }
+
+ Layout.fillWidth: true
+ }
+
+ Item {
+ Layout.preferredHeight: 40
+ }
}
PropertyAnimation {
@@ -174,7 +224,7 @@ ApplicationWindow {
qsTr("Cell monitor"),
qsTr("BMS settings"),
qsTr("Visualization"),
- qsTr("History"),
+ qsTr("Information output"),
qsTr("Terminal"),
qsTr("Exit"),
]
@@ -189,6 +239,45 @@ ApplicationWindow {
Layout.fillWidth: true
}
+ RowLayout {
+ ColumnLayout {
+ RowLayout {
+ Controls.ContentLabel {
+ id: connectionStatusLabel
+ text: qsTr("Disconnected")
+ Layout.alignment: Qt.AlignRight
+ }
+
+ Controls.AvailabilityIndicator {
+ id: connectionStatusIndicator
+ enabled: false
+ Layout.alignment: Qt.AlignCenter
+ }
+
+ Controls.ContentLabel {
+ text: qsTr("V1.3")
+ Layout.alignment: Qt.AlignRight
+ }
+
+ Layout.alignment: Qt.AlignRight
+ }
+
+ RowLayout {
+ Controls.ContentLabel {
+ text: qsTr("Serial number") + ":"
+ Layout.alignment: Qt.AlignRight
+ }
+
+ Controls.SubtitleLabel {
+ text: qsTr("9999997")
+ Layout.alignment: Qt.AlignRight
+ }
+
+ Layout.alignment: Qt.AlignRight
+ }
+ }
+ }
+
Layout.leftMargin: 45
Layout.rightMargin: 45
}
@@ -215,7 +304,7 @@ ApplicationWindow {
Screens.VisualizationScreen {
}
- Screens.BmsSettingsScreen {
+ Screens.DebugInformationScreen {
}
Screens.BmsServiceScreen {
@@ -224,8 +313,84 @@ ApplicationWindow {
}
}
- Screens.ConnectionScreen {
- id: connectionScreen
+ Connections {
+ target: BmsInterface
+
+ onPortConnectedChanged: {
+ connectionStatusLabel.text = BmsInterface.isPortConnected() ? qsTr("Connected") : qsTr("Disconnected")
+ connectionStatusIndicator.enabled = BmsInterface.isPortConnected()
+ }
+
+ 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()
+ hideStatusTimer.start()
+ } else {
+ if (statusPopup.text !== msg) {
+ statusPopup.queue.push({"text": msg, "good": isGood})
+ }
+ }
+ }
+ }
+
+ 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: [qsTr("BMS configuration updated")]
+ property var queue: []
+
+ onClosed: {
+ if (queue.length > 0) {
+ var message = queue.pop()
+ statusPopup.text = message.text
+ statusPopup.good = message.good
+ statusPopup.open()
+ hideStatusTimer.start()
+ }
+ }
+ }
+
+ Timer {
+ id: hideStatusTimer
+ interval: 3000
+ onTriggered: statusPopup.close()
}
background: Rectangle {
@@ -233,9 +398,9 @@ ApplicationWindow {
}
Component.onCompleted: {
- BmsInterface.bmsConfig().loadParamsXml("://res/config.xml")
- BmsInterface.infoConfig().loadParamsXml("://res/info.xml")
+// BmsInterface.bmsConfig().loadParamsXml("://res/config.xml")
+// BmsInterface.infoConfig().loadParamsXml("://res/info.xml")
- connectionScreen.open()
+ connectionDialog.open()
}
}
diff --git a/qml/Screens/ConnectionDialog.qml b/qml/Screens/ConnectionDialog.qml
new file mode 100644
index 0000000..7c7cbaf
--- /dev/null
+++ b/qml/Screens/ConnectionDialog.qml
@@ -0,0 +1,86 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Controls 1.0 as Controls
+import Cubo 1.0
+import Utils 1.0
+
+Dialog {
+ id: root
+ title: qsTr("Connection screen")
+ width: 400
+ height: 320
+ modal: true
+ closePolicy: Popup.CloseOnEscape
+
+
+ header: Controls.DialogHeader {
+ dialog: root
+ }
+
+ contentItem: Rectangle {
+ color: Palette.screenBackgroundColor
+
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.leftMargin: 45
+ anchors.rightMargin: 45
+ spacing: 20
+
+ Item {
+ Layout.fillHeight: true
+ }
+
+ Label {
+ text: qsTr("Select serial port")
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
+ }
+
+ Controls.ComboBox {
+ id: serialBox
+ model: BmsInterface.serialPortNames()
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignCenter
+ }
+
+ Controls.Button {
+ id: connectButton
+ text: qsTr("Connect")
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+ onClicked: {
+ if (BmsInterface.isPortConnected()) {
+ BmsInterface.disconnectPort()
+ } else {
+ var currentPort = BmsInterface.serialPortNames()[serialBox.currentIndex]
+ if (BmsInterface.connectSerial(currentPort)) {
+ root.close()
+ }
+ }
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+ }
+ }
+
+ background: Controls.DialogBackground {}
+
+ onVisibleChanged: {
+ x = Qt.binding(function() { return (parent.width - width) / 2})
+ y = Qt.binding(function() { return (parent.height - height) / 2})
+ serialBox.model = BmsInterface.serialPortNames()
+ }
+
+ Connections {
+ target: BmsInterface
+ onPortConnectedChanged: {
+ connectButton.text = BmsInterface.isPortConnected() ? qsTr("Disconnect") : qsTr("Connect")
+ serialBox.enabled = !BmsInterface.isPortConnected()
+ }
+ }
+}
diff --git a/qml/Screens/ConnectionScreen.qml b/qml/Screens/ConnectionScreen.qml
deleted file mode 100644
index 335b83f..0000000
--- a/qml/Screens/ConnectionScreen.qml
+++ /dev/null
@@ -1,49 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Controls 2.12
-import QtQuick.Dialogs 1.2
-import QtQuick.Layouts 1.12
-
-import Controls 1.0 as Controls
-import Cubo 1.0
-import Utils 1.0
-
-Dialog {
- id: root
- title: qsTr("Connection Screen")
- width: 300
- height: 300
- standardButtons: Dialog.NoButton
-
- contentItem: Rectangle {
- color: Palette.screenBackgroundColor
-
- ColumnLayout {
- anchors.fill: parent
- anchors.margins: 45
-
- Label {
- text: qsTr("Select serial port")
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
- }
-
- Controls.ComboBox {
- id: serialBox
- model: BmsInterface.serialPortNames()
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignCenter
- }
-
- Controls.Button {
- text: qsTr("Connect")
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
- onClicked: {
- var currentPort = BmsInterface.serialPortNames()[serialBox.currentIndex]
- if (BmsInterface.connectSerial(currentPort))
- root.close()
- }
- }
- }
- }
-}
diff --git a/qml/Screens/DebugInformationScreen.qml b/qml/Screens/DebugInformationScreen.qml
new file mode 100644
index 0000000..6c73a46
--- /dev/null
+++ b/qml/Screens/DebugInformationScreen.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Controls 1.0 as Controls
+import Cubo 1.0
+
+ColumnLayout {
+ spacing: 20
+
+ Controls.Frame {
+ ScrollView {
+ anchors.fill: parent
+ Controls.TextArea {
+ id: outputArea
+ }
+ }
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ Controls.Button {
+ text: qsTr("Clear")
+ Layout.preferredWidth: 120
+ onClicked: outputArea.clear()
+ }
+
+ Connections {
+ target: BmsInterface
+
+ onStatusMessage: {
+ outputArea.append(msg)
+ }
+ }
+}
diff --git a/qml/Screens/MessageDialog.qml b/qml/Screens/MessageDialog.qml
new file mode 100644
index 0000000..198f8d0
--- /dev/null
+++ b/qml/Screens/MessageDialog.qml
@@ -0,0 +1,65 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+
+import Controls 1.0 as Controls
+import Utils 1.0
+
+Dialog {
+ id: root
+ width: 500
+ height: 350
+ modal: true
+ closePolicy: Popup.CloseOnEscape
+ bottomPadding: 0
+
+ property string description: ""
+ property bool good: true
+
+ header: Controls.DialogHeader {
+ dialog: root
+ }
+
+ contentItem: ColumnLayout {
+ spacing: 20
+
+ RowLayout {
+ spacing: 20
+
+ Image {
+ source: good ? "qrc:/Icons/info.svg" : "qrc:/Icons/warning.svg"
+ sourceSize.width: 52
+ sourceSize.height: 48
+ }
+
+ Controls.SubtitleLabel {
+ text: root.description
+ maximumLineCount: 10
+ wrapMode: Text.Wrap
+ Layout.fillWidth: true
+ }
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ RowLayout {
+ Controls.Button {
+ text: qsTr("Ok")
+ Layout.alignment: Qt.AlignCenter
+ Layout.preferredWidth: 100
+ onClicked: root.close()
+ }
+
+ Layout.alignment: Qt.AlignCenter
+ Layout.fillWidth: true
+ }
+ }
+
+ background: Controls.DialogBackground {}
+
+ onVisibleChanged: {
+ x = Qt.binding(function() { return (parent.width - width) / 2})
+ y = Qt.binding(function() { return (parent.height - height) / 2})
+ }
+}
diff --git a/qml/Screens/StatusPopup.qml b/qml/Screens/StatusPopup.qml
new file mode 100644
index 0000000..5f5db03
--- /dev/null
+++ b/qml/Screens/StatusPopup.qml
@@ -0,0 +1,48 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+
+import Controls 1.0 as Controls
+import Utils 1.0
+
+Popup {
+ id: root
+ x: (parent.width - width) / 2
+ y: parent.height - height - 20
+ closePolicy: Popup.NoAutoClose
+
+ property string text: ""
+ property bool good: true
+
+ Controls.SubtitleLabel {
+ id: label
+ text: root.text
+ maximumLineCount: 10
+ wrapMode: Text.Wrap
+ color: Palette.alternativeTextColor
+ }
+
+ background: Rectangle {
+ radius: 6
+ color: good ? Palette.alternativeBackgroundColor : Palette.invalidColor
+ border.width: 1
+ border.color: Palette.borderColor
+ }
+
+ enter: Transition {
+ NumberAnimation {
+ property: "opacity"
+ from: 0.0
+ to: 1.0
+ duration: 300
+ }
+ }
+
+ exit: Transition {
+ NumberAnimation {
+ property: "opacity"
+ from: 1.0
+ to: 0.0
+ duration: 2500
+ }
+ }
+}
diff --git a/qml/Screens/qmldir b/qml/Screens/qmldir
index fbd6b1f..ea698af 100644
--- a/qml/Screens/qmldir
+++ b/qml/Screens/qmldir
@@ -1,7 +1,10 @@
module Screens
-ConnectionScreen 1.0 ConnectionScreen.qml
AkbMonitorScreen 1.0 AkbMonitorScreen.qml
CellMonitorScreen 1.0 CellMonitorScreen.qml
BmsSettingsScreen 1.0 BmsSettingsScreen.qml
VisualizationScreen 1.0 VisualizationScreen.qml
BmsServiceScreen 1.0 BmsServiceScreen.qml
+DebugInformationScreen 1.0 DebugInformationScreen.qml
+ConnectionDialog 1.0 ConnectionDialog.qml
+MessageDialog 1.0 MessageDialog.qml
+StatusPopup 1.0 StatusPopup.qml
diff --git a/qml/Utils/Palette.qml b/qml/Utils/Palette.qml
index 5664faf..f13b725 100644
--- a/qml/Utils/Palette.qml
+++ b/qml/Utils/Palette.qml
@@ -21,4 +21,6 @@ QtObject {
property color outlineButtonColor: "#F7F8FC"
property color hoveredButtonColor: "#03AC61"
property color pressedButtonColor: "#057845"
+
+ property color invalidColor: "#A31C00"
}
diff --git a/qml/qml_icons.qrc b/qml/qml_icons.qrc
index aecde6e..42420ca 100644
--- a/qml/qml_icons.qrc
+++ b/qml/qml_icons.qrc
@@ -10,5 +10,9 @@
Icons/history.svg
Icons/visualization.svg
Icons/check-indicator.svg
+ Icons/connection.svg
+ Icons/close.svg
+ Icons/info.svg
+ Icons/warning.svg
diff --git a/qml/qml_items.qrc b/qml/qml_items.qrc
index 4803137..5cd7ea5 100644
--- a/qml/qml_items.qrc
+++ b/qml/qml_items.qrc
@@ -1,7 +1,7 @@
MainWindow.qml
- Screens/ConnectionScreen.qml
+ Screens/ConnectionDialog.qml
Screens/AkbMonitorScreen.qml
Screens/CellMonitorScreen.qml
Controls/ComboBox.qml
@@ -32,5 +32,10 @@
Controls/ChartView.qml
Screens/BmsServiceScreen.qml
Controls/TextArea.qml
+ Screens/DebugInformationScreen.qml
+ Controls/DialogHeader.qml
+ Controls/DialogBackground.qml
+ Screens/MessageDialog.qml
+ Screens/StatusPopup.qml