/* Original copyright 2018 Benjamin Vedder benjamin@vedder.se and the VESC Tool project ( https://github.com/vedderb/vesc_tool ) Forked to: Copyright 2018 Danny Bokma github@diebie.nl (https://github.com/DieBieEngineering/DieBieMS-Tool) Now forked to: Copyright 2019 - 2020 Kevin Dionne kevin.dionne@ennoid.me (https://github.com/EnnoidMe/ENNOID-BMS-Tool) This file is part of ENNOID-BMS Tool. ENNOID-BMS Tool is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. ENNOID-BMS Tool is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "parametereditor.h" #include "ui_parametereditor.h" #include #include #include #include #include #include ParameterEditor::ParameterEditor(QWidget *parent) : QMainWindow(parent), ui(new Ui::ParameterEditor) { ui->setupUi(this); setEditorValues("new_parameter", ConfigParam()); mStatusInfoTime = 0; mStatusLabel = new QLabel(this); ui->statusBar->addPermanentWidget(mStatusLabel); mTimer = new QTimer(this); mTimer->start(20); connect(mTimer, SIGNAL(timeout()), this, SLOT(timerSlot())); } ParameterEditor::~ParameterEditor() { delete ui; } void ParameterEditor::setParams(const ConfigParams *params) { QStringList paramList = params->getParamOrder(); mParams.clearParams(); mParams.setSerializeOrder(params->getSerializeOrder()); for (int i = 0;i < paramList.size();i++) { QString name = paramList.at(i); mParams.addParam(name, params->getParamCopy(name)); } mParams.setUpdatesEnabled(false); showStatusInfo(tr("Parameters Loaded"), true); updateUi(); } void ParameterEditor::timerSlot() { // Update status label if (mStatusInfoTime) { mStatusInfoTime--; if (!mStatusInfoTime) { mStatusLabel->setStyleSheet(qApp->styleSheet()); } } else { if (!mStatusLabel->text().isEmpty()) { mStatusLabel->clear(); } } } void ParameterEditor::on_paramRemoveButton_clicked() { int row = ui->paramList->currentRow(); if (row >= 0) { mParams.deleteParam(ui->paramList->item(row)->text()); delete ui->paramList->takeItem(row); } } void ParameterEditor::on_paramDownButton_clicked() { int row = ui->paramList->currentRow(); QStringList order = mParams.getParamOrder(); if (row >= 0 && row < (order.size() - 1)) { QString name = order.at(row); order.removeAt(row); order.insert(row + 1, name); mParams.setParamOrder(order); updateUi(); ui->paramList->setCurrentRow(row + 1); } } void ParameterEditor::on_paramUpButton_clicked() { int row = ui->paramList->currentRow(); QStringList order = mParams.getParamOrder(); if (row >= 1) { QString name = order.at(row); order.removeAt(row); order.insert(row - 1, name); mParams.setParamOrder(order); updateUi(); ui->paramList->setCurrentRow(row - 1); } } void ParameterEditor::on_paramOpenButton_clicked() { QListWidgetItem *item = ui->paramList->currentItem(); QString selected; if (item) { selected = item->text(); } ConfigParam *p = mParams.getParam(selected); if (p) { setEditorValues(selected, *p); if (ui->previewTable->rowCount() > 0) { ui->previewTable->removeRow(0); } if (p->type != CFG_T_UNDEFINED) { ui->previewTable->addParamRow(&mParams, selected); } } } void ParameterEditor::on_paramSaveButton_clicked() { if (ui->nameEdit->text().contains(" ")) { QMessageBox::warning(this, tr("Save Parameter"), tr("Spaces are not allowed in the name.")); return; } if (ui->nameEdit->text().isEmpty()) { QMessageBox::warning(this, tr("Save Parameter"), tr("Name is empty.")); return; } QString name; ConfigParam p; name = getEditorValues(&p); if (mParams.hasParam(name)) { *mParams.getParam(name) = p; showStatusInfo(tr("Parameter updated: %1").arg(name), true); } else { mParams.addParam(name, p); int row = ui->paramList->currentRow(); QStringList order = mParams.getParamOrder(); order.removeLast(); if (row < 0) { row = order.size(); } else { row += 1; } order.insert(row, name); mParams.setParamOrder(order); updateUi(); ui->paramList->setCurrentRow(row); showStatusInfo(tr("New parameter added: %1").arg(name), true); } if (ui->previewTable->rowCount() > 0) { ui->previewTable->removeRow(0); } if (p.type != CFG_T_QSTRING && p.type != CFG_T_UNDEFINED) { ui->previewTable->addParamRow(&mParams, name); } } void ParameterEditor::on_paramResetButton_clicked() { setEditorValues("new_parameter", ConfigParam()); } void ParameterEditor::on_serRemoveButton_clicked() { int row = ui->paramSerialOrderList->currentRow(); if (row >= 0) { QStringList order = mParams.getSerializeOrder(); order.removeAt(row); mParams.setSerializeOrder(order); delete ui->paramSerialOrderList->takeItem(row); } } void ParameterEditor::on_serDownButton_clicked() { int row = ui->paramSerialOrderList->currentRow(); QStringList order = mParams.getSerializeOrder(); if (row >= 0 && row < (order.size() - 1)) { QString name = order.at(row); order.removeAt(row); order.insert(row + 1, name); mParams.setSerializeOrder(order); updateUi(); ui->paramSerialOrderList->setCurrentRow(row + 1); } } void ParameterEditor::on_serUpButton_clicked() { int row = ui->paramSerialOrderList->currentRow(); QStringList order = mParams.getSerializeOrder(); if (row >= 1) { QString name = order.at(row); order.removeAt(row); order.insert(row - 1, name); mParams.setSerializeOrder(order); updateUi(); ui->paramSerialOrderList->setCurrentRow(row - 1); } } void ParameterEditor::on_serAddButton_clicked() { QListWidgetItem *item = ui->paramList->currentItem(); QString selected = ""; if (item) { selected = item->text(); } bool ok; QString name = QInputDialog::getText(this, tr("Add to Serialization Order"), tr("Parameter Name"), QLineEdit::Normal, selected, &ok); if (ok) { if (name.contains(" ")) { QMessageBox::warning(this, tr("Add"), tr("Spaces are not allowed in the name.")); return; } if (name.isEmpty()) { QMessageBox::warning(this, tr("Add"), tr("Name is empty.")); return; } int row = ui->paramSerialOrderList->currentRow(); QStringList order = mParams.getSerializeOrder(); if (row < 0 || row >= order.size()) { row = order.size() - 1; } order.insert(row + 1, name); mParams.setSerializeOrder(order); updateUi(); } } void ParameterEditor::on_paramList_doubleClicked(const QModelIndex &index) { (void)index; on_paramOpenButton_clicked(); } void ParameterEditor::on_enumAddButton_clicked() { addEnum(tr("")); } void ParameterEditor::on_enumRemoveButton_clicked() { int row = ui->enumList->currentRow(); if (row >= 0) { delete ui->enumList->takeItem(row); } } void ParameterEditor::on_enumMoveUpButton_clicked() { int row = ui->enumList->currentRow(); if (row >= 1) { QListWidgetItem *item = ui->enumList->takeItem(row); ui->enumList->insertItem(row - 1, item); ui->enumList->setCurrentRow(row - 1); } } void ParameterEditor::on_enumMoveDownButton_clicked() { int row = ui->enumList->currentRow(); if (row >= 0 && row < (ui->enumList->count() - 1)) { QListWidgetItem *item = ui->enumList->takeItem(row); ui->enumList->insertItem(row + 1, item); ui->enumList->setCurrentRow(row + 1); } } void ParameterEditor::on_actionLoad_XML_triggered() { QString path; path = QFileDialog::getOpenFileName(this, tr("Choose parameter file to load"), ".", tr("Xml files (*.xml)")); if (path.isNull()) { return; } bool res = mParams.loadParamsXml(path); if (!res) { QMessageBox::information(this, tr("Load Parameters"), tr("Could not load parameters:
" "%1").arg(mParams.xmlStatus())); } else { showStatusInfo(tr("Configuration Loaded"), true); } updateUi(); } void ParameterEditor::on_actionSave_XML_as_triggered() { QString path; path = QFileDialog::getSaveFileName(this, tr("Choose where to save the parameter XML file"), ".", tr("Xml files (*.xml)")); if (path.isNull()) { return; } if (!path.toLower().endsWith(".xml")) { path += ".xml"; } bool res = mParams.saveParamsXml(path); if (!res) { QMessageBox::information(this, tr("Save Parameters"), tr("Could not save parameters:
" "%1").arg(mParams.xmlStatus())); } else { showStatusInfo(tr("Configuration Saved"), true); } } void ParameterEditor::on_actionDeleteAll_triggered() { QMessageBox::StandardButton reply; reply = QMessageBox::question(this, tr("Delete All"), tr("Are you sure that you want to delete all data?"), QMessageBox::Yes|QMessageBox::No); if (reply == QMessageBox::Yes) { mParams.clearAll(); updateUi(); showStatusInfo(tr("Configuration Deleted"), true); } } void ParameterEditor::updateUi() { ui->paramList->clear(); ui->paramList->addItems(mParams.getParamOrder()); ui->paramSerialOrderList->clear(); ui->paramSerialOrderList->addItems(mParams.getSerializeOrder()); } void ParameterEditor::setEditorValues(QString name, ConfigParam p) { ui->nameEdit->setText(name); ui->longNameEdit->setText(p.longName); ui->typeBox->setCurrentIndex(p.type); ui->transmittableBox->setCurrentIndex(p.transmittable ? 0 : 1); ui->descriptionEdit->document()->setHtml(p.description); ui->cDefineEdit->setText(p.cDefine); // Double ui->doubleEditorScaleBox->setValue(p.editorScale); ui->doubleEditPercentageBox->setChecked(p.editAsPercentage); ui->doubleDecimalsBox->setValue(p.editorDecimalsDouble); ui->doubleMaxBox->setValue(p.maxDouble); ui->doubleMinBox->setValue(p.minDouble); ui->doubleShowDisplayBox->setChecked(p.showDisplay); ui->doubleStep->setValue(p.stepDouble); ui->doubleSuffixEdit->setText(p.suffix); double val = p.vTxDoubleScale; double power = floor(log10(val)); val /= pow(10, power); ui->doubleTxScaleBaseBox->setValue(val); ui->doubleTxScaleExpBox->setValue(power); if (p.vTx == VESC_TX_DOUBLE16) { ui->doubleTxTypeBox->setCurrentIndex(0); } else if (p.vTx == VESC_TX_DOUBLE32) { ui->doubleTxTypeBox->setCurrentIndex(1); } else { ui->doubleTxTypeBox->setCurrentIndex(2); } ui->doubleValBox->setValue(p.valDouble); // Int ui->intEditorScaleBox->setValue(p.editorScale); ui->intEditPercentageBox->setChecked(p.editAsPercentage); ui->intMaxBox->setValue(p.maxInt); ui->intMinBox->setValue(p.minInt); ui->intShowDisplayBox->setChecked(p.showDisplay); ui->intStepBox->setValue(p.stepInt); ui->intSuffixEdit->setText(p.suffix); if (p.vTx <= 6 && p.vTx > 0) { ui->intTxTypeBox->setCurrentIndex(p.vTx - 1); } ui->intValBox->setValue(p.valInt); // String ui->stringValEdit->setText(p.valString); // Enum ui->enumList->clear(); for (int i = 0;i < p.enumNames.size();i++) { addEnum(p.enumNames.at(i)); } if (p.valInt >= 0 && p.valInt < p.enumNames.size()) { ui->enumList->setCurrentRow(p.valInt); } // Bool ui->boolBox->setCurrentIndex(p.valInt > 0 ? 1 : 0); } QString ParameterEditor::getEditorValues(ConfigParam *p) { if (p) { p->longName = ui->longNameEdit->text(); p->type = (CFG_T)ui->typeBox->currentIndex(); p->transmittable = ui->transmittableBox->currentIndex() == 0; p->description = ui->descriptionEdit->toHtmlNoFontSize(); p->cDefine = ui->cDefineEdit->text(); switch (p->type) { case CFG_T_DOUBLE: p->editorScale = ui->doubleEditorScaleBox->value(); p->editAsPercentage = ui->doubleEditPercentageBox->isChecked(); p->editorDecimalsDouble = ui->doubleDecimalsBox->value(); p->maxDouble = ui->doubleMaxBox->value(); p->minDouble = ui->doubleMinBox->value(); p->showDisplay = ui->doubleShowDisplayBox->isChecked(); p->stepDouble = ui->doubleStep->value(); p->suffix = ui->doubleSuffixEdit->text(); p->vTxDoubleScale = ui->doubleTxScaleBaseBox->value() * pow(10, ui->doubleTxScaleExpBox->value()); p->vTx = (VESC_TX_T)(ui->doubleTxTypeBox->currentIndex() + 7); p->valDouble = ui->doubleValBox->value(); break; case CFG_T_INT: p->editorScale = ui->intEditorScaleBox->value(); p->editAsPercentage = ui->intEditPercentageBox->isChecked(); p->maxInt = ui->intMaxBox->value(); p->minInt = ui->intMinBox->value(); p->showDisplay = ui->intShowDisplayBox->isChecked(); p->stepInt = ui->intStepBox->value(); p->suffix = ui->intSuffixEdit->text(); p->vTx = (VESC_TX_T)(ui->intTxTypeBox->currentIndex() + 1); p->valInt = ui->intValBox->value(); break; case CFG_T_QSTRING: p->valString = ui->stringValEdit->text(); break; case CFG_T_ENUM: p->enumNames.clear(); for (int i = 0;i < ui->enumList->count();i++) { p->enumNames.append(ui->enumList->item(i)->text()); } p->valInt = ui->enumList->currentRow(); break; case CFG_T_BOOL: p->valInt = ui->boolBox->currentIndex(); break; default: break; } } return ui->nameEdit->text(); } void ParameterEditor::addEnum(QString name) { QListWidgetItem *item = new QListWidgetItem(name); item->setFlags (item->flags() | Qt :: ItemIsEditable); ui->enumList->addItem(item); } void ParameterEditor::showStatusInfo(QString info, bool isGood) { if (isGood) { mStatusLabel->setStyleSheet("QLabel { background-color : lightgreen; color : black; }"); } else { mStatusLabel->setStyleSheet("QLabel { background-color : red; color : black; }"); } mStatusInfoTime = 80; mStatusLabel->setText(info); } void ParameterEditor::on_doubleTxTypeBox_currentIndexChanged(int index) { if (index == 2) { ui->doubleTxScaleBaseBox->setEnabled(false); ui->doubleTxScaleExpBox->setEnabled(false); ui->doubleTxScaleExpLabel->setEnabled(false); ui->doubleTxScaleLabel->setEnabled(false); } else { ui->doubleTxScaleBaseBox->setEnabled(true); ui->doubleTxScaleExpBox->setEnabled(true); ui->doubleTxScaleExpLabel->setEnabled(true); ui->doubleTxScaleLabel->setEnabled(true); } } void ParameterEditor::on_actionCalculatePacketSize_triggered() { VByteArray bytes; mParams.serialize(bytes); QMessageBox::information(this, tr("Packet Size"), tr("%1 Bytes").arg(bytes.size())); }