| ");
- COMPARE(modelPrinter->printMixerName(i+1));
+ COMPARE(modelPrinter->printChannelName(i));
columns.append(" | ");
for (int j=0; j 0)
@@ -444,23 +455,25 @@ QString MultiModelPrinter::printMixers()
QString MultiModelPrinter::printCurves(QTextDocument * document)
{
QString str;
- MultiColumns columns(models.size());
+ MultiColumns columns(modelPrinterMap.size());
int count = 0;
columns.append("");
for (int i=0; igetCapability(NumCurves); i++) {
bool curveEmpty = true;
- for (int k=0; kcurves[i].isEmpty()) {
+ for (int k=0; k < modelPrinterMap.size(); k++) {
+ if (!modelPrinterMap.value(k).first->curves[i].isEmpty()) {
curveEmpty = false;
break;
}
}
if (!curveEmpty) {
count++;
- columns.append("| " + tr("CV%1").arg(i+1) + " | ");
+ columns.append(" | | ");
+ COMPARE(modelPrinter->printCurveName(i));
+ columns.append(" | ");
COMPARE(modelPrinter->printCurve(i));
- for (int k=0; k ").arg(modelPrinters[k]->createCurveImage(i, document)));
+ for (int k=0; k < modelPrinterMap.size(); k++)
+ columns.append(k, QString("
").arg(modelPrinterMap.value(k).second->createCurveImage(i, document)));
columns.append(" | ");
}
}
@@ -475,13 +488,13 @@ QString MultiModelPrinter::printCurves(QTextDocument * document)
QString MultiModelPrinter::printLogicalSwitches()
{
QString str;
- MultiColumns columns(models.size());
+ MultiColumns columns(modelPrinterMap.size());
int count = 0;
columns.append("");
for (int i=0; igetCapability(LogicalSwitches); i++) {
bool lsEmpty = true;
- for (int k=0; kprintLogicalSwitchLine(i).isEmpty()) {
+ for (int k=0; k < modelPrinterMap.size(); k++) {
+ if (!modelPrinterMap.value(k).first->logicalSw[i].isEmpty()) {
lsEmpty = false;
break;
}
@@ -504,13 +517,13 @@ QString MultiModelPrinter::printLogicalSwitches()
QString MultiModelPrinter::printCustomFunctions()
{
QString str;
- MultiColumns columns(models.size());
+ MultiColumns columns(modelPrinterMap.size());
int count = 0;
columns.append("");
- for (int i=0; igetCapability(CustomFunctions); i++) {
+ for (int i=0; i < firmware->getCapability(CustomFunctions); i++) {
bool sfEmpty = true;
- for (int k=0; kprintCustomFunctionLine(i).isEmpty()) {
+ for (int k=0; k < modelPrinterMap.size(); k++) {
+ if (!modelPrinterMap.value(k).first->customFn[i].isEmpty()) {
sfEmpty = false;
break;
}
@@ -536,7 +549,7 @@ QString MultiModelPrinter::printTelemetry()
// Analogs on non ARM boards
if (!IS_ARM(firmware->getBoard())) {
- MultiColumns columns(models.size());
+ MultiColumns columns(modelPrinterMap.size());
columns.append("" \
"| " + tr("Analogs") + " | " + tr("Unit") + " | " + tr("Scale") + " | " + tr("Offset") + " | ");
for (int i=0; i<2; i++) {
@@ -555,7 +568,7 @@ QString MultiModelPrinter::printTelemetry()
// RSSI alarms
{
- MultiColumns columns(models.size());
+ MultiColumns columns(modelPrinterMap.size());
columns.append("");
for (int i=0; i<2; i++) {
columns.append("| " + QString(i==0 ? tr("RSSI Alarms") : "") + " | ");
diff --git a/companion/src/multimodelprinter.h b/companion/src/multimodelprinter.h
index 31c807e54..a896f9d6e 100644
--- a/companion/src/multimodelprinter.h
+++ b/companion/src/multimodelprinter.h
@@ -33,8 +33,10 @@ class MultiModelPrinter: public QObject
public:
MultiModelPrinter(Firmware * firmware);
virtual ~MultiModelPrinter();
-
- void setModel(int idx, const ModelData & model);
+
+ void setModel(int idx, const ModelData * model, const GeneralSettings * generalSettings);
+ void setModel(int idx, const ModelData * model);
+ void clearModels();
QString print(QTextDocument * document);
protected:
@@ -58,8 +60,7 @@ class MultiModelPrinter: public QObject
Firmware * firmware;
GeneralSettings defaultSettings;
- QVector models; // TODO const
- QVector modelPrinters;
+ QMap > modelPrinterMap;
QString printTitle(const QString & label);
QString printSetup();
diff --git a/companion/src/multiprotocols.cpp b/companion/src/multiprotocols.cpp
index ce2249f1c..602075284 100644
--- a/companion/src/multiprotocols.cpp
+++ b/companion/src/multiprotocols.cpp
@@ -23,10 +23,19 @@
#include "multiprotocols.h"
#include "radiodata.h"
-#define tr QObject::tr
+#define STR_MULTI_SUBTYPE QT_TRANSLATE_NOOP("Multiprotocols", "Subtype")
+#define STR_MULTI_VIDFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Video TX frequency")
+#define STR_MULTI_RFTUNE QT_TRANSLATE_NOOP("Multiprotocols", "CC2500 frequency fine tune")
+#define STR_MULTI_TELEMETRY QT_TRANSLATE_NOOP("Multiprotocols", "Telemetry")
+#define STR_MULTI_RFPOWER QT_TRANSLATE_NOOP("Multiprotocols", "Radio output power")
+#define STR_MULTI_SERVOFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Servo output frequency")
+#define STR_MULTI_OPTION QT_TRANSLATE_NOOP("Multiprotocols", "Option value")
+#define STR_MULTI_DEFAULT QT_TRANSLATE_NOOP("Multiprotocols", "DEFAULT")
-static const QStringList STR_SUBTYPE_CUSTOM ({tr("Subtype 0"), tr("Subtype 1"), tr("Subtype 2"), tr("Subtype 3"),
- tr("Subtype 4"), tr("Subtype 5"), tr("Subtype 6"), tr("Subtype 7")});
+static const QStringList STR_SUBTYPE_CUSTOM ({
+ STR_MULTI_SUBTYPE " 0", STR_MULTI_SUBTYPE " 1", STR_MULTI_SUBTYPE " 2", STR_MULTI_SUBTYPE " 3",
+ STR_MULTI_SUBTYPE " 4", STR_MULTI_SUBTYPE " 5", STR_MULTI_SUBTYPE " 6", STR_MULTI_SUBTYPE " 7"
+ });
static const QStringList STR_SUBTYPE_FLYSKY {"Standard", "V9x9", "V6x6", "V912", "CX20"};
static const QStringList STR_SUBTYPE_FRSKY {"D16", "D8", "D16 8ch", "V8", "D16 EU-LBT", "D16 EU-LBT 8ch"};
static const QStringList STR_SUBTYPE_HISKY {"HiSky", "HK310"};
@@ -36,7 +45,7 @@ static const QStringList STR_SUBTYPE_YD717 {"YD717", "Skywalker", "Syma X2", "
static const QStringList STR_SUBTYPE_SYMAX {"Standard", "Syma X5C"};
static const QStringList STR_SUBTYPE_SLT {"SLT", "Vista"};
static const QStringList STR_SUBTYPE_CX10 {"Green", "Blue", "DM007", "-", "JC3015a", "JC3015b", "MK33041", "Q242"};
-static const QStringList STR_SUBTYPE_CG023 {"CG023", "YD829", "H3 3D"};
+static const QStringList STR_SUBTYPE_CG023 {"CG023", "YD829", "H8 3D"};
static const QStringList STR_SUBTYPE_BAYANG {"Bayang", "H8S3D"};
static const QStringList STR_SUBTYPE_KN {"WLtoys", "FeiLun"};
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
@@ -47,14 +56,7 @@ static const QStringList STR_SUBTYPE_AFHDS2A {"PWM and IBUS", "PPM and IBUS", "P
static const QStringList STR_SUBTYPE_Q2X2 {"Q222", "Q242", "Q282"};
static const QStringList STR_SUBTYPE_WK2x01 {"WK2801", "WK2401", "W6_5_1", "W6_6_1", "W6_HEL", "W6_HEL_I"};
static const QStringList STR_SUBTYPE_Q303 {"Q303", "CX35", "CX10D", "CX10WD"};
-static const QStringList NO_SUBTYPE {tr("DEFAULT")};
-
-static const QString STR_MULTI_VIDFREQ = tr("Video TX frequency");
-static const QString STR_MULTI_RFTUNE = tr("C2500 frequency fine tune");
-static const QString STR_MULTI_TELEMETRY = tr("Telemetry");
-static const QString STR_MULTI_RFPOWER = tr("Radio output power");
-static const QString STR_MULTI_SERVOFREQ = tr("Servo output frequency");
-static const QString STR_MULTI_OPTION= tr("Option value");
+static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
// Table is designed to be shared with gui_common_arm.cpp
@@ -83,7 +85,6 @@ const Multiprotocols multiProtocols {
{ MM_RF_PROTO_Q2X2, STR_SUBTYPE_Q2X2, 2, nullptr },
{ MM_RF_PROTO_WK_2X01, STR_SUBTYPE_WK2x01, 5, nullptr },
{ MM_RF_PROTO_Q303, STR_SUBTYPE_Q303, 3, nullptr },
- { MM_RF_PROTO_GW08, NO_SUBTYPE, 0, nullptr },
{ MM_RF_CUSTOM_SELECTED, STR_SUBTYPE_CUSTOM, 7, STR_MULTI_OPTION },
//Sential and default for protocols not listed above (MM_RF_CUSTOM is 0xff()
diff --git a/companion/src/printdialog.cpp b/companion/src/printdialog.cpp
index 082785e71..8ea8d0525 100644
--- a/companion/src/printdialog.cpp
+++ b/companion/src/printdialog.cpp
@@ -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();
@@ -44,7 +44,7 @@ PrintDialog::PrintDialog(QWidget *parent, Firmware * firmware, GeneralSettings &
}
}
-void PrintDialog::closeEvent(QCloseEvent *event)
+void PrintDialog::closeEvent(QCloseEvent *event)
{
}
diff --git a/companion/src/radiodata.cpp b/companion/src/radiodata.cpp
index 4d09f71b9..dfddfa71a 100644
--- a/companion/src/radiodata.cpp
+++ b/companion/src/radiodata.cpp
@@ -23,7 +23,7 @@
// TODO here we will move a lot of functions from eeprominterface.cpp when no merge risk
-void RawSource::convert(Board::Type before, Board::Type after)
+RawSource RawSource::convert(Board::Type before, Board::Type after)
{
if (type == SOURCE_TYPE_STICK && index >= 4 + getBoardCapability(before, Board::Pots)) {
// 1st slider alignment
@@ -57,11 +57,79 @@ void RawSource::convert(Board::Type before, Board::Type after)
}
}
}
+
+ return *this;
+}
+
+RawSwitch RawSwitch::convert(Board::Type before, Board::Type after)
+{
+ // SWI to SWR don't exist on !X9E board
+ if (!IS_TARANIS_X9E(after) && IS_TARANIS_X9E(before)) {
+ if (type == SWITCH_TYPE_SWITCH && index >= 24) {
+ index = index % 24;
+ }
+ }
+
+ // No SE and SG on X7 board
+ if (IS_TARANIS_X7(after)) {
+ if (IS_TARANIS_X9(before) || IS_HORUS(before)) {
+ if (type == SWITCH_TYPE_SWITCH && index >= 18) {
+ index -= 6;
+ }
+ else if (type == SWITCH_TYPE_SWITCH && index >= 12) {
+ index -= 3;
+ }
+ }
+ }
+
+ return *this;
+}
+
+void ExpoData::convert(Board::Type before, Board::Type after)
+{
+ swtch.convert(before, after);
}
void MixData::convert(Board::Type before, Board::Type after)
{
srcRaw.convert(before, after);
+ swtch.convert(before, after);
+}
+
+void LogicalSwitchData::convert(Board::Type before, Board::Type after)
+{
+ CSFunctionFamily family = getFunctionFamily();
+ switch(family) {
+ case LS_FAMILY_VOFS:
+ val1 = RawSource(val1).convert(before, after).toValue();
+ break;
+ case LS_FAMILY_STICKY:
+ case LS_FAMILY_VBOOL:
+ val1 = RawSwitch(val1).convert(before, after).toValue();
+ val2 = RawSwitch(val2).convert(before, after).toValue();
+ break;
+ case LS_FAMILY_EDGE:
+ val1 = RawSwitch(val1).convert(before, after).toValue();
+ break;
+ case LS_FAMILY_VCOMP:
+ val1 = RawSource(val1).convert(before, after).toValue();
+ val2 = RawSource(val2).convert(before, after).toValue();
+ break;
+ default:
+ break;
+ }
+
+ andsw = RawSwitch(andsw).convert(before, after).toValue();
+}
+
+void CustomFunctionData::convert(Board::Type before, Board::Type after)
+{
+ swtch.convert(before, after);
+}
+
+void FlightModeData::convert(Board::Type before, Board::Type after)
+{
+ swtch.convert(before, after);
}
void ModelData::convert(Board::Type before, Board::Type after)
@@ -70,11 +138,47 @@ void ModelData::convert(Board::Type before, Board::Type after)
for (int i=0; igetCapability(Models));
}
void RadioData::setCurrentModel(unsigned int index)
@@ -150,4 +254,4 @@ void RadioData::convert(Board::Type before, Board::Type after)
if (IS_HORUS(after)) {
fixModelFilenames();
}
-}
\ No newline at end of file
+}
diff --git a/companion/src/radiodata.h b/companion/src/radiodata.h
index e5b8b8bc2..15d029af8 100644
--- a/companion/src/radiodata.h
+++ b/companion/src/radiodata.h
@@ -69,20 +69,6 @@ enum FailsafeModes {
FAILSAFE_LAST = FAILSAFE_RECEIVER
};
-#define TRIM_LH_L 0
-#define TRIM_LH_R 1
-#define TRIM_LV_DN 2
-#define TRIM_LV_UP 3
-#define TRIM_RV_DN 4
-#define TRIM_RV_UP 5
-#define TRIM_RH_L 6
-#define TRIM_RH_R 7
-#define TRIM_T5_DN 8
-#define TRIM_T5_UP 9
-#define TRIM_T6_DN 10
-#define TRIM_T6_UP 11
-#define TRIM_NONE 12
-
#define CHAR_FOR_NAMES " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
#define CHAR_FOR_NAMES_REGEX "[ A-Za-z0-9_.-,]*"
@@ -225,14 +211,14 @@ class RawSource {
{
}
- void convert(Board::Type before, Board::Type after);
+ RawSource convert(Board::Type before, Board::Type after);
inline const int toValue() const
{
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;
@@ -245,8 +231,9 @@ class RawSource {
}
bool isTimeBased() const;
- bool isPot() const;
- bool isSlider() const;
+ bool isStick(int * potsIndex = NULL) const;
+ bool isPot(int * potsIndex = NULL) const;
+ bool isSlider(int * sliderIndex = NULL) const;
RawSourceType type;
int index;
@@ -291,7 +278,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);
@@ -301,6 +288,8 @@ class RawSwitch {
return (this->type != other.type) || (this->index != other.index);
}
+ RawSwitch convert(Board::Type before, Board::Type after);
+
RawSwitchType type;
int index;
};
@@ -327,7 +316,7 @@ class CurveReference {
CurveRefType type;
int value;
- QString toString() const;
+ QString toString(const ModelData * model = NULL, bool verbose = true) const;
};
enum InputMode {
@@ -352,6 +341,7 @@ class ExpoData {
int carryTrim;
char name[10+1];
void clear() { memset(this, 0, sizeof(ExpoData)); }
+ void convert(Board::Type before, Board::Type after);
};
class CurvePoint {
@@ -371,6 +361,8 @@ class CurveData {
CurveData();
void clear(int count);
bool isEmpty() const;
+ QString nameToString(const int idx) const;
+
CurveType type;
bool smooth;
int count;
@@ -478,10 +470,13 @@ class LogicalSwitchData { // Logical Switches data
unsigned int delay;
unsigned int duration;
int andsw;
+
void clear() { memset(this, 0, sizeof(LogicalSwitchData)); }
+ bool isEmpty() const;
CSFunctionFamily getFunctionFamily() const;
unsigned int getRangeFlags() const;
QString funcToString() const;
+ void convert(Board::Type before, Board::Type after);
};
enum AssignFunc {
@@ -540,8 +535,10 @@ class CustomFunctionData { // Function Switches data
unsigned int enabled; // TODO perhaps not any more the right name
unsigned int adjustMode;
int repeatParam;
+
void clear();
- QString funcToString() const;
+ bool isEmpty() const;
+ QString funcToString(const ModelData * model = NULL) const;
QString paramToString(const ModelData * model) const;
QString repeatToString() const;
QString enabledToString() const;
@@ -550,14 +547,16 @@ class CustomFunctionData { // Function Switches data
static void populatePlaySoundParams(QStringList & qs);
static void populateHapticParams(QStringList & qs);
+ void convert(Board::Type before, Board::Type after);
+
};
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;
@@ -565,6 +564,7 @@ class FlightModeData {
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void clear(const int phase);
+ void convert(Board::Type before, Board::Type after);
};
class SwashRingData { // Swash Ring data
@@ -799,8 +799,9 @@ enum MultiModuleRFProtocols {
MM_RF_PROTO_Q2X2,
MM_RF_PROTO_WK_2X01,
MM_RF_PROTO_Q303,
- MM_RF_PROTO_GW08,
- MM_RF_PROTO_LAST=MM_RF_PROTO_GW08
+ MM_RF_PROTO_GW008,
+ MM_RF_PROTO_DM002,
+ MM_RF_PROTO_LAST=MM_RF_PROTO_DM002
};
enum TrainerProtocol {
@@ -1010,9 +1011,9 @@ class ModelData {
ModelData();
ModelData(const ModelData & src);
ModelData & operator = (const ModelData & src);
-
+
void convert(Board::Type before, Board::Type after);
-
+
ExpoData * insertInput(const int idx);
void removeInput(const int idx);
@@ -1027,6 +1028,8 @@ class ModelData {
int category;
char name[15+1];
char filename[16+1];
+ int modelIndex; // Companion only, temporary index position managed by data model.
+
TimerData timers[CPN_MAX_TIMERS];
bool noGlobalFunctions;
bool thrTrim; // Enable Throttle Trim
@@ -1047,8 +1050,8 @@ class ModelData {
ExpoData expoData[CPN_MAX_EXPOS];
CurveData curves[CPN_MAX_CURVES];
- LogicalSwitchData logicalSw[CPN_MAX_CSW];
- CustomFunctionData customFn[CPN_MAX_CUSTOM_FUNCTIONS];
+ LogicalSwitchData logicalSw[CPN_MAX_LOGICAL_SWITCHES];
+ CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS];
SwashRingData swashRingData;
unsigned int thrTraceSrc;
uint64_t switchWarningStates;
@@ -1141,9 +1144,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;
@@ -1214,14 +1217,14 @@ class GeneralSettings {
unsigned int switchUnlockStates;
unsigned int hw_uartMode;
unsigned int backlightColor;
- CustomFunctionData customFn[CPN_MAX_CUSTOM_FUNCTIONS];
- char switchName[18][3+1];
+ CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS];
+ 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];
@@ -1248,7 +1251,7 @@ class RadioData {
GeneralSettings generalSettings;
std::vector categories;
std::vector models;
-
+
void convert(Board::Type before, Board::Type after);
void setCurrentModel(unsigned int index);
diff --git a/companion/src/radiointerface.cpp b/companion/src/radiointerface.cpp
index 58654e673..cf6a0e2c0 100644
--- a/companion/src/radiointerface.cpp
+++ b/companion/src/radiointerface.cpp
@@ -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;
}
@@ -467,7 +463,7 @@ QString findMassstoragePath(const QString & filename, bool onlyPath)
#if !defined __APPLE__
QString fstype = entry->me_type;
// qDebug() << eepromfile;
-
+
if (fstype.contains("fat") && QFile::exists(eepromfile)) {
#else
if (QFile::exists(eepromfile)) {
diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt
index ed9709e9b..210f6a44f 100644
--- a/companion/src/simulation/CMakeLists.txt
+++ b/companion/src/simulation/CMakeLists.txt
@@ -40,6 +40,7 @@ set(simulation_HDRS
radiouiaction.h
simulateduiwidget.h
# simulator.h
+ simulatorinterface.h
simulatormainwindow.h
simulatorstartupdialog.h
simulatorwidget.h
@@ -49,8 +50,10 @@ set(simulation_HDRS
widgets/lcdwidget.h
widgets/radiowidget.h
widgets/radiofaderwidget.h
+ widgets/radiokeywidget.h
widgets/radioknobwidget.h
widgets/radioswitchwidget.h
+ widgets/radiotrimwidget.h
widgets/sliderwidget.h
widgets/virtualjoystickwidget.h
)
diff --git a/companion/src/simulation/debugoutput.cpp b/companion/src/simulation/debugoutput.cpp
index 80013b527..c031084f0 100644
--- a/companion/src/simulation/debugoutput.cpp
+++ b/companion/src/simulation/debugoutput.cpp
@@ -36,20 +36,13 @@
extern AppData g; // ensure what "g" means
-FilteredTextBuffer * DebugOutput::m_dataBufferDevice = Q_NULLPTR;
const quint16 DebugOutput::m_savedViewStateVersion = 1;
-void firmwareTraceCb(const char * text)
-{
- if (DebugOutput::m_dataBufferDevice) {
- DebugOutput::m_dataBufferDevice->write(text);
- }
-}
-
DebugOutput::DebugOutput(QWidget * parent, SimulatorInterface *simulator):
QWidget(parent),
ui(new Ui::DebugOutput),
m_simulator(simulator),
+ m_dataBufferDevice(NULL),
m_radioProfileId(g.sessionId()),
m_filterEnable(false),
m_filterExclude(false)
@@ -71,7 +64,7 @@ DebugOutput::DebugOutput(QWidget * parent, SimulatorInterface *simulator):
ui->filterText->addItem(fltr, "no_delete");
ui->filterText->setValidator(new DebugOutputFilterValidator(ui->filterText));
- ui->filterText->installEventFilter(new DeleteComboBoxItemEventFilter());
+ ui->filterText->installEventFilter(new DeleteComboBoxItemEventFilter(this));
ui->actionShowFilterHelp->setIcon(SimulatorIcon("info"));
ui->actionWordWrap->setIcon(SimulatorIcon("word_wrap"));
@@ -87,8 +80,8 @@ DebugOutput::DebugOutput(QWidget * parent, SimulatorInterface *simulator):
m_dataBufferDevice->setInputBufferMaxSize(DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE);
m_dataBufferDevice->open(QIODevice::ReadWrite | QIODevice::Text);
- connect(m_dataBufferDevice, &FilteredTextBuffer::readyRead, this, &DebugOutput::processBytesReceived);
- connect(m_dataBufferDevice, &FilteredTextBuffer::bufferOverflow, this, &DebugOutput::onDataBufferOverflow);
+ connect(m_dataBufferDevice, &FilteredTextBuffer::readyRead, this, &DebugOutput::processBytesReceived, Qt::QueuedConnection);
+ connect(m_dataBufferDevice, &FilteredTextBuffer::bufferOverflow, this, &DebugOutput::onDataBufferOverflow, Qt::QueuedConnection);
connect(this, &DebugOutput::filterChanged, m_dataBufferDevice, &FilteredTextBuffer::setLineFilter);
connect(this, &DebugOutput::filterEnabledChanged, m_dataBufferDevice, &FilteredTextBuffer::setLineFilterEnabled);
connect(this, &DebugOutput::filterExprChanged, m_dataBufferDevice, &FilteredTextBuffer::setLineFilterExpr);
@@ -101,32 +94,28 @@ DebugOutput::DebugOutput(QWidget * parent, SimulatorInterface *simulator):
connect(ui->actionToggleFilter, &QAction::toggled, this, &DebugOutput::onFilterToggled);
connect(ui->filterText, &QComboBox::currentTextChanged, this, &DebugOutput::onFilterTextChanged);
- if (AppDebugMessageHandler::instance()) {
-#if (QT_VERSION < QT_VERSION_CHECK(5, 3, 0)) // https://bugreports.qt.io/browse/QTBUG-36119
- connect(AppDebugMessageHandler::instance(), SIGNAL(messageOutput(quint8,QString,QMessageLogContext)), this, SLOT(onAppDebugMessage(quint8,QString,QMessageLogContext)));
-#else
+ if (AppDebugMessageHandler::instance())
connect(AppDebugMessageHandler::instance(), &AppDebugMessageHandler::messageOutput, this, &DebugOutput::onAppDebugMessage);
-#endif
- }
// send firmware TRACE events to our data collector
- m_simulator->installTraceHook(firmwareTraceCb);
+ m_simulator->addTracebackDevice(m_dataBufferDevice);
}
DebugOutput::~DebugOutput()
{
- saveState();
-
if (AppDebugMessageHandler::instance())
disconnect(AppDebugMessageHandler::instance(), 0, this, 0);
if (m_dataBufferDevice) {
+ m_simulator->removeTracebackDevice(m_dataBufferDevice);
disconnect(m_dataBufferDevice, 0, this, 0);
disconnect(this, 0, m_dataBufferDevice, 0);
- m_dataBufferDevice->deleteLater();
+ delete m_dataBufferDevice;
m_dataBufferDevice = Q_NULLPTR;
}
+ saveState();
+
delete ui;
}
@@ -173,15 +162,18 @@ void DebugOutput::restoreState()
void DebugOutput::processBytesReceived()
{
+ static char buf[512];
const QTextCursor savedCursor(ui->console->textCursor());
const int sbValue = ui->console->verticalScrollBar()->value();
const bool sbAtBottom = (sbValue == ui->console->verticalScrollBar()->maximum());
qint64 len;
+ QString text;
- while ((len = m_dataBufferDevice->bytesAvailable()) > 0) {
- QString text(m_dataBufferDevice->read(qMin(len, qint64(512))));
- if (text.isEmpty())
+ while (m_dataBufferDevice && m_dataBufferDevice->bytesAvailable() > 0) {
+ len = m_dataBufferDevice->read(buf, sizeof(buf));
+ if (len <= 0)
break;
+ text = QString::fromLocal8Bit(buf, len);
ui->console->moveCursor(QTextCursor::End);
ui->console->textCursor().insertText(text);
if (sbAtBottom) {
@@ -209,11 +201,10 @@ void DebugOutput::onDataBufferOverflow(const qint64 len)
}
}
-void DebugOutput::onAppDebugMessage(quint8 level, const QString & msg, const QMessageLogContext & context)
+void DebugOutput::onAppDebugMessage(quint8 level, const QString & msg)
{
- if (level > 0) {
- firmwareTraceCb(qPrintable(msg));
- firmwareTraceCb("\n");
+ if (level > 0 && m_dataBufferDevice) {
+ m_dataBufferDevice->write(qPrintable(msg % "\n"));
}
}
diff --git a/companion/src/simulation/debugoutput.h b/companion/src/simulation/debugoutput.h
index 72b51b9b4..b7a325b46 100644
--- a/companion/src/simulation/debugoutput.h
+++ b/companion/src/simulation/debugoutput.h
@@ -29,14 +29,15 @@
#include
#include
-// NOTE : The buffer sizes need to be large enough to handle the flood of data when X12/X10 simulator starts up (almost 40K!).
+// NOTE : The buffer sizes need to be large enough to handle the flood of data when X12/X10 simulator starts up with TRACE_SIMPGMSPACE=1 (> 40K!).
+// These are maximum sizes, not necessarily allocated sizes.
#ifndef DEBUG_OUTPUT_WIDGET_OUT_BUFF_SIZE
// This buffer holds received and processed data until it can be printed to our console.
- #define DEBUG_OUTPUT_WIDGET_OUT_BUFF_SIZE (40 * 1024) // [bytes]
+ #define DEBUG_OUTPUT_WIDGET_OUT_BUFF_SIZE (50 * 1024) // [bytes]
#endif
#ifndef DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE
// This buffer is active if line filter is enabled and holds received data until it can be filtered and placed in output buffer.
- #define DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE (30 * 1024) // [bytes]
+ #define DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE (50 * 1024) // [bytes]
#endif
namespace Ui {
@@ -59,20 +60,19 @@ class DebugOutput : public QWidget
static QRegularExpression makeRegEx(const QString & input, bool * isExlusive = NULL);
- static FilteredTextBuffer * m_dataBufferDevice;
-
signals:
void filterExprChanged(const QRegularExpression & expr);
void filterEnabledChanged(const bool enabled);
void filterExclusiveChanged(const bool exlusive);
void filterChanged(bool enable, bool exclusive, const QRegularExpression & expr);
+ void tracebackDeviceChange(QIODevice * device);
protected slots:
void saveState();
void restoreState();
void processBytesReceived();
void onDataBufferOverflow(const qint64 len);
- void onAppDebugMessage(quint8 level, const QString & msg, const QMessageLogContext & context);
+ void onAppDebugMessage(quint8 level, const QString & msg);
void onFilterStateChanged();
void onFilterTextChanged(const QString &);
void onFilterToggled(bool enable);
@@ -84,6 +84,7 @@ class DebugOutput : public QWidget
protected:
Ui::DebugOutput * ui;
SimulatorInterface * m_simulator;
+ FilteredTextBuffer * m_dataBufferDevice;
int m_radioProfileId;
bool m_filterEnable;
bool m_filterExclude;
@@ -101,6 +102,8 @@ class DebugOutputFilterValidator : public QValidator
class DeleteComboBoxItemEventFilter : public QObject
{
Q_OBJECT
+ public:
+ DeleteComboBoxItemEventFilter(QObject *parent = Q_NULLPTR) : QObject(parent) { }
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
diff --git a/companion/src/simulation/filteredtextbuffer.cpp b/companion/src/simulation/filteredtextbuffer.cpp
index 75f50cd51..61d30d911 100644
--- a/companion/src/simulation/filteredtextbuffer.cpp
+++ b/companion/src/simulation/filteredtextbuffer.cpp
@@ -115,7 +115,9 @@ qint64 FIFOBufferDevice::readData(char * data, qint64 len)
qint64 FIFOBufferDevice::readLine(char * data, qint64 maxSize)
{
+ m_dataRWLock.lockForRead();
qint64 len = buffer().indexOf('\n', 0);
+ m_dataRWLock.unlock();
if (len < 0 || maxSize <= 0)
return 0;
@@ -128,7 +130,9 @@ qint64 FIFOBufferDevice::readLine(char * data, qint64 maxSize)
QByteArray FIFOBufferDevice::readLine(qint64 maxSize)
{
QByteArray ba;
+ m_dataRWLock.lockForRead();
qint64 len = buffer().indexOf('\n', 0);
+ m_dataRWLock.unlock();
if (len < 0)
return ba;
@@ -169,9 +173,9 @@ FilteredTextBuffer::FilteredTextBuffer(QObject * parent) :
setInputBufferMaxSize(m_inBuffMaxSize);
setInputBufferTimeout(m_inBuffFlushTimeout);
- connect(m_inBuffer, &FIFOBufferDevice::readyRead, this, &FilteredTextBuffer::processInputBuffer);
- connect(m_inBuffer, &FIFOBufferDevice::bytesWritten, this, &FilteredTextBuffer::onInputBufferWrite);
- connect(m_inBuffer, &FIFOBufferDevice::bufferOverflow, this, &FilteredTextBuffer::onInputBufferOverflow);
+ connect(m_inBuffer, &FIFOBufferDevice::readyRead, this, &FilteredTextBuffer::processInputBuffer, Qt::QueuedConnection);
+ connect(m_inBuffer, &FIFOBufferDevice::bytesWritten, this, &FilteredTextBuffer::onInputBufferWrite, Qt::QueuedConnection);
+ connect(m_inBuffer, &FIFOBufferDevice::bufferOverflow, this, &FilteredTextBuffer::onInputBufferOverflow, Qt::QueuedConnection);
connect(m_bufferFlushTimer, &QTimer::timeout, this, &FilteredTextBuffer::processInputBuffer);
connect(this, &FilteredTextBuffer::timerStart, m_bufferFlushTimer, static_cast(&QTimer::start));
connect(this, &FilteredTextBuffer::timerStop, m_bufferFlushTimer, &QTimer::stop);
diff --git a/companion/src/simulation/joystickdialog.cpp b/companion/src/simulation/joystickdialog.cpp
index 76a08e5c2..d2c87b2d6 100644
--- a/companion/src/simulation/joystickdialog.cpp
+++ b/companion/src/simulation/joystickdialog.cpp
@@ -21,6 +21,9 @@
#include "joystickdialog.h"
#include "ui_joystickdialog.h"
+#include "boards.h"
+#include "constants.h"
+
joystickDialog::joystickDialog(QWidget *parent, int stick) :
QDialog(parent),
ui(new Ui::joystickDialog),
@@ -43,6 +46,7 @@ joystickDialog::joystickDialog(QWidget *parent, int stick) :
memcpy(jscal, jscaltmp, sizeof (jscal));
foreach(QComboBox *cb, findChildren(QRegExp("jsmapCB_[0-9]+"))) {
+ populateSourceCombo(cb);
sticks[cb->property("channel").toUInt()] = cb;
}
foreach(QCheckBox *ib, findChildren(QRegExp("ChInv_[0-9]+"))) {
@@ -62,7 +66,7 @@ joystickDialog::joystickDialog(QWidget *parent, int stick) :
sliders[i]->setMinimum(jscal[i][0]);
sliders[i]->setMaximum(jscal[i][2]);
invert[i]->setChecked(g.joystick[i].stick_inv());
- sticks[i]->setCurrentIndex(g.joystick[i].stick_axe() + 1);
+ sticks[i]->setCurrentIndex(sticks[i]->findData(g.joystick[i].stick_axe()));
}
ui->backButton->setEnabled(false);
@@ -72,7 +76,13 @@ joystickDialog::joystickDialog(QWidget *parent, int stick) :
if (stick < 0)
stick = g.jsCtrl();
- loadJoysticks(stick);
+ if (loadJoysticks(stick)) {
+ joystickSetEnabled(ui->joystickChkB->isChecked());
+ joystickOpen(ui->joystickCB->currentIndex());
+ }
+ else {
+ joystickSetEnabled(false);
+ }
loadStep();
connect(joystick, SIGNAL(axisValueChanged(int, int)), this, SLOT(onjoystickAxisValueChanged(int, int)));
@@ -85,7 +95,20 @@ joystickDialog::~joystickDialog()
delete ui;
}
-void joystickDialog::loadJoysticks(int stick)
+void joystickDialog::populateSourceCombo(QComboBox * cb)
+{
+ int i;
+ cb->clear();
+ cb->addItem(tr("Not Assigned"), -1);
+ for (i=0; i < Board::STICK_AXIS_COUNT; ++i) {
+ cb->addItem(Boards::getAxisName(i) % tr(" Stick"), 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);
+ }
+}
+
+bool joystickDialog::loadJoysticks(int stick)
{
QStringList joystickNames;
bool found = false;
@@ -101,23 +124,19 @@ void joystickDialog::loadJoysticks(int stick)
joystick->close();
}
ui->joystickCB->insertItems(0, joystickNames);
- if (found && stick < joystickNames.size())
+ if (found && stick < joystickNames.size()) {
ui->joystickCB->setCurrentIndex(stick);
- else if (!found)
- ui->joystickCB->setCurrentIndex(0);
-
- joystickSetEnabled(found && ui->joystickChkB->isChecked());
+ }
+ else if (!found) {
+ joystickSetEnabled(false);
+ }
+ return found;
}
void joystickDialog::joystickOpen(int stick)
{
- if (stick == -1 || !ui->joystickChkB->isChecked() || !ui->joystickCB->isEnabled()) {
- ui->calibrationWidget->setDisabled(true);
+ if (stick < 0)
return;
- }
-
- ui->calibrationWidget->setEnabled(true);
- ui->nextButton->setEnabled(true);
joystick = new Joystick(this, 1, false, 0);
if (joystick && joystick->open(stick)) {
@@ -138,8 +157,6 @@ void joystickDialog::joystickSetEnabled(bool enable)
ui->calibrationWidget->setEnabled(enable);
ui->nextButton->setEnabled(enable && step < 4);
ui->backButton->setEnabled(enable && step);
- if (enable)
- joystickOpen(ui->joystickCB->currentIndex());
}
void joystickDialog::onjoystickAxisValueChanged(int axis, int value)
@@ -229,6 +246,9 @@ void joystickDialog::on_okButton_clicked()
g.jsSupport(ui->joystickChkB->isChecked());
g.jsCtrl(ui->joystickCB->currentIndex());
+ if (joystick)
+ joystick->close();
+
if (!g.jsSupport() || g.jsCtrl() < 0) {
this->accept();
return;
@@ -241,31 +261,20 @@ void joystickDialog::on_okButton_clicked()
return;
}
- int stickAssignments[MAX_JOYSTICKS] = {0};
-
for (int i = 0; i < MAX_JOYSTICKS; ++i) {
- stick = sticks[i]->currentIndex() - 1;
- if (stick >= 0 && stick < MAX_JOYSTICKS && ++stickAssignments[stick] > 1) {
- QMessageBox::critical(this, tr("Error"), tr("Duplicated stick assignment!"));
- return;
+ stick = sticks[i]->currentData().toInt();
+ if (stick < 0) {
+ g.joystick[i].stick_axe(-1);
+ }
+ else {
+ g.joystick[i].stick_axe(stick);
+ g.joystick[i].stick_max(jscal[i][2]);
+ g.joystick[i].stick_med(jscal[i][1]);
+ g.joystick[i].stick_min(jscal[i][0]);
+ g.joystick[i].stick_inv(invert[i]->isChecked() );
+ qDebug() << "joystick mapping " << sticks[i]->objectName() << "stick:" << i << "axe:" << stick;
}
}
- joystick->close();
-
- for (int i = 0; i < MAX_JOYSTICKS; ++i)
- g.joystick[i].remove();
-
- for (int i = 0; i < MAX_JOYSTICKS; ++i) {
- stick = sticks[i]->currentIndex() - 1;
- qDebug() << "joystick mapping " << sticks[i]->objectName() << "axe:" << i << "stick:" << stick;
- if (stick >= 0 && stick < MAX_JOYSTICKS) {
- g.joystick[stick].stick_axe( i );
- g.joystick[stick].stick_max( jscal[i][2] );
- g.joystick[stick].stick_med( jscal[i][1] );
- g.joystick[stick].stick_min( jscal[i][0] );
- g.joystick[stick].stick_inv( invert[i]->isChecked() );
- }
- }
this->accept();
}
diff --git a/companion/src/simulation/joystickdialog.h b/companion/src/simulation/joystickdialog.h
index 8c6fb5555..cdb85593a 100644
--- a/companion/src/simulation/joystickdialog.h
+++ b/companion/src/simulation/joystickdialog.h
@@ -53,7 +53,8 @@ class joystickDialog : public QDialog
bool started;
private slots:
- void loadJoysticks(int stick = -1);
+ void populateSourceCombo(QComboBox * cb);
+ bool loadJoysticks(int stick = -1);
void joystickOpen(int stick);
void joystickSetEnabled(bool enable);
void onjoystickAxisValueChanged(int axis, int value);
diff --git a/companion/src/simulation/joystickdialog.ui b/companion/src/simulation/joystickdialog.ui
index d52c6ceb5..eb2be2965 100644
--- a/companion/src/simulation/joystickdialog.ui
+++ b/companion/src/simulation/joystickdialog.ui
@@ -6,8 +6,8 @@
0
0
- 473
- 335
+ 554
+ 351
@@ -90,51 +90,6 @@
1
- -
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
@@ -155,51 +110,6 @@
2
-
-
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
@@ -241,51 +151,6 @@
0
-
-
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
@@ -348,51 +213,6 @@
4
-
-
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
@@ -434,51 +254,6 @@
3
-
-
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
@@ -520,51 +295,6 @@
5
-
-
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
@@ -620,51 +350,6 @@
6
-
-
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
@@ -713,51 +398,6 @@
7
-
-
-
- Not Assigned
-
-
- -
-
- Right Vertical
-
-
- -
-
- Right Horizontal
-
-
- -
-
- Left Vertical
-
-
- -
-
- Left Horizontal
-
-
- -
-
- P1
-
-
- -
-
- P2
-
-
- -
-
- P3/LS
-
-
- -
-
- RS
-
-
-
diff --git a/companion/src/simulation/radiooutputswidget.cpp b/companion/src/simulation/radiooutputswidget.cpp
index 76e257269..d51eba7fc 100644
--- a/companion/src/simulation/radiooutputswidget.cpp
+++ b/companion/src/simulation/radiooutputswidget.cpp
@@ -26,39 +26,32 @@
#include "eeprominterface.h"
#include "radiodata.h"
#include "simulator.h"
-#include "simulatorinterface.h"
extern AppData g; // ensure what "g" means
-const int RadioOutputsWidget::m_dataUpdateFreqDefault = 10; // ms
const quint16 RadioOutputsWidget::m_savedViewStateVersion = 1;
RadioOutputsWidget::RadioOutputsWidget(SimulatorInterface * simulator, Firmware * firmware, QWidget *parent) :
QWidget(parent),
m_simulator(simulator),
m_firmware(firmware),
- m_tmrUpdateData(new QTimer),
m_radioProfileId(g.sessionId()),
- m_lastFlightPhase(-1),
- m_started(false),
ui(new Ui::RadioOutputsWidget)
{
ui->setupUi(this);
restoreState();
- m_dataUpdateFreq = m_dataUpdateFreqDefault;
- m_tmrUpdateData->setInterval(m_dataUpdateFreq);
-
- connect(m_tmrUpdateData, &QTimer::timeout, this, &RadioOutputsWidget::setValues);
+ connect(m_simulator, &SimulatorInterface::channelOutValueChange, this, &RadioOutputsWidget::onChannelOutValueChange);
+ connect(m_simulator, &SimulatorInterface::virtualSwValueChange, this, &RadioOutputsWidget::onVirtSwValueChange);
+ connect(m_simulator, &SimulatorInterface::gVarValueChange, this, &RadioOutputsWidget::onGVarValueChange);
+ connect(m_simulator, &SimulatorInterface::phaseChanged, this, &RadioOutputsWidget::onPhaseChanged);
}
RadioOutputsWidget::~RadioOutputsWidget()
{
- stop();
+ //stop();
saveState();
- if (m_tmrUpdateData)
- delete m_tmrUpdateData;
delete ui;
}
@@ -74,36 +67,20 @@ void RadioOutputsWidget::changeEvent(QEvent *e)
}
}
-void RadioOutputsWidget::showEvent(QShowEvent * event)
-{
- if (m_started)
- m_tmrUpdateData->start();
-}
-
-void RadioOutputsWidget::hideEvent(QHideEvent * event)
-{
- m_tmrUpdateData->stop();
-}
-
void RadioOutputsWidget::start()
{
setupChannelsDisplay();
setupGVarsDisplay();
setupLsDisplay();
- m_lastFlightPhase = -1;
- m_tmrUpdateData->start();
- m_started = true;
}
-void RadioOutputsWidget::stop()
-{
- m_tmrUpdateData->stop();
- m_started = false;
-}
+//void RadioOutputsWidget::stop()
+//{
+//}
void RadioOutputsWidget::restart()
{
- stop();
+ //stop();
start();
}
@@ -139,7 +116,6 @@ void RadioOutputsWidget::restoreState()
ui->splitter->restoreState(splitterState);
}
-
void RadioOutputsWidget::setupChannelsDisplay()
{
int outputs = std::min(32, m_firmware->getCapability(Capability(Outputs)));
@@ -291,74 +267,79 @@ QWidget * RadioOutputsWidget::createLogicalSwitch(QWidget * parent, int switchNo
swtch->setMinimumWidth(swtch->fontMetrics().width("99") + 10);
font.setBold(false);
swtch->setFont(font);
- swtch->setText(QString("%1").arg(RawSwitch(SWITCH_TYPE_VIRTUAL, switchNo+1).toString().remove("L"), 2, QLatin1Char('0')));
+ swtch->setText(QString("%1").arg(switchNo+1, 2, 10, QChar('0')));
swtch->setAlignment(Qt::AlignCenter);
m_logicSwitchMap.insert(switchNo, swtch);
return swtch;
}
-// Read various values from firmware simulator and populate values in this UI
-void RadioOutputsWidget::setValues()
+void RadioOutputsWidget::onChannelOutValueChange(quint8 index, qint32 value)
{
- static TxOutputs prevOutputs = TxOutputs();
- int currentPhase;
- TxOutputs outputs;
- QFont font;
-
- m_simulator->getValues(outputs);
- currentPhase = m_simulator->getPhase();
-
- if (ui->channelsWidget->isVisible()) {
- QHash >::const_iterator ch;
- for (ch = m_channelsMap.constBegin(); ch != m_channelsMap.constEnd(); ++ch) {
- if (ch.key() >= CPN_MAX_CHNOUT)
- continue;
- ch.value().first->setText(QString("%1%").arg(outputs.chans[ch.key()] * 100 / 1024));
- ch.value().second->setValue(qMin(1024, qMax(-1024, outputs.chans[ch.key()])));
- }
+ if (m_channelsMap.contains(index)) {
+ QPair ch = m_channelsMap.value(index);
+ ch.first->setText(QString("%1%").arg(calcRESXto100(value)));
+ ch.second->setValue(qMin(1024, qMax(-1024, value)));
}
+ //qDebug() << index << value;
+}
- if (ui->logicalSwitchesWidget->isVisible()) {
- QHash::const_iterator ls;
- for (ls = m_logicSwitchMap.constBegin(); ls != m_logicSwitchMap.constEnd(); ++ls) {
- if (ls.key() >= CPN_MAX_CSW || (prevOutputs.vsw[ls.key()] == outputs.vsw[ls.key()] && m_lastFlightPhase > -1))
- continue;
- ls.value()->setBackgroundRole(outputs.vsw[ls.key()] ? QPalette::Dark : QPalette::Background);
- ls.value()->setForegroundRole(outputs.vsw[ls.key()] ? QPalette::BrightText : QPalette::WindowText);
- ls.value()->setFrameShadow(outputs.vsw[ls.key()] ? QFrame::Sunken : QFrame::Raised);
- font = ls.value()->font();
- font.setBold(outputs.vsw[ls.key()]);
- ls.value()->setFont(font);
- prevOutputs.vsw[ls.key()] = outputs.vsw[ls.key()];
- }
+void RadioOutputsWidget::onVirtSwValueChange(quint8 index, qint32 value)
+{
+ if (!m_logicSwitchMap.contains(index))
+ return;
+
+ QLabel * ls = m_logicSwitchMap.value(index);
+ ls->setBackgroundRole(value ? QPalette::Dark : QPalette::Background);
+ ls->setForegroundRole(value ? QPalette::BrightText : QPalette::WindowText);
+ ls->setFrameShadow(value ? QFrame::Sunken : QFrame::Raised);
+ QFont font = ls->font();
+ font.setBold((bool)value);
+ ls->setFont(font);
+ //qDebug() << index << value;
+}
+
+void RadioOutputsWidget::onGVarValueChange(quint8 index, qint32 value)
+{
+ if (!m_globalVarsMap.contains(index))
+ return;
+
+ QHash fmMap = m_globalVarsMap.value(index);
+ SimulatorInterface::gVarMode_t gv(value);
+
+ if (fmMap.contains(gv.mode)) {
+ QLabel * lbl = fmMap.value(gv.mode);
+ if (lbl)
+ lbl->setText(QString::number(gv.value));
}
+ //qDebug() << index << value << gv.mode << gv.value;
+}
+
+void RadioOutputsWidget::onPhaseChanged(qint32 phase, const QString &)
+{
+ QPalette::ColorRole fgrole, bgrole;
+ QLabel * lbl;
+ QFont font;
+ QHash >::const_iterator gv;
+ QHash::const_iterator fm;
- if (ui->globalVarsWidget->isVisible()) {
- QPalette::ColorRole bgrole;
- QHash >::const_iterator gv;
- QHash::const_iterator fm;
- for (gv = m_globalVarsMap.constBegin(); gv != m_globalVarsMap.constEnd(); ++gv) {
- if (gv.key() >= CPN_MAX_GVARS)
- continue;
- for (fm = gv.value().constBegin(); fm != gv.value().constEnd(); ++fm) {
- if (fm.key() >= CPN_MAX_FLIGHT_MODES)
- continue;
- if (currentPhase != m_lastFlightPhase || prevOutputs.gvars[fm.key()][gv.key()] != outputs.gvars[fm.key()][gv.key()]) {
- if (fm.key() == currentPhase)
- bgrole = QPalette::Dark;
- else
- bgrole = ((gv.key() % 2) ? QPalette::Background : QPalette::AlternateBase);
- fm.value()->setBackgroundRole(bgrole);
- fm.value()->setForegroundRole(fm.key() == currentPhase ? QPalette::BrightText : QPalette::WindowText);
- font = fm.value()->font();
- font.setBold(fm.key() == currentPhase);
- fm.value()->setFont(font);
- fm.value()->setText(QString::number(outputs.gvars[fm.key()][gv.key()]));
- prevOutputs.gvars[fm.key()][gv.key()] = outputs.gvars[fm.key()][gv.key()];
- }
+ for (gv = m_globalVarsMap.constBegin(); gv != m_globalVarsMap.constEnd(); ++gv) {
+ for (fm = gv.value().constBegin(); fm != gv.value().constEnd(); ++fm) {
+ lbl = fm.value();
+ font = lbl->font();
+ if (fm.key() == phase) {
+ fgrole = QPalette::BrightText;
+ bgrole = QPalette::Dark;
+ font.setBold(true);
}
+ else {
+ fgrole = QPalette::WindowText;
+ bgrole = ((gv.key() % 2) ? QPalette::Background : QPalette::AlternateBase);
+ font.setBold(false);
+ }
+ lbl->setForegroundRole(fgrole);
+ lbl->setBackgroundRole(bgrole);
+ lbl->setFont(font);
}
}
-
- m_lastFlightPhase = currentPhase;
+ //qDebug() << phase;
}
diff --git a/companion/src/simulation/radiooutputswidget.h b/companion/src/simulation/radiooutputswidget.h
index dbcd82d90..1f699e99d 100644
--- a/companion/src/simulation/radiooutputswidget.h
+++ b/companion/src/simulation/radiooutputswidget.h
@@ -22,6 +22,7 @@
#define RADIOOUTPUTSWIDGET_H
#include "simulator.h"
+#include "simulatorinterface.h"
#include
#include
@@ -31,7 +32,7 @@ class RadioOutputsWidget;
}
class Firmware;
-class SimulatorInterface;
+//class SimulatorInterface;
class QFrame;
class QLabel;
@@ -47,16 +48,18 @@ class RadioOutputsWidget : public QWidget
explicit RadioOutputsWidget(SimulatorInterface * simulator, Firmware * firmware, QWidget * parent = 0);
~RadioOutputsWidget();
+ public slots:
void start();
- void stop();
+ //void stop();
void restart();
protected slots:
void saveState();
void restoreState();
- void setValues();
- void showEvent(QShowEvent *event);
- void hideEvent(QHideEvent *event);
+ void onChannelOutValueChange(quint8 index, qint32 value);
+ void onVirtSwValueChange(quint8 index, qint32 value);
+ void onGVarValueChange(quint8 index, qint32 value);
+ void onPhaseChanged(qint32 phase, const QString &);
protected:
void changeEvent(QEvent *e);
@@ -67,7 +70,6 @@ class RadioOutputsWidget : public QWidget
SimulatorInterface * m_simulator;
Firmware * m_firmware;
- QTimer * m_tmrUpdateData;
QHash > m_channelsMap; // m_channelsMap[chanIndex] = {QLabel*, QSlider*}
QHash m_logicSwitchMap; // m_logicSwitchMap[lsIndex] = QLabel*
@@ -75,10 +77,7 @@ class RadioOutputsWidget : public QWidget
int m_radioProfileId;
int m_dataUpdateFreq;
- int m_lastFlightPhase;
- bool m_started;
- const static int m_dataUpdateFreqDefault;
const static quint16 m_savedViewStateVersion;
private:
diff --git a/companion/src/simulation/radiouiaction.h b/companion/src/simulation/radiouiaction.h
index cc3a4b5e1..d2904c491 100644
--- a/companion/src/simulation/radiouiaction.h
+++ b/companion/src/simulation/radiouiaction.h
@@ -37,12 +37,12 @@ class RadioUiAction : public QObject
/*
* @param index Typically this is the hardware array index corresponding to button on current radio model,
* but it could be anything. Use -1 or any other negative value for non-hardware indices.
- * @param key An optional Qt:Key code for shortcut.
+ * @param key An optional Qt:Key code for shortcut (zero for none).
* @param parent Parent widget, required for handling keyboard events.
* @param text Optional title for this action. The text and description are currently used in generated help text.
* @param descript Optional longer description text for this action.
*/
- RadioUiAction(int index = -1, int key = 0, QWidget * parent = NULL, const QString &text = "", const QString &descript = ""):
+ RadioUiAction(int index = -1, int key = 0, const QString &text = "", const QString &descript = "", QWidget * parent = NULL):
m_hwIndex(index),
m_active(false),
m_keys(QList()),
@@ -50,36 +50,50 @@ class RadioUiAction : public QObject
m_description(descript),
m_parent(parent)
{
- if (key)
- m_keys.append(key);
-
- init();
+ addKey(key);
}
/*
* @param keys QList of Qt:Key codes to use as shortcuts.
* [See above for other params.]
*/
- RadioUiAction(int index, QList keys, QWidget * parent = NULL, const QString &text = "", const QString &descript = ""):
- m_hwIndex(index),
- m_active(false),
- m_keys(keys),
- m_text(text),
- m_description(descript),
- m_parent(parent)
+ RadioUiAction(int index, QList keys, const QString &text = "", const QString &descript = "", QWidget * parent = NULL):
+ RadioUiAction(index, 0, text, descript, parent)
{
- init();
+ addKeys(keys);
}
- void init()
+ void addKey(const int & key)
{
- if (m_keys.size())
+ if (key > 0 && !m_keys.contains(key)) {
+ m_keys.append(key);
addShortcut();
+ }
+ }
+
+ void addKeys(const QList & keys)
+ {
+ foreach (int key, keys)
+ addKey(key);
}
void addShortcut()
{
- if (m_parent)
- m_parent->installEventFilter(this);
+ if (m_parent) {
+ m_parent->removeEventFilter(this);
+ if (m_keys.size())
+ m_parent->installEventFilter(this);
+ }
+ }
+
+ // override
+ void setParent(QObject * parent)
+ {
+ QObject::setParent(parent);
+ QWidget * w = qobject_cast(parent);
+ if (w && w != m_parent) {
+ m_parent = w;
+ addShortcut();
+ }
}
void setDescription(const QString & description) { m_description = description; }
diff --git a/companion/src/simulation/simulateduiwidget.cpp b/companion/src/simulation/simulateduiwidget.cpp
index fc4ed35bb..c3db6f4ef 100644
--- a/companion/src/simulation/simulateduiwidget.cpp
+++ b/companion/src/simulation/simulateduiwidget.cpp
@@ -22,8 +22,13 @@
#include "eeprominterface.h"
#include "lcdwidget.h"
#include "radiouiaction.h"
+#include "radiokeywidget.h"
#include "simulatorinterface.h"
+//#define FLASH_DURATION 10
+//#define CBEEP_ON "QLabel { background-color: #FF364E }"
+//#define CBEEP_OFF "QLabel { }"
+
SimulatedUIWidget::SimulatedUIWidget(SimulatorInterface * simulator, QWidget * parent) :
QWidget(parent),
m_simulator(simulator),
@@ -31,16 +36,18 @@ SimulatedUIWidget::SimulatedUIWidget(SimulatorInterface * simulator, QWidget * p
m_lcd(NULL),
m_scrollUpAction(NULL),
m_scrollDnAction(NULL),
- m_rotEncClickAction(NULL),
+ m_mouseMidClickAction(NULL),
+ m_screenshotAction(NULL),
m_board(getCurrentBoard()),
m_backLight(0),
- m_lightOn(false),
m_beepShow(0),
m_beepVal(0)
{
- m_rotEncClickAction = addRadioUiAction(-1, 0, tr("Rotary encoder click"));
- m_screenshotAction = addRadioUiAction(-1, Qt::Key_Print, tr("Take Screenshot"));
+ m_screenshotAction = new RadioUiAction(-1, Qt::Key_Print);
connect(m_screenshotAction, static_cast(&RadioUiAction::pushed), this, &SimulatedUIWidget::captureScreenshot);
+
+ connect(m_simulator, &SimulatorInterface::lcdChange, this, &SimulatedUIWidget::onLcdChange);
+ connect(this, &SimulatedUIWidget::simulatorWheelEvent, m_simulator, &SimulatorInterface::rotaryEncoderEvent);
}
SimulatedUIWidget::~SimulatedUIWidget()
@@ -49,28 +56,44 @@ SimulatedUIWidget::~SimulatedUIWidget()
if (act)
delete act;
}
+ foreach (RadioWidget * w, m_widgets) {
+ if (w)
+ delete w;
+ }
}
-RadioUiAction * SimulatedUIWidget::addRadioUiAction(RadioUiAction * act)
+RadioWidget * SimulatedUIWidget::addRadioWidget(RadioWidget * widget)
{
- if (act) {
+ if (widget && !m_widgets.contains(widget)) {
+ m_widgets.append(widget);
+ // TODO : connect to actions instead
+ connect(widget, &RadioWidget::valueChange, this, &SimulatedUIWidget::controlValueChange);
+ if (widget->getAction())
+ addRadioAction(widget->getAction());
+ }
+ return widget;
+}
+
+RadioUiAction * SimulatedUIWidget::addRadioAction(RadioUiAction * act)
+{
+ if (act && !m_actions.contains(act)) {
+ act->setParent(m_parent);
m_actions.append(act);
- if (!act->getText().isEmpty() && !act->getDescription().isEmpty())
- m_keymapHelp.append(keymapHelp_t(act->getText(), act->getDescription()));
}
return act;
}
-RadioUiAction * SimulatedUIWidget::addRadioUiAction(int index, int key, const QString & text, const QString & descript)
+QVector SimulatedUIWidget::getKeymapHelp() const
{
- return addRadioUiAction(new RadioUiAction(index, key, m_parent, text, descript));
-}
-
-RadioUiAction * SimulatedUIWidget::addRadioUiAction(int index, QList keys, const QString & text, const QString & descript)
-{
- return addRadioUiAction(new RadioUiAction(index, keys, m_parent, text, descript));
+ QVector keymapHelp;
+ foreach (RadioUiAction * act, m_actions) {
+ if (act && !act->getText().isEmpty())
+ keymapHelp.append(Simulator::keymapHelp_t(act->getText(), act->getDescription()));
+ }
+ return keymapHelp;
}
+// static
QPolygon SimulatedUIWidget::polyArc(int ctrX, int ctrY, int radius, int startAngle, int endAngle, int step)
{
QPolygon polygon;
@@ -83,20 +106,10 @@ QPolygon SimulatedUIWidget::polyArc(int ctrX, int ctrY, int radius, int startAng
return polygon;
}
+/* TODO : beep indicator
void SimulatedUIWidget::updateUi()
{
//static quint32 loop = 0;
- if (m_lcd->isVisible()) {
- bool lightEnable;
- if (m_simulator->lcdChanged(lightEnable)) {
- m_lcd->onLcdChanged(lightEnable);
- if (m_lightOn != lightEnable) {
- setLightOn(lightEnable);
- m_lightOn = lightEnable;
- }
- }
- }
- /* TODO : beep indicator
if (!(loop % 5)) {
TxOutputs outputs;
simulator->getValues(outputs);
@@ -111,7 +124,16 @@ void SimulatedUIWidget::updateUi()
beepShow--;
}
ui->label_beep->setStyleSheet(beepShow ? CBEEP_ON : CBEEP_OFF);
- } */
+ }
+} */
+
+void SimulatedUIWidget::onLcdChange(bool backlightEnable)
+{
+ if (!m_lcd || !m_lcd->isVisible())
+ return;
+
+ m_lcd->onLcdChanged(backlightEnable);
+ setLightOn(backlightEnable);
}
void SimulatedUIWidget::captureScreenshot()
@@ -136,32 +158,27 @@ void SimulatedUIWidget::captureScreenshot()
m_lcd->makeScreenshot(fileName);
}
-// steps can be negative or positive to determine direction (negative is UP/RIGHT scroll)
-void SimulatedUIWidget::simulatorWheelEvent(qint8 steps)
-{
- m_simulator->wheelEvent(steps);
-}
-
void SimulatedUIWidget::wheelEvent(QWheelEvent * event)
{
if (event->angleDelta().isNull())
return;
+ // steps can be negative or positive to determine direction (negative is UP/LEFT scroll)
QPoint numSteps = event->angleDelta() / 8 / 15 * -1; // one step per 15deg
- simulatorWheelEvent(numSteps.y());
+ emit simulatorWheelEvent(numSteps.y());
}
void SimulatedUIWidget::mousePressEvent(QMouseEvent * event)
{
- if (event->button() == Qt::MidButton && m_rotEncClickAction)
- m_rotEncClickAction->trigger(true);
+ if (event->button() == Qt::MidButton && m_mouseMidClickAction)
+ m_mouseMidClickAction->trigger(true);
else
event->ignore();
}
void SimulatedUIWidget::mouseReleaseEvent(QMouseEvent * event)
{
- if (event->button() == Qt::MidButton && m_rotEncClickAction)
- m_rotEncClickAction->trigger(false);
+ if (event->button() == Qt::MidButton && m_mouseMidClickAction)
+ m_mouseMidClickAction->trigger(false);
else
event->ignore();
}
@@ -184,13 +201,19 @@ void SimulatedUIWidget::setLcd(LcdWidget * lcd)
void SimulatedUIWidget::connectScrollActions()
{
- connect(m_scrollUpAction, static_cast(&RadioUiAction::pushed), [this](void) {
- this->simulatorWheelEvent(-1);
- m_scrollUpAction->toggle(false);
- });
+ if (m_scrollUpAction) {
+ addRadioAction(m_scrollUpAction);
+ connect(m_scrollUpAction, static_cast(&RadioUiAction::pushed), [this](void) {
+ emit simulatorWheelEvent(-1);
+ m_scrollUpAction->toggle(false);
+ });
+ }
- connect(m_scrollDnAction, static_cast(&RadioUiAction::pushed), [this](void) {
- simulatorWheelEvent(1);
- m_scrollDnAction->toggle(false);
- });
+ if (m_scrollDnAction) {
+ addRadioAction(m_scrollDnAction);
+ connect(m_scrollDnAction, static_cast(&RadioUiAction::pushed), [this](void) {
+ emit simulatorWheelEvent(1);
+ m_scrollDnAction->toggle(false);
+ });
+ }
}
diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h
index dba6e7435..225fb65fe 100644
--- a/companion/src/simulation/simulateduiwidget.h
+++ b/companion/src/simulation/simulateduiwidget.h
@@ -23,17 +23,18 @@
#include "boards.h"
#include "constants.h"
+#include "radiowidget.h"
#include "simulator.h"
+#include "simulator_strings.h"
#include
#include
class SimulatorInterface;
class LcdWidget;
+class RadioKeyWidget;
class RadioUiAction;
-using namespace Simulator;
-
/*
* This is a base class for the main hardware-specific radio user interface, including LCD screen and navigation buttons/widgets.
* It is responsible for hanlding all interactions with this part of the simulation (vs. common radio widgets like sticks/switches/knobs).
@@ -52,51 +53,51 @@ class SimulatedUIWidget : public QWidget
~SimulatedUIWidget();
- RadioUiAction * addRadioUiAction(RadioUiAction * act);
- RadioUiAction * addRadioUiAction(int index = -1, int key = 0, const QString &text = "", const QString &descript = "");
- RadioUiAction * addRadioUiAction(int index, QList keys, const QString &text = "", const QString &descript = "");
+ RadioWidget * addRadioWidget(RadioWidget * keyWidget);
+ RadioUiAction * addRadioAction(RadioUiAction * act);
- QVector * getKeymapHelp() { return &m_keymapHelp; }
- QList getActions() const { return m_actions; }
- RadioUiAction * getRotEncAction() const { return m_rotEncClickAction; }
+ QVector getKeymapHelp() const;
- QPolygon polyArc(int ctrX, int ctrY, int radius, int startAngle = 0, int endAngle = 360, int step = 10);
+ static QPolygon polyArc(int ctrX, int ctrY, int radius, int startAngle = 0, int endAngle = 360, int step = 10);
public slots:
- void updateUi();
void captureScreenshot();
- void simulatorWheelEvent(qint8 steps);
void wheelEvent(QWheelEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
- protected:
+ signals:
+
+ void controlValueChange(RadioWidget::RadioWidgetType type, int index, int value);
+ void customStyleRequest(const QString & style);
+ void simulatorWheelEvent(qint8 steps);
+
+ protected slots:
void setLcd(LcdWidget * lcd);
void connectScrollActions();
+ void onLcdChange(bool backlightEnable);
virtual void setLightOn(bool enable) { }
+ protected:
+
SimulatorInterface * m_simulator;
QWidget * m_parent;
LcdWidget * m_lcd;
QVector m_backlightColors;
- QVector m_keymapHelp;
QList m_actions;
+ QList m_widgets;
RadioUiAction * m_scrollUpAction;
RadioUiAction * m_scrollDnAction;
- RadioUiAction * m_rotEncClickAction;
+ RadioUiAction * m_mouseMidClickAction;
RadioUiAction * m_screenshotAction;
Board::Type m_board;
unsigned int m_backLight;
- bool m_lightOn;
int m_beepShow;
int m_beepVal;
- signals:
- void customStyleRequest(const QString & style);
-
};
diff --git a/companion/src/simulation/simulateduiwidget9X.cpp b/companion/src/simulation/simulateduiwidget9X.cpp
index 725511528..398593cf6 100644
--- a/companion/src/simulation/simulateduiwidget9X.cpp
+++ b/companion/src/simulation/simulateduiwidget9X.cpp
@@ -20,6 +20,7 @@
#include "simulateduiwidget.h"
#include "ui_simulateduiwidget9X.h"
+#include "eeprominterface.h"
SimulatedUIWidget9X::SimulatedUIWidget9X(SimulatorInterface * simulator, QWidget * parent):
SimulatedUIWidget(simulator, parent),
@@ -30,39 +31,49 @@ SimulatedUIWidget9X::SimulatedUIWidget9X(SimulatorInterface * simulator, QWidget
ui->setupUi(this);
+ bool hasRotEnc = getCurrentFirmware()->getCapability(Capability::RotaryEncoders);
+
// add actions in order of appearance on the help menu
int x = 68, y = 91, oR = 63;
polygon << QPoint(x, y) << polyArc(x, y, oR, -45, 45);
- act = addRadioUiAction(3, QList() << Qt::Key_Up << Qt::Key_PageUp, tr("UP/PG-UP"), tr("[ UP ]"));
- ui->leftbuttons->addArea(polygon, "9X/9xcursup.png", act);
+ act = new RadioUiAction(3, QList() << Qt::Key_Up << Qt::Key_PageUp, SIMU_STR_HLP_KEYS_GO_UP % (hasRotEnc ? QString("") : "|" % SIMU_STR_HLP_MOUSE_UP), SIMU_STR_HLP_ACT_UP);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursup.png", act));
polygon.clear();
polygon << QPoint(x, y) << polyArc(x, y, oR, 135, 225);
- act = addRadioUiAction(2, QList() << Qt::Key_Down << Qt::Key_PageDown, tr("DN/PG-DN"), tr("[ DN ]"));
- ui->leftbuttons->addArea(polygon, "9X/9xcursdown.png", act);
+ act = new RadioUiAction(2, QList() << Qt::Key_Down << Qt::Key_PageDown, SIMU_STR_HLP_KEYS_GO_DN % (hasRotEnc ? QString("") : "|" % SIMU_STR_HLP_MOUSE_DN), SIMU_STR_HLP_ACT_DN);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursdown.png", act));
polygon.clear();
polygon << QPoint(x, y) << polyArc(x, y, oR, 45, 135);
- act = addRadioUiAction(4, QList() << Qt::Key_Right << Qt::Key_Plus << Qt::Key_Equal, tr("RIGHT/+"), tr("[ + ]"));
- ui->leftbuttons->addArea(polygon, "9X/9xcursmin.png", act);
+ act = new RadioUiAction(4, QList() << Qt::Key_Right << Qt::Key_Minus, SIMU_STR_HLP_KEY_RGT % "|" % SIMU_STR_HLP_KEY_MIN, SIMU_STR_HLP_ACT_MIN);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursmin.png", act));
polygon.clear();
polygon << QPoint(x, y) << polyArc(x, y, oR, 225, 315);
- act = addRadioUiAction(5, QList() << Qt::Key_Left << Qt::Key_Minus, tr("LEFT/-"), tr("[ - ]"));
- ui->leftbuttons->addArea(polygon, "9X/9xcursplus.png", act);
+ act = new RadioUiAction(5, QList() << Qt::Key_Left << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_LFT % "|" % SIMU_STR_HLP_KEY_PLS, SIMU_STR_HLP_ACT_PLS);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursplus.png", act));
- act = addRadioUiAction(0, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("[ MENU ]"));
- m_rotEncClickAction = act;
- ui->rightbuttons->addArea(25, 60, 71, 81, "9X/9xmenumenu.png", act);
+ act = new RadioUiAction(0, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEY_ENTER, SIMU_STR_HLP_ACT_MENU);
+ addRadioWidget(ui->rightbuttons->addArea(QRect(16, 54, 60, 34), "9X/9xmenumenu.png", act));
- act = addRadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DEL/BKSP/ESC"), tr("[ EXIT ]"));
- ui->rightbuttons->addArea(25, 117, 71, 139, "9X/9xmenuexit.png", act);
+ if (!hasRotEnc) {
+ m_mouseMidClickAction = act;
+ m_mouseMidClickAction->setText(act->getText() % "|" % SIMU_STR_HLP_MOUSE_MID);
+ }
- ui->leftbuttons->addArea(-1, 148, 39, 182, "9X/9xcursphoto.png", m_screenshotAction);
+ act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
+ addRadioWidget(ui->rightbuttons->addArea(QRect(16, 114, 60, 34), "9X/9xmenuexit.png", act));
- m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("[ UP ]/[ DN ] or Rotary Sel.")));
+ addRadioWidget(ui->leftbuttons->addArea(QRect(6, 149, 30, 30), "9X/9xcursphoto.png", m_screenshotAction));
+
+ if (hasRotEnc) {
+ addRadioAction(new RadioUiAction(-1, 0, SIMU_STR_HLP_MOUSE_SCRL, SIMU_STR_HLP_ROTENC % "|" % SIMU_STR_HLP_ROTENC_LR));
+ m_mouseMidClickAction = new RadioUiAction(14, Qt::Key_Insert, SIMU_STR_HLP_KEY_INS % "|" % SIMU_STR_HLP_MOUSE_MID, SIMU_STR_HLP_ACT_ROT_DN);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(0, 0, 0, 0), "9X/9xcurs.png", m_mouseMidClickAction));
+ }
m_backlightColors << QColor(159,165,247);
m_backlightColors << QColor(166,247,159);
diff --git a/companion/src/simulation/simulateduiwidgetX12.cpp b/companion/src/simulation/simulateduiwidgetX12.cpp
index 7a3658799..6511e4393 100644
--- a/companion/src/simulation/simulateduiwidgetX12.cpp
+++ b/companion/src/simulation/simulateduiwidgetX12.cpp
@@ -35,48 +35,47 @@ SimulatedUIWidgetX12::SimulatedUIWidgetX12(SimulatorInterface *simulator, QWidge
int x = 74, y = 190, oR = 63, iR = 40;
polygon << polyArc(x, y, oR, 225, 315) << polyArc(x, y, iR, 225, 315);
- act = addRadioUiAction(0, QList() << Qt::Key_PageUp, tr("PG-UP"), tr("[ PgUp ]"));
- ui->leftbuttons->addArea(polygon, "Horus/left_btn1.png", act);
+ act = new RadioUiAction(0, QList() << Qt::Key_PageUp, SIMU_STR_HLP_KEY_PGUP, SIMU_STR_HLP_ACT_PGUP);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "Horus/left_btn1.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, 135, 225) << polyArc(x, y, iR, 135, 225);
- act = addRadioUiAction(1, QList() << Qt::Key_PageDown, tr("PG-DN"), tr("[ PgDn ]"));
- ui->leftbuttons->addArea(polygon, "Horus/left_btn2.png", act);
+ act = new RadioUiAction(1, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "Horus/left_btn2.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, -45, 45) << polyArc(x, y, iR, -45, 45);
- act = addRadioUiAction(3, QList() << Qt::Key_Up, tr("UP"), tr("[ MDL ]"));
- ui->rightbuttons->addArea(polygon, "Horus/right_btnU.png", act);
-
- polygon.clear();
- polygon << polyArc(x, y, oR, 135, 225) << polyArc(x, y, iR, 135, 225);
- act = addRadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DN/DEL/BKSP"), tr("[ RTN ]"));
- ui->rightbuttons->addArea(polygon, "Horus/right_btnD.png", act);
+ act = new RadioUiAction(3, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
+ addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnU.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, 225, 315) << polyArc(x, y, iR, 225, 315);
- act = addRadioUiAction(6, QList() << Qt::Key_Left, tr("LEFT"), tr("[ SYS ]"));
- ui->rightbuttons->addArea(polygon, "Horus/right_btnL.png", act);
+ act = new RadioUiAction(6, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS);
+ addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnL.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, 45, 135) << polyArc(x, y, iR, 45, 135);
- act = addRadioUiAction(5, QList() << Qt::Key_Right, tr("RIGHT"), tr("[ TELE ]"));
- ui->rightbuttons->addArea(polygon, "Horus/right_btnR.png", act);
+ act = new RadioUiAction(5, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE);
+ addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnR.png", act));
- m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("Rotary Selector")));
+ polygon.clear();
+ polygon << polyArc(x, y, oR, 135, 225) << polyArc(x, y, iR, 135, 225);
+ act = new RadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace,
+ SIMU_STR_HLP_KEY_DN % "
" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN);
+ addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnD.png", act));
- m_scrollUpAction = addRadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_X, tr("-/X"), tr("Rotary UP"));
- m_scrollDnAction = addRadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_C, tr("+/C"), tr("Rotary DOWN"));
+ m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT);
+ m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
+ connectScrollActions();
- act = addRadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("Selector Press"));
- ui->rightbuttons->addArea(polyArc(x, y, iR), "Horus/right_ent.png", act);
+ m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
+ addRadioWidget(ui->rightbuttons->addArea(polyArc(x, y, iR), "Horus/right_ent.png", m_mouseMidClickAction));
- ui->leftbuttons->addArea(9, 259, 34, 282, "Horus/left_scrnsht.png", m_screenshotAction);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(9, 259, 30, 30), "Horus/left_scrnsht.png", m_screenshotAction));
m_backlightColors << QColor(47, 123, 227);
setLcd(ui->lcd);
- connectScrollActions();
}
SimulatedUIWidgetX12::~SimulatedUIWidgetX12()
diff --git a/companion/src/simulation/simulateduiwidgetX7.cpp b/companion/src/simulation/simulateduiwidgetX7.cpp
index 993d01460..ee37a0621 100644
--- a/companion/src/simulation/simulateduiwidgetX7.cpp
+++ b/companion/src/simulation/simulateduiwidgetX7.cpp
@@ -14,26 +14,25 @@ SimulatedUIWidgetX7::SimulatedUIWidgetX7(SimulatorInterface *simulator, QWidget
QPoint ctr(70, 91);
polygon << polyArc(ctr.x(), ctr.y(), 50, -90, 90) << polyArc(ctr.x(), ctr.y(), 22, -90, 90);
- act = addRadioUiAction(3, QList() << Qt::Key_PageUp, tr("PG-UP"), tr("[ PAGE ]"));
- ui->leftbuttons->addArea(polygon, "X7/left_page.png", act);
+ act = new RadioUiAction(3, QList() << Qt::Key_PageUp << Qt::Key_Up, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_PAGE);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "X7/left_page.png", act));
- act = addRadioUiAction(0, QList() << Qt::Key_PageDown, tr("PG-DN"), tr("[ MENU ]"));
- ui->leftbuttons->addArea(polyArc(ctr.x(), ctr.y(), 20), "X7/left_menu.png", act);
+ act = new RadioUiAction(0, QList() << Qt::Key_PageDown << Qt::Key_Down, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_MENU_ICN);
+ addRadioWidget(ui->leftbuttons->addArea(polyArc(ctr.x(), ctr.y(), 20), "X7/left_menu.png", act));
polygon.clear();
polygon << polyArc(ctr.x(), ctr.y(), 50, 90, 270) << polyArc(ctr.x(), ctr.y(), 22, 90, 270);
- act = addRadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DEL/BKSP/ESC"), tr("[ EXIT ]"));
- ui->leftbuttons->addArea(polygon, "X7/left_exit.png", act);
+ act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "X7/left_exit.png", act));
- m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("Rotary Selector")));
- m_scrollUpAction = addRadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Up, tr("-/UP"), tr("Rotary UP"));
- m_scrollDnAction = addRadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Down, tr("+/DN"), tr("Rotary DOWN"));
+ m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Left, SIMU_STR_HLP_KEYS_GO_LFT, SIMU_STR_HLP_ACT_ROT_LFT);
+ m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Right, SIMU_STR_HLP_KEYS_GO_RGT, SIMU_STR_HLP_ACT_ROT_RGT);
connectScrollActions();
- act = addRadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("Selector Press"));
- ui->rightbuttons->addArea(polyArc(88, 92, 33), "X7/right_ent.png", act);
+ m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
+ addRadioWidget(ui->rightbuttons->addArea(polyArc(88, 92, 33), "X7/right_ent.png", m_mouseMidClickAction));
- ui->leftbuttons->addArea(9, 154, 34, 177, "X7/left_scrnshot.png", m_screenshotAction);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(9, 154, 30, 30), "X7/left_scrnshot.png", m_screenshotAction));
m_backlightColors << QColor(215, 243, 255); // X7 Blue
m_backlightColors << QColor(166,247,159);
diff --git a/companion/src/simulation/simulateduiwidgetX7.ui b/companion/src/simulation/simulateduiwidgetX7.ui
index 573be197b..46d6092ea 100644
--- a/companion/src/simulation/simulateduiwidgetX7.ui
+++ b/companion/src/simulation/simulateduiwidgetX7.ui
@@ -29,7 +29,7 @@
- Taranis X7 Simulator
+ Taranis X7 Simulator
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.757062 rgba(241, 238, 238, 255), stop:1 rgba(247, 245, 245, 255));
diff --git a/companion/src/simulation/simulateduiwidgetX9.cpp b/companion/src/simulation/simulateduiwidgetX9.cpp
index a3767fb7d..b274089bd 100644
--- a/companion/src/simulation/simulateduiwidgetX9.cpp
+++ b/companion/src/simulation/simulateduiwidgetX9.cpp
@@ -26,40 +26,46 @@ SimulatedUIWidgetX9::SimulatedUIWidgetX9(SimulatorInterface *simulator, QWidget
ui(new Ui::SimulatedUIWidgetX9)
{
RadioUiAction * act;
- QPolygon polygon;
ui->setupUi(this);
// add actions in order of appearance on the help menu
- act = addRadioUiAction(0, QList() << Qt::Key_PageUp, tr("PG-UP"), tr("[ MENU ]"));
- polygon.setPoints(6, 20, 59, 27, 50, 45, 52, 56, 59, 50, 71, 26, 72);
- ui->leftbuttons->addArea(polygon, "Taranis/x9l1.png", act);
+ // button placement, size, spacing
+ const int btop = 45, vsp = 17;
+ QRect btn(16, btop, 46, 31);
- act = addRadioUiAction(3, QList() << Qt::Key_PageDown, tr("PG-DN"), tr("[ PAGE ]"));
- polygon.setPoints(6, 23, 107, 30, 99, 46, 100, 55, 106, 47, 117, 28, 117);
- ui->leftbuttons->addArea(polygon, "Taranis/x9l2.png", act);
+ // left side
- act = addRadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DEL/BKSP/ESC"), tr("[ EXIT ]"));
- polygon.setPoints(6, 24, 154, 32, 144, 46, 146, 57, 156, 46, 167, 29, 166);
- ui->leftbuttons->addArea(polygon, "Taranis/x9l3.png", act);
+ act = new RadioUiAction(0, QList() << Qt::Key_Up << Qt::Key_PageUp, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU);
+ addRadioWidget(ui->leftbuttons->addArea(btn, "Taranis/x9l1.png", act));
+ btn.moveTop(btn.top() + btn.height() + vsp);
- m_scrollUpAction = addRadioUiAction(4, QList() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Up, tr("+/UP"), tr("[ + ]"));
- m_scrollDnAction = addRadioUiAction(5, QList() << Qt::Key_Minus << Qt::Key_Down, tr("-/DN"), tr("[ - ]"));
+ act = new RadioUiAction(3, QList() << Qt::Key_Down << Qt::Key_PageDown, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE);
+ addRadioWidget(ui->leftbuttons->addArea(btn, "Taranis/x9l2.png", act));
+ btn.moveTop(btn.top() + btn.height() + vsp);
- polygon.setPoints(6, 64, 60, 71, 50, 90, 50, 100, 60, 90, 73, 72, 73);
- ui->rightbuttons->addArea(polygon, "Taranis/x9r1.png", m_scrollUpAction);
+ act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
+ addRadioWidget(ui->leftbuttons->addArea(btn, "Taranis/x9l3.png", act));
- polygon.setPoints(6, 63, 109, 73, 100, 88, 100, 98, 109, 88, 119, 72, 119);
- ui->rightbuttons->addArea(polygon, "Taranis/x9r2.png", m_scrollDnAction);
+ m_scrollUpAction = new RadioUiAction(4, QList() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Left,
+ SIMU_STR_HLP_KEY_LFT % "|" % SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_PLS);
+ m_scrollDnAction = new RadioUiAction(5, QList() << Qt::Key_Minus << Qt::Key_Right,
+ SIMU_STR_HLP_KEY_RGT % "|" % SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_MIN);
- act = addRadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("[ ENT ]"));
- polygon.setPoints(6, 63, 155, 72, 146, 90, 146, 98, 155, 88, 166, 72, 166);
- ui->rightbuttons->addArea(polygon, "Taranis/x9r3.png", act);
+ // right side
+ btn.moveTopLeft(QPoint(58, btop));
- ui->leftbuttons->addArea(90, 177, 118, 197, "Taranis/x9l4.png", m_screenshotAction);
+ addRadioWidget(ui->rightbuttons->addArea(btn, "Taranis/x9r1.png", m_scrollUpAction));
+ btn.moveTop(btn.top() + btn.height() + vsp);
- m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("[ + ]/[ - ]")));
+ addRadioWidget(ui->rightbuttons->addArea(btn, "Taranis/x9r2.png", m_scrollDnAction));
+ btn.moveTop(btn.top() + btn.height() + vsp);
+
+ m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ENT);
+ addRadioWidget(ui->rightbuttons->addArea(btn, "Taranis/x9r3.png", m_mouseMidClickAction));
+
+ addRadioWidget(ui->leftbuttons->addArea(QRect(89, 177, 30, 20), "Taranis/x9l4.png", m_screenshotAction));
m_backlightColors << QColor(47, 123, 227); // Taranis Blue
m_backlightColors << QColor(166,247,159);
diff --git a/companion/src/simulation/simulateduiwidgetX9E.cpp b/companion/src/simulation/simulateduiwidgetX9E.cpp
index 8f3f97008..2c0d6adfa 100644
--- a/companion/src/simulation/simulateduiwidgetX9E.cpp
+++ b/companion/src/simulation/simulateduiwidgetX9E.cpp
@@ -35,28 +35,27 @@ SimulatedUIWidgetX9E::SimulatedUIWidgetX9E(SimulatorInterface *simulator, QWidge
QPoint ctr(70, 100);
polygon << polyArc(ctr.x(), ctr.y(), 60, -90, 0) << ctr;
- act = addRadioUiAction(0, QList() << Qt::Key_PageUp, tr("PG-UP"), tr("[ MENU ]"));
- ui->leftbuttons->addArea(polygon, "X9E/left_menu.png", act);
+ act = new RadioUiAction(0, QList() << Qt::Key_Up << Qt::Key_PageUp, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "X9E/left_menu.png", act));
polygon.clear();
polygon << polyArc(ctr.x(), ctr.y(), 45, 0, 180);
- act = addRadioUiAction(3, QList() << Qt::Key_PageDown, tr("PG-DN"), tr("[ PAGE ]"));
- ui->leftbuttons->addArea(polygon, "X9E/left_page.png", act);
+ act = new RadioUiAction(3, QList() << Qt::Key_Down << Qt::Key_PageDown, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "X9E/left_page.png", act));
polygon.clear();
polygon << polyArc(ctr.x(), ctr.y(), 60, 180, 270) << ctr;
- act = addRadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DEL/BKSP/ESC"), tr("[ EXIT ]"));
- ui->leftbuttons->addArea(polygon, "X9E/left_exit.png", act);
+ act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
+ addRadioWidget(ui->leftbuttons->addArea(polygon, "X9E/left_exit.png", act));
- m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("Rotary Selector")));
- m_scrollUpAction = addRadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Up, tr("-/UP"), tr("Rotary UP"));
- m_scrollDnAction = addRadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Down, tr("+/DN"), tr("Rotary DOWN"));
+ m_scrollUpAction = addRadioAction(new RadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Left, SIMU_STR_HLP_KEYS_GO_LFT, SIMU_STR_HLP_ACT_ROT_LFT));
+ m_scrollDnAction = addRadioAction(new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Right, SIMU_STR_HLP_KEYS_GO_RGT, SIMU_STR_HLP_ACT_ROT_RGT));
connectScrollActions();
- act = addRadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("Selector Press"));
- ui->rightbuttons->addArea(polyArc(90, 100, 50), "X9E/right_enter.png", act);
+ m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
+ addRadioWidget(ui->rightbuttons->addArea(polyArc(90, 100, 50), "X9E/right_enter.png", m_mouseMidClickAction));
- ui->leftbuttons->addArea(10, 170, 40, 200, "X9E/left_scrnshot.png", m_screenshotAction);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(10, 170, 30, 30), "X9E/left_scrnshot.png", m_screenshotAction));
m_backlightColors << QColor(47, 123, 227); // Taranis Blue
m_backlightColors << QColor(166,247,159);
diff --git a/companion/src/simulation/simulator_strings.h b/companion/src/simulation/simulator_strings.h
new file mode 100644
index 000000000..795901048
--- /dev/null
+++ b/companion/src/simulation/simulator_strings.h
@@ -0,0 +1,66 @@
+#ifndef SIMULATOR_STRINGS_H
+#define SIMULATOR_STRINGS_H
+
+#include
+
+#define SIMU_STR_HLP_KEY_ENTER QCoreApplication::translate("SimulatedUIWidget", "ENTER")
+#define SIMU_STR_HLP_KEY_PGUP QCoreApplication::translate("SimulatedUIWidget", "PG-UP")
+#define SIMU_STR_HLP_KEY_PGDN QCoreApplication::translate("SimulatedUIWidget", "PG-DN")
+#define SIMU_STR_HLP_KEY_DEL QCoreApplication::translate("SimulatedUIWidget", "DEL")
+#define SIMU_STR_HLP_KEY_BKSP QCoreApplication::translate("SimulatedUIWidget", "BKSP")
+#define SIMU_STR_HLP_KEY_ESC QCoreApplication::translate("SimulatedUIWidget", "ESC")
+#define SIMU_STR_HLP_KEY_INS QCoreApplication::translate("SimulatedUIWidget", "INS")
+#define SIMU_STR_HLP_KEY_PLS QCoreApplication::translate("SimulatedUIWidget", "+")
+#define SIMU_STR_HLP_KEY_MIN QCoreApplication::translate("SimulatedUIWidget", "-")
+
+#define SIMU_STR_HLP_KEY_LFT QCoreApplication::translate("SimulatedUIWidget", "←") // ←
+#define SIMU_STR_HLP_KEY_RGT QCoreApplication::translate("SimulatedUIWidget", "→") // →
+#define SIMU_STR_HLP_KEY_UP QCoreApplication::translate("SimulatedUIWidget", "↑") // ↑
+#define SIMU_STR_HLP_KEY_DN QCoreApplication::translate("SimulatedUIWidget", "↓") // ↓
+
+#define SIMU_STR_HLP_ROTENC QCoreApplication::translate("SimulatedUIWidget", "⚆") // ⚆
+#define SIMU_STR_HLP_ROTENC_LFT QCoreApplication::translate("SimulatedUIWidget", "↶") // ↶
+#define SIMU_STR_HLP_ROTENC_RGT QCoreApplication::translate("SimulatedUIWidget", "↷") // ↷
+#define SIMU_STR_HLP_ROTENC_LR QCoreApplication::translate("SimulatedUIWidget", "⇆") // ⇆
+#define SIMU_STR_HLP_ROTENC_DN QCoreApplication::translate("SimulatedUIWidget", "⇓") // ⇓
+
+#define SIMU_STR_HLP_SCRL_UP QCoreApplication::translate("SimulatedUIWidget", "⇑") // ⇑
+#define SIMU_STR_HLP_SCRL_DN QCoreApplication::translate("SimulatedUIWidget", "⇓") // ⇓
+#define SIMU_STR_HLP_SCRL_UD QCoreApplication::translate("SimulatedUIWidget", "⇕") // ⇕
+
+#define SIMU_STR_HLP_MOUSE QCoreApplication::translate("SimulatedUIWidget", " ")
+#define SIMU_STR_HLP_CLICK QCoreApplication::translate("SimulatedUIWidget", " ")
+#define SIMU_STR_HLP_MOUSE_MID SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_CLICK
+#define SIMU_STR_HLP_MOUSE_UP SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_SCRL_UP
+#define SIMU_STR_HLP_MOUSE_DN SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_SCRL_DN
+#define SIMU_STR_HLP_MOUSE_SCRL SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_SCRL_UD
+
+#define SIMU_STR_HLP_ACT_MENU QCoreApplication::translate("SimulatedUIWidget", "[ MENU ] ")
+#define SIMU_STR_HLP_ACT_PAGE QCoreApplication::translate("SimulatedUIWidget", "[ PAGE ] ")
+#define SIMU_STR_HLP_ACT_EXIT QCoreApplication::translate("SimulatedUIWidget", "[ EXIT ] ")
+#define SIMU_STR_HLP_ACT_ENT QCoreApplication::translate("SimulatedUIWidget", "[ ENT ] ")
+#define SIMU_STR_HLP_ACT_UP QCoreApplication::translate("SimulatedUIWidget", "[ UP ] ")
+#define SIMU_STR_HLP_ACT_DN QCoreApplication::translate("SimulatedUIWidget", "[ DN ] ")
+#define SIMU_STR_HLP_ACT_PLS QCoreApplication::translate("SimulatedUIWidget", "[ + ] ")
+#define SIMU_STR_HLP_ACT_MIN QCoreApplication::translate("SimulatedUIWidget", "[ - ] ")
+#define SIMU_STR_HLP_ACT_PGUP QCoreApplication::translate("SimulatedUIWidget", "[ PgUp ] ")
+#define SIMU_STR_HLP_ACT_PGDN QCoreApplication::translate("SimulatedUIWidget", "[ PgDn ] ")
+#define SIMU_STR_HLP_ACT_MDL QCoreApplication::translate("SimulatedUIWidget", "[ MDL ] ")
+#define SIMU_STR_HLP_ACT_RTN QCoreApplication::translate("SimulatedUIWidget", "[ RTN ] ")
+#define SIMU_STR_HLP_ACT_SYS QCoreApplication::translate("SimulatedUIWidget", "[ SYS ] ")
+#define SIMU_STR_HLP_ACT_TELE QCoreApplication::translate("SimulatedUIWidget", "[ TELE ] ")
+#define SIMU_STR_HLP_ACT_MENU_ICN QCoreApplication::translate("SimulatedUIWidget", "≡") // ≡
+
+
+#define SIMU_STR_HLP_KEYS_EXIT SIMU_STR_HLP_KEY_DEL % "|" % SIMU_STR_HLP_KEY_BKSP % "|" % SIMU_STR_HLP_KEY_ESC
+#define SIMU_STR_HLP_KEYS_ACTIVATE SIMU_STR_HLP_KEY_ENTER % "|" % SIMU_STR_HLP_MOUSE_MID
+#define SIMU_STR_HLP_KEYS_GO_UP SIMU_STR_HLP_KEY_UP % "|" % SIMU_STR_HLP_KEY_PGUP
+#define SIMU_STR_HLP_KEYS_GO_DN SIMU_STR_HLP_KEY_DN % "|" % SIMU_STR_HLP_KEY_PGDN
+#define SIMU_STR_HLP_KEYS_GO_LFT SIMU_STR_HLP_KEY_LFT % "|" % SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP
+#define SIMU_STR_HLP_KEYS_GO_RGT SIMU_STR_HLP_KEY_RGT % "|" % SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN
+
+#define SIMU_STR_HLP_ACT_ROT_LFT SIMU_STR_HLP_ROTENC % " " % SIMU_STR_HLP_ROTENC_LFT
+#define SIMU_STR_HLP_ACT_ROT_RGT SIMU_STR_HLP_ROTENC % " " % SIMU_STR_HLP_ROTENC_RGT
+#define SIMU_STR_HLP_ACT_ROT_DN SIMU_STR_HLP_ROTENC % " " % SIMU_STR_HLP_ROTENC_DN
+
+#endif // SIMULATOR_STRINGS_H
diff --git a/companion/src/simulation/simulatorimport.h b/companion/src/simulation/simulatorimport.h
deleted file mode 100644
index 3ec4527fa..000000000
--- a/companion/src/simulation/simulatorimport.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) OpenTX
- *
- * Based on code named
- * th9x - http://code.google.com/p/th9x
- * er9x - http://code.google.com/p/er9x
- * gruvin9x - http://code.google.com/p/gruvin9x
- *
- * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include
-
-#if !defined(MAX_LOGICAL_SWITCHES) && defined(NUM_CSW)
-#define MAX_LOGICAL_SWITCHES NUM_CSW
-#endif
-
-#ifdef INIT_IMPORT
-#undef INIT_IMPORT
-#ifdef TELEMETRY_FRSKY
-telemetryStreaming = 20;
-#endif
-#endif
-
-#ifdef SETVALUES_IMPORT
-#undef SETVALUES_IMPORT
-for (int i=0; iPIO_PDSR &= ~0x40;
- else
- PIOB->PIO_PDSR |= 0x40;
-#else
- if (inputs.rotenc)
- simuSetKey(KEY_ENTER, true);
-#endif
-#endif // SETVALUES_IMPORT
-
-#ifdef GETVALUES_IMPORT
-#undef GETVALUES_IMPORT
-memset(outputs.chans, 0, sizeof(outputs.chans));
-for (unsigned int i=0; i
-#include
-#include
-#include
-#include
-#include
+#include "customdebug.h"
#include "version.h"
+
+#include
+#include
+
#if defined _MSC_VER || !defined __GNUC__
#include
#endif
-QMap registered_simulators;
+#ifndef SIMULATOR_INTERFACE_LOADER_METHOD
+ #define SIMULATOR_INTERFACE_LOADER_DYNAMIC 1 // How to load simulator libraries: 1=dynamic load and unload; 0=load once (old way)
+#endif
-void registerSimulator(const QString & filename)
+QMap SimulatorLoader::registeredSimulators;
+
+QStringList SimulatorLoader::getAvailableSimulators()
{
- QLibrary lib(filename);
- typedef SimulatorFactory * (*RegisterSimulator)();
- qDebug() << "trying to register simulator in " << filename;
- RegisterSimulator registerFunc = (RegisterSimulator)lib.resolve("registerSimu");
- if (registerFunc) {
- SimulatorFactory * factory = registerFunc();
- registered_simulators[factory->name()] = factory;
- qDebug() << "Registered" << factory->name() << "simulator";
- }
- else {
- qWarning() << "Library error" << filename << lib.errorString();
- }
+ return registeredSimulators.keys();
}
-int registerSimulators(const QDir & dir)
+int SimulatorLoader::registerSimulators(const QDir & dir)
{
- int noSimulatorsFound = 0;
QStringList filters;
#if defined(__APPLE__)
filters << "*-simulator.dylib";
@@ -59,17 +50,41 @@ int registerSimulators(const QDir & dir)
#else
filters << "*-simulator.so";
#endif
+ registeredSimulators.clear();
+
+ qCDebug(simulatorInterfaceLoader) << "Searching for simulators in" << dir.path() << "matching pattern" << filters;
- qDebug() << "Searching for simulators in" << dir.path();
foreach(QString filename, dir.entryList(filters, QDir::Files)) {
- QString libraryFilename = dir.path() + "/" + filename;
- registerSimulator(libraryFilename);
- noSimulatorsFound++;
+ QLibrary * lib = new QLibrary( dir.path() + "/" + filename);
+
+ qCDebug(simulatorInterfaceLoader) << "Trying to register simulator in " << filename;
+
+ SimulatorFactory * factory;
+ RegisterSimulator registerFunc = (RegisterSimulator)lib->resolve("registerSimu");
+
+ if (registerFunc && (factory = registerFunc())) {
+ if (getAvailableSimulators().contains(factory->name()))
+ continue;
+
+ lib->setProperty("instances_used", 0);
+ registeredSimulators.insert(factory->name(), lib);
+ delete factory;
+#if SIMULATOR_INTERFACE_LOADER_DYNAMIC
+ lib->unload();
+#endif
+ qCDebug(simulatorInterfaceLoader) << "Registered" << registeredSimulators.lastKey() << "simulator in " << lib->fileName() << "and unloaded:" << !lib->isLoaded();
+ }
+ else {
+ qWarning() << "Library error" << lib->fileName() << lib->errorString();
+ delete lib;
+ }
+
}
- return noSimulatorsFound;
+ qCDebug(simulatorInterfaceLoader) << "Found libraries:" << (registeredSimulators.size() ? registeredSimulators.keys() : QStringList() << "none");
+ return registeredSimulators.size();
}
-void registerSimulators()
+void SimulatorLoader::registerSimulators()
{
QDir dir(".");
if (registerSimulators(dir)) {
@@ -90,31 +105,93 @@ void registerSimulators()
registerSimulators(dir);
}
-SimulatorFactory * getSimulatorFactory(const QString & name)
+void SimulatorLoader::unregisterSimulators()
{
+ foreach(QLibrary * lib, registeredSimulators)
+ delete lib;
+}
+
+QString SimulatorLoader::findSimulatorByFirmwareName(const QString & name)
+{
+ int pos;
+ QString ret;
QString simuName = name;
+
while(1) {
- qDebug() << "searching" << simuName << "simulator";
- foreach (QString name, registered_simulators.keys()) {
- if (name.contains(simuName)) {
- simuName = name;
- qDebug() << "found" << simuName;
- return registered_simulators[simuName];
- }
+ qCDebug(simulatorInterfaceLoader) << "searching" << simuName << "simulator";
+ if (registeredSimulators.contains(simuName)) {
+ ret = simuName;
+ break;
}
- int pos = simuName.lastIndexOf('-');
- if (pos <= 0)
+ if ((pos = simuName.lastIndexOf('-')) <= 0)
break;
simuName = simuName.mid(0, pos);
if (simuName.count('-') == 0)
break;
}
- return NULL;
+ return ret;
}
-void unregisterSimulators()
+SimulatorInterface * SimulatorLoader::loadSimulator(const QString & name)
{
- foreach(SimulatorFactory *factory, registered_simulators) {
+ SimulatorInterface * si = NULL;
+ QString libname = findSimulatorByFirmwareName(name);
+
+ if (libname.isEmpty()) {
+ qWarning() << "Simulator" << name << "not found.";
+ return si;
+ }
+
+ QLibrary * lib = registeredSimulators.value(libname, NULL);
+ if (!lib) {
+ qWarning() << "Simulator library is NULL";
+ return si;
+ }
+
+ qCDebug(simulatorInterfaceLoader) << "Trying to load simulator in " << lib->fileName();
+
+ SimulatorFactory * factory;
+ RegisterSimulator registerFunc = (RegisterSimulator)lib->resolve("registerSimu");
+ if (registerFunc && (factory = registerFunc()) && (si = factory->create())) {
+ quint8 instance = lib->property("instances_used").toUInt();
+ lib->setProperty("instances_used", ++instance);
+ qCDebug(simulatorInterfaceLoader) << "Loaded" << factory->name() << "simulator instance" << instance;
delete factory;
}
+ else {
+ qWarning() << "Library error" << lib->fileName() << lib->errorString();
+ }
+ return si;
+}
+
+bool SimulatorLoader::unloadSimulator(const QString & name)
+{
+ bool ret = false;
+#if SIMULATOR_INTERFACE_LOADER_DYNAMIC
+ QString simuName = findSimulatorByFirmwareName(name);
+ if (simuName.isEmpty())
+ return ret;
+
+ QLibrary * lib = registeredSimulators.value(simuName, NULL);
+
+ if (lib && lib->isLoaded()) {
+ quint8 instance = lib->property("instances_used").toUInt();
+ lib->setProperty("instances_used", --instance);
+ if (!instance) {
+ ret = lib->unload();
+ qCDebug(simulatorInterfaceLoader) << "Unloading" << simuName << "(" << lib->fileName() << ")" << "result:" << ret;
+ }
+ else {
+ ret = true;
+ qCDebug(simulatorInterfaceLoader) << "Simulator" << simuName << "instances remaining:" << instance;
+ }
+ }
+ else {
+ qCDebug(simulatorInterfaceLoader) << "Simulator library for " << simuName << "already unloaded.";
+ }
+#else
+ qCDebug(simulatorInterfaceLoader) << "Keeping simulator library" << simuName << "loaded.";
+#endif
+
+ return ret;
}
diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h
index 42fef7557..6be9040ad 100644
--- a/companion/src/simulation/simulatorinterface.h
+++ b/companion/src/simulation/simulatorinterface.h
@@ -23,108 +23,170 @@
#include "boards.h"
#include "constants.h"
+
+#include
#include
+
+#include
#include
#include
+#include
+#include
#include
-#include
-struct TxInputs
-{
- int sticks[CPN_MAX_STICKS]; /* lh lv rv rh */
- int pots[CPN_MAX_POTS];
- int switches[CPN_MAX_SWITCHES];
- bool keys[CPN_MAX_KEYS];
- bool rotenc;
- bool trims[(CPN_MAX_STICKS + CPN_MAX_AUX_TRIMS) * 2];
-};
+#define SIMULATOR_INTERFACE_HEARTBEAT_PERIOD 1000 // ms
-class TxOutputs
+class SimulatorInterface : public QObject
{
+ Q_OBJECT
+
public:
- TxOutputs() { memset(this, 0, sizeof(TxOutputs)); }
- int chans[CPN_MAX_CHNOUT];
- bool vsw[CPN_MAX_CSW];
- int gvars[CPN_MAX_FLIGHT_MODES][CPN_MAX_GVARS];
- unsigned int beep;
- // uint8_t phase;
-};
-struct Trims
-{
- int values[CPN_MAX_STICKS]; /* lh lv rv rh */
- bool extended;
-};
+ enum InputSourceType {
+ INPUT_SRC_NONE = 0,
+ INPUT_SRC_ANALOG, // any analog source, index into g_anas[]
+ INPUT_SRC_STICK, // Board::StickAxes, g_anas[index]
+ INPUT_SRC_KNOB, // g_anas[index + StickAxes]
+ INPUT_SRC_SLIDER, // g_anas[index + StickAxes + num_pots]
+ INPUT_SRC_TXVIN, // g_anas[Analogs::TX_VOLTAGE]
+ INPUT_SRC_SWITCH, // Named 2/3-pos switches
+ INPUT_SRC_TRIM_SW, // Board::TrimSwitches
+ INPUT_SRC_TRIM, // Board::TrimAxes
+ INPUT_SRC_KEY, // UI key/pushbutton
+ INPUT_SRC_ROTENC, // Rotary encoder (TODO)
+ INPUT_SRC_TRAINER, // Virtual trainer input
+ INPUT_SRC_ENUM_COUNT
+ };
-class SimulatorInterface
-{
- public:
+ enum OutputSourceType {
+ OUTPUT_SRC_NONE = 0,
+ OUTPUT_SRC_CHAN_OUT,
+ OUTPUT_SRC_CHAN_MIX,
+ OUTPUT_SRC_TRIM_VALUE,
+ OUTPUT_SRC_TRIM_RANGE,
+ OUTPUT_SRC_VIRTUAL_SW,
+ OUTPUT_SRC_PHASE,
+ OUTPUT_SRC_GVAR,
+ OUTPUT_SRC_ENUM_COUNT
+ };
+
+ // only for data not available from Boards or Firmware, eg. compile-time options
+ enum Capability {
+ CAP_LUA, // LUA
+ CAP_ROTARY_ENC, // ROTARY_ENCODERS
+ CAP_ROTARY_ENC_NAV, // ROTARY_ENCODER_NAVIGATION
+ CAP_TELEM_FRSKY_SPORT, // TELEMETRY_FRSKY_SPORT
+ CAP_ENUM_COUNT
+ };
+
+ // This allows automatic en/decoding of flight mode + gvar value to/from any int32
+ struct gVarMode_t {
+ int16_t value;
+ uint8_t mode;
+
+ gVarMode_t(int i = 0) {
+ set(i);
+ }
+ void set(int i) {
+ mode = (i >> 16) & 0xFF;
+ value = (i & 0xFFFF);
+ }
+ operator int() {
+ return ((mode << 16) | (value & 0xFFFF));
+ }
+ gVarMode_t & operator =(const int i) {
+ set(i);
+ return *this;
+ }
+ };
+
+ struct TxOutputs {
+ TxOutputs() { clear(); }
+ void clear() { memset(this, 0, sizeof(TxOutputs)); }
+
+ int16_t chans[CPN_MAX_CHNOUT]; // final channel outputs
+ int16_t ex_chans[CPN_MAX_CHNOUT]; // raw mix outputs
+ int16_t gvars[CPN_MAX_FLIGHT_MODES][CPN_MAX_GVARS];
+ int trims[CPN_MAX_TRIMS]; // Board::TrimAxes enum
+ bool vsw[CPN_MAX_LOGICAL_SWITCHES]; // virtual/logic switches
+ int8_t phase;
+ qint16 trimRange; // TRIM_MAX or TRIM_EXTENDED_MAX
+ // bool beep;
+ };
virtual ~SimulatorInterface() {}
- virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") { }
-
- virtual void setVolumeGain(int value) { }
-
- virtual void start(QByteArray & eeprom, bool tests=true) = 0;
-
- virtual void start(const char * filename, bool tests=true) = 0;
-
- virtual void stop() = 0;
-
- virtual void readEepromData(QByteArray & dest) = 0;
-
- virtual bool timer10ms() = 0;
-
+ virtual QString name() = 0;
+ virtual bool isRunning() = 0;
+ virtual void readRadioData(QByteArray & dest) = 0;
virtual uint8_t * getLcd() = 0;
-
- virtual bool lcdChanged(bool &lightEnable) = 0;
-
- virtual void setValues(TxInputs &inputs) = 0;
-
- virtual void getValues(TxOutputs &outputs) = 0;
-
- virtual void setTrim(unsigned int idx, int value) = 0;
-
- virtual void getTrims(Trims &trims) = 0;
-
- virtual unsigned int getPhase() = 0;
-
- virtual const char * getPhaseName(unsigned int phase) = 0;
-
- virtual void wheelEvent(int steps) { }
-
- virtual const char * getError() = 0;
-
- virtual void sendTelemetry(uint8_t * data, unsigned int len) = 0;
-
virtual uint8_t getSensorInstance(uint16_t id, uint8_t defaultValue = 0) = 0;
-
virtual uint16_t getSensorRatio(uint16_t id) = 0;
+ virtual const int getCapability(Capability cap) = 0;
+ public slots:
+
+ virtual void init() = 0;
+ virtual void start(const char * filename = NULL, bool tests = true) = 0;
+ virtual void stop() = 0;
+ virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") = 0;
+ virtual void setVolumeGain(const int value) = 0;
+ virtual void setRadioData(const QByteArray & data) = 0;
+ virtual void setAnalogValue(uint8_t index, int16_t value) = 0;
+ virtual void setKey(uint8_t key, bool state) = 0;
+ virtual void setSwitch(uint8_t swtch, int8_t state) = 0;
+ virtual void setTrim(unsigned int idx, int value) = 0;
+ virtual void setTrimSwitch(uint8_t trim, bool state) = 0;
virtual void setTrainerInput(unsigned int inputNumber, int16_t value) = 0;
-
- virtual void installTraceHook(void (*callback)(const char *)) = 0;
-
+ virtual void setInputValue(int type, uint8_t index, int16_t value) = 0;
+ virtual void rotaryEncoderEvent(int steps) = 0;
+ virtual void setTrainerTimeout(uint16_t ms) = 0;
+ virtual void sendTelemetry(const QByteArray data) = 0;
virtual void setLuaStateReloadPermanentScripts() = 0;
+ virtual void addTracebackDevice(QIODevice * device) = 0;
+ virtual void removeTracebackDevice(QIODevice * device) = 0;
+
+ signals:
+
+ void started();
+ void stopped();
+ void heartbeat(qint32 loops, qint64 timestamp);
+ void runtimeError(const QString & error);
+ void lcdChange(bool backlightEnable);
+ void phaseChanged(qint8 phase, const QString & name);
+ void channelOutValueChange(quint8 index, qint32 value);
+ void channelMixValueChange(quint8 index, qint32 value);
+ void virtualSwValueChange(quint8 index, qint32 value);
+ void trimValueChange(quint8 index, qint32 value);
+ void trimRangeChange(quint8 index, qint32 min, qint16 max);
+ void gVarValueChange(quint8 index, qint32 value);
+ void outputValueChange(int type, quint8 index, qint32 value);
};
class SimulatorFactory {
public:
-
virtual ~SimulatorFactory() { }
-
virtual QString name() = 0;
-
virtual Board::Type type() = 0;
-
virtual SimulatorInterface *create() = 0;
};
-void registerSimulators();
-void unregisterSimulators();
-SimulatorFactory *getSimulatorFactory(const QString &name);
-extern QMap registered_simulators;
+class SimulatorLoader
+{
+ public:
+ static void registerSimulators();
+ static void unregisterSimulators();
+ static QStringList getAvailableSimulators();
+ static QString findSimulatorByFirmwareName(const QString & name);
+ static SimulatorInterface * loadSimulator(const QString & name);
+ static bool unloadSimulator(const QString & name);
+
+ protected:
+ typedef SimulatorFactory * (*RegisterSimulator)();
+
+ static int registerSimulators(const QDir & dir);
+ static QMap registeredSimulators;
+};
#endif // _SIMULATORINTERFACE_H_
diff --git a/companion/src/simulation/simulatormainwindow.cpp b/companion/src/simulation/simulatormainwindow.cpp
index c530fc82c..9fe5e969e 100644
--- a/companion/src/simulation/simulatormainwindow.cpp
+++ b/companion/src/simulation/simulatormainwindow.cpp
@@ -33,14 +33,15 @@
#endif
#include
+#include
+#include
extern AppData g; // ensure what "g" means
const quint16 SimulatorMainWindow::m_savedUiStateVersion = 2;
-SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * simulator, quint8 flags, Qt::WindowFlags wflags) :
+SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & firmwareId, quint8 flags, Qt::WindowFlags wflags) :
QMainWindow(parent, wflags),
- m_simulator(simulator),
ui(new Ui::SimulatorMainWindow),
m_simulatorWidget(NULL),
m_consoleWidget(NULL),
@@ -50,12 +51,27 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * s
m_telemetryDockWidget(NULL),
m_trainerDockWidget(NULL),
m_outputsDockWidget(NULL),
+ m_simulatorId(firmwareId),
+ m_exitStatusCode(0),
m_radioProfileId(g.sessionId()),
m_radioSizeConstraint(Qt::Horizontal | Qt::Vertical),
m_firstShow(true),
m_showRadioDocked(true),
m_showMenubar(true)
{
+ if (m_simulatorId.isEmpty()) {
+ m_simulatorId = SimulatorLoader::findSimulatorByFirmwareName(getCurrentFirmware()->getId());
+ }
+ m_simulator = SimulatorLoader::loadSimulator(m_simulatorId);
+ if (!m_simulator) {
+ m_exitStatusMsg = tr("ERROR: Failed to create simulator interface, possibly missing or bad library.");
+ m_exitStatusCode = -1;
+ return;
+ }
+
+ m_simulator->moveToThread(&simuThread);
+ simuThread.start();
+
ui->setupUi(this);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
@@ -90,73 +106,85 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * s
ui->menuView->insertSeparator(ui->actionToggleMenuBar);
ui->menuView->insertAction(ui->actionToggleMenuBar, ui->toolBar->toggleViewAction());
- // Hide some actions based on board capabilities.
- Firmware * firmware = getCurrentFirmware();
- if(!firmware->getCapability(Capability(LuaInputsPerScript)))
+ // Hide some actions based on simulator capabilities.
+ if(!m_simulator->getCapability(SimulatorInterface::CAP_LUA))
ui->actionReloadLua->setDisabled(true);
- if (!firmware->getCapability(Capability(SportTelemetry)))
+ if(!m_simulator->getCapability(SimulatorInterface::CAP_TELEM_FRSKY_SPORT))
m_telemetryDockWidget->toggleViewAction()->setDisabled(true);
#ifndef JOYSTICKS
ui->actionJoystickSettings->setDisabled(true);
#endif
- // Add radio-specific help text from simulator widget
- foreach (keymapHelp_t item, *m_simulatorWidget->getKeymapHelp())
- m_keymapHelp.append(item);
-
restoreUiState();
setStyleSheet(SimulatorStyle::styleSheet());
connect(ui->actionShowKeymap, &QAction::triggered, this, &SimulatorMainWindow::showHelp);
connect(ui->actionJoystickSettings, &QAction::triggered, this, &SimulatorMainWindow::openJoystickDialog);
- connect(ui->actionReloadLua, &QAction::triggered, this, &SimulatorMainWindow::luaReload);
connect(ui->actionToggleMenuBar, &QAction::toggled, this, &SimulatorMainWindow::showMenuBar);
connect(ui->actionFixedRadioWidth, &QAction::toggled, this, &SimulatorMainWindow::showRadioFixedWidth);
connect(ui->actionFixedRadioHeight, &QAction::toggled, this, &SimulatorMainWindow::showRadioFixedHeight);
connect(ui->actionDockRadio, &QAction::toggled, this, &SimulatorMainWindow::showRadioDocked);
+ connect(ui->actionReloadRadioData, &QAction::triggered, this, &SimulatorMainWindow::simulatorRestart);
+
+ connect(ui->actionReloadLua, &QAction::triggered, m_simulator, &SimulatorInterface::setLuaStateReloadPermanentScripts);
+
+ if (m_outputsWidget) {
+ connect(this, &SimulatorMainWindow::simulatorStart, m_outputsWidget, &RadioOutputsWidget::start);
+ connect(this, &SimulatorMainWindow::simulatorRestart, m_outputsWidget, &RadioOutputsWidget::restart);
+ }
+
if (m_simulatorWidget) {
+ connect(this, &SimulatorMainWindow::simulatorStart, m_simulatorWidget, &SimulatorWidget::start);
+ connect(this, &SimulatorMainWindow::simulatorRestart, m_simulatorWidget, &SimulatorWidget::restart);
connect(ui->actionScreenshot, &QAction::triggered, m_simulatorWidget, &SimulatorWidget::captureScreenshot);
- connect(ui->actionReloadRadioData, &QAction::triggered, m_simulatorWidget, &SimulatorWidget::restart);
connect(m_simulatorWidget, &SimulatorWidget::windowTitleChanged, this, &SimulatorMainWindow::setWindowTitle);
}
- if (m_outputsWidget)
- connect(ui->actionReloadRadioData, &QAction::triggered, m_outputsWidget, &RadioOutputsWidget::restart);
+
+
}
SimulatorMainWindow::~SimulatorMainWindow()
{
- delete ui;
-}
-
-void SimulatorMainWindow::closeEvent(QCloseEvent *)
-{
- saveUiState();
-
if (m_telemetryDockWidget)
delete m_telemetryDockWidget;
if (m_trainerDockWidget)
delete m_trainerDockWidget;
if (m_outputsDockWidget)
delete m_outputsDockWidget;
- if (m_consoleDockWidget)
- delete m_consoleDockWidget;
if (m_simulatorDockWidget)
delete m_simulatorDockWidget;
else if (m_simulatorWidget)
delete m_simulatorWidget;
+ if (m_consoleDockWidget)
+ delete m_consoleDockWidget;
+
+ delete ui;
+
+ if (m_simulator) {
+ simuThread.quit();
+ simuThread.wait();
+ delete m_simulator;
+ }
+ SimulatorLoader::unloadSimulator(m_simulatorId);
+}
+
+void SimulatorMainWindow::closeEvent(QCloseEvent *)
+{
+ saveUiState();
}
void SimulatorMainWindow::show()
{
QMainWindow::show();
-#ifdef Q_OS_LINUX
- // for whatever reason, w/out this workaround any floating docks may appear and get "stuck" behind other windows, eg. Terminal or Companion.
if (m_firstShow) {
- restoreUiState();
m_firstShow = false;
+ #ifdef Q_OS_LINUX
+ // for whatever reason, w/out this workaround any floating docks may appear and get "stuck" behind other windows, eg. Terminal or Companion.
+ restoreUiState();
+ #endif
+ start();
}
-#endif
}
void SimulatorMainWindow::changeEvent(QEvent *e)
@@ -171,7 +199,8 @@ void SimulatorMainWindow::changeEvent(QEvent *e)
}
}
-QMenu * SimulatorMainWindow::createPopupMenu(){
+QMenu * SimulatorMainWindow::createPopupMenu()
+{
QMenu * menu = QMainWindow::createPopupMenu();
menu->clear();
menu->addActions(ui->menuView->actions());
@@ -212,6 +241,13 @@ void SimulatorMainWindow::restoreUiState()
restoreState(windowState, m_savedUiStateVersion);
}
+int SimulatorMainWindow::getExitStatus(QString * msg)
+{
+ if (msg)
+ *msg = m_exitStatusMsg;
+ return m_exitStatusCode;
+}
+
bool SimulatorMainWindow::setRadioData(RadioData * radioData)
{
return m_simulatorWidget->setRadioData(radioData);
@@ -229,10 +265,7 @@ bool SimulatorMainWindow::setOptions(SimulatorOptions & options, bool withSave)
void SimulatorMainWindow::start()
{
- if (m_simulatorWidget)
- m_simulatorWidget->start();
- if (m_outputsWidget)
- m_outputsWidget->start();
+ emit simulatorStart();
}
void SimulatorMainWindow::createDockWidgets()
@@ -422,13 +455,6 @@ void SimulatorMainWindow::toggleRadioDocked(bool dock)
}
-void SimulatorMainWindow::luaReload(bool)
-{
- // force a reload of the lua environment
- if (m_simulator)
- m_simulator->setLuaStateReloadPermanentScripts();
-}
-
void SimulatorMainWindow::openJoystickDialog(bool)
{
#ifdef JOYSTICKS
@@ -441,19 +467,34 @@ void SimulatorMainWindow::openJoystickDialog(bool)
void SimulatorMainWindow::showHelp(bool show)
{
- QString helpText = tr("Simulator Controls:");
+ QString helpText = ""
+ "";
+ helpText += tr("Simulator Controls:");
helpText += "";
- helpText += tr("| Key/Mouse | Action | ");
- QString keyTemplate = "%1 | %2 | ";
- foreach (keymapHelp_t pair, m_keymapHelp)
+ helpText += tr("| Key/Mouse | Action | ", "note: must match html layout of each table row (keyTemplate).");
+
+ QString keyTemplate = tr("| %1 | %2 | ", "note: must match html layout of help text table header.");
+ keymapHelp_t pair;
+ // Add our own help text (if any)
+ foreach (pair, m_keymapHelp)
helpText += keyTemplate.arg(pair.first, pair.second);
+ // Add any radio-specific help text from simulator widget
+ foreach (pair, m_simulatorWidget->getKeymapHelp())
+ helpText += keyTemplate.arg(pair.first, pair.second);
+
helpText += " ";
QMessageBox * msgBox = new QMessageBox(this);
+ msgBox->setObjectName("SimulatorHelpText");
msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setWindowFlags(msgBox->windowFlags() | Qt::WindowStaysOnTopHint);
msgBox->setStandardButtons( QMessageBox::Ok );
msgBox->setWindowTitle(tr("Simulator Help"));
+ msgBox->setTextFormat(Qt::RichText);
msgBox->setText(helpText);
msgBox->setModal(false);
msgBox->show();
diff --git a/companion/src/simulation/simulatormainwindow.h b/companion/src/simulation/simulatormainwindow.h
index a63982bd6..eb134a63f 100644
--- a/companion/src/simulation/simulatormainwindow.h
+++ b/companion/src/simulation/simulatormainwindow.h
@@ -25,7 +25,7 @@
#include
#include
-#include
+#include
class DebugOutput;
class RadioData;
@@ -48,13 +48,14 @@ class SimulatorMainWindow : public QMainWindow
Q_OBJECT
public:
- explicit SimulatorMainWindow(QWidget * parent, SimulatorInterface * simulator, quint8 flags=0, Qt::WindowFlags wflags = Qt::WindowFlags());
+ explicit SimulatorMainWindow(QWidget * parent, const QString & firmwareId = "", quint8 flags=0, Qt::WindowFlags wflags = Qt::WindowFlags());
~SimulatorMainWindow();
+ int getExitStatus(QString * msg = Q_NULLPTR);
bool setRadioData(RadioData * radioData);
bool useTempDataPath(bool deleteOnClose = true);
bool setOptions(SimulatorOptions & options, bool withSave = true);
- QMenu * createPopupMenu();
+ virtual QMenu * createPopupMenu();
public slots:
virtual void show();
@@ -65,6 +66,10 @@ class SimulatorMainWindow : public QMainWindow
void showRadioFixedHeight(bool fixed);
void showRadioDocked(bool dock);
+ signals:
+ void simulatorStart();
+ void simulatorRestart();
+
protected slots:
virtual void closeEvent(QCloseEvent *);
virtual void changeEvent(QEvent *e);
@@ -73,7 +78,6 @@ class SimulatorMainWindow : public QMainWindow
void toggleMenuBar(bool show);
void setRadioSizePolicy(int fixType);
void toggleRadioDocked(bool dock);
- void luaReload(bool);
void openJoystickDialog(bool);
void showHelp(bool show);
@@ -94,7 +98,11 @@ class SimulatorMainWindow : public QMainWindow
QDockWidget * m_trainerDockWidget;
QDockWidget * m_outputsDockWidget;
+ QThread simuThread;
QVector m_keymapHelp;
+ QString m_simulatorId;
+ QString m_exitStatusMsg;
+ int m_exitStatusCode;
int m_radioProfileId;
int m_radioSizeConstraint;
bool m_firstShow;
diff --git a/companion/src/simulation/simulatorstartupdialog.cpp b/companion/src/simulation/simulatorstartupdialog.cpp
index b09d254e4..c87da3399 100644
--- a/companion/src/simulation/simulatorstartupdialog.cpp
+++ b/companion/src/simulation/simulatorstartupdialog.cpp
@@ -23,13 +23,13 @@
#include "appdata.h"
#include "constants.h"
-#include "eeprominterface.h"
-#include "helpers.h"
+#include "simulatorinterface.h"
#include
+using namespace Simulator;
+
extern AppData g;
-extern QMap registered_simulators;
SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int * profId, QWidget *parent) :
QDialog(parent),
@@ -45,13 +45,13 @@ SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int *
ui->radioProfile->addItem(pi.value(), pi.key());
}
- ui->radioType->addItems(registered_simulators.keys());
+ ui->radioType->addItems(SimulatorLoader::getAvailableSimulators());
ui->optGrp_dataSource->setId(ui->optFile, SimulatorOptions::START_WITH_FILE);
ui->optGrp_dataSource->setId(ui->optFolder, SimulatorOptions::START_WITH_FOLDER);
ui->optGrp_dataSource->setId(ui->optSdPath, SimulatorOptions::START_WITH_SDPATH);
- CompanionIcon icon("open.png");
+ SimulatorIcon icon("folder_open");
ui->btnSelectDataFile->setIcon(icon);
ui->btnSelectDataFolder->setIcon(icon);
ui->btnSelectSdPath->setIcon(icon);
@@ -151,7 +151,7 @@ void SimulatorStartupDialog::updateContainerTypes(void)
void SimulatorStartupDialog::loadRadioProfile(int id)
{
- QString tmpstr;
+ QString tmpstr, tmpstr2;
int i;
if (id < 0 || !g.getActiveProfiles().contains(id))
@@ -166,8 +166,8 @@ void SimulatorStartupDialog::loadRadioProfile(int id)
tmpstr = m_options->firmwareId;
if (tmpstr.isEmpty() && !g.profile[id].fwType().isEmpty())
tmpstr = g.profile[id].fwType();
- else if (getSimulatorFactory(tmpstr))
- tmpstr = getSimulatorFactory(tmpstr)->name();
+ else if (!(tmpstr2 = SimulatorLoader::findSimulatorByFirmwareName(m_options->firmwareId)).isEmpty())
+ tmpstr = tmpstr2;
i = ui->radioType->findText(findRadioId(tmpstr), Qt::MatchContains);
if (i > -1)
ui->radioType->setCurrentIndex(i);
@@ -227,7 +227,7 @@ void SimulatorStartupDialog::onRadioTypeChanged(int index)
void SimulatorStartupDialog::onDataFileSelect(bool)
{
- QString filter = tr(EEPROM_FILES_FILTER) + tr("All files (*.*)");
+ QString filter = EEPROM_FILES_FILTER % tr("All files (*.*)");
QString file = QFileDialog::getSaveFileName(this, QObject::tr("Select a data file"), ui->dataFile->text(),
filter, NULL, QFileDialog::DontConfirmOverwrite);
if (!file.isEmpty()) {
diff --git a/companion/src/simulation/simulatorstartupdialog.h b/companion/src/simulation/simulatorstartupdialog.h
index dc5abcbea..ba5dc2f6a 100644
--- a/companion/src/simulation/simulatorstartupdialog.h
+++ b/companion/src/simulation/simulatorstartupdialog.h
@@ -28,8 +28,6 @@ namespace Ui {
class SimulatorStartupDialog;
}
-using namespace Simulator;
-
class SimulatorStartupDialog : public QDialog
{
Q_OBJECT
diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp
index 55ab9adab..00a481028 100644
--- a/companion/src/simulation/simulatorwidget.cpp
+++ b/companion/src/simulation/simulatorwidget.cpp
@@ -24,12 +24,13 @@
#include "appdata.h"
#include "appdebugmessagehandler.h"
#include "radiofaderwidget.h"
+#include "radiokeywidget.h"
#include "radioknobwidget.h"
#include "radioswitchwidget.h"
+#include "radiotrimwidget.h"
#include "radiouiaction.h"
#include "sdcard.h"
#include "simulateduiwidget.h"
-#include "simulatorinterface.h"
#include "storage.h"
#include "virtualjoystickwidget.h"
#ifdef JOYSTICKS
@@ -38,38 +39,30 @@
#endif
#include
+#include
#include
-SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator, quint8 flags):
+using namespace Simulator;
+
+SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulator, quint8 flags):
QWidget(parent),
ui(new Ui::SimulatorWidget),
simulator(simulator),
firmware(getCurrentFirmware()),
radioSettings(GeneralSettings()),
- timer(new QTimer(this)),
radioUiWidget(NULL),
vJoyLeft(NULL),
vJoyRight(NULL),
m_board(getCurrentBoard()),
flags(flags),
- lastPhase(-1),
- buttonPressed(0),
- trimPressed(TRIM_NONE),
startupFromFile(false),
deleteTempRadioData(false),
- saveTempRadioData(false),
- middleButtonPressed(false),
- firstShow(true)
-{
-
+ saveTempRadioData(false)
#ifdef JOYSTICKS
- joystick = NULL;
+ , joystick(NULL)
#endif
- // defaults
- setRadioProfileId(g.sessionId());
- setSdPath(g.profile[radioProfileId].sdPath());
-
+{
ui->setupUi(this);
windowName = tr("Radio Simulator (%1)").arg(firmware->getName());
@@ -95,14 +88,16 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator
break;
}
- foreach (keymapHelp_t item, *radioUiWidget->getKeymapHelp())
+ foreach (keymapHelp_t item, radioUiWidget->getKeymapHelp())
keymapHelp.append(item);
ui->radioUiWidget->layout()->removeItem(ui->radioUiTempSpacer);
+ delete ui->radioUiTempSpacer;
ui->radioUiWidget->layout()->addWidget(radioUiWidget);
radioUiWidget->setFocusPolicy(Qt::WheelFocus);
radioUiWidget->setFocus();
+ connect(radioUiWidget, &SimulatedUIWidget::controlValueChange, this, &SimulatorWidget::onRadioWidgetValueChange);
connect(radioUiWidget, &SimulatedUIWidget::customStyleRequest, this, &SimulatorWidget::setUiAreaStyle);
vJoyLeft = new VirtualJoystickWidget(this, 'L');
@@ -111,25 +106,41 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator
vJoyRight = new VirtualJoystickWidget(this, 'R');
ui->rightStickLayout->addWidget(vJoyRight);
- connect(vJoyLeft, SIGNAL(trimButtonPressed(int)), this, SLOT(onTrimPressed(int)));
- connect(vJoyLeft, SIGNAL(trimButtonReleased()), this, SLOT(onTrimReleased()));
- connect(vJoyLeft, SIGNAL(trimSliderMoved(int,int)), this, SLOT(onTrimSliderMoved(int,int)));
+ connect(vJoyLeft, &VirtualJoystickWidget::valueChange, this, &SimulatorWidget::onRadioWidgetValueChange);
+ connect(vJoyRight, &VirtualJoystickWidget::valueChange, this, &SimulatorWidget::onRadioWidgetValueChange);
+ connect(this, &SimulatorWidget::stickModeChange, vJoyLeft, &VirtualJoystickWidget::loadDefaultsForMode);
+ connect(this, &SimulatorWidget::stickModeChange, vJoyRight, &VirtualJoystickWidget::loadDefaultsForMode);
+ connect(simulator, &SimulatorInterface::trimValueChange, vJoyLeft, &VirtualJoystickWidget::setTrimValue);
+ connect(simulator, &SimulatorInterface::trimValueChange, vJoyRight, &VirtualJoystickWidget::setTrimValue);
+ connect(simulator, &SimulatorInterface::trimRangeChange, vJoyLeft, &VirtualJoystickWidget::setTrimRange);
+ connect(simulator, &SimulatorInterface::trimRangeChange, vJoyRight, &VirtualJoystickWidget::setTrimRange);
- connect(vJoyRight, SIGNAL(trimButtonPressed(int)), this, SLOT(onTrimPressed(int)));
- connect(vJoyRight, SIGNAL(trimButtonReleased()), this, SLOT(onTrimReleased()));
- connect(vJoyRight, SIGNAL(trimSliderMoved(int,int)), this, SLOT(onTrimSliderMoved(int,int)));
+ connect(this, &SimulatorWidget::simulatorInit, simulator, &SimulatorInterface::init);
+ connect(this, &SimulatorWidget::simulatorStart, simulator, &SimulatorInterface::start);
+ connect(this, &SimulatorWidget::simulatorStop, simulator, &SimulatorInterface::stop);
+ connect(this, &SimulatorWidget::inputValueChange, simulator, &SimulatorInterface::setInputValue);
+ connect(this, &SimulatorWidget::simulatorSdPathChange, simulator, &SimulatorInterface::setSdPath);
+ connect(this, &SimulatorWidget::simulatorVolumeGainChange, simulator, &SimulatorInterface::setVolumeGain);
- timer->setInterval(10);
- connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent()));
- connect(timer, SIGNAL(timeout()), radioUiWidget, SLOT(updateUi()));
+ connect(simulator, &SimulatorInterface::started, this, &SimulatorWidget::onSimulatorStarted);
+ connect(simulator, &SimulatorInterface::heartbeat, this, &SimulatorWidget::onSimulatorHeartbeat);
+ connect(simulator, &SimulatorInterface::runtimeError, this, &SimulatorWidget::onSimulatorError);
+ connect(simulator, &SimulatorInterface::phaseChanged, this, &SimulatorWidget::onPhaseChanged);
+
+ m_timer.setInterval(SIMULATOR_INTERFACE_HEARTBEAT_PERIOD * 6);
+ connect(&m_timer, &QTimer::timeout, this, &SimulatorWidget::onTimerEvent);
+
+ setupJoysticks();
+
+ // defaults
+ setRadioProfileId(g.sessionId());
+ setSdPath(g.profile[radioProfileId].sdPath());
}
SimulatorWidget::~SimulatorWidget()
{
shutdown();
- if (timer)
- timer->deleteLater();
if (radioUiWidget)
delete radioUiWidget;
if (vJoyLeft)
@@ -140,10 +151,7 @@ SimulatorWidget::~SimulatorWidget()
if (joystick)
delete joystick;
#endif
-
- firmware = NULL; // Not sure we should delete this but at least release our pointer.
- // NOTE : should be deleted (or not) in the parent process which gave it to us in the first place.
-
+ firmware = NULL;
delete ui;
}
@@ -166,8 +174,7 @@ void SimulatorWidget::setPaths(const QString & sdPath, const QString & dataPath)
{
sdCardPath = sdPath;
radioDataPath = dataPath;
- if (simulator)
- simulator->setSdPath(sdPath, dataPath);
+ emit simulatorSdPathChange(sdPath, dataPath);
}
void SimulatorWidget::setRadioSettings(const GeneralSettings settings)
@@ -223,6 +230,7 @@ bool SimulatorWidget::setStartupData(const QByteArray & dataSource, bool fromFil
else {
// the binary file will be read/written directly by the fw interface, save the file name for simulator->start()
startupData = dataSource;
+ ret = 1;
}
}
}
@@ -261,7 +269,7 @@ bool SimulatorWidget::setRadioData(RadioData * radioData)
if (ret) {
if (radioDataPath.isEmpty()) {
- startupData.fill(0, getEEpromSize(m_board));
+ startupData.fill(0, Boards::getEEpromSize(m_board));
if (firmware->getEEpromInterface()->save((uint8_t *)startupData.data(), *radioData, 0, firmware->getCapability(SimulatorVariant)) <= 0) {
ret = false;
}
@@ -407,8 +415,7 @@ void SimulatorWidget::deleteTempData()
void SimulatorWidget::saveState()
{
SimulatorOptions opts = g.profile[radioProfileId].simulatorOptions();
- //opts.windowGeometry = saveGeometry();
- opts.controlsState = saveRadioWidgetsState();
+ saveRadioWidgetsState(opts.controlsState);
g.profile[radioProfileId].simulatorOptions(opts);
}
@@ -429,32 +436,56 @@ void SimulatorWidget::captureScreenshot(bool)
void SimulatorWidget::start()
{
+ emit simulatorInit(); // init simulator default I/O values
+
setupRadioWidgets();
- setupJoysticks();
restoreRadioWidgetsState();
- if (startupData.isEmpty())
- simulator->start((const char *)0);
- else if (startupFromFile)
- simulator->start(startupData.constData());
- else
- simulator->start(startupData, (flags & SIMULATOR_FLAGS_NOTX) ? false : true);
-
- setTrims();
- getValues();
- setupTimer();
+ bool tests = !(flags & SIMULATOR_FLAGS_NOTX);
+ if (!startupData.isEmpty()) {
+ if (startupFromFile) {
+ emit simulatorStart(startupData.constData(), tests);
+ }
+ else {
+ simulator->setRadioData(startupData);
+ emit simulatorStart((const char *)0, tests);
+ }
+ }
+ else {
+ emit simulatorStart((const char *)0, tests);
+ }
}
void SimulatorWidget::stop()
{
- if (timer)
- timer->stop();
- if (simulator) {
- simulator->stop();
- if (saveTempRadioData) {
- startupData.fill(0, getEEpromSize(m_board));
- simulator->readEepromData(startupData);
+ emit simulatorStop();
+ QElapsedTimer tmout;
+ tmout.start();
+ // block until simulator stops or times out
+ while (simulator->isRunning()) {
+ if (tmout.hasExpired(2000)) {
+ onSimulatorError("Timeout while trying to stop simulation!");
+ break;
}
+ QApplication::processEvents();
+ }
+ onSimulatorStopped();
+}
+
+void SimulatorWidget::onSimulatorStarted()
+{
+ m_heartbeatTimer.start();
+ m_timer.start();
+}
+
+void SimulatorWidget::onSimulatorStopped()
+{
+ m_timer.stop();
+ m_heartbeatTimer.invalidate();
+
+ if (simulator && !simulator->isRunning() && saveTempRadioData) {
+ startupData.fill(0, getEEpromSize(m_board));
+ simulator->readRadioData(startupData);
}
}
@@ -483,124 +514,120 @@ void SimulatorWidget::shutdown()
void SimulatorWidget::setRadioProfileId(int value)
{
radioProfileId = value;
- if (simulator)
- simulator->setVolumeGain(g.profile[radioProfileId].volumeGain());
+ emit simulatorVolumeGainChange(g.profile[radioProfileId].volumeGain());
}
void SimulatorWidget::setupRadioWidgets()
{
- int i, midpos, aIdx;
QString wname;
- Board::Type board = firmware->getBoard();
+ int i, midpos;
+ const int ttlSticks = Boards::getCapability(m_board, Board::Sticks);
+ const int ttlSwitches = Boards::getCapability(m_board, Board::Switches);
+ const int ttlKnobs = Boards::getCapability(m_board, Board::Pots);
+ const int ttlFaders = Boards::getCapability(m_board, Board::Sliders);
+ const int extraTrims = Boards::getCapability(m_board, Board::NumTrims) - ttlSticks;
// First clear out any existing widgets.
- if (switches.size()) {
- foreach (RadioWidget * w, switches) {
- ui->radioWidgetsHTLayout->removeWidget(w);
- w->deleteLater();
+ foreach (RadioWidget * rw, m_radioWidgets) {
+ switch(rw->getType()) {
+ case RadioWidget::RADIO_WIDGET_SWITCH :
+ case RadioWidget::RADIO_WIDGET_KNOB :
+ ui->radioWidgetsHTLayout->removeWidget(rw);
+ break;
+ case RadioWidget::RADIO_WIDGET_FADER :
+ case RadioWidget::RADIO_WIDGET_TRIM :
+ ui->VCGridLayout->removeWidget(rw);
+ break;
+ default :
+ break;
}
- switches.clear();
- }
- if (analogs.size()) {
- foreach (RadioWidget * w, analogs) {
- if (w->getType() == RadioWidget::RADIO_WIDGET_KNOB)
- ui->radioWidgetsHTLayout->removeWidget(w);
- else
- ui->VCGridLayout->removeWidget(w);
- w->deleteLater();
- }
- analogs.clear();
+ disconnect(rw, 0, this, 0);
+ disconnect(this, 0, rw, 0);
+ rw->deleteLater();
}
+ m_radioWidgets.clear();
// Now set up new widgets.
// switches
- Board::SwitchInfo switchInfo;
Board::SwitchType swcfg;
- for (i = 0; i < getBoardCapability(board, Board::Switches) && i < CPN_MAX_SWITCHES; ++i) {
+ for (i = 0; i < ttlSwitches; ++i) {
if (radioSettings.switchConfig[i] == Board::SWITCH_NOT_AVAILABLE)
continue;
swcfg = Board::SwitchType(radioSettings.switchConfig[i]);
-
- if ((wname = QString(radioSettings.switchName[i])).isEmpty()) {
- switchInfo = getSwitchInfo(board, i);
- wname = QString(switchInfo.name);
- }
+ wname = RawSource(RawSourceType::SOURCE_TYPE_SWITCH, i).toString(NULL, &radioSettings);
RadioSwitchWidget * sw = new RadioSwitchWidget(swcfg, wname, -1, ui->radioWidgetsHT);
sw->setIndex(i);
ui->radioWidgetsHTLayout->addWidget(sw);
- switches.append(sw);
+
+ m_radioWidgets.append(sw);
}
- midpos = (int)floorf(switches.size() / 2.0f);
- aIdx = 0;
+ midpos = (int)floorf(m_radioWidgets.size() / 2.0f);
// pots in middle of switches
- for (i = 0; i < getBoardCapability(board, Board::Pots) && i < CPN_MAX_POTS; ++i) {
+ for (i = 0; i < ttlKnobs; ++i) {
if (!radioSettings.isPotAvailable(i))
continue;
- if ((wname = QString(radioSettings.potName[i])).isEmpty())
- wname = firmware->getAnalogInputName(4 + aIdx + i);
-
+ wname = RawSource(RawSourceType::SOURCE_TYPE_STICK, ttlSticks + i).toString(NULL, &radioSettings);
RadioKnobWidget * pot = new RadioKnobWidget(Board::PotType(radioSettings.potConfig[i]), wname, 0, ui->radioWidgetsHT);
- pot->setIndex(aIdx + i);
- // FIXME : total hack here -- this needs to follow the exception in radio/src/mixer.cpp:evalInputs()
- if (i == 0 && IS_TARANIS(board) && !IS_TARANIS_X7(board))
- pot->setInvertValue(true);
+ pot->setIndex(i);
ui->radioWidgetsHTLayout->insertWidget(midpos++, pot);
- analogs.append(pot);
+
+ m_radioWidgets.append(pot);
}
- aIdx += i;
-
// faders between sticks
- int r = 0, c = 0;
- for (i = 0; i < getBoardCapability(board, Board::Sliders) && i + aIdx < CPN_MAX_POTS; ++i) {
+ int c = extraTrims / 2; // leave space for any extra trims
+ for (i = 0; i < ttlFaders; ++i) {
if (!radioSettings.isSliderAvailable(i))
continue;
- if ((wname = QString(radioSettings.sliderName[i])).isEmpty())
- wname = firmware->getAnalogInputName(4 + aIdx + i);
-
+ wname = RawSource(RawSourceType::SOURCE_TYPE_STICK, ttlSticks + ttlKnobs + i).toString(NULL, &radioSettings);
RadioFaderWidget * sl = new RadioFaderWidget(wname, 0, ui->radioWidgetsVC);
- sl->setIndex(aIdx + i);
- // FIXME : total hack here -- this needs to follow the exception in radio/src/mixer.cpp:evalInputs()
- if (i == 0 && IS_TARANIS(board) && !IS_TARANIS_X7(board))
- sl->setInvertValue(true);
- /* 2-row option
- if (!(i % 2)) {
- ++r;
- c = 0;
- } */
- ui->VCGridLayout->addWidget(sl, r, c++, 1, 1);
- analogs.append(sl);
+ sl->setIndex(i);
+ ui->VCGridLayout->addWidget(sl, 0, c++, 1, 1);
+
+ m_radioWidgets.append(sl);
}
+
+ // extra trims around faders
+ int tridx = Board::TRIM_AXIS_COUNT;
+ int trswidx = Board::TRIM_SW_COUNT;
+ for (i = extraTrims; i > 0; --i) {
+ trswidx -= 2;
+ --tridx;
+ wname = RawSource(RawSourceType::SOURCE_TYPE_TRIM, tridx).toString(NULL, &radioSettings);
+ wname = wname.left(1) % wname.right(1);
+ RadioTrimWidget * tw = new RadioTrimWidget(Qt::Vertical, ui->radioWidgetsVC);
+ tw->setIndices(tridx, trswidx, trswidx + 1);
+ tw->setLabelText(wname);
+ if (i <= extraTrims / 2)
+ c = 0;
+ ui->VCGridLayout->addWidget(tw, 0, c++, 1, 1);
+
+ connect(simulator, &SimulatorInterface::trimValueChange, tw, &RadioTrimWidget::setTrimValue);
+ connect(simulator, &SimulatorInterface::trimRangeChange, tw, &RadioTrimWidget::setTrimRangeQual);
+ m_radioWidgets.append(tw);
+ }
+
+ // connect all the widgets
+ foreach (RadioWidget * rw, m_radioWidgets) {
+ connect(rw, &RadioWidget::valueChange, this, &SimulatorWidget::onRadioWidgetValueChange);
+ connect(this, &SimulatorWidget::widgetValueChange, rw, &RadioWidget::setValueQual);
+ connect(this, &SimulatorWidget::widgetStateChange, rw, &RadioWidget::setStateData);
+ }
+
}
void SimulatorWidget::setupJoysticks()
{
#ifdef JOYSTICKS
- static bool joysticksEnabled = false;
- if (g.jsSupport() && g.jsCtrl() > -1) {
- int count=0, axe;
- for (int j=0; j < MAX_JOYSTICKS; j++){
- axe = g.joystick[j].stick_axe();
- if (axe >= 0 && axe < MAX_JOYSTICKS) {
- jsmap[axe] = j + 1;
- jscal[axe][0] = g.joystick[j].stick_min();
- jscal[axe][1] = g.joystick[j].stick_med();
- jscal[axe][2] = g.joystick[j].stick_max();
- jscal[axe][3] = g.joystick[j].stick_inv();
- count++;
- }
- }
- if (count<3) {
- QMessageBox::critical(this, tr("Warning"), tr("Joystick enabled but not configured correctly"));
- return;
- }
+ bool joysticksEnabled = false;
+ if (g.jsSupport() && g.jsCtrl() > -1) {
if (!joystick)
joystick = new Joystick(this);
else
@@ -612,188 +639,69 @@ void SimulatorWidget::setupJoysticks()
joystick->sensitivities[j] = 0;
joystick->deadzones[j] = 0;
}
- //mode 1,3 -> THR on right
- vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
- vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_X, true);
- vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
- vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_X, true);
- connect(joystick, SIGNAL(axisValueChanged(int, int)), this, SLOT(onjoystickAxisValueChanged(int, int)));
+ connect(joystick, &Joystick::axisValueChanged, this, &SimulatorWidget::onjoystickAxisValueChanged);
+ if (vJoyLeft)
+ connect(this, &SimulatorWidget::stickValueChange, vJoyLeft, &VirtualJoystickWidget::setStickAxisValue);
+ if (vJoyRight)
+ connect(this, &SimulatorWidget::stickValueChange, vJoyRight, &VirtualJoystickWidget::setStickAxisValue);
joysticksEnabled = true;
}
else {
QMessageBox::critical(this, tr("Warning"), tr("Cannot open joystick, joystick disabled"));
}
}
- else if (joysticksEnabled && joystick) {
+ else if (joystick) {
+ joystick->close();
disconnect(joystick, 0, this, 0);
- vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_Y, false);
- vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_X, false);
- vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_Y, false);
- vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_X, false);
+ if (vJoyLeft)
+ disconnect(this, 0, vJoyLeft, 0);
+ if (vJoyRight)
+ disconnect(this, 0, vJoyRight, 0);
+ joystick->deleteLater();
+ joystick = NULL;
}
+ if (vJoyRight)
+ vJoyRight->setStickConstraint((VirtualJoystickWidget::HOLD_X | VirtualJoystickWidget::HOLD_Y), joysticksEnabled);
+ if (vJoyLeft)
+ vJoyLeft->setStickConstraint((VirtualJoystickWidget::HOLD_X | VirtualJoystickWidget::HOLD_Y), joysticksEnabled);
#endif
}
-void SimulatorWidget::setupTimer()
-{
- if (!timer)
- return;
-
- if (timer->isActive())
- timer->stop();
-
- timer->start();
-}
-
void SimulatorWidget::restoreRadioWidgetsState()
{
+ // All RadioWidgets
RadioWidget::RadioWidgetState state;
- QMap switchesMap;
- QMap analogsMap;
QList states = g.profile[radioProfileId].simulatorOptions().controlsState;
-
foreach (QByteArray ba, states) {
QDataStream stream(ba);
stream >> state;
- if (state.type == RadioWidget::RADIO_WIDGET_SWITCH)
- switchesMap.insert(state.index, ba);
- else
- analogsMap.insert(state.index, ba);
- }
-
- for (int i = 0; i < analogs.size(); ++i) {
- if (analogsMap.contains(analogs[i]->getIndex()))
- analogs[i]->setStateData(analogsMap.value(analogs[i]->getIndex()));
- }
-
- for (int i = 0; i < switches.size(); ++i) {
- if (switchesMap.contains(switches[i]->getIndex()))
- switches[i]->setStateData(switchesMap.value(switches[i]->getIndex()));
+ emit widgetStateChange(state);
}
// Set throttle stick down and locked, side depends on mode
- if (radioSettings.stickMode & 1) {
- vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
- vJoyLeft->setStickY(1);
- }
- else {
- vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
- vJoyRight->setStickY(1);
- }
+ emit stickModeChange(radioSettings.stickMode);
+
+ // TODO : custom voltages
+ qint16 volts = radioSettings.vBatWarn + 2;
+ if (firmware->getCapability(Capability::HasBatMeterRange))
+ volts = (radioSettings.vBatMin + 90) + ((radioSettings.vBatMax + 30) - radioSettings.vBatMin) / 2;
+ emit inputValueChange(SimulatorInterface::INPUT_SRC_TXVIN, 0, volts);
}
-QList SimulatorWidget::saveRadioWidgetsState()
+void SimulatorWidget::saveRadioWidgetsState(QList & state)
{
- QList states;
-
- for (int i = 0; i < analogs.size(); ++i)
- states.append(analogs[i]->getStateData());
-
- for (int i = 0; i < switches.size(); ++i)
- states.append(switches[i]->getStateData());
-
- return states;
-}
-
-/*
- * Input/Output handlers for SimulatorInterface
- */
-
-// Read various values from firmware simulator and populate values in this UI
-void SimulatorWidget::setValues()
-{
- int currentPhase = simulator->getPhase();
-
- // display current flight mode in window title
- if (currentPhase != lastPhase) {
- lastPhase = currentPhase;
- QString phase_name = QString(simulator->getPhaseName(currentPhase));
- if (phase_name.isEmpty())
- phase_name = QString::number(currentPhase);
- setWindowTitle(windowName + QString(" - Flight Mode %1").arg(phase_name));
+ if (m_radioWidgets.size()) {
+ state.clear();
+ foreach (RadioWidget * rw, m_radioWidgets)
+ state.append(rw->getStateData());
}
}
-// "get" values from this UI and send them to the firmware simulator.
-void SimulatorWidget::getValues()
-{
- static const int numTrims = getBoardCapability(m_board, Board::NumTrimSwitches);
- int i;
-
- TxInputs inp;
- memset(&inp, 0, sizeof(TxInputs));
-
- inp.sticks[0] = int(1024 * vJoyLeft->getStickX()); // LEFT HORZ
- inp.sticks[1] = int(-1024 * vJoyLeft->getStickY()); // LEFT VERT
- inp.sticks[2] = int(-1024 * vJoyRight->getStickY()); // RGHT VERT
- inp.sticks[3] = int(1024 * vJoyRight->getStickX()); // RGHT HORZ
-
- for (i = 0; i < analogs.size() && i < CPN_MAX_POTS; ++i)
- inp.pots[analogs[i]->getIndex()] = analogs[i]->getValue();
-
- for (i = 0; i < switches.size() && i < CPN_MAX_SWITCHES; ++i)
- inp.switches[switches[i]->getIndex()] = switches[i]->getValue();
-
- for (i = 0; i < numTrims; ++i)
- inp.trims[i] = (trimPressed == i);
-
- foreach (RadioUiAction * act, radioUiWidget->getActions()) {
- if (act->getIndex() > -1 && act->getIndex() < CPN_MAX_KEYS)
- inp.keys[act->getIndex()] = act->isActive();
- }
-
- if (radioUiWidget->getRotEncAction())
- inp.rotenc = radioUiWidget->getRotEncAction()->isActive();
-
- simulator->setValues(inp);
-}
-
-// Read stick trim values from firmware simulator and set joystick widgets as needed.
-void SimulatorWidget::setTrims()
-{
- typedef VirtualJoystickWidget VJW;
- static Trims lastTrims;
- Trims trims;
- simulator->getTrims(trims);
-
- if (trims.values[VJW::TRIM_AXIS_L_X] != lastTrims.values[VJW::TRIM_AXIS_L_X])
- vJoyLeft->setTrimValue(VJW::TRIM_AXIS_L_X, trims.values[VJW::TRIM_AXIS_L_X]);
- if (trims.values[VJW::TRIM_AXIS_L_Y] != lastTrims.values[VJW::TRIM_AXIS_L_Y])
- vJoyLeft->setTrimValue(VJW::TRIM_AXIS_L_Y, trims.values[VJW::TRIM_AXIS_L_Y]);
- if (trims.values[VJW::TRIM_AXIS_R_Y] != lastTrims.values[VJW::TRIM_AXIS_R_Y])
- vJoyRight->setTrimValue(VJW::TRIM_AXIS_R_Y, trims.values[VJW::TRIM_AXIS_R_Y]);
- if (trims.values[VJW::TRIM_AXIS_R_X] != lastTrims.values[VJW::TRIM_AXIS_R_X])
- vJoyRight->setTrimValue(VJW::TRIM_AXIS_R_X, trims.values[VJW::TRIM_AXIS_R_X]);
-
- if (trims.extended != lastTrims.extended) {
- int trimMin = -125, trimMax = +125;
- if (trims.extended) {
- trimMin = -500;
- trimMax = +500;
- }
- vJoyLeft->setTrimRange(VJW::TRIM_AXIS_L_X, trimMin, trimMax);
- vJoyLeft->setTrimRange(VJW::TRIM_AXIS_L_Y, trimMin, trimMax);
- vJoyRight->setTrimRange(VJW::TRIM_AXIS_R_Y, trimMin, trimMax);
- vJoyRight->setTrimRange(VJW::TRIM_AXIS_R_X, trimMin, trimMax);
- }
- lastTrims = trims;
-}
/*
* Event handlers/private slots
*/
-//void SimulatorDialog::showEvent(QShowEvent *)
-//{
-// if (firstShow && isVisible()) {
-// firstShow = false;
-// }
-//}
-
-//void SimulatorDialog::closeEvent(QCloseEvent *)
-//{
-//}
-
void SimulatorWidget::mousePressEvent(QMouseEvent *event)
{
if (radioUiWidget)
@@ -814,82 +722,129 @@ void SimulatorWidget::wheelEvent(QWheelEvent *event)
void SimulatorWidget::onTimerEvent()
{
- static unsigned int lcd_counter = 0;
+ if (m_heartbeatTimer.isValid() && m_heartbeatTimer.hasExpired(m_timer.interval())) {
+ onSimulatorError("Heartbeat timeout!");
+ onSimulatorStopped();
+ }
+}
- if (!simulator->timer10ms()) {
- QMessageBox::critical(this, "Companion", tr("Firmware %1 error: %2").arg(firmware->getName()).arg(simulator->getError()));
- timer->stop();
+void SimulatorWidget::onSimulatorHeartbeat(qint32 loops, qint64 timestamp)
+{
+ Q_UNUSED(loops)
+ Q_UNUSED(timestamp)
+ m_heartbeatTimer.start();
+
+#if 0
+ static qint64 lastTs = 0;
+ if (!(loops % 1000)) {
+ qDebug() << "loops:" << loops << "ts:" << timestamp << "ts-delta:" << timestamp - lastTs << "This:" << QThread::currentThread() << "Simu:" << simulator->thread();
+ lastTs = timestamp;
+ }
+#endif
+}
+
+void SimulatorWidget::onSimulatorError(const QString & error)
+{
+ QMessageBox::critical(this, windowName, tr("Radio firmware error: %1").arg(error.isEmpty() ? "Unknown reason" : error));
+}
+
+void SimulatorWidget::onPhaseChanged(qint32 phase, const QString & name)
+{
+ setWindowTitle(windowName + tr(" - Flight Mode %1 (#%2)").arg(name).arg(phase));
+}
+
+void SimulatorWidget::onRadioWidgetValueChange(const RadioWidget::RadioWidgetType type, const int index, int value)
+{
+ //qDebug() << type << index << value;
+ if (!simulator || index < 0)
return;
+
+ SimulatorInterface::InputSourceType inpType = SimulatorInterface::INPUT_SRC_NONE;
+
+ switch (type) {
+ case RadioWidget::RADIO_WIDGET_SWITCH :
+ inpType = SimulatorInterface::INPUT_SRC_SWITCH;
+ break;
+
+ case RadioWidget::RADIO_WIDGET_KNOB :
+ inpType = SimulatorInterface::INPUT_SRC_KNOB;
+ break;
+
+ case RadioWidget::RADIO_WIDGET_FADER :
+ inpType = SimulatorInterface::INPUT_SRC_SLIDER;
+ break;
+
+ case RadioWidget::RADIO_WIDGET_TRIM :
+ switch (value) {
+ case RadioWidget::RADIO_TRIM_BTN_ON :
+ inpType = SimulatorInterface::INPUT_SRC_TRIM_SW;
+ value = 1;
+ break;
+ case RadioWidget::RADIO_TRIM_BTN_OFF :
+ inpType = SimulatorInterface::INPUT_SRC_TRIM_SW;
+ value = 0;
+ break;
+ default :
+ inpType = SimulatorInterface::INPUT_SRC_TRIM;
+ break;
+ }
+ break;
+
+ case RadioWidget::RADIO_WIDGET_STICK :
+ inpType = SimulatorInterface::INPUT_SRC_STICK;
+ break;
+
+ case RadioWidget::RADIO_WIDGET_KEY :
+ inpType = SimulatorInterface::INPUT_SRC_KEY;
+ break;
+
+ default :
+ return;
}
- getValues();
-
- if (!(lcd_counter++ % 5)) {
- setValues();
- setTrims();
- centerSticks();
- }
-}
-
-void SimulatorWidget::onTrimPressed(int which)
-{
- trimPressed = which;
-}
-
-void SimulatorWidget::onTrimReleased()
-{
- trimPressed = TRIM_NONE;
-}
-
-void SimulatorWidget::onTrimSliderMoved(int which, int value)
-{
- simulator->setTrim(which, value);
-}
-
-void SimulatorWidget::centerSticks()
-{
- if (vJoyLeft)
- vJoyLeft->centerStick();
-
- if (vJoyRight)
- vJoyRight->centerStick();
+ emit inputValueChange(inpType, index, value);
}
void SimulatorWidget::onjoystickAxisValueChanged(int axis, int value)
{
#ifdef JOYSTICKS
- int stick;
- if (axis>=0 && axis<=8) {
- stick=jsmap[axis];
- int stickval;
- if (value>jscal[axis][1]) {
- if ((jscal[axis][2]-jscal[axis][1])==0)
- return;
- stickval=(1024*(value-jscal[axis][1]))/(jscal[axis][2]-jscal[axis][1]);
- }
- else {
- if ((jscal[axis][1]-jscal[axis][0])==0)
- return;
- stickval=(1024*(value-jscal[axis][1]))/(jscal[axis][1]-jscal[axis][0]);
- }
- if (jscal[axis][3]==1) {
- stickval*=-1;
- }
- if (stick==1 ) {
- vJoyRight->setStickY(-stickval/1024.0);
- }
- else if (stick==2) {
- vJoyRight->setStickX(stickval/1024.0);
- }
- else if (stick==3) {
- vJoyLeft->setStickY(-stickval/1024.0);
- }
- else if (stick==4) {
- vJoyLeft->setStickX(stickval/1024.0);
- }
- else if (stick >= 5 && stick < 5 + analogs.count()) {
- analogs[stick-5]->setValue(stickval);
- }
+ static const int ttlSticks = 4;
+ static const int ttlKnobs = Boards::getCapability(m_board, Board::Pots);
+ static const int ttlFaders = Boards::getCapability(m_board, Board::Sliders);
+ static const int valueRange = 1024;
+
+ if (!joystick || axis >= MAX_JOYSTICKS)
+ return;
+
+ int dlta;
+ int stick = g.joystick[axis].stick_axe();
+
+ if (stick < 0 || stick >= ttlSticks + ttlKnobs + ttlFaders)
+ return;
+
+ int stickval = valueRange * (value - g.joystick[axis].stick_med());
+
+ if (value > g.joystick[axis].stick_med()) {
+ if ((dlta = g.joystick[axis].stick_max() - g.joystick[axis].stick_med()))
+ stickval /= dlta;
}
+ else if ((dlta = g.joystick[axis].stick_med() - g.joystick[axis].stick_min())) {
+ stickval /= dlta;
+ }
+
+ if (g.joystick[axis].stick_inv())
+ stickval *= -1;
+
+ if (stick < ttlSticks) {
+ emit stickValueChange(stick, stickval);
+ }
+ else {
+ stick -= ttlSticks;
+ if (stick < ttlKnobs)
+ emit widgetValueChange(RadioWidget::RADIO_WIDGET_KNOB, stick, stickval);
+ else
+ emit widgetValueChange(RadioWidget::RADIO_WIDGET_FADER, stick, stickval);
+ }
+
#endif
}
diff --git a/companion/src/simulation/simulatorwidget.h b/companion/src/simulation/simulatorwidget.h
index 69e798ec3..e3377084b 100644
--- a/companion/src/simulation/simulatorwidget.h
+++ b/companion/src/simulation/simulatorwidget.h
@@ -24,23 +24,20 @@
#include "constants.h"
#include "helpers.h"
#include "radiodata.h"
+#include "radiowidget.h"
#include "simulator.h"
+#include "simulatorinterface.h"
+#include
+#include
#include
#include
-#define FLASH_DURATION 10
-
-#define CBEEP_ON "QLabel { background-color: #FF364E }"
-#define CBEEP_OFF "QLabel { }"
-
void traceCb(const char * text);
class Firmware;
class SimulatorInterface;
class SimulatedUIWidget;
-class RadioWidget;
-class RadioSwitchWidget;
class VirtualJoystickWidget;
#ifdef JOYSTICKS
class Joystick;
@@ -55,8 +52,6 @@ namespace Ui {
class SimulatorWidget;
}
-using namespace Simulator;
-
class SimulatorWidget : public QWidget
{
Q_OBJECT
@@ -83,7 +78,7 @@ class SimulatorWidget : public QWidget
QString getSdPath() const { return sdCardPath; }
QString getDataPath() const { return radioDataPath; }
- QVector * getKeymapHelp() { return &keymapHelp; }
+ QVector getKeymapHelp() const { return keymapHelp; }
public slots:
void start();
@@ -91,33 +86,54 @@ class SimulatorWidget : public QWidget
void restart();
void shutdown();
- private:
+ signals:
+ void stickValueChange(int axis, int value);
+ void stickModeChange(const unsigned mode);
+ void widgetValueChange(const RadioWidget::RadioWidgetType type, const int index, const int value);
+ void widgetStateChange(const RadioWidget::RadioWidgetState & state);
+ void inputValueChange(int type, quint8 index, qint16 value);
+ void simulatorSetData(const QByteArray & data);
+ void simulatorInit();
+ void simulatorStart(const char * filename, bool tests);
+ void simulatorStop();
+ void simulatorSdPathChange(const QString & sdPath, const QString & dataPath);
+ void simulatorVolumeGainChange(const int gain);
+
+ private slots:
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseReleaseEvent(QMouseEvent *event);
+ virtual void wheelEvent(QWheelEvent *event);
+
+ void onTimerEvent();
+ void onSimulatorStarted();
+ void onSimulatorStopped();
+ void onSimulatorHeartbeat(qint32 loops, qint64 timestamp);
+ void onPhaseChanged(qint32 phase, const QString & name);
+ void onSimulatorError(const QString & error);
+ void onRadioWidgetValueChange(const RadioWidget::RadioWidgetType type, const int index, int value);
+ void onjoystickAxisValueChanged(int axis, int value);
+
void setRadioProfileId(int value);
void setupRadioWidgets();
- void setupTimer();
void restoreRadioWidgetsState();
- QList saveRadioWidgetsState();
-
- void setValues();
- void getValues();
- void setTrims();
+ private:
+ void saveRadioWidgetsState(QList & state);
Ui::SimulatorWidget * ui;
SimulatorInterface * simulator;
Firmware * firmware;
GeneralSettings radioSettings;
- QTimer * timer;
+ QTimer m_timer;
QString windowName;
- QVector keymapHelp;
+ QVector keymapHelp;
+ QElapsedTimer m_heartbeatTimer;
SimulatedUIWidget * radioUiWidget;
VirtualJoystickWidget * vJoyLeft;
VirtualJoystickWidget * vJoyRight;
-
- QVector switches;
- QVector analogs;
+ QVector m_radioWidgets;
QString sdCardPath;
QString radioDataPath;
@@ -125,35 +141,14 @@ class SimulatorWidget : public QWidget
Board::Type m_board;
quint8 flags;
int radioProfileId;
- int lastPhase;
- int buttonPressed;
- int trimPressed;
bool startupFromFile;
bool deleteTempRadioData;
bool saveTempRadioData;
- bool middleButtonPressed;
- bool firstShow;
#ifdef JOYSTICKS
Joystick *joystick;
- int jscal[8][4];
- int jsmap[8];
#endif
- private slots:
- //virtual void showEvent(QShowEvent *);
- //virtual void closeEvent(QCloseEvent *);
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
- virtual void wheelEvent(QWheelEvent *event);
-
- void onTimerEvent();
- void onTrimPressed(int which);
- void onTrimReleased();
- void onTrimSliderMoved(int which, int value);
- void centerSticks();
- void onjoystickAxisValueChanged(int axis, int value);
-
};
#endif // _SIMULATORWIDGET_H_
diff --git a/companion/src/simulation/telemetrysimu.cpp b/companion/src/simulation/telemetrysimu.cpp
index 46ff5f3e9..3f2594286 100644
--- a/companion/src/simulation/telemetrysimu.cpp
+++ b/companion/src/simulation/telemetrysimu.cpp
@@ -27,27 +27,13 @@
TelemetrySimulator::TelemetrySimulator(QWidget * parent, SimulatorInterface * simulator):
QWidget(parent),
ui(new Ui::TelemetrySimulator),
- simulator(simulator)
+ simulator(simulator),
+ m_simuStarted(false),
+ m_telemEnable(false),
+ m_logReplayEnable(false)
{
ui->setupUi(this);
- timer = new QTimer(this);
- timer->setInterval(10);
- connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent()));
-
- logTimer = new QTimer(this);
- connect(logTimer, SIGNAL(timeout()), this, SLOT(onLogTimerEvent()));
-
- connect(ui->Simulate, SIGNAL(toggled(bool)), this, SLOT(onSimulateToggled(bool)));
- connect(ui->loadLogFile, SIGNAL(released()), this, SLOT(onLoadLogFile()));
- connect(ui->play, SIGNAL(released()), this, SLOT(onPlay()));
- connect(ui->rewind, SIGNAL(clicked()), this, SLOT(onRewind()));
- connect(ui->stepForward, SIGNAL(clicked()), this, SLOT(onStepForward()));
- connect(ui->stepBack, SIGNAL(clicked()), this, SLOT(onStepBack()));
- connect(ui->stop, SIGNAL(clicked()), this, SLOT(onStop()));
- connect(ui->positionIndicator, SIGNAL(valueChanged(int)), this, SLOT(onPositionIndicatorChanged(int)));
- connect(ui->replayRate, SIGNAL(valueChanged(int)), this, SLOT(onReplayRateChanged(int)));
-
ui->A1->setSpecialValueText(" ");
ui->A2->setSpecialValueText(" ");
ui->A3->setSpecialValueText(" ");
@@ -59,38 +45,63 @@ TelemetrySimulator::TelemetrySimulator(QWidget * parent, SimulatorInterface * si
ui->A1_ratio->setEnabled(false);
ui->A2_ratio->setEnabled(false);
+
+ timer.setInterval(10);
+ connect(&timer, &QTimer::timeout, this, &TelemetrySimulator::generateTelemetryFrame);
+
+ connect(&logTimer, &QTimer::timeout, this, &TelemetrySimulator::onLogTimerEvent);
+
logPlayback = new LogPlaybackController(ui);
+
+ connect(ui->Simulate, SIGNAL(toggled(bool)), this, SLOT(onSimulateToggled(bool)));
+ connect(ui->loadLogFile, SIGNAL(released()), this, SLOT(onLoadLogFile()));
+ connect(ui->play, SIGNAL(released()), this, SLOT(onPlay()));
+ connect(ui->rewind, SIGNAL(clicked()), this, SLOT(onRewind()));
+ connect(ui->stepForward, SIGNAL(clicked()), this, SLOT(onStepForward()));
+ connect(ui->stepBack, SIGNAL(clicked()), this, SLOT(onStepBack()));
+ connect(ui->stop, SIGNAL(clicked()), this, SLOT(onStop()));
+ connect(ui->positionIndicator, SIGNAL(valueChanged(int)), this, SLOT(onPositionIndicatorChanged(int)));
+ connect(ui->replayRate, SIGNAL(valueChanged(int)), this, SLOT(onReplayRateChanged(int)));
+
+ connect(this, &TelemetrySimulator::telemetryDataChanged, simulator, &SimulatorInterface::sendTelemetry);
+ connect(simulator, &SimulatorInterface::started, this, &TelemetrySimulator::onSimulatorStarted);
+ connect(simulator, &SimulatorInterface::stopped, this, &TelemetrySimulator::onSimulatorStopped);
}
TelemetrySimulator::~TelemetrySimulator()
{
- timer->stop();
- logTimer->stop();
+ timer.stop();
+ logTimer.stop();
+ delete logPlayback;
delete ui;
}
+void TelemetrySimulator::onSimulatorStarted()
+{
+ m_simuStarted = true;
+ setupDataFields();
+}
+
+void TelemetrySimulator::onSimulatorStopped()
+{
+ m_simuStarted = false;
+}
+
void TelemetrySimulator::onSimulateToggled(bool isChecked)
{
if (isChecked) {
- timer->start();
+ timer.start();
}
else {
- timer->stop();
+ timer.stop();
}
}
-
void TelemetrySimulator::onLogTimerEvent()
{
logPlayback->stepForward(false);
}
-
-void TelemetrySimulator::onTimerEvent()
-{
- generateTelemetryFrame();
-}
-
void TelemetrySimulator::onLoadLogFile()
{
onStop(); // in case we are in playback mode
@@ -100,7 +111,7 @@ void TelemetrySimulator::onLoadLogFile()
void TelemetrySimulator::onPlay()
{
if (logPlayback->isReady()) {
- logTimer->start(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
+ logTimer.start(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
logPlayback->play();
}
}
@@ -108,7 +119,7 @@ void TelemetrySimulator::onPlay()
void TelemetrySimulator::onRewind()
{
if (logPlayback->isReady()) {
- logTimer->stop();
+ logTimer.stop();
logPlayback->rewind();
}
}
@@ -116,7 +127,7 @@ void TelemetrySimulator::onRewind()
void TelemetrySimulator::onStepForward()
{
if (logPlayback->isReady()) {
- logTimer->stop();
+ logTimer.stop();
logPlayback->stepForward(true);
}
}
@@ -124,7 +135,7 @@ void TelemetrySimulator::onStepForward()
void TelemetrySimulator::onStepBack()
{
if (logPlayback->isReady()) {
- logTimer->stop();
+ logTimer.stop();
logPlayback->stepBack();
}
}
@@ -132,7 +143,7 @@ void TelemetrySimulator::onStepBack()
void TelemetrySimulator::onStop()
{
if (logPlayback->isReady()) {
- logTimer->stop();
+ logTimer.stop();
logPlayback->stop();
}
}
@@ -147,21 +158,31 @@ void TelemetrySimulator::onPositionIndicatorChanged(int value)
void TelemetrySimulator::onReplayRateChanged(int value)
{
- if (logTimer->isActive()) {
- logTimer->setInterval(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
+ if (logTimer.isActive()) {
+ logTimer.setInterval(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
}
}
-void TelemetrySimulator::closeEvent(QCloseEvent *event)
+void TelemetrySimulator::hideEvent(QHideEvent *event)
{
- timer->stop();
- logTimer->stop();
+ m_telemEnable = ui->Simulate->isChecked();
+ m_logReplayEnable = logTimer.isActive();
+
+ ui->Simulate->setChecked(false);
+ ui->stop->click();
event->accept();
}
+void TelemetrySimulator::showEvent(QShowEvent * event)
+{
+ ui->Simulate->setChecked(m_telemEnable);
+ if (m_logReplayEnable)
+ ui->play->click();
+}
+
#define SET_INSTANCE(control, id, def) ui->control->setText(QString::number(simulator->getSensorInstance(id, ((def) & 0x1F) + 1)))
-void TelemetrySimulator::showEvent(QShowEvent *event)
+void TelemetrySimulator::setupDataFields()
{
SET_INSTANCE(rxbt_inst, BATT_ID, 0);
SET_INSTANCE(rssi_inst, RSSI_ID, 24);
@@ -206,7 +227,6 @@ void setSportPacketCrc(uint8_t * packet)
crc &= 0x00ff;
}
packet[FRSKY_SPORT_PACKET_SIZE-1] = 0xFF - (crc & 0x00ff);
- //TRACE("crc set: %x", packet[FRSKY_SPORT_PACKET_SIZE-1]);
}
uint8_t getBit(uint8_t position, uint8_t value)
@@ -236,11 +256,12 @@ void TelemetrySimulator::generateTelemetryFrame()
{
static int item = 0;
bool ok = true;
- uint8_t buffer[FRSKY_SPORT_PACKET_SIZE];
+ uint8_t buffer[FRSKY_SPORT_PACKET_SIZE] = {0};
static FlvssEmulator *flvss = new FlvssEmulator();
static GPSEmulator *gps = new GPSEmulator();
- memset(buffer, 0, sizeof(buffer));
+ if (!m_simuStarted)
+ return;
switch (item++) {
case 0:
@@ -407,10 +428,14 @@ void TelemetrySimulator::generateTelemetryFrame()
return;
}
- if (ok && (buffer[2] || buffer[3]))
- simulator->sendTelemetry(buffer, FRSKY_SPORT_PACKET_SIZE);
- else
- onTimerEvent();
+ if (ok && (buffer[2] || buffer[3])) {
+ QByteArray ba((char *)buffer, FRSKY_SPORT_PACKET_SIZE);
+ emit telemetryDataChanged(ba);
+ //qDebug("%02X %02X %02X %02X %02X %02X %02X %02X %02X", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8]);
+ }
+ else {
+ generateTelemetryFrame();
+ }
}
uint32_t TelemetrySimulator::FlvssEmulator::encodeCellPair(uint8_t cellNum, uint8_t firstCellNo, double cell1, double cell2)
diff --git a/companion/src/simulation/telemetrysimu.h b/companion/src/simulation/telemetrysimu.h
index bd0096ba8..08bdd9fa0 100644
--- a/companion/src/simulation/telemetrysimu.h
+++ b/companion/src/simulation/telemetrysimu.h
@@ -46,12 +46,18 @@ class TelemetrySimulator : public QWidget
explicit TelemetrySimulator(QWidget * parent, SimulatorInterface * simulator);
virtual ~TelemetrySimulator();
+ signals:
+
+ void telemetryDataChanged(const QByteArray data);
+
protected slots:
- virtual void closeEvent(QCloseEvent *event);
+ virtual void hideEvent(QHideEvent *event);
virtual void showEvent(QShowEvent *event);
+ void onSimulatorStarted();
+ void onSimulatorStopped();
+ void setupDataFields();
void onSimulateToggled(bool isChecked);
- void onTimerEvent();
void onLogTimerEvent();
void onLoadLogFile();
void onPlay();
@@ -61,14 +67,17 @@ class TelemetrySimulator : public QWidget
void onStop();
void onPositionIndicatorChanged(int value);
void onReplayRateChanged(int value);
+ void generateTelemetryFrame();
protected:
Ui::TelemetrySimulator * ui;
- QTimer * timer;
- QTimer * logTimer;
+ QTimer timer;
+ QTimer logTimer;
SimulatorInterface *simulator;
- void generateTelemetryFrame();
+ bool m_simuStarted;
+ bool m_telemEnable;
+ bool m_logReplayEnable;
// protected classes follow
@@ -81,7 +90,7 @@ class TelemetrySimulator : public QWidget
void play();
void stop();
void rewind();
- void stepForward(bool focusOnStop);
+ void stepForward(bool focusOnStop = false);
void stepBack();
void updatePositionLabel(int32_t percentage);
void setUiDataValues();
diff --git a/companion/src/simulation/telemetrysimu.ui b/companion/src/simulation/telemetrysimu.ui
index fbc909e2a..3ad9ae83e 100644
--- a/companion/src/simulation/telemetrysimu.ui
+++ b/companion/src/simulation/telemetrysimu.ui
@@ -528,7 +528,7 @@ Timestamp
- SWR
+ RAS
diff --git a/companion/src/simulation/trainersimu.cpp b/companion/src/simulation/trainersimu.cpp
index 50a506669..f26fa05af 100644
--- a/companion/src/simulation/trainersimu.cpp
+++ b/companion/src/simulation/trainersimu.cpp
@@ -24,32 +24,40 @@
#include "helpers.h"
#include "virtualjoystickwidget.h"
+#define TRAINERSIMU_HEARTBEAT_PERIOD 500 // [ms]
+
TrainerSimulator::TrainerSimulator(QWidget * parent, SimulatorInterface * simulator):
QWidget(parent),
ui(new Ui::TrainerSimulator),
- simulator(simulator)
+ simulator(simulator),
+ m_simuStarted(false)
{
ui->setupUi(this);
vJoyLeft = new VirtualJoystickWidget(this, 'L', false);
vJoyLeft->setStickColor(Qt::cyan);
+ vJoyLeft->setStickScale(512);
ui->leftStickLayout->addWidget(vJoyLeft);
vJoyRight = new VirtualJoystickWidget(this, 'R', false);
vJoyRight->setStickColor(Qt::cyan);
+ vJoyRight->setStickScale(512);
ui->rightStickLayout->addWidget(vJoyRight);
- timer = new QTimer(this);
- timer->setInterval(10);
- connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent()));
+ connect(vJoyLeft, &VirtualJoystickWidget::valueChange, this, &TrainerSimulator::onRadioWidgetValueChange);
+ connect(vJoyRight, &VirtualJoystickWidget::valueChange, this, &TrainerSimulator::onRadioWidgetValueChange);
+
+ connect(this, &TrainerSimulator::trainerHeartbeat, simulator, &SimulatorInterface::setTrainerTimeout);
+ connect(this, &TrainerSimulator::trainerChannelChange, simulator, &SimulatorInterface::setTrainerInput);
+ connect(simulator, &SimulatorInterface::started, this, &TrainerSimulator::onSimulatorStarted);
+ connect(simulator, &SimulatorInterface::stopped, this, &TrainerSimulator::onSimulatorStopped);
+
+ timer.setInterval(TRAINERSIMU_HEARTBEAT_PERIOD - 10);
+ connect(&timer, &QTimer::timeout, this, &TrainerSimulator::emitHeartbeat);
}
TrainerSimulator::~TrainerSimulator()
{
- if (timer) {
- timer->stop();
- delete timer;
- }
if (vJoyLeft)
delete vJoyLeft;
if (vJoyRight)
@@ -60,42 +68,44 @@ TrainerSimulator::~TrainerSimulator()
void TrainerSimulator::showEvent(QShowEvent *event)
{
- timer->start();
- event->accept();
+ start();
}
-void TrainerSimulator::closeEvent(QCloseEvent *event)
+void TrainerSimulator::hideEvent(QHideEvent *event)
{
- timer->stop();
- event->accept();
+ stop();
}
-void TrainerSimulator::centerSticks()
+void TrainerSimulator::start()
{
- if (vJoyLeft)
- vJoyLeft->centerStick();
-
- if (vJoyRight)
- vJoyRight->centerStick();
+ timer.start();
}
-void TrainerSimulator::onTimerEvent()
+void TrainerSimulator::stop()
{
- centerSticks();
- setTrainerInputs();
+ timer.stop();
}
-void TrainerSimulator::setTrainerInputs()
+void TrainerSimulator::onSimulatorStarted()
{
- if (!simulator)
- return;
+ m_simuStarted = true;
+}
- if (vJoyLeft) {
- simulator->setTrainerInput(0, int( 512 * vJoyLeft->getStickX())); // LEFT HORZ
- simulator->setTrainerInput(1, int(-512 * vJoyLeft->getStickY())); // LEFT VERT
- }
- if (vJoyRight) {
- simulator->setTrainerInput(2, int(-512 * vJoyRight->getStickY())); // RGHT VERT
- simulator->setTrainerInput(3, int( 512 * vJoyRight->getStickX())); // RGHT HORZ
+void TrainerSimulator::onSimulatorStopped()
+{
+ m_simuStarted = false;
+ stop();
+}
+
+void TrainerSimulator::emitHeartbeat()
+{
+ emit trainerHeartbeat(TRAINERSIMU_HEARTBEAT_PERIOD);
+}
+
+void TrainerSimulator::onRadioWidgetValueChange(RadioWidget::RadioWidgetType type, int index, int value)
+{
+ if (type == RadioWidget::RADIO_WIDGET_STICK && m_simuStarted && timer.isActive()) {
+ emit trainerChannelChange(index, value);
+ emitHeartbeat();
}
}
diff --git a/companion/src/simulation/trainersimu.h b/companion/src/simulation/trainersimu.h
index 520df6d6c..ec1198c5b 100644
--- a/companion/src/simulation/trainersimu.h
+++ b/companion/src/simulation/trainersimu.h
@@ -26,6 +26,7 @@
#include
#include
#include
+#include "radiowidget.h"
#include "simulatorinterface.h"
namespace Ui {
@@ -42,21 +43,27 @@ class TrainerSimulator : public QWidget
explicit TrainerSimulator(QWidget * parent, SimulatorInterface * simulator);
virtual ~TrainerSimulator();
+ signals:
+ void trainerHeartbeat(quint16 ms);
+ void trainerChannelChange(quint8 index, qint16 value);
protected slots:
+ void start();
+ void stop();
virtual void showEvent(QShowEvent *event);
- virtual void closeEvent(QCloseEvent *event);
- void centerSticks();
- void setTrainerInputs();
- void onTimerEvent();
+ virtual void hideEvent(QHideEvent *event);
+ void onSimulatorStarted();
+ void onSimulatorStopped();
+ void onRadioWidgetValueChange(RadioWidget::RadioWidgetType type, int index, int value);
+ void emitHeartbeat();
protected:
Ui::TrainerSimulator * ui;
- QTimer * timer;
SimulatorInterface *simulator;
-
VirtualJoystickWidget * vJoyLeft;
VirtualJoystickWidget * vJoyRight;
+ QTimer timer;
+ bool m_simuStarted;
};
diff --git a/companion/src/simulation/widgets/buttonswidget.h b/companion/src/simulation/widgets/buttonswidget.h
index 074ca0851..4fef883e6 100644
--- a/companion/src/simulation/widgets/buttonswidget.h
+++ b/companion/src/simulation/widgets/buttonswidget.h
@@ -22,47 +22,12 @@
#define _BUTTONSWIDGET_H_
#include "radiouiaction.h"
+#include "radiokeywidget.h"
#include
#include
#include
-class Area : public QObject
-{
- Q_OBJECT
-
- public:
- explicit Area(const QPolygon & polygon, const QString &image, RadioUiAction * action = NULL, QObject * parent = NULL):
- QObject(parent),
- polygon(polygon),
- imgFile(image),
- action(action)
- {
- if (action)
- connect(action, &RadioUiAction::toggled, this, &Area::onActionToggled);
- }
-
- bool contains(int x, int y)
- {
- return polygon.containsPoint(QPoint(x, y), Qt::OddEvenFill);
- }
-
- void onActionToggled(int, bool active)
- {
- if (active)
- emit imageChanged(imgFile);
- else
- emit imageChanged("");
- }
-
- QPolygon polygon;
- QString imgFile;
- RadioUiAction * action;
-
- signals:
- void imageChanged(const QString image);
-};
-
class ButtonsWidget : public QWidget
{
Q_OBJECT
@@ -80,18 +45,17 @@ class ButtonsWidget : public QWidget
QWidget::setStyleSheet(sheet);
}
- void addArea(int x1, int y1, int x2, int y2, const char * image, RadioUiAction * action = NULL)
+ RadioKeyWidget * addArea(const QRect & rect, const char * image, RadioUiAction * action = NULL)
{
- QPolygon polygon;
- polygon.setPoints(4, x1, y1, x1, y2, x2, y2, x2, y1);
- addArea(polygon, image, action);
+ return addArea(QPolygon(rect), image, action);
}
- void addArea(const QPolygon & polygon, const char * image, RadioUiAction * action = NULL)
+ RadioKeyWidget * addArea(const QPolygon & polygon, const char * image, RadioUiAction * action = NULL)
{
- Area * area = new Area(polygon, image, action, this);
- areas.push_back(area);
- connect(area, &Area::imageChanged, this, &ButtonsWidget::setBitmap);
+ RadioKeyWidget * btn = new RadioKeyWidget(polygon, image, action, this);
+ m_buttons.append(btn);
+ connect(btn, &RadioKeyWidget::imageChanged, this, &ButtonsWidget::setBitmap);
+ return btn;
}
protected:
@@ -113,16 +77,14 @@ class ButtonsWidget : public QWidget
return;
}
- foreach(Area * area, areas) {
- if (!area->action)
- continue;
- if (area->contains(event->x(), event->y())) {
- area->action->trigger(press);
+ foreach(RadioKeyWidget * key, m_buttons) {
+ if (key->contains(event->pos())) {
+ key->toggle(press);
event->accept();
return;
}
- else if (area->action->isActive()) {
- area->action->trigger(false);
+ else if (key->getValue()) {
+ key->toggle(false);
}
}
event->ignore();
@@ -145,7 +107,7 @@ class ButtonsWidget : public QWidget
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
- QList areas;
+ QList m_buttons;
QString defaultStyleSheet;
};
diff --git a/companion/src/simulation/widgets/lcdwidget.h b/companion/src/simulation/widgets/lcdwidget.h
index 355c9b5b5..879ce3236 100644
--- a/companion/src/simulation/widgets/lcdwidget.h
+++ b/companion/src/simulation/widgets/lcdwidget.h
@@ -26,10 +26,15 @@
#include
#include
#include
+#include
+#include
+#include
#include "appdata.h"
#include "appdebugmessagehandler.h"
+#define LCD_WIDGET_REFRESH_PERIOD 16 // [ms] 16 = 62.5fps
+
class LcdWidget : public QWidget
{
Q_OBJECT
@@ -39,7 +44,7 @@ class LcdWidget : public QWidget
LcdWidget(QWidget * parent = 0):
QWidget(parent),
lcdBuf(NULL),
- previousBuf(NULL),
+ localBuf(NULL),
lightEnable(false),
bgDefaultColor(QColor(198, 208, 199))
{
@@ -47,8 +52,8 @@ class LcdWidget : public QWidget
~LcdWidget()
{
- if (previousBuf) {
- free(previousBuf);
+ if (localBuf) {
+ free(localBuf);
}
}
@@ -62,8 +67,9 @@ class LcdWidget : public QWidget
lcdSize = (width * height) * ((depth+7) / 8);
else
lcdSize = (width * ((height+7)/8)) * depth;
- previousBuf = (unsigned char *)malloc(lcdSize);
- memset(previousBuf, 0, lcdSize);
+
+ localBuf = (unsigned char *)malloc(lcdSize);
+ memset(localBuf, 0, lcdSize);
}
void setBgDefaultColor(const QColor & color)
@@ -102,10 +108,12 @@ class LcdWidget : public QWidget
void onLcdChanged(bool light)
{
- if (light != lightEnable || memcmp(previousBuf, lcdBuf, lcdSize)) {
- lightEnable = light;
- memcpy(previousBuf, lcdBuf, lcdSize);
+ QMutexLocker locker(&lcdMtx);
+ lightEnable = light;
+ memcpy(localBuf, lcdBuf, lcdSize);
+ if (!redrawTimer.isValid() || redrawTimer.hasExpired(LCD_WIDGET_REFRESH_PERIOD)) {
update();
+ redrawTimer.start();
}
}
@@ -117,24 +125,26 @@ class LcdWidget : public QWidget
int lcdSize;
unsigned char *lcdBuf;
- unsigned char *previousBuf;
+ unsigned char *localBuf;
bool lightEnable;
QColor bgColor;
QColor bgDefaultColor;
+ QMutex lcdMtx;
+ QElapsedTimer redrawTimer;
inline void doPaint(QPainter & p)
{
QRgb rgb;
uint16_t z;
- if (!lcdBuf)
+ if (!localBuf)
return;
if (lcdDepth == 16) {
for (int x = 0; x < lcdWidth; x++) {
for (int y = 0; y < lcdHeight; y++) {
- z = ((uint16_t *)lcdBuf)[y * lcdWidth + x];
+ z = ((uint16_t *)localBuf)[y * lcdWidth + x];
rgb = qRgb(255 * ((z & 0xF800) >> 11) / 0x1F,
255 * ((z & 0x07E0) >> 5) / 0x3F,
255 * (z & 0x001F) / 0x1F);
@@ -147,7 +157,7 @@ class LcdWidget : public QWidget
if (lcdDepth == 12) {
for (int x = 0; x < lcdWidth; x++) {
for (int y = 0; y < lcdHeight; y++) {
- z = ((uint16_t *)lcdBuf)[y * lcdWidth + x];
+ z = ((uint16_t *)localBuf)[y * lcdWidth + x];
rgb = qRgb(255 * ((z & 0xF00) >> 8) / 0x0F,
255 * ((z & 0x0F0) >> 4) / 0x0F,
255 * (z & 0x00F) / 0x0F);
@@ -181,12 +191,12 @@ class LcdWidget : public QWidget
mask = (1 << (y % 8));
for (int x = 0; x < lcdWidth; x++, idx++) {
if (lcdDepth == 1) {
- if (lcdBuf[idx] & mask)
+ if (localBuf[idx] & mask)
p.drawRect(2 * x, 2 * y, 1, 1);
continue;
}
// lcdDepth == 4
- z = (y & 1) ? (lcdBuf[idx] >> 4) : (lcdBuf[idx] & 0x0F);
+ z = (y & 1) ? (localBuf[idx] >> 4) : (localBuf[idx] & 0x0F);
if (!z)
continue;
if (z != previousDepth) {
diff --git a/companion/src/simulation/widgets/radiokeywidget.h b/companion/src/simulation/widgets/radiokeywidget.h
new file mode 100644
index 000000000..ee63c3b71
--- /dev/null
+++ b/companion/src/simulation/widgets/radiokeywidget.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef RADIOKEYWIDGET_H
+#define RADIOKEYWIDGET_H
+
+#include "radiouiaction.h"
+#include "radiowidget.h"
+
+class RadioKeyWidget : public RadioWidget
+{
+ Q_OBJECT
+
+ public:
+
+ explicit RadioKeyWidget(const QPolygon & polygon, const QString &image, RadioUiAction * action = NULL, QWidget * parent = NULL, Qt::WindowFlags f = Qt::WindowFlags()):
+ RadioWidget(action, parent, f),
+ polygon(polygon),
+ imgFile(image)
+ {
+ m_type = RADIO_WIDGET_KEY;
+ setValue(0);
+ hide(); // we're a "virtual" button for now
+ setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+ }
+
+ virtual void setAction(RadioUiAction * action)
+ {
+ if (m_action)
+ disconnect(m_action, 0, this, 0);
+ RadioWidget::setAction(action);
+ if (m_action)
+ connect(m_action, &RadioUiAction::toggled, this, &RadioKeyWidget::onActionToggled);
+ }
+
+ virtual int getValue() const
+ {
+ return (m_action && m_action->isActive()) ? 1 : 0;
+ }
+
+ void press() {
+ if (m_action)
+ m_action->trigger(true);
+ }
+
+ void release() {
+ if (m_action)
+ m_action->trigger(false);
+ }
+
+ void toggle(bool down)
+ {
+ if (down)
+ press();
+ else
+ release();
+ }
+
+ bool contains(const QPoint & point)
+ {
+ return polygon.containsPoint(point, Qt::OddEvenFill);
+ }
+
+ signals:
+
+ void imageChanged(const QString image);
+
+ protected:
+
+ virtual void onActionToggled(int index, bool active)
+ {
+ RadioWidget::onActionToggled(index, active);
+ emit imageChanged(active ? imgFile : "");
+ }
+
+ QPolygon polygon;
+ QString imgFile;
+
+};
+
+#endif // RADIOKEYWIDGET_H
+
+
diff --git a/companion/src/simulation/widgets/radioknobwidget.h b/companion/src/simulation/widgets/radioknobwidget.h
index be74a9ee9..d66eddf18 100644
--- a/companion/src/simulation/widgets/radioknobwidget.h
+++ b/companion/src/simulation/widgets/radioknobwidget.h
@@ -26,7 +26,7 @@
#include
#include
-#include
+#include
#include
class RadioKnobWidget : public RadioWidget
@@ -65,7 +65,6 @@ class RadioKnobWidget : public RadioWidget
Board::PotType m_potType;
-
class KnobWidget : public QDial
{
public:
@@ -73,6 +72,8 @@ class RadioKnobWidget : public RadioWidget
explicit KnobWidget(Board::PotType type, QWidget * parent = 0):
QDial(parent)
{
+ m_toolTip = tr("Value (input): %1 ");
+
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setFixedSize(QSize(42, 42));
setNotchesVisible(true);
@@ -88,7 +89,7 @@ class RadioKnobWidget : public RadioWidget
}
else {
m_stepSize = 1;
- setToolTip(tr("Right-double-click to reset to center."));
+ m_toolTip.append(tr("Right-double-click to reset to center."));
setMinimum(-1024);
setMaximum(1024);
setPageStep(128);
@@ -104,6 +105,19 @@ class RadioKnobWidget : public RadioWidget
QDial::setValue(value);
}
+
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::ToolTip) {
+ QHelpEvent * helpEvent = static_cast(event);
+ if (helpEvent) {
+ QToolTip::showText(helpEvent->globalPos(), m_toolTip.arg(this->value()));
+ return true;
+ }
+ }
+ return QWidget::event(event);
+ }
+
void mousePressEvent(QMouseEvent * event)
{
if (m_stepSize == 1 && event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) {
@@ -129,6 +143,7 @@ class RadioKnobWidget : public RadioWidget
}
quint16 m_stepSize;
+ QString m_toolTip;
};
};
diff --git a/companion/src/simulation/widgets/radioswitchwidget.h b/companion/src/simulation/widgets/radioswitchwidget.h
index 45c50d710..39878a648 100644
--- a/companion/src/simulation/widgets/radioswitchwidget.h
+++ b/companion/src/simulation/widgets/radioswitchwidget.h
@@ -110,9 +110,8 @@ class RadioSwitchWidget : public RadioWidget
void setToggleLocked(bool lock)
{
if (m_flags != (quint16)lock) {
- m_flags = lock;
+ setFlags((quint16)lock);
setValue((int)lock);
- emit flagsChanged(m_flags);
}
}
diff --git a/companion/src/simulation/widgets/radiotrimwidget.h b/companion/src/simulation/widgets/radiotrimwidget.h
new file mode 100644
index 000000000..54659b0a4
--- /dev/null
+++ b/companion/src/simulation/widgets/radiotrimwidget.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _RADIOTRIMWIDGET_H_
+#define _RADIOTRIMWIDGET_H_
+
+#include "radiowidget.h"
+#include "boards.h"
+#include "sliderwidget.h"
+
+#include
+
+class RadioTrimWidget : public RadioWidget
+{
+ Q_OBJECT
+
+ public:
+
+ explicit RadioTrimWidget(Qt::Orientation orientation = Qt::Vertical, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
+ RadioWidget(parent, f),
+ m_slider(NULL)
+ {
+ init(orientation);
+ }
+
+ void setIndices(int sliderIdx = -1, int decrBtnIdx = -1, int incrBtnIdx = -1)
+ {
+ setIndex(sliderIdx);
+ m_btnDecIndex = decrBtnIdx;
+ m_btnIncIndex = incrBtnIdx;
+ }
+
+ void setTrimRange(int min, int max)
+ {
+ if (m_slider)
+ m_slider->setRange(min, max);
+ }
+
+ void setTrimRangeQual(const int index, const int min, const int max)
+ {
+ if (index == m_index || index == Board::TRIM_AXIS_COUNT)
+ setTrimRange(min, max);
+ }
+
+ void setTrimValue(const int index, const int value)
+ {
+ if (index == m_index || index == Board::TRIM_AXIS_COUNT)
+ setValue(value);
+ }
+
+ void setValue(const int & value)
+ {
+ if (sender() && qobject_cast(sender())) {
+ RadioWidget::setValue(value);
+ }
+ else if (m_slider) {
+ m_slider->setValue(value);
+ }
+ }
+
+ protected slots:
+
+ void init(Qt::Orientation orientation)
+ {
+ m_type = RADIO_WIDGET_TRIM;
+ m_slider = new SliderWidget(this);
+ m_slider->setOrientation(orientation);
+
+ setTrimRange(-125, 125);
+ setIndices();
+
+ const QSize btnSz(18, 18);
+ QWidget * trimWidget = new QWidget(this);
+ QBoxLayout * trimLayout = new QVBoxLayout(trimWidget);
+ trimLayout->setSpacing(4);
+ QToolButton * trimBtnInc = new QToolButton(trimWidget);
+ trimBtnInc->setMaximumSize(btnSz);
+ QToolButton * trimBtnDec = new QToolButton(trimWidget);
+ trimBtnDec->setMaximumSize(btnSz);
+
+ Qt::Alignment algn;
+ if (orientation == Qt::Horizontal) {
+ trimWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ trimLayout->setDirection(QBoxLayout::RightToLeft);
+ trimLayout->setContentsMargins(0, 8, 0, 8);
+ trimBtnInc->setArrowType(Qt::RightArrow);
+ trimBtnDec->setArrowType(Qt::LeftArrow);
+ algn = Qt::AlignVCenter;
+ }
+ else {
+ trimWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ trimLayout->setDirection(QBoxLayout::TopToBottom);
+ trimLayout->setContentsMargins(8, 0, 8, 0);
+ trimBtnInc->setArrowType(Qt::UpArrow);
+ trimBtnDec->setArrowType(Qt::DownArrow);
+ algn = Qt::AlignHCenter;
+ }
+
+ trimLayout->addWidget(trimBtnInc, 0, algn);
+ trimLayout->addWidget(m_slider, 1, algn);
+ trimLayout->addWidget(trimBtnDec, 0, algn);
+
+ setWidget(trimWidget, algn);
+
+ connect(m_slider, &SliderWidget::valueChanged, this, &RadioTrimWidget::setValue);
+ connect(trimBtnInc, &QToolButton::pressed, [this]() { emit valueChange(m_type, m_btnIncIndex, RADIO_TRIM_BTN_ON); });
+ connect(trimBtnInc, &QToolButton::released, [this]() { emit valueChange(m_type, m_btnIncIndex, RADIO_TRIM_BTN_OFF); });
+ connect(trimBtnDec, &QToolButton::pressed, [this]() { emit valueChange(m_type, m_btnDecIndex, RADIO_TRIM_BTN_ON); });
+ connect(trimBtnDec, &QToolButton::released, [this]() { emit valueChange(m_type, m_btnDecIndex, RADIO_TRIM_BTN_OFF); });
+ }
+
+ protected:
+ SliderWidget * m_slider;
+ int m_btnDecIndex;
+ int m_btnIncIndex;
+};
+
+#endif // _RADIOTRIMWIDGET_H_
diff --git a/companion/src/simulation/widgets/radiowidget.cpp b/companion/src/simulation/widgets/radiowidget.cpp
index f87522234..9e4d9177a 100644
--- a/companion/src/simulation/widgets/radiowidget.cpp
+++ b/companion/src/simulation/widgets/radiowidget.cpp
@@ -18,51 +18,66 @@
* GNU General Public License for more details.
*/
+#include "radiouiaction.h"
#include "radiowidget.h"
RadioWidget::RadioWidget(QWidget * parent, Qt::WindowFlags f) :
QWidget(parent, f),
+ m_gridLayout(NULL),
+ m_controlWidget(NULL),
+ m_nameLabel(NULL),
+ m_action(NULL),
m_value(0),
m_flags(0),
- m_invertValue(false),
+ m_valueReset(false),
m_showLabel(false),
- m_labelText(""),
- m_type(RADIO_WIDGET_NONE)
+ m_labelText("")
{
- init();
+ qRegisterMetaType();
+ setIndex(-1);
+ setType(RADIO_WIDGET_NONE);
+}
+
+RadioWidget::RadioWidget(RadioUiAction * action, QWidget * parent, Qt::WindowFlags f) :
+ RadioWidget(parent, f)
+{
+ setAction(action);
}
RadioWidget::RadioWidget(const QString & labelText, int value, QWidget * parent, Qt::WindowFlags f) :
- QWidget(parent, f),
- m_value(value),
- m_flags(0),
- m_invertValue(false),
- m_showLabel(true),
- m_labelText(labelText),
- m_type(RADIO_WIDGET_NONE)
+ RadioWidget(parent, f)
{
- init();
+ setValue(value);
+ setLabelText(labelText);
}
-void RadioWidget::setIndex(int index)
+void RadioWidget::setIndex(const int & index)
{
m_index = index;
}
-void RadioWidget::setInvertValue(bool invertValue)
+void RadioWidget::setType(const RadioWidgetType & type)
{
- m_invertValue = invertValue;
+ m_type = type;
}
-void RadioWidget::setValue(int value)
+void RadioWidget::setValue(const int & value)
{
- if (value != m_value) {
+ if (value != m_value || m_valueReset) {
m_value = value;
- emit valueChanged(m_value);
+ m_valueReset = false;
+ emit valueChanged(value);
+ emit valueChange(m_type, m_index, value);
}
}
-void RadioWidget::setFlags(quint16 flags)
+void RadioWidget::setValueQual(const RadioWidget::RadioWidgetType & type, const int & index, const int & value)
+{
+ if (type == m_type && index == m_index)
+ setValue(value);
+}
+
+void RadioWidget::setFlags(const quint16 & flags)
{
if (flags != m_flags) {
m_flags = flags;
@@ -70,7 +85,7 @@ void RadioWidget::setFlags(quint16 flags)
}
}
-void RadioWidget::setShowLabel(bool show)
+void RadioWidget::setShowLabel(const bool show)
{
if (show != m_showLabel) {
m_showLabel = show;
@@ -85,13 +100,12 @@ void RadioWidget::setLabelText(const QString & labelText, bool showLabel)
addLabel();
}
-void RadioWidget::setStateData(const QByteArray & data)
+void RadioWidget::setStateData(const RadioWidgetState & state)
{
- RadioWidgetState state;
- QDataStream stream(data);
- stream >> state;
+ if (state.type != m_type || state.index != m_index)
+ return;
- //setIndex(state.index);
+ m_valueReset = true;
setValue(state.value);
setFlags(state.flags);
}
@@ -109,9 +123,26 @@ void RadioWidget::changeVisibility(bool visible)
}
}
+void RadioWidget::setAction(RadioUiAction * action)
+{
+ if (m_action) {
+ disconnect(m_action, 0, this, 0);
+ delete m_action;
+ m_action = NULL;
+ }
+ m_action = action;
+
+ if (m_action) {
+ if (m_action->getIndex() > -1)
+ setIndex(m_action->getIndex());
+ connect(m_action, &RadioUiAction::toggled, this, &RadioWidget::onActionToggled);
+ }
+}
+
+
int RadioWidget::getValue() const
{
- return m_value * (m_invertValue ? -1 : 1);
+ return m_value;
}
int RadioWidget::getIndex() const
@@ -134,25 +165,34 @@ QByteArray RadioWidget::getStateData() const
RadioWidget::RadioWidgetState RadioWidget::getState() const
{
- return RadioWidgetState(quint8(m_type), qint8(m_index), qint16(m_value), quint16(m_flags));;
+ return RadioWidgetState(quint8(m_type), qint8(m_index), qint16(m_value), quint16(m_flags));
}
-void RadioWidget::init()
+RadioUiAction * RadioWidget::getAction() const
{
- setIndex(0);
- m_controlWidget = NULL;
- m_nameLabel = NULL;
+ return m_action;
+}
- m_gridLayout= new QGridLayout(this);
+void RadioWidget::onActionToggled(int index, bool active)
+{
+ emit valueChange(m_type, index, getValue());
+}
+
+
+void RadioWidget::addLayout()
+{
+ if (m_gridLayout)
+ return;
+
+ m_gridLayout = new QGridLayout(this);
m_gridLayout->setContentsMargins(0, 0, 0, 0);
m_gridLayout->setVerticalSpacing(4);
m_gridLayout->setHorizontalSpacing(0);
-
- addLabel();
}
void RadioWidget::addLabel()
{
+ addLayout();
if (m_nameLabel) {
m_gridLayout->removeWidget(m_nameLabel);
m_nameLabel->deleteLater();
@@ -166,15 +206,16 @@ void RadioWidget::addLabel()
}
}
-void RadioWidget::setWidget(QWidget * widget)
+void RadioWidget::setWidget(QWidget * widget, Qt::Alignment align)
{
+ addLayout();
if (m_controlWidget) {
m_gridLayout->removeWidget(m_controlWidget);
m_controlWidget->deleteLater();
}
m_controlWidget = widget;
if (widget) {
- m_gridLayout->addWidget(widget, 0, 0, 1, 1, Qt::AlignHCenter);
+ m_gridLayout->addWidget(widget, 0, 0, 1, 1, align);
m_gridLayout->setRowStretch(0, 1);
}
}
diff --git a/companion/src/simulation/widgets/radiowidget.h b/companion/src/simulation/widgets/radiowidget.h
index ad1b5bac7..af218495b 100644
--- a/companion/src/simulation/widgets/radiowidget.h
+++ b/companion/src/simulation/widgets/radiowidget.h
@@ -28,6 +28,8 @@
#define RADIO_WIDGET_STATE_VERSION 1
+class RadioUiAction;
+
class RadioWidget : public QWidget
{
Q_OBJECT
@@ -41,9 +43,14 @@ class RadioWidget : public QWidget
RADIO_WIDGET_SWITCH,
RADIO_WIDGET_KNOB,
RADIO_WIDGET_FADER,
- RADIO_WIDGET_STICK // actually one axis of a stick
+ RADIO_WIDGET_TRIM, // trim axis, usually 2 buttons & slider
+ RADIO_WIDGET_STICK, // actually one axis of a stick
+ RADIO_WIDGET_KEY, // UI key/pushbutton
+ RADIO_WIDGET_ENUM_COUNT
};
+ enum RadioTrimWidgetButtonStates { RADIO_TRIM_BTN_ON = 1024, RADIO_TRIM_BTN_OFF = -1024 };
+
struct RadioWidgetState {
public:
RadioWidgetState(quint8 type = 0, qint8 index = 0, qint16 value = 0, quint16 flags = 0) :
@@ -64,50 +71,58 @@ class RadioWidget : public QWidget
quint8 _version = RADIO_WIDGET_STATE_VERSION; // structure definition version
};
- explicit RadioWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
- explicit RadioWidget(const QString &labelText, int value = 0, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
-
- void setIndex(int index);
- void setInvertValue(bool invertValue);
- void setValue(int value);
- void setFlags(quint16 flags);
- void setShowLabel(bool show);
- void setLabelText(const QString &labelText, bool showLabel = true);
- void setStateData(const QByteArray & data);
- void changeVisibility(bool visible);
-
+ explicit RadioWidget(QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
+ explicit RadioWidget(RadioUiAction * action = NULL, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
+ explicit RadioWidget(const QString & labelText, int value = 0, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
virtual int getValue() const;
- int getIndex() const;
- int getType() const;
- QByteArray getStateData() const;
- RadioWidgetState getState() const;
+ virtual int getIndex() const;
+ virtual int getType() const;
+ virtual QByteArray getStateData() const;
+ virtual RadioWidgetState getState() const;
+ virtual RadioUiAction * getAction() const;
+
+ public slots:
+
+ virtual void setIndex(const int & index);
+ virtual void setType(const RadioWidgetType & type);
+ virtual void setValue(const int & value);
+ virtual void setValueQual(const RadioWidgetType & type, const int & index, const int & value);
+ virtual void setFlags(const quint16 & flags);
+ virtual void setShowLabel(const bool show);
+ virtual void setLabelText(const QString & labelText, bool showLabel = true);
+ virtual void setStateData(const RadioWidgetState & state);
+ virtual void changeVisibility(bool visible);
+ virtual void setAction(RadioUiAction * action);
+
+ signals:
+
+ void valueChange(const RadioWidgetType type, const int index, int value);
+ void valueChanged(const int value);
+ void flagsChanged(const quint16 flags);
protected:
- void init();
+ void addLayout();
void addLabel();
- void setWidget(QWidget * widget = NULL);
-
- int m_value;
- int m_index;
- quint16 m_flags;
- bool m_invertValue;
- bool m_showLabel;
- QString m_labelText;
- RadioWidgetType m_type;
-
- private:
+ void setWidget(QWidget * widget = NULL, Qt::Alignment align = Qt::AlignHCenter);
+ virtual void onActionToggled(int index, bool active);
QGridLayout * m_gridLayout;
QWidget * m_controlWidget;
QLabel * m_nameLabel;
+ RadioUiAction * m_action;
- signals:
-
- void valueChanged(int m_value);
- void flagsChanged(quint16 flags);
+ int m_value;
+ int m_index;
+ quint16 m_flags;
+ bool m_valueReset;
+ bool m_showLabel;
+ QString m_labelText;
+ RadioWidgetType m_type;
};
+Q_DECLARE_METATYPE(RadioWidget::RadioWidgetState)
+
#endif // _RADIOWIDGET_H_
diff --git a/companion/src/simulation/widgets/sliderwidget.h b/companion/src/simulation/widgets/sliderwidget.h
index aa5140b82..1ed285ba8 100644
--- a/companion/src/simulation/widgets/sliderwidget.h
+++ b/companion/src/simulation/widgets/sliderwidget.h
@@ -23,6 +23,7 @@
#include
#include
+#include
class SliderWidget : public QSlider
{
@@ -33,19 +34,34 @@ class SliderWidget : public QSlider
explicit SliderWidget(QWidget * parent = 0):
QSlider(parent)
{
- setToolTip(tr("Right-double-click to reset to center."));
+ m_toolTip = tr("Value (input): %1 ") % tr("Right-double-click to reset to center.");
}
- protected:
+ protected:
- void mousePressEvent(QMouseEvent * event)
- {
- if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) {
- setValue(0);
- event->accept();
- }
- QSlider::mousePressEvent(event);
- }
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::ToolTip) {
+ QHelpEvent * helpEvent = static_cast(event);
+ if (helpEvent) {
+ QToolTip::showText(helpEvent->globalPos(), m_toolTip.arg(this->value()));
+ return true;
+ }
+ }
+ return QWidget::event(event);
+ }
+
+ void mousePressEvent(QMouseEvent * event)
+ {
+ if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) {
+ setValue(0);
+ emit sliderMoved(0);
+ event->accept();
+ }
+ QSlider::mousePressEvent(event);
+ }
+
+ QString m_toolTip;
};
#endif // _SLIDERWIDGET_H_
diff --git a/companion/src/simulation/widgets/virtualjoystickwidget.cpp b/companion/src/simulation/widgets/virtualjoystickwidget.cpp
index 9242b01c4..8e9a4fa45 100644
--- a/companion/src/simulation/widgets/virtualjoystickwidget.cpp
+++ b/companion/src/simulation/widgets/virtualjoystickwidget.cpp
@@ -18,27 +18,33 @@
* GNU General Public License for more details.
*/
-#define GBALL_SIZE 20
-#define RESX 1024
+#define GBALL_SIZE 25
+#define GBALL_SIZE_MN 20
+#define GBALL_SIZE_MX 35
+#define CENTER_INTERVAL 50 // ms
#include "virtualjoystickwidget.h"
-#include "constants.h"
-#include "sliderwidget.h"
+
+#include "boards.h"
#include "modeledit/node.h"
#include "helpers.h"
+#include "radiotrimwidget.h"
+#include "simulator.h"
VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool showTrims, bool showBtns, bool showValues, QSize size) :
QWidget(parent),
stickSide(side),
prefSize(size),
- hTrimSlider(NULL),
- vTrimSlider(NULL),
+ hTrimWidget(NULL),
+ vTrimWidget(NULL),
btnHoldX(NULL),
btnHoldY(NULL),
btnFixX(NULL),
btnFixY(NULL),
nodeLabelX(NULL),
- nodeLabelY(NULL)
+ nodeLabelY(NULL),
+ m_stickScale(1024),
+ m_stickPressed(false)
{
ar = (float)size.width() / size.height();
extraSize = QSize(0, 0);
@@ -54,12 +60,11 @@ VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool s
gv = new QGraphicsView(this);
gv->setSizePolicy(sizePolicy);
gv->setMinimumSize(size);
-// gv->setMaximumSize(size + size * 3);
-// gv->setFixedSize(prefSize);
gv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
gv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ gv->setRenderHints(QPainter::Antialiasing);
- scene = new QGraphicsScene(gv);
+ scene = new CustomGraphicsScene(gv);
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
gv->setScene(scene);
@@ -83,14 +88,12 @@ VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool s
}
if (showTrims) {
- QWidget * hTrimWidget = createTrimWidget('H');
- QWidget * vTrimWidget = createTrimWidget('V');
+ hTrimWidget = createTrimWidget('H');
+ vTrimWidget = createTrimWidget('V');
layout->addWidget(vTrimWidget, 1, colvt, 1, 1);
layout->addWidget(hTrimWidget, 2, 2, 1, 1);
- hTrimSlider = hTrimWidget->findChild();
- vTrimSlider = vTrimWidget->findChild();
extraSize += QSize(vTrimWidget->sizeHint().width(), hTrimWidget->sizeHint().height());
}
else {
@@ -131,12 +134,20 @@ VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool s
layout->addItem(new QSpacerItem(0, 0), 1, 0, 2, 1); // r1-2 c0: left h spacer
layout->addWidget(gv, 1, 2, 1, 1); // r1 c2: stick widget
layout->addItem(new QSpacerItem(0, 0), 1, 4, 2, 1); // r1-2 c4: right h spacer
- layout->addItem(new QSpacerItem(0, 0), 3, 0, 1, 5); // r3 c0-4: bot v spacer
+ layout->addItem(new QSpacerItem(0, 0), 3, 0, 1, 5); // r4 c0-4: bot v spacer
- connect(node, SIGNAL(xChanged()), this, SLOT(updateNodeValueLabels()));
- connect(node, SIGNAL(yChanged()), this, SLOT(updateNodeValueLabels()));
+ setStickIndices(getStickIndex('H'), getStickIndex('V'));
+
+ connect(node, &Node::xChanged, this, &VirtualJoystickWidget::onNodeXChanged);
+ connect(node, &Node::yChanged, this, &VirtualJoystickWidget::onNodeYChanged);
+
+ connect(scene, &CustomGraphicsScene::mouseEvent, this, &VirtualJoystickWidget::onGsMouseEvent);
setSize(prefSize, frameSize());
+
+ centerStickTimer.setInterval(CENTER_INTERVAL);
+ connect(¢erStickTimer, &QTimer::timeout, this, &VirtualJoystickWidget::centerStick);
+ centerStickTimer.start();
}
void VirtualJoystickWidget::setStickX(qreal x)
@@ -154,6 +165,31 @@ void VirtualJoystickWidget::setStickPos(QPointF xy)
node->setPos(xy);
}
+void VirtualJoystickWidget::setStickAxisValue(int index, int value)
+{
+ using namespace Board;
+ qreal rvalue = value / 1024.0f;
+
+ switch (index) {
+ case STICK_AXIS_LH :
+ if (stickSide == 'L')
+ setStickX(rvalue);
+ break;
+ case STICK_AXIS_RH :
+ if (stickSide == 'R')
+ setStickX(rvalue);
+ break;
+ case STICK_AXIS_LV :
+ if (stickSide == 'L')
+ setStickY(rvalue);
+ break;
+ case STICK_AXIS_RV :
+ if (stickSide == 'R')
+ setStickY(rvalue);
+ break;
+ }
+}
+
void VirtualJoystickWidget::centerStick()
{
node->stepToCenter();
@@ -174,52 +210,85 @@ QPointF VirtualJoystickWidget::getStickPos()
return QPointF(node->getX(), node->getY());
}
-void VirtualJoystickWidget::setTrimValue(int which, int value)
+void VirtualJoystickWidget::setTrimsRange(int min, int max)
{
- SliderWidget * slider = getTrimSlider(which);
- if (slider) {
- slider->setValue(value);
+ if (hTrimWidget)
+ hTrimWidget->setTrimRange(min, max);
+ if (vTrimWidget)
+ vTrimWidget->setTrimRange(min, max);
+}
+
+void VirtualJoystickWidget::setTrimsRange(int rng)
+{
+ setTrimsRange(-rng, rng);
+}
+
+void VirtualJoystickWidget::setTrimRange(int index, int min, int max)
+{
+ if (index == Board::TRIM_AXIS_COUNT) {
+ setTrimsRange(min, max);
+ return;
+ }
+ RadioTrimWidget * trim = getTrimWidget(index);
+ if (trim) {
+ trim->setTrimRange(min, max);
}
}
-void VirtualJoystickWidget::setTrimRange(int which, int min, int max)
+void VirtualJoystickWidget::setTrimValue(int index, int value)
{
- SliderWidget * slider = getTrimSlider(which);
- if (slider) {
- slider->setRange(min, max);
+ RadioTrimWidget * trim = getTrimWidget(index);
+ if (trim) {
+ trim->setValue(value);
}
}
+int VirtualJoystickWidget::getStickScale() const
+{
+ return m_stickScale;
+}
+
+void VirtualJoystickWidget::setStickScale(int stickScale)
+{
+ m_stickScale = stickScale;
+}
+
+void VirtualJoystickWidget::setWidgetValue(const RadioWidget::RadioWidgetType type, const int index, const int value)
+{
+ if (type == RadioWidget::RADIO_WIDGET_TRIM)
+ setTrimValue(index, value);
+ else if (type == RadioWidget::RADIO_WIDGET_STICK)
+ setStickAxisValue(index, value);
+}
+
int VirtualJoystickWidget::getTrimValue(int which)
{
- SliderWidget * slider = getTrimSlider(which);
- if (slider) {
- return slider->value();
+ RadioTrimWidget * trim = getTrimWidget(which);
+ if (trim) {
+ return trim->getValue();
}
return 0;
}
-void VirtualJoystickWidget::setStickConstraint(int which, bool active)
+void VirtualJoystickWidget::setStickIndices(int xIdx, int yIdx)
{
- if (btnHoldX == NULL)
+ m_xIndex = xIdx;
+ m_yIndex = yIdx;
+}
+
+void VirtualJoystickWidget::setStickConstraint(quint8 index, bool active)
+{
+ if (btnHoldX == NULL || !index)
return; // no buttons
- switch (which) {
- case HOLD_X:
- btnHoldX->setChecked(active);
- break;
- case HOLD_Y:
- btnHoldY->setChecked(active);
- break;
- case FIX_X:
- btnFixX->setChecked(active);
- break;
- case FIX_Y:
- btnFixY->setChecked(active);
- break;
- default:
- break;
- }
+ if (index & HOLD_X)
+ btnHoldX->setChecked(active);
+ if (index & HOLD_Y)
+ btnHoldY->setChecked(active);
+ if (index & FIX_X)
+ btnFixX->setChecked(active);
+ if (index & FIX_Y)
+ btnFixY->setChecked(active);
}
void VirtualJoystickWidget::setStickColor(const QColor & color)
@@ -227,6 +296,15 @@ void VirtualJoystickWidget::setStickColor(const QColor & color)
node->setColor(color);
}
+void VirtualJoystickWidget::loadDefaultsForMode(const unsigned mode)
+{
+ if (((mode & 1) && stickSide == 'L') || (!(mode & 1) && stickSide == 'R')) {
+ setStickConstraint(HOLD_Y, true);
+ setStickY(1.0);
+ onNodeYChanged();
+ }
+}
+
QSize VirtualJoystickWidget::sizeHint() const {
return prefSize;
}
@@ -237,6 +315,18 @@ void VirtualJoystickWidget::resizeEvent(QResizeEvent * event)
setSize(event->size(), event->oldSize());
}
+void VirtualJoystickWidget::onNodeXChanged()
+{
+ emit valueChange(RadioWidget::RADIO_WIDGET_STICK, m_xIndex, int(m_stickScale * getStickX()));
+ updateNodeValueLabels();
+}
+
+void VirtualJoystickWidget::onNodeYChanged()
+{
+ emit valueChange(RadioWidget::RADIO_WIDGET_STICK, m_yIndex, int(-m_stickScale * getStickY()));
+ updateNodeValueLabels();
+}
+
void VirtualJoystickWidget::setSize(const QSize & size, const QSize &)
{
float thisAspectRatio = (float)size.width() / size.height();
@@ -269,13 +359,15 @@ void VirtualJoystickWidget::setSize(const QSize & size, const QSize &)
layout->setColumnStretch(2, newGvSz);
layout->setRowStretch(1, newGvSz);
- //prefSize = QSize(newGvSz + extraSize.width(), newGvSz + extraSize.height());
gv->resize(newGvSz, newGvSz);
gv->updateGeometry();
+ int ballSize = (newGvSz * GBALL_SIZE * 0.005f);
+ ballSize = qMin(GBALL_SIZE_MX, qMax(ballSize, GBALL_SIZE_MN));
+
QRectF qr = (QRectF)gv->contentsRect();
- qreal w = qr.width() - GBALL_SIZE;
- qreal h = qr.height() - GBALL_SIZE;
+ qreal w = qr.width() - ballSize;
+ qreal h = qr.height() - ballSize;
qreal cx = qr.width() / 2;
qreal cy = qr.height() / 2;
qreal nodeX = node->getX();
@@ -283,120 +375,62 @@ void VirtualJoystickWidget::setSize(const QSize & size, const QSize &)
scene->setSceneRect(-cx,-cy,w,h);
+ node->setBallSize(ballSize);
node->setX(nodeX);
node->setY(nodeY);
//qDebug() << thisAspectRatio << size << newGvSz << spacerSz << extraSize << gv->geometry() << gv->contentsRect() << gv->frameRect() << getStickPos();
}
-QWidget *VirtualJoystickWidget::createTrimWidget(QChar type)
+RadioTrimWidget * VirtualJoystickWidget::createTrimWidget(QChar type)
{
- QSizePolicy sp;
- QString btnAlabel, btnBlabel;
+ RadioTrimWidget * trimWidget = new RadioTrimWidget(type == 'H' ? Qt::Horizontal : Qt::Vertical);
+ trimWidget->setIndices(getTrimSliderType(type), getTrimButtonType(type, 0), getTrimButtonType(type, 1));
- QString btnAname = QString("%1TrimBtnA_%2").arg(type.toLower()).arg(stickSide);
- QString btnBname = QString("%1TrimBtnB_%2").arg(type.toLower()).arg(stickSide);
- QString sliderName = QString("%1TrimAdj_%2").arg(type.toLower()).arg(stickSide);
-
- QWidget * trimWidget = new QWidget(this);
- QBoxLayout * trimLayout = new QVBoxLayout(trimWidget);
- SliderWidget * trimSlider = new SliderWidget(trimWidget);
- QPushButton * trimBtnA = new QPushButton(trimWidget);
- QPushButton * trimBtnB = new QPushButton(trimWidget);
-
- if (type == 'H') {
- sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- trimLayout->setDirection(QBoxLayout::LeftToRight);
- trimSlider->setFixedHeight(23);
- trimSlider->setOrientation(Qt::Horizontal);
- trimBtnA->setText(ARROW_LEFT);
- trimBtnB->setText(ARROW_RIGHT);
- }
- else {
- sp = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
- trimLayout->setDirection(QBoxLayout::TopToBottom);
- trimSlider->setFixedWidth(23);
- trimSlider->setOrientation(Qt::Vertical);
- trimBtnA->setText(ARROW_UP);
- trimBtnB->setText(ARROW_DOWN);
- }
-
- trimWidget->setSizePolicy(sp);
-
- trimSlider->setObjectName(sliderName);
- trimSlider->setProperty("trimType", getTrimSliderType(type));
- trimSlider->setSizePolicy(sp);
- trimSlider->setMinimum(-125);
- trimSlider->setMaximum(125);
-
- trimBtnA->setObjectName(btnAname);
- trimBtnA->setProperty("btnType", getTrimButtonType(type, 0));
- trimBtnA->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
- trimBtnA->setMaximumSize(QSize(23, 23));
- trimBtnA->setAutoDefault(false);
-
- trimBtnB->setObjectName(btnBname);
- trimBtnB->setProperty("btnType", getTrimButtonType(type, 1));
- trimBtnB->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
- trimBtnB->setMaximumSize(QSize(23, 23));
- trimBtnB->setAutoDefault(false);
-
- trimLayout->setSpacing(6);
- trimLayout->setContentsMargins(8, 9, 8, 9);
- trimLayout->addWidget(trimBtnA);
- trimLayout->addWidget(trimSlider);
- trimLayout->addWidget(trimBtnB);
-
- connect(trimBtnA, SIGNAL(pressed()), SLOT(onTrimPressed()));
- connect(trimBtnB, SIGNAL(pressed()), SLOT(onTrimPressed()));
- connect(trimBtnA, SIGNAL(released()), SIGNAL(trimButtonReleased()));
- connect(trimBtnB, SIGNAL(released()), SIGNAL(trimButtonReleased()));
- connect(trimSlider, SIGNAL(valueChanged(int)), SLOT(onSliderChange(int)));
+ connect(trimWidget, &RadioTrimWidget::valueChange, this, &VirtualJoystickWidget::valueChange);
return trimWidget;
}
-QPushButton * VirtualJoystickWidget::createButtonWidget(int type)
+QToolButton * VirtualJoystickWidget::createButtonWidget(int type)
{
- QString btnRole, btnLabel;
+ QString btnLabel, tooltip;
+ QIcon icon;
switch (type) {
case HOLD_Y:
- btnLabel = tr("Hold Y");
+ btnLabel = tr("Hld Y");
+ tooltip = tr("Hold Vertical stick position.");
+ icon = Simulator::SimulatorIcon("hold_y");
break;
case FIX_Y:
btnLabel = tr("Fix Y");
+ tooltip = tr("Prevent Vertical movement of stick.");
+ icon = Simulator::SimulatorIcon("fixed_y");
break;
case FIX_X:
btnLabel = tr("Fix X");
+ tooltip = tr("Prevent Horizontal movement of stick.");
+ icon = Simulator::SimulatorIcon("fixed_x");
break;
case HOLD_X:
- default:
- btnLabel = tr("Hold X");
+ btnLabel = tr("Hld X");
+ tooltip = tr("Hold Horizontal stick position.");
+ icon = Simulator::SimulatorIcon("hold_x");
break;
+ default:
+ return NULL;
}
- QPushButton * btn = new QPushButton(this);
- btn->setObjectName(QString("%1_%2").arg(btnLabel.replace(" ", "_")).arg(stickSide));
+ QToolButton * btn = new QToolButton(this);
btn->setProperty("btnType", type);
+ btn->setIcon(icon);
+ btn->setIconSize(QSize(20, 20));
+ btn->setToolButtonStyle(Qt::ToolButtonIconOnly);
btn->setText(btnLabel);
- QFont font;
- font.setPointSize(8);
- btn->setFont(font);
- btn->setStyleSheet(QLatin1String( \
- "QPushButton {"
- " background-color: #EEEEEE;"
- " border-style: outset;"
- " border-width: 1px;"
- " border-radius: 4px;"
- " border-color: black;"
- " padding: 2px;"
- "}"
- "QPushButton:checked {\n"
- " background-color: #4CC417;\n"
- " border-style: inset;\n"
- "}" ));
+ btn->setToolTip(tooltip);
btn->setCheckable(true);
+ btn->setAutoRaise(true);
- connect(btn, SIGNAL(toggled(bool)), SLOT(onButtonChange(bool)));
+ connect(btn, &QToolButton::toggled, this, &VirtualJoystickWidget::onButtonChange);
return btn;
}
@@ -421,78 +455,85 @@ QLayout *VirtualJoystickWidget::createNodeValueLayout(QChar type, QLabel *& valL
return layout;
}
-int VirtualJoystickWidget::getTrimSliderType(QChar type)
+int VirtualJoystickWidget::getStickIndex(QChar type)
{
+ using namespace Board;
+
if (stickSide == 'L') {
if (type == 'H')
- return TRIM_AXIS_L_X;
+ return STICK_AXIS_LH;
else
- return TRIM_AXIS_L_Y;
+ return STICK_AXIS_LV;
}
else {
if (type == 'H')
- return TRIM_AXIS_R_X;
+ return STICK_AXIS_RH;
else
- return TRIM_AXIS_R_Y;
+ return STICK_AXIS_RV;
+ }
+}
+
+int VirtualJoystickWidget::getTrimSliderType(QChar type)
+{
+ using namespace Board;
+
+ if (stickSide == 'L') {
+ if (type == 'H')
+ return TRIM_AXIS_LH;
+ else
+ return TRIM_AXIS_LV;
+ }
+ else {
+ if (type == 'H')
+ return TRIM_AXIS_RH;
+ else
+ return TRIM_AXIS_RV;
}
}
int VirtualJoystickWidget::getTrimButtonType(QChar type, int pos)
{
+ using namespace Board;
+
if (stickSide == 'L') {
if (type == 'H') {
if (pos == 0)
- return TRIM_LH_L;
+ return TRIM_SW_LH_DEC;
else
- return TRIM_LH_R;
+ return TRIM_SW_LH_INC;
}
else {
if (pos == 0)
- return TRIM_LV_UP;
+ return TRIM_SW_LV_DEC;
else
- return TRIM_LV_DN;
+ return TRIM_SW_LV_INC;
}
}
// right side
else {
if (type == 'H') {
if (pos == 0)
- return TRIM_RH_L;
+ return TRIM_SW_RH_DEC;
else
- return TRIM_RH_R;
+ return TRIM_SW_RH_INC;
}
else {
if (pos == 0)
- return TRIM_RV_UP;
+ return TRIM_SW_RV_DEC;
else
- return TRIM_RV_DN;
+ return TRIM_SW_RV_INC;
}
}
}
-SliderWidget *VirtualJoystickWidget::getTrimSlider(int which)
+RadioTrimWidget * VirtualJoystickWidget::getTrimWidget(int which)
{
- if (which == TRIM_AXIS_L_X || which == TRIM_AXIS_R_X)
- return hTrimSlider;
+ if ((stickSide == 'L' && which == Board::TRIM_AXIS_LH) || (stickSide == 'R' && which == Board::TRIM_AXIS_RH))
+ return hTrimWidget;
+ else if ((stickSide == 'L' && which == Board::TRIM_AXIS_LV) || (stickSide == 'R' && which == Board::TRIM_AXIS_RV))
+ return vTrimWidget;
else
- return vTrimSlider;
-}
-
-void VirtualJoystickWidget::onTrimPressed()
-{
- if (!sender() || !sender()->property("btnType").isValid())
- return;
-
- emit trimButtonPressed(sender()->property("btnType").toInt());
-}
-
-void VirtualJoystickWidget::onSliderChange(int value)
-{
- if (!sender() || !sender()->property("trimType").isValid())
- return;
-
- emit trimSliderMoved(sender()->property("trimType").toInt(), value);
- updateNodeValueLabels();
+ return NULL;
}
void VirtualJoystickWidget::onButtonChange(bool checked)
@@ -519,7 +560,61 @@ void VirtualJoystickWidget::onButtonChange(bool checked)
void VirtualJoystickWidget::updateNodeValueLabels()
{
if (nodeLabelX)
- nodeLabelX->setText(QString("%1").arg((qreal)node->getX() * 100 + getTrimValue(0) / 5, 2, 'f', 0));
+ nodeLabelX->setText(QString("%1").arg(node->getX() * 100.0f, 2, 'f', 0));
if (nodeLabelY)
- nodeLabelY->setText(QString("%1").arg((qreal)node->getY() * -100 + getTrimValue(1) / 5, 2, 'f', 0));
+ nodeLabelY->setText(QString("%1").arg(node->getY() * -100.0f, 2, 'f', 0));
+}
+
+void VirtualJoystickWidget::onGsMouseEvent(QGraphicsSceneMouseEvent * event)
+{
+ if (!node)
+ return;
+
+ //qDebug() << event->type() << event->scenePos() << event->buttons() << event->isAccepted() << m_stickPressed;
+ if (event->type() == QEvent::GraphicsSceneMouseRelease && m_stickPressed) {
+ node->setPressed(false);
+ m_stickPressed = false;
+ return;
+ }
+
+ if (!(event->buttons() & Qt::LeftButton))
+ return;
+
+ if (event->type() == QEvent::GraphicsSceneMousePress) {
+ node->setPressed(true);
+ m_stickPressed = true;
+ }
+ else if (!m_stickPressed || event->type() != QEvent::GraphicsSceneMouseMove) {
+ return;
+ }
+ node->setPos(event->scenePos());
+}
+
+
+/*
+ * CustomGraphicsScene
+*/
+
+void CustomGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * event)
+{
+ QGraphicsScene::mousePressEvent(event);
+ if (!event->isAccepted()) {
+ event->accept();
+ emit mouseEvent(event);
+ }
+}
+
+void CustomGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
+{
+ QGraphicsScene::mouseReleaseEvent(event);
+ emit mouseEvent(event);
+}
+
+void CustomGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
+{
+ QGraphicsScene::mouseMoveEvent(event);
+ if (!event->isAccepted() && (event->buttons() & Qt::LeftButton)) {
+ event->accept();
+ emit mouseEvent(event);
+ }
}
diff --git a/companion/src/simulation/widgets/virtualjoystickwidget.h b/companion/src/simulation/widgets/virtualjoystickwidget.h
index 478f6398e..5507d46e2 100644
--- a/companion/src/simulation/widgets/virtualjoystickwidget.h
+++ b/companion/src/simulation/widgets/virtualjoystickwidget.h
@@ -21,90 +21,123 @@
#ifndef VIRTUALJOYSTICKWIDGET_H
#define VIRTUALJOYSTICKWIDGET_H
+#include "radiowidget.h"
+
#include
#include
#include
#include
#include
#include
-#include
+#include
+#include
#include
+class CustomGraphicsScene;
class Node;
-class SliderWidget;
+class RadioTrimWidget;
class VirtualJoystickWidget : public QWidget
{
Q_OBJECT
public:
- enum TrimAxes {
- TRIM_AXIS_L_X = 0,
- TRIM_AXIS_L_Y,
- TRIM_AXIS_R_Y,
- TRIM_AXIS_R_X,
- };
-
enum ConstraintTypes {
- HOLD_X = 0,
- HOLD_Y,
- FIX_X,
- FIX_Y
+ HOLD_X = 0x01,
+ HOLD_Y = 0x02,
+ FIX_X = 0x04,
+ FIX_Y = 0x08
};
explicit VirtualJoystickWidget(QWidget * parent = NULL, QChar side = 'L', bool showTrims = true, bool showBtns = true, bool showValues = true, QSize size = QSize(125, 125));
- void setStickX(qreal x);
- void setStickY(qreal y);
- void setStickPos(QPointF xy);
- void centerStick();
qreal getStickX();
qreal getStickY();
QPointF getStickPos();
-
- void setTrimValue(int which, int value);
- void setTrimRange(int which, int min, int max);
int getTrimValue(int which);
-
- void setStickConstraint(int which, bool active);
- void setStickColor(const QColor & color);
-
virtual QSize sizeHint() const;
virtual void resizeEvent(QResizeEvent *event);
+ int getStickScale() const;
+ void setStickScale(int stickScale);
+
+ public slots:
+ void setStickX(qreal x);
+ void setStickY(qreal y);
+ void setStickPos(QPointF xy);
+ void setStickAxisValue(int index, int value);
+ void centerStick();
+ void setTrimsRange(int min, int max);
+ void setTrimsRange(int rng);
+ void setTrimRange(int index, int min, int max);
+ void setTrimValue(int index, int value);
+ void setWidgetValue(const RadioWidget::RadioWidgetType type, const int index, const int value);
+
+ void setStickIndices(int xIdx = -1, int yIdx = -1);
+ void setStickConstraint(quint8 index, bool active);
+ void setStickColor(const QColor & color);
+ void loadDefaultsForMode(const unsigned mode);
+
signals:
- void trimButtonPressed(int which);
- void trimButtonReleased();
- void trimSliderMoved(int which, int value);
+ void valueChange(const RadioWidget::RadioWidgetType type, const int index, int value);
protected slots:
- void onTrimPressed();
- void onSliderChange(int value);
+ void onNodeXChanged();
+ void onNodeYChanged();
void onButtonChange(bool checked);
void updateNodeValueLabels();
+ void onGsMouseEvent(QGraphicsSceneMouseEvent * event);
protected:
void setSize(const QSize & size, const QSize &);
- QWidget * createTrimWidget(QChar type);
- QPushButton * createButtonWidget(int type);
+ RadioTrimWidget * createTrimWidget(QChar type);
+ QToolButton * createButtonWidget(int type);
QLayout * createNodeValueLayout(QChar type, QLabel *& valLabel);
+ int getStickIndex(QChar type);
int getTrimSliderType(QChar type);
int getTrimButtonType(QChar type, int pos);
- SliderWidget * getTrimSlider(int which);
+ RadioTrimWidget * getTrimWidget(int which);
QChar stickSide;
QSize prefSize;
QGridLayout * layout;
QGraphicsView * gv;
- QGraphicsScene * scene;
+ CustomGraphicsScene * scene;
Node * node;
- SliderWidget * hTrimSlider, * vTrimSlider;
- QPushButton * btnHoldX, * btnHoldY;
- QPushButton * btnFixX, * btnFixY;
+ RadioTrimWidget * hTrimWidget;
+ RadioTrimWidget * vTrimWidget;
+ QToolButton * btnHoldX, * btnHoldY;
+ QToolButton * btnFixX, * btnFixY;
QLabel * nodeLabelX, * nodeLabelY;
QSize extraSize;
+ QTimer centerStickTimer;
float ar; // aspect ratio
+ int m_xIndex;
+ int m_yIndex;
+ int m_stickScale;
+ bool m_stickPressed;
+};
+
+/*
+ * Custom GraphicsScene for mouse handling
+*/
+class CustomGraphicsScene : public QGraphicsScene
+{
+ Q_OBJECT
+
+ public:
+ CustomGraphicsScene(QObject *parent = Q_NULLPTR) :
+ QGraphicsScene(parent)
+ {}
+
+ signals:
+ void mouseEvent(QGraphicsSceneMouseEvent * event);
+
+ protected:
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
};
#endif // VIRTUALJOYSTICKWIDGET_H
diff --git a/companion/src/simulator.cpp b/companion/src/simulator.cpp
index 3a767da7d..2f8d3f0f8 100644
--- a/companion/src/simulator.cpp
+++ b/companion/src/simulator.cpp
@@ -19,13 +19,10 @@
*/
#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include
#include
+#include
+#include
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
#include
#undef main
@@ -34,75 +31,227 @@
#include "appdata.h"
#include "appdebugmessagehandler.h"
#include "constants.h"
+#include "customdebug.h"
#include "eeprominterface.h"
#include "simulator.h"
#include "simulatormainwindow.h"
#include "simulatorstartupdialog.h"
#include "storage.h"
-#include "qxtcommandoptions.h"
+#include "translations.h"
#include "version.h"
using namespace Simulator;
int finish(int exitCode);
-void showMessage(const QString & message, enum QMessageBox::Icon icon = QMessageBox::NoIcon)
+void showMessage(const QString & message, enum QMessageBox::Icon icon = QMessageBox::NoIcon, bool useConsole = false)
{
+ if (useConsole) {
+ if (icon < QMessageBox::Warning)
+ QTextStream(stdout) << message << endl;
+ else
+ QTextStream(stderr) << message << endl;
+
+ return;
+ }
+ // use GUI
QMessageBox msgBox;
- msgBox.setText(message);
+ QString escMsg(message);
+ escMsg.replace("<", "<");
+ msgBox.setText("" + escMsg + " ");
msgBox.setIcon(icon);
msgBox.exec();
}
-void sharedHelpText(QTextStream &stream)
+const QString sharedHelpText()
{
+ QString ret;
+ QTextStream stream(&ret);
// list all available profiles
- stream << endl << QObject::tr("Available profiles:") << endl;
+ stream << endl << QApplication::translate("SimulatorMain", "Available profiles:") << endl;
QMapIterator pi(g.getActiveProfiles());
while (pi.hasNext()) {
pi.next();
- stream << "\t" << QObject::tr("ID: ") << pi.key() << QObject::tr(" Name: ") << pi.value() << endl;
+ stream << "\t" << QApplication::translate("SimulatorMain", "ID: ") << pi.key() << "; " << QApplication::translate("SimulatorMain", "Name: ") << pi.value() << endl;
}
// list all available radios
- stream << endl << QObject::tr("Available radios:") << endl;
- foreach(QString name, registered_simulators.keys()) {
+ stream << endl << QApplication::translate("SimulatorMain", "Available radios:") << endl;
+ foreach(QString name, SimulatorLoader::getAvailableSimulators()) {
stream << "\t" << name << endl;
}
+ return ret;
}
-QString findFirmwareId(int profileId)
+void showHelp(QCommandLineParser & parser, const QString & addMsg = QString(), int exitCode = 0) {
+ QString msg = "\n";
+ if (!addMsg.isEmpty())
+ msg.append(addMsg).append("\n\n");
+ msg.append(parser.helpText());
+ msg.append(sharedHelpText());
+ // display
+ showMessage(msg, (exitCode ? QMessageBox::Warning : QMessageBox::Information));
+}
+
+enum CommandLineParseResult
{
- SimulatorFactory * sf = getSimulatorFactory(g.profile[profileId].fwType());
- if (sf)
- return sf->name();
+ CommandLineNone,
+ CommandLineFound,
+ CommandLineExitOk,
+ CommandLineExitErr
+};
+
+CommandLineParseResult cliOptions(SimulatorOptions * simOptions, int * profileId)
+{
+ QCommandLineParser cliOptions;
+ bool cliOptsFound = false;
+ int pId = *profileId;
+
+ const QCommandLineOption optHelp = cliOptions.addHelpOption();
+ const QCommandLineOption optVer = cliOptions.addVersionOption();
+
+ const QCommandLineOption optProfi(QStringList() << "profile" << "p",
+ QApplication::translate("SimulatorMain", "Radio profile ID or Name to use for simulator."),
+ QApplication::translate("SimulatorMain", "profile"));
+
+ const QCommandLineOption optRadio(QStringList() << "radio" << "r",
+ QApplication::translate("SimulatorMain", "Radio type to simulate (usually defined in profile)."),
+ QApplication::translate("SimulatorMain", "radio"));
+
+ const QCommandLineOption optSdDir(QStringList() << "sd-path" << "s",
+ QApplication::translate("SimulatorMain", "Directory containing the SD card image to use. The default is configured in the chosen Radio Profile."),
+ QApplication::translate("SimulatorMain", "path"));
+
+ const QCommandLineOption optStart(QStringList() << "start-with" << "w",
+ QApplication::translate("SimulatorMain", "Data source type to use (applicable to Horus only). One of:") + " (file|folder|sd)",
+ QApplication::translate("SimulatorMain", "type"));
+
+ cliOptions.addPositionalArgument(QApplication::translate("SimulatorMain", "data-source"),
+ QApplication::translate("SimulatorMain", "Radio data (.bin/.eeprom/.otx) image file to use OR data folder path (for Horus-style radios).\n"
+ "NOTE: any existing EEPROM data incompatible with the selected radio type may be overwritten!"),
+ QApplication::translate("SimulatorMain", "[data-source]"));
+
+ cliOptions.addOption(optProfi);
+ cliOptions.addOption(optRadio);
+ cliOptions.addOption(optSdDir);
+ cliOptions.addOption(optStart);
+
+ QStringList args = QCoreApplication::arguments();
+#ifdef Q_OS_WIN
+ // For backwards compat. with QxtCommandOptions, convert Windows-style CLI switches (/opt) since QCommandLineParser doesn't support them
+ for (int i=0; i < args.size(); ++i) {
+ args[i].replace(QRegExp("^/([^\\s]{2,10})$"), "--\\1"); // long opts
+ args[i].replace(QRegExp("^/([^\\s]){1}$"), "-\\1"); // short opts
+ }
+#endif
+
+ if (!cliOptions.parse(args)) {
+ showHelp(cliOptions, cliOptions.errorText());
+ return CommandLineExitErr;
+ }
+
+ if (cliOptions.isSet(optHelp)) {
+ showHelp(cliOptions);
+ return CommandLineExitOk;
+ }
+
+ if (cliOptions.isSet(optVer)) {
+ showMessage(APP_SIMULATOR " v" VERSION " " __DATE__, QMessageBox::Information);
+ return CommandLineExitOk;
+ }
+
+ if (cliOptions.isSet(optProfi)) {
+ bool chk;
+ pId = cliOptions.value(optProfi).toInt(&chk);
+ if (!chk)
+ pId = g.getActiveProfiles().key(cliOptions.value(optProfi), -1);
+
+ if (!g.getActiveProfiles().contains(pId)) {
+ showHelp(cliOptions, QApplication::translate("SimulatorMain", "Error: Profile ID %1 was not found.").arg(pId));
+ return CommandLineExitErr;
+ }
+
+ *simOptions = g.profile[pId].simulatorOptions();
+ cliOptsFound = true;
+ }
+
+ if (cliOptions.isSet(optRadio)) {
+ simOptions->firmwareId = cliOptions.value(optRadio);
+ cliOptsFound = true;
+ }
+
+ if (cliOptsFound || (simOptions->dataFile.isEmpty() && !simOptions->firmwareId.isEmpty())) {
+ // this constructs a new default radio data file name in the user-configured eeprom directory
+ simOptions->dataFile = SimulatorStartupDialog::radioEepromFileName(simOptions->firmwareId, g.eepromDir());
+ }
+
+ if (cliOptions.isSet(optSdDir)) {
+ simOptions->sdPath = cliOptions.value(optSdDir);
+ cliOptsFound = true;
+ }
+
+ if (cliOptions.positionalArguments().size()) {
+ QString datasrc = cliOptions.positionalArguments().at(0);
+ if (datasrc.contains(QRegExp(".*\\.[\\w]{2,6}$"))) {
+ simOptions->dataFile = datasrc;
+ simOptions->startupDataType = SimulatorOptions::START_WITH_FILE;
+ }
+ else {
+ simOptions->dataFolder = datasrc;
+ simOptions->startupDataType = SimulatorOptions::START_WITH_FOLDER;
+ }
+ cliOptsFound = true;
+ }
+
+ if (cliOptions.isSet(optStart)) {
+ QString stTyp = cliOptions.value(optStart);
+ if (stTyp == "file") {
+ simOptions->startupDataType = SimulatorOptions::START_WITH_FILE;
+ }
+ else if (stTyp == "folder") {
+ simOptions->startupDataType = SimulatorOptions::START_WITH_FOLDER;
+ }
+ else if (stTyp == "sd") {
+ simOptions->startupDataType = SimulatorOptions::START_WITH_SDPATH;
+ }
+ else {
+ showHelp(cliOptions, QApplication::translate("SimulatorMain", "Unrecognized startup data source type: %1").arg(stTyp));
+ return CommandLineExitErr;
+ }
+
+ cliOptsFound = true;
+ }
+
+ *profileId = pId;
+ if (cliOptsFound)
+ return CommandLineFound;
else
- return QString();
+ return CommandLineNone;
}
int main(int argc, char *argv[])
{
- Q_INIT_RESOURCE(companion);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
+ /* From doc: This attribute must be set before Q(Gui)Application is constructed. */
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
app.setApplicationName(APP_SIMULATOR);
+ app.setApplicationVersion(VERSION);
app.setOrganizationName(COMPANY);
app.setOrganizationDomain(COMPANY_DOMAIN);
+ Q_INIT_RESOURCE(companion);
+
if (AppDebugMessageHandler::instance())
AppDebugMessageHandler::instance()->installAppMessageHandler();
- g.init();
+ CustomDebug::setFilterRules();
- QTranslator companionTranslator;
- companionTranslator.load(":/companion_" + g.locale());
- QTranslator qtTranslator;
- qtTranslator.load((QString)"qt_" + g.locale().left(2), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
- app.installTranslator(&companionTranslator);
- app.installTranslator(&qtTranslator);
+ g.init(); // init settings before installing translations
+
+ Translations::installTranslators();
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
uint32_t sdlFlags = 0;
@@ -113,154 +262,108 @@ int main(int argc, char *argv[])
sdlFlags |= SDL_INIT_AUDIO;
#endif
if (SDL_Init(sdlFlags) < 0) {
- showMessage(QObject::tr("WARNING: couldn't initialize SDL:\n%1").arg(SDL_GetError()), QMessageBox::Warning);
+ showMessage(QApplication::translate("SimulatorMain", "WARNING: couldn't initialize SDL:\n%1").arg(SDL_GetError()), QMessageBox::Warning);
}
#endif
- QxtCommandOptions cliOptions;
- bool cliOptsFound = false;
- int profileId = (g.simuLastProfId() > -1 ? g.simuLastProfId() : g.id());
- SimulatorOptions simOptions = g.profile[profileId].simulatorOptions();
-
registerStorageFactories();
registerOpenTxFirmwares();
- registerSimulators();
+ SimulatorLoader::registerSimulators();
- if (!registered_simulators.size()) {
- showMessage(QObject::tr("ERROR: No simulator libraries available."), QMessageBox::Critical);
+ if (!SimulatorLoader::getAvailableSimulators().size()) {
+ showMessage(QApplication::translate("SimulatorMain", "ERROR: No simulator libraries available."), QMessageBox::Critical);
return finish(3);
}
- cliOptions.add("profile", QObject::tr("Radio profile ID or Name to use for simulator."), QxtCommandOptions::ValueRequired);
- cliOptions.alias("profile", "p");
- cliOptions.add("radio", QObject::tr("Radio type to simulate (usually defined in profile)."), QxtCommandOptions::ValueRequired);
- cliOptions.alias("radio", "r");
- cliOptions.add("help", QObject::tr("show this help text"));
- cliOptions.alias("help", "h");
- cliOptions.parse(QCoreApplication::arguments());
- if (cliOptions.count("help") || cliOptions.showUnrecognizedWarning()) {
- QString msg;
- QTextStream stream(&msg);
- stream << QObject::tr("Usage: simulator [OPTION]... [EEPROM.BIN FILE OR DATA FOLDER] ") << endl << endl;
- stream << QObject::tr("Options:") << endl;
- cliOptions.showUsage(false, stream);
- sharedHelpText(stream);
- // display
- showMessage(msg, QMessageBox::Information);
- return finish(1);
- }
+ int profileId = (g.simuLastProfId() > -1 ? g.simuLastProfId() : g.id());
+ SimulatorOptions simOptions = g.profile[profileId].simulatorOptions();
// TODO : defaults should be set in Profile::init()
if (simOptions.firmwareId.isEmpty())
- simOptions.firmwareId = findFirmwareId(profileId);
+ simOptions.firmwareId = SimulatorLoader::findSimulatorByFirmwareName(g.profile[profileId].fwType());
if (simOptions.dataFolder.isEmpty())
simOptions.dataFolder = g.eepromDir();
if (simOptions.sdPath.isEmpty())
simOptions.sdPath = g.profile[profileId].sdPath();
- if (cliOptions.count("profile") == 1) {
- bool chk;
- int pid = cliOptions.value("profile").toInt(&chk);
- if (chk)
- profileId = pid;
- else
- profileId = g.getActiveProfiles().key(cliOptions.value("profile").toString(), -1);
+ // Handle startup options
- if (!g.getActiveProfiles().contains(profileId)) {
- fprintf(stderr, "Error: Profile ID %d was not found.", profileId);
- return finish(1);
- }
+ // check for command-line options
+ CommandLineParseResult cliResult = cliOptions(&simOptions, &profileId);
- simOptions = g.profile[profileId].simulatorOptions();
- cliOptsFound = true;
- }
+ if (cliResult == CommandLineExitOk)
+ return finish(0);
+ if (cliResult == CommandLineExitErr)
+ return finish(1);
- if (cliOptions.count("radio") == 1) {
- simOptions.firmwareId = cliOptions.value("radio").toString();
- cliOptsFound = true;
- }
-
- if (cliOptsFound || (simOptions.dataFile.isEmpty() && !simOptions.firmwareId.isEmpty()))
- simOptions.dataFile = SimulatorStartupDialog::radioEepromFileName(simOptions.firmwareId, g.eepromDir());
-
- if (!cliOptions.positional().isEmpty()) {
- if (QString(cliOptions.positional().at(0)).contains(QRegExp(".*\\.[\\w]{2,6}$"))) {
- simOptions.dataFile = cliOptions.positional()[0];
- simOptions.startupDataType = SimulatorOptions::START_WITH_FILE;
- }
- else {
- simOptions.dataFolder = cliOptions.positional()[0];
- simOptions.startupDataType = SimulatorOptions::START_WITH_FOLDER;
- }
- cliOptsFound = true;
- }
-
- if (!cliOptsFound || profileId == -1 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
+ // Present GUI startup options dialog if necessary
+ if (cliResult == CommandLineNone || profileId == -1 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
SimulatorStartupDialog * dlg = new SimulatorStartupDialog(&simOptions, &profileId);
int ret = dlg->exec();
- dlg->deleteLater();
+ delete dlg;
if (ret != QDialog::Accepted) {
return finish(0);
}
}
- qDebug() << "profileId=" << profileId << simOptions;
+ qDebug() << "Starting with options: profileId=" << profileId << simOptions;
+ // Validate startup options
+
+ QString resultMsg;
if (profileId < 0 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
- showMessage(QObject::tr("ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\n Profile ID: [%1]; Radio ID: [%2];\nData File: [%3]")
- .arg(profileId).arg(simOptions.firmwareId, simOptions.dataFile), QMessageBox::Critical);
+ resultMsg = QApplication::translate("SimulatorMain", "ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\n Profile ID: [%1]; Radio ID: [%2];\nData File: [%3]");
+ showMessage(resultMsg.arg(profileId).arg(simOptions.firmwareId, simOptions.dataFile), QMessageBox::Critical);
return finish(1);
}
- if (!g.getActiveProfiles().contains(profileId) || !registered_simulators.keys().contains(simOptions.firmwareId)) {
- QString msg;
- QTextStream stream(&msg);
- stream << QObject::tr("ERROR: Radio profile or simulator firmware not found.\nProfile ID: [%1]; Radio ID: [%2]")
- .arg(profileId).arg(simOptions.firmwareId);
- sharedHelpText(stream);
- showMessage(msg, QMessageBox::Critical);
- return finish(2);
+ if (!g.getActiveProfiles().contains(profileId) || !SimulatorLoader::getAvailableSimulators().contains(simOptions.firmwareId)) {
+ QTextStream stream(&resultMsg);
+ stream << QApplication::translate("SimulatorMain", "ERROR: Radio profile or simulator firmware not found.\nProfile ID: [%1]; Radio ID: [%2]").arg(profileId).arg(simOptions.firmwareId);
+ stream << sharedHelpText();
+ showMessage(resultMsg, QMessageBox::Critical);
+ return finish(1);
}
- SimulatorFactory * factory = getSimulatorFactory(simOptions.firmwareId);
- if (!factory) {
- showMessage(QObject::tr("ERROR: Simulator %1 not found").arg(simOptions.firmwareId), QMessageBox::Critical);
- return finish(2);
- }
- SimulatorInterface * simulator = factory->create();
- if (!simulator) {
- showMessage(QObject::tr("ERROR: Failed to create simulator interface, possibly missing or bad library."), QMessageBox::Critical);
- return finish(2);
- }
-
- current_firmware_variant = getFirmware(simOptions.firmwareId);
+ // All checks passed, save profile ID and start simulator
g.sessionId(profileId);
g.simuLastProfId(profileId);
- int result = 1;
- SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simulator, SIMULATOR_FLAGS_STANDALONE);
- if (mainWindow->setOptions(simOptions, true)) {
- mainWindow->start();
+ // Set global firmware environment
+ Firmware::setCurrentVariant(Firmware::getFirmwareForId(simOptions.firmwareId));
+
+ int result = 0;
+ SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simOptions.firmwareId, SIMULATOR_FLAGS_STANDALONE);
+ if ((result = mainWindow->getExitStatus(&resultMsg))) {
+ if (resultMsg.isEmpty())
+ resultMsg = QApplication::translate("SimulatorMain", "Uknown error during Simulator startup.");
+ showMessage(resultMsg, QMessageBox::Critical);
+ }
+ else if (mainWindow->setOptions(simOptions, true)) {
mainWindow->show();
result = app.exec();
+ if (!result) {
+ if ((result = mainWindow->getExitStatus(&resultMsg)) && !resultMsg.isEmpty())
+ qWarning() << "Exit message from SimulatorMainWindow:" << resultMsg;
+ }
}
else {
result = 3;
}
- delete mainWindow;
- delete simulator;
+ delete mainWindow;
return finish(result);
}
int finish(int exitCode)
{
- qDebug() << "SIMULATOR EXIT" << exitCode;
- unregisterSimulators();
+ SimulatorLoader::unregisterSimulators();
unregisterOpenTxFirmwares();
+ unregisterStorageFactories();
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
SDL_Quit();
#endif
+ qDebug() << "SIMULATOR EXIT" << exitCode;
return exitCode;
}
diff --git a/companion/src/storage/CMakeLists.txt b/companion/src/storage/CMakeLists.txt
index 76f940881..5b1aefb20 100644
--- a/companion/src/storage/CMakeLists.txt
+++ b/companion/src/storage/CMakeLists.txt
@@ -27,4 +27,5 @@ foreach(name ${storage_NAMES})
endforeach()
add_library(storage ${storage_SRCS})
-target_link_libraries(storage Qt5::Core Qt5::Gui Qt5::Xml Qt5::Widgets)
\ No newline at end of file
+qt5_use_modules(storage Core Xml Widgets)
+target_link_libraries(storage PRIVATE ${CPN_COMMON_LIB})
diff --git a/companion/src/storage/appdata.cpp b/companion/src/storage/appdata.cpp
index 0c9ae6dfe..e6feb194c 100644
--- a/companion/src/storage/appdata.cpp
+++ b/companion/src/storage/appdata.cpp
@@ -434,6 +434,9 @@ QStringList AppData::simuDbgFilters() { return _simuDbgFilters; }
QByteArray AppData::mainWinGeo() { return _mainWinGeo; }
QByteArray AppData::mainWinState() { return _mainWinState; }
QByteArray AppData::modelEditGeo() { return _modelEditGeo; }
+QByteArray AppData::mdiWinGeo() { return _mdiWinGeo; }
+QByteArray AppData::mdiWinState() { return _mdiWinState; }
+QByteArray AppData::compareWinGeo(){ return _compareWinGeo; }
QString AppData::armMcu() { return _armMcu; }
QString AppData::avrArguments() { return _avrArguments; }
@@ -464,8 +467,10 @@ bool AppData::snapToClpbrd() { return _snapToClpbrd; }
bool AppData::autoCheckApp() { return _autoCheckApp; }
bool AppData::autoCheckFw() { return _autoCheckFw; }
bool AppData::simuSW() { return _simuSW; }
-bool AppData::useWizard() { return _useWizard; }
+bool AppData::tabbedMdi() { return _tabbedMdi; }
+bool AppData::removeModelSlots() { return _remvModelSlots; }
+int AppData::newModelAction() { return _newModelAction; }
int AppData::backLight() { return _backLight; }
int AppData::embedSplashes() { return _embedSplashes; }
int AppData::fwServerFails() { return _fwServerFails; }
@@ -486,6 +491,9 @@ void AppData::simuDbgFilters (const QStringList x) { store(x, _simuDbgFilters,
void AppData::mainWinGeo (const QByteArray x) { store(x, _mainWinGeo, "mainWindowGeometry" );}
void AppData::mainWinState (const QByteArray x) { store(x, _mainWinState, "mainWindowState" );}
void AppData::modelEditGeo (const QByteArray x) { store(x, _modelEditGeo, "modelEditGeometry" );}
+void AppData::mdiWinGeo (const QByteArray x) { store(x, _mdiWinGeo, "mdiWinGeo" );}
+void AppData::mdiWinState (const QByteArray x) { store(x, _mdiWinState, "mdiWinState" );}
+void AppData::compareWinGeo (const QByteArray x) { store(x, _compareWinGeo, "compareWinGeo" );}
void AppData::armMcu (const QString x) { store(x, _armMcu, "arm_mcu" );}
void AppData::avrArguments (const QString x) { store(x, _avrArguments, "avr_arguments" );}
@@ -516,8 +524,10 @@ void AppData::snapToClpbrd (const bool x) { store(x, _snapToClpbrd,
void AppData::autoCheckApp (const bool x) { store(x, _autoCheckApp, "startup_check_companion" );}
void AppData::autoCheckFw (const bool x) { store(x, _autoCheckFw, "startup_check_fw" );}
void AppData::simuSW (const bool x) { store(x, _simuSW, "simuSW" );}
-void AppData::useWizard (const bool x) { store(x, _useWizard, "useWizard" );}
+void AppData::tabbedMdi (const bool x) { store(x, _tabbedMdi, "tabbedMdi" );}
+void AppData::removeModelSlots(const bool x) { store(x, _remvModelSlots, "removeModelSlots" );}
+void AppData::newModelAction (const int x) { store(x, _newModelAction, "newModelAction" );}
void AppData::backLight (const int x) { store(x, _backLight, "backLight" );}
void AppData::embedSplashes (const int x) { store(x, _embedSplashes, "embedded_splashes" );}
void AppData::fwServerFails (const int x) { store(x, _fwServerFails, "fwserver" );}
@@ -569,6 +579,9 @@ void AppData::init()
getset( _mainWinGeo, "mainWindowGeometry" ,"" );
getset( _mainWinState, "mainWindowState" ,"" );
getset( _modelEditGeo, "modelEditGeometry" ,"" );
+ getset( _mdiWinGeo, "mdiWinGeo" ,"" );
+ getset( _mdiWinState, "mdiWinState" ,"" );
+ getset( _compareWinGeo, "compareWinGeo" ,"" );
getset( _armMcu, "arm_mcu" ,"at91sam3s4-9x" );
getset( _avrArguments, "avr_arguments" ,"" );
@@ -607,8 +620,10 @@ void AppData::init()
getset( _autoCheckApp, "startup_check_companion" ,true );
getset( _autoCheckFw, "startup_check_fw" ,true );
getset( _simuSW, "simuSW" ,false );
- getset( _useWizard, "useWizard" ,true );
+ getset( _tabbedMdi, "tabbedMdi" ,false );
+ getset( _remvModelSlots, "removeModelSlots" ,true );
+ getset( _newModelAction, "newModelAction" ,1 );
getset( _backLight, "backLight" ,0 );
getset( _embedSplashes, "embedded_splashes" ,0 );
getset( _fwServerFails, "fwserver" ,0 );
@@ -636,7 +651,7 @@ QMap AppData::getActiveProfiles()
bool AppData::importSettings(QSettings & toSettings)
{
- QSettings * fromSettings;
+ QSettings * fromSettings = NULL;
QSettings settings21("OpenTX", "Companion 2.1");
QSettings settings20("OpenTX", "Companion 2.0");
@@ -651,8 +666,6 @@ bool AppData::importSettings(QSettings & toSettings)
fromSettings = &settings16;
else if (settings9x.contains("default_mode"))
fromSettings = &settings9x;
- else
- return false;
// do not copy these settings
QStringList excludeKeys = QStringList() << "compilation-server";
@@ -664,17 +677,19 @@ bool AppData::importSettings(QSettings & toSettings)
#endif
// import settings
- foreach (const QString & key, fromSettings->allKeys()) {
- if (fromSettings->value(key).isValid() && !excludeKeys.contains(key)) {
- toSettings.setValue(key, fromSettings->value(key));
+ if (fromSettings) {
+ foreach (const QString & key, fromSettings->allKeys()) {
+ if (fromSettings->value(key).isValid() && !excludeKeys.contains(key)) {
+ toSettings.setValue(key, fromSettings->value(key));
+ }
}
}
// Additional adjustments for companion9x settings
- if (fromSettings->applicationName() == "companion9x") {
+ if (fromSettings && fromSettings->applicationName() == "companion9x") {
// Store old values in new locations
autoCheckApp(toSettings.value("startup_check_companion9x", true).toBool());
- useWizard(toSettings.value("wizardEnable", true).toBool());
+ toSettings.setValue("useWizard", toSettings.value("wizardEnable", true));
// Convert and store the firmware type
QString fwType = toSettings.value("firmware", "").toString();
@@ -717,5 +732,14 @@ bool AppData::importSettings(QSettings & toSettings)
id( 0 );
}
- return true;
+ // convert old settings to new
+
+ if (toSettings.contains("useWizard")) {
+ if (!toSettings.contains("newModelAction")) {
+ newModelAction(toSettings.value("useWizard").toBool() ? 1 : 2);
+ }
+ toSettings.remove("useWizard");
+ }
+
+ return fromSettings ? true : false;
}
diff --git a/companion/src/storage/appdata.h b/companion/src/storage/appdata.h
index f7d3d0cd4..2f85e50e8 100644
--- a/companion/src/storage/appdata.h
+++ b/companion/src/storage/appdata.h
@@ -255,6 +255,9 @@ class AppData: protected CompStoreObj
QByteArray _mainWinGeo;
QByteArray _mainWinState;
QByteArray _modelEditGeo;
+ QByteArray _mdiWinGeo;
+ QByteArray _mdiWinState;
+ QByteArray _compareWinGeo;
QString _armMcu;
QString _avrArguments;
@@ -285,8 +288,10 @@ class AppData: protected CompStoreObj
bool _autoCheckApp;
bool _autoCheckFw;
bool _simuSW;
- bool _useWizard;
+ bool _tabbedMdi;
+ bool _remvModelSlots;
+ int _newModelAction; // 0=no action; 1=model wizard; 2=model edit
int _backLight;
int _embedSplashes;
int _fwServerFails;
@@ -309,6 +314,9 @@ class AppData: protected CompStoreObj
QByteArray mainWinGeo();
QByteArray mainWinState();
QByteArray modelEditGeo();
+ QByteArray mdiWinGeo();
+ QByteArray mdiWinState();
+ QByteArray compareWinGeo();
QString armMcu();
QString avrArguments();
@@ -340,8 +348,10 @@ class AppData: protected CompStoreObj
bool autoCheckApp();
bool autoCheckFw();
bool simuSW();
- bool useWizard();
+ bool tabbedMdi();
+ bool removeModelSlots();
+ int newModelAction();
int backLight();
int embedSplashes();
int fwServerFails();
@@ -362,6 +372,9 @@ class AppData: protected CompStoreObj
void mainWinGeo (const QByteArray);
void mainWinState (const QByteArray);
void modelEditGeo (const QByteArray);
+ void mdiWinGeo (const QByteArray);
+ void mdiWinState (const QByteArray);
+ void compareWinGeo (const QByteArray);
void armMcu (const QString);
void avrArguments (const QString);
@@ -393,8 +406,10 @@ class AppData: protected CompStoreObj
void autoCheckApp (const bool);
void autoCheckFw (const bool);
void simuSW (const bool);
- void useWizard (const bool);
+ void tabbedMdi (const bool);
+ void removeModelSlots(const bool);
+ void newModelAction (const int);
void backLight (const int);
void embedSplashes (const int);
void fwServerFails (const int);
diff --git a/companion/src/storage/bineeprom.cpp b/companion/src/storage/bineeprom.cpp
index ffbebdcab..c27d5681c 100644
--- a/companion/src/storage/bineeprom.cpp
+++ b/companion/src/storage/bineeprom.cpp
@@ -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;
}
diff --git a/companion/src/storage/eepe.cpp b/companion/src/storage/eepe.cpp
index a1e399d61..b7c7f218c 100644
--- a/companion/src/storage/eepe.cpp
+++ b/companion/src/storage/eepe.cpp
@@ -31,23 +31,23 @@ bool EepeFormat::load(RadioData & radioData)
setError(QObject::tr("Unable to open %1: %2").arg(filename).arg(file.errorString()));
return false;
}
-
+
QTextStream inputStream(&file);
QString hline = inputStream.readLine();
if (hline != EEPE_EEPROM_FILE_HEADER) {
qDebug() << qPrintable("[eepe] No EEPE header");
return false;
}
-
+
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;
}
eeprom.resize(eeprom_size);
-
+
return extract(radioData, eeprom);
}
diff --git a/companion/src/storage/firmwareinterface.cpp b/companion/src/storage/firmwareinterface.cpp
index 0e0b222e2..369af6504 100644
--- a/companion/src/storage/firmwareinterface.cpp
+++ b/companion/src/storage/firmwareinterface.cpp
@@ -24,11 +24,14 @@
#include "helpers.h"
#include "storage.h"
+#include
+
#define FW_MARK "FW"
#define VERS_MARK "VERS"
#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),
diff --git a/companion/src/storage/hexeeprom.cpp b/companion/src/storage/hexeeprom.cpp
index e49230be9..a0ecc33ae 100644
--- a/companion/src/storage/hexeeprom.cpp
+++ b/companion/src/storage/hexeeprom.cpp
@@ -31,17 +31,16 @@ bool HexEepromFormat::load(RadioData & radioData)
qDebug() << "Unable to open" << filename << file.errorString();
return false;
}
-
+
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;
}
eeprom.resize(eeprom_size);
-
+
return extract(radioData, eeprom);
}
@@ -52,12 +51,12 @@ bool HexEepromFormat::writeToFile(const uint8_t * eeprom, uint32_t size)
setError(QObject::tr("Cannot open file %1:\n%2.").arg(filename).arg(file.errorString()));
return false;
}
-
+
QTextStream outputStream(&file);
if (!HexInterface(outputStream).save(eeprom, size)) {
setError(QObject::tr("Error writing file %1:\n%2.").arg(filename).arg(file.errorString()));
return false;
}
-
+
return true;
}
diff --git a/companion/src/storage/rlefile.cpp b/companion/src/storage/rlefile.cpp
index c19723d2a..82cbf5bbf 100644
--- a/companion/src/storage/rlefile.cpp
+++ b/companion/src/storage/rlefile.cpp
@@ -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 {
@@ -406,7 +406,7 @@ unsigned int RleFile::readRlc12(uint8_t *buf, unsigned int i_len, bool rlc2)
qDebug() << "RLC decoding error!";
return 0;
}
-
+
if (rlc2) {
if(m_bRlc&0x80){ // if contains high byte
m_zeroes =(m_bRlc>>4) & 0x7;
diff --git a/companion/src/storage/storage.cpp b/companion/src/storage/storage.cpp
index 936af71c5..cd9b5bac6 100644
--- a/companion/src/storage/storage.cpp
+++ b/companion/src/storage/storage.cpp
@@ -64,6 +64,12 @@ void registerStorageFactories()
registerStorageFactory(new SdcardStorageFactory());
}
+void unregisterStorageFactories()
+{
+ foreach (StorageFactory * factory, registeredStorageFactories)
+ delete factory;
+}
+
bool Storage::load(RadioData & radioData)
{
QFile file(filename);
@@ -71,30 +77,37 @@ bool Storage::load(RadioData & radioData)
setError(QObject::tr("Unable to find file %1!").arg(filename));
return false;
}
-
+
+ bool ret = false;
foreach(StorageFactory * factory, registeredStorageFactories) {
StorageFormat * format = factory->instance(filename);
if (format->load(radioData)) {
board = format->getBoard();
setWarning(format->warning());
- return true;
+ ret = true;
+ break;
}
else {
setError(format->error());
}
+ delete format;
}
- return false;
+ return ret;
}
bool Storage::write(const RadioData & radioData)
{
+ bool ret = false;
foreach(StorageFactory * factory, registeredStorageFactories) {
if (factory->probe(filename)) {
- return factory->instance(filename)->write(radioData);
+ StorageFormat * format = factory->instance(filename);
+ ret = format->write(radioData);
+ delete format;
+ break;
}
}
- return false;
+ return ret;
}
bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEprom, const QString & firmwareFilename)
@@ -102,26 +115,26 @@ bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEpr
FirmwareInterface firmware(firmwareFilename);
if (!firmware.isValid())
return false;
-
+
uint8_t version = firmware.getEEpromVersion();
unsigned int variant = firmware.getEEpromVariant();
-
+
QSharedPointer radioData = QSharedPointer(new RadioData());
Storage storage(sourceEEprom);
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;
}
-
+
QFile destinationFile(destinationEEprom);
if (!destinationFile.open(QIODevice::WriteOnly)) {
return false;
}
-
+
int result = destinationFile.write(eeprom.constData(), size);
destinationFile.close();
return (result == size);
@@ -131,7 +144,7 @@ bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEpr
unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int index)
{
std::bitset errors;
-
+
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
std::bitset result((unsigned long long)eepromInterface->loadBackup(radioData, eeprom, size, index));
if (result.test(ALL_OK)) {
@@ -141,7 +154,7 @@ unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int
errors |= result;
}
}
-
+
if (errors.none()) {
errors.set(UNKNOWN_ERROR);
}
@@ -152,7 +165,7 @@ unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int
unsigned long LoadEepromXml(RadioData & radioData, QDomDocument & doc)
{
std::bitset errors;
-
+
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
std::bitset result((unsigned long long)eepromInterface->loadxml(radioData, doc));
if (result.test(ALL_OK)) {
@@ -162,7 +175,7 @@ unsigned long LoadEepromXml(RadioData & radioData, QDomDocument & doc)
errors |= result;
}
}
-
+
if (errors.none()) {
errors.set(UNKNOWN_ERROR);
}
diff --git a/companion/src/storage/storage.h b/companion/src/storage/storage.h
index eaaa0d8f0..aa288451f 100644
--- a/companion/src/storage/storage.h
+++ b/companion/src/storage/storage.h
@@ -48,14 +48,14 @@ class StorageFormat
board(Board::BOARD_UNKNOWN)
{
}
-
+ virtual ~StorageFormat() {}
virtual bool load(RadioData & radioData) = 0;
virtual bool write(const RadioData & radioData) = 0;
QString error() {
return _error;
}
-
+
QString warning() {
return _warning;
}
@@ -67,15 +67,38 @@ class StorageFormat
return board;
}
+ static uint32_t getFourCC(Board::Type board)
+ {
+ switch (board) {
+ case Board::BOARD_X12S:
+ case Board::BOARD_X10:
+ return 0x3478746F;
+ case Board::BOARD_TARANIS_X7:
+ return 0x3678746F;
+ case Board::BOARD_TARANIS_X9E:
+ return 0x3578746F;
+ case Board::BOARD_TARANIS_X9D:
+ case Board::BOARD_TARANIS_X9DP:
+ return 0x3378746F;
+ case Board::BOARD_SKY9X:
+ case Board::BOARD_AR9X:
+ return 0x3278746F;
+ case Board::BOARD_MEGA2560:
+ case Board::BOARD_GRUVIN9X:
+ return 0x3178746F;
+ default:
+ return 0;
+ }
+ }
+
+ uint32_t getFourCC()
+ {
+ return getFourCC(board);
+ }
+
virtual bool isBoardCompatible(Board::Type board)
{
- if (this->board == board)
- return true;
-
- if (IS_TARANIS_X9D(this->board) && IS_TARANIS_X9D(board))
- return true;
-
- return false;
+ return getFourCC() == getFourCC(board);
}
protected:
@@ -84,13 +107,13 @@ class StorageFormat
qDebug() << qPrintable(QString("[%1] error: %2").arg(name()).arg(error));
_error = error;
}
-
+
void setWarning(const QString & warning)
{
qDebug() << qPrintable(QString("[%1] warning: %2").arg(name()).arg(warning));
_warning = warning;
}
-
+
QString filename;
uint8_t version;
QString _error;
@@ -104,6 +127,7 @@ class StorageFactory
StorageFactory()
{
}
+ virtual ~StorageFactory() {}
virtual QString name() = 0;
virtual bool probe(const QString & filename) = 0;
virtual StorageFormat * instance(const QString & filename) = 0;
@@ -118,22 +142,22 @@ class DefaultStorageFactory : public StorageFactory
_name(name)
{
}
-
+
virtual QString name()
{
return _name;
}
-
+
virtual bool probe(const QString & filename)
{
return filename.toLower().endsWith("." + _name);
}
-
+
virtual StorageFormat * instance(const QString & filename)
{
return new T(filename);
}
-
+
QString _name;
};
@@ -144,24 +168,25 @@ class Storage : public StorageFormat
StorageFormat(filename)
{
}
-
- virtual QString name() { return "storage"; };
-
+
+ virtual QString name() { return "storage"; }
+
void setError(const QString & error)
{
_error = error;
}
-
+
void setWarning(const QString & warning)
{
_warning = warning;
}
-
+
virtual bool load(RadioData & radioData);
virtual bool write(const RadioData & radioData);
};
void registerStorageFactories();
+void unregisterStorageFactories();
#if 0
unsigned long LoadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index);
diff --git a/companion/src/themes/default/style.css b/companion/src/themes/default/style.css
index c7548a661..5b018a1d0 100644
--- a/companion/src/themes/default/style.css
+++ b/companion/src/themes/default/style.css
@@ -55,6 +55,7 @@ QSplitter::handle:hover {
SimulatorWidget > QWidget {
background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(242, 242, 242, 255), stop:0.757062 rgba(222, 220, 220, 255), stop:1 rgba(232, 230, 230, 255));
}
+
/* radio LCD/controls area under "case" */
SimulatorWidget #radioUiWidget {
background-color: qlineargradient(spread:reflect, x1:0.22, y1:0, x2:0.55065, y2:0.54, stop:0 rgba(7, 7, 7, 250), stop:0.864407 rgba(66, 66, 66, 255));
@@ -63,10 +64,13 @@ SimulatorWidget #radioUiWidget {
}
+/** RadioOutputsWidget **/
+
/* outputs display splitter areas (channels, logical switches, global vars) */
RadioOutputsWidget > QSplitter > QWidget {
border: 1px solid #a1a1a1;
}
+
/* vertical headings with the area names */
RadioOutputsWidget QLabel[heading=true] {
background-color: qlineargradient(spread:reflect, x1:0.22, y1:0, x2:0.5, y2:0.55, stop:0 rgba(20, 20, 20, 250), stop:0.85 rgba(86, 86, 86, 255));
@@ -75,3 +79,36 @@ RadioOutputsWidget QLabel[heading=true] {
padding: 0.8em 0.45em;
font-size: 8pt;
}
+
+/* Channel output indicator sliders */
+
+RadioOutputsWidget #channelsWidget QSlider::groove:vertical {
+ width: 18px;
+ background-color: transparent;
+ border-image: url(:/images/simulator/icons/svg/line_horiz.svg) 0 0 0 0 stretch round;
+}
+
+RadioOutputsWidget #channelsWidget QSlider::add-page:vertical,
+RadioOutputsWidget #channelsWidget QSlider::sub-page:vertical {
+ border: 1px solid #777;
+ margin: 0 5px;
+}
+
+RadioOutputsWidget #channelsWidget QSlider::sub-page:vertical {
+ background: qlineargradient(x1: .4, y1: 0, x2: 1, y2: 1, stop: 0 #bbb, stop:1 #fff);
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+
+RadioOutputsWidget #channelsWidget QSlider::add-page:vertical {
+ background: qlineargradient(x1: .6, y1: 1, x2: 0, y2: 0, stop:0 #55f, stop: 1 #eef);
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+}
+
+RadioOutputsWidget #channelsWidget QSlider::handle:vertical:disabled {
+ background-color: darkgreen;
+ border: 1px solid #ccc;
+ border-radius: 1px;
+ height: 3px;
+}
diff --git a/companion/src/themes/monoblue/16/sdsync.png b/companion/src/themes/monoblue/16/sdsync.png
new file mode 100644
index 000000000..47fc3ba81
Binary files /dev/null and b/companion/src/themes/monoblue/16/sdsync.png differ
diff --git a/companion/src/themes/monoblue/24/sdsync.png b/companion/src/themes/monoblue/24/sdsync.png
new file mode 100644
index 000000000..87bc0debf
Binary files /dev/null and b/companion/src/themes/monoblue/24/sdsync.png differ
diff --git a/companion/src/themes/monoblue/32/sdsync.png b/companion/src/themes/monoblue/32/sdsync.png
new file mode 100644
index 000000000..bbc3697ce
Binary files /dev/null and b/companion/src/themes/monoblue/32/sdsync.png differ
diff --git a/companion/src/themes/monoblue/48/sdsync.png b/companion/src/themes/monoblue/48/sdsync.png
new file mode 100644
index 000000000..451087d1d
Binary files /dev/null and b/companion/src/themes/monoblue/48/sdsync.png differ
diff --git a/companion/src/themes/monowhite/16/sdsync.png b/companion/src/themes/monowhite/16/sdsync.png
new file mode 100644
index 000000000..019c24125
Binary files /dev/null and b/companion/src/themes/monowhite/16/sdsync.png differ
diff --git a/companion/src/themes/monowhite/24/sdsync.png b/companion/src/themes/monowhite/24/sdsync.png
new file mode 100644
index 000000000..9dcb93ece
Binary files /dev/null and b/companion/src/themes/monowhite/24/sdsync.png differ
diff --git a/companion/src/themes/monowhite/32/sdsync.png b/companion/src/themes/monowhite/32/sdsync.png
new file mode 100644
index 000000000..f2362e59a
Binary files /dev/null and b/companion/src/themes/monowhite/32/sdsync.png differ
diff --git a/companion/src/themes/monowhite/48/sdsync.png b/companion/src/themes/monowhite/48/sdsync.png
new file mode 100644
index 000000000..fbc1e8ce7
Binary files /dev/null and b/companion/src/themes/monowhite/48/sdsync.png differ
diff --git a/companion/src/themes/yerico/16/add_category.png b/companion/src/themes/yerico/16/add_category.png
new file mode 100644
index 000000000..d796af414
Binary files /dev/null and b/companion/src/themes/yerico/16/add_category.png differ
diff --git a/companion/src/themes/yerico/16/add_model.png b/companion/src/themes/yerico/16/add_model.png
new file mode 100644
index 000000000..384e805d8
Binary files /dev/null and b/companion/src/themes/yerico/16/add_model.png differ
diff --git a/companion/src/themes/yerico/24/add_category.png b/companion/src/themes/yerico/24/add_category.png
new file mode 100644
index 000000000..185e88e4a
Binary files /dev/null and b/companion/src/themes/yerico/24/add_category.png differ
diff --git a/companion/src/themes/yerico/24/add_model.png b/companion/src/themes/yerico/24/add_model.png
new file mode 100644
index 000000000..e27d9608e
Binary files /dev/null and b/companion/src/themes/yerico/24/add_model.png differ
diff --git a/companion/src/themes/yerico/32/add_category.png b/companion/src/themes/yerico/32/add_category.png
new file mode 100644
index 000000000..9f78ec8bb
Binary files /dev/null and b/companion/src/themes/yerico/32/add_category.png differ
diff --git a/companion/src/themes/yerico/32/add_model.png b/companion/src/themes/yerico/32/add_model.png
new file mode 100644
index 000000000..1e823fdd9
Binary files /dev/null and b/companion/src/themes/yerico/32/add_model.png differ
diff --git a/companion/src/themes/yerico/48/add_category.png b/companion/src/themes/yerico/48/add_category.png
new file mode 100644
index 000000000..2a03e8b5a
Binary files /dev/null and b/companion/src/themes/yerico/48/add_category.png differ
diff --git a/companion/src/themes/yerico/48/add_model.png b/companion/src/themes/yerico/48/add_model.png
new file mode 100644
index 000000000..31c6e6e19
Binary files /dev/null and b/companion/src/themes/yerico/48/add_model.png differ
diff --git a/companion/src/thirdparty/qxtcommandoptions/AUTHORS b/companion/src/thirdparty/qxtcommandoptions/AUTHORS
deleted file mode 100644
index 4490d1aa9..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/AUTHORS
+++ /dev/null
@@ -1,7 +0,0 @@
-Arvid Picciani
-Adam Higerd
-J-P Nurmi
-Benjamin Zeller
-Thomas Mueller
-
-thanks for all the minor contributions, bug reports, beta tests, and the free beer :-)
diff --git a/companion/src/thirdparty/qxtcommandoptions/CHANGES b/companion/src/thirdparty/qxtcommandoptions/CHANGES
deleted file mode 100644
index a1cacd7e0..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/CHANGES
+++ /dev/null
@@ -1,230 +0,0 @@
-LibQxt 0.6.2 contains improvements and bug fixes to the 0.6.x series. For more
-details, see the documentation included in this package or online at
-http://docs.libqxt.org.
-
-0.6.2
------
-
- * QxtWindowSystem:
- - X11 implementation cleanup/overhaul
- - Fixed #85 QxtWindowSystem::windowGeometry issue
- * QxtSpanSlider: Improved span drawing on Mac
- * QxtGlobalShortcut:
- - Fixed #51 QxtGlobalShortcut doesn't send signal
- - Fixed #131 QxtGlobalShortcutKey unregistered other's shortcut key by mistake
- * QxtZeroconf: Fixed a bug in the custom AvahiPoll introduced by a timestamp wrap-around that accured just last week.
- * QxtCrumbView:
- - Don't render delegate for invalid indexes
- - Remove unnecessary padding
- * QxtDataStreamSignalSerializer:
- - Handle incomplete length
- - Added cast to eliminate a compiler warning
- * QxtMailMessage:
- - Fix some encoding issues, support explicit transfer encodings
- - Handle lines with only one word
- * QxtJSON:
- - Add support for long long ints
- - Handle control characters in QxtJSON::stringify
- - Fix \u decoding
- - Fixed a error in json parsing code. Nested arrays were incorrectly combined into one big array.
- * Build system
- - Various enhancements
- - Fixed #130 DEPENTPATH = DEPENDPATH?
- * QxtLogger: Fixed the incorrect association of log level string names to their enumerations
- * QxtAbstractHttpConnector: remove request disconnected on (QHash)"requests"
- * QxtWebContent: Fix comparison on size
- * QxtLanguageBox:
- - Fixed #124 QxtLanguageBox logic maybe bug
- - Fixed #125 QxtLanguageBox improvment in logic
-
-0.6.1
------
-
-- Improvements
- * Revised configure.bat:
- - added -make-bin option
- - removed -msvc from help
- - added build_all config for -debug_and_release
- - cleaned up possible mkdir/move output
- * Added -I, -i and -L options to configure
- * Revised QxtConfig.cmake, based on a proposal from zeke (thanks!)
- * QxtGlobalShortcut/Mac: removed the extra route via QApplication::macEventFilter() - use qxt_mac_handle_hot_key() directly
- * tests/other/app: changed the shortcut to "ctrl+alt+s" (ie. "cmd+alt+s" on mac)
- * examples/jsonrpcclient: added CONFIG+=console to make windows users happy
- * Configure: added -nomake docs
- * Configure: added -no-openssl to -help
- * Added MediaKeys to qxtglobalshortcut_win
- * Added mod4 support in qxtglobalshortcut_x11
- * Added QXT_RPCSERVICE_DEBUG environment variable for convenient network debugging
- * Improved QxtSlotMapper docs
- * Fixed qmake deprecation warnings
-
-- Bug fixes
- * #48 Won't build using Qt 4.4.3 b/c of QVariant::Hash
- * #6 QxtFileLockTest::rw_same() does not pass on Windows
- * Fixed QxtFileLock docs
- * Fixed examples/jsonrpcclient: exit properly with no arguments set
- * Fixed config.tests/db version check to respect MAJOR>4
- * #69 Documentation errors
- * #46 Install on Mac
- * #62 QxtXMLFileLoggerEngine vs QxtXmlFileLoggerEngine
- * #60 including doens't work
- * #63 QxtCheckComboBox display not correct
- * Fixed qdoc3 tags in QxtZeroConf docs
- * QxtSerialDevice: fixed r/w in open, disable ionotifier on error
- * #77 QxtXmlRpcCall: default type not handled
- * #78 Case of an empty string as return parameter without type specified
- * #79 Missing element inside element in XML-RPC
- * #65 QxtCountryComboBox
- * #70 QxtConfigWidget display not correct
- * QxtAbstractHttpConnector: don't add null devices to buffer list
- * QxtZeroconf: Fixed the avahipoll so that the avahi mdns implementation work
-
-0.6.0
------
-- General
- * Revised the build system
- * Revised docs (now based on qdoc3)
- * QxtConfig.cmake
-
-- Bug fixes
- * #4 QxtDaemon::daemonize() compilation warning
- * #24 QxtFlowView::currentIndex()
- * #29 qxtwecore
- * #33 Problem in QxtMailMessage
- * #34 Debug PDB files
- * #36 QxtCommandoptions on Windows wrong option parsing
- * #41 Compilation issue on Mac
-
-- QxtCore
- * Added QxtModelSerializer
- * Removed obsolete QxtSemaphore
- * Added QxtJSON
-
-- QxtGui
- * Added rich text support to QxtItemDelegate
- * Removed obsolete QxtTabWidget::TabMovementMode & QxtTabBar
- * Removed obsolete QxtDockWidget
- * Revised QxtConfigDialog & QxtConfigWidget
- * Enhanced QxtWindowSystem::idleTime() to resolve libXss at run-time
- * Added QxtCrumbView::crumbDelegate()
- * Added QxtFilterDialog and QxtLookupLineEdit
-
-- QxtNetwork
- * Added QxtXmlRpc
- * Added QxtMainAttachment::fromFile()
- * Revised QxtSmtp
- * Added QxtJSONRpcClient and QxtJSONRpcCall
-
-- Added QxtZeroConf module
-
-0.5.2
------
-
-- Bug fixes
- * QxtSerialDevice: update QIODevice status when device is closed
- * QxtSerialDevice: destroy QSocketNotifier when device is closed
- * Modified QxtGlobalShortcut to use XSetErrorHandler() to catch X(Un)GrabKey() errors on X11
-
-0.5.1
------
-
-- Bug fixes
- * #3 [Vista/Qt 4.5.0] - static build issue
- * #9 QxtCheckComboBox display is inconsistent
- * #10 qxtwindowsystem_win.cpp(105) : error C2065: 'LASTINPUTINFO': undeclared identifier
- * #16 Static lib linkage problem in Qt Creator
- * #17 QxtPushButton::minimumSizeHint returns wrong value
- * Fixed QxtGlobalShortcut to allow NumLock on X11
- * Fixed compilation problems with the GCC-4.4.X series
- * Fixed QxtGlobalShortcut::shortcut()
-
-0.5.0
------
-
-- General
- * Added LGPL license option
- * Run Krazy checks and fixed found issues
- * Improved configure.bat
- * Added missing export macros
- * Added missing convenience headers
- * Improved compatibility
- - QT_FORWARD_DECLARE_CLASS
- - Q_SLOTS, Q_SIGNALS & Q_FOREACH in headers
- - interface
-
-- QxtCore
- * Revised QxtFifo
- * Added QxtAlgorithms
- * Added QxtSerialDevice
- * Added QxtSlotMapper
-
-- QxtCrypto
- * Revised QxtBlowfish
-
-- QxtGui
- * Added QxtWindowSystem::idleTime()
- * Added QxtCrumbView
- * Improved QxtScheduleView
- * Added QxtSortFilterProxyModel
- * Improved QxtSpanSlider
- - Added QxtSpanSlider::HandleMovementMode
- * Improved QxtItemDelegate
- - Added ProgressMinimumRole & ProgressMaximumRole
- - Added support for busy indicator mode
- * Improved QxtLetterBoxWidget
- - Added QxtLetterBoxWidget::margin
- - Added QxtLetterBoxWidget::resizeWidget
-
-- QxtWeb
- * Added QxtWebCgiService
-
-0.4.0
------
-
-- QxtCore
- * Added QxtDeplex
- * Added QxtLocale
- * Added QxtPointerList
- * Added QxtMultiSignalWaiter
- * Added QxtSignalGroup
- * Added QxtCommandOptions
- * Added QxtLogger
- * Added QxtAbstractConnectionManager
- * Added QxtDataStreamSignalSerializer
- * Added QxtAbstractSignalSerializer
-
-- QxtCrypto
- * Added QxtHmac
-
-- QxtGui
- * Added QxtItemEditorCreatorBase
- * Added QxtStandardItemEditorCreator
- * Added QxtItemEditorCreator
- * Added QxtBaseSpinBox
- * Added QxtCountryComboBox
- * Added QxtCountryModel
- * Added QxtLanguageComboBox
- * Added QxtScheduleView
- * Added QxtTabBar
- * Added QxtFlowView
- * Added QxtLetterBoxWidget
- * Improved QxtTabWidget
- - Added QxtTabWidget::alwaysShowTabBar
- - Added QxtTabWidget::tabAnimation
- - Added QxtTabWidget::tabMovementMode
- * Improved QxtConfirmationMessage
- - Added QxtConfirmationMessage::settingsFormat
- - Added QxtConfirmationMessage::rememberOnReject
- - Added QxtConfirmationMessage::overrideSettingsApplication
- - Added QxtConfirmationMessage::overrideSettingsKey
- - Added QxtConfirmationMessage::overrideSettingsOrganization
-
-- QxtBerkeley
- * Added QxtBdbTree
-
-- QxtWeb
- * Revised the whole module
-
-- QxtNetwork
- * Added QxtTcpConnectionManager
diff --git a/companion/src/thirdparty/qxtcommandoptions/CMakeLists.txt b/companion/src/thirdparty/qxtcommandoptions/CMakeLists.txt
deleted file mode 100644
index 80074c141..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-set(qxtcommandoptions_SRCS
- qxtcommandoptions.cpp
-)
-
-qt5_wrap_cpp(qxtcommandoptions_SRCS)
-
-add_library(qxtcommandoptions ${qxtcommandoptions_SRCS})
-qt5_use_modules(qxtcommandoptions Widgets)
-
diff --git a/companion/src/thirdparty/qxtcommandoptions/LICENSE b/companion/src/thirdparty/qxtcommandoptions/LICENSE
deleted file mode 100644
index 91a9970ff..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/LICENSE
+++ /dev/null
@@ -1,89 +0,0 @@
-Qt Extension Library
-Copyright (C) 2007 Qxt Foundation
-
-------------------- Disclaimer ------------------------------------------------
-
-Until the Qxt Foundation is legally established, copyright for the
-source code falls back to the original contributor. For information about the
-status of the Qxt Foundation, or about the copyright status of any part of Qxt,
-contact the Qxt project maintainers at
-
-Once the Qxt Foundation has been legally established, all contributors must
-transfer all copyright interest to the Qxt Foundation before their submissions
-will be added to the project.
-
-------------------- License ---------------------------------------------------
-
-This library is free software; you can redistribute it and/or modify it
-under the terms of the Common Public License, version 1.0, as published by IBM
-or under the terms of the GNU Lesser General Public License, version 2.1,
-as published by the Free Software Foundation
-
-This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
-KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
-FITNESS FOR A PARTICULAR PURPOSE.
-
-You should have received a copy of the CPL along with this file.
-See the LICENSE file and the cpl1.0.txt file included with the source
-distribution for more information. If you did not receive a copy of the
-license, contact the Qxt Foundation.
-
-You should have received a copy of the LGPL along with this file.
-See the LICENSE file and the lgpl-2.1.txt file included with the source
-distribution for more information. If you did not receive a copy of the
-license, contact the Qxt Foundation.
-
-Parts of Qxt depend on Qt 4 and/or other libraries that have their own
-licenses. Qxt is independent of these licenses; however, use of these other
-libraries is subject to their respective license agreements.
-
-------------------- Intent ----------------------------------------------------
-
-The following section describes the opinions and intent of the Qxt Foundation
-with regards to the licensing and use of the Qxt source code and library. In
-the event that the CPL is found to be illegal or invalid, or if any application
-or clause of the license is subjected to question or abuse, this section is a
-general statement of the desired interpretation.
-
-This section has no legal standing and the statements made here are strictly
-subject to the text of the CPL; that is, if this section and the CPL are in
-disagreement, the text of the CPL takes precedence. In no way does this
-intent grant you any additional rights or impose any additional restrictions.
-
-If you have questions about licensing, contact the maintainers.
-
-Qxt is built and supported by open-source enthusiasts.
-- Please respect the open-source background of the contributors. The code is
- provided for everyone's use; you may not restrict the rights of anyone to
- use it.
- - No individual may claim ownership of any part of the code. It belongs
- to the community.
- - You may modify the source code to suit your needs, but these changes
- must be made free. If you distribute a modified form of Qxt, you must
- also distribute the entire source code of the modified form.
- - Digital Rights Management (DRM) puts unfair, unfree restrictions on
- users and developers. It is the opposite of Free Software. We can't
- stop you from using it, but please don't use the Qxt name for software
- restricted by DRM.
-- Please respect the time and effort put into the project by the developers.
- - If you find Qxt useful, it would be appreciated if you would include
- text in your application (for instance, in the About dialog) giving
- acknowledgement to Qxt.
- - If you make modifications to the source code, you must not call the
- modified version "Qxt." It's okay to include "Qxt" in the name, but
- anyone who receives the modified version needs to know that it's not
- the same as the version distributed by the Qxt Foundation.
-- We want everyone to be able to use Qxt without restrictions.
- - If you distribute Qxt in compiled binary form, please ensure that
- everyone who receives it can get the source code used to create it.
- - You are free to use Qxt in closed-source applications as long as you
- distribute Qxt in an open-source fashion. This does not require you
- to make your entire application open-source.
-- The Qxt Foundation is a non-profit, non-political organization.
- - Please don't use the Qxt name in any political or semi-political
- propaganda or publication. We don't like it.
-- Qxt is distributed "as-is," with no warranty.
- - If it makes your program crash, your computer blow up, or tiny demons
- fly out of your nose, please don't sue us.
-
diff --git a/companion/src/thirdparty/qxtcommandoptions/cpl1.0.txt b/companion/src/thirdparty/qxtcommandoptions/cpl1.0.txt
deleted file mode 100644
index c448ea00a..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/cpl1.0.txt
+++ /dev/null
@@ -1,213 +0,0 @@
-
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC
-LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
-CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and are
-distributed by that particular Contributor. A Contribution 'originates' from a
-Contributor if it was added to the Program by such Contributor itself or anyone
-acting on such Contributor's behalf. Contributions do not include additions to
-the Program which: (i) are separate modules of software distributed in
-conjunction with the Program under their own license agreement, and (ii) are not
-derivative works of the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which are
-necessarily infringed by the use or sale of its Contribution alone or when
-combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-2. GRANT OF RIGHTS
-
-a) Subject to the terms of this Agreement, each Contributor hereby grants
-Recipient a non-exclusive, worldwide, royalty-free copyright license to
-reproduce, prepare derivative works of, publicly display, publicly perform,
-distribute and sublicense the Contribution of such Contributor, if any, and such
-derivative works, in source code and object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby grants
-Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed
-Patents to make, use, sell, offer to sell, import and otherwise transfer the
-Contribution of such Contributor, if any, in source code and object code form.
-This patent license shall apply to the combination of the Contribution and the
-Program if, at the time the Contribution is added by the Contributor, such
-addition of the Contribution causes such combination to be covered by the
-Licensed Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the licenses
-to its Contributions set forth herein, no assurances are provided by any
-Contributor that the Program does not infringe the patent or other intellectual
-property rights of any other entity. Each Contributor disclaims any liability to
-Recipient for claims brought by any other entity based on infringement of
-intellectual property rights or otherwise. As a condition to exercising the
-rights and licenses granted hereunder, each Recipient hereby assumes sole
-responsibility to secure any other intellectual property rights needed, if any.
-For example, if a third party patent license is required to allow Recipient to
-distribute the Program, it is Recipient's responsibility to acquire that license
-before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright license set
-forth in this Agreement.
-
-3. REQUIREMENTS
-
-A Contributor may choose to distribute the Program in object code form under its
-own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties and
-conditions, express and implied, including warranties or conditions of title and
-non-infringement, and implied warranties or conditions of merchantability and
-fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and consequential
-damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are offered
-by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable manner on or
-through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained within the
-Program.
-
-Each Contributor must identify itself as the originator of its Contribution, if
-any, in a manner that reasonably allows subsequent Recipients to identify the
-originator of the Contribution.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain responsibilities with
-respect to end users, business partners and the like. While this license is
-intended to facilitate the commercial use of the Program, the Contributor who
-includes the Program in a commercial product offering should do so in a manner
-which does not create potential liability for other Contributors. Therefore, if
-a Contributor includes the Program in a commercial product offering, such
-Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
-every other Contributor ("Indemnified Contributor") against any losses, damages
-and costs (collectively "Losses") arising from claims, lawsuits and other legal
-actions brought by a third party against the Indemnified Contributor to the
-extent caused by the acts or omissions of such Commercial Contributor in
-connection with its distribution of the Program in a commercial product
-offering. The obligations in this section do not apply to any claims or Losses
-relating to any actual or alleged intellectual property infringement. In order
-to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial Contributor to
-control, and cooperate with the Commercial Contributor in, the defense and any
-related settlement negotiations. The Indemnified Contributor may participate in
-any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial product
-offering, Product X. That Contributor is then a Commercial Contributor. If that
-Commercial Contributor then makes performance claims, or offers warranties
-related to Product X, those performance claims and warranties are such
-Commercial Contributor's responsibility alone. Under this section, the
-Commercial Contributor would have to defend claims against the other
-Contributors related to those performance claims and warranties, and if a court
-requires any other Contributor to pay any damages as a result, the Commercial
-Contributor must pay those damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
-IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
-Recipient is solely responsible for determining the appropriateness of using and
-distributing the Program and assumes all risks associated with its exercise of
-rights under this Agreement, including but not limited to the risks and costs of
-program errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
-CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
-PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
-GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under applicable
-law, it shall not affect the validity or enforceability of the remainder of the
-terms of this Agreement, and without further action by the parties hereto, such
-provision shall be reformed to the minimum extent necessary to make such
-provision valid and enforceable.
-
-If Recipient institutes patent litigation against a Contributor with respect to
-a patent applicable to software (including a cross-claim or counterclaim in a
-lawsuit), then any patent licenses granted by that Contributor to such Recipient
-under this Agreement shall terminate as of the date such litigation is filed. In
-addition, if Recipient institutes patent litigation against any entity
-(including a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or hardware)
-infringes such Recipient's patent(s), then such Recipient's rights granted under
-Section 2(b) shall terminate as of the date such litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails to
-comply with any of the material terms or conditions of this Agreement and does
-not cure such failure in a reasonable period of time after becoming aware of
-such noncompliance. If all Recipient's rights under this Agreement terminate,
-Recipient agrees to cease use and distribution of the Program as soon as
-reasonably practicable. However, Recipient's obligations under this Agreement
-and any licenses granted by Recipient relating to the Program shall continue and
-survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement, but in
-order to avoid inconsistency the Agreement is copyrighted and may only be
-modified in the following manner. The Agreement Steward reserves the right to
-publish new versions (including revisions) of this Agreement from time to time.
-No one other than the Agreement Steward has the right to modify this Agreement.
-IBM is the initial Agreement Steward. IBM may assign the responsibility to serve
-as the Agreement Steward to a suitable separate entity. Each new version of the
-Agreement will be given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the Agreement
-under which it was received. In addition, after a new version of the Agreement
-is published, Contributor may elect to distribute the Program (including its
-Contributions) under the new version. Except as expressly stated in Sections
-2(a) and 2(b) above, Recipient receives no rights or licenses to the
-intellectual property of any Contributor under this Agreement, whether
-expressly, by implication, estoppel or otherwise. All rights in the Program not
-expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to this
-Agreement will bring a legal action under this Agreement more than one year
-after the cause of action arose. Each party waives its rights to a jury trial in
-any resulting litigation.
diff --git a/companion/src/thirdparty/qxtcommandoptions/lgpl-2.1.txt b/companion/src/thirdparty/qxtcommandoptions/lgpl-2.1.txt
deleted file mode 100644
index 5ab7695ab..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/lgpl-2.1.txt
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- , 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/companion/src/thirdparty/qxtcommandoptions/qxtcommandoptions.cpp b/companion/src/thirdparty/qxtcommandoptions/qxtcommandoptions.cpp
deleted file mode 100644
index f1b6fde20..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/qxtcommandoptions.cpp
+++ /dev/null
@@ -1,914 +0,0 @@
-/****************************************************************************
- **
- ** Copyright (C) Qxt Foundation. Some rights reserved.
- **
- ** This file is part of the QxtCore module of the Qxt library.
- **
- ** This library is free software; you can redistribute it and/or modify it
- ** under the terms of the Common Public License, version 1.0, as published
- ** by IBM, and/or under the terms of the GNU Lesser General Public License,
- ** version 2.1, as published by the Free Software Foundation.
- **
- ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
- ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
- ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
- ** FITNESS FOR A PARTICULAR PURPOSE.
- **
- ** You should have received a copy of the CPL and the LGPL along with this
- ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
- ** included with the source distribution for more information.
- ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
- **
- **
- **
- ****************************************************************************/
-
-#include "qxtcommandoptions.h"
-
-#include
-#include
-#include
-#include
-
-/*!
-\class QxtCommandOptions
-
-\inmodule QxtCore
-
-\brief The QxtCommandOptions class is a Parser for command-line options
-
-This class is used by applications that need to accept command-line arguments. It can
-also automatically generate help text, which keeps it from accidentally falling out of
-sync with the supported options, and it can produce warnings for common errors.
-
-It accepts Windows-style ("/option"), UNIX-style ("-option"), and GNU-style
-("--option") options. By default, QxtCommandOptions uses Windows-style options
-(QxtCommandOptions::Slash) on Windows and GNU-style options (QxtCommandOptions::DoubleDash)
-on UNIX and Mac. When using GNU-style options, single-character option names only
-require a single leading dash and can be grouped together, for example, "-abc".
-
-Any parameter that does not start with the option prefix is considered a positional
-parameter. Most applications treat positional parameters as filenames. When using
-GNU- or UNIX-style options, use a double dash ("--") alone to force the remaining
-parameters to be interpreted as positional parameters.
-
-To use QxtCommandOptions, first add the supported options using the add() and alias()
-methods, then process the command line using the parse() method, and finally retrieve
-the processed options using the positional(), count(), value() and/or parameters()
-methods.
-
-Mutually-exclusive options can be specified by using the \a group parameter to add().
-Only one option in a group will be accepted on the command line; if multiple options
-are provided, only the last one takes effect.
-
-Some options may accept an optional or required parameter. Depending on the value
-of the paramStyle() property, the parameter may be separated from the option by
-an equals sign ("/option=value") or by a space ("-option value"). By default,
-Windows uses an equals sign and UNIX and Mac accept both an equals sign and a
-space. Optional parameters always require an equals sign. Note that, when using
-GNU-style options, single-character options cannot have optional parameters.
-
-A simple archiving application might use code similar to this:
-\code
-QxtCommandOptions options;
-options.add("compress", "create a new archive");
-options.alias("compress", "c");
-options.add("extract", "extract files from an archive");
-options.alias("extract", "x");
-options.add("level", "set the compression level (0-9)", QxtCommandOptions::Required);
-options.alias("level", "l");
-options.add("verbose", "show more information about the process; specify twice for more detail", QxtCommandOptions::AllowMultiple);
-options.alias("verbose", "v");
-options.add("help", "show this help text");
-options.alias("help", "h");
-options.parse(QCoreApplication::arguments());
-if(options.count("help") || options.showUnrecognizedWarning()) {
- options.showUsage();
- return -1;
-}
-bool verbose = options.count("verbose");
-int level = 5;
-if(options.count("level")) {
- level = options.value("level").toInt();
-}
-\endcode
-
-\sa QCoreApplication::arguments()
-*/
-
-static const char* qxt_qt_options[] =
-{
- "=style", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application GUI style"),
- "=stylesheet", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application stylesheet"),
- "=session", QT_TRANSLATE_NOOP("QxtCommandOptions", "restores the application from an earlier session"),
- "widgetcount", QT_TRANSLATE_NOOP("QxtCommandOptions", "displays debugging information about widgets"),
- "reverse", QT_TRANSLATE_NOOP("QxtCommandOptions", "use right-to-left layout"),
-#ifdef QT_DEBUG
- "nograb", QT_TRANSLATE_NOOP("QxtCommandOptions", "never grab the mouse or keyboard"),
-#endif
-#if defined(QT_DEBUG) && defined(Q_WS_X11)
- "dograb", QT_TRANSLATE_NOOP("QxtCommandOptions", "grab the mouse/keyboard even in a debugger"),
- "sync", QT_TRANSLATE_NOOP("QxtCommandOptions", "run in synchronous mode for debugging"),
-#endif
-#ifdef Q_WS_WIN
- "direct3d", QT_TRANSLATE_NOOP("QxtCommandOptions", "use Direct3D by default"),
-#endif
-#ifdef Q_WS_X11
- "=display", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the X11 display"),
- "=geometry", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the geometry of the first window"),
- "=font", "",
- "=fn", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default font"),
- "=background", "",
- "=bg", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default background color"),
- "=foreground", "",
- "=fg", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default foreground color"),
- "=button", "",
- "=btn", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default button color"),
- "=name", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application name"),
- "=title", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application title"),
- "=visual", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the X11 visual type"),
- "=ncols", QT_TRANSLATE_NOOP("QxtCommandOptions", "limit the number of colors on an 8-bit display"),
- "cmap", QT_TRANSLATE_NOOP("QxtCommandOptions", "use a private color map"),
- "=im", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the input method server"),
- "noxim", QT_TRANSLATE_NOOP("QxtCommandOptions", "disable the X Input Method"),
- "=inputstyle", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the style used by the input method"),
-#endif
- 0, 0
-};
-
-/*
- * This function is used to check to see if a parameter
- * is used by Qt.
- */
-static int isQtOption(const QString& param)
-{
- // Qt options all start with a single dash regardless of platform
- if (param.length() < 2) return 0;
- if (param[0] != '-') return 0;
- if (param[1] == '-') return 0;
-#ifdef Q_OS_MAC
- if (param.left(5) == "-psn_") return 1;
-#endif
- QString name = param.mid(1), value;
- // bool hasEquals;
-
- // Separate the option and the value, if present
- if (name.indexOf('=') != -1)
- {
- value = param.section('=', 1);
- name = param.section('=', 0, 0);
- // hasEquals = true;
- }
- else
- {
- value = "";
- // hasEquals = false;
- }
-
- const char* option;
- bool optionHasValue;
- for (int i = 0; qxt_qt_options[i]; i += 2)
- {
- option = qxt_qt_options[i];
- // In the table above, options that require parameters start with =
- if (option[0] == '=')
- {
- optionHasValue = true;
- option = option + 1; // pointer math to skip =
- }
- else
- {
- optionHasValue = false;
- }
-
- // The return value indicates how many parameters to skip
- if (name == option)
- {
- if (optionHasValue) return 2;
- return 1;
- }
- }
-
- return 0;
-}
-
-// Storage structure for option data
-struct QxtCommandOption
-{
- QStringList names; // aliases accepted at the command line
- QString canonicalName; // name used for alias()/count()/value()
- QString desc; // documentation string
- QStringList values; // values passed on command line
- QxtCommandOptions::ParamTypes paramType; // flags
- quint16 group; // mutual exclusion group
-};
-
-class QxtCommandOptionsPrivate : public QxtPrivate
-{
- Q_DECLARE_TR_FUNCTIONS(QxtCommandOptions)
-public:
- QXT_DECLARE_PUBLIC(QxtCommandOptions)
-
- QList options;
- QHash lookup; // cache structure to simplify processing
- QHash > groups; // cache structure to simplify processing
- QxtCommandOptions::FlagStyle flagStyle;
- QxtCommandOptions::ParamStyle paramStyle;
- QStringList positional; // prefixless parameters
- QStringList unrecognized; // prefixed parameters not in recognized options
- QStringList missingParams; // parameters with required values missing
- int screenWidth;
- bool parsed;
-
- QxtCommandOption* findOption(const QString& name);
- const QxtCommandOption* findOption(const QString& name) const;
- void setOption(QxtCommandOption* option, const QString& value = QString());
- void parse(const QStringList& params);
-};
-
-/* Looks up an option in qxt_d().options by canonical name */
-QxtCommandOption* QxtCommandOptionsPrivate::findOption(const QString& name)
-{
- // The backwards loop will find what we're looking for more quickly in the
- // typical use case, where you add aliases immediately after adding the option.
- for (int i = options.count() - 1; i >= 0; --i)
- {
- if (options[i].canonicalName == name) return &options[i];
- }
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("option \"%1\" not found").arg(name));
- return 0;
-}
-
-/* Looks up an option in qxt_d().options by canonical name
- * This is a const overload for const functions */
-const QxtCommandOption* QxtCommandOptionsPrivate::findOption(const QString& name) const
-{
- // The backwards loop will find what we're looking for more quickly in the
- // typical use case, where you add aliases immediately after adding the option.
- for (int i = options.count() - 1; i >= 0; --i)
- {
- if (options[i].canonicalName == name) return &(options.at(i));
- }
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("option \"%1\" not found").arg(name));
- return 0;
-}
-
-/*!
- * Constructs a QxtCommandOptions object.
- */
-QxtCommandOptions::QxtCommandOptions()
-{
- QXT_INIT_PRIVATE(QxtCommandOptions);
- qxt_d().screenWidth = 80;
- qxt_d().parsed = false;
-#ifdef Q_OS_WIN
- setFlagStyle(Slash);
- setParamStyle(Equals);
-#else
- setFlagStyle(DoubleDash);
- setParamStyle(SpaceAndEquals);
-#endif
-}
-
-/*!
- * Sets which prefix is used to identify options. The default value is Slash on Windows
- * and DoubleDash on all other platforms.
- *
- * Note that Qt's built-in options (see QApplication) always use a single dash,
- * regardless of this setting.
- */
-void QxtCommandOptions::setFlagStyle(FlagStyle style)
-{
- qxt_d().flagStyle = style;
-}
-
-/*!
- * Gets which prefix is used to identify options.
- */
-QxtCommandOptions::FlagStyle QxtCommandOptions::flagStyle() const
-{
- return qxt_d().flagStyle;
-}
-
-/*!
- * Sets which value separator is used for options that accept parameters.
- * The default value is Equals on Windows and SpaceAndEquals on all other
- * platforms.
- *
- * Single-letter options with optional parameters in DoubleDash mode
- * always use an equals sign, regardless of this setting.
- *
- * Qt's built-in options always behave as SpaceAndEquals, regardless of
- * this setting.
- */
-void QxtCommandOptions::setParamStyle(ParamStyle style)
-{
- qxt_d().paramStyle = style;
-}
-
-/*!
- * Sets which value separator is used for options that accept parameters.
- */
-QxtCommandOptions::ParamStyle QxtCommandOptions::paramStyle() const
-{
- return qxt_d().paramStyle;
-}
-
-/*!
- * Sets the width of the screen, in characters. This is used for word-wrapping
- * the automatically-generated help text to the size of the screen. The default
- * value is 80 characters. Pass 0 to disable word-wrapping.
- */
-void QxtCommandOptions::setScreenWidth(quint16 width)
-{
- qxt_d().screenWidth = width;
-}
-
-/*!
- * Gets the width of the screen, in characters.
- */
-quint16 QxtCommandOptions::screenWidth() const
-{
- return qxt_d().screenWidth;
-}
-
-/*!
- * Adds a section separator. Section separators are only used in generating
- * help text, and can be used to visually separate related groups of
- * options.
- */
-void QxtCommandOptions::addSection(const QString& name)
-{
- QxtCommandOption option;
- option.canonicalName.clear();
- option.desc = name;
- qxt_d().options.append(option);
-}
-
-/*!
- * Adds an option to the parser.
- *
- * The name parameter defines the name that will be used by the alias(),
- * count(), value(), and parameters() methods. Additional names for the
- * same option can be defined using the alias() method.
- *
- * The group parameter, if used, defines a set of mutually-exclusive options.
- * If more than one option in the same group is passed on the command line,
- * only the last one takes effect.
- */
-void QxtCommandOptions::add(const QString& name, const QString& desc, ParamTypes paramType, int group)
-{
- QxtCommandOption option;
- option.canonicalName = name;
- option.desc = desc;
- option.paramType = paramType;
- option.group = group;
- qxt_d().options.append(option);
- if (group != -1)
- qxt_d().groups[group].append(&(qxt_d().options.last()));
- // Connect the canonical name to a usable name
- alias(name, name);
-}
-
-/*!
- * Provides an alias for an option. An alias is another name for the option that can be
- * given on the command line. Aliases cannot be used as parameters to alias(), count()
- * or value() nor can single-letter aliases be created for options with an optional value.
- *
- * The from parameter must be a name has previously been added with the add() method.
- */
-void QxtCommandOptions::alias(const QString& from, const QString& to)
-{
- QxtCommandOption* option = qxt_d().findOption(from);
- if (!option) return; // findOption outputs the warning
- option->names.append(to);
- qxt_d().lookup[to] = option;
- if (option->paramType & ValueOptional && qxt_d().flagStyle == DoubleDash && to.length() == 1)
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("Short options cannot have optional parameters"));
-}
-
-/*!
- * Returns the positional parameters from the command line, that is, the arguments that
- * do not begin with the option prefix.
- *
- * \sa flagStyle()
- */
-QStringList QxtCommandOptions::positional() const
-{
- if (!qxt_d().parsed)
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("positional() called before parse()"));
- return qxt_d().positional;
-}
-
-/*!
- * Returns the options that could not be parsed.
- *
- * An argument is unrecognized if it begins with the option prefix but was never
- * defined using the add() or alias() methods, or if it requires a value but the
- * user did not provide one.
- */
-QStringList QxtCommandOptions::unrecognized() const
-{
- if (!qxt_d().parsed)
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("unrecognized() called before parse()"));
- return qxt_d().unrecognized + qxt_d().missingParams;
-}
-
-/*!
- * Returns the number of times an option was passed on the command line.
- *
- * This function will only return 0 or 1 for options that were not created with the
- * QxtCommandOptions::AllowMultiple flag set.
- */
-int QxtCommandOptions::count(const QString& name) const
-{
- if (!qxt_d().parsed)
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("count() called before parse()"));
- const QxtCommandOption* option = qxt_d().findOption(name);
- if (!option) return 0; // findOption outputs the warning
- return option->values.count();
-}
-
-/*!
- * Returns the value or values for an option passed on the command line.
- *
- * If the option was not passed on the command line, this function returns a null QVariant.
- * If the option was created with the QxtCommandOptions::AllowMultiple flag, and the option
- * was passed more than once, this function returns a QStringList containing the values.
- * Otherwise, this function returns the last (or only) value given to the option on the
- * command line. When an option allowing an optional value is provided on the command
- * line and for which no value is provided, an empty but non-null QString will be returned
- * in the QVariant.
- */
-QVariant QxtCommandOptions::value(const QString& name) const
-{
- if (!qxt_d().parsed)
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("value() called before parse()"));
- const QxtCommandOption* option = qxt_d().findOption(name);
- if (!option) return QVariant(); // findOption outputs the warning
- int ct = option->values.count();
- if (ct == 0) return QVariant();
- if (ct == 1) return option->values.first();
- return option->values;
-}
-
-/*!
- * Returns all of the recognized options passed on the command line.
- */
-QMultiHash QxtCommandOptions::parameters() const
-{
- if (!qxt_d().parsed)
- qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("parameters() called before parse()"));
- QMultiHash params;
- int ct;
- foreach(const QxtCommandOption& option, qxt_d().options)
- {
- ct = option.values.count();
- if (!ct)
- {
- continue;
- }
- else if (!(option.paramType & (ValueOptional | ValueRequired)))
- {
- // Valueless options are really a true/false flag
- params.insert(option.canonicalName, true);
- }
- else
- {
- foreach(const QVariant& value, option.values)
- params.insert(option.canonicalName, value);
- }
- }
- return params;
-}
-
-/*!
- * This is an overloaded member function, provided for convenience.
- *
- * Process a set of command-line options. This overload accepts a number of
- * arguments and a pointer to the list of arguments.
- *
- * Note that parse() may be invoked multiple times to handle arguments from
- * more than one source.
- */
-void QxtCommandOptions::parse(int argc, char** argv)
-{
- QStringList args;
- for (int i = 0; i < argc; i++)
- args << argv[i];
- parse(args);
-}
-
-/*!
- * Process a set of command-line options. This overload accepts a QStringList
- * containing the command-line options, such as the one returned by
- * QCoreApplication::arguments().
- *
- * Note that parse() may be invoked multiple times to handle arguments from
- * more than one source.
- *
- * \sa QCoreApplication::arguments()
- */
-void QxtCommandOptions::parse(QStringList params)
-{
- qxt_d().parse(params);
- qxt_d().parsed = true;
-}
-
-/* Update the internal data structures with an option from the command line. */
-void QxtCommandOptionsPrivate::setOption(QxtCommandOption* option, const QString& value)
-{
- if (groups.contains(option->group))
- {
- // Clear mutually-exclusive options
- QList& others = groups[option->group];
- foreach(QxtCommandOption* other, others)
- {
- if (other != option) other->values.clear();
- }
- }
- // Clear all previous values if multiples are not accepted
- if (!(option->paramType & QxtCommandOptions::AllowMultiple))
- option->values.clear();
- option->values.append(value);
-}
-
-/* Do the work of parsing the command line */
-void QxtCommandOptionsPrivate::parse(const QStringList& params)
-{
- int pos = 1; // 0 is the application name
- int ct = params.count();
- int skip = 0;
- bool endFlags = false;
- bool /*notUnrecognized, */hasEquals;
- QString name, param, value;
-
- while (pos < ct)
- {
- // Ignore Qt built-in options
- while ((skip = isQtOption(params[pos])))
- {
- pos += skip;
- if (pos >= ct)
- return;
- }
-
- param = params[pos];
- pos++;
-
- if (!endFlags && ((flagStyle == QxtCommandOptions::Slash && param[0] == '/') ||
- (flagStyle != QxtCommandOptions::Slash && param[0] == '-')))
- {
- // tagged argument
- if (param.length() == 1)
- {
- // "-" or "/" alone can't possibly match a flag, so use positional.
- positional.append(param);
- continue;
- }
- // notUnrecognized = false;
-
- if (flagStyle != QxtCommandOptions::Slash && param == "--")
- {
- // End of parameters flag
- endFlags = true;
- }
- else if (flagStyle == QxtCommandOptions::DoubleDash && param[1] != '-')
- {
- // Handle short-form options
- int len = param.length();
- QxtCommandOption* option;
- for (int i = 1; i < len; i++)
- {
- QString ch(param[i]);
- if (ch == "-")
- {
- endFlags = true;
- }
- else
- {
- option = lookup.value(ch, 0);
- if (!option)
- {
- // single-letter flag has no known equivalent
- unrecognized.append(QString("-") + param[i]);
- }
- else
- {
- if (option->paramType & QxtCommandOptions::ValueRequired)
- {
- // Check for required parameters
- // Short options can't have optional parameters
- if (pos >= params.count())
- {
- missingParams.append(param);
- break;
- }
- value = params[pos];
- }
- else
- {
- value = "";
- }
- setOption(option, value);
- }
- }
- }
- }
- else
- {
- // Break apart a value
- if (param.indexOf('=') != -1)
- {
- value = param.section('=', 1);
- param = param.section('=', 0, 0);
- hasEquals = true;
- }
- else
- {
- value = "";
- hasEquals = false;
- }
-
- if (flagStyle == QxtCommandOptions::DoubleDash)
- name = param.mid(2);
- else
- name = param.mid(1);
-
- QxtCommandOption* option = lookup.value(name, 0);
- if (!option)
- {
- unrecognized.append(param);
- }
- else
- {
- if (option->paramType & QxtCommandOptions::ValueRequired && !hasEquals)
- {
- // Check for parameters
- if (pos >= params.count())
- {
- missingParams.append(param);
- break;
- }
- value = params[pos];
- pos++;
- }
- else if ((paramStyle & QxtCommandOptions::Space)
- && (option->paramType & QxtCommandOptions::ValueOptional)
- && !hasEquals)
- {
- if (pos < params.count())
- {
- if (!((flagStyle == QxtCommandOptions::Slash && params.at(pos)[0] == '/') ||
- (flagStyle != QxtCommandOptions::Slash && params.at(pos)[0] == '-')))
- {
- value = params[pos];
- pos++;
- }
- }
- }
-
- setOption(option, value);
- }
- }
- }
- else
- {
- // positional argument
- positional.append(param);
- }
- }
-}
-
-/*!
- * This is an overloaded member function, provided for convenience.
- *
- * Outputs a warning about any unrecognized options to the provided device, or
- * standard error by default. The device must already be opened for writing.
- *
- * This function returns true if any warnings were output, or false otherwise.
- *
- * If a QCoreApplication or a subclass of QCoreApplication has been instantiated,
- * this function uses QCoreApplication::applicationFilePath() to get the name
- * of the executable to include in the message.
- *
- * \sa QCoreApplication::applicationFilePath()
- */
-bool QxtCommandOptions::showUnrecognizedWarning(QIODevice* device) const
-{
- if (!device)
- {
- QTextStream stream(stderr);
- return showUnrecognizedWarning(*&stream);
- }
- else
- {
- QTextStream stream(device);
- return showUnrecognizedWarning(*&stream);
- }
-}
-
-/*!
- * Returns the automatically-generated warning text about any unrecognized options.
- *
- * If a QCoreApplication or a subclass of QCoreApplication has been instantiated,
- * this function uses QCoreApplication::applicationFilePath() to get the name
- * of the executable to include in the message.
- *
- * \sa QCoreApplication::applicationFilePath()
- */
-QString QxtCommandOptions::getUnrecognizedWarning() const
-{
- QString usage;
- QTextStream stream(&usage);
- showUnrecognizedWarning(*&stream);
- return usage;
-}
-
-/*!
- * This is an overloaded member function, provided for convenience.
- *
- * Outputs a warning about any unrecognized options to the provided stream.
- *
- * This function returns true if any warnings were output, or false otherwise.
- *
- * If a QCoreApplication or a subclass of QCoreApplication has been instantiated,
- * this function uses QCoreApplication::applicationFilePath() to get the name
- * of the executable to include in the message.
- *
- * \sa QCoreApplication::applicationFilePath()
- */
-bool QxtCommandOptions::showUnrecognizedWarning(QTextStream& stream) const
-{
- if (!qxt_d().unrecognized.count() && !qxt_d().missingParams.count()) return false;
-
- QString name;
- if (QCoreApplication::instance())
- name = QDir(QCoreApplication::applicationFilePath()).dirName();
- if (name.isEmpty())
- name = "QxtCommandOptions";
-
- if (qxt_d().unrecognized.count())
- stream << name << ": " << tr("unrecognized parameters: ") << qxt_d().unrecognized.join(" ") << endl;
-
- foreach(const QString& param, qxt_d().missingParams)
- stream << name << ": " << tr("%1 requires a parameter").arg(param) << endl;
-
- return true;
-}
-
-/*!
- * This is an overloaded member function, provided for convenience.
- *
- * Outputs automatically-generated usage text for the accepted options to the provided
- * device, or standard error by default. The device must already be opened for writing.
- *
- * Pass true to showQtOptions to output usage text for the options recognized by
- * QApplication.
- *
- * \sa QApplication
- */
-void QxtCommandOptions::showUsage(bool showQtOptions, QIODevice* device) const
-{
- if (!device)
- {
- QTextStream stream(stdout);
- showUsage(showQtOptions, *&stream);
- }
- else
- {
- QTextStream stream(device);
- showUsage(showQtOptions, *&stream);
- }
-}
-
-/*!
- * Returns the automatically-generated usage text for the accepted options.
- */
-QString QxtCommandOptions::getUsage(bool showQtOptions) const
-{
- QString usage;
- QTextStream stream(&usage);
- showUsage(showQtOptions, *&stream);
- return usage;
-}
-
-/*!
- * This is an overloaded member function, provided for convenience.
- *
- * Outputs automatically-generated usage text for the accepted options to the provided
- * stream.
- *
- * Pass true to showQtOptions to output usage text for the options recognized by
- * QApplication.
- *
- * \sa QApplication
- */
-void QxtCommandOptions::showUsage(bool showQtOptions, QTextStream& stream) const
-{
- QStringList names;
- QStringList descs;
- int maxNameLength = 0;
- QString name;
-
- foreach(const QxtCommandOption& option, qxt_d().options)
- {
- // Don't generate usage for undocumented parameters
- if (option.paramType & Undocumented) continue;
-
- foreach(const QString& n, option.names)
- {
- if (name.length()) name += ", ";
- if (qxt_d().flagStyle == Slash)
- name += '/';
- else if (qxt_d().flagStyle == DoubleDash && n.length() > 1)
- name += "--";
- else
- name += '-';
- name += n;
- if (option.paramType & (ValueOptional | ValueRequired))
- {
- if (option.paramType & ValueOptional)
- name += "[=x]";
- else if (qxt_d().paramStyle == SpaceAndEquals)
- name += "[=]x";
- else if (qxt_d().paramStyle == Equals)
- name += "=x";
- else
- name += " x";
- }
- }
-
- // The maximum name length is used for formatting the output columns
- if (name.length() > maxNameLength)
- maxNameLength = name.length();
- names.append(name);
- descs.append(option.desc);
- name = "";
- }
-
- if (showQtOptions)
- {
- // Add a section header
- names.append(QString());
- descs.append("Common Qt Options");
-
- // Parse through qxt_qt_options
- const char* option;
- bool optionHasValue;
- for (int i = 0; qxt_qt_options[i]; i += 2)
- {
- option = qxt_qt_options[i];
-
- if (option[0] == '=')
- {
- // The option takes a parameter
- optionHasValue = true;
- option = option + 1; // pointer math to skip the =
- }
- else
- {
- optionHasValue = false;
- }
-
- // Concatenate on the option alias
- if (!name.isEmpty()) name += ", ";
- name += '-';
- name += option;
- if (optionHasValue) name += "[=]x";
-
- if (qxt_qt_options[i+1][0] != 0)
- {
- // The last alias for the option has the description
- if (name.length() > maxNameLength)
- maxNameLength = name.length();
- names.append(name);
- descs.append(qxt_qt_options[i+1]);
- name = "";
- }
- }
- }
-
- int ct = names.count();
- QString line, wrap(maxNameLength + 3, ' ');
- for (int i = 0; i < ct; i++)
- {
- if (names[i].isEmpty())
- {
- // Section headers have no name entry
- stream << endl << descs[i] << ":" << endl;
- continue;
- }
- line = ' ' + names[i] + QString(maxNameLength - names[i].length() + 2, ' ');
- foreach(const QString& word, descs[i].split(' ', QString::SkipEmptyParts))
- {
- if (qxt_d().screenWidth > 0 && line.length() + word.length() >= qxt_d().screenWidth)
- {
- stream << line << endl;
- line = wrap;
- }
- line += word + ' ';
- }
- stream << line << endl;
- }
-}
diff --git a/companion/src/thirdparty/qxtcommandoptions/qxtcommandoptions.h b/companion/src/thirdparty/qxtcommandoptions/qxtcommandoptions.h
deleted file mode 100644
index e302d90f1..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/qxtcommandoptions.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
- **
- ** Copyright (C) Qxt Foundation. Some rights reserved.
- **
- ** This file is part of the QxtCore module of the Qxt library.
- **
- ** This library is free software; you can redistribute it and/or modify it
- ** under the terms of the Common Public License, version 1.0, as published
- ** by IBM, and/or under the terms of the GNU Lesser General Public License,
- ** version 2.1, as published by the Free Software Foundation.
- **
- ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
- ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
- ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
- ** FITNESS FOR A PARTICULAR PURPOSE.
- **
- ** You should have received a copy of the CPL and the LGPL along with this
- ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
- ** included with the source distribution for more information.
- ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
- **
- **
- **
- ****************************************************************************/
-
-#ifndef QXTCOMMANDOPTIONS_H
-#define QXTCOMMANDOPTIONS_H
-#include
-#include
-#include
-#include // for Q_DECLARE_TR_FUNCTIONS
-#include
-#include
-class QxtCommandOptionsPrivate;
-QT_FORWARD_DECLARE_CLASS(QTextStream)
-QT_FORWARD_DECLARE_CLASS(QIODevice)
-
-
-class QxtCommandOptions
-{
- Q_DECLARE_TR_FUNCTIONS(QxtCommandOptions)
-
-public:
- /*!
- * \enum QxtCommandOptions::FlagStyle
- * This enum type defines which type of option prefix is used.
- * Slash is the default on Windows.
- * DoubleDash is the default on all other platforms.
- */
- enum FlagStyle
- {
- DoubleDash, /*!< Two dashes (GNU-style) */
- SingleDash, /*!< One dash (UNIX-style) */
- Slash /*!< Forward slash (Windows-style) */
- };
- /*!
- * \enum QxtCommandOptions::ParamStyle
- * This enum type defines what syntax is used for options that
- * require parameters. Equals is the default on Windows.
- * SpaceAndEquals is the default on all other platforms.
- */
- enum ParamStyle
- {
- Space = 1, /*!< Space ("-option value") */
- Equals = 2, /*!< Equals sign ("/option=value") */
- SpaceAndEquals = 3 /*!< Accept either */
- };
- /*!
- * \enum QxtCommandOptions::ParamType
- * \flags QxtCommandOptions::ParamTypes
- * This enum type is used to specify flags that control the
- * interpretation of an option.
- *
- * The ParamTypes type is a typedef for QFlags. It stores
- * an OR combination of ParamType values.
- */
- enum ParamType
- {
- NoValue = 0, /*!< The option does not accept a value. */
- ValueOptional = 1, /*!< The option may accept a value. */
- ValueRequired = 2, /*!< The option requires a value. */
- Optional = ValueOptional, /*!< The option may accept a value. Deprecated in favor of ValueOptional. */
- Required = ValueRequired, /*!< The option requires a value. Deprecated in favor of ValueRequired. */
- AllowMultiple = 4, /*!< The option may be passed multiple times. */
- Undocumented = 8 /*!< The option is not output in the help text. */
- };
- Q_DECLARE_FLAGS(ParamTypes, ParamType)
-
- QxtCommandOptions();
-
- void setFlagStyle(FlagStyle style);
- FlagStyle flagStyle() const;
- void setParamStyle(ParamStyle style);
- ParamStyle paramStyle() const;
- void setScreenWidth(quint16 width);
- quint16 screenWidth() const;
-
- void addSection(const QString& name);
- void add(const QString& name, const QString& desc = QString(), ParamTypes paramType = NoValue, int group = -1);
- void alias(const QString& from, const QString& to);
-
- QStringList positional() const;
- QStringList unrecognized() const;
- int count(const QString& name) const;
- QVariant value(const QString& name) const;
- QMultiHash parameters() const;
-
- void parse(int argc, char** argv);
- void parse(QStringList params);
-
- void showUsage(bool showQtOptions = false, QIODevice* device = 0) const;
- void showUsage(bool showQtOptions, QTextStream& stream) const;
- QString getUsage(bool showQtOptions = false) const;
-
- bool showUnrecognizedWarning(QIODevice* device = 0) const;
- bool showUnrecognizedWarning(QTextStream& stream) const;
- QString getUnrecognizedWarning() const;
-
-private:
- QXT_DECLARE_PRIVATE(QxtCommandOptions)
-};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QxtCommandOptions::ParamTypes)
-
-#endif // QXTCOMMANDOPTIONS_H
diff --git a/companion/src/thirdparty/qxtcommandoptions/qxtglobal.h b/companion/src/thirdparty/qxtcommandoptions/qxtglobal.h
deleted file mode 100644
index a5744d88f..000000000
--- a/companion/src/thirdparty/qxtcommandoptions/qxtglobal.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/****************************************************************************
- **
- ** Copyright (C) Qxt Foundation. Some rights reserved.
- **
- ** This file is part of the QxtCore module of the Qxt library.
- **
- ** This library is free software; you can redistribute it and/or modify it
- ** under the terms of the Common Public License, version 1.0, as published
- ** by IBM, and/or under the terms of the GNU Lesser General Public License,
- ** version 2.1, as published by the Free Software Foundation.
- **
- ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
- ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
- ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
- ** FITNESS FOR A PARTICULAR PURPOSE.
- **
- ** You should have received a copy of the CPL and the LGPL along with this
- ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
- ** included with the source distribution for more information.
- ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
- **
- **
- **
- ****************************************************************************/
-
-#ifndef QXTGLOBAL_H
-#define QXTGLOBAL_H
-
-#include
-
-#define QXT_VERSION 0x000602
-#define QXT_VERSION_STR "0.6.2"
-
-//--------------------------global macros------------------------------
-
-#ifndef QXT_NO_MACROS
-
-#endif // QXT_NO_MACROS
-
-//--------------------------export macros------------------------------
-
-#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
-
-#if !defined(QXT_STATIC)
-# if defined(BUILD_QXT_CORE)
-# define QXT_CORE_EXPORT Q_DECL_EXPORT
-# else
-# define QXT_CORE_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define QXT_CORE_EXPORT
-#endif // BUILD_QXT_CORE
-
-#if !defined(QXT_STATIC)
-# if defined(BUILD_QXT_GUI)
-# define QXT_GUI_EXPORT Q_DECL_EXPORT
-# else
-# define QXT_GUI_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define QXT_GUI_EXPORT
-#endif // BUILD_QXT_GUI
-
-#if !defined(QXT_STATIC)
-# if defined(BUILD_QXT_NETWORK)
-# define QXT_NETWORK_EXPORT Q_DECL_EXPORT
-# else
-# define QXT_NETWORK_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define QXT_NETWORK_EXPORT
-#endif // BUILD_QXT_NETWORK
-
-#if !defined(QXT_STATIC)
-# if defined(BUILD_QXT_SQL)
-# define QXT_SQL_EXPORT Q_DECL_EXPORT
-# else
-# define QXT_SQL_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define QXT_SQL_EXPORT
-#endif // BUILD_QXT_SQL
-
-#if !defined(QXT_STATIC)
-# if defined(BUILD_QXT_WEB)
-# define QXT_WEB_EXPORT Q_DECL_EXPORT
-# else
-# define QXT_WEB_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define QXT_WEB_EXPORT
-#endif // BUILD_QXT_WEB
-
-#if !defined(QXT_STATIC)
-# if defined(BUILD_QXT_BERKELEY)
-# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT
-# else
-# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define QXT_BERKELEY_EXPORT
-#endif // BUILD_QXT_BERKELEY
-
-#if !defined(QXT_STATIC)
-# if defined(BUILD_QXT_ZEROCONF)
-# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT
-# else
-# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define QXT_ZEROCONF_EXPORT
-#endif // QXT_ZEROCONF_EXPORT
-
-#if defined BUILD_QXT_CORE || defined BUILD_QXT_GUI || defined BUILD_QXT_SQL || defined BUILD_QXT_NETWORK || defined BUILD_QXT_WEB || defined BUILD_QXT_BERKELEY || defined BUILD_QXT_ZEROCONF
-# define BUILD_QXT
-#endif
-
-QXT_CORE_EXPORT const char* qxtVersion();
-
-#ifndef QT_BEGIN_NAMESPACE
-#define QT_BEGIN_NAMESPACE
-#endif
-
-#ifndef QT_END_NAMESPACE
-#define QT_END_NAMESPACE
-#endif
-
-#ifndef QT_FORWARD_DECLARE_CLASS
-#define QT_FORWARD_DECLARE_CLASS(Class) class Class;
-#endif
-
-/****************************************************************************
-** This file is derived from code bearing the following notice:
-** The sole author of this file, Adam Higerd, has explicitly disclaimed all
-** copyright interest and protection for the content within. This file has
-** been placed in the public domain according to United States copyright
-** statute and case law. In jurisdictions where this public domain dedication
-** is not legally recognized, anyone who receives a copy of this file is
-** permitted to use, modify, duplicate, and redistribute this file, in whole
-** or in part, with no restrictions or conditions. In these jurisdictions,
-** this file shall be copyright (C) 2006-2008 by Adam Higerd.
-****************************************************************************/
-
-#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface qxt_d;
-#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
-#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
-#define QXT_D(PUB) PUB##Private& d = qxt_d()
-#define QXT_P(PUB) PUB& p = qxt_p()
-
-template
-class QxtPrivate
-{
-public:
- virtual ~QxtPrivate()
- {}
- inline void QXT_setPublic(PUB* pub)
- {
- qxt_p_ptr = pub;
- }
-
-protected:
- inline PUB& qxt_p()
- {
- return *qxt_p_ptr;
- }
- inline const PUB& qxt_p() const
- {
- return *qxt_p_ptr;
- }
-
-private:
- PUB* qxt_p_ptr;
-};
-
-template
-class QxtPrivateInterface
-{
- friend class QxtPrivate;
-public:
- QxtPrivateInterface()
- {
- pvt = new PVT;
- }
- ~QxtPrivateInterface()
- {
- delete pvt;
- }
-
- inline void setPublic(PUB* pub)
- {
- pvt->QXT_setPublic(pub);
- }
- inline PVT& operator()()
- {
- return *static_cast(pvt);
- }
- inline const PVT& operator()() const
- {
- return *static_cast(pvt);
- }
-private:
- QxtPrivateInterface(const QxtPrivateInterface&) { }
- QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
- QxtPrivate* pvt;
-};
-
-#endif // QXT_GLOBAL
diff --git a/companion/src/translations.cpp b/companion/src/translations.cpp
new file mode 100644
index 000000000..2bd75881c
--- /dev/null
+++ b/companion/src/translations.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "translations.h"
+#include "appdata.h"
+
+#include
+#include
+#include
+#include
+
+// List of available Companion translations
+// todo: make dynamic eg. from directory listing
+// todo: make locale name country-agnostic unless translation is specifically for a country (like zh_CN)
+QStringList const Translations::getAvailableTranslations()
+{
+ static QStringList locales;
+
+ if (!locales.size()) {
+ locales << "cs_CZ"
+ << "de_DE"
+ << "en"
+ << "es_ES"
+ << "fi_FI"
+ << "fr_FR"
+ //<< "he_IL"
+ << "it_IT"
+ //<< "nl_NL"
+ << "pl_PL"
+ //<< "pt_PT"
+ //<< "ru_RU"
+ << "sv_SE"
+ << "zh_CN" ;
+ }
+ return locales;
+}
+
+QStringList const Translations::getAvailableLanguages()
+{
+ static QStringList languages;
+ if (!languages.size()) {
+ foreach (const QString & loc, getAvailableTranslations())
+ languages.append(loc.left(2));
+ }
+ return languages;
+}
+
+QStringList const Translations::getTranslationPaths()
+{
+ // Look for translation files in the following locations, in order of priority
+ QStringList paths;
+
+ // Prefer path set in environment variable, makes it possible to test/replace translations w/out rebuilding.
+ if (qEnvironmentVariableIsSet("OPENTX_APP_TRANSLATIONS_PATH") && QDir(qgetenv("OPENTX_APP_TRANSLATIONS_PATH").constData()).exists()) {
+ paths << qgetenv("OPENTX_APP_TRANSLATIONS_PATH").constData();
+ }
+ // Try application subfolder first, also eg. to test/replace translations quickly.
+ paths << APP_TRANSLATIONS_FILE_PATH;
+ // Then the resource file
+ paths << APP_TRANSLATIONS_RESOURCE_PATH;
+ // Finally the system folder (more likely for Qt translations than Companion ones)
+ paths << QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+
+ return paths;
+}
+
+void Translations::installTranslators()
+{
+ Q_INIT_RESOURCE(translations);
+
+ static QList appTranslators;
+
+ // Determine the locale
+
+ QLocale locale; // defaults to system locale
+ if (!g.locale().isEmpty()) {
+ locale = QLocale(g.locale()); // reverts to "C" locale if invalid
+ if (locale.language() == QLocale::C) {
+ // reset
+ locale = QLocale::system();
+ g.locale("");
+ }
+ }
+ qDebug() << "Locale name:" << locale.name() << "language:" << locale.nativeLanguageName() << "country:" << locale.nativeCountryName();
+
+ // Remove any existing translators, this lets us re-translate w/out restart.
+ foreach (QTranslator * t, appTranslators) {
+ if (t) {
+ QCoreApplication::removeTranslator(t);
+ delete t;
+ }
+ }
+ appTranslators.clear();
+
+ /* Multiple translation files can be installed.
+ * Translations are searched for in the reverse order from which they were installed (last added is searched first).
+ * The search stops as soon as a translation containing a matching string is found.
+ */
+
+ // Look for translation files in several locations
+ QStringList tryPaths = getTranslationPaths();
+
+ // First try to install Qt translations for common GUI elements.
+
+ QStringList qtFiles = QStringList() << "qt";
+ // After Qt5.3 some translation files are broken up into modules. We only need "qtbase" for now.
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 3, 0))
+ qtFiles << "qtbase";
+#endif
+
+ foreach (const QString & qtfile, qtFiles) {
+ QTranslator * translator = new QTranslator(qApp);
+ if (tryLoadTranslator(translator, locale, qtfile, tryPaths)) {
+ appTranslators.append(translator);
+ }
+ else {
+ delete translator;
+ //qDebug() << "Could not find Qt translations for:" << locale.name() << "In file:" << qtfile << "Using paths:" << tryPaths;
+ }
+ }
+
+ // Now try to install our custom translations if we support the current locale/language.
+ if (!getAvailableTranslations().contains(locale.name()) && !getAvailableLanguages().contains(locale.name().left(2)))
+ return;
+
+ QTranslator * translator = new QTranslator(qApp);
+ if (tryLoadTranslator(translator, locale, "companion", tryPaths)) {
+ appTranslators.append(translator);
+ }
+ else {
+ delete translator;
+ qWarning() << "Could not find Companion translations for:" << locale.name() << "Using paths:" << tryPaths;
+ }
+}
+
+bool Translations::tryLoadTranslator(QTranslator * t, const QLocale & locale, const QString & baseFile, const QStringList & paths)
+{
+ foreach (const QString & path, paths) {
+ if (t->load(locale, baseFile, "_", path)) {
+ if (QCoreApplication::installTranslator(t)) {
+ qDebug() << "Installed translation file" << baseFile << "from" << path << "for" << locale.name();
+ return true;
+ }
+ else {
+ qWarning() << "Error installing translation file" << baseFile << "for:" << locale.name() << "from:" << path;
+ return false;
+ }
+ }
+ }
+ return false;
+}
diff --git a/companion/src/translations.h b/companion/src/translations.h
new file mode 100644
index 000000000..0099317ed
--- /dev/null
+++ b/companion/src/translations.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef TRANSLATIONS_H
+#define TRANSLATIONS_H
+
+#include
+
+// Where to find translation files?
+// First any path in environment variable OPENTX_APP_TRANSLATIONS_PATH is used if it exists.
+
+// Default location for .qm files when NOT compiled into application (this is searched after OPENTX_APP_TRANSLATIONS_PATH).
+#ifndef APP_TRANSLATIONS_FILE_PATH
+ #define APP_TRANSLATIONS_FILE_PATH QCoreApplication::applicationDirPath() % "/translations"
+#endif
+\
+// Default location for .qm files when compiled into application as a resource (this is searched after APP_TRANSLATIONS_FILE_PATH) .
+#ifndef APP_TRANSLATIONS_RESOURCE_PATH
+ #define APP_TRANSLATIONS_RESOURCE_PATH ":/translations"
+#endif
+
+class QLocale;
+class QTranslator;
+
+class Translations
+{
+ public:
+ static QStringList const getTranslationPaths();
+ static QStringList const getAvailableTranslations();
+ static QStringList const getAvailableLanguages();
+
+ static void installTranslators();
+
+ protected:
+ static bool tryLoadTranslator(QTranslator * t, const QLocale & locale, const QString & baseFile, const QStringList & paths);
+};
+
+#endif // TRANSLATIONS_H
diff --git a/companion/src/translations.qrc.in b/companion/src/translations.qrc.in
index 975494eb8..6fc7f6a1f 100644
--- a/companion/src/translations.qrc.in
+++ b/companion/src/translations.qrc.in
@@ -1,13 +1,6 @@
-
-
- companion_cs.qm
- companion_de.qm
- companion_es.qm
- companion_fi.qm
- companion_fr.qm
- companion_it.qm
- companion_pl.qm
- companion_sv.qm
- companion_zh.qm
-
+
+
+
+@TRANSLATION_FILES_LIST@
+
diff --git a/companion/src/translations/companion_cs.ts b/companion/src/translations/companion_cs.ts
index e283c6cfe..76b2edf5e 100644
--- a/companion/src/translations/companion_cs.ts
+++ b/companion/src/translations/companion_cs.ts
@@ -1,30 +1,30 @@
-
+
AileronsPage
-
+
No
Ne
-
+
Yes, controlled by a single channel
Ano, ovládané jedním kanálem
-
+
Yes, controlled by two channels
Ano, ovládané dvěma kanály
-
+
<br>First Aileron Channel:
<br>První kanál křidélek:
-
+
Second Aileron Channel:
<br>Druhý kanál křidélek:
@@ -32,27 +32,27 @@
AirbrakesPage
-
+
No
Ne
-
+
Yes, controlled by a single channel
Ano, ovládané jedním kanálem
-
+
Yes, controlled by two channels
Ano, ovládané dvěma kanály
-
+
<br>First Airbrake Channel:
<br>První kanál brzdících klapek:
-
+
Second Airbrake Channel:
<br>Druhý kanál brzdících klapek:
@@ -524,498 +524,149 @@ Může být jiná než verze firmwaru
Pamatovat si polohy přepínačů v simulátoru
-
+
My Radio
Moje rádio
-
+
Select your snapshot folder
Vyberat složku pro snímky obrazovky simulátoru
-
-
+
+
No joysticks found
Joystick nenalezen
-
+
EMPTY: No radio settings stored in profile
PRÁZDNÉ: V profilu nejsou uložena žádná nastavení rádia
-
+
AVAILABLE: Radio settings of unknown age
DOSTUPNÉ: Nastavení rádia jsou neznámého stáří
-
+
AVAILABLE: Radio settings stored %1
DOSTUPNÉ: Nastavení rádia jsou uložena %1
-
+
Select your library folder
Vyberat složkus s logy
-
-
+
+
Select your Models and Settings backup folder
Zvolit složku pro automatické zálohy modelů a nastavení
-
+
Select Google Earth executable
Zvolit spustitelnou binárku aplikace Google Earth
-
+
Select the folder replicating your SD structure
Vyberat složku která představuje obsah SD karty rádia
-
+
Not possible to remove profile
Není možné odebrat profil
-
+
The default profile can not be removed.
Výchozí profil nemůže být odstraněn.
-
+
Open Image to load
Otevřít soubor s logem
-
+
Images (%1)
Obrázky (%1)
-
- Calibration
-
-
- Form
-
-
-
-
- SQ
-
-
-
-
- SR
-
-
-
-
- LS2
-
-
-
-
- SP
-
-
-
-
- SO
-
-
-
-
- S4
-
-
-
-
- RS
-
-
-
-
- SB
-
-
-
-
- Serial Port
- Seriový port
-
-
-
-
-
-
-
-
-
-
-
-
- Beeper volume
-
-0 - Quiet. No beeps at all.
-1 - No Keys. Normal beeps but menu keys do not beep.
-2 - Normal.
-3 - Loud.
-4 - Extra loud.
- Hlasitost Bzučáku
-
-0 - Tichý. No beeps at all.
-1 - Bez kláves. Normal beeps but menu keys do not beep.
-2 - Normální.
-3 - Hlasitý.
-4 - Extra Hlasitý.
-
-
-
- OFF
- Vypnuto
-
-
-
- S-Port Mirror
- Zrcadlit S-Port
-
-
-
- Telemetry
- Telemetrie
-
-
-
- SBUS Trainer
- SBUS trenér
-
-
-
- Debug
-
-
-
-
- Rud
- Směrovka
-
-
-
-
- Mid value
- Střed
-
-
-
- Pot. 4
-
-
-
-
- Pot. 3
-
-
-
-
- Pot. 2
-
-
-
-
- Pot. 1
-
-
-
-
- PPM 1
-
-
-
-
- Stick 3
- Páka 3
-
-
-
-
- Negative span
- Negativní
-
-
-
-
- Positive span
- Pozitivní
-
-
-
- Stick 1
- Páka 1
-
-
-
- PPM 2
-
-
-
-
- Stick 2
- Páka 2
-
-
-
- Stick 4
- Páka 4
-
-
-
- v
- V
-
-
-
- PPM Multiplier
- PPM Násobič
-
-
-
- PPM 3
-
-
-
-
- PPM 4
-
-
-
-
- Battery Offset
- Ofset baterie
-
-
-
- Current Offset
- Ofset proudu
-
-
-
- S1
-
-
-
-
- S2
-
-
-
-
- S3
-
-
-
-
- SA
-
-
-
-
- Ele
- Výškovka
-
-
-
- Ail
- Křidélka
-
-
-
- Thr
- Plyn
-
-
-
- SC
-
-
-
-
- LS
-
-
-
-
- SD
-
-
-
-
- SE
-
-
-
-
- SF
-
-
-
-
- SG
-
-
-
-
- SH
-
-
-
-
- SI
-
-
-
-
- SJ
-
-
-
-
- SK
-
-
-
-
- SL
-
-
-
-
- SM
-
-
-
-
- SN
-
-
-
-
- RS2
-
-
-
-
- Bluetooth
-
-
-
-
- CalibrationPanel
-
-
-
-
- None
- Žádný
-
-
-
- 2 Positions Toggle
- 2 pozice bez aretace
-
-
-
- 2 Positions
- 2 pozice
-
-
-
- 3 Positions
- 3 pozice
-
-
-
- Pot with detent
- Pot s aretací
-
-
-
- Multipos switch
- Vícepolohový přepínač
-
-
-
- Pot without detent
- Pot bez aretace
-
-
-
- Slider with detent
- Jezdec s aretací
-
-
Channels
-
+
Name
Název
-
+
Min
-
+
Max
-
+
Subtrim
-
+
Direction
Invertovat
-
+
Curve
Křivka
-
+
PPM Center
Střed
-
+
Linear Subtrim
Symetrický
-
- Channel %1
- Kanál %1
+
+ CH%1
+
-
+
---
-
+
INV
+
+ CompanionMacros
+
+
+ files
+
+
+
+
+ Radio and Models settings
+
+
+
CompareDialog
@@ -1049,17 +700,17 @@ Může být jiná než verze firmwaru
Tisk do souboru
-
+
No name
Model nepojmenován
-
+
Print Document
Vytisknout dokument
-
+
Select PDF output file
Vyberte cílový PDF soubor
@@ -1067,7 +718,7 @@ Může být jiná než verze firmwaru
ConclusionPage
-
+
OK, I understand.
OK, rozuměl jsem.
@@ -1075,43 +726,43 @@ Může být jiná než verze firmwaru
ContributorsDialog
-
+
OpenTX Contributors
Přispěvatelé OpenTX
-
+
Main Developers
Vývojáři
-
+
Other contributors
Ostatní přispěvatelé
-
+
Companies and projects who have donated to OpenTX
Společnosti a projekty které přispěly OpenTx
-
+
People who have donated to OpenTX
Lidé kteří přispěli projektu OpenTx
-
+
Honors go to Rafal Tomczak (RadioClone), Thomas Husterer (th9x) and Erez Raviv (er9x and eePe)
Speciální poděkování patří Rafalu Tomczakovi (RadioClone),
Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
-
+
OpenTX Blacklist
-
+
monthly
měsíčně
@@ -1119,24 +770,24 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
CopyProcess
-
-
-
+
+
+
Error
Chyba
-
+
Write error
Chyba zápisu
-
+
Cannot write %1 (reason: %2)
Nelze zapsat %1 (důvod: %2)
-
+
Cannot open %1 (reason: %2)
Nelze otevřít %1 (důvod: %2)
@@ -1144,22 +795,22 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
CurveGroup
-
+
Diff
Diferenciace
-
+
Expo
Exponenciála
-
+
Func
Funkce
-
+
Curve
Křivka
@@ -1248,72 +899,72 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
Název křivky
-
+
Curve %1
Křivka %1
-
+
%1 points
%1 bodů
-
+
Linear
Lineární
-
+
Single Expo
Expo
-
+
Symmetrical f(x)=-f(-x)
Symetrická f(x)=-f(-x)
-
+
Symmetrical f(x)=f(-x)
Symetrická f(x)=f(-x)
-
+
Copy
Kopírovat
-
+
Paste
Vložit
-
+
Clear
Vymazat
-
+
Clear all curves
Vymazat všechny křivky
-
+
Are you sure you want to reset curve %1?
Opravdu chcete vymazat křivku %1?
-
+
Are you sure you want to reset all curves?
Opravdu chcete vymazat všechny křivky?
-
+
Editing curve %1
Upravit křivku k%1
-
+
Not enough free points in EEPROM to store the curve.
V nastavení modelu již nejsou volné body k uložení této křivky.
@@ -1321,88 +972,88 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
CustomFunctionsPanel
-
+
Switch
Spínač
-
+
Action
Akce
-
+
Parameters
Hodnota
-
+
Enable
Povolit
-
+
SF%1
-
+
GF%1
-
+
ON
Překlad se do formuláře nevejde.
Zap
-
+
Error
Chyba
-
+
Unable to find sound file %1!
Nemohu nalézt zvukový soubor %1!
-
+
&Delete
&Odstranit
-
+
Delete
-
+
&Copy
&Kopírovat
-
+
Ctrl+C
-
+
&Cut
V&yjmout
-
+
Ctrl+X
-
+
&Paste
&Vložit
-
+
Ctrl+V
@@ -1410,22 +1061,22 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
CyclicPage
-
+
90
-
+
120
-
+
120x
-
+
140
@@ -1433,99 +1084,175 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
DebugOutput
-
+
Debug Output
+
+
+ <html><head/><body><p>Enable or disable the filter. If the button won't stay enabled, it is likely there is a syntax error in the Regular Expression entered.</p></body></html>
+
+
+
+
+ Filter:
+
+
+
+
+ <html><head/><body><p>Enter filter text here. Click the help/info button for details about using the filter. </p><p>
+To <b>remove a remembered entry</b> from the filter list, first choose it, and then press <code>Shift-Delete</code> (or <code>Shift-Backspace</code>) key combination.</p></body></html>
+
+
+
+
+ Buffer:
+
+
+
+
+ Number of lines to keep in display.
+
+
+
+
+ Filter &Help
+
+
+
+
+ Show information about using the filter.
+
+
+
+
+ Word &Wrap
+
+
+
+
+ Toggle word wrapping on/off.
+
+
+
+
+ &Clear
+
+
+
+
+ Clear the output window of all text.
+
+
+
+
+ Enable &Filter
+
+
+
+
+ Turn the filter on/off.
+
+
+
+
+ <html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>The filter supports two syntax types: basic matching with common wildcards as well as full Perl-style (<code>pcre</code>) Regular Expressions.</p><p>By default a filter will only show lines which match (<b>inclusive</b>). To make an <b>exclusive</b> filter which removes matching lines, prefix the filter expression with a <kbd>!</kbd> (exclamation mark).</p><p>To use <b>Regular Expressions</b> (RegEx), prefix the filter text with a <kbd>/</kbd> (slash) or <kbd>^</kbd> (up caret). <ul><li>Put the <kbd>/</kbd> or <kbd>^</kbd> after the exclusive <kbd>!</kbd> indicator if you're using one.</li><li>By default the match is case-sensitive. To make it insensitive, add the typical <kbd>/i</kbd> (slash i) operator at the end of your RegEx.</li><li>If you use a caret (^) to denote a RegEx, it will become part of the Reg. Ex. (that is, matches from start of line).</li><li>If the RegEx is invalid, the filter edit field should show a red border and you will not be able to enable the filter.</li><li>A useful resource for testing REs (with a full reference) can be found at <a href="http://www.regexr.com/">http://www.regexr.com/</a></li></ul></p><p>To use <b>basic matching</b> just type any text.<ul><li>Wildcards: <kbd>*</kbd> (asterisk) matches zero or more of any character(s), and <kbd>?</kbd> (question mark) matches any single character.</li><li>The match is always case-insensitive.</li><li>The match always starts from the beginning of a log line. To ignore characters at the start, use a leading <kbd>*</kbd> wildcard.</li><li>A trailing <kbd>*</kbd> is always implied (that is, matches anything to the end of the log line). To avoid this, use a RegEx.</li><li>You can match literal wildcard characters by prefixing them with a <kbd>\</kbd> (backslash) character (eg. "foo\*bar" matches "foo*bar").</li></ul></p><p>After <b>editing text</b>, press ENTER or TAB key (or click anywhere outside the box) to update the filter.</p><p>To <b>remove an entry</b> from the filter selector list, first choose it, and while in the line editor press <kbd>Shift-Delete</kbd> (or <kbd>Shift-Backspace</kbd>) key combination. The default filters cannot be removed. Up to 50 filters are stored.</p></body></html>
+
+
+
+
+ Debug Console Filter Help
+
+
EepromInterface
-
+
Possible causes for this:
Možné příčiny:
-
+
- Eeprom is from a newer version of OpenTX
- eeprom pochází z novější verze OpenTX
-
+
- Eeprom is not from OpenTX
- eeprom nepochází z OpenTX
-
+
- Eeprom is not from Th9X
- eeprom nepochází z Th9X
-
+
- Eeprom is not from Gruvin9X
- eeprom nepochází z Gruvin9X
-
+
- Eeprom is not from ErSky9X
- eeprom nepochází z Ersky9X
-
+
- Eeprom is not from Er9X
- eeprom nepochází z Er9X
-
+
- Eeprom size is invalid
- velikost eeprom není platná
-
+
- Eeprom file system is invalid
- eeprom struktura souboru je poškozená
-
+
- Eeprom is from a unknown board
- eeprom pochází z neznámé hw platformy
-
+
- Eeprom is from the wrong board
- eeprom pochází z jiné desky
-
+
- Eeprom backup not supported
- záloha eeprom není podporována
-
+
- Something that couldn't be guessed, sorry
- problém který neumíme určit, bohužel
-
+
Warning:
Varování:
-
-
+
+
- Your radio probably uses a wrong firmware,
eeprom size is 4096 but only the first 2048 are used
Vaše rádio možná používá jiný firmware než by mělo, velikost eeprom je 4096, ale jen polovina je používána
-
+
- Your eeprom is from an old version of OpenTX, upgrading!
You should 'save as' to keep the old file as a backup.
- Vaše eeprom pochází ze starší verze openTX, aktualizuji!
Měl byste ji 'Uložit jako' pro uchování starší verze jako zálohy.
-
+
Warnings!
Pozor!
@@ -1533,12 +1260,12 @@ Měl byste ji 'Uložit jako' pro uchování starší verze jako záloh
ElevonsPage
-
+
<br>First Elevon Channel:
<br>První kanál elevonů:
-
+
Second Elevon Channel:
<br>Druhý kanál elevonů:
@@ -1655,30 +1382,50 @@ Pokud není použito, vstup je AKTIVNÍ stále.
Křivka která se aplikuje na zdroj.
-
+
Edit %1
Upravit %1
+
+
+ Click to access popup menu
+
+
+
+
+ Clear All
+
+
+
+
+ Set All
+
+
+
+
+ Invert All
+
+
FblPage
-
+
Throttle Channel:
Kanál plynu:
-
+
Yaw Channel:
Kanál bočení:
-
+
Pitch Channel:
Kanál klopení:
-
+
Roll Channel:
Kanál klonění:
@@ -1731,27 +1478,27 @@ Může být jiná než verze firmwaru
FlapsPage
-
+
No
Ne
-
+
Yes, controlled by a single channel
Ano, ovládané jedním kanálem
-
+
Yes, controlled by two channels
Ano, ovládané dvěma kanály
-
+
<br>First Flap Channel:
<br>První kanál klapek:
-
+
Second Flap Channel:
<br>Druhý kanál klapek:
@@ -1760,7 +1507,7 @@ Může být jiná než verze firmwaru
FlashEEpromDialog
-
+
Write Models and Settings to Radio
Zapsat modely a nastavení do rádia
@@ -1776,7 +1523,6 @@ Může být jiná než verze firmwaru
-
Allows Companion to write to older version of the firmware
Umožní Companion zapisovat do starší verze firmware
@@ -1785,6 +1531,11 @@ Může být jiná než verze firmwaru
Check Firmware compatibility
Zkontrolovat kompatibilitu firmware
+
+
+ <html><head/><body><p>Saves a dated copy of your eeprom to the backup folder you specified in the Companion settings before writing the current model to the radio.</p></body></html>
+
+
Backup before Write
@@ -1821,107 +1572,66 @@ Může být jiná než verze firmwaru
Zapsat do rádia
-
+
Current profile: %1
Současný profil: %1
-
+
Choose Radio Backup file
Vyberte soubor se zálohou rádia
-
-
-
-
-
-
-
-
-
-
+
+
Error
Chyba
-
-
- Unable to find file %1!
- Nemohu nalézt soubor %1!
-
-
-
-
-
- Error opening file %1:
-%2.
- Chyba při otevírání souboru %1:
-%2.
-
-
-
-
- Invalid Models and Settings File %1
- Neplatný soubor modelů a nastavení %1
-
-
-
- Error reading file %1:
-%2.
- Chyba při otevírání souboru %1:
-%2.
-
- Invalid Models and Settings file %1
- Neplatný soubor modelů a nastavení %1
-
-
-
-
-
-
+
+
+
Warning
Pozor
-
+
Wrong radio calibration data in profile, Settings not patched
Profil neobsahuje platná kalibrační data, nastavení nebyla upravena
-
+
Wrong radio setting data in profile, Settings not patched
Profil neobsahuje platná data nastavení rádia, nastavení nebyla upravena
-
-
+
Cannot write file %1:
%2.
Nelze zapsat soubor %1:
%2.
-
+
Error writing file %1:
%2.
Chyba při zápisu souboru %1:
%2.
-
+
The radio firmware belongs to another product family, check file and preferences!
Firmware rádia je z jiné rodiny produktů , zkontrolujte nastavení předvoleb!
-
+
The radio firmware is outdated, please upgrade!
Firmware rádia je zastaralý, aktualizujte ho prosím!
-
+
Cannot check Models and Settings compatibility! Continue anyway?
Nelze ověřit kompatibilitu dat modelů a nastavení! Chcete přesto pokračovat?
@@ -1999,119 +1709,119 @@ Může být jiná než verze firmwaru
Zapsat do rádia
-
+
Open Firmware File
Otevřít soubor firmwaru
-
-
-
+
+
+
Warning
Pozor
-
+
%1 may not be a valid firmware file
%1 nemusí být platný soubor firmwaru
-
-
-
-
+
+
+
+
Error
Chyba
-
+
The firmware file is not valid.
Soubor firmwaru není platný.
-
+
There is no start screen image in the firmware file.
Soubor firmware neobsahuje žádné logo.
-
+
Profile image %1 is invalid.
Obrázek profilu %1 není platný.
-
+
Open image file to use as radio start screen
Otevřít soubor obrázku pro použití jako úvodní logo
-
+
Images (%1)
Obrázky (%1)
-
+
Image could not be loaded from %1
Nelze načíst obrázek z %1
-
+
The library image could not be loaded
Nelze načíst obrázek z knihovny
-
+
Splash image not found
Obrázek loga nebyl nalezen
-
+
Cannot save customized firmware
Nelze uložit upravený firmware
-
+
Write Firmware to Radio
Zapsat firmware do rádia
-
-
+
+
Firmware check failed
Kontrola firmwaru selhala
-
+
Could not check firmware from radio
Nelze ověřit firmware v rádiu
-
+
New firmware is not compatible with the one currently installed!
Nový firmware není kompatibilní s verzí instalovanou v rádiu!
-
+
Conversion failed
Převod selhal
-
+
Cannot convert Models and Settings for use with this firmware, original data will be used
Nemohu převést modely a nastavení pro použití s tímto firmwarem, budou použita původní data
-
+
Restore failed
Obnovení selhalo
-
+
Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1
Nelze obnovit modely a nastavení rádia. Data modelů a nastavení naleznete v %1
-
+
Flashing done
Zápis firmware je dokončen
@@ -2119,47 +1829,47 @@ Může být jiná než verze firmwaru
FlashProcess
-
+
Executable %1 not found
Spustitelný soubor %1 nebyl nalezen
-
+
Writing...
Zápis...
-
+
Reading...
Načítání...
-
+
Verifying...
Ověřování...
-
+
unknown
neznámý
-
+
ie: OpenTX for 9X board or OpenTX for 9XR board
ie: OpenTX pro desku 9X nebo OpenTX pro 9XR
-
+
ie: OpenTX for M128 / 9X board or OpenTX for 9XR board with M128 chip
ie: OpenTX pro M128 / 9X nebo OpenTX pro 9XR s čipem M128
-
+
ie: OpenTX for Gruvin9X board
ie: OpenTX pro desku Gruvin9X
-
+
Your radio uses a %1 CPU!!!
Please check advanced burn options to set the correct cpu type.
@@ -2168,7 +1878,7 @@ Please check advanced burn options to set the correct cpu type.
Zkontrolujte prosím rozšířená nastavení programátoru a nastavte správný typ CPU.
-
+
Your radio uses a %1 CPU!!!
Please select an appropriate firmware type to program it.
@@ -2177,7 +1887,7 @@ Please select an appropriate firmware type to program it.
Vyberte prosím správný typ firmwaru.
-
+
You are currently using:
%1
@@ -2186,7 +1896,7 @@ Nyní používáte:
%1
-
+
Your radio does not seem connected to USB or the driver is not installed!!!
Please use ZADIG to properly install the driver.
@@ -2195,22 +1905,22 @@ Please use ZADIG to properly install the driver.
Prosím, použijte program Zadig pro správnou instalaci ovladače.
-
+
Your radio does not seem connected to USB or the driver is not initialized!!!.
Vaše rádio není připojeno k USB nebo není inicializován ovladač!.
-
+
Flashing done (exit code = %1)
Zápis je dokončen (exit code = %1)
-
+
Flashing done with errors
Zápis byl dokončen s chybami
-
+
FUSES: Low=%1 High=%2 Ext=%3
POJISTKY MCU: Low=%1 High=%2 Ext=%3
@@ -2241,35 +1951,65 @@ Prosím, použijte program Zadig pro správnou instalaci ovladače.
FlightModePanel
-
+
Rotary Encoder %1
Otočný enkodér %1
-
+
+ Name
+ Název
+
+
+
+ Value source
+
+
+
+
+ Value
+ Hodnota
+
+
+
GVAR%1
GP%1
-
+
Popup enabled
Vyskakovací okno povoleno
+
+
+ &Clear
+
+
+
+
+ Clear
+ Vymazat
+
+
+
+ Clear all current Flight Mode properties?
+
+
FlightModesPanel
-
+
Flight Mode %1
Letový režim %1
-
+
(%1)
-
+
(default)
(výchozí)
@@ -2277,17 +2017,17 @@ Prosím, použijte program Zadig pro správnou instalaci ovladače.
FlybarSelectionPage
-
+
Has Flybar
Má stabilizátor(Flybar)
-
+
Flybarless
Bez stabilizátoru (Flybarless)
-
+
Flybar:
Stabilizátor:
@@ -2393,24 +2133,19 @@ p, li { white-space: pre-wrap; }
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Provádějte pouze pokud opravdu víte co děláte.</p></body></html>
-
-
+
+
Reset Radio Fuses
-
+
Read Fuses from Radio
GeneralEdit
-
-
- General Edit
- Obecná nastavení
-
Store calib. and hw settings in selected profile
@@ -2421,6 +2156,11 @@ p, li { white-space: pre-wrap; }
Retrieve calib. and hw settings from profile
Získat kalibraci a HW nastavení z profilu
+
+
+ Radio settings
+
+
General settings used throught the transmitter.
@@ -2429,48 +2169,59 @@ These will be relevant for all models in the same EEPROM.
Tyto volby jsou platné pro všechny modely v jedné EEPROM.
-
+
Setup
Nastevní
-
+
Trainer
Trenér
-
+
Global Functions
Globální funkce
-
- Hardware / Calibration
- Hardware / Kalibrace
+
+ Hardware
+
-
-
+
+ Calibration
+
+
+
+
+
+
Warning
Pozor
-
+
Wrong data in profile, radio calibration was not retrieved
Špatná data v profilu, není možné získat parametry kalibrace
-
+
+ Wrong data in profile, Switch/pot config not retrieved
+
+
+
+
Wrong data in profile, hw related parameters were not retrieved
Špatná data v profilu, není možné získat HW parametry
-
+
Do you want to store calibration in %1 profile<br>overwriting existing calibration?
Chcete uložit kalibraci do profilu %1<br>Přepsat existující kalibraci?
-
+
Calibration and HW parameters saved.
Kalibrace a HW parametry byly uloženy.
@@ -2528,173 +2279,172 @@ Tyto volby jsou platné pro všechny modely v jedné EEPROM.
-
+
Timeshift from UTC
Časový posun od UTC
-
+
Voice Language
Jazyk hlasových zpráv
-
+
Country Code
Kód země
-
+
Stick reverse
Revers os kniplů
-
+
FAI Mode
FAI mód
-
-
+
If you enable FAI, you loose the vario, the play functions, the telemetry screen. This function cannot be disabled by the radio.
FAI je soutéžní mód (www.fai.org), zablokuje vario, zobrazení telemetrie a funkce hlasového hlášení. Tuto funkci nelze vypnout v menu rádia.
-
+
Adjust RTC
Nastavit RTC
-
+
Vario pitch at max
Tón varia na maximu
-
-
+
+
Hz
-
+
Speaker Volume
Hlasitost reproduktoru
-
+
Backlight Switch
Spínač podsvětlení
-
+
Sound Mode
Mód zvuku
-
+
Color 1
Barva 1
-
+
Color 2
Barva 2
-
+
Speaker Pitch (spkr only)
Tón zvuku (pouze spkr)
-
+
If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.
Pokud tato hodnota není nula, každé stisknutí klávesy zapne podsvétlení a vypne ho až po uplynutí nastaveného počtu sekund.
-
+
sec
s
-
+
Backlight color
Barva podsvětlení
-
+
Beeper
Bzučák
-
+
Speaker
Reproduktor
-
+
BeeperVoice
Bzučák+Hlas
-
+
SpeakerVoice
Repro+Hlas
-
+
Beep volume
Upozornění
-
+
Wav volume
Wav soubor
-
+
Vario volume
Vario
-
+
Background volume
Zvuk v pozadí
-
-
+
+
ms
-
+
Backlight Auto OFF after
Auto. vypnutí podsvětlení po
-
+
Backlight flash on alarm
Blik. podsvětlením při alarmu
-
+
Vario pitch at zero
Tón varia na nule
-
+
Vario repeat at zero
Opakování varia na nule
-
+
This is the switch selectrion for turning on the backlight (if installed).
Toto je volba spínače který zapne podsvětlení (pokud je nainstalováno).
-
-
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -2709,32 +2459,42 @@ p, li { white-space: pre-wrap; }
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Hodnoty mohou být 20-45</span></p></body></html>
-
+
Backlight Brightness
Jas podsvětlení
-
+
RotEnc Navigation
Navigace otočným enkodérem
-
+
+ Automatically adjust the radio's clock if a GPS is connected to telemetry.
+
+
+
+
America
Amerika
-
+
Japan
Japonsko
-
+
Europe
Evropa
-
+
+ Backlight OFF Brightness
+
+
+
+
Mode selection:
Mode 1:
@@ -2775,271 +2535,271 @@ Mode 4:
-
+
Mode 1 (RUD ELE THR AIL)
Mód1 (Směr.Výšk.Plyn.Křid)
-
+
Mode 2 (RUD THR ELE AIL)
Mód2 (Směr.Plyn.Výšk.Křid)
-
+
Mode 3 (AIL ELE THR RUD)
Mód3 (Křid.Výšk.Plyn.Směr)
-
+
Mode 4 (AIL THR ELE RUD)
Mód4 (Křid.Plyn.Výšk.Směr)
-
+
<html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
<html><head/><body><p>Pořadí kanálů</p><p><br/></p><p>Definuje výchozí pořadí kanálů použité při vytvoření nového modelu.</p></body></html>
-
+
R E T A
S V P K
-
+
R E A T
S V K P
-
+
R T E A
S P V K
-
+
R T A E
S P K V
-
+
R A E T
S K V P
-
+
R A T E
S K P V
-
+
E R T A
V S P K
-
+
E R A T
V S K P
-
+
E T R A
V P S K
-
+
E T A R
V P K S
-
+
E A R T
V K S P
-
+
E A T R
V K P S
-
+
T R E A
P S V K
-
+
T R A E
P S K V
-
+
T E R A
P V S K
-
+
T E A R
P V K S
-
+
T A R E
P K S V
-
+
T A E R
P K V S
-
+
A R E T
K S V P
-
+
A R T E
K S P V
-
+
A E R T
K V S P
-
+
A E T R
K V P S
-
+
A T R E
K P S V
-
+
A T E R
K P V S
-
+
Stick Mode
Výchozí mód vysílačky
-
+
Metric
Metrické
-
+
Imperial
Imperiální
-
+
Default Channel Order
Výchozí pořadí kanálů
-
+
GPS Coordinates
Souřadnice GPS
-
+
Min
-
-
+
+
v
V
-
+
Max
-
+
Low Memory Warning
Upozornit na nedostatek paměti
-
+
Inactivity Timer
Časovač nečinnosti
-
+
Show Splash Screen on Startup
Zobrazit úvodní logo
-
+
Contrast
Kontrast
-
+
Battery Meter Range
Rozsah ukazatele baterie
-
+
Haptic Strength
Síla vibrací
-
+
LCD Display Type
Typ LCD zobrazovače
-
+
"No Sound" Warning
Upozornění na vypnutý zvuk
-
+
Battery Warning
Alarm baterie
-
+
Haptic Length
Délka vibrací
-
+
MAVLink Baud Rate
-
-
+
+
Quiet
Tichý
-
+
Only Alarms
Jen alarm
-
-
+
+
No Keys
Bez kláves
-
-
+
+
All
Vše
-
+
Battery warning voltage.
This is the threashhold where the battery warning sounds.
@@ -3048,114 +2808,114 @@ Acceptable values are 5v..10v
Použitelné hodnoty jsou 5v..10v
-
+
Standard
-
+
Optrex
-
+
If not zero will sound beeps if the transmitter has been left without inputs for the specified number of minutes.
Pokud není nastaveno na nulu, bude zapnuto zvukové upozornění, že jste rádio nechali bez povšimnutí nastavený počet minut.
-
+
min
-
-
+
+
Show splash screen on startup
Zobrazit úvodní logo při zapnutí vysílčky
-
+
---
-
+
2s
-
+
3s
-
+
4s
-
+
6s
-
+
8s
-
+
10s
-
+
15s
-
+
4800 Baud
-
+
9600 Baud
-
+
14400 Baud
-
+
19200 Baud
-
+
38400 Baud
-
+
57600 Baud
-
+
76800 Baud
-
+
115200 Baud
-
-
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -3170,72 +2930,72 @@ p, li { white-space: pre-wrap; }
-
-
+
+
X-Short
Extra krátký
-
-
+
+
Short
Krátký
-
-
+
+
Normal
Normální
-
-
+
+
Long
Dlouhý
-
-
+
+
X-Long
Extra dlouhý
-
-
+
+
hh° (N/S) mm' ss''.dd
-
+
NMEA
-
+
Play Delay (switch mid position)
Přechod střední polohy přepínače
-
+
Measurement Units
Měrné jednotky
-
+
Haptic Mode
Mód vibrací
-
+
Beeper Length
Délka zvuku
-
+
Beeper Mode
Mód zvuku
-
+
Beeper volume
0 - Quiet. No beeps at all.
@@ -3252,7 +3012,7 @@ p, li { white-space: pre-wrap; }
4 - Extra Hlasitý.
-
+
Alarms Only
Jen alarmy
@@ -3260,7 +3020,7 @@ p, li { white-space: pre-wrap; }
GeneralSetupPanel
-
+
If you enable FAI, you loose the vario, the play functions, the telemetry screen.
This function cannot be disabled by the radio.
Are you sure ?
@@ -3273,21 +3033,324 @@ Opravdu to takto chcete ?
GyroPage
-
+
No
Ne
-
+
Yes, controled by a switch
Ano, ovládané spínačem
-
+
Yes, controlled by a pot
Ano, ovládané potenciomerem
+
+ Hardware
+
+
+ Form
+
+
+
+
+ SQ
+
+
+
+
+ SR
+
+
+
+
+ LS2
+
+
+
+
+ SP
+
+
+
+
+ SO
+
+
+
+
+ S4
+ S4
+
+
+
+ RS
+
+
+
+
+ SB
+
+
+
+
+ PPM 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Beeper volume
+
+0 - Quiet. No beeps at all.
+1 - No Keys. Normal beeps but menu keys do not beep.
+2 - Normal.
+3 - Loud.
+4 - Extra loud.
+
+
+
+
+ OFF
+
+
+
+
+ S-Port Mirror
+ Zrcadlit S-Port
+
+
+
+ Telemetry
+ Telemetrie
+
+
+
+ SBUS Trainer
+ SBUS trenér
+
+
+
+ Debug
+
+
+
+
+ Rud
+ Směrovka
+
+
+
+ PPM 3
+
+
+
+
+ S1
+ S1
+
+
+
+ S2
+ S2
+
+
+
+ S3
+ S3
+
+
+
+ PPM 1
+
+
+
+
+ Serial Port
+ Seriový port
+
+
+
+ v
+ V
+
+
+
+ PPM Multiplier
+ PPM Násobič
+
+
+
+ Current Offset
+ Ofset proudu
+
+
+
+ PPM 4
+
+
+
+
+ SA
+
+
+
+
+ Ele
+ Výškovka
+
+
+
+ Ail
+ Křidélka
+
+
+
+ Thr
+
+
+
+
+ SC
+
+
+
+
+ LS
+
+
+
+
+ SD
+
+
+
+
+ Battery Offset
+ Ofset baterie
+
+
+
+ SE
+
+
+
+
+ SF
+
+
+
+
+ SG
+
+
+
+
+ SH
+
+
+
+
+ SI
+
+
+
+
+ SJ
+
+
+
+
+ SK
+
+
+
+
+ SL
+
+
+
+
+ SM
+
+
+
+
+ SN
+
+
+
+
+ RS2
+
+
+
+
+ Bluetooth
+
+
+
+
+ ADC Filter
+
+
+
+
+ HardwarePanel
+
+
+
+
+ None
+ Žádný
+
+
+
+ 2 Positions Toggle
+ 2 pozice bez aretace
+
+
+
+ 2 Positions
+ 2 pozice
+
+
+
+ 3 Positions
+ 3 pozice
+
+
+
+ Pot with detent
+ Pot s aretací
+
+
+
+ Multipos switch
+ Vícepolohový přepínač
+
+
+
+ Pot without detent
+ Pot bez aretace
+
+
+
+ Slider with detent
+ Jezdec s aretací
+
+
Heli
@@ -3364,22 +3427,22 @@ Opravdu to takto chcete ?
HeliPage
-
+
Throttle Channel:
Kanál plynu:
-
+
Yaw Channel:
Kanál bočení:
-
+
Pitch Channel:
Kanál klopení:
-
+
Roll Channel:
Kanál klonění:
@@ -3387,122 +3450,122 @@ Opravdu to takto chcete ?
InputsPanel
-
-
+
+
Move Up
Posunout nahoru
-
-
+
+
Ctrl+Up
Ctrl+Nahoru
Ctrl+Up
-
-
+
+
Move Down
Posunout dolů
-
-
+
+
Ctrl+Down
Ctrl+Dolů
-
+
Clear All Inputs
Vymazat všechny vstupy
-
+
Not enough available inputs!
Již nejsou další volné vstupy!
-
+
Delete Selected Inputs?
Vymazat vybrané vstupy?
-
+
&Add
&Přidat
-
+
Ctrl+A
-
+
&Edit
&Upravit
-
+
Enter
-
+
&Delete
V&ymazat
-
+
Delete
-
+
&Copy
&Kopírovat
-
+
Ctrl+C
-
+
&Cut
Vyj&mout
-
+
Ctrl+X
-
+
&Paste
&Vložit
-
+
Ctrl+V
-
+
Du&plicate
&Duplikovat
-
+
Ctrl+U
-
+
Clear Inputs?
Vymazat vstupy?
-
+
Really clear all the inputs?
Opravdu chcete vymazat všechny vstupy?
@@ -3510,88 +3573,89 @@ Opravdu to takto chcete ?
LogicalSwitchesPanel
-
+
V1
-
+
V2
-
+
Duration
Trvání
-
+
Delay
Zpoždění
-
+
Function
Funkce
-
+
AND Switch
AND spínač
-
+
L%1
-
-
+
+
(instant)
-
+
&Delete
Vy&mazat
-
+
Delete
-
+
&Copy
&Kopírovat
-
+
+
(infinite)
-
+
Ctrl+C
-
+
&Cut
V&yjmout
-
+
Ctrl+X
-
+
&Paste
&Vložit
-
+
Ctrl+V
@@ -3604,146 +3668,166 @@ Opravdu to takto chcete ?
Prohlížeč logu
-
+
Filename
Soubor
-
+
Open LogFile
Otevřít
-
+
Zoom
-
+
X
-
+
Y
-
+
Reset
-
+
Fly sessions
Lety
-
+
Telemetry logs
Logy telemetrie
-
+
Time (hh:mm:ss)
Čas (hh:mm:ss)
-
+
Plot Title Change
-
+
New plot title:
-
+
Axis Label Change
-
+
New axis label:
-
+
Graph Name Change
-
+
New graph name:
-
+
Error: no GPS data not found
-
+
The column containing GPS coordinates must be named "GPS".
The columns for altitude "GAlt" and for speed "GSpd" are optional
-
+
Error
Chyba
-
+
Cannot write file %1:
%2.
Nelze zapsat soubor %1:
%2.
-
+
+ Cursor A: %1 m
+
+
+
+
+ Cursor B: %1 m
+
+
+
+
+ Time delta: %1
+
+
+
+
+ Climb rate: %1 m/s
+
+
+
+
Select your log file
Vyberte soubor s logy
-
+
Available fields
Dostupná pole
-
+
The selected logfile contains %1 invalid lines out of %2 total lines
Zvolený soubor logu obsahuje %1neplatných řádků z celkových %2
-
+
total duration
-
+
duration
-
+
(L1)
-
+
(R1)
-
+
(L2)
-
+
(R2)
@@ -3751,261 +3835,239 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
MainWindow
-
-
-
-
+
+
File loaded
Soubor byl načten
-
+
Display previous warning again at startup ?
Chcete zobrazit předchozí upozornění i příště ?
-
+
Checking for updates
Kontroluji aktualizace
-
+
Unable to check for updates.
Nelze ověřit aktualizace.
-
-
+
+
Save As
Uložit jako
-
+
Executable (*.exe)
Spustitelný (*.exe)
-
+
New release available
Je dostupné nové vydání
-
-
+
+
No updates available at this time.
Žádné aktualizace nejsou nyní dostupné.
-
+
Would you like to launch the installer?
Chcete spustit instalátor?
-
-
+
+
Error
Chyba
-
+
Error opening file %1:
%2.
Chyba při otevírání souboru %1:
%2.
-
- Compilation server termporary failure, try later
- Server companion je dočasně nedostupný, zkuste to později
-
-
-
+
A new release of Companion is available, please check the OpenTX website!
Je dostupná nová verze Companion, prosím navštivte internetové stránky OpenTX!
-
- Not enough memory for all the selected firmware options
- Není dostatek paměti pro všechny zvolené vlastnosti firmwaru
-
-
-
+
Compilation server too busy, try later
Server companion je zaneprázdněn, zkuste to později
-
+
Unknown server failure, try later
Neznámá chyba serveru, zkuste to později
-
+
Do you want to write the firmware to the radio now ?
Chcete zapsat firmware do rádia nyní?
-
-
+
+
Yes
Ano
-
-
+
+
No
Ne
-
-
+
+
Release Notes
Poznámky k vydání
-
-
+
+
Do you want to download release %1 now ?
Chcete nyní stáhnout vydání %1 ?
-
-
+
+
File saved
Soubor byl uložen
-
+
Firmware updates
Aktualizace firmwaru
-
+
Current firmware does not provide release notes informations.
K tomuto firmwaru nejsou poznámky k vydání.
-
+
A new version of Companion is available (version %1)<br>Would you like to download it?
Je dostupná nová verze Companion (verze %1)<br>Chcete ji nyní stáhnout?
-
- Compilation server requires registration, please check OpenTX web site
- Kompilační server vyžaduje registraci, prosím navštivte internetové stránky OpenTX
-
-
-
+
Ignore this release %1?
Ignorovat tuto verzi %1?
-
- The selected language will be used the next time you start Companion.
- Zvolený jazyk bude použit při příštím spuštění Companion.
-
-
-
+
The new theme will be loaded the next time you start Companion.
Nové téma bude použito při příštím spuštění Companion.
-
+
The icon size will be used the next time you start Companion.
Zvolená velikost ikon bude použita při příštím spuštění Companion.
-
+
The OpenTX Companion project was originally forked from <a href='%1'>eePe</a>
Projekt OpenTX Companion vznikl oddělením z <a href='%1'>eePe</a>
-
+
Load backup from file
Načíst zálohu ze souboru
-
-
+
+
Open Models and Settings file
Otevřít soubor modelů a nastavení
-
+
Read Models and Settings From Radio
Načíst modely a nastavení z rádia
-
+
Save Radio Backup to File
Uložit zálohu rádia do souboru
-
+
Read Radio Firmware to File
Načíst firmware rádia do souboru
-
+
OpenTX Home Page: <a href='%1'>%1</a>
Internetová stránka OpenTX : <a href='%1'>%1</a>
-
+
If you've found this program useful, please support by <a href='%1'>donating</a>
Pokud vám byl tento program užitečný, podpořte jej <a href='%1'>darem</a>
-
+
Copyright OpenTX Team
-
+
About Companion
O aplikaci Companion
-
+
New
Nový
-
+
Open...
Otevřít
-
+
Save
Uložit
-
+
Save As...
Uložit jako...
-
+
Copy Model
Kopírovat model
-
+
Paste Model
Vložit model
-
+
Compare models
Porovnat modely
-
+
Exit the application
Ukončit aplikaci
-
+
Firmware %1 does not seem to have ever been downloaded.
Release %2 is available.
Do you want to download it now?
@@ -4018,7 +4080,7 @@ Chcete ho stáhnout nyní?
Doporučujeme prohlédnout poznámky k vydání, pomocí tlačítka níže se dozvíte o případných změnách, které mohou být pro vás důležité.
-
+
A new version of %1 firmware is available:
- current is %2
- newer is %3
@@ -4035,574 +4097,533 @@ Chcete firmware stáhnout nyní?
Doporučujeme prohlédnout poznámky k vydání, pomocí tlačítka níže se dozvíte o případných změnách, které mohou být pro vás důležité.
-
-
+
+
Synchronize SD
Synchronizace SD
-
+
A monochrome black icon theme
Černé mono téma
-
+
A monochrome white icon theme
Bílé mono téma
-
+
A monochrome blue icon theme
Modré mono téma
-
+
Small
Malá
-
+
Use small toolbar icons
Použít malé ikony nástrojové lišty
-
+
Use normal size toolbar icons
Použít normální velikost ikon nástrojové lišty
-
+
Normal
Normální
-
+
Use big toolbar icons
Použít velké ikony nástrojové lišty
-
+
Big
Velká
-
+
Use huge toolbar icons
Použít největší ikony nástrojové lišty
-
+
Huge
Největší
-
+
Create a new Models and Settings file
Vytvořit nový soubor modelů a nastavení
-
-
+
+
Save Models and Settings file
Uložit soubor modelů a nastavení
-
+
Exit
Ukončit
-
+
Cut Model
Vyjmout model
-
+
Cut current model to the clipboard
Vyjmout aktuální model a uložit do schránky
-
+
Copy current model to the clipboard
Kopírovat aktuální model do schránky
-
+
Paste model from clipboard
Vložit obsah schránky na aktuální pozici
-
+
Classical
Klasik9x
-
+
The classic companion9x icon theme
Původní téma companion9x
-
+
Yerico
-
+
Yellow round honey sweet icon theme
Žluté medové téma
-
+
Monochrome
Mono
-
+
MonoWhite
Mono-bílé
-
+
MonoBlue
Mono-modré
-
+
System language
Výchozí jazyk prostředí
-
- Use system language in menus
- Použít systémový jazyk
-
-
-
- Czech
- Čeština
-
-
-
- Use Czech in menus
- Aplikace v českém jazyce
-
-
-
- German
-
-
-
-
- Use German in menus
-
-
-
-
- English
-
-
-
-
- Use English in menus
-
-
-
-
- Finnish
-
-
-
-
- Use Finnish in menus
-
-
-
-
- French
-
-
-
-
- Use French in menus
-
-
-
-
- Italian
-
-
-
-
- Use Italian in menus
-
-
-
-
- Polish
-
-
-
-
- Use Polish in menus
-
-
-
-
- Spanish
-
-
-
-
- Use Spanish in menus
-
-
-
-
- Swedish
-
-
-
-
- Use Swedish in menus
-
-
-
-
+
About...
O aplikaci
-
+
Print...
Tisk
-
+
Print current model
Vytisknout zvolený model
-
+
Simulate...
Simulace
-
+
Simulate current model
Simulace vybraného modelu
-
+
Alt+S
-
+
Load Backup...
Načíst zálohu...
-
+
View Log File...
Zobrazit Log
-
+
Open and view log file
Otevře a zobrazí soubor logu rádia
-
+
Settings...
Předvolby...
-
+
Edit Settings
Upravit nastavení předvoleb
-
+
Download...
Stáhnout
-
+
Download firmware and voice files
Stáhnout firmware a hlasové soubory
-
+
Check for Updates...
Zkontrolovat aktualizace
-
+
Check OpenTX and Companion updates
Zkontrolovat aktualizace OpenTX a Companion
-
+
Companion Changes...
Změny Companion
-
+
Show Companion change log
Zobrazí seznam změn jednotlivých vydání Companion
-
+
Firmware Changes...
Změny Firmwaru
-
+
Show firmware change log
Zobrazí seznam změn jednotlivých vydání Firmware
-
+
Compare Models...
Porovnat modely...
-
+
Edit Radio Splash Image...
Upravit úvodní logo rádia...
-
+
Edit the splash image of your Radio
Upravit úvodní grafické logo rádia
-
+
List programmers...
Seznam programátorů...
-
+
Fuses...
Pojistky mikrokontroléru...
-
-
+
+
Read Firmware from Radio
Načíst firmware z rádia
-
+
Read firmware from Radio
Načíst firmware z rádia
-
-
+
Write Firmware to Radio
Zapsat firmware do rádia
-
+
Write firmware to Radio
Zapsat firmware do rádia
-
+
Add Radio Profile
Nový profil rádia
-
+
Create a new Radio Setting Profile
Vytvořit nový profil nastavení rádia
-
+
Manuals and other Documents
Manuály a jiné dokumenty
-
+
Open the OpenTX document page in a web browser
Otevřít stránku s dokumenty OpenTX v prohlížeči
-
+
Write Models and Settings To Radio
Zapsat modely a nastavení do rádia
-
-
+
Write Models and Settings to Radio
Zapsat modely a nastavení do rádia
-
-
-
+
+
+
Companion
-
-
+
+ Not enough flash available on this board for all the selected options
+
+
+
+
+ Compilation server temporary failure, try later
+
+
+
+
+ Compilation error
+
+
+
+
+ Invalid firmware
+
+
+
+
+ Invalid board
+
+
+
+
+ Invalid language
+
+
+
+
+ Some text will not be translated until the next time you start Companion. Please note that some translations may not be complete.
+
+
+
+
+
Read Models and Settings from Radio
Načíst modely a nastavení z rádia
-
+
+ Models and Settings read
+
+
+
+
+
+ This function is not yet implemented
+
+
+
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
OpenTX Companion %1 - Rádio: %2 - Profil: %3
-
+
Configure Communications...
Nastavení propojení
-
+
Configure software for communicating with the Radio
Nastavení softwaru pro komunikaci s rádiem
-
+
Write Backup to Radio
Zapsat zálohu do rádia
-
+
Write Backup from file to Radio
Zapsat zálohu ze souboru do rádia
-
+
Backup Radio to File
Zálohovat rádio do souboru
-
+
Save a complete backup file of all settings and model data in the Radio
Uložit kompletní zálohu modelů a nastavení rádia
-
+
Contributors...
Přispěvatelé
-
+
A tribute to those who have contributed to OpenTX and Companion
Hold těm, kteří přispěli k OpenTX a Companion
-
+
SD card synchronization
Syncronizace SD karty se složkou s daty
-
+
+ Use default system language.
+
+
+
+
+ Use %1 language (some translations may not be complete).
+
+
+
+
Recent Files
Nedávné soubory
-
+
Recent Models+Settings
Nedávné modely a nastavení
-
+
Set Icon Theme
Téma ikon
-
+
Set Icon Size
Velikost ikon
-
+
Show the list of radio profiles
Výběr profilů rádia
-
+
Write
Zápis
-
+
New Radio
Nové rádio
-
+
List available programmers
Seznam použitelných programátorů
-
+
Show fuses dialog
Zobrazit dialog nastavení pojistek mikrokontroléru
-
+
Show the application's About box
O aplikaci Companion
-
+
Set Menu Language
Nastavení jazyka
-
-
+
+
File
Soubor
-
-
+
+
Edit
Úpravy
-
+
Settings
Nastavení
-
+
Read/Write
Čtení/Zápis
-
-
+
+
Help
Nápověda
-
-
+
+
Radio Profile
Profil rádia
-
+
Show recent Models+Settings documents
Nedávné dokumenty modelů a nastavení rádia
-
+
Ready
Připraven
-
+
%2
@@ -4610,134 +4631,260 @@ Doporučujeme prohlédnout poznámky k vydání, pomocí tlačítka níže se do
MdiChild
-
+
free bytes
volné[B]
-
+
Editing model %1:
Editace modelu %1:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
Error
Chyba
-
-
+
Unable to find file %1!
Nemohu nalézt soubor %1!
-
-
-
-
+
Error opening file %1:
%2.
Chyba při otevírání souboru %1:
%2.
-
-
- Invalid EEPROM File %1
- Neplatný soubor EEPROM %1
-
-
-
-
+
Error reading file %1:
%2.
Chyba při otevírání souboru %1:
%2.
-
- Invalid binary EEPROM File %1
- Neplatný binární soubor EEPROM %1
-
-
-
-
-
-
+
+
+
+
Save As
Uložit jako
-
-
-
-
- Cannot write file %1:
-%2.
- Nelze zapsat soubor %1:
-%2.
-
-
-
-
- Error writing file %1:
-%2.
- Chyba při zápisuí souboru %1:
-%2.
-
-
-
+
Open backup Models and Settings file
Otevřít zálohu modelů a nastavení rádia
-
+
+
Companion
+
+
+ Delete selected models?
+
+
+
+
+ Cannot delete default model.
+ Nelze odstranit výchozí model.
+
+
+
+ &Edit
+ &Upravit
+
+
+
+ &Restore from backup
+ &Obnovit ze zálohy
+
+
+
+ &Model Wizard
+ &Průvodce nastavením modelu
+
+
+
+ &Delete
+
+
+
+
+ Delete
+
+
+
+
+ &Copy
+ &Kopírovat
+
+
+
+ Ctrl+C
+
+
+
+
+ &Cut
+
+
+
+
+ Ctrl+X
+
+
+
+
+
+ &Paste
+ &Vložit
+
+
+
+
+ Ctrl+V
+
+
+
+
+ D&uplicate
+ &Duplikovat
+
+
+
+ Ctrl+U
+
+
+
+
+ Move to Category
+
+
+
+
+ &Use as default
+ &Použít jako výchozí
+
+
+
+ P&rint model
+ Vy&tisknout model
+
+
+
+ Ctrl+P
+
+
+
+
+ &Simulate model
+ &Simulovat model
+
+
+
+ Alt+S
+
+
+
+
+ &Add model
+
+
+
+
+ &Rename category
+
+
+
+
+ &Delete category
+
+
+
+
+ &Add category
+
+
+
+
+ Models and settings will be automatically converted.
+If that is not what you intended, please close the file
+and choose the correct radio type/profile before reopening it.
+
+
+
+
+ Do you want to overwrite radio general settings?
+ Chcete přepsat obecná nastavení rádia?
+
+
+
+ You are pasting on an not empty model, are you sure?
+ Vkládáte do modelu který není prázdný, jste si jist?
+
+
+
+ This category is not empty!
+
+
+ New model
+
+
+
+
%1 has been modified.
Do you want to save your changes?
%1 byl změněn.
Chcete ho uložit?
-
+
+ Unable to find Horus radio SD card!
+
+
+
+
+ Models and Settings written
+
+
+
+
Cannot write temporary file!
Nelze zapsat dočasný soubor!
-
-
-
-
+
Warning
Varování
-
+
Invalid binary backup File %1
Neplatný binární soubor zálohy %1
+
+
+ Radio settings
+
+
+
+
+ Simulate Tx
+ Simulace Rádia
+
MixerDialog
@@ -4946,139 +5093,159 @@ p, li { white-space: pre-wrap; }
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Pokud je nastaveno zpomalení, nastavená hodnota udává rychlost mixu -> hodnota udává počet sekund které trvá změna hodnoty z -100 na 100.</p></body></html>
-
+
DEST -> CH%1
+
+
+ Click to access popup menu
+
+
+
+
+ Clear All
+
+
+
+
+ Set All
+
+
+
+
+ Invert All
+
+
MixesPanel
-
-
+
+
Move Up
Posunout nahoru
-
-
+
+
Ctrl+Up
Ctrl+Nahoru
-
-
+
+
Move Down
Posunout dolů
-
-
+
+
Ctrl+Down
Ctrl+Dolů
-
+
Clear Mixes
Vymazat všechny mixy
-
+
Not enough available mixers!
Není k dispozici dostatek mixů!
-
+
Delete Selected Mixes?
Odstranit vybrané mixy?
-
+
&Add
&Přidat
-
+
Ctrl+A
-
+
&Edit
&Upravit
-
+
Enter
-
+
&Toggle highlight
Přepnout &zvýraznění
-
+
Ctrl+T
-
+
&Delete
&Odstranit
-
+
Delete
-
+
&Copy
&Kopírovat
-
+
Ctrl+C
-
+
Ctrl+X
-
+
C&ut
&Vyjmout
-
+
&Paste
&Vložit
-
+
Ctrl+V
-
+
Du&plicate
&Duplikovat
-
+
Ctrl+U
-
+
Clear Mixes?
Vymazat mixy?
-
+
Really clear all the mixes?
Opravdu vymazat všechny mixy?
@@ -5096,52 +5263,52 @@ p, li { white-space: pre-wrap; }
Simulace
-
+
Setup
Nastevní
-
+
Heli
-
+
Inputs
Vstupy(DR/Expo)
-
+
Logical Switches
Logické spínače
-
+
Mixes
Mixer
-
+
Flight Modes
Letové režimy
-
+
Outputs
Výstupy
-
+
Curves
Křivky
-
+
Special Functions
Speciální funkce
-
+
Telemetry
Telemetrie
@@ -5149,281 +5316,308 @@ p, li { white-space: pre-wrap; }
ModelPrinter
-
+
%1 bytes
%1 bajtů
-
+
CH%1
-
+
Exponential
Exponenciální
-
+
Extra Fine
Extra jemný
-
+
Fine
Jemný
-
+
Medium
Střední
-
+
Coarse
Hrubý
-
+
Unknown
Neznámý
-
+
Enabled
Povoleno
-
+
Disabled
Zakázáno
-
+
%1, Channels(%2-%3), PPM delay(%4usec), Pulse polarity(%5)
%1, Kanály(%2-%3), PPM pauza(%4usec), Polarita pulzů(%5)
-
+
%1, Channels(%2-%3)
%1, Kanály(%2-%3)
-
+
Receiver number(%1)
Přijímač číslo(%1)
-
+
+ radio Protocol %1, subType %2, option value %3
+
+
+
+
Slave/Jack
Žák/Jack konektor
-
+
Master/SBUS Module
Učitel/SBUS modul
-
+
Master/CPPM Module
Učitel/CPPM modul
-
+
Master/SBUS in battery compartment
Učitel/SBUS konektor v šachtě baterie
-
+
Master/Jack
Učitel/Jack konektor
-
+
+ 90
+ CH9X {90?}
+
+
+
+ 120
+ CH9X {120?}
+
+
+
+ 120X
+ CH9X {120X?}
+
+
+
+ 140
+ CH9X {140?}
+
+
+
Rudder
Směrovka
-
+
Elevator
Výškovka
-
+
Throttle
Plyn
-
+
Aileron
Křidélka
-
+
Name(%1)
Název(%1)
-
+
Persistent
Trvalé
-
+
MinuteBeep
Oznamovat minuty
-
+
CountDown(Beeps)
Odečítat (Zvuk)
-
+
CountDown(Voice)
Odečítat (Hlas)
-
+
CountDown(Haptic)
Odečítat (Vibrace)
-
+
+
Off
Vypnuto
-
-
-
-
+
+
+
+
FM%1
LR%1
-
+
FM%1%2
LR%1%2
-
+
FM%1+%2
LR%1+%2
-
+
[I%1]
-
+
Input%1
Vstup%1
-
+
Weight
Váha
-
+
Switch
Spínač
-
-
+
+
NoTrim
Žádný trim
-
+
Weight(%1)
Váha(%1)
-
+
Switch(%1)
Spínač(%1)
-
+
No DR/Expo
Bez DR/Expo
-
+
+
Offset(%1)
Ofset(%1)
-
+
Delay(u%1:d%2)
Zpoždění(u%1:d%2)
-
+
Slow(u%1:d%2)
Zpomalení(u%1:d%2)
-
+
Warn(%1)
Varování(%1)
-
+
Disabled in all flight modes
Zakázáno ve všech letových režimech
-
+
Flight modes(%1)
Letové režimy(%1)
-
+
Flight mode(%1)
Letový režim(%1)
-
+
Edge(%1, [%2:%3])
-
+
instant
-
+
Sticky(%1, %2)
-
+
Timer(%1, %2)
-
+
Duration(%1s)
Trvání(%1s)
-
+
Delay(%1s)
Zpoždění(%1s)
-
+
Custom
Volná-XY
-
+
Standard
Rastr-X
@@ -5431,27 +5625,27 @@ p, li { white-space: pre-wrap; }
ModelSelectionPage
-
+
Plane
Letadlo
-
+
Multirotor
-
+
Helicopter
Helikoptéra
-
+
Model Name:
Název modelu:
-
+
Model Type:
Typ modelu:
@@ -5459,129 +5653,7 @@ p, li { white-space: pre-wrap; }
ModelsListWidget
-
-
- &Edit
- &Upravit
-
-
-
- &Restore from backup
- &Obnovit ze zálohy
-
-
-
- &Model Wizard
- &Průvodce nastavením modelu
-
-
-
- &Delete
- &Odstranit
-
-
-
- Delete
-
-
-
-
- &Copy
- &Kopírovat
-
-
-
- Ctrl+C
-
-
-
-
- &Cut
- &Vyjmout
-
-
-
- Ctrl+X
-
-
-
-
- &Paste
- &Vložit
-
-
-
- Ctrl+V
-
-
-
-
- D&uplicate
- &Duplikovat
-
-
-
- Ctrl+U
-
-
-
-
- &Use as default
- &Použít jako výchozí
-
-
-
- P&rint model
- Vy&tisknout model
-
-
-
- Ctrl+P
-
-
-
-
- &Simulate model
- &Simulovat model
-
-
-
- Alt+S
-
-
-
-
- General Settings
- Obecná nastavení
-
-
-
- Delete Selected Models?
- Odstranit vybrané modely?
-
-
-
-
- Cannot delete default model.
- Nelze odstranit výchozí model.
-
-
-
- Cannot cut default model.
- Nelze přesunout výchozí model.
-
-
-
- Do you want to overwrite radio general settings?
- Chcete přepsat obecná nastavení rádia?
-
-
-
- You are pasting on an not empty model, are you sure?
- Vkládáte do modelu který není prázdný, jste si jist?
-
-
-
+
No free slot available, cannot duplicate
Není už volný slot, nelze duplikovat
@@ -5589,142 +5661,199 @@ p, li { white-space: pre-wrap; }
Module
-
+
Failsafe Mode
Režim Failsafe
-
+
Start
První kanál
-
+
PPM delay
PPM zpoždění
-
+
Negative
Negativní
-
+
Positive
Pozitivní
-
+
Polarity
Polarita
-
+
Trainer Mode
Mód trenér
-
+
PPM Frame Length
Délka PPM rámce
-
+
CH
-
+
+ SubType
+
+
+
+
+ Antenna
+
+
+
+
+ Internal
+
+
+
+
+ Ext. + Int.
+
+
+
+
+ Option value
+
+
+
+
+ Bind on startup
+
+
+
+
+ Low Power
+
+
+
+
us
-
+
+ Multi Radio Protocol
+
+
+
+
Master/Jack
Učitel/Jack konektor
-
+
Slave/Jack
Žák/Jack konektor
-
+
Master/SBUS Module
Učitel/SBUS modul
-
+
Master/CPPM Module
Učitel/CPPM modul
-
+
Master/SBUS in battery compartment
Učitel/SBUS konektor v šachtě baterie
-
+
+ Show values in:
+
+
+
+
+ %
+ abbreviation for percent
+
+
+
+
+ μs
+ abbreviation for microseconds
+
+
+
+
ms
-
+
Channels
Počet kanálů
-
+
Not set
Nenastaveno
-
+
Hold
Držet hodnotu
-
+
Custom
Vlastní
-
+
No Pulses
Žádné pulzy
-
+
Receiver
Dle nastavení přijímače
-
+
Failsafe Positions
Pozice Failsafe
-
+
Protocol
Protokol
-
+
Receiver No.
Číslo přijímače
-
+
Output type
Typ řízení výstupu
-
+
Open Drain
-
+
Push Pull
@@ -5732,43 +5861,43 @@ p, li { white-space: pre-wrap; }
ModulePanel
-
+
Trainer Port
Port Trenér
-
+
Internal Radio System
Interní vysílací modul
-
+
External Radio Module
Externí vysílací modul
-
-
+
+
Radio System
Vysílací modul
-
+
Extra Radio System
Extra modul
-
+
Value
Hodnota
-
+
Hold
Držet hodnotu
-
+
No Pulse
Žádné pulzy
@@ -5776,229 +5905,322 @@ p, li { white-space: pre-wrap; }
MultiModelPrinter
-
+
General Model Settings
Obecná nastavení modelu
-
+
Name:
Název:
-
+
EEprom Size:
Velikost EEPROM:
-
+
Timer%1:
Stopky%1:
-
+
Module%1:
Modul%1:
-
+
Module:
Modul:
-
+
Trainer port:
Port Trenér:
-
+
Throttle Trim:
Trim plynu:
-
+
Trim Increment:
Krok trimu:
-
+
Center Beep:
Zvuk ve středové poloze:
-
+
+ Helicopter Setup
+
+
+
+
+ Swash Type:
+
+
+
+
+ Swash Ring:
+
+
+
+
+ Input
+ Vstup
+
+
+
+ Weight
+ Váha
+
+
+
+ Long. cyc
+
+
+
+
+ Lateral cyc
+
+
+
+
+ Collective
+ Kolektiv
+
+
+
Flight modes
Letové režimy
-
-
+
+
Flight mode
Letový režim
-
+
Switch
Spínač
-
+
Fade IN
Přechod při aktivaci
-
+
Fade OUT
Přechod při deaktivaci
-
-
+
+
FM%1
LR%1
-
-
+
+
GV%1
GP%1
-
+
RE%1
-
+
Limits
Limity
-
+
Channel
Kanál
-
+
Name
Název
-
-
+
+
Offset
Subtrim
-
+
Min
-
+
Max
-
+
Invert
Invertovat
-
+
Global Variables
Globální proměnné
-
+
Inputs
Vstupy(DR/Expo)
-
+
Mixers
Mixy
-
+
CV%1
K%1
-
+
Curves
Křivky
-
+
L%1
-
+
Logical Switches
Logické spínače
-
+
SF%1
-
+
Special Functions
Speciální funkce
-
+
Telemetry Settings
Nastavení telemetrie
-
+
Analogs
Analogy
-
+
Unit
Jednotky
-
+
Scale
Rozsah
-
+
A%1
-
+
RSSI Alarms
RSSI Alarmy
+
+
+ Low Alarm
+ Nízký alarm
+
+
+
+ Critical Alarm
+ Kriticky alarm
+
+
+
+ Multiprotocols
+
+
+ Subtype
+
+
+
+
+ Video TX frequency
+
+
+
+
+ C2500 frequency fine tune
+
+
+
+
+ Telemetry
+ Telemetrie
+
+
+
+ Radio output power
+
+
+
+
+ Servo output frequency
+
+
+
+
+ Option value
+
+
+
+
+ DEFAULT
+
+
MultirotorPage
-
+
Throttle Channel:
Kanál plynu:
-
+
Yaw Channel:
Kanál bočení:
-
+
Pitch Channel:
Kanál klopení:
-
+
Roll Channel:
Kanál klonění:
@@ -6006,17 +6228,17 @@ p, li { white-space: pre-wrap; }
OptionsPage
-
+
Throttle Cut
Zámek plynu (spínač THR)
-
+
Throttle Timer
Stopky na plynu
-
+
Flight Timer
Letové stopky
@@ -6039,17 +6261,17 @@ p, li { white-space: pre-wrap; }
Tisk do souboru
-
+
Print Document
Vytisknout dokument
-
+
Select PDF output file
Vyberte cílový PDF soubor
-
+
ODF files (*.odt);;PDF Files(*.pdf);;HTML-Files (*.htm *.html);;All Files (*)
soubor ODF (*.odt);;soubor PDF (*.pdf);;soubor HTML (*.htm *.html);;Všechny (*)
@@ -6083,681 +6305,731 @@ p, li { white-space: pre-wrap; }
QObject
-
-
+
+
Rud
Směrovka
-
-
+
+
Ele
Výškovka
-
-
+
+
Thr
Plyn
-
-
+
+
Ail
Křidélka
-
-
-
+
+
P1
Potenciometr P1
-
-
-
+
+
P2
Potenciometr P2
-
-
-
+
+
P3
Potenciometr P3
-
-
-
-
+
+
+
S1
-
-
-
-
+
+
+
S2
-
-
-
-
+
+
+
LS
-
-
-
-
+
+
+
RS
-
+
TrmR
Trim směrovky
-
+
TrmE
Trim výškovky
-
+
TrmT
Trim plynu
-
+
TrmA
Trim křidélek
-
-
-
+
+
+
REa
Otočný enkodér REa
-
-
-
+
+
+
REb
Otočný enkodér REb
-
-
+
+
Batt
-
+
A1
Telem. vstup A1
-
+
A2
Telem. vstup A2
-
+
Alt
Výška
-
+
Rpm
Otáčky
-
+
Fuel
Palivo
-
+
T1
-
+
SWR
-
-
+
+
°F
-
+
+ mW
+
+
+
+
+ Rad
+
+
+
+
+ Trm5
+
+
+
+
+ Trm6
+
+
+
+
T2
-
+
Speed
Rychlost
-
+
Dist
Vzdálenost
-
+
GPS Alt
Výška GPS
-
+
Cell
Článek
-
+
Vfas
-
+
Curr
Proud
-
+
Cnsp
-
+
Powr
Výkon
-
+
AccX
-
+
AccY
-
+
AccZ
-
+
VSpd
-
+
A1-
-
+
A2-
-
+
Alt-
-
+
Alt+
-
+
Rpm+
-
+
T1+
-
+
T2+
-
-
+
+
Time
-
+
MAX
-
- S11
- S11 (multipos1_poloha1)
-
-
-
- S12
- S12 (multipos1_poloha2)
-
-
-
- S13
- S13 (multipos1_poloha3)
-
-
-
- S14
- S14 (multipos1_poloha4)
-
-
-
- S15
- S15 (multipos1_poloha5)
-
-
-
- S16
- S16 (multipos1_poloha6)
-
-
-
- S21
- S21 (multipos2_poloha1)
-
-
-
- S22
- S22 (multipos2_poloha2)
-
-
-
- S23
- S23 (multipos2_poloha3)
-
-
-
- S24
- S24 (multipos2_poloha4)
-
-
-
- S25
- S25 (multipos2_poloha5)
-
-
-
- S26
- S26 (multipos2_poloha6)
-
-
-
+
CYC%1
-
-
-
-
+
+
+
+
----
-
+
THR
Plyn
-
-
-
+
+
+
ON
ZAPNUTO
-
-
-
+
+
+
OFF
VYPNUTO
-
+
Diff(%1)
Dif(%1)
-
+
Expo(%1)
-
+
Function(%1)
Funkce(%1)
-
+
Curve(%1)
Křivka(%1)
-
+
!Curve(%1)
!Křivka(%1)
-
-
+
+
Support for frsky telemetry mod
Podpora frsky telemetrie tj. zobrazení telemetrických dat na displeji rádia
(je potřeba upravit HW, bez této úpravy nebudou fungovat dva přepínače!
a pochopitelně nebudou zobrazena žádná telem. data.)
-
-
+
+
Support for jeti telemetry mod
Podpora telemetrie JETI
-
-
+
+
Support for receiving ardupilot data
telemetrie - podpora pro příjem ardupilot dat
-
-
+
+
Support for receiving NMEA data
telemetrie - podpora pro příjem NMEA dat
-
+
Support for telemetry easy board
Podpora pro desku TelemetrEZ
-
-
+
+
Support for MAVLINK devices
Podpora pro zařízení s MAVLINK
-
+
Rotary Encoder use in menus navigation
Použít Rotary Encoder pro navigaci v menu
-
+
No OverrideCH functions available
Funkce Zámek kanálu není dostupná
-
-
-
-
-
-
+
+
+
+
+
+
Enable heli menu and cyclic mix support
Funkce pro heli, nastavení typu mechaniky
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
Enable TEMPLATES menu
Přidá menu s jednoduchými
šablonami modelu
-
-
-
-
+
+
+
+
No splash screen
Bez úvodního loga
Firmware nebude obsahovat žádné logo, ani podporu pro něj.
Toto se hodí pokud je potřeba ušetřit místo v paměti FLASH pro jiné funkce
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
No flight modes
Firmware nebude obsahovat podporu Letových Režimů
-
+
Support for Lua model scripts
Podpora pro Lua skripty.
-miniaplikace spustitelné z SD karty
-
+
+
+
+
+
+
+
+
+
+
+
Use alternative SQT5 font
Použít alternativní znakovou sadu písma (jiný font)
-
- (displaying only first 10 warnings)
- (zobrazeno pouze prvních 10 varování)
-
-
-
+
Possibility to enable FAI MODE (no telemetry) at field
Možnost povolit FAI MODE v menu rádia.
FAI je soutěžní mód (www.fai.org), zablokuje vario, zobrazení telemetrie a funkce hlasového hlášení.
-
+
FAI MODE (no telemetry) always enabled
FAI MODE vždy aktivní (nelze vypnout v menu rádia)
FAI je soutěžní mód (www.fai.org), zablokuje vario, zobrazení telemetrie a funkce hlasového hlášení.
-
-
-
-
- Support for a third timer
- Přidá třetí stopky
-
-
-
+
Instead of Joystick emulation, USB connection is Mass Storage (as in the Bootloader)
Místo emulace joisticku je USB připojeno v režimu přenosu souborů (jako v Bootloaderu)
-
+
Instead of Joystick emulation, USB connection is Command Line Interface
Místo emulace joisticku je USB připojeno v režimu CLI (textová konzole)
-
- Removes D8 and LR12 FrSky protocols that are not legal for use in the EU on radios sold after Jan 1st, 2015
- Odstraní volby pro Frsky protokoly D8 a LR12 která nejsou legální pro rádia zakoupená po 1.1.2015
-
-
-
+
+
Support for PPM internal module hack
Podpora pro upravený vnitřní modul v režimu PPM
-
+
ST7565P LCD or compatible
ST7565P LCD a kompatibilní
-
+
ST7565R LCD or compatible
ST7565R LCD a kompatibilní
-
+
ERC12864FSF LCD
-
+
ST7920 LCD
-
- 9X board
- 9X základní deska
-
-
-
+
EEprom write progress bar
Progresbar zobrazující zápis do EEPROM
(tj. ukládání nastavení)
-
-
+
+
No Winged Shadow How High support
Bez podpory - Winged Shadow How High
-
-
+
+ Turnigy 9XR
+
+
+
+
+
No vario support
Bez podpory varia
-
-
+
+
No GPS support
Bez podpory GPS
-
-
+
+
No gauges in the custom telemetry screen
Bez grafických ukazatelů hodnoty na obrazovkách telemetrie
-
+
+ 9X with stock board
+
+
+
+
Allow compensating for offset errors in FrSky FAS current sensors
Povolit možnost kompenzace chyby ofsetu u Frsky FAS proudového senzoru, pokud je to potřeba
-
-
+
+
Add support for reversing stick inputs (e.g. needed for FrSky gimbals)
Přidá podporu pro revers os kniplů.
To je nutné zejména pro osazení FrSky kniplů do 9X.
-
+
+ 9X with stock board and m128 chip
+
+
+
+
+ 9X with AR9X board
+
+
+
+
+ 9X with Sky9x board
+
+
+
+
+ 9X with Gruvin9x board
+
+
+
+
+ DIY MEGA2560 radio
+
+
+
+
Power management by soft-off circuitry
Ovládání napájení pomocí soft-off obvodu
-
- ar9x board / 9X
- ar9x deska / 9X
-
-
-
- 9XR-PRO
-
-
-
-
- FrSky Taranis
-
-
-
-
- FrSky Taranis Plus
-
-
-
-
+
FrSky Taranis X9E
-
+
Confirmation before radio shutdown
Přidá potvrzování před vypnutím rádia
-
-
- Adds mixers output view to the CHANNELS MONITOR screen, pressing [ENT] switches between the views
- Přidá monitor výstupu mixů k monitoru kanálů, stiskem [ENT] přepnete z jednoho do druhého
-
-
-
+
Haptic module installed
Podpora pro vibrační modul
-
+
Disable HELI menu and cyclic mix support
Odstranit funkce pro heli a nastavení typu mechaniky
-
+
+ Unknown error
+
+
+
+
+ ... plus %1 errors
+
+
+
+
+ Cannot write radio settings
+
+
+
+
+ Cannot write model %1
+
+
+
+
+ 6P
+ CH9X {6P?}
+
+
+
+ JSx
+
+
+
+
+ JSy
+
+
+
+
+ Support for the DIY-Multiprotocol-TX-Module
+
+
+
+
+ Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015
+
+
+
+
Disable Global variables
Odstranit Globální proměnné
-
-
+
+ Enable Lua compiler
+
+
+
+
+ KS108 LCD
+
+
+
+
+ WTV20 voice module
+
+
+
+
+ JQ6500 voice module
+
+
+
+
+ FrSky Taranis X9D+
+
+
+
+
+ FrSky Taranis X9D
+
+
+
-
-
-
-
-
-
+ Horus gimbals installed (Hall sensors)
+
+
+
+
+ FrSky Taranis X7
+
+
+
+
+ FrSky Horus
+
+
+
+
+ Use ONLY with first DEV pcb version
+
+
+
+
+ Turnigy 9XR-PRO
+
+
+
+
+ Turnigy 9XR with m128 chip
+
+
+
+
+
+
+
+
+
Disable curves menus
Bez uživatelsky definovatelných křivek
-
-
-
-
+
+
+
+
+
Support for radio modified with regular speaker
Vylepšený zvukový výstup,
funkční i s origo pípákem,
@@ -6765,137 +7037,111 @@ ale doporučuje se provést
instalaci reproduktoru
-
-
-
-
-
+
+
+
+
+
Used if you have modified your radio with voice mode
Hlasový výstup pro telemetrii,
nutno zastavět hlasový modul
-
-
-
-
-
+
+
+
+
+
Used if you have modified your radio with haptic mode
Výstrahy pomocí vibračního motoru
(je třeba osadit)
-
+
Channel values displayed in us
Hodnoty kanálů budou zobrazeny v us (mikrosekundy) místo procent
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
In model setup menus automatically set source by moving the control
Výběr spínače v mixu atd.
se provádí jeho sepnutím
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
In model setup menus automatically set switch by moving the control
Výběr spínače v mixu atd.
se provádí jeho sepnutím
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
Battery graph
Grafické znázornění stavu baterie
-
-
-
-
+
+
+
+
Enable the throttle trace in Statistics
Přidat Stopu Plynu (Throttle-trace) v panelu STATISTIKA
-
- M128 / 9X board
- M128 / 9X základní deska
-
-
-
- 9XR
-
-
-
-
- 9XR with M128 chip
- 9XR s čipem M128
-
-
-
- Gruvin9x board / 9X
- Gruvin9x deska / 9X
-
-
-
-
+
+
Support of FrSky PXX protocol
Podpora pro Frsky PXX protokol
-
-
-
-
-
+
+
+
+
+
Support for DSM2 modules
Podpora DSM2 modulů
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
PPM center adjustment in limits
Možnost nastavovat střed serva šířkou pulzu
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
Symetrical Limits
Symetrické limity
Přidá možnost volby mezi
@@ -6906,33 +7152,33 @@ Přidá možnost volby mezi
nastavené limity tedy nemusí být rovny hodnotě -100% a 100%, ale budou pouze maximem výchylky)
-
-
-
-
-
-
-
+
+
+
+
+
+
+
Pots use in menus navigation
Moznost zadávat hodnoty
a pohybovat se v menu
pomocí potenciometrů
-
-
+
+
SmartieParts 2.2 Backlight support
Podpora pro modul SmartieParts 2.2
(programátor/podsvícení)
Není určeno pro starší verze Smartie Parts
-
-
-
-
-
-
+
+
+
+
+
+
Enable resetting values by pressing up and down at the same time
Rychlé nastavení hodnoty současným stiskem dvou tlačítek.
(+) a (-) invertuje hodnotu
@@ -6941,28 +7187,28 @@ Není určeno pro starší verze Smartie Parts
(UP) a (DN) vastaví výchozí hodnotu
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
No graphical check boxes and sliders
Nahrazeni posuvníku a zatržítek (checkboxu) textem
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
Don't use bold font for highlighting active items
Vypnout zvýraznění aktivních mixů/spínačů tučným písmem.
Pokud není tato volby vybrána,
@@ -6971,53 +7217,43 @@ zobrazovány tučným pismem. Neaktivní mixy/spínače budou
zobrazeny normálním písmem
-
-
-
-
-
+
+
+
+
+
EEprom write Progress bar
Progresbar zobrazující zápis do EEPROM
(tj. ukládání nastavení)
-
-
-
-
-
-
+
+
+
+
+
+
Imperial units
Imerialní jednotky pro telemetrii
(stopy, palce, míle atd.)
-
- MEGA2560 board
- MEGA2560 deska
-
-
-
- Sky9x board / 9X
- Sky9x deska / 9X
-
-
-
-
-
+
+
+
Bluetooth interface
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
Global variables
Aktivuje Globální Proměnné
Jsou to proměnné, které lze použít pro konfiguraci místo některých pevných číselných hodnot.
@@ -7026,1355 +7262,1210 @@ Jejich hodnoty naleznete u originální 9x desky v seznamu křivek. U ostatních
Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Funkce
-
-
+
+
Support for SD memory card
Podpora paměťové karty SD
-
+
Support for DSM2 modules using ppm instead of true serial
Podpora DSM2 modulů s použitím PPM místo sériového protokolu
-
-
-
+
+
+
Enable HELI menu and cyclic mix support
Funkce pro heli, nastavení typu mechaniky
-
-
+
Warning
Varování
-
- EEPROM saved with these warnings:
- EEPROM uložena s těmito varováními:
-
-
-
+
English
-
+
French
-
+
Italian
-
+
German
-
+
Czech
-
+
Slovak
-
+
Spanish
-
+
Portuguese
-
+
Swedish
-
- Finnish
-
+
+ Dutch
+
-
+
+ Hungarian
+
+
+
+
No
Žádný
-
+
RotEnc A
Otočný enkodér :A
-
+
Rot Enc B
Otočný enkodér :B
-
+
Rot Enc C
Otočný enkodér :C
-
+
Rot Enc D
Otočný enkodér :D
-
+
Rot Enc E
Otočný enkodér :E
-
+
No repeat
Neopakovat
-
-
-
-
-
-
-
+
+
+
+
+
+
+
V
-
-
+
+
s
-
+
ft
-
-
-
+
+
+
m
-
-
-
+
+
+
°C
-
-
-
+
+
+
°
-
-
+
+
%
-
-
-
+
+
+
mph
-
-
-
+
+
+
km/h
-
-
+
+
m/s
-
-
+
+
A
-
+
mA
-
+
kts
-
+
f
-
-
+
+
mAh
-
-
+
+
W
-
+
dB
-
+
rpms
-
-
+
+
g
-
+
hours
-
+
minutes
-
+
seconds
-
+
h:m
-
+
m:s
-
+
h:m:s
-
-
+
F1
-
-
+
F2
-
-
+
F3
-
-
+
F4
-
-
+
S3
-
-
-
+
+
+
Timer3
Stopky3
-
+
RSSI Tx
-
+
RSSI Rx
-
+
A3
Telem. vstup A3
-
+
A4
Telem. vstup A4
-
+
Cells
-
+
dTE
-
+
Hdg
-
+
AirSpeed
-
+
A3-
Telem. vstup A3-
-
+
A4-
Telem. vstup A4-
-
+
Speed+
-
+
Dist+
-
+
AirSpeed+
-
+
Cell-
-
+
Cells-
-
+
Vfas-
-
+
Curr+
-
+
Powr+
-
+
ACC
-
+
GPS Time
-
-
+
L1
-
-
+
L2
-
-
- L3
-
-
-
-
-
- L4
-
-
-
-
-
- L5
-
-
-
-
-
- L6
-
-
-
-
-
- L7
-
-
-
-
-
- L8
-
-
-
-
-
- L9
-
-
-
-
-
- L10
-
-
-
-
-
- L11
-
-
-
-
-
- L12
-
-
-
-
-
- L13
-
-
-
-
-
- L14
-
-
-
-
-
- L15
-
-
-
-
-
- L16
-
-
-
-
-
- L17
-
-
-
-
-
- L18
-
-
-
-
-
- L19
-
-
-
-
-
- L20
-
-
-
-
-
- L21
-
-
-
-
-
- L22
-
-
-
-
-
- L23
-
-
-
-
-
- L24
-
-
-
-
-
- L25
-
-
-
-
-
- L26
-
-
-
-
-
- L27
-
-
-
-
-
- L28
-
-
-
-
-
- L29
-
-
-
-
-
- L30
-
-
-
-
-
- L31
-
-
-
-
-
- L32
-
-
-
-
+
[I%1]
-
+
LUA%1%2
-
+
+
+ L%1
+
+
+
+
TR%1
-
+
FM0
LR0
-
+
FM1
LR1
-
+
FM2
LR2
-
+
FM3
LR3
-
+
FM4
LR4
-
+
FM5
LR5
-
+
FM6
LR6
-
+
FM7
LR7
-
+
FM8
LR8
-
- S31
- S31 (multipos3_poloha1)
-
-
-
- S32
- S32 (multipos3_poloha2)
-
-
-
- S33
- S33 (multipos3_poloha3)
-
-
-
- S34
- S34 (multipos3_poloha4)
-
-
-
- S35
- S35 (multipos3_poloha5)
-
-
-
- S36
- S36 (multipos3_poloha6)
-
-
-
+
RudTrim Left
TrimSmě.r-Vlevo
-
+
RudTrim Right
TrimSměr.-Vpravo
-
+
EleTrim Down
TrimVýšk.-Dolů
-
+
EleTrim Up
TrimVýšk.-Nahoru
-
+
ThrTrim Down
TrimPlyn-Dolů
-
+
ThrTrim Up
TrimPlyn-Nahoru
-
+
AilTrim Left
Trimkřid.-Vlevo
-
+
AilTrim Right
TrimKřid-Vpravo
-
+
+ Trim 5 Down
+
+
+
+
+ Trim 5 Up
+
+
+
+
+ Trim 6 Down
+
+
+
+
+ Trim 6 Up
+
+
+
+
THs
Pln>
-
+
TH%
Pln%
-
+
THt
Pln*
-
+
One
One(výběr modelu)
-
+
???
-
+
a>x
-
+
a<x
-
+
|a|>x
-
+
|a|<x
-
+
AND
-
+
OR
-
+
XOR
-
+
a=b
-
+
a!=b
-
+
a>b
-
+
a<b
-
+
a>=b
-
+
a<=b
-
+
d>=x
-
+
|d|>=x
-
+
a=x
-
+
a~x
-
+
Timer
-
+
Sticky
-
+
+ Left Horizontal
+ Levá horizontální
+
+
+
+ Left Vertical
+ Levá vertikální
+
+
+
+ Right Vertical
+ Pravá vertikální
+
+
+
+ Right Horizontal
+ Pravá horizontální
+
+
+
+ Aux. 1
+
+
+
+
+ Aux. 2
+
+
+
+
+
Unknown
Neznámý
-
+
Override %1
Zámek %1
-
+
Trainer
Trenér
-
+
Trainer RUD
Trenér - směrovka
-
+
Trainer ELE
Trenér - výškovka
-
+
Trainer THR
Trenér - plyn
-
+
Trainer AIL
Trenér - křidélka
-
+
Instant Trim
-
+
Play Sound
Přehrát zvuk
-
+
Haptic
Vibrovat
-
+
Reset
-
+
Set Timer %1
Nastav Timer %1
-
+
Vario
-
+
Play Both
Přehrát pár
-
+
Play Value
Přehrát hodnotu
-
+
Play Script
Spustit skript
-
+
Volume
Hlasitost
-
+
Backlight
Podsvětlení
-
+
Screenshot
Snímek LCD
-
+
Adjust GV%1
Upravit GP%1
-
+
SetFailsafe Int. Module
Nastavit Failsafe vnitř. modulu
-
+
SetFailsafe Ext. Module
Nastavit Failsafe ext. modulu
-
+
RangeCheck Int. Module
Test dosahu vnitř. modulu
-
+
RangeCheck Ext. Module
Test dosahu ext. modulu
-
+
Bind Int. Module
Bind vnitř. modulu
-
+
Bind Ext. Module
Bind ext. modulu
-
-
-
+
+
+
<font color=red><b>Inconsistent parameter</b></font>
<font color=red><b>parametr není konzistentní</b></font>
-
+
played once, not during startup
přehrát jednou, ale ne po startu
-
+
repeat(%1s)
opakovat(%1s)
-
+
DISABLED
ZAKÁZÁN
-
+
INV
-
+
NOR
---
-
+
Rotary Encoder
Rotační enkodér
-
+
+ -GV%1 (%2)
+
+
+
+
+ GV%1 (%2)
+
+
+
+
!Flight mode %1
!Letový režim %1
-
+
Flight mode %1
Letový režim %1
-
+
Yellow
Žlutá
-
+
Orange
Oranžová
-
+
Red
Červená
-
+
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
Winged Shadow How High (nepodporován)
-
+
FrSky Sensor Hub
FrSky Senzor Hub
-
+
None
Žádný
-
+
Imperial
Imperiální
-
+
Metric
Metrické
-
+
+
+ Uknown error during Simulator startup.
+
+
+
+
+ Simulator Error
+
+
+
+
+ Data Load Error
+
+
+
+
+ Error occurred while starting simulator.
+
+
+
+
Play Track
Hrát stopu
-
-
-
+
+
+
---
-
+
Rud Trim
Trim směrovky
-
+
Ele Trim
Trim výškovky
-
+
Thr Trim
Trim plynu
-
+
Ail Trim
Trim křidélek
-
+
Rot Enc
-
+
Polish
-
+
CH%1
-
+
Background Music
Hudba na pozadí
-
+
Background Music Pause
Hudba na pozadí -pozastavit
-
-
-
+
+
+
Timer1
Stopky1
-
-
-
+
+
+
Timer2
Stopky2
-
+
Edge
-
+
SD Logs
SD logy
-
+
Telemetry
Telemetrie
-
+
Value
Hodnota
-
+
Decr:
Zmenšit:
-
+
Incr:
Zvětšit:
-
+
Played once, not during startup
Hrát jednou, ne při výběru modelu
-
+
%1s
-
+
Value
Hodnota
-
+
Source
Zdroj
-
+
GVAR
Proměnná
-
+
Increment
Upravit
-
+
Flight
Let
-
+
Own value
Vlastní hodnota
-
+
Flight mode %1 value
Flight phase %1 value
Hodnota režimu LR%1
-
+
Keys
Klávesy
-
+
Sticks
Páky
-
+
Keys + Sticks
Klávesy i páky
-
-
+
+
-GV%1
-GP%1
-
-
-
+
+
+
GV%1
GP%1
-
+
Simulator for this firmware is not yet available
Simulátor pro tuto verzi firmware zatím není dostupný
-
-
- Simultaneous usage of expo and curves is no longer supported
- Současné použití expa a křivek již není podporováno
-
-
-
+
Switch
Spínač
-
+
Switch
Spínač
-
+
cannot be exported on this board!
-na této desce nelze exportovat!
-
+
Source %1 cannot be exported on this board!
Zdroj %1 nelze na této desce exportovat!
-
+
OpenTX only accepts %1 points in all curves
V OpenTX je možné zadat pouze %1 bodů dohromady ve všech křivkách
-
+
OpenTx only accepts %1 points in all curves
V OpenTX je možné zadat pouze %1 bodů dohromady ve všech křivkách
-
-
-
-
-
+
+
+
+
+
+
OpenTX on this board doesn't accept this function
OpenTX nepodporuje tuto funkci na této zákl. desce
-
+
OpenTX doesn't accept this telemetry protocol
OpenTX nepodporuje tento protokol
-
-
-
+
+
+
OpenTX doesn't accept this radio protocol
OpenTX nepodporuje tento protokol
-
+
OpenTX doesn't allow this number of channels
V OpenTX nelze použít tento počet kanálů
-
- th9x on this board doesn't have Rotary Encoders
- v th9x na této desce nelze použít rotační enkodéry
-
-
-
+
Trim disabled
Trim zakázán
-
+
Own Trim
Vlastní trim
-
+
Use Trim from Flight mode %1
Použít trim z letového režimu %1
-
+
Use Trim from Flight mode %1 + Own Trim as an offset
Použít hodnotu trimu z letového režimu %1 + vlastní trim jako ofset
-
+
FW: %1
-
+
Pict: %1
Obr: %1
-
+
Profile image
Obrázek profilu
-
- Simultaneous usage of expo and curves is no longer supported in OpenTX
- Současné použití expa a křivky již není podporováno
-
-
-
+
Thank you for upgrading to OpenTX 2.0. This is a major upgrade that adds and modifies a lot of things, so please make sure that you read release notes carefully to learn about the changes, and thoroughly check each of your models for proper function.
The OpenTX Team.
@@ -8383,99 +8474,496 @@ The OpenTX Team.
Tým OpenTX.
-
+
GV
GP
-
-
-
-
-
+
+
+
+
+
Synchronization error
Chyba synchronizace
-
+
No SD directory configured!
Složka SD karty nebyla nastavena!
-
+
No Radio connected!
Není připojeno rádio!
-
+
-%1
-
-
+
+
The directory '%1' doesn't exist!
Složka '%1' neexistuje!
-
+
Create '%1' failed
Vytvoření '%1' selhalo
-
+
Copy '%1' to '%2' failed
Kopírování '%1' do '%2' selhalo
-
+
Open '%1' failed
Otevření '%1' selhalo
-
+
Write '%1' failed
Zápis '%1' selhal
-
-
-
+
+
+
+
+
+
+
Error
Chyba
-
+
Cannot write file %1:
%2.
Nelze zapsat soubor %1:
%2.
-
+
Companion
-
+
<b><u>WARNING!</u></b><br>This will reset the fuses of %1 to the factory settings.<br>Writing fuses can mess up your radio.<br>Do this only if you are sure they are wrong!<br>Are you sure you want to continue?
<b><u>POZOR!</u></b><br>Toto nastaví pojistky %1 do továrního nastavení.<br>Zápis pojistek může poškodit vaše rádio.<br>Proveďte pouze pokud jste si jist že jsou nastaveny špatně!<br>Jste si opravdu jist, že chcete pokračovat?
-
-
+
+
Could not delete temporary file: %1
Nelze odstarnit dočasný soubor: %1
-
- Radio type
- Typ rádia
+
+ Unable to find Horus radio SD card!
+
-
- Which radio type do you want to simulate?
- Jaký typ rádia chcete simulovat?
+
+ Conversion error on field %1
+
+
+
+
+ Negative span
+ Negativní
+
+
+
+ Mid value
+ Střed
+
+
+
+ Positive span
+ Pozitivní
+
+
+
+
+ Models
+ Translators do NOT use accent for this, this is the default category name on Horus.
+
+
+
+
+ Positive
+ Pozitivní
+
+
+
+ Negative
+ Negativní
+
+
+
+ Select a data file
+
+
+
+
+ Select Data Directory
+
+
+
+
+ Select SD Card Image Folder
+
+
+
+
+ Available profiles:
+
+
+
+
+ ID:
+
+
+
+
+ Name:
+
+
+
+
+ Available radios:
+
+
+
+
+ WARNING: couldn't initialize SDL:
+%1
+
+
+
+
+ ERROR: No simulator libraries available.
+
+
+
+
+ Radio profile ID or Name to use for simulator.
+
+
+
+
+ Radio type to simulate (usually defined in profile).
+
+
+
+
+ show this help text
+
+
+
+
+ Usage: simulator [OPTION]... [EEPROM.BIN FILE OR DATA FOLDER]
+
+
+
+
+ Options:
+
+
+
+
+ ERROR: Couldn't start simulator, missing radio/profile/data file/folder.
+ Profile ID: [%1]; Radio ID: [%2];
+Data File: [%3]
+
+
+
+
+ ERROR: Radio profile or simulator firmware not found.
+Profile ID: [%1]; Radio ID: [%2]
+
+
+
+
+ Error reading %1: %2
+
+
+
+
+ Cannot save EEPROM
+
+
+
+
+
+ Cannot open file %1:
+%2.
+
+
+
+
+
+
+ Error writing file %1:
+%2.
+
+
+
+
+ Invalid binary EEPROM file %1
+
+
+
+
+ Can't extract RADIO/radio.bin
+
+
+
+
+ Can't extract RADIO/models.txt
+
+
+
+
+ Can't extract %1
+
+
+
+
+ Unable to open %1: %2
+
+
+
+
+ Invalid EEPROM file %1
+
+
+
+
+ Invalid EEPROM File %1
+ Neplatný soubor EEPROM %1
+
+
+
+
+ Error opening file %1:
+%2.
+ Chyba při otevírání souboru %1:
+%2.
+
+
+
+ Error opening OTX archive %1
+
+
+
+
+ Error initializing OTX archive writer
+
+
+
+
+ Error creating OTX file %1:
+%2.
+
+
+
+
+ Error creating OTX archive
+
+
+
+
+ Error adding %1 to OTX archive
+
+
+
+
+ Error opening file %1 in write mode:
+%2.
+
+
+
+
+ Unable to find file %1!
+ Nemohu nalézt soubor %1!
+
+
+
+ QxtCommandOptions
+
+
+ sets the application GUI style
+
+
+
+
+ sets the application stylesheet
+
+
+
+
+ restores the application from an earlier session
+
+
+
+
+ displays debugging information about widgets
+
+
+
+
+ use right-to-left layout
+
+
+
+
+ never grab the mouse or keyboard
+
+
+
+
+ grab the mouse/keyboard even in a debugger
+
+
+
+
+ run in synchronous mode for debugging
+
+
+
+
+ use Direct3D by default
+
+
+
+
+ sets the X11 display
+
+
+
+
+ sets the geometry of the first window
+
+
+
+
+ sets the default font
+
+
+
+
+ sets the default background color
+
+
+
+
+ sets the default foreground color
+
+
+
+
+ sets the default button color
+
+
+
+
+ sets the application name
+
+
+
+
+ sets the application title
+
+
+
+
+ sets the X11 visual type
+
+
+
+
+ limit the number of colors on an 8-bit display
+
+
+
+
+ use a private color map
+
+
+
+
+ sets the input method server
+
+
+
+
+ disable the X Input Method
+
+
+
+
+ sets the style used by the input method
+
+
+
+
+
+ option "%1" not found
+
+
+
+
+ Short options cannot have optional parameters
+
+
+
+
+ positional() called before parse()
+
+
+
+
+ unrecognized() called before parse()
+
+
+
+
+ count() called before parse()
+
+
+
+
+ value() called before parse()
+
+
+
+
+ parameters() called before parse()
+
+
+
+
+ unrecognized parameters:
+
+
+
+
+ %1 requires a parameter
+
+
+
+
+ RadioKnobWidget
+
+
+ Right-double-click to reset to center.
+
@@ -8496,10 +8984,100 @@ Tým OpenTX.
+
+ RadioOutputsWidget
+
+
+ Form
+
+
+
+
+ View:
+
+
+
+
+ Logical Switches
+ Logické spínače
+
+
+
+ Global Variables
+ Globální proměnné
+
+
+
+ Channel Outputs
+
+
+
+
+ L
+o
+g
+i
+c
+
+
+
+
+ G
+l
+o
+b
+a
+l
+
+
+
+
+ C
+h
+a
+n
+n
+e
+l
+s
+
+
+
+
+ RadioSwitchWidget
+
+
+ Latch/unlatch the momentary switch.
+
+
+
+
+ RawSwitch
+
+
+ ↑
+
+
+
+
+ ↓
+
+
+
+
+ -
+
+
+
+
+ !
+
+
+
ReleaseNotesDialog
-
+
Companion Release Notes
Poznámky k vydání Companion
@@ -8507,7 +9085,7 @@ Tým OpenTX.
ReleaseNotesFirmwareDialog
-
+
OpenTX Release Notes
Poznámky k vydání OpenTX
@@ -8515,17 +9093,17 @@ Tým OpenTX.
RudderPage
-
+
No
Ne
-
+
Yes
Ano
-
+
<br>Rudder Channel:
<br>Kanál směrovky:
@@ -8703,7 +9281,7 @@ Funkce trimu bude opačná, stejně tak i varování polohy páky plynu.
SetupPanel
-
+
Timer %1
@@ -8711,179 +9289,847 @@ Funkce trimu bude opačná, stejně tak i varování polohy páky plynu.
SimpleTailPage
- | |