/*
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 "configparams.h"
#include
#include "widgets/parameditdouble.h"
#include "widgets/parameditint.h"
#include "widgets/parameditstring.h"
#include "widgets/parameditenum.h"
#include "widgets/parameditbool.h"
#include
#include
#include
#include
#include "utility.h"
ConfigParams::ConfigParams(QObject *parent) : QObject(parent)
{
mUpdateOnlyName.clear();
mXmlStatus = tr("OK");
mUpdatesEnabled = true;
}
void ConfigParams::addParam(const QString &name, ConfigParam param)
{
if (!mParams.contains(name)) {
mParams.insert(name, param);
mParamList.append(name);
} else {
qWarning() << name << "already present.";
}
}
void ConfigParams::deleteParam(const QString &name)
{
mParams.remove(name);
for (int i = 0;i < mParamList.size();i++) {
if (mParamList.at(i) == name) {
mParamList.removeAt(i);
break;
}
}
}
/**
* @brief ConfigParams::setUpdateOnly
* Only update parameter with the following name.
*
* @param name
* The name of the parameter to update. If empty all parameters will be updated.
*/
void ConfigParams::setUpdateOnly(const QString &name)
{
mUpdateOnlyName = name;
}
QString ConfigParams::getUpdateOnly()
{
return mUpdateOnlyName;
}
bool ConfigParams::getUpdatesEnabled() const
{
return mUpdatesEnabled;
}
void ConfigParams::setUpdatesEnabled(bool updatesEnabled)
{
mUpdatesEnabled = updatesEnabled;
}
void ConfigParams::clearParams()
{
mParams.clear();
mParamList.clear();
}
void ConfigParams::clearAll()
{
clearParams();
clearSerializeOrder();
}
bool ConfigParams::hasParam(const QString &name)
{
return mParams.contains(name);
}
ConfigParam *ConfigParams::getParam(const QString &name)
{
ConfigParam *retVal = 0;
if (mParams.contains(name)) {
retVal = &mParams[name];
} else {
qWarning() << name << "not found";
}
return retVal;
}
ConfigParam ConfigParams::getParamCopy(const QString &name) const
{
ConfigParam retVal;
if (mParams.contains(name)) {
retVal = mParams.value(name);
} else {
qWarning() << name << "not found";
}
return retVal;
}
bool ConfigParams::isParamDouble(const QString &name)
{
if (mParams.contains(name) && mParams[name].type == CFG_T_DOUBLE) {
return true;
} else {
return false;
}
}
bool ConfigParams::isParamInt(const QString &name)
{
if (mParams.contains(name) && mParams[name].type == CFG_T_INT) {
return true;
} else {
return false;
}
}
bool ConfigParams::isParamEnum(const QString &name)
{
if (mParams.contains(name) && mParams[name].type == CFG_T_ENUM) {
return true;
} else {
return false;
}
}
bool ConfigParams::isParamQString(const QString &name)
{
if (mParams.contains(name) && mParams[name].type == CFG_T_QSTRING) {
return true;
} else {
return false;
}
}
bool ConfigParams::isParamBool(const QString &name)
{
if (mParams.contains(name) && mParams[name].type == CFG_T_BOOL) {
return true;
} else {
return false;
}
}
double ConfigParams::getParamDouble(const QString &name)
{
double retVal = 0.0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_DOUBLE) {
retVal = p.valDouble;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
int ConfigParams::getParamInt(const QString &name)
{
int retVal = 0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_INT) {
retVal = p.valInt;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
int ConfigParams::getParamEnum(const QString &name)
{
int retVal = 0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_ENUM) {
retVal = p.valInt;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
QString ConfigParams::getParamQString(const QString &name)
{
QString retVal = "";
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_QSTRING) {
retVal = p.valString;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
bool ConfigParams::getParamBool(const QString &name)
{
bool retVal = false;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_BOOL) {
retVal = p.valInt;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
QString ConfigParams::getLongName(const QString &name)
{
QString retVal = "";
if (mParams.contains(name)) {
retVal = mParams[name].longName;
} else {
qWarning() << name << "not found";
}
return retVal;
}
QString ConfigParams::getDescription(const QString &name)
{
QString retVal = "";
if (mParams.contains(name)) {
retVal = mParams[name].description;
} else {
qWarning() << name << "not found";
}
return retVal;
}
double ConfigParams::getParamMaxDouble(const QString &name)
{
double retVal = 0.0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_DOUBLE) {
retVal = p.maxDouble;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
double ConfigParams::getParamMinDouble(const QString &name)
{
double retVal = 0.0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_DOUBLE) {
retVal = p.minDouble;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
double ConfigParams::getParamStepDouble(const QString &name)
{
double retVal = 0.0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_DOUBLE) {
retVal = p.stepDouble;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
int ConfigParams::getParamDecimalsDouble(const QString &name)
{
int retVal = 0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_DOUBLE) {
retVal = p.editorDecimalsDouble;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
int ConfigParams::getParamMaxInt(const QString &name)
{
int retVal = 0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_INT) {
retVal = p.maxInt;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
int ConfigParams::getParamMinInt(const QString &name)
{
int retVal = 0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_INT) {
retVal = p.minInt;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
int ConfigParams::getParamStepInt(const QString &name)
{
int retVal = 0;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_INT) {
retVal = p.stepInt;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
QStringList ConfigParams::getParamEnumNames(const QString &name)
{
QStringList retVal;
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_ENUM) {
retVal = p.enumNames;
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
double ConfigParams::getParamEditorScale(const QString &name)
{
double retVal = 0.0;
if (mParams.contains(name)) {
retVal = mParams[name].editorScale;
} else {
qWarning() << name << "not found";
}
return retVal;
}
QString ConfigParams::getParamSuffix(const QString &name)
{
QString retVal = "";
if (mParams.contains(name)) {
retVal = mParams[name].suffix;
} else {
qWarning() << name << "not found";
}
return retVal;
}
bool ConfigParams::getParamEditAsPercentage(const QString &name)
{
bool retVal = false;
if (mParams.contains(name)) {
retVal = mParams[name].editAsPercentage;
} else {
qWarning() << name << "not found";
}
return retVal;
}
bool ConfigParams::getParamShowDisplay(const QString &name)
{
bool retVal = false;
if (mParams.contains(name)) {
retVal = mParams[name].showDisplay;
} else {
qWarning() << name << "not found";
}
return retVal;
}
bool ConfigParams::getParamTransmittable(const QString &name)
{
bool retVal = false;
if (mParams.contains(name)) {
retVal = mParams[name].transmittable;
} else {
qWarning() << name << "not found";
}
return retVal;
}
QStringList ConfigParams::getParamOrder() const
{
return mParamList;
}
void ConfigParams::setParamOrder(const QStringList &order)
{
// TODO: Add check to make sure that the new order is valid.
mParamList = order;
}
void ConfigParams::setParamValue(const QString &name, QVariant val)
{
ConfigParam *retVal = 0;
ConfigParam &p = mParams[name];
if (mParams.contains(name)) {
p.suffix;
p.editorDecimalsDouble;
p.editAsPercentage;
p.showDisplay;
//int(p.type);
switch (p.type) {
case CFG_T_QSTRING: {
p.valString = val.toString();
}
break;
case CFG_T_DOUBLE: {
p.valDouble = val.toDouble();
}
break;
case CFG_T_ENUM:
case CFG_T_BOOL:
case CFG_T_INT: {
if(val.type() == QVariant::Bool)
p.valInt = val.toBool() ? 1 : 0;
else
p.valInt = val.toInt();
}
break;
}
//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);
} else {
qWarning() << name << "not found";
}
}
//QWidget *ConfigParams::getEditor(const QString &name, QWidget *parent)
//{
// QWidget *retVal = 0;
// 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);
// 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;
// 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->setConfig(this);
// retVal = edit;
// } break;
// 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->setConfig(this);
// retVal = edit;
// } break;
// 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->setConfig(this);
// retVal = edit;
// } break;
// 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->setConfig(this);
// retVal = edit;
// } break;
// default:
// qWarning() << "no editor for" << name << "could be created";
// break;
// }
// } else {
// qWarning() << name << "not found";
// }
// return retVal;
//}
/*
QWidget *ConfigParams::getEditor(const QString &name, QWidget *parent)
{
QWidget *retVal = 0;
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);
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);
edit->setConfig(this);
retVal = edit;
} break;
case CFG_T_QSTRING: {
ParamEditString *edit = new ParamEditString(parent);
edit->setName(name);
edit->setConfig(this);
retVal = edit;
} break;
case CFG_T_ENUM: {
ParamEditEnum *edit = new ParamEditEnum(parent);
edit->setName(name);
edit->setConfig(this);
retVal = edit;
} break;
case CFG_T_BOOL: {
ParamEditBool *edit = new ParamEditBool(parent);
edit->setName(name);
edit->setConfig(this);
retVal = edit;
} break;
default:
qWarning() << "no editor for" << name << "could be created";
break;
}
} else {
qWarning() << name << "not found";
}
return retVal;
}
*/
void ConfigParams::getParamSerial(VByteArray &vb, const QString &name)
{
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
switch (p.type) {
case CFG_T_UNDEFINED:
qWarning() << name << ": type not defined.";
break;
case CFG_T_DOUBLE:
if (p.vTx == VESC_TX_DOUBLE16) {
vb.vbAppendDouble16(p.valDouble, p.vTxDoubleScale);
} else if (p.vTx == VESC_TX_DOUBLE32) {
vb.vbAppendDouble32(p.valDouble, p.vTxDoubleScale);
} else if (p.vTx == VESC_TX_DOUBLE32_AUTO) {
vb.vbAppendDouble32Auto(p.valDouble);
} else {
qWarning() << name << ": wrong tx type set.";
}
break;
case CFG_T_INT:
if (p.vTx == VESC_TX_UINT8) {
vb.vbAppendUint8(p.valInt);
} else if (p.vTx == VESC_TX_INT8) {
vb.vbAppendInt8(p.valInt);
} else if (p.vTx == VESC_TX_UINT16) {
vb.vbAppendUint16(p.valInt);
} else if (p.vTx == VESC_TX_INT16) {
vb.vbAppendInt16(p.valInt);
} else if (p.vTx == VESC_TX_UINT32) {
vb.vbAppendUint32(p.valInt);
} else if (p.vTx == VESC_TX_INT32) {
vb.vbAppendInt32(p.valInt);
} else {
qWarning() << name << ": wrong tx type set.";
}
break;
case CFG_T_QSTRING:
qWarning() << name << ": QString not supported.";
break;
case CFG_T_ENUM:
case CFG_T_BOOL:
vb.vbAppendInt8(p.valInt);
break;
}
} else {
qWarning() << name << "not found";
}
}
void ConfigParams::setParamSerial(VByteArray &vb, const QString &name, QObject *src)
{
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
switch (p.type) {
case CFG_T_UNDEFINED:
qWarning() << name << ": type not defined.";
break;
case CFG_T_DOUBLE: {
double val = 0.0;
if (p.vTx == VESC_TX_DOUBLE16) {
val = vb.vbPopFrontDouble16(p.vTxDoubleScale);
} else if (p.vTx == VESC_TX_DOUBLE32) {
val = vb.vbPopFrontDouble32(p.vTxDoubleScale);
} else if (p.vTx == VESC_TX_DOUBLE32_AUTO) {
val = vb.vbPopFrontDouble32Auto();
} else {
qWarning() << name << ": wrong tx type set.";
}
if (mUpdatesEnabled && (mUpdateOnlyName.isEmpty() || mUpdateOnlyName == name)) {
if (p.valDouble != val) {
p.valDouble = val;
emit paramChangedDouble(src, name, val);
}
}
} break;
case CFG_T_INT: {
int val = 0;
if (p.vTx == VESC_TX_UINT8) {
val = vb.vbPopFrontUint8();
} else if (p.vTx == VESC_TX_INT8) {
val = vb.vbPopFrontInt8();
} else if (p.vTx == VESC_TX_UINT16) {
val = vb.vbPopFrontUint16();
} else if (p.vTx == VESC_TX_INT16) {
val = vb.vbPopFrontInt16();
} else if (p.vTx == VESC_TX_UINT32) {
val = vb.vbPopFrontUint32();
} else if (p.vTx == VESC_TX_INT32) {
val = vb.vbPopFrontInt32();
} else {
qWarning() << name << ": wrong tx type set.";
}
if (mUpdatesEnabled && (mUpdateOnlyName.isEmpty() || mUpdateOnlyName == name)) {
if (p.valInt != val) {
p.valInt = val;
emit paramChangedInt(src, name, val);
}
}
} break;
case CFG_T_QSTRING:
qWarning() << name << ": QString not supported.";
break;
case CFG_T_ENUM:
case CFG_T_BOOL: {
int val = vb.vbPopFrontInt8();
if (mUpdatesEnabled && (mUpdateOnlyName.isEmpty() || mUpdateOnlyName == name)) {
if (p.valInt != val) {
p.valInt = val;
if (p.type == CFG_T_BOOL) {
emit paramChangedBool(src, name, val);
} else {
emit paramChangedEnum(src, name, val);
}
}
}
} break;
}
} else {
qWarning() << name << "not found";
}
}
void ConfigParams::updateParamDouble(QString name, double param, QObject *src)
{
if (!mUpdatesEnabled || (!mUpdateOnlyName.isEmpty() && mUpdateOnlyName != name)) {
return;
}
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_DOUBLE) {
if (p.valDouble != param) {
p.valDouble = param;
emit paramChangedDouble(src, name, param);
}
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
}
void ConfigParams::updateParamInt(QString name, int param, QObject *src)
{
if (!mUpdatesEnabled || (!mUpdateOnlyName.isEmpty() && mUpdateOnlyName != name)) {
return;
}
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_INT) {
if (p.valInt != param) {
p.valInt = param;
emit paramChangedInt(src, name, param);
}
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
}
void ConfigParams::updateParamEnum(QString name, int param, QObject *src)
{
if (!mUpdatesEnabled || (!mUpdateOnlyName.isEmpty() && mUpdateOnlyName != name)) {
return;
}
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_ENUM) {
if (p.valInt != param) {
p.valInt = param;
emit paramChangedEnum(src, name, param);
}
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
}
void ConfigParams::updateParamString(QString name, QString param, QObject *src)
{
if (!mUpdatesEnabled || (!mUpdateOnlyName.isEmpty() && mUpdateOnlyName != name)) {
return;
}
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_QSTRING) {
if (p.valString != param) {
p.valString = param;
emit paramChangedQString(src, name, param);
}
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
}
void ConfigParams::updateParamBool(QString name, bool param, QObject *src)
{
if (!mUpdatesEnabled || (!mUpdateOnlyName.isEmpty() && mUpdateOnlyName != name)) {
return;
}
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (p.type == CFG_T_BOOL) {
if (p.valInt != param) {
p.valInt = param;
emit paramChangedBool(src, name, param);
}
} else {
qWarning() << name << "wrong type";
}
} else {
qWarning() << name << "not found";
}
}
void ConfigParams::requestUpdate()
{
emit updateRequested();
}
void ConfigParams::requestUpdateDefault()
{
emit updateRequestDefault();
}
void ConfigParams::updateDone()
{
// Accept all names from now on again.
mUpdateOnlyName.clear();
emit updated();
}
void ConfigParams::storingDone()
{
emit stored();
}
// http://realtimecollisiondetection.net/blog/?p=89
bool ConfigParams::almostEqual(float A, float B, float eps)
{
return fabsf(A - B) <= eps * fmaxf(1.0f, fmaxf(fabsf(A), fabsf(B)));
}
QStringList ConfigParams::getSerializeOrder() const
{
return mSerializeOrder;
}
void ConfigParams::setSerializeOrder(const QStringList &serializeOrder)
{
mSerializeOrder = serializeOrder;
}
void ConfigParams::clearSerializeOrder()
{
mSerializeOrder.clear();
}
void ConfigParams::serialize(VByteArray &vb)
{
for (int i = 0;i < mSerializeOrder.size();i++) {
getParamSerial(vb, mSerializeOrder.at(i));
}
}
void ConfigParams::deSerialize(VByteArray &vb)
{
for (int i = 0;i < mSerializeOrder.size();i++) {
setParamSerial(vb, mSerializeOrder.at(i));
}
}
void ConfigParams::getXML(QXmlStreamWriter &stream, QString configName)
{
stream.writeStartDocument();
stream.writeStartElement(configName);
QHashIterator i(mParams);
while (i.hasNext()) {
i.next();
const ConfigParam &p = i.value();
QString name = i.key();
switch (p.type) {
case CFG_T_BOOL:
case CFG_T_ENUM:
case CFG_T_INT:
stream.writeTextElement(name, QString::number(p.valInt));
break;
case CFG_T_DOUBLE:
stream.writeTextElement(name, QString::number(p.valDouble));
break;
case CFG_T_QSTRING:
stream.writeTextElement(name, p.valString);
break;
case CFG_T_UNDEFINED:
// Undefined parameters have no value to save.
break;
default:
qWarning() << name << ": type not supported.";
break;
}
}
stream.writeEndDocument();
}
bool ConfigParams::setXML(QXmlStreamReader &stream, QString configName)
{
bool nameFound = false;
while (stream.readNextStartElement()) {
if (stream.name() == configName) {
nameFound = true;
break;
}
}
if (nameFound) {
while (stream.readNextStartElement()) {
QString name = stream.name().toString();
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
QString text = stream.readElementText();
int valInt = text.toInt();
double valDouble = text.toDouble();
switch (p.type) {
case CFG_T_BOOL:
if (valInt != p.valInt) {
p.valInt = valInt;
emit paramChangedBool(0, name, valInt);
}
break;
case CFG_T_ENUM:
if (valInt != p.valInt) {
p.valInt = valInt;
emit paramChangedEnum(0, name, valInt);
}
break;
case CFG_T_INT:
if (valInt != p.valInt) {
p.valInt = valInt;
emit paramChangedInt(0, name, valInt);
}
break;
case CFG_T_DOUBLE:
if (valDouble != p.valDouble) {
p.valDouble = valDouble;
emit paramChangedDouble(0, name, valDouble);
}
break;
case CFG_T_QSTRING:
if (text != p.valString) {
p.valString = text;
emit paramChangedQString(0, name, text);
}
break;
default:
qWarning() << name << ": type not supported.";
break;
}
} else {
qWarning() << "Parameter not found: " << name;
stream.skipCurrentElement();
}
if (stream.hasError()) {
qWarning() << "XML ERROR :" << stream.errorString();
qWarning() << stream.lineNumber() << stream.columnNumber();
}
}
mXmlStatus = tr("OK");
emit updated();
return true;
} else {
mXmlStatus = tr("tag %1 not found").arg(configName);
qWarning() << mXmlStatus;
return false;
}
}
bool ConfigParams::saveXml(QString fileName, QString configName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
mXmlStatus = tr("Could not open %1 for writing").arg(fileName);
qWarning() << mXmlStatus;
return false;
}
emit savingXml();
QXmlStreamWriter stream(&file);
stream.setCodec("UTF-8");
stream.setAutoFormatting(true);
getXML(stream, configName);
file.close();
mXmlStatus = tr("OK");
return true;
}
bool ConfigParams::loadXml(QString fileName, QString configName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
mXmlStatus = tr("Could not open %1 for reading").arg(fileName);
qWarning() << mXmlStatus;
return false;
}
QXmlStreamReader stream(&file);
bool res = setXML(stream, configName);
file.close();
return res;
}
QString ConfigParams::xmlStatus()
{
return mXmlStatus;
}
void ConfigParams::getParamsXML(QXmlStreamWriter &stream)
{
stream.writeStartDocument();
stream.writeStartElement("ConfigParams");
stream.writeStartElement("Params");
for (int i = 0;i < mParamList.size();i++) {
QString paramName = mParamList.at(i);
ConfigParam *p = getParam(paramName);
stream.writeStartElement(paramName);
stream.writeTextElement("longName", p->longName);
stream.writeTextElement("type", QString::number(p->type));
stream.writeTextElement("transmittable", QString::number(p->transmittable));
stream.writeTextElement("description", p->description);
stream.writeTextElement("cDefine", p->cDefine);
switch (p->type) {
case CFG_T_DOUBLE:
stream.writeTextElement("editorDecimalsDouble", QString::number(p->editorDecimalsDouble));
stream.writeTextElement("editorScale", QString::number(p->editorScale));
stream.writeTextElement("editAsPercentage", QString::number(p->editAsPercentage));
stream.writeTextElement("maxDouble", QString::number(p->maxDouble));
stream.writeTextElement("minDouble", QString::number(p->minDouble));
stream.writeTextElement("showDisplay", QString::number(p->showDisplay));
stream.writeTextElement("stepDouble", QString::number(p->stepDouble));
stream.writeTextElement("valDouble", QString::number(p->valDouble));
stream.writeTextElement("vTxDoubleScale", QString::number(p->vTxDoubleScale));
stream.writeTextElement("suffix", p->suffix);
stream.writeTextElement("vTx", QString::number(p->vTx));
break;
case CFG_T_INT:
stream.writeTextElement("editorScale", QString::number(p->editorScale));
stream.writeTextElement("editAsPercentage", QString::number(p->editAsPercentage));
stream.writeTextElement("maxInt", QString::number(p->maxInt));
stream.writeTextElement("minInt", QString::number(p->minInt));
stream.writeTextElement("showDisplay", QString::number(p->showDisplay));
stream.writeTextElement("stepInt", QString::number(p->stepInt));
stream.writeTextElement("valInt", QString::number(p->valInt));
stream.writeTextElement("suffix", p->suffix);
stream.writeTextElement("vTx", QString::number(p->vTx));
break;
case CFG_T_QSTRING:
stream.writeTextElement("valString", p->valString);
break;
case CFG_T_ENUM:
stream.writeTextElement("valInt", QString::number(p->valInt));
for (int j = 0;j < p->enumNames.size();j++) {
stream.writeTextElement("enumNames", p->enumNames.at(j));
}
break;
case CFG_T_BOOL:
stream.writeTextElement("valInt", QString::number(p->valInt));
break;
default:
break;
}
stream.writeEndElement();
}
stream.writeEndElement();
stream.writeStartElement("SerOrder");
for (int i = 0;i < mSerializeOrder.size();i++) {
stream.writeTextElement("ser", mSerializeOrder.at(i));
}
stream.writeEndDocument();
}
bool ConfigParams::setParamsXML(QXmlStreamReader &stream)
{
QString configName = "ConfigParams";
bool nameFound = false;
while (stream.readNextStartElement()) {
if (stream.name() == configName) {
nameFound = true;
break;
}
}
if (nameFound) {
while (stream.readNextStartElement()) {
QString nameFirst = stream.name().toString();
if (nameFirst == "Params") {
clearParams();
while (stream.readNextStartElement()) {
QString paramName = stream.name().toString();
ConfigParam p;
while (stream.readNextStartElement()) {
QString name = stream.name().toString();
if (name == "description") {
p.description = stream.readElementText();
} else if (name == "cDefine") {
p.cDefine = stream.readElementText();
} else if (name == "editorDecimalsDouble") {
p.editorDecimalsDouble = stream.readElementText().toDouble();
} else if (name == "editorScale") {
p.editorScale = stream.readElementText().toDouble();
} else if (name == "editAsPercentage") {
p.editAsPercentage = stream.readElementText().toInt();
} else if (name == "enumNames") {
p.enumNames.append(stream.readElementText());
} else if (name == "longName") {
p.longName = stream.readElementText();
} else if (name == "maxDouble") {
p.maxDouble = stream.readElementText().toDouble();
} else if (name == "maxInt") {
p.maxInt = stream.readElementText().toInt();
} else if (name == "minDouble") {
p.minDouble = stream.readElementText().toDouble();
} else if (name == "minInt") {
p.minInt = stream.readElementText().toInt();
} else if (name == "showDisplay") {
p.showDisplay = stream.readElementText().toInt();
} else if (name == "stepDouble") {
p.stepDouble = stream.readElementText().toDouble();
} else if (name == "stepInt") {
p.stepInt = stream.readElementText().toInt();
} else if (name == "suffix") {
p.suffix = stream.readElementText();
} else if (name == "type") {
p.type = (CFG_T)stream.readElementText().toInt();
} else if (name == "transmittable") {
p.transmittable = stream.readElementText().toInt();
} else if (name == "valDouble") {
p.valDouble = stream.readElementText().toDouble();
} else if (name == "valInt") {
p.valInt = stream.readElementText().toInt();
} else if (name == "valString") {
p.valString = stream.readElementText();
} else if (name == "vTx") {
p.vTx = (VESC_TX_T)stream.readElementText().toInt();
} else if (name == "vTxDoubleScale") {
p.vTxDoubleScale = stream.readElementText().toDouble();
} else {
qWarning() << "Parameter not found: " << name;
stream.skipCurrentElement();
}
if (stream.hasError()) {
qWarning() << "XML ERROR :" << stream.errorString();
qWarning() << stream.lineNumber() << stream.columnNumber();
}
}
addParam(paramName, p);
}
} else if (nameFirst == "SerOrder") {
mSerializeOrder.clear();
while (stream.readNextStartElement()) {
QString name = stream.name().toString();
if (name == "ser") {
mSerializeOrder.append(stream.readElementText());
} else {
qWarning() << "Parameter not found: " << name;
stream.skipCurrentElement();
}
}
} else {
qWarning() << "Parameter not found: " << nameFirst;
stream.skipCurrentElement();
}
}
mXmlStatus = tr("OK");
return true;
} else {
mXmlStatus = tr("tag %1 not found").arg(configName);
qWarning() << mXmlStatus;
return false;
}
}
bool ConfigParams::saveParamsXml(QString fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
mXmlStatus = tr("Could not open %1 for writing").arg(fileName);
qWarning() << mXmlStatus;
return false;
}
QXmlStreamWriter stream(&file);
stream.setCodec("UTF-8");
stream.setAutoFormatting(true);
getParamsXML(stream);
file.close();
mXmlStatus = tr("OK");
return true;
}
bool ConfigParams::loadParamsXml(QString fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
mXmlStatus = tr("Could not open %1 for reading").arg(fileName);
qWarning() << mXmlStatus;
return false;
}
QXmlStreamReader stream(&file);
bool res = setParamsXML(stream);
file.close();
return res;
}
bool ConfigParams::saveCDefines(const QString &fileName, bool wrapIfdef)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
mXmlStatus = tr("Could not open %1 for writing").arg(fileName);
qWarning() << mXmlStatus;
return false;
}
QTextStream out(&file);
QFileInfo info(file);
QString nameStr = info.fileName().toUpper().replace(".", "_") + "_";
out << "// This file is autogenerated by EBMS Tool\n\n";
out << "#ifndef " + nameStr + "\n";
out << "#define " + nameStr + "\n\n";
for (int i = 0;i < mSerializeOrder.size();i++) {
QString name = mSerializeOrder.at(i);
if (mParams.contains(name)) {
ConfigParam &p = mParams[name];
if (!p.cDefine.isEmpty()) {
out << "// " + p.longName + "\n";
if (wrapIfdef) {
out << "#ifndef " + p.cDefine + "\n";
}
switch (p.type) {
case CFG_T_BOOL:
case CFG_T_ENUM:
case CFG_T_INT:
out << "#define " + p.cDefine + " " + QString::number(p.valInt) + "\n";
break;
case CFG_T_DOUBLE:
out << "#define " + p.cDefine + " " + QString::number(p.valDouble) + "\n";
break;
case CFG_T_QSTRING:
out << "#define " + p.cDefine + " " + p.valString + "\n";
break;
default:
qWarning() << name << ": type not supported.";
break;
}
if (wrapIfdef) {
out << "#endif\n";
}
out << "\n";
}
} else {
qWarning() << name << "not found.";
}
}
out << "// " + nameStr + "\n";
out << "#endif\n\n";
out.flush();
file.close();
return true;
}
/**
* @brief ConfigParams::checkDifference
* Check which parameters differ between this configuration and another one.
*
* @param config
* The configuration to check against.
*
* @return
* A list with parameters that differ.
*/
QStringList ConfigParams::checkDifference(ConfigParams *config)
{
QStringList res;
for(QString p: mParamList) {
ConfigParam *thisParam = this->getParam(p);
ConfigParam *otherParam = config->getParam(p);
if (thisParam && otherParam) {
if (thisParam->type == otherParam->type) {
switch (thisParam->type) {
case CFG_T_BOOL:
case CFG_T_ENUM:
case CFG_T_INT:
if (thisParam->valInt != otherParam->valInt) {
res.append(p);
}
break;
case CFG_T_DOUBLE:
if (!almostEqual(thisParam->valDouble, otherParam->valDouble, 0.0001)) {
res.append(p);
}
break;
case CFG_T_QSTRING:
if (thisParam->valString != otherParam->valString) {
res.append(p);
}
break;
default:
break;
}
}
}
}
return res;
}
ConfigParams &ConfigParams::operator=(const ConfigParams &other)
{
this->mParams = other.mParams;
this->mParamList = other.mParamList;
this->mUpdateOnlyName = other.mUpdateOnlyName;
this->mUpdatesEnabled = other.mUpdatesEnabled;
this->mSerializeOrder = other.mSerializeOrder;
this->mXmlStatus = other.mXmlStatus;
return *this;
}