From 33998c2981ca434b07360c6a2967668b04167d48 Mon Sep 17 00:00:00 2001 From: Neil Horne Date: Sun, 25 Mar 2018 18:44:41 +1100 Subject: [PATCH] Add Companion Outputs context menu (#5665) * Start of cut copy paste delete * Outputs context menu continued * Mods from testing * Add tool tip to channel label --- companion/src/helpers.cpp | 65 +++++--- companion/src/helpers.h | 5 + companion/src/modeledit/channels.cpp | 236 +++++++++++++++++++-------- companion/src/modeledit/channels.h | 33 +++- 4 files changed, 241 insertions(+), 98 deletions(-) diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index b7809bee3..8b2ef1648 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -87,6 +87,9 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo dsb(dynamic_cast(weightSB)), weightCB(weightCB), weight(weight), + deflt(deflt), + mini(mini), + maxi(maxi), step(step), lock(true) { @@ -102,31 +105,7 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo } } - int val; - - if (weight>maxi || weightsetChecked(true); - weightSB->hide(); - weightCB->show(); - } - else { - val = weight; - weightGV->setChecked(false); - weightSB->show(); - weightCB->hide(); - } - - if (sb) { - sb->setMinimum(mini); - sb->setMaximum(maxi); - sb->setValue(val); - } - else { - dsb->setMinimum(mini*step); - dsb->setMaximum(maxi*step); - dsb->setValue(val*step); - } + setWeight(weight); connect(weightSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged())); @@ -157,6 +136,42 @@ void GVarGroup::valuesChanged() } } +void GVarGroup::setWeight(int val) +{ + lock = true; + + int tval; + + if (val>maxi || valsetChecked(true); + weightSB->hide(); + weightCB->setCurrentIndex(weightCB->findData(val)); + if (weightCB->currentIndex() == -1) + weightCB->setCurrentIndex(getCurrentFirmware()->getCapability(Gvars)); + weightCB->show(); + } + else { + tval = val; + weightGV->setChecked(false); + weightSB->show(); + weightCB->hide(); + } + + if (sb) { + sb->setMinimum(mini); + sb->setMaximum(maxi); + sb->setValue(tval); + } + else { + dsb->setMinimum(mini*step); + dsb->setMaximum(maxi*step); + dsb->setValue(tval*step); + } + + lock = false; +} + /* * CurveGroup */ diff --git a/companion/src/helpers.h b/companion/src/helpers.h index 1f62fa205..47cc12f7c 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -66,6 +66,8 @@ class GVarGroup: public QObject { public: GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step=1.0, bool allowGVars=true); + void setWeight(int val); + signals: void valueChanged(); @@ -80,6 +82,9 @@ class GVarGroup: public QObject { QDoubleSpinBox *dsb; QComboBox *weightCB; int & weight; + int deflt; + int mini; + int maxi; double step; bool lock; }; diff --git a/companion/src/modeledit/channels.cpp b/companion/src/modeledit/channels.cpp index 740aa2c99..5347efe54 100644 --- a/companion/src/modeledit/channels.cpp +++ b/companion/src/modeledit/channels.cpp @@ -52,14 +52,14 @@ LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row internalStep *= 10; } - spinbox->setSingleStep(displayStep*internalStep); + spinbox->setSingleStep(displayStep * internalStep); spinbox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - QHBoxLayout * horizontalLayout = new QHBoxLayout(); - QCheckBox * gv = new QCheckBox(tr("GV")); + QHBoxLayout *horizontalLayout = new QHBoxLayout(); + QCheckBox *gv = new QCheckBox(tr("GV")); gv->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); horizontalLayout->addWidget(gv); - QComboBox * cb = new QComboBox(); + QComboBox *cb = new QComboBox(); cb->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); horizontalLayout->addWidget(cb); horizontalLayout->addWidget(spinbox); @@ -73,16 +73,21 @@ LimitsGroup::~LimitsGroup() delete gvarGroup; } +void LimitsGroup::setValue(int val) +{ + gvarGroup->setWeight(val); +} + void LimitsGroup::updateMinMax(int max) { if (spinbox->maximum() == 0) { - spinbox->setMinimum(-max*displayStep); + spinbox->setMinimum(-max * displayStep); if (value < -max) { value = -max; } } if (spinbox->minimum() == 0) { - spinbox->setMaximum(max*displayStep); + spinbox->setMaximum(max * displayStep); if (value > max) { value = max; } @@ -108,7 +113,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera headerLabels << tr("PPM Center"); if (firmware->getCapability(SYMLimits)) headerLabels << tr("Linear Subtrim"); - TableLayout * tableLayout = new TableLayout(this, firmware->getCapability(LogicalSwitches), headerLabels); + TableLayout *tableLayout = new TableLayout(this, firmware->getCapability(LogicalSwitches), headerLabels); s1.report("header"); @@ -118,75 +123,78 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera // Channel label QLabel *label = new QLabel(this); label->setText(tr("CH%1").arg(i+1)); + label->setProperty("index", i); label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); + label->setContextMenuPolicy(Qt::CustomContextMenu); + label->setToolTip(tr("Popup menu available")); + label->setMouseTracking(true); + connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(chn_customContextMenuRequested(QPoint))); tableLayout->addWidget(i, col++, label); // Channel name if (channelNameMaxLen > 0) { - QLineEdit * name = new QLineEdit(this); - name->setProperty("index", i); - name->setMaxLength(channelNameMaxLen); + name[i] = new QLineEdit(this); + name[i]->setProperty("index", i); + name[i]->setMaxLength(channelNameMaxLen); QRegExp rx(CHAR_FOR_NAMES_REGEX); - name->setValidator(new QRegExpValidator(rx, this)); - name->setText(model.limitData[i].name); - connect(name, SIGNAL(editingFinished()), this, SLOT(nameEdited())); - tableLayout->addWidget(i, col++, name); + name[i]->setValidator(new QRegExpValidator(rx, this)); + connect(name[i], SIGNAL(editingFinished()), this, SLOT(nameEdited())); + tableLayout->addWidget(i, col++, name[i]); } // Channel offset - limitsGroups << new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].offset, model, -1000, 1000, 0, this); + chnOffset[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].offset, model, -1000, 1000, 0, this); // Channel min - limitsGroups << new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].min, model, -model.getChannelsMax()*10, 0, -1000, this); + chnMin[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].min, model, -model.getChannelsMax() * 10, 0, -1000, this); // Channel max - limitsGroups << new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].max, model, 0, model.getChannelsMax()*10, 1000, this); + chnMax[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].max, model, 0, model.getChannelsMax() * 10, 1000, this); // Channel inversion - QComboBox * invCB = new QComboBox(this); - invCB->insertItems(0, QStringList() << tr("---") << tr("INV")); - invCB->setProperty("index", i); - invCB->setCurrentIndex((model.limitData[i].revert) ? 1 : 0); - connect(invCB, SIGNAL(currentIndexChanged(int)), this, SLOT(invEdited())); - tableLayout->addWidget(i, col++, invCB); + invCB[i] = new QComboBox(this); + invCB[i]->insertItems(0, QStringList() << tr("---") << tr("INV")); + invCB[i]->setProperty("index", i); + connect(invCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(invEdited())); + tableLayout->addWidget(i, col++, invCB[i]); // Curve if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { - QComboBox * curveCB = new QComboBox(this); - curveCB->setProperty("index", i); + curveCB[i] = new QComboBox(this); + curveCB[i]->setProperty("index", i); int numcurves = firmware->getCapability(NumCurves); for (int j=-numcurves; j<=numcurves; j++) { - curveCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(&model, false), j); + curveCB[i]->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(&model, false), j); } - curveCB->setCurrentIndex(model.limitData[i].curve.value+numcurves); - connect(curveCB, SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited())); - tableLayout->addWidget(i, col++, curveCB); + curveCB[i]->setCurrentIndex(model.limitData[i].curve.value+numcurves); + connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited())); + tableLayout->addWidget(i, col++, curveCB[i]); } // PPM center int ppmCenterMax = firmware->getCapability(PPMCenter); if (ppmCenterMax) { - QSpinBox * center = new QSpinBox(this); - center->setProperty("index", i); - center->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); - center->setSuffix("us"); - center->setMinimum(1500-ppmCenterMax); - center->setMaximum(1500+ppmCenterMax); - center->setValue(1500); - center->setValue(model.limitData[i].ppmCenter + 1500); - connect(center, SIGNAL(editingFinished()), this, SLOT(ppmcenterEdited())); - tableLayout->addWidget(i, col++, center); + centerSB[i] = new QSpinBox(this); + centerSB[i]->setProperty("index", i); + centerSB[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + centerSB[i]->setSuffix("us"); + centerSB[i]->setMinimum(1500 - ppmCenterMax); + centerSB[i]->setMaximum(1500 + ppmCenterMax); + centerSB[i]->setValue(1500); + connect(centerSB[i], SIGNAL(editingFinished()), this, SLOT(ppmcenterEdited())); + tableLayout->addWidget(i, col++, centerSB[i]); } // Symetrical limits if (firmware->getCapability(SYMLimits)) { - QCheckBox * symlimits = new QCheckBox(this); - symlimits->setProperty("index", i); - symlimits->setChecked(model.limitData[i].symetrical); - connect(symlimits, SIGNAL(toggled(bool)), this, SLOT(symlimitsEdited())); - tableLayout->addWidget(i, col++, symlimits); + symlimitsChk[i] = new QCheckBox(this); + symlimitsChk[i]->setProperty("index", i); + symlimitsChk[i]->setChecked(model.limitData[i].symetrical); + connect(symlimitsChk[i], SIGNAL(toggled(bool)), this, SLOT(symlimitsEdited())); + tableLayout->addWidget(i, col++, symlimitsChk[i]); } } + update(); s1.report("add elements"); disableMouseScrolling(); @@ -197,17 +205,27 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera Channels::~Channels() { - foreach(LimitsGroup *group, limitsGroups) { - delete group; + // compiler warning if delete[] + for (int i=0; i(sender()); - int index = ckb->property("index").toInt(); - model->limitData[index].symetrical = (ckb->checkState() ? 1 : 0); - emit modified(); + if (!lock) { + QCheckBox *ckb = qobject_cast(sender()); + int index = ckb->property("index").toInt(); + model->limitData[index].symetrical = (ckb->checkState() ? 1 : 0); + emit modified(); + } } void Channels::nameEdited() @@ -224,34 +242,124 @@ void Channels::refreshExtendedLimits() { int channelMax = model->getChannelsMax(); - foreach(LimitsGroup *group, limitsGroups) { - group->updateMinMax(10*channelMax); + for (int i=0 ; iupdateMinMax(10 * channelMax); + chnMin[i]->updateMinMax(10 * channelMax); + chnMax[i]->updateMinMax(10 * channelMax); } - emit modified(); } void Channels::invEdited() { - QComboBox *cb = qobject_cast(sender()); - int index = cb->property("index").toInt(); - model->limitData[index].revert = cb->currentIndex(); - emit modified(); + if (!lock) { + QComboBox *cb = qobject_cast(sender()); + int index = cb->property("index").toInt(); + model->limitData[index].revert = cb->currentIndex(); + emit modified(); + } } void Channels::curveEdited() { - QComboBox *cb = qobject_cast(sender()); - int index = cb->property("index").toInt(); - model->limitData[index].curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt()); - emit modified(); + if (!lock) { + QComboBox *cb = qobject_cast(sender()); + int index = cb->property("index").toInt(); + model->limitData[index].curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt()); + emit modified(); + } } void Channels::ppmcenterEdited() { - QSpinBox *sb = qobject_cast(sender()); - int index = sb->property("index").toInt(); - model->limitData[index].ppmCenter = sb->value() - 1500; + if (!lock) { + QSpinBox *sb = qobject_cast(sender()); + int index = sb->property("index").toInt(); + model->limitData[index].ppmCenter = sb->value() - 1500; + emit modified(); + } +} + +void Channels::update() +{ + for (int i=0; igetCapability(Outputs); i++) { + updateLine(i); + } +} + +void Channels::updateLine(int i) +{ + lock = true; + if (firmware->getCapability(ChannelsName) > 0) { + name[i]->setText(model->limitData[i].name); + } + chnOffset[i]->setValue(model->limitData[i].offset); + chnMin[i]->setValue(model->limitData[i].min); + chnMax[i]->setValue(model->limitData[i].max); + invCB[i]->setCurrentIndex((model->limitData[i].revert) ? 1 : 0); + if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { + curveCB[i]->setCurrentIndex(model->limitData[i].curve.value + firmware->getCapability(NumCurves)); + } + if (firmware->getCapability(PPMCenter)) { + centerSB[i]->setValue(model->limitData[i].ppmCenter + 1500); + } + if (firmware->getCapability(SYMLimits)) { + symlimitsChk[i]->setChecked(model->limitData[i].symetrical); + } + lock = false; +} + +void Channels::chnPaste() +{ + const QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + if (mimeData->hasFormat("application/x-companion-chn")) { + QByteArray chnData = mimeData->data("application/x-companion-chn"); + LimitData *chn = &model->limitData[selectedChannel]; + memcpy(chn, chnData.constData(), sizeof(LimitData)); + updateLine(selectedChannel); + emit modified(); + } +} + +void Channels::chnDelete() +{ + model->limitData[selectedChannel].clear(); + updateLine(selectedChannel); emit modified(); } +void Channels::chnCopy() +{ + QByteArray chnData; + chnData.append((char*)&model->limitData[selectedChannel],sizeof(LimitData)); + QMimeData *mimeData = new QMimeData; + mimeData->setData("application/x-companion-chn", chnData); + QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard); +} + +void Channels::chnCut() +{ + chnCopy(); + chnDelete(); +} + +void Channels::chn_customContextMenuRequested(QPoint pos) +{ + QLabel *label = (QLabel *)sender(); + selectedChannel = 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-chn"); + + QMenu contextMenu; + contextMenu.addAction(CompanionIcon("copy.png"), tr("&Copy"),this,SLOT(chnCopy())); + contextMenu.addAction(CompanionIcon("cut.png"), tr("&Cut"),this,SLOT(chnCut())); + contextMenu.addAction(CompanionIcon("paste.png"), tr("&Paste"),this,SLOT(chnPaste()))->setEnabled(hasData); + contextMenu.addAction(CompanionIcon("clear.png"), tr("&Delete"),this,SLOT(chnDelete())); + + contextMenu.exec(globalPos); +} diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h index 38746f4c6..a13fa84a6 100644 --- a/companion/src/modeledit/channels.h +++ b/companion/src/modeledit/channels.h @@ -33,16 +33,17 @@ class LimitsGroup Q_DECLARE_TR_FUNCTIONS(LimitsGroup) public: - LimitsGroup(Firmware * firmware, TableLayout *tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel=NULL); + LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel=NULL); ~LimitsGroup(); + void setValue(int val); void updateMinMax(int max); protected: - Firmware * firmware; - QDoubleSpinBox * spinbox; - GVarGroup * gvarGroup; - int & value; + Firmware *firmware; + QDoubleSpinBox *spinbox; + GVarGroup *gvarGroup; + int &value; double displayStep; }; @@ -51,12 +52,9 @@ class Channels : public ModelPanel Q_OBJECT public: - Channels(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + Channels(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); ~Channels(); - private: - QVector limitsGroups; - public slots: void refreshExtendedLimits(); @@ -66,7 +64,24 @@ class Channels : public ModelPanel void invEdited(); void curveEdited(); void ppmcenterEdited(); + void update(); + void updateLine(int index); + void chnDelete(); + void chnCopy(); + void chnPaste(); + void chnCut(); + void chn_customContextMenuRequested(QPoint pos); + private: + QLineEdit *name[CPN_MAX_CHNOUT]; + LimitsGroup *chnOffset[CPN_MAX_CHNOUT]; + LimitsGroup *chnMin[CPN_MAX_CHNOUT]; + LimitsGroup *chnMax[CPN_MAX_CHNOUT]; + QComboBox *invCB[CPN_MAX_CHNOUT]; + QComboBox *curveCB[CPN_MAX_CHNOUT]; + QSpinBox *centerSB[CPN_MAX_CHNOUT]; + QCheckBox *symlimitsChk[CPN_MAX_CHNOUT]; + int selectedChannel; }; #endif // _CHANNELS_H_