diff --git a/ENNOID-BMS-Tool.pro b/ENNOID-BMS-Tool.pro index 446ff1c..c40953e 100644 --- a/ENNOID-BMS-Tool.pro +++ b/ENNOID-BMS-Tool.pro @@ -5,7 +5,7 @@ #------------------------------------------------- INCLUDEPATH += $$PWD # Version -DT_VERSION = 1.3 +DT_VERSION = 2.0 DEFINES += DT_VERSION=$$DT_VERSION !android: { @@ -21,13 +21,13 @@ CONFIG += c++14 # Bluetooth available -DEFINES += HAS_BLUETOOTH +#DEFINES += HAS_BLUETOOTH QT += core gui -QT += widgets -QT += printsupport +#QT += widgets +#QT += printsupport QT += network -QT += bluetooth +#QT += bluetooth QT += quick QT += quickcontrols2 QT += charts @@ -75,96 +75,104 @@ build_mobile { } SOURCES += main.cpp\ - akbmonitorpage.cpp \ - bmsservicepage.cpp \ - bmssettings.cpp \ - bmssettingswidget.cpp \ - cellsmonitorcheckboxdelegate.cpp \ - cellsmonitorlabelvoltagedelegate.cpp \ - cellsmonitorpage.cpp \ - configparamsgetter.cpp \ - configurationpage.cpp \ - connectandenterpage.cpp \ - customlefttabbarbutton.cpp \ - debugprintpage.cpp \ - historylineeditbox.cpp \ - hoverablecombobox.cpp \ - languageselectorbutton.cpp \ - mainwindow.cpp \ - mainwindownew.cpp \ +# akbmonitorpage.cpp \ +# bmsservicepage.cpp \ +# bmssettings.cpp \ +# bmssettingswidget.cpp \ +# cellsmonitorcheckboxdelegate.cpp \ +# cellsmonitorlabelvoltagedelegate.cpp \ +# cellsmonitorpage.cpp \ +# configparamsgetter.cpp \ +# configurationpage.cpp \ +# connectandenterpage.cpp \ +# customlefttabbarbutton.cpp \ +# debugprintpage.cpp \ +# historylineeditbox.cpp \ +# hoverablecombobox.cpp \ +# languageselectorbutton.cpp \ +# mainwindow.cpp \ +# mainwindownew.cpp \ packet.cpp \ - settingsextrapage.cpp \ +# settingsextrapage.cpp \ vbytearray.cpp \ commands.cpp \ configparams.cpp \ configparam.cpp \ - parametereditor.cpp \ - digitalfiltering.cpp \ - bleuart.cpp \ +# parametereditor.cpp \ +# digitalfiltering.cpp \ +# bleuart.cpp \ utility.cpp \ bmsinterface.cpp \ - visualizationchart.cpp \ - visualizationpage.cpp + translator.cpp \ +# visualizationchart.cpp \ +# visualizationpage.cpp -HEADERS += mainwindow.h \ - akbmonitorpage.h \ - bmsservicepage.h \ - bmssettings.h \ - bmssettingswidget.h \ - cellsmonitorcheckboxdelegate.h \ - cellsmonitorlabelvoltagedelegate.h \ - cellsmonitorpage.h \ - configparamsgetter.h \ - configurationpage.h \ - connectandenterpage.h \ - customlefttabbarbutton.h \ - debugprintpage.h \ - historylineedit.h \ - historylineeditbox.h \ - hoverablecombobox.h \ - languageselectorbutton.h \ - mainwindownew.h \ +HEADERS += \ #mainwindow.h \ +# akbmonitorpage.h \ +# bmsservicepage.h \ +# bmssettings.h \ +# bmssettingswidget.h \ +# cellsmonitorcheckboxdelegate.h \ +# cellsmonitorlabelvoltagedelegate.h \ +# cellsmonitorpage.h \ +# configparamsgetter.h \ +# configurationpage.h \ +# connectandenterpage.h \ +# customlefttabbarbutton.h \ +# debugprintpage.h \ +# historylineedit.h \ +# historylineeditbox.h \ +# hoverablecombobox.h \ +# languageselectorbutton.h \ +# mainwindownew.h \ packet.h \ - settingsextrapage.h \ +# settingsextrapage.h \ vbytearray.h \ commands.h \ datatypes.h \ configparams.h \ configparam.h \ - parametereditor.h \ - digitalfiltering.h \ - bleuart.h \ +# parametereditor.h \ +# digitalfiltering.h \ +# bleuart.h \ utility.h \ bmsinterface.h \ - visualizationchart.h \ - visualizationpage.h + translator.h \ +# visualizationchart.h \ +# visualizationpage.h -FORMS += mainwindow.ui \ - akbmonitorpage.ui \ - bmsservicepage.ui \ - bmssettings.ui \ - bmssettingswidget.ui \ - cellsmonitorpage.ui \ - configurationpage.ui \ - connectandenterpage.ui \ - debugprintpage.ui \ - mainwindownew.ui \ - parametereditor.ui \ - settingsextrapage.ui \ - visualizationpage.ui +#FORMS += mainwindow.ui \ +# akbmonitorpage.ui \ +# bmsservicepage.ui \ +# bmssettings.ui \ +# bmssettingswidget.ui \ +# cellsmonitorpage.ui \ +# configurationpage.ui \ +# connectandenterpage.ui \ +# debugprintpage.ui \ +# mainwindownew.ui \ +# parametereditor.ui \ +# settingsextrapage.ui \ +# visualizationpage.ui -include(pages/pages.pri) -include(widgets/widgets.pri) -include(mobile/mobile.pri) +#include(pages/pages.pri) +#include(widgets/widgets.pri) +#include(mobile/mobile.pri) RESOURCES += res.qrc \ - qml/qml_icons.qrc \ + translations/translations.qrc + +RESOURCES += qml/qml_icons.qrc \ qml/qml_items.qrc # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH *= $$PWD/qml QML2_IMPORT_PATH *= $$PWD/qml +TRANSLATIONS = translations/cubo_en.ts \ + translations/cubo_ru.ts \ + translations/cubo_it.ts + DISTFILES += \ android/AndroidManifest.xml \ android/gradle/wrapper/gradle-wrapper.jar \ diff --git a/bmsinterface.cpp b/bmsinterface.cpp index c7f7a35..eb7d654 100644 --- a/bmsinterface.cpp +++ b/bmsinterface.cpp @@ -89,8 +89,11 @@ BMSInterface::BMSInterface(QObject *parent) : QObject(parent) // BLE +#ifdef HAS_BLUETOOTH mBleUart = new BleUart(this); mLastBleAddr = QSettings().value("ble_addr").toString(); + connect(mBleUart, SIGNAL(dataRx(QByteArray)), this, SLOT(bleDataRx(QByteArray))); +#endif int size = mSettings.beginReadArray("bleNames"); for (int i = 0; i < size; ++i) { @@ -101,8 +104,6 @@ BMSInterface::BMSInterface(QObject *parent) : QObject(parent) } mSettings.endArray(); - connect(mBleUart, SIGNAL(dataRx(QByteArray)), this, SLOT(bleDataRx(QByteArray))); - mCommands->setbmsConfig(mbmsConfig); // Other signals/slots @@ -280,9 +281,11 @@ bool BMSInterface::isPortConnected() res = true; } +#ifdef HAS_BLUETOOTH if (mBleUart->isConnected()) { res = true; } +#endif return res; } @@ -301,10 +304,12 @@ void BMSInterface::disconnectPort() updateFwRx(false); } +#ifdef HAS_BLUETOOTH if (mBleUart->isConnected()) { mBleUart->disconnectBle(); updateFwRx(false); } +#endif mFwRetries = 0; } @@ -321,8 +326,12 @@ bool BMSInterface::reconnectLastPort() connectTcp(mLastTcpServer, mLastTcpPort); return true; } else if (mLastConnType == CONN_BLE) { +#ifdef HAS_BLUETOOTH mBleUart->startConnect(mLastBleAddr); return true; +#else + return false; +#endif } else { #ifdef HAS_SERIALPORT QList ports = listSerialPorts(); @@ -408,10 +417,12 @@ QString BMSInterface::getConnectedPortName() connected = true; } +#ifdef HAS_BLUETOOTH if (mBleUart->isConnected()) { res = tr("Connected (BLE) to %1").arg(mLastBleAddr); connected = true; } +#endif if (connected && mCommands->isLimitedMode()) { res += tr(", limited mode"); @@ -551,10 +562,12 @@ void BMSInterface::connectTcp(QString server, int port) void BMSInterface::connectBle(QString address) { +#ifdef HAS_BLUETOOTH mBleUart->startConnect(address); mLastConnType = CONN_BLE; mLastBleAddr = address; setLastConnectionType(CONN_BLE); +#endif } bool BMSInterface::isAutoconnectOngoing() const @@ -629,7 +642,7 @@ void BMSInterface::serialPortError(QSerialPort::SerialPortError error) break; default: - message = "Serial port error: " + mSerialPort->errorString(); + message = tr("Serial port error: ") + mSerialPort->errorString(); break; } @@ -762,9 +775,11 @@ void BMSInterface::packetDataToSend(QByteArray &data) mTcpSocket->write(data); } +#ifdef HAS_BLUETOOTH if (mBleUart->isConnected()) { mBleUart->writeData(data); } +#endif } void BMSInterface::packetReceived(QByteArray &data) @@ -846,15 +861,17 @@ void BMSInterface::fwVersionReceived(int major, int minor, QString hw, QByteArra } } - QString fwStr; - fwStr.sprintf("ENNOID-BMS Firmware Version %d.%d", major, minor); - if (!hw.isEmpty()) { - fwStr += ", Hardware: " + hw; - } + auto fwStr = tr("Firmware version: %1.%2, Hardware: %3, UUID: %4").arg(major).arg(minor).arg(hw).arg(strUuid); - if (!strUuid.isEmpty()) { - fwStr += ", UUID: " + strUuid; - } +// QString fwStr; +// fwStr.sprintf("ENNOID-BMS Firmware Version %d.%d", major, minor); +// if (!hw.isEmpty()) { +// fwStr += ", Hardware: " + hw; +// } + +// if (!strUuid.isEmpty()) { +// fwStr += ", UUID: " + strUuid; +// } emit statusMessage(fwStr, true); #if 0 diff --git a/bmsinterface.h b/bmsinterface.h index ff67eab..da0a34e 100644 --- a/bmsinterface.h +++ b/bmsinterface.h @@ -141,7 +141,9 @@ private slots: void tcpInputDataAvailable(); void tcpInputError(QAbstractSocket::SocketError socketError); +#ifdef HAS_BLUETOOTH void bleDataRx(QByteArray data); +#endif void timerSlot(); void packetDataToSend(QByteArray &data); diff --git a/commands.cpp b/commands.cpp index a6398ac..c89da80 100644 --- a/commands.cpp +++ b/commands.cpp @@ -234,7 +234,7 @@ void Commands::processPacket(QByteArray data) break; case COMM_SET_MCCONF: - emit ackReceived("BMS Write OK"); + emit ackReceived(tr("BMS configuration is set")); break; case COMM_STORE_BMS_CONF: diff --git a/configparams.cpp b/configparams.cpp index e0eecaf..657d0f9 100644 --- a/configparams.cpp +++ b/configparams.cpp @@ -575,102 +575,102 @@ void ConfigParams::setParamValue(const QString &name, QVariant val) } -QWidget *ConfigParams::getEditor(const QString &name, QWidget *parent) -{ - QWidget *retVal = 0; +//QWidget *ConfigParams::getEditor(const QString &name, QWidget *parent) +//{ +// QWidget *retVal = 0; - if (mParams.contains(name)) { - ConfigParam &p = mParams[name]; +// if (mParams.contains(name)) { +// ConfigParam &p = mParams[name]; - switch (p.type) { - case CFG_T_DOUBLE: { - ParamEditDouble *edit = new ParamEditDouble(parent); - edit->setName(name); - edit->setSuffix(p.suffix); - edit->setDecimals(p.editorDecimalsDouble); - edit->setShowAsPercentage(p.editAsPercentage); - edit->showDisplay(p.showDisplay); +// switch (p.type) { +// case CFG_T_DOUBLE: { +// ParamEditDouble *edit = new ParamEditDouble(parent); +// edit->setName(name); +// edit->setSuffix(p.suffix); +// edit->setDecimals(p.editorDecimalsDouble); +// edit->setShowAsPercentage(p.editAsPercentage); +// edit->showDisplay(p.showDisplay); - edit->setProperty("type", int(p.type)); - edit->setProperty("suffix", p.suffix); - edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); - edit->setProperty("editAsPercentage", p.editAsPercentage); - edit->setProperty("value", p.valDouble); +// edit->setProperty("type", int(p.type)); +// edit->setProperty("suffix", p.suffix); +// edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); +// edit->setProperty("editAsPercentage", p.editAsPercentage); +// edit->setProperty("value", p.valDouble); - edit->setConfig(this); - retVal = edit; - } break; +// edit->setConfig(this); +// retVal = edit; +// } break; - case CFG_T_INT: { - ParamEditInt *edit = new ParamEditInt(parent); - edit->setName(name); - edit->setSuffix(p.suffix); - edit->setShowAsPercentage(p.editAsPercentage); - edit->showDisplay(p.showDisplay); +// case CFG_T_INT: { +// ParamEditInt *edit = new ParamEditInt(parent); +// edit->setName(name); +// edit->setSuffix(p.suffix); +// edit->setShowAsPercentage(p.editAsPercentage); +// edit->showDisplay(p.showDisplay); - edit->setProperty("type", int(p.type)); - edit->setProperty("suffix", p.suffix); - edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); - edit->setProperty("editAsPercentage", p.editAsPercentage); - edit->setProperty("value", p.valInt); +// edit->setProperty("type", int(p.type)); +// edit->setProperty("suffix", p.suffix); +// edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); +// edit->setProperty("editAsPercentage", p.editAsPercentage); +// edit->setProperty("value", p.valInt); - edit->setConfig(this); - retVal = edit; - } break; +// edit->setConfig(this); +// retVal = edit; +// } break; - case CFG_T_QSTRING: { - ParamEditString *edit = new ParamEditString(parent); - edit->setName(name); +// case CFG_T_QSTRING: { +// ParamEditString *edit = new ParamEditString(parent); +// edit->setName(name); - edit->setProperty("type", int(p.type)); - edit->setProperty("suffix", p.suffix); - edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); - edit->setProperty("editAsPercentage", p.editAsPercentage); - edit->setProperty("value", p.valString); +// edit->setProperty("type", int(p.type)); +// edit->setProperty("suffix", p.suffix); +// edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); +// edit->setProperty("editAsPercentage", p.editAsPercentage); +// edit->setProperty("value", p.valString); - edit->setConfig(this); - retVal = edit; - } break; +// edit->setConfig(this); +// retVal = edit; +// } break; - case CFG_T_ENUM: { - ParamEditEnum *edit = new ParamEditEnum(parent); - edit->setName(name); +// case CFG_T_ENUM: { +// ParamEditEnum *edit = new ParamEditEnum(parent); +// edit->setName(name); - edit->setProperty("type", int(p.type)); - edit->setProperty("suffix", p.suffix); - edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); - edit->setProperty("editAsPercentage", p.editAsPercentage); - edit->setProperty("value", p.valInt); +// edit->setProperty("type", int(p.type)); +// edit->setProperty("suffix", p.suffix); +// edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); +// edit->setProperty("editAsPercentage", p.editAsPercentage); +// edit->setProperty("value", p.valInt); - edit->setConfig(this); - retVal = edit; - } break; +// edit->setConfig(this); +// retVal = edit; +// } break; - case CFG_T_BOOL: { - ParamEditBool *edit = new ParamEditBool(parent); - edit->setName(name); +// case CFG_T_BOOL: { +// ParamEditBool *edit = new ParamEditBool(parent); +// edit->setName(name); - edit->setProperty("type", int(p.type)); - edit->setProperty("suffix", p.suffix); - edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); - edit->setProperty("editAsPercentage", p.editAsPercentage); - edit->setProperty("value", p.valInt); +// edit->setProperty("type", int(p.type)); +// edit->setProperty("suffix", p.suffix); +// edit->setProperty("editorDecimalsDouble", p.editorDecimalsDouble); +// edit->setProperty("editAsPercentage", p.editAsPercentage); +// edit->setProperty("value", p.valInt); - edit->setConfig(this); - retVal = edit; - } break; +// edit->setConfig(this); +// retVal = edit; +// } break; - default: - qWarning() << "no editor for" << name << "could be created"; - break; - } +// default: +// qWarning() << "no editor for" << name << "could be created"; +// break; +// } - } else { - qWarning() << name << "not found"; - } +// } else { +// qWarning() << name << "not found"; +// } - return retVal; -} +// return retVal; +//} /* QWidget *ConfigParams::getEditor(const QString &name, QWidget *parent) diff --git a/configparams.h b/configparams.h index 84e355b..417d0b6 100644 --- a/configparams.h +++ b/configparams.h @@ -84,7 +84,7 @@ public: QStringList getParamOrder() const; void setParamOrder(const QStringList &order); - QWidget *getEditor(const QString &name, QWidget *parent = 0); +// QWidget *getEditor(const QString &name, QWidget *parent = 0); void getParamSerial(VByteArray &vb, const QString &name); void setParamSerial(VByteArray &vb, const QString &name, QObject *src = 0); diff --git a/main.cpp b/main.cpp index cf96846..d4a3022 100644 --- a/main.cpp +++ b/main.cpp @@ -20,7 +20,7 @@ #include "bmsinterface.h" #include "utility.h" -#include "mobile/fwhelper.h" +#include "translator.h" #include #include @@ -40,9 +40,16 @@ QObject *utilitySingletontypeProvider(QQmlEngine */*engine*/, QJSEngine */*scrip return utility; } +QObject *translatorSingletontypeProvider(QQmlEngine *engine, QJSEngine */*scriptEngine*/) +{ + auto *translator = new Translator(engine); + return translator; +} + int main(int argc, char *argv[]) { Q_INIT_RESOURCE(res); + Q_INIT_RESOURCE(translations); Q_INIT_RESOURCE(qml_icons); Q_INIT_RESOURCE(qml_items); @@ -59,16 +66,13 @@ int main(int argc, char *argv[]) font.setStyleStrategy(QFont::PreferAntialias); app.setFont(font); -// app.setFont(QFont("Artifakt Element", 16, QFont::Medium)); - QQmlApplicationEngine engine; qmlRegisterSingletonType("Cubo", 1, 0, "BmsInterface", bmsInterfaceSingletontypeProvider); qmlRegisterSingletonType("Cubo", 1, 0, "Utility", utilitySingletontypeProvider); - qmlRegisterType("Cubo", 1, 0, "BleUart"); + qmlRegisterSingletonType("Cubo", 1, 0, "Translator", translatorSingletontypeProvider); qmlRegisterType("Cubo", 1, 0, "Commands"); qmlRegisterType("Cubo", 1, 0, "ConfigParams"); - qmlRegisterType("Cubo", 1, 0, "FwHelper"); engine.addImportPath(QStringLiteral("qrc:/")); engine.load(QUrl(QStringLiteral("qrc:/MainWindow.qml"))); diff --git a/qml/Controls/BusyIndicator.qml b/qml/Controls/BusyIndicator.qml new file mode 100644 index 0000000..f8d86ea --- /dev/null +++ b/qml/Controls/BusyIndicator.qml @@ -0,0 +1,57 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +import Utils 1.0 + +BusyIndicator { + id: control + running: true + implicitWidth: 86 + implicitHeight: 86 + + contentItem: Item { + id: item + width: parent.width + height: parent.height + opacity: control.running ? 1 : 0 + + Behavior on opacity { + OpacityAnimator { + duration: 250 + } + } + + RotationAnimator { + target: item + running: control.visible && control.running + from: 0 + to: 360 + loops: Animation.Infinite + duration: 5000 + } + + Repeater { + id: repeater + model: 6 + + Rectangle { + x: item.width / 2 - width / 2 + y: item.height / 2 - height / 2 + implicitWidth: 12 + implicitHeight: 12 + radius: 6 + color: Palette.alternativeBackgroundColor + transform: [ + Translate { + y: -Math.min(item.width, item.height) * 0.5 + 6 + }, + Rotation { + angle: index / repeater.count * 360 + origin.x: 6 + origin.y: 6 + } + ] + } + } + } +} diff --git a/qml/Controls/Button.qml b/qml/Controls/Button.qml index 8caf41c..70558c6 100644 --- a/qml/Controls/Button.qml +++ b/qml/Controls/Button.qml @@ -15,6 +15,8 @@ Button { horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight + maximumLineCount: 2 + wrapMode: Text.Wrap } background: Rectangle { diff --git a/qml/Controls/Label.qml b/qml/Controls/Label.qml deleted file mode 100644 index 9c36e13..0000000 --- a/qml/Controls/Label.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick 2.0 - -Item { - -} diff --git a/qml/Controls/LineSeparator.qml b/qml/Controls/LineSeparator.qml index 5703086..691cc8c 100644 --- a/qml/Controls/LineSeparator.qml +++ b/qml/Controls/LineSeparator.qml @@ -5,13 +5,15 @@ import Utils 1.0 Shape { id: shape + implicitWidth: 1 implicitHeight: 1 + property bool horizontal: true ShapePath { strokeColor: Palette.borderColor strokeStyle: ShapePath.SolidLine startX: 0 startY: 0 - PathLine { x: shape.width; y: 0 } + PathLine { x: horizontal ? shape.width : 0; y: horizontal ? 0 : shape.height } } } diff --git a/qml/Controls/MenuItemDelegate.qml b/qml/Controls/MenuItemDelegate.qml new file mode 100644 index 0000000..71e41a3 --- /dev/null +++ b/qml/Controls/MenuItemDelegate.qml @@ -0,0 +1,59 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import QtGraphicalEffects 1.0 + +import Utils 1.0 + +ItemDelegate { + id: control + implicitHeight: 52 + padding: 0 + leftPadding: control.minimized ? 0 : 40 + font.weight: Font.Bold + icon.color: "transparent" + icon.width: 24 + icon.height: 24 + + property bool minimized: false + + contentItem: RowLayout { + spacing: control.minimized ? 0 : 25 + + Item { + visible: control.minimized + Layout.fillWidth: true + } + + Image { + source: control.icon.source + sourceSize.width: control.icon.width + sourceSize.height: control.icon.height + Layout.alignment: Qt.AlignCenter + + ColorOverlay { + anchors.fill: parent + source: parent + color: icon.color + visible: icon.color !== "transparent" + } + } + + Label { + text: control.text + font: control.font + color: Palette.alternativeTextColor + visible: !control.minimized + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + } + + Item { + Layout.fillWidth: true + } + } + + background: Rectangle { + color: control.pressed ? Palette.pressedButtonColor : + control.hovered ? Palette.hoveredButtonColor : Palette.buttonColor + } +} diff --git a/qml/Controls/OutlineButton.qml b/qml/Controls/OutlineButton.qml index 5361621..111dc9d 100644 --- a/qml/Controls/OutlineButton.qml +++ b/qml/Controls/OutlineButton.qml @@ -15,6 +15,8 @@ Button { horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight + maximumLineCount: 2 + wrapMode: Text.Wrap } background: Rectangle { diff --git a/qml/Controls/PaneItem.qml b/qml/Controls/PaneItem.qml deleted file mode 100644 index 9c36e13..0000000 --- a/qml/Controls/PaneItem.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick 2.0 - -Item { - -} diff --git a/qml/Controls/TextArea.qml b/qml/Controls/TextArea.qml index 7597929..f11af9d 100644 --- a/qml/Controls/TextArea.qml +++ b/qml/Controls/TextArea.qml @@ -6,6 +6,6 @@ import Utils 1.0 TextArea { color: Palette.textColor selectByMouse: true - selectionColor: Palette.alternativeBackgroundColor + selectionColor: Palette.selectedTextBackgroundColor font.pixelSize: 16 } diff --git a/qml/Controls/TextField.qml b/qml/Controls/TextField.qml index 771d894..8e4022a 100644 --- a/qml/Controls/TextField.qml +++ b/qml/Controls/TextField.qml @@ -7,7 +7,7 @@ TextField { implicitHeight: 58 color: Palette.textColor selectByMouse: true - selectionColor: Palette.alternativeBackgroundColor + selectionColor: Palette.selectedTextBackgroundColor background: Rectangle { color: enabled ? Palette.backgroundColor : Palette.hoveredBackgroundColor diff --git a/qml/Controls/qmldir b/qml/Controls/qmldir index b0b9cb5..866e050 100644 --- a/qml/Controls/qmldir +++ b/qml/Controls/qmldir @@ -1,7 +1,5 @@ module Controls -Label 1.0 Label.qml ComboBox 1.0 ComboBox.qml -PaneItem 1.0 PaneItem.qml ScrollBar 1.0 ScrollBar.qml Button 1.0 Button.qml OutlineButton 1.0 OutlineButton.qml @@ -22,3 +20,5 @@ ChartView 1.0 ChartView.qml TextArea 1.0 TextArea.qml DialogHeader 1.0 DialogHeader.qml DialogBackground 1.0 DialogBackground.qml +BusyIndicator 1.0 BusyIndicator.qml +MenuItemDelegate 1.0 MenuItemDelegate.qml diff --git a/qml/Icons/cell-monitor.svg b/qml/Icons/cell-monitor.svg index a179990..9a63879 100644 --- a/qml/Icons/cell-monitor.svg +++ b/qml/Icons/cell-monitor.svg @@ -1,18 +1,18 @@ - + - + - + - + - + - + - + - + diff --git a/qml/Icons/english-flag.svg b/qml/Icons/english-flag.svg new file mode 100644 index 0000000..e321058 --- /dev/null +++ b/qml/Icons/english-flag.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/qml/Icons/italian-flag.svg b/qml/Icons/italian-flag.svg new file mode 100644 index 0000000..3d85006 --- /dev/null +++ b/qml/Icons/italian-flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/qml/Icons/russian-flag.svg b/qml/Icons/russian-flag.svg new file mode 100644 index 0000000..5cc4522 --- /dev/null +++ b/qml/Icons/russian-flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/qml/MainWindow.qml b/qml/MainWindow.qml index 3c458ce..a1e89ae 100644 --- a/qml/MainWindow.qml +++ b/qml/MainWindow.qml @@ -1,7 +1,6 @@ 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 @@ -10,7 +9,7 @@ import Utils 1.0 ApplicationWindow { id: window - title: qsTr("Cubo Verde BMS Tool") + title: qsTr("Cubo Verde BMS tool") width: 1366 height: 768 visible: true @@ -45,38 +44,11 @@ ApplicationWindow { Layout.preferredHeight: pane.minimized ? 85 : 40 } - ItemDelegate { - leftPadding: pane.minimized ? 0 : 40 - - contentItem: RowLayout { - height: 50 - spacing: 25 - - Item { - visible: pane.minimized - Layout.fillWidth: true - } - - Image { - source: "qrc:/Icons/hide-menu.svg" - mirror: pane.minimized - Layout.alignment: Qt.AlignCenter - } - - Label { - text: qsTr("Hide menu") - color: Palette.alternativeTextColor - visible: !pane.minimized - } - - Item { - Layout.fillWidth: true - } - } - - background: Rectangle { - color: "transparent" - } + 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 @@ -90,7 +62,6 @@ ApplicationWindow { pane.minimized = false } - Layout.preferredHeight: 52 Layout.fillWidth: true } @@ -100,101 +71,36 @@ ApplicationWindow { ListView { id: menuView - model: [ + + 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"}, -// {"text": qsTr("Exit"), "icon": "qrc:/Icons/exit.svg"}, + {"text": qsTr("BMS service"), "icon": "qrc:/Icons/bms-service.svg"} ] - delegate: ItemDelegate { - id: menuDelegate + model: menuModel.length + + delegate: Controls.MenuItemDelegate { width: ListView.view.width - height: 52 - leftPadding: pane.minimized ? 0 : 40 - highlighted: ListView.isCurrentItem + text: menuView.menuModel[modelData].text + icon.source: menuView.menuModel[modelData].icon + minimized: pane.minimized onClicked: menuView.currentIndex = index - - contentItem: RowLayout { - spacing: pane.minimized ? 0 : 25 - height: 50 - - Item { - visible: pane.minimized - Layout.fillWidth: true - } - - Image { - source: modelData.icon - Layout.alignment: Qt.AlignCenter - } - - Label { - text: modelData.text - font.weight: Font.Bold - color: Palette.alternativeTextColor - visible: !pane.minimized - } - - Item { - Layout.fillWidth: true - } - } - - background: Rectangle { - color: menuDelegate.highlighted ? Palette.pressedButtonColor : Palette.buttonColor - } } Layout.fillHeight: true Layout.fillWidth: true } - ItemDelegate { - leftPadding: pane.minimized ? 0 : 40 + Controls.MenuItemDelegate { + text: qsTr("Connection") + icon.source: "qrc:/Icons/connection.svg" + icon.color: "#FFFFFF" + minimized: pane.minimized 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 } @@ -216,6 +122,8 @@ ApplicationWindow { } ColumnLayout { + spacing: 0 + RowLayout { id: topBar @@ -226,13 +134,13 @@ ApplicationWindow { qsTr("Visualization"), qsTr("Information output"), qsTr("Terminal"), - qsTr("Exit"), ] Label { text: topBar.labels[stack.currentIndex] font.pixelSize: 38 font.weight: Font.Bold + color: Palette.textColor } Item { @@ -240,8 +148,14 @@ ApplicationWindow { } RowLayout { + spacing: 20 + ColumnLayout { + spacing: 5 + RowLayout { + spacing: 7 + Controls.ContentLabel { id: connectionStatusLabel text: qsTr("Disconnected") @@ -264,6 +178,8 @@ ApplicationWindow { } RowLayout { + spacing: 5 + Controls.ContentLabel { text: qsTr("Serial number") + ":" Layout.alignment: Qt.AlignRight @@ -277,11 +193,111 @@ ApplicationWindow { 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 { @@ -301,6 +317,14 @@ ApplicationWindow { } Screens.BmsSettingsScreen { + onNeedWait: { + if (active) { + busyPopup.text = text + busyPopup.open() + } else { + busyPopup.close() + } + } } Screens.VisualizationScreen { @@ -319,7 +343,7 @@ ApplicationWindow { target: BmsInterface onPortConnectedChanged: { - connectionStatusLabel.text = BmsInterface.isPortConnected() ? qsTr("Connected") : qsTr("Disconnected") + connectionStatusLabel.text = Qt.binding(function(){ return BmsInterface.isPortConnected() ? qsTr("Connected") : qsTr("Disconnected") }) connectionStatusIndicator.enabled = BmsInterface.isPortConnected() if (BmsInterface.isPortConnected()) { BmsInterface.commands().getBMSconf() @@ -351,7 +375,6 @@ ApplicationWindow { statusPopup.text = msg statusPopup.good = isGood statusPopup.open() - hideStatusTimer.start() } else { if (statusPopup.text !== msg) { statusPopup.queue.push({"text": msg, "good": isGood}) @@ -395,7 +418,7 @@ ApplicationWindow { Screens.StatusPopup { id: statusPopup - property var filteredStatuses: []//[qsTr("BMS configuration updated")] + property var filteredStatuses: [] property var queue: [] onClosed: { @@ -404,9 +427,13 @@ ApplicationWindow { statusPopup.text = message.text statusPopup.good = message.good statusPopup.open() - hideStatusTimer.start() } } + + onOpened: { + hideStatusTimer.start() + busyPopup.close() + } } Timer { @@ -415,13 +442,57 @@ ApplicationWindow { 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: { -// BmsInterface.bmsConfig().loadParamsXml("://res/config.xml") -// BmsInterface.infoConfig().loadParamsXml("://res/info.xml") connectionDialog.open() } } diff --git a/qml/Screens/AkbMonitorScreen.qml b/qml/Screens/AkbMonitorScreen.qml index 7e9b27d..93c4c1f 100644 --- a/qml/Screens/AkbMonitorScreen.qml +++ b/qml/Screens/AkbMonitorScreen.qml @@ -16,7 +16,7 @@ Item { Layout.fillWidth: true RowLayout { - spacing: 90 + spacing: 70 anchors.fill: parent Controls.TitleLabel { @@ -41,14 +41,14 @@ Item { GridLayout { columns: 2 - columnSpacing: 90 + columnSpacing: 70 rowSpacing: 20 anchors.fill: parent RowLayout { spacing: 10 Controls.ContentLabel { - text: qsTr("Battery charge level, V") + text: qsTr("Battery charge level, %") Layout.fillWidth: true Layout.maximumWidth: implicitWidth } @@ -222,7 +222,7 @@ Item { GridLayout { columns: 2 - columnSpacing: 90 + columnSpacing: 70 rowSpacing: 20 anchors.fill: parent diff --git a/qml/Screens/BmsSettingsScreen.qml b/qml/Screens/BmsSettingsScreen.qml index 3ff4dc4..eeee39f 100644 --- a/qml/Screens/BmsSettingsScreen.qml +++ b/qml/Screens/BmsSettingsScreen.qml @@ -12,6 +12,8 @@ RowLayout { property real contentRowSpacing: 20 property real contentColumnSpacing: 35 + signal needWait(bool active, string text) + spacing: contentColumnSpacing Flickable { @@ -163,12 +165,16 @@ RowLayout { Controls.SubtitleLabel { text: qsTr("Maximum charge current, A") + maximumLineCount: 2 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 } Controls.SubtitleLabel { text: qsTr("Maximum load current, A") + maximumLineCount: 2 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 } @@ -189,6 +195,8 @@ RowLayout { Controls.SubtitleLabel { text: qsTr("Maximum temperature, °C") + maximumLineCount: 2 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 Layout.columnSpan: 2 @@ -224,12 +232,16 @@ RowLayout { Controls.SubtitleLabel { text: qsTr("Lower disable threshold, V") + maximumLineCount: 2 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 } Controls.SubtitleLabel { text: qsTr("Upper disable threshold, V") + maximumLineCount: 2 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 } @@ -250,14 +262,16 @@ RowLayout { Controls.SubtitleLabel { text: qsTr("Lower enable threshold (should be higher than disable), V") - maximumLineCount: 2 + maximumLineCount: 3 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 } Controls.SubtitleLabel { text: qsTr("Upper enable threshold (should be higher than disable), V") - maximumLineCount: 2 + maximumLineCount: 3 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 } @@ -328,6 +342,8 @@ RowLayout { Controls.SubtitleLabel { text: qsTr("Cell balancing interval, ms") + maximumLineCount: 2 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 Layout.columnSpan: 2 @@ -367,13 +383,13 @@ RowLayout { spacing: 20 Controls.LabelWithBackground { - text: qsTr("№ 1") + text: qsTr("# 1") Layout.preferredWidth: outputSettingsFrame.outputNumberSize Layout.preferredHeight: outputSettingsFrame.outputNumberSize } Controls.CheckBox { - text: qsTr("Use for management") + text: qsTr("Use for storage management") Layout.fillWidth: true Layout.preferredHeight: outputSettingsFrame.outputNumberSize } @@ -391,7 +407,7 @@ RowLayout { spacing: 20 Controls.LabelWithBackground { - text: qsTr("№ 2") + text: qsTr("# 2") Layout.preferredWidth: outputSettingsFrame.outputNumberSize Layout.preferredHeight: outputSettingsFrame.outputNumberSize } @@ -408,6 +424,8 @@ RowLayout { Controls.SubtitleLabel { text: qsTr("Change in value during SOC") + maximumLineCount: 2 + wrapMode: Text.WordWrap Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 Layout.columnSpan: 2 @@ -429,7 +447,7 @@ RowLayout { spacing: 20 Controls.LabelWithBackground { - text: qsTr("№ 3") + text: qsTr("# 3") Layout.preferredWidth: outputSettingsFrame.outputNumberSize Layout.preferredHeight: outputSettingsFrame.outputNumberSize } @@ -476,7 +494,7 @@ RowLayout { spacing: 20 Controls.LabelWithBackground { - text: qsTr("№ 4") + text: qsTr("# 4") Layout.preferredWidth: outputSettingsFrame.outputNumberSize Layout.preferredHeight: outputSettingsFrame.outputNumberSize } @@ -534,7 +552,7 @@ RowLayout { anchors.fill: parent Controls.SubtitleLabel { - text: qsTr("Current sensor value «0»") + text: qsTr("Current sensor value \"0\"") Layout.fillWidth: true Layout.columnSpan: 2 } @@ -549,7 +567,7 @@ RowLayout { Controls.Button { id: zeroSensorValueCalibrationButton - text: qsTr("Calibrate «0»") + text: qsTr("Calibrate \"0\"") Layout.fillWidth: true Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2 Layout.columnSpan: 2 @@ -561,6 +579,7 @@ RowLayout { Controls.OutlineButton { text: qsTr("Load settings from file") onClicked: loadFileDialog.open() + Layout.preferredWidth: 270 FileDialog { id: loadFileDialog @@ -576,6 +595,7 @@ RowLayout { Controls.OutlineButton { text: qsTr("Save settings to file") onClicked: saveFileDialog.open() + Layout.preferredWidth: 270 FileDialog { id: saveFileDialog @@ -637,7 +657,7 @@ RowLayout { } Controls.LinkLabel { - text: qsTr("Current sensor value «0»") + text: qsTr("Current sensor value \"0\"") onClicked: settingsFlickable.contentY = zeroSensorSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y } @@ -649,7 +669,7 @@ RowLayout { spacing: 15 Controls.OutlineButton { - text: qsTr("Read settings from file") + text: qsTr("Read default settings") Layout.fillWidth: true onClicked: BmsInterface.commands().getBMSconfDefault() } @@ -661,15 +681,6 @@ RowLayout { } Controls.OutlineButton { - text: qsTr("Write to non-volatile memory of BMS") - Layout.fillWidth: true - onClicked: { - writeValuesToConfig() - BmsInterface.commands().storeBMSConfig() - } - } - - Controls.Button { text: qsTr("Write current values to BMS") Layout.fillWidth: true onClicked: { @@ -678,10 +689,20 @@ RowLayout { } } + Controls.Button { + text: qsTr("Write to non-volatile memory of BMS") + Layout.fillWidth: true + onClicked: { + needWait(true, qsTr("The settings are written to non-volatile memory.\nWait, please.")) + writeValuesToConfig() + BmsInterface.commands().storeBMSConfig() + } + } + Layout.fillWidth: true } - Layout.maximumWidth: 320 + Layout.maximumWidth: 280 Layout.fillHeight: true } diff --git a/qml/Screens/CellMonitorScreen.qml b/qml/Screens/CellMonitorScreen.qml index 1da3318..88195e8 100644 --- a/qml/Screens/CellMonitorScreen.qml +++ b/qml/Screens/CellMonitorScreen.qml @@ -21,7 +21,7 @@ Item { Layout.fillWidth: true Controls.SubtitleLabel { - text: qsTr("№") + text: qsTr("#") color: Palette.tableHeaderTextColor anchors.centerIn: parent } diff --git a/qml/Screens/ConnectionDialog.qml b/qml/Screens/ConnectionDialog.qml index 7c7cbaf..449afc9 100644 --- a/qml/Screens/ConnectionDialog.qml +++ b/qml/Screens/ConnectionDialog.qml @@ -9,7 +9,7 @@ import Utils 1.0 Dialog { id: root title: qsTr("Connection screen") - width: 400 + width: 470 height: 320 modal: true closePolicy: Popup.CloseOnEscape @@ -79,7 +79,7 @@ Dialog { Connections { target: BmsInterface onPortConnectedChanged: { - connectButton.text = BmsInterface.isPortConnected() ? qsTr("Disconnect") : qsTr("Connect") + connectButton.text = Qt.binding(function() { return BmsInterface.isPortConnected() ? qsTr("Disconnect") : qsTr("Connect") }) serialBox.enabled = !BmsInterface.isPortConnected() } } diff --git a/qml/Screens/VisualizationScreen.qml b/qml/Screens/VisualizationScreen.qml index 7ae44d9..84b104f 100644 --- a/qml/Screens/VisualizationScreen.qml +++ b/qml/Screens/VisualizationScreen.qml @@ -37,27 +37,27 @@ ColumnLayout { Controls.TabButton { text: qsTr("Current") - width: bar.width / 6 * 0.9 - } - - Controls.TabButton { - text: qsTr("Battery temperature") - width: bar.width / 6 * 1.2 - } - - Controls.TabButton { - text: qsTr("BMS temperature") - width: bar.width / 6 * 1.2 - } - - Controls.TabButton { - text: qsTr("Cell voltage") width: bar.width / 6 * 0.8 } + Controls.TabButton { + text: qsTr("Battery temperature") + width: bar.width / 6 * 1.3 + } + + Controls.TabButton { + text: qsTr("BMS temperature") + width: bar.width / 6 * 1.1 + } + + Controls.TabButton { + text: qsTr("Cell voltage") + width: bar.width / 6 * 1 + } + Controls.TabButton { text: qsTr("Cell list") - width: bar.width / 6 * 0.9 + width: bar.width / 6 * 0.85 } Layout.fillWidth: true @@ -81,6 +81,8 @@ ColumnLayout { Controls.CheckBox { id: checkSeries checked: true + spacing: 10 + onCheckedChanged: { if (checked) { chartItem.series(modelData).color = seriesColor @@ -103,7 +105,7 @@ ColumnLayout { chartItem = ListView.view ? ListView.view.chartItem : parent.chartItem horizontal = !ListView.view seriesColor = chartItem.series(modelData).color - checkSeries.text = chartItem.series(modelData).name + checkSeries.text = Qt.binding(function(){ return chartItem.series(modelData).name }) } } } @@ -145,7 +147,7 @@ ColumnLayout { RowLayout { visible: horizontalLegend - spacing: 20 + spacing: 0 property Controls.ChartView chartItem: chart @@ -170,7 +172,7 @@ ColumnLayout { property Controls.ChartView chartItem: chart - Layout.preferredWidth: 180 + Layout.preferredWidth: 200 Layout.fillHeight: true } } @@ -362,6 +364,15 @@ ColumnLayout { } } + Connections { + target: Translator + onCurrentLanguageChanged: { + for (var i = 0; i < cellListLoader.item.chart.count; ++i) { + cellListLoader.item.chart.series(i).name = qsTr("Cell #") + (i + 1).toString() + } + } + } + Connections { target: BmsInterface.commands() @@ -461,38 +472,53 @@ ColumnLayout { Component.onCompleted: { voltageLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Voltage indicator"), voltageLoader.item.chart.xAxis, voltageLoader.item.chart.yAxis) + voltageLoader.item.chart.series(0).name = Qt.binding(function(){ return qsTr("Voltage indicator") }) voltageLoader.item.chart.axes[0].max = 10 voltageLoader.item.seriesCount = voltageLoader.item.chart.count + //////////////////////////////////////////////////////////////////////////////////////////////////////////// currentLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Current indicator"), currentLoader.item.chart.xAxis, currentLoader.item.chart.yAxis) + currentLoader.item.chart.series(0).name = Qt.binding(function(){ return qsTr("Current indicator") }) currentLoader.item.chart.axes[0].max = 10 currentLoader.item.seriesCount = currentLoader.item.chart.count + //////////////////////////////////////////////////////////////////////////////////////////////////////////// batteryTemperatureLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Maximum temperature"), batteryTemperatureLoader.item.chart.xAxis, batteryTemperatureLoader.item.chart.yAxis) batteryTemperatureLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Average temperature"), batteryTemperatureLoader.item.chart.xAxis, batteryTemperatureLoader.item.chart.yAxis) batteryTemperatureLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Minimum temperature"), batteryTemperatureLoader.item.chart.xAxis, batteryTemperatureLoader.item.chart.yAxis) + batteryTemperatureLoader.item.chart.series(0).name = Qt.binding(function(){ return qsTr("Maximum temperature") }) + batteryTemperatureLoader.item.chart.series(1).name = Qt.binding(function(){ return qsTr("Average temperature") }) + batteryTemperatureLoader.item.chart.series(2).name = Qt.binding(function(){ return qsTr("Minimum temperature") }) batteryTemperatureLoader.item.chart.axes[0].max = 10 batteryTemperatureLoader.item.seriesCount = batteryTemperatureLoader.item.chart.count + /////////////////////////////////////////////////////////////////////////////////////////////////////////// bmsTemperatureLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Maximum temperature"), bmsTemperatureLoader.item.chart.xAxis, bmsTemperatureLoader.item.chart.yAxis) bmsTemperatureLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Average temperature"), bmsTemperatureLoader.item.chart.xAxis, bmsTemperatureLoader.item.chart.yAxis) bmsTemperatureLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Minimum temperature"), bmsTemperatureLoader.item.chart.xAxis, bmsTemperatureLoader.item.chart.yAxis) + bmsTemperatureLoader.item.chart.series(0).name = Qt.binding(function(){ return qsTr("Maximum temperature") }) + bmsTemperatureLoader.item.chart.series(1).name = Qt.binding(function(){ return qsTr("Average temperature") }) + bmsTemperatureLoader.item.chart.series(2).name = Qt.binding(function(){ return qsTr("Minimum temperature") }) bmsTemperatureLoader.item.chart.axes[0].max = 10 bmsTemperatureLoader.item.seriesCount = bmsTemperatureLoader.item.chart.count + /////////////////////////////////////////////////////////////////////////////////////////////////////////// cellVoltageLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Maximum voltage"), cellVoltageLoader.item.chart.xAxis, cellVoltageLoader.item.chart.yAxis) cellVoltageLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Average voltage"), cellVoltageLoader.item.chart.xAxis, cellVoltageLoader.item.chart.yAxis) cellVoltageLoader.item.chart.createSeries(ChartView.SeriesTypeLine, qsTr("Minimum voltage"), cellVoltageLoader.item.chart.xAxis, cellVoltageLoader.item.chart.yAxis) + cellVoltageLoader.item.chart.series(0).name = Qt.binding(function(){ return qsTr("Maximum voltage") }) + cellVoltageLoader.item.chart.series(1).name = Qt.binding(function(){ return qsTr("Average voltage") }) + cellVoltageLoader.item.chart.series(2).name = Qt.binding(function(){ return qsTr("Minimum voltage") }) cellVoltageLoader.item.chart.axes[0].max = 10 cellVoltageLoader.item.seriesCount = cellVoltageLoader.item.chart.count } diff --git a/qml/Utils/Palette.qml b/qml/Utils/Palette.qml index 7f0a590..ac447fb 100644 --- a/qml/Utils/Palette.qml +++ b/qml/Utils/Palette.qml @@ -14,6 +14,7 @@ QtObject { property color alternativeBackgroundColor: "#009352" property color screenBackgroundColor: "#F7F8FC" property color tableHeaderBackgroundColor: "#F0F1F4" + property color selectedTextBackgroundColor: "#009150" property color borderColor: "#DFE0EB" diff --git a/qml/qml_icons.qrc b/qml/qml_icons.qrc index 42420ca..0c55858 100644 --- a/qml/qml_icons.qrc +++ b/qml/qml_icons.qrc @@ -14,5 +14,8 @@ Icons/close.svg Icons/info.svg Icons/warning.svg + Icons/english-flag.svg + Icons/italian-flag.svg + Icons/russian-flag.svg diff --git a/qml/qml_items.qrc b/qml/qml_items.qrc index 2f39209..ed200fa 100644 --- a/qml/qml_items.qrc +++ b/qml/qml_items.qrc @@ -5,8 +5,6 @@ Screens/AkbMonitorScreen.qml Screens/CellMonitorScreen.qml Controls/ComboBox.qml - Controls/PaneItem.qml - Controls/Label.qml Utils/Palette.qml Controls/qmldir Screens/qmldir @@ -38,5 +36,7 @@ Screens/MessageDialog.qml Screens/StatusPopup.qml Utils/MathHelper.qml + Controls/BusyIndicator.qml + Controls/MenuItemDelegate.qml diff --git a/translations/cubo_en.qm b/translations/cubo_en.qm new file mode 100644 index 0000000..9dad8df Binary files /dev/null and b/translations/cubo_en.qm differ diff --git a/translations/cubo_en.ts b/translations/cubo_en.ts new file mode 100644 index 0000000..fd3ca5b --- /dev/null +++ b/translations/cubo_en.ts @@ -0,0 +1,818 @@ + + + + + AkbMonitorScreen + + + Serial number + + + + + Battery charge level, % + + + + + Number of modules + + + + + Battery voltage, V + + + + + Number of cells + + + + + Nominal capacity, A/h + + + + + Actual capacity, A/h + + + + + Battery temperature, °C + + + + + BMS temperature, °C + + + + + Maximum cell voltage, V + + + + + Minimum cell voltage, V + + + + + Current + + + + + BMSInterface + + + + Reconnect + + + + + No ports found + + + + + Please specify the connection manually the first time you are connecting. + + + + + Not connected + + + + + Connected (serial) to %1 + + + + + Connected (TCP) to %1:%2 + + + + + Connected (BLE) to %1 + + + + + , limited mode + + + + + Invalid serial port: %1 + + + + + Serial port is not writable + + + + + Connect serial + + + + + Serial port support is not enabled in this build of ENNOID-BMS Tool. + + + + + Serial port error: + + + + + TCP Error + + + + + No firmware read response + + + + + Read Firmware Version + + + + + Could not read firmware version. Make sure that selected port really belongs to the ENNOID-BMS. + + + + + Not Supported Firmwares + + + + + This version of ENNOID-BMS Tool does not seem to have any supported firmwares. Something is probably wrong with the BMS configuration file. + + + + + + Error + + + + + + The firmware on the connected ENNOID-BMS is too old. Please update it using a programmer. + + + + + + Warning + + + + + The connected ENNOID-BMS has newer firmware than this version of the ENNOID-BMS Tool supports. It is recommended that you update the ENNOID-BMS Tool to the latest version. Alternatively, the firmware on the connected ENNOID-BMS can be downgraded in the firmware page. Until then, limited communication mode will be used where only the firmware can be changed. + + + + + The connected ENNOID-BMS has too old firmware. Since the connected ENNOID-BMS has firmware with bootloader support, it can be updated from the Firmware page. Until then, limited communication mode will be used where only the firmware can be changed. + + + + + Firmware version: %1.%2, Hardware: %3, UUID: %4 + + + + + BMS configuration updated + + + + + BMS configuration stored to Flash + + + + + BmsServiceScreen + + + Clear + + + + + Send + + + + + Help + + + + + BmsSettingsScreen + + + + Serial number + + + + + + Configuration + + + + + Number of boards + + + + + Number of cells + + + + + + SOC + + + + + Number of cells connected in parallel + + + + + Battery capacity + + + + + + Limits + + + + + Maximum charge current, A + + + + + Maximum load current, A + + + + + Maximum temperature, °C + + + + + + Cell configuration + + + + + Lower disable threshold, V + + + + + Upper disable threshold, V + + + + + Lower enable threshold (should be higher than disable), V + + + + + Upper enable threshold (should be higher than disable), V + + + + + + Balancing configuration + + + + + Balancing start voltage, V + + + + + Cell voltage delta to start balancing, V + + + + + Cell balancing interval, ms + + + + + + Output settings + + + + + # 1 + + + + + Use for storage management + + + + + # 2 + + + + + # 3 + + + + + # 4 + + + + + Read default settings + + + + + The settings are written to non-volatile memory. +Wait, please. + + + + + Normally closed + + + + + Change in value during SOC + + + + + + Closes at t<, °C + + + + + + Opens at t>, °C + + + + + + Current sensor value "0" + + + + + Calibrate "0" + + + + + Load settings from file + + + + + + Select configuration file + + + + + + Configuration files (*.xml) + + + + + + All files (*) + + + + + Save settings to file + + + + + Read current settings from BMS + + + + + Write to non-volatile memory of BMS + + + + + Write current values to BMS + + + + + CellMonitorScreen + + + # + + + + + Voltage + + + + + Balancing + + + + + V + + + + + Commands + + + BMS configuration is set + + + + + ConfigParams + + + + + + + OK + + + + + + tag <b>%1</b> not found + + + + + + + Could not open %1 for writing + + + + + + Could not open %1 for reading + + + + + ConnectionDialog + + + Connection screen + + + + + Select serial port + + + + + + Connect + + + + + Disconnect + + + + + DebugInformationScreen + + + Clear + + + + + MainWindow + + + Cubo Verde BMS tool + + + + + Hide menu + + + + + + AKB monitor + + + + + + Cell monitor + + + + + Configuration + + + + + + Visualization + + + + + History + + + + + BMS service + + + + + Connection + + + + + BMS settings + + + + + Information output + + + + + Terminal + + + + + + Disconnected + + + + + Serial number + + + + + Connected + + + + + MessageDialog + + + Ok + + + + + QObject + + + Autoconnect + + + + + Could not autoconnect. Make sure that the USB cable is plugged in and that the ENNOID-BMS is powered. + + + + + Translator + + + EN + + + + + RU + + + + + IT + + + + + Utility + + + <b>ENNOID-BMS Tool V%1</b><br>&copy; Kevin Dionne 2019<br><a href="mailto:kevin.dionne@ennoid.me">kevin.dionne@ennoid.me</a><br><a href="https://www.ennoid.me/">https://www.ennoid.me/</a><br>Based on: DieBieMS-tool<br><br><b>DieBieMS Tool </b><br>&copy; Danny Bokma 2018<br><a href="mailto:bms@diebie.nl">bms@diebie.nl</a><br><a href="https://diebie.nl/">https://diebie.nl/</a><br>Based on: VESC-tool<br><br><b>VESC Tool </b><br>&copy; Benjamin Vedder 2018<br><a href="mailto:benjamin@vedder.se">benjamin@vedder.se</a><br><a href="https://vesc-project.com/">https://vesc-project.com/</a><br><br> + + + + + VisualizationScreen + + + Voltage + + + + + Current + + + + + Battery temperature + + + + + BMS temperature + + + + + Cell voltage + + + + + Cell list + + + + + + + + + + Time, s + + + + + + + Voltage, V + + + + + Current, A + + + + + + Temperature, °C + + + + + Pause data collection + + + + + Resume data collection + + + + + Clear data + + + + + Reset zoom + + + + + + Cell # + + + + + + Voltage indicator + + + + + + Current indicator + + + + + + + + Maximum temperature + + + + + + + + Average temperature + + + + + + + + Minimum temperature + + + + + + Maximum voltage + + + + + + Average voltage + + + + + + Minimum voltage + + + + diff --git a/translations/cubo_it.qm b/translations/cubo_it.qm new file mode 100644 index 0000000..9dad8df Binary files /dev/null and b/translations/cubo_it.qm differ diff --git a/translations/cubo_it.ts b/translations/cubo_it.ts new file mode 100644 index 0000000..e384e53 --- /dev/null +++ b/translations/cubo_it.ts @@ -0,0 +1,818 @@ + + + + + AkbMonitorScreen + + + Serial number + + + + + Battery charge level, % + + + + + Number of modules + + + + + Battery voltage, V + + + + + Number of cells + + + + + Nominal capacity, A/h + + + + + Actual capacity, A/h + + + + + Battery temperature, °C + + + + + BMS temperature, °C + + + + + Maximum cell voltage, V + + + + + Minimum cell voltage, V + + + + + Current + + + + + BMSInterface + + + + Reconnect + + + + + No ports found + + + + + Please specify the connection manually the first time you are connecting. + + + + + Not connected + + + + + Connected (serial) to %1 + + + + + Connected (TCP) to %1:%2 + + + + + Connected (BLE) to %1 + + + + + , limited mode + + + + + Invalid serial port: %1 + + + + + Serial port is not writable + + + + + Connect serial + + + + + Serial port support is not enabled in this build of ENNOID-BMS Tool. + + + + + Serial port error: + + + + + TCP Error + + + + + No firmware read response + + + + + Read Firmware Version + + + + + Could not read firmware version. Make sure that selected port really belongs to the ENNOID-BMS. + + + + + Not Supported Firmwares + + + + + This version of ENNOID-BMS Tool does not seem to have any supported firmwares. Something is probably wrong with the BMS configuration file. + + + + + + Error + + + + + + The firmware on the connected ENNOID-BMS is too old. Please update it using a programmer. + + + + + + Warning + + + + + The connected ENNOID-BMS has newer firmware than this version of the ENNOID-BMS Tool supports. It is recommended that you update the ENNOID-BMS Tool to the latest version. Alternatively, the firmware on the connected ENNOID-BMS can be downgraded in the firmware page. Until then, limited communication mode will be used where only the firmware can be changed. + + + + + The connected ENNOID-BMS has too old firmware. Since the connected ENNOID-BMS has firmware with bootloader support, it can be updated from the Firmware page. Until then, limited communication mode will be used where only the firmware can be changed. + + + + + Firmware version: %1.%2, Hardware: %3, UUID: %4 + + + + + BMS configuration updated + + + + + BMS configuration stored to Flash + + + + + BmsServiceScreen + + + Clear + + + + + Send + + + + + Help + + + + + BmsSettingsScreen + + + + Serial number + + + + + + Configuration + + + + + Number of boards + + + + + Number of cells + + + + + + SOC + + + + + Number of cells connected in parallel + + + + + Battery capacity + + + + + + Limits + + + + + Maximum charge current, A + + + + + Maximum load current, A + + + + + Maximum temperature, °C + + + + + + Cell configuration + + + + + Lower disable threshold, V + + + + + Upper disable threshold, V + + + + + Lower enable threshold (should be higher than disable), V + + + + + Upper enable threshold (should be higher than disable), V + + + + + + Balancing configuration + + + + + Balancing start voltage, V + + + + + Cell voltage delta to start balancing, V + + + + + Cell balancing interval, ms + + + + + + Output settings + + + + + # 1 + + + + + Use for storage management + + + + + # 2 + + + + + # 3 + + + + + # 4 + + + + + Read default settings + + + + + The settings are written to non-volatile memory. +Wait, please. + + + + + Normally closed + + + + + Change in value during SOC + + + + + + Closes at t<, °C + + + + + + Opens at t>, °C + + + + + + Current sensor value "0" + + + + + Calibrate "0" + + + + + Load settings from file + + + + + + Select configuration file + + + + + + Configuration files (*.xml) + + + + + + All files (*) + + + + + Save settings to file + + + + + Read current settings from BMS + + + + + Write to non-volatile memory of BMS + + + + + Write current values to BMS + + + + + CellMonitorScreen + + + # + + + + + Voltage + + + + + Balancing + + + + + V + + + + + Commands + + + BMS configuration is set + + + + + ConfigParams + + + + + + + OK + + + + + + tag <b>%1</b> not found + + + + + + + Could not open %1 for writing + + + + + + Could not open %1 for reading + + + + + ConnectionDialog + + + Connection screen + + + + + Select serial port + + + + + + Connect + + + + + Disconnect + + + + + DebugInformationScreen + + + Clear + + + + + MainWindow + + + Cubo Verde BMS tool + + + + + Hide menu + + + + + + AKB monitor + + + + + + Cell monitor + + + + + Configuration + + + + + + Visualization + + + + + History + + + + + BMS service + + + + + Connection + + + + + BMS settings + + + + + Information output + + + + + Terminal + + + + + + Disconnected + + + + + Serial number + + + + + Connected + + + + + MessageDialog + + + Ok + + + + + QObject + + + Autoconnect + + + + + Could not autoconnect. Make sure that the USB cable is plugged in and that the ENNOID-BMS is powered. + + + + + Translator + + + EN + + + + + RU + + + + + IT + + + + + Utility + + + <b>ENNOID-BMS Tool V%1</b><br>&copy; Kevin Dionne 2019<br><a href="mailto:kevin.dionne@ennoid.me">kevin.dionne@ennoid.me</a><br><a href="https://www.ennoid.me/">https://www.ennoid.me/</a><br>Based on: DieBieMS-tool<br><br><b>DieBieMS Tool </b><br>&copy; Danny Bokma 2018<br><a href="mailto:bms@diebie.nl">bms@diebie.nl</a><br><a href="https://diebie.nl/">https://diebie.nl/</a><br>Based on: VESC-tool<br><br><b>VESC Tool </b><br>&copy; Benjamin Vedder 2018<br><a href="mailto:benjamin@vedder.se">benjamin@vedder.se</a><br><a href="https://vesc-project.com/">https://vesc-project.com/</a><br><br> + + + + + VisualizationScreen + + + Voltage + + + + + Current + + + + + Battery temperature + + + + + BMS temperature + + + + + Cell voltage + + + + + Cell list + + + + + + + + + + Time, s + + + + + + + Voltage, V + + + + + Current, A + + + + + + Temperature, °C + + + + + Pause data collection + + + + + Resume data collection + + + + + Clear data + + + + + Reset zoom + + + + + + Cell # + + + + + + Voltage indicator + + + + + + Current indicator + + + + + + + + Maximum temperature + + + + + + + + Average temperature + + + + + + + + Minimum temperature + + + + + + Maximum voltage + + + + + + Average voltage + + + + + + Minimum voltage + + + + diff --git a/translations/cubo_ru.qm b/translations/cubo_ru.qm new file mode 100644 index 0000000..04eeb25 Binary files /dev/null and b/translations/cubo_ru.qm differ diff --git a/translations/cubo_ru.ts b/translations/cubo_ru.ts new file mode 100644 index 0000000..e830087 --- /dev/null +++ b/translations/cubo_ru.ts @@ -0,0 +1,827 @@ + + + + + AkbMonitorScreen + + + Serial number + Серийный номер + + + + Battery charge level, % + Степень заряда батареи, % + + + + Number of modules + Количество модулей + + + + Battery voltage, V + Напряжение батареи, В + + + + Number of cells + Количество ячеек + + + + Nominal capacity, A/h + Номинальная ёмкость, А/ч + + + + Actual capacity, A/h + Реальная ёмкость, А/ч + + + + Battery temperature, °C + Температура батареи, °C + + + + BMS temperature, °C + Температура BMS, °C + + + + Maximum cell voltage, V + Максимальное напряжение на ячейке, В + + + + Minimum cell voltage, V + Минимальное напряжение на ячейке, В + + + + Current + Ток + + + + BMSInterface + + + + Reconnect + Переподключение + + + + No ports found + Порты не найдены + + + + Please specify the connection manually the first time you are connecting. + Укажите тип подключения вручную при первом подключении. + + + + Not connected + Не подключено + + + + Connected (serial) to %1 + Подключено (последовательный порт) к %1 + + + + Connected (TCP) to %1:%2 + Подключено (TCP) к %1:%2 + + + + Connected (BLE) to %1 + Подключено (BLE) к %1 + + + + , limited mode + , ограниченный режим + + + + Invalid serial port: %1 + Недопустимый последовательный порт: %1 + + + + Serial port is not writable + Последовательный порт недоступен для записи + + + + Connect serial + Подключение последовательного порта + + + + Serial port support is not enabled in this build of ENNOID-BMS Tool. + Поддержка последовательного порта не включена в этой сборке утилиты. + + + + Serial port error: + Ошибка последовательного порта: + + + + TCP Error + Ошибка TCP + + + + No firmware read response + Нет ответа на чтение прошивки + + + + Read Firmware Version + Чтение версии прошивки + + + + Could not read firmware version. Make sure that selected port really belongs to the ENNOID-BMS. + Не удалось прочитать версию прошивки. Убедитесь, что выбранный порт действительно принадлежит ENNOID-BMS. + + + + Not Supported Firmwares + Не поддерживаемые прошивки + + + + This version of ENNOID-BMS Tool does not seem to have any supported firmwares. Something is probably wrong with the BMS configuration file. + Эта версия утилиты не имеет поддерживаемых прошивок. Вероятно, что-то не так с файлом конфигурации BMS. + + + + + Error + Ошибка + + + + + The firmware on the connected ENNOID-BMS is too old. Please update it using a programmer. + Прошивка подключенного ENNOID-BMS устарела. Пожалуйста, обновите его с помощью программатора. + + + + + Warning + Внимание + + + + The connected ENNOID-BMS has newer firmware than this version of the ENNOID-BMS Tool supports. It is recommended that you update the ENNOID-BMS Tool to the latest version. Alternatively, the firmware on the connected ENNOID-BMS can be downgraded in the firmware page. Until then, limited communication mode will be used where only the firmware can be changed. + Подключенный ENNOID-BMS имеет более новую прошивку, чем поддерживает эта версия инструмента ENNOID-BMS. Рекомендуется обновить инструмент ENNOID-BMS до последней версии. Кроме того, прошивку подключенного ENNOID-BMS можно понизить на странице прошивки. До тех пор будет использоваться ограниченный режим связи, при котором можно будет изменить только прошивку. + + + + The connected ENNOID-BMS has too old firmware. Since the connected ENNOID-BMS has firmware with bootloader support, it can be updated from the Firmware page. Until then, limited communication mode will be used where only the firmware can be changed. + Подключенный ENNOID-BMS имеет слишком старую прошивку. Поскольку подключенный ENNOID-BMS имеет встроенное ПО с поддержкой загрузчика, его можно обновить со страницы встроенного ПО. До тех пор будет использоваться ограниченный режим связи, при котором можно будет изменить только прошивку. + + + + Firmware version: %1.%2, Hardware: %3, UUID: %4 + Версия прошивки: %1.%2, Оборудование: %3, UUID: %4 + + + + BMS configuration updated + Конфигурация BMS обновлена + + + + BMS configuration stored to Flash + Конфигурация BMS сохранена во флэш-памяти + + + + BmsServiceScreen + + + Clear + Очистить + + + + Send + Отправить + + + + Help + Помощь + + + + BmsSettingsScreen + + + + Serial number + Серийный номер + + + + + Configuration + Конфигурация + + + + Number of boards + Количество плат + + + + Number of cells + Количество ячеек + + + + + SOC + SOC + + + + Number of cells connected in parallel + Количество параллельно включенных ячеек + + + + Battery capacity + Ёмкость батареи + + + + + Limits + Ограничения + + + + Maximum charge current, A + Максимальный ток заряда, A + + + + Maximum load current, A + Максимальный ток нагрузки, A + + + + Maximum temperature, °C + Максимальная температура, C + + + + + Cell configuration + Конфигурация ячеек + + + + Lower disable threshold, V + Нижний порог отключения, В + + + + Upper disable threshold, V + Верхний порог отключения, В + + + + Lower enable threshold (should be higher than disable), V + Нижний порог включения (должен быть выше отключения), В + + + + Upper enable threshold (should be higher than disable), V + Верхний порог включения (должен быть выше отключения), В + + + + + Balancing configuration + Конфигурация балансировки + + + + Balancing start voltage, V + Напряжение старта балансировки, В + + + + Cell voltage delta to start balancing, V + Дельта напряжения ячеек для старта балансировки, В + + + + Cell balancing interval, ms + Интервал балансировки ячейки, мс + + + + + Output settings + Настройка выходов + + + + # 1 + № 1 + + + + Use for storage management + Использовать для управления ЗУ + + + + # 2 + № 2 + + + + # 3 + № 3 + + + + # 4 + № 4 + + + + Read default settings + Загрузить настройки по-умолчанию + + + + The settings are written to non-volatile memory. +Wait, please. + Выполняется запись настроек в энергонезависимую память. +Пожалуйста подождите. + + + + Normally closed + Нормально замкнут + + + + Change in value during SOC + Изменение значения при SOC + + + + + Closes at t<, °C + Замыкается при t<, °C + + + + + Opens at t>, °C + Размыкается при t>, °C + + + + + Current sensor value "0" + Значение датчика тока «0» + + + + Calibrate "0" + Калибровать «0» + + + + Load settings from file + Загрузить настройки из файла + + + + + Select configuration file + Выберите файл конфигурации + + + + + Configuration files (*.xml) + Файлы конфигурации (*.xml) + + + + + All files (*) + Все файлы (*) + + + + Save settings to file + Сохранить настройки в файл + + + Read settings from file + Загрузить настройки из файла + + + + Read current settings from BMS + Загрузить текущие настройки из BMS + + + + Write to non-volatile memory of BMS + Записать в энергонезависимую память BMS + + + + Write current values to BMS + Записать текущие значения в BMS + + + + CellMonitorScreen + + + # + + + + + Voltage + Напряжение + + + + Balancing + Балансировка + + + + V + V + + + + Commands + + + BMS configuration is set + Конфигурация BMS установлена + + + + ConfigParams + + + + + + + OK + Ок + + + + + tag <b>%1</b> not found + тэг <b>%1</b> не найден + + + + + + Could not open %1 for writing + Не удалось открыть %1 для записи + + + + + Could not open %1 for reading + Не удалось открыть %1 для чтения + + + + ConnectionDialog + + + Connection screen + Экран подключения + + + + Select serial port + Выберите последовательный порт + + + + + Connect + Подключение + + + + Disconnect + Отключение + + + + DebugInformationScreen + + + Clear + Очистить + + + + MainWindow + + + Cubo Verde BMS tool + Cubo Verde утилита для BMS + + + + Hide menu + Скрыть меню + + + + + AKB monitor + Монитор АКБ + + + + + Cell monitor + Монитор ячеек + + + + Configuration + Конфигурация + + + + + Visualization + Визуализация + + + + History + История + + + + BMS service + Сервис BMS + + + + Connection + Подключение + + + + BMS settings + Настройка BMS + + + + Information output + Вывод информации + + + + Terminal + Терминал + + + Exit + Выход + + + + + Disconnected + Отключено + + + + Serial number + Серийный номер + + + + Connected + Подключено + + + + MessageDialog + + + Ok + Ок + + + + QObject + + + Autoconnect + Автоподключение + + + + Could not autoconnect. Make sure that the USB cable is plugged in and that the ENNOID-BMS is powered. + Не удалось автоматически подключиться. Убедитесь, что USB-кабель подключен и ENNOID-BMS включен. + + + + Translator + + + EN + + + + + RU + + + + + IT + + + + + Utility + + + <b>ENNOID-BMS Tool V%1</b><br>&copy; Kevin Dionne 2019<br><a href="mailto:kevin.dionne@ennoid.me">kevin.dionne@ennoid.me</a><br><a href="https://www.ennoid.me/">https://www.ennoid.me/</a><br>Based on: DieBieMS-tool<br><br><b>DieBieMS Tool </b><br>&copy; Danny Bokma 2018<br><a href="mailto:bms@diebie.nl">bms@diebie.nl</a><br><a href="https://diebie.nl/">https://diebie.nl/</a><br>Based on: VESC-tool<br><br><b>VESC Tool </b><br>&copy; Benjamin Vedder 2018<br><a href="mailto:benjamin@vedder.se">benjamin@vedder.se</a><br><a href="https://vesc-project.com/">https://vesc-project.com/</a><br><br> + + + + + VisualizationScreen + + + Voltage + Напряжение + + + + Current + Ток + + + + Battery temperature + Температура батареи + + + + BMS temperature + Температура BMS + + + + Cell voltage + Вольтаж ячейки + + + + Cell list + Список ячеек + + + + + + + + + Time, s + Время, c + + + + + + Voltage, V + Напряжение, В + + + + Current, A + Ток, А + + + + + Temperature, °C + Температура, °C + + + + Pause data collection + Приостановить сбор данных + + + + Resume data collection + Продолжить сбор данных + + + + Clear data + Очистить данные + + + + Reset zoom + Сбросить масштаб + + + + + Cell # + Ячейка № + + + + + Voltage indicator + Показатель вольтажа + + + + + Current indicator + Показатель тока + + + + + + + Maximum temperature + Максимальная температура + + + + + + + Average temperature + Средняя температура + + + + + + + Minimum temperature + Минимальная температура + + + + + Maximum voltage + Максимальное напряжение + + + + + Average voltage + Среднее напряжение + + + + + Minimum voltage + Минимальное напряжение + + + diff --git a/translations/translations.qrc b/translations/translations.qrc new file mode 100644 index 0000000..37f042f --- /dev/null +++ b/translations/translations.qrc @@ -0,0 +1,7 @@ + + + cubo_en.qm + cubo_it.qm + cubo_ru.qm + + diff --git a/translator.cpp b/translator.cpp new file mode 100644 index 0000000..54aec58 --- /dev/null +++ b/translator.cpp @@ -0,0 +1,87 @@ +#include "translator.h" + +#include +#include +#include +#include +#include + +Translator::Translator(QQmlEngine *engine, QObject *parent) : + QObject(parent), + mQmlEngine(engine), + mCurrentTranslator(new QTranslator(this)) +{ + mNamesMap = + { + {Language::English, tr("EN")}, + {Language::Russian, tr("RU")}, + {Language::Italian, tr("IT")} + }; + + mIconsMap = + { + {Language::English, "qrc:/Icons/english-flag.svg"}, + {Language::Russian, "qrc:/Icons/russian-flag.svg"}, + {Language::Italian, "qrc:/Icons/italian-flag.svg"} + }; + + mTranslationsMap = + { + {Language::English, ":/cubo_en.qm"}, + {Language::Russian, ":/cubo_ru.qm"}, + {Language::Italian, ":/cubo_it.qm"} + }; + + QCoreApplication::installTranslator(mCurrentTranslator); + + if (QLocale::system().language() == QLocale::Russian) + { + setCurrentLanguage(Language::Russian); + } + else if (QLocale::system().language() == QLocale::Italian) + { + setCurrentLanguage(Language::Italian); + } + else + { + setCurrentLanguage(Language::English); + } +} + +QString Translator::languageName(Language language) const +{ + return mNamesMap.value(language); +} + +QString Translator::languageIcon(Language language) const +{ + return mIconsMap.value(language); +} + +Translator::Language Translator::currentLanguage() const +{ + return mCurrentLanguage; +} + +void Translator::setCurrentLanguage(Language language) +{ + if (mCurrentTranslator->load(mTranslationsMap.value(language))) + { + QTimer::singleShot(0, this, [this]{ mQmlEngine->retranslate();} ); + } + + mCurrentLanguage = language; + emit currentLanguageChanged(); + emit currentLanguageNameChanged(); + emit currentLanguageIconChanged(); +} + +QString Translator::currentLanguageName() const +{ + return languageName(mCurrentLanguage); +} + +QString Translator::currentLanguageIcon() const +{ + return languageIcon(mCurrentLanguage); +} diff --git a/translator.h b/translator.h new file mode 100644 index 0000000..0e23e3b --- /dev/null +++ b/translator.h @@ -0,0 +1,53 @@ +#ifndef TRANSLATOR_H +#define TRANSLATOR_H + +#include +#include + +class QQmlEngine; +class QTranslator; + +class Translator : public QObject +{ + Q_OBJECT + + Q_PROPERTY(Language currentLanguage READ currentLanguage WRITE setCurrentLanguage NOTIFY currentLanguageChanged) + Q_PROPERTY(QString currentLanguageName READ currentLanguageName NOTIFY currentLanguageNameChanged) + Q_PROPERTY(QString currentLanguageIcon READ currentLanguageIcon NOTIFY currentLanguageNameChanged) + +public: + enum class Language { + English, + Russian, + Italian + }; + Q_ENUM(Language) + + explicit Translator(QQmlEngine* engine, QObject *parent = nullptr); + +public slots: + QString languageName(Language language) const; + QString languageIcon(Language language) const; + +public: + Language currentLanguage() const; + void setCurrentLanguage(Language language); + + QString currentLanguageName() const; + QString currentLanguageIcon() const; + +signals: + void currentLanguageChanged(); + void currentLanguageNameChanged(); + void currentLanguageIconChanged(); + +private: + Language mCurrentLanguage = Language::English; + QQmlEngine* mQmlEngine = nullptr; + QTranslator* mCurrentTranslator = nullptr; + QMap mNamesMap; + QMap mIconsMap; + QMap mTranslationsMap; +}; + +#endif // TRANSLATOR_H