/* 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; }