1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-13 11:29:51 +03:00

Merge branch '2.3' into 2.4

# Conflicts:
#	radio/src/fonts/480x272/font_dblsize.png
#	radio/src/fonts/480x272/font_xxlsize.png
#	radio/src/gui/128x64/model_setup.cpp
#	radio/src/gui/128x64/radio_setup.cpp
#	radio/src/gui/480x272/model_receiver_options.cpp
#	radio/src/gui/480x272/model_setup.cpp
#	radio/src/gui/480x272/radio_calibration.cpp
#	radio/src/gui/480x272/radio_hardware.cpp
#	radio/src/gui/common/stdlcd/draw_functions.cpp
#	radio/src/gui/gui_common.cpp
#	radio/src/keys.h
#	radio/src/lua/interface.cpp
#	radio/src/pulses/afhds3.h
#	radio/src/rtos.h
#	radio/src/switches.cpp
#	radio/src/targets/common/arm/stm32/aux_serial_driver.cpp
#	radio/src/targets/horus/CMakeLists.txt
#	radio/src/targets/horus/lcd_driver.cpp
#	radio/src/targets/horus/startup_stm32f42_43xxx.s
#	radio/src/targets/taranis/CMakeLists.txt
#	radio/src/telemetry/crossfire.h
#	radio/src/telemetry/multi.cpp
#	radio/src/translations.cpp
#	radio/src/translations/it.h.txt
#	radio/src/translations/untranslated.h
#	radio/util/font2png.py
#	tools/commit-tests.sh
This commit is contained in:
3djc 2021-04-08 11:42:28 +02:00
commit 70d24506da
270 changed files with 10876 additions and 6176 deletions

View file

@ -6,7 +6,7 @@ set(VERSION_REVISION "0")
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
set(SDCARD_REVISION "0035") set(SDCARD_REVISION "0036")
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION}) set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)

View file

@ -2093,3 +2093,135 @@ Burt Pickard-Richardson
Michal Mesaros Michal Mesaros
Conrad Young Conrad Young
Martin Mathes Martin Mathes
Jens Rainer Hansen
Mark Trible
Marc Dubois
Alan Wilkins
Daniel Hryciuk
Thomas Fox
Sidney B Harden
Augustas Sereika
David Belletete
Karl-Heinz Behn
Lena Hjort
Jan Langhorst
Alberto Scotti
John Rock
Adam Kouse
Ricardo Martins
Noel Irwin
Christoph Rausch
Anthony Hrabusicky
Sergio Tondini
Aldo Visentin
Greg Wilson
Mark Sutton
Lukas Kana
Peter Newman
Kevin Cave
Arold Reinders
Jason Plant
John Beech
Ian Parris
Danny Music
Eric Bissonnette
Riso LTD
William Booth
Ferenc Kunkli
Offer Shmuely
Troy Atneosen
Long Technologies
John Jaugilas
Jan-Hinrich Klee
Hans-Reinhard Mette
Alejandro Casals Oliver
David Homewood
John Dunning
Konrad Helbach
Bernard Delpy
Raymond Ellsworth
Bogdan Musial
Гасак Сергей
Philip Garcia
Helder Simoes
Thomas Blanchin
Jean-Luc Mesnier
Michael Bajer
David Homewood
Marc Sanders
Буров Александр
Rudy T'Jolleyn
Jay Watkins
Blaz Vodopivec
David De Salvo
Willem Verschoren
Dennis Kathrens
Alan Aucote
Richard Jerome Danstrom
David Garcia-Mendia
Mark Jones
John Zseleczky
Xiao Sun
Glenn Harvey
Albrecht Friebel
Gunter Klemke
Travis McCarthy
Franz Zier
Ian Contessa
Sean Sadler
Richard F Janczak
Mateusz Dziadosz
Thomas Merchant
M L Perkins
Stefano Boggia
Новоселов Юрий
James Rhodes
Peter Gaskill
Jacques Temey
Anthony Challis
Gerard Falaise
George McGinnis
Antoine Soulie
Tjeerd Jager
Bertold Van den Bergh
Stefanie Zerbe
James Mandelbaum
Javier J. Cordovez
Jess Barkley
Schneider Modell
Michael Hasselgaard
Thomas Young
Непочатов Алексей
Thomas Goebel
Joseph Macias
Paw Melin-Nielsen
Liam O'Brien
Ronald B Backman
Corvus Inspection Services Inc
Stuart Posnett
Clark Emerick
Helmut Sippel
Jhon Lennon Silva do Nascimento
Peter McCarthy
Bob Brown
Claude Lawyer
Peter Fithern
Michael Hoffman
Tim Smith
OpenSki Institute
Simon Melov
Richard Podolsky
James Wilson
John Norrbin
James Goins
Phillip Nguyen
Jeffrey M Engel
Richard Marotto
Greg Bell
Scott Geer
Thomas Abshier
Ernst Camenzind
Radomir Sterba
Ignacio Barrio
Bradley Murchie
Emmanuel Balintec

View file

@ -343,8 +343,12 @@ if(PCB STREQUAL X7 AND PCBREV STREQUAL ACCESS)
set(FLAVOUR x7access) set(FLAVOUR x7access)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T12) elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T12)
set(FLAVOUR t12) set(FLAVOUR t12)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TLITE)
set(FLAVOUR tlite)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TX12) elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TX12)
set(FLAVOUR tx12) set(FLAVOUR tx12)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T8)
set(FLAVOUR t8)
elseif(PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019) elseif(PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019)
set(FLAVOUR x9d+2019) set(FLAVOUR x9d+2019)
elseif(PCB STREQUAL X10 AND PCBREV STREQUAL EXPRESS) elseif(PCB STREQUAL X10 AND PCBREV STREQUAL EXPRESS)

View file

@ -179,6 +179,16 @@
<file>images/simulator/JumperT12/JumperT12-x.png</file> <file>images/simulator/JumperT12/JumperT12-x.png</file>
<file>images/simulator/JumperT12/JumperT12-center.png</file> <file>images/simulator/JumperT12/JumperT12-center.png</file>
<file>images/simulator/JumperT12/JumperT12-top.png</file> <file>images/simulator/JumperT12/JumperT12-top.png</file>
<file>images/simulator/JumperTLITE/bottom.png</file>
<file>images/simulator/JumperTLITE/bottom_right.png</file>
<file>images/simulator/JumperTLITE/bottom_left.png</file>
<file>images/simulator/JumperTLITE/left.png</file>
<file>images/simulator/JumperTLITE/left_top.png</file>
<file>images/simulator/JumperTLITE/left_bottom.png</file>
<file>images/simulator/JumperTLITE/right.png</file>
<file>images/simulator/JumperTLITE/right_top.png</file>
<file>images/simulator/JumperTLITE/right_bottom.png</file>
<file>images/simulator/JumperTLITE/top.png</file>
<file>images/simulator/TX12/left.png</file> <file>images/simulator/TX12/left.png</file>
<file>images/simulator/TX12/left-pageup.png</file> <file>images/simulator/TX12/left-pageup.png</file>
<file>images/simulator/TX12/left-pagedn.png</file> <file>images/simulator/TX12/left-pagedn.png</file>
@ -190,6 +200,18 @@
<file>images/simulator/TX12/right-mdl.png</file> <file>images/simulator/TX12/right-mdl.png</file>
<file>images/simulator/TX12/bottom.png</file> <file>images/simulator/TX12/bottom.png</file>
<file>images/simulator/TX12/top.png</file> <file>images/simulator/TX12/top.png</file>
<file>images/simulator/T8/left.png</file>
<file>images/simulator/T8/left-pageup.png</file>
<file>images/simulator/T8/left-pagedn.png</file>
<file>images/simulator/T8/left-rtn.png</file>
<file>images/simulator/T8/left-sys.png</file>
<file>images/simulator/T8/right.png</file>
<file>images/simulator/T8/right-ent.png</file>
<file>images/simulator/T8/right-mdl.png</file>
<file>images/simulator/T8/right-up.png</file>
<file>images/simulator/T8/right-dn.png</file>
<file>images/simulator/T8/bottom.png</file>
<file>images/simulator/T8/top.png</file>
<file>images/simulator/JumperT16/left.png</file> <file>images/simulator/JumperT16/left.png</file>
<file>images/simulator/JumperT16/right.png</file> <file>images/simulator/JumperT16/right.png</file>
<file>images/simulator/JumperT16/top.png</file> <file>images/simulator/JumperT16/top.png</file>

View file

@ -1,12 +1,12 @@
set(datamodels_SRCS set(datamodels_SRCS
rawitemdatamodels.cpp compounditemmodels.cpp
rawitemfilteredmodel.cpp filtereditemmodels.cpp
) )
set(datamodels_HDRS set(datamodels_HDRS
rawitemdatamodels.h compounditemmodels.h
rawitemfilteredmodel.h filtereditemmodels.h
) )
qt5_wrap_cpp(datamodels_SRCS ${datamodels_HDRS}) qt5_wrap_cpp(datamodels_SRCS ${datamodels_HDRS})

View file

@ -0,0 +1,758 @@
/*
* 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 "compounditemmodels.h"
#include "generalsettings.h"
#include "eeprominterface.h"
#include "modeldata.h"
#include "adjustmentreference.h"
// static
QString AbstractItemModel::idToString(const int value)
{
switch (value) {
case IMID_Unknown:
return "Unknown";
case IMID_RawSource:
return "RawSource";
case IMID_RawSwitch:
return "RawSwitch";
case IMID_Curve:
return "Curve";
case IMID_GVarRef:
return "GVarRef";
case IMID_ThrSource:
return "ThrSource";
case IMID_CustomFuncAction:
return "CustomFuncAction";
case IMID_CustomFuncResetParam:
return "CustomFuncResetParam";
case IMID_TeleSource:
return "TeleSource";
case IMID_RssiSource:
return "RssiSource";
case IMID_CurveRefType:
return "CurveRefType";
case IMID_CurveRefFunc:
return "CurveRefFunc";
default:
return "Custom";
}
}
// static
void AbstractItemModel::dumpItemModelContents(AbstractItemModel * itemModel)
{
if (itemModel) {
qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName();
for (int i = 0; i < itemModel->rowCount(); ++i) {
qDebug() << "row:" << i
<< "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString()
<< "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt()
<< "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool()
<< "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt()
<< "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt();
}
}
else
qDebug() << "Error: model not of class AbstractItemModel";
}
//
// AbstractStaticItemModel
//
void AbstractStaticItemModel::loadItemList()
{
foreach (const ListItem *item, itemList) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(item->text);
modelItem->setData(item->id, IMDR_Id);
modelItem->setData(item->type, IMDR_Type);
modelItem->setData(item->flags, IMDR_Flags);
modelItem->setData(item->isAvailable, IMDR_Available);
appendRow(modelItem);
}
itemList.clear();
};
//
// RawSourceItemModel
//
RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_RawSource);
setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts));
addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1);
for (int i = 0; i < firmware->getCapability(LuaScripts); i++)
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, firmware->getCapability(LuaOutputsPerScript), i * 16);
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::MaxAnalogs));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches));
addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, firmware->getCapability(LogicalSwitches));
addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC);
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, firmware->getCapability(TrainerInputs));
addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, firmware->getCapability(Outputs));
addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5);
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, firmware->getCapability(Sensors) * 3);
addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, firmware->getCapability(Gvars));
}
void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const
{
item->setText(src.toString(modelData, generalSettings, boardType));
item->setData(src.isAvailable(modelData, generalSettings, boardType), IMDR_Available);
}
void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start)
{
for (int i = start; i < start + count; i++) {
const RawSource src = RawSource(type, i);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(src.toValue(), IMDR_Id);
modelItem->setData(type, IMDR_Type);
modelItem->setData(group, IMDR_Flags);
setDynamicItemData(modelItem, src);
appendRow(modelItem);
}
}
void RawSourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSource(item(i)->data(IMDR_Id).toInt()));
emit updateComplete();
}
}
//
// RawSwitchItemModel
//
RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_RawSwitch);
setUpdateMask(IMUE_FlightModes | IMUE_LogicalSwitches | IMUE_TeleSensors);
// Descending switch direction: NOT (!) switches
addItems(SWITCH_TYPE_ACT, -1);
addItems(SWITCH_TYPE_SENSOR, -firmware->getCapability(Sensors));
addItems(SWITCH_TYPE_TELEMETRY, -1);
addItems(SWITCH_TYPE_FLIGHT_MODE, -firmware->getCapability(FlightModes));
addItems(SWITCH_TYPE_VIRTUAL, -firmware->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_TRIM, -board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions)));
addItems(SWITCH_TYPE_SWITCH, -board->getCapability(Board::SwitchPositions));
// Ascending switch direction (including zero)
addItems(SWITCH_TYPE_TIMER_MODE, 5);
addItems(SWITCH_TYPE_NONE, 1);
addItems(SWITCH_TYPE_SWITCH, board->getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_MULTIPOS_POT, board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions));
addItems(SWITCH_TYPE_TRIM, board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_VIRTUAL, firmware->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_FLIGHT_MODE, firmware->getCapability(FlightModes));
addItems(SWITCH_TYPE_TELEMETRY, 1);
addItems(SWITCH_TYPE_SENSOR, firmware->getCapability(Sensors));
addItems(SWITCH_TYPE_ON, 1);
addItems(SWITCH_TYPE_ONE, 1);
addItems(SWITCH_TYPE_ACT, 1);
}
void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const
{
item->setText(rsw.toString(boardType, generalSettings, modelData));
item->setData(rsw.isAvailable(modelData, generalSettings, boardType), IMDR_Available);
}
void RawSwitchItemModel::addItems(const RawSwitchType & type, int count)
{
// Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule:
const static QVector<int> rawSwitchIndexBaseZeroTypes = QVector<int>() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE;
// handle exceptions in RawSwitch() index values
const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0;
// determine cotext flags
int context = RawSwitch::AllSwitchContexts;
switch (type) {
case SWITCH_TYPE_FLIGHT_MODE:
context &= ~RawSwitch::MixesContext;
// fallthrough
case SWITCH_TYPE_VIRTUAL:
case SWITCH_TYPE_SENSOR:
context &= ~RawSwitch::GlobalFunctionsContext;
break;
case SWITCH_TYPE_TIMER_MODE:
context = RawSwitch::TimersContext;
break;
case SWITCH_TYPE_NONE:
context &= ~RawSwitch::TimersContext;
break;
case SWITCH_TYPE_ON:
case SWITCH_TYPE_ONE:
context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext;
break;
default:
break;
}
int i = (count < 0 ? count : 1);
count = (i < 0 ? 0 : count + i);
for ( ; i < count; ++i) {
RawSwitch rs(type, i + rawIdxAdj);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(rs.toValue(), IMDR_Id);
modelItem->setData(type, IMDR_Type);
modelItem->setData(context, IMDR_Flags);
setDynamicItemData(modelItem, rs);
appendRow(modelItem);
}
}
void RawSwitchItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSwitch(item(i)->data(IMDR_Id).toInt()));
emit updateComplete();
}
}
//
// CurveItemModel
//
CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_Curve);
if (!modelData)
return;
setUpdateMask(IMUE_Curves);
const int count = firmware->getCapability(NumCurves);
for (int i = -count ; i <= count; ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CurveItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
CurveReference cr = CurveReference(CurveReference::CURVE_REF_CUSTOM, value);
item->setText(cr.toString(modelData, false));
item->setData(cr.isAvailable(), IMDR_Available);
}
void CurveItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// GVarReferenceItemModel
//
GVarReferenceItemModel::GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_GVarRef);
if (!modelData)
return;
setUpdateMask(IMUE_GVars | IMUE_FlightModes | IMUE_LogicalSwitches);
const int count = firmware->getCapability(Gvars);
if (count > 0) {
addItems(-count);
addItems(count);
}
}
void GVarReferenceItemModel::addItems(int count)
{
int i = (count < 0 ? count : 1);
count = (i < 0 ? 0 : count + i);
for ( ; i < count; ++i) {
QStandardItem * modelItem = new QStandardItem();
AdjustmentReference ar(AdjustmentReference::ADJUST_REF_GVAR, i);
modelItem->setData(ar.toValue(), IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, ar);
appendRow(modelItem);
}
}
void GVarReferenceItemModel::setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const
{
item->setText(ar.toString(modelData, false));
item->setData(ar.isAvailable(), IMDR_Available);
}
void GVarReferenceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), AdjustmentReference(item(i)->data(IMDR_Id).toInt()));
emit updateComplete();
}
}
//
// ThrottleSourceItemModel
//
ThrottleSourceItemModel::ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_ThrSource);
if (!modelData)
return;
setUpdateMask(IMUE_Timers | IMUE_Inputs | IMUE_TeleSensors);
for (int i = 0; i < modelData->thrTraceSrcCount(); i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void ThrottleSourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(modelData->thrTraceSrcToString(value));
item->setData(modelData->isThrTraceSrcAvailable(generalSettings, value), IMDR_Available);
}
void ThrottleSourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// CustomFuncActionItemModel
//
CustomFuncActionItemModel::CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CustomFuncAction);
setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts));
for (int i = 0; i < AssignFunc::FuncCount; i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(CustomFunctionData::funcContext(i), IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CustomFuncActionItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(CustomFunctionData::funcToString((AssignFunc)value, modelData));
item->setData(CustomFunctionData::isFuncAvailable(value), IMDR_Available);
}
void CustomFuncActionItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// CustomFuncResetParamItemModel
//
CustomFuncResetParamItemModel::CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CustomFuncResetParam);
setUpdateMask(IMUE_TeleSensors | IMUE_Timers);
for (int i = 0; i < CustomFunctionData::resetParamCount(); i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CustomFuncResetParamItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(CustomFunctionData::resetToString(value, modelData));
item->setData(CustomFunctionData::isResetParamAvailable(value, modelData), IMDR_Available);
}
void CustomFuncResetParamItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// TelemetrySourceItemModel
//
TelemetrySourceItemModel::TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_TeleSource);
if (!modelData)
return;
setUpdateMask(IMUE_TeleSensors | IMUE_Modules);
const int count = firmware->getCapability(Sensors);
for (int i = -count; i <= count; ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void TelemetrySourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(SensorData::sourceToString(modelData, value));
item->setData(SensorData::isSourceAvailable(modelData, value), IMDR_Available);
}
void TelemetrySourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i) {
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
}
emit updateComplete();
}
}
//
// RssiSourceItemModel
//
RssiSourceItemModel::RssiSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_RssiSource);
if (!modelData)
return;
setUpdateMask(IMUE_TeleSensors | IMUE_Modules);
for (int i = 0; i <= firmware->getCapability(Sensors); ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void RssiSourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(SensorData::rssiSensorToString(modelData, value));
item->setData(SensorData::isRssiSensorAvailable(modelData, value), IMDR_Available);
}
void RssiSourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i) {
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
}
emit updateComplete();
}
}
//
// CurveRefTypeItemModel
//
CurveRefTypeItemModel::CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CurveRefType);
for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(CurveReference::typeToString((CurveReference::CurveRefType)i));
modelItem->setData(i, IMDR_Id);
modelItem->setData(CurveReference::isTypeAvailable((CurveReference::CurveRefType)i), IMDR_Available);
appendRow(modelItem);
}
}
//
// CurveRefFuncItemModel
//
CurveRefFuncItemModel::CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CurveRefFunc);
for (int i = 1; i <= CurveReference::functionCount(); i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(CurveReference::functionToString(i));
modelItem->setData(i, IMDR_Id);
modelItem->setData(CurveReference::isFunctionAvailable(i), IMDR_Available);
appendRow(modelItem);
}
}
//
// PrecisionItemModel
//
PrecisionItemModel::PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix, const bool placeholders) :
AbstractStaticItemModel()
{
for (int i = minDecimals, j = maxDecimals; j >= 0; i++, j--) {
QString str = QString("0.%1").arg(QString(i, '0'));
if (placeholders)
str.append(QString(j, '_'));
if (!suffix.isEmpty())
str.append(QString(" %1").arg(suffix));
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(str);
modelItem->setData(i, IMDR_Id);
modelItem->setData(true, IMDR_Available);
appendRow(modelItem);
}
}
//
// CompoundItemModelFactory
//
CompoundItemModelFactory::CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData) :
generalSettings(generalSettings),
modelData(modelData)
{
firmware = getCurrentFirmware();
board = new Boards(getCurrentBoard());
boardType = getCurrentBoard();
}
CompoundItemModelFactory::~CompoundItemModelFactory()
{
unregisterItemModels();
delete board;
}
void CompoundItemModelFactory::addItemModel(const int id)
{
switch (id) {
case AbstractItemModel::IMID_RawSource:
registerItemModel(new RawSourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_RawSwitch:
registerItemModel(new RawSwitchItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_Curve:
registerItemModel(new CurveItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_GVarRef:
registerItemModel(new GVarReferenceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_ThrSource:
registerItemModel(new ThrottleSourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CustomFuncAction:
registerItemModel(new CustomFuncActionItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CustomFuncResetParam:
registerItemModel(new CustomFuncResetParamItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_TeleSource:
registerItemModel(new TelemetrySourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_RssiSource:
registerItemModel(new RssiSourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CurveRefType:
registerItemModel(new CurveRefTypeItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CurveRefFunc:
registerItemModel(new CurveRefFuncItemModel(generalSettings, modelData, firmware, board, boardType));
break;
default:
qDebug() << "Error: unknown item model: id";
break;
}
}
int CompoundItemModelFactory::registerItemModel(AbstractItemModel * itemModel)
{
if (itemModel) {
if (!isItemModelRegistered(itemModel->getId())) {
setSourceId(itemModel);
registeredItemModels.append(itemModel);
return itemModel->getId();
}
else
return itemModel->getId();
}
return -1;
}
void CompoundItemModelFactory::unregisterItemModels()
{
foreach (AbstractItemModel *itemModel, registeredItemModels) {
delete itemModel;
}
}
void CompoundItemModelFactory::unregisterItemModel(const int id)
{
AbstractItemModel * itemModel = getItemModel(id);
if (itemModel)
delete itemModel;
}
AbstractItemModel * CompoundItemModelFactory::getItemModel(const int id) const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
if (itemModel->getId() == id)
return itemModel;
}
return nullptr;
}
AbstractItemModel * CompoundItemModelFactory::getItemModel(const QString name) const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
if (itemModel->getName() == name)
return itemModel;
}
return nullptr;
}
bool CompoundItemModelFactory::isItemModelRegistered(const int id) const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
if (itemModel->getId() == id)
return true;
}
return false;
}
void CompoundItemModelFactory::update(const int event)
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
itemModel->update(event);
}
}
void CompoundItemModelFactory::dumpAllItemModelContents() const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
AbstractItemModel::dumpItemModelContents(itemModel);
}
}
void CompoundItemModelFactory::setSourceId(AbstractItemModel * itemModel)
{
if (itemModel && itemModel->getId() == AbstractItemModel::IMID_Unknown)
itemModel->setId(AbstractItemModel::IMID_ReservedCount + registeredItemModels.count());
}

View file

@ -0,0 +1,380 @@
/*
* 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 "rawsource.h"
#include "rawswitch.h"
#include <QStandardItemModel>
class GeneralSettings;
class ModelData;
class AdjustmentReference;
class AbstractItemModel: public QStandardItemModel
{
Q_OBJECT
public:
enum ItemModelId {
IMID_Unknown,
IMID_RawSource,
IMID_RawSwitch,
IMID_Curve,
IMID_GVarRef,
IMID_ThrSource,
IMID_CustomFuncAction,
IMID_CustomFuncResetParam,
IMID_TeleSource,
IMID_RssiSource,
IMID_CurveRefType,
IMID_CurveRefFunc,
IMID_ReservedCount,
IMID_Custom
};
Q_ENUM(ItemModelId)
enum ItemModelDataRoles {
IMDR_Id = Qt::UserRole,
IMDR_Type,
IMDR_Flags,
IMDR_Available
};
Q_ENUM(ItemModelDataRoles)
enum ItemModelDataGroups {
IMDG_None = 0x01,
IMDG_Negative = 0x02,
IMDG_Positive = 0x04
};
Q_ENUM(ItemModelDataGroups)
enum ItemModelUpdateEvent {
IMUE_None = 0,
IMUE_SystemRefresh = 1 << 0,
IMUE_Channels = 1 << 1,
IMUE_Curves = 1 << 2,
IMUE_FlightModes = 1 << 3,
IMUE_GVars = 1 << 4,
IMUE_Inputs = 1 << 5,
IMUE_LogicalSwitches = 1 << 6,
IMUE_Scripts = 1 << 7,
IMUE_TeleSensors = 1 << 8,
IMUE_Timers = 1 << 9,
IMUE_Modules = 1 << 10,
IMUE_All = IMUE_SystemRefresh | IMUE_Channels | IMUE_Curves | IMUE_FlightModes | IMUE_GVars | IMUE_Inputs |
IMUE_LogicalSwitches | IMUE_Scripts | IMUE_TeleSensors | IMUE_Timers | IMUE_Modules
};
Q_ENUM(ItemModelUpdateEvent)
explicit AbstractItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
QStandardItemModel(nullptr),
generalSettings(generalSettings),
modelData(modelData),
firmware(firmware),
board(board),
boardType(boardType),
m_id(IMID_Unknown),
m_name(""),
m_updateMask(IMUE_None)
{}
virtual ~AbstractItemModel() {}
void setId(int id) { m_id = id; }
int getId () const { return m_id; }
bool isReservedModelId() const { return m_id > IMID_Unknown && m_id < IMID_ReservedCount; }
void setName(QString name) { m_name = name; }
QString getName() const { return isReservedModelId() ? idToString(m_id) : m_name; }
void setUpdateMask(const int mask) { m_updateMask = mask; }
int getUpdateMask() const { return m_updateMask; }
inline bool doUpdate(const int event) const { return m_updateMask & event; }
AbstractItemModel * getItemModel(const int id) const;
static void dumpItemModelContents(AbstractItemModel * itemModel);
public slots:
virtual void update(const int event = IMUE_SystemRefresh) = 0;
protected:
const GeneralSettings * generalSettings;
const ModelData * modelData;
Firmware * firmware;
const Boards * board;
const Board::Type boardType;
private:
int m_id = IMID_Unknown;
QString m_name = "";
int m_updateMask = IMUE_None;
static QString idToString(const int value);
};
class AbstractStaticItemModel: public AbstractItemModel
{
Q_OBJECT
public:
explicit AbstractStaticItemModel(const GeneralSettings * const generalSettings = nullptr, const ModelData * const modelData = nullptr,
Firmware * firmware = nullptr, const Boards * const board = nullptr,
const Board::Type boardType = Board::BOARD_UNKNOWN) :
AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {}
virtual ~AbstractStaticItemModel() {};
inline void appendToItemList(QString text, int id, bool isAvailable = true, int type = 0, int flags = 0)
{ itemList.append(new ListItem(text, id, isAvailable, type, flags)); }
void loadItemList();
public slots:
virtual void update(const int event) override final {}
protected:
struct ListItem
{
QString text;
int id;
bool isAvailable;
int type;
int flags;
ListItem() {}
ListItem(QString p_text, int p_id, bool p_isAvailable, int p_type, int p_flags) :
text(p_text), id(p_id), isAvailable(p_isAvailable), type(p_type), flags(p_flags) {}
};
QVector<ListItem *> itemList;
};
class AbstractDynamicItemModel: public AbstractItemModel
{
Q_OBJECT
public:
explicit AbstractDynamicItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {}
virtual ~AbstractDynamicItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) {}
signals:
void aboutToBeUpdated();
void updateComplete();
};
class RawSourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~RawSourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const RawSource & src) const;
void addItems(const RawSourceType & type, const int group, const int count, const int start = 0);
};
class RawSwitchItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~RawSwitchItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const;
void addItems(const RawSwitchType & type, int count);
};
class CurveItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CurveItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class GVarReferenceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~GVarReferenceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const;
void addItems(int count);
};
class ThrottleSourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~ThrottleSourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class CustomFuncActionItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CustomFuncActionItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class CustomFuncResetParamItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CustomFuncResetParamItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class TelemetrySourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~TelemetrySourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class RssiSourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit RssiSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~RssiSourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class CurveRefTypeItemModel : public AbstractStaticItemModel
{
Q_OBJECT
public:
explicit CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CurveRefTypeItemModel() {};
};
class CurveRefFuncItemModel : public AbstractStaticItemModel
{
Q_OBJECT
public:
explicit CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CurveRefFuncItemModel() {};
};
class PrecisionItemModel : public AbstractStaticItemModel
{
Q_OBJECT
public:
explicit PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix = "", const bool placeholders = false);
virtual ~PrecisionItemModel() {};
};
//
// CompoundItemModelFactory
//
class CompoundItemModelFactory
{
public:
CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData);
virtual ~CompoundItemModelFactory();
void addItemModel(const int id);
int registerItemModel(AbstractItemModel * itemModel);
void unregisterItemModels();
void unregisterItemModel(const int id);
bool isItemModelRegistered(const int id) const;
AbstractItemModel * getItemModel(const int id) const;
AbstractItemModel * getItemModel(const QString name) const;
void update(const int event = AbstractItemModel::IMUE_SystemRefresh);
void dumpAllItemModelContents() const;
protected:
const GeneralSettings * generalSettings;
const ModelData * modelData;
Firmware * firmware;
Boards * board;
Board::Type boardType;
QVector<AbstractItemModel *> registeredItemModels;
private:
void setSourceId(AbstractItemModel * itemModel);
};

View file

@ -0,0 +1,252 @@
/*
* 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 "filtereditemmodels.h"
FilteredItemModel::FilteredItemModel(AbstractItemModel * sourceModel, int flags) :
QSortFilterProxyModel(nullptr),
filterFlags(0),
m_id(0),
m_name("")
{
setFilterRole(AbstractItemModel::IMDR_Available);
setFilterKeyColumn(0);
setFilterFlags(flags);
setDynamicSortFilter(true);
setSourceModel(sourceModel);
AbstractDynamicItemModel * itemModel = qobject_cast<AbstractDynamicItemModel *>(sourceModel);
if (itemModel) {
connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &FilteredItemModel::onAboutToBeUpdated);
connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &FilteredItemModel::onUpdateComplete);
}
}
void FilteredItemModel::setFilterFlags(int flags)
{
if (filterFlags != flags) {
filterFlags = flags;
invalidateFilter();
}
}
bool FilteredItemModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
{
const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent);
if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool())
return false;
if (!filterFlags)
return true;
bool ok;
const int flags = sourceModel()->data(srcIdx, AbstractItemModel::IMDR_Flags).toInt(&ok);
return (ok && (!flags || (filterFlags & flags)));
}
void FilteredItemModel::update() const
{
AbstractDynamicItemModel * itemModel = qobject_cast<AbstractDynamicItemModel *>(sourceModel());
if (itemModel)
itemModel->update();
}
void FilteredItemModel::onAboutToBeUpdated()
{
emit aboutToBeUpdated();
}
void FilteredItemModel::onUpdateComplete()
{
emit updateComplete();
}
// static
void FilteredItemModel::dumpItemModelContents(FilteredItemModel * itemModel)
{
if (itemModel) {
qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName();
for (int i = 0; i < itemModel->rowCount(); ++i) {
qDebug() << "row:" << i
<< "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString()
<< "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt()
<< "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool()
<< "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt()
<< "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt();
}
}
else
qDebug() << "Error: model not of class FilteredItemModel";
}
//
// FilteredItemModelFactory
//
FilteredItemModelFactory::FilteredItemModelFactory()
{
}
FilteredItemModelFactory::~FilteredItemModelFactory()
{
unregisterItemModels();
}
int FilteredItemModelFactory::registerItemModel(FilteredItemModel * itemModel, const QString name, const int id)
{
if (itemModel) {
if (isItemModelRegistered(name)) {
qDebug() << "Error: item model already registered with name:" << name;
return 0;
}
else if (id > -1 && isItemModelRegistered(id)) {
qDebug() << "Error: item model already registered with id:" << id;
return 0;
}
else {
int fid = id;
if (fid < 0) {
fid = registeredItemModels.count() + 1;
AbstractItemModel * mdl = qobject_cast<AbstractItemModel *>(itemModel->sourceModel());
if (mdl) {
fid += mdl->getId() * 128;
}
}
itemModel->setId(fid);
itemModel->setName(name);
registeredItemModels.append(itemModel);
return fid;
}
}
qDebug() << "Error: invalid filtered item model pointer";
return 0;
}
void FilteredItemModelFactory::unregisterItemModels()
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
delete itemModel;
}
}
void FilteredItemModelFactory::unregisterItemModel(const int id)
{
FilteredItemModel * itemModel = getItemModel(id);
if (itemModel)
delete itemModel;
}
bool FilteredItemModelFactory::isItemModelRegistered(const int id) const
{
return getItemModel(id);
}
bool FilteredItemModelFactory::isItemModelRegistered(const QString name) const
{
return getItemModel(name);
}
FilteredItemModel * FilteredItemModelFactory::getItemModel(const int id) const
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
if (itemModel->getId() == id)
return itemModel;
}
return nullptr;
}
FilteredItemModel * FilteredItemModelFactory::getItemModel(const QString name) const
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
if (itemModel->getName() == name)
return itemModel;
}
return nullptr;
}
void FilteredItemModelFactory::update()
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
itemModel->update();
}
}
void FilteredItemModelFactory::dumpItemModelContents(const int id) const
{
FilteredItemModel::dumpItemModelContents(getItemModel(id));
}
void FilteredItemModelFactory::dumpItemModelContents(const QString name) const
{
FilteredItemModel::dumpItemModelContents(getItemModel(name));
}
void FilteredItemModelFactory::dumpAllItemModelContents() const
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
FilteredItemModel::dumpItemModelContents(itemModel);
}
}
//
// CurveRefFilteredFactory
//
CurveRefFilteredFactory::CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags, const int gvarRefFlags)
{
if (!sharedItemModels) {
qDebug() << "Error: invalid compound item model factory pointer";
return;
}
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve), curveFlags),
fidToString(CRFIM_CURVE), CRFIM_CURVE);
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef), gvarRefFlags),
fidToString(CRFIM_GVARREF), CRFIM_GVARREF);
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefType)),
fidToString(CRFIM_TYPE), CRFIM_TYPE);
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefFunc)),
fidToString(CRFIM_FUNC), CRFIM_FUNC);
}
CurveRefFilteredFactory::~CurveRefFilteredFactory()
{
}
// static
QString CurveRefFilteredFactory::fidToString(const int value)
{
switch(value) {
case CRFIM_CURVE:
return "Curves";
case CRFIM_GVARREF:
return "Global Variables";
case CRFIM_TYPE:
return "Types";
case CRFIM_FUNC:
return "Functions";
default:
return CPN_STR_UNKNOWN_ITEM;
}
}

View file

@ -0,0 +1,115 @@
/*
* 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.
*/
#ifndef FILTEREDITEMMODELS_H
#define FILTEREDITEMMODELS_H
#include "compounditemmodels.h"
#include <QObject>
#include <QSortFilterProxyModel>
#include <QString>
class FilteredItemModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
enum DataFilters {
AllFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None | AbstractItemModel::IMDG_Positive,
AllExcludeNoneFilter = AllFilter &~ AbstractItemModel::IMDG_None,
NegativeFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None,
NegativeExcludeNoneFilter = AbstractItemModel::IMDG_Negative,
PositiveFilter = AbstractItemModel::IMDG_Positive | AbstractItemModel::IMDG_None,
PositiveExcludeNoneFilter = AbstractItemModel::IMDG_Positive
};
Q_ENUM(DataFilters)
explicit FilteredItemModel(AbstractItemModel * sourceModel, int flags);
explicit FilteredItemModel(AbstractItemModel * sourceModel) :
FilteredItemModel(sourceModel, 0) {}
virtual ~FilteredItemModel() {};
void setId(int id) { m_id = id; }
int getId() const { return m_id; };
void setName(QString name) { m_name = name; }
QString getName() const { return m_name; }
static void dumpItemModelContents(FilteredItemModel * itemModel);
public slots:
void setFilterFlags(int flags);
void update() const;
void onAboutToBeUpdated();
void onUpdateComplete();
signals:
void aboutToBeUpdated();
void updateComplete();
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
int filterFlags;
private:
int m_id = 0;
QString m_name = "";
};
class FilteredItemModelFactory
{
public:
explicit FilteredItemModelFactory();
virtual ~FilteredItemModelFactory();
int registerItemModel(FilteredItemModel * itemModel, const QString name, const int id = -1);
void unregisterItemModels();
void unregisterItemModel(const int id);
bool isItemModelRegistered(const int id) const;
bool isItemModelRegistered(const QString name) const;
FilteredItemModel * getItemModel(const int id) const;
FilteredItemModel * getItemModel(const QString name) const;
void update();
void dumpItemModelContents(const int id) const;
void dumpItemModelContents(const QString name) const;
void dumpAllItemModelContents() const;
protected:
QVector<FilteredItemModel *> registeredItemModels;
};
class CurveRefFilteredFactory : public FilteredItemModelFactory
{
public:
enum FilteredItemModelId {
CRFIM_CURVE,
CRFIM_GVARREF,
CRFIM_TYPE,
CRFIM_FUNC
};
explicit CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags = 0, const int gvarRefFlags = 0);
virtual ~CurveRefFilteredFactory();
static QString fidToString(const int value);
};
#endif // FILTEREDITEMMODELS_H

View file

@ -1,264 +0,0 @@
/*
* 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 "rawitemdatamodels.h"
#include "generalsettings.h"
#include "eeprominterface.h"
#include "modeldata.h"
RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
const Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1);
for (int i = 0; i < fw->getCapability(LuaScripts); i++)
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, fw->getCapability(LuaOutputsPerScript), i * 16);
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, fw->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board.getCapability(Board::MaxAnalogs));
addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, fw->getCapability(RotaryEncoders));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board.getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board.getCapability(Board::Switches));
addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, fw->getCapability(LogicalSwitches));
addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC);
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, fw->getCapability(TrainerInputs));
addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, fw->getCapability(Outputs));
addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5);
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, fw->getCapability(Sensors) * 3);
addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, fw->getCapability(Gvars));
}
void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const
{
Board::Type board = getCurrentBoard();
item->setText(src.toString(modelData, generalSettings, board));
item->setData(src.isAvailable(modelData, generalSettings, board), IsAvailableRole);
}
void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start)
{
for (int i = start; i < start + count; i++) {
const RawSource src = RawSource(type, i);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(src.toValue(), ItemIdRole);
modelItem->setData(type, ItemTypeRole);
modelItem->setData(group, ItemFlagsRole);
setDynamicItemData(modelItem, src);
appendRow(modelItem);
}
}
void RawSourceItemModel::update()
{
emit dataAboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt()));
emit dataUpdateComplete();
}
//
// RawSwitchItemModel
//
RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
// Descending switch direction: NOT (!) switches
addItems(SWITCH_TYPE_ACT, -1);
addItems(SWITCH_TYPE_SENSOR, -fw->getCapability(Sensors));
addItems(SWITCH_TYPE_TELEMETRY, -1);
addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_TRIM, -board.getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions)));
addItems(SWITCH_TYPE_SWITCH, -board.getCapability(Board::SwitchPositions));
// Ascending switch direction (including zero)
addItems(SWITCH_TYPE_TIMER_MODE, 5);
addItems(SWITCH_TYPE_NONE, 1);
addItems(SWITCH_TYPE_SWITCH, board.getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_MULTIPOS_POT, board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions));
addItems(SWITCH_TYPE_TRIM, board.getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_TELEMETRY, 1);
addItems(SWITCH_TYPE_SENSOR, fw->getCapability(Sensors));
addItems(SWITCH_TYPE_ON, 1);
addItems(SWITCH_TYPE_ONE, 1);
addItems(SWITCH_TYPE_ACT, 1);
}
void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const
{
const Board::Type board = getCurrentBoard();
item->setText(rsw.toString(board, generalSettings, modelData));
item->setData(rsw.isAvailable(modelData, generalSettings, board), IsAvailableRole);
}
void RawSwitchItemModel::addItems(const RawSwitchType & type, int count)
{
// Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule:
const static QVector<int> rawSwitchIndexBaseZeroTypes = QVector<int>() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE;
// handle exceptions in RawSwitch() index values
const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0;
// determine cotext flags
int context = RawSwitch::AllSwitchContexts;
switch (type) {
case SWITCH_TYPE_FLIGHT_MODE:
context &= ~RawSwitch::MixesContext;
// fallthrough
case SWITCH_TYPE_VIRTUAL:
case SWITCH_TYPE_SENSOR:
context &= ~RawSwitch::GlobalFunctionsContext;
break;
case SWITCH_TYPE_TIMER_MODE:
context = RawSwitch::TimersContext;
break;
case SWITCH_TYPE_NONE:
context &= ~RawSwitch::TimersContext;
break;
case SWITCH_TYPE_ON:
case SWITCH_TYPE_ONE:
context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext;
break;
default:
break;
}
int i = (count < 0 ? count : 1);
count = (i < 0 ? 0 : count + i);
for ( ; i < count; ++i) {
RawSwitch rs(type, i + rawIdxAdj);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(rs.toValue(), ItemIdRole);
modelItem->setData(type, ItemTypeRole);
modelItem->setData(context, ItemFlagsRole);
setDynamicItemData(modelItem, rs);
appendRow(modelItem);
}
}
void RawSwitchItemModel::update()
{
emit dataAboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt()));
emit dataUpdateComplete();
}
//
// CurveItemModel
//
CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
const int count = getCurrentFirmware()->getCapability(NumCurves);
for (int i = -count ; i <= count; ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, ItemIdRole);
int flags;
if (i < 0)
flags = DataGroups::NegativeGroup;
else if (i > 0)
flags = DataGroups::PositiveGroup;
else
flags = DataGroups::NoneGroup;
modelItem->setData(flags, ItemFlagsRole);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CurveItemModel::setDynamicItemData(QStandardItem * item, int index) const
{
item->setText(CurveReference(CurveReference::CURVE_REF_CUSTOM, index).toString(modelData, false));
item->setData(true, IsAvailableRole);
}
void CurveItemModel::update()
{
emit dataAboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt());
emit dataUpdateComplete();
}
//
// CommonItemModels
//
CommonItemModels::CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
QObject(parent)
{
m_rawSourceItemModel = new RawSourceItemModel(generalSettings, modelData, parent);
m_rawSwitchItemModel = new RawSwitchItemModel(generalSettings, modelData, parent);
m_curveItemModel = new CurveItemModel(generalSettings, modelData, parent);
}
CommonItemModels::~CommonItemModels()
{
}
void CommonItemModels::update(const RadioModelObjects radioModelObjects)
{
switch (radioModelObjects) {
case RMO_CHANNELS:
case RMO_INPUTS:
case RMO_TELEMETRY_SENSORS:
case RMO_TIMERS:
m_rawSourceItemModel->update();
break;
case RMO_FLIGHT_MODES:
case RMO_GLOBAL_VARIABLES:
case RMO_LOGICAL_SWITCHES:
m_rawSourceItemModel->update();
m_rawSwitchItemModel->update();
break;
case RMO_CURVES:
m_curveItemModel->update();
break;
case RMO_SCRIPTS:
// no need to refresh
break;
default:
qDebug() << "Unknown RadioModelObject:" << radioModelObjects;
}
}

View file

@ -1,140 +0,0 @@
/*
* 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.
*/
#ifndef RAWITEMDATAMODELS_H
#define RAWITEMDATAMODELS_H
#include "rawsource.h"
#include "rawswitch.h"
#include <QStandardItemModel>
class GeneralSettings;
class ModelData;
class AbstractRawItemDataModel: public QStandardItemModel
{
Q_OBJECT
public:
enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ItemFlagsRole, IsAvailableRole };
Q_ENUM(DataRoles)
enum DataGroups {
NoneGroup = 0x01,
NegativeGroup = 0x02,
PositiveGroup = 0x04
};
Q_ENUM(DataGroups)
explicit AbstractRawItemDataModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
QStandardItemModel(parent),
generalSettings(generalSettings),
modelData(modelData)
{}
public slots:
virtual void update() = 0;
signals:
void dataAboutToBeUpdated();
void dataUpdateComplete();
protected:
const GeneralSettings * generalSettings;
const ModelData * modelData;
};
class RawSourceItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSource & src) const;
void addItems(const RawSourceType & type, const int group, const int count, const int start = 0);
};
class RawSwitchItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const;
void addItems(const RawSwitchType & type, int count);
};
class CurveItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() override;
protected:
void setDynamicItemData(QStandardItem * item, int index) const;
};
class CommonItemModels: public QObject
{
Q_OBJECT
public:
enum RadioModelObjects {
RMO_CHANNELS,
RMO_CURVES,
RMO_FLIGHT_MODES,
RMO_GLOBAL_VARIABLES,
RMO_INPUTS,
RMO_LOGICAL_SWITCHES,
RMO_SCRIPTS,
RMO_TELEMETRY_SENSORS,
RMO_TIMERS
};
Q_ENUM(RadioModelObjects)
explicit CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
~CommonItemModels();
void update(const RadioModelObjects radioModelObjects);
RawSourceItemModel * rawSourceItemModel() const { return m_rawSourceItemModel; }
RawSwitchItemModel * rawSwitchItemModel() const { return m_rawSwitchItemModel; }
CurveItemModel * curveItemModel() const { return m_curveItemModel; }
private:
RawSourceItemModel *m_rawSourceItemModel;
RawSwitchItemModel *m_rawSwitchItemModel;
CurveItemModel *m_curveItemModel;
};
#endif // RAWITEMDATAMODELS_H

View file

@ -1,77 +0,0 @@
/*
* 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 "rawitemfilteredmodel.h"
RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent) :
QSortFilterProxyModel(parent),
filterFlags(0)
{
setFilterRole(AbstractRawItemDataModel::IsAvailableRole);
setFilterKeyColumn(0);
setFilterFlags(flags);
setDynamicSortFilter(true);
setSourceModel(sourceModel);
AbstractRawItemDataModel * itemModel = qobject_cast<AbstractRawItemDataModel *>(sourceModel);
if (itemModel) {
connect(itemModel, &AbstractRawItemDataModel::dataAboutToBeUpdated, this, &RawItemFilteredModel::onDataAboutToBeUpdated);
connect(itemModel, &AbstractRawItemDataModel::dataUpdateComplete, this, &RawItemFilteredModel::onDataUpdateComplete);
}
}
void RawItemFilteredModel::setFilterFlags(int flags)
{
if (filterFlags != flags) {
filterFlags = flags;
invalidateFilter();
}
}
bool RawItemFilteredModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
{
const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent);
if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool())
return false;
if (!filterFlags)
return true;
bool ok;
const int flags = sourceModel()->data(srcIdx, AbstractRawItemDataModel::ItemFlagsRole).toInt(&ok);
return (ok && (!flags || (filterFlags & flags)));
}
void RawItemFilteredModel::update() const
{
AbstractRawItemDataModel * itemModel = qobject_cast<AbstractRawItemDataModel *>(sourceModel());
if (itemModel)
itemModel->update();
}
void RawItemFilteredModel::onDataAboutToBeUpdated()
{
emit dataAboutToBeUpdated();
}
void RawItemFilteredModel::onDataUpdateComplete()
{
emit dataUpdateComplete();
}

View file

@ -1,63 +0,0 @@
/*
* 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.
*/
#ifndef RAWITEMFILTEREDMODEL_H
#define RAWITEMFILTEREDMODEL_H
#include "rawitemdatamodels.h"
#include <QSortFilterProxyModel>
class GeneralSettings;
class ModelData;
class RawItemFilteredModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
enum DataFilters {
AllFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup | AbstractRawItemDataModel::PositiveGroup,
AllExcludeNoneFilter = AllFilter &~ AbstractRawItemDataModel::NoneGroup,
NegativeFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup,
NegativeExcludeNoneFilter = AbstractRawItemDataModel::NegativeGroup,
PositiveFilter = AbstractRawItemDataModel::PositiveGroup | AbstractRawItemDataModel::NoneGroup,
PositiveExcludeNoneFilter = AbstractRawItemDataModel::PositiveGroup
};
Q_ENUM(DataFilters)
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent = nullptr);
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, QObject * parent = nullptr) : RawItemFilteredModel(sourceModel, 0, parent) {}
public slots:
void setFilterFlags(int flags);
void update() const;
void onDataAboutToBeUpdated();
void onDataUpdateComplete();
signals:
void dataAboutToBeUpdated();
void dataUpdateComplete();
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
int filterFlags;
};
#endif // RAWITEMFILTEREDMODEL_H

View file

@ -39,6 +39,8 @@
#include <QLineEdit> #include <QLineEdit>
#include <QMenu> #include <QMenu>
#include <QSpinBox> #include <QSpinBox>
#include <QMessageBox>
#include <QPushButton>
FileSyncDialog::FileSyncDialog(QWidget * parent, const SyncProcess::SyncOptions & syncOptions) : FileSyncDialog::FileSyncDialog(QWidget * parent, const SyncProcess::SyncOptions & syncOptions) :
QDialog(parent), QDialog(parent),

View file

@ -2,27 +2,34 @@
set(firmwares_SRCS set(firmwares_SRCS
adjustmentreference.cpp adjustmentreference.cpp
boards.cpp boards.cpp
curvedata.cpp
curvereference.cpp curvereference.cpp
customfunctiondata.cpp customfunctiondata.cpp
eeprominterface.cpp eeprominterface.cpp
generalsettings.cpp generalsettings.cpp
gvardata.cpp gvardata.cpp
io_data.cpp input_data.cpp
flightmodedata.cpp
heli_data.cpp
logicalswitchdata.cpp logicalswitchdata.cpp
mixdata.cpp
modeldata.cpp modeldata.cpp
moduledata.cpp moduledata.cpp
multiprotocols.cpp multiprotocols.cpp
output_data.cpp
radiodata.cpp radiodata.cpp
radiodataconversionstate.cpp radiodataconversionstate.cpp
rawsource.cpp rawsource.cpp
rawswitch.cpp rawswitch.cpp
sensordata.cpp sensordata.cpp
telem_data.cpp telem_data.cpp
timerdata.cpp
afhds3.cpp afhds3.cpp
ersky9x/ersky9xeeprom.cpp ersky9x/ersky9xeeprom.cpp
ersky9x/ersky9xinterface.cpp ersky9x/ersky9xinterface.cpp
opentx/opentxeeprom.cpp opentx/opentxeeprom.cpp
opentx/opentxinterface.cpp opentx/opentxinterface.cpp
datahelpers.cpp
) )
string(REPLACE ".cpp" ".h" firmwares_HDRS "${firmwares_SRCS}") string(REPLACE ".cpp" ".h" firmwares_HDRS "${firmwares_SRCS}")

View file

@ -19,7 +19,7 @@
*/ */
#include "adjustmentreference.h" #include "adjustmentreference.h"
#include "radiodata.h" // for ModelData #include "modeldata.h"
AdjustmentReference::AdjustmentReference(int value) AdjustmentReference::AdjustmentReference(int value)
{ {
@ -76,3 +76,8 @@ QString AdjustmentReference::toString(const ModelData * model, const bool sign)
} }
return ret; return ret;
} }
const bool AdjustmentReference::isAvailable() const
{
return true;
}

View file

@ -45,6 +45,7 @@ class AdjustmentReference {
bool isSet() const { return type != ADJUST_REF_VALUE || value != 0; } bool isSet() const { return type != ADJUST_REF_VALUE || value != 0; }
bool isValid(const int value) const; bool isValid(const int value) const;
QString toString(const ModelData * model = nullptr, const bool sign = false) const; QString toString(const ModelData * model = nullptr, const bool sign = false) const;
const bool isAvailable() const;
inline const int toValue() const inline const int toValue() const
{ {

View file

@ -79,6 +79,8 @@ uint32_t Boards::getFourCC(Type board)
return 0x3278746F; return 0x3278746F;
case BOARD_JUMPER_T12: case BOARD_JUMPER_T12:
return 0x3D78746F; return 0x3D78746F;
case BOARD_JUMPER_TLITE:
return 0x4278746F;
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
return 0x3F78746F; return 0x3F78746F;
case BOARD_JUMPER_T18: case BOARD_JUMPER_T18:
@ -87,11 +89,11 @@ uint32_t Boards::getFourCC(Type board)
return 0x3878746F; return 0x3878746F;
case BOARD_RADIOMASTER_TX12: case BOARD_RADIOMASTER_TX12:
return 0x4178746F; return 0x4178746F;
case BOARD_UNKNOWN: case BOARD_RADIOMASTER_T8:
break; return 0x4378746F;
default:
return 0;
} }
return 0;
} }
int Boards::getEEpromSize(Board::Type board) int Boards::getEEpromSize(Board::Type board)
@ -113,7 +115,9 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_TARANIS_X9DP_2019: case BOARD_TARANIS_X9DP_2019:
case BOARD_TARANIS_X9E: case BOARD_TARANIS_X9E:
case BOARD_JUMPER_T12: case BOARD_JUMPER_T12:
case BOARD_JUMPER_TLITE:
case BOARD_RADIOMASTER_TX12: case BOARD_RADIOMASTER_TX12:
case BOARD_RADIOMASTER_T8:
return EESIZE_TARANIS; return EESIZE_TARANIS;
case BOARD_UNKNOWN: case BOARD_UNKNOWN:
return EESIZE_MAX; return EESIZE_MAX;
@ -124,9 +128,9 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_JUMPER_T18: case BOARD_JUMPER_T18:
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
return 0; return 0;
default:
return 0;
} }
return 0;
} }
int Boards::getFlashSize(Type board) int Boards::getFlashSize(Type board)
@ -148,7 +152,9 @@ int Boards::getFlashSize(Type board)
case BOARD_TARANIS_X9DP_2019: case BOARD_TARANIS_X9DP_2019:
case BOARD_TARANIS_X9E: case BOARD_TARANIS_X9E:
case BOARD_JUMPER_T12: case BOARD_JUMPER_T12:
case BOARD_JUMPER_TLITE:
case BOARD_RADIOMASTER_TX12: case BOARD_RADIOMASTER_TX12:
case BOARD_RADIOMASTER_T8:
return FSIZE_TARANIS; return FSIZE_TARANIS;
case BOARD_HORUS_X12S: case BOARD_HORUS_X12S:
case BOARD_X10: case BOARD_X10:
@ -181,7 +187,7 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches)) if (index < DIM(switches))
return switches[index]; return switches[index];
} }
else if (IS_TARANIS_XLITE(board)) { else if (IS_TARANIS_XLITE(board) || IS_JUMPER_TLITE(board)) {
const Board::SwitchInfo switches[] = { const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"}, {SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"}, {SWITCH_3POS, "SB"},
@ -232,6 +238,16 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches)) if (index < DIM(switches))
return switches[index]; return switches[index];
} }
else if (IS_RADIOMASTER_T8(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_TOGGLE, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_3POS, "SC"},
{SWITCH_TOGGLE, "SD"}
};
if (index < DIM(switches))
return switches[index];
}
else if (IS_JUMPER_T12(board)) { else if (IS_JUMPER_T12(board)) {
const Board::SwitchInfo switches[] = { const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"}, {SWITCH_3POS, "SA"},
@ -310,6 +326,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case Pots: case Pots:
if (IS_TARANIS_X9LITE(board)) if (IS_TARANIS_X9LITE(board))
return 1; return 1;
else if (IS_JUMPER_TLITE(board))
return 0;
else if (IS_TARANIS_SMALL(board)) else if (IS_TARANIS_SMALL(board))
return 2; return 2;
else if (IS_TARANIS_X9E(board)) else if (IS_TARANIS_X9E(board))
@ -367,6 +385,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 7; return 7;
else if (board == BOARD_TARANIS_X7) else if (board == BOARD_TARANIS_X7)
return 8; return 8;
else if (board == BOARD_JUMPER_TLITE)
return 4;
else if (IS_FAMILY_T12(board)) else if (IS_FAMILY_T12(board))
return 8; return 8;
else if (IS_TARANIS_XLITE(board)) else if (IS_TARANIS_XLITE(board))
@ -383,9 +403,11 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case FactoryInstalledSwitches: case FactoryInstalledSwitches:
if (IS_TARANIS_X9E(board)) if (IS_TARANIS_X9E(board))
return 8; return 8;
if (IS_FAMILY_T12(board)) else if (IS_JUMPER_TLITE(board))
return 4;
else if (IS_FAMILY_T12(board))
return 6; return 6;
if (IS_HORUS_X12S(board)) else if (IS_HORUS_X12S(board))
return 8; return 8;
else else
return getCapability(board, Switches); return getCapability(board, Switches);
@ -530,8 +552,6 @@ QString Boards::getBoardName(Board::Type board)
return "Taranis X7/X7S"; return "Taranis X7/X7S";
case BOARD_TARANIS_X7_ACCESS: case BOARD_TARANIS_X7_ACCESS:
return "Taranis X7/X7S Access"; return "Taranis X7/X7S Access";
case BOARD_JUMPER_T12:
return "Jumper T12";
case BOARD_TARANIS_XLITE: case BOARD_TARANIS_XLITE:
return "Taranis X-Lite"; return "Taranis X-Lite";
case BOARD_TARANIS_XLITES: case BOARD_TARANIS_XLITES:
@ -560,6 +580,10 @@ QString Boards::getBoardName(Board::Type board)
return "Horus X10/X10S"; return "Horus X10/X10S";
case BOARD_X10_EXPRESS: case BOARD_X10_EXPRESS:
return "Horus X10/X10S Express"; return "Horus X10/X10S Express";
case BOARD_JUMPER_T12:
return "Jumper T12";
case BOARD_JUMPER_TLITE:
return "Jumper T-Lite";
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
return "Jumper T16"; return "Jumper T16";
case BOARD_JUMPER_T18: case BOARD_JUMPER_T18:
@ -568,6 +592,8 @@ QString Boards::getBoardName(Board::Type board)
return "Radiomaster TX16S"; return "Radiomaster TX16S";
case BOARD_RADIOMASTER_TX12: case BOARD_RADIOMASTER_TX12:
return "Radiomaster TX12"; return "Radiomaster TX12";
case BOARD_RADIOMASTER_T8:
return "Radiomaster T8";
default: default:
return tr("Unknown"); return tr("Unknown");
} }

View file

@ -53,10 +53,12 @@ namespace Board {
BOARD_RADIOMASTER_TX16S, BOARD_RADIOMASTER_TX16S,
BOARD_JUMPER_T18, BOARD_JUMPER_T18,
BOARD_RADIOMASTER_TX12, BOARD_RADIOMASTER_TX12,
BOARD_RADIOMASTER_T8,
BOARD_JUMPER_TLITE,
BOARD_TYPE_COUNT,
BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1
}; };
constexpr int BOARD_TYPE_MAX = BOARD_RADIOMASTER_TX12;
enum PotType enum PotType
{ {
POT_NONE, POT_NONE,
@ -204,6 +206,11 @@ inline bool IS_JUMPER_T12(Board::Type board)
return board == Board::BOARD_JUMPER_T12; return board == Board::BOARD_JUMPER_T12;
} }
inline bool IS_JUMPER_TLITE(Board::Type board)
{
return board == Board::BOARD_JUMPER_TLITE;
}
inline bool IS_JUMPER_T16(Board::Type board) inline bool IS_JUMPER_T16(Board::Type board)
{ {
return board == Board::BOARD_JUMPER_T16; return board == Board::BOARD_JUMPER_T16;
@ -224,6 +231,11 @@ inline bool IS_RADIOMASTER_TX12(Board::Type board)
return board == Board::BOARD_RADIOMASTER_TX12; return board == Board::BOARD_RADIOMASTER_TX12;
} }
inline bool IS_RADIOMASTER_T8(Board::Type board)
{
return board == Board::BOARD_RADIOMASTER_T8;
}
inline bool IS_FAMILY_T16(Board::Type board) inline bool IS_FAMILY_T16(Board::Type board)
{ {
return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18; return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18;
@ -231,7 +243,7 @@ inline bool IS_FAMILY_T16(Board::Type board)
inline bool IS_FAMILY_T12(Board::Type board) inline bool IS_FAMILY_T12(Board::Type board)
{ {
return board == Board::BOARD_JUMPER_T12 || board == Board::BOARD_RADIOMASTER_TX12; return board == Board::BOARD_JUMPER_T12 || board == Board::BOARD_RADIOMASTER_TX12 || board == Board::BOARD_RADIOMASTER_T8 || board == Board::BOARD_JUMPER_TLITE;
} }
inline bool IS_TARANIS_XLITE(Board::Type board) inline bool IS_TARANIS_XLITE(Board::Type board)

View file

@ -0,0 +1,48 @@
/*
* 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 "curvedata.h"
#include "radiodata.h"
CurveData::CurveData()
{
clear();
}
void CurveData::clear(int count)
{
memset(reinterpret_cast<void *>(this), 0, sizeof(CurveData));
this->count = count;
}
bool CurveData::isEmpty() const
{
for (int i = 0; i < count; i++) {
if (points[i].y != 0) {
return false;
}
}
return true;
}
QString CurveData::nameToString(const int idx) const
{
return RadioData::getElementName(tr("CV"), idx + 1, name);
}

View file

@ -0,0 +1,56 @@
/*
* 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 <QtCore>
class CurvePoint {
public:
int8_t x;
int8_t y;
};
#define CURVEDATA_NAME_LEN 6
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
public:
enum CurveType {
CURVE_TYPE_STANDARD,
CURVE_TYPE_CUSTOM,
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
CurveData();
CurveType type;
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
char name[CURVEDATA_NAME_LEN + 1];
void clear(int count = 5);
bool isEmpty() const;
QString nameToString(const int idx) const;
};

View file

@ -22,7 +22,7 @@
#include "adjustmentreference.h" #include "adjustmentreference.h"
#include "helpers.h" #include "helpers.h"
#include "modeldata.h" #include "modeldata.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
const QString CurveReference::toString(const ModelData * model, bool verbose) const const QString CurveReference::toString(const ModelData * model, bool verbose) const
{ {
@ -63,6 +63,11 @@ const bool CurveReference::isValueNumber() const
return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE; return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE;
} }
const bool CurveReference::isAvailable() const
{
return true;
}
// static // static
int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar) int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar)
{ {
@ -77,7 +82,7 @@ int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar)
// static // static
QString CurveReference::typeToString(const CurveRefType type) QString CurveReference::typeToString(const CurveRefType type)
{ {
const QStringList strl = { "Diff", "Expo" , "Func", "Curve" }; const QStringList strl = { tr("Diff"), tr("Expo") , tr("Func"), tr("Curve") };
int idx = (int)type; int idx = (int)type;
if (idx < 0 || idx >= strl.count()) if (idx < 0 || idx >= strl.count())
@ -86,8 +91,6 @@ QString CurveReference::typeToString(const CurveRefType type)
return strl.at(idx); return strl.at(idx);
} }
constexpr int MAX_CURVE_REF_FUNC { 6 };
// static // static
QString CurveReference::functionToString(const int value) QString CurveReference::functionToString(const int value)
{ {
@ -100,76 +103,65 @@ QString CurveReference::functionToString(const int value)
return strl.at(idx); return strl.at(idx);
} }
// static
bool CurveReference::isTypeAvailable(const CurveRefType type)
{
bool ret = false;
Firmware * fw = getCurrentFirmware();
switch(type) {
case CURVE_REF_DIFF:
if (fw->getCapability(HasInputDiff))
ret = true;
break;
case CURVE_REF_EXPO:
if (fw->getCapability(HasMixerExpo))
ret = true;
break;
case CURVE_REF_FUNC:
case CURVE_REF_CUSTOM:
ret = true;
break;
}
return ret;
}
// static
bool CurveReference::isFunctionAvailable(const int value)
{
return true;
}
// static
int CurveReference::functionCount()
{
return 6;
}
/* /*
* CurveReferenceUIManager * CurveReferenceUIManager
*/ */
constexpr int CURVE_REF_UI_HIDE_DIFF { 0x01 };
constexpr int CURVE_REF_UI_HIDE_EXPO { 0x02 };
constexpr int CURVE_REF_UI_HIDE_NEGATIVE_CURVES { 0x04 };
// static
bool CurveReferenceUIManager::firsttime { true };
int CurveReferenceUIManager::flags { 0 };
bool CurveReferenceUIManager::hasCapabilityGvars { false };
int CurveReferenceUIManager::numCurves { 0 };
RawItemFilteredModel * CurveReferenceUIManager::curveItemModel { nullptr };
QStandardItemModel * CurveReferenceUIManager::tempModel { nullptr };
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveValueCB, CurveReference & curve, const ModelData & model,
RawItemFilteredModel * curveItemModel, QObject * parent) :
QObject(parent),
curveTypeCB(nullptr),
curveGVarCB(nullptr),
curveValueSB(nullptr),
curveValueCB(curveValueCB),
curve(curve),
model(model),
lock(false)
{
init(curveItemModel);
}
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB, CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB,
QComboBox * curveValueCB, CurveReference & curve, const ModelData & model, QComboBox * curveValueCB, CurveReference & curveRef, const ModelData & model,
RawItemFilteredModel * curveItemModel, QObject * parent) : CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent) :
QObject(parent), QObject(parent),
curveTypeCB(curveTypeCB), curveTypeCB(curveTypeCB),
curveGVarCB(curveGVarCB), curveGVarCB(curveGVarCB),
curveValueSB(curveValueSB), curveValueSB(curveValueSB),
curveValueCB(curveValueCB), curveValueCB(curveValueCB),
curve(curve), curveRef(curveRef),
model(model), model(model),
lock(false) lock(false),
filteredModelFactory(curveRefFilteredFactory)
{ {
init(curveItemModel); hasCapabilityGvars = getCurrentFirmware()->getCapability(Gvars);
}
CurveReferenceUIManager::~CurveReferenceUIManager()
{
delete tempModel;
}
void CurveReferenceUIManager::init(RawItemFilteredModel * curveModel)
{
tempModel = new QStandardItemModel();
if (firsttime) {
firsttime = false;
Firmware * fw = getCurrentFirmware();
hasCapabilityGvars = fw->getCapability(Gvars);
numCurves = fw->getCapability(NumCurves);
curveItemModel = curveModel;
if (!fw->getCapability(HasInputDiff))
flags |= (CURVE_REF_UI_HIDE_DIFF | CURVE_REF_UI_HIDE_NEGATIVE_CURVES);
if (!fw->getCapability(HasMixerExpo))
flags |= CURVE_REF_UI_HIDE_EXPO;
}
if (curveTypeCB) { if (curveTypeCB) {
populateTypeCB(curveTypeCB, curve); curveTypeCB->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_TYPE));
curveTypeCB->setCurrentIndex(curveTypeCB->findData((int)curveRef.type));
connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int))); connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
} }
@ -182,13 +174,20 @@ void CurveReferenceUIManager::init(RawItemFilteredModel * curveModel)
connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged())); connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged()));
} }
curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); if (curveValueCB) {
curveValueCB->setMaxVisibleItems(10); curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents);
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged())); curveValueCB->setMaxVisibleItems(10);
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged()));
}
update(); update();
} }
CurveReferenceUIManager::~CurveReferenceUIManager()
{
delete filteredModelFactory;
}
#define CURVE_REF_UI_GVAR_SHOW (1<<0) #define CURVE_REF_UI_GVAR_SHOW (1<<0)
#define CURVE_REF_UI_VALUE_SHOW (1<<1) #define CURVE_REF_UI_VALUE_SHOW (1<<1)
#define CURVE_REF_UI_REF_SHOW (1<<2) #define CURVE_REF_UI_REF_SHOW (1<<2)
@ -198,12 +197,12 @@ void CurveReferenceUIManager::update()
lock = true; lock = true;
int widgetsMask = 0; int widgetsMask = 0;
if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) { if (curveRef.type == CurveReference::CURVE_REF_DIFF || curveRef.type == CurveReference::CURVE_REF_EXPO) {
if (hasCapabilityGvars) if (hasCapabilityGvars)
widgetsMask |= CURVE_REF_UI_GVAR_SHOW; widgetsMask |= CURVE_REF_UI_GVAR_SHOW;
if (curve.isValueNumber()) { if (curveRef.isValueNumber()) {
curveGVarCB->setChecked(false); curveGVarCB->setChecked(false);
curveValueSB->setValue(curve.value); curveValueSB->setValue(curveRef.value);
widgetsMask |= CURVE_REF_UI_VALUE_SHOW; widgetsMask |= CURVE_REF_UI_VALUE_SHOW;
} }
else { else {
@ -216,7 +215,7 @@ void CurveReferenceUIManager::update()
} }
if(curveTypeCB) { if(curveTypeCB) {
curveTypeCB->setCurrentIndex(curveTypeCB->findData(curve.type)); curveTypeCB->setCurrentIndex(curveTypeCB->findData(curveRef.type));
curveTypeCB->show(); curveTypeCB->show();
} }
if(curveGVarCB) if(curveGVarCB)
@ -224,8 +223,8 @@ void CurveReferenceUIManager::update()
if(curveValueSB) if(curveValueSB)
curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW); curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW);
if(curveValueCB) { if(curveValueCB) {
if (curve.isValueReference()) if (curveRef.isValueReference())
populateValueCB(curveValueCB, curve, &model); populateValueCB(curveValueCB);
curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW); curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW);
} }
@ -235,7 +234,7 @@ void CurveReferenceUIManager::update()
void CurveReferenceUIManager::gvarCBChanged(int state) void CurveReferenceUIManager::gvarCBChanged(int state)
{ {
if (!lock) { if (!lock) {
curve.value = CurveReference::getDefaultValue(curve.type, state); curveRef.value = CurveReference::getDefaultValue(curveRef.type, state);
update(); update();
} }
} }
@ -244,7 +243,7 @@ void CurveReferenceUIManager::typeChanged(int value)
{ {
if (!lock) { if (!lock) {
CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt(); CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
curve = CurveReference(type, CurveReference::getDefaultValue(type)); curveRef = CurveReference(type, CurveReference::getDefaultValue(type));
update(); update();
} }
} }
@ -252,7 +251,7 @@ void CurveReferenceUIManager::typeChanged(int value)
void CurveReferenceUIManager::valueSBChanged() void CurveReferenceUIManager::valueSBChanged()
{ {
if (!lock) { if (!lock) {
curve.value = curveValueSB->value(); curveRef.value = curveValueSB->value();
update(); update();
} }
} }
@ -260,47 +259,24 @@ void CurveReferenceUIManager::valueSBChanged()
void CurveReferenceUIManager::valueCBChanged() void CurveReferenceUIManager::valueCBChanged()
{ {
if (!lock) { if (!lock) {
curve.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt(); curveRef.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
update(); update();
} }
} }
// static void CurveReferenceUIManager::populateValueCB(QComboBox * cb)
void CurveReferenceUIManager::populateTypeCB(QComboBox * cb, const CurveReference & curveRef)
{ {
if (cb) { if (cb) {
cb->clear();
for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) {
if ((curveRef.type == CurveReference::CURVE_REF_DIFF && !(flags & CURVE_REF_UI_HIDE_DIFF)) ||
(curveRef.type == CurveReference::CURVE_REF_EXPO && !(flags & CURVE_REF_UI_HIDE_EXPO)) ||
(curveRef.type != CurveReference::CURVE_REF_DIFF && curveRef.type != CurveReference::CURVE_REF_EXPO))
cb->addItem(CurveReference::typeToString((CurveReference::CurveRefType)i), i);
}
cb->setCurrentIndex(cb->findData((int)curveRef.type));
}
}
// static
void CurveReferenceUIManager::populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model)
{
if (cb) {
cb->setModel(tempModel); // do not want to clear/alter the shared curves model and set to nullptr is invalid
switch (curveRef.type) { switch (curveRef.type) {
case CurveReference::CURVE_REF_DIFF: case CurveReference::CURVE_REF_DIFF:
case CurveReference::CURVE_REF_EXPO: case CurveReference::CURVE_REF_EXPO:
cb->clear(); cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_GVARREF));
Helpers::populateGVCB(*cb, curveRef.value, *model);
break; break;
case CurveReference::CURVE_REF_FUNC: case CurveReference::CURVE_REF_FUNC:
cb->clear(); cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_FUNC));
for (int i = 1; i <= MAX_CURVE_REF_FUNC; i++) {
cb->addItem(CurveReference::functionToString(i), i);
}
break; break;
case CurveReference::CURVE_REF_CUSTOM: case CurveReference::CURVE_REF_CUSTOM:
cb->setModel(curveItemModel); cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_CURVE));
break; break;
default: default:
break; break;

View file

@ -29,7 +29,7 @@
class ModelData; class ModelData;
class RawItemFilteredModel; class CurveRefFilteredFactory;
class CurveReference { class CurveReference {
@ -63,6 +63,7 @@ class CurveReference {
const bool isValueNumber() const; const bool isValueNumber() const;
const bool isValueReference() const { return !isValueNumber(); } const bool isValueReference() const { return !isValueNumber(); }
const QString toString(const ModelData * model = nullptr, bool verbose = true) const; const QString toString(const ModelData * model = nullptr, bool verbose = true) const;
const bool isAvailable() const;
CurveRefType type; CurveRefType type;
int value; int value;
@ -78,6 +79,9 @@ class CurveReference {
static int getDefaultValue(const CurveRefType type, const bool isGVar = false); static int getDefaultValue(const CurveRefType type, const bool isGVar = false);
static QString typeToString(const CurveRefType type); static QString typeToString(const CurveRefType type);
static QString functionToString(const int value); static QString functionToString(const int value);
static bool isTypeAvailable(const CurveRefType type);
static bool isFunctionAvailable(const int value);
static int functionCount();
}; };
class CurveReferenceUIManager : public QObject { class CurveReferenceUIManager : public QObject {
@ -85,38 +89,34 @@ class CurveReferenceUIManager : public QObject {
Q_OBJECT Q_OBJECT
public: public:
CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model, explicit CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB,
RawItemFilteredModel * curveItemModel, QObject * parent = nullptr); CurveReference & curve, const ModelData & model, CurveRefFilteredFactory * curveRefFilteredFactory,
CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB, QObject * parent = nullptr);
CurveReference & curve, const ModelData & model, RawItemFilteredModel * curveItemModel, QObject * parent = nullptr);
explicit CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model,
CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr) :
CurveReferenceUIManager(nullptr, nullptr, nullptr, curveValueCB, curve, model, curveRefFilteredFactory, parent) {}
virtual ~CurveReferenceUIManager(); virtual ~CurveReferenceUIManager();
void init(RawItemFilteredModel * curveModel);
void update();
protected slots: protected slots:
void gvarCBChanged(int); void gvarCBChanged(int);
void typeChanged(int); void typeChanged(int);
void valueSBChanged(); void valueSBChanged();
void valueCBChanged(); void valueCBChanged();
void update();
protected: private:
QComboBox *curveTypeCB; QComboBox *curveTypeCB;
QCheckBox *curveGVarCB; QCheckBox *curveGVarCB;
QSpinBox *curveValueSB; QSpinBox *curveValueSB;
QComboBox *curveValueCB; QComboBox *curveValueCB;
CurveReference & curve; CurveReference & curveRef;
const ModelData & model; const ModelData & model;
bool lock; bool lock;
bool hasCapabilityGvars;
static bool firsttime; CurveRefFilteredFactory *filteredModelFactory;
static int flags; void populateValueCB(QComboBox * cb);
static bool hasCapabilityGvars;
static int numCurves;
static RawItemFilteredModel * curveItemModel;
static QStandardItemModel * tempModel;
static void populateTypeCB(QComboBox * cb, const CurveReference & curveRef);
static void populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model = nullptr);
}; };
#endif // CURVEREFERENCE_H #endif // CURVEREFERENCE_H

View file

@ -22,6 +22,17 @@
#include "eeprominterface.h" #include "eeprominterface.h"
#include "radiodata.h" #include "radiodata.h"
#include "radiodataconversionstate.h" #include "radiodataconversionstate.h"
#include "compounditemmodels.h"
void CustomFunctionData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate);
if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
}
}
void CustomFunctionData::clear() void CustomFunctionData::clear()
{ {
@ -36,14 +47,21 @@ bool CustomFunctionData::isEmpty() const
return (swtch.type == SWITCH_TYPE_NONE); return (swtch.type == SWITCH_TYPE_NONE);
} }
QString CustomFunctionData::nameToString(int index, bool globalContext) const // static
QString CustomFunctionData::nameToString(const int index, const bool globalContext)
{ {
return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index+1, 0, true); return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index + 1, 0, true);
} }
QString CustomFunctionData::funcToString(const ModelData * model) const QString CustomFunctionData::funcToString(const ModelData * model) const
{ {
if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) return funcToString(func, model);
}
// static
QString CustomFunctionData::funcToString(const AssignFunc func, const ModelData * model)
{
if (func >= FuncOverrideCH1 && func <= FuncOverrideCHLast)
return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model)); return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
else if (func == FuncTrainer) else if (func == FuncTrainer)
return tr("Trainer Sticks"); return tr("Trainer Sticks");
@ -65,8 +83,8 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
return tr("Haptic"); return tr("Haptic");
else if (func == FuncReset) else if (func == FuncReset)
return tr("Reset"); return tr("Reset");
else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) else if (func >= FuncSetTimer1 && func <= FuncSetTimerLast)
return tr("Set Timer %1").arg(func-FuncSetTimer1+1); return tr("Set %1").arg(RawSource(SOURCE_TYPE_SPECIAL, SOURCE_TYPE_SPECIAL_TIMER1_IDX + func - FuncSetTimer1).toString(model));
else if (func == FuncVario) else if (func == FuncVario)
return tr("Vario"); return tr("Vario");
else if (func == FuncPlayPrompt) else if (func == FuncPlayPrompt)
@ -76,7 +94,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
else if (func == FuncPlayValue) else if (func == FuncPlayValue)
return tr("Play Value"); return tr("Play Value");
else if (func == FuncPlayScript) else if (func == FuncPlayScript)
return tr("Play Script"); return tr("Lua Script");
else if (func == FuncLogs) else if (func == FuncLogs)
return tr("SD Logs"); return tr("SD Logs");
else if (func == FuncVolume) else if (func == FuncVolume)
@ -90,62 +108,22 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
else if (func == FuncBackgroundMusicPause) else if (func == FuncBackgroundMusicPause)
return tr("Background Music Pause"); return tr("Background Music Pause");
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast)
return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model)); return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func - FuncAdjustGV1).toString(model));
else if (func == FuncSetFailsafe) else if (func == FuncSetFailsafe)
return tr("Set Failsafe"); return tr("Set Failsafe");
else if (func == FuncRangeCheckInternalModule) else if (func == FuncRangeCheckInternalModule)
return tr("RangeCheck Int. Module"); return tr("Range Check Int. Module");
else if (func == FuncRangeCheckExternalModule) else if (func == FuncRangeCheckExternalModule)
return tr("RangeCheck Ext. Module"); return tr("Range Check Ext. Module");
else if (func == FuncBindInternalModule) else if (func == FuncBindInternalModule)
return tr("Bind Int. Module"); return tr("Bind Int. Module");
else if (func == FuncBindExternalModule) else if (func == FuncBindExternalModule)
return tr("Bind Ext. Module"); return tr("Bind Ext. Module");
else { else {
return QString("???"); // Highlight unknown functions with output of question marks.(BTW should not happen that we do not know what a function is) return QString(CPN_STR_UNKNOWN_ITEM);
} }
} }
void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox * b, unsigned int value = 0)
{
int val = 0;
Firmware * firmware = Firmware::getCurrentVariant();
b->addItem(tr("Timer1"), val++);
b->addItem(tr("Timer2"), val++);
b->addItem( tr("Timer3"), val++);
b->addItem(tr("Flight"), val++);
b->addItem(tr("Telemetry"), val++);
int reCount = firmware->getCapability(RotaryEncoders);
if (reCount == 1) {
b->addItem(tr("Rotary Encoder"), val++);
}
else if (reCount == 2) {
b->addItem(tr("REa"), val++);
b->addItem(tr("REb"), val++);
}
if (model) {
for (int i = 0; i < firmware->getCapability(Sensors); ++i) {
if (model->sensorData[i].isAvailable()) {
RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3 * i);
b->addItem(item.toString(model), val + i);
}
}
}
b->setCurrentIndex(b->findData(value));
}
void CustomFunctionData::populatePlaySoundParams(QStringList & qs)
{
qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ;
qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ;
}
void CustomFunctionData::populateHapticParams(QStringList & qs)
{
qs << "0" << "1" << "2" << "3";
}
QString CustomFunctionData::paramToString(const ModelData * model) const QString CustomFunctionData::paramToString(const ModelData * model) const
{ {
QStringList qs; QStringList qs;
@ -153,34 +131,19 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
return QString("%1").arg(param); return QString("%1").arg(param);
} }
else if (func == FuncLogs) { else if (func == FuncLogs) {
return QString("%1").arg(param/10.0) + tr("s"); return QString("%1").arg(param / 10.0) + tr("s");
} }
else if (func == FuncPlaySound) { else if (func == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs); return playSoundToString(param);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
} }
else if (func == FuncPlayHaptic) { else if (func == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs); return harpicToString(param);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
} }
else if (func == FuncReset) { else if (func == FuncReset) {
QComboBox cb; return resetToString(param, model);
CustomFunctionData::populateResetParams(model, &cb);
int pos = cb.findData(param);
if (pos >= 0)
return cb.itemText(pos);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
} }
else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) { else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) {
RawSource item(param); return RawSource(param).toString(model);
return item.toString(model);
} }
else if (func == FuncPlayPrompt || func == FuncPlayBoth) { else if (func == FuncPlayPrompt || func == FuncPlayBoth) {
if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) { if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) {
@ -193,16 +156,14 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
else if (func >= FuncAdjustGV1 && func < FuncCount) { else if (func >= FuncAdjustGV1 && func < FuncCount) {
switch (adjustMode) { switch (adjustMode) {
case FUNC_ADJUST_GVAR_CONSTANT: case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value ")+QString("%1").arg(param); return gvarAdjustModeToString(adjustMode) + QString(" %1").arg(param);
case FUNC_ADJUST_GVAR_SOURCE: case FUNC_ADJUST_GVAR_SOURCE:
case FUNC_ADJUST_GVAR_GVAR: case FUNC_ADJUST_GVAR_GVAR:
return RawSource(param).toString(); return RawSource(param).toString();
case FUNC_ADJUST_GVAR_INCDEC: case FUNC_ADJUST_GVAR_INCDEC:
float val; const float val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
QString unit; const QString unit = model->gvarData[func - FuncAdjustGV1].unitToString();
val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet(); return gvarAdjustModeToString(adjustMode) + QString(": %1%2").arg(val).arg(unit);
unit = model->gvarData[func - FuncAdjustGV1].unitToString();
return QString("Increment: %1%2").arg(val).arg(unit);
} }
} }
return ""; return "";
@ -210,24 +171,29 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
QString CustomFunctionData::repeatToString() const QString CustomFunctionData::repeatToString() const
{ {
if (repeatParam == -1) { return repeatToString(repeatParam);
return tr("played once, not during startup"); }
// static
QString CustomFunctionData::repeatToString(const int value)
{
if (value == -1) {
return tr("Played once, not during startup");
} }
else if (repeatParam == 0) { else if (value == 0) {
return ""; return tr("No repeat");
} }
else { else {
unsigned int step = 1; return tr("Repeat %1s").arg(value);
return tr("repeat(%1s)").arg(step*repeatParam);
} }
} }
QString CustomFunctionData::enabledToString() const QString CustomFunctionData::enabledToString() const
{ {
if ((func >= FuncOverrideCH1 && func <= FuncOverrideCH32) || if ((func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) ||
(func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) ||
(func == FuncReset) || (func == FuncReset) ||
(func >= FuncSetTimer1 && func <= FuncSetTimer2) || (func >= FuncSetTimer1 && func <= FuncSetTimerLast) ||
(func == FuncVolume) || (func == FuncVolume) ||
(func == FuncBacklight) || (func == FuncBacklight) ||
(func <= FuncInstantTrim)) { (func <= FuncInstantTrim)) {
@ -238,12 +204,197 @@ QString CustomFunctionData::enabledToString() const
return ""; return "";
} }
void CustomFunctionData::convert(RadioDataConversionState & cstate) // static
bool CustomFunctionData::isFuncAvailable(const int index)
{ {
cstate.setComponent(tr("CFN"), 8); Firmware * fw = getCurrentFirmware();
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate); bool ret = (((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) && !fw->getCapability(SafetyChannelCustomFunction)) ||
if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) { ((index == FuncVolume || index == FuncBackgroundMusic || index == FuncBackgroundMusicPause) && !fw->getCapability(HasVolume)) ||
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue(); ((index == FuncPlayScript && !IS_HORUS_OR_TARANIS(fw->getBoard()))) ||
((index == FuncPlayHaptic) && !fw->getCapability(Haptic)) ||
((index == FuncPlayBoth) && !fw->getCapability(HasBeeper)) ||
((index == FuncLogs) && !fw->getCapability(HasSDLogs)) ||
((index >= FuncSetTimer1 && index <= FuncSetTimerLast) && index > FuncSetTimer1 + fw->getCapability(Timers)) ||
((index == FuncScreenshot) && !IS_HORUS_OR_TARANIS(fw->getBoard())) ||
((index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) && !fw->getCapability(DangerousFunctions)) ||
((index >= FuncAdjustGV1 && index <= FuncAdjustGVLast) && !fw->getCapability(Gvars))
);
return !ret;
}
// static
int CustomFunctionData::funcContext(const int index)
{
int ret = AllFunctionContexts;
if ((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) ||
(index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) ||
(index >= FuncAdjustGV1 && index <= FuncAdjustGVLast))
ret &= ~GlobalFunctionsContext;
return ret;
}
// static
QString CustomFunctionData::resetToString(const int value, const ModelData * model)
{
Firmware * firmware = getCurrentFirmware();
int step = CPN_MAX_TIMERS;
if (value < step) {
if (value < firmware->getCapability(Timers))
return RawSource(SOURCE_TYPE_SPECIAL, value + SOURCE_TYPE_SPECIAL_TIMER1_IDX).toString(model);
else
return QString(CPN_STR_UNKNOWN_ITEM);
}
if (value < ++step)
return tr("Flight");
if (value < ++step)
return tr("Telemetry");
if (value < step + firmware->getCapability(Sensors))
return RawSource(SOURCE_TYPE_TELEMETRY, 3 * (value - step)).toString(model);
return QString(CPN_STR_UNKNOWN_ITEM);
}
// static
int CustomFunctionData::resetParamCount()
{
Firmware * firmware = getCurrentFirmware();
return CPN_MAX_TIMERS + 2 + firmware->getCapability(Sensors);
}
// static
bool CustomFunctionData::isResetParamAvailable(const int index, const ModelData * model)
{
Firmware * firmware = getCurrentFirmware();
if (index < CPN_MAX_TIMERS) {
if (index < firmware->getCapability(Timers))
return true;
else
return false;
}
else if (index < CPN_MAX_TIMERS + 2)
return true;
else if (model && index < resetParamCount())
return model->sensorData[index - (CPN_MAX_TIMERS + 2)].isAvailable();
return false;
}
QString CustomFunctionData::harpicToString() const
{
return harpicToString(param);
}
// static
QString CustomFunctionData::harpicToString(const int value)
{
return QString("%1").arg(value);
}
// static
QStringList CustomFunctionData::playSoundStringList()
{
return QStringList({ tr("Beep 1"), tr("Beep 2"), tr("Beep 3"), tr("Warn 1"), tr("Warn 2"), tr("Cheep"), tr("Ratata"), tr("Tick"),
tr("Siren"), tr("Ring"), tr("Sci Fi"), tr("Robot"), tr("Chirp"), tr("Tada"), tr("Cricket"), tr("Alarm Clock") });
}
QString CustomFunctionData::playSoundToString() const
{
return playSoundToString(param);
}
// static
QString CustomFunctionData::playSoundToString(const int value)
{
const QStringList strl = playSoundStringList();
if (value < strl.count())
return strl.at(value);
else
return QString(CPN_STR_UNKNOWN_ITEM);
}
QString CustomFunctionData::gvarAdjustModeToString() const
{
return gvarAdjustModeToString(adjustMode);
}
// static
QString CustomFunctionData::gvarAdjustModeToString(const int value)
{
switch (value) {
case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value");
case FUNC_ADJUST_GVAR_SOURCE:
return tr("Source");
case FUNC_ADJUST_GVAR_GVAR:
return tr("Global Variable");
case FUNC_ADJUST_GVAR_INCDEC:
return tr("Inc/Decrement");
default:
return QString(CPN_STR_UNKNOWN_ITEM);
} }
} }
// static
AbstractStaticItemModel * CustomFunctionData::repeatItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.repeat");
for (int i = -1; i <= 60; i++) {
mdl->appendToItemList(repeatToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::playSoundItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.playsound");
for (int i = 0; i < playSoundStringList().count(); i++) {
mdl->appendToItemList(playSoundToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::harpicItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.harpic");
for (int i = 0; i <= 3; i++) {
mdl->appendToItemList(harpicToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::gvarAdjustModeItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.gvaradjustmode");
for (int i = 0; i < FUNC_ADJUST_GVAR_COUNT; i++) {
mdl->appendToItemList(gvarAdjustModeToString(i), i);
}
mdl->loadItemList();
return mdl;
}

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef CUSTOMFUNCTIONDATA_H #pragma once
#define CUSTOMFUNCTIONDATA_H
#include "boards.h" #include "boards.h"
#include "constants.h" #include "constants.h"
@ -32,10 +31,12 @@ class Firmware;
class ModelData; class ModelData;
class GeneralSettings; class GeneralSettings;
class RadioDataConversionState; class RadioDataConversionState;
class AbstractStaticItemModel;
enum AssignFunc { enum AssignFunc {
FuncOverrideCH1 = 0, FuncOverrideCH1 = 0,
FuncOverrideCH32 = FuncOverrideCH1+CPN_MAX_CHNOUT-1, FuncOverrideCHLast = FuncOverrideCH1 + CPN_MAX_CHNOUT - 1,
FuncOverrideCH32 = FuncOverrideCHLast, // TODO remove
FuncTrainer, FuncTrainer,
FuncTrainerRUD, FuncTrainerRUD,
FuncTrainerELE, FuncTrainerELE,
@ -47,8 +48,9 @@ enum AssignFunc {
FuncPlayHaptic, FuncPlayHaptic,
FuncReset, FuncReset,
FuncSetTimer1, FuncSetTimer1,
FuncSetTimer2, FuncSetTimer2, // TODO remove
FuncSetTimer3, FuncSetTimer3, // TODO remove
FuncSetTimerLast = FuncSetTimer1 + CPN_MAX_TIMERS - 1,
FuncVario, FuncVario,
FuncPlayPrompt, FuncPlayPrompt,
FuncPlayBoth, FuncPlayBoth,
@ -61,7 +63,7 @@ enum AssignFunc {
FuncBackgroundMusic, FuncBackgroundMusic,
FuncBackgroundMusicPause, FuncBackgroundMusicPause,
FuncAdjustGV1, FuncAdjustGV1,
FuncAdjustGVLast = FuncAdjustGV1+CPN_MAX_GVARS-1, FuncAdjustGVLast = FuncAdjustGV1 + CPN_MAX_GVARS - 1,
FuncSetFailsafe, FuncSetFailsafe,
FuncRangeCheckInternalModule, FuncRangeCheckInternalModule,
FuncRangeCheckExternalModule, FuncRangeCheckExternalModule,
@ -76,14 +78,23 @@ enum GVarAdjustModes
FUNC_ADJUST_GVAR_CONSTANT, FUNC_ADJUST_GVAR_CONSTANT,
FUNC_ADJUST_GVAR_SOURCE, FUNC_ADJUST_GVAR_SOURCE,
FUNC_ADJUST_GVAR_GVAR, FUNC_ADJUST_GVAR_GVAR,
FUNC_ADJUST_GVAR_INCDEC FUNC_ADJUST_GVAR_INCDEC,
FUNC_ADJUST_GVAR_COUNT
}; };
class CustomFunctionData { class CustomFunctionData {
Q_DECLARE_TR_FUNCTIONS(CustomFunctionData) Q_DECLARE_TR_FUNCTIONS(CustomFunctionData)
public: public:
CustomFunctionData(AssignFunc func=FuncOverrideCH1) { clear(); this->func = func; } enum CustomFunctionContext
{
GlobalFunctionsContext = 0x01,
SpecialFunctionsContext = 0x02,
AllFunctionContexts = GlobalFunctionsContext | SpecialFunctionsContext
};
CustomFunctionData(AssignFunc func = FuncOverrideCH1) { clear(); this->func = func; }
RawSwitch swtch; RawSwitch swtch;
AssignFunc func; AssignFunc func;
int param; int param;
@ -92,21 +103,33 @@ class CustomFunctionData {
unsigned int adjustMode; unsigned int adjustMode;
int repeatParam; int repeatParam;
void clear();
bool isEmpty() const;
QString nameToString(int index, bool globalContext = false) const;
QString funcToString(const ModelData * model = NULL) const;
QString paramToString(const ModelData * model) const;
QString repeatToString() const;
QString enabledToString() const;
static void populateResetParams(const ModelData * model, QComboBox * b, unsigned int value);
static void populatePlaySoundParams(QStringList & qs);
static void populateHapticParams(QStringList & qs);
void convert(RadioDataConversionState & cstate); void convert(RadioDataConversionState & cstate);
void clear();
bool isEmpty() const;
QString funcToString(const ModelData * model = nullptr) const;
QString paramToString(const ModelData * model = nullptr) const;
QString repeatToString() const;
QString enabledToString() const;
QString playSoundToString() const;
QString harpicToString() const;
QString gvarAdjustModeToString() const;
static QString nameToString(const int index, const bool globalContext = false);
static QString funcToString(const AssignFunc func, const ModelData * model = nullptr);
static bool isFuncAvailable(const int index);
static int funcContext(const int index);
static QString resetToString(const int value, const ModelData * model = nullptr);
static int resetParamCount();
static bool isResetParamAvailable(const int index, const ModelData * model = nullptr);
static QString repeatToString(const int value);
static QStringList playSoundStringList();
static QString playSoundToString(const int value);
static QString harpicToString(const int value);
static QStringList gvarAdjustModeStringList();
static QString gvarAdjustModeToString(const int value);
static AbstractStaticItemModel * repeatItemModel();
static AbstractStaticItemModel * playSoundItemModel();
static AbstractStaticItemModel * harpicItemModel();
static AbstractStaticItemModel * gvarAdjustModeItemModel();
}; };
#endif // CUSTOMFUNCTIONDATA_H

View file

@ -0,0 +1,70 @@
/*
* 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 "datahelpers.h"
QString DataHelpers::boolToString(const bool value, const BoolFormat format)
{
static const char *strings[] = {
QT_TRANSLATE_NOOP("DataHelpers", "Disabled"),
QT_TRANSLATE_NOOP("DataHelpers", "Enabled"),
QT_TRANSLATE_NOOP("DataHelpers", "OFF"),
QT_TRANSLATE_NOOP("DataHelpers", "ON"),
QT_TRANSLATE_NOOP("DataHelpers", "False"),
QT_TRANSLATE_NOOP("DataHelpers", "True"),
QT_TRANSLATE_NOOP("DataHelpers", "N"),
QT_TRANSLATE_NOOP("DataHelpers", "Y"),
QT_TRANSLATE_NOOP("DataHelpers", "No"),
QT_TRANSLATE_NOOP("DataHelpers", "Yes")
};
return QCoreApplication::translate("DataHelpers", strings[format * 2 + value]);
}
QString DataHelpers::getElementName(const QString & prefix, const unsigned int index, const char * name, const bool padding)
{
QString result = prefix;
result.append(padding ? QString("%1").arg(index, 2, 10, QChar('0')) : QString("%1").arg(index));
if (name && QString(name).trimmed().length() > 0)
result.append(":" + QString(name).trimmed());
return result;
}
QString DataHelpers::timeToString(const int value, const unsigned int mask)
{
bool negative = value < 0 ? true : false;
int val = abs(value);
QString result = QString("%1").arg(negative ? "-" : ((mask & TIMESTR_MASK_PADSIGN) ? " " : ""));
if (mask & TIMESTR_MASK_HRSMINS) {
int hours = val / 3600;
if (hours > 0 || (mask & TIMESTR_MASK_ZEROHRS)) {
val -= hours * 3600;
result.append(QString("%1:").arg(hours, 2, 10, QLatin1Char('0')));
}
}
int minutes = val / 60;
int seconds = val % 60;
result.append(QString("%1:%2").arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
return result;
}

View file

@ -0,0 +1,69 @@
/*
* 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 <QtCore>
class FieldRange
{
public:
FieldRange():
decimals(0),
min(0.0),
max(0.0),
step(1.0),
offset(0.0),
prefix(""),
unit("")
{
}
float getValue(int value) { return float(value) * step; }
int decimals;
double min;
double max;
double step;
double offset;
QString prefix;
QString unit;
};
constexpr unsigned int TIMESTR_MASK_HRSMINS { 1 << 1 };
constexpr unsigned int TIMESTR_MASK_ZEROHRS { 1 << 2 };
constexpr unsigned int TIMESTR_MASK_PADSIGN { 1 << 3 };
namespace DataHelpers
{
enum BoolFormat {
BOOL_FMT_ENABLEDISABLE,
BOOL_FMT_ONOFF,
BOOL_FMT_TRUEFALSE,
BOOL_FMT_YN,
BOOL_FMT_YESNO
};
QString boolToString(const bool value, const BoolFormat format);
QString getElementName(const QString & prefix, const unsigned int index, const char * name = 0, const bool padding = false);
QString timeToString(const int value, const unsigned int mask);
}

View file

@ -18,121 +18,17 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include "io_data.h" #include "flightmodedata.h"
#include "radiodata.h"
#include "radiodata.h" // for RadioData::getElementName
#include "radiodataconversionstate.h" #include "radiodataconversionstate.h"
/* void FlightModeData::convert(RadioDataConversionState & cstate)
* ExpoData
*/
void ExpoData::convert(RadioDataConversionState & cstate)
{ {
cstate.setComponent(tr("INP"), 3); cstate.setComponent("FMD", 2);
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx)); cstate.setSubComp(nameToString(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate); swtch.convert(cstate);
} }
bool ExpoData::isEmpty() const
{
return (chn == 0 && mode == INPUT_MODE_NONE);
}
/*
* MixData
*/
void MixData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("MIX"), 4);
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool MixData::isEmpty() const
{
return (destCh == 0);
}
/*
* LimitData
*/
QString LimitData::minToString() const
{
return QString::number((qreal)min/10);
}
QString LimitData::maxToString() const
{
return QString::number((qreal)max/10);
}
QString LimitData::revertToString() const
{
return revert ? tr("INV") : tr("NOR");
}
QString LimitData::nameToString(int index) const
{
return RadioData::getElementName(tr("CH"), index + 1, name);
}
QString LimitData::offsetToString() const
{
return QString::number((qreal)offset/10, 'f', 1);
}
void LimitData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
min = -1000;
max = +1000;
}
bool LimitData::isEmpty() const
{
return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0' && !curve.isSet());
}
/*
* CurveData
*/
CurveData::CurveData()
{
clear();
}
void CurveData::clear(int count)
{
memset(this, 0, sizeof(CurveData));
this->count = count;
}
bool CurveData::isEmpty() const
{
for (int i=0; i<count; i++) {
if (points[i].y != 0) {
return false;
}
}
return true;
}
QString CurveData::nameToString(const int idx) const
{
return RadioData::getElementName(tr("CV"), idx + 1, name);
}
/*
* FlightModeData
*/
void FlightModeData::clear(const int phaseIdx) void FlightModeData::clear(const int phaseIdx)
{ {
memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData)); memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData));
@ -149,13 +45,6 @@ QString FlightModeData::nameToString(int phaseIdx) const
return RadioData::getElementName(tr("FM"), phaseIdx, name); // names are zero-based, FM0, FM1, etc return RadioData::getElementName(tr("FM"), phaseIdx, name); // names are zero-based, FM0, FM1, etc
} }
void FlightModeData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent("FMD", 2);
cstate.setSubComp(nameToString(cstate.subCompIdx));
swtch.convert(cstate);
}
bool FlightModeData::isEmpty(int phaseIdx) const bool FlightModeData::isEmpty(int phaseIdx) const
{ {
if (name[0] != '\0' || swtch.isSet() || fadeIn != 0 || fadeOut != 0) if (name[0] != '\0' || swtch.isSet() || fadeIn != 0 || fadeOut != 0)

View file

@ -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 "constants.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
#define FLIGHTMODE_NAME_LEN 10
#define RENC_MAX_VALUE 1024
#define RENC_MIN_VALUE -RENC_MAX_VALUE
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
public:
FlightModeData() { clear(0); }
int trimMode[CPN_MAX_TRIMS];
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
char name[FLIGHTMODE_NAME_LEN + 1];
unsigned int fadeIn;
unsigned int fadeOut;
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void convert(RadioDataConversionState & cstate);
void clear(const int phaseIdx);
bool isEmpty(int phaseIdx) const;
QString nameToString(int phaseIdx) const;
bool isGVarEmpty(int phaseIdx, int gvIdx) const;
bool isREncEmpty(int phaseIdx, int reIdx) const;
int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
int linkedGVarFlightModeZero(int phaseIdx) const;
int linkedREncFlightModeZero(int phaseIdx) const;
};

View file

@ -94,6 +94,12 @@ GeneralSettings::GeneralSettings()
vBatMin = -23; // 6.7V vBatMin = -23; // 6.7V
vBatMax = -37; // 8.3V vBatMax = -37; // 8.3V
} }
else if (IS_JUMPER_TLITE(board)) {
// 1S Li-Ion
vBatWarn = 32;
vBatMin = -60; //3V
vBatMax = -78; //4.2V
}
else if (IS_TARANIS(board)) { else if (IS_TARANIS(board)) {
// NI-MH 7.2V, X9D, X9D+ and X7 // NI-MH 7.2V, X9D, X9D+ and X7
vBatWarn = 65; vBatWarn = 65;
@ -239,6 +245,10 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board)
switchConfig[i] = Boards::getSwitchInfo(board, i).config; switchConfig[i] = Boards::getSwitchInfo(board, i).config;
} }
// TLite does not have pots or sliders
if (IS_JUMPER_TLITE(board))
return;
// TODO: move to Boards, like with switches // TODO: move to Boards, like with switches
if (IS_FAMILY_HORUS_OR_T16(board)) { if (IS_FAMILY_HORUS_OR_T16(board)) {
potConfig[0] = Board::POT_WITH_DETENT; potConfig[0] = Board::POT_WITH_DETENT;

View file

@ -0,0 +1,21 @@
/*
* 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 "heli_data.h"

View file

@ -0,0 +1,44 @@
/*
* 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 "rawsource.h"
#include <QtCore>
class SwashRingData {
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
public:
SwashRingData() { clear(); }
int elevatorWeight;
int aileronWeight;
int collectiveWeight;
unsigned int type;
RawSource collectiveSource;
RawSource aileronSource;
RawSource elevatorSource;
unsigned int value;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
};

View file

@ -0,0 +1,35 @@
/*
* 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 "input_data.h"
#include "radiodataconversionstate.h"
void ExpoData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("INP"), 3);
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool ExpoData::isEmpty() const
{
return (chn == 0 && mode == INPUT_MODE_NONE);
}

View file

@ -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.
*/
#pragma once
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum InputMode {
INPUT_MODE_NONE,
INPUT_MODE_POS,
INPUT_MODE_NEG,
INPUT_MODE_BOTH
};
#define EXPODATA_NAME_LEN 10
class ExpoData {
Q_DECLARE_TR_FUNCTIONS(ExpoData)
public:
ExpoData() { clear(); }
RawSource srcRaw;
unsigned int scale;
unsigned int mode; // InputMode
unsigned int chn;
RawSwitch swtch;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int weight;
int offset;
CurveReference curve;
int carryTrim;
char name[EXPODATA_NAME_LEN + 1];
void convert(RadioDataConversionState & cstate);
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
bool isEmpty() const;
};

View file

@ -1,199 +0,0 @@
/*
* 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.
*/
#ifndef IO_DATA_H
#define IO_DATA_H
#include "constants.h"
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum InputMode {
INPUT_MODE_NONE,
INPUT_MODE_POS,
INPUT_MODE_NEG,
INPUT_MODE_BOTH
};
#define EXPODATA_NAME_LEN 10
class ExpoData {
Q_DECLARE_TR_FUNCTIONS(ExpoData)
public:
ExpoData() { clear(); }
RawSource srcRaw;
unsigned int scale;
unsigned int mode; // InputMode
unsigned int chn;
RawSwitch swtch;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int weight;
int offset;
CurveReference curve;
int carryTrim;
char name[EXPODATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
void convert(RadioDataConversionState & cstate);
bool isEmpty() const;
};
enum MltpxValue {
MLTPX_ADD=0,
MLTPX_MUL=1,
MLTPX_REP=2
};
#define MIXDATA_NAME_LEN 10
class MixData {
Q_DECLARE_TR_FUNCTIONS(MixData)
public:
MixData() { clear(); }
void convert(RadioDataConversionState & cstate);
unsigned int destCh; // 1..CPN_MAX_CHNOUT
RawSource srcRaw;
int weight;
RawSwitch swtch;
CurveReference curve; //0=symmetrisch
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedUp; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
unsigned int speedDown; // 0 nichts
int carryTrim;
bool noExpo;
MltpxValue mltpx; // multiplex method 0=+ 1=* 2=replace
unsigned int mixWarn; // mixer warning
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int sOffset;
char name[MIXDATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
bool isEmpty() const;
};
#define LIMITDATA_NAME_LEN 6
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
public:
LimitData() { clear(); }
int min;
int max;
bool revert;
int offset;
int ppmCenter;
bool symetrical;
int failsafe;
char name[LIMITDATA_NAME_LEN + 1];
CurveReference curve;
QString minToString() const;
QString maxToString() const;
QString offsetToString() const;
QString revertToString() const;
QString nameToString(int index) const;
void clear();
bool isEmpty() const;
};
class CurvePoint {
public:
int8_t x;
int8_t y;
};
#define CURVEDATA_NAME_LEN 6
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
public:
enum CurveType {
CURVE_TYPE_STANDARD,
CURVE_TYPE_CUSTOM,
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
CurveData();
void clear(int count = 5);
bool isEmpty() const;
QString nameToString(const int idx) const;
CurveType type;
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
char name[CURVEDATA_NAME_LEN+1];
};
#define FLIGHTMODE_NAME_LEN 10
#define RENC_MAX_VALUE 1024
#define RENC_MIN_VALUE -RENC_MAX_VALUE
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
public:
FlightModeData() { clear(0); }
int trimMode[CPN_MAX_TRIMS];
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
char name[FLIGHTMODE_NAME_LEN+1];
unsigned int fadeIn;
unsigned int fadeOut;
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void clear(const int phaseIdx);
QString nameToString(int phaseIdx) const;
void convert(RadioDataConversionState & cstate);
bool isEmpty(int phaseIdx) const;
bool isGVarEmpty(int phaseIdx, int gvIdx) const;
bool isREncEmpty(int phaseIdx, int reIdx) const;
int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
int linkedGVarFlightModeZero(int phaseIdx) const;
int linkedREncFlightModeZero(int phaseIdx) const;
};
class SwashRingData {
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
public:
SwashRingData() { clear(); }
int elevatorWeight;
int aileronWeight;
int collectiveWeight;
unsigned int type;
RawSource collectiveSource;
RawSource aileronSource;
RawSource elevatorSource;
unsigned int value;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
};
#endif // IO_DATA_H

View file

@ -0,0 +1,35 @@
/*
* 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 "mixdata.h"
#include "radiodataconversionstate.h"
void MixData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("MIX"), 4);
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool MixData::isEmpty() const
{
return (destCh == 0);
}

View file

@ -0,0 +1,65 @@
/*
* 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 "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum MltpxValue {
MLTPX_ADD,
MLTPX_MUL,
MLTPX_REP
};
#define MIXDATA_NAME_LEN 10
class MixData {
Q_DECLARE_TR_FUNCTIONS(MixData)
public:
MixData() { clear(); }
unsigned int destCh; // 1..CPN_MAX_CHNOUT
RawSource srcRaw;
int weight;
RawSwitch swtch;
CurveReference curve;
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedUp;
unsigned int speedDown;
int carryTrim;
bool noExpo;
MltpxValue mltpx;
unsigned int mixWarn;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int sOffset;
char name[MIXDATA_NAME_LEN + 1];
void convert(RadioDataConversionState & cstate);
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
bool isEmpty() const;
};

View file

@ -27,31 +27,6 @@
#include "helpers.h" #include "helpers.h"
#include "adjustmentreference.h" #include "adjustmentreference.h"
/*
* TimerData
*/
void TimerData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("TMR"), 1);
cstate.setSubComp(tr("Timer %1").arg(cstate.subCompIdx + 1));
mode.convert(cstate);
}
bool TimerData::isEmpty()
{
return (mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0) && name[0] == '\0' && minuteBeep == 0 && countdownBeep == COUNTDOWN_SILENT && val == 0 && persistent == 0 /*&& pvalue == 0*/);
}
QString TimerData::nameToString(int index) const
{
return RadioData::getElementName(tr("TMR", "as in Timer"), index + 1, name);
}
/*
* ModelData
*/
ModelData::ModelData() ModelData::ModelData()
{ {
clear(); clear();
@ -678,41 +653,56 @@ int ModelData::updateReference()
LogicalSwitchData *lsd = &logicalSw[i]; LogicalSwitchData *lsd = &logicalSw[i];
if (!lsd->isEmpty()) { if (!lsd->isEmpty()) {
bool clearlsd = false; bool clearlsd = false;
int oldval1;
int oldval2;
CSFunctionFamily family = lsd->getFunctionFamily(); CSFunctionFamily family = lsd->getFunctionFamily();
switch(family) { switch(family) {
case LS_FAMILY_VOFS: case LS_FAMILY_VOFS:
updateSourceIntRef(lsd->val1); if (lsd->val1 != 0) {
if (lsd->val1 == 0) updateSourceIntRef(lsd->val1);
clearlsd = true; if (lsd->val1 == 0)
clearlsd = true;
}
break; break;
case LS_FAMILY_STICKY: case LS_FAMILY_STICKY:
case LS_FAMILY_VBOOL: case LS_FAMILY_VBOOL:
updateSwitchIntRef(lsd->val1); oldval1 = lsd->val1;
updateSwitchIntRef(lsd->val2); oldval2 = lsd->val2;
if (lsd->val1 == 0 && lsd->val2 == 0) if (lsd->val1 != 0)
updateSwitchIntRef(lsd->val1);
if (lsd->val2 != 0)
updateSwitchIntRef(lsd->val2);
if (lsd->val1 == 0 && lsd->val2 == 0 && ((lsd->val1 != oldval1 && oldval2 == 0) || (lsd->val2 != oldval2 && oldval1 == 0)))
clearlsd = true; clearlsd = true;
break; break;
case LS_FAMILY_EDGE: case LS_FAMILY_EDGE:
updateSwitchIntRef(lsd->val1); if (lsd->val1 != 0) {
if (lsd->val1 == 0) updateSwitchIntRef(lsd->val1);
clearlsd = true; if (lsd->val1 == 0)
clearlsd = true;
}
break; break;
case LS_FAMILY_VCOMP: case LS_FAMILY_VCOMP:
updateSourceIntRef(lsd->val1); oldval1 = lsd->val1;
updateSourceIntRef(lsd->val2); oldval2 = lsd->val2;
if (lsd->val1 == 0 && lsd->val2 == 0) if (lsd->val1 != 0)
updateSourceIntRef(lsd->val1);
if (lsd->val2 != 0)
updateSourceIntRef(lsd->val2);
if (lsd->val1 == 0 && lsd->val2 == 0 && ((lsd->val1 != oldval1 && oldval2 == 0) || (lsd->val2 != oldval2 && oldval1 == 0)))
clearlsd = true; clearlsd = true;
break; break;
default: default:
break; break;
} }
if (clearlsd) {
if (lsd->andsw != 0)
updateSwitchIntRef(lsd->andsw);
if (clearlsd && lsd->andsw == 0) {
lsd->clear(); lsd->clear();
appendUpdateReferenceParams(REF_UPD_TYPE_LOGICAL_SWITCH, REF_UPD_ACT_CLEAR, i); appendUpdateReferenceParams(REF_UPD_TYPE_LOGICAL_SWITCH, REF_UPD_ACT_CLEAR, i);
} }
else {
updateSwitchIntRef(lsd->andsw);
}
} }
} }
//s1.report("Logical Switches"); //s1.report("Logical Switches");
@ -841,6 +831,7 @@ void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, c
newRef.index = abs(curRef.index); newRef.index = abs(curRef.index);
div_t idx = div(newRef.index, updRefInfo.occurences); div_t idx = div(newRef.index, updRefInfo.occurences);
div_t newidx;
switch (updRefInfo.action) switch (updRefInfo.action)
{ {
@ -858,9 +849,10 @@ void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, c
if (idx.quot < (updRefInfo.index1 + idxAdj)) if (idx.quot < (updRefInfo.index1 + idxAdj))
return; return;
newRef.index += updRefInfo.shift; newRef.index = ((idx.quot + updRefInfo.shift) * updRefInfo.occurences) + idx.rem;
newidx = div(newRef.index, updRefInfo.occurences);
if (idx.quot < (updRefInfo.index1 + idxAdj) || idx.quot > (updRefInfo.maxindex + idxAdj)) { if (newidx.quot < (updRefInfo.index1 + idxAdj) || newidx.quot > (updRefInfo.maxindex + idxAdj)) {
if (defClear) if (defClear)
newRef.clear(); newRef.clear();
else { else {
@ -1106,7 +1098,7 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
switch (updRefInfo.action) switch (updRefInfo.action)
{ {
case REF_UPD_ACT_CLEAR: case REF_UPD_ACT_CLEAR:
flag[updRefInfo.index1] = false; flag[updRefInfo.index1] = true;
break; break;
case REF_UPD_ACT_SHIFT: case REF_UPD_ACT_SHIFT:
if(updRefInfo.shift < 0) { if(updRefInfo.shift < 0) {
@ -1114,7 +1106,7 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
if (i - updRefInfo.shift <= updRefInfo.maxindex) if (i - updRefInfo.shift <= updRefInfo.maxindex)
flag[i] = flag[i - updRefInfo.shift]; flag[i] = flag[i - updRefInfo.shift];
else else
flag[i] = false; flag[i] = true;
} }
} }
else { else {
@ -1122,7 +1114,7 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
if (i - updRefInfo.shift >= updRefInfo.index1) if (i - updRefInfo.shift >= updRefInfo.index1)
flag[i] = flag[i - updRefInfo.shift]; flag[i] = flag[i - updRefInfo.shift];
else else
flag[i] = false; flag[i] = true;
} }
} }
break; break;
@ -1381,7 +1373,6 @@ void ModelData::sortMixes()
void ModelData::updateResetParam(CustomFunctionData * cfd) void ModelData::updateResetParam(CustomFunctionData * cfd)
{ {
if (cfd->func != FuncReset) if (cfd->func != FuncReset)
return; return;
@ -1392,6 +1383,11 @@ void ModelData::updateResetParam(CustomFunctionData * cfd)
switch (updRefInfo.type) switch (updRefInfo.type)
{ {
case REF_UPD_TYPE_TIMER:
if (cfd->param < 0 || cfd->param > 2)
return;
idxAdj = -2; // reverse earlier offset required for rawsource
break;
case REF_UPD_TYPE_SENSOR: case REF_UPD_TYPE_SENSOR:
idxAdj = 5/*3 Timers + Flight + Telemetery*/ + firmware->getCapability(RotaryEncoders); idxAdj = 5/*3 Timers + Flight + Telemetery*/ + firmware->getCapability(RotaryEncoders);
if (cfd->param < idxAdj || cfd->param > (idxAdj + firmware->getCapability(Sensors))) if (cfd->param < idxAdj || cfd->param > (idxAdj + firmware->getCapability(Sensors)))
@ -1439,3 +1435,118 @@ void ModelData::updateResetParam(CustomFunctionData * cfd)
updRefInfo.updcnt++; updRefInfo.updcnt++;
} }
} }
QString ModelData::thrTraceSrcToString() const
{
return thrTraceSrcToString((int)thrTraceSrc);
}
QString ModelData::thrTraceSrcToString(const int index) const
{
Firmware * firmware = getCurrentFirmware();
const Boards board = Boards(getCurrentBoard());
const int pscnt = board.getCapability(Board::Pots) + board.getCapability(Board::Sliders);
if (index == 0)
return tr("THR");
else if (index <= pscnt)
return board.getAnalogInputName(index + board.getCapability(Board::Sticks) - 1);
else if (index <= pscnt + firmware->getCapability(Outputs))
return RawSource(SOURCE_TYPE_CH, index - pscnt - 1).toString(this);
return QString(CPN_STR_UNKNOWN_ITEM);
}
int ModelData::thrTraceSrcCount() const
{
const Boards board = Boards(getCurrentBoard());
Firmware * firmware = getCurrentFirmware();
return 1 + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + firmware->getCapability(Outputs);
}
bool ModelData::isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const
{
const Boards board = Boards(getCurrentBoard());
if (index > 0 && index <= board.getCapability(Board::Pots) + board.getCapability(Board::Sliders))
return RawSource(SOURCE_TYPE_STICK, index + board.getCapability(Board::Sticks) - 1).isAvailable(this, generalSettings, board.getBoardType());
else
return true;
}
void ModelData::limitsClear(const int index)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
if (!limitData[index].isEmpty()) {
limitData[index].clear();
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_CLEAR, index);
}
}
void ModelData::limitsClearAll()
{
for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
limitsClear(i);
}
}
void ModelData::limitsDelete(const int index)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
memmove(&limitData[index], &limitData[index + 1], (CPN_MAX_CHNOUT - (index + 1)) * sizeof(LimitData));
limitData[CPN_MAX_CHNOUT - 1].clear();
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_SHIFT, index, 0, -1);
}
void ModelData::limitsGet(const int index, QByteArray & data)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
data.append((char*)&limitData[index], sizeof(LimitData));
}
void ModelData::limitsInsert(const int index)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
memmove(&limitData[index + 1], &limitData[index], (CPN_MAX_CHNOUT - (index + 1)) * sizeof(LimitData));
limitData[index].clear();
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_SHIFT, index, 0, 1);
}
void ModelData::limitsMove(const int index, const int offset)
{
if (index + offset < 0 || index + offset >= CPN_MAX_CHNOUT)
return;
int idx1 = index;
int idx2;
const int direction = offset < 0 ? -1 : 1;
const int cnt = abs(offset);
for (int i = 1; i <= cnt; i++) {
idx2 = idx1 + direction;
LimitData tmp = limitData[idx2];
LimitData *d1 = &limitData[idx1];
LimitData *d2 = &limitData[idx2];
memcpy(d2, d1, sizeof(LimitData));
memcpy(d1, &tmp, sizeof(LimitData));
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_SWAP, idx1, idx2);
idx1 += direction;
}
}
void ModelData::limitsSet(const int index, const QByteArray & data)
{
if (index < 0 || index >= CPN_MAX_CHNOUT || data.size() < (int)sizeof(LimitData))
return;
memcpy(&limitData[index], data.constData(), sizeof(LimitData));
}

View file

@ -18,17 +18,22 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef MODELDATA_H #pragma once
#define MODELDATA_H
#include "constants.h" #include "constants.h"
#include "curvedata.h"
#include "customfunctiondata.h" #include "customfunctiondata.h"
#include "gvardata.h" #include "gvardata.h"
#include "io_data.h" #include "flightmodedata.h"
#include "heli_data.h"
#include "input_data.h"
#include "logicalswitchdata.h" #include "logicalswitchdata.h"
#include "mixdata.h"
#include "moduledata.h" #include "moduledata.h"
#include "output_data.h"
#include "sensordata.h" #include "sensordata.h"
#include "telem_data.h" #include "telem_data.h"
#include "timerdata.h"
#include <QtCore> #include <QtCore>
@ -51,33 +56,6 @@ class RSSIAlarmData {
} }
}; };
#define TIMER_NAME_LEN 8
class TimerData {
Q_DECLARE_TR_FUNCTIONS(TimerData)
public:
enum CountDownMode {
COUNTDOWN_SILENT,
COUNTDOWN_BEEPS,
COUNTDOWN_VOICE,
COUNTDOWN_HAPTIC
};
TimerData() { clear(); }
RawSwitch mode;
char name[TIMER_NAME_LEN+1];
bool minuteBeep;
unsigned int countdownBeep;
unsigned int val;
unsigned int persistent;
int pvalue;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData)); mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
void convert(RadioDataConversionState & cstate);
bool isEmpty();
bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
QString nameToString(int index) const;
};
#define CPN_MAX_SCRIPTS 9 #define CPN_MAX_SCRIPTS 9
#define CPN_MAX_SCRIPT_INPUTS 10 #define CPN_MAX_SCRIPT_INPUTS 10
class ScriptData { class ScriptData {
@ -283,6 +261,18 @@ class ModelData {
bool hasExpoChildren(const int index); bool hasExpoChildren(const int index);
bool hasExpoSiblings(const int index); bool hasExpoSiblings(const int index);
void removeMix(const int idx); void removeMix(const int idx);
QString thrTraceSrcToString() const;
QString thrTraceSrcToString(const int index) const;
int thrTraceSrcCount() const;
bool isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const;
void limitsClear(const int index);
void limitsClearAll();
void limitsDelete(const int index);
void limitsGet(const int index, QByteArray & data);
void limitsInsert(const int index);
void limitsMove(const int index, const int offset);
void limitsSet(const int index, const QByteArray & data);
protected: protected:
void removeGlobalVar(int & var); void removeGlobalVar(int & var);
@ -340,5 +330,3 @@ class ModelData {
void sortMixes(); void sortMixes();
void updateResetParam(CustomFunctionData * cfd); void updateResetParam(CustomFunctionData * cfd);
}; };
#endif // MODELDATA_H

View file

@ -76,6 +76,8 @@ inline int MAX_POTS(Board::Type board, int version)
{ {
if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board)) if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 3; return 3;
if (IS_FAMILY_T12(board))
return 2;
return Boards::getCapability(board, Board::Pots); return Boards::getCapability(board, Board::Pots);
} }
@ -85,6 +87,8 @@ inline int MAX_POTS_STORAGE(Board::Type board, int version)
return 3; return 3;
if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board)) if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board))
return 5; return 5;
if (IS_FAMILY_T12(board))
return 2;
return Boards::getCapability(board, Board::Pots); return Boards::getCapability(board, Board::Pots);
} }
@ -92,6 +96,8 @@ inline int MAX_POTS_SOURCES(Board::Type board, int version)
{ {
if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board)) if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 5; return 5;
if (IS_FAMILY_T12(board))
return 2;
return Boards::getCapability(board, Board::Pots); return Boards::getCapability(board, Board::Pots);
} }
@ -2305,7 +2311,8 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<2>(this, modelData.timers[i].countdownBeep)); internalField.Append(new UnsignedField<2>(this, modelData.timers[i].countdownBeep));
internalField.Append(new BoolField<1>(this, modelData.timers[i].minuteBeep)); internalField.Append(new BoolField<1>(this, modelData.timers[i].minuteBeep));
internalField.Append(new UnsignedField<2>(this, modelData.timers[i].persistent)); internalField.Append(new UnsignedField<2>(this, modelData.timers[i].persistent));
internalField.Append(new SpareBitsField<3>(this)); internalField.Append(new SignedField<2>(this, modelData.timers[i].countdownStart));
internalField.Append(new UnsignedField<1>(this, modelData.timers[i].direction));
if (HAS_LARGE_LCD(board)) if (HAS_LARGE_LCD(board))
internalField.Append(new ZCharField<8>(this, modelData.timers[i].name, "Timer name")); internalField.Append(new ZCharField<8>(this, modelData.timers[i].name, "Timer name"));
else else

View file

@ -37,6 +37,8 @@
#define TARANIS_X9LITES_VARIANT 0x0801 #define TARANIS_X9LITES_VARIANT 0x0801
#define JUMPER_T12_VARIANT 0x4001 #define JUMPER_T12_VARIANT 0x4001
#define RADIOMASTER_TX12_VARIANT 0x4002 #define RADIOMASTER_TX12_VARIANT 0x4002
#define JUMPER_TLITE_VARIANT 0x4003
#define RADIOMASTER_T8_VARIANT 0x4004
class OpenTxGeneralData: public TransformedField { class OpenTxGeneralData: public TransformedField {
public: public:

View file

@ -60,6 +60,8 @@ const char * OpenTxEepromInterface::getName()
switch (board) { switch (board) {
case BOARD_JUMPER_T12: case BOARD_JUMPER_T12:
return "OpenTX for Jumper T12"; return "OpenTX for Jumper T12";
case BOARD_JUMPER_TLITE:
return "OpenTX for Jumper T-Lite";
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
return "OpenTX for Jumper T16"; return "OpenTX for Jumper T16";
case BOARD_JUMPER_T18: case BOARD_JUMPER_T18:
@ -68,6 +70,8 @@ const char * OpenTxEepromInterface::getName()
return "OpenTX for Radiomaster TX16S"; return "OpenTX for Radiomaster TX16S";
case BOARD_RADIOMASTER_TX12: case BOARD_RADIOMASTER_TX12:
return "OpenTX for Radiomaster TX12"; return "OpenTX for Radiomaster TX12";
case BOARD_RADIOMASTER_T8:
return "OpenTX for Radiomaster T8";
case BOARD_TARANIS_X9D: case BOARD_TARANIS_X9D:
return "OpenTX for FrSky Taranis X9D"; return "OpenTX for FrSky Taranis X9D";
case BOARD_TARANIS_X9DP: case BOARD_TARANIS_X9DP:
@ -336,9 +340,15 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
else if (IS_JUMPER_T12(board)) { else if (IS_JUMPER_T12(board)) {
variant |= JUMPER_T12_VARIANT; variant |= JUMPER_T12_VARIANT;
} }
else if (IS_JUMPER_TLITE(board)) {
variant |= JUMPER_TLITE_VARIANT;
}
else if (IS_RADIOMASTER_TX12(board)) { else if (IS_RADIOMASTER_TX12(board)) {
variant |= RADIOMASTER_TX12_VARIANT; variant |= RADIOMASTER_TX12_VARIANT;
} }
else if (IS_RADIOMASTER_T8(board)) {
variant |= RADIOMASTER_T8_VARIANT;
}
OpenTxGeneralData generator((GeneralSettings &)radioData.generalSettings, board, version, variant); OpenTxGeneralData generator((GeneralSettings &)radioData.generalSettings, board, version, variant);
// generator.dump(); // generator.dump();
QByteArray data; QByteArray data;
@ -683,8 +693,12 @@ int OpenTxFirmware::getCapability(::Capability capability)
return TARANIS_XLITE_VARIANT; return TARANIS_XLITE_VARIANT;
else if (IS_JUMPER_T12(board)) else if (IS_JUMPER_T12(board))
return JUMPER_T12_VARIANT; return JUMPER_T12_VARIANT;
else if (IS_JUMPER_TLITE(board))
return JUMPER_TLITE_VARIANT;
else if (IS_RADIOMASTER_TX12(board)) else if (IS_RADIOMASTER_TX12(board))
return RADIOMASTER_TX12_VARIANT; return RADIOMASTER_TX12_VARIANT;
else if (IS_RADIOMASTER_T8(board))
return RADIOMASTER_T8_VARIANT;
else else
return 0; return 0;
case MavlinkTelemetry: case MavlinkTelemetry:
@ -746,7 +760,7 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
case PULSES_ACCST_ISRM_D16: case PULSES_ACCST_ISRM_D16:
return IS_ACCESS_RADIO(board, id); return IS_ACCESS_RADIO(board, id);
case PULSES_MULTIMODULE: case PULSES_MULTIMODULE:
return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board); return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board) || IS_RADIOMASTER_TX12(board) || IS_JUMPER_TLITE(board);
default: default:
return false; return false;
} }
@ -778,7 +792,7 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
case PULSES_XJT_LITE_X16: case PULSES_XJT_LITE_X16:
case PULSES_XJT_LITE_D8: case PULSES_XJT_LITE_D8:
case PULSES_XJT_LITE_LR12: case PULSES_XJT_LITE_LR12:
return (IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board)); return (IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_JUMPER_TLITE(board));
default: default:
return false; return false;
} }
@ -949,11 +963,21 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari
variantError = true; variantError = true;
} }
} }
else if (IS_JUMPER_TLITE(board)) {
if (variant != JUMPER_TLITE_VARIANT) {
variantError = true;
}
}
else if (IS_RADIOMASTER_TX12(board)) { else if (IS_RADIOMASTER_TX12(board)) {
if (variant != RADIOMASTER_TX12_VARIANT) { if (variant != RADIOMASTER_TX12_VARIANT) {
variantError = true; variantError = true;
} }
} }
else if (IS_RADIOMASTER_T8(board)) {
if (variant != RADIOMASTER_T8_VARIANT) {
variantError = true;
}
}
else if (IS_TARANIS(board)) { else if (IS_TARANIS(board)) {
if (variant != 0) { if (variant != 0) {
variantError = true; variantError = true;
@ -1275,6 +1299,16 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX); addOpenTxRfOptions(firmware, FLEX);
/* Jumper T-Lite board */
firmware = new OpenTxFirmware("opentx-tlite", QCoreApplication::translate("Firmware", "Jumper T-Lite"), BOARD_JUMPER_TLITE);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T16 board */ /* Jumper T16 board */
firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16); firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
addOpenTxFrskyOptions(firmware); addOpenTxFrskyOptions(firmware);
@ -1294,6 +1328,17 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX); addOpenTxRfOptions(firmware, FLEX);
/* Radiomaster T8 board */
firmware = new OpenTxFirmware("opentx-t8", QCoreApplication::translate("Firmware", "Radiomaster T8"), BOARD_RADIOMASTER_T8);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, NONE);
firmware->addOption("bindkey", Firmware::tr("Allow bind using bind key"));
/* Radiomaster TX16S board */ /* Radiomaster TX16S board */
firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S); firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S);
addOpenTxFrskyOptions(firmware); addOpenTxFrskyOptions(firmware);

View file

@ -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 "output_data.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
void LimitData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
min = -1000;
max = +1000;
}
bool LimitData::isEmpty() const
{
LimitData tmp;
return !memcmp(this, &tmp, sizeof(LimitData));
}
QString LimitData::minToString() const
{
return QString::number((qreal)min / 10);
}
QString LimitData::maxToString() const
{
return QString::number((qreal)max / 10);
}
QString LimitData::revertToString() const
{
return revert ? tr("INV") : tr("NOR");
}
QString LimitData::nameToString(int index) const
{
return RadioData::getElementName(tr("CH"), index + 1, name);
}
QString LimitData::offsetToString() const
{
return QString::number((qreal)offset / 10, 'f', 1);
}

View file

@ -0,0 +1,52 @@
/*
* 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 "curvereference.h"
#include <QtCore>
#define LIMITDATA_NAME_LEN 6
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
public:
LimitData() { clear(); }
int min;
int max;
bool revert;
int offset;
int ppmCenter;
bool symetrical;
int failsafe;
char name[LIMITDATA_NAME_LEN + 1];
CurveReference curve;
void clear();
bool isEmpty() const;
QString minToString() const;
QString maxToString() const;
QString offsetToString() const;
QString revertToString() const;
QString nameToString(int index) const;
};

View file

@ -22,23 +22,6 @@
#include "radiodataconversionstate.h" #include "radiodataconversionstate.h"
#include "eeprominterface.h" #include "eeprominterface.h"
// static
QString RadioData::getElementName(const QString & prefix, unsigned int index, const char * name, bool padding)
{
QString result = prefix;
if (padding)
result += QString("%1").arg(index, 2, 10, QChar('0'));
else
result += QString("%1").arg(index);
if (name) {
QString trimmed = QString(name).trimmed();
if (trimmed.length() > 0) {
result += ":" + QString(name).trimmed();
}
}
return result;
}
RadioData::RadioData() RadioData::RadioData()
{ {
models.resize(getCurrentFirmware()->getCapability(Models)); models.resize(getCurrentFirmware()->getCapability(Models));

View file

@ -1,9 +1,10 @@
#ifndef _RADIODATA_H_ #pragma once
#define _RADIODATA_H_
#include "generalsettings.h" #include "generalsettings.h"
#include "modeldata.h" #include "modeldata.h"
#include "datahelpers.h" // required for getElementName
#include <QtCore> #include <QtCore>
class RadioDataConversionState; class RadioDataConversionState;
@ -32,10 +33,10 @@ class RadioData {
void fixModelFilenames(); void fixModelFilenames();
QString getNextModelFilename(); QString getNextModelFilename();
static QString getElementName(const QString & prefix, unsigned int index, const char * name = 0, bool padding = false); // leave here until all calls repointed
static QString getElementName(const QString & prefix, unsigned int index, const char * name = 0, bool padding = false)
{ return DataHelpers::getElementName(prefix, index, name, padding); }
protected: protected:
void fixModelFilename(unsigned int index); void fixModelFilename(unsigned int index);
}; };
#endif // _RADIODATA_H_

View file

@ -60,7 +60,7 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
result.min = -30000 * result.step; result.min = -30000 * result.step;
result.max = +30000 * result.step; result.max = +30000 * result.step;
result.decimals = sensor.prec; result.decimals = sensor.prec;
result.unit = sensor.unitString(); result.unit = SensorData::unitToString(qr.quot);
break; break;
} }
@ -143,14 +143,14 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
static const QString rotary[] = { tr("REa"), tr("REb") }; static const QString rotary[] = { tr("REa"), tr("REb") };
if (index<0) { if (index<0) {
return tr("???"); return QString(CPN_STR_UNKNOWN_ITEM);
} }
QString result; QString result;
int genAryIdx = 0; int genAryIdx = 0;
switch (type) { switch (type) {
case SOURCE_TYPE_NONE: case SOURCE_TYPE_NONE:
return tr("----"); return QString(CPN_STR_NONE_ITEM);
case SOURCE_TYPE_VIRTUAL_INPUT: case SOURCE_TYPE_VIRTUAL_INPUT:
{ {
@ -161,7 +161,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
} }
case SOURCE_TYPE_LUA_OUTPUT: case SOURCE_TYPE_LUA_OUTPUT:
return tr("LUA%1%2").arg(index/16+1).arg(QChar('a'+index%16)); return tr("LUA%1%2").arg(index / 16 + 1).arg(QChar('a' + index % 16));
case SOURCE_TYPE_STICK: case SOURCE_TYPE_STICK:
if (generalSettings) { if (generalSettings) {
@ -193,10 +193,10 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return result; return result;
case SOURCE_TYPE_CUSTOM_SWITCH: case SOURCE_TYPE_CUSTOM_SWITCH:
return RawSwitch(SWITCH_TYPE_VIRTUAL, index+1).toString(); return RawSwitch(SWITCH_TYPE_VIRTUAL, index + 1).toString();
case SOURCE_TYPE_CYC: case SOURCE_TYPE_CYC:
return tr("CYC%1").arg(index+1); return tr("CYC%1").arg(index + 1);
case SOURCE_TYPE_PPM: case SOURCE_TYPE_PPM:
return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1); return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1);
@ -208,18 +208,15 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return LimitData().nameToString(index); return LimitData().nameToString(index);
case SOURCE_TYPE_SPECIAL: case SOURCE_TYPE_SPECIAL:
result = CHECK_IN_ARRAY(special, index); if (index >= SOURCE_TYPE_SPECIAL_TIMER1_IDX && index <= SOURCE_TYPE_SPECIAL_TIMER1_IDX + CPN_MAX_TIMERS - 1) {
// TODO refactor timers into own source type if (model)
if (result.startsWith("Timer")) { result = model->timers[index - SOURCE_TYPE_SPECIAL_TIMER1_IDX].nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX);
bool ok; else
int n = result.right(1).toInt(&ok); result = TimerData().nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX);
if (ok) {
if (model)
result = model->timers[n - 1].nameToString(n - 1);
else
result = TimerData().nameToString(n - 1);
}
} }
else
result = CHECK_IN_ARRAY(special, index);
return result; return result;
case SOURCE_TYPE_TELEMETRY: case SOURCE_TYPE_TELEMETRY:
@ -241,7 +238,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return GVarData().nameToString(index); return GVarData().nameToString(index);
default: default:
return tr("???"); return QString(CPN_STR_UNKNOWN_ITEM);
} }
} }
@ -409,4 +406,3 @@ QStringList RawSource::getSwitchList(Boards board) const
} }
return ret; return ret;
} }

View file

@ -178,6 +178,9 @@ enum RawSourceType {
MAX_SOURCE_TYPE MAX_SOURCE_TYPE
}; };
constexpr int SOURCE_TYPE_STICK_THR_IDX { 3 }; // TODO is there a function to determine index?
constexpr int SOURCE_TYPE_SPECIAL_TIMER1_IDX { 2 }; // TODO temp const until Timers own source type
class RawSourceRange class RawSourceRange
{ {
Q_DECLARE_TR_FUNCTIONS(RawSourceRange) Q_DECLARE_TR_FUNCTIONS(RawSourceRange)

View file

@ -19,9 +19,9 @@
*/ */
#include "sensordata.h" #include "sensordata.h"
#include "radiodata.h"
#include "modeldata.h" #include "modeldata.h"
#include "eeprominterface.h"
#include "compounditemmodels.h"
void SensorData::updateUnit() void SensorData::updateUnit()
{ {
@ -31,9 +31,322 @@ void SensorData::updateUnit()
} }
} }
QString SensorData::unitString() const QString SensorData::nameToString(int index) const
{ {
switch (unit) { return DataHelpers::getElementName(tr("TELE"), index + 1, label);
}
QString SensorData::getOrigin(const ModelData * model) const
{
if (type != TELEM_TYPE_CUSTOM || !id)
return QString();
const ModuleData & module = model->moduleData[moduleIdx];
if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) {
return QString(module.access.receiverName[rxIdx]);
}
else {
return QString();
}
}
bool SensorData::isEmpty() const
{
return (!isAvailable() && type == 0 && id == 0 && subid == 0 && instance == 0 && rxIdx == 0 && moduleIdx == 0 && unit == 0 && ratio == 0 && prec == 0 && offset == 0 && autoOffset == 0 && filter == 0 && onlyPositive == 0 && logs == 0);
}
QString SensorData::idToString() const
{
return idToString(id);
}
QString SensorData::typeToString() const
{
return typeToString(type);
}
QString SensorData::formulaToString() const
{
return formulaToString(formula);
}
QString SensorData::cellIndexToString() const
{
return cellIndexToString(index);
}
QString SensorData::unitToString() const
{
return unitToString(unit);
}
QString SensorData::precToString() const
{
return precToString(prec);
}
int SensorData::getMask() const
{
int mask = 0;
if (type == TELEM_TYPE_CALCULATED) {
if (formula < TELEM_FORMULA_CELL)
mask |= SENSOR_ISCONFIGURABLE | SENSOR_HAS_POSITIVE;
if (formula == TELEM_FORMULA_DIST)
mask |= SENSOR_HAS_GPS;
if (formula == TELEM_FORMULA_CELL)
mask |= SENSOR_HAS_CELLS;
if (formula == TELEM_FORMULA_CONSUMPTION)
mask |= SENSOR_HAS_CONSUMPTION;
if (formula <= TELEM_FORMULA_MULTIPLY)
mask |= SENSOR_HAS_SOURCES_12;
if (formula < TELEM_FORMULA_MULTIPLY)
mask |= SENSOR_HAS_SOURCES_34;
if (formula == TELEM_FORMULA_TOTALIZE)
mask |= SENSOR_HAS_TOTALIZE;
}
else {
if (unit < UNIT_FIRST_VIRTUAL)
mask |= (SENSOR_ISCONFIGURABLE | SENSOR_HAS_RATIO | SENSOR_HAS_POSITIVE);
}
if (mask & SENSOR_ISCONFIGURABLE && unit != UNIT_FAHRENHEIT)
mask |= SENSOR_HAS_PRECISION;
return mask;
}
constexpr char FMT_LABEL[] { "<b>%1:</b> " };
constexpr char FMT_VALUE[] { "%1 " };
constexpr char FMT_LABEL_VALUE[] { "<b>%1:</b> %2 " };
QString SensorData::paramsToString(const ModelData * model) const
{
if (!isAvailable())
return "";
QString str;
int mask = getMask();
if (type == TELEM_TYPE_CALCULATED) {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Formula")).arg(formulaToString()));
}
else {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Id")).arg(idToString()));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Instance")).arg(instance));
}
if (mask & SENSOR_HAS_CELLS) {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Sensor")).arg(sourceToString(model, source)));
str.append(QString(FMT_VALUE).arg(cellIndexToString()));
}
if (mask & SENSOR_HAS_SOURCES_12) {
str.append(QString(FMT_LABEL).arg(tr("Sources")));
for (int i = 0; i < 4; i++) {
if (i < 2 || mask & SENSOR_HAS_SOURCES_34) {
str.append(QString(FMT_VALUE).arg(sourceToString(model, sources[i])));
}
}
}
if (mask & SENSOR_HAS_CONSUMPTION || mask & SENSOR_HAS_TOTALIZE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Sensor")).arg(sourceToString(model, amps)));
if (mask & SENSOR_HAS_GPS) {
str.append(QString(FMT_LABEL_VALUE).arg(tr("GPS")).arg(sourceToString(model, gps)));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Alt")).arg(sourceToString(model, alt)));
}
if (mask & SENSOR_ISCONFIGURABLE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Unit")).arg(unitToString()));
if (mask & SENSOR_HAS_PRECISION)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Precision")).arg(precToString()));
if (mask & SENSOR_HAS_RATIO) {
if (unit != UNIT_RPMS) {
int precsn = prec == 0 ? 1 : pow(10, prec);
str.append(QString(FMT_LABEL_VALUE).arg(tr("Ratio")).arg((float)ratio / 10));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Offset")).arg(QString::number((float)offset / precsn, 'f', prec)));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Auto Offset")).arg(DataHelpers::boolToString(autoOffset, DataHelpers::BOOL_FMT_YN)));
}
else {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Blades")).arg(ratio)); // TODO refactor to dedicated RPMS field
str.append(QString(FMT_LABEL_VALUE).arg(tr("Multiplier")).arg(offset)); // TODO refactor to dedicated RPMS field
}
}
if (mask & SENSOR_ISCONFIGURABLE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Filter")).arg(DataHelpers::boolToString(filter, DataHelpers::BOOL_FMT_YN)));
if (type == TELEM_TYPE_CALCULATED)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Persist")).arg(DataHelpers::boolToString(persistent, DataHelpers::BOOL_FMT_YN)));
if (mask & SENSOR_HAS_POSITIVE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Positive")).arg(DataHelpers::boolToString(onlyPositive, DataHelpers::BOOL_FMT_YN)));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Log")).arg(DataHelpers::boolToString(logs, DataHelpers::BOOL_FMT_YN)));
return str;
}
FieldRange SensorData::getRatioRange() const
{
FieldRange result;
if (unit == SensorData::UNIT_RPMS) {
result.decimals = 0;
result.max = 30000;
result.min = 1;
result.step = 1;
}
else {
result.decimals = 1;
result.max = 30000;
result.min = 0;
result.step = 0.1;
}
return result;
}
FieldRange SensorData::getOffsetRange() const
{
FieldRange result;
if (unit == SensorData::UNIT_RPMS) {
result.decimals = 0;
result.max = 30000;
result.min = 1;
result.step = 1;
}
else {
result.decimals = prec;
result.max = 30000.0f / powf(10.0f, prec);
result.min = -result.max;
result.step = pow(0.1, prec);
}
return result;
}
void SensorData::formulaChanged()
{
switch (formula) {
case TELEM_FORMULA_CELL:
prec = 2;
unit = UNIT_VOLTS;
break;
case TELEM_FORMULA_CONSUMPTION:
prec = 0;
unit = UNIT_MAH;
break;
case TELEM_FORMULA_DIST:
prec = 0;
unit = UNIT_METERS;
break;
}
}
void SensorData::unitChanged()
{
if (unit == UNIT_FAHRENHEIT)
prec = 0;
}
// static
QString SensorData::idToString(const int value)
{
return QString::number(value, 16).toUpper();
}
// static
QString SensorData::typeToString(const int value)
{
switch(value) {
case TELEM_TYPE_CUSTOM:
return tr("Custom");
case TELEM_TYPE_CALCULATED:
return tr("Calculated");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString SensorData::formulaToString(const int value)
{
switch(value) {
case TELEM_FORMULA_ADD:
return tr("Add");
case TELEM_FORMULA_AVERAGE:
return tr("Average");
case TELEM_FORMULA_MIN:
return tr("Minimum");
case TELEM_FORMULA_MAX:
return tr("Maximum");
case TELEM_FORMULA_MULTIPLY:
return tr("Multiply");
case TELEM_FORMULA_TOTALIZE:
return tr("Totalize");
case TELEM_FORMULA_CELL:
return tr("Cell");
case TELEM_FORMULA_CONSUMPTION:
return tr("Consumption");
case TELEM_FORMULA_DIST:
return tr("Distance");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString SensorData::cellIndexToString(const int value)
{
if (value == TELEM_CELL_INDEX_LOWEST)
return tr("Lowest");
if (value > TELEM_CELL_INDEX_LOWEST && value < TELEM_CELL_INDEX_HIGHEST)
return tr("Cell %1").arg(value - TELEM_CELL_INDEX_LOWEST);
if (value== TELEM_CELL_INDEX_HIGHEST)
return tr("Highest");
if (value == TELEM_CELL_INDEX_DELTA)
return tr("Delta");
return CPN_STR_UNKNOWN_ITEM;
}
// static
QString SensorData::precToString(const int value)
{
return QString("0.%1").arg(QString(value, '0'));
}
// static
QString SensorData::sourceToString(const ModelData * model, const int index, const bool sign)
{
if (model) {
const QString prfx = sign ? index < 0 ? "-" : "+" : "";
if (abs(index) > 0) {
const SensorData &sd = model->sensorData[abs(index) - 1];
if (sd.type == SensorData::TELEM_TYPE_CUSTOM)
return QString("%1%2 (%3)").arg(prfx).arg(sd.label).arg(sd.getOrigin(model));
else
return QString("%1%2").arg(prfx).arg(sd.label);
}
else
return CPN_STR_NONE_ITEM;
}
return "";
}
// static
QString SensorData::unitToString(const int value)
{
switch (value) {
case UNIT_RAW:
return tr("Raw (-)");
case UNIT_VOLTS: case UNIT_VOLTS:
return tr("V"); return tr("V");
case UNIT_AMPS: case UNIT_AMPS:
@ -91,30 +404,111 @@ QString SensorData::unitString() const
case UNIT_US: case UNIT_US:
return tr("uS"); return tr("uS");
default: default:
return ""; return CPN_STR_UNKNOWN_ITEM;
} }
} }
QString SensorData::nameToString(int index) const // static
bool SensorData::isSourceAvailable(const ModelData * model, const int index)
{ {
return RadioData::getElementName(tr("TELE"), index + 1, label); Firmware * firmware = getCurrentFirmware();
const int sensorcnt = firmware->getCapability(Sensors);
const int i = abs(index);
if (model && sensorcnt > 0 && i <= sensorcnt) {
if (i > 0)
return model->sensorData[i - 1].isAvailable();
else
return true;
}
return false;
} }
QString SensorData::getOrigin(const ModelData * model) const #define RSSI_ID 0xF101
{
if (type != TELEM_TYPE_CUSTOM || !id)
return QString();
const ModuleData & module = model->moduleData[moduleIdx]; // static
if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) { bool SensorData::isRssiSensorAvailable(const ModelData * model, const int value)
return QString(module.access.receiverName[rxIdx]); {
} if (value == 0)
return true;
else { else {
return QString(); const SensorData &sensor = model->sensorData[abs(value) - 1];
return (sensor.isAvailable() && sensor.id == RSSI_ID);
} }
} }
bool SensorData::isEmpty() const // static
QString SensorData::rssiSensorToString(const ModelData * model, const int value)
{ {
return (!isAvailable() && type == 0 && id == 0 && subid == 0 && instance == 0 && rxIdx == 0 && moduleIdx == 0 && unit == 0 && ratio == 0 && prec == 0 && offset == 0 && autoOffset == 0 && filter == 0 && onlyPositive == 0 && logs == 0); if (value == 0)
return tr("(default)");
else
return sourceToString(model, value);
}
// static
AbstractStaticItemModel * SensorData::typeItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.type");
for (int i = 0; i <= TELEM_TYPE_LAST; i++) {
mdl->appendToItemList(typeToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * SensorData::formulaItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.formula");
for (int i = 0; i <= TELEM_FORMULA_LAST; i++) {
mdl->appendToItemList(formulaToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * SensorData::cellIndexItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.cellindex");
for (int i = 0; i <= TELEM_CELL_INDEX_LAST; i++) {
mdl->appendToItemList(cellIndexToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * SensorData::unitItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.unit");
for (int i = 0; i <= UNIT_MAX; i++) {
QString str = unitToString(i);
if (str != CPN_STR_UNKNOWN_ITEM)
mdl->appendToItemList(str, i);
}
mdl->loadItemList();
return mdl;
}
// static
PrecisionItemModel * SensorData::precisionItemModel()
{
PrecisionItemModel * mdl = new PrecisionItemModel(0, 2);
mdl->setName("sensordata.precision");
return mdl;
} }

View file

@ -18,17 +18,32 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef SENSORDATA_H #pragma once
#define SENSORDATA_H
#include "datahelpers.h"
#include <QtCore> #include <QtCore>
constexpr int CPN_MAX_SENSORS = 60; constexpr int CPN_MAX_SENSORS { 60 };
constexpr int SENSOR_LABEL_LEN = 4; constexpr int SENSOR_LABEL_LEN { 4 };
constexpr int SENSOR_ISCONFIGURABLE { 1 << 1 };
constexpr int SENSOR_HAS_GPS { 1 << 2 };
constexpr int SENSOR_HAS_CELLS { 1 << 3 };
constexpr int SENSOR_HAS_CONSUMPTION { 1 << 4 };
constexpr int SENSOR_HAS_RATIO { 1 << 5 };
constexpr int SENSOR_HAS_TOTALIZE { 1 << 6 };
constexpr int SENSOR_HAS_SOURCES_12 { 1 << 7 };
constexpr int SENSOR_HAS_SOURCES_34 { 1 << 8 };
constexpr int SENSOR_HAS_POSITIVE { 1 << 9 };
constexpr int SENSOR_HAS_PRECISION { 1 << 10 };
class ModelData; class ModelData;
class AbstractStaticItemModel;
class PrecisionItemModel;
class SensorData { class SensorData {
Q_DECLARE_TR_FUNCTIONS(SensorData) Q_DECLARE_TR_FUNCTIONS(SensorData)
public: public:
@ -36,7 +51,8 @@ class SensorData {
enum enum
{ {
TELEM_TYPE_CUSTOM, TELEM_TYPE_CUSTOM,
TELEM_TYPE_CALCULATED TELEM_TYPE_CALCULATED,
TELEM_TYPE_LAST = TELEM_TYPE_CALCULATED
}; };
enum enum
@ -63,6 +79,7 @@ class SensorData {
TELEM_CELL_INDEX_6, TELEM_CELL_INDEX_6,
TELEM_CELL_INDEX_HIGHEST, TELEM_CELL_INDEX_HIGHEST,
TELEM_CELL_INDEX_DELTA, TELEM_CELL_INDEX_DELTA,
TELEM_CELL_INDEX_LAST = TELEM_CELL_INDEX_DELTA
}; };
enum enum
@ -163,11 +180,37 @@ class SensorData {
bool isAvailable() const { return strlen(label) > 0; } bool isAvailable() const { return strlen(label) > 0; }
void updateUnit(); void updateUnit();
QString unitString() const;
QString nameToString(int index) const; QString nameToString(int index) const;
QString getOrigin(const ModelData* model) const; QString getOrigin(const ModelData* model) const;
void clear() { memset(this, 0, sizeof(SensorData)); } void clear() { memset(this, 0, sizeof(SensorData)); }
bool isEmpty() const; bool isEmpty() const;
}; QString idToString() const;
QString typeToString() const;
QString formulaToString() const;
QString cellIndexToString() const;
QString unitToString() const;
QString precToString() const;
int getMask() const;
QString paramsToString(const ModelData * model) const;
FieldRange getRatioRange() const;
FieldRange getOffsetRange() const;
void formulaChanged();
void unitChanged();
#endif // SENSORDATA_H static QString sourceToString(const ModelData * model, const int index, const bool sign = false);
static bool isSourceAvailable(const ModelData * model, const int index);
static QString idToString(const int value);
static QString typeToString(const int value);
static QString formulaToString(const int value);
static QString cellIndexToString(const int value);
static QString unitToString(const int value);
static QString precToString(const int value);
static bool isRssiSensorAvailable(const ModelData * model, const int value);
static QString rssiSensorToString(const ModelData * model, const int value);
static AbstractStaticItemModel * typeItemModel();
static AbstractStaticItemModel * formulaItemModel();
static AbstractStaticItemModel * cellIndexItemModel();
static AbstractStaticItemModel * unitItemModel();
static PrecisionItemModel * precisionItemModel();
};

View file

@ -0,0 +1,188 @@
/*
* 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 "timerdata.h"
#include "radiodataconversionstate.h"
#include "compounditemmodels.h"
void TimerData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("TMR"), 1);
cstate.setSubComp(tr("Timer %1").arg(cstate.subCompIdx + 1));
mode.convert(cstate);
}
void TimerData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData));
mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0);
}
bool TimerData::isEmpty()
{
return (mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0) && name[0] == '\0' && minuteBeep == 0 && countdownBeep == COUNTDOWNBEEP_SILENT && val == 0 && persistent == 0 /*&& pvalue == 0*/);
}
bool TimerData::isModeOff()
{
return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0);
}
QString TimerData::nameToString(int index) const
{
return DataHelpers::getElementName(tr("TMR", "as in Timer"), index + 1, name);
}
QString TimerData::countdownBeepToString() const
{
return countdownBeepToString(countdownBeep);
}
QString TimerData::countdownStartToString() const
{
if (countdownBeep == COUNTDOWNBEEP_SILENT)
return "";
else
return countdownStartToString(countdownStart);
}
QString TimerData::persistentToString(const bool verbose) const
{
return persistentToString(persistent, verbose);
}
QString TimerData::pvalueToString() const
{
return pvalueToString(pvalue);
}
QString TimerData::valToString() const
{
return valToString(val);
}
void TimerData::countdownBeepChanged()
{
if (countdownBeep == COUNTDOWNBEEP_SILENT)
countdownStart = 0;
}
// static
QString TimerData::countdownBeepToString(const int value)
{
switch(value) {
case COUNTDOWNBEEP_SILENT:
return tr("Silent");
case COUNTDOWNBEEP_BEEPS:
return tr("Beeps");
case COUNTDOWNBEEP_VOICE:
return tr("Voice");
case COUNTDOWNBEEP_HAPTIC:
return tr("Haptic");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString TimerData::countdownStartToString(const int value)
{
switch(value) {
case COUNTDOWNSTART_5:
return tr("5s");
case COUNTDOWNSTART_10:
return tr("10s");
case COUNTDOWNSTART_20:
return tr("20s");
case COUNTDOWNSTART_30:
return tr("30s");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString TimerData::persistentToString(const int value, const bool verbose)
{
switch(value) {
case PERSISTENT_NOT:
return verbose ? tr("Not persistent") : tr("NOT");
case PERSISTENT_FLIGHT:
return verbose ? tr("Persistent (flight)") : tr("Flight");
case PERSISTENT_MANUALRESET:
return verbose ? tr("Persistent (manual reset)") : tr("Manual reset");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString TimerData::pvalueToString(const int value)
{
return DataHelpers::timeToString(value, TIMESTR_MASK_HRSMINS | TIMESTR_MASK_ZEROHRS);
}
// static
QString TimerData::valToString(const int value)
{
return DataHelpers::timeToString(value, TIMESTR_MASK_HRSMINS | TIMESTR_MASK_ZEROHRS);
}
// static
AbstractStaticItemModel * TimerData::countdownBeepItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName(AIM_TIMER_COUNTDOWNBEEP);
for (int i = 0; i < COUNTDOWNBEEP_COUNT; i++) {
mdl->appendToItemList(countdownBeepToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * TimerData::countdownStartItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName(AIM_TIMER_COUNTDOWNSTART);
for (int i = COUNTDOWNSTART_LAST; i >= COUNTDOWNSTART_FIRST; i--) {
mdl->appendToItemList(countdownStartToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * TimerData::persistentItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName(AIM_TIMER_PERSISTENT);
for (int i = 0; i < PERSISTENT_COUNT; i++) {
mdl->appendToItemList(persistentToString(i), i);
}
mdl->loadItemList();
return mdl;
}

View file

@ -0,0 +1,98 @@
/*
* 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 "rawswitch.h"
#include "datahelpers.h"
#include <QtCore>
class RadioDataConversionState;
class AbstractStaticItemModel;
constexpr char AIM_TIMER_COUNTDOWNBEEP[] {"timerdata.countdownBeep"};
constexpr char AIM_TIMER_COUNTDOWNSTART[] {"timerdata.countdownStart"};
constexpr char AIM_TIMER_PERSISTENT[] {"timerdata.persistent"};
constexpr int TIMER_NAME_LEN {8};
class TimerData {
Q_DECLARE_TR_FUNCTIONS(TimerData)
public:
enum CountDownBeepType {
COUNTDOWNBEEP_SILENT,
COUNTDOWNBEEP_BEEPS,
COUNTDOWNBEEP_VOICE,
COUNTDOWNBEEP_HAPTIC,
COUNTDOWNBEEP_COUNT
};
enum CountDownStart {
COUNTDOWNSTART_30 = -2,
COUNTDOWNSTART_FIRST = COUNTDOWNSTART_30,
COUNTDOWNSTART_20,
COUNTDOWNSTART_10,
COUNTDOWNSTART_5,
COUNTDOWNSTART_LAST = COUNTDOWNSTART_5
};
enum PersistentType {
PERSISTENT_NOT,
PERSISTENT_FLIGHT,
PERSISTENT_MANUALRESET,
PERSISTENT_COUNT
};
TimerData() { clear(); }
RawSwitch mode;
char name[TIMER_NAME_LEN + 1];
bool minuteBeep;
unsigned int countdownBeep;
unsigned int val;
unsigned int persistent;
int countdownStart;
unsigned int direction;
int pvalue;
void convert(RadioDataConversionState & cstate);
void clear();
bool isEmpty();
bool isModeOff();
QString nameToString(int index) const;
QString countdownBeepToString() const;
QString countdownStartToString() const;
QString persistentToString(const bool verbose = true) const;
QString pvalueToString() const;
QString valToString() const;
void countdownBeepChanged();
static QString countdownBeepToString(const int value);
static QString countdownStartToString(const int value);
static QString persistentToString(const int value, const bool verbose = true);
static QString pvalueToString(const int value);
static QString valToString(const int value);
static AbstractStaticItemModel * countdownBeepItemModel();
static AbstractStaticItemModel * countdownStartItemModel();
static AbstractStaticItemModel * persistentItemModel();
};

View file

@ -28,7 +28,7 @@
#include "hardware.h" #include "hardware.h"
#include "../modeledit/customfunctions.h" #include "../modeledit/customfunctions.h"
#include "verticalscrollarea.h" #include "verticalscrollarea.h"
#include "rawitemdatamodels.h" #include "compounditemmodels.h"
GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) : GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) :
QDialog(parent), QDialog(parent),
@ -56,10 +56,14 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir
} }
} }
commonItemModels = new CommonItemModels(&generalSettings, nullptr, this); sharedItemModels = new CompoundItemModelFactory(&generalSettings, nullptr);
sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource);
sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch);
sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction);
sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam);
addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup")); addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup"));
addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, commonItemModels), tr("Global Functions")); addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, sharedItemModels), tr("Global Functions"));
addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer")); addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer"));
addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware")); addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware"));
addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration")); addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration"));
@ -70,6 +74,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir
GeneralEdit::~GeneralEdit() GeneralEdit::~GeneralEdit()
{ {
delete ui; delete ui;
delete sharedItemModels;
} }
void GeneralEdit::closeEvent(QCloseEvent *event) void GeneralEdit::closeEvent(QCloseEvent *event)

View file

@ -25,7 +25,7 @@
#include "eeprominterface.h" #include "eeprominterface.h"
#include "genericpanel.h" #include "genericpanel.h"
class CommonItemModels; class CompoundItemModelFactory;
namespace Ui { namespace Ui {
class GeneralEdit; class GeneralEdit;
@ -73,7 +73,7 @@ class GeneralEdit : public QDialog
QVector<GenericPanel *> panels; QVector<GenericPanel *> panels;
void addTab(GenericPanel *panel, QString text); void addTab(GenericPanel *panel, QString text);
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
CommonItemModels *commonItemModels; CompoundItemModelFactory *sharedItemModels;
}; };
#endif // _GENERALEDIT_H_ #endif // _GENERALEDIT_H_

View file

@ -1527,7 +1527,7 @@ Mode 4:
<string>Battery warning voltage. <string>Battery warning voltage.
This is the threashhold where the battery warning sounds. This is the threashhold where the battery warning sounds.
Acceptable values are 5v..10v</string> Acceptable values are 3v..12v</string>
</property> </property>
<property name="prefix"> <property name="prefix">
<string notr="true"/> <string notr="true"/>
@ -1539,7 +1539,7 @@ Acceptable values are 5v..10v</string>
<number>1</number> <number>1</number>
</property> </property>
<property name="minimum"> <property name="minimum">
<double>4.000000000000000</double> <double>3.000000000000000</double>
</property> </property>
<property name="maximum"> <property name="maximum">
<double>12.000000000000000</double> <double>12.000000000000000</double>
@ -1679,7 +1679,7 @@ Acceptable values are 5v..10v</string>
<number>1</number> <number>1</number>
</property> </property>
<property name="minimum"> <property name="minimum">
<double>4.000000000000000</double> <double>3.000000000000000</double>
</property> </property>
<property name="maximum"> <property name="maximum">
<double>16.000000000000000</double> <double>16.000000000000000</double>
@ -1708,7 +1708,7 @@ Acceptable values are 5v..10v</string>
<number>1</number> <number>1</number>
</property> </property>
<property name="minimum"> <property name="minimum">
<double>4.000000000000000</double> <double>3.000000000000000</double>
</property> </property>
<property name="maximum"> <property name="maximum">
<double>16.000000000000000</double> <double>16.000000000000000</double>

View file

@ -32,6 +32,7 @@
#include "simulatorinterface.h" #include "simulatorinterface.h"
#include "simulatormainwindow.h" #include "simulatormainwindow.h"
#include "storage/sdcard.h" #include "storage/sdcard.h"
#include "filtereditemmodels.h"
#include <QFileDialog> #include <QFileDialog>
#include <QLabel> #include <QLabel>
@ -117,7 +118,8 @@ void CompanionIcon::addImage(const QString & baseimage, Mode mode, State state)
* GVarGroup * GVarGroup
*/ */
GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step, bool allowGvars): GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model,
const int deflt, const int mini, const int maxi, const double step, FilteredItemModel * gvarModel):
QObject(), QObject(),
weightGV(weightGV), weightGV(weightGV),
weightSB(weightSB), weightSB(weightSB),
@ -131,8 +133,8 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
step(step), step(step),
lock(true) lock(true)
{ {
if (allowGvars && getCurrentFirmware()->getCapability(Gvars)) { if (gvarModel && gvarModel->rowCount() > 0) {
Helpers::populateGVCB(*weightCB, weight, model); weightCB->setModel(gvarModel);
connect(weightGV, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int))); connect(weightGV, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
connect(weightCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged())); connect(weightCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
} }
@ -152,12 +154,19 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
void GVarGroup::gvarCBChanged(int state) void GVarGroup::gvarCBChanged(int state)
{ {
weightCB->setVisible(state); if (!lock) {
if (weightSB) weightCB->setVisible(state);
if (weightGV->isChecked()) {
// set CB to +GV1
int cnt = getCurrentFirmware()->getCapability(Gvars);
if (weightCB->count() > cnt)
weightCB->setCurrentIndex(cnt);
else
weightCB->setCurrentIndex(0);
}
weightSB->setVisible(!state); weightSB->setVisible(!state);
else valuesChanged();
weightSB->setVisible(!state); }
valuesChanged();
} }
void GVarGroup::valuesChanged() void GVarGroup::valuesChanged()
@ -168,7 +177,7 @@ void GVarGroup::valuesChanged()
else if (sb) else if (sb)
weight = sb->value(); weight = sb->value();
else else
weight = round(dsb->value()/step); weight = round(dsb->value() / step);
emit valueChanged(); emit valueChanged();
} }
@ -180,7 +189,7 @@ void GVarGroup::setWeight(int val)
int tval; int tval;
if (val>maxi || val<mini) { if (val > maxi || val < mini) {
tval = deflt; tval = deflt;
weightGV->setChecked(true); weightGV->setChecked(true);
weightSB->hide(); weightSB->hide();
@ -214,27 +223,6 @@ void GVarGroup::setWeight(int val)
* Helpers namespace functions * Helpers namespace functions
*/ */
void Helpers::populateGVCB(QComboBox & b, int value, const ModelData & model)
{
int count = getCurrentFirmware()->getCapability(Gvars);
b.clear();
for (int i=-count; i<=-1; i++) {
int16_t gval = (int16_t)(-10000+i);
b.addItem("-" + RawSource(SOURCE_TYPE_GVAR, abs(i)-1).toString(&model), gval);
}
for (int i=1; i<=count; i++) {
int16_t gval = (int16_t)(10000+i);
b.addItem(RawSource(SOURCE_TYPE_GVAR, i-1).toString(&model), gval);
}
b.setCurrentIndex(b.findData(value));
if (b.currentIndex() == -1)
b.setCurrentIndex(count);
}
// TODO: Move lookup to GVarData class (w/out combobox) // TODO: Move lookup to GVarData class (w/out combobox)
void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase) void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
{ {

View file

@ -18,8 +18,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef _HELPERS_H_ #pragma once
#define _HELPERS_H_
#include "eeprominterface.h" #include "eeprominterface.h"
#include <QCheckBox> #include <QCheckBox>
@ -60,12 +59,15 @@ class CompanionIcon: public QIcon {
void addImage(const QString &baseimage, Mode mode = Normal, State state = Off); void addImage(const QString &baseimage, Mode mode = Normal, State state = Off);
}; };
class FilteredItemModel;
class GVarGroup: public QObject { class GVarGroup: public QObject {
Q_OBJECT Q_OBJECT
public: public:
GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step=1.0, bool allowGVars=true); GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model,
const int deflt, const int mini, const int maxi, const double step = 1.0, FilteredItemModel * gvarModel = nullptr);
void setWeight(int val); void setWeight(int val);
@ -101,7 +103,6 @@ class GVarGroup: public QObject {
namespace Helpers namespace Helpers
{ {
void populateGvarUseCB(QComboBox *b, unsigned int phase); void populateGvarUseCB(QComboBox *b, unsigned int phase);
void populateGVCB(QComboBox & b, int value, const ModelData & model);
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current); void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
void getFileComboBoxValue(QComboBox * b, char * dest, int length); void getFileComboBoxValue(QComboBox * b, char * dest, int length);
@ -234,5 +235,3 @@ private:
}; };
extern Stopwatch gStopwatch; extern Stopwatch gStopwatch;
#endif // _HELPERS_H_

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -1585,7 +1585,7 @@ void MainWindow::updateWindowActions()
QString scut; QString scut;
if (++count < 10) if (++count < 10)
scut = tr("Alt+%1").arg(count); scut = tr("Alt+%1").arg(count);
QAction * act = addActToGroup(windowsListActions, "", "", "window_ptr", qVariantFromValue(win), QVariant(), scut); QAction * act = addActToGroup(windowsListActions, "", "", "window_ptr", QVariant::fromValue(win), QVariant(), scut);
act->setChecked(win == mdiArea->activeSubWindow()); act->setChecked(win == mdiArea->activeSubWindow());
updateWindowActionTitle(win, act); updateWindowActionTitle(win, act);
} }

View file

@ -20,44 +20,33 @@
#include "channels.h" #include "channels.h"
#include "helpers.h" #include "helpers.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel): 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):
firmware(firmware), firmware(firmware),
spinbox(new QDoubleSpinBox()), spinbox(new QDoubleSpinBox()),
value(value), value(value)
displayStep(0.1)
{ {
Board::Type board = firmware->getBoard();
bool allowGVars = IS_HORUS_OR_TARANIS(board);
int internalStep = 1;
spinbox->setProperty("index", row); spinbox->setProperty("index", row);
spinbox->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); spinbox->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
spinbox->setAccelerated(true); spinbox->setAccelerated(true);
spinbox->setDecimals(1);
if (firmware->getCapability(PPMUnitMicroseconds)) { if (firmware->getCapability(PPMUnitMicroseconds)) {
displayStep = 0.512; displayStep = 0.512;
spinbox->setDecimals(1);
spinbox->setSuffix("us"); spinbox->setSuffix("us");
} }
else { else {
spinbox->setDecimals(0); displayStep = 0.1;
spinbox->setSuffix("%"); spinbox->setSuffix("%");
} }
if (deflt == 0 /*it's the offset*/) { spinbox->setSingleStep(displayStep);
spinbox->setDecimals(1);
}
else {
internalStep *= 10;
}
spinbox->setSingleStep(displayStep * internalStep);
spinbox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); spinbox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
QHBoxLayout *horizontalLayout = new QHBoxLayout(); QHBoxLayout *horizontalLayout = new QHBoxLayout();
QCheckBox *gv = new QCheckBox(tr("GV")); gv = new QCheckBox(tr("GV"));
gv->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); gv->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
horizontalLayout->addWidget(gv); horizontalLayout->addWidget(gv);
QComboBox *cb = new QComboBox(); QComboBox *cb = new QComboBox();
@ -65,7 +54,7 @@ LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row
horizontalLayout->addWidget(cb); horizontalLayout->addWidget(cb);
horizontalLayout->addWidget(spinbox); horizontalLayout->addWidget(spinbox);
tableLayout->addLayout(row, col, horizontalLayout); tableLayout->addLayout(row, col, horizontalLayout);
gvarGroup = new GVarGroup(gv, spinbox, cb, value, model, deflt, min, max, displayStep, allowGVars); gvarGroup = new GVarGroup(gv, spinbox, cb, value, model, deflt, min, max, displayStep, gvarModel);
QObject::connect(gvarGroup, &GVarGroup::valueChanged, panel, &ModelPanel::modified); QObject::connect(gvarGroup, &GVarGroup::valueChanged, panel, &ModelPanel::modified);
} }
@ -84,28 +73,32 @@ void LimitsGroup::updateMinMax(int max)
if (spinbox->maximum() == 0) { if (spinbox->maximum() == 0) {
spinbox->setMinimum(-max * displayStep); spinbox->setMinimum(-max * displayStep);
gvarGroup->setMinimum(-max); gvarGroup->setMinimum(-max);
if (value < -max) { if (!gv->isChecked() && value < -max) {
value = -max; value = -max;
} }
} }
if (spinbox->minimum() == 0) { if (spinbox->minimum() == 0) {
spinbox->setMaximum(max * displayStep); spinbox->setMaximum(max * displayStep);
gvarGroup->setMaximum(max); gvarGroup->setMaximum(max);
if (value > max) { if (!gv->isChecked() && value > max) {
value = max; value = max;
} }
} }
} }
ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
commonItemModels(commonItemModels) sharedItemModels(sharedItemModels)
{ {
chnCapability = firmware->getCapability(Outputs); chnCapability = firmware->getCapability(Outputs);
int channelNameMaxLen = firmware->getCapability(ChannelsName); int channelNameMaxLen = firmware->getCapability(ChannelsName);
curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this); dialogFilteredItemModels = new FilteredItemModelFactory();
connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &ChannelsPanel::onModelDataAboutToBeUpdated);
connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &ChannelsPanel::onModelDataUpdateComplete); int crvid = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve)), "Curve");
connectItemModelEvents(dialogFilteredItemModels->getItemModel(crvid));
int gvid = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef");
QStringList headerLabels; QStringList headerLabels;
headerLabels << "#"; headerLabels << "#";
@ -147,13 +140,13 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
} }
// Channel offset // Channel offset
chnOffset[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].offset, model, -1000, 1000, 0, this); chnOffset[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].offset, model, -1000, 1000, 0, dialogFilteredItemModels->getItemModel(gvid), this);
// Channel min // Channel min
chnMin[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].min, model, -model.getChannelsMax() * 10, 0, -1000, this); chnMin[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].min, model, -model.getChannelsMax() * 10, 0, -1000, dialogFilteredItemModels->getItemModel(gvid), this);
// Channel max // Channel max
chnMax[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].max, model, 0, model.getChannelsMax() * 10, 1000, this); chnMax[i] = new LimitsGroup(firmware, tableLayout, i, col++, model.limitData[i].max, model, 0, model.getChannelsMax() * 10, 1000, dialogFilteredItemModels->getItemModel(gvid), this);
// Channel inversion // Channel inversion
invCB[i] = new QComboBox(this); invCB[i] = new QComboBox(this);
@ -166,7 +159,7 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
curveCB[i] = new QComboBox(this); curveCB[i] = new QComboBox(this);
curveCB[i]->setProperty("index", i); curveCB[i]->setProperty("index", i);
curveCB[i]->setModel(curveFilteredModel); curveCB[i]->setModel(dialogFilteredItemModels->getItemModel(crvid));
connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited())); connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited()));
tableLayout->addWidget(i, col++, curveCB[i]); tableLayout->addWidget(i, col++, curveCB[i]);
} }
@ -214,6 +207,7 @@ ChannelsPanel::~ChannelsPanel()
delete centerSB[i]; delete centerSB[i];
delete symlimitsChk[i]; delete symlimitsChk[i];
} }
delete dialogFilteredItemModels;
} }
void ChannelsPanel::symlimitsEdited() void ChannelsPanel::symlimitsEdited()
@ -241,12 +235,11 @@ void ChannelsPanel::nameEdited()
void ChannelsPanel::refreshExtendedLimits() void ChannelsPanel::refreshExtendedLimits()
{ {
int channelMax = model->getChannelsMax(); int channelMax = model->getChannelsMax() * 10;
for (int i = 0 ; i < CPN_MAX_CHNOUT; i++) { for (int i = 0 ; i < CPN_MAX_CHNOUT; i++) {
chnOffset[i]->updateMinMax(10 * channelMax); chnMin[i]->updateMinMax(channelMax);
chnMin[i]->updateMinMax(10 * channelMax); chnMax[i]->updateMinMax(channelMax);
chnMax[i]->updateMinMax(10 * channelMax);
} }
emit modified(); emit modified();
} }
@ -319,10 +312,9 @@ void ChannelsPanel::cmPaste()
{ {
QByteArray data; QByteArray data;
if (hasClipboardData(&data)) { if (hasClipboardData(&data)) {
memcpy(&model->limitData[selectedIndex], data.constData(), sizeof(LimitData)); model->limitsSet(selectedIndex, data);
updateLine(selectedIndex); updateLine(selectedIndex);
updateItemModels(); updateItemModels();
emit modified();
} }
} }
@ -331,22 +323,18 @@ void ChannelsPanel::cmDelete()
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return; return;
memmove(&model->limitData[selectedIndex], &model->limitData[selectedIndex + 1], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData)); model->limitsDelete(selectedIndex);
model->limitData[chnCapability - 1].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
for (int i = selectedIndex; i < chnCapability; i++) { for (int i = selectedIndex; i < chnCapability; i++) {
updateLine(i); updateLine(i);
} }
updateItemModels(); updateItemModels();
emit modified();
} }
void ChannelsPanel::cmCopy() void ChannelsPanel::cmCopy()
{ {
QByteArray data; QByteArray data;
data.append((char*)&model->limitData[selectedIndex], sizeof(LimitData)); model->limitsGet(selectedIndex, data);
QMimeData *mimeData = new QMimeData; QMimeData *mimeData = new QMimeData;
mimeData->setData(MIMETYPE_CHANNEL, data); mimeData->setData(MIMETYPE_CHANNEL, data);
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard); QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
@ -412,12 +400,18 @@ bool ChannelsPanel::moveUpAllowed() const
void ChannelsPanel::cmMoveUp() void ChannelsPanel::cmMoveUp()
{ {
swapData(selectedIndex, selectedIndex - 1); model->limitsMove(selectedIndex, -1);
updateLine(selectedIndex - 1);
updateLine(selectedIndex);
updateItemModels();
} }
void ChannelsPanel::cmMoveDown() void ChannelsPanel::cmMoveDown()
{ {
swapData(selectedIndex, selectedIndex + 1); model->limitsMove(selectedIndex, 1);
updateLine(selectedIndex);
updateLine(selectedIndex + 1);
updateItemModels();
} }
void ChannelsPanel::cmClear(bool prompt) void ChannelsPanel::cmClear(bool prompt)
@ -427,11 +421,9 @@ void ChannelsPanel::cmClear(bool prompt)
return; return;
} }
model->limitData[selectedIndex].clear(); model->limitsClear(selectedIndex);
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
updateLine(selectedIndex); updateLine(selectedIndex);
updateItemModels(); updateItemModels();
emit modified();
} }
void ChannelsPanel::cmClearAll() void ChannelsPanel::cmClearAll()
@ -439,47 +431,33 @@ void ChannelsPanel::cmClearAll()
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Channels. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Channels. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return; return;
for (int i = 0; i < chnCapability; i++) { model->limitsClearAll();
model->limitData[i].clear(); update();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, i);
updateLine(i);
}
updateItemModels(); updateItemModels();
emit modified();
} }
void ChannelsPanel::cmInsert() void ChannelsPanel::cmInsert()
{ {
memmove(&model->limitData[selectedIndex + 1], &model->limitData[selectedIndex], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData)); model->limitsInsert(selectedIndex);
model->limitData[selectedIndex].clear(); for (int i = selectedIndex; i < chnCapability; i++) {
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); updateLine(i);
update();
updateItemModels();
emit modified();
}
void ChannelsPanel::swapData(int idx1, int idx2)
{
if ((idx1 != idx2) && (!model->limitData[idx1].isEmpty() || !model->limitData[idx2].isEmpty())) {
LimitData chntmp = model->limitData[idx2];
LimitData *chn1 = &model->limitData[idx1];
LimitData *chn2 = &model->limitData[idx2];
memcpy(chn2, chn1, sizeof(LimitData));
memcpy(chn1, &chntmp, sizeof(LimitData));
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
updateLine(idx1);
updateLine(idx2);
updateItemModels();
emit modified();
} }
updateItemModels();
} }
void ChannelsPanel::onModelDataAboutToBeUpdated() void ChannelsPanel::connectItemModelEvents(const FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &ChannelsPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &ChannelsPanel::onItemModelUpdateComplete);
}
void ChannelsPanel::onItemModelAboutToBeUpdated()
{ {
lock = true; lock = true;
} }
void ChannelsPanel::onModelDataUpdateComplete() void ChannelsPanel::onItemModelUpdateComplete()
{ {
update(); update();
lock = false; lock = false;
@ -487,5 +465,6 @@ void ChannelsPanel::onModelDataUpdateComplete()
void ChannelsPanel::updateItemModels() void ChannelsPanel::updateItemModels()
{ {
commonItemModels->update(CommonItemModels::RMO_CHANNELS); sharedItemModels->update(AbstractItemModel::IMUE_Channels);
emit modified();
} }

View file

@ -18,16 +18,15 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef _CHANNELS_H_ #pragma once
#define _CHANNELS_H_
#include "helpers.h" #include "helpers.h"
#include "modeledit.h" #include "modeledit.h"
#include <QtCore> #include <QtCore>
class CommonItemModels; class CompoundItemModelFactory;
class RawItemFilteredModel; class FilteredItemModelFactory;
constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel"; constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel";
@ -38,7 +37,8 @@ class LimitsGroup
Q_DECLARE_TR_FUNCTIONS(LimitsGroup) Q_DECLARE_TR_FUNCTIONS(LimitsGroup)
public: public:
LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel=NULL); LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model,
int min, int max, int deflt, FilteredItemModel * gvarModel, ModelPanel * panel = nullptr);
~LimitsGroup(); ~LimitsGroup();
void setValue(int val); void setValue(int val);
@ -50,6 +50,7 @@ class LimitsGroup
GVarGroup *gvarGroup; GVarGroup *gvarGroup;
int &value; int &value;
double displayStep; double displayStep;
QCheckBox *gv;
}; };
class ChannelsPanel : public ModelPanel class ChannelsPanel : public ModelPanel
@ -57,8 +58,9 @@ class ChannelsPanel : public ModelPanel
Q_OBJECT Q_OBJECT
public: public:
ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
~ChannelsPanel(); CompoundItemModelFactory * sharedItemModels);
virtual ~ChannelsPanel();
public slots: public slots:
void refreshExtendedLimits(); void refreshExtendedLimits();
@ -81,15 +83,14 @@ class ChannelsPanel : public ModelPanel
void cmClear(bool prompt = true); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
void onCustomContextMenuRequested(QPoint pos); void onCustomContextMenuRequested(QPoint pos);
void onModelDataAboutToBeUpdated(); void onItemModelAboutToBeUpdated();
void onModelDataUpdateComplete(); void onItemModelUpdateComplete();
private: private:
bool hasClipboardData(QByteArray * data = nullptr) const; bool hasClipboardData(QByteArray * data = nullptr) const;
bool insertAllowed() const; bool insertAllowed() const;
bool moveDownAllowed() const; bool moveDownAllowed() const;
bool moveUpAllowed() const; bool moveUpAllowed() const;
void swapData(int idx1, int idx2);
QLineEdit *name[CPN_MAX_CHNOUT]; QLineEdit *name[CPN_MAX_CHNOUT];
LimitsGroup *chnOffset[CPN_MAX_CHNOUT]; LimitsGroup *chnOffset[CPN_MAX_CHNOUT];
LimitsGroup *chnMin[CPN_MAX_CHNOUT]; LimitsGroup *chnMin[CPN_MAX_CHNOUT];
@ -100,9 +101,8 @@ class ChannelsPanel : public ModelPanel
QCheckBox *symlimitsChk[CPN_MAX_CHNOUT]; QCheckBox *symlimitsChk[CPN_MAX_CHNOUT];
int selectedIndex; int selectedIndex;
int chnCapability; int chnCapability;
CommonItemModels * commonItemModels; CompoundItemModelFactory *sharedItemModels;
RawItemFilteredModel *curveFilteredModel;
void updateItemModels(); void updateItemModels();
void connectItemModelEvents(const FilteredItemModel * itemModel);
FilteredItemModelFactory *dialogFilteredItemModels;
}; };
#endif // _CHANNELS_H_

View file

@ -23,7 +23,7 @@
#include "node.h" #include "node.h"
#include "edge.h" #include "edge.h"
#include "helpers.h" #include "helpers.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
#define GFX_MARGIN 16 #define GFX_MARGIN 16
@ -109,11 +109,12 @@ float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax
return y; return y;
} }
CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::Curves), ui(new Ui::Curves),
currentCurve(0), currentCurve(0),
commonItemModels(commonItemModels) sharedItemModels(sharedItemModels)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -812,7 +813,7 @@ void CurvesPanel::swapData(int idx1, int idx2)
void CurvesPanel::updateItemModels() void CurvesPanel::updateItemModels()
{ {
commonItemModels->update(CommonItemModels::RMO_CURVES); sharedItemModels->update(AbstractItemModel::IMUE_Curves);
} }
CustomScene::CustomScene(QGraphicsView * view) : CustomScene::CustomScene(QGraphicsView * view) :

View file

@ -26,7 +26,7 @@
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QGraphicsView> #include <QGraphicsView>
class CommonItemModels; class CompoundItemModelFactory;
constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve"; constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve";
@ -61,7 +61,7 @@ class CurvesPanel : public ModelPanel
Q_OBJECT Q_OBJECT
public: public:
CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
virtual ~CurvesPanel(); virtual ~CurvesPanel();
virtual void update(); virtual void update();
@ -121,7 +121,7 @@ class CurvesPanel : public ModelPanel
bool moveDownAllowed() const; bool moveDownAllowed() const;
bool moveUpAllowed() const; bool moveUpAllowed() const;
void swapData(int idx1, int idx2); void swapData(int idx1, int idx2);
CommonItemModels * commonItemModels; CompoundItemModelFactory * sharedItemModels;
void updateItemModels(); void updateItemModels();
}; };

View file

@ -19,57 +19,15 @@
*/ */
#include "customfunctions.h" #include "customfunctions.h"
#include "rawitemfilteredmodel.h"
#include "helpers.h" #include "helpers.h"
#include "appdata.h" #include "appdata.h"
#include <TimerEdit> #include <TimerEdit>
RepeatComboBox::RepeatComboBox(QWidget *parent, int & repeatParam): CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware,
QComboBox(parent), CompoundItemModelFactory * sharedItemModels):
repeatParam(repeatParam)
{
unsigned int step = 1;
int value = repeatParam/step;
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
if (step == 1) {
addItem(tr("Played once, not during startup"), -1);
value++;
}
addItem(tr("No repeat"), 0);
for (unsigned int i = step; i <= 60; i += step) {
addItem(tr("%1s").arg(i), i);
}
setCurrentIndex(value);
connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onIndexChanged(int)));
}
void RepeatComboBox::onIndexChanged(int index)
{
repeatParam = itemData(index).toInt();
emit modified();
}
void RepeatComboBox::update()
{
unsigned int step = 1;
int value = repeatParam/step;
if (step == 1) {
value++;
}
setCurrentIndex(value);
}
CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels):
GenericPanel(parent, model, generalSettings, firmware), GenericPanel(parent, model, generalSettings, firmware),
functions(model ? model->customFn : generalSettings.customFn), functions(model ? model->customFn : generalSettings.customFn),
commonItemModels(commonItemModels),
mediaPlayerCurrent(-1), mediaPlayerCurrent(-1),
mediaPlayer(nullptr), mediaPlayer(nullptr),
modelsUpdateCnt(0) modelsUpdateCnt(0)
@ -77,21 +35,41 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
lock = true; lock = true;
fswCapability = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions); fswCapability = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext, this); tabModelFactory = new CompoundItemModelFactory(&generalSettings, model);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); playSoundId = tabModelFactory->registerItemModel(CustomFunctionData::playSoundItemModel());
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); harpicId = tabModelFactory->registerItemModel(CustomFunctionData::harpicItemModel());
repeatId = tabModelFactory->registerItemModel(CustomFunctionData::repeatItemModel());
gvarAdjustModeId = tabModelFactory->registerItemModel(CustomFunctionData::gvarAdjustModeItemModel());
rawSourceAllModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), this); tabFilterFactory = new FilteredItemModelFactory();
connect(rawSourceAllModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated);
connect(rawSourceAllModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete);
rawSourceInputsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this); funcActionsId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CustomFuncAction),
connect(rawSourceInputsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); model ? CustomFunctionData::AllFunctionContexts : CustomFunctionData::GlobalFunctionsContext),
connect(rawSourceInputsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); "Function Actions");
connectItemModelEvents(tabFilterFactory->getItemModel(funcActionsId));
rawSourceGVarsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::GVarsGroup, this); funcResetParamId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CustomFuncResetParam)),
connect(rawSourceGVarsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); "Reset Params");
connect(rawSourceGVarsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); connectItemModelEvents(tabFilterFactory->getItemModel(funcResetParamId));
rawSwitchId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch),
model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext),
"RawSwitch");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSwitchId));
rawSourceAllId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource)),
"RawSource All");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSourceAllId));
rawSourceInputsId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource),
RawSource::InputSourceGroups),
"RawSource Inputs");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSourceInputsId));
rawSourceGVarsId = tabFilterFactory->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource),
RawSource::GVarsGroup),
"RawSource GVars");
connectItemModelEvents(tabFilterFactory->getItemModel(rawSourceGVarsId));
if (!firmware->getCapability(VoicesAsNumbers)) { if (!firmware->getCapability(VoicesAsNumbers)) {
tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength)); tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength));
@ -121,7 +99,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
playIcon.addImage("stop.png", QIcon::Normal, QIcon::On); playIcon.addImage("stop.png", QIcon::Normal, QIcon::On);
QStringList headerLabels; QStringList headerLabels;
headerLabels << "#" << tr("Switch") << tr("Action") << tr("Parameters") << tr("Enable"); headerLabels << "#" << tr("Switch") << tr("Action") << tr("Parameters") << "";
TableLayout * tableLayout = new TableLayout(this, fswCapability, headerLabels); TableLayout * tableLayout = new TableLayout(this, fswCapability, headerLabels);
for (int i = 0; i < fswCapability; i++) { for (int i = 0; i < fswCapability; i++) {
@ -138,32 +116,26 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint))); connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
tableLayout->addWidget(i, 0, label); tableLayout->addWidget(i, 0, label);
// s1.report("label");
// The switch // The switch
fswtchSwtch[i] = new QComboBox(this); fswtchSwtch[i] = new QComboBox(this);
fswtchSwtch[i]->setModel(rawSwitchFilteredModel);
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue()));
fswtchSwtch[i]->setProperty("index", i); fswtchSwtch[i]->setProperty("index", i);
fswtchSwtch[i]->setModel(tabFilterFactory->getItemModel(rawSwitchId));
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue()));
fswtchSwtch[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum); fswtchSwtch[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
fswtchSwtch[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
fswtchSwtch[i]->setMaxVisibleItems(10); fswtchSwtch[i]->setMaxVisibleItems(10);
connect(fswtchSwtch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited())); connect(fswtchSwtch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
tableLayout->addWidget(i, 1, fswtchSwtch[i]); tableLayout->addWidget(i, 1, fswtchSwtch[i]);
// s1.report("switch");
// The function // The function
fswtchFunc[i] = new QComboBox(this); fswtchFunc[i] = new QComboBox(this);
if (!i) {
populateFuncCB(fswtchFunc[i], functions[i].func);
}
else {
fswtchFunc[i]->setModel(fswtchFunc[0]->model());
fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(functions[i].func));
}
fswtchFunc[i]->setProperty("index", i); fswtchFunc[i]->setProperty("index", i);
fswtchFunc[i]->setModel(tabFilterFactory->getItemModel(funcActionsId));
fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(functions[i].func));
fswtchFunc[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
connect(fswtchFunc[i], SIGNAL(currentIndexChanged(int)), this, SLOT(functionEdited())); connect(fswtchFunc[i], SIGNAL(currentIndexChanged(int)), this, SLOT(functionEdited()));
tableLayout->addWidget(i, 2, fswtchFunc[i]); tableLayout->addWidget(i, 2, fswtchFunc[i]);
// s1.report("func");
// The parameters // The parameters
QHBoxLayout * paramLayout = new QHBoxLayout(); QHBoxLayout * paramLayout = new QHBoxLayout();
@ -171,15 +143,15 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
fswtchGVmode[i] = new QComboBox(this); fswtchGVmode[i] = new QComboBox(this);
fswtchGVmode[i]->setProperty("index", i); fswtchGVmode[i]->setProperty("index", i);
populateGVmodeCB(fswtchGVmode[i], functions[i].adjustMode); fswtchGVmode[i]->setModel(tabModelFactory->getItemModel(gvarAdjustModeId));
fswtchGVmode[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents); fswtchGVmode[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
connect(fswtchGVmode[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited())); connect(fswtchGVmode[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
paramLayout->addWidget(fswtchGVmode[i]); paramLayout->addWidget(fswtchGVmode[i]);
fswtchParamGV[i] = new QCheckBox(this); fswtchParamGV[i] = new QCheckBox(this);
fswtchParamGV[i]->setProperty("index", i); fswtchParamGV[i]->setProperty("index", i);
fswtchParamGV[i]->setText("GV"); fswtchParamGV[i]->setText(tr("GV"));
fswtchParamGV[i]->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); fswtchParamGV[i]->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
connect(fswtchParamGV[i], SIGNAL(stateChanged(int)), this, SLOT(customFunctionEdited())); connect(fswtchParamGV[i], SIGNAL(stateChanged(int)), this, SLOT(customFunctionEdited()));
paramLayout->addWidget(fswtchParamGV[i]); paramLayout->addWidget(fswtchParamGV[i]);
@ -210,15 +182,6 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
connect(fswtchParamArmT[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited())); connect(fswtchParamArmT[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
connect(fswtchParamArmT[i], SIGNAL(editTextChanged ( const QString)), this, SLOT(customFunctionEdited())); connect(fswtchParamArmT[i], SIGNAL(editTextChanged ( const QString)), this, SLOT(customFunctionEdited()));
fswtchBLcolor[i] = new QSlider(this);
fswtchBLcolor[i]->setProperty("index", i);
fswtchBLcolor[i]->setMinimum(0);
fswtchBLcolor[i]->setMaximum(100);
fswtchBLcolor[i]->setSingleStep(1);
fswtchBLcolor[i]->setOrientation(Qt::Horizontal);
paramLayout->addWidget(fswtchBLcolor[i]);
connect(fswtchBLcolor[i], SIGNAL(sliderReleased()), this, SLOT(customFunctionEdited()));
playBT[i] = new QToolButton(this); playBT[i] = new QToolButton(this);
playBT[i]->setProperty("index", i); playBT[i]->setProperty("index", i);
playBT[i]->setIcon(playIcon); playBT[i]->setIcon(playIcon);
@ -228,9 +191,13 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
QHBoxLayout * repeatLayout = new QHBoxLayout(); QHBoxLayout * repeatLayout = new QHBoxLayout();
tableLayout->addLayout(i, 4, repeatLayout); tableLayout->addLayout(i, 4, repeatLayout);
fswtchRepeat[i] = new RepeatComboBox(this, functions[i].repeatParam); fswtchRepeat[i] = new QComboBox(this);
fswtchRepeat[i]->setProperty("index", i);
fswtchRepeat[i]->setModel(tabModelFactory->getItemModel(repeatId));
fswtchRepeat[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
fswtchRepeat[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
repeatLayout->addWidget(fswtchRepeat[i], i + 1); repeatLayout->addWidget(fswtchRepeat[i], i + 1);
connect(fswtchRepeat[i], SIGNAL(modified()), this, SLOT(onRepeatModified())); connect(fswtchRepeat[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
fswtchEnable[i] = new QCheckBox(this); fswtchEnable[i] = new QCheckBox(this);
fswtchEnable[i]->setProperty("index", i); fswtchEnable[i]->setProperty("index", i);
@ -253,6 +220,8 @@ CustomFunctionsPanel::~CustomFunctionsPanel()
{ {
if (mediaPlayer) if (mediaPlayer)
stopSound(mediaPlayerCurrent); stopSound(mediaPlayerCurrent);
delete tabModelFactory;
delete tabFilterFactory;
} }
void CustomFunctionsPanel::onMediaPlayerStateChanged(QMediaPlayer::State state) void CustomFunctionsPanel::onMediaPlayerStateChanged(QMediaPlayer::State state)
@ -332,7 +301,6 @@ void CustomFunctionsPanel::toggleSound(bool play)
#define CUSTOM_FUNCTION_ENABLE (1<<6) #define CUSTOM_FUNCTION_ENABLE (1<<6)
#define CUSTOM_FUNCTION_REPEAT (1<<7) #define CUSTOM_FUNCTION_REPEAT (1<<7)
#define CUSTOM_FUNCTION_PLAY (1<<8) #define CUSTOM_FUNCTION_PLAY (1<<8)
#define CUSTOM_FUNCTION_BL_COLOR (1<<9)
#define CUSTOM_FUNCTION_SHOW_FUNC (1<<10) #define CUSTOM_FUNCTION_SHOW_FUNC (1<<10)
@ -362,11 +330,6 @@ void CustomFunctionsPanel::functionEdited()
} }
} }
void CustomFunctionsPanel::onRepeatModified()
{
emit modified();
}
void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
{ {
CustomFunctionData & cfn = functions[i]; CustomFunctionData & cfn = functions[i];
@ -413,8 +376,8 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) { else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) {
int gvidx = func - FuncAdjustGV1; int gvidx = func - FuncAdjustGV1;
if (modified) if (modified)
cfn.adjustMode = fswtchGVmode[i]->currentIndex(); cfn.adjustMode = fswtchGVmode[i]->currentData().toInt();
fswtchGVmode[i]->setCurrentIndex(cfn.adjustMode); fswtchGVmode[i]->setCurrentIndex(fswtchGVmode[i]->findData(cfn.adjustMode));
widgetsMask |= CUSTOM_FUNCTION_GV_MODE | CUSTOM_FUNCTION_ENABLE; widgetsMask |= CUSTOM_FUNCTION_GV_MODE | CUSTOM_FUNCTION_ENABLE;
if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) { if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) {
if (modified) if (modified)
@ -467,8 +430,10 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
} }
else if (func == FuncPlaySound || func == FuncPlayHaptic || func == FuncPlayValue || func == FuncPlayPrompt || func == FuncPlayBoth || func == FuncBackgroundMusic) { else if (func == FuncPlaySound || func == FuncPlayHaptic || func == FuncPlayValue || func == FuncPlayPrompt || func == FuncPlayBoth || func == FuncBackgroundMusic) {
if (func != FuncBackgroundMusic) { if (func != FuncBackgroundMusic) {
if (modified)
cfn.repeatParam = fswtchRepeat[i]->currentData().toInt();
widgetsMask |= CUSTOM_FUNCTION_REPEAT; widgetsMask |= CUSTOM_FUNCTION_REPEAT;
fswtchRepeat[i]->update(); fswtchRepeat[i]->setCurrentIndex(fswtchRepeat[i]->findData(cfn.repeatParam));
} }
if (func == FuncPlayValue) { if (func == FuncPlayValue) {
if (modified) if (modified)
@ -492,7 +457,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
if (modified) { if (modified) {
if (fswtchParamGV[i]->isChecked()) { if (fswtchParamGV[i]->isChecked()) {
fswtchParam[i]->setMinimum(1); fswtchParam[i]->setMinimum(1);
cfn.param = std::min(fswtchParam[i]->value(),5.0)+(fswtchParamGV[i]->isChecked() ? 250 : 0); cfn.param = std::min(fswtchParam[i]->value(), 5.0) + (fswtchParamGV[i]->isChecked() ? 250 : 0);
} }
else { else {
cfn.param = fswtchParam[i]->value(); cfn.param = fswtchParam[i]->value();
@ -576,7 +541,6 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
fswtchEnable[i]->setChecked(false); fswtchEnable[i]->setChecked(false);
fswtchRepeat[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_REPEAT); fswtchRepeat[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_REPEAT);
fswtchGVmode[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_MODE); fswtchGVmode[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_MODE);
fswtchBLcolor[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_BL_COLOR);
playBT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_PLAY); playBT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_PLAY);
} }
@ -652,77 +616,43 @@ void CustomFunctionsPanel::onCustomContextMenuRequested(QPoint pos)
contextMenu.exec(globalPos); contextMenu.exec(globalPos);
} }
void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value)
{
b->clear();
for (unsigned int i = 0; i < FuncCount; i++) {
if (((i >= FuncOverrideCH1 && i <= FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) ||
((i == FuncVolume || i == FuncBackgroundMusic || i == FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) ||
((i == FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) ||
((i == FuncPlayHaptic) && !firmware->getCapability(Haptic)) ||
((i == FuncPlayBoth) && !firmware->getCapability(HasBeeper)) ||
((i == FuncLogs) && !firmware->getCapability(HasSDLogs)) ||
((i == FuncSetTimer3) && firmware->getCapability(Timers) < 3) ||
((i == FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) ||
((i >= FuncRangeCheckInternalModule && i <= FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) ||
((i >= FuncAdjustGV1 && i <= FuncAdjustGVLast) && (!model || !firmware->getCapability(Gvars)))
) {
// skipped
continue;
}
else {
b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(model), i);
if (i == value) {
b->setCurrentIndex(b->count() - 1);
}
}
}
}
void CustomFunctionsPanel::populateGVmodeCB(QComboBox *b, unsigned int value)
{
b->clear();
b->addItem(tr("Value"));
b->addItem(tr("Source"));
b->addItem(tr("GVAR"));
b->addItem(tr("Increment"));
b->setCurrentIndex(value);
}
void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode) void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode)
{ {
QStringList qs; QStringList qs;
b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model
if (function == FuncPlaySound) { if (function == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs); b->setModel(tabModelFactory->getItemModel(playSoundId));
b->addItems(qs); b->setCurrentIndex(b->findData(value));
b->setCurrentIndex(value);
} }
else if (function == FuncPlayHaptic) { else if (function == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs); b->setModel(tabModelFactory->getItemModel(harpicId));
b->addItems(qs); b->setCurrentIndex(b->findData(value));
b->setCurrentIndex(value);
} }
else if (function == FuncReset) { else if (function == FuncReset) {
CustomFunctionData::populateResetParams(model, b, value); b->setModel(tabFilterFactory->getItemModel(funcResetParamId));
b->setCurrentIndex(b->findData(value));
} }
else if (function == FuncVolume || function == FuncBacklight) { else if (function == FuncVolume || function == FuncBacklight) {
b->setModel(rawSourceInputsModel); b->setModel(tabFilterFactory->getItemModel(rawSourceInputsId));
b->setCurrentIndex(b->findData(value)); b->setCurrentIndex(b->findData(value));
} }
else if (function == FuncPlayValue) { else if (function == FuncPlayValue) {
b->setModel(rawSourceAllModel); b->setModel(tabFilterFactory->getItemModel(rawSourceAllId));
b->setCurrentIndex(b->findData(value)); b->setCurrentIndex(b->findData(value));
} }
else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) { else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) {
switch (adjustmode) { switch (adjustmode) {
case 1: case 1:
b->setModel(rawSourceInputsModel); b->setModel(tabFilterFactory->getItemModel(rawSourceInputsId));
b->setCurrentIndex(b->findData(value)); b->setCurrentIndex(b->findData(value));
if (b->currentIndex() < 0)
b->setCurrentIndex(0);
break; break;
case 2: case 2:
b->setModel(rawSourceGVarsModel); b->setModel(tabFilterFactory->getItemModel(rawSourceGVarsId));
b->setCurrentIndex(b->findData(value)); b->setCurrentIndex(b->findData(value));
if (b->currentIndex() < 0)
b->setCurrentIndex(0);
break; break;
} }
} }
@ -827,13 +757,19 @@ bool CustomFunctionsPanel::moveUpAllowed() const
return selectedIndex > 0; return selectedIndex > 0;
} }
void CustomFunctionsPanel::onModelDataAboutToBeUpdated() void CustomFunctionsPanel::connectItemModelEvents(FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &CustomFunctionsPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &CustomFunctionsPanel::onItemModelUpdateComplete);
}
void CustomFunctionsPanel::onItemModelAboutToBeUpdated()
{ {
lock = true; lock = true;
modelsUpdateCnt++; modelsUpdateCnt++;
} }
void CustomFunctionsPanel::onModelDataUpdateComplete() void CustomFunctionsPanel::onItemModelUpdateComplete()
{ {
modelsUpdateCnt--; modelsUpdateCnt--;
if (modelsUpdateCnt < 1) { if (modelsUpdateCnt < 1) {

View file

@ -18,45 +18,26 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef _CUSTOMFUNCTIONS_H_ #pragma once
#define _CUSTOMFUNCTIONS_H_
#include "modeledit.h" #include "modeledit.h"
#include "eeprominterface.h" #include "eeprominterface.h"
#include "compounditemmodels.h"
#include "filtereditemmodels.h"
#include <QMediaPlayer> #include <QMediaPlayer>
class CommonItemModels;
class RawItemFilteredModel;
class TimerEdit; class TimerEdit;
constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function"; constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function";
class RepeatComboBox: public QComboBox
{
Q_OBJECT
public:
RepeatComboBox(QWidget * parent, int & repeatParam);
void update();
signals:
void modified();
private slots:
void onIndexChanged(int);
protected:
int & repeatParam;
};
class CustomFunctionsPanel : public GenericPanel class CustomFunctionsPanel : public GenericPanel
{ {
Q_OBJECT Q_OBJECT
public: public:
CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
~CustomFunctionsPanel(); virtual ~CustomFunctionsPanel();
virtual void update(); virtual void update();
@ -68,7 +49,6 @@ class CustomFunctionsPanel : public GenericPanel
void functionEdited(); void functionEdited();
void onCustomContextMenuRequested(QPoint pos); void onCustomContextMenuRequested(QPoint pos);
void refreshCustomFunction(int index, bool modified=false); void refreshCustomFunction(int index, bool modified=false);
void onRepeatModified();
bool playSound(int index); bool playSound(int index);
void stopSound(int index); void stopSound(int index);
void toggleSound(bool play); void toggleSound(bool play);
@ -83,12 +63,10 @@ class CustomFunctionsPanel : public GenericPanel
void cmInsert(); void cmInsert();
void cmClear(bool prompt = true); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
void onModelDataAboutToBeUpdated(); void onItemModelAboutToBeUpdated();
void onModelDataUpdateComplete(); void onItemModelUpdateComplete();
private: private:
void populateFuncCB(QComboBox *b, unsigned int value);
void populateGVmodeCB(QComboBox *b, unsigned int value);
void populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode=0); void populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode=0);
bool hasClipboardData(QByteArray * data = nullptr) const; bool hasClipboardData(QByteArray * data = nullptr) const;
bool insertAllowed() const; bool insertAllowed() const;
@ -96,11 +74,20 @@ class CustomFunctionsPanel : public GenericPanel
bool moveUpAllowed() const; bool moveUpAllowed() const;
void swapData(int idx1, int idx2); void swapData(int idx1, int idx2);
void resetCBsAndRefresh(int idx); void resetCBsAndRefresh(int idx);
CommonItemModels * commonItemModels; void connectItemModelEvents(FilteredItemModel * itemModel);
RawItemFilteredModel * rawSwitchFilteredModel;
RawItemFilteredModel * rawSourceAllModel; CompoundItemModelFactory * tabModelFactory;
RawItemFilteredModel * rawSourceInputsModel; FilteredItemModelFactory * tabFilterFactory;
RawItemFilteredModel * rawSourceGVarsModel; int funcActionsId;
int funcResetParamId;
int rawSwitchId;
int rawSourceAllId;
int rawSourceInputsId;
int rawSourceGVarsId;
int playSoundId;
int harpicId;
int repeatId;
int gvarAdjustModeId;
QSet<QString> tracksSet; QSet<QString> tracksSet;
QSet<QString> scriptsSet; QSet<QString> scriptsSet;
@ -114,14 +101,11 @@ class CustomFunctionsPanel : public GenericPanel
QComboBox * fswtchParamT[CPN_MAX_SPECIAL_FUNCTIONS]; QComboBox * fswtchParamT[CPN_MAX_SPECIAL_FUNCTIONS];
QComboBox * fswtchParamArmT[CPN_MAX_SPECIAL_FUNCTIONS]; QComboBox * fswtchParamArmT[CPN_MAX_SPECIAL_FUNCTIONS];
QCheckBox * fswtchEnable[CPN_MAX_SPECIAL_FUNCTIONS]; QCheckBox * fswtchEnable[CPN_MAX_SPECIAL_FUNCTIONS];
RepeatComboBox * fswtchRepeat[CPN_MAX_SPECIAL_FUNCTIONS]; QComboBox * fswtchRepeat[CPN_MAX_SPECIAL_FUNCTIONS];
QComboBox * fswtchGVmode[CPN_MAX_SPECIAL_FUNCTIONS]; QComboBox * fswtchGVmode[CPN_MAX_SPECIAL_FUNCTIONS];
QSlider * fswtchBLcolor[CPN_MAX_SPECIAL_FUNCTIONS];
QMediaPlayer * mediaPlayer; QMediaPlayer * mediaPlayer;
int selectedIndex; int selectedIndex;
int fswCapability; int fswCapability;
int modelsUpdateCnt; int modelsUpdateCnt;
}; };
#endif // _CUSTOMFUNCTIONS_H_

View file

@ -20,12 +20,11 @@
#include "expodialog.h" #include "expodialog.h"
#include "ui_expodialog.h" #include "ui_expodialog.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
#include "helpers.h" #include "helpers.h"
ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings, ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings,
Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceModel, Firmware * firmware, QString & inputName, CompoundItemModelFactory * sharedItemModels) :
RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) :
QDialog(parent), QDialog(parent),
ui(new Ui::ExpoDialog), ui(new Ui::ExpoDialog),
model(model), model(model),
@ -38,6 +37,9 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
{ {
ui->setupUi(this); ui->setupUi(this);
dialogFilteredItemModels = new FilteredItemModelFactory();
int id;
QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 }; QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 };
QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 };
for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
@ -48,11 +50,20 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings))); setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings)));
QRegExp rx(CHAR_FOR_NAMES_REGEX); QRegExp rx(CHAR_FOR_NAMES_REGEX);
gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100); id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef");
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100); gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100, 1.0,
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model, curveItemModel, this); dialogFilteredItemModels->getItemModel(id));
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100, 1.0,
dialogFilteredItemModels->getItemModel(id));
ui->switchesCB->setModel(rawSwitchModel); 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);
id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch),
RawSwitch::MixesContext), "RawSwitch");
ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id));
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue())); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue()));
ui->sideCB->setCurrentIndex(ed->mode - 1); ui->sideCB->setCurrentIndex(ed->mode - 1);
@ -83,7 +94,10 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
if (firmware->getCapability(VirtualInputs)) { if (firmware->getCapability(VirtualInputs)) {
ui->inputName->setMaxLength(firmware->getCapability(InputsLength)); ui->inputName->setMaxLength(firmware->getCapability(InputsLength));
ui->sourceCB->setModel(rawSourceModel); id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource),
(RawSource::InputSourceGroups & ~RawSource::NoneGroup & ~RawSource::InputsGroup) | RawSource::TelemGroup),
"RawSource");
ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id));
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue())); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue()));
ui->inputName->setValidator(new QRegExpValidator(rx, this)); ui->inputName->setValidator(new QRegExpValidator(rx, this));
ui->inputName->setText(inputName); ui->inputName->setText(inputName);
@ -135,9 +149,10 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
ExpoDialog::~ExpoDialog() ExpoDialog::~ExpoDialog()
{ {
delete ui;
delete gvWeightGroup; delete gvWeightGroup;
delete gvOffsetGroup; delete gvOffsetGroup;
delete ui; delete dialogFilteredItemModels;
} }
void ExpoDialog::updateScale() void ExpoDialog::updateScale()

View file

@ -26,7 +26,9 @@
#include "modelprinter.h" #include "modelprinter.h"
class GVarGroup; class GVarGroup;
class RawItemFilteredModel; class CompoundItemModelFactory;
class FilteredItemModelFactory;
class CurveRefFilteredFactory;
class CurveReferenceUIManager; class CurveReferenceUIManager;
namespace Ui { namespace Ui {
@ -37,9 +39,8 @@ class ExpoDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings, ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings,
Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceItemModel, Firmware * firmware, QString & inputName, CompoundItemModelFactory * sharedItemModels);
RawItemFilteredModel * rawSwitchItemModel, RawItemFilteredModel * curveItemModel); virtual ~ExpoDialog();
~ExpoDialog();
protected: protected:
void updateScale(); void updateScale();
@ -65,6 +66,8 @@ class ExpoDialog : public QDialog {
ModelPrinter modelPrinter; ModelPrinter modelPrinter;
bool lock; bool lock;
QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES];
FilteredItemModelFactory *dialogFilteredItemModels;
CurveRefFilteredFactory *curveRefFilteredItemModels;
}; };
#endif // _EXPODIALOG_H_ #endif // _EXPODIALOG_H_

View file

@ -20,19 +20,19 @@
#include "flightmodes.h" #include "flightmodes.h"
#include "ui_flightmode.h" #include "ui_flightmode.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
#include "helpers.h" #include "helpers.h"
#include "customdebug.h" #include "customdebug.h"
FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel): FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware,
FilteredItemModel * rawSwitchFilteredModel):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::FlightMode), ui(new Ui::FlightMode),
phaseIdx(phaseIdx), phaseIdx(phaseIdx),
phase(model.flightModeData[phaseIdx]) phase(model.flightModeData[phaseIdx])
{ {
ui->setupUi(this); ui->setupUi(this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &FlightModePanel::onModelDataAboutToBeUpdated); connectItemModelEvents(rawSwitchFilteredModel);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &FlightModePanel::onModelDataUpdateComplete);
ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu); ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu);
ui->labelName->setToolTip(tr("Popup menu available")); ui->labelName->setToolTip(tr("Popup menu available"));
@ -1361,12 +1361,18 @@ void FlightModePanel::gvSwapData(int idx1, int idx2)
} }
} }
void FlightModePanel::onModelDataAboutToBeUpdated() void FlightModePanel::connectItemModelEvents(const FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModePanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModePanel::onItemModelUpdateComplete);
}
void FlightModePanel::onItemModelAboutToBeUpdated()
{ {
lock = true; lock = true;
} }
void FlightModePanel::onModelDataUpdateComplete() void FlightModePanel::onItemModelUpdateComplete()
{ {
update(); update();
lock = false; lock = false;
@ -1374,11 +1380,14 @@ void FlightModePanel::onModelDataUpdateComplete()
/**********************************************************/ /**********************************************************/
FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
commonItemModels(commonItemModels) sharedItemModels(sharedItemModels)
{ {
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this); rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::MixesContext);
connectItemModelEvents(rawSwitchFilteredModel);
modesCount = firmware->getCapability(FlightModes); modesCount = firmware->getCapability(FlightModes);
QGridLayout * gridLayout = new QGridLayout(this); QGridLayout * gridLayout = new QGridLayout(this);
@ -1403,6 +1412,7 @@ FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralS
FlightModesPanel::~FlightModesPanel() FlightModesPanel::~FlightModesPanel()
{ {
delete rawSwitchFilteredModel;
} }
QString FlightModesPanel::getTabName(int index) QString FlightModesPanel::getTabName(int index)
@ -1431,10 +1441,24 @@ void FlightModesPanel::update()
emit updated(); emit updated();
} }
void FlightModesPanel::connectItemModelEvents(const FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModesPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModesPanel::onItemModelUpdateComplete);
}
void FlightModesPanel::onItemModelAboutToBeUpdated()
{
}
void FlightModesPanel::onItemModelUpdateComplete()
{
}
void FlightModesPanel::updateItemModels() void FlightModesPanel::updateItemModels()
{ {
commonItemModels->update(CommonItemModels::RMO_FLIGHT_MODES); sharedItemModels->update(AbstractItemModel::IMUE_FlightModes);
commonItemModels->update(CommonItemModels::RMO_GLOBAL_VARIABLES); sharedItemModels->update(AbstractItemModel::IMUE_GVars);
} }
void FlightModesPanel::onTabIndexChanged(int index) void FlightModesPanel::onTabIndexChanged(int index)

View file

@ -24,8 +24,8 @@
#include "modeledit.h" #include "modeledit.h"
#include "eeprominterface.h" #include "eeprominterface.h"
class CommonItemModels; class CompoundItemModelFactory;
class RawItemFilteredModel; class FilteredItemModel;
constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode"; constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode";
constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params"; constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params";
@ -41,7 +41,8 @@ class FlightModePanel : public ModelPanel
Q_OBJECT Q_OBJECT
public: public:
FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel); FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware,
FilteredItemModel * rawSwitchFilteredModel);
virtual ~FlightModePanel(); virtual ~FlightModePanel();
virtual void update(); virtual void update();
@ -90,8 +91,8 @@ class FlightModePanel : public ModelPanel
void gvCmPaste(); void gvCmPaste();
void gvCmMoveDown(); void gvCmMoveDown();
void gvCmMoveUp(); void gvCmMoveUp();
void onModelDataAboutToBeUpdated(); void onItemModelAboutToBeUpdated();
void onModelDataUpdateComplete(); void onItemModelUpdateComplete();
private: private:
Ui::FlightMode *ui; Ui::FlightMode *ui;
@ -138,6 +139,7 @@ class FlightModePanel : public ModelPanel
bool gvMoveDownAllowed() const; bool gvMoveDownAllowed() const;
bool gvMoveUpAllowed() const; bool gvMoveUpAllowed() const;
void gvSwapData(int idx1, int idx2); void gvSwapData(int idx1, int idx2);
void connectItemModelEvents(const FilteredItemModel * itemModel);
}; };
class FlightModesPanel : public ModelPanel class FlightModesPanel : public ModelPanel
@ -145,7 +147,7 @@ class FlightModesPanel : public ModelPanel
Q_OBJECT Q_OBJECT
public: public:
FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
virtual ~FlightModesPanel(); virtual ~FlightModesPanel();
public slots: public slots:
@ -157,16 +159,19 @@ class FlightModesPanel : public ModelPanel
private slots: private slots:
void onPhaseNameChanged(); void onPhaseNameChanged();
void onTabIndexChanged(int index); void onTabIndexChanged(int index);
void onItemModelAboutToBeUpdated();
void onItemModelUpdateComplete();
private: private:
QString getTabName(int index); QString getTabName(int index);
int modesCount; int modesCount;
QTabWidget *tabWidget; QTabWidget *tabWidget;
CommonItemModels *commonItemModels; CompoundItemModelFactory *sharedItemModels;
RawItemFilteredModel *rawSwitchFilteredModel; FilteredItemModel *rawSwitchFilteredModel;
QVector<GenericPanel *> panels; QVector<GenericPanel *> panels;
void updateItemModels(); void updateItemModels();
void connectItemModelEvents(const FilteredItemModel * itemModel);
}; };
#endif // _FLIGHTMODES_H_ #endif // _FLIGHTMODES_H_

View file

@ -21,18 +21,16 @@
#include "heli.h" #include "heli.h"
#include "ui_heli.h" #include "ui_heli.h"
#include "helpers.h" #include "helpers.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::Heli), ui(new Ui::Heli)
commonItemModels(commonItemModels)
{ {
ui->setupUi(this); ui->setupUi(this);
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this); rawSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::InputSourceGroups);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &HeliPanel::onModelDataAboutToBeUpdated); connectItemModelEvents(rawSourceFilteredModel);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &HeliPanel::onModelDataUpdateComplete);
connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited())); connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited()));
@ -71,6 +69,7 @@ HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & gener
HeliPanel::~HeliPanel() HeliPanel::~HeliPanel()
{ {
delete ui; delete ui;
delete rawSourceFilteredModel;
} }
void HeliPanel::update() void HeliPanel::update()
@ -118,12 +117,18 @@ void HeliPanel::edited()
} }
} }
void HeliPanel::onModelDataAboutToBeUpdated() void HeliPanel::connectItemModelEvents(const FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &HeliPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &HeliPanel::onItemModelUpdateComplete);
}
void HeliPanel::onItemModelAboutToBeUpdated()
{ {
lock = true; lock = true;
} }
void HeliPanel::onModelDataUpdateComplete() void HeliPanel::onItemModelUpdateComplete()
{ {
update(); update();
lock = false; lock = false;

View file

@ -23,8 +23,8 @@
#include "modeledit.h" #include "modeledit.h"
class CommonItemModels; class CompoundItemModelFactory;
class RawItemFilteredModel; class FilteredItemModel;
namespace Ui { namespace Ui {
class Heli; class Heli;
@ -35,19 +35,19 @@ class HeliPanel : public ModelPanel
Q_OBJECT Q_OBJECT
public: public:
HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
~HeliPanel(); virtual ~HeliPanel();
void update(); void update();
private slots: private slots:
void edited(); void edited();
void onModelDataAboutToBeUpdated(); void onItemModelAboutToBeUpdated();
void onModelDataUpdateComplete(); void onItemModelUpdateComplete();
private: private:
Ui::Heli *ui; Ui::Heli *ui;
CommonItemModels * commonItemModels; FilteredItemModel * rawSourceFilteredModel;
RawItemFilteredModel * rawSourceFilteredModel; void connectItemModelEvents(const FilteredItemModel * itemModel);
}; };
#endif // _HELI_H_ #endif // _HELI_H_

View file

@ -21,25 +21,19 @@
#include "inputs.h" #include "inputs.h"
#include "expodialog.h" #include "expodialog.h"
#include "helpers.h" #include "helpers.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
expoInserted(false), expoInserted(false),
modelPrinter(firmware, generalSettings, model), modelPrinter(firmware, generalSettings, model),
commonItemModels(commonItemModels) sharedItemModels(sharedItemModels),
modelsUpdateCnt(0)
{ {
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), (RawSource::InputSourceGroups & ~ RawSource::NoneGroup & ~RawSource::InputsGroup), this); connectItemModelEvents(AbstractItemModel::IMID_RawSource);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated); connectItemModelEvents(AbstractItemModel::IMID_RawSwitch);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete); connectItemModelEvents(AbstractItemModel::IMID_Curve);
connectItemModelEvents(AbstractItemModel::IMID_GVarRef);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete);
curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this);
connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated);
connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete);
inputsCount = firmware->getCapability(VirtualInputs); inputsCount = firmware->getCapability(VirtualInputs);
if (inputsCount == 0) if (inputsCount == 0)
@ -194,7 +188,7 @@ void InputsPanel::gm_openExpo(int index)
if (firmware->getCapability(VirtualInputs)) if (firmware->getCapability(VirtualInputs))
inputName = model->inputNames[ed.chn]; inputName = model->inputNames[ed.chn];
ExpoDialog *dlg = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel); ExpoDialog *dlg = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, sharedItemModels);
if (dlg->exec()) { if (dlg->exec()) {
model->expoData[index] = ed; model->expoData[index] = ed;
if (firmware->getCapability(VirtualInputs)) if (firmware->getCapability(VirtualInputs))
@ -357,6 +351,9 @@ void InputsPanel::expoOpen(QListWidgetItem *item)
if (!item) if (!item)
item = ExposlistWidget->currentItem(); item = ExposlistWidget->currentItem();
if (item == nullptr)
return;
int idx = item->data(Qt::UserRole).toByteArray().at(0); int idx = item->data(Qt::UserRole).toByteArray().at(0);
if (idx < 0) { if (idx < 0) {
int ch = -idx - 1; int ch = -idx - 1;
@ -374,7 +371,11 @@ void InputsPanel::expoOpen(QListWidgetItem *item)
void InputsPanel::expoAdd() void InputsPanel::expoAdd()
{ {
int index = ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0); QListWidgetItem *item = ExposlistWidget->currentItem();
if (item == nullptr)
return;
int index = item->data(Qt::UserRole).toByteArray().at(0);
if (index < 0) { // if empty then return relevant index if (index < 0) { // if empty then return relevant index
expoOpen(); expoOpen();
@ -579,13 +580,15 @@ bool InputsPanel::cmInputMoveUpAllowed() const
void InputsPanel::cmInputClear() void InputsPanel::cmInputClear()
{ {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all lines for the selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all lines for the selected Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return; return;
for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) { for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) {
ExpoData *ed = &model->expoData[i]; ExpoData *ed = &model->expoData[i];
if ((int)ed->chn == inputIdx) if (!ed->isEmpty()) {
model->removeInput(i); if ((int)ed->chn == inputIdx)
model->removeInput(i);
}
} }
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, inputIdx); model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, inputIdx);
update(); update();
@ -595,15 +598,17 @@ void InputsPanel::cmInputClear()
void InputsPanel::cmInputDelete() void InputsPanel::cmInputDelete()
{ {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete all lines for the selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete all lines for the selected Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return; return;
for (int i = 0; i < CPN_MAX_EXPOS; i++) { for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) {
ExpoData *ed = &model->expoData[i]; ExpoData *ed = &model->expoData[i];
if ((int)ed->chn == inputIdx) if (!ed->isEmpty()) {
model->removeInput(i); if ((int)ed->chn == inputIdx)
else if ((int)ed->chn > inputIdx) model->removeInput(i);
ed->chn--; else if ((int)ed->chn > inputIdx)
ed->chn--;
}
} }
for (int i = inputIdx; i < inputsCount; i++) { for (int i = inputIdx; i < inputsCount; i++) {
@ -730,18 +735,31 @@ int InputsPanel::getInputIndexFromSelected()
return idx; return idx;
} }
void InputsPanel::onModelDataAboutToBeUpdated() void InputsPanel::connectItemModelEvents(const int id)
{ {
lock = true; AbstractDynamicItemModel * itemModel = qobject_cast<AbstractDynamicItemModel *>(sharedItemModels->getItemModel(id));
if (itemModel) {
connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &InputsPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &InputsPanel::onItemModelUpdateComplete);
}
} }
void InputsPanel::onModelDataUpdateComplete() void InputsPanel::onItemModelAboutToBeUpdated()
{ {
update(); lock = true;
lock = false; modelsUpdateCnt++;
}
void InputsPanel::onItemModelUpdateComplete()
{
modelsUpdateCnt--;
if (modelsUpdateCnt < 1) {
update();
lock = false;
}
} }
void InputsPanel::updateItemModels() void InputsPanel::updateItemModels()
{ {
commonItemModels->update(CommonItemModels::RMO_INPUTS); sharedItemModels->update(AbstractItemModel::IMUE_Inputs);
} }

View file

@ -25,8 +25,8 @@
#include "mixerslistwidget.h" #include "mixerslistwidget.h"
#include "modelprinter.h" #include "modelprinter.h"
class CommonItemModels; class CompoundItemModelFactory;
class RawItemFilteredModel; class FilteredItemModel;
constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo"; constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo";
@ -35,7 +35,7 @@ class InputsPanel : public ModelPanel
Q_OBJECT Q_OBJECT
public: public:
InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
virtual ~InputsPanel(); virtual ~InputsPanel();
virtual void update(); virtual void update();
@ -62,8 +62,8 @@ class InputsPanel : public ModelPanel
void cmInputInsert(); void cmInputInsert();
void cmInputMoveDown(); void cmInputMoveDown();
void cmInputMoveUp(); void cmInputMoveUp();
void onModelDataAboutToBeUpdated(); void onItemModelAboutToBeUpdated();
void onModelDataUpdateComplete(); void onItemModelUpdateComplete();
private: private:
bool expoInserted; bool expoInserted;
@ -72,10 +72,8 @@ class InputsPanel : public ModelPanel
ModelPrinter modelPrinter; ModelPrinter modelPrinter;
int selectedIdx; int selectedIdx;
int inputIdx; int inputIdx;
CommonItemModels * commonItemModels; CompoundItemModelFactory *sharedItemModels;
RawItemFilteredModel *rawSourceFilteredModel; int modelsUpdateCnt;
RawItemFilteredModel *rawSwitchFilteredModel;
RawItemFilteredModel *curveFilteredModel;
int getExpoIndex(unsigned int dch); int getExpoIndex(unsigned int dch);
bool gm_insertExpo(int idx); bool gm_insertExpo(int idx);
@ -97,6 +95,7 @@ class InputsPanel : public ModelPanel
int getIndexFromSelected(); int getIndexFromSelected();
int getInputIndexFromSelected(); int getInputIndexFromSelected();
void updateItemModels(); void updateItemModels();
void connectItemModelEvents(const int id);
}; };
#endif // _INPUTS_H_ #endif // _INPUTS_H_

View file

@ -19,25 +19,25 @@
*/ */
#include "logicalswitches.h" #include "logicalswitches.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
#include "helpers.h" #include "helpers.h"
#include <TimerEdit> #include <TimerEdit>
LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
commonItemModels(commonItemModels), sharedItemModels(sharedItemModels),
selectedIndex(0), selectedIndex(0),
modelsUpdateCnt(0) modelsUpdateCnt(0)
{ {
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::LogicalSwitchesContext, this); rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch),
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); RawSwitch::LogicalSwitchesContext);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete); connectItemModelEvents(rawSwitchFilteredModel);
const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup); const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup);
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), srcGroups, this); rawSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), srcGroups);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); connectItemModelEvents(rawSourceFilteredModel);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete);
lsCapability = firmware->getCapability(LogicalSwitches); lsCapability = firmware->getCapability(LogicalSwitches);
lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt); lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt);
@ -161,6 +161,8 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
LogicalSwitchesPanel::~LogicalSwitchesPanel() LogicalSwitchesPanel::~LogicalSwitchesPanel()
{ {
delete rawSourceFilteredModel;
delete rawSwitchFilteredModel;
} }
void LogicalSwitchesPanel::onFunctionChanged() void LogicalSwitchesPanel::onFunctionChanged()
@ -644,16 +646,22 @@ void LogicalSwitchesPanel::swapData(int idx1, int idx2)
void LogicalSwitchesPanel::updateItemModels() void LogicalSwitchesPanel::updateItemModels()
{ {
lock = true; lock = true;
commonItemModels->update(CommonItemModels::RMO_LOGICAL_SWITCHES); sharedItemModels->update(AbstractItemModel::IMUE_LogicalSwitches);
} }
void LogicalSwitchesPanel::onModelDataAboutToBeUpdated() void LogicalSwitchesPanel::connectItemModelEvents(const FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &LogicalSwitchesPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &LogicalSwitchesPanel::onItemModelUpdateComplete);
}
void LogicalSwitchesPanel::onItemModelAboutToBeUpdated()
{ {
lock = true; lock = true;
modelsUpdateCnt++; modelsUpdateCnt++;
} }
void LogicalSwitchesPanel::onModelDataUpdateComplete() void LogicalSwitchesPanel::onItemModelUpdateComplete()
{ {
modelsUpdateCnt--; modelsUpdateCnt--;
if (modelsUpdateCnt < 1) { if (modelsUpdateCnt < 1) {

View file

@ -24,8 +24,8 @@
#include "modeledit.h" #include "modeledit.h"
#include "radiodata.h" #include "radiodata.h"
class CommonItemModels; class CompoundItemModelFactory;
class RawItemFilteredModel; class FilteredItemModel;
class TimerEdit; class TimerEdit;
constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch"; constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch";
@ -35,7 +35,7 @@ class LogicalSwitchesPanel : public ModelPanel
Q_OBJECT Q_OBJECT
public: public:
LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels);
virtual ~LogicalSwitchesPanel(); virtual ~LogicalSwitchesPanel();
virtual void update(); virtual void update();
@ -60,8 +60,8 @@ class LogicalSwitchesPanel : public ModelPanel
void cmInsert(); void cmInsert();
void cmClear(bool prompt = true); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
void onModelDataAboutToBeUpdated(); void onItemModelAboutToBeUpdated();
void onModelDataUpdateComplete(); void onItemModelUpdateComplete();
private: private:
QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES];
@ -74,9 +74,9 @@ class LogicalSwitchesPanel : public ModelPanel
QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES]; QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES];
QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES];
QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES];
CommonItemModels * commonItemModels; CompoundItemModelFactory * sharedItemModels;
RawItemFilteredModel * rawSwitchFilteredModel; FilteredItemModel * rawSwitchFilteredModel;
RawItemFilteredModel * rawSourceFilteredModel; FilteredItemModel * rawSourceFilteredModel;
int selectedIndex; int selectedIndex;
void populateFunctionCB(QComboBox *b); void populateFunctionCB(QComboBox *b);
void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0); void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0);
@ -89,6 +89,7 @@ class LogicalSwitchesPanel : public ModelPanel
bool moveUpAllowed() const; bool moveUpAllowed() const;
int modelsUpdateCnt; int modelsUpdateCnt;
void updateItemModels(); void updateItemModels();
void connectItemModelEvents(const FilteredItemModel * itemModel);
}; };
#endif // _LOGICALSWITCHES_H_ #endif // _LOGICALSWITCHES_H_

View file

@ -21,11 +21,11 @@
#include "mixerdialog.h" #include "mixerdialog.h"
#include "ui_mixerdialog.h" #include "ui_mixerdialog.h"
#include "radiodata.h" #include "radiodata.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
#include "helpers.h" #include "helpers.h"
MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware, MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware,
RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) : CompoundItemModelFactory * sharedItemModels) :
QDialog(parent), QDialog(parent),
ui(new Ui::MixerDialog), ui(new Ui::MixerDialog),
model(model), model(model),
@ -36,6 +36,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
{ {
ui->setupUi(this); ui->setupUi(this);
dialogFilteredItemModels = new FilteredItemModelFactory();
int id;
QRegExp rx(CHAR_FOR_NAMES_REGEX); QRegExp rx(CHAR_FOR_NAMES_REGEX);
QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 }; QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 };
QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 };
@ -45,14 +48,24 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
this->setWindowTitle(tr("DEST -> %1").arg(RawSource(SOURCE_TYPE_CH, md->destCh - 1).toString(&model, &generalSettings))); this->setWindowTitle(tr("DEST -> %1").arg(RawSource(SOURCE_TYPE_CH, md->destCh - 1).toString(&model, &generalSettings)));
ui->sourceCB->setModel(rawSourceModel); id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource),
(RawSource::InputSourceGroups & ~RawSource::NoneGroup) | RawSource::ScriptsGroup),
"RawSource");
ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id));
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue())); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue()));
int limit = firmware->getCapability(OffsetWeight); 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); gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit, 1.0,
gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit); dialogFilteredItemModels->getItemModel(id));
curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model, curveItemModel, this); 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);
ui->MixDR_CB->setChecked(md->noExpo == 0); ui->MixDR_CB->setChecked(md->noExpo == 0);
@ -104,7 +117,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata,
} }
} }
ui->switchesCB->setModel(rawSwitchModel); id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch),
RawSwitch::MixesContext), "RawSwitch");
ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id));
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue())); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue()));
ui->warningCB->setCurrentIndex(md->mixWarn); ui->warningCB->setCurrentIndex(md->mixWarn);
ui->mltpxCB->setCurrentIndex(md->mltpx); ui->mltpxCB->setCurrentIndex(md->mltpx);
@ -150,6 +165,7 @@ MixerDialog::~MixerDialog()
delete ui; delete ui;
delete gvWeightGroup; delete gvWeightGroup;
delete gvOffsetGroup; delete gvOffsetGroup;
delete dialogFilteredItemModels;
} }
void MixerDialog::changeEvent(QEvent *e) void MixerDialog::changeEvent(QEvent *e)

View file

@ -25,7 +25,9 @@
#include "eeprominterface.h" #include "eeprominterface.h"
class GVarGroup; class GVarGroup;
class RawItemFilteredModel; class CompoundItemModelFactory;
class FilteredItemModelFactory;
class CurveRefFilteredFactory;
class CurveReferenceUIManager; class CurveReferenceUIManager;
namespace Ui { namespace Ui {
@ -36,7 +38,7 @@ class MixerDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware, MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware,
RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel); CompoundItemModelFactory * sharedItemModels);
~MixerDialog(); ~MixerDialog();
protected: protected:
@ -61,6 +63,8 @@ class MixerDialog : public QDialog {
GVarGroup * gvOffsetGroup; GVarGroup * gvOffsetGroup;
CurveReferenceUIManager * curveGroup; CurveReferenceUIManager * curveGroup;
QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES];
FilteredItemModelFactory *dialogFilteredItemModels;
CurveRefFilteredFactory *curveRefFilteredItemModels;
}; };
#endif // _MIXERDIALOG_H_ #endif // _MIXERDIALOG_H_

View file

@ -20,26 +20,20 @@
#include "mixes.h" #include "mixes.h"
#include "helpers.h" #include "helpers.h"
#include "rawitemfilteredmodel.h" #include "filtereditemmodels.h"
MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,CommonItemModels * commonItemModels): MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
mixInserted(false), mixInserted(false),
highlightedSource(0), highlightedSource(0),
modelPrinter(firmware, generalSettings, model), modelPrinter(firmware, generalSettings, model),
commonItemModels(commonItemModels) sharedItemModels(sharedItemModels),
modelsUpdateCnt(0)
{ {
rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), ((RawSource::InputSourceGroups | RawSource::ScriptsGroup) & ~ RawSource::NoneGroup), this); connectItemModelEvents(AbstractItemModel::IMID_RawSource);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated); connectItemModelEvents(AbstractItemModel::IMID_RawSwitch);
connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete); connectItemModelEvents(AbstractItemModel::IMID_Curve);
connectItemModelEvents(AbstractItemModel::IMID_GVarRef);
rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated);
connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete);
curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this);
connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated);
connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete);
QGridLayout * mixesLayout = new QGridLayout(this); QGridLayout * mixesLayout = new QGridLayout(this);
@ -189,7 +183,7 @@ void MixesPanel::gm_openMix(int index)
MixData mixd(model->mixData[index]); MixData mixd(model->mixData[index]);
MixerDialog *dlg = new MixerDialog(this, *model, &mixd, generalSettings, firmware, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel); MixerDialog *dlg = new MixerDialog(this, *model, &mixd, generalSettings, firmware, sharedItemModels);
if(dlg->exec()) { if(dlg->exec()) {
model->mixData[index] = mixd; model->mixData[index] = mixd;
emit modified(); emit modified();
@ -360,7 +354,11 @@ void MixesPanel::mixersDuplicate()
void MixesPanel::mixerOpen() void MixesPanel::mixerOpen()
{ {
int idx = mixersListWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0); QListWidgetItem *item = mixersListWidget->currentItem();
if (item == nullptr)
return;
int idx = item->data(Qt::UserRole).toByteArray().at(0);
if(idx < 0) { if(idx < 0) {
int i = -idx; int i = -idx;
idx = getMixerIndex(i); //get mixer index to insert idx = getMixerIndex(i); //get mixer index to insert
@ -377,7 +375,11 @@ void MixesPanel::mixerOpen()
void MixesPanel::mixerHighlight() void MixesPanel::mixerHighlight()
{ {
int idx = mixersListWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0); QListWidgetItem *item = mixersListWidget->currentItem();
if (item == nullptr)
return;
int idx = item->data(Qt::UserRole).toByteArray().at(0);
int dest; int dest;
if (idx<0) { if (idx<0) {
dest = -idx; dest = -idx;
@ -545,13 +547,26 @@ void MixesPanel::clearMixes()
} }
} }
void MixesPanel::onModelDataAboutToBeUpdated() void MixesPanel::connectItemModelEvents(const int id)
{ {
lock = true; AbstractDynamicItemModel * itemModel = qobject_cast<AbstractDynamicItemModel *>(sharedItemModels->getItemModel(id));
if (itemModel) {
connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &MixesPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &MixesPanel::onItemModelUpdateComplete);
}
} }
void MixesPanel::onModelDataUpdateComplete() void MixesPanel::onItemModelAboutToBeUpdated()
{ {
update(); lock = true;
lock = false; modelsUpdateCnt++;
}
void MixesPanel::onItemModelUpdateComplete()
{
modelsUpdateCnt--;
if (modelsUpdateCnt < 1) {
update();
lock = false;
}
} }

Some files were not shown because too many files have changed in this diff Show more