Refactor curve reference

This commit is contained in:
elecpower
2020-12-05 06:50:43 +11:00
parent b52a921c59
commit 83561fe6fe
10 changed files with 326 additions and 233 deletions
+1
View File
@@ -71,6 +71,7 @@
#define CPN_STR_APP_SETTINGS_FILTER CPN_STR_APP_SETTINGS_FILES % " (*.ini)"
#define CPN_STR_UNKNOWN_ITEM "???"
#define CPN_STR_NONE_ITEM "----"
#define CPN_STR_SW_INDICATOR_UP QCoreApplication::translate("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
#define CPN_STR_SW_INDICATOR_DN QCoreApplication::translate("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.
+6
View File
@@ -32,6 +32,12 @@ list(APPEND firmwares_HDRS
moduledata.h
)
set(firmwares_QT
curvereference.h
)
qt5_wrap_cpp(firmwares_SRCS ${firmwares_QT})
add_library(firmwares ${firmwares_SRCS} ${firmwares_HDRS})
target_link_libraries(firmwares ${CPN_COMMON_LIB} Qt5::Core Qt5::Xml Qt5::Widgets)
target_include_directories(firmwares
+259 -19
View File
@@ -19,45 +19,285 @@
*/
#include "curvereference.h"
#include "adjustmentreference.h"
#include "helpers.h"
#include "modeldata.h"
#include "helpers.h" // for Helpers::getAdjustmentString()
#include "radiodata.h" // for ModelData
QString CurveReference::toString(const ModelData * model, bool verbose) const
const QString CurveReference::toString(const ModelData * model, bool verbose) const
{
if (value == 0) {
return "----";
}
if (value == 0)
return CPN_STR_NONE_ITEM;
QString ret;
unsigned idx = abs(value) - 1;
switch(type) {
case CURVE_REF_DIFF:
ret = tr("Diff(%1)").arg(Helpers::getAdjustmentString(value, model));
break;
case CURVE_REF_EXPO:
ret = tr("Expo(%1)").arg(Helpers::getAdjustmentString(value, model));
ret = AdjustmentReference(value).toString(model);
break;
case CURVE_REF_FUNC:
ret = QString("x>0" "x<0" "|x|" "f>0" "f<0" "|f|").mid(3*(value-1), 3);
if (verbose)
ret = tr("Function(%1)").arg(ret);
ret = functionToString(value);
break;
default:
case CURVE_REF_CUSTOM:
if (model)
ret = model->curves[idx].nameToString(idx);
else
ret = CurveData().nameToString(idx);
if (verbose)
ret = tr("Curve(%1)").arg(ret);
if (value < 0)
ret.prepend(CPN_STR_SW_INDICATOR_REV);
break;
default:
return CPN_STR_UNKNOWN_ITEM;
}
if (verbose)
ret = tr(qPrintable(QString(typeToString(type) + "(%1)").arg(ret)));
return ret;
}
const bool CurveReference::isValueNumber() const
{
return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE;
}
// static
int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar)
{
if (isGVar && (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO))
return AdjustmentReference(AdjustmentReference::ADJUST_REF_GVAR, 1).toValue();
else if (type == CURVE_REF_FUNC)
return 1;
else
return 0;
}
// static
QString CurveReference::typeToString(const CurveRefType type)
{
const QStringList strl = { "Diff", "Expo" , "Func", "Curve" };
int idx = (int)type;
if (idx < 0 || idx >= strl.count())
return CPN_STR_UNKNOWN_ITEM;
return strl.at(idx);
}
constexpr int MAX_CURVE_REF_FUNC { 6 };
// static
QString CurveReference::functionToString(const int value)
{
const QStringList strl = { "x>0", "x<0", "|x|", "f>0", "f<0", "|f|" };
int idx = value - 1;
if (idx < 0 || idx >= strl.count())
return CPN_STR_UNKNOWN_ITEM;
return strl.at(idx);
}
/*
* CurveReferenceUIManager
*/
constexpr int CURVE_REF_UI_HIDE_DIFF { 0x01 };
constexpr int CURVE_REF_UI_HIDE_EXPO { 0x02 };
constexpr int CURVE_REF_UI_HIDE_NEGATIVE_CURVES { 0x04 };
// static
bool CurveReferenceUIManager::firsttime { true };
int CurveReferenceUIManager::flags{ 0 };
bool CurveReferenceUIManager::hasCapabilityGvars{ false };
int CurveReferenceUIManager::numCurves{ 0 };
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveValueCB, CurveReference & curve, const ModelData & model, QObject * parent) :
QObject(parent),
curveTypeCB(nullptr),
curveGVarCB(nullptr),
curveValueSB(nullptr),
curveValueCB(curveValueCB),
curve(curve),
model(model),
lock(false)
{
init();
}
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB, QComboBox * curveValueCB,
CurveReference & curve, const ModelData & model, QObject * parent) :
QObject(parent),
curveTypeCB(curveTypeCB),
curveGVarCB(curveGVarCB),
curveValueSB(curveValueSB),
curveValueCB(curveValueCB),
curve(curve),
model(model),
lock(false)
{
init();
}
CurveReferenceUIManager::~CurveReferenceUIManager()
{
}
void CurveReferenceUIManager::init()
{
if (firsttime) {
firsttime = false;
Firmware * fw = getCurrentFirmware();
hasCapabilityGvars = fw->getCapability(Gvars);
numCurves = fw->getCapability(NumCurves);
if (!fw->getCapability(HasInputDiff))
flags |= (CURVE_REF_UI_HIDE_DIFF | CURVE_REF_UI_HIDE_NEGATIVE_CURVES);
if (!fw->getCapability(HasMixerExpo))
flags |= CURVE_REF_UI_HIDE_EXPO;
}
if (curveTypeCB) {
populateTypeCB(curveTypeCB, curve);
connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
}
if (curveGVarCB)
connect(curveGVarCB, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
if (curveValueSB) {
curveValueSB->setMinimum(-100);
curveValueSB->setMaximum(100);
connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged()));
}
curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents);
curveValueCB->setMaxVisibleItems(10);
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged()));
update();
}
#define CURVE_REF_UI_GVAR_SHOW (1<<0)
#define CURVE_REF_UI_VALUE_SHOW (1<<1)
#define CURVE_REF_UI_REF_SHOW (1<<2)
void CurveReferenceUIManager::update()
{
lock = true;
int widgetsMask = 0;
if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) {
if (hasCapabilityGvars)
widgetsMask |= CURVE_REF_UI_GVAR_SHOW;
if (curve.isValueNumber()) {
curveGVarCB->setChecked(false);
curveValueSB->setValue(curve.value);
widgetsMask |= CURVE_REF_UI_VALUE_SHOW;
}
else {
curveGVarCB->setChecked(true);
widgetsMask |= CURVE_REF_UI_REF_SHOW;
}
}
else {
widgetsMask |= CURVE_REF_UI_REF_SHOW;
}
if(curveTypeCB) {
curveTypeCB->setCurrentIndex(curveTypeCB->findData(curve.type));
curveTypeCB->show();
}
if(curveGVarCB)
curveGVarCB->setVisible(widgetsMask & CURVE_REF_UI_GVAR_SHOW);
if(curveValueSB)
curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW);
if(curveValueCB) {
if (curve.isValueReference())
populateValueCB(curveValueCB, curve, &model);
curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW);
}
lock = false;
}
void CurveReferenceUIManager::gvarCBChanged(int state)
{
if (!lock) {
curve.value = CurveReference::getDefaultValue(curve.type, state);
update();
}
}
void CurveReferenceUIManager::typeChanged(int value)
{
if (!lock) {
CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
curve = CurveReference(type, CurveReference::getDefaultValue(type));
update();
}
}
void CurveReferenceUIManager::valueSBChanged()
{
if (!lock) {
curve.value = curveValueSB->value();
update();
}
}
void CurveReferenceUIManager::valueCBChanged()
{
if (!lock) {
curve.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
update();
}
}
// static
void CurveReferenceUIManager::populateTypeCB(QComboBox * cb, const CurveReference & curveRef)
{
if (cb) {
cb->clear();
for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) {
if ((curveRef.type == CurveReference::CURVE_REF_DIFF && !(flags & CURVE_REF_UI_HIDE_DIFF)) ||
(curveRef.type == CurveReference::CURVE_REF_EXPO && !(flags & CURVE_REF_UI_HIDE_EXPO)) ||
(curveRef.type != CurveReference::CURVE_REF_DIFF && curveRef.type != CurveReference::CURVE_REF_EXPO))
cb->addItem(CurveReference::typeToString((CurveReference::CurveRefType)i), i);
}
cb->setCurrentIndex(cb->findData((int)curveRef.type));
}
}
// static
void CurveReferenceUIManager::populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model)
{
if (cb) {
cb->clear();
switch (curveRef.type) {
case CurveReference::CURVE_REF_DIFF:
case CurveReference::CURVE_REF_EXPO:
Helpers::populateGVCB(*cb, curveRef.value, *model);
break;
case CurveReference::CURVE_REF_FUNC:
for (int i = 1; i <= MAX_CURVE_REF_FUNC; i++) {
cb->addItem(CurveReference::functionToString(i), i);
}
break;
case CurveReference::CURVE_REF_CUSTOM:
// TODO replace with ui datamodel
for (int i = ((flags & CURVE_REF_UI_HIDE_NEGATIVE_CURVES) ? 0 : -numCurves); i <= numCurves; i++) {
cb->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, i).toString(model, false), i);
}
break;
default:
break;
}
cb->setCurrentIndex(cb->findData(curveRef.value));
}
}
+54 -10
View File
@@ -22,18 +22,25 @@
#define CURVEREFERENCE_H
#include <QtCore>
#include <QComboBox>
#include <QCheckBox>
#include <QSpinBox>
class ModelData;
class CurveReference {
Q_DECLARE_TR_FUNCTIONS(CurveReference)
public:
enum CurveRefType {
CURVE_REF_DIFF,
CURVE_REF_EXPO,
CURVE_REF_FUNC,
CURVE_REF_CUSTOM
CURVE_REF_CUSTOM,
MAX_CURVE_REF_TYPE = CURVE_REF_CUSTOM
};
enum CurveRefGroups {
@@ -46,21 +53,18 @@ class CurveReference {
};
CurveReference() { clear(); }
CurveReference(CurveRefType type, int value):
type(type),
value(value)
{
}
CurveReference(CurveRefType type, int value) : type(type), value(value) { ; }
void clear() { memset(this, 0, sizeof(CurveReference)); }
const bool isEmpty() const { return type == CURVE_REF_DIFF && value == 0; }
const bool isSet() const { return !isEmpty(); }
const bool isValueNumber() const;
const bool isValueReference() const { return !isValueNumber(); }
const QString toString(const ModelData * model = nullptr, bool verbose = true) const;
CurveRefType type;
int value;
QString toString(const ModelData * model = NULL, bool verbose = true) const;
bool isSet() const { return type != CURVE_REF_DIFF || value != 0; }
bool operator == ( const CurveReference & other) const {
return (this->type == other.type) && (this->value == other.value);
}
@@ -68,6 +72,46 @@ class CurveReference {
bool operator != ( const CurveReference & other) const {
return (this->type != other.type) || (this->value != other.value);
}
static int getDefaultValue(const CurveRefType type, const bool isGVar = false);
static QString typeToString(const CurveRefType type);
static QString functionToString(const int value);
};
class CurveReferenceUIManager : public QObject {
Q_OBJECT
public:
CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model, QObject * parent = nullptr);
CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB,
CurveReference & curve, const ModelData & model, QObject * parent = nullptr);
virtual ~CurveReferenceUIManager();
void init();
void update();
protected slots:
void gvarCBChanged(int);
void typeChanged(int);
void valueSBChanged();
void valueCBChanged();
protected:
QComboBox *curveTypeCB;
QCheckBox *curveGVarCB;
QSpinBox *curveValueSB;
QComboBox *curveValueCB;
CurveReference & curve;
const ModelData & model;
bool lock;
static bool firsttime;
static int flags;
static bool hasCapabilityGvars;
static int numCurves;
static void populateTypeCB(QComboBox * cb, const CurveReference & curveRef);
static void populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model = nullptr);
};
#endif // CURVEREFERENCE_H
-164
View File
@@ -210,170 +210,6 @@ void GVarGroup::setWeight(int val)
lock = false;
}
/*
* CurveGroup
*/
CurveGroup::CurveGroup(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QComboBox * curveValueCB, QSpinBox * curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags):
QObject(),
curveTypeCB(curveTypeCB),
curveGVarCB(curveGVarCB),
curveValueCB(curveValueCB),
curveValueSB(curveValueSB),
curve(curve),
model(model),
flags(flags),
lock(false),
lastType(-1)
{
if (!(flags & HIDE_DIFF)) curveTypeCB->addItem(tr("Diff"), 0);
if (!(flags & HIDE_EXPO)) curveTypeCB->addItem(tr("Expo"), 1);
curveTypeCB->addItem(tr("Func"), 2);
curveTypeCB->addItem(tr("Curve"), 3);
curveValueCB->setMaxVisibleItems(10);
connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
connect(curveGVarCB, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged()));
update();
}
void CurveGroup::update()
{
lock = true;
int found = curveTypeCB->findData(curve.type);
if (found < 0) found = 0;
curveTypeCB->setCurrentIndex(found);
if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) {
curveGVarCB->setVisible(getCurrentFirmware()->getCapability(Gvars));
if (curve.value > 100 || curve.value < -100) {
curveGVarCB->setChecked(true);
if (lastType != CurveReference::CURVE_REF_DIFF && lastType != CurveReference::CURVE_REF_EXPO) {
lastType = curve.type;
Helpers::populateGVCB(*curveValueCB, curve.value, model);
}
curveValueCB->show();
curveValueSB->hide();
}
else {
curveGVarCB->setChecked(false);
curveValueSB->setMinimum(-100);
curveValueSB->setMaximum(100);
curveValueSB->setValue(curve.value);
curveValueSB->show();
curveValueCB->hide();
}
}
else {
curveGVarCB->hide();
curveValueSB->hide();
curveValueCB->show();
switch (curve.type) {
case CurveReference::CURVE_REF_FUNC:
if (lastType != curve.type) {
lastType = curve.type;
curveValueCB->clear();
for (int i=0; i<=6/*TODO constant*/; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_FUNC, i).toString(&model, false));
}
}
curveValueCB->setCurrentIndex(curve.value);
break;
case CurveReference::CURVE_REF_CUSTOM:
{
int numcurves = getCurrentFirmware()->getCapability(NumCurves);
if (lastType != curve.type) {
lastType = curve.type;
curveValueCB->clear();
for (int i= ((flags & HIDE_NEGATIVE_CURVES) ? 0 : -numcurves); i<=numcurves; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, i).toString(&model, false), i);
if (i == curve.value) {
curveValueCB->setCurrentIndex(curveValueCB->count() - 1);
}
}
}
break;
}
default:
break;
}
}
lock = false;
}
void CurveGroup::gvarCBChanged(int state)
{
if (!lock) {
if (state) {
curve.value = 10000+1; // TODO constant in EEpromInterface ...
lastType = -1; // quickfix for issue #3518: force refresh of curveValueCB at next update() to set current index to GV1
}
else {
curve.value = 0; // TODO could be better
}
update();
}
}
void CurveGroup::typeChanged(int value)
{
if (!lock) {
int type = curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
switch (type) {
case 0:
curve = CurveReference(CurveReference::CURVE_REF_DIFF, 0);
break;
case 1:
curve = CurveReference(CurveReference::CURVE_REF_EXPO, 0);
break;
case 2:
curve = CurveReference(CurveReference::CURVE_REF_FUNC, 0);
break;
case 3:
curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, 0);
break;
}
update();
}
}
void CurveGroup::valuesChanged()
{
if (!lock) {
switch (curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt()) {
case 0:
case 1:
{
int value;
if (curveGVarCB->isChecked())
value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
else
value = curveValueSB->value();
curve = CurveReference(curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt() == 0 ? CurveReference::CURVE_REF_DIFF : CurveReference::CURVE_REF_EXPO, value);
break;
}
case 2:
curve = CurveReference(CurveReference::CURVE_REF_FUNC, curveValueCB->currentIndex());
break;
case 3:
curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, curveValueCB->itemData(curveValueCB->currentIndex()).toInt());
break;
}
update();
}
}
/*
* Helpers namespace functions
*/
-29
View File
@@ -98,35 +98,6 @@ class GVarGroup: public QObject {
bool lock;
};
#define HIDE_DIFF 0x01
#define HIDE_EXPO 0x02
#define HIDE_NEGATIVE_CURVES 0x04
class CurveGroup : public QObject {
Q_OBJECT
public:
CurveGroup(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QComboBox *curveValueCB, QSpinBox *curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags=0);
void update();
protected slots:
void gvarCBChanged(int);
void typeChanged(int);
void valuesChanged();
protected:
QComboBox *curveTypeCB;
QCheckBox *curveGVarCB;
QComboBox *curveValueCB;
QSpinBox *curveValueSB;
CurveReference & curve;
const ModelData & model;
unsigned int flags;
bool lock;
int lastType;
};
namespace Helpers
{
void populateGvarUseCB(QComboBox *b, unsigned int phase);
+1 -4
View File
@@ -50,9 +50,7 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100);
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100);
curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model,
firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES));
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model, this);
ui->switchesCB->setModel(rawSwitchModel);
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue()));
@@ -139,7 +137,6 @@ ExpoDialog::~ExpoDialog()
{
delete gvWeightGroup;
delete gvOffsetGroup;
delete curveGroup;
delete ui;
}
+2 -2
View File
@@ -26,8 +26,8 @@
#include "modelprinter.h"
class GVarGroup;
class CurveGroup;
class RawItemFilteredModel;
class CurveReferenceUIManager;
namespace Ui {
class ExpoDialog;
@@ -61,7 +61,7 @@ class ExpoDialog : public QDialog {
QString & inputName;
GVarGroup * gvWeightGroup;
GVarGroup * gvOffsetGroup;
CurveGroup * curveGroup;
CurveReferenceUIManager * curveGroup;
ModelPrinter modelPrinter;
bool lock;
QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES];
+1 -3
View File
@@ -52,8 +52,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit);
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit);
curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB,
md->curve, model, firmware->getCapability(HasMixerExpo) ? 0 : HIDE_EXPO);
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model, this);
ui->MixDR_CB->setChecked(md->noExpo == 0);
@@ -151,7 +150,6 @@ MixerDialog::~MixerDialog()
delete ui;
delete gvWeightGroup;
delete gvOffsetGroup;
delete curveGroup;
}
void MixerDialog::changeEvent(QEvent *e)
+2 -2
View File
@@ -25,8 +25,8 @@
#include "eeprominterface.h"
class GVarGroup;
class CurveGroup;
class RawItemFilteredModel;
class CurveReferenceUIManager;
namespace Ui {
class MixerDialog;
@@ -59,7 +59,7 @@ class MixerDialog : public QDialog {
bool lock;
GVarGroup * gvWeightGroup;
GVarGroup * gvOffsetGroup;
CurveGroup * curveGroup;
CurveReferenceUIManager * curveGroup;
QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES];
};