mirror of
https://github.com/opentx/opentx.git
synced 2025-07-24 00:35:18 +03:00
[Companion] Show custom control names throughout the UI (& internal refactoring) (#4693)
* [Companion] Introduce new Boards class to further consolidate hardware metadata and remove some globals. * [Companion] * RawSource::toString() and RawSwitch::toString() can now return custom hardware names (if given a GeneralSettings object) for the following types (respectively): SOURCE_TYPE_STICK, SOURCE_TYPE_SWITCH, SWITCH_TYPE_SWITCH, & SWITCH_TYPE_MULTIPOS_POT; * RawSource::isPot() and isSlider() can now return their own index position in potConfig[]/sliderConfig[]; * Switch indicator strings can be localized if necessary. * [Companion] Refactor model printers to use new RawSource/RawSwitch capabilities; Simplify model-to-printer mapping scheme in multimodelprinter; Use const ModelData pointer. * [Companion] Refactor how RawSource and RawSwitch selection combo boxes are populated, using cache-able data models instead of direct manipulation; Refactor some other Helpers function into their own namespace. * Cosmetics & forgotten qualifier.
This commit is contained in:
parent
627347a48c
commit
f5ab145d2f
40 changed files with 886 additions and 747 deletions
|
@ -21,92 +21,156 @@
|
|||
#include "boards.h"
|
||||
#include "macros.h"
|
||||
|
||||
// TODO remove all those constants
|
||||
// Update: These are now all only used within this class.
|
||||
// External access is only via getEEpromSize() and getFlashSize()
|
||||
|
||||
#define EESIZE_STOCK 2048
|
||||
#define EESIZE_M128 4096
|
||||
#define EESIZE_GRUVIN9X 4096
|
||||
#define EESIZE_TARANIS (32*1024)
|
||||
#define EESIZE_SKY9X (128*4096)
|
||||
#define EESIZE_9XRPRO (128*4096)
|
||||
#define EESIZE_MAX EESIZE_9XRPRO
|
||||
|
||||
// getFlashSize() (and these macros) is only used by radiointerface::getDfuArgs (perhaps can find a better way?)
|
||||
#define FSIZE_STOCK (64*1024)
|
||||
#define FSIZE_M128 (128*1024)
|
||||
#define FSIZE_GRUVIN9X (256*1024)
|
||||
#define FSIZE_TARANIS (512*1024)
|
||||
#define FSIZE_SKY9X (256*1024)
|
||||
#define FSIZE_9XRPRO (512*1024)
|
||||
#define FSIZE_HORUS (2048*1024)
|
||||
#define FSIZE_MAX FSIZE_HORUS
|
||||
|
||||
using namespace Board;
|
||||
|
||||
int getEEpromSize(Board::Type board)
|
||||
void Boards::setBoardType(const Type & board)
|
||||
{
|
||||
if (board >= BOARD_UNKNOWN && board < BOARD_ENUM_COUNT)
|
||||
m_boardType = board;
|
||||
else
|
||||
m_boardType = BOARD_UNKNOWN;
|
||||
}
|
||||
|
||||
const int Boards::getEEpromSize(Board::Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case Board::BOARD_STOCK:
|
||||
case BOARD_STOCK:
|
||||
return EESIZE_STOCK;
|
||||
case Board::BOARD_M128:
|
||||
case BOARD_M128:
|
||||
return EESIZE_M128;
|
||||
case Board::BOARD_MEGA2560:
|
||||
case Board::BOARD_GRUVIN9X:
|
||||
case BOARD_MEGA2560:
|
||||
case BOARD_GRUVIN9X:
|
||||
return EESIZE_GRUVIN9X;
|
||||
case Board::BOARD_SKY9X:
|
||||
case BOARD_SKY9X:
|
||||
return EESIZE_SKY9X;
|
||||
case Board::BOARD_9XRPRO:
|
||||
case Board::BOARD_AR9X:
|
||||
case BOARD_9XRPRO:
|
||||
case BOARD_AR9X:
|
||||
return EESIZE_9XRPRO;
|
||||
case Board::BOARD_TARANIS_X7:
|
||||
case Board::BOARD_TARANIS_X9D:
|
||||
case Board::BOARD_TARANIS_X9DP:
|
||||
case Board::BOARD_TARANIS_X9E:
|
||||
case Board::BOARD_FLAMENCO:
|
||||
case BOARD_TARANIS_X7:
|
||||
case BOARD_TARANIS_X9D:
|
||||
case BOARD_TARANIS_X9DP:
|
||||
case BOARD_TARANIS_X9E:
|
||||
case BOARD_FLAMENCO:
|
||||
return EESIZE_TARANIS;
|
||||
case BOARD_UNKNOWN:
|
||||
return EESIZE_MAX;
|
||||
default:
|
||||
return 0; // unlimited
|
||||
}
|
||||
}
|
||||
|
||||
Board::SwitchInfo getSwitchInfo(Board::Type board, unsigned index)
|
||||
const int Boards::getFlashSize(Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case BOARD_STOCK:
|
||||
return FSIZE_STOCK;
|
||||
case BOARD_M128:
|
||||
return FSIZE_M128;
|
||||
case BOARD_MEGA2560:
|
||||
case BOARD_GRUVIN9X:
|
||||
return FSIZE_GRUVIN9X;
|
||||
case BOARD_SKY9X:
|
||||
return FSIZE_SKY9X;
|
||||
case BOARD_9XRPRO:
|
||||
case BOARD_AR9X:
|
||||
return FSIZE_9XRPRO;
|
||||
case BOARD_TARANIS_X9D:
|
||||
case BOARD_TARANIS_X9DP:
|
||||
case BOARD_TARANIS_X9E:
|
||||
case BOARD_FLAMENCO:
|
||||
return FSIZE_TARANIS;
|
||||
case BOARD_X12S:
|
||||
case BOARD_X10:
|
||||
return FSIZE_HORUS;
|
||||
case BOARD_UNKNOWN:
|
||||
return FSIZE_MAX;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const SwitchInfo Boards::getSwitchInfo(Board::Type board, unsigned index)
|
||||
{
|
||||
if (IS_TARANIS_X7(board)) {
|
||||
const Board::SwitchInfo switches[] = {
|
||||
{Board::SWITCH_3POS, "SA"},
|
||||
{Board::SWITCH_3POS, "SB"},
|
||||
{Board::SWITCH_3POS, "SC"},
|
||||
{Board::SWITCH_3POS, "SD"},
|
||||
{Board::SWITCH_2POS, "SF"},
|
||||
{Board::SWITCH_TOGGLE, "SH"}
|
||||
{SWITCH_3POS, "SA"},
|
||||
{SWITCH_3POS, "SB"},
|
||||
{SWITCH_3POS, "SC"},
|
||||
{SWITCH_3POS, "SD"},
|
||||
{SWITCH_2POS, "SF"},
|
||||
{SWITCH_TOGGLE, "SH"}
|
||||
};
|
||||
if (index < DIM(switches))
|
||||
return switches[index];
|
||||
}
|
||||
else if (IS_HORUS_OR_TARANIS(board)) {
|
||||
const Board::SwitchInfo switches[] = {
|
||||
{Board::SWITCH_3POS, "SA"},
|
||||
{Board::SWITCH_3POS, "SB"},
|
||||
{Board::SWITCH_3POS, "SC"},
|
||||
{Board::SWITCH_3POS, "SD"},
|
||||
{Board::SWITCH_3POS, "SE"},
|
||||
{Board::SWITCH_2POS, "SF"},
|
||||
{Board::SWITCH_3POS, "SG"},
|
||||
{Board::SWITCH_TOGGLE, "SH"},
|
||||
{Board::SWITCH_3POS, "SI"},
|
||||
{Board::SWITCH_3POS, "SJ"},
|
||||
{Board::SWITCH_3POS, "SK"},
|
||||
{Board::SWITCH_3POS, "SL"},
|
||||
{Board::SWITCH_3POS, "SM"},
|
||||
{Board::SWITCH_3POS, "SN"},
|
||||
{Board::SWITCH_3POS, "SO"},
|
||||
{Board::SWITCH_3POS, "SP"},
|
||||
{Board::SWITCH_3POS, "SQ"},
|
||||
{Board::SWITCH_3POS, "SR"}
|
||||
{SWITCH_3POS, "SA"},
|
||||
{SWITCH_3POS, "SB"},
|
||||
{SWITCH_3POS, "SC"},
|
||||
{SWITCH_3POS, "SD"},
|
||||
{SWITCH_3POS, "SE"},
|
||||
{SWITCH_2POS, "SF"},
|
||||
{SWITCH_3POS, "SG"},
|
||||
{SWITCH_TOGGLE, "SH"},
|
||||
{SWITCH_3POS, "SI"},
|
||||
{SWITCH_3POS, "SJ"},
|
||||
{SWITCH_3POS, "SK"},
|
||||
{SWITCH_3POS, "SL"},
|
||||
{SWITCH_3POS, "SM"},
|
||||
{SWITCH_3POS, "SN"},
|
||||
{SWITCH_3POS, "SO"},
|
||||
{SWITCH_3POS, "SP"},
|
||||
{SWITCH_3POS, "SQ"},
|
||||
{SWITCH_3POS, "SR"}
|
||||
};
|
||||
if (index < DIM(switches))
|
||||
return switches[index];
|
||||
}
|
||||
else {
|
||||
const Board::SwitchInfo switches[] = {
|
||||
{Board::SWITCH_2POS, "THR"},
|
||||
{Board::SWITCH_2POS, "RUD"},
|
||||
{Board::SWITCH_2POS, "ELE"},
|
||||
{Board::SWITCH_3POS, "3POS"},
|
||||
{Board::SWITCH_2POS, "AIL"},
|
||||
{Board::SWITCH_2POS, "GEA"},
|
||||
{Board::SWITCH_TOGGLE, "TRN"}
|
||||
{SWITCH_2POS, "THR"},
|
||||
{SWITCH_2POS, "RUD"},
|
||||
{SWITCH_2POS, "ELE"},
|
||||
{SWITCH_3POS, "3POS"},
|
||||
{SWITCH_2POS, "AIL"},
|
||||
{SWITCH_2POS, "GEA"},
|
||||
{SWITCH_TOGGLE, "TRN"}
|
||||
};
|
||||
if (index < DIM(switches))
|
||||
return switches[index];
|
||||
}
|
||||
|
||||
return {Board::SWITCH_NOT_AVAILABLE, "???"};
|
||||
return {SWITCH_NOT_AVAILABLE, "???"};
|
||||
}
|
||||
|
||||
int getBoardCapability(Board::Type board, Board::Capability capability)
|
||||
const int Boards::getCapability(Board::Type board, Board::Capability capability)
|
||||
{
|
||||
switch (capability) {
|
||||
case Sticks:
|
||||
return 4;
|
||||
case Pots:
|
||||
if (IS_HORUS(board))
|
||||
return 3;
|
||||
|
@ -153,8 +217,61 @@ int getBoardCapability(Board::Type board, Board::Capability capability)
|
|||
else
|
||||
return 4;
|
||||
case NumTrimSwitches:
|
||||
return getBoardCapability(board, NumTrims) * 2;
|
||||
return getCapability(board, NumTrims) * 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QString Boards::getAxisName(int index)
|
||||
{
|
||||
const QString axes[] = {
|
||||
QObject::tr("Left Horizontal"),
|
||||
QObject::tr("Left Vertical"),
|
||||
QObject::tr("Right Vertical"),
|
||||
QObject::tr("Right Horizontal"),
|
||||
QObject::tr("Aux. 1"),
|
||||
QObject::tr("Aux. 2"),
|
||||
};
|
||||
if (index < (int)DIM(axes))
|
||||
return axes[index];
|
||||
else
|
||||
return QObject::tr("Unknown");
|
||||
}
|
||||
|
||||
/* Currently unused
|
||||
|
||||
const QString Boards::getBoardName(Board::Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case BOARD_STOCK:
|
||||
return "9X";
|
||||
case BOARD_M128:
|
||||
return "9X128";
|
||||
case BOARD_GRUVIN9X:
|
||||
return "Gruvin9x";
|
||||
case BOARD_MEGA2560:
|
||||
return "MEGA2560";
|
||||
case BOARD_TARANIS_X7:
|
||||
return "Taranis X7";
|
||||
case BOARD_TARANIS_X9D:
|
||||
return "Taranis X9D";
|
||||
case BOARD_TARANIS_X9DP:
|
||||
return "Taranis X9D+";
|
||||
case BOARD_TARANIS_X9E:
|
||||
return "Taranis X9E";
|
||||
case BOARD_SKY9X:
|
||||
return "Sky9x";
|
||||
case BOARD_9XRPRO:
|
||||
return "9XR-PRO";
|
||||
case BOARD_AR9X:
|
||||
return "AR9X";
|
||||
case BOARD_X12S:
|
||||
return "Horus";
|
||||
case BOARD_X10:
|
||||
return "X10";
|
||||
default:
|
||||
return QObject::tr("Unknown");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -21,13 +21,17 @@
|
|||
#ifndef _BOARDS_H_
|
||||
#define _BOARDS_H_
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
// TODO create a Board class with all these functions
|
||||
|
||||
namespace Board {
|
||||
|
||||
enum Type
|
||||
{
|
||||
BOARD_STOCK,
|
||||
BOARD_UNKNOWN = -1,
|
||||
BOARD_STOCK = 0,
|
||||
BOARD_M128,
|
||||
BOARD_MEGA2560,
|
||||
BOARD_GRUVIN9X,
|
||||
|
@ -41,7 +45,7 @@ namespace Board {
|
|||
BOARD_FLAMENCO,
|
||||
BOARD_X12S,
|
||||
BOARD_X10,
|
||||
BOARD_UNKNOWN = -1
|
||||
BOARD_ENUM_COUNT
|
||||
};
|
||||
|
||||
enum PotType
|
||||
|
@ -66,6 +70,14 @@ namespace Board {
|
|||
SWITCH_3POS
|
||||
};
|
||||
|
||||
enum StickAxes {
|
||||
STICK_AXIS_LH = 0,
|
||||
STICK_AXIS_LV,
|
||||
STICK_AXIS_RV,
|
||||
STICK_AXIS_RH,
|
||||
STICK_AXIS_COUNT
|
||||
};
|
||||
|
||||
enum TrimAxes {
|
||||
TRIM_AXIS_LH = 0,
|
||||
TRIM_AXIS_LV,
|
||||
|
@ -73,9 +85,10 @@ namespace Board {
|
|||
TRIM_AXIS_RH,
|
||||
TRIM_AXIS_T5,
|
||||
TRIM_AXIS_T6,
|
||||
TRIM_AXIS_COUNT
|
||||
};
|
||||
|
||||
enum TrimSwitchIndex
|
||||
enum TrimSwitches
|
||||
{
|
||||
TRIM_SW_LH_DEC,
|
||||
TRIM_SW_LH_INC,
|
||||
|
@ -89,10 +102,11 @@ namespace Board {
|
|||
TRIM_SW_T5_INC,
|
||||
TRIM_SW_T6_DEC,
|
||||
TRIM_SW_T6_INC,
|
||||
TRIM_SW_ENUM_END
|
||||
TRIM_SW_COUNT
|
||||
};
|
||||
|
||||
enum Capability {
|
||||
Sticks,
|
||||
Pots,
|
||||
Sliders,
|
||||
MouseAnalogs,
|
||||
|
@ -105,7 +119,7 @@ namespace Board {
|
|||
struct SwitchInfo
|
||||
{
|
||||
SwitchType config;
|
||||
const char * name;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct SwitchPosition {
|
||||
|
@ -120,29 +134,38 @@ namespace Board {
|
|||
|
||||
}
|
||||
|
||||
// TODO remove all those constants
|
||||
#define EESIZE_STOCK 2048
|
||||
#define EESIZE_M128 4096
|
||||
#define EESIZE_GRUVIN9X 4096
|
||||
#define EESIZE_TARANIS (32*1024)
|
||||
#define EESIZE_SKY9X (128*4096)
|
||||
#define EESIZE_9XRPRO (128*4096)
|
||||
#define EESIZE_MAX EESIZE_9XRPRO
|
||||
class Boards
|
||||
{
|
||||
public:
|
||||
|
||||
// TODO remove all those constants
|
||||
#define FSIZE_STOCK (64*1024)
|
||||
#define FSIZE_M128 (128*1024)
|
||||
#define FSIZE_GRUVIN9X (256*1024)
|
||||
#define FSIZE_TARANIS (512*1024)
|
||||
#define FSIZE_SKY9X (256*1024)
|
||||
#define FSIZE_9XRPRO (512*1024)
|
||||
#define FSIZE_HORUS (2048*1024)
|
||||
#define FSIZE_MAX FSIZE_HORUS
|
||||
Boards(Board::Type board)
|
||||
{
|
||||
setBoardType(board);
|
||||
}
|
||||
|
||||
int getEEpromSize(Board::Type board);
|
||||
Board::SwitchInfo getSwitchInfo(Board::Type board, unsigned index);
|
||||
void setBoardType(const Board::Type & board);
|
||||
Board::Type getBoardType() const { return m_boardType; }
|
||||
|
||||
int getBoardCapability(Board::Type board, Board::Capability capability);
|
||||
const int getEEpromSize() { return getEEpromSize(m_boardType); }
|
||||
const int getFlashSize() { return getFlashSize(m_boardType); }
|
||||
const Board::SwitchInfo getSwitchInfo(unsigned index) { return getSwitchInfo(m_boardType, index); }
|
||||
const int getCapability(Board::Capability capability) { return getCapability(m_boardType, capability); }
|
||||
|
||||
static const int getEEpromSize(Board::Type board);
|
||||
static const int getFlashSize(Board::Type board);
|
||||
static const Board::SwitchInfo getSwitchInfo(Board::Type board, unsigned index);
|
||||
static const int getCapability(Board::Type board, Board::Capability capability);
|
||||
static const QString getAxisName(int index);
|
||||
|
||||
protected:
|
||||
|
||||
Board::Type m_boardType;
|
||||
};
|
||||
|
||||
// temporary aliases for transition period, use Boards class instead.
|
||||
#define getBoardCapability(b__, c__) Boards::getCapability(b__, c__)
|
||||
#define getEEpromSize(b__) Boards::getEEpromSize(b__)
|
||||
#define getSwitchInfo(b__, i__) Boards::getSwitchInfo(b__, i__)
|
||||
|
||||
#define IS_9X(board) (board==Board::BOARD_STOCK || board==Board::BOARD_M128)
|
||||
#define IS_STOCK(board) (board==Board::BOARD_STOCK)
|
||||
|
|
|
@ -30,18 +30,22 @@
|
|||
#define CPN_MAX_CURVES 32
|
||||
#define CPN_MAX_POINTS 17
|
||||
#define CPN_MAX_GVARS 9
|
||||
#define CPN_MAX_ENCODERS 2
|
||||
#define CPN_MAX_ENCODERS 2 // rotary encoders
|
||||
#define CPN_MAX_CHNOUT 32 // number of real output channels
|
||||
#define CPN_MAX_CSW 64 // number of custom switches
|
||||
#define CPN_MAX_CUSTOM_FUNCTIONS 64 // number of functions assigned to switches
|
||||
#define CPN_MAX_MODULES 2
|
||||
#define CPN_MAX_STICKS 4
|
||||
#define CPN_MAX_AUX_TRIMS 2
|
||||
#define CPN_MAX_POTS 8
|
||||
#define CPN_MAX_STICKS Board::STICK_AXIS_COUNT
|
||||
#define CPN_MAX_TRIMS Board::TRIM_AXIS_COUNT
|
||||
#define CPN_MAX_TRIM_SW Board::TRIM_SW_COUNT
|
||||
#define CPN_MAX_KNOBS 4
|
||||
#define CPN_MAX_SLIDERS 4
|
||||
#define CPN_MAX_POTS (CPN_MAX_KNOBS + CPN_MAX_SLIDERS)
|
||||
#define CPN_MAX_CYC 3
|
||||
#define CPN_MAX_SWITCHES 32
|
||||
#define CPN_MAX_KEYS 32
|
||||
#define CPN_MAX_MOUSE_ANALOGS 2
|
||||
#define CPN_MAX_ANALOGS (CPN_MAX_STICKS + CPN_MAX_POTS + CPN_MAX_MOUSE_ANALOGS)
|
||||
|
||||
#define CPN_STR_FILES QT_TRANSLATE_NOOP("CompanionMacros", "files")
|
||||
#define CPN_STR_RAD_MOD_SETTINGS QT_TRANSLATE_NOOP("CompanionMacros", "Radio and Models settings")
|
||||
|
@ -57,9 +61,9 @@
|
|||
#define EEPE_EEPROM_FILE_HEADER "EEPE EEPROM FILE"
|
||||
#define EEPE_MODEL_FILE_HEADER "EEPE MODEL FILE"
|
||||
|
||||
const char * const ARROW_LEFT = "\xE2\x86\x90";
|
||||
const char * const ARROW_UP = "\xE2\x86\x91";
|
||||
const char * const ARROW_RIGHT = "\xE2\x86\x92";
|
||||
const char * const ARROW_DOWN = "\xE2\x86\x93";
|
||||
#define CPN_STR_SW_INDICATOR_UP QT_TRANSLATE_NOOP("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
|
||||
#define CPN_STR_SW_INDICATOR_DN QT_TRANSLATE_NOOP("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.
|
||||
#define CPN_STR_SW_INDICATOR_NEUT QT_TRANSLATE_NOOP("RawSwitch", "-") // Switch neutral (middle) position indicator.
|
||||
#define CPN_STR_SW_INDICATOR_REV QT_TRANSLATE_NOOP("RawSwitch", "!") // Switch reversed logic (NOT) indicator.
|
||||
|
||||
#endif // _CONSTANTS_H_
|
||||
|
|
|
@ -500,7 +500,12 @@ QString RotaryEncoderString(int index)
|
|||
return CHECK_IN_ARRAY(rotary, index);
|
||||
}
|
||||
|
||||
QString RawSource::toString(const ModelData * model) const
|
||||
|
||||
/*
|
||||
* RawSource
|
||||
*/
|
||||
|
||||
QString RawSource::toString(const ModelData * model, const GeneralSettings * const generalSettings) const
|
||||
{
|
||||
static const QString trims[] = {
|
||||
QObject::tr("TrmR"), QObject::tr("TrmE"), QObject::tr("TrmT"), QObject::tr("TrmA"), QObject::tr("Trm5"), QObject::tr("Trm6")
|
||||
|
@ -529,69 +534,109 @@ QString RawSource::toString(const ModelData * model) const
|
|||
return QObject::tr("----");
|
||||
}
|
||||
|
||||
QString result;
|
||||
int genAryIdx = 0;
|
||||
switch (type) {
|
||||
case SOURCE_TYPE_VIRTUAL_INPUT:
|
||||
{
|
||||
QString result = QObject::tr("[I%1]").arg(index+1);
|
||||
if (model && strlen(model->inputNames[index]) > 0) {
|
||||
result = QObject::tr("[I%1]").arg(index+1);
|
||||
if (model)
|
||||
result += QString(model->inputNames[index]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
case SOURCE_TYPE_LUA_OUTPUT:
|
||||
return QObject::tr("LUA%1%2").arg(index/16+1).arg(QChar('a'+index%16));
|
||||
|
||||
case SOURCE_TYPE_STICK:
|
||||
return getCurrentFirmware()->getAnalogInputName(index);
|
||||
if (generalSettings) {
|
||||
if (isPot(&genAryIdx))
|
||||
result = QString(generalSettings->potName[genAryIdx]);
|
||||
else if (isSlider(&genAryIdx))
|
||||
result = QString(generalSettings->sliderName[genAryIdx]);
|
||||
else
|
||||
result = QString(generalSettings->stickName[index]);
|
||||
}
|
||||
if (result.isEmpty())
|
||||
result = getCurrentFirmware()->getAnalogInputName(index);;
|
||||
return result;
|
||||
|
||||
case SOURCE_TYPE_TRIM:
|
||||
return CHECK_IN_ARRAY(trims, index);
|
||||
case SOURCE_TYPE_ROTARY_ENCODER:
|
||||
return RotaryEncoderString(index);
|
||||
case SOURCE_TYPE_MAX:
|
||||
return QObject::tr("MAX");
|
||||
|
||||
case SOURCE_TYPE_SWITCH:
|
||||
return getSwitchInfo(getCurrentBoard(), index).name;
|
||||
if (generalSettings)
|
||||
result = QString(generalSettings->switchName[index]);
|
||||
if (result.isEmpty())
|
||||
result = getSwitchInfo(getCurrentBoard(), index).name;
|
||||
return result;
|
||||
|
||||
case SOURCE_TYPE_CUSTOM_SWITCH:
|
||||
return QObject::tr("L%1").arg(index+1);
|
||||
|
||||
case SOURCE_TYPE_CYC:
|
||||
return QObject::tr("CYC%1").arg(index+1);
|
||||
|
||||
case SOURCE_TYPE_PPM:
|
||||
return QObject::tr("TR%1").arg(index+1);
|
||||
|
||||
case SOURCE_TYPE_CH:
|
||||
return QObject::tr("CH%1").arg(index+1);
|
||||
|
||||
case SOURCE_TYPE_SPECIAL:
|
||||
return CHECK_IN_ARRAY(special, index);
|
||||
|
||||
case SOURCE_TYPE_TELEMETRY:
|
||||
if (IS_ARM(getCurrentBoard())) {
|
||||
div_t qr = div(index, 3);
|
||||
QString result = QString(model ? model->sensorData[qr.quot].label : QString("[T%1]").arg(qr.quot+1));
|
||||
if (qr.rem) result += qr.rem == 1 ? "-" : "+";
|
||||
result = model ? QString(model->sensorData[qr.quot].label) : QString("[T%1]").arg(qr.quot+1);
|
||||
if (qr.rem)
|
||||
result += (qr.rem == 1 ? "-" : "+");
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return CHECK_IN_ARRAY(telemetry, index);
|
||||
}
|
||||
|
||||
case SOURCE_TYPE_GVAR:
|
||||
return QObject::tr("GV%1").arg(index+1);
|
||||
|
||||
default:
|
||||
return QObject::tr("----");
|
||||
}
|
||||
}
|
||||
|
||||
bool RawSource::isPot() const
|
||||
bool RawSource::isPot(int * potsIndex) const
|
||||
{
|
||||
return (type == SOURCE_TYPE_STICK &&
|
||||
index >= CPN_MAX_STICKS &&
|
||||
index < CPN_MAX_STICKS + getBoardCapability(getCurrentBoard(), Board::Pots));
|
||||
if (type == SOURCE_TYPE_STICK &&
|
||||
index >= getBoardCapability(getCurrentBoard(), Board::Sticks) &&
|
||||
index < getBoardCapability(getCurrentBoard(), Board::Sticks) + getBoardCapability(getCurrentBoard(), Board::Pots)) {
|
||||
if (potsIndex)
|
||||
*potsIndex = index - getBoardCapability(getCurrentBoard(), Board::Sticks);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RawSource::isSlider() const
|
||||
bool RawSource::isSlider(int * sliderIndex) const
|
||||
{
|
||||
return (type == SOURCE_TYPE_STICK &&
|
||||
index >= CPN_MAX_STICKS + getBoardCapability(getCurrentBoard(), Board::Pots) &&
|
||||
index < CPN_MAX_STICKS + getBoardCapability(getCurrentBoard(), Board::Pots) + getBoardCapability(getCurrentBoard(), Board::Sliders));
|
||||
if (type == SOURCE_TYPE_STICK &&
|
||||
index >= getBoardCapability(getCurrentBoard(), Board::Sticks) + getBoardCapability(getCurrentBoard(), Board::Pots) &&
|
||||
index < getBoardCapability(getCurrentBoard(), Board::Sticks) + getBoardCapability(getCurrentBoard(), Board::Pots) + getBoardCapability(getCurrentBoard(), Board::Sliders)) {
|
||||
if (sliderIndex)
|
||||
*sliderIndex = index - getBoardCapability(getCurrentBoard(), Board::Sticks) - getBoardCapability(getCurrentBoard(), Board::Pots);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString RawSwitch::toString(Board::Type board) const
|
||||
/*
|
||||
* RawSwitch
|
||||
*/
|
||||
|
||||
QString RawSwitch::toString(Board::Type board, const GeneralSettings * const generalSettings) const
|
||||
{
|
||||
if (board == Board::BOARD_UNKNOWN) {
|
||||
board = getCurrentBoard();
|
||||
|
@ -607,12 +652,6 @@ QString RawSwitch::toString(Board::Type board) const
|
|||
QObject::tr("FM0"), QObject::tr("FM1"), QObject::tr("FM2"), QObject::tr("FM3"), QObject::tr("FM4"), QObject::tr("FM5"), QObject::tr("FM6"), QObject::tr("FM7"), QObject::tr("FM8")
|
||||
};
|
||||
|
||||
static const QString multiposPots[] = {
|
||||
QObject::tr("S11"), QObject::tr("S12"), QObject::tr("S13"), QObject::tr("S14"), QObject::tr("S15"), QObject::tr("S16"),
|
||||
QObject::tr("S21"), QObject::tr("S22"), QObject::tr("S23"), QObject::tr("S24"), QObject::tr("S25"), QObject::tr("S26"),
|
||||
QObject::tr("S31"), QObject::tr("S32"), QObject::tr("S33"), QObject::tr("S34"), QObject::tr("S35"), QObject::tr("S36")
|
||||
};
|
||||
|
||||
static const QString trimsSwitches[] = {
|
||||
QObject::tr("RudTrim Left"), QObject::tr("RudTrim Right"),
|
||||
QObject::tr("EleTrim Down"), QObject::tr("EleTrim Up"),
|
||||
|
@ -631,47 +670,77 @@ QString RawSwitch::toString(Board::Type board) const
|
|||
QObject::tr("THs"), QObject::tr("TH%"), QObject::tr("THt")
|
||||
};
|
||||
|
||||
const QStringList directionIndicators = QStringList()
|
||||
<< CPN_STR_SW_INDICATOR_UP
|
||||
<< CPN_STR_SW_INDICATOR_NEUT
|
||||
<< CPN_STR_SW_INDICATOR_DN;
|
||||
|
||||
if (index < 0) {
|
||||
return QString("!") + RawSwitch(type, -index).toString();
|
||||
return CPN_STR_SW_INDICATOR_REV % RawSwitch(type, -index).toString(board, generalSettings);
|
||||
}
|
||||
else {
|
||||
QString swName;
|
||||
div_t qr;
|
||||
switch(type) {
|
||||
case SWITCH_TYPE_SWITCH:
|
||||
if (IS_HORUS_OR_TARANIS(board)) {
|
||||
div_t qr = div(index-1, 3);
|
||||
Board::SwitchInfo switchInfo = getSwitchInfo(board, qr.quot);
|
||||
const char * positions[] = { ARROW_UP, "-", ARROW_DOWN };
|
||||
return QString(switchInfo.name) + QString(positions[qr.rem]);
|
||||
qr = div(index-1, 3);
|
||||
if (generalSettings)
|
||||
swName = QString(generalSettings->switchName[qr.quot]);
|
||||
if (swName.isEmpty())
|
||||
swName = getSwitchInfo(board, qr.quot).name;
|
||||
return swName + directionIndicators.at(qr.rem < directionIndicators.size() ? qr.rem : 1);
|
||||
}
|
||||
else {
|
||||
return CHECK_IN_ARRAY(switches9X, index - 1);
|
||||
}
|
||||
|
||||
case SWITCH_TYPE_VIRTUAL:
|
||||
return QObject::tr("L%1").arg(index);
|
||||
|
||||
case SWITCH_TYPE_MULTIPOS_POT:
|
||||
return CHECK_IN_ARRAY(multiposPots, index-1);
|
||||
qr = div(index - 1, getCurrentFirmware()->getCapability(MultiposPotsPositions));
|
||||
if (generalSettings && qr.quot < (int)DIM(generalSettings->potConfig))
|
||||
swName = QString(generalSettings->potName[qr.quot]);
|
||||
if (swName.isEmpty())
|
||||
swName = getCurrentFirmware()->getAnalogInputName(qr.quot + getBoardCapability(board, Board::Sticks));;
|
||||
return swName + "_" + QString::number(qr.rem + 1);
|
||||
|
||||
case SWITCH_TYPE_TRIM:
|
||||
return CHECK_IN_ARRAY(trimsSwitches, index-1);
|
||||
|
||||
case SWITCH_TYPE_ROTARY_ENCODER:
|
||||
return CHECK_IN_ARRAY(rotaryEncoders, index-1);
|
||||
|
||||
case SWITCH_TYPE_ON:
|
||||
return QObject::tr("ON");
|
||||
|
||||
case SWITCH_TYPE_OFF:
|
||||
return QObject::tr("OFF");
|
||||
|
||||
case SWITCH_TYPE_ONE:
|
||||
return QObject::tr("One");
|
||||
|
||||
case SWITCH_TYPE_FLIGHT_MODE:
|
||||
return CHECK_IN_ARRAY(flightModes, index-1);
|
||||
|
||||
case SWITCH_TYPE_NONE:
|
||||
return QObject::tr("----");
|
||||
|
||||
case SWITCH_TYPE_TIMER_MODE:
|
||||
return CHECK_IN_ARRAY(timerModes, index);
|
||||
|
||||
default:
|
||||
return QObject::tr("???");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CurveReference
|
||||
*/
|
||||
|
||||
QString CurveReference::toString() const
|
||||
{
|
||||
if (value == 0) {
|
||||
|
@ -1063,7 +1132,7 @@ GeneralSettings::GeneralSettings()
|
|||
contrast = 25;
|
||||
vBatWarn = 90;
|
||||
|
||||
for (int i=0; i<CPN_MAX_STICKS+CPN_MAX_POTS; ++i) {
|
||||
for (int i=0; i < CPN_MAX_ANALOGS; ++i) {
|
||||
calibMid[i] = 0x200;
|
||||
calibSpanNeg[i] = 0x180;
|
||||
calibSpanPos[i] = 0x180;
|
||||
|
@ -1073,7 +1142,7 @@ GeneralSettings::GeneralSettings()
|
|||
Board::Type board = firmware->getBoard();
|
||||
|
||||
for (int i=0; i<getBoardCapability(board, Board::FactoryInstalledSwitches); i++) {
|
||||
switchConfig[i] = getSwitchInfo(board, i).config;
|
||||
switchConfig[i] = Boards::getSwitchInfo(board, i).config;
|
||||
}
|
||||
|
||||
backlightMode = 3; // keys and sticks
|
||||
|
@ -1721,68 +1790,6 @@ void ShowEepromWarnings(QWidget *parent, const QString &title, unsigned long err
|
|||
msgBox.exec();
|
||||
}
|
||||
|
||||
QString getBoardName(Board::Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case Board::BOARD_STOCK:
|
||||
return "9X";
|
||||
case Board::BOARD_M128:
|
||||
return "9X128";
|
||||
case Board::BOARD_GRUVIN9X:
|
||||
return "Gruvin9x";
|
||||
case Board::BOARD_MEGA2560:
|
||||
return "MEGA2560";
|
||||
case Board::BOARD_TARANIS_X7:
|
||||
return "Taranis X7";
|
||||
case Board::BOARD_TARANIS_X9D:
|
||||
return "Taranis X9D";
|
||||
case Board::BOARD_TARANIS_X9DP:
|
||||
return "Taranis X9D+";
|
||||
case Board::BOARD_TARANIS_X9E:
|
||||
return "Taranis X9E";
|
||||
case Board::BOARD_SKY9X:
|
||||
return "Sky9x";
|
||||
case Board::BOARD_9XRPRO:
|
||||
return "9XR-PRO";
|
||||
case Board::BOARD_AR9X:
|
||||
return "AR9X";
|
||||
case Board::BOARD_X12S:
|
||||
return "Horus";
|
||||
case Board::BOARD_X10:
|
||||
return "X10";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const int Firmware::getFlashSize()
|
||||
{
|
||||
switch (board) {
|
||||
case Board::BOARD_STOCK:
|
||||
return FSIZE_STOCK;
|
||||
case Board::BOARD_M128:
|
||||
return FSIZE_M128;
|
||||
case Board::BOARD_MEGA2560:
|
||||
case Board::BOARD_GRUVIN9X:
|
||||
return FSIZE_GRUVIN9X;
|
||||
case Board::BOARD_SKY9X:
|
||||
return FSIZE_SKY9X;
|
||||
case Board::BOARD_9XRPRO:
|
||||
case Board::BOARD_AR9X:
|
||||
return FSIZE_9XRPRO;
|
||||
case Board::BOARD_TARANIS_X9D:
|
||||
case Board::BOARD_TARANIS_X9DP:
|
||||
case Board::BOARD_TARANIS_X9E:
|
||||
case Board::BOARD_FLAMENCO:
|
||||
return FSIZE_TARANIS;
|
||||
case Board::BOARD_X12S:
|
||||
case Board::BOARD_X10:
|
||||
return FSIZE_HORUS;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Firmware * getFirmware(const QString & id)
|
||||
{
|
||||
foreach(Firmware * firmware, firmwares) {
|
||||
|
|
|
@ -63,7 +63,8 @@ enum Capability {
|
|||
Outputs,
|
||||
ChannelsName,
|
||||
ExtraInputs,
|
||||
ExtendedTrims,
|
||||
TrimsRange,
|
||||
ExtendedTrimsRange,
|
||||
NumCurves,
|
||||
NumCurvePoints,
|
||||
OffsetWeight,
|
||||
|
|
|
@ -116,7 +116,7 @@ unsigned long Er9xInterface::load(RadioData &radioData, const uint8_t *eeprom, i
|
|||
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
if (size != getEEpromSize(Board::BOARD_STOCK)) {
|
||||
if (size != Boards::getEEpromSize(Board::BOARD_STOCK)) {
|
||||
std::cout << "wrong size\n";
|
||||
errors.set(WRONG_SIZE);
|
||||
return errors.to_ulong();
|
||||
|
|
|
@ -158,7 +158,7 @@ unsigned long Ersky9xInterface::load(RadioData &radioData, const uint8_t *eeprom
|
|||
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
if (size != EESIZE_SKY9X) {
|
||||
if (size != Boards::getEEpromSize(Board::BOARD_SKY9X)) {
|
||||
std::cout << "wrong size\n";
|
||||
errors.set(WRONG_SIZE);
|
||||
return errors.to_ulong();
|
||||
|
|
|
@ -955,9 +955,9 @@ class FlightModeField: public TransformedField {
|
|||
Board::Type board;
|
||||
unsigned int version;
|
||||
int rotencCount;
|
||||
int trimBase[CPN_MAX_STICKS+CPN_MAX_AUX_TRIMS];
|
||||
int trimExt[CPN_MAX_STICKS+CPN_MAX_AUX_TRIMS];
|
||||
unsigned int trimMode[CPN_MAX_STICKS+CPN_MAX_AUX_TRIMS];
|
||||
int trimBase[CPN_MAX_TRIMS];
|
||||
int trimExt[CPN_MAX_TRIMS];
|
||||
unsigned int trimMode[CPN_MAX_TRIMS];
|
||||
};
|
||||
|
||||
class MixField: public TransformedField {
|
||||
|
|
|
@ -207,7 +207,7 @@ unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *
|
|||
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
if (size != getEEpromSize(board)) {
|
||||
if (size != Boards::getEEpromSize(board)) {
|
||||
if (size == 4096) {
|
||||
int notnull = false;
|
||||
for (int i = 2048; i < 4096; i++) {
|
||||
|
@ -227,7 +227,7 @@ unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *
|
|||
}
|
||||
}
|
||||
else {
|
||||
std::cout << " wrong size (" << size << "/" << getEEpromSize(board) << ")\n";
|
||||
std::cout << " wrong size (" << size << "/" << Boards::getEEpromSize(board) << ")\n";
|
||||
errors.set(WRONG_SIZE);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
|
|||
version = getLastDataVersion(board);
|
||||
}
|
||||
|
||||
int size = getEEpromSize(board);
|
||||
int size = Boards::getEEpromSize(board);
|
||||
|
||||
efile->EeFsCreate(eeprom, size, board, version);
|
||||
|
||||
|
@ -379,8 +379,8 @@ int OpenTxEepromInterface::getSize(const ModelData &model)
|
|||
if (model.isEmpty())
|
||||
return 0;
|
||||
|
||||
QByteArray tmp(EESIZE_MAX, 0);
|
||||
efile->EeFsCreate((uint8_t *) tmp.data(), EESIZE_MAX, board, 255/*version max*/);
|
||||
QByteArray tmp(Boards::getEEpromSize(Board::BOARD_UNKNOWN), 0);
|
||||
efile->EeFsCreate((uint8_t *) tmp.data(), Boards::getEEpromSize(Board::BOARD_UNKNOWN), board, 255/*version max*/);
|
||||
|
||||
OpenTxModelData open9xModel((ModelData &) model, board, 255/*version max*/, getCurrentFirmware()->getVariantNumber());
|
||||
|
||||
|
@ -398,8 +398,8 @@ int OpenTxEepromInterface::getSize(const GeneralSettings &settings)
|
|||
if (IS_SKY9X(board))
|
||||
return 0;
|
||||
|
||||
QByteArray tmp(EESIZE_MAX, 0);
|
||||
efile->EeFsCreate((uint8_t *) tmp.data(), EESIZE_MAX, board, 255);
|
||||
QByteArray tmp(Boards::getEEpromSize(Board::BOARD_UNKNOWN), 0);
|
||||
efile->EeFsCreate((uint8_t *) tmp.data(), Boards::getEEpromSize(Board::BOARD_UNKNOWN), board, 255);
|
||||
|
||||
OpenTxGeneralData open9xGeneral((GeneralSettings &) settings, board, 255, getCurrentFirmware()->getVariantNumber());
|
||||
// open9xGeneral.Dump();
|
||||
|
@ -570,7 +570,9 @@ int OpenTxFirmware::getCapability(::Capability capability)
|
|||
return (IS_ARM(board) ? 1 : 0);
|
||||
case ExtraInputs:
|
||||
return 1;
|
||||
case ExtendedTrims:
|
||||
case TrimsRange:
|
||||
return 125;
|
||||
case ExtendedTrimsRange:
|
||||
return 500;
|
||||
case Simulation:
|
||||
return 1;
|
||||
|
@ -727,7 +729,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
|
|||
|
||||
QString OpenTxFirmware::getAnalogInputName(unsigned int index)
|
||||
{
|
||||
if (index < 4) {
|
||||
if ((int)index < getBoardCapability(board, Board::Sticks)) {
|
||||
const QString sticks[] = {
|
||||
QObject::tr("Rud"),
|
||||
QObject::tr("Ele"),
|
||||
|
@ -737,7 +739,7 @@ QString OpenTxFirmware::getAnalogInputName(unsigned int index)
|
|||
return sticks[index];
|
||||
}
|
||||
|
||||
index -= 4;
|
||||
index -= getBoardCapability(board, Board::Sticks);
|
||||
|
||||
if (IS_9X(board) || IS_2560(board) || IS_SKY9X(board)) {
|
||||
const QString pots[] = {
|
||||
|
|
|
@ -227,7 +227,7 @@ void FlashEEpromDialog::on_burnButton_clicked()
|
|||
if (patch) {
|
||||
QString filename = generateProcessUniqueTempFileName("temp.bin");
|
||||
QFile file(filename);
|
||||
uint8_t *eeprom = (uint8_t*)malloc(getEEpromSize(getCurrentBoard()));
|
||||
uint8_t *eeprom = (uint8_t*)malloc(Boards::getEEpromSize(getCurrentBoard()));
|
||||
int eeprom_size = getCurrentEEpromInterface()->save(eeprom, *radioData, 0, getCurrentFirmware()->getVariantNumber());
|
||||
if (eeprom_size == 0) {
|
||||
return;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#endif
|
||||
|
||||
#include "appdata.h"
|
||||
#include "macros.h"
|
||||
#include "helpers.h"
|
||||
#include "simulatormainwindow.h"
|
||||
#include "storage/sdcard.h"
|
||||
|
@ -34,6 +35,8 @@
|
|||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
|
||||
using namespace Helpers;
|
||||
|
||||
Stopwatch gStopwatch("global");
|
||||
|
||||
const QColor colors[CPN_MAX_CURVES] = {
|
||||
|
@ -71,60 +74,6 @@ const QColor colors[CPN_MAX_CURVES] = {
|
|||
QColor(255,127,0),
|
||||
};
|
||||
|
||||
void populateGvSourceCB(QComboBox *b, int value)
|
||||
{
|
||||
QString strings[] = { QObject::tr("---"), QObject::tr("Rud Trim"), QObject::tr("Ele Trim"), QObject::tr("Thr Trim"), QObject::tr("Ail Trim"), QObject::tr("Rot Enc"), QObject::tr("Rud"), QObject::tr("Ele"), QObject::tr("Thr"), QObject::tr("Ail"), QObject::tr("P1"), QObject::tr("P2"), QObject::tr("P3")};
|
||||
b->clear();
|
||||
for (int i=0; i<= 12; i++) {
|
||||
b->addItem(strings[i]);
|
||||
}
|
||||
b->setCurrentIndex(value);
|
||||
}
|
||||
|
||||
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current)
|
||||
{
|
||||
b->clear();
|
||||
b->addItem("----");
|
||||
|
||||
bool added = false;
|
||||
// Convert set into list and sort it alphabetically case insensitive
|
||||
QStringList list = QStringList::fromSet(set);
|
||||
qSort(list.begin(), list.end(), caseInsensitiveLessThan);
|
||||
foreach (QString entry, list) {
|
||||
b->addItem(entry);
|
||||
if (entry == current) {
|
||||
b->setCurrentIndex(b->count()-1);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added && !current.isEmpty()) {
|
||||
b->addItem(current);
|
||||
b->setCurrentIndex(b->count()-1);
|
||||
}
|
||||
}
|
||||
|
||||
void getFileComboBoxValue(QComboBox * b, char * dest, int length)
|
||||
{
|
||||
memset(dest, 0, length+1);
|
||||
if (b->currentText() != "----") {
|
||||
strncpy(dest, b->currentText().toLatin1(), length);
|
||||
}
|
||||
}
|
||||
|
||||
void populatePhasesCB(QComboBox *b, int value)
|
||||
{
|
||||
for (int i=-getCurrentFirmware()->getCapability(FlightModes); i<=getCurrentFirmware()->getCapability(FlightModes); i++) {
|
||||
if (i < 0)
|
||||
b->addItem(QObject::tr("!Flight mode %1").arg(-i-1), i);
|
||||
else if (i > 0)
|
||||
b->addItem(QObject::tr("Flight mode %1").arg(i-1), i);
|
||||
else
|
||||
b->addItem(QObject::tr("----"), 0);
|
||||
}
|
||||
b->setCurrentIndex(value + getCurrentFirmware()->getCapability(FlightModes));
|
||||
}
|
||||
|
||||
/*
|
||||
* GVarGroup
|
||||
*/
|
||||
|
@ -141,7 +90,7 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
|
|||
lock(true)
|
||||
{
|
||||
if (allowGvars && getCurrentFirmware()->getCapability(Gvars)) {
|
||||
populateGVCB(*weightCB, weight, model);
|
||||
Helpers::populateGVCB(*weightCB, weight, model);
|
||||
connect(weightGV, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
|
||||
connect(weightCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
|
||||
}
|
||||
|
@ -252,7 +201,7 @@ void CurveGroup::update()
|
|||
curveGVarCB->setChecked(true);
|
||||
if (lastType != CurveReference::CURVE_REF_DIFF && lastType != CurveReference::CURVE_REF_EXPO) {
|
||||
lastType = curve.type;
|
||||
populateGVCB(*curveValueCB, curve.value, model);
|
||||
Helpers::populateGVCB(*curveValueCB, curve.value, model);
|
||||
}
|
||||
curveValueCB->show();
|
||||
curveValueSB->hide();
|
||||
|
@ -370,145 +319,10 @@ void CurveGroup::valuesChanged()
|
|||
}
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
* Helpers namespace functions
|
||||
*/
|
||||
|
||||
void populateGvarUseCB(QComboBox *b, unsigned int phase)
|
||||
{
|
||||
b->addItem(QObject::tr("Own value"));
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(FlightModes); i++) {
|
||||
if (i != (int)phase) {
|
||||
b->addItem(QObject::tr("Flight mode %1 value").arg(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void populateSwitchCB(QComboBox * b, const RawSwitch & value, const GeneralSettings & generalSettings, SwitchContext context)
|
||||
{
|
||||
Board::Type board = getCurrentBoard();
|
||||
RawSwitch item;
|
||||
|
||||
b->clear();
|
||||
|
||||
if (context != MixesContext && context != GlobalFunctionsContext) {
|
||||
// !FMx
|
||||
if (IS_ARM(board)) {
|
||||
for (int i=-getCurrentFirmware()->getCapability(FlightModes); i<0; i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_FLIGHT_MODE, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context != GlobalFunctionsContext) {
|
||||
for (int i=-getCurrentFirmware()->getCapability(LogicalSwitches); i<0; i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_VIRTUAL, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=-getCurrentFirmware()->getCapability(RotaryEncoders); i<0; i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_ROTARY_ENCODER, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
for (int i = -getBoardCapability(board, Board::NumTrimSwitches); i < 0; i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_TRIM, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
for (int i=getCurrentFirmware()->getCapability(MultiposPots)-1; i>=0; i--) {
|
||||
if (generalSettings.potConfig[i] == Board::POT_MULTIPOS_SWITCH) {
|
||||
for (int j=-getCurrentFirmware()->getCapability(MultiposPotsPositions); j<0; j++) {
|
||||
item = RawSwitch(SWITCH_TYPE_MULTIPOS_POT, -i*getCurrentFirmware()->getCapability(MultiposPotsPositions)+j);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=-getCurrentFirmware()->getCapability(SwitchesPositions); i<0; i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_SWITCH, i);
|
||||
if (IS_HORUS_OR_TARANIS(board) && !generalSettings.switchPositionAllowedTaranis(i)) {
|
||||
continue;
|
||||
}
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
if (context == TimersContext) {
|
||||
for (int i=0; i<5; i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_TIMER_MODE, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
}
|
||||
else {
|
||||
item = RawSwitch(SWITCH_TYPE_NONE);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
for (int i=1; i<=getCurrentFirmware()->getCapability(SwitchesPositions); i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_SWITCH, i);
|
||||
if (IS_HORUS_OR_TARANIS(board) && !generalSettings.switchPositionAllowedTaranis(i)) {
|
||||
continue;
|
||||
}
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(MultiposPots); i++) {
|
||||
if (generalSettings.potConfig[i] == Board::POT_MULTIPOS_SWITCH) {
|
||||
for (int j=1; j<=getCurrentFirmware()->getCapability(MultiposPotsPositions); j++) {
|
||||
item = RawSwitch(SWITCH_TYPE_MULTIPOS_POT, i*getCurrentFirmware()->getCapability(MultiposPotsPositions)+j);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=1; i <= getBoardCapability(board, Board::NumTrimSwitches); i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_TRIM, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
for (int i=1; i<=getCurrentFirmware()->getCapability(RotaryEncoders); i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_ROTARY_ENCODER, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
if (context != GlobalFunctionsContext) {
|
||||
for (int i=1; i<=getCurrentFirmware()->getCapability(LogicalSwitches); i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_VIRTUAL, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (context == SpecialFunctionsContext || context == GlobalFunctionsContext) {
|
||||
// ON
|
||||
item = RawSwitch(SWITCH_TYPE_ON);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
// One
|
||||
item = RawSwitch(SWITCH_TYPE_ONE, 1);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
|
||||
// FMx
|
||||
if (context != MixesContext && context != GlobalFunctionsContext) {
|
||||
if (IS_ARM(board)) {
|
||||
for (int i=1; i<=getCurrentFirmware()->getCapability(FlightModes); i++) {
|
||||
item = RawSwitch(SWITCH_TYPE_FLIGHT_MODE, i);
|
||||
b->addItem(item.toString(), item.toValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < b->count(); ++i) {
|
||||
if (RawSwitch(b->itemData(i).toInt()) == value) {
|
||||
b->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
b->setMaxVisibleItems(10);
|
||||
}
|
||||
|
||||
void populateGVCB(QComboBox & b, int value, const ModelData & model)
|
||||
void Helpers::populateGVCB(QComboBox & b, int value, const ModelData & model)
|
||||
{
|
||||
bool selected = false;
|
||||
|
||||
|
@ -544,146 +358,253 @@ void populateGVCB(QComboBox & b, int value, const ModelData & model)
|
|||
}
|
||||
}
|
||||
|
||||
void populateSourceCB(QComboBox * b, const RawSource & source, const GeneralSettings generalSettings, const ModelData * model, unsigned int flags)
|
||||
void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
|
||||
{
|
||||
Board::Type board = getCurrentBoard();
|
||||
RawSource item;
|
||||
b->addItem(QObject::tr("Own value"));
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(FlightModes); i++) {
|
||||
if (i != (int)phase) {
|
||||
b->addItem(QObject::tr("Flight mode %1 value").arg(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Helpers::populateGvSourceCB(QComboBox * b, int value)
|
||||
{
|
||||
QString strings[] = { QObject::tr("---"), QObject::tr("Rud Trim"), QObject::tr("Ele Trim"), QObject::tr("Thr Trim"), QObject::tr("Ail Trim"), QObject::tr("Rot Enc"), QObject::tr("Rud"), QObject::tr("Ele"), QObject::tr("Thr"), QObject::tr("Ail"), QObject::tr("P1"), QObject::tr("P2"), QObject::tr("P3")};
|
||||
b->clear();
|
||||
for (int i=0; i<= 12; i++) {
|
||||
b->addItem(strings[i]);
|
||||
}
|
||||
b->setCurrentIndex(value);
|
||||
}
|
||||
|
||||
void Helpers::populatePhasesCB(QComboBox * b, int value)
|
||||
{
|
||||
for (int i=-getCurrentFirmware()->getCapability(FlightModes); i<=getCurrentFirmware()->getCapability(FlightModes); i++) {
|
||||
if (i < 0)
|
||||
b->addItem(QObject::tr("!Flight mode %1").arg(-i-1), i);
|
||||
else if (i > 0)
|
||||
b->addItem(QObject::tr("Flight mode %1").arg(i-1), i);
|
||||
else
|
||||
b->addItem(QObject::tr("----"), 0);
|
||||
}
|
||||
b->setCurrentIndex(value + getCurrentFirmware()->getCapability(FlightModes));
|
||||
}
|
||||
|
||||
void Helpers::populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current)
|
||||
{
|
||||
b->clear();
|
||||
b->addItem("----");
|
||||
|
||||
bool added = false;
|
||||
// Convert set into list and sort it alphabetically case insensitive
|
||||
QStringList list = QStringList::fromSet(set);
|
||||
qSort(list.begin(), list.end(), caseInsensitiveLessThan);
|
||||
foreach (QString entry, list) {
|
||||
b->addItem(entry);
|
||||
if (entry == current) {
|
||||
b->setCurrentIndex(b->count()-1);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added && !current.isEmpty()) {
|
||||
b->addItem(current);
|
||||
b->setCurrentIndex(b->count()-1);
|
||||
}
|
||||
}
|
||||
|
||||
void Helpers::getFileComboBoxValue(QComboBox * b, char * dest, int length)
|
||||
{
|
||||
memset(dest, 0, length+1);
|
||||
if (b->currentText() != "----") {
|
||||
strncpy(dest, b->currentText().toLatin1(), length);
|
||||
}
|
||||
}
|
||||
|
||||
void Helpers::addRawSwitchItems(QStandardItemModel * itemModel, const RawSwitchType & type, int count, const GeneralSettings * const generalSettings)
|
||||
{
|
||||
// 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;
|
||||
|
||||
int rawIdxAdj = 0;
|
||||
const Board::Type board = getCurrentBoard();
|
||||
int i = (count < 0 ? count : 1);
|
||||
const int maxCount = (i < 0 ? 0 : count + i);
|
||||
|
||||
// handle exceptions in RawSwitch() index values
|
||||
if (rawSwitchIndexBaseZeroTypes.contains(type))
|
||||
rawIdxAdj = -1;
|
||||
|
||||
for ( ; i < maxCount; ++i) {
|
||||
if (generalSettings) {
|
||||
if (type == SWITCH_TYPE_SWITCH && IS_HORUS_OR_TARANIS(board) && !generalSettings->switchPositionAllowedTaranis(abs(i)))
|
||||
continue;
|
||||
if (type == SWITCH_TYPE_MULTIPOS_POT) {
|
||||
int pot = div(abs(i) - 1, getCurrentFirmware()->getCapability(MultiposPotsPositions)).quot;
|
||||
if (!generalSettings->isPotAvailable(pot) || generalSettings->potConfig[pot] != Board::POT_MULTIPOS_SWITCH)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
RawSwitch rs(type, i + rawIdxAdj);
|
||||
QStandardItem * modelItem = new QStandardItem(rs.toString(board, generalSettings));
|
||||
modelItem->setData(rs.toValue(), Qt::UserRole);
|
||||
itemModel->appendRow(modelItem);
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItemModel * Helpers::getRawSwitchItemModel(const GeneralSettings * const generalSettings, SwitchContext context)
|
||||
{
|
||||
QStandardItemModel * itemModel = new QStandardItemModel();
|
||||
Board::Type board = getCurrentBoard();
|
||||
Firmware * fw = getCurrentFirmware();
|
||||
|
||||
// Descending switch direction: NOT (!) switches
|
||||
|
||||
if (context != MixesContext && context != GlobalFunctionsContext && IS_ARM(board)) {
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes), generalSettings);
|
||||
}
|
||||
if (context != GlobalFunctionsContext) {
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches), generalSettings);
|
||||
}
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders), generalSettings);
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_TRIM, -getBoardCapability(board, Board::NumTrimSwitches), generalSettings);
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_MULTIPOS_POT, -(fw->getCapability(MultiposPots) * fw->getCapability(MultiposPotsPositions)), generalSettings);
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_SWITCH, -fw->getCapability(SwitchesPositions), generalSettings);
|
||||
|
||||
// Ascending switch direction (including zero)
|
||||
|
||||
if (context == TimersContext) {
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_TIMER_MODE, 5, generalSettings);
|
||||
}
|
||||
else {
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_NONE, 1);
|
||||
}
|
||||
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_SWITCH, fw->getCapability(SwitchesPositions), generalSettings);
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_MULTIPOS_POT, fw->getCapability(MultiposPots) * fw->getCapability(MultiposPotsPositions), generalSettings);
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_TRIM, getBoardCapability(board, Board::NumTrimSwitches), generalSettings);
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders), generalSettings);
|
||||
if (context != GlobalFunctionsContext) {
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches), generalSettings);
|
||||
}
|
||||
if (context != MixesContext && context != GlobalFunctionsContext && IS_ARM(board)) {
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes), generalSettings);
|
||||
}
|
||||
if (context == SpecialFunctionsContext || context == GlobalFunctionsContext) {
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_ON, 1);
|
||||
addRawSwitchItems(itemModel, SWITCH_TYPE_ONE, 1);
|
||||
}
|
||||
|
||||
return itemModel;
|
||||
}
|
||||
|
||||
void Helpers::addRawSourceItems(QStandardItemModel * itemModel, const RawSourceType & type, int count, const GeneralSettings * const generalSettings,
|
||||
const ModelData * const model, const int start, const QList<int> exclude)
|
||||
{
|
||||
for (int i = start; i < start + count; i++) {
|
||||
if (exclude.contains(i))
|
||||
continue;
|
||||
|
||||
RawSource src = RawSource(type, i);
|
||||
if (model) {
|
||||
if (type == SOURCE_TYPE_VIRTUAL_INPUT && !model->isInputValid(i))
|
||||
continue;
|
||||
}
|
||||
if (generalSettings) {
|
||||
int genAryIdx = 0;
|
||||
if (type == SOURCE_TYPE_STICK && ((src.isPot(&genAryIdx) && !generalSettings->isPotAvailable(genAryIdx)) || (src.isSlider(&genAryIdx) && !generalSettings->isSliderAvailable(genAryIdx))))
|
||||
continue;
|
||||
}
|
||||
|
||||
QStandardItem * modelItem = new QStandardItem(src.toString(model, generalSettings));
|
||||
modelItem->setData(src.toValue(), Qt::UserRole);
|
||||
itemModel->appendRow(modelItem);
|
||||
|
||||
if (type == SOURCE_TYPE_SWITCH && generalSettings && IS_HORUS_OR_TARANIS(getCurrentBoard()) && !generalSettings->switchSourceAllowedTaranis(i)) {
|
||||
modelItem->setData(0, Qt::UserRole - 1); // trick to disable an item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItemModel * Helpers::getRawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const model, unsigned int flags)
|
||||
{
|
||||
QStandardItemModel * itemModel = new QStandardItemModel();
|
||||
Board::Type board = getCurrentBoard();
|
||||
Firmware * fw = getCurrentFirmware();
|
||||
|
||||
if (flags & POPULATE_NONE) {
|
||||
item = RawSource(SOURCE_TYPE_NONE);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_NONE, 1, generalSettings, model);
|
||||
}
|
||||
|
||||
if (flags & POPULATE_SCRIPT_OUTPUTS) {
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(LuaScripts); i++) {
|
||||
for (int j=0; j<getCurrentFirmware()->getCapability(LuaOutputsPerScript); j++) {
|
||||
item = RawSource(SOURCE_TYPE_LUA_OUTPUT, i*16+j);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
for (int i=0; i < getCurrentFirmware()->getCapability(LuaScripts); i++) {
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_LUA_OUTPUT, fw->getCapability(LuaOutputsPerScript), generalSettings, model, i * 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (model && (flags & POPULATE_VIRTUAL_INPUTS)) {
|
||||
int virtualInputs = getCurrentFirmware()->getCapability(VirtualInputs);
|
||||
for (int i=0; i<virtualInputs; i++) {
|
||||
if (model->isInputValid(i)) {
|
||||
item = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
}
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_VIRTUAL_INPUT, fw->getCapability(VirtualInputs), generalSettings, model);
|
||||
}
|
||||
|
||||
if (flags & POPULATE_SOURCES) {
|
||||
int totalSources = CPN_MAX_STICKS + getBoardCapability(board, Board::Pots) + getBoardCapability(board, Board::Sliders) + getBoardCapability(board, Board::MouseAnalogs);
|
||||
for (int i=0; i < totalSources; i++) {
|
||||
item = RawSource(SOURCE_TYPE_STICK, i);
|
||||
// skip unavailable pots and sliders
|
||||
if (item.isPot() && !generalSettings.isPotAvailable(i-CPN_MAX_STICKS))
|
||||
continue;
|
||||
if (item.isSlider() && !generalSettings.isSliderAvailable(i-CPN_MAX_STICKS-getBoardCapability(board, Board::Pots)))
|
||||
continue;
|
||||
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(RotaryEncoders); i++) {
|
||||
item = RawSource(SOURCE_TYPE_ROTARY_ENCODER, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_STICK, totalSources, generalSettings, model);
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders), generalSettings, model);
|
||||
}
|
||||
|
||||
if (flags & POPULATE_TRIMS) {
|
||||
for (int i=0; i < getBoardCapability(board, Board::NumTrims); i++) {
|
||||
item = RawSource(SOURCE_TYPE_TRIM, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_TRIM, getBoardCapability(board, Board::NumTrims), generalSettings, model);
|
||||
}
|
||||
|
||||
if (flags & POPULATE_SOURCES) {
|
||||
item = RawSource(SOURCE_TYPE_MAX);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_MAX, 1, generalSettings, model);
|
||||
}
|
||||
|
||||
if (flags & POPULATE_SWITCHES) {
|
||||
for (int i=0; i<getBoardCapability(board, Board::Switches); i++) {
|
||||
item = RawSource(SOURCE_TYPE_SWITCH, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
if (IS_HORUS_OR_TARANIS(board) && !generalSettings.switchSourceAllowedTaranis(i)) {
|
||||
QModelIndex index = b->model()->index(b->count()-1, 0);
|
||||
QVariant v(0);
|
||||
b->model()->setData(index, v, Qt::UserRole - 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(LogicalSwitches); i++) {
|
||||
item = RawSource(SOURCE_TYPE_CUSTOM_SWITCH, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_SWITCH, getBoardCapability(board, Board::Switches), generalSettings, model);
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_CUSTOM_SWITCH, fw->getCapability(LogicalSwitches), generalSettings, model);
|
||||
}
|
||||
|
||||
if (flags & POPULATE_SOURCES) {
|
||||
for (int i=0; i<CPN_MAX_CYC; i++) {
|
||||
item = RawSource(SOURCE_TYPE_CYC, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(TrainerInputs); i++) {
|
||||
item = RawSource(SOURCE_TYPE_PPM, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(Outputs); i++) {
|
||||
item = RawSource(SOURCE_TYPE_CH, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_CYC, CPN_MAX_CYC, generalSettings, model);
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_PPM, fw->getCapability(TrainerInputs), generalSettings, model);
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_CH, fw->getCapability(Outputs), generalSettings, model);
|
||||
}
|
||||
|
||||
if (flags & POPULATE_TELEMETRY) {
|
||||
if (IS_ARM(board)) {
|
||||
for (int i=0; i<5; ++i) {
|
||||
item = RawSource(SOURCE_TYPE_SPECIAL, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
for (int i=0; i<CPN_MAX_SENSORS; ++i) {
|
||||
if (model && model->sensorData[i].isAvailable()) { //this conditon must be false if we populate Global Functions where model = 0
|
||||
for (int j=0; j<3; ++j) {
|
||||
item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i+j);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
// qDebug() << item.toString(model) << source.toString(model);
|
||||
}
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_SPECIAL, 5, generalSettings, model);
|
||||
|
||||
if (model) {
|
||||
QList<int> exclude;
|
||||
for (int i=0; i < CPN_MAX_SENSORS * 3; ++i) {
|
||||
//this conditon must be false if we populate Global Functions where model = 0
|
||||
if (!model->sensorData[div(i, 3).quot].isAvailable())
|
||||
exclude << i;
|
||||
}
|
||||
if (exclude.size() < CPN_MAX_SENSORS * 3)
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_TELEMETRY, CPN_MAX_SENSORS * 3, generalSettings, model, 0, exclude);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i=0; i<(flags & POPULATE_TELEMETRYEXT ? TELEMETRY_SOURCES_STATUS_COUNT : TELEMETRY_SOURCES_COUNT); i++) {
|
||||
if (i==TELEMETRY_SOURCE_TX_TIME && !getCurrentFirmware()->getCapability(RtcTime))
|
||||
continue;
|
||||
if (i==TELEMETRY_SOURCE_SWR && !getCurrentFirmware()->getCapability(SportTelemetry))
|
||||
continue;
|
||||
if (i==TELEMETRY_SOURCE_TIMER3 && !IS_ARM(board))
|
||||
continue;
|
||||
item = RawSource(SOURCE_TYPE_TELEMETRY, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
QList<int> exclude;
|
||||
if (!fw->getCapability(RtcTime))
|
||||
exclude << TELEMETRY_SOURCE_TX_TIME;
|
||||
if (!fw->getCapability(SportTelemetry))
|
||||
exclude << TELEMETRY_SOURCE_SWR;
|
||||
if (!IS_ARM(board))
|
||||
exclude << TELEMETRY_SOURCE_TIMER3;
|
||||
int count = ((flags & POPULATE_TELEMETRYEXT) ? TELEMETRY_SOURCES_STATUS_COUNT : TELEMETRY_SOURCES_COUNT);
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_TELEMETRY, count, generalSettings, model, 0, exclude);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & POPULATE_GVARS) {
|
||||
for (int i=0; i<getCurrentFirmware()->getCapability(Gvars); i++) {
|
||||
item = RawSource(SOURCE_TYPE_GVAR, i);
|
||||
b->addItem(item.toString(model), item.toValue());
|
||||
}
|
||||
addRawSourceItems(itemModel, SOURCE_TYPE_GVAR, fw->getCapability(Gvars), generalSettings, model);
|
||||
}
|
||||
|
||||
for (int i=0; i < b->count(); ++i) {
|
||||
if (RawSource(b->itemData(i).toInt()) == source) {
|
||||
b->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
b->setMaxVisibleItems(10);
|
||||
return itemModel;
|
||||
}
|
||||
|
||||
QString image2qstring(QImage image)
|
||||
|
@ -871,6 +792,7 @@ QPixmap makePixMap(const QImage & image)
|
|||
return QPixmap::fromImage(result);
|
||||
}
|
||||
|
||||
|
||||
int version2index(const QString & version)
|
||||
{
|
||||
int result = 999;
|
||||
|
@ -887,8 +809,10 @@ int version2index(const QString & version)
|
|||
return result;
|
||||
}
|
||||
|
||||
QString index2version(int index)
|
||||
const QString index2version(int index)
|
||||
{
|
||||
QString result;
|
||||
QString templt("%1.%2.%3");
|
||||
if (index >= 19900000) {
|
||||
int nightly = index % 1000;
|
||||
index /= 1000;
|
||||
|
@ -896,22 +820,19 @@ QString index2version(int index)
|
|||
index /= 100;
|
||||
int minor = index % 100;
|
||||
int major = index / 100;
|
||||
QString result = QString("%1.%2.%3").arg(major).arg(minor).arg(revision);
|
||||
result = templt.arg(major).arg(minor).arg(revision);
|
||||
if (nightly > 0 && nightly < 999) {
|
||||
result += QString("N%1").arg(nightly);
|
||||
result += "N" + QString::number(nightly);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (index >= 19900) {
|
||||
int revision = index % 100;
|
||||
index /= 100;
|
||||
int minor = index % 100;
|
||||
int major = index / 100;
|
||||
return QString("%1.%2.%3").arg(major).arg(minor).arg(revision);
|
||||
}
|
||||
else {
|
||||
return QString();
|
||||
result = templt.arg(major).arg(minor).arg(revision);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool qunlink(const QString & fileName)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <QDebug>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
extern const QColor colors[CPN_MAX_CURVES];
|
||||
|
||||
|
@ -51,11 +52,6 @@ extern const QColor colors[CPN_MAX_CURVES];
|
|||
|
||||
#define TRIM_MODE_NONE 0x1F // 0b11111
|
||||
|
||||
void populateGvSourceCB(QComboBox *b, int value);
|
||||
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
|
||||
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
|
||||
void populateRotEncCB(QComboBox *b, int value, int renumber);
|
||||
|
||||
QString getTheme();
|
||||
|
||||
class CompanionIcon: public QIcon {
|
||||
|
@ -117,19 +113,6 @@ class CurveGroup : public QObject {
|
|||
int lastType;
|
||||
};
|
||||
|
||||
enum SwitchContext
|
||||
{
|
||||
LogicalSwitchesContext,
|
||||
SpecialFunctionsContext,
|
||||
GlobalFunctionsContext,
|
||||
TimersContext,
|
||||
MixesContext
|
||||
};
|
||||
|
||||
void populateSwitchCB(QComboBox *b, const RawSwitch & value, const GeneralSettings & generalSettings, SwitchContext context);
|
||||
|
||||
void populatePhasesCB(QComboBox *b, int value);
|
||||
void populateGvarUseCB(QComboBox *b, unsigned int phase);
|
||||
|
||||
#define POPULATE_NONE (1<<0)
|
||||
#define POPULATE_SOURCES (1<<1)
|
||||
|
@ -144,8 +127,35 @@ void populateGvarUseCB(QComboBox *b, unsigned int phase);
|
|||
#define GVARS_VARIANT 0x0001
|
||||
#define FRSKY_VARIANT 0x0002
|
||||
|
||||
void populateGVCB(QComboBox & b, int value, const ModelData & model);
|
||||
void populateSourceCB(QComboBox *b, const RawSource &source, const GeneralSettings generalSettings, const ModelData * model, unsigned int flags);
|
||||
namespace Helpers
|
||||
{
|
||||
enum SwitchContext
|
||||
{
|
||||
LogicalSwitchesContext,
|
||||
SpecialFunctionsContext,
|
||||
GlobalFunctionsContext,
|
||||
TimersContext,
|
||||
MixesContext
|
||||
};
|
||||
|
||||
void addRawSwitchItems(QStandardItemModel * itemModel, const RawSwitchType & type, int count, const GeneralSettings * const generalSettings = NULL);
|
||||
QStandardItemModel * getRawSwitchItemModel(const GeneralSettings * const generalSettings = NULL, SwitchContext context = LogicalSwitchesContext);
|
||||
|
||||
void addRawSourceItems(QStandardItemModel * itemModel, const RawSourceType & type, int count, const GeneralSettings * const generalSettings = NULL,
|
||||
const ModelData * const model = NULL, const int start = 0, const QList<int> exclude = QList<int>());
|
||||
QStandardItemModel * getRawSourceItemModel(const GeneralSettings * const generalSettings = NULL, const ModelData * const model = NULL, unsigned int flags = 0);
|
||||
|
||||
void populateGvarUseCB(QComboBox *b, unsigned int phase);
|
||||
void populateGvSourceCB(QComboBox *b, int value);
|
||||
void populatePhasesCB(QComboBox *b, int value);
|
||||
void populateGVCB(QComboBox & b, int value, const ModelData & model);
|
||||
|
||||
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
|
||||
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
|
||||
} // namespace Helpers
|
||||
|
||||
// TODO : move to Helpers namespace
|
||||
|
||||
QString image2qstring(QImage image);
|
||||
int findmult(float value, float base);
|
||||
|
||||
|
@ -162,14 +172,14 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx);
|
|||
QPixmap makePixMap(const QImage & image);
|
||||
|
||||
int version2index(const QString & version);
|
||||
QString index2version(int index);
|
||||
const QString index2version(int index);
|
||||
|
||||
class QTimeS : public QTime
|
||||
{
|
||||
public:
|
||||
QTimeS(int s) { int h = s/3600; s %= 3600; int m = s/60; s %=60; setHMS(h, m, s); };
|
||||
QTimeS(const QTime & q) : QTime(q) {};
|
||||
int seconds() const { return hour()*3600 + minute()*60 + second(); };
|
||||
QTimeS(int s) { int h = s/3600; s %= 3600; int m = s/60; s %=60; setHMS(h, m, s); }
|
||||
QTimeS(const QTime & q) : QTime(q) {}
|
||||
int seconds() const { return hour()*3600 + minute()*60 + second(); }
|
||||
};
|
||||
|
||||
bool qunlink(const QString & fileName);
|
||||
|
@ -186,7 +196,7 @@ bool caseInsensitiveLessThan(const QString &s1, const QString &s2);
|
|||
class GpsCoord
|
||||
{
|
||||
public:
|
||||
GpsCoord(): latitude(0), longitude(0) {};
|
||||
GpsCoord(): latitude(0), longitude(0) {}
|
||||
double latitude; // Precede South latitudes and West longitudes with a minus sign. Latitudes range from -90 to 90.
|
||||
double longitude; // Longitudes range from -180 to 180.
|
||||
};
|
||||
|
@ -194,7 +204,7 @@ public:
|
|||
class GpsGlitchFilter
|
||||
{
|
||||
public:
|
||||
GpsGlitchFilter() : lastValid(false), glitchCount(0) {};
|
||||
GpsGlitchFilter() : lastValid(false), glitchCount(0) {}
|
||||
bool isGlitch(GpsCoord coord);
|
||||
|
||||
private:
|
||||
|
@ -207,7 +217,7 @@ private:
|
|||
class GpsLatLonFilter
|
||||
{
|
||||
public:
|
||||
GpsLatLonFilter() {};
|
||||
GpsLatLonFilter() {}
|
||||
bool isValid(GpsCoord coord);
|
||||
|
||||
private:
|
||||
|
@ -248,7 +258,7 @@ public:
|
|||
name(name), total(0) {
|
||||
timer.start();
|
||||
};
|
||||
~Stopwatch() {};
|
||||
~Stopwatch() {}
|
||||
|
||||
void restart() {
|
||||
total = 0;
|
||||
|
|
|
@ -73,6 +73,13 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
|
|||
lock = true;
|
||||
int num_fsw = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions);
|
||||
|
||||
rawSwitchItemModel = Helpers::getRawSwitchItemModel(&generalSettings, model ? Helpers::SpecialFunctionsContext : Helpers::GlobalFunctionsContext);
|
||||
rawSwitchItemModel->setParent(this);
|
||||
rawSrcInputsItemModel = Helpers::getRawSourceItemModel(&generalSettings, model, POPULATE_NONE|POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_TRIMS|POPULATE_SWITCHES);
|
||||
rawSrcInputsItemModel->setParent(this);
|
||||
rawSrcAllItemModel = Helpers::getRawSourceItemModel(&generalSettings, model, POPULATE_NONE|POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_SWITCHES|POPULATE_GVARS|POPULATE_TRIMS|POPULATE_TELEMETRY|POPULATE_TELEMETRYEXT|POPULATE_SCRIPT_OUTPUTS);
|
||||
rawSrcAllItemModel->setParent(this);
|
||||
|
||||
if (!firmware->getCapability(VoicesAsNumbers)) {
|
||||
tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength));
|
||||
for (int i=0; i<num_fsw; i++) {
|
||||
|
@ -123,8 +130,9 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
|
|||
|
||||
// The switch
|
||||
fswtchSwtch[i] = new QComboBox(this);
|
||||
fswtchSwtch[i]->setModel(rawSwitchItemModel);
|
||||
fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue()));
|
||||
fswtchSwtch[i]->setProperty("index", i);
|
||||
populateSwitchCB(fswtchSwtch[i], functions[i].swtch, generalSettings, model ? SpecialFunctionsContext : GlobalFunctionsContext);
|
||||
fswtchSwtch[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
|
||||
fswtchSwtch[i]->setMaxVisibleItems(10);
|
||||
connect(fswtchSwtch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited()));
|
||||
|
@ -133,8 +141,14 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
|
|||
|
||||
// The function
|
||||
fswtchFunc[i] = new QComboBox(this);
|
||||
fswtchFunc[i]->setProperty("index", i);
|
||||
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);
|
||||
connect(fswtchFunc[i], SIGNAL(currentIndexChanged(int)), this, SLOT(functionEdited()));
|
||||
tableLayout->addWidget(i, 2, fswtchFunc[i]);
|
||||
// s1.report("func");
|
||||
|
@ -216,6 +230,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
|
|||
repeatLayout->addWidget(fswtchEnable[i], i+1);
|
||||
connect(fswtchEnable[i], SIGNAL(stateChanged(int)), this, SLOT(customFunctionEdited()));
|
||||
}
|
||||
|
||||
s1.report("add items");
|
||||
|
||||
disableMouseScrolling();
|
||||
|
@ -367,7 +382,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
|
|||
cfn.adjustMode = (AssignFunc)fswtchGVmode[i]->currentIndex();
|
||||
}
|
||||
|
||||
if (cfn.swtch.toValue()){
|
||||
if (cfn.swtch.toValue()) {
|
||||
|
||||
if (func>=FuncOverrideCH1 && func<=FuncOverrideCH32) {
|
||||
if (model) {
|
||||
|
@ -432,7 +447,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
|
|||
fswtchParamTime[i]->setMinimumTime(QTime(0, 0, 0));
|
||||
fswtchParamTime[i]->setMaximumTime(firmware->getMaxTimerStart());
|
||||
fswtchParamTime[i]->setTime(QTimeS(cfn.param));
|
||||
widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM + CUSTOM_FUNCTION_ENABLE;
|
||||
widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM | CUSTOM_FUNCTION_ENABLE;
|
||||
}
|
||||
else if (func>=FuncSetFailsafeInternalModule && func<=FuncBindExternalModule) {
|
||||
widgetsMask |= CUSTOM_FUNCTION_ENABLE;
|
||||
|
@ -491,9 +506,9 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
|
|||
else {
|
||||
widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM;
|
||||
if (modified) {
|
||||
getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength));
|
||||
Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength));
|
||||
}
|
||||
populateFileComboBox(fswtchParamArmT[i], tracksSet, cfn.paramarm);
|
||||
Helpers::populateFileComboBox(fswtchParamArmT[i], tracksSet, cfn.paramarm);
|
||||
if (fswtchParamArmT[i]->currentText() != "----") {
|
||||
widgetsMask |= CUSTOM_FUNCTION_PLAY;
|
||||
}
|
||||
|
@ -502,9 +517,9 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
|
|||
else if (func==FuncBackgroundMusic) {
|
||||
widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM;
|
||||
if (modified) {
|
||||
getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength));
|
||||
Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength));
|
||||
}
|
||||
populateFileComboBox(fswtchParamArmT[i], tracksSet, cfn.paramarm);
|
||||
Helpers::populateFileComboBox(fswtchParamArmT[i], tracksSet, cfn.paramarm);
|
||||
if (fswtchParamArmT[i]->currentText() != "----") {
|
||||
widgetsMask |= CUSTOM_FUNCTION_PLAY;
|
||||
}
|
||||
|
@ -525,9 +540,9 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
|
|||
else if (func==FuncPlayScript) {
|
||||
widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM;
|
||||
if (modified) {
|
||||
getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, 8);
|
||||
Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, 8);
|
||||
}
|
||||
populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm);
|
||||
Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm);
|
||||
}
|
||||
else if (func==FuncBacklight && IS_TARANIS_PLUS(getCurrentBoard())) {
|
||||
if (modified)
|
||||
|
@ -584,7 +599,8 @@ void CustomFunctionsPanel::fswPaste()
|
|||
CustomFunctionData *fsw = &functions[selectedFunction];
|
||||
memcpy(fsw, fswData.constData(), sizeof(CustomFunctionData));
|
||||
lock = true;
|
||||
populateSwitchCB(fswtchSwtch[selectedFunction], functions[selectedFunction].swtch, generalSettings, model ? SpecialFunctionsContext : GlobalFunctionsContext);
|
||||
fswtchSwtch[selectedFunction]->setModel(rawSwitchItemModel);
|
||||
fswtchSwtch[selectedFunction]->setCurrentIndex(fswtchSwtch[selectedFunction]->findData(functions[selectedFunction].swtch.toValue()));
|
||||
populateFuncCB(fswtchFunc[selectedFunction], functions[selectedFunction].func);
|
||||
populateGVmodeCB(fswtchGVmode[selectedFunction], functions[selectedFunction].adjustMode);
|
||||
populateFuncParamCB(fswtchParamT[selectedFunction], functions[selectedFunction].func, functions[selectedFunction].param, functions[selectedFunction].adjustMode);
|
||||
|
@ -599,7 +615,8 @@ void CustomFunctionsPanel::fswDelete()
|
|||
functions[selectedFunction].clear();
|
||||
// TODO update switch and func
|
||||
lock = true;
|
||||
populateSwitchCB(fswtchSwtch[selectedFunction], functions[selectedFunction].swtch, generalSettings, model ? SpecialFunctionsContext : GlobalFunctionsContext);
|
||||
fswtchSwtch[selectedFunction]->setModel(rawSwitchItemModel);
|
||||
fswtchSwtch[selectedFunction]->setCurrentIndex(fswtchSwtch[selectedFunction]->findData(functions[selectedFunction].swtch.toValue()));
|
||||
populateFuncCB(fswtchFunc[selectedFunction], functions[selectedFunction].func);
|
||||
refreshCustomFunction(selectedFunction);
|
||||
lock = false;
|
||||
|
@ -699,18 +716,22 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi
|
|||
CustomFunctionData::populateResetParams(model, b, value);
|
||||
}
|
||||
else if (function==FuncVolume) {
|
||||
populateSourceCB(b, RawSource(value), generalSettings, model, POPULATE_NONE|POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_TRIMS|POPULATE_SWITCHES);
|
||||
b->setModel(rawSrcInputsItemModel);
|
||||
b->setCurrentIndex(b->findData(value));
|
||||
}
|
||||
else if (function==FuncPlayValue) {
|
||||
populateSourceCB(b, RawSource(value), generalSettings, model, POPULATE_NONE|POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_SWITCHES|POPULATE_GVARS|POPULATE_TRIMS|POPULATE_TELEMETRY|POPULATE_TELEMETRYEXT|POPULATE_SCRIPT_OUTPUTS);
|
||||
b->setModel(rawSrcAllItemModel);
|
||||
b->setCurrentIndex(b->findData(value));
|
||||
}
|
||||
else if (function>=FuncAdjustGV1 && function<=FuncAdjustGVLast) {
|
||||
switch (adjustmode) {
|
||||
case 1:
|
||||
populateSourceCB(b, RawSource(value), generalSettings, model, POPULATE_NONE|POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_TRIMS|POPULATE_SWITCHES);
|
||||
b->setModel(rawSrcInputsItemModel);
|
||||
b->setCurrentIndex(b->findData(value));
|
||||
break;
|
||||
case 2:
|
||||
populateSourceCB(b, RawSource(value), generalSettings, model, POPULATE_GVARS);
|
||||
b->setModel(Helpers::getRawSourceItemModel(&generalSettings, model, POPULATE_GVARS));
|
||||
b->setCurrentIndex(b->findData(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,9 @@ class CustomFunctionsPanel : public GenericPanel
|
|||
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);
|
||||
QStandardItemModel * rawSwitchItemModel;
|
||||
QStandardItemModel * rawSrcInputsItemModel;
|
||||
QStandardItemModel * rawSrcAllItemModel;
|
||||
|
||||
QSet<QString> tracksSet;
|
||||
QSet<QString> scriptsSet;
|
||||
|
|
|
@ -60,7 +60,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
|
|||
curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model,
|
||||
firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES));
|
||||
|
||||
populateSwitchCB(ui->switchesCB, ed->swtch, generalSettings, MixesContext);
|
||||
ui->switchesCB->setModel(Helpers::getRawSwitchItemModel(&generalSettings, Helpers::MixesContext));
|
||||
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue()));
|
||||
|
||||
ui->sideCB->setCurrentIndex(ed->mode-1);
|
||||
|
||||
|
@ -90,8 +91,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
|
|||
|
||||
if (firmware->getCapability(VirtualInputs)) {
|
||||
ui->inputName->setMaxLength(firmware->getCapability(InputsLength));
|
||||
populateSourceCB(ui->sourceCB, ed->srcRaw, generalSettings, &model, POPULATE_NONE | POPULATE_SOURCES |
|
||||
POPULATE_SWITCHES | POPULATE_TRIMS | POPULATE_TELEMETRY);
|
||||
ui->sourceCB->setModel(Helpers::getRawSourceItemModel(&generalSettings, &model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SWITCHES | POPULATE_TRIMS | POPULATE_TELEMETRY));
|
||||
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue()));
|
||||
ui->sourceCB->removeItem(0);
|
||||
ui->inputName->setValidator(new QRegExpValidator(rx, this));
|
||||
ui->inputName->setText(inputName);
|
||||
|
|
|
@ -50,7 +50,8 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
|
|||
|
||||
// Phase switch
|
||||
if (phaseIdx > 0) {
|
||||
populateSwitchCB(ui->swtch, phase.swtch, generalSettings, MixesContext);
|
||||
ui->swtch->setModel(Helpers::getRawSwitchItemModel(&generalSettings, Helpers::MixesContext));
|
||||
ui->swtch->setCurrentIndex(ui->swtch->findData(phase.swtch.toValue()));
|
||||
connect(ui->swtch, SIGNAL(currentIndexChanged(int)), this, SLOT(phaseSwitch_currentIndexChanged(int)));
|
||||
}
|
||||
else {
|
||||
|
@ -129,7 +130,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
|
|||
// RE link to another RE
|
||||
reUse[i] = new QComboBox(ui->reGB);
|
||||
reUse[i]->setProperty("index", i);
|
||||
populateGvarUseCB(reUse[i], phaseIdx);
|
||||
Helpers::populateGvarUseCB(reUse[i], phaseIdx);
|
||||
if (phase.rotaryEncoders[i] > 1024) {
|
||||
reUse[i]->setCurrentIndex(phase.rotaryEncoders[i] - 1024);
|
||||
}
|
||||
|
@ -171,7 +172,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
|
|||
// GVar link to another GVar
|
||||
gvUse[i] = new QComboBox(ui->gvGB);
|
||||
gvUse[i]->setProperty("index", i);
|
||||
populateGvarUseCB(gvUse[i], phaseIdx);
|
||||
Helpers::populateGvarUseCB(gvUse[i], phaseIdx);
|
||||
if (phase.gvars[i] > 1024) {
|
||||
gvUse[i]->setCurrentIndex(phase.gvars[i] - 1024);
|
||||
}
|
||||
|
@ -219,9 +220,9 @@ void FlightModePanel::update()
|
|||
ui->fadeOut->setValue(float(phase.fadeOut)/scale);
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
int trimsMax = firmware->getCapability(ExtendedTrims);
|
||||
int trimsMax = firmware->getCapability(ExtendedTrimsRange);
|
||||
if (trimsMax == 0 || !model->extendedTrims) {
|
||||
trimsMax = 125;
|
||||
trimsMax = firmware->getCapability(TrimsRange);
|
||||
}
|
||||
trimsSlider[i]->setRange(-trimsMax, +trimsMax);
|
||||
trimsValue[i]->setRange(-trimsMax, +trimsMax);
|
||||
|
|
|
@ -28,6 +28,9 @@ HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & gener
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
rawSourceItemModel = Helpers::getRawSourceItemModel(&generalSettings, &model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS);
|
||||
rawSourceItemModel->setParent(this);
|
||||
|
||||
connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
|
||||
connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited()));
|
||||
connect(ui->swashCollectiveSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited()));
|
||||
|
@ -68,11 +71,14 @@ void HeliPanel::update()
|
|||
lock = true;
|
||||
|
||||
ui->swashType->setCurrentIndex(model->swashRingData.type);
|
||||
populateSourceCB(ui->swashCollectiveSource, model->swashRingData.collectiveSource, generalSettings, model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS);
|
||||
ui->swashCollectiveSource->setModel(rawSourceItemModel);
|
||||
ui->swashCollectiveSource->setCurrentIndex(ui->swashCollectiveSource->findData(model->swashRingData.collectiveSource.toValue()));
|
||||
ui->swashRingVal->setValue(model->swashRingData.value);
|
||||
if (firmware->getCapability(VirtualInputs)) {
|
||||
populateSourceCB(ui->swashElevatorSource, model->swashRingData.elevatorSource, generalSettings, model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS);
|
||||
populateSourceCB(ui->swashAileronSource, model->swashRingData.aileronSource, generalSettings, model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS);
|
||||
ui->swashElevatorSource->setModel(rawSourceItemModel);
|
||||
ui->swashElevatorSource->setCurrentIndex(ui->swashElevatorSource->findData(model->swashRingData.elevatorSource.toValue()));
|
||||
ui->swashAileronSource->setModel(rawSourceItemModel);
|
||||
ui->swashAileronSource->setCurrentIndex(ui->swashAileronSource->findData(model->swashRingData.aileronSource.toValue()));
|
||||
ui->swashElevatorWeight->setValue(model->swashRingData.elevatorWeight);
|
||||
ui->swashAileronWeight->setValue(model->swashRingData.aileronWeight);
|
||||
ui->swashCollectiveWeight->setValue(model->swashRingData.collectiveWeight);
|
||||
|
|
|
@ -41,6 +41,7 @@ class HeliPanel : public ModelPanel
|
|||
|
||||
private:
|
||||
Ui::Heli *ui;
|
||||
QStandardItemModel * rawSourceItemModel;
|
||||
};
|
||||
|
||||
#endif // _HELI_H_
|
||||
|
|
|
@ -28,6 +28,11 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
|
|||
Stopwatch s1("LogicalSwitchesPanel");
|
||||
|
||||
int channelsMax = model.getChannelsMax(true);
|
||||
rawSwitchItemModel = Helpers::getRawSwitchItemModel(&generalSettings, Helpers::LogicalSwitchesContext);
|
||||
rawSwitchItemModel->setParent(this);
|
||||
int srcFlags = POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (firmware->getCapability(GvarsInCS) ? POPULATE_GVARS : 0);
|
||||
rawSourceItemModel = Helpers::getRawSourceItemModel(&generalSettings, &model, srcFlags);
|
||||
rawSourceItemModel->setParent(this);
|
||||
|
||||
QStringList headerLabels;
|
||||
headerLabels << "#" << tr("Function") << tr("V1") << tr("V2") << tr("AND Switch");
|
||||
|
@ -309,7 +314,6 @@ void LogicalSwitchesPanel::setSwitchWidgetVisibility(int i)
|
|||
}
|
||||
else {
|
||||
mask = DELAY_ENABLED | DURATION_ENABLED;
|
||||
|
||||
switch (model->logicalSw[i].getFunctionFamily())
|
||||
{
|
||||
case LS_FAMILY_VOFS:
|
||||
|
@ -317,7 +321,8 @@ void LogicalSwitchesPanel::setSwitchWidgetVisibility(int i)
|
|||
mask |= SOURCE1_VISIBLE;
|
||||
RawSource source = RawSource(model->logicalSw[i].val1);
|
||||
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[i].getRangeFlags());
|
||||
populateSourceCB(cswitchSource1[i], source, generalSettings, model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (firmware->getCapability(GvarsInCS) ? POPULATE_GVARS : 0));
|
||||
cswitchSource1[i]->setModel(rawSourceItemModel);
|
||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(source.toValue()));
|
||||
cswitchOffset[i]->setDecimals(range.decimals);
|
||||
cswitchOffset[i]->setSingleStep(range.step);
|
||||
if (source.isTimeBased()) {
|
||||
|
@ -341,19 +346,22 @@ void LogicalSwitchesPanel::setSwitchWidgetVisibility(int i)
|
|||
cswitchOffset[i]->setMaximum(range.max);
|
||||
cswitchOffset[i]->setValue(range.step*(model->logicalSw[i].val2/* TODO+source.getRawOffset(model)*/)+range.offset);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case LS_FAMILY_STICKY:
|
||||
// no break
|
||||
case LS_FAMILY_STICKY: // no break
|
||||
case LS_FAMILY_VBOOL:
|
||||
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
|
||||
populateSwitchCB(cswitchSource1[i], RawSwitch(model->logicalSw[i].val1), generalSettings, LogicalSwitchesContext);
|
||||
populateSwitchCB(cswitchSource2[i], RawSwitch(model->logicalSw[i].val2), generalSettings, LogicalSwitchesContext);
|
||||
cswitchSource1[i]->setModel(rawSwitchItemModel);
|
||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
|
||||
cswitchSource2[i]->setModel(rawSwitchItemModel);
|
||||
cswitchSource2[i]->setCurrentIndex(cswitchSource2[i]->findData(model->logicalSw[i].val2));
|
||||
break;
|
||||
case LS_FAMILY_EDGE:
|
||||
mask |= SOURCE1_VISIBLE | VALUE2_VISIBLE | VALUE3_VISIBLE;
|
||||
mask &= ~DELAY_ENABLED;
|
||||
populateSwitchCB(cswitchSource1[i], RawSwitch(model->logicalSw[i].val1), generalSettings, LogicalSwitchesContext);
|
||||
cswitchSource1[i]->setModel(rawSwitchItemModel);
|
||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
|
||||
updateTimerParam(cswitchOffset[i], model->logicalSw[i].val2, 0.0);
|
||||
updateTimerParam(cswitchOffset2[i], model->logicalSw[i].val2+model->logicalSw[i].val3, ValToTim(TimToVal(cswitchOffset[i]->value())-1));
|
||||
cswitchOffset2[i]->setSpecialValueText(tr("(instant)"));
|
||||
|
@ -366,13 +374,16 @@ void LogicalSwitchesPanel::setSwitchWidgetVisibility(int i)
|
|||
break;
|
||||
case LS_FAMILY_VCOMP:
|
||||
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
|
||||
populateSourceCB(cswitchSource1[i], RawSource(model->logicalSw[i].val1), generalSettings, model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (firmware->getCapability(GvarsInCS) ? POPULATE_GVARS : 0));
|
||||
populateSourceCB(cswitchSource2[i], RawSource(model->logicalSw[i].val2), generalSettings, model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (firmware->getCapability(GvarsInCS) ? POPULATE_GVARS : 0));
|
||||
cswitchSource1[i]->setModel(rawSourceItemModel);
|
||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
|
||||
cswitchSource2[i]->setModel(rawSourceItemModel);
|
||||
cswitchSource2[i]->setCurrentIndex(cswitchSource2[i]->findData(model->logicalSw[i].val2));
|
||||
break;
|
||||
case LS_FAMILY_TIMER:
|
||||
mask |= VALUE1_VISIBLE | VALUE2_VISIBLE;
|
||||
updateTimerParam(cswitchValue[i], model->logicalSw[i].val1, 0.1);
|
||||
updateTimerParam(cswitchOffset[i], model->logicalSw[i].val2, 0.1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,7 +456,8 @@ void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b, const RawSwitch & v
|
|||
}
|
||||
|
||||
if (IS_ARM(firmware->getBoard())) {
|
||||
populateSwitchCB(b, value, generalSettings, LogicalSwitchesContext);
|
||||
b->setModel(rawSwitchItemModel);
|
||||
b->setCurrentIndex(b->findData(value.toValue()));
|
||||
}
|
||||
else {
|
||||
RawSwitch item;
|
||||
|
|
|
@ -58,6 +58,8 @@ class LogicalSwitchesPanel : public ModelPanel
|
|||
QDoubleSpinBox * cswitchDelay[CPN_MAX_CSW];
|
||||
QComboBox * cswitchSource1[CPN_MAX_CSW];
|
||||
QComboBox * cswitchSource2[CPN_MAX_CSW];
|
||||
QStandardItemModel * rawSwitchItemModel;
|
||||
QStandardItemModel * rawSourceItemModel;
|
||||
void setSwitchWidgetVisibility(int i);
|
||||
int selectedSwitch;
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, G
|
|||
|
||||
this->setWindowTitle(tr("DEST -> CH%1").arg(md->destCh));
|
||||
|
||||
populateSourceCB(ui->sourceCB, md->srcRaw, generalSettings, &model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS |
|
||||
POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS);
|
||||
ui->sourceCB->setModel(Helpers::getRawSourceItemModel(&generalSettings, &model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS));
|
||||
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue()));
|
||||
ui->sourceCB->removeItem(0);
|
||||
|
||||
int limit = firmware->getCapability(OffsetWeight);
|
||||
|
@ -103,7 +103,8 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, G
|
|||
}
|
||||
}
|
||||
|
||||
populateSwitchCB(ui->switchesCB, md->swtch, generalSettings, MixesContext);
|
||||
ui->switchesCB->setModel(Helpers::getRawSwitchItemModel(&generalSettings, Helpers::MixesContext));
|
||||
ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue()));
|
||||
ui->warningCB->setCurrentIndex(md->mixWarn);
|
||||
ui->mltpxCB->setCurrentIndex(md->mltpx);
|
||||
int scale=firmware->getCapability(SlowScale);
|
||||
|
|
|
@ -49,7 +49,9 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
|
|||
}
|
||||
|
||||
// Mode
|
||||
populateSwitchCB(ui->mode, timer.mode, generalSettings, TimersContext);
|
||||
ui->mode->setModel(Helpers::getRawSwitchItemModel(&generalSettings, Helpers::TimersContext));
|
||||
ui->mode->setCurrentIndex(ui->mode->findData(timer.mode.toValue()));
|
||||
//Helpers::populateSwitchCB(ui->mode, timer.mode, generalSettings, Helpers::TimersContext);
|
||||
|
||||
if (!firmware->getCapability(PermTimers)) {
|
||||
ui->persistent->hide();
|
||||
|
@ -887,19 +889,20 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
|||
// Beep Center checkboxes
|
||||
prevFocus = ui->trimsDisplay;
|
||||
int analogs = CPN_MAX_STICKS + getBoardCapability(board, Board::Pots) + getBoardCapability(board, Board::Sliders);
|
||||
for (int i=0; i<analogs+firmware->getCapability(RotaryEncoders); i++) {
|
||||
int genAryIdx = 0;
|
||||
for (int i=0; i < analogs + firmware->getCapability(RotaryEncoders); i++) {
|
||||
RawSource src((i < analogs) ? SOURCE_TYPE_STICK : SOURCE_TYPE_ROTARY_ENCODER, (i < analogs) ? i : analogs - i);
|
||||
QCheckBox * checkbox = new QCheckBox(this);
|
||||
checkbox->setProperty("index", i);
|
||||
checkbox->setText(i<analogs ? firmware->getAnalogInputName(i) : RotaryEncoderString(i-analogs));
|
||||
checkbox->setText(src.toString(&model, &generalSettings));
|
||||
ui->centerBeepLayout->addWidget(checkbox, 0, i+1);
|
||||
connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(onBeepCenterToggled(bool)));
|
||||
centerBeepCheckboxes << checkbox;
|
||||
if (IS_HORUS_OR_TARANIS(board)) {
|
||||
RawSource src(SOURCE_TYPE_STICK, i);
|
||||
if (src.isPot() && !generalSettings.isPotAvailable(i-CPN_MAX_STICKS)) {
|
||||
if (src.isPot(&genAryIdx) && !generalSettings.isPotAvailable(genAryIdx)) {
|
||||
checkbox->hide();
|
||||
}
|
||||
else if (src.isSlider() && !generalSettings.isSliderAvailable(i-CPN_MAX_STICKS-getBoardCapability(board, Board::Pots))) {
|
||||
else if (src.isSlider(&genAryIdx) && !generalSettings.isSliderAvailable(genAryIdx)) {
|
||||
checkbox->hide();
|
||||
}
|
||||
}
|
||||
|
@ -909,13 +912,12 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
|||
|
||||
// Startup switches warnings
|
||||
for (int i=0; i<getBoardCapability(board, Board::Switches); i++) {
|
||||
Board::SwitchInfo switchInfo = getSwitchInfo(board, i);
|
||||
if (IS_HORUS_OR_TARANIS(board)) {
|
||||
Board::SwitchInfo switchInfo = Boards::getSwitchInfo(board, i);
|
||||
switchInfo.config = Board::SwitchType(generalSettings.switchConfig[i]);
|
||||
}
|
||||
if (switchInfo.config == Board::SWITCH_NOT_AVAILABLE || switchInfo.config == Board::SWITCH_TOGGLE) {
|
||||
continue;
|
||||
}
|
||||
RawSource src(RawSourceType::SOURCE_TYPE_SWITCH, i);
|
||||
QLabel * label = new QLabel(this);
|
||||
QSlider * slider = new QSlider(this);
|
||||
QCheckBox * cb = new QCheckBox(this);
|
||||
|
@ -923,13 +925,14 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
|||
slider->setOrientation(Qt::Vertical);
|
||||
slider->setMinimum(0);
|
||||
slider->setInvertedAppearance(true);
|
||||
slider->setInvertedControls(true);
|
||||
slider->setTickPosition(QSlider::TicksBothSides);
|
||||
slider->setMinimumSize(QSize(30, 50));
|
||||
slider->setMaximumSize(QSize(50, 50));
|
||||
slider->setSingleStep(1);
|
||||
slider->setPageStep(1);
|
||||
slider->setTickInterval(1);
|
||||
label->setText(switchInfo.name);
|
||||
label->setText(src.toString(&model, &generalSettings));
|
||||
slider->setMaximum(switchInfo.config == Board::SWITCH_3POS ? 2 : 1);
|
||||
cb->setProperty("index", i);
|
||||
ui->switchesStartupLayout->addWidget(label, 0, i+1);
|
||||
|
@ -951,22 +954,19 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
|||
prevFocus = ui->potWarningMode;
|
||||
if (IS_HORUS_OR_TARANIS(board)) {
|
||||
for (int i=0; i<getBoardCapability(board, Board::Pots)+getBoardCapability(board, Board::Sliders); i++) {
|
||||
RawSource src(SOURCE_TYPE_STICK, CPN_MAX_STICKS + i);
|
||||
QCheckBox * cb = new QCheckBox(this);
|
||||
cb->setProperty("index", i);
|
||||
cb->setText(firmware->getAnalogInputName(i+4));
|
||||
cb->setText(src.toString(&model, &generalSettings));
|
||||
ui->potWarningLayout->addWidget(cb, 0, i+1);
|
||||
connect(cb, SIGNAL(toggled(bool)), this, SLOT(potWarningToggled(bool)));
|
||||
potWarningCheckboxes << cb;
|
||||
if (RawSource(SOURCE_TYPE_STICK, CPN_MAX_STICKS+i).isPot()) {
|
||||
if (!generalSettings.isPotAvailable(i)) {
|
||||
if (src.isPot(&genAryIdx) && !generalSettings.isPotAvailable(genAryIdx)) {
|
||||
cb->hide();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!generalSettings.isSliderAvailable(i-getBoardCapability(board, Board::Pots))) {
|
||||
else if (src.isSlider(&genAryIdx) && !generalSettings.isSliderAvailable(genAryIdx)) {
|
||||
cb->hide();
|
||||
}
|
||||
}
|
||||
QWidget::setTabOrder(prevFocus, cb);
|
||||
prevFocus = cb;
|
||||
}
|
||||
|
|
|
@ -352,7 +352,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
|
|||
|
||||
if (IS_TARANIS(firmware->getBoard())) {
|
||||
QSet<QString> scriptsSet = getFilesSet(g.profile[g.id()].sdPath() + "/SCRIPTS/TELEMETRY", QStringList() << "*.lua", 8);
|
||||
populateFileComboBox(ui->scriptName, scriptsSet, screen.body.script.filename);
|
||||
Helpers::populateFileComboBox(ui->scriptName, scriptsSet, screen.body.script.filename);
|
||||
connect(ui->scriptName, SIGNAL(currentIndexChanged(int)), this, SLOT(scriptNameEdited()));
|
||||
connect(ui->scriptName, SIGNAL(editTextChanged ( const QString)), this, SLOT(scriptNameEdited()));
|
||||
}
|
||||
|
@ -362,12 +362,15 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
|
|||
|
||||
void TelemetryCustomScreen::populateTelemetrySourceCB(QComboBox * b, RawSource & source, bool last)
|
||||
{
|
||||
int flags = POPULATE_NONE | POPULATE_TELEMETRY;
|
||||
if (IS_ARM(firmware->getBoard())) {
|
||||
populateSourceCB(b, source, generalSettings, model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | POPULATE_TELEMETRY | (firmware->getCapability(GvarsInCS) ? POPULATE_GVARS : 0));
|
||||
flags |= POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_TRIMS | POPULATE_SWITCHES | (firmware->getCapability(GvarsInCS) ? POPULATE_GVARS : 0);
|
||||
}
|
||||
else {
|
||||
populateSourceCB(b, source, generalSettings, model, POPULATE_NONE | POPULATE_TELEMETRY | (last ? POPULATE_TELEMETRYEXT : 0));
|
||||
else if (last) {
|
||||
flags |= POPULATE_TELEMETRYEXT;
|
||||
}
|
||||
b->setModel(Helpers::getRawSourceItemModel(&generalSettings, model, flags));
|
||||
b->setCurrentIndex(b->findData(source.toValue()));
|
||||
}
|
||||
|
||||
TelemetryCustomScreen::~TelemetryCustomScreen()
|
||||
|
@ -454,7 +457,7 @@ void TelemetryCustomScreen::scriptNameEdited()
|
|||
{
|
||||
if (!lock) {
|
||||
lock = true;
|
||||
getFileComboBoxValue(ui->scriptName, screen.body.script.filename, 8);
|
||||
Helpers::getFileComboBoxValue(ui->scriptName, screen.body.script.filename, 8);
|
||||
emit modified();
|
||||
lock = false;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "helpers.h"
|
||||
#include "modelprinter.h"
|
||||
#include "multiprotocols.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
|
@ -342,7 +344,7 @@ QString ModelPrinter::printInputName(int idx)
|
|||
}
|
||||
}
|
||||
else {
|
||||
result = RawSource(SOURCE_TYPE_STICK, idx).toString(&model);
|
||||
result = RawSource(SOURCE_TYPE_STICK, idx).toString(&model, &generalSettings);
|
||||
}
|
||||
return result.toHtmlEscaped();
|
||||
}
|
||||
|
@ -363,22 +365,26 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
|
|||
}
|
||||
|
||||
if (firmware->getCapability(VirtualInputs)) {
|
||||
str += input.srcRaw.toString(&model).toHtmlEscaped();
|
||||
str += input.srcRaw.toString(&model, &generalSettings).toHtmlEscaped();
|
||||
}
|
||||
|
||||
str += " " + tr("Weight").toHtmlEscaped() + QString("(%1)").arg(getGVarString(input.weight,true).toHtmlEscaped());
|
||||
if (input.curve.value) str += " " + input.curve.toString().toHtmlEscaped();
|
||||
if (input.curve.value)
|
||||
str += " " + input.curve.toString().toHtmlEscaped();
|
||||
|
||||
QString flightModesStr = printFlightModes(input.flightModes);
|
||||
if (!flightModesStr.isEmpty()) str += " " + flightModesStr.toHtmlEscaped();
|
||||
if (!flightModesStr.isEmpty())
|
||||
str += " " + flightModesStr.toHtmlEscaped();
|
||||
|
||||
if (input.swtch.type != SWITCH_TYPE_NONE)
|
||||
str += " " + tr("Switch").toHtmlEscaped() + QString("(%1)").arg(input.swtch.toString().toHtmlEscaped());
|
||||
str += " " + tr("Switch").toHtmlEscaped() + QString("(%1)").arg(input.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped();
|
||||
|
||||
|
||||
if (firmware->getCapability(VirtualInputs)) {
|
||||
if (input.carryTrim>0) str += " " + tr("NoTrim").toHtmlEscaped();
|
||||
else if (input.carryTrim<0) str += " " + RawSource(SOURCE_TYPE_TRIM, (-(input.carryTrim)-1)).toString(&model).toHtmlEscaped();
|
||||
if (input.carryTrim>0)
|
||||
str += " " + tr("NoTrim").toHtmlEscaped();
|
||||
else if (input.carryTrim<0)
|
||||
str += " " + RawSource(SOURCE_TYPE_TRIM, (-(input.carryTrim)-1)).toString(&model, &generalSettings).toHtmlEscaped();
|
||||
}
|
||||
|
||||
if (input.offset)
|
||||
|
@ -424,7 +430,7 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in
|
|||
str += " ";
|
||||
}
|
||||
// highlight source if needed
|
||||
QString source = mix.srcRaw.toString(&model).toHtmlEscaped();
|
||||
QString source = mix.srcRaw.toString(&model, &generalSettings).toHtmlEscaped();
|
||||
if ( (mix.srcRaw.type == SOURCE_TYPE_CH) && (mix.srcRaw.index+1 == (int)highlightedSource) ) {
|
||||
source = "<b>" + source + "</b>";
|
||||
}
|
||||
|
@ -440,12 +446,12 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in
|
|||
str += " " + flightModesStr.toHtmlEscaped();
|
||||
|
||||
if (mix.swtch.type != SWITCH_TYPE_NONE)
|
||||
str += " " + tr("Switch(%1)").arg(mix.swtch.toString()).toHtmlEscaped();
|
||||
str += " " + tr("Switch(%1)").arg(mix.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped();
|
||||
|
||||
if (mix.carryTrim > 0)
|
||||
str += " " + tr("NoTrim").toHtmlEscaped();
|
||||
else if (mix.carryTrim < 0)
|
||||
str += " " + RawSource(SOURCE_TYPE_TRIM, (-(mix.carryTrim)-1)).toString(&model);
|
||||
str += " " + RawSource(SOURCE_TYPE_TRIM, (-(mix.carryTrim)-1)).toString(&model, &generalSettings);
|
||||
|
||||
if (firmware->getCapability(HasNoExpo) && mix.noExpo)
|
||||
str += " " + tr("No DR/Expo").toHtmlEscaped();
|
||||
|
@ -467,16 +473,9 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in
|
|||
return str;
|
||||
}
|
||||
|
||||
QString ModelPrinter::printFlightModeSwitch(int index)
|
||||
QString ModelPrinter::printFlightModeSwitch(const RawSwitch & swtch)
|
||||
{
|
||||
if (index == 0)
|
||||
return "---";
|
||||
else if (index > 0) {
|
||||
return printFlightModeName(index-1);
|
||||
}
|
||||
else {
|
||||
return "!" + printFlightModeName(-index-1);
|
||||
}
|
||||
return swtch.toString(getCurrentBoard(), &generalSettings);
|
||||
}
|
||||
|
||||
QString ModelPrinter::printFlightModeName(int index)
|
||||
|
@ -517,6 +516,8 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
|
|||
{
|
||||
QString result = "";
|
||||
const LogicalSwitchData & ls = model.logicalSw[idx];
|
||||
const QString sw1Name = RawSwitch(ls.val1).toString(getCurrentBoard(), &generalSettings);
|
||||
const QString sw2Name = RawSwitch(ls.val2).toString(getCurrentBoard(), &generalSettings);
|
||||
|
||||
if (!ls.func)
|
||||
return result;
|
||||
|
@ -526,10 +527,10 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
|
|||
}
|
||||
switch (ls.getFunctionFamily()) {
|
||||
case LS_FAMILY_EDGE:
|
||||
result += tr("Edge(%1, [%2:%3])").arg(RawSwitch(ls.val1).toString()).arg(ValToTim(ls.val2)).arg(ls.val3<0 ? tr("instant") : QString("%1").arg(ValToTim(ls.val2+ls.val3)));
|
||||
result += tr("Edge(%1, [%2:%3])").arg(sw1Name).arg(ValToTim(ls.val2)).arg(ls.val3<0 ? tr("instant") : QString("%1").arg(ValToTim(ls.val2+ls.val3)));
|
||||
break;
|
||||
case LS_FAMILY_STICKY:
|
||||
result += tr("Sticky(%1, %2)").arg(RawSwitch(ls.val1).toString()).arg(RawSwitch(ls.val2).toString());
|
||||
result += tr("Sticky(%1, %2)").arg(sw1Name).arg(sw2Name);
|
||||
break;
|
||||
case LS_FAMILY_TIMER:
|
||||
result += tr("Timer(%1, %2)").arg(ValToTim(ls.val1)).arg(ValToTim(ls.val2));
|
||||
|
@ -539,7 +540,7 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
|
|||
RawSourceRange range = source.getRange(&model, generalSettings);
|
||||
QString res;
|
||||
if (ls.val1)
|
||||
res += source.toString(&model);
|
||||
res += source.toString(&model, &generalSettings);
|
||||
else
|
||||
res += "0";
|
||||
res.remove(" ");
|
||||
|
@ -564,7 +565,7 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
|
|||
break;
|
||||
}
|
||||
case LS_FAMILY_VBOOL:
|
||||
result += RawSwitch(ls.val1).toString();
|
||||
result += sw1Name;
|
||||
switch (ls.func) {
|
||||
case LS_FN_AND:
|
||||
result += " AND ";
|
||||
|
@ -579,12 +580,12 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
|
|||
result += " bar ";
|
||||
break;
|
||||
}
|
||||
result += RawSwitch(ls.val2).toString();
|
||||
result += sw2Name;
|
||||
break;
|
||||
|
||||
case LS_FAMILY_VCOMP:
|
||||
if (ls.val1)
|
||||
result += RawSource(ls.val1).toString(&model);
|
||||
result += RawSource(ls.val1).toString(&model, &generalSettings);
|
||||
else
|
||||
result += "0";
|
||||
switch (ls.func) {
|
||||
|
@ -612,7 +613,7 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
|
|||
break;
|
||||
}
|
||||
if (ls.val2)
|
||||
result += RawSource(ls.val2).toString(&model);
|
||||
result += RawSource(ls.val2).toString(&model, &generalSettings);
|
||||
else
|
||||
result += "0";
|
||||
break;
|
||||
|
@ -620,7 +621,7 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
|
|||
|
||||
if (ls.andsw != 0) {
|
||||
result +=" ) AND ";
|
||||
result += RawSwitch(ls.andsw).toString();
|
||||
result += RawSwitch(ls.andsw).toString(getCurrentBoard(), &generalSettings);
|
||||
}
|
||||
|
||||
if (firmware->getCapability(LogicalSwitchesExt)) {
|
||||
|
@ -637,13 +638,16 @@ QString ModelPrinter::printCustomFunctionLine(int idx)
|
|||
{
|
||||
QString result;
|
||||
const CustomFunctionData & cf = model.customFn[idx];
|
||||
if (cf.swtch.type == SWITCH_TYPE_NONE) return result;
|
||||
if (cf.swtch.type == SWITCH_TYPE_NONE)
|
||||
return result;
|
||||
|
||||
result += cf.swtch.toString() + " - ";
|
||||
result += cf.swtch.toString(getCurrentBoard(), &generalSettings) + " - ";
|
||||
result += cf.funcToString() + "(";
|
||||
result += cf.paramToString(&model) + ")";
|
||||
if (!cf.repeatToString().isEmpty()) result += " " + cf.repeatToString();
|
||||
if (!cf.enabledToString().isEmpty()) result += " " + cf.enabledToString();
|
||||
if (!cf.repeatToString().isEmpty())
|
||||
result += " " + cf.repeatToString();
|
||||
if (!cf.enabledToString().isEmpty())
|
||||
result += " " + cf.enabledToString();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class ModelPrinter: public QObject
|
|||
static QString printModuleProtocol(unsigned int protocol);
|
||||
static QString printMultiRfProtocol(int rfProtocol, bool custom);
|
||||
static QString printMultiSubType(int rfProtocol, bool custom, unsigned int subType);
|
||||
QString printFlightModeSwitch(int index);
|
||||
QString printFlightModeSwitch(const RawSwitch & swtch);
|
||||
QString printFlightModeName(int index);
|
||||
QString printFlightModes(unsigned int flightModes);
|
||||
QString printModule(int idx);
|
||||
|
|
|
@ -247,7 +247,7 @@ void TreeModel::refresh()
|
|||
Board::Type board = eepromInterface->getBoard();
|
||||
|
||||
if (!IS_SKY9X(board) && !IS_HORUS(board)) {
|
||||
availableEEpromSize = getEEpromSize(board) - 64; // let's consider fat
|
||||
availableEEpromSize = Boards::getEEpromSize(board) - 64; // let's consider fat
|
||||
availableEEpromSize -= 16 * ((eepromInterface->getSize(radioData->generalSettings) + 14) / 15);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,9 +101,9 @@ bool MultiModelPrinter::MultiColumns::isEmpty()
|
|||
|
||||
#define COMPARE(what) \
|
||||
columns.beginCompare(); \
|
||||
for (int cc=0; cc<models.size(); cc++) { \
|
||||
ModelPrinter * modelPrinter = modelPrinters[cc]; \
|
||||
ModelData * model = models[cc]; \
|
||||
for (int cc=0; cc < modelPrinterMap.size(); cc++) { \
|
||||
ModelPrinter * modelPrinter = modelPrinterMap.value(cc).second; \
|
||||
const ModelData * model = modelPrinterMap.value(cc).first; \
|
||||
(void)(model); (void)(modelPrinter); \
|
||||
columns.append(cc, (what)); \
|
||||
} \
|
||||
|
@ -111,7 +111,7 @@ bool MultiModelPrinter::MultiColumns::isEmpty()
|
|||
|
||||
QString MultiModelPrinter::printTitle(const QString & label)
|
||||
{
|
||||
return QString("<tr><td colspan='%1'><h2>").arg(modelPrinters.count()) + label + "</h2></td></tr>";
|
||||
return QString("<tr><td colspan='%1'><h2>").arg(modelPrinterMap.count()) + label + "</h2></td></tr>";
|
||||
}
|
||||
|
||||
MultiModelPrinter::MultiModelPrinter(Firmware * firmware):
|
||||
|
@ -121,25 +121,27 @@ MultiModelPrinter::MultiModelPrinter(Firmware * firmware):
|
|||
|
||||
MultiModelPrinter::~MultiModelPrinter()
|
||||
{
|
||||
for(int i=0; i<modelPrinters.size(); i++) {
|
||||
delete modelPrinters[i];
|
||||
for(int i=0; i < modelPrinterMap.size(); i++) {
|
||||
if (modelPrinterMap.value(i).second)
|
||||
delete modelPrinterMap.value(i).second;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiModelPrinter::setModel(int idx, const ModelData & model, const GeneralSettings & generalSettings)
|
||||
{
|
||||
if (modelPrinterMap.contains(idx) && modelPrinterMap.value(idx).second) {
|
||||
// free existing model printer
|
||||
delete modelPrinterMap.value(idx).second;
|
||||
modelPrinterMap[idx].second = NULL;
|
||||
}
|
||||
|
||||
QPair<const ModelData *, ModelPrinter *> pair(&model, new ModelPrinter(firmware, generalSettings, model));
|
||||
modelPrinterMap.insert(idx, pair); // QMap.insert will replace any existing key
|
||||
}
|
||||
|
||||
void MultiModelPrinter::setModel(int idx, const ModelData & model)
|
||||
{
|
||||
int count = std::max(models.size(), idx+1);
|
||||
models.resize(count);
|
||||
modelPrinters.resize(count);
|
||||
|
||||
if (modelPrinters[idx]) {
|
||||
// free existing model printer
|
||||
delete modelPrinters[idx];
|
||||
modelPrinters[idx] = 0;
|
||||
}
|
||||
|
||||
models[idx] = (ModelData *)&model; // TODO remove cast
|
||||
modelPrinters[idx] = new ModelPrinter(firmware, defaultSettings, model);
|
||||
setModel(idx, model, defaultSettings);
|
||||
}
|
||||
|
||||
QString MultiModelPrinter::print(QTextDocument * document)
|
||||
|
@ -169,7 +171,7 @@ QString MultiModelPrinter::printSetup()
|
|||
{
|
||||
QString str = printTitle(tr("General Model Settings"));
|
||||
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.appendTitle(tr("Name:"));
|
||||
COMPARE(model->name);
|
||||
columns.append("<br/>");
|
||||
|
@ -207,15 +209,15 @@ QString MultiModelPrinter::printSetup()
|
|||
QString MultiModelPrinter::printHeliSetup()
|
||||
{
|
||||
bool heliEnabled = false;
|
||||
for (int k=0; k<models.size(); k++) {
|
||||
heliEnabled = heliEnabled || models[k]->swashRingData.type != HELI_SWASH_TYPE_NONE;
|
||||
for (int k=0; k < modelPrinterMap.size(); k++) {
|
||||
heliEnabled = heliEnabled || modelPrinterMap.value(k).first->swashRingData.type != HELI_SWASH_TYPE_NONE;
|
||||
}
|
||||
|
||||
if (!heliEnabled)
|
||||
return "";
|
||||
|
||||
QString str = printTitle(tr("Helicopter Setup"));
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.appendTitle (tr("Swash Type:"));
|
||||
COMPARE(modelPrinter->printHeliSwashType());
|
||||
columns.append ("<br/>");
|
||||
|
@ -260,15 +262,15 @@ QString MultiModelPrinter::printFlightModes()
|
|||
|
||||
// Trims
|
||||
{
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table cellspacing='0' cellpadding='1' width='100%' border='0' style='border-collapse:collapse'>");
|
||||
columns.append("<tr>");
|
||||
columns.append("<td><b>" + tr("Flight mode") + "</b></td>");
|
||||
columns.append("<td><b>" + tr("Switch") + "</b></td>");
|
||||
columns.append("<td><b>" + tr("Fade IN") + "</b></td>");
|
||||
columns.append("<td><b>" + tr("Fade OUT") + "</b></td>");
|
||||
for (int i=0; i<4; i++) {
|
||||
columns.append("<td><b>" + getCurrentFirmware()->getAnalogInputName(i) + " trim</b></td>");
|
||||
for (int i=0; i < getBoardCapability(getCurrentBoard(), Board::NumTrims); i++) {
|
||||
columns.append("<td><b>" + RawSource(SOURCE_TYPE_TRIM, i).toString() + "</b></td>");
|
||||
}
|
||||
columns.append("</tr>");
|
||||
|
||||
|
@ -276,13 +278,13 @@ QString MultiModelPrinter::printFlightModes()
|
|||
columns.append("<tr><td><b>" + tr("FM%1").arg(i) + "</b> ");
|
||||
COMPARE(model->flightModeData[i].name);
|
||||
columns.append("</td><td>");
|
||||
COMPARE(model->flightModeData[i].swtch.toString());
|
||||
COMPARE(modelPrinter->printFlightModeSwitch(model->flightModeData[i].swtch));
|
||||
columns.append("</td><td>");
|
||||
COMPARE(model->flightModeData[i].fadeIn);
|
||||
columns.append("</td><td>");
|
||||
COMPARE(model->flightModeData[i].fadeOut);
|
||||
columns.append("</td>");
|
||||
for (int k=0; k<CPN_MAX_STICKS; k++) {
|
||||
for (int k=0; k < getBoardCapability(getCurrentBoard(), Board::NumTrims); k++) {
|
||||
columns.append("<td>");
|
||||
COMPARE(modelPrinter->printTrim(i, k));
|
||||
columns.append("</td>");
|
||||
|
@ -297,7 +299,7 @@ QString MultiModelPrinter::printFlightModes()
|
|||
// GVars and Rotary Encoders
|
||||
int gvars = firmware->getCapability(Gvars);
|
||||
if ((gvars && firmware->getCapability(GvarsFlightModes)) || firmware->getCapability(RotaryEncoders)) {
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table cellspacing='0' cellpadding='1' width='100%' border='0' style='border-collapse:collapse'>");
|
||||
columns.append("<tr><td><b>" + tr("Flight mode") + "</b></td>");
|
||||
if (firmware->getCapability(GvarsFlightModes)) {
|
||||
|
@ -339,7 +341,7 @@ QString MultiModelPrinter::printFlightModes()
|
|||
QString MultiModelPrinter::printLimits()
|
||||
{
|
||||
QString str = printTitle(tr("Limits"));
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table border='0' cellspacing='0' cellpadding='1' width='100%'>" \
|
||||
"<tr>" \
|
||||
" <td><b>" + tr("Channel") + "</b></td>" \
|
||||
|
@ -350,6 +352,11 @@ QString MultiModelPrinter::printLimits()
|
|||
" <td><b>" + tr("Invert") + "</b></td>" \
|
||||
"</tr>");
|
||||
for (int i=0; i<firmware->getCapability(Outputs); i++) {
|
||||
int count = 0;
|
||||
for (int k=0; k < modelPrinterMap.size(); k++)
|
||||
count = std::max(count, modelPrinterMap.value(k).first->mixes(i).size());
|
||||
if (!count)
|
||||
continue;
|
||||
columns.append("<tr><td><b>");
|
||||
COMPARE(modelPrinter->printChannelName(i));
|
||||
columns.append("</b></td><td>");
|
||||
|
@ -363,6 +370,7 @@ QString MultiModelPrinter::printLimits()
|
|||
columns.append("</td><td>");
|
||||
COMPARE(model->limitData[i].revertToString());
|
||||
columns.append("</td></tr>");
|
||||
|
||||
}
|
||||
columns.append("</table>");
|
||||
str.append(columns.print());
|
||||
|
@ -373,7 +381,7 @@ QString MultiModelPrinter::printGvars()
|
|||
{
|
||||
QString str = printTitle(tr("Global Variables"));
|
||||
int gvars = firmware->getCapability(Gvars);
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table border='0' cellspacing='0' cellpadding='1' width='100%'><tr>");
|
||||
for (int i=0; i<gvars; i++) {
|
||||
columns.append(QString("<td><b>") + tr("GV%1").arg(i+1) + "</b></td>");
|
||||
|
@ -392,12 +400,12 @@ QString MultiModelPrinter::printGvars()
|
|||
QString MultiModelPrinter::printInputs()
|
||||
{
|
||||
QString str = printTitle(tr("Inputs"));
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table cellspacing='0' cellpadding='1' width='100%' border='0' style='border-collapse:collapse'>");
|
||||
for (int i=0; i<std::max(4, firmware->getCapability(VirtualInputs)); i++) {
|
||||
int count = 0;
|
||||
for (int k=0; k<models.size(); k++) {
|
||||
count = std::max(count, models[k]->expos(i).size());
|
||||
for (int k=0; k < modelPrinterMap.size(); k++) {
|
||||
count = std::max(count, modelPrinterMap.value(k).first->expos(i).size());
|
||||
}
|
||||
if (count > 0) {
|
||||
columns.append("<tr><td width='20%'><b>");
|
||||
|
@ -418,12 +426,12 @@ QString MultiModelPrinter::printInputs()
|
|||
QString MultiModelPrinter::printMixers()
|
||||
{
|
||||
QString str = printTitle(tr("Mixers"));
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table cellspacing='0' cellpadding='1' width='100%' border='0' style='border-collapse:collapse'>");
|
||||
for (int i=0; i<firmware->getCapability(Outputs); i++) {
|
||||
int count = 0;
|
||||
for (int k=0; k<models.size(); k++) {
|
||||
count = std::max(count, models[k]->mixes(i).size());
|
||||
for (int k=0; k < modelPrinterMap.size(); k++) {
|
||||
count = std::max(count, modelPrinterMap.value(k).first->mixes(i).size());
|
||||
}
|
||||
if (count > 0) {
|
||||
columns.append("<tr><td width='20%'><b>");
|
||||
|
@ -444,13 +452,13 @@ QString MultiModelPrinter::printMixers()
|
|||
QString MultiModelPrinter::printCurves(QTextDocument * document)
|
||||
{
|
||||
QString str;
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
int count = 0;
|
||||
columns.append("<table cellspacing='0' cellpadding='1' width='100%' border='0' style='border-collapse:collapse'>");
|
||||
for (int i=0; i<firmware->getCapability(NumCurves); i++) {
|
||||
bool curveEmpty = true;
|
||||
for (int k=0; k<models.size(); k++) {
|
||||
if (!models[k]->curves[i].isEmpty()) {
|
||||
for (int k=0; k < modelPrinterMap.size(); k++) {
|
||||
if (!modelPrinterMap.value(k).first->curves[i].isEmpty()) {
|
||||
curveEmpty = false;
|
||||
break;
|
||||
}
|
||||
|
@ -459,8 +467,8 @@ QString MultiModelPrinter::printCurves(QTextDocument * document)
|
|||
count++;
|
||||
columns.append("<tr><td width='20%'><b>" + tr("CV%1").arg(i+1) + "</b></td><td>");
|
||||
COMPARE(modelPrinter->printCurve(i));
|
||||
for (int k=0; k<models.size(); k++)
|
||||
columns.append(k, QString("<br/><img src='%1' border='0' />").arg(modelPrinters[k]->createCurveImage(i, document)));
|
||||
for (int k=0; k < modelPrinterMap.size(); k++)
|
||||
columns.append(k, QString("<br/><img src='%1' border='0' />").arg(modelPrinterMap.value(k).second->createCurveImage(i, document)));
|
||||
columns.append("</td></tr>");
|
||||
}
|
||||
}
|
||||
|
@ -475,13 +483,13 @@ QString MultiModelPrinter::printCurves(QTextDocument * document)
|
|||
QString MultiModelPrinter::printLogicalSwitches()
|
||||
{
|
||||
QString str;
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
int count = 0;
|
||||
columns.append("<table cellspacing='0' cellpadding='1' width='100%' border='0' style='border-collapse:collapse'>");
|
||||
for (int i=0; i<firmware->getCapability(LogicalSwitches); i++) {
|
||||
bool lsEmpty = true;
|
||||
for (int k=0; k<models.size(); k++) {
|
||||
if (!modelPrinters[k]->printLogicalSwitchLine(i).isEmpty()) {
|
||||
for (int k=0; k < modelPrinterMap.size(); k++) {
|
||||
if (!modelPrinterMap.value(k).second->printLogicalSwitchLine(i).isEmpty()) {
|
||||
lsEmpty = false;
|
||||
break;
|
||||
}
|
||||
|
@ -504,13 +512,13 @@ QString MultiModelPrinter::printLogicalSwitches()
|
|||
QString MultiModelPrinter::printCustomFunctions()
|
||||
{
|
||||
QString str;
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
int count = 0;
|
||||
columns.append("<table cellspacing='0' cellpadding='1' width='100%' border='0' style='border-collapse:collapse'>");
|
||||
for (int i=0; i<firmware->getCapability(CustomFunctions); i++) {
|
||||
for (int i=0; i < firmware->getCapability(CustomFunctions); i++) {
|
||||
bool sfEmpty = true;
|
||||
for (int k=0; k<models.size(); k++) {
|
||||
if (!modelPrinters[k]->printCustomFunctionLine(i).isEmpty()) {
|
||||
for (int k=0; k < modelPrinterMap.size(); k++) {
|
||||
if (modelPrinterMap.value(k).first->customFn[i].swtch.type != SWITCH_TYPE_NONE) {
|
||||
sfEmpty = false;
|
||||
break;
|
||||
}
|
||||
|
@ -536,7 +544,7 @@ QString MultiModelPrinter::printTelemetry()
|
|||
|
||||
// Analogs on non ARM boards
|
||||
if (!IS_ARM(firmware->getBoard())) {
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table border='0' cellspacing='0' cellpadding='1' width='100%'>" \
|
||||
"<tr><td width='22%'><b>" + tr("Analogs") + "</b></td><td width='26%'><b>" + tr("Unit") + "</b></td><td width='26%'><b>" + tr("Scale") + "</b></td><td width='26%'><b>" + tr("Offset") + "</b></td></tr>");
|
||||
for (int i=0; i<2; i++) {
|
||||
|
@ -555,7 +563,7 @@ QString MultiModelPrinter::printTelemetry()
|
|||
|
||||
// RSSI alarms
|
||||
{
|
||||
MultiColumns columns(models.size());
|
||||
MultiColumns columns(modelPrinterMap.size());
|
||||
columns.append("<table border='0' cellspacing='0' cellpadding='1' width='100%'>");
|
||||
for (int i=0; i<2; i++) {
|
||||
columns.append("<tr><td><b>" + QString(i==0 ? tr("RSSI Alarms") : "") + "</b></td><td>");
|
||||
|
|
|
@ -34,6 +34,7 @@ class MultiModelPrinter: public QObject
|
|||
MultiModelPrinter(Firmware * firmware);
|
||||
virtual ~MultiModelPrinter();
|
||||
|
||||
void setModel(int idx, const ModelData & model, const GeneralSettings & generalSettings);
|
||||
void setModel(int idx, const ModelData & model);
|
||||
QString print(QTextDocument * document);
|
||||
|
||||
|
@ -58,8 +59,7 @@ class MultiModelPrinter: public QObject
|
|||
|
||||
Firmware * firmware;
|
||||
GeneralSettings defaultSettings;
|
||||
QVector<ModelData *> models; // TODO const
|
||||
QVector<ModelPrinter *> modelPrinters;
|
||||
QMap<int, QPair<const ModelData *, ModelPrinter *> > modelPrinterMap;
|
||||
|
||||
QString printTitle(const QString & label);
|
||||
QString printSetup();
|
||||
|
|
|
@ -36,7 +36,7 @@ PrintDialog::PrintDialog(QWidget *parent, Firmware * firmware, GeneralSettings &
|
|||
ui->setupUi(this);
|
||||
setWindowIcon(CompanionIcon("print.png"));
|
||||
setWindowTitle(model.name);
|
||||
multimodelprinter.setModel(0, model);
|
||||
multimodelprinter.setModel(0, model, generalSettings);
|
||||
ui->textEdit->setHtml(multimodelprinter.print(ui->textEdit->document()));
|
||||
if (!printfilename.isEmpty()) {
|
||||
printToFile();
|
||||
|
|
|
@ -218,7 +218,7 @@ class RawSource {
|
|||
return index >= 0 ? (type * 65536 + index) : -(type * 65536 - index);
|
||||
}
|
||||
|
||||
QString toString(const ModelData * model = NULL) const;
|
||||
QString toString(const ModelData * model = NULL, const GeneralSettings * const generalSettings = NULL) const;
|
||||
|
||||
RawSourceRange getRange(const ModelData * model, const GeneralSettings & settings, unsigned int flags=0) const;
|
||||
|
||||
|
@ -231,8 +231,8 @@ class RawSource {
|
|||
}
|
||||
|
||||
bool isTimeBased() const;
|
||||
bool isPot() const;
|
||||
bool isSlider() const;
|
||||
bool isPot(int * potsIndex = NULL) const;
|
||||
bool isSlider(int * sliderIndex = NULL) const;
|
||||
|
||||
RawSourceType type;
|
||||
int index;
|
||||
|
@ -277,7 +277,7 @@ class RawSwitch {
|
|||
return index >= 0 ? (type * 256 + index) : -(type * 256 - index);
|
||||
}
|
||||
|
||||
QString toString(Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||
QString toString(Board::Type board = Board::BOARD_UNKNOWN, const GeneralSettings * const generalSettings = NULL) const;
|
||||
|
||||
bool operator== ( const RawSwitch& other) {
|
||||
return (this->type == other.type) && (this->index == other.index);
|
||||
|
@ -541,9 +541,9 @@ class CustomFunctionData { // Function Switches data
|
|||
class FlightModeData {
|
||||
public:
|
||||
FlightModeData() { clear(0); }
|
||||
int trimMode[CPN_MAX_STICKS+CPN_MAX_AUX_TRIMS];
|
||||
int trimRef[CPN_MAX_STICKS+CPN_MAX_AUX_TRIMS];
|
||||
int trim[CPN_MAX_STICKS+CPN_MAX_AUX_TRIMS];
|
||||
int trimMode[CPN_MAX_TRIMS];
|
||||
int trimRef[CPN_MAX_TRIMS];
|
||||
int trim[CPN_MAX_TRIMS];
|
||||
RawSwitch swtch;
|
||||
char name[10+1];
|
||||
unsigned int fadeIn;
|
||||
|
@ -1127,9 +1127,9 @@ class GeneralSettings {
|
|||
|
||||
unsigned int version;
|
||||
unsigned int variant;
|
||||
int calibMid[CPN_MAX_STICKS+CPN_MAX_POTS+CPN_MAX_MOUSE_ANALOGS];
|
||||
int calibSpanNeg[CPN_MAX_STICKS+CPN_MAX_POTS+CPN_MAX_MOUSE_ANALOGS];
|
||||
int calibSpanPos[CPN_MAX_STICKS+CPN_MAX_POTS+CPN_MAX_MOUSE_ANALOGS];
|
||||
int calibMid[CPN_MAX_ANALOGS];
|
||||
int calibSpanNeg[CPN_MAX_ANALOGS];
|
||||
int calibSpanPos[CPN_MAX_ANALOGS];
|
||||
unsigned int currModelIndex;
|
||||
char currModelFilename[16+1];
|
||||
unsigned int contrast;
|
||||
|
@ -1201,13 +1201,13 @@ class GeneralSettings {
|
|||
unsigned int hw_uartMode;
|
||||
unsigned int backlightColor;
|
||||
CustomFunctionData customFn[CPN_MAX_CUSTOM_FUNCTIONS];
|
||||
char switchName[18][3+1];
|
||||
char switchName[CPN_MAX_SWITCHES][3+1];
|
||||
unsigned int switchConfig[CPN_MAX_SWITCHES];
|
||||
char stickName[4][3+1];
|
||||
char potName[4][3+1];
|
||||
unsigned int potConfig[4];
|
||||
char sliderName[4][3+1];
|
||||
unsigned int sliderConfig[4];
|
||||
char stickName[CPN_MAX_STICKS][3+1];
|
||||
char potName[CPN_MAX_KNOBS][3+1];
|
||||
unsigned int potConfig[CPN_MAX_KNOBS];
|
||||
char sliderName[CPN_MAX_SLIDERS][3+1];
|
||||
unsigned int sliderConfig[CPN_MAX_SLIDERS];
|
||||
|
||||
char themeName[8+1];
|
||||
typedef uint8_t ThemeOptionData[8+1];
|
||||
|
|
|
@ -84,17 +84,13 @@ QStringList getDfuArgs(const QString & cmd, const QString & filename)
|
|||
{
|
||||
QStringList args;
|
||||
burnConfigDialog bcd;
|
||||
QString memory = "0x08000000";
|
||||
if (cmd == "-U") {
|
||||
memory.append(QString(":%1").arg(getCurrentFirmware()->getFlashSize()));
|
||||
}
|
||||
args << bcd.getDFUArgs();
|
||||
if (!filename.endsWith(".dfu")) {
|
||||
args << "--dfuse-address" << memory;
|
||||
}
|
||||
args << "-d" << "0483:df11";
|
||||
QString fullcmd = cmd + filename;
|
||||
args << "" << fullcmd;
|
||||
if (!filename.endsWith(".dfu"))
|
||||
args << "--dfuse-address" << "0x08000000";
|
||||
if (cmd == "-U")
|
||||
args.last().append(":" % QString::number(Boards::getFlashSize(getCurrentBoard())));
|
||||
args << "--device" << "0483:df11";
|
||||
args << "" << cmd % filename;
|
||||
return args;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "joystickdialog.h"
|
||||
#include "ui_joystickdialog.h"
|
||||
|
||||
#include "boards.h"
|
||||
#include "constants.h"
|
||||
|
||||
joystickDialog::joystickDialog(QWidget *parent, int stick) :
|
||||
|
@ -97,19 +98,13 @@ joystickDialog::~joystickDialog()
|
|||
void joystickDialog::populateSourceCombo(QComboBox * cb)
|
||||
{
|
||||
int i;
|
||||
const QString axes[] = {
|
||||
tr("Left Horizontal"),
|
||||
tr("Left Vertical"),
|
||||
tr("Right Vertical"),
|
||||
tr("Right Horizontal")
|
||||
};
|
||||
cb->clear();
|
||||
cb->addItem(tr("Not Assigned"), -1);
|
||||
for (i=0; i < 4; ++i) {
|
||||
cb->addItem(axes[i] % tr(" Stick"), i);
|
||||
for (i=0; i < Board::STICK_AXIS_COUNT; ++i) {
|
||||
cb->addItem(Boards::getAxisName(i) % tr(" Stick"), i);
|
||||
}
|
||||
for (; i < CPN_MAX_STICKS + CPN_MAX_POTS; ++i) {
|
||||
cb->addItem(tr("Knob/Slider %1").arg(i - CPN_MAX_STICKS + 1), i);
|
||||
for (; i < Board::STICK_AXIS_COUNT + CPN_MAX_POTS; ++i) {
|
||||
cb->addItem(tr("Knob/Slider %1").arg(i - Board::STICK_AXIS_COUNT + 1), i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct TxInputs
|
|||
int switches[CPN_MAX_SWITCHES];
|
||||
bool keys[CPN_MAX_KEYS];
|
||||
bool rotenc;
|
||||
bool trims[(CPN_MAX_STICKS + CPN_MAX_AUX_TRIMS) * 2];
|
||||
bool trims[CPN_MAX_TRIM_SW];
|
||||
};
|
||||
|
||||
class TxOutputs
|
||||
|
@ -57,7 +57,7 @@ class TxOutputs
|
|||
|
||||
struct Trims
|
||||
{
|
||||
int values[CPN_MAX_STICKS + CPN_MAX_AUX_TRIMS]; /* lh lv rv rh t5 t6 */
|
||||
int values[CPN_MAX_TRIMS]; /* lh lv rv rh t5 t6 */
|
||||
bool extended;
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ bool BinEepromFormat::write(const RadioData & radioData)
|
|||
{
|
||||
bool result;
|
||||
EEPROMInterface * eepromInterface = getCurrentEEpromInterface();
|
||||
int size = getEEpromSize(eepromInterface->getBoard());
|
||||
int size = Boards::getEEpromSize(eepromInterface->getBoard());
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@ bool EepeFormat::load(RadioData & radioData)
|
|||
|
||||
qDebug() << qPrintable("[eepe] EEPE header found");
|
||||
|
||||
QByteArray eeprom(EESIZE_MAX, 0);
|
||||
int eeprom_size = HexInterface(inputStream).load((uint8_t *)eeprom.data(), EESIZE_MAX);
|
||||
QByteArray eeprom(Boards::getEEpromSize(Board::BOARD_UNKNOWN), 0);
|
||||
int eeprom_size = HexInterface(inputStream).load((uint8_t *)eeprom.data(), Boards::getEEpromSize(Board::BOARD_UNKNOWN));
|
||||
if (!eeprom_size) {
|
||||
setError(QObject::tr("Invalid EEPROM file %1").arg(filename));
|
||||
return false;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define DATE_MARK "DATE"
|
||||
#define TIME_MARK "TIME"
|
||||
#define EEPR_MARK "EEPR"
|
||||
#define FSIZE_MAX Boards::getFlashSize(Board::BOARD_UNKNOWN)
|
||||
|
||||
FirmwareInterface::FirmwareInterface(const QString & filename):
|
||||
flash(FSIZE_MAX, 0),
|
||||
|
|
|
@ -33,9 +33,8 @@ bool HexEepromFormat::load(RadioData & radioData)
|
|||
}
|
||||
|
||||
QTextStream inputStream(&file);
|
||||
// TODO remove EESIZE_MAX
|
||||
QByteArray eeprom(EESIZE_MAX, 0);
|
||||
int eeprom_size = HexInterface(inputStream).load((uint8_t *)eeprom.data(), EESIZE_MAX);
|
||||
QByteArray eeprom(Boards::getEEpromSize(Board::BOARD_UNKNOWN), 0);
|
||||
int eeprom_size = HexInterface(inputStream).load((uint8_t *)eeprom.data(), Boards::getEEpromSize(Board::BOARD_UNKNOWN));
|
||||
if (!eeprom_size) {
|
||||
setError(QObject::tr("Invalid EEPROM File %1").arg(filename));
|
||||
return false;
|
||||
|
|
|
@ -71,7 +71,7 @@ void RleFile::EeFsCreate(uint8_t *eeprom, int size, Board::Type board, unsigned
|
|||
eeFsBlockSize = 64;
|
||||
eeFsFirstBlock = 1;
|
||||
eeFsBlocksOffset = eeFsSize - eeFsBlockSize;
|
||||
eeFsBlocksMax = 1 + (EESIZE_TARANIS-eeFsSize)/eeFsBlockSize;
|
||||
eeFsBlocksMax = 1 + (Boards::getEEpromSize(board)-eeFsSize) / eeFsBlockSize;
|
||||
eeFsLinkSize = sizeof(int16_t);
|
||||
memset(eeprom, 0, size);
|
||||
eeFsArm->version = eeFsVersion;
|
||||
|
@ -154,7 +154,7 @@ bool RleFile::EeFsOpen(uint8_t *eeprom, int size, Board::Type board)
|
|||
eeFsLinkSize = sizeof(int16_t);
|
||||
eeFsFirstBlock = 1;
|
||||
eeFsBlocksOffset = eeFsSize - eeFsBlockSize;
|
||||
eeFsBlocksMax = 1 + (EESIZE_TARANIS-eeFsSize)/eeFsBlockSize;
|
||||
eeFsBlocksMax = 1 + (Boards::getEEpromSize(board)-eeFsSize) / eeFsBlockSize;
|
||||
return eeFsArm->mySize == eeFsSize;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -124,7 +124,7 @@ bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEpr
|
|||
if (!storage.load(*radioData))
|
||||
return false;
|
||||
|
||||
QByteArray eeprom(EESIZE_MAX, 0);
|
||||
QByteArray eeprom(Boards::getEEpromSize(Board::BOARD_UNKNOWN), 0);
|
||||
int size = getCurrentEEpromInterface()->save((uint8_t *)eeprom.data(), *radioData, version, variant);
|
||||
if (size == 0) {
|
||||
return false;
|
||||
|
|
|
@ -134,7 +134,7 @@ void OpenTxSimulator::getTrims(Trims & trims)
|
|||
{
|
||||
uint8_t phase = getFlightMode();
|
||||
trims.extended = hasExtendedTrims();
|
||||
for (uint8_t idx=0; idx < CPN_MAX_STICKS + CPN_MAX_AUX_TRIMS; idx++) {
|
||||
for (uint8_t idx=0; idx < CPN_MAX_TRIMS; idx++) {
|
||||
trims.values[idx] = getTrimValue(getTrimFlightMode(phase, idx), idx);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue