feat: Companion - New model curve tab layout, curve edit dialog and mix edit curve view (#1484)
Add curve image and double click to edit to input edit, mix edit and outputs
This commit is contained in:
@@ -66,7 +66,7 @@ qt5_wrap_cpp(firmwares_SRCS ${firmwares_QT})
|
||||
|
||||
add_library(firmwares ${firmwares_SRCS} ${firmwares_HDRS})
|
||||
|
||||
target_link_libraries(firmwares ${CPN_COMMON_LIB} datamodels Qt5::Core Qt5::Xml Qt5::Widgets)
|
||||
target_link_libraries(firmwares ${CPN_COMMON_LIB} datamodels shared Qt5::Core Qt5::Xml Qt5::Widgets)
|
||||
target_link_libraries(firmwares yaml-cpp)
|
||||
|
||||
target_include_directories(firmwares
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "curvedata.h"
|
||||
#include "datahelpers.h"
|
||||
#include "compounditemmodels.h"
|
||||
#include "eeprominterface.h"
|
||||
|
||||
CurveData::CurveData()
|
||||
{
|
||||
@@ -32,6 +34,22 @@ void CurveData::clear(int count)
|
||||
this->count = count;
|
||||
}
|
||||
|
||||
void CurveData::init()
|
||||
{
|
||||
float incr = 200.0 / ((float)count - 1.0);
|
||||
|
||||
// points[0].x must be -100
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i < count - 1)
|
||||
points[i].x = -100 + (int)(incr * i);
|
||||
else
|
||||
points[i].x = 100; // points[count - 1].x must be +100 do not risk a rounding issue using incr
|
||||
|
||||
points[i].y = points[i].x;
|
||||
}
|
||||
}
|
||||
|
||||
bool CurveData::isEmpty() const
|
||||
{
|
||||
CurveData tmp;
|
||||
@@ -42,3 +60,72 @@ QString CurveData::nameToString(const int idx) const
|
||||
{
|
||||
return DataHelpers::getElementName(tr("CV"), idx + 1, name);
|
||||
}
|
||||
|
||||
QString CurveData::typeToString() const
|
||||
{
|
||||
return typeToString(type);
|
||||
}
|
||||
|
||||
// static
|
||||
QString CurveData::typeToString(int value)
|
||||
{
|
||||
switch (value) {
|
||||
case CURVE_TYPE_STANDARD:
|
||||
return tr("Standard");
|
||||
case CURVE_TYPE_CUSTOM:
|
||||
return tr("Custom");
|
||||
default:
|
||||
return CPN_STR_UNKNOWN_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
QString CurveData::pointsToString() const
|
||||
{
|
||||
QString result = "[";
|
||||
|
||||
if (type == CURVE_TYPE_CUSTOM) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
if (j != 0)
|
||||
result.append(", ");
|
||||
result.append(QString("(%1, %2)").arg(points[j].x).arg(points[j].y));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int j = 0; j < count; j++) {
|
||||
if (j != 0)
|
||||
result.append(", ");
|
||||
result.append(QString("%1").arg(points[j].y));
|
||||
}
|
||||
}
|
||||
|
||||
result.append("]");
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
AbstractStaticItemModel * CurveData::typeItemModel()
|
||||
{
|
||||
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
|
||||
mdl->setName("curvedata.type");
|
||||
|
||||
for (int i = 0; i <= CURVE_TYPE_LAST; i++) {
|
||||
mdl->appendToItemList(typeToString(i), i);
|
||||
}
|
||||
|
||||
mdl->loadItemList();
|
||||
return mdl;
|
||||
}
|
||||
|
||||
// static
|
||||
AbstractStaticItemModel * CurveData::pointsItemModel()
|
||||
{
|
||||
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
|
||||
mdl->setName("curvedata.points");
|
||||
|
||||
for (int i = 2; i <= CPN_MAX_POINTS; i++) {
|
||||
mdl->appendToItemList(tr("%1 points").arg(i), i);
|
||||
}
|
||||
|
||||
mdl->loadItemList();
|
||||
return mdl;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class AbstractStaticItemModel;
|
||||
|
||||
class CurvePoint {
|
||||
public:
|
||||
int8_t x;
|
||||
@@ -51,6 +53,12 @@ class CurveData {
|
||||
char name[CURVEDATA_NAME_LEN + 1];
|
||||
|
||||
void clear(int count = 5);
|
||||
void init();
|
||||
bool isEmpty() const;
|
||||
QString nameToString(const int idx) const;
|
||||
QString typeToString() const;
|
||||
QString pointsToString() const;
|
||||
static QString typeToString(int value);
|
||||
static AbstractStaticItemModel * typeItemModel();
|
||||
static AbstractStaticItemModel * pointsItemModel();
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "helpers.h"
|
||||
#include "modeldata.h"
|
||||
#include "filtereditemmodels.h"
|
||||
#include "curveimagewidget.h"
|
||||
#include "curvedialog.h"
|
||||
|
||||
const QString CurveReference::toString(const ModelData * model, bool verbose) const
|
||||
{
|
||||
@@ -82,7 +84,7 @@ int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar)
|
||||
// static
|
||||
QString CurveReference::typeToString(const CurveRefType type)
|
||||
{
|
||||
const QStringList strl = { tr("Diff"), tr("Expo") , tr("Func"), tr("Curve") };
|
||||
const QStringList strl = { tr("Diff"), tr("Expo") , tr("Func"), tr("Custom") };
|
||||
int idx = (int)type;
|
||||
|
||||
if (idx < 0 || idx >= strl.count())
|
||||
@@ -145,7 +147,8 @@ int CurveReference::functionCount()
|
||||
*/
|
||||
|
||||
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB,
|
||||
QComboBox * curveValueCB, CurveReference & curveRef, const ModelData & model,
|
||||
QComboBox * curveValueCB, QLabel * curveLabelImage,
|
||||
CurveReference & curveRef, ModelData & model, CompoundItemModelFactory * sharedItemModels,
|
||||
CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent) :
|
||||
QObject(parent),
|
||||
curveTypeCB(curveTypeCB),
|
||||
@@ -154,9 +157,13 @@ CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheck
|
||||
curveValueCB(curveValueCB),
|
||||
curveRef(curveRef),
|
||||
model(model),
|
||||
sharedItemModels(sharedItemModels),
|
||||
filteredModelFactory(curveRefFilteredFactory),
|
||||
lock(false),
|
||||
filteredModelFactory(curveRefFilteredFactory)
|
||||
curveImageWidget(nullptr)
|
||||
{
|
||||
connectItemModelEvents(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_CURVE));
|
||||
|
||||
hasCapabilityGvars = getCurrentFirmware()->getCapability(Gvars);
|
||||
|
||||
if (curveTypeCB) {
|
||||
@@ -178,6 +185,15 @@ CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheck
|
||||
curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
curveValueCB->setMaxVisibleItems(10);
|
||||
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged()));
|
||||
|
||||
if (curveLabelImage) {
|
||||
curveImageWidget = qobject_cast<CurveImageWidget *>(curveLabelImage);
|
||||
if (curveImageWidget) {
|
||||
curveImageWidget->set(&model, getCurrentFirmware(), sharedItemModels, abs(curveRef.value) - 1, Qt::black, 3);
|
||||
curveImageWidget->setGrid(Qt::gray, 2);
|
||||
connect(curveImageWidget, &CurveImageWidget::doubleClicked, this, &CurveReferenceUIManager::curveImageDoubleClicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
@@ -185,12 +201,13 @@ CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheck
|
||||
|
||||
CurveReferenceUIManager::~CurveReferenceUIManager()
|
||||
{
|
||||
delete filteredModelFactory;
|
||||
|
||||
}
|
||||
|
||||
#define CURVE_REF_UI_GVAR_SHOW (1<<0)
|
||||
#define CURVE_REF_UI_VALUE_SHOW (1<<1)
|
||||
#define CURVE_REF_UI_REF_SHOW (1<<2)
|
||||
#define CURVE_REF_UI_GVAR_SHOW (1 << 0)
|
||||
#define CURVE_REF_UI_VALUE_SHOW (1 << 1)
|
||||
#define CURVE_REF_UI_REF_SHOW (1 << 2)
|
||||
#define CURVE_REF_UI_CURVE_SHOW (1 << 3)
|
||||
|
||||
void CurveReferenceUIManager::update()
|
||||
{
|
||||
@@ -214,20 +231,34 @@ void CurveReferenceUIManager::update()
|
||||
widgetsMask |= CURVE_REF_UI_REF_SHOW;
|
||||
}
|
||||
|
||||
if(curveTypeCB) {
|
||||
if (curveRef.type == CurveReference::CURVE_REF_CUSTOM)
|
||||
widgetsMask |= CURVE_REF_UI_CURVE_SHOW;
|
||||
|
||||
|
||||
if (curveTypeCB) {
|
||||
curveTypeCB->setCurrentIndex(curveTypeCB->findData(curveRef.type));
|
||||
curveTypeCB->show();
|
||||
}
|
||||
if(curveGVarCB)
|
||||
|
||||
if (curveGVarCB)
|
||||
curveGVarCB->setVisible(widgetsMask & CURVE_REF_UI_GVAR_SHOW);
|
||||
if(curveValueSB)
|
||||
|
||||
if (curveValueSB)
|
||||
curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW);
|
||||
if(curveValueCB) {
|
||||
|
||||
if (curveValueCB) {
|
||||
if (curveRef.isValueReference())
|
||||
populateValueCB(curveValueCB);
|
||||
curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW);
|
||||
}
|
||||
|
||||
if (curveValueCB && curveImageWidget) {
|
||||
curveImageWidget->draw();
|
||||
curveImageWidget->setVisible(widgetsMask & CURVE_REF_UI_CURVE_SHOW);
|
||||
}
|
||||
|
||||
emit resized();
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
@@ -244,6 +275,8 @@ void CurveReferenceUIManager::typeChanged(int value)
|
||||
if (!lock) {
|
||||
CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
|
||||
curveRef = CurveReference(type, CurveReference::getDefaultValue(type));
|
||||
if (curveImageWidget && curveRef.type == CurveReference::CURVE_REF_CUSTOM)
|
||||
curveImageWidget->setIndex(abs(curveRef.value) - 1);
|
||||
update();
|
||||
}
|
||||
}
|
||||
@@ -260,6 +293,8 @@ void CurveReferenceUIManager::valueCBChanged()
|
||||
{
|
||||
if (!lock) {
|
||||
curveRef.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
|
||||
if (curveImageWidget && curveRef.type == CurveReference::CURVE_REF_CUSTOM)
|
||||
curveImageWidget->setIndex(abs(curveRef.value) - 1);
|
||||
update();
|
||||
}
|
||||
}
|
||||
@@ -285,3 +320,25 @@ void CurveReferenceUIManager::populateValueCB(QComboBox * cb)
|
||||
cb->setCurrentIndex(cb->findData(curveRef.value));
|
||||
}
|
||||
}
|
||||
|
||||
void CurveReferenceUIManager::curveImageDoubleClicked()
|
||||
{
|
||||
if (curveRef.type == CurveReference::CURVE_REF_CUSTOM && abs(curveRef.value) > 0)
|
||||
curveImageWidget->edit();
|
||||
}
|
||||
|
||||
void CurveReferenceUIManager::connectItemModelEvents(const FilteredItemModel * itemModel)
|
||||
{
|
||||
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &CurveReferenceUIManager::onItemModelAboutToBeUpdated);
|
||||
connect(itemModel, &FilteredItemModel::updateComplete, this, &CurveReferenceUIManager::onItemModelUpdateComplete);
|
||||
}
|
||||
|
||||
void CurveReferenceUIManager::onItemModelAboutToBeUpdated()
|
||||
{
|
||||
lock = true;
|
||||
}
|
||||
|
||||
void CurveReferenceUIManager::onItemModelUpdateComplete()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -18,18 +18,20 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef CURVEREFERENCE_H
|
||||
#define CURVEREFERENCE_H
|
||||
#pragma once
|
||||
|
||||
#include <QtCore>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
|
||||
class ModelData;
|
||||
class CurveRefFilteredFactory;
|
||||
class CompoundItemModelFactory;
|
||||
class FilteredItemModel;
|
||||
class CurveImageWidget;
|
||||
|
||||
class CurveReference {
|
||||
|
||||
@@ -90,21 +92,27 @@ class CurveReferenceUIManager : public QObject {
|
||||
|
||||
public:
|
||||
explicit CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB,
|
||||
CurveReference & curve, const ModelData & model, CurveRefFilteredFactory * curveRefFilteredFactory,
|
||||
QObject * parent = nullptr);
|
||||
QLabel *curveImage, CurveReference & curve, ModelData & model, CompoundItemModelFactory * sharedItemModels,
|
||||
CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr);
|
||||
|
||||
explicit CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model,
|
||||
explicit CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, ModelData & model, CompoundItemModelFactory * sharedItemModels,
|
||||
CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr) :
|
||||
CurveReferenceUIManager(nullptr, nullptr, nullptr, curveValueCB, curve, model, curveRefFilteredFactory, parent) {}
|
||||
CurveReferenceUIManager(nullptr, nullptr, nullptr, curveValueCB, nullptr, curve, model, sharedItemModels, curveRefFilteredFactory, parent) {}
|
||||
|
||||
virtual ~CurveReferenceUIManager();
|
||||
|
||||
signals:
|
||||
void resized();
|
||||
|
||||
protected slots:
|
||||
void gvarCBChanged(int);
|
||||
void typeChanged(int);
|
||||
void valueSBChanged();
|
||||
void valueCBChanged();
|
||||
void update();
|
||||
void curveImageDoubleClicked();
|
||||
void onItemModelAboutToBeUpdated();
|
||||
void onItemModelUpdateComplete();
|
||||
|
||||
private:
|
||||
QComboBox *curveTypeCB;
|
||||
@@ -112,11 +120,14 @@ class CurveReferenceUIManager : public QObject {
|
||||
QSpinBox *curveValueSB;
|
||||
QComboBox *curveValueCB;
|
||||
CurveReference & curveRef;
|
||||
const ModelData & model;
|
||||
bool lock;
|
||||
bool hasCapabilityGvars;
|
||||
ModelData & model;
|
||||
CompoundItemModelFactory *sharedItemModels;
|
||||
CurveRefFilteredFactory *filteredModelFactory;
|
||||
bool lock;
|
||||
CurveImageWidget *curveImageWidget = nullptr;
|
||||
|
||||
bool hasCapabilityGvars;
|
||||
|
||||
void connectItemModelEvents(const FilteredItemModel * itemModel);
|
||||
void populateValueCB(QComboBox * cb);
|
||||
};
|
||||
|
||||
#endif // CURVEREFERENCE_H
|
||||
|
||||
@@ -48,11 +48,6 @@ void YamlReadCurvePoints(const YAML::Node& node, CurveData* curves)
|
||||
}
|
||||
}
|
||||
curve.points[curve.count - 1].x = +100;
|
||||
} else {
|
||||
// Standard curve: X points are generated
|
||||
for (int k = 0; k < curve.count; k++) {
|
||||
curve.points[k].x = -100 + (200 * k) / (curve.count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,18 +584,18 @@ TableLayout::TableLayout(QWidget * parent, int rowCount, const QStringList & hea
|
||||
#endif
|
||||
}
|
||||
|
||||
void TableLayout::addWidget(int row, int column, QWidget * widget)
|
||||
void TableLayout::addWidget(int row, int column, QWidget * widget, Qt::Alignment alignment)
|
||||
{
|
||||
#if defined(TABLE_LAYOUT)
|
||||
QHBoxLayout * layout = new QHBoxLayout(tableWidget);
|
||||
layout->addWidget(widget);
|
||||
addLayout(row, column, layout);
|
||||
#else
|
||||
gridWidget->addWidget(widget, row + 1, column);
|
||||
gridWidget->addWidget(widget, row + 1, column, alignment);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TableLayout::addLayout(int row, int column, QLayout * layout)
|
||||
void TableLayout::addLayout(int row, int column, QLayout * layout, Qt::Alignment alignment)
|
||||
{
|
||||
#if defined(TABLE_LAYOUT)
|
||||
layout->setContentsMargins(1, 3, 1, 3);
|
||||
@@ -603,7 +603,7 @@ void TableLayout::addLayout(int row, int column, QLayout * layout)
|
||||
containerWidget->setLayout(layout);
|
||||
tableWidget->setCellWidget(row, column, containerWidget);
|
||||
#else
|
||||
gridWidget->addLayout(layout, row + 1, column);
|
||||
gridWidget->addLayout(layout, row + 1, column, alignment);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -186,8 +186,8 @@ public:
|
||||
TableLayout(QWidget * parent, int rowCount, const QStringList & headerLabels);
|
||||
// ~TableLayout() ;
|
||||
|
||||
void addWidget(int row, int column, QWidget * widget);
|
||||
void addLayout(int row, int column, QLayout * layout);
|
||||
void addWidget(int row, int column, QWidget * widget, Qt::Alignment alignment = Qt::Alignment());
|
||||
void addLayout(int row, int column, QLayout * layout, Qt::Alignment alignment = Qt::Alignment());
|
||||
|
||||
void resizeColumnsToContents();
|
||||
void setColumnWidth(int col, int width);
|
||||
|
||||
@@ -8,7 +8,6 @@ set(modeledit_NAMES
|
||||
modeledit
|
||||
setup
|
||||
heli
|
||||
curves
|
||||
telemetry
|
||||
expodialog
|
||||
mixerdialog
|
||||
@@ -27,6 +26,7 @@ set(modeledit_SRCS
|
||||
# edge.cpp ## commenting them here avoids a "duplicate target" warning eg. from ninja
|
||||
colorcustomscreens.cpp
|
||||
telemetry_customscreens.cpp
|
||||
curves.cpp
|
||||
)
|
||||
|
||||
set(modeledit_HDRS
|
||||
@@ -40,6 +40,7 @@ set(modeledit_HDRS
|
||||
# node.h
|
||||
colorcustomscreens.h
|
||||
telemetry_customscreens.h
|
||||
curves.h
|
||||
)
|
||||
|
||||
set(modeledit_UIS
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "channels.h"
|
||||
#include "helpers.h"
|
||||
#include "filtereditemmodels.h"
|
||||
#include "curveimagewidget.h"
|
||||
|
||||
LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model,
|
||||
int min, int max, int deflt, FilteredItemModel * gvarModel, ModelPanel * panel):
|
||||
@@ -107,7 +108,7 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
|
||||
}
|
||||
headerLabels << tr("Subtrim") << tr("Min") << tr("Max") << tr("Direction");
|
||||
if (IS_HORUS_OR_TARANIS(firmware->getBoard()))
|
||||
headerLabels << tr("Curve");
|
||||
headerLabels << tr("Curve") << tr("Plot");
|
||||
if (firmware->getCapability(PPMCenter))
|
||||
headerLabels << tr("PPM Center");
|
||||
if (firmware->getCapability(SYMLimits))
|
||||
@@ -159,9 +160,20 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
|
||||
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
|
||||
curveCB[i] = new QComboBox(this);
|
||||
curveCB[i]->setProperty("index", i);
|
||||
curveCB[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
curveCB[i]->setModel(dialogFilteredItemModels->getItemModel(crvid));
|
||||
connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited()));
|
||||
tableLayout->addWidget(i, col++, curveCB[i]);
|
||||
|
||||
curveImage[i] = new CurveImageWidget(this);
|
||||
int crvidx = model.limitData[i].curve.value - 1;
|
||||
QColor pencolor = colors[crvidx >= 0 ? crvidx : Qt::black];
|
||||
curveImage[i]->set(&model, firmware, sharedItemModels, crvidx, pencolor, 3);
|
||||
curveImage[i]->setGrid(Qt::gray, 2);
|
||||
curveImage[i]->setProperty("index", i);
|
||||
curveImage[i]->setFixedSize(QSize(100, 100));
|
||||
connect(curveImage[i], &CurveImageWidget::doubleClicked, this, &ChannelsPanel::on_curveImageDoubleClicked);
|
||||
tableLayout->addWidget(i, col++, curveImage[i]);
|
||||
}
|
||||
|
||||
// PPM center
|
||||
@@ -191,7 +203,9 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
|
||||
|
||||
disableMouseScrolling();
|
||||
tableLayout->resizeColumnsToContents();
|
||||
tableLayout->pushRowsUp(chnCapability+1);
|
||||
tableLayout->pushRowsUp(chnCapability + 1);
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
ChannelsPanel::~ChannelsPanel()
|
||||
@@ -260,8 +274,13 @@ void ChannelsPanel::curveEdited()
|
||||
QComboBox *cb = qobject_cast<QComboBox*>(sender());
|
||||
int index = cb->property("index").toInt();
|
||||
// ignore unnecessary updates that could be triggered by updates to the data model
|
||||
if (model->limitData[index].curve != CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt())) {
|
||||
model->limitData[index].curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt());
|
||||
LimitData &ld = model->limitData[index];
|
||||
if (ld.curve != CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt())) {
|
||||
ld.curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt());
|
||||
curveImage[index]->setIndex(abs(ld.curve.value) - 1);
|
||||
if (abs(ld.curve.value) > 0)
|
||||
curveImage[index]->setPen(colors[abs(ld.curve.value) - 1], 3);
|
||||
updateLine(index);
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
@@ -298,6 +317,13 @@ void ChannelsPanel::updateLine(int i)
|
||||
invCB[i]->setCurrentIndex((chn.revert) ? 1 : 0);
|
||||
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
|
||||
curveCB[i]->setCurrentIndex(curveCB[i]->findData(chn.curve.value));
|
||||
if (chn.curve.value == 0) {
|
||||
curveImage[i]->setVisible(false);
|
||||
}
|
||||
else {
|
||||
curveImage[i]->setVisible(true);
|
||||
curveImage[i]->draw();
|
||||
}
|
||||
}
|
||||
if (firmware->getCapability(PPMCenter)) {
|
||||
centerSB[i]->setValue(chn.ppmCenter + 1500);
|
||||
@@ -468,3 +494,14 @@ void ChannelsPanel::updateItemModels()
|
||||
sharedItemModels->update(AbstractItemModel::IMUE_Channels);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void ChannelsPanel::on_curveImageDoubleClicked()
|
||||
{
|
||||
bool ok = false;
|
||||
int index = sender()->property("index").toInt(&ok);
|
||||
|
||||
if (ok && curveImage[abs(index)]->edit()) {
|
||||
updateLine(index);
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
class CompoundItemModelFactory;
|
||||
class FilteredItemModelFactory;
|
||||
class CurveImageWidget;
|
||||
|
||||
constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel";
|
||||
|
||||
@@ -85,24 +86,28 @@ class ChannelsPanel : public ModelPanel
|
||||
void onCustomContextMenuRequested(QPoint pos);
|
||||
void onItemModelAboutToBeUpdated();
|
||||
void onItemModelUpdateComplete();
|
||||
void on_curveImageDoubleClicked();
|
||||
|
||||
private:
|
||||
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||
bool insertAllowed() const;
|
||||
bool moveDownAllowed() const;
|
||||
bool moveUpAllowed() const;
|
||||
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];
|
||||
CurveImageWidget *curveImage[CPN_MAX_CHNOUT];
|
||||
QSpinBox *centerSB[CPN_MAX_CHNOUT];
|
||||
QCheckBox *symlimitsChk[CPN_MAX_CHNOUT];
|
||||
int selectedIndex;
|
||||
int chnCapability;
|
||||
CompoundItemModelFactory *sharedItemModels;
|
||||
FilteredItemModelFactory *dialogFilteredItemModels;
|
||||
|
||||
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||
bool insertAllowed() const;
|
||||
bool moveDownAllowed() const;
|
||||
bool moveUpAllowed() const;
|
||||
|
||||
void updateItemModels();
|
||||
void connectItemModelEvents(const FilteredItemModel * itemModel);
|
||||
FilteredItemModelFactory *dialogFilteredItemModels;
|
||||
};
|
||||
|
||||
+121
-634
@@ -19,652 +19,140 @@
|
||||
*/
|
||||
|
||||
#include "curves.h"
|
||||
#include "ui_curves.h"
|
||||
#include "node.h"
|
||||
#include "edge.h"
|
||||
#include "curveimagewidget.h"
|
||||
#include "compounditemmodels.h"
|
||||
#include "datahelpers.h"
|
||||
#include "helpers.h"
|
||||
#include "filtereditemmodels.h"
|
||||
|
||||
#define GFX_MARGIN 16
|
||||
|
||||
#define CURVE_COEFF_ENABLE 1
|
||||
#define CURVE_YMID_ENABLE 2
|
||||
#define CURVE_YMIN_ENABLE 4
|
||||
|
||||
float curveLinear(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
float a = (yMax - yMin) / 200.0;
|
||||
return yMin + a * (x + 100.0);
|
||||
}
|
||||
|
||||
float c9xexpou(float point, float coeff)
|
||||
{
|
||||
float x = point * 1024.0 / 100.0;
|
||||
float k = coeff * 256.0 / 100.0;
|
||||
return ((k * x * x * x / (1024 * 1024) + x * (256 - k) + 128) / 256) / 1024.0 * 100;
|
||||
}
|
||||
|
||||
float curveExpo(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
float a = (yMax - yMin) / 100.0;
|
||||
|
||||
x += 100.0;
|
||||
x /= 2.0;
|
||||
|
||||
if (coeff >= 0) {
|
||||
return round(c9xexpou(x, coeff)*a + yMin);
|
||||
}
|
||||
else {
|
||||
coeff = -coeff;
|
||||
x = 100 - x;
|
||||
return round((100.0 - c9xexpou(x, coeff)) * a + yMin);
|
||||
}
|
||||
}
|
||||
|
||||
float curveSymmetricalY(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
bool invert;
|
||||
if (x < 0) {
|
||||
x = -x;
|
||||
invert = 1;
|
||||
}
|
||||
else {
|
||||
invert = 0;
|
||||
}
|
||||
|
||||
float y;
|
||||
if (coeff >= 0) {
|
||||
y = round(c9xexpou(x, coeff) * (yMax / 100.0));
|
||||
}
|
||||
else {
|
||||
coeff = -coeff;
|
||||
x = 100.0 - x;
|
||||
y = round((100.0 - c9xexpou(x, coeff)) * (yMax / 100.0));
|
||||
}
|
||||
|
||||
if (invert) {
|
||||
y = -y;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
float a = (yMax - yMid) / 100.0;
|
||||
|
||||
if (x < 0)
|
||||
x = -x;
|
||||
|
||||
float y;
|
||||
if (coeff >= 0) {
|
||||
y = round(c9xexpou(x, coeff) * a + yMid);
|
||||
}
|
||||
else {
|
||||
coeff = -coeff;
|
||||
x = 100 - x;
|
||||
y = round((100.0 - c9xexpou(x, coeff)) * a + yMid);
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
|
||||
CompoundItemModelFactory * sharedItemModels):
|
||||
CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels):
|
||||
ModelPanel(parent, model, generalSettings, firmware),
|
||||
ui(new Ui::Curves),
|
||||
currentCurve(0),
|
||||
sharedItemModels(sharedItemModels)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
lock = true;
|
||||
|
||||
maxCurves = firmware->getCapability(NumCurves);
|
||||
hasNames = firmware->getCapability(HasCvNames);
|
||||
hasEnhanced = firmware->getCapability(EnhancedCurves);
|
||||
maxPoints = firmware->getCapability(NumCurvePoints);
|
||||
|
||||
if (!hasNames) {
|
||||
ui->curveName->hide();
|
||||
ui->curveNameLabel->hide();
|
||||
}
|
||||
QStringList headerLabels;
|
||||
headerLabels << "#";
|
||||
|
||||
scene = new CustomScene(ui->curvePreview);
|
||||
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
|
||||
connect(scene, SIGNAL(newPoint(int, int)), this, SLOT(onSceneNewPoint(int, int)));
|
||||
headerLabels << tr("Plot") << tr("Details");
|
||||
|
||||
ui->curvePreview->setScene(scene);
|
||||
TableLayout *tableLayout = new TableLayout(this, maxCurves, headerLabels);
|
||||
|
||||
int limit;
|
||||
if (maxCurves > 16) {
|
||||
limit = maxCurves / 2;
|
||||
} else {
|
||||
limit = maxCurves;
|
||||
}
|
||||
for (int i = 0; i < maxCurves; i++) {
|
||||
visibleCurves[i] = false;
|
||||
int col = 0;
|
||||
|
||||
// The edit curve button
|
||||
QPushButton * edit = new QPushButton(this);
|
||||
edit->setProperty("index", i);
|
||||
QLabel *label = new QLabel(this);
|
||||
label->setText(tr("CV%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(onCustomContextMenuRequested(QPoint)));
|
||||
tableLayout->addWidget(i, col++, label);
|
||||
|
||||
QString style = QString(
|
||||
"QPushButton {"
|
||||
#ifdef __GNUC__
|
||||
// creates more compact and likely consistent buttons across OS flavors
|
||||
"background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; border-radius: 2px; border-color: inherit;"
|
||||
#else
|
||||
"background-color: %1; color: white;"
|
||||
#endif
|
||||
"}"
|
||||
"QToolTip { background: white; color: black; }");
|
||||
image[i] = new CurveImageWidget(this);
|
||||
image[i]->set(&model, firmware, sharedItemModels, i, colors[i], 3);
|
||||
image[i]->setGrid(Qt::gray, 2);
|
||||
image[i]->setProperty("index", i);
|
||||
image[i]->setFixedSize(QSize(100, 100));
|
||||
connect(image[i], &CurveImageWidget::doubleClicked, this, &CurvesPanel::on_curveImageDoubleClicked);
|
||||
|
||||
edit->setStyleSheet(style.arg(colors[i].name()));
|
||||
edit->setText(tr("Curve %1").arg(i + 1));
|
||||
edit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
edit->setToolTip(tr("Popup menu available"));
|
||||
connect(edit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onCustomContextMenuRequested(const QPoint&)));
|
||||
connect(edit, SIGNAL(clicked()), this, SLOT(editCurve()));
|
||||
if (i < limit) {
|
||||
ui->curvesLayout->addWidget(edit, i, 1, 1, 1);
|
||||
} else {
|
||||
ui->curvesLayout2->addWidget(edit, i - limit, 2, 1, 1);
|
||||
}
|
||||
tableLayout->addWidget(i, col++, image[i]);
|
||||
|
||||
// The curve plot checkbox
|
||||
QCheckBox * plot = new QCheckBox(this);
|
||||
plot->setProperty("index", i);
|
||||
connect(plot, SIGNAL(toggled(bool)), this, SLOT(plotCurve(bool)));
|
||||
if (i < limit) {
|
||||
ui->curvesLayout->addWidget(plot, i, 2, 1, 1);
|
||||
} else {
|
||||
ui->curvesLayout2->addWidget(plot, i-limit, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
QSpacerItem * item = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
grp[i] = new QWidget(); // layouts are not hideable so use widget as parent for grid
|
||||
|
||||
ui->curvesLayout->addItem(item,limit + 1, 1, 1, 1, 0);
|
||||
if (limit != maxCurves) {
|
||||
QSpacerItem * item2 = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
ui->curvesLayout2->addItem(item2,limit + 1, 1, 1, 1, 0);
|
||||
grid[i] = new QGridLayout(grp[i]);
|
||||
int row = 0;
|
||||
|
||||
grid[i]->addWidget(new QLabel(tr("Name:")), row, 0, Qt::AlignLeft);
|
||||
name[i] = new QLabel();
|
||||
grid[i]->addWidget(name[i], row++, 1, Qt::AlignLeft);
|
||||
|
||||
grid[i]->addWidget(new QLabel(tr("Type:")), row, 0, Qt::AlignLeft);
|
||||
type[i] = new QLabel();
|
||||
grid[i]->addWidget(type[i], row++, 1, Qt::AlignLeft);
|
||||
|
||||
grid[i]->addWidget(new QLabel(tr("Points:")), row, 0, Qt::AlignLeft);
|
||||
numpoints[i] = new QLabel();
|
||||
grid[i]->addWidget(numpoints[i], row, 1);
|
||||
points[i] = new QLabel();
|
||||
grid[i]->addWidget(points[i], row++, 2, Qt::AlignLeft);
|
||||
|
||||
grid[i]->addWidget(new QLabel(tr("Smooth:")), row, 0, Qt::AlignLeft);
|
||||
smooth[i] = new QLabel();
|
||||
grid[i]->addWidget(smooth[i], row++, 1, Qt::AlignLeft);
|
||||
|
||||
tableLayout->addWidget(i, col++, grp[i], Qt::AlignLeft);
|
||||
}
|
||||
|
||||
for (int i = 0; i < CPN_MAX_POINTS; i++) {
|
||||
spnx[i] = new QSpinBox(this);
|
||||
spnx[i]->setProperty("index", i);
|
||||
spnx[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
spnx[i]->setAccelerated(true);
|
||||
connect(spnx[i], SIGNAL(valueChanged(int)), this, SLOT(onPointEdited()));
|
||||
ui->pointsLayout->addWidget(spnx[i], i, 0, 1, 1);
|
||||
tableLayout->resizeColumnsToContents();
|
||||
tableLayout->pushColumnsLeft(headerLabels.count());
|
||||
tableLayout->pushRowsUp(maxCurves + 1);
|
||||
|
||||
spny[i] = new QSpinBox(this);
|
||||
spny[i]->setProperty("index", i);
|
||||
spny[i]->setMinimum(-100);
|
||||
spny[i]->setMaximum(+100);
|
||||
spny[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
spny[i]->setAccelerated(true);
|
||||
connect(spny[i], SIGNAL(valueChanged(int)), this, SLOT(onPointEdited()));
|
||||
ui->pointsLayout->addWidget(spny[i], i, 1, 1, 1);
|
||||
|
||||
bool insert;
|
||||
if (hasEnhanced) {
|
||||
insert = (i >= 1);
|
||||
}
|
||||
else {
|
||||
insert = (i == 2 || i == 4 || i ==8 || i == 16);
|
||||
}
|
||||
if (insert) {
|
||||
ui->curvePoints->addItem(tr("%1 points").arg(i + 1), i + 1);
|
||||
}
|
||||
for (int i = 0; i < CPN_MAX_CURVES; i++) {
|
||||
update(i);
|
||||
}
|
||||
|
||||
addTemplate(tr("Linear"), CURVE_YMIN_ENABLE, curveLinear);
|
||||
addTemplate(tr("Single Expo"), CURVE_COEFF_ENABLE | CURVE_YMIN_ENABLE, curveExpo);
|
||||
addTemplate(tr("Symmetrical f(x)=-f(-x)"), CURVE_COEFF_ENABLE, curveSymmetricalY);
|
||||
addTemplate(tr("Symmetrical f(x)=f(-x)"), CURVE_COEFF_ENABLE | CURVE_YMID_ENABLE, curveSymmetricalX);
|
||||
|
||||
ui->pointSize->setValue(10);
|
||||
ui->pointSize->setMinimum(3);
|
||||
ui->pointSize->setMaximum(20);
|
||||
connect(ui->pointSize, SIGNAL(valueChanged(int)), this, SLOT(onPointSizeEdited()));
|
||||
|
||||
disableMouseScrolling();
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
CurvesPanel::~CurvesPanel()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CurvesPanel::editCurve()
|
||||
{
|
||||
QPushButton *button = (QPushButton *)sender();
|
||||
int index = button->property("index").toInt();
|
||||
setCurrentCurve(index);
|
||||
update();
|
||||
}
|
||||
|
||||
void CurvesPanel::plotCurve(bool checked)
|
||||
{
|
||||
QCheckBox *chk = (QCheckBox *)sender();
|
||||
int index = chk->property("index").toInt();
|
||||
visibleCurves[index] = checked;
|
||||
updateCurve();
|
||||
// compiler warning if delete[]
|
||||
for (int i = 0; i < CPN_MAX_CURVES; i++) {
|
||||
delete image[i];
|
||||
delete name[i];
|
||||
delete type[i];
|
||||
delete numpoints[i];
|
||||
delete points[i];
|
||||
delete smooth[i];
|
||||
delete grid[i];
|
||||
delete grp[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::update()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
if (hasNames) {
|
||||
ui->curveName->setText(model->curves[currentCurve].name);
|
||||
}
|
||||
|
||||
updateCurveType();
|
||||
updateCurve();
|
||||
updateCurvePoints();
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurvesPanel::setCurrentCurve(int index)
|
||||
{
|
||||
currentCurve = index;
|
||||
}
|
||||
|
||||
void CurvesPanel::updateCurveType()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
int index = 0;
|
||||
|
||||
if (hasEnhanced) {
|
||||
index = model->curves[currentCurve].count - 2;
|
||||
}
|
||||
else {
|
||||
ui->curveSmooth->hide();
|
||||
if (model->curves[currentCurve].count == 5)
|
||||
index = 1;
|
||||
else if (model->curves[currentCurve].count == 9)
|
||||
index = 2;
|
||||
else if (model->curves[currentCurve].count == 17)
|
||||
index = 3;
|
||||
}
|
||||
|
||||
ui->curvePoints->setCurrentIndex(index);
|
||||
ui->curveCustom->setCurrentIndex(model->curves[currentCurve].type);
|
||||
ui->curveSmooth->setCurrentIndex(model->curves[currentCurve].smooth);
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurvesPanel::updateCurve()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
Node * nodel = 0;
|
||||
Node * nodex = 0;
|
||||
QColor color;
|
||||
|
||||
scene->clear();
|
||||
|
||||
qreal width = scene->sceneRect().width();
|
||||
qreal height = scene->sceneRect().height();
|
||||
|
||||
qreal centerX = scene->sceneRect().left() + width / 2;
|
||||
qreal centerY = scene->sceneRect().top() + height / 2;
|
||||
|
||||
QGraphicsSimpleTextItem *ti = scene->addSimpleText(tr("Editing curve %1").arg(currentCurve + 1));
|
||||
ti->setPos(3, 3);
|
||||
|
||||
scene->addLine(centerX, GFX_MARGIN, centerX, height + GFX_MARGIN);
|
||||
scene->addLine(GFX_MARGIN, centerY, width + GFX_MARGIN, centerY);
|
||||
|
||||
QPen pen;
|
||||
pen.setWidth(1);
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
|
||||
for (int k = 0; k < maxCurves; k++) {
|
||||
pen.setColor(colors[k]);
|
||||
if (currentCurve != k && visibleCurves[k]) {
|
||||
int numpoints = model->curves[k].count;
|
||||
for (int i = 0; i < numpoints - 1; i++) {
|
||||
if (model->curves[k].type == CurveData::CURVE_TYPE_CUSTOM)
|
||||
scene->addLine(centerX + (qreal)model->curves[k].points[i].x * width / 200,
|
||||
centerY - (qreal)model->curves[k].points[i].y * height / 200,
|
||||
centerX + (qreal)model->curves[k].points[i + 1].x * width / 200,
|
||||
centerY - (qreal)model->curves[k].points[i + 1].y * height / 200, pen);
|
||||
else
|
||||
scene->addLine(GFX_MARGIN + i * width / (numpoints - 1),
|
||||
centerY - (qreal)model->curves[k].points[i].y * height / 200,
|
||||
GFX_MARGIN + (i + 1) * width / (numpoints - 1),
|
||||
centerY - (qreal)model->curves[k].points[i + 1].y * height / 200, pen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int numpoints = model->curves[currentCurve].count;
|
||||
for (int i = 0; i < numpoints; i++) {
|
||||
nodel = nodex;
|
||||
nodex = new Node();
|
||||
nodex->setProperty("index", i);
|
||||
nodex->setColor(colors[currentCurve]);
|
||||
nodex->setBallSize(ui->pointSize->value());
|
||||
nodex->setBallHeight(0);
|
||||
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
|
||||
if (i > 0 && i < numpoints - 1) {
|
||||
nodex->setFixedX(false);
|
||||
nodex->setMinX(model->curves[currentCurve].points[i - 1].x);
|
||||
nodex->setMaxX(model->curves[currentCurve].points[i + 1].x);
|
||||
}
|
||||
else {
|
||||
nodex->setFixedX(true);
|
||||
}
|
||||
nodex->setPos(centerX + (qreal)model->curves[currentCurve].points[i].x * width / 200,
|
||||
centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200);
|
||||
}
|
||||
else {
|
||||
nodex->setFixedX(true);
|
||||
nodex->setPos(GFX_MARGIN + i * width / (numpoints - 1),
|
||||
centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200);
|
||||
}
|
||||
connect(nodex, SIGNAL(moved(int, int)), this, SLOT(onNodeMoved(int, int)));
|
||||
connect(nodex, SIGNAL(focus()), this, SLOT(onNodeFocus()));
|
||||
connect(nodex, SIGNAL(unfocus()), this, SLOT(onNodeUnfocus()));
|
||||
connect(nodex, SIGNAL(deleteMe()), this, SLOT(onNodeDelete()));
|
||||
scene->addItem(nodex);
|
||||
if (i > 0)
|
||||
scene->addItem(new Edge(nodel, nodex));
|
||||
}
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurvesPanel::updateCurvePoints()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
int count = model->curves[currentCurve].count;
|
||||
for (int i = 0; i < count; i++) {
|
||||
spny[i]->show();
|
||||
spny[i]->setValue(model->curves[currentCurve].points[i].y);
|
||||
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
|
||||
spnx[i]->show();
|
||||
if (i == 0 || i == model->curves[currentCurve].count - 1) {
|
||||
spnx[i]->setDisabled(true);
|
||||
spnx[i]->setMaximum(+100);
|
||||
spnx[i]->setMinimum(-100);
|
||||
}
|
||||
else {
|
||||
spnx[i]->setDisabled(false);
|
||||
spnx[i]->setMaximum(model->curves[currentCurve].points[i + 1].x);
|
||||
spnx[i]->setMinimum(model->curves[currentCurve].points[i - 1].x);
|
||||
}
|
||||
spnx[i]->setValue(model->curves[currentCurve].points[i].x);
|
||||
}
|
||||
else {
|
||||
spnx[i]->hide();
|
||||
}
|
||||
}
|
||||
for (int i = count; i < CPN_MAX_POINTS; i++) {
|
||||
spny[i]->hide();
|
||||
spnx[i]->hide();
|
||||
}
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurvesPanel::onPointEdited()
|
||||
{
|
||||
if (!lock) {
|
||||
int index = sender()->property("index").toInt();
|
||||
model->curves[currentCurve].points[index].x = spnx[index]->value();
|
||||
model->curves[currentCurve].points[index].y = spny[index]->value();
|
||||
updateCurve();
|
||||
updateCurvePoints();
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::onNodeMoved(int x, int y)
|
||||
{
|
||||
if (!lock) {
|
||||
lock = true;
|
||||
int index = sender()->property("index").toInt();
|
||||
model->curves[currentCurve].points[index].x = x;
|
||||
model->curves[currentCurve].points[index].y = y;
|
||||
spnx[index]->setValue(x);
|
||||
spny[index]->setValue(y);
|
||||
if (index > 0)
|
||||
spnx[index - 1]->setMaximum(x);
|
||||
if (index < model->curves[currentCurve].count - 1)
|
||||
spnx[index + 1]->setMinimum(x);
|
||||
emit modified();
|
||||
lock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::onNodeFocus()
|
||||
{
|
||||
int index = sender()->property("index").toInt();
|
||||
spny[index]->setFocus();
|
||||
}
|
||||
|
||||
void CurvesPanel::onNodeUnfocus()
|
||||
{
|
||||
int index = sender()->property("index").toInt();
|
||||
spny[index]->clearFocus();
|
||||
updateCurve();
|
||||
}
|
||||
|
||||
bool CurvesPanel::allowCurveType(int points, CurveData::CurveType type)
|
||||
{
|
||||
int totalpoints = 0;
|
||||
for (int i = 0; i < maxCurves; i++) {
|
||||
int cvPoints = (i == currentCurve ? points : model->curves[i].count);
|
||||
CurveData::CurveType cvType = (i == currentCurve ? type : model->curves[i].type);
|
||||
totalpoints += cvPoints + (cvType == CurveData::CURVE_TYPE_CUSTOM ? cvPoints - 2 : 0);
|
||||
update(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalpoints > maxPoints) {
|
||||
QMessageBox::warning(this, "companion", tr("Not enough free points in EEPROM to store the curve."));
|
||||
return false;
|
||||
void CurvesPanel::update(int index)
|
||||
{
|
||||
if (model->curves[index].isEmpty()) {
|
||||
image[index]->setVisible(false);
|
||||
grp[index]->setVisible(false);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
image[index]->setVisible(true);
|
||||
grp[index]->setVisible(true);
|
||||
|
||||
image[index]->draw();
|
||||
name[index]->setText(QString(model->curves[index].name));
|
||||
type[index]->setText(model->curves[index].typeToString());
|
||||
numpoints[index]->setText(QString::number(model->curves[index].count));
|
||||
points[index]->setText(model->curves[index].pointsToString());
|
||||
smooth[index]->setText(DataHelpers::boolToString(model->curves[index].smooth, DataHelpers::BOOL_FMT_YESNO));
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::on_curvePoints_currentIndexChanged(int index)
|
||||
void CurvesPanel::editCurve(int index)
|
||||
{
|
||||
if (!lock) {
|
||||
int numpoints = ((QComboBox *)sender())->itemData(index).toInt();
|
||||
|
||||
if (allowCurveType(numpoints, model->curves[currentCurve].type)) {
|
||||
model->curves[currentCurve].count = numpoints;
|
||||
|
||||
// TODO something better + reuse!
|
||||
for (int i = 0; i < CPN_MAX_POINTS; i++) {
|
||||
model->curves[currentCurve].points[i].x = (i >= numpoints - 1 ? +100 : -100 + (200 * i) / (numpoints - 1));
|
||||
model->curves[currentCurve].points[i].y = 0;
|
||||
}
|
||||
|
||||
update();
|
||||
emit modified();
|
||||
}
|
||||
else {
|
||||
updateCurveType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::on_curveCustom_currentIndexChanged(int index)
|
||||
{
|
||||
if (!lock) {
|
||||
CurveData::CurveType type = (CurveData::CurveType)index;
|
||||
int numpoints = ui->curvePoints->itemData(ui->curvePoints->currentIndex()).toInt();
|
||||
|
||||
if (allowCurveType(model->curves[currentCurve].count, type)) {
|
||||
model->curves[currentCurve].type = type;
|
||||
|
||||
// TODO something better + reuse!
|
||||
for (int i = 0; i < CPN_MAX_POINTS; i++) {
|
||||
model->curves[currentCurve].points[i].x = (i >= numpoints - 1 ? +100 : -100 + (200 * i) / (numpoints - 1));
|
||||
model->curves[currentCurve].points[i].y = 0;
|
||||
}
|
||||
|
||||
update();
|
||||
emit modified();
|
||||
}
|
||||
else {
|
||||
updateCurveType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::on_curveSmooth_currentIndexChanged(int index)
|
||||
{
|
||||
model->curves[currentCurve].smooth = index;
|
||||
update();
|
||||
}
|
||||
|
||||
void CurvesPanel::on_curveName_editingFinished()
|
||||
{
|
||||
if (ui->curveName->text() != model->curves[currentCurve].name) {
|
||||
memset(model->curves[currentCurve].name, 0, sizeof(model->curves[currentCurve].name));
|
||||
strcpy(model->curves[currentCurve].name, ui->curveName->text().toLatin1());
|
||||
updateItemModels();
|
||||
if (image[index]->edit()) {
|
||||
update(index);
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::resizeEvent(QResizeEvent *event)
|
||||
void CurvesPanel::on_curveImageDoubleClicked()
|
||||
{
|
||||
QRect qr = ui->curvePreview->contentsRect();
|
||||
ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width() - GFX_MARGIN * 2, qr.height() - GFX_MARGIN * 2);
|
||||
updateCurve();
|
||||
ModelPanel::resizeEvent(event);
|
||||
}
|
||||
bool ok = false;
|
||||
int index = sender()->property("index").toInt(&ok);
|
||||
|
||||
void CurvesPanel::on_curveType_currentIndexChanged(int index)
|
||||
{
|
||||
unsigned int flags = templates[index].flags;
|
||||
ui->curveCoeffLabel->setVisible(flags & CURVE_COEFF_ENABLE);
|
||||
ui->curveCoeff->setVisible(flags & CURVE_COEFF_ENABLE);
|
||||
ui->yMax->setValue(100);
|
||||
ui->yMidLabel->setVisible(flags & CURVE_YMID_ENABLE);
|
||||
ui->yMid->setVisible(flags & CURVE_YMID_ENABLE);
|
||||
ui->yMid->setValue(0);
|
||||
ui->yMinLabel->setVisible(flags & CURVE_YMIN_ENABLE);
|
||||
ui->yMin->setVisible(flags & CURVE_YMIN_ENABLE);
|
||||
ui->yMin->setValue(-100);
|
||||
}
|
||||
|
||||
void CurvesPanel::addTemplate(QString name, unsigned int flags, curveFunction function)
|
||||
{
|
||||
CurveCreatorTemplate tmpl;
|
||||
tmpl.name = name;
|
||||
tmpl.flags = flags;
|
||||
tmpl.function = function;
|
||||
templates.append(tmpl);
|
||||
ui->curveType->addItem(name);
|
||||
}
|
||||
|
||||
void CurvesPanel::on_curveApply_clicked()
|
||||
{
|
||||
int index = ui->curveType->currentIndex();
|
||||
int numpoints = model->curves[currentCurve].count;
|
||||
|
||||
for (int i = 0; i < numpoints; i++) {
|
||||
float x;
|
||||
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM)
|
||||
x = model->curves[currentCurve].points[i].x;
|
||||
else
|
||||
x = -100.0 + (200.0 / (numpoints - 1)) * i;
|
||||
|
||||
bool apply = false;
|
||||
switch (ui->curveSide->currentIndex()) {
|
||||
case 0:
|
||||
apply = true;
|
||||
break;
|
||||
case 1:
|
||||
if (x >= 0)
|
||||
apply = true;
|
||||
break;
|
||||
case 2:
|
||||
if (x < 0)
|
||||
apply = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (apply) {
|
||||
model->curves[currentCurve].points[i].y = templates[index].function(x, ui->curveCoeff->value(), ui->yMin->value(), ui->yMid->value(),
|
||||
ui->yMax->value());
|
||||
}
|
||||
}
|
||||
|
||||
updateCurve();
|
||||
updateCurvePoints();
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void CurvesPanel::onPointSizeEdited()
|
||||
{
|
||||
if (!lock) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::onNodeDelete()
|
||||
{
|
||||
int index = sender()->property("index").toInt();
|
||||
int numpoints = model->curves[currentCurve].count;
|
||||
if ((model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) && (index > 0) && (index < numpoints-1)) {
|
||||
spny[index]->clearFocus();
|
||||
for (int i=index+1; i<numpoints; i++) {
|
||||
model->curves[currentCurve].points[i-1] = model->curves[currentCurve].points[i];
|
||||
}
|
||||
numpoints--;
|
||||
model->curves[currentCurve].points[numpoints].x = 0;
|
||||
model->curves[currentCurve].points[numpoints].y = 0;
|
||||
model->curves[currentCurve].count = numpoints;
|
||||
update();
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesPanel::onSceneNewPoint(int x, int y)
|
||||
{
|
||||
if ((model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) && (model->curves[currentCurve].count < CPN_MAX_POINTS)) {
|
||||
int newidx = 0;
|
||||
int numpoints = model->curves[currentCurve].count;
|
||||
if (x < model->curves[currentCurve].points[0].x) {
|
||||
newidx = 0;
|
||||
}
|
||||
else if (x > model->curves[currentCurve].points[numpoints - 1].x) {
|
||||
newidx = numpoints;
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < numpoints; i++) {
|
||||
if (x < model->curves[currentCurve].points[i].x) {
|
||||
newidx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
numpoints++;
|
||||
model->curves[currentCurve].count = numpoints;
|
||||
for (int idx = (numpoints - 1); idx > newidx; idx--) {
|
||||
model->curves[currentCurve].points[idx] = model->curves[currentCurve].points[idx - 1];
|
||||
}
|
||||
model->curves[currentCurve].points[newidx].x = x;
|
||||
model->curves[currentCurve].points[newidx].y = y;
|
||||
update();
|
||||
emit modified();
|
||||
}
|
||||
if (ok)
|
||||
editCurve(index);
|
||||
}
|
||||
|
||||
void CurvesPanel::onCustomContextMenuRequested(QPoint pos)
|
||||
@@ -674,10 +162,13 @@ void CurvesPanel::onCustomContextMenuRequested(QPoint pos)
|
||||
QPoint globalPos = button->mapToGlobal(pos);
|
||||
|
||||
QMenu contextMenu;
|
||||
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmCopy()));
|
||||
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmCut()));
|
||||
contextMenu.addAction(CompanionIcon("new.png"), tr("Add"), this, SLOT(cmEdit()))->setEnabled(!curveExists());
|
||||
contextMenu.addAction(CompanionIcon("edit.png"), tr("Edit"), this, SLOT(cmEdit()))->setEnabled(curveExists());
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmCopy()))->setEnabled(curveExists());
|
||||
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmCut()))->setEnabled(curveExists());
|
||||
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmPaste()))->setEnabled(hasClipboardData());
|
||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmClear()));
|
||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmClear()))->setEnabled(curveExists());
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmInsert()))->setEnabled(insertAllowed());
|
||||
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmDelete()));
|
||||
@@ -701,6 +192,11 @@ bool CurvesPanel::hasClipboardData(QByteArray * data) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CurvesPanel::curveExists() const
|
||||
{
|
||||
return !model->curves[selectedIndex].isEmpty();
|
||||
}
|
||||
|
||||
bool CurvesPanel::insertAllowed() const
|
||||
{
|
||||
return ((selectedIndex < maxCurves - 1) && (model->curves[maxCurves - 1].isEmpty()));
|
||||
@@ -708,37 +204,38 @@ bool CurvesPanel::insertAllowed() const
|
||||
|
||||
bool CurvesPanel::moveDownAllowed() const
|
||||
{
|
||||
return selectedIndex < maxCurves - 1;
|
||||
return selectedIndex < maxCurves - 1 && curveExists();
|
||||
}
|
||||
|
||||
bool CurvesPanel::moveUpAllowed() const
|
||||
{
|
||||
return selectedIndex > 0;
|
||||
return selectedIndex > 0 && curveExists();
|
||||
}
|
||||
|
||||
void CurvesPanel::cmClear(bool prompt)
|
||||
{
|
||||
if (prompt) {
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear curve %1:%2. Are you sure?").arg(QString::number(selectedIndex + 1)).arg(model->curves[selectedIndex].name), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
||||
model->curves[selectedIndex].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
|
||||
update();
|
||||
update(selectedIndex);
|
||||
updateItemModels();
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void CurvesPanel::cmClearAll()
|
||||
{
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Curves. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all curves. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < maxCurves; i++) {
|
||||
model->curves[i].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, i);
|
||||
}
|
||||
|
||||
update();
|
||||
updateItemModels();
|
||||
emit modified();
|
||||
@@ -755,7 +252,7 @@ void CurvesPanel::cmCopy()
|
||||
|
||||
void CurvesPanel::cmCut()
|
||||
{
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut curve %1:%2. Are you sure?").arg(QString::number(selectedIndex + 1)).arg(model->curves[selectedIndex].name), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
cmCopy();
|
||||
cmClear(false);
|
||||
@@ -763,23 +260,32 @@ void CurvesPanel::cmCut()
|
||||
|
||||
void CurvesPanel::cmDelete()
|
||||
{
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete curve %1:%2. Are you sure?").arg(QString::number(selectedIndex + 1)).arg(model->curves[selectedIndex].name), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
|
||||
memmove(&model->curves[selectedIndex], &model->curves[selectedIndex + 1], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData));
|
||||
model->curves[maxCurves - 1].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
|
||||
update();
|
||||
for (int i = selectedIndex; i < CPN_MAX_CURVES; i++) {
|
||||
update(i);
|
||||
}
|
||||
updateItemModels();
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void CurvesPanel::cmEdit()
|
||||
{
|
||||
editCurve(selectedIndex);
|
||||
}
|
||||
|
||||
void CurvesPanel::cmInsert()
|
||||
{
|
||||
memmove(&model->curves[selectedIndex + 1], &model->curves[selectedIndex], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData));
|
||||
model->curves[selectedIndex].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
|
||||
update();
|
||||
for (int i = selectedIndex; i < CPN_MAX_CURVES; i++) {
|
||||
update(i);
|
||||
}
|
||||
updateItemModels();
|
||||
emit modified();
|
||||
}
|
||||
@@ -800,7 +306,7 @@ void CurvesPanel::cmPaste()
|
||||
if (hasClipboardData(&data)) {
|
||||
CurveData *cd = &model->curves[selectedIndex];
|
||||
memcpy(cd, data.constData(), sizeof(CurveData));
|
||||
update();
|
||||
update(selectedIndex);
|
||||
updateItemModels();
|
||||
emit modified();
|
||||
}
|
||||
@@ -815,7 +321,8 @@ void CurvesPanel::swapData(int idx1, int idx2)
|
||||
memcpy(cd2, cd1, sizeof(CurveData));
|
||||
memcpy(cd1, &cdtmp, sizeof(CurveData));
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
|
||||
update();
|
||||
update(idx1);
|
||||
update(idx2);
|
||||
updateItemModels();
|
||||
emit modified();
|
||||
}
|
||||
@@ -825,23 +332,3 @@ void CurvesPanel::updateItemModels()
|
||||
{
|
||||
sharedItemModels->update(AbstractItemModel::IMUE_Curves);
|
||||
}
|
||||
|
||||
CustomScene::CustomScene(QGraphicsView * view) :
|
||||
QGraphicsScene(view)
|
||||
{
|
||||
}
|
||||
|
||||
void CustomScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) {
|
||||
QRectF rect = sceneRect();
|
||||
QPointF pos = event->scenePos();
|
||||
QPointF p;
|
||||
p.setX(-100 + ((pos.x() - rect.left()) * 200) / rect.width());
|
||||
p.setY(100 + (rect.top() - pos.y()) * 200 / rect.height());
|
||||
QGraphicsScene::mouseReleaseEvent(event);
|
||||
emit newPoint((int)p.x(), (int)p.y());
|
||||
}
|
||||
else
|
||||
QGraphicsScene::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
@@ -18,111 +18,69 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _CURVES_H_
|
||||
#define _CURVES_H_
|
||||
#pragma once
|
||||
|
||||
#include "constants.h"
|
||||
#include "modeledit.h"
|
||||
#include "eeprominterface.h"
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
|
||||
class CompoundItemModelFactory;
|
||||
|
||||
constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve";
|
||||
constexpr char MIMETYPE_CURVE[] = { "application/x-companion-curve" };
|
||||
|
||||
namespace Ui {
|
||||
class Curves;
|
||||
}
|
||||
|
||||
typedef float (*curveFunction) (float x, float coeff, float yMin, float yMid, float yMax);
|
||||
|
||||
struct CurveCreatorTemplate {
|
||||
QString name;
|
||||
unsigned int flags;
|
||||
curveFunction function;
|
||||
};
|
||||
|
||||
class CustomScene : public QGraphicsScene
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CustomScene(QGraphicsView * view);
|
||||
|
||||
signals:
|
||||
void newPoint(int, int);
|
||||
|
||||
protected:
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event) override;
|
||||
};
|
||||
class CurveImageWidget;
|
||||
|
||||
class CurvesPanel : public ModelPanel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
|
||||
CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
|
||||
CompoundItemModelFactory * sharedItemModels);
|
||||
virtual ~CurvesPanel();
|
||||
|
||||
virtual void update();
|
||||
|
||||
private slots:
|
||||
void editCurve();
|
||||
void plotCurve(bool checked);
|
||||
void on_curveName_editingFinished();
|
||||
void on_curvePoints_currentIndexChanged(int index);
|
||||
void on_curveCustom_currentIndexChanged(int index);
|
||||
void on_curveSmooth_currentIndexChanged(int index);
|
||||
void onPointEdited();
|
||||
void onNodeMoved(int x, int y);
|
||||
void onNodeFocus();
|
||||
void onNodeUnfocus();
|
||||
void on_curveType_currentIndexChanged(int index);
|
||||
void on_curveApply_clicked();
|
||||
void onSceneNewPoint(int x, int y);
|
||||
void onPointSizeEdited();
|
||||
void onNodeDelete();
|
||||
void update();
|
||||
void update(int index);
|
||||
void on_curveImageDoubleClicked();
|
||||
|
||||
void onCustomContextMenuRequested(QPoint pos);
|
||||
void cmClear(bool prompt = true);
|
||||
void cmClearAll();
|
||||
void cmCopy();
|
||||
void cmCut();
|
||||
void cmDelete();
|
||||
void cmEdit();
|
||||
void cmInsert();
|
||||
void cmPaste();
|
||||
void cmMoveDown();
|
||||
void cmMoveUp();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
void addTemplate(QString name, unsigned int flags, curveFunction function);
|
||||
void cmPaste();
|
||||
|
||||
private:
|
||||
Ui::Curves *ui;
|
||||
int currentCurve;
|
||||
bool visibleCurves[CPN_MAX_CURVES];
|
||||
QSpinBox * spnx[CPN_MAX_POINTS];
|
||||
QSpinBox * spny[CPN_MAX_POINTS];
|
||||
QVector<CurveCreatorTemplate> templates;
|
||||
void setCurrentCurve(int index);
|
||||
void updateCurve();
|
||||
void updateCurveType();
|
||||
void updateCurvePoints();
|
||||
bool allowCurveType(int points, CurveData::CurveType type);
|
||||
void setPointY(int i, int x, int y);
|
||||
CustomScene * scene;
|
||||
void editCurve(int index);
|
||||
|
||||
int maxCurves;
|
||||
int hasNames;
|
||||
int hasEnhanced;
|
||||
int maxPoints;
|
||||
int selectedIndex;
|
||||
|
||||
void swapData(int idx1, int idx2);
|
||||
void updateItemModels();
|
||||
|
||||
// context menu
|
||||
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||
bool curveExists() const;
|
||||
bool insertAllowed() const;
|
||||
bool moveDownAllowed() const;
|
||||
bool moveUpAllowed() const;
|
||||
void swapData(int idx1, int idx2);
|
||||
CompoundItemModelFactory * sharedItemModels;
|
||||
void updateItemModels();
|
||||
};
|
||||
int selectedIndex;
|
||||
|
||||
#endif // _CURVES_H_
|
||||
// keep constructor pointer to enable triggering update of item models when curves change
|
||||
CompoundItemModelFactory *sharedItemModels;
|
||||
|
||||
// ui widgets
|
||||
QWidget *grp[CPN_MAX_CURVES];
|
||||
QGridLayout *grid[CPN_MAX_CURVES];
|
||||
CurveImageWidget *image[CPN_MAX_CURVES];
|
||||
QLabel *name[CPN_MAX_CURVES];
|
||||
QLabel *type[CPN_MAX_CURVES];
|
||||
QLabel *numpoints[CPN_MAX_CURVES];
|
||||
QLabel *points[CPN_MAX_CURVES];
|
||||
QLabel *smooth[CPN_MAX_CURVES];
|
||||
};
|
||||
|
||||
@@ -53,13 +53,21 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
|
||||
id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef");
|
||||
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100, 1.0,
|
||||
dialogFilteredItemModels->getItemModel(id));
|
||||
|
||||
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100, 1.0,
|
||||
dialogFilteredItemModels->getItemModel(id));
|
||||
|
||||
curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels,
|
||||
firmware->getCapability(HasInputDiff) ? 0 : FilteredItemModel::PositiveFilter);
|
||||
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model,
|
||||
curveRefFilteredItemModels, this);
|
||||
|
||||
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ui->curveImage, ed->curve, model,
|
||||
sharedItemModels, curveRefFilteredItemModels, this);
|
||||
|
||||
|
||||
connect(curveGroup, &CurveReferenceUIManager::resized, this, [=] () {
|
||||
this->adjustSize();
|
||||
this->adjustSize(); // second call seems to be required when hidden fields otherwise not all padding removed
|
||||
});
|
||||
|
||||
id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch),
|
||||
RawSwitch::MixesContext), "RawSwitch");
|
||||
@@ -143,14 +151,16 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
|
||||
connect(ui->trimCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
|
||||
connect(ui->switchesCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
|
||||
connect(ui->sideCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
|
||||
|
||||
for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
|
||||
connect(cb_fp[i], SIGNAL(toggled(bool)), this, SLOT(valuesChanged()));
|
||||
}
|
||||
|
||||
if (firmware->getCapability(VirtualInputs)) {
|
||||
connect(ui->inputName, SIGNAL(editingFinished()), this, SLOT(valuesChanged()));
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, this, SLOT(shrink()));
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
ExpoDialog::~ExpoDialog()
|
||||
@@ -224,11 +234,6 @@ void ExpoDialog::valuesChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void ExpoDialog::shrink()
|
||||
{
|
||||
resize(0, 0);
|
||||
}
|
||||
|
||||
void ExpoDialog::label_phases_customContextMenuRequested(const QPoint & pos)
|
||||
{
|
||||
QLabel *label = (QLabel *)sender();
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _EXPODIALOG_H_
|
||||
#define _EXPODIALOG_H_
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "eeprominterface.h"
|
||||
@@ -47,7 +46,6 @@ class ExpoDialog : public QDialog {
|
||||
|
||||
private slots:
|
||||
void valuesChanged();
|
||||
void shrink();
|
||||
void label_phases_customContextMenuRequested(const QPoint & pos);
|
||||
void fmClearAll();
|
||||
void fmSetAll();
|
||||
@@ -70,5 +68,3 @@ class ExpoDialog : public QDialog {
|
||||
CurveRefFilteredFactory *curveRefFilteredItemModels;
|
||||
int carryTrimFilterFlags = 0;
|
||||
};
|
||||
|
||||
#endif // _EXPODIALOG_H_
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>394</width>
|
||||
<height>488</height>
|
||||
<width>442</width>
|
||||
<height>411</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@@ -30,6 +30,237 @@
|
||||
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="13" column="1">
|
||||
<widget class="QComboBox" name="sideCB">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>NEG</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>POS</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ALL</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<layout class="QHBoxLayout" name="offsetLayout" stretch="0,0,1,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="offsetGV">
|
||||
<property name="text">
|
||||
<string>GV</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="offsetSB"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="offsetCB">
|
||||
<property name="whatsThis">
|
||||
<string>The source for the mixer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="offsetSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="trimCB"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineName">
|
||||
<property name="maxLength">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_curves">
|
||||
<property name="text">
|
||||
<string>Curve</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Switch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_phases">
|
||||
<property name="text">
|
||||
<string>Flight modes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="sideLabel">
|
||||
<property name="text">
|
||||
<string>Stick Side</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Weight</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,1,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="weightGV">
|
||||
<property name="text">
|
||||
<string>GV</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="weightSB"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="weightCB">
|
||||
<property name="whatsThis">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QComboBox" name="switchesCB">
|
||||
<property name="whatsThis">
|
||||
<string>Switch used to enable the line.
|
||||
If blank then the input is considered to be "ON" all the time.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="offsetLabel">
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="sourceLabel">
|
||||
<property name="text">
|
||||
<string>Source</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="inputNameLabel">
|
||||
<property name="text">
|
||||
<string>Input name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="sourceCB">
|
||||
<property name="whatsThis">
|
||||
<string>Source for the mixer.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="inputName">
|
||||
<property name="maxLength">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="dsbScale">
|
||||
<property name="whatsThis">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblScaleUnit">
|
||||
<property name="text">
|
||||
<string>unit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
@@ -187,25 +418,15 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="inputName">
|
||||
<property name="maxLength">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="offsetLabel">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lblScale">
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
<string>Scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="trimCB"/>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,1,0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,1,0,0">
|
||||
<item>
|
||||
<widget class="QComboBox" name="curveTypeCB">
|
||||
<property name="toolTip">
|
||||
@@ -233,102 +454,27 @@
|
||||
<item>
|
||||
<widget class="QSpinBox" name="curveValueSB"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="sideLabel">
|
||||
<property name="text">
|
||||
<string>Stick Side</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="sourceCB">
|
||||
<property name="whatsThis">
|
||||
<string>Source for the mixer.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<layout class="QHBoxLayout" name="offsetLayout" stretch="0,0,1,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="offsetGV">
|
||||
<property name="text">
|
||||
<string>GV</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="offsetSB"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="offsetCB">
|
||||
<property name="whatsThis">
|
||||
<string>The source for the mixer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="offsetSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<widget class="CurveImageWidget" name="curveImage">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QComboBox" name="sideCB">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>NEG</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>POS</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ALL</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Switch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineName">
|
||||
<property name="maxLength">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="trimLabel">
|
||||
<property name="text">
|
||||
@@ -336,76 +482,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_phases">
|
||||
<property name="text">
|
||||
<string>Flight modes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="inputNameLabel">
|
||||
<property name="text">
|
||||
<string>Input name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,1,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="weightGV">
|
||||
<property name="text">
|
||||
<string>GV</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="weightSB"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="weightCB">
|
||||
<property name="whatsThis">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QComboBox" name="switchesCB">
|
||||
<property name="whatsThis">
|
||||
<string>Switch used to enable the line.
|
||||
If blank then the input is considered to be "ON" all the time.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Weight</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="sourceLabel">
|
||||
<property name="text">
|
||||
<string>Source</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lineNameLabel">
|
||||
<property name="text">
|
||||
@@ -413,78 +489,15 @@ If blank then the input is considered to be "ON" all the time.</string
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_curves">
|
||||
<property name="text">
|
||||
<string>Curve</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lblScale">
|
||||
<property name="text">
|
||||
<string>Scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="dsbScale">
|
||||
<property name="whatsThis">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblScaleUnit">
|
||||
<property name="text">
|
||||
<string>unit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>CurveImageWidget</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>curveimagewidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>inputName</tabstop>
|
||||
<tabstop>lineName</tabstop>
|
||||
|
||||
@@ -55,17 +55,25 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
|
||||
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue()));
|
||||
|
||||
int limit = firmware->getCapability(OffsetWeight);
|
||||
|
||||
id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef");
|
||||
|
||||
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit, 1.0,
|
||||
dialogFilteredItemModels->getItemModel(id));
|
||||
|
||||
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit, 1.0,
|
||||
dialogFilteredItemModels->getItemModel(id));
|
||||
|
||||
curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels,
|
||||
firmware->getCapability(HasMixerExpo) ? 0 : FilteredItemModel::PositiveFilter);
|
||||
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model,
|
||||
curveRefFilteredItemModels, this);
|
||||
|
||||
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ui->curveImage, md->curve,
|
||||
model, sharedItemModels, curveRefFilteredItemModels, this);
|
||||
|
||||
connect(curveGroup, &CurveReferenceUIManager::resized, this, [=] () {
|
||||
this->adjustSize();
|
||||
this->adjustSize(); // second call seems to be required when hidden fields otherwise not all padding removed
|
||||
});
|
||||
|
||||
ui->MixDR_CB->setChecked(md->noExpo == 0);
|
||||
|
||||
@@ -141,9 +149,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
|
||||
ui->delayUpSB->setSingleStep(1.0 / scale);
|
||||
ui->delayUpSB->setDecimals((scale == 1 ? 0 : 1));
|
||||
ui->delayUpSB->setValue((float)md->delayUp / scale);
|
||||
QTimer::singleShot(0, this, SLOT(shrink()));
|
||||
|
||||
valuesChanged();
|
||||
|
||||
connect(ui->mixerName,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
|
||||
connect(ui->sourceCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged()));
|
||||
connect(ui->trimCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged()));
|
||||
@@ -155,9 +163,12 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
|
||||
connect(ui->delayUpSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
|
||||
connect(ui->slowDownSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
|
||||
connect(ui->slowUpSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged()));
|
||||
|
||||
for (int i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
|
||||
connect(cb_fp[i],SIGNAL(toggled(bool)),this,SLOT(valuesChanged()));
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
MixerDialog::~MixerDialog()
|
||||
@@ -216,11 +227,6 @@ void MixerDialog::valuesChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void MixerDialog::shrink()
|
||||
{
|
||||
resize(0, 0);
|
||||
}
|
||||
|
||||
void MixerDialog::label_phases_customContextMenuRequested(const QPoint & pos)
|
||||
{
|
||||
QLabel *label = (QLabel *)sender();
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _MIXERDIALOG_H_
|
||||
#define _MIXERDIALOG_H_
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "eeprominterface.h"
|
||||
@@ -46,7 +45,6 @@ class MixerDialog : public QDialog {
|
||||
|
||||
private slots:
|
||||
void valuesChanged();
|
||||
void shrink();
|
||||
void label_phases_customContextMenuRequested(const QPoint & pos);
|
||||
void fmClearAll();
|
||||
void fmSetAll();
|
||||
@@ -66,5 +64,3 @@ class MixerDialog : public QDialog {
|
||||
FilteredItemModelFactory *dialogFilteredItemModels;
|
||||
CurveRefFilteredFactory *curveRefFilteredItemModels;
|
||||
};
|
||||
|
||||
#endif // _MIXERDIALOG_H_
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>412</width>
|
||||
<height>541</height>
|
||||
<width>527</width>
|
||||
<height>571</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@@ -24,158 +24,9 @@
|
||||
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Delay</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Slow</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QDoubleSpinBox" name="slowUpSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>7.500000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QDoubleSpinBox" name="slowDownSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>7.500000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="delayUpSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="delayDownSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,0">
|
||||
<item row="5" column="0">
|
||||
@@ -587,7 +438,7 @@ If blank then the mix is considered to be "ON" all the time.</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,0,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="curveGVarCB">
|
||||
<property name="text">
|
||||
@@ -605,12 +456,196 @@ If blank then the mix is considered to be "ON" all the time.</string>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="curveValueSB"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="CurveImageWidget" name="curveImage">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>imgage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Delay</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Slow</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QDoubleSpinBox" name="slowUpSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>7.500000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QDoubleSpinBox" name="slowDownSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>7.500000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="delayUpSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="delayDownSB">
|
||||
<property name="whatsThis">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>CurveImageWidget</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>curveimagewidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>mixerName</tabstop>
|
||||
<tabstop>sourceCB</tabstop>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "helpers_html.h"
|
||||
#include "appdata.h"
|
||||
#include "adjustmentreference.h"
|
||||
#include "curveimage.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
@@ -646,55 +647,8 @@ QString ModelPrinter::printCurveName(int idx)
|
||||
|
||||
QString ModelPrinter::printCurve(int idx)
|
||||
{
|
||||
QString result;
|
||||
const CurveData & curve = model.curves[idx];
|
||||
result += (curve.type == CurveData::CURVE_TYPE_CUSTOM) ? tr("Custom") : tr("Standard");
|
||||
result += ", [";
|
||||
if (curve.type == CurveData::CURVE_TYPE_CUSTOM) {
|
||||
for (int j=0; j<curve.count; j++) {
|
||||
if (j != 0)
|
||||
result += ", ";
|
||||
result += QString("(%1, %2)").arg(curve.points[j].x).arg(curve.points[j].y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int j=0; j<curve.count; j++) {
|
||||
if (j != 0)
|
||||
result += ", ";
|
||||
result += QString("%1").arg(curve.points[j].y);
|
||||
}
|
||||
}
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
|
||||
CurveImage::CurveImage():
|
||||
size(200),
|
||||
image(size+1, size+1, QImage::Format_RGB32),
|
||||
painter(&image)
|
||||
{
|
||||
painter.setBrush(QBrush("#FFFFFF"));
|
||||
painter.setPen(QColor(0, 0, 0));
|
||||
painter.drawRect(0, 0, size, size);
|
||||
|
||||
painter.setPen(QColor(0, 0, 0));
|
||||
painter.drawLine(0, size/2, size, size/2);
|
||||
painter.drawLine(size/2, 0, size/2, size);
|
||||
for (int i=0; i<21; i++) {
|
||||
painter.drawLine(size/2-5, (size*i)/(20), size/2+5, (size*i)/(20));
|
||||
painter.drawLine((size*i)/(20), size/2-5, (size*i)/(20), size/2+5);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveImage::drawCurve(const CurveData & curve, QColor color)
|
||||
{
|
||||
painter.setPen(QPen(color, 2, Qt::SolidLine));
|
||||
for (int j=1; j<curve.count; j++) {
|
||||
if (curve.type == CurveData::CURVE_TYPE_CUSTOM)
|
||||
painter.drawLine(size/2+(size*curve.points[j-1].x)/200, size/2-(size*curve.points[j-1].y)/200, size/2+(size*curve.points[j].x)/200, size/2-(size*curve.points[j].y)/200);
|
||||
else
|
||||
painter.drawLine(size*(j-1)/(curve.count-1), size/2-(size*curve.points[j-1].y)/200, size*(j)/(curve.count-1), size/2-(size*curve.points[j].y)/200);
|
||||
}
|
||||
return QString("%1 %2").arg(curve.typeToString()).arg(curve.pointsToString());
|
||||
}
|
||||
|
||||
QString ModelPrinter::createCurveImage(int idx, QTextDocument * document)
|
||||
|
||||
@@ -31,19 +31,6 @@ QString addFont(const QString & input, const QString & color = "", const QString
|
||||
void debugHtml(const QString & html);
|
||||
QString formatTitle(const QString & name);
|
||||
|
||||
class CurveImage
|
||||
{
|
||||
public:
|
||||
CurveImage();
|
||||
void drawCurve(const CurveData & curve, QColor color);
|
||||
const QImage & get() const { return image; }
|
||||
|
||||
protected:
|
||||
int size;
|
||||
QImage image;
|
||||
QPainter painter;
|
||||
};
|
||||
|
||||
class ModelPrinter: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -14,6 +14,12 @@ set(shared_NAMES
|
||||
autoslider
|
||||
autospinbox
|
||||
autotimeedit
|
||||
curveimagewidget
|
||||
curvedialog
|
||||
)
|
||||
|
||||
set(shared_UIS
|
||||
curvedialog.ui
|
||||
)
|
||||
|
||||
foreach(name ${shared_NAMES})
|
||||
@@ -21,13 +27,16 @@ foreach(name ${shared_NAMES})
|
||||
set(shared_HDRS ${shared_HDRS} ${name}.h)
|
||||
endforeach()
|
||||
|
||||
qt5_wrap_ui(shared_SRCS ${shared_UIS})
|
||||
qt5_wrap_cpp(shared_SRCS ${shared_HDRS})
|
||||
|
||||
# add after moc generation to stop warnings
|
||||
set(shared_SRCS ${shared_SRCS}
|
||||
autowidget.h
|
||||
autowidget.cpp
|
||||
curveimage.h
|
||||
curveimage.cpp
|
||||
)
|
||||
|
||||
add_library(shared ${shared_SRCS})
|
||||
target_link_libraries(shared PRIVATE Qt5::Widgets ${CPN_COMMON_LIB})
|
||||
target_link_libraries(shared PRIVATE datamodels Qt5::Widgets ${CPN_COMMON_LIB})
|
||||
|
||||
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include "curvedialog.h"
|
||||
#include "ui_curvedialog.h"
|
||||
#include "../modeledit/node.h"
|
||||
#include "../modeledit/edge.h"
|
||||
#include "helpers.h"
|
||||
#include "filtereditemmodels.h"
|
||||
#include "eeprominterface.h"
|
||||
|
||||
float curveLinear(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
float a = (yMax - yMin) / 200.0;
|
||||
return yMin + a * (x + 100.0);
|
||||
}
|
||||
|
||||
float curveexpou(float point, float coeff)
|
||||
{
|
||||
float x = point * 1024.0 / 100.0;
|
||||
float k = coeff * 256.0 / 100.0;
|
||||
return ((k * x * x * x / (1024 * 1024) + x * (256 - k) + 128) / 256) / 1024.0 * 100;
|
||||
}
|
||||
|
||||
float curveExpo(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
float a = (yMax - yMin) / 100.0;
|
||||
|
||||
x += 100.0;
|
||||
x /= 2.0;
|
||||
|
||||
if (coeff >= 0) {
|
||||
return round(curveexpou(x, coeff)*a + yMin);
|
||||
}
|
||||
else {
|
||||
coeff = -coeff;
|
||||
x = 100 - x;
|
||||
return round((100.0 - curveexpou(x, coeff)) * a + yMin);
|
||||
}
|
||||
}
|
||||
|
||||
float curveSymmetricalY(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
bool invert;
|
||||
if (x < 0) {
|
||||
x = -x;
|
||||
invert = 1;
|
||||
}
|
||||
else {
|
||||
invert = 0;
|
||||
}
|
||||
|
||||
float y;
|
||||
if (coeff >= 0) {
|
||||
y = round(curveexpou(x, coeff) * (yMax / 100.0));
|
||||
}
|
||||
else {
|
||||
coeff = -coeff;
|
||||
x = 100.0 - x;
|
||||
y = round((100.0 - curveexpou(x, coeff)) * (yMax / 100.0));
|
||||
}
|
||||
|
||||
if (invert) {
|
||||
y = -y;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax)
|
||||
{
|
||||
float a = (yMax - yMid) / 100.0;
|
||||
|
||||
if (x < 0)
|
||||
x = -x;
|
||||
|
||||
float y;
|
||||
if (coeff >= 0) {
|
||||
y = round(curveexpou(x, coeff) * a + yMid);
|
||||
}
|
||||
else {
|
||||
coeff = -coeff;
|
||||
x = 100 - x;
|
||||
y = round((100.0 - curveexpou(x, coeff)) * a + yMid);
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
#define GFX_MARGIN 16
|
||||
|
||||
#define CURVE_COEFF_ENABLE 1
|
||||
#define CURVE_YMID_ENABLE 2
|
||||
#define CURVE_YMIN_ENABLE 4
|
||||
|
||||
/*
|
||||
CurveDialog
|
||||
*/
|
||||
|
||||
CurveDialog::CurveDialog(QWidget * parent, ModelData & model, const int curveIdx, Firmware * firmware,
|
||||
CompoundItemModelFactory * sharedItemModels) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::CurveDialog),
|
||||
model(model),
|
||||
curve(model.curves[curveIdx]),
|
||||
curveIdx(curveIdx),
|
||||
sharedItemModels(sharedItemModels)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if (curve.isEmpty())
|
||||
curve.init();
|
||||
|
||||
lock = true;
|
||||
|
||||
maxCurves = firmware->getCapability(NumCurves);
|
||||
maxPoints = firmware->getCapability(NumCurvePoints);
|
||||
|
||||
ui->curveName->setField(curve.name, CURVEDATA_NAME_LEN);
|
||||
connect(ui->curveName, &AutoLineEdit::currentDataChanged, this, &CurveDialog::on_curveNameChanged);
|
||||
on_curveNameChanged();
|
||||
|
||||
dialogFilterFactory = new FilteredItemModelFactory();
|
||||
int id = dialogFilterFactory->registerItemModel(new FilteredItemModel(CurveData::typeItemModel()),
|
||||
"Curve Type");
|
||||
ui->curveType->setModel(dialogFilterFactory->getItemModel(id));
|
||||
ui->curveType->setField((int &)curve.type);
|
||||
connect(ui->curveType, &AutoComboBox::currentDataChanged, this, [&] () { on_curveTypeChanged(ui->curveType->currentIndex()) ;});
|
||||
|
||||
id = dialogFilterFactory->registerItemModel(new FilteredItemModel(CurveData::pointsItemModel()),
|
||||
"Curve Points");
|
||||
|
||||
ui->curvePoints->setModel(dialogFilterFactory->getItemModel(id));
|
||||
ui->curvePoints->setField(curve.count);
|
||||
connect(ui->curvePoints, &AutoComboBox::currentDataChanged, this, [&] () { on_curvePointsChanged(ui->curvePoints->currentIndex()) ;});
|
||||
|
||||
ui->curveSmooth->setField(curve.smooth);
|
||||
connect(ui->curveSmooth, &AutoCheckBox::currentDataChanged, this, [&] () { update() ;});
|
||||
|
||||
scene = new CustomScene(ui->curvePreview);
|
||||
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
|
||||
connect(scene, &CustomScene::newPoint, this, &CurveDialog::onSceneNewPoint);
|
||||
|
||||
ui->curvePreview->setScene(scene);
|
||||
|
||||
for (int i = 0; i < CPN_MAX_POINTS; i++) {
|
||||
spnx[i] = new QSpinBox(this);
|
||||
spnx[i]->setProperty("index", i);
|
||||
spnx[i]->setMinimum(-100);
|
||||
spnx[i]->setMaximum(+100);
|
||||
spnx[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
spnx[i]->setAccelerated(true);
|
||||
connect(spnx[i], QOverload<int>::of(&QSpinBox::valueChanged), this, &CurveDialog::onPointEdited);
|
||||
ui->pointsLayout->addWidget(spnx[i], i, 0, 1, 1);
|
||||
|
||||
spny[i] = new QSpinBox(this);
|
||||
spny[i]->setProperty("index", i);
|
||||
spny[i]->setMinimum(-100);
|
||||
spny[i]->setMaximum(+100);
|
||||
spny[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
spny[i]->setAccelerated(true);
|
||||
connect(spny[i], QOverload<int>::of(&QSpinBox::valueChanged), this, &CurveDialog::onPointEdited);
|
||||
ui->pointsLayout->addWidget(spny[i], i, 1, 1, 1);
|
||||
}
|
||||
|
||||
addTemplate(tr("Linear"), CURVE_YMIN_ENABLE, curveLinear);
|
||||
addTemplate(tr("Single Expo"), CURVE_COEFF_ENABLE | CURVE_YMIN_ENABLE, curveExpo);
|
||||
addTemplate(tr("Symmetrical f(x)=-f(-x)"), CURVE_COEFF_ENABLE, curveSymmetricalY);
|
||||
addTemplate(tr("Symmetrical f(x)=f(-x)"), CURVE_COEFF_ENABLE | CURVE_YMID_ENABLE, curveSymmetricalX);
|
||||
on_curveTemplateChanged(0);
|
||||
|
||||
ui->pointSize->setValue(10);
|
||||
ui->pointSize->setMinimum(3);
|
||||
ui->pointSize->setMaximum(20);
|
||||
connect(ui->pointSize, QOverload<int>::of(&QSpinBox::valueChanged), this, [&] () { if (!lock) update(); });
|
||||
|
||||
connect(ui->curveTemplate, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CurveDialog::on_curveTemplateChanged);
|
||||
connect(ui->curveApply, &QPushButton::clicked, this, &CurveDialog::on_curveApplyClicked);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
connect(this, &QDialog::accepted, this, &CurveDialog::onDialogAccepted);
|
||||
|
||||
update();
|
||||
shrink();
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
CurveDialog::~CurveDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete dialogFilterFactory;
|
||||
}
|
||||
|
||||
void CurveDialog::onDialogAccepted()
|
||||
{
|
||||
model.curves[curveIdx] = curve;
|
||||
if (sharedItemModels)
|
||||
sharedItemModels->update(AbstractItemModel::IMUE_Curves);
|
||||
}
|
||||
|
||||
void CurveDialog::update()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
ui->curveName->update();
|
||||
updateCurveType();
|
||||
updateCurve();
|
||||
updateCurvePoints();
|
||||
shrink();
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurveDialog::updateCurveType()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
ui->curveType->update();
|
||||
ui->curvePoints->update();
|
||||
ui->curveSmooth->update();
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurveDialog::updateCurve()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
Node * nodel = 0;
|
||||
Node * nodex = 0;
|
||||
QColor color;
|
||||
|
||||
scene->clear();
|
||||
|
||||
qreal width = scene->sceneRect().width();
|
||||
qreal height = scene->sceneRect().height();
|
||||
|
||||
qreal leftX = scene->sceneRect().left() + width / 4 * 1;
|
||||
qreal centerX = scene->sceneRect().left() + width / 2;
|
||||
qreal rightX = scene->sceneRect().left() + width / 4 * 3;
|
||||
qreal topY = scene->sceneRect().top() + height / 4 * 1;
|
||||
qreal centerY = scene->sceneRect().top() + height / 2;
|
||||
qreal bottomY = scene->sceneRect().top() + height / 4 * 3;
|
||||
|
||||
scene->addLine(leftX, GFX_MARGIN, leftX, height + GFX_MARGIN);
|
||||
scene->addLine(centerX, GFX_MARGIN, centerX, height + GFX_MARGIN);
|
||||
scene->addLine(rightX, GFX_MARGIN, rightX, height + GFX_MARGIN);
|
||||
scene->addLine(GFX_MARGIN, topY, width + GFX_MARGIN, topY);
|
||||
scene->addLine(GFX_MARGIN, centerY, width + GFX_MARGIN, centerY);
|
||||
scene->addLine(GFX_MARGIN, bottomY, width + GFX_MARGIN, bottomY);
|
||||
|
||||
QPen pen;
|
||||
pen.setWidth(1);
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
|
||||
pen.setColor(colors[0]); // needed????
|
||||
|
||||
int numpoints = curve.count;
|
||||
|
||||
for (int i = 0; i < numpoints - 1; i++) {
|
||||
if (curve.type == CurveData::CURVE_TYPE_CUSTOM)
|
||||
scene->addLine(centerX + (qreal)curve.points[i].x * width / 200,
|
||||
centerY - (qreal)curve.points[i].y * height / 200,
|
||||
centerX + (qreal)curve.points[i + 1].x * width / 200,
|
||||
centerY - (qreal)curve.points[i + 1].y * height / 200, pen);
|
||||
else
|
||||
scene->addLine(GFX_MARGIN + i * width / (numpoints - 1),
|
||||
centerY - (qreal)curve.points[i].y * height / 200,
|
||||
GFX_MARGIN + (i + 1) * width / (numpoints - 1),
|
||||
centerY - (qreal)curve.points[i + 1].y * height / 200, pen);
|
||||
}
|
||||
|
||||
for (int i = 0; i < numpoints; i++) {
|
||||
nodel = nodex;
|
||||
nodex = new Node();
|
||||
nodex->setProperty("index", i);
|
||||
nodex->setColor(colors[0]);
|
||||
nodex->setBallSize(ui->pointSize->value());
|
||||
nodex->setBallHeight(0);
|
||||
if (curve.type == CurveData::CURVE_TYPE_CUSTOM) {
|
||||
if (i > 0 && i < numpoints - 1) {
|
||||
nodex->setFixedX(false);
|
||||
nodex->setMinX(curve.points[i - 1].x);
|
||||
nodex->setMaxX(curve.points[i + 1].x);
|
||||
}
|
||||
else {
|
||||
nodex->setFixedX(true);
|
||||
}
|
||||
nodex->setPos(centerX + (qreal)curve.points[i].x * width / 200,
|
||||
centerY - (qreal)curve.points[i].y * height / 200);
|
||||
}
|
||||
else {
|
||||
nodex->setFixedX(true);
|
||||
nodex->setPos(GFX_MARGIN + i * width / (numpoints - 1),
|
||||
centerY - (qreal)curve.points[i].y * height / 200);
|
||||
}
|
||||
connect(nodex, SIGNAL(moved(int, int)), this, SLOT(onNodeMoved(int, int)));
|
||||
connect(nodex, SIGNAL(focus()), this, SLOT(onNodeFocus()));
|
||||
connect(nodex, SIGNAL(unfocus()), this, SLOT(onNodeUnfocus()));
|
||||
connect(nodex, SIGNAL(deleteMe()), this, SLOT(onNodeDelete()));
|
||||
scene->addItem(nodex);
|
||||
if (i > 0)
|
||||
scene->addItem(new Edge(nodel, nodex));
|
||||
}
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurveDialog::updateCurvePoints()
|
||||
{
|
||||
lock = true;
|
||||
|
||||
int count = curve.count;
|
||||
for (int i = 0; i < count; i++) {
|
||||
spny[i]->show();
|
||||
spny[i]->setValue(curve.points[i].y);
|
||||
if (curve.type == CurveData::CURVE_TYPE_CUSTOM) {
|
||||
spnx[i]->show();
|
||||
if (i == 0 || i == count - 1) {
|
||||
spnx[i]->setDisabled(true);
|
||||
spnx[i]->setMaximum(+100);
|
||||
spnx[i]->setMinimum(-100);
|
||||
}
|
||||
else {
|
||||
spnx[i]->setDisabled(false);
|
||||
spnx[i]->setMaximum(curve.points[i + 1].x);
|
||||
spnx[i]->setMinimum(curve.points[i - 1].x);
|
||||
}
|
||||
spnx[i]->setValue(curve.points[i].x);
|
||||
}
|
||||
else {
|
||||
spnx[i]->hide();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = count; i < CPN_MAX_POINTS; i++) {
|
||||
spny[i]->hide();
|
||||
spnx[i]->hide();
|
||||
}
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
void CurveDialog::onPointEdited(int i)
|
||||
{
|
||||
if (!lock) {
|
||||
int index = sender()->property("index").toInt();
|
||||
curve.points[index].x = spnx[index]->value();
|
||||
curve.points[index].y = spny[index]->value();
|
||||
updateCurve();
|
||||
updateCurvePoints();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDialog::onNodeMoved(int x, int y)
|
||||
{
|
||||
if (!lock) {
|
||||
lock = true;
|
||||
int index = sender()->property("index").toInt();
|
||||
curve.points[index].x = x;
|
||||
curve.points[index].y = y;
|
||||
spnx[index]->setValue(x);
|
||||
spny[index]->setValue(y);
|
||||
if (index > 0)
|
||||
spnx[index - 1]->setMaximum(x);
|
||||
if (index < curve.count - 1)
|
||||
spnx[index + 1]->setMinimum(x);
|
||||
lock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDialog::onNodeFocus()
|
||||
{
|
||||
int index = sender()->property("index").toInt();
|
||||
spny[index]->setFocus();
|
||||
}
|
||||
|
||||
void CurveDialog::onNodeUnfocus()
|
||||
{
|
||||
int index = sender()->property("index").toInt();
|
||||
spny[index]->clearFocus();
|
||||
updateCurve();
|
||||
}
|
||||
|
||||
bool CurveDialog::allowCurveType(int points, CurveData::CurveType type)
|
||||
{
|
||||
int totalpoints = 0;
|
||||
for (int i = 0; i < maxCurves; i++) {
|
||||
int cvPoints = (i == curveIdx ? points : model.curves[i].count);
|
||||
CurveData::CurveType cvType = (i == curveIdx ? type : model.curves[i].type);
|
||||
totalpoints += cvPoints + (cvType == CurveData::CURVE_TYPE_CUSTOM ? cvPoints - 2 : 0);
|
||||
}
|
||||
|
||||
if (totalpoints > maxPoints) {
|
||||
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Not enough free points in global points array to store the curve."));
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDialog::on_curveNameChanged()
|
||||
{
|
||||
setWindowTitle(tr("Editing curve %1: %2").arg(curveIdx + 1).arg(QString(curve.name)));
|
||||
}
|
||||
|
||||
void CurveDialog::on_curvePointsChanged(int index)
|
||||
{
|
||||
if (!lock) {
|
||||
int numpoints = ((QComboBox *)sender())->itemData(index).toInt();
|
||||
|
||||
if (allowCurveType(numpoints, curve.type)) {
|
||||
curve.count = numpoints;
|
||||
curve.init();
|
||||
update();
|
||||
}
|
||||
else {
|
||||
updateCurveType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDialog::on_curveTypeChanged(int index)
|
||||
{
|
||||
if (!lock) {
|
||||
CurveData::CurveType type = (CurveData::CurveType)index;
|
||||
int numpoints = ui->curvePoints->itemData(ui->curvePoints->currentIndex()).toInt();
|
||||
|
||||
if (allowCurveType(numpoints, type)) {
|
||||
//curve.clear(numpoints);
|
||||
curve.type = type;
|
||||
//curve.init();
|
||||
update();
|
||||
}
|
||||
else {
|
||||
updateCurveType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDialog::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QRect qr = ui->curvePreview->contentsRect();
|
||||
ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width() - GFX_MARGIN * 2, qr.height() - GFX_MARGIN * 2);
|
||||
updateCurve();
|
||||
}
|
||||
|
||||
void CurveDialog::on_curveTemplateChanged(int index)
|
||||
{
|
||||
unsigned int flags = templates[index].flags;
|
||||
ui->curveCoeffLabel->setVisible(flags & CURVE_COEFF_ENABLE);
|
||||
ui->curveCoeff->setVisible(flags & CURVE_COEFF_ENABLE);
|
||||
ui->yMax->setValue(100);
|
||||
ui->yMidLabel->setVisible(flags & CURVE_YMID_ENABLE);
|
||||
ui->yMid->setVisible(flags & CURVE_YMID_ENABLE);
|
||||
ui->yMid->setValue(0);
|
||||
ui->yMinLabel->setVisible(flags & CURVE_YMIN_ENABLE);
|
||||
ui->yMin->setVisible(flags & CURVE_YMIN_ENABLE);
|
||||
ui->yMin->setValue(-100);
|
||||
}
|
||||
|
||||
void CurveDialog::addTemplate(QString name, unsigned int flags, curveFunction function)
|
||||
{
|
||||
CurveCreatorTemplate tmpl;
|
||||
tmpl.name = name;
|
||||
tmpl.flags = flags;
|
||||
tmpl.function = function;
|
||||
templates.append(tmpl);
|
||||
ui->curveTemplate->addItem(name);
|
||||
}
|
||||
|
||||
void CurveDialog::on_curveApplyClicked()
|
||||
{
|
||||
int index = ui->curveTemplate->currentIndex();
|
||||
int numpoints = curve.count;
|
||||
|
||||
for (int i = 0; i < numpoints; i++) {
|
||||
float x;
|
||||
if (curve.type == CurveData::CURVE_TYPE_CUSTOM)
|
||||
x = curve.points[i].x;
|
||||
else
|
||||
x = -100.0 + (200.0 / (numpoints - 1)) * i;
|
||||
|
||||
bool apply = false;
|
||||
switch (ui->curveSide->currentIndex()) {
|
||||
case 0:
|
||||
apply = true;
|
||||
break;
|
||||
case 1:
|
||||
if (x >= 0)
|
||||
apply = true;
|
||||
break;
|
||||
case 2:
|
||||
if (x < 0)
|
||||
apply = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (apply) {
|
||||
curve.points[i].y = templates[index].function(x, ui->curveCoeff->value(), ui->yMin->value(), ui->yMid->value(),
|
||||
ui->yMax->value());
|
||||
}
|
||||
}
|
||||
|
||||
updateCurve();
|
||||
updateCurvePoints();
|
||||
}
|
||||
|
||||
void CurveDialog::onNodeDelete()
|
||||
{
|
||||
int index = sender()->property("index").toInt();
|
||||
int numpoints = curve.count;
|
||||
if ((curve.type == CurveData::CURVE_TYPE_CUSTOM) && (index > 0) && (index < numpoints - 1)) {
|
||||
spny[index]->clearFocus();
|
||||
for (int i = index + 1; i < numpoints; i++) {
|
||||
curve.points[i - 1] = curve.points[i];
|
||||
}
|
||||
numpoints--;
|
||||
curve.points[numpoints].x = 0;
|
||||
curve.points[numpoints].y = 0;
|
||||
curve.count = numpoints;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDialog::onSceneNewPoint(int x, int y)
|
||||
{
|
||||
if ((curve.type == CurveData::CURVE_TYPE_CUSTOM) && (curve.count < CPN_MAX_POINTS)) {
|
||||
int newidx = 0;
|
||||
int numpoints = curve.count;
|
||||
if (x < curve.points[0].x) {
|
||||
newidx = 0;
|
||||
}
|
||||
else if (x > curve.points[numpoints - 1].x) {
|
||||
newidx = numpoints;
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < numpoints; i++) {
|
||||
if (x < curve.points[i].x) {
|
||||
newidx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
numpoints++;
|
||||
curve.count = numpoints;
|
||||
for (int idx = (numpoints - 1); idx > newidx; idx--) {
|
||||
curve.points[idx] = curve.points[idx - 1];
|
||||
}
|
||||
curve.points[newidx].x = x;
|
||||
curve.points[newidx].y = y;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDialog::shrink()
|
||||
{
|
||||
resize(0, 0);
|
||||
}
|
||||
|
||||
CustomScene::CustomScene(QGraphicsView * view) :
|
||||
QGraphicsScene(view)
|
||||
{
|
||||
}
|
||||
|
||||
void CustomScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) {
|
||||
QRectF rect = sceneRect();
|
||||
QPointF pos = event->scenePos();
|
||||
QPointF p;
|
||||
p.setX(-100 + ((pos.x() - rect.left()) * 200) / rect.width());
|
||||
p.setY(100 + (rect.top() - pos.y()) * 200 / rect.height());
|
||||
QGraphicsScene::mouseReleaseEvent(event);
|
||||
emit newPoint((int)p.x(), (int)p.y());
|
||||
}
|
||||
else
|
||||
QGraphicsScene::mouseReleaseEvent(event);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "constants.h"
|
||||
#include "modeldata.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
|
||||
class Firmware;
|
||||
class FilteredItemModelFactory;
|
||||
class CompoundItemModelFactory;
|
||||
|
||||
namespace Ui {
|
||||
class CurveDialog;
|
||||
}
|
||||
|
||||
typedef float (*curveFunction) (float x, float coeff, float yMin, float yMid, float yMax);
|
||||
|
||||
struct CurveCreatorTemplate {
|
||||
QString name;
|
||||
unsigned int flags;
|
||||
curveFunction function;
|
||||
};
|
||||
|
||||
class CustomScene : public QGraphicsScene
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CustomScene(QGraphicsView * view);
|
||||
|
||||
signals:
|
||||
void newPoint(int, int);
|
||||
|
||||
protected:
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event) override;
|
||||
};
|
||||
|
||||
class CurveDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CurveDialog(QWidget *parent, ModelData & model, const int curveIdx, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
|
||||
virtual ~CurveDialog();
|
||||
|
||||
private slots:
|
||||
void shrink();
|
||||
void on_curveNameChanged();
|
||||
void on_curvePointsChanged(int index);
|
||||
void on_curveTypeChanged(int index);
|
||||
void onPointEdited(int i);
|
||||
void onNodeMoved(int x, int y);
|
||||
void onNodeFocus();
|
||||
void onNodeUnfocus();
|
||||
void on_curveTemplateChanged(int index);
|
||||
void on_curveApplyClicked();
|
||||
void onSceneNewPoint(int x, int y);
|
||||
void onNodeDelete();
|
||||
void onDialogAccepted();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
void addTemplate(QString name, unsigned int flags, curveFunction function);
|
||||
|
||||
private:
|
||||
Ui::CurveDialog *ui;
|
||||
ModelData &model;
|
||||
CurveData curve; // copy initialised in constructor and copied back to model if dialog is accepted
|
||||
const int curveIdx;
|
||||
CompoundItemModelFactory *sharedItemModels;
|
||||
|
||||
QSpinBox *spnx[CPN_MAX_POINTS];
|
||||
QSpinBox *spny[CPN_MAX_POINTS];
|
||||
QVector<CurveCreatorTemplate> templates;
|
||||
CustomScene *scene;
|
||||
int maxCurves;
|
||||
int maxPoints;
|
||||
bool lock;
|
||||
FilteredItemModelFactory * dialogFilterFactory;
|
||||
|
||||
void update();
|
||||
void updateCurve();
|
||||
void updateCurveType();
|
||||
void updateCurvePoints();
|
||||
bool allowCurveType(int points, CurveData::CurveType type);
|
||||
void setPointY(int i, int x, int y);
|
||||
};
|
||||
@@ -1,153 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Curves</class>
|
||||
<widget class="QWidget" name="Curves">
|
||||
<class>CurveDialog</class>
|
||||
<widget class="QDialog" name="CurveDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>672</width>
|
||||
<height>539</height>
|
||||
<width>658</width>
|
||||
<height>523</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="curvesLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_1">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="curvePreview">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="curveNameLabel">
|
||||
<property name="text">
|
||||
<string>Curve name</string>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="curvePreview">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="curvePoints"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="curveCustom">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Fixed X</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom X</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="curveNameLabel">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="curveSmooth">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Lines</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Smooth</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="AutoLineEdit" name="curveName">
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="curveTypeLabel">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="AutoComboBox" name="curveType"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="AutoComboBox" name="curvePoints"/>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="AutoCheckBox" name="curveSmooth">
|
||||
<property name="text">
|
||||
<string>Smooth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="curveName">
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="curveTypeLabel">
|
||||
<property name="text">
|
||||
<string>Curve type</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="curvesLayout2"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="pointsLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</layout>
|
||||
<layout class="QGridLayout" name="pointsLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
@@ -161,7 +127,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<widget class="QGroupBox" name="curveCreator">
|
||||
<property name="font">
|
||||
<font>
|
||||
@@ -175,7 +141,17 @@
|
||||
<property name="title">
|
||||
<string>Curve Creator</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_76" rowstretch="0,0,0,0,0,0,0,0,0,0">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="curveTemplateLabel">
|
||||
<property name="text">
|
||||
<string>Template</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="curveTemplate"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="curveCoeffLabel">
|
||||
<property name="text">
|
||||
@@ -183,51 +159,8 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="curveTypeLabel_2">
|
||||
<property name="text">
|
||||
<string>Curve type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="curveSideLabel">
|
||||
<property name="text">
|
||||
<string>Side</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="3">
|
||||
<widget class="QSpinBox" name="yMax">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3">
|
||||
<widget class="QSpinBox" name="yMid">
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="curveCoeff">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -249,7 +182,76 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="yMin">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="yMidLabel">
|
||||
<property name="text">
|
||||
<string>Y at X=0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="yMid">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="yMaxLabel">
|
||||
<property name="text">
|
||||
<string>Y at X=100</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="yMax">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="curveSideLabel">
|
||||
<property name="text">
|
||||
<string>Side</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="curveSide">
|
||||
<item>
|
||||
<property name="text">
|
||||
@@ -268,43 +270,17 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="yMaxLabel">
|
||||
<property name="text">
|
||||
<string>Y at X=100</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QSpinBox" name="curveCoeff">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="4">
|
||||
<item row="6" column="0">
|
||||
<widget class="QPushButton" name="curveApply">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="curveType"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="yMidLabel">
|
||||
<property name="text">
|
||||
<string>Y at X=0</string>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -315,57 +291,74 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="3">
|
||||
<widget class="QSpinBox" name="yMin">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3">
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="pointSize"/>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="4">
|
||||
<widget class="Line" name="line">
|
||||
<item row="9" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AutoLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>autolineedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AutoComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>autocombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AutoCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>autocheckbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>curvePreview</tabstop>
|
||||
<tabstop>curvePoints</tabstop>
|
||||
<tabstop>curveCustom</tabstop>
|
||||
<tabstop>curveSmooth</tabstop>
|
||||
<tabstop>curveName</tabstop>
|
||||
<tabstop>curveType</tabstop>
|
||||
<tabstop>curveTemplate</tabstop>
|
||||
<tabstop>curveCoeff</tabstop>
|
||||
<tabstop>yMin</tabstop>
|
||||
<tabstop>yMid</tabstop>
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include "curveimage.h"
|
||||
#include "curvedata.h"
|
||||
|
||||
constexpr int IMAGE_SIZE = { 200 };
|
||||
|
||||
CurveImage::CurveImage(QColor gridColor, qreal gridWidth):
|
||||
size(IMAGE_SIZE),
|
||||
image(size + 1, size + 1, QImage::Format_RGB32),
|
||||
painter(&image)
|
||||
{
|
||||
painter.setBrush(QBrush(Qt::white));
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawRect(0, 0, size, size);
|
||||
|
||||
painter.setPen(QPen(gridColor, gridWidth));
|
||||
const int step = size / 4;
|
||||
painter.drawLine(0, step * 1, size, step * 1);
|
||||
painter.drawLine(0, step * 2, size, step * 2);
|
||||
painter.drawLine(0, step * 3, size, step * 3);
|
||||
painter.drawLine(step * 1, 0, step * 1, size);
|
||||
painter.drawLine(step * 2, 0, step * 2, size);
|
||||
painter.drawLine(step * 3, 0, step * 3, size);
|
||||
}
|
||||
|
||||
void CurveImage::drawCurve(const CurveData & curve, QColor color, qreal width)
|
||||
{
|
||||
painter.setPen(QPen(color, width, Qt::SolidLine));
|
||||
|
||||
for (int j = 1; j < curve.count; j++) {
|
||||
if (curve.type == CurveData::CURVE_TYPE_CUSTOM)
|
||||
painter.drawLine(size / 2 + (size * curve.points[j - 1].x) / IMAGE_SIZE,
|
||||
size / 2 - (size * curve.points[j - 1].y) / IMAGE_SIZE,
|
||||
size / 2 + (size * curve.points[j].x) / IMAGE_SIZE,
|
||||
size / 2 - (size * curve.points[j].y) / IMAGE_SIZE);
|
||||
else
|
||||
painter.drawLine(size * (j-1) / (curve.count - 1),
|
||||
size / 2 - (size * curve.points[j - 1].y) / IMAGE_SIZE,
|
||||
size * (j) / (curve.count - 1),
|
||||
size / 2 - (size * curve.points[j].y) / IMAGE_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
class CurveData;
|
||||
|
||||
class CurveImage
|
||||
{
|
||||
public:
|
||||
CurveImage(QColor gridColor = Qt::darkGray, qreal gridWidth = 1);
|
||||
|
||||
void drawCurve(const CurveData & curve, QColor color = Qt::black, qreal width = 2);
|
||||
const QImage & get() const { return image; }
|
||||
|
||||
protected:
|
||||
int size;
|
||||
QImage image;
|
||||
QPainter painter;
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include "curveimagewidget.h"
|
||||
#include "curveimage.h"
|
||||
#include "curvedialog.h"
|
||||
#include "compounditemmodels.h"
|
||||
#include "modeldata.h"
|
||||
#include "eeprominterface.h"
|
||||
|
||||
CurveImageWidget::CurveImageWidget(QWidget * parent) :
|
||||
QLabel(parent)
|
||||
{
|
||||
setToolTip(tr("Double click to edit"));
|
||||
}
|
||||
|
||||
void CurveImageWidget::set(ModelData * model, Firmware * firmware, CompoundItemModelFactory * sharedItemModels, int index, QColor penColor, qreal penWidth)
|
||||
{
|
||||
this->model = model;
|
||||
this->firmware = firmware;
|
||||
this->sharedItemModels = sharedItemModels;
|
||||
this->penWidth = penWidth;
|
||||
this->penColor = penColor;
|
||||
setIndex(index);
|
||||
setGrid();
|
||||
}
|
||||
|
||||
void CurveImageWidget::setIndex(int index)
|
||||
{
|
||||
this->index = (index >= 0 && index < CPN_MAX_CURVES) ? index : -1;
|
||||
}
|
||||
|
||||
void CurveImageWidget::setGrid(QColor color, qreal width)
|
||||
{
|
||||
gridColor = color;
|
||||
gridWidth = width;
|
||||
}
|
||||
|
||||
void CurveImageWidget::setPen(QColor color, qreal width)
|
||||
{
|
||||
penColor = color;
|
||||
penWidth = width;
|
||||
}
|
||||
|
||||
int CurveImageWidget::edit()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (index >= 0 && index < CPN_MAX_CURVES) {
|
||||
CurveDialog *dlg = new CurveDialog(this, *model, index, firmware, sharedItemModels);
|
||||
ret = dlg->exec();
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CurveImageWidget::draw()
|
||||
{
|
||||
if (index >= 0 && index < CPN_MAX_CURVES) {
|
||||
CurveImage *curveImage = new CurveImage(gridColor, gridWidth);
|
||||
curveImage->drawCurve(model->curves[index], penColor, penWidth);
|
||||
|
||||
QImage image = curveImage->get();
|
||||
setPixmap(QPixmap::fromImage(image.scaled(height(), width())));
|
||||
|
||||
delete curveImage;
|
||||
}
|
||||
else {
|
||||
CurveImage *curveImage = new CurveImage(gridColor, gridWidth);
|
||||
QImage image = curveImage->get();
|
||||
setPixmap(QPixmap::fromImage(image.scaled(height(), width())));
|
||||
}
|
||||
}
|
||||
|
||||
void CurveImageWidget::mouseDoubleClickEvent(QMouseEvent * event)
|
||||
{
|
||||
QLabel::mouseDoubleClickEvent(event);
|
||||
emit doubleClicked();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class ModelData;
|
||||
class Firmware;
|
||||
class CompoundItemModelFactory;
|
||||
|
||||
class CurveImageWidget : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CurveImageWidget(QWidget * parent);
|
||||
virtual ~CurveImageWidget() {}
|
||||
|
||||
void set(ModelData * model, Firmware * firmware, CompoundItemModelFactory * sharedItemModels, int index, QColor penColor = Qt::black, qreal penWidth = 2);
|
||||
void setIndex(int index);
|
||||
void setGrid(QColor color = Qt::darkGray, qreal width = 1);
|
||||
void setPen(QColor color = Qt::black, qreal width = 2);
|
||||
int edit();
|
||||
void draw();
|
||||
|
||||
signals:
|
||||
void doubleClicked();
|
||||
|
||||
protected:
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent * event);
|
||||
|
||||
private:
|
||||
ModelData *model = nullptr;
|
||||
Firmware *firmware = nullptr;
|
||||
CompoundItemModelFactory *sharedItemModels;
|
||||
int index;
|
||||
qreal penWidth;
|
||||
QColor penColor;
|
||||
qreal gridWidth;
|
||||
QColor gridColor;
|
||||
};
|
||||
@@ -119,4 +119,4 @@ qt5_wrap_ui(simulation_SRCS ${simulation_UIS})
|
||||
qt5_wrap_cpp(simulation_SRCS ${simulation_HDRS})
|
||||
|
||||
add_library(simulation ${simulation_SRCS} ${simulation_HDRS})
|
||||
target_link_libraries(simulation PRIVATE ${CPN_COMMON_LIB} Qt5::Core Qt5::Widgets Qt5::Svg)
|
||||
target_link_libraries(simulation PRIVATE ${CPN_COMMON_LIB} shared Qt5::Core Qt5::Widgets Qt5::Svg)
|
||||
|
||||
Reference in New Issue
Block a user