400 lines
15 KiB
C++
400 lines
15 KiB
C++
#include "customswitches.h"
|
|
#include <QLabel>
|
|
#include <QLineEdit>
|
|
#include <QSpinBox>
|
|
#include <QComboBox>
|
|
#include <QCheckBox>
|
|
#include <QDoubleSpinBox>
|
|
#include "helpers.h"
|
|
|
|
CustomSwitchesPanel::CustomSwitchesPanel(QWidget * parent, ModelData & model):
|
|
ModelPanel(parent, model),
|
|
selectedSwitch(0)
|
|
{
|
|
QGridLayout * gridLayout = new QGridLayout(this);
|
|
|
|
int col = 1;
|
|
addLabel(gridLayout, tr("Function"), col++);
|
|
addLabel(gridLayout, tr("V1"), col++);
|
|
addLabel(gridLayout, tr("V2"), col++);
|
|
addLabel(gridLayout, tr("AND"), col++);
|
|
if (GetEepromInterface()->getCapability(CustomSwitchesExt)) {
|
|
addLabel(gridLayout, tr("Duration"), col++);
|
|
addLabel(gridLayout, tr("Delay"), col++);
|
|
}
|
|
|
|
lock = true;
|
|
for (int i=0; i<GetEepromInterface()->getCapability(CustomSwitches); i++) {
|
|
// The label
|
|
QLabel * label = new QLabel(this);
|
|
label->setProperty("index", i);
|
|
if (i < 9)
|
|
label->setText(tr("CS%1").arg(i+1));
|
|
else
|
|
label->setText(tr("CS%1").arg(QChar('A'+i-9)));
|
|
label->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
label->setMouseTracking(true);
|
|
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(csw_customContextMenuRequested(QPoint)));
|
|
gridLayout->addWidget(label, i+1, 0);
|
|
|
|
// The function
|
|
csw[i] = new QComboBox(this);
|
|
csw[i]->setProperty("index", i);
|
|
connect(csw[i], SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
|
|
gridLayout->addWidget(csw[i], i+1, 1);
|
|
|
|
// V1
|
|
cswitchSource1[i] = new QComboBox(this);
|
|
cswitchSource1[i]->setProperty("index",i);
|
|
connect(cswitchSource1[i], SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
|
|
gridLayout->addWidget(cswitchSource1[i], i+1, 2);
|
|
cswitchSource1[i]->setVisible(false);
|
|
cswitchValue[i] = new QDoubleSpinBox(this);
|
|
cswitchValue[i]->setMaximum(125);
|
|
cswitchValue[i]->setMinimum(-125);
|
|
cswitchValue[i]->setAccelerated(true);
|
|
cswitchValue[i]->setDecimals(0);
|
|
cswitchValue[i]->setProperty("index", i);
|
|
connect(cswitchValue[i], SIGNAL(editingFinished()), this, SLOT(edited()));
|
|
gridLayout->addWidget(cswitchValue[i], i+1, 2);
|
|
cswitchValue[i]->setVisible(false);
|
|
|
|
// V2
|
|
cswitchSource2[i] = new QComboBox(this);
|
|
cswitchSource2[i]->setProperty("index", i);
|
|
connect(cswitchSource2[i], SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
|
|
gridLayout->addWidget(cswitchSource2[i], i+1, 3);
|
|
cswitchSource2[i]->setVisible(false);
|
|
cswitchOffset[i] = new QDoubleSpinBox(this);
|
|
cswitchOffset[i]->setProperty("index",i);
|
|
cswitchOffset[i]->setMaximum(125);
|
|
cswitchOffset[i]->setMinimum(-125);
|
|
cswitchOffset[i]->setAccelerated(true);
|
|
cswitchOffset[i]->setDecimals(0);
|
|
connect(cswitchOffset[i], SIGNAL(editingFinished()), this, SLOT(edited()));
|
|
gridLayout->addWidget(cswitchOffset[i], i+1, 3);
|
|
cswitchOffset[i]->setVisible(false);
|
|
|
|
// AND
|
|
cswitchAnd[i] = new QComboBox(this);
|
|
cswitchAnd[i]->setProperty("index", i);
|
|
connect(cswitchAnd[i], SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
|
|
gridLayout->addWidget(cswitchAnd[i], i+1, 4);
|
|
cswitchAnd[i]->setVisible(false);
|
|
|
|
if (GetEepromInterface()->getCapability(CustomSwitchesExt)) {
|
|
// Duration
|
|
cswitchDuration[i] = new QDoubleSpinBox(this);
|
|
cswitchDuration[i]->setProperty("index", i);
|
|
cswitchDuration[i]->setSingleStep(0.5);
|
|
cswitchDuration[i]->setMaximum(50);
|
|
cswitchDuration[i]->setMinimum(0);
|
|
cswitchDuration[i]->setAccelerated(true);
|
|
cswitchDuration[i]->setDecimals(1);
|
|
connect(cswitchDuration[i],SIGNAL(editingFinished()), this, SLOT(edited()));
|
|
gridLayout->addWidget(cswitchDuration[i], i+1, 5);
|
|
cswitchDuration[i]->setVisible(false);
|
|
|
|
// Delay
|
|
cswitchDelay[i] = new QDoubleSpinBox(this);
|
|
cswitchDelay[i]->setProperty("index", i);
|
|
cswitchDelay[i]->setSingleStep(0.5);
|
|
cswitchDelay[i]->setMaximum(50);
|
|
cswitchDelay[i]->setMinimum(0);
|
|
cswitchDelay[i]->setAccelerated(true);
|
|
cswitchDelay[i]->setDecimals(1);
|
|
connect(cswitchDelay[i], SIGNAL(editingFinished()), this, SLOT(edited()));
|
|
gridLayout->addWidget(cswitchDelay[i], i+1, 6);
|
|
cswitchDelay[i]->setVisible(false);
|
|
}
|
|
}
|
|
|
|
lock = false;
|
|
}
|
|
|
|
CustomSwitchesPanel::~CustomSwitchesPanel()
|
|
{
|
|
}
|
|
|
|
void CustomSwitchesPanel::edited()
|
|
{
|
|
if (!lock) {
|
|
lock = true;
|
|
int i = sender()->property("index").toInt();
|
|
bool chAr;
|
|
float value, step;
|
|
int newval;
|
|
chAr = (getCSFunctionFamily(model.customSw[i].func) != getCSFunctionFamily(csw[i]->itemData(csw[i]->currentIndex()).toInt()));
|
|
model.customSw[i].func = csw[i]->itemData(csw[i]->currentIndex()).toInt();
|
|
if(chAr) {
|
|
if (getCSFunctionFamily(model.customSw[i].func)==CS_FAMILY_TIMERS) {
|
|
model.customSw[i].val1 = -119;
|
|
model.customSw[i].val2 = -119;
|
|
} else {
|
|
model.customSw[i].val1 = 0;
|
|
model.customSw[i].val2 = 0;
|
|
}
|
|
model.customSw[i].andsw = 0;
|
|
setSwitchWidgetVisibility(i);
|
|
}
|
|
if (GetEepromInterface()->getCapability(CustomSwitchesExt)) {
|
|
model.customSw[i].duration= (uint8_t)round(cswitchDuration[i]->value()*2);
|
|
model.customSw[i].delay= (uint8_t)round(cswitchDelay[i]->value()*2);
|
|
}
|
|
RawSource source;
|
|
switch (getCSFunctionFamily(model.customSw[i].func))
|
|
{
|
|
case (CS_FAMILY_VOFS):
|
|
if (model.customSw[i].val1 != cswitchSource1[i]->itemData(cswitchSource1[i]->currentIndex()).toInt()) {
|
|
source=RawSource(model.customSw[i].val1);
|
|
model.customSw[i].val1 = cswitchSource1[i]->itemData(cswitchSource1[i]->currentIndex()).toInt();
|
|
RawSource newSource = RawSource(model.customSw[i].val1);
|
|
if (newSource.type == SOURCE_TYPE_TELEMETRY) {
|
|
if (model.customSw[i].func>CS_FN_ELESS && model.customSw[i].func<CS_FN_VEQUAL) {
|
|
model.customSw[i].val2 = 0;
|
|
} else {
|
|
model.customSw[i].val2 = -128;
|
|
}
|
|
} else {
|
|
if (model.customSw[i].func>CS_FN_ELESS && model.customSw[i].func<CS_FN_VEQUAL) {
|
|
model.customSw[i].val2 = (cswitchOffset[i]->value()/source.getStep(model));
|
|
} else {
|
|
model.customSw[i].val2 = ((cswitchOffset[i]->value()-source.getOffset(model))/source.getStep(model))-source.getRawOffset(model);
|
|
}
|
|
}
|
|
setSwitchWidgetVisibility(i);
|
|
} else {
|
|
source=RawSource(model.customSw[i].val1);
|
|
if (model.customSw[i].func>CS_FN_ELESS && model.customSw[i].func<CS_FN_VEQUAL) {
|
|
model.customSw[i].val2 = (cswitchOffset[i]->value()/source.getStep(model));
|
|
cswitchOffset[i]->setValue(model.customSw[i].val2*source.getStep(model));
|
|
} else {
|
|
model.customSw[i].val2 = ((cswitchOffset[i]->value()-source.getOffset(model))/source.getStep(model))-source.getRawOffset(model);
|
|
cswitchOffset[i]->setValue((model.customSw[i].val2 +source.getRawOffset(model))*source.getStep(model)+source.getOffset(model));
|
|
}
|
|
}
|
|
break;
|
|
case (CS_FAMILY_TIMERS): {
|
|
value=cswitchOffset[i]->value();
|
|
newval=TimToVal(value);
|
|
if (newval>model.customSw[i].val2) {
|
|
if (value >=60) {
|
|
value=round(value);
|
|
step=1;
|
|
} else if (value>=2) {
|
|
value=(round(value*2.0)/2);
|
|
step=0.5;
|
|
} else {
|
|
step=0.1;
|
|
}
|
|
} else {
|
|
if (value <=2) {
|
|
step=0.1;
|
|
} else if (value<=60) {
|
|
value=(round(value*2.0)/2);
|
|
step=0.5;
|
|
} else {
|
|
value=round(value);
|
|
step=1;
|
|
}
|
|
}
|
|
model.customSw[i].val2=TimToVal(value);
|
|
value=ValToTim(model.customSw[i].val2);
|
|
cswitchOffset[i]->setValue(value);
|
|
cswitchOffset[i]->setSingleStep(step);
|
|
|
|
value=cswitchValue[i]->value();
|
|
newval=TimToVal(value);
|
|
if (newval>model.customSw[i].val1) {
|
|
if (value >=60) {
|
|
value=round(value);
|
|
step=1;
|
|
} else if (value>=2) {
|
|
value=(round(value*2.0)/2);
|
|
step=0.5;
|
|
} else {
|
|
step=0.1;
|
|
}
|
|
} else {
|
|
if (value <=2) {
|
|
step=0.1;
|
|
} else if (value<=60) {
|
|
value=(round(value*2.0)/2);
|
|
step=0.5;
|
|
} else {
|
|
value=round(value);
|
|
step=1;
|
|
}
|
|
}
|
|
model.customSw[i].val1=TimToVal(value);
|
|
value=ValToTim(model.customSw[i].val1);
|
|
cswitchValue[i]->setValue(value);
|
|
cswitchValue[i]->setSingleStep(step);
|
|
break;
|
|
}
|
|
case (CS_FAMILY_VBOOL):
|
|
case (CS_FAMILY_VCOMP):
|
|
model.customSw[i].val1 = cswitchSource1[i]->itemData(cswitchSource1[i]->currentIndex()).toInt();
|
|
model.customSw[i].val2 = cswitchSource2[i]->itemData(cswitchSource2[i]->currentIndex()).toInt();
|
|
break;
|
|
}
|
|
model.customSw[i].andsw = cswitchAnd[i]->itemData(cswitchAnd[i]->currentIndex()).toInt();
|
|
emit modified();
|
|
lock = false;
|
|
}
|
|
}
|
|
|
|
void CustomSwitchesPanel::setSwitchWidgetVisibility(int i)
|
|
{
|
|
RawSource source = RawSource(model.customSw[i].val1);
|
|
switch (getCSFunctionFamily(model.customSw[i].func))
|
|
{
|
|
case CS_FAMILY_VOFS:
|
|
cswitchSource1[i]->setVisible(true);
|
|
cswitchSource2[i]->setVisible(false);
|
|
cswitchValue[i]->setVisible(false);
|
|
cswitchOffset[i]->setVisible(true);
|
|
populateSourceCB(cswitchSource1[i], source, model, POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (GetEepromInterface()->getCapability(GvarsInCS) ? POPULATE_GVARS : 0));
|
|
cswitchOffset[i]->setDecimals(source.getDecimals(model));
|
|
cswitchOffset[i]->setSingleStep(source.getStep(model));
|
|
if (model.customSw[i].func>CS_FN_ELESS && model.customSw[i].func<CS_FN_VEQUAL) {
|
|
cswitchOffset[i]->setMinimum(source.getStep(model)*-127);
|
|
cswitchOffset[i]->setMaximum(source.getStep(model)*127);
|
|
cswitchOffset[i]->setValue(source.getStep(model)*model.customSw[i].val2);
|
|
} else {
|
|
cswitchOffset[i]->setMinimum(source.getMin(model));
|
|
cswitchOffset[i]->setMaximum(source.getMax(model));
|
|
cswitchOffset[i]->setValue(source.getStep(model)*(model.customSw[i].val2+source.getRawOffset(model))+source.getOffset(model));
|
|
}
|
|
break;
|
|
case CS_FAMILY_VBOOL:
|
|
cswitchSource1[i]->setVisible(true);
|
|
cswitchSource2[i]->setVisible(true);
|
|
cswitchValue[i]->setVisible(false);
|
|
cswitchOffset[i]->setVisible(false);
|
|
populateSwitchCB(cswitchSource1[i], RawSwitch(model.customSw[i].val1));
|
|
populateSwitchCB(cswitchSource2[i], RawSwitch(model.customSw[i].val2));
|
|
break;
|
|
case CS_FAMILY_VCOMP:
|
|
cswitchSource1[i]->setVisible(true);
|
|
cswitchSource2[i]->setVisible(true);
|
|
cswitchValue[i]->setVisible(false);
|
|
cswitchOffset[i]->setVisible(false);
|
|
populateSourceCB(cswitchSource1[i], RawSource(model.customSw[i].val1), model, POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (GetEepromInterface()->getCapability(GvarsInCS) ? POPULATE_GVARS : 0));
|
|
populateSourceCB(cswitchSource2[i], RawSource(model.customSw[i].val2), model, POPULATE_SOURCES | POPULATE_TRIMS | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (GetEepromInterface()->getCapability(GvarsInCS) ? POPULATE_GVARS : 0));
|
|
break;
|
|
case CS_FAMILY_TIMERS:
|
|
cswitchSource1[i]->setVisible(false);
|
|
cswitchSource2[i]->setVisible(false);
|
|
cswitchValue[i]->setVisible(true);
|
|
cswitchOffset[i]->setVisible(true);
|
|
cswitchOffset[i]->setDecimals(1);
|
|
cswitchOffset[i]->setMinimum(0.1);
|
|
cswitchOffset[i]->setMaximum(175);
|
|
float value=ValToTim(model.customSw[i].val2);
|
|
cswitchOffset[i]->setSingleStep(0.1);
|
|
if (value>60) {
|
|
cswitchOffset[i]->setSingleStep(1);
|
|
} else if (value>2) {
|
|
cswitchOffset[i]->setSingleStep(0.5);
|
|
}
|
|
cswitchOffset[i]->setValue(value);
|
|
|
|
cswitchValue[i]->setDecimals(1);
|
|
cswitchValue[i]->setMinimum(0.1);
|
|
cswitchValue[i]->setMaximum(175);
|
|
value=ValToTim(model.customSw[i].val1);
|
|
cswitchValue[i]->setSingleStep(0.1);
|
|
if (value>60) {
|
|
cswitchValue[i]->setSingleStep(1);
|
|
} else if (value>2) {
|
|
cswitchValue[i]->setSingleStep(0.5);
|
|
}
|
|
cswitchValue[i]->setValue(value);
|
|
break;
|
|
}
|
|
cswitchAnd[i]->setVisible(true);
|
|
populateSwitchCB(cswitchAnd[i], RawSwitch(model.customSw[i].andsw), POPULATE_AND_SWITCHES);
|
|
if (GetEepromInterface()->getCapability(CustomSwitchesExt)) {
|
|
cswitchDuration[i]->setVisible(true);
|
|
cswitchDuration[i]->setValue(model.customSw[i].duration/2.0);
|
|
cswitchDelay[i]->setVisible(true);
|
|
cswitchDelay[i]->setValue(model.customSw[i].delay/2.0);
|
|
}
|
|
}
|
|
|
|
void CustomSwitchesPanel::update()
|
|
{
|
|
lock = true;
|
|
for (int i=0; i<GetEepromInterface()->getCapability(CustomSwitches); i++) {
|
|
populateCSWCB(csw[i], model.customSw[i].func);
|
|
setSwitchWidgetVisibility(i);
|
|
}
|
|
lock = false;
|
|
}
|
|
|
|
void CustomSwitchesPanel::cswPaste()
|
|
{
|
|
const QClipboard *clipboard = QApplication::clipboard();
|
|
const QMimeData *mimeData = clipboard->mimeData();
|
|
if (mimeData->hasFormat("application/x-companion-csw")) {
|
|
QByteArray cswData = mimeData->data("application/x-companion-csw");
|
|
|
|
CustomSwData *csw = &model.customSw[selectedSwitch];
|
|
memcpy(csw, cswData.mid(0, sizeof(CustomSwData)).constData(), sizeof(CustomSwData));
|
|
emit modified();
|
|
updateSelectedSwitch();
|
|
}
|
|
}
|
|
|
|
void CustomSwitchesPanel::cswDelete()
|
|
{
|
|
model.customSw[selectedSwitch].clear();
|
|
emit modified();
|
|
updateSelectedSwitch();
|
|
}
|
|
|
|
void CustomSwitchesPanel::cswCopy()
|
|
{
|
|
QByteArray cswData;
|
|
cswData.append((char*)&model.customSw[selectedSwitch],sizeof(CustomSwData));
|
|
QMimeData *mimeData = new QMimeData;
|
|
mimeData->setData("application/x-companion-csw", cswData);
|
|
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
|
}
|
|
|
|
void CustomSwitchesPanel::updateSelectedSwitch()
|
|
{
|
|
lock = true;
|
|
populateCSWCB(csw[selectedSwitch], model.customSw[selectedSwitch].func);
|
|
setSwitchWidgetVisibility(selectedSwitch);
|
|
lock = false;
|
|
}
|
|
|
|
void CustomSwitchesPanel::cswCut()
|
|
{
|
|
cswCopy();
|
|
cswDelete();
|
|
}
|
|
|
|
// TODO make something generic here!
|
|
void CustomSwitchesPanel::csw_customContextMenuRequested(QPoint pos)
|
|
{
|
|
QLabel *label = (QLabel *)sender();
|
|
selectedSwitch = label->property("index").toInt();
|
|
|
|
QPoint globalPos = label->mapToGlobal(pos);
|
|
|
|
const QClipboard *clipboard = QApplication::clipboard();
|
|
const QMimeData *mimeData = clipboard->mimeData();
|
|
bool hasData = mimeData->hasFormat("application/x-companion-csw");
|
|
|
|
QMenu contextMenu;
|
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("&Delete"),this,SLOT(cswDelete()),tr("Delete"));
|
|
contextMenu.addAction(CompanionIcon("copy.png"), tr("&Copy"),this,SLOT(cswCopy()),tr("Ctrl+C"));
|
|
contextMenu.addAction(CompanionIcon("cut.png"), tr("&Cut"),this,SLOT(cswCut()),tr("Ctrl+X"));
|
|
contextMenu.addAction(CompanionIcon("paste.png"), tr("&Paste"),this,SLOT(cswPaste()),tr("Ctrl+V"))->setEnabled(hasData);
|
|
|
|
contextMenu.exec(globalPos);
|
|
}
|