[Simulator] Further Simulator improvements. (#4282)
* Refactor CompStoreObj to use templates. Clean up some formatting.
* [Simulator] Add SimulatorOptions type to replace individual simulator options; Fix storage handler for custom types; Cleanup some redundant code.
* [Simulator][Joystick] Rework the joystick options/calibration dialog. Can now enable/disable/select the Joystick from there. Delay start of calibration until Start is pressed (otherwise looks like last calibration didn't work). And generally refactor a lot of it to be smarter.
* Cosmetics.
* [Simulator] Add state handling for RadioWidget class. Split code to cpp file.
* [Simulator] Add SimulatorStartupDialog as its own UI class.
* [Simulator] Multiple changes and new features:
All Horus data source options are now fully supported with data properly saved after use (SD path, .otx file, or custom data path);
Loading .otx files now works for all radio types (but not saving data back to .otx);
Switch and knob/slider states are now saved to per radio profile;
Joystick configuration/calibration is now available directly from inside Simulator;
Due to refactoring, all previously saved per-profile simulator settings are now invalid;
Further consolidated simulator dialog startup/shutdown, now handles temp. paths internally, etc;
With WIN_USE_CONSOLE defined, Simulator and Companion when started from Windows command line will now use that console for all messages (instead of opening a new one). This allows full debug output to be seen at all stages of execution and after exit.
* [Simulator] Fix build w/out SDL Joystick support.
* [Simulator] Fix bogus throttle warning on simulator start; Add forgotten RadioWidgetState flags to stream handlers; Add debug state saver in SimulatorOptions.
This commit is contained in:
committed by
Bertrand Songis
parent
b53ec7392c
commit
6e2474081f
@@ -71,6 +71,9 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
include_directories(SYSTEM ${WIN_INCLUDE_DIRS})
|
||||
if(NOT WIN_USE_CONSOLE)
|
||||
set(WIN_EXECUTABLE_TYPE WIN32) # GUI (WinMain) app
|
||||
endif()
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /LD /MP")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,5.01")
|
||||
@@ -246,7 +249,7 @@ add_custom_target(gen_qrc DEPENDS ${companion_RCC})
|
||||
|
||||
add_definitions(-DQT_TRANSLATIONS_DIR="${QT_TRANSLATIONS_DIR}")
|
||||
|
||||
add_executable(${COMPANION_NAME} MACOSX_BUNDLE WIN32 ${companion_SRCS} ${companion_RCC} ${companion_QM})
|
||||
add_executable(${COMPANION_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${companion_SRCS} ${companion_RCC} ${companion_QM})
|
||||
|
||||
add_dependencies(${COMPANION_NAME} gen_qrc)
|
||||
qt5_use_modules(${COMPANION_NAME} Core Widgets Network)
|
||||
@@ -275,7 +278,7 @@ if(WIN32)
|
||||
list(APPEND simu_SRCS icon.rc)
|
||||
endif()
|
||||
|
||||
add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE WIN32 ${simu_SRCS} ${companion_RCC})
|
||||
add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${simu_SRCS} ${companion_RCC})
|
||||
|
||||
add_dependencies(${SIMULATOR_NAME} gen_qrc)
|
||||
qt5_use_modules(${SIMULATOR_NAME} Core Widgets Multimedia)
|
||||
|
||||
+18
-27
@@ -816,18 +816,17 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
|
||||
SimulatorInterface * simulator = getCurrentSimulator();
|
||||
if (simulator) {
|
||||
#if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO)
|
||||
AllocConsole();
|
||||
SetConsoleTitle("Companion Console");
|
||||
freopen("conin$", "r", stdin);
|
||||
freopen("conout$", "w", stdout);
|
||||
freopen("conout$", "w", stderr);
|
||||
bool freeConsoleOnClose = false;
|
||||
if (!GetConsoleWindow()) {
|
||||
AllocConsole();
|
||||
SetConsoleTitle("Companion Console");
|
||||
freeConsoleOnClose = true;
|
||||
freopen("conin$", "r", stdin);
|
||||
freopen("conout$", "w", stdout);
|
||||
freopen("conout$", "w", stderr);
|
||||
}
|
||||
#endif
|
||||
Firmware * firmware = getCurrentFirmware();
|
||||
RadioData * simuData = new RadioData(radioData);
|
||||
Board::Type board = getCurrentBoard();
|
||||
QByteArray eeprom = QByteArray();
|
||||
QString sdPath = g.profile[g.id()].sdPath();
|
||||
QString settingsPath = "";
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (modelIdx >= 0) {
|
||||
@@ -835,29 +834,21 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
|
||||
simuData->setCurrentModel(modelIdx);
|
||||
}
|
||||
|
||||
if (IS_HORUS(board)) {
|
||||
QTemporaryDir tmpDir(QDir::tempPath() + "/otx-XXXXXX");
|
||||
settingsPath = tmpDir.path();
|
||||
tmpDir.setAutoRemove(false);
|
||||
}
|
||||
|
||||
qDebug() << "Starting" << firmware->getName() << "simulation with SD path" << sdPath << "and models/settings path" << settingsPath;
|
||||
|
||||
SimulatorDialog * dialog = new SimulatorDialog(parent, simulator, flags);
|
||||
dialog->setPaths(sdPath, settingsPath);
|
||||
if (IS_HORUS(getCurrentBoard()) && !dialog->useTempDataPath(true)) {
|
||||
QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error: Could not create temporary directory in '%1'").arg(QDir::tempPath()));
|
||||
return;
|
||||
}
|
||||
dialog->setRadioData(simuData);
|
||||
qDebug() << __FILE__ << __LINE__ << "Starting" << getCurrentFirmware()->getName() << "simulation with SD path" << dialog->getSdPath() << "and models/settings path" << dialog->getDataPath();
|
||||
dialog->start();
|
||||
dialog->exec();
|
||||
dialog->deleteLater();
|
||||
if (!settingsPath.isEmpty()) {
|
||||
// TODO either delete tmp directory and its contents OR use it to get back data from the simulation
|
||||
qDebug() << "Simulation finished, deleting temporary settings directory" << settingsPath;
|
||||
QDir tmp(settingsPath);
|
||||
tmp.removeRecursively();
|
||||
}
|
||||
delete simuData;
|
||||
// TODO Horus tmp directory is deleted on simulator close OR we could use it to get back data from the simulation
|
||||
delete simuData; // TODO same with simuData, could read it back and update the file data
|
||||
#if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO)
|
||||
FreeConsole();
|
||||
if (freeConsoleOnClose)
|
||||
FreeConsole();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -7,8 +7,10 @@ set(simulation_SRCS
|
||||
simulateduiwidgetX7.cpp
|
||||
simulateduiwidgetX9.cpp
|
||||
simulateduiwidgetX12.cpp
|
||||
simulatorstartupdialog.cpp
|
||||
telemetrysimu.cpp
|
||||
trainersimu.cpp
|
||||
widgets/radiowidget.cpp
|
||||
widgets/virtualjoystickwidget.cpp
|
||||
)
|
||||
|
||||
@@ -19,6 +21,7 @@ set(simulation_UIS
|
||||
simulateduiwidgetX7.ui
|
||||
simulateduiwidgetX9.ui
|
||||
simulateduiwidgetX12.ui
|
||||
simulatorstartupdialog.ui
|
||||
telemetrysimu.ui
|
||||
trainersimu.ui
|
||||
)
|
||||
@@ -26,8 +29,10 @@ set(simulation_UIS
|
||||
set(simulation_HDRS
|
||||
debugoutput.h
|
||||
radiouiaction.h
|
||||
simulatordialog.h
|
||||
simulateduiwidget.h
|
||||
# simulator.h
|
||||
simulatordialog.h
|
||||
simulatorstartupdialog.h
|
||||
telemetrysimu.h
|
||||
trainersimu.h
|
||||
widgets/buttonswidget.h
|
||||
|
||||
@@ -20,12 +20,16 @@
|
||||
|
||||
#include "joystickdialog.h"
|
||||
#include "ui_joystickdialog.h"
|
||||
#include "appdata.h"
|
||||
|
||||
joystickDialog::joystickDialog(QWidget *parent, int stick) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::joystickDialog) {
|
||||
QDialog(parent),
|
||||
ui(new Ui::joystickDialog),
|
||||
step(0),
|
||||
numAxes(0),
|
||||
started(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
int jscaltmp[8][3] = {
|
||||
{32767, 0, -32767},
|
||||
{32767, 0, -32767},
|
||||
@@ -37,137 +41,231 @@ ui(new Ui::joystickDialog) {
|
||||
{32767, 0, -32767}
|
||||
};
|
||||
memcpy(jscal, jscaltmp, sizeof (jscal));
|
||||
ui->okButton->setDisabled(true);
|
||||
ui->howtoLabel->setText(tr("Move sticks and pots in every direction making full movement\nPress next when finished"));
|
||||
step = 0;
|
||||
|
||||
foreach(QComboBox *cb, findChildren<QComboBox *>(QRegExp("jsmapCB_[0-9]+"))) {
|
||||
cb->setDisabled(true);
|
||||
sticks[cb->property("channel").toUInt()] = cb;
|
||||
}
|
||||
foreach(QCheckBox *ib, findChildren<QCheckBox *>(QRegExp("ChInv_[0-9]+"))) {
|
||||
ib->setDisabled(true);
|
||||
invert[ib->property("channel").toUInt()] = ib;
|
||||
}
|
||||
joystickOpen(stick);
|
||||
foreach(QSlider *sl, findChildren<QSlider *>(QRegExp("Ch_[0-9]+"))) {
|
||||
sliders[sl->property("channel").toUInt()] = sl;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_JOYSTICKS; ++i) {
|
||||
if (!g.joystick[i].existsOnDisk())
|
||||
continue;
|
||||
|
||||
jscal[i][0] = g.joystick[i].stick_min();
|
||||
jscal[i][1] = g.joystick[i].stick_med();
|
||||
jscal[i][2] = g.joystick[i].stick_max();
|
||||
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);
|
||||
}
|
||||
|
||||
ui->backButton->setEnabled(false);
|
||||
|
||||
ui->joystickChkB->setChecked(g.jsSupport() || stick > -1);
|
||||
|
||||
if (stick < 0)
|
||||
stick = g.jsCtrl();
|
||||
|
||||
loadJoysticks(stick);
|
||||
loadStep();
|
||||
|
||||
connect(joystick, SIGNAL(axisValueChanged(int, int)), this, SLOT(onjoystickAxisValueChanged(int, int)));
|
||||
connect(ui->joystickCB, SIGNAL(currentIndexChanged(int)), this, SLOT(joystickOpen(int)));
|
||||
connect(ui->joystickChkB, SIGNAL(toggled(bool)), this, SLOT(joystickSetEnabled(bool)));
|
||||
}
|
||||
|
||||
joystickDialog::~joystickDialog() {
|
||||
joystickDialog::~joystickDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void joystickDialog::joystickOpen(int stick) {
|
||||
if (stick == -1) {
|
||||
this->close();
|
||||
void joystickDialog::loadJoysticks(int stick)
|
||||
{
|
||||
QStringList joystickNames;
|
||||
bool found = false;
|
||||
|
||||
ui->joystickCB->clear();
|
||||
joystickNames << tr("No joysticks found");
|
||||
joystick = new Joystick(0, false, 0, 0);
|
||||
if ( joystick ) {
|
||||
if ( joystick->joystickNames.count() > 0 ) {
|
||||
joystickNames = joystick->joystickNames;
|
||||
found = true;
|
||||
}
|
||||
joystick->close();
|
||||
}
|
||||
ui->joystickCB->insertItems(0, joystickNames);
|
||||
if (found && stick < joystickNames.size())
|
||||
ui->joystickCB->setCurrentIndex(stick);
|
||||
else if (!found)
|
||||
ui->joystickCB->setCurrentIndex(0);
|
||||
|
||||
joystickSetEnabled(found && ui->joystickChkB->isChecked());
|
||||
}
|
||||
|
||||
void joystickDialog::joystickOpen(int stick)
|
||||
{
|
||||
if (stick == -1 || !ui->joystickChkB->isChecked() || !ui->joystickCB->isEnabled()) {
|
||||
ui->calibrationWidget->setDisabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
ui->calibrationWidget->setEnabled(true);
|
||||
ui->nextButton->setEnabled(true);
|
||||
|
||||
joystick = new Joystick(this, 1, false, 0);
|
||||
int numAxes=std::min(joystick->numAxes,8);
|
||||
if (joystick) {
|
||||
joystick->open(stick);
|
||||
|
||||
if (joystick && joystick->open(stick)) {
|
||||
numAxes = std::min(joystick->numAxes, MAX_JOYSTICKS);
|
||||
for (int j=0; j<numAxes; j++) {
|
||||
joystick->sensitivities[j] = 0;
|
||||
joystick->deadzones[j]=20;
|
||||
joystick->sensitivities[j] = 0;
|
||||
joystick->deadzones[j]=20;
|
||||
}
|
||||
}
|
||||
else {
|
||||
QMessageBox::critical(this, tr("Error"), tr("Cannot open joystick."));
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
|
||||
void joystickDialog::onjoystickAxisValueChanged(int axis, int value) {
|
||||
if (value > jscal[axis][2]) {
|
||||
jscal[axis][2] = value;
|
||||
}
|
||||
if (value < jscal[axis][0]) {
|
||||
jscal[axis][0] = value;
|
||||
}
|
||||
QSlider * sl[]= {ui->Ch_1, ui->Ch_2, ui->Ch_3, ui->Ch_4, ui->Ch_5, ui->Ch_6, ui->Ch_7, ui->Ch_8};
|
||||
QCheckBox * ib[]={ui->ChInv_1, ui->ChInv_2, ui->ChInv_3, ui->ChInv_4, ui->ChInv_5, ui->ChInv_6, ui->ChInv_7, ui->ChInv_8};
|
||||
if (ib[axis]->isChecked()) {
|
||||
sl[axis]->setInvertedAppearance(true);
|
||||
} else {
|
||||
sl[axis]->setInvertedAppearance(false);
|
||||
}
|
||||
sl[axis]->setMinimum(jscal[axis][0]);
|
||||
sl[axis]->setMaximum(jscal[axis][2]);
|
||||
sl[axis]->setValue(value);
|
||||
void joystickDialog::joystickSetEnabled(bool enable)
|
||||
{
|
||||
ui->joystickCB->setEnabled(enable);
|
||||
ui->calibrationWidget->setEnabled(enable);
|
||||
ui->nextButton->setEnabled(enable && step < 4);
|
||||
ui->backButton->setEnabled(enable && step);
|
||||
if (enable)
|
||||
joystickOpen(ui->joystickCB->currentIndex());
|
||||
}
|
||||
|
||||
void joystickDialog::on_nextButton_clicked() {
|
||||
int numAxes=std::min(joystick->numAxes,8);
|
||||
void joystickDialog::onjoystickAxisValueChanged(int axis, int value)
|
||||
{
|
||||
if (axis >= MAX_JOYSTICKS)
|
||||
return;
|
||||
|
||||
if (started) {
|
||||
if (value > jscal[axis][2])
|
||||
jscal[axis][2] = value;
|
||||
else if (value < jscal[axis][0])
|
||||
jscal[axis][0] = value;
|
||||
|
||||
sliders[axis]->setMinimum(jscal[axis][0]);
|
||||
sliders[axis]->setMaximum(jscal[axis][2]);
|
||||
}
|
||||
sliders[axis]->setInvertedAppearance(invert[axis]->isChecked());
|
||||
sliders[axis]->setValue(value);
|
||||
}
|
||||
|
||||
void joystickDialog::loadStep()
|
||||
{
|
||||
switch (step) {
|
||||
case 0:
|
||||
ui->howtoLabel->setText(tr("Place sticks and pots in middle position.\nPress next when done"));
|
||||
step++;
|
||||
ui->howtoLabel->setText(tr("Press the Start button to start the stick range calibration procedure.\n" \
|
||||
"You may change the channel assignments or inversion at any time."));
|
||||
ui->backButton->setDisabled(true);
|
||||
break;
|
||||
case 1:
|
||||
for (int i=0; i<numAxes; i++) {
|
||||
jscal[i][1]=0;
|
||||
for (int j=0; j<100;j++) {
|
||||
jscal[i][1]+=joystick->getAxisValue(i);
|
||||
}
|
||||
jscal[i][1]/=100;
|
||||
}
|
||||
ui->howtoLabel->setText(tr("Map joystick channels to controls using comboboxes.\nPress next when done"));
|
||||
step++;
|
||||
foreach(QComboBox *cb, findChildren<QComboBox *>(QRegExp("jsmapCB_[0-9]+"))) {
|
||||
cb->setEnabled(true);
|
||||
}
|
||||
started = true;
|
||||
ui->howtoLabel->setText(tr("Move sticks and pots in every direction making full movement\nPress Next when finished"));
|
||||
ui->nextButton->setText(tr("Next"));
|
||||
ui->backButton->setDisabled(true);
|
||||
break;
|
||||
case 2:
|
||||
ui->howtoLabel->setText(tr("Check inversion checkbox to get maximum at top-right position.\nPress next when done"));
|
||||
step++;
|
||||
foreach(QCheckBox *ib, findChildren<QCheckBox *>(QRegExp("ChInv_[0-9]+"))) {
|
||||
ib->setEnabled(true);
|
||||
}
|
||||
ui->howtoLabel->setText(tr("Place sticks and pots in middle position.\nPress Next when done"));
|
||||
ui->backButton->setEnabled(true);
|
||||
ui->nextButton->setEnabled(true);
|
||||
break;
|
||||
case 3:
|
||||
ui->howtoLabel->setText(tr("Press ok to save configuration\nPress cancel to abort joystick calibration"));
|
||||
ui->okButton->setEnabled(true);
|
||||
for (int i=0; i < numAxes; i++) {
|
||||
jscal[i][1]=0;
|
||||
for (int j=0; j < 100; j++) {
|
||||
jscal[i][1] += joystick->getAxisValue(i);
|
||||
}
|
||||
jscal[i][1] /= 100;
|
||||
}
|
||||
ui->howtoLabel->setText(tr("Map joystick channels to controls using comboboxes.\nPress Next when done."));
|
||||
ui->nextButton->setEnabled(true);
|
||||
break;
|
||||
case 4:
|
||||
ui->howtoLabel->setText(tr("Check inversion checkbox to if necessary to reverse direction.\nPress Next when done."));
|
||||
ui->nextButton->setEnabled(true);
|
||||
break;
|
||||
case 5:
|
||||
ui->howtoLabel->setText(tr("Press OK to save configuration\nPress Cancel to abort joystick calibration without saving."));
|
||||
ui->nextButton->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void joystickDialog::on_cancelButton_clicked() {
|
||||
void joystickDialog::on_backButton_clicked()
|
||||
{
|
||||
if (step) {
|
||||
--step;
|
||||
loadStep();
|
||||
}
|
||||
}
|
||||
|
||||
void joystickDialog::on_nextButton_clicked()
|
||||
{
|
||||
if (step < 5){
|
||||
++step;
|
||||
loadStep();
|
||||
}
|
||||
}
|
||||
|
||||
void joystickDialog::on_cancelButton_clicked()
|
||||
{
|
||||
joystick->close();
|
||||
this->close();
|
||||
this->reject();
|
||||
}
|
||||
|
||||
void joystickDialog::on_okButton_clicked()
|
||||
{
|
||||
int stickAssignments[MAX_JOYSTICKS] = {0};
|
||||
foreach(QComboBox *cb, findChildren<QComboBox *>(QRegExp("jsmapCB_[0-9]+"))) {
|
||||
int mappedValue = cb->currentIndex() - 1;
|
||||
// qDebug() << "cb->currentIndex()" << mappedValue;
|
||||
if (mappedValue >= 0 && mappedValue < MAX_JOYSTICKS) {
|
||||
stickAssignments[mappedValue]++;
|
||||
}
|
||||
int stick;
|
||||
|
||||
g.jsSupport(ui->joystickChkB->isChecked());
|
||||
g.jsCtrl(ui->joystickCB->currentIndex());
|
||||
|
||||
if (!g.jsSupport() || g.jsCtrl() < 0) {
|
||||
this->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i<MAX_JOYSTICKS; i++) {
|
||||
if (stickAssignments[i] > 1) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("Duplicated stick assignment"));
|
||||
if (started && step < 4) {
|
||||
int resp = QMessageBox::warning(this, tr("Warning"), tr("Calibration not complete, save anyway?"),
|
||||
QDialogButtonBox::Ok | QMessageBox::Default, QDialogButtonBox::Cancel | QMessageBox::Escape, QMessageBox::NoButton);
|
||||
if (resp == QDialogButtonBox::Cancel)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
joystick->close();
|
||||
for (int i=0; i<MAX_JOYSTICKS; i++) {
|
||||
|
||||
for (int i = 0; i < MAX_JOYSTICKS; ++i)
|
||||
g.joystick[i].remove();
|
||||
}
|
||||
QCheckBox * ib[]={ui->ChInv_1, ui->ChInv_2, ui->ChInv_3, ui->ChInv_4, ui->ChInv_5, ui->ChInv_6, ui->ChInv_7, ui->ChInv_8};
|
||||
foreach(QComboBox *cb, findChildren<QComboBox *>(QRegExp("jsmapCB_[0-9]+"))) {
|
||||
int axe=cb->objectName().mid(cb->objectName().lastIndexOf("_")+1).toInt()-1;
|
||||
int stick=cb->currentIndex() - 1;
|
||||
qDebug() << "joystick mapping " << cb->objectName() <<"axe:" << axe << "stick:" << stick;
|
||||
|
||||
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( axe );
|
||||
g.joystick[stick].stick_max( jscal[axe][2] );
|
||||
g.joystick[stick].stick_med( jscal[axe][1] );
|
||||
g.joystick[stick].stick_min( jscal[axe][0] );
|
||||
g.joystick[stick].stick_inv( ib[axe]->isChecked() ? 1 : 0 );
|
||||
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->close();
|
||||
this->accept();
|
||||
}
|
||||
|
||||
@@ -22,8 +22,13 @@
|
||||
#define _JOYSTICKDIALOG_H_
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "appdata.h"
|
||||
#include "joystick.h"
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QSlider;
|
||||
|
||||
namespace Ui {
|
||||
class joystickDialog;
|
||||
}
|
||||
@@ -32,25 +37,32 @@ class joystickDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit joystickDialog(QWidget *parent = 0, int stick=-1);
|
||||
~joystickDialog();
|
||||
Joystick *joystick;
|
||||
|
||||
public slots:
|
||||
void onjoystickAxisValueChanged(int axis, int value);
|
||||
|
||||
private:
|
||||
private:
|
||||
Ui::joystickDialog *ui;
|
||||
void joystickOpen(int stick);
|
||||
int jscal[8][3];
|
||||
int jscal[MAX_JOYSTICKS][3];
|
||||
QCheckBox * invert[MAX_JOYSTICKS];
|
||||
QComboBox * sticks[MAX_JOYSTICKS];
|
||||
QSlider * sliders[MAX_JOYSTICKS];
|
||||
int step;
|
||||
|
||||
private slots:
|
||||
int numAxes;
|
||||
bool started;
|
||||
|
||||
private slots:
|
||||
void loadJoysticks(int stick = -1);
|
||||
void joystickOpen(int stick);
|
||||
void joystickSetEnabled(bool enable);
|
||||
void onjoystickAxisValueChanged(int axis, int value);
|
||||
void loadStep();
|
||||
void on_backButton_clicked();
|
||||
void on_nextButton_clicked();
|
||||
void on_cancelButton_clicked();
|
||||
void on_okButton_clicked();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // _JOYSTICKDIALOG_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,8 @@ class SimulatorInterface;
|
||||
class LcdWidget;
|
||||
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).
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 SIMULATOR_H
|
||||
#define SIMULATOR_H
|
||||
|
||||
#include <QColor>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
|
||||
#define SIMULATOR_OPTIONS_VERSION 1
|
||||
|
||||
namespace Simulator {
|
||||
|
||||
typedef QPair<QString, QString> keymapHelp_t;
|
||||
|
||||
}
|
||||
|
||||
struct SimulatorOptions
|
||||
{
|
||||
enum StartupDataTypes {
|
||||
START_WITH_FILE = 0,
|
||||
START_WITH_FOLDER,
|
||||
START_WITH_SDPATH,
|
||||
START_WITH_RAWDATA
|
||||
};
|
||||
|
||||
private:
|
||||
quint16 _version = SIMULATOR_OPTIONS_VERSION; // structure definition version
|
||||
|
||||
public:
|
||||
// v1 fields
|
||||
quint8 startupDataType = START_WITH_FILE;
|
||||
QString firmwareId;
|
||||
QString dataFile;
|
||||
QString dataFolder;
|
||||
QString sdPath;
|
||||
QByteArray windowGeometry;
|
||||
QList<QByteArray> controlsState; // saved switch/pot/stick settings
|
||||
QColor lcdColor;
|
||||
|
||||
friend QDataStream & operator << (QDataStream &out, const SimulatorOptions & o)
|
||||
{
|
||||
out << o._version << o.startupDataType << o.firmwareId << o.dataFile << o.dataFolder
|
||||
<< o.sdPath << o.windowGeometry << o.controlsState << o.lcdColor;
|
||||
return out;
|
||||
}
|
||||
|
||||
friend QDataStream & operator >> (QDataStream &in, SimulatorOptions & o)
|
||||
{
|
||||
if (o._version <= SIMULATOR_OPTIONS_VERSION) {
|
||||
in >> o._version >> o.startupDataType >> o.firmwareId >> o.dataFile >> o.dataFolder
|
||||
>> o.sdPath >> o.windowGeometry >> o.controlsState >> o.lcdColor;
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
friend QDebug operator << (QDebug d, const SimulatorOptions & o)
|
||||
{
|
||||
QDebugStateSaver saver(d);
|
||||
d.nospace() << "SimulatorOptions: firmwareId=" << o.firmwareId << "; dataFile=" << o.dataFile << "; dataFolder=" << o.dataFolder
|
||||
<< "; sdPath=" << o.sdPath << "; startupDataType=" << o.startupDataType;
|
||||
return d;
|
||||
}
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(SimulatorOptions)
|
||||
|
||||
|
||||
#endif // SIMULATOR_H
|
||||
@@ -30,12 +30,13 @@
|
||||
#include "sdcard.h"
|
||||
#include "simulateduiwidget.h"
|
||||
#include "simulatorinterface.h"
|
||||
//#include "storage.h"
|
||||
#include "storage.h"
|
||||
#include "telemetrysimu.h"
|
||||
#include "trainersimu.h"
|
||||
#include "virtualjoystickwidget.h"
|
||||
#ifdef JOYSTICKS
|
||||
#include "joystick.h"
|
||||
#include "joystickdialog.h"
|
||||
#endif
|
||||
|
||||
#include <QDebug>
|
||||
@@ -71,7 +72,9 @@ SimulatorDialog::SimulatorDialog(QWidget * parent, SimulatorInterface *simulator
|
||||
lastPhase(-1),
|
||||
buttonPressed(0),
|
||||
trimPressed(TRIM_NONE),
|
||||
eepromDataFromFile(false),
|
||||
startupFromFile(false),
|
||||
deleteTempRadioData(false),
|
||||
saveTempRadioData(false),
|
||||
middleButtonPressed(false)
|
||||
{
|
||||
setWindowFlags(Qt::Window);
|
||||
@@ -80,6 +83,10 @@ SimulatorDialog::SimulatorDialog(QWidget * parent, SimulatorInterface *simulator
|
||||
traceCallbackInstance = this;
|
||||
simulator->installTraceHook(traceCb);
|
||||
|
||||
// defaults
|
||||
setRadioProfileId(radioProfileId);
|
||||
setSdPath(g.profile[radioProfileId].sdPath());
|
||||
|
||||
setupUi();
|
||||
}
|
||||
|
||||
@@ -98,8 +105,13 @@ SimulatorDialog::~SimulatorDialog()
|
||||
void SimulatorDialog::setRadioProfileId(int value)
|
||||
{
|
||||
radioProfileId = value;
|
||||
simulator->setVolumeGain(g.profile[radioProfileId].volumeGain());
|
||||
setPaths(g.profile[radioProfileId].sdPath(), radioDataPath);
|
||||
if (simulator)
|
||||
simulator->setVolumeGain(g.profile[radioProfileId].volumeGain());
|
||||
}
|
||||
|
||||
void SimulatorDialog::setSdPath(const QString & sdPath)
|
||||
{
|
||||
setPaths(sdPath, radioDataPath);
|
||||
}
|
||||
|
||||
void SimulatorDialog::setDataPath(const QString & dataPath)
|
||||
@@ -111,7 +123,8 @@ void SimulatorDialog::setPaths(const QString & sdPath, const QString & dataPath)
|
||||
{
|
||||
sdCardPath = sdPath;
|
||||
radioDataPath = dataPath;
|
||||
simulator->setSdPath(sdPath, dataPath);
|
||||
if (simulator)
|
||||
simulator->setSdPath(sdPath, dataPath);
|
||||
}
|
||||
|
||||
void SimulatorDialog::setRadioSettings(const GeneralSettings settings)
|
||||
@@ -119,35 +132,66 @@ void SimulatorDialog::setRadioSettings(const GeneralSettings settings)
|
||||
radioSettings = settings;
|
||||
}
|
||||
|
||||
void SimulatorDialog::setEepromData(const QByteArray & eeprom, bool fromFile)
|
||||
/*
|
||||
* This function can accept no parameters, a file name (QString is a QBA), or a data array. It will attempt to load radio settings data from one of
|
||||
* several sources into a RadioData object, parse the data, and then pass it on as appropriate to the SimulatorInterface in start().
|
||||
* If given no/blank <eeprom>, and setDataPath() was already called, then it will check that directory for "Horus-style" data files.
|
||||
* If given a file name, set the <fromFile> parameter to 'true'. This will attempt to load radio settings from said file
|
||||
* and later start the simulator interface in start() using the same data.
|
||||
* If <eeprom> is a byte array of data, attempts to load radio settings from there and will also start the simulator interface
|
||||
* with the same data when start() is called.
|
||||
* If you already have a valid RadioData structure, call setRadioData() instead.
|
||||
*/
|
||||
void SimulatorDialog::setStartupData(const QByteArray & dataSource, bool fromFile)
|
||||
{
|
||||
RadioData simuData;
|
||||
quint16 ret = 1;
|
||||
QString error;
|
||||
|
||||
if (eeprom.isEmpty() && !radioDataPath.isEmpty()) {
|
||||
// FIXME : need Storage classes to return error code, not just a message.
|
||||
// If <eeprom> is blank but we have a data path, use that for individual radio/model files.
|
||||
if (dataSource.isEmpty() && !radioDataPath.isEmpty()) {
|
||||
// If directory structure already exists, try to load data from there.
|
||||
// FIXME : need Storage class to return formal error code, not just a boolean, because it would be better
|
||||
// to avoid hard-coding paths like "RADIO" here. E.g. did it fail due to no data at all, or corrupt data, or...?
|
||||
if (QDir(QString(radioDataPath).append("/RADIO")).exists()) {
|
||||
SdcardFormat sdcard(radioDataPath);
|
||||
ret = sdcard.load(simuData);
|
||||
if (!ret)
|
||||
if (!(ret = sdcard.load(simuData)))
|
||||
error = sdcard.error();
|
||||
}
|
||||
}
|
||||
// Supposedly we're being given a file name to use, try that out.
|
||||
else if (fromFile) {
|
||||
// Storage store = Storage(QString(eeprom));
|
||||
// if (!(ret = store.load(simuData))) {
|
||||
// error = store.error();
|
||||
// }
|
||||
QFile file;
|
||||
QByteArray ba;
|
||||
file.setFileName(QString(eeprom));
|
||||
if (file.exists() && file.open(QIODevice::ReadOnly) && !(ba = file.readAll()).isEmpty()) {
|
||||
ret = firmware->getEEpromInterface()->load(simuData, (uint8_t *)ba.constData(), getEEpromSize(m_board));
|
||||
Storage store = Storage(QString(dataSource));
|
||||
if ((ret = store.load(simuData))) {
|
||||
if (IS_HORUS(m_board)) {
|
||||
// save the data to a temp folder
|
||||
if (!(ret = useTempDataPath(true, true))) // save data back to file on simulator close
|
||||
error = tr("Error: Could not save data to temporary directory in '%1'").arg(QDir::tempPath());
|
||||
else
|
||||
ret = saveRadioData(&simuData, radioDataPath, &error);
|
||||
}
|
||||
else if (QString(dataSource).endsWith(".otx", Qt::CaseInsensitive)) {
|
||||
// FIXME : Right now there's no way to read data back into the .otx file after simulation finishes.
|
||||
setRadioData(&simuData);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
startupData = dataSource; // save the file name for start()
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = store.error();
|
||||
}
|
||||
}
|
||||
else if (!eeprom.isEmpty()) {
|
||||
ret = firmware->getEEpromInterface()->load(simuData, (uint8_t *)eeprom.constData(), getEEpromSize(m_board));
|
||||
// Assume a byte array of radio data was passed, load it.
|
||||
else if (!dataSource.isEmpty()) {
|
||||
ret = firmware->getEEpromInterface()->load(simuData, (uint8_t *)dataSource.constData(), getEEpromSize(m_board));
|
||||
startupData = dataSource; // save the data for start()
|
||||
}
|
||||
// we're :-(
|
||||
else {
|
||||
ret = 0;
|
||||
error = tr("Could not determine startup data source.");
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
@@ -158,8 +202,7 @@ void SimulatorDialog::setEepromData(const QByteArray & eeprom, bool fromFile)
|
||||
}
|
||||
|
||||
radioSettings = simuData.generalSettings;
|
||||
eepromData = eeprom;
|
||||
eepromDataFromFile = fromFile;
|
||||
startupFromFile = fromFile;
|
||||
}
|
||||
|
||||
void SimulatorDialog::setRadioData(RadioData * radioData)
|
||||
@@ -167,15 +210,108 @@ void SimulatorDialog::setRadioData(RadioData * radioData)
|
||||
if (radioDataPath.isEmpty()) {
|
||||
QByteArray eeprom(getEEpromSize(m_board), 0);
|
||||
if (firmware->getEEpromInterface()->save((uint8_t *)eeprom.data(), *radioData, 0, firmware->getCapability(SimulatorVariant)) > 0)
|
||||
setEepromData(eeprom, false);
|
||||
setStartupData(eeprom, false);
|
||||
}
|
||||
else {
|
||||
SdcardFormat sdcard(radioDataPath);
|
||||
sdcard.write(*radioData);
|
||||
saveRadioData(radioData, radioDataPath);
|
||||
radioSettings = radioData->generalSettings;
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::setOptions(SimulatorOptions & options, bool withSave)
|
||||
{
|
||||
setSdPath(options.sdPath);
|
||||
if (options.startupDataType == SimulatorOptions::START_WITH_FOLDER && !options.dataFolder.isEmpty()) {
|
||||
setDataPath(options.dataFolder);
|
||||
setStartupData();
|
||||
}
|
||||
else if (options.startupDataType == SimulatorOptions::START_WITH_SDPATH && !options.sdPath.isEmpty()) {
|
||||
setDataPath(options.sdPath);
|
||||
setStartupData();
|
||||
}
|
||||
else if (options.startupDataType == SimulatorOptions::START_WITH_FILE && !options.dataFile.isEmpty()) {
|
||||
setStartupData(options.dataFile.toLocal8Bit(), true);
|
||||
}
|
||||
|
||||
if (withSave)
|
||||
g.profile[radioProfileId].simulatorOptions(options);
|
||||
}
|
||||
|
||||
bool SimulatorDialog::saveRadioData(RadioData * radioData, const QString & path, QString * error)
|
||||
{
|
||||
QString dir = path;
|
||||
if (dir.isEmpty())
|
||||
dir = radioDataPath;
|
||||
if (radioData && !dir.isEmpty()) {
|
||||
SdcardFormat sdcard(dir);
|
||||
bool ret = sdcard.write(*radioData);
|
||||
if (!ret && error)
|
||||
*error = sdcard.error();
|
||||
return ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SimulatorDialog::useTempDataPath(bool deleteOnClose, bool saveOnClose)
|
||||
{
|
||||
if (deleteTempRadioData)
|
||||
deleteTempData();
|
||||
|
||||
QTemporaryDir tmpDir(QDir::tempPath() + "/otx-XXXXXX");
|
||||
if (tmpDir.isValid()) {
|
||||
setDataPath(tmpDir.path());
|
||||
tmpDir.setAutoRemove(false);
|
||||
deleteTempRadioData = deleteOnClose;
|
||||
saveTempRadioData = saveOnClose;
|
||||
qDebug() << __FILE__ << __LINE__ << "Created temporary settings directory" << radioDataPath
|
||||
<< "with delteOnClose:" << deleteOnClose << "with saveOnClose:" << saveOnClose;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qDebug() << __FILE__ << __LINE__ << "ERROR : Failed to create temporary settings directory" << radioDataPath;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This will save radio data from temporary folder structure back into an .otx file, eg. for Horus.
|
||||
bool SimulatorDialog::saveTempData()
|
||||
{
|
||||
bool ret = false;
|
||||
QString error;
|
||||
QString file = g.profile[radioProfileId].simulatorOptions().dataFile;
|
||||
|
||||
if (!saveTempRadioData || radioDataPath.isEmpty() || file.isEmpty())
|
||||
return ret;
|
||||
|
||||
RadioData radioData;
|
||||
SdcardFormat sdcard(radioDataPath);
|
||||
if (!(ret = sdcard.load(radioData))) {
|
||||
error = sdcard.error();
|
||||
}
|
||||
else {
|
||||
Storage store(file);
|
||||
if (!(ret = store.write(radioData)))
|
||||
error = store.error();
|
||||
else
|
||||
qDebug() << __FILE__ << __LINE__ << "Saved radio data to file" << file;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
QMessageBox::critical(this, tr("Data Save Error"), error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SimulatorDialog::deleteTempData()
|
||||
{
|
||||
if (!radioDataPath.isEmpty()) {
|
||||
QDir tpath(radioDataPath);
|
||||
qDebug() << __FILE__ << __LINE__ << "Deleting temporary settings directory" << tpath.absolutePath();
|
||||
tpath.removeRecursively();
|
||||
tpath.rmdir(radioDataPath); // for some reason this is necessary to remove the base folder
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::setUiAreaStyle(const QString & style)
|
||||
{
|
||||
ui->radioUiTab->setStyleSheet(style);
|
||||
@@ -192,6 +328,31 @@ void SimulatorDialog::traceCallback(const char * text)
|
||||
traceMutex.unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup
|
||||
*/
|
||||
|
||||
void SimulatorDialog::start()
|
||||
{
|
||||
setupRadioWidgets();
|
||||
setupJoysticks();
|
||||
setupOutputsDisplay();
|
||||
setupGVarsDisplay();
|
||||
restoreRadioWidgetsState();
|
||||
setTrims();
|
||||
|
||||
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);
|
||||
|
||||
getValues();
|
||||
setupTimer();
|
||||
startupData.clear(); // this is safe because simulator->start() makes copy of data/discards the file name
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup
|
||||
*/
|
||||
@@ -220,7 +381,6 @@ void SimulatorDialog::setupUi()
|
||||
break;
|
||||
}
|
||||
|
||||
// support for <QT5.5
|
||||
foreach (keymapHelp_t item, *radioUiWidget->getKeymapHelp()) {
|
||||
keymapHelp.append(item);
|
||||
}
|
||||
@@ -235,47 +395,6 @@ void SimulatorDialog::setupUi()
|
||||
vJoyRight = new VirtualJoystickWidget(this, 'R');
|
||||
ui->rightStickLayout->addWidget(vJoyRight);
|
||||
|
||||
#ifdef JOYSTICKS
|
||||
if (g.jsSupport()) {
|
||||
int count=0;
|
||||
for (int j=0; j<8; j++){
|
||||
int axe = g.joystick[j].stick_axe();
|
||||
if (axe>=0 && axe<8) {
|
||||
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"));
|
||||
}
|
||||
if (g.jsCtrl()!=-1) {
|
||||
joystick = new Joystick(this);
|
||||
if (joystick) {
|
||||
if (joystick->open(g.jsCtrl())) {
|
||||
int numAxes=std::min(joystick->numAxes,8);
|
||||
for (int j=0; j<numAxes; j++) {
|
||||
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)));
|
||||
}
|
||||
else {
|
||||
QMessageBox::critical(this, tr("Warning"), tr("Cannot open joystick, joystick disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ui->tabWidget->setCurrentIndex(flags & SIMULATOR_FLAGS_NOTX);
|
||||
|
||||
connect(vJoyLeft, SIGNAL(trimButtonPressed(int)), this, SLOT(onTrimPressed(int)));
|
||||
@@ -287,30 +406,43 @@ void SimulatorDialog::setupUi()
|
||||
connect(vJoyRight, SIGNAL(trimSliderMoved(int,int)), this, SLOT(onTrimSliderMoved(int,int)));
|
||||
|
||||
connect(ui->btn_help, SIGNAL(released()), this, SLOT(showHelp()));
|
||||
connect(ui->btn_joystickDialog, SIGNAL(released()), this, SLOT(openJoystickDialog()));
|
||||
connect(ui->btn_telemSim, SIGNAL(released()), this, SLOT(openTelemetrySimulator()));
|
||||
connect(ui->btn_trainerSim, SIGNAL(released()), this, SLOT(openTrainerSimulator()));
|
||||
connect(ui->btn_debugConsole, SIGNAL(released()), this, SLOT(openDebugOutput()));
|
||||
connect(ui->btn_luaReload, SIGNAL(released()), this, SLOT(luaReload()));
|
||||
connect(ui->btn_screenshot, SIGNAL(released()), radioUiWidget, SLOT(captureScreenshot()));
|
||||
|
||||
// Hide some main UI buttons based on board capabilities, and add keymap help texts.
|
||||
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_help->shortcut().toString(QKeySequence::NativeText), ui->btn_help->statusTip()));
|
||||
if (!firmware->getCapability(Capability(LuaInputsPerScript))) // hackish! but using "LuaScripts" checks for id "lua" in fw.
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_telemSim->shortcut().toString(QKeySequence::NativeText), ui->btn_telemSim->statusTip()));
|
||||
else
|
||||
ui->btn_luaReload->hide();
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_trainerSim->shortcut().toString(QKeySequence::NativeText), ui->btn_trainerSim->statusTip()));
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_debugConsole->shortcut().toString(QKeySequence::NativeText), ui->btn_debugConsole->statusTip()));
|
||||
|
||||
#ifdef JOYSTICKS
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_joystickDialog->shortcut().toString(QKeySequence::NativeText), ui->btn_joystickDialog->statusTip()));
|
||||
#else
|
||||
ui->btn_joystickDialog->hide();
|
||||
#endif
|
||||
|
||||
if (firmware->getCapability(Capability(SportTelemetry)))
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_luaReload->shortcut().toString(QKeySequence::NativeText), ui->btn_luaReload->statusTip()));
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_telemSim->shortcut().toString(QKeySequence::NativeText), ui->btn_luaReload->statusTip()));
|
||||
else
|
||||
ui->btn_telemSim->hide();
|
||||
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_trainerSim->shortcut().toString(QKeySequence::NativeText), ui->btn_trainerSim->statusTip()));
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_debugConsole->shortcut().toString(QKeySequence::NativeText), ui->btn_debugConsole->statusTip()));
|
||||
|
||||
if (!firmware->getCapability(Capability(LuaInputsPerScript))) // hackish! but using "LuaScripts" checks for id "lua" in fw.
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_luaReload->shortcut().toString(QKeySequence::NativeText), ui->btn_telemSim->statusTip()));
|
||||
else
|
||||
ui->btn_luaReload->hide();
|
||||
|
||||
keymapHelp.append(keymapHelp_t(ui->btn_screenshot->shortcut().toString(QKeySequence::NativeText), ui->btn_screenshot->statusTip()));
|
||||
|
||||
}
|
||||
|
||||
void SimulatorDialog::setupRadioWidgets()
|
||||
{
|
||||
int i, midpos, aIdx;
|
||||
int i, midpos, aIdx, wval;
|
||||
QString wname;
|
||||
Board::Type board = firmware->getBoard();
|
||||
|
||||
@@ -335,16 +467,20 @@ void SimulatorDialog::setupRadioWidgets()
|
||||
|
||||
// switches
|
||||
Board::SwitchInfo switchInfo;
|
||||
Board::SwitchType swcfg;
|
||||
// FIXME : CPN_MAX_SWITCHES == 32 but GeneralSettings::switchConfig[18] !!
|
||||
for (i = 0; i < firmware->getCapability(Capability(Switches)) && i < 18 /*CPN_MAX_SWITCHES*/; ++i) {
|
||||
if (radioSettings.switchConfig[i] == Board::SWITCH_NOT_AVAILABLE)
|
||||
continue;
|
||||
|
||||
swcfg = Board::SwitchType(radioSettings.switchConfig[i]);
|
||||
wval = (swcfg == Board::SWITCH_3POS ? -1 : 0);
|
||||
|
||||
if ((wname = QString(radioSettings.switchName[i])).isEmpty()) {
|
||||
switchInfo = getSwitchInfo(board, i);
|
||||
wname = QString(switchInfo.name);
|
||||
}
|
||||
RadioSwitchWidget * sw = new RadioSwitchWidget(Board::SwitchType(radioSettings.switchConfig[i]), wname, 0, ui->radioWidgetsHT);
|
||||
RadioSwitchWidget * sw = new RadioSwitchWidget(swcfg, wname, wval, ui->radioWidgetsHT);
|
||||
sw->setIndex(i);
|
||||
ui->radioWidgetsHTLayout->addWidget(sw);
|
||||
switches.append(sw);
|
||||
@@ -532,6 +668,56 @@ QFrame * SimulatorDialog::createLogicalSwitch(QWidget * parent, int switchNo, QV
|
||||
return swtch;
|
||||
}
|
||||
|
||||
void SimulatorDialog::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;
|
||||
}
|
||||
joystick = new Joystick(this);
|
||||
if (joystick && joystick->open(g.jsCtrl())) {
|
||||
int numAxes = std::min(joystick->numAxes, MAX_JOYSTICKS);
|
||||
for (int j=0; j<numAxes; j++) {
|
||||
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)));
|
||||
joysticksEnabled = true;
|
||||
}
|
||||
else {
|
||||
QMessageBox::critical(this, tr("Warning"), tr("Cannot open joystick, joystick disabled"));
|
||||
}
|
||||
}
|
||||
else if (joysticksEnabled && joystick) {
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimulatorDialog::setupTimer()
|
||||
{
|
||||
timer = new QTimer(this);
|
||||
@@ -539,26 +725,44 @@ void SimulatorDialog::setupTimer()
|
||||
timer->start(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup
|
||||
*/
|
||||
|
||||
void SimulatorDialog::start()
|
||||
void SimulatorDialog::restoreRadioWidgetsState()
|
||||
{
|
||||
setupRadioWidgets();
|
||||
setupOutputsDisplay();
|
||||
setupGVarsDisplay();
|
||||
setTrims();
|
||||
RadioWidget::RadioWidgetState state;
|
||||
QMap<int, QByteArray> switchesMap;
|
||||
QMap<int, QByteArray> analogsMap;
|
||||
QList<QByteArray> states = g.profile[radioProfileId].simulatorOptions().controlsState;
|
||||
|
||||
if (eepromData.isEmpty())
|
||||
simulator->start((const char *)0);
|
||||
else if (eepromDataFromFile)
|
||||
simulator->start(eepromData.constData());
|
||||
else
|
||||
simulator->start(eepromData, (flags & SIMULATOR_FLAGS_NOTX) ? false : true);
|
||||
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);
|
||||
}
|
||||
|
||||
setupTimer();
|
||||
eepromData.clear(); // this is safe because simulator->start() makes copy of data/discards the file name
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
QList<QByteArray> SimulatorDialog::saveRadioWidgetsState()
|
||||
{
|
||||
QList<QByteArray> 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -687,14 +891,21 @@ void SimulatorDialog::closeEvent(QCloseEvent *)
|
||||
{
|
||||
simulator->stop();
|
||||
timer->stop();
|
||||
g.profile[radioProfileId].simuWinGeo(saveGeometry());
|
||||
SimulatorOptions opts = g.profile[radioProfileId].simulatorOptions();
|
||||
opts.windowGeometry = saveGeometry();
|
||||
opts.controlsState = saveRadioWidgetsState();
|
||||
g.profile[radioProfileId].simulatorOptions(opts);
|
||||
if (saveTempRadioData)
|
||||
saveTempData();
|
||||
if (deleteTempRadioData)
|
||||
deleteTempData();
|
||||
}
|
||||
|
||||
void SimulatorDialog::showEvent(QShowEvent *)
|
||||
{
|
||||
static bool firstShow = true;
|
||||
if (firstShow) {
|
||||
restoreGeometry(g.profile[radioProfileId].simuWinGeo());
|
||||
restoreGeometry(g.profile[radioProfileId].simulatorOptions().windowGeometry);
|
||||
|
||||
// The stick position needs to be set after the final show event, otherwise resizes during dialog creation will screw it up.
|
||||
if (radioSettings.stickMode & 1) {
|
||||
@@ -803,6 +1014,16 @@ void SimulatorDialog::openTrainerSimulator()
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::openJoystickDialog()
|
||||
{
|
||||
#ifdef JOYSTICKS
|
||||
joystickDialog * jd = new joystickDialog(this);
|
||||
if (jd->exec() == QDialog::Accepted)
|
||||
setupJoysticks();
|
||||
jd->deleteLater();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimulatorDialog::openDebugOutput()
|
||||
{
|
||||
// allow only one instance, but install signal handler to catch dialog destruction just in case
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "constants.h"
|
||||
#include "helpers.h"
|
||||
#include "radiodata.h"
|
||||
#include "simulator.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QVector>
|
||||
@@ -39,8 +40,6 @@
|
||||
#define CBEEP_ON "QLabel { background-color: #FF364E }"
|
||||
#define CBEEP_OFF "QLabel { }"
|
||||
|
||||
typedef QPair<QString, QString> keymapHelp_t;
|
||||
|
||||
void traceCb(const char * text);
|
||||
|
||||
class Firmware;
|
||||
@@ -66,6 +65,8 @@ namespace Ui {
|
||||
class SimulatorDialog;
|
||||
}
|
||||
|
||||
using namespace Simulator;
|
||||
|
||||
class SimulatorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -75,22 +76,34 @@ class SimulatorDialog : public QDialog
|
||||
virtual ~SimulatorDialog();
|
||||
|
||||
void setRadioProfileId(int value);
|
||||
void setSdPath(const QString & sdPath);
|
||||
void setDataPath(const QString & dataPath);
|
||||
void setPaths(const QString & sdPath, const QString & dataPath);
|
||||
void setRadioSettings(const GeneralSettings settings);
|
||||
void setEepromData(const QByteArray & eeprom = NULL, bool fromFile = false);
|
||||
void setStartupData(const QByteArray & dataSource = NULL, bool fromFile = false);
|
||||
void setRadioData(RadioData * radioData);
|
||||
void setOptions(SimulatorOptions & options, bool withSave = true);
|
||||
bool saveRadioData(RadioData * radioData, const QString & path = "", QString * error = NULL);
|
||||
bool useTempDataPath(bool deleteOnClose = true, bool saveOnClose = false);
|
||||
bool saveTempData();
|
||||
void deleteTempData();
|
||||
void setUiAreaStyle(const QString & style);
|
||||
void traceCallback(const char * text);
|
||||
void start();
|
||||
|
||||
QString getSdPath() const { return sdCardPath; }
|
||||
QString getDataPath() const { return radioDataPath; }
|
||||
|
||||
private:
|
||||
void setupUi();
|
||||
void setupRadioWidgets();
|
||||
void setupOutputsDisplay();
|
||||
void setupGVarsDisplay();
|
||||
void setupJoysticks();
|
||||
QFrame * createLogicalSwitch(QWidget * parent, int switchNo, QVector<QLabel *> & labels);
|
||||
void setupTimer();
|
||||
void restoreRadioWidgetsState();
|
||||
QList<QByteArray> saveRadioWidgetsState();
|
||||
|
||||
void setValues();
|
||||
void getValues();
|
||||
@@ -125,14 +138,16 @@ class SimulatorDialog : public QDialog
|
||||
|
||||
QString sdCardPath;
|
||||
QString radioDataPath;
|
||||
QByteArray eepromData;
|
||||
QByteArray startupData;
|
||||
Board::Type m_board;
|
||||
quint8 flags;
|
||||
int radioProfileId;
|
||||
int lastPhase;
|
||||
int buttonPressed;
|
||||
int trimPressed;
|
||||
bool eepromDataFromFile;
|
||||
bool startupFromFile;
|
||||
bool deleteTempRadioData;
|
||||
bool saveTempRadioData;
|
||||
bool middleButtonPressed;
|
||||
|
||||
#ifdef JOYSTICKS
|
||||
@@ -155,6 +170,7 @@ class SimulatorDialog : public QDialog
|
||||
void centerSticks();
|
||||
void openTelemetrySimulator();
|
||||
void openTrainerSimulator();
|
||||
void openJoystickDialog();
|
||||
void openDebugOutput();
|
||||
void updateDebugOutput();
|
||||
void luaReload();
|
||||
|
||||
@@ -246,13 +246,29 @@
|
||||
<string>Show Help/Keymap</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Keymap</string>
|
||||
<string>Keymap Help</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_joystickDialog">
|
||||
<property name="toolTip">
|
||||
<string>Open the Joystick Settings window (F3)</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Telemetry Simulator</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Joystick Config.</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_telemSim">
|
||||
<property name="toolTip">
|
||||
@@ -262,7 +278,7 @@
|
||||
<string>Telemetry Simulator</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Telemetry Simulator</string>
|
||||
<string>Telemetry Sim.</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F4</string>
|
||||
@@ -278,7 +294,7 @@
|
||||
<string>Trainer Simulator</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Trainer Simulator</string>
|
||||
<string>Trainer Sim.</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F5</string>
|
||||
@@ -310,7 +326,7 @@
|
||||
<string>Reload Lua Scripts</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reload Lua Scripts</string>
|
||||
<string>Lua Reload</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F7</string>
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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 "simulatorstartupdialog.h"
|
||||
#include "ui_simulatorstartupdialog.h"
|
||||
|
||||
#include "appdata.h"
|
||||
#include "constants.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
extern AppData g;
|
||||
extern QMap<QString, SimulatorFactory *> registered_simulators;
|
||||
|
||||
SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int * profId, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::SimulatorStartupDialog),
|
||||
m_options(options),
|
||||
m_profileId(profId)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QMapIterator<int, QString> pi(g.getActiveProfiles());
|
||||
while (pi.hasNext()) {
|
||||
pi.next();
|
||||
ui->radioProfile->addItem(pi.value(), pi.key());
|
||||
}
|
||||
|
||||
ui->radioType->addItems(registered_simulators.keys());
|
||||
|
||||
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");
|
||||
ui->btnSelectDataFile->setIcon(icon);
|
||||
ui->btnSelectDataFolder->setIcon(icon);
|
||||
ui->btnSelectSdPath->setIcon(icon);
|
||||
|
||||
QObject::connect(ui->radioProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(onRadioProfileChanged(int)));
|
||||
QObject::connect(ui->radioType, SIGNAL(currentIndexChanged(int)), this, SLOT(onRadioTypeChanged(int)));
|
||||
QObject::connect(ui->btnSelectDataFile, &QToolButton::clicked, this, &SimulatorStartupDialog::onDataFileSelect);
|
||||
QObject::connect(ui->btnSelectDataFolder, &QToolButton::clicked, this, &SimulatorStartupDialog::onDataFolderSelect);
|
||||
QObject::connect(ui->btnSelectSdPath, &QToolButton::clicked, this, &SimulatorStartupDialog::onSdPathSelect);
|
||||
|
||||
loadRadioProfile(*m_profileId);
|
||||
}
|
||||
|
||||
SimulatorStartupDialog::~SimulatorStartupDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::changeEvent(QEvent *e)
|
||||
{
|
||||
QDialog::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME : need a better way to check for this
|
||||
bool SimulatorStartupDialog::usesCategorizedStorage(const QString & name)
|
||||
{
|
||||
return name.contains("horus", Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool SimulatorStartupDialog::usesCategorizedStorage()
|
||||
{
|
||||
return usesCategorizedStorage(ui->radioType->currentText());
|
||||
}
|
||||
|
||||
QString SimulatorStartupDialog::findRadioId(const QString & str)
|
||||
{
|
||||
QString radioId(str);
|
||||
int pos = str.indexOf("-");
|
||||
if (pos > 0) {
|
||||
radioId = str.mid(pos+1);
|
||||
pos = radioId.lastIndexOf("-");
|
||||
if (pos > 0) {
|
||||
radioId = radioId.mid(0, pos);
|
||||
}
|
||||
}
|
||||
return radioId;
|
||||
}
|
||||
|
||||
// TODO : this could be smarter and actually look for a matching file in the folder
|
||||
QString SimulatorStartupDialog::radioEepromFileName(const QString & firmwareId, QString folder)
|
||||
{
|
||||
QString eepromFileName = "", ext = "bin";
|
||||
|
||||
if (folder.isEmpty())
|
||||
folder = g.eepromDir();
|
||||
|
||||
QString radioId = findRadioId(firmwareId);
|
||||
if (usesCategorizedStorage(radioId))
|
||||
ext = "otx";
|
||||
|
||||
eepromFileName = QString("eeprom-%1.%2").arg(radioId, ext);
|
||||
eepromFileName = QDir(folder).filePath(eepromFileName.toLatin1());
|
||||
// qDebug() << "radioId" << radioId << "eepromFileName" << eepromFileName;
|
||||
|
||||
return eepromFileName;
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::updateContainerTypes(void)
|
||||
{
|
||||
static int oldstate = -1;
|
||||
int state = usesCategorizedStorage();
|
||||
|
||||
if (state == oldstate)
|
||||
return;
|
||||
|
||||
oldstate = state;
|
||||
|
||||
ui->wdgt_dataSource->setVisible(state);
|
||||
ui->layout_options->labelForField(ui->wdgt_dataSource)->setVisible(state);
|
||||
ui->wdgt_dataFolder->setVisible(state);
|
||||
ui->layout_options->labelForField(ui->wdgt_dataFolder)->setVisible(state);
|
||||
|
||||
if (!state || ui->optGrp_dataSource->checkedId() < 0)
|
||||
ui->optFile->setChecked(true);
|
||||
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::loadRadioProfile(int id)
|
||||
{
|
||||
QString tmpstr;
|
||||
int i;
|
||||
|
||||
if (id < 0 || !g.getActiveProfiles().contains(id))
|
||||
return;
|
||||
|
||||
i = ui->radioProfile->findData(id);
|
||||
if (i > -1 && ui->radioProfile->currentIndex() != i) {
|
||||
ui->radioProfile->setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
|
||||
*m_options = g.profile[id].simulatorOptions();
|
||||
|
||||
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();
|
||||
i = ui->radioType->findText(findRadioId(tmpstr), Qt::MatchFixedString | Qt::MatchContains);
|
||||
if (i > -1)
|
||||
ui->radioType->setCurrentIndex(i);
|
||||
|
||||
tmpstr = m_options->dataFile;
|
||||
if (!tmpstr.isEmpty())
|
||||
ui->dataFile->setText(tmpstr);
|
||||
|
||||
tmpstr = m_options->dataFolder;
|
||||
if (tmpstr.isEmpty())
|
||||
tmpstr = g.eepromDir();
|
||||
ui->dataFolder->setText(tmpstr);
|
||||
|
||||
tmpstr = m_options->sdPath;
|
||||
if (tmpstr.isEmpty())
|
||||
tmpstr = g.profile[id].sdPath();
|
||||
ui->sdPath->setText(tmpstr);
|
||||
|
||||
foreach (QAbstractButton * btn, ui->optGrp_dataSource->buttons()) {
|
||||
if (ui->optGrp_dataSource->id(btn) == m_options->startupDataType) {
|
||||
btn->setChecked(true);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
updateContainerTypes();
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::accept()
|
||||
{
|
||||
*m_profileId = ui->radioProfile->currentData().toInt();
|
||||
m_options->firmwareId = ui->radioType->currentText();
|
||||
m_options->dataFile = ui->dataFile->text();
|
||||
m_options->dataFolder = ui->dataFolder->text();
|
||||
m_options->sdPath = ui->sdPath->text();
|
||||
m_options->startupDataType = ui->optGrp_dataSource->checkedId();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::onRadioProfileChanged(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
loadRadioProfile(ui->radioProfile->currentData().toInt());
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::onRadioTypeChanged(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
ui->dataFile->setText(radioEepromFileName(ui->radioType->currentText()));
|
||||
updateContainerTypes();
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::onDataFileSelect(bool)
|
||||
{
|
||||
QString filter = tr(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()) {
|
||||
ui->dataFile->setText(file);
|
||||
ui->optFile->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::onDataFolderSelect(bool)
|
||||
{
|
||||
QString folder = QFileDialog::getExistingDirectory(this, QObject::tr("Select Data Directory"),
|
||||
ui->dataFolder->text(), QFileDialog::DontUseNativeDialog);
|
||||
if (!folder.isEmpty()) {
|
||||
ui->dataFolder->setText(folder);
|
||||
if (usesCategorizedStorage())
|
||||
ui->optFolder->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorStartupDialog::onSdPathSelect(bool)
|
||||
{
|
||||
QString folder = QFileDialog::getExistingDirectory(this, QObject::tr("Select SD Card Image Folder"),
|
||||
ui->sdPath->text(), QFileDialog::DontUseNativeDialog);
|
||||
if (!folder.isEmpty()) {
|
||||
ui->sdPath->setText(folder);
|
||||
if (usesCategorizedStorage())
|
||||
ui->optSdPath->setChecked(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef SIMULATORSTARTUPDIALOG_H
|
||||
#define SIMULATORSTARTUPDIALOG_H
|
||||
|
||||
#include "simulator.h"
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class SimulatorStartupDialog;
|
||||
}
|
||||
|
||||
using namespace Simulator;
|
||||
|
||||
class SimulatorStartupDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit SimulatorStartupDialog(SimulatorOptions * options, int * profId, QWidget *parent = 0);
|
||||
~SimulatorStartupDialog();
|
||||
|
||||
static bool usesCategorizedStorage(const QString & name);
|
||||
static QString findRadioId(const QString & str);
|
||||
static QString radioEepromFileName(const QString & firmwareId, QString folder = "");
|
||||
|
||||
void updateContainerTypes();
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void accept();
|
||||
void loadRadioProfile(int id);
|
||||
void onRadioProfileChanged(int index);
|
||||
void onRadioTypeChanged(int index);
|
||||
void onDataFileSelect(bool);
|
||||
void onDataFolderSelect(bool);
|
||||
void onSdPathSelect(bool);
|
||||
|
||||
protected:
|
||||
|
||||
bool usesCategorizedStorage();
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private:
|
||||
Ui::SimulatorStartupDialog *ui;
|
||||
SimulatorOptions * m_options;
|
||||
int * m_profileId;
|
||||
};
|
||||
|
||||
#endif // SIMULATORSTARTUPDIALOG_H
|
||||
@@ -0,0 +1,357 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SimulatorStartupDialog</class>
|
||||
<widget class="QDialog" name="SimulatorStartupDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>488</width>
|
||||
<height>219</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>OpenTX Simulator - Startup Options</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Simulator Startup Options:</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="layout_options">
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Radio Profile:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="radioProfile">
|
||||
<property name="toolTip">
|
||||
<string>Existing radio profiles are shown here.<br />
|
||||
Create or edit profiles using the Companion application.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Radio Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="radioType">
|
||||
<property name="toolTip">
|
||||
<string>Existing radio simulators are shown here.<br />
|
||||
The radio type specified in the selected profile is used by default.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Data Source:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Data File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Data Folder:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>SD Image Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QWidget" name="wdgt_dataFile" native="true">
|
||||
<layout class="QHBoxLayout" name="layout_dataFile" stretch="1,0">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="dataFile">
|
||||
<property name="toolTip">
|
||||
<string>Radio data (.bin/.eeprom/.otx) image file to use. A new file with a default image will be created if necessary.<br />
|
||||
<b>NOTE</b>: any existing EEPROM data incompatible with the selected radio type may be overwritten!</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSelectDataFile">
|
||||
<property name="toolTip">
|
||||
<string>Select data file...</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../companion.qrc">
|
||||
<normaloff>:/themes/monoblue/16/open.png</normaloff>:/themes/monoblue/16/open.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QWidget" name="wdgt_dataFolder" native="true">
|
||||
<layout class="QHBoxLayout" name="layout_dataFolder" stretch="1,0">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="dataFolder">
|
||||
<property name="toolTip">
|
||||
<string>Directory containing RADIO and MODELS folders to use.<br />
|
||||
New folder(s) with default radio/model will be created here if necessary.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSelectDataFolder">
|
||||
<property name="toolTip">
|
||||
<string>Select data folder...</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../companion.qrc">
|
||||
<normaloff>:/themes/monoblue/16/open.png</normaloff>:/themes/monoblue/16/open.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QWidget" name="wdgt_sdPath" native="true">
|
||||
<layout class="QHBoxLayout" name="layout_sdPath" stretch="1,0">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="sdPath">
|
||||
<property name="toolTip">
|
||||
<string>Directory containing the SD card image to use.<br/>
|
||||
The default is configured in the chosen Radio Profile.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSelectSdPath">
|
||||
<property name="toolTip">
|
||||
<string>Select SD card image folder...</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../companion.qrc">
|
||||
<normaloff>:/themes/monoblue/16/open.png</normaloff>:/themes/monoblue/16/open.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QWidget" name="wdgt_dataSource" native="true">
|
||||
<property name="toolTip">
|
||||
<string>Select which of the data sources (File/Folder/SD Card) you would like to start the simulator with.</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="layout_dataSource">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="optFile">
|
||||
<property name="text">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optGrp_dataSource</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="optFolder">
|
||||
<property name="text">
|
||||
<string>Folder</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optGrp_dataSource</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="optSdPath">
|
||||
<property name="text">
|
||||
<string>SD Path</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optGrp_dataSource</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>groupBox</zorder>
|
||||
<zorder>buttonBox</zorder>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../companion.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SimulatorStartupDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SimulatorStartupDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="optGrp_dataSource"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
@@ -30,12 +30,12 @@ class RadioFaderWidget : public RadioWidget
|
||||
|
||||
public:
|
||||
|
||||
explicit RadioFaderWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
explicit RadioFaderWidget(QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(parent, f)
|
||||
{
|
||||
init();
|
||||
}
|
||||
explicit RadioFaderWidget(const QString &labelText, int value = 0, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
explicit RadioFaderWidget(const QString & labelText, int value = 0, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(labelText, value, parent, f)
|
||||
{
|
||||
init();
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define _RADIOKNOBWIDGET_H_
|
||||
|
||||
#include "radiowidget.h"
|
||||
#include "radiodata.h"
|
||||
#include "boards.h"
|
||||
|
||||
#include <QDial>
|
||||
#include <QMouseEvent>
|
||||
@@ -68,7 +68,7 @@ class RadioKnobWidget : public RadioWidget
|
||||
|
||||
class KnobWidget : public QDial
|
||||
{
|
||||
friend class RadioKnobWidget;
|
||||
friend class RadioKnobWidget;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define _RADIOSWITCHWIDGET_H_
|
||||
|
||||
#include "radiowidget.h"
|
||||
#include "radiodata.h"
|
||||
#include "boards.h"
|
||||
|
||||
#include <QSlider>
|
||||
#include <QDebug>
|
||||
@@ -33,15 +33,15 @@ class RadioSwitchWidget : public RadioWidget
|
||||
|
||||
public:
|
||||
|
||||
explicit RadioSwitchWidget(Board::SwitchType type = Board::SWITCH_3POS, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
explicit RadioSwitchWidget(Board::SwitchType type = Board::SWITCH_3POS, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(parent, f),
|
||||
switchConfig(type)
|
||||
swType(type)
|
||||
{
|
||||
init();
|
||||
}
|
||||
explicit RadioSwitchWidget(Board::SwitchType type, const QString &labelText, int value = 0, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
explicit RadioSwitchWidget(Board::SwitchType type, const QString & labelText, int value = 0, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(labelText, value, parent, f),
|
||||
switchConfig(type)
|
||||
swType(type)
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class RadioSwitchWidget : public RadioWidget
|
||||
sl->setInvertedControls(true);
|
||||
sl->setTickPosition(QSlider::TicksBothSides);
|
||||
sl->setPageStep(1);
|
||||
sl->setMinimum((switchConfig == Board::SWITCH_3POS ? -1 : 0));
|
||||
sl->setMinimum((swType == Board::SWITCH_3POS ? -1 : 0));
|
||||
sl->setMaximum(1);
|
||||
sl->setTickInterval(1);
|
||||
sl->setValue(m_value);
|
||||
@@ -70,7 +70,7 @@ class RadioSwitchWidget : public RadioWidget
|
||||
}
|
||||
|
||||
private:
|
||||
Board::SwitchType switchConfig;
|
||||
Board::SwitchType swType;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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 "radiowidget.h"
|
||||
|
||||
RadioWidget::RadioWidget(QWidget * parent, Qt::WindowFlags f) :
|
||||
QWidget(parent, f),
|
||||
m_value(0),
|
||||
m_flags(0),
|
||||
m_invertValue(false),
|
||||
m_showLabel(false),
|
||||
m_labelText(""),
|
||||
m_type(RADIO_WIDGET_NONE)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void RadioWidget::setIndex(int index)
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
void RadioWidget::setInvertValue(bool invertValue)
|
||||
{
|
||||
m_invertValue = invertValue;
|
||||
}
|
||||
|
||||
void RadioWidget::setValue(int value)
|
||||
{
|
||||
if (value != m_value) {
|
||||
m_value = value;
|
||||
emit valueChanged(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioWidget::setFlags(quint16 flags)
|
||||
{
|
||||
if (flags != m_flags) {
|
||||
m_flags = flags;
|
||||
emit flagsChanged(flags);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioWidget::setShowLabel(bool show)
|
||||
{
|
||||
if (show != m_showLabel) {
|
||||
m_showLabel = show;
|
||||
addLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void RadioWidget::setLabelText(const QString & labelText, bool showLabel)
|
||||
{
|
||||
m_labelText = labelText;
|
||||
m_showLabel = showLabel;
|
||||
addLabel();
|
||||
}
|
||||
|
||||
void RadioWidget::setStateData(const QByteArray & data)
|
||||
{
|
||||
RadioWidgetState state;
|
||||
QDataStream stream(data);
|
||||
stream >> state;
|
||||
|
||||
//setIndex(state.index);
|
||||
setValue(state.value);
|
||||
setFlags(state.flags);
|
||||
}
|
||||
|
||||
void RadioWidget::changeVisibility(bool visible)
|
||||
{
|
||||
static QSizePolicy oldSP = sizePolicy();
|
||||
setVisible(visible);
|
||||
if (visible) {
|
||||
setSizePolicy(oldSP);
|
||||
}
|
||||
else {
|
||||
oldSP = sizePolicy();
|
||||
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
}
|
||||
}
|
||||
|
||||
int RadioWidget::getValue() const
|
||||
{
|
||||
return m_value * (m_invertValue ? -1 : 1);
|
||||
}
|
||||
|
||||
int RadioWidget::getIndex() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
int RadioWidget::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
QByteArray RadioWidget::getStateData() const
|
||||
{
|
||||
QByteArray ba;
|
||||
QDataStream stream(&ba, QIODevice::WriteOnly);
|
||||
stream << getState();
|
||||
return ba;
|
||||
}
|
||||
|
||||
RadioWidget::RadioWidgetState RadioWidget::getState() const
|
||||
{
|
||||
return RadioWidgetState(quint8(m_type), qint8(m_index), qint16(m_value));;
|
||||
}
|
||||
|
||||
void RadioWidget::init()
|
||||
{
|
||||
setIndex(0);
|
||||
m_controlWidget = NULL;
|
||||
m_nameLabel = NULL;
|
||||
|
||||
m_gridLayout= new QGridLayout(this);
|
||||
m_gridLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_gridLayout->setVerticalSpacing(4);
|
||||
m_gridLayout->setHorizontalSpacing(0);
|
||||
|
||||
addLabel();
|
||||
}
|
||||
|
||||
void RadioWidget::addLabel()
|
||||
{
|
||||
if (m_nameLabel) {
|
||||
m_gridLayout->removeWidget(m_nameLabel);
|
||||
m_nameLabel->deleteLater();
|
||||
}
|
||||
if (m_showLabel && !m_labelText.isEmpty()) {
|
||||
m_nameLabel = new QLabel(m_labelText, this);
|
||||
m_nameLabel->setAlignment(Qt::AlignCenter);
|
||||
m_nameLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
m_gridLayout->addWidget(m_nameLabel, 1, 0, 1, 1, Qt::AlignTop);
|
||||
m_gridLayout->setRowStretch(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioWidget::setWidget(QWidget * widget)
|
||||
{
|
||||
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->setRowStretch(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
QDataStream & operator << (QDataStream &out, const RadioWidget::RadioWidgetState & o)
|
||||
{
|
||||
out << o._version << o.type << o.index << o.value << o.flags;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream & operator >> (QDataStream &in, RadioWidget::RadioWidgetState & o)
|
||||
{
|
||||
if (o._version <= RADIO_WIDGET_STATE_VERSION)
|
||||
in >> o._version >> o.type >> o.index >> o.value >> o.flags;
|
||||
return in;
|
||||
}
|
||||
|
||||
QDebug operator << (QDebug d, const RadioWidget::RadioWidgetState & o)
|
||||
{
|
||||
QDebugStateSaver saver(d);
|
||||
d << "RadioWidget::RadioWidgetState: type=" << o.type << "; index=" << o.index
|
||||
<< "; value=" << o.value << "; flags=0x" << hex << o.flags;
|
||||
return d;
|
||||
}
|
||||
@@ -21,146 +21,93 @@
|
||||
#ifndef _RADIOWIDGET_H_
|
||||
#define _RADIOWIDGET_H_
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <QGridLayout>
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
|
||||
#define RADIO_WIDGET_STATE_VERSION 1
|
||||
|
||||
class RadioWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum RadioWidgetType { RADIO_WIDGET_NONE, RADIO_WIDGET_SWITCH, RADIO_WIDGET_KNOB, RADIO_WIDGET_FADER };
|
||||
|
||||
explicit RadioWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
QWidget(parent, f),
|
||||
m_value(0),
|
||||
m_invertValue(false),
|
||||
m_showLabel(false),
|
||||
m_labelText(""),
|
||||
m_type(RADIO_WIDGET_NONE)
|
||||
{
|
||||
init();
|
||||
}
|
||||
explicit RadioWidget(const QString &labelText, int value = 0, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
QWidget(parent, f),
|
||||
m_value(value),
|
||||
m_invertValue(false),
|
||||
m_showLabel(true),
|
||||
m_labelText(labelText),
|
||||
m_type(RADIO_WIDGET_NONE)
|
||||
{
|
||||
init();
|
||||
}
|
||||
// These are saved to persistent user settings in RadioWidgetState,
|
||||
// so only append entires here, do not change index value if it can be avoided.
|
||||
enum RadioWidgetType {
|
||||
RADIO_WIDGET_NONE = 0,
|
||||
RADIO_WIDGET_SWITCH,
|
||||
RADIO_WIDGET_KNOB,
|
||||
RADIO_WIDGET_FADER,
|
||||
RADIO_WIDGET_STICK // actually one axis of a stick
|
||||
};
|
||||
|
||||
void setIndex(int index) { m_index = index; }
|
||||
void setInvertValue(bool invertValue) { m_invertValue = invertValue; }
|
||||
struct RadioWidgetState {
|
||||
public:
|
||||
RadioWidgetState(quint8 type = 0, qint8 index = 0, qint16 value = 0, quint16 flags = 0) :
|
||||
type(type), index(index), value(value), flags(flags),
|
||||
_version(RADIO_WIDGET_STATE_VERSION)
|
||||
{ }
|
||||
|
||||
void setValue(int value)
|
||||
{
|
||||
if (value != m_value) {
|
||||
m_value = value;
|
||||
emit valueChanged(m_value);
|
||||
}
|
||||
}
|
||||
quint8 type;
|
||||
qint8 index;
|
||||
qint16 value;
|
||||
quint16 flags;
|
||||
|
||||
void setShowLabel(bool show)
|
||||
{
|
||||
if (show != m_showLabel) {
|
||||
m_showLabel = show;
|
||||
addLabel();
|
||||
}
|
||||
}
|
||||
friend QDataStream & operator << (QDataStream &out, const RadioWidgetState & o);
|
||||
friend QDataStream & operator >> (QDataStream &in, RadioWidgetState & o);
|
||||
friend QDebug operator << (QDebug d, const RadioWidgetState & o);
|
||||
|
||||
void setLabelText(const QString &labelText, bool showLabel = true)
|
||||
{
|
||||
m_labelText = labelText;
|
||||
m_showLabel = showLabel;
|
||||
addLabel();
|
||||
}
|
||||
private:
|
||||
quint8 _version = RADIO_WIDGET_STATE_VERSION; // structure definition version
|
||||
};
|
||||
|
||||
void changeVisibility(bool visible)
|
||||
{
|
||||
static QSizePolicy oldSP = sizePolicy();
|
||||
setVisible(visible);
|
||||
if (visible) {
|
||||
setSizePolicy(oldSP);
|
||||
}
|
||||
else {
|
||||
oldSP = sizePolicy();
|
||||
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
}
|
||||
}
|
||||
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());
|
||||
|
||||
int getValue() const { return m_value * (m_invertValue ? -1 : 1); }
|
||||
int getIndex() const { return m_index; }
|
||||
int getType() const { return m_type; }
|
||||
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);
|
||||
|
||||
|
||||
int getValue() const;
|
||||
int getIndex() const;
|
||||
int getType() const;
|
||||
QByteArray getStateData() const;
|
||||
RadioWidgetState getState() const;
|
||||
|
||||
protected:
|
||||
void init()
|
||||
{
|
||||
setIndex(0);
|
||||
m_controlWidget = NULL;
|
||||
m_nameLabel = NULL;
|
||||
|
||||
m_gridLayout= new QGridLayout(this);
|
||||
m_gridLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_gridLayout->setVerticalSpacing(4);
|
||||
m_gridLayout->setHorizontalSpacing(0);
|
||||
|
||||
addLabel();
|
||||
}
|
||||
|
||||
void addLabel()
|
||||
{
|
||||
if (m_nameLabel) {
|
||||
m_gridLayout->removeWidget(m_nameLabel);
|
||||
m_nameLabel->deleteLater();
|
||||
}
|
||||
if (m_showLabel && !m_labelText.isEmpty()) {
|
||||
m_nameLabel = new QLabel(m_labelText, this);
|
||||
m_nameLabel->setAlignment(Qt::AlignCenter);
|
||||
m_nameLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
m_gridLayout->addWidget(m_nameLabel, 1, 0, 1, 1, Qt::AlignTop);
|
||||
m_gridLayout->setRowStretch(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void setWidget(QWidget * widget = NULL)
|
||||
{
|
||||
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->setRowStretch(0, 1);
|
||||
}
|
||||
}
|
||||
void init();
|
||||
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:
|
||||
|
||||
QGridLayout * m_gridLayout;
|
||||
QWidget * m_controlWidget;
|
||||
QLabel * m_nameLabel;
|
||||
|
||||
signals:
|
||||
|
||||
void valueChanged(int m_value);
|
||||
void flagsChanged(quint16 flags);
|
||||
|
||||
};
|
||||
|
||||
#endif // _RADIOWIDGET_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+69
-284
@@ -26,9 +26,6 @@
|
||||
#include <QDebug>
|
||||
#include <QTextStream>
|
||||
#include <QDialog>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QToolButton>
|
||||
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
||||
#include <SDL.h>
|
||||
#undef main
|
||||
@@ -37,7 +34,9 @@
|
||||
#include "appdata.h"
|
||||
#include "constants.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "simulator.h"
|
||||
#include "simulatordialog.h"
|
||||
#include "simulatorstartupdialog.h"
|
||||
#include "storage.h"
|
||||
#include "qxtcommandoptions.h"
|
||||
|
||||
@@ -66,17 +65,7 @@ class MyProxyStyle : public QProxyStyle
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int profileId;
|
||||
QString firmwareId;
|
||||
QString eepromFileName;
|
||||
QString dataFolder;
|
||||
bool useFolder;
|
||||
} simulatorOptions_t;
|
||||
|
||||
|
||||
QDir g_eepromDirectory;
|
||||
using namespace Simulator;
|
||||
|
||||
int finish(int exitCode);
|
||||
|
||||
@@ -88,202 +77,6 @@ void showMessage(const QString & message, enum QMessageBox::Icon icon = QMessage
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
bool usesCategorizedStorage(const QString &name)
|
||||
{
|
||||
return name.contains("horus", Qt::CaseInsensitive);
|
||||
}
|
||||
QString radioEepromFileName(QString firmwareId)
|
||||
{
|
||||
QString eepromFileName = "", ext = "bin";
|
||||
QString radioId = firmwareId;
|
||||
int pos = firmwareId.indexOf("-");
|
||||
if (pos > 0) {
|
||||
radioId = firmwareId.mid(pos+1);
|
||||
pos = radioId.lastIndexOf("-");
|
||||
if (pos > 0) {
|
||||
radioId = radioId.mid(0, pos);
|
||||
}
|
||||
}
|
||||
if (usesCategorizedStorage(radioId))
|
||||
ext = "otx";
|
||||
|
||||
eepromFileName = QString("eeprom-%1.%2").arg(radioId, ext);
|
||||
eepromFileName = g_eepromDirectory.filePath(eepromFileName.toLatin1());
|
||||
// qDebug() << "radioId" << radioId << "eepromFileName" << eepromFileName;
|
||||
|
||||
return eepromFileName;
|
||||
}
|
||||
|
||||
bool startupOptionsDialog(simulatorOptions_t &opts)
|
||||
{
|
||||
bool ret = false;
|
||||
QString label;
|
||||
|
||||
QDialog * dialog = new QDialog();
|
||||
dialog->setWindowFlags(dialog->windowFlags() & (~ Qt::WindowContextHelpButtonHint));
|
||||
|
||||
QFormLayout * form = new QFormLayout(dialog);
|
||||
form->addRow(new QLabel(QObject::tr("Simulator Startup Options:")));
|
||||
|
||||
label = QObject::tr("Profile:");
|
||||
QComboBox * cbProf = new QComboBox();
|
||||
cbProf->setToolTip(QObject::tr("Existing radio profiles are shown here.<br/>" \
|
||||
"Create or edit profiles using the Companion application."));
|
||||
QMapIterator<int, QString> pi(g.getActiveProfiles());
|
||||
while (pi.hasNext()) {
|
||||
pi.next();
|
||||
cbProf->addItem(pi.value(), pi.key());
|
||||
if (pi.key() == opts.profileId)
|
||||
cbProf->setCurrentIndex(cbProf->count() - 1);
|
||||
}
|
||||
form->addRow(label, cbProf);
|
||||
|
||||
label = QObject::tr("Radio Type:");
|
||||
QComboBox * cbType = new QComboBox();
|
||||
cbType->setToolTip(QObject::tr("Existing radio simulators are shown here.<br/>" \
|
||||
"The radio type specified in the selected profile is used by default."));
|
||||
cbType->addItems(registered_simulators.keys());
|
||||
cbType->setCurrentIndex(cbType->findText(opts.firmwareId));
|
||||
if (cbType->currentIndex() == -1 && cbProf->currentIndex() > -1){
|
||||
SimulatorFactory * sf = getSimulatorFactory(g.profile[cbProf->currentIndex()].fwType());
|
||||
if (sf)
|
||||
cbType->setCurrentIndex(cbType->findText(sf->name()));
|
||||
}
|
||||
form->addRow(label, cbType);
|
||||
|
||||
label = QObject::tr("Data File:");
|
||||
QLineEdit * fwFile = new QLineEdit(opts.eepromFileName, dialog);
|
||||
fwFile->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
fwFile->setToolTip(QObject::tr("Radio data (.bin/.eeprom/.otx) image file to use. A new file with a default image will be created if necessary.<br />" \
|
||||
"<b>NOTE</b>: any existing EEPROM data incompatible with the selected radio type may be overwritten!"));
|
||||
QToolButton * fwBtn = new QToolButton(dialog);
|
||||
fwBtn->setText("...");
|
||||
fwBtn->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||
fwBtn->setToolTip(QObject::tr("Select radio data..."));
|
||||
QWidget * fw = new QWidget(dialog);
|
||||
QHBoxLayout * hl = new QHBoxLayout(fw);
|
||||
hl->setContentsMargins(0, 0, 0, 0);
|
||||
hl->setSpacing(2);
|
||||
hl->addWidget(fwFile, 2);
|
||||
hl->addWidget(fwBtn, 0);
|
||||
form->addRow(label, fw);
|
||||
|
||||
label = QObject::tr("Data Folder:");
|
||||
QLineEdit * fwFolder = new QLineEdit(opts.dataFolder, dialog);
|
||||
fwFolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
fwFolder->setToolTip(QObject::tr("Directory containing RADIO and MODELS folders to use." \
|
||||
"<br>New folder(s) with default radio/model will be created here if necessary."));
|
||||
QToolButton * fwFolderBtn = new QToolButton(dialog);
|
||||
fwFolderBtn->setText("...");
|
||||
fwFolderBtn->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||
fwFolderBtn->setToolTip(QObject::tr("Select data folder..."));
|
||||
QWidget * fwf = new QWidget(dialog);
|
||||
QHBoxLayout * hlf = new QHBoxLayout(fwf);
|
||||
hlf->setContentsMargins(0, 0, 0, 0);
|
||||
hlf->setSpacing(2);
|
||||
hlf->addWidget(fwFolder, 2);
|
||||
hlf->addWidget(fwFolderBtn, 0);
|
||||
form->addRow(label, fwf);
|
||||
|
||||
label = QObject::tr("Date Source:");
|
||||
QRadioButton * dsfileBtn = new QRadioButton(QObject::tr("File"), dialog);
|
||||
QRadioButton * dsdirBtn = new QRadioButton(QObject::tr("Folder"), dialog);
|
||||
dsfileBtn->setChecked(true);
|
||||
QButtonGroup * btngrp = new QButtonGroup(dialog);
|
||||
btngrp->setExclusive(true);
|
||||
btngrp->addButton(dsfileBtn);
|
||||
btngrp->addButton(dsdirBtn);
|
||||
QWidget * btnwdgt = new QWidget(dialog);
|
||||
QHBoxLayout * btnlo = new QHBoxLayout(btnwdgt);
|
||||
btnlo->setContentsMargins(0, 0, 0, 0);
|
||||
btnlo->setSpacing(9);
|
||||
btnlo->addWidget(dsfileBtn);
|
||||
btnlo->addWidget(dsdirBtn);
|
||||
btnlo->addStretch(1);
|
||||
form->addRow(label, btnwdgt);
|
||||
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, dialog);
|
||||
form->addRow(&buttonBox);
|
||||
|
||||
dialog->resize(400, dialog->sizeHint().height());
|
||||
|
||||
QObject::connect(&buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
|
||||
QObject::connect(&buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
|
||||
|
||||
auto changeContainerType = [cbType, btnwdgt, dsfileBtn, dsdirBtn, fw, fwf, form] (void)
|
||||
{
|
||||
bool show = usesCategorizedStorage(cbType->currentText());
|
||||
//btnwdgt->setVisible(show);
|
||||
//form->labelForField(btnwdgt)->setVisible(show);
|
||||
fwf->setVisible(show);
|
||||
form->labelForField(fwf)->setVisible(show);
|
||||
// TODO : remove below once .otx support works and un-comment 2 lines above
|
||||
fw->setVisible(!show);
|
||||
form->labelForField(fw)->setVisible(!show);
|
||||
dsdirBtn->setChecked(show);
|
||||
dsfileBtn->setChecked(!show);
|
||||
btnwdgt->setVisible(false);
|
||||
form->labelForField(btnwdgt)->setVisible(false);
|
||||
};
|
||||
|
||||
changeContainerType();
|
||||
|
||||
// set new default radio type when profile choice changes
|
||||
QObject::connect(cbProf, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [cbProf, cbType] (int index) {
|
||||
if (index < 0)
|
||||
return;
|
||||
SimulatorFactory * sf = getSimulatorFactory(g.profile[index].fwType());
|
||||
if (sf) {
|
||||
int i = cbType->findText(sf->name());
|
||||
if (i > -1) {
|
||||
cbType->setCurrentIndex(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// set new default firmware file when radio type changes
|
||||
QObject::connect(cbType, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [cbType, fwFile, changeContainerType] (int index) {
|
||||
if (index < 0)
|
||||
return;
|
||||
fwFile->setText(radioEepromFileName(cbType->currentText()));
|
||||
changeContainerType();
|
||||
});
|
||||
|
||||
// connect button to file selector dialog
|
||||
QObject::connect(fwBtn, &QToolButton::clicked, [dialog, fwFile, cbType, opts, dsfileBtn] (bool) {
|
||||
QString filter = QObject::tr((usesCategorizedStorage(cbType->currentText()) ? OTX_FILES_FILTER : EEPROM_FILES_FILTER));
|
||||
filter += QObject::tr("All files (*.*)");
|
||||
QString file = QFileDialog::getSaveFileName(dialog, QObject::tr("Select EEPROM image"), fwFile->text(),
|
||||
filter, NULL, QFileDialog::DontConfirmOverwrite);
|
||||
if (!file.isEmpty()) {
|
||||
fwFile->setText(file);
|
||||
dsfileBtn->setChecked(true);
|
||||
}
|
||||
});
|
||||
|
||||
// connect button to folder selector dialog
|
||||
QObject::connect(fwFolderBtn, &QToolButton::clicked, [dialog, fwFolder, cbType, opts, dsdirBtn](bool) {
|
||||
QString folder = QFileDialog::getExistingDirectory(dialog, QObject::tr("Select Data Directory"), fwFolder->text(), QFileDialog::DontUseNativeDialog);
|
||||
if (!folder.isEmpty()) {
|
||||
fwFolder->setText(folder);
|
||||
dsdirBtn->setChecked(true);
|
||||
}
|
||||
});
|
||||
|
||||
// go
|
||||
if (dialog->exec() == QDialog::Accepted) {
|
||||
opts.profileId = cbProf->currentData().toInt();
|
||||
opts.firmwareId = cbType->currentText();
|
||||
opts.eepromFileName = fwFile->text();
|
||||
opts.dataFolder = fwFolder->text();
|
||||
opts.useFolder = dsdirBtn->isChecked();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
dialog->deleteLater();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sharedHelpText(QTextStream &stream)
|
||||
{
|
||||
// list all available profiles
|
||||
@@ -300,24 +93,36 @@ void sharedHelpText(QTextStream &stream)
|
||||
}
|
||||
}
|
||||
|
||||
QString findFirmwareId(int profileId)
|
||||
{
|
||||
SimulatorFactory * sf = getSimulatorFactory(g.profile[profileId].fwType());
|
||||
if (sf)
|
||||
return sf->name();
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(companion);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
#endif
|
||||
#if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO)
|
||||
AllocConsole();
|
||||
SetConsoleTitle("Simulator Console");
|
||||
freopen("conin$", "r", stdin);
|
||||
freopen("conout$", "w", stdout);
|
||||
freopen("conout$", "w", stderr);
|
||||
if (!GetConsoleWindow()) {
|
||||
AllocConsole();
|
||||
freopen("conin$", "r", stdin);
|
||||
freopen("conout$", "w", stdout);
|
||||
freopen("conout$", "w", stderr);
|
||||
}
|
||||
SetConsoleTitle(APP_SIMULATOR " Console");
|
||||
#endif
|
||||
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationName("OpenTX Simulator");
|
||||
app.setOrganizationName("OpenTX");
|
||||
app.setOrganizationDomain("open-tx.org");
|
||||
app.setApplicationName(APP_SIMULATOR);
|
||||
app.setOrganizationName(COMPANY);
|
||||
app.setOrganizationDomain(COMPANY_DOMAIN);
|
||||
|
||||
g.init();
|
||||
|
||||
@@ -348,20 +153,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
simulatorOptions_t simOptions;
|
||||
QxtCommandOptions cliOptions;
|
||||
bool cliOptsFound = false;
|
||||
int profileId = (g.simuLastProfId() > -1 ? g.simuLastProfId() : g.id());
|
||||
SimulatorOptions simOptions = g.profile[profileId].simulatorOptions();
|
||||
|
||||
g_eepromDirectory = QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
||||
if (!g_eepromDirectory.exists("OpenTX")) {
|
||||
if (!g_eepromDirectory.mkpath("OpenTX")) {
|
||||
showMessage(QObject::tr("WARNING: couldn't create directory for EEPROM:\n%1").arg(g_eepromDirectory.absoluteFilePath("OpenTX")), QMessageBox::Warning);
|
||||
}
|
||||
}
|
||||
g_eepromDirectory.cd("OpenTX");
|
||||
|
||||
registerSimulators();
|
||||
registerStorageFactories();
|
||||
registerOpenTxFirmwares();
|
||||
registerSimulators();
|
||||
|
||||
if (!registered_simulators.size()) {
|
||||
showMessage(QObject::tr("ERROR: No simulator libraries available."), QMessageBox::Critical);
|
||||
@@ -387,75 +186,71 @@ int main(int argc, char *argv[])
|
||||
return finish(1);
|
||||
}
|
||||
|
||||
if (cliOptions.count("radio") == 1) {
|
||||
simOptions.firmwareId = cliOptions.value("radio").toString();
|
||||
cliOptsFound = true;
|
||||
}
|
||||
else {
|
||||
simOptions.firmwareId = g.lastSimulator();
|
||||
}
|
||||
// TODO : defaults should be set in Profile::init()
|
||||
if (simOptions.firmwareId.isEmpty())
|
||||
simOptions.firmwareId = findFirmwareId(profileId);
|
||||
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) {
|
||||
simOptions.profileId = pid;
|
||||
}
|
||||
else {
|
||||
simOptions.profileId = g.getActiveProfiles().key(cliOptions.value("profile").toString(), -1);
|
||||
}
|
||||
// load default radio for this profile if not already passed on command line
|
||||
if (!cliOptsFound) {
|
||||
SimulatorFactory * sf = getSimulatorFactory(g.profile[simOptions.profileId].fwType());
|
||||
if (sf)
|
||||
simOptions.firmwareId = sf->name();
|
||||
if (chk)
|
||||
profileId = pid;
|
||||
else
|
||||
profileId = g.getActiveProfiles().key(cliOptions.value("profile").toString(), -1);
|
||||
|
||||
if (!g.getActiveProfiles().contains(profileId)) {
|
||||
fprintf(stderr, "Error: Profile ID %d was not found.", profileId);
|
||||
return finish(1);
|
||||
}
|
||||
|
||||
simOptions = g.profile[profileId].simulatorOptions();
|
||||
cliOptsFound = true;
|
||||
}
|
||||
else if (g.simuLastProfId() != -1) {
|
||||
simOptions.profileId = g.simuLastProfId();
|
||||
}
|
||||
else {
|
||||
simOptions.profileId = g.id();
|
||||
|
||||
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.eepromFileName = cliOptions.positional()[0];
|
||||
simOptions.dataFile = cliOptions.positional()[0];
|
||||
simOptions.startupDataType = SimulatorOptions::START_WITH_FILE;
|
||||
}
|
||||
else {
|
||||
simOptions.dataFolder = cliOptions.positional()[0];
|
||||
simOptions.useFolder = true;
|
||||
simOptions.startupDataType = SimulatorOptions::START_WITH_FOLDER;
|
||||
}
|
||||
cliOptsFound = true;
|
||||
}
|
||||
else if (cliOptsFound || g.simuLastEepe().isEmpty()) {
|
||||
simOptions.eepromFileName = radioEepromFileName(simOptions.firmwareId);
|
||||
simOptions.dataFolder = g_eepromDirectory.absolutePath();
|
||||
}
|
||||
else {
|
||||
simOptions.eepromFileName = g.simuLastEepe();
|
||||
simOptions.dataFolder = g.simuLastFolder();
|
||||
}
|
||||
|
||||
if (!cliOptsFound || simOptions.profileId == -1 || simOptions.firmwareId.isEmpty() || (simOptions.eepromFileName.isEmpty() && simOptions.dataFolder.isEmpty())) {
|
||||
if (!startupOptionsDialog(simOptions)) {
|
||||
if (!cliOptsFound || profileId == -1 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
|
||||
SimulatorStartupDialog * dlg = new SimulatorStartupDialog(&simOptions, &profileId);
|
||||
int ret = dlg->exec();
|
||||
dlg->deleteLater();
|
||||
if (ret != QDialog::Accepted) {
|
||||
return finish(0);
|
||||
}
|
||||
}
|
||||
qDebug() << "firmwareId" << simOptions.firmwareId << "profileId" << simOptions.profileId << "eepromFileName" \
|
||||
<< simOptions.eepromFileName << "dataFolder" << simOptions.dataFolder << "useFolder" << simOptions.useFolder;
|
||||
qDebug() << __FILE__ << __LINE__ << "profileId=" << profileId << simOptions;
|
||||
|
||||
if (simOptions.profileId < 0 || simOptions.firmwareId.isEmpty() || (simOptions.eepromFileName.isEmpty() && simOptions.dataFolder.isEmpty())) {
|
||||
showMessage(QObject::tr("ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\nProfile ID: [%1]; Radio ID: [%2];\nData File: [%3]")
|
||||
.arg(simOptions.profileId).arg(simOptions.firmwareId).arg(simOptions.eepromFileName), QMessageBox::Critical);
|
||||
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);
|
||||
return finish(1);
|
||||
}
|
||||
if (!g.getActiveProfiles().contains(simOptions.profileId) || !registered_simulators.keys().contains(simOptions.firmwareId)) {
|
||||
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(simOptions.profileId).arg(simOptions.firmwareId);
|
||||
.arg(profileId).arg(simOptions.firmwareId);
|
||||
sharedHelpText(stream);
|
||||
showMessage(msg, QMessageBox::Critical);
|
||||
return finish(2);
|
||||
@@ -468,24 +263,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
current_firmware_variant = getFirmware(simOptions.firmwareId);
|
||||
registerStorageFactories();
|
||||
|
||||
int oldProfId = g.id();
|
||||
g.id(simOptions.profileId);
|
||||
g.simuLastProfId(simOptions.profileId);
|
||||
g.lastSimulator(simOptions.firmwareId);
|
||||
g.simuLastEepe(simOptions.eepromFileName);
|
||||
g.simuLastFolder(simOptions.dataFolder);
|
||||
g.id(profileId);
|
||||
g.simuLastProfId(profileId);
|
||||
|
||||
SimulatorDialog * dialog = new SimulatorDialog(NULL, factory->create(), SIMULATOR_FLAGS_STANDALONE);
|
||||
dialog->setRadioProfileId(simOptions.profileId);
|
||||
if (simOptions.useFolder && !simOptions.dataFolder.isEmpty()) {
|
||||
dialog->setDataPath(simOptions.dataFolder);
|
||||
dialog->setEepromData();
|
||||
}
|
||||
else {
|
||||
dialog->setEepromData(simOptions.eepromFileName.toLocal8Bit(), true);
|
||||
}
|
||||
dialog->setRadioProfileId(profileId);
|
||||
dialog->setOptions(simOptions, true);
|
||||
dialog->start();
|
||||
dialog->show();
|
||||
int result = app.exec();
|
||||
|
||||
+146
-244
@@ -24,191 +24,93 @@
|
||||
AppData g;
|
||||
|
||||
// ** CompStoreObj class********************
|
||||
void CompStoreObj::clear (const QString tag1, const QString tag2, const QString tag3)
|
||||
void CompStoreObj::clear (const QString &tag1, const QString &tag2, const QString &tag3)
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (tag2.isEmpty())
|
||||
{
|
||||
settings.remove(tag1);
|
||||
}
|
||||
else if (tag3.isEmpty())
|
||||
{
|
||||
settings.beginGroup(tag1);
|
||||
settings.remove(tag2);
|
||||
settings.endGroup();
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.beginGroup(tag1);
|
||||
settings.beginGroup(tag2);
|
||||
settings.remove(tag3);
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (tag2.isEmpty())
|
||||
{
|
||||
settings.remove(tag1);
|
||||
}
|
||||
else if (tag3.isEmpty())
|
||||
{
|
||||
settings.beginGroup(tag1);
|
||||
settings.remove(tag2);
|
||||
settings.endGroup();
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.beginGroup(tag1);
|
||||
settings.beginGroup(tag2);
|
||||
settings.remove(tag3);
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void CompStoreObj::store(const QByteArray newArray, QByteArray &array, const QString tag, const QString group1, const QString group2 )
|
||||
template <typename OBJ_T, typename TAG_T, typename GP1_T, typename GP2_T>
|
||||
void CompStoreObj::store(const OBJ_T newValue, OBJ_T & destValue, const TAG_T tag, const GP1_T group1, const GP2_T group2)
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
QString g1 = group1; // these may come in as const char * or QString
|
||||
QString g2 = group2;
|
||||
if (!g1.isEmpty()){
|
||||
settings.beginGroup(g1);
|
||||
if (!g2.isEmpty())
|
||||
settings.beginGroup(g2);
|
||||
}
|
||||
|
||||
settings.setValue(tag, newArray);
|
||||
array = newArray;
|
||||
settings.setValue(tag, QVariant::fromValue(newValue));
|
||||
destValue = newValue;
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
if (!g1.isEmpty()){
|
||||
settings.endGroup();
|
||||
if (!g2.isEmpty())
|
||||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void CompStoreObj::store(const QStringList newSList, QStringList &stringList, const QString tag, const QString group1, const QString group2 )
|
||||
template <typename OBJ_T, typename TAG_T, typename DEF_T, typename GP1_T, typename GP2_T>
|
||||
void CompStoreObj::retrieve(OBJ_T & destValue, const TAG_T tag, const DEF_T def, const GP1_T group1, const GP2_T group2)
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
QString g1 = group1; // these may come in as const char * or QString
|
||||
QString g2 = group2;
|
||||
if (!g1.isEmpty()){
|
||||
settings.beginGroup(g1);
|
||||
if (!g2.isEmpty())
|
||||
settings.beginGroup(g2);
|
||||
}
|
||||
|
||||
settings.setValue(tag, newSList);
|
||||
stringList = newSList;
|
||||
QVariant val = settings.value(QString(tag), QVariant::fromValue(def));
|
||||
if (val.canConvert<OBJ_T>())
|
||||
destValue = val.value<OBJ_T>();
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
if (!g1.isEmpty()){;
|
||||
settings.endGroup();
|
||||
if (!g2.isEmpty())
|
||||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void CompStoreObj::store(const QString newString, QString &string, const QString tag, const QString group1, const QString group2 )
|
||||
template <typename OBJ_T, typename TAG_T, typename DEF_T, typename GP1_T, typename GP2_T>
|
||||
void CompStoreObj::getset(OBJ_T & value, const TAG_T tag, const DEF_T def, const GP1_T group1, const GP2_T group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
settings.setValue(tag, newString);
|
||||
string = newString;
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
retrieve(value, tag, def, group1, group2);
|
||||
store(value, value, tag, group1, group2);
|
||||
}
|
||||
|
||||
void CompStoreObj::store(const bool newTruth, bool &truth, const QString tag, const QString group1, const QString group2 )
|
||||
template <typename OBJ_T, typename TAG_T, typename GP1_T, typename GP2_T>
|
||||
void CompStoreObj::getset(OBJ_T & value, const TAG_T tag, const char * def, const GP1_T group1, const GP2_T group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
settings.setValue(tag, newTruth);
|
||||
truth = newTruth;
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
getset(value, tag, QString(def), group1, group2);
|
||||
}
|
||||
|
||||
void CompStoreObj::store(const int newNumber, int &number, const QString tag, const QString group1, const QString group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
settings.setValue(tag, newNumber);
|
||||
number = newNumber;
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
}
|
||||
|
||||
// Retrieval functions
|
||||
void CompStoreObj::retrieve( QByteArray &array, const QString tag, const QString def, const QString group1, const QString group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
array = settings.value(tag, def).toByteArray();
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
}
|
||||
|
||||
void CompStoreObj::retrieve( QStringList &stringList, const QString tag, const QString def, const QString group1, const QString group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
stringList = settings.value(tag, def).toStringList();
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
}
|
||||
|
||||
void CompStoreObj::retrieve( QString &string, const QString tag, const QString def, const QString group1, const QString group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
string = settings.value(tag, def).toString();
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
}
|
||||
|
||||
void CompStoreObj::retrieve( bool &truth, const QString tag, const bool def, const QString group1, const QString group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
truth = settings.value(tag, def).toBool();
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
}
|
||||
|
||||
void CompStoreObj::retrieve( int &number, const QString tag, const int def, const QString group1, const QString group2 )
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
if (!group1.isEmpty()) settings.beginGroup(group1);
|
||||
if (!group2.isEmpty()) settings.beginGroup(group2);
|
||||
|
||||
number = settings.value(tag, def).toInt();
|
||||
|
||||
if (!group1.isEmpty()) settings.endGroup();
|
||||
if (!group2.isEmpty()) settings.endGroup();
|
||||
}
|
||||
|
||||
// Retrieve and Store functions
|
||||
void CompStoreObj::getset( QByteArray &array, const QString tag, const QString def, const QString group1, const QString group2 )
|
||||
{
|
||||
retrieve( array, tag, def, group1, group2);
|
||||
store(array, array, tag, group1, group2);
|
||||
}
|
||||
|
||||
void CompStoreObj::getset( QStringList &stringList, const QString tag, const QString def, const QString group1, const QString group2 )
|
||||
{
|
||||
retrieve( stringList, tag, def, group1, group2);
|
||||
store(stringList, stringList, tag, group1, group2);
|
||||
}
|
||||
|
||||
void CompStoreObj::getset( QString &string, const QString tag, const QString def, const QString group1, const QString group2 )
|
||||
{
|
||||
retrieve( string, tag, def, group1, group2);
|
||||
store(string, string, tag, group1, group2);
|
||||
}
|
||||
|
||||
void CompStoreObj::getset( bool &truth, const QString tag, const bool def, const QString group1, const QString group2 )
|
||||
{
|
||||
retrieve( truth, tag, def, group1, group2);
|
||||
store(truth, truth, tag, group1, group2);
|
||||
}
|
||||
|
||||
void CompStoreObj::getset( int &number, const QString tag, const int def, const QString group1, const QString group2 )
|
||||
{
|
||||
retrieve( number, tag, def, group1, group2);
|
||||
store(number, number, tag, group1, group2);
|
||||
}
|
||||
|
||||
// ** FwRevision class********************
|
||||
int FwRevision::get( const QString fwType )
|
||||
{
|
||||
QString result;
|
||||
retrieve( result, fwType, "", "FwRevisions" );
|
||||
retrieve( result, fwType, QString(""), "FwRevisions" );
|
||||
return result.toInt();
|
||||
}
|
||||
|
||||
@@ -310,8 +212,6 @@ bool Profile::renameFwFiles() const { return _renameFwFiles; }
|
||||
int Profile::channelOrder() const { return _channelOrder; }
|
||||
int Profile::defaultMode() const { return _defaultMode; }
|
||||
|
||||
QByteArray Profile::simuWinGeo() const { return _simuWinGeo; }
|
||||
|
||||
QString Profile::beeper() const { return _beeper; }
|
||||
QString Profile::countryCode() const { return _countryCode; }
|
||||
QString Profile::display() const { return _display; }
|
||||
@@ -322,47 +222,48 @@ QString Profile::timeStamp() const { return _timeStamp; }
|
||||
QString Profile::trainerCalib() const { return _trainerCalib; }
|
||||
QString Profile::controlTypes() const { return _controlTypes; }
|
||||
QString Profile::controlNames() const { return _controlNames; }
|
||||
int Profile::txCurrentCalibration() const { return _txCurrentCalibration; }
|
||||
int Profile::gsStickMode() const { return _gsStickMode; }
|
||||
int Profile::ppmMultiplier() const { return _ppmMultiplier; }
|
||||
int Profile::txVoltageCalibration() const { return _txVoltageCalibration; }
|
||||
int Profile::vBatWarn() const { return _vBatWarn; }
|
||||
int Profile::vBatMin() const { return _vBatMin; }
|
||||
int Profile::vBatMax() const { return _vBatMax; }
|
||||
int Profile::txCurrentCalibration() const { return _txCurrentCalibration; }
|
||||
int Profile::txVoltageCalibration() const { return _txVoltageCalibration; }
|
||||
|
||||
SimulatorOptions Profile::simulatorOptions() const { return _simulatorOptions; }
|
||||
|
||||
// Set declarations
|
||||
void Profile::name (const QString x) { store(x, _name, "Name" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::fwName (const QString x) { store(x, _fwName, "fwName" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::fwType (const QString x) { store(x, _fwType, "fwType" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::sdPath (const QString x) { store(x, _sdPath, "sdPath" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::volumeGain (const int x) { store(x, _volumeGain, "volumeGain" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::pBackupDir (const QString x) { store(x, _pBackupDir, "pBackupDir" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::splashFile (const QString x) { store(x, _splashFile, "SplashFileName" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::burnFirmware (const bool x) { store(x, _burnFirmware, "burnFirmware" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::renameFwFiles (const bool x) { store(x, _renameFwFiles, "rename_firmware_files" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::penableBackup (const bool x) { store(x, _penableBackup, "penableBackup" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::channelOrder (const int x) { store(x, _channelOrder, "default_channel_order" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::defaultMode (const int x) { store(x, _defaultMode, "default_mode" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::name (const QString x) { store(x, _name, "Name" ,"Profiles", groupId());}
|
||||
void Profile::fwName (const QString x) { store(x, _fwName, "fwName" ,"Profiles", groupId());}
|
||||
void Profile::fwType (const QString x) { store(x, _fwType, "fwType" ,"Profiles", groupId());}
|
||||
void Profile::sdPath (const QString x) { store(x, _sdPath, "sdPath" ,"Profiles", groupId());}
|
||||
void Profile::volumeGain (const int x) { store(x, _volumeGain, "volumeGain" ,"Profiles", groupId());}
|
||||
void Profile::pBackupDir (const QString x) { store(x, _pBackupDir, "pBackupDir" ,"Profiles", groupId());}
|
||||
void Profile::splashFile (const QString x) { store(x, _splashFile, "SplashFileName" ,"Profiles", groupId());}
|
||||
void Profile::burnFirmware (const bool x) { store(x, _burnFirmware, "burnFirmware" ,"Profiles", groupId());}
|
||||
void Profile::renameFwFiles (const bool x) { store(x, _renameFwFiles, "rename_firmware_files" ,"Profiles", groupId());}
|
||||
void Profile::penableBackup (const bool x) { store(x, _penableBackup, "penableBackup" ,"Profiles", groupId());}
|
||||
void Profile::channelOrder (const int x) { store(x, _channelOrder, "default_channel_order" ,"Profiles", groupId());}
|
||||
void Profile::defaultMode (const int x) { store(x, _defaultMode, "default_mode" ,"Profiles", groupId());}
|
||||
void Profile::beeper (const QString x) { store(x, _beeper, "Beeper" ,"Profiles", groupId());}
|
||||
void Profile::countryCode (const QString x) { store(x, _countryCode, "countryCode" ,"Profiles", groupId());}
|
||||
void Profile::display (const QString x) { store(x, _display, "Display" ,"Profiles", groupId());}
|
||||
void Profile::haptic (const QString x) { store(x, _haptic, "Haptic" ,"Profiles", groupId());}
|
||||
void Profile::speaker (const QString x) { store(x, _speaker, "Speaker" ,"Profiles", groupId());}
|
||||
void Profile::stickPotCalib (const QString x) { store(x, _stickPotCalib, "StickPotCalib" ,"Profiles", groupId());}
|
||||
void Profile::timeStamp (const QString x) { store(x, _timeStamp, "TimeStamp" ,"Profiles", groupId());}
|
||||
void Profile::trainerCalib (const QString x) { store(x, _trainerCalib, "TrainerCalib" ,"Profiles", groupId());}
|
||||
void Profile::controlTypes (const QString x) { store(x, _controlTypes, "ControlTypes" ,"Profiles", groupId());}
|
||||
void Profile::controlNames (const QString x) { store(x, _controlNames, "ControlNames" ,"Profiles", groupId());}
|
||||
void Profile::gsStickMode (const int x) { store(x, _gsStickMode, "GSStickMode" ,"Profiles", groupId());}
|
||||
void Profile::ppmMultiplier (const int x) { store(x, _ppmMultiplier, "PPM_Multiplier" ,"Profiles", groupId());}
|
||||
void Profile::vBatWarn (const int x) { store(x, _vBatWarn, "vBatWarn" ,"Profiles", groupId());}
|
||||
void Profile::vBatMin (const int x) { store(x, _vBatMin, "VbatMin" ,"Profiles", groupId());}
|
||||
void Profile::vBatMax (const int x) { store(x, _vBatMax, "VbatMax" ,"Profiles", groupId());}
|
||||
void Profile::txCurrentCalibration (const int x) { store(x, _txCurrentCalibration, "currentCalib","Profiles", groupId());}
|
||||
void Profile::txVoltageCalibration (const int x) { store(x, _txVoltageCalibration, "VbatCalib" ,"Profiles", groupId());}
|
||||
|
||||
void Profile::simuWinGeo (const QByteArray x) { store(x, _simuWinGeo, "simuWindowGeometry" ,"Profiles", QString("profile%1").arg(index));}
|
||||
|
||||
void Profile::beeper (const QString x) { store(x, _beeper, "Beeper" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::countryCode (const QString x) { store(x, _countryCode, "countryCode" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::display (const QString x) { store(x, _display, "Display" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::haptic (const QString x) { store(x, _haptic, "Haptic" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::speaker (const QString x) { store(x, _speaker, "Speaker" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::stickPotCalib (const QString x) { store(x, _stickPotCalib, "StickPotCalib" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::timeStamp (const QString x) { store(x, _timeStamp, "TimeStamp" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::trainerCalib (const QString x) { store(x, _trainerCalib, "TrainerCalib" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::controlTypes (const QString x) { store(x, _controlTypes, "ControlTypes" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::controlNames (const QString x) { store(x, _controlNames, "ControlNames" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::txCurrentCalibration (const int x) { store(x, _txCurrentCalibration, "currentCalib","Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::gsStickMode (const int x) { store(x, _gsStickMode, "GSStickMode" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::ppmMultiplier (const int x) { store(x, _ppmMultiplier, "PPM_Multiplier" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::txVoltageCalibration (const int x) { store(x, _txVoltageCalibration, "VbatCalib","Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::vBatWarn (const int x) { store(x, _vBatWarn, "vBatWarn" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::vBatMin (const int x) { store(x, _vBatMin, "VbatMin" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::vBatMax (const int x) { store(x, _vBatMax, "VbatMax" ,"Profiles", QString("profile%1").arg(index));}
|
||||
void Profile::simulatorOptions(const SimulatorOptions & x) { store(x, _simulatorOptions, "simulatorOptions" ,"Profiles", groupId()); }
|
||||
|
||||
// Constructor
|
||||
Profile::Profile()
|
||||
@@ -394,13 +295,14 @@ Profile& Profile::operator=(const Profile& rhs)
|
||||
trainerCalib ( rhs.trainerCalib() );
|
||||
controlTypes ( rhs.controlTypes() );
|
||||
controlNames ( rhs.controlNames() );
|
||||
txCurrentCalibration ( rhs.txCurrentCalibration() );
|
||||
gsStickMode ( rhs.gsStickMode() );
|
||||
ppmMultiplier( rhs.ppmMultiplier() );
|
||||
txVoltageCalibration ( rhs.txVoltageCalibration() );
|
||||
vBatWarn ( rhs.vBatWarn() );
|
||||
vBatMin ( rhs.vBatMin() );
|
||||
vBatMax ( rhs.vBatMax() );
|
||||
txCurrentCalibration ( rhs.txCurrentCalibration() );
|
||||
txVoltageCalibration ( rhs.txVoltageCalibration() );
|
||||
simulatorOptions ( rhs.simulatorOptions() );
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -410,7 +312,7 @@ void Profile::remove()
|
||||
// Remove all profile values from settings file
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
settings.beginGroup("Profiles");
|
||||
settings.remove(QString("profile%1").arg(index));
|
||||
settings.remove(groupId());
|
||||
settings.endGroup();
|
||||
|
||||
// Reset all profile variables to initial values
|
||||
@@ -421,7 +323,7 @@ bool Profile::existsOnDisk()
|
||||
{
|
||||
QSettings settings(COMPANY, PRODUCT);
|
||||
settings.beginGroup("Profiles");
|
||||
settings.beginGroup(QString("profile%1").arg(index));
|
||||
settings.beginGroup(groupId());
|
||||
QStringList keyList = settings.allKeys();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
@@ -468,7 +370,7 @@ void Profile::init(int newIndex)
|
||||
_channelOrder = 0;
|
||||
_defaultMode = 1;
|
||||
|
||||
_simuWinGeo = QByteArray();
|
||||
_simulatorOptions = SimulatorOptions();
|
||||
|
||||
initFwVariables();
|
||||
|
||||
@@ -482,38 +384,44 @@ void Profile::init(int newIndex)
|
||||
void Profile::flush()
|
||||
{
|
||||
// Load and store all variables. Use default values if setting values are missing
|
||||
getset( _fwName, "fwName" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _fwType, "fwType" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _name, "Name" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _sdPath, "sdPath" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _volumeGain, "volumeGain" ,10 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _pBackupDir, "pBackupDir" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _splashFile, "SplashFileName" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _burnFirmware, "burnFirmware" ,false ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _penableBackup, "penableBackup" ,false ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _renameFwFiles, "rename_firmware_files" ,false ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _channelOrder, "default_channel_order" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _defaultMode, "default_mode" ,1 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _fwName, "fwName" ,"" ,"Profiles", groupId());
|
||||
getset( _fwType, "fwType" ,"" ,"Profiles", groupId());
|
||||
getset( _name, "Name" ,"" ,"Profiles", groupId());
|
||||
getset( _sdPath, "sdPath" ,"" ,"Profiles", groupId());
|
||||
getset( _volumeGain, "volumeGain" ,10 ,"Profiles", groupId());
|
||||
getset( _pBackupDir, "pBackupDir" ,"" ,"Profiles", groupId());
|
||||
getset( _splashFile, "SplashFileName" ,"" ,"Profiles", groupId());
|
||||
getset( _burnFirmware, "burnFirmware" ,false ,"Profiles", groupId());
|
||||
getset( _penableBackup, "penableBackup" ,false ,"Profiles", groupId());
|
||||
getset( _renameFwFiles, "rename_firmware_files" ,false ,"Profiles", groupId());
|
||||
getset( _channelOrder, "default_channel_order" ,0 ,"Profiles", groupId());
|
||||
getset( _defaultMode, "default_mode" ,1 ,"Profiles", groupId());
|
||||
|
||||
getset( _simuWinGeo, "simuWindowGeometry" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _beeper, "Beeper" ,"" ,"Profiles", groupId());
|
||||
getset( _countryCode, "countryCode" ,"" ,"Profiles", groupId());
|
||||
getset( _display, "Display" ,"" ,"Profiles", groupId());
|
||||
getset( _haptic, "Haptic" ,"" ,"Profiles", groupId());
|
||||
getset( _speaker, "Speaker" ,"" ,"Profiles", groupId());
|
||||
getset( _stickPotCalib, "StickPotCalib" ,"" ,"Profiles", groupId());
|
||||
getset( _timeStamp, "TimeStamp" ,"" ,"Profiles", groupId());
|
||||
getset( _trainerCalib, "TrainerCalib" ,"" ,"Profiles", groupId());
|
||||
getset( _controlTypes, "ControlTypes" ,"" ,"Profiles", groupId());
|
||||
getset( _controlNames, "ControlNames" ,"" ,"Profiles", groupId());
|
||||
getset( _gsStickMode, "GSStickMode" ,0 ,"Profiles", groupId());
|
||||
getset( _ppmMultiplier, "PPM_Multiplier" ,0 ,"Profiles", groupId());
|
||||
getset( _vBatWarn, "vBatWarn" ,0 ,"Profiles", groupId());
|
||||
getset( _vBatMin, "VbatMin" ,0 ,"Profiles", groupId());
|
||||
getset( _vBatMax, "VbatMax" ,0 ,"Profiles", groupId());
|
||||
getset( _txCurrentCalibration, "currentCalib" ,0 ,"Profiles", groupId());
|
||||
getset( _txVoltageCalibration, "VbatCalib" ,0 ,"Profiles", groupId());
|
||||
|
||||
getset( _beeper, "Beeper" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _countryCode, "countryCode" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _display, "Display" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _haptic, "Haptic" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _speaker, "Speaker" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _stickPotCalib, "StickPotCalib" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _timeStamp, "TimeStamp" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _trainerCalib, "TrainerCalib" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _controlTypes, "ControlTypes" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _controlNames, "ControlNames" ,"" ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _txCurrentCalibration, "currentCalib" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _gsStickMode, "GSStickMode" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _ppmMultiplier, "PPM_Multiplier" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _txVoltageCalibration, "VbatCalib" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _vBatWarn, "vBatWarn" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _vBatMin, "VbatMin" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _vBatMax, "VbatMax" ,0 ,"Profiles", QString("profile%1").arg(index));
|
||||
getset( _simulatorOptions, "simulatorOptions", SimulatorOptions(), "Profiles", groupId());
|
||||
|
||||
}
|
||||
|
||||
QString Profile::groupId()
|
||||
{
|
||||
return QString("profile%1").arg(index);
|
||||
}
|
||||
|
||||
|
||||
@@ -536,9 +444,6 @@ QString AppData::mcu() { return _mcu; }
|
||||
QString AppData::programmer() { return _programmer; }
|
||||
QString AppData::sambaLocation() { return _sambaLocation; }
|
||||
QString AppData::sambaPort() { return _sambaPort; }
|
||||
QString AppData::lastSimulator() { return _lastSimulator; }
|
||||
QString AppData::simuLastEepe() { return _simuLastEepe; }
|
||||
QString AppData::simuLastFolder() { return _simuLastFolder; }
|
||||
|
||||
QString AppData::backupDir() { return _backupDir; }
|
||||
QString AppData::gePath() { return _gePath; }
|
||||
@@ -588,9 +493,6 @@ void AppData::mcu (const QString x) { store(x, _mcu,
|
||||
void AppData::programmer (const QString x) { store(x, _programmer, "programmer" );}
|
||||
void AppData::sambaLocation (const QString x) { store(x, _sambaLocation, "samba_location" );}
|
||||
void AppData::sambaPort (const QString x) { store(x, _sambaPort, "samba_port" );}
|
||||
void AppData::lastSimulator (const QString x) { store(x, _lastSimulator, "last_simulator" );}
|
||||
void AppData::simuLastEepe (const QString x) { store(x, _simuLastEepe, "simuLastEepe" );}
|
||||
void AppData::simuLastFolder (const QString x) { store(x, _simuLastFolder, "simuLastFolder" );}
|
||||
|
||||
void AppData::backupDir (const QString x) { store(x, _backupDir, "backupPath" );}
|
||||
void AppData::gePath (const QString x) { store(x, _gePath, "gePath" );}
|
||||
@@ -630,6 +532,8 @@ AppData::AppData()
|
||||
|
||||
void AppData::init()
|
||||
{
|
||||
qRegisterMetaTypeStreamOperators<SimulatorOptions>("SimulatorOptions");
|
||||
|
||||
//Initialize the profiles
|
||||
for (int i=0; i<MAX_PROFILES; i++)
|
||||
profile[i].init( i );
|
||||
@@ -778,9 +682,6 @@ void AppData::init()
|
||||
getset( _programmer, "programmer" ,"usbasp" );
|
||||
getset( _sambaLocation, "samba_location" ,"" );
|
||||
getset( _sambaPort, "samba_port" ,"\\USBserial\\COM23" );
|
||||
getset( _lastSimulator, "last_simulator" ,"" );
|
||||
getset( _simuLastEepe, "simuLastEepe" ,"" );
|
||||
getset( _simuLastFolder, "simuLastFolder" ,"" );
|
||||
|
||||
getset( _backupDir, "backupPath" ,"" );
|
||||
getset( _gePath, "gePath" ,"" );
|
||||
@@ -792,13 +693,13 @@ void AppData::init()
|
||||
getset( _snapshotDir, "snapshotpath" ,"" );
|
||||
getset( _updatesDir, "lastUpdatesDir" ,"" );
|
||||
|
||||
getset( _outputDisplayDetails, "outputDisplayDetails" ,false );
|
||||
getset( _enableBackup, "enableBackup" ,false );
|
||||
getset( _backupOnFlash, "backupOnFlash" ,true );
|
||||
getset( _checkHardwareCompatibility, "checkHardwareCompatibility" ,true );
|
||||
|
||||
getset( _useCompanionNightlyBuilds, "useCompanionNightlyBuilds" ,false );
|
||||
getset( _useFirmwareNightlyBuilds, "useFirmwareNightlyBuilds" ,false );
|
||||
getset( _outputDisplayDetails, "outputDisplayDetails" ,false );
|
||||
getset( _checkHardwareCompatibility, "checkHardwareCompatibility" ,true );
|
||||
getset( _useCompanionNightlyBuilds, "useCompanionNightlyBuilds" ,false );
|
||||
getset( _useFirmwareNightlyBuilds, "useFirmwareNightlyBuilds" ,false );
|
||||
|
||||
getset( _jsSupport, "js_support" ,false );
|
||||
getset( _maximized, "maximized" ,false );
|
||||
@@ -820,6 +721,7 @@ void AppData::init()
|
||||
getset( _theme, "theme" ,1 );
|
||||
getset( _warningId, "warningId" ,0 );
|
||||
getset( _simuLastProfId, "simuLastProfId" ,-1 );
|
||||
|
||||
}
|
||||
|
||||
QMap<int, QString> AppData::getActiveProfiles()
|
||||
|
||||
@@ -30,8 +30,13 @@
|
||||
#include <QString>
|
||||
#include <QSettings>
|
||||
|
||||
#define COMPANY "OpenTX"
|
||||
#define PRODUCT "Companion 2.2"
|
||||
#include "simulator.h"
|
||||
|
||||
#define COMPANY "OpenTX"
|
||||
#define COMPANY_DOMAIN "open-tx.org"
|
||||
#define PRODUCT "Companion 2.2"
|
||||
#define APP_COMPANION "OpenTX Companion"
|
||||
#define APP_SIMULATOR "OpenTX Simulator"
|
||||
|
||||
#define MAX_PROFILES 15
|
||||
#define MAX_JOYSTICKS 8
|
||||
@@ -39,26 +44,24 @@
|
||||
class CompStoreObj
|
||||
{
|
||||
public:
|
||||
void clear (const QString tag1="", const QString tag2="", const QString tag3="");
|
||||
void store(const QByteArray newArray, QByteArray &array, const QString tag, const QString group1="", const QString group2="" );
|
||||
void store(const QStringList newSList, QStringList &stringList, const QString tag, const QString group1="", const QString group2="" );
|
||||
void store(const QString newString, QString &string, const QString tag, const QString group1="", const QString group2="" );
|
||||
void store(const bool newTruth, bool &truth, const QString tag, const QString group1="", const QString group2="" );
|
||||
void store(const int newNumber, int &number, const QString tag, const QString group1="", const QString group2="" );
|
||||
void clear (const QString & tag1 = "", const QString &tag2 = "", const QString &tag3 = "");
|
||||
|
||||
// Retrieval functions
|
||||
void retrieve( QByteArray &array, const QString tag, const QString def, const QString group1="", const QString group2="" );
|
||||
void retrieve( QStringList &stringList, const QString tag, const QString def, const QString group1="", const QString group2="" );
|
||||
void retrieve( QString &string, const QString tag, const QString def, const QString group1="", const QString group2="" );
|
||||
void retrieve( bool &truth, const QString tag, const bool def, const QString group1="", const QString group2="" );
|
||||
void retrieve( int &number, const QString tag, const int def, const QString group1="", const QString group2="" );
|
||||
// NOTE: OBJ_T can only be a standard or registered Qt type. To use custom types,
|
||||
// either Q_DECLARE_METATYPE() them or add additional logic in retrieve() to handle QMetaType::User.
|
||||
|
||||
template <typename OBJ_T, typename TAG_T, typename GP1_T = QString, typename GP2_T = QString>
|
||||
void store(const OBJ_T newValue, OBJ_T & destValue, const TAG_T tag, const GP1_T group1 = "", const GP2_T group2 = "");
|
||||
|
||||
template <typename OBJ_T, typename TAG_T, typename DEF_T, typename GP1_T = QString, typename GP2_T = QString>
|
||||
void retrieve(OBJ_T & destValue, const TAG_T tag, const DEF_T def, const GP1_T group1 = "", const GP2_T group2 = "");
|
||||
|
||||
template <typename OBJ_T, typename TAG_T, typename DEF_T, typename GP1_T = QString, typename GP2_T = QString>
|
||||
void getset(OBJ_T & value, const TAG_T tag, const DEF_T def, const GP1_T group1 = "", const GP2_T group2 = "" );
|
||||
|
||||
// this specialization is needed because QVariant::fromValue(const char *) fails
|
||||
template <typename OBJ_T, typename TAG_T, typename GP1_T = QString, typename GP2_T = QString>
|
||||
void getset(OBJ_T & value, const TAG_T tag, const char * def, const GP1_T group1 = "", const GP2_T group2 = "" );
|
||||
|
||||
// Retrieve and Store functions
|
||||
void getset( QByteArray &array, const QString tag, const QString def, const QString group1="", const QString group2="" );
|
||||
void getset( QStringList &stringList, const QString tag, const QString def, const QString group1="", const QString group2="" );
|
||||
void getset( QString &string, const QString tag, const QString def, const QString group1="", const QString group2="" );
|
||||
void getset( bool &truth, const QString tag, const bool def, const QString group1="", const QString group2="" );
|
||||
void getset( int &number, const QString tag, const int def, const QString group1="", const QString group2="" );
|
||||
};
|
||||
|
||||
class FwRevision: protected CompStoreObj
|
||||
@@ -122,9 +125,6 @@ class Profile: protected CompStoreObj
|
||||
int _channelOrder;
|
||||
int _defaultMode;
|
||||
|
||||
// Simulator variables
|
||||
QByteArray _simuWinGeo;
|
||||
|
||||
// Firmware Variables
|
||||
QString _beeper;
|
||||
QString _countryCode;
|
||||
@@ -136,13 +136,16 @@ class Profile: protected CompStoreObj
|
||||
QString _trainerCalib;
|
||||
QString _controlTypes;
|
||||
QString _controlNames;
|
||||
int _txCurrentCalibration;
|
||||
int _gsStickMode;
|
||||
int _ppmMultiplier;
|
||||
int _txVoltageCalibration;
|
||||
int _vBatWarn;
|
||||
int _vBatMin;
|
||||
int _vBatMax;
|
||||
int _txCurrentCalibration;
|
||||
int _txVoltageCalibration;
|
||||
|
||||
// Simulator variables
|
||||
SimulatorOptions _simulatorOptions;
|
||||
|
||||
public:
|
||||
// All the get definitions
|
||||
@@ -159,8 +162,6 @@ class Profile: protected CompStoreObj
|
||||
int channelOrder() const;
|
||||
int defaultMode() const;
|
||||
|
||||
QByteArray simuWinGeo() const;
|
||||
|
||||
QString beeper() const;
|
||||
QString countryCode() const;
|
||||
QString display() const;
|
||||
@@ -179,6 +180,8 @@ class Profile: protected CompStoreObj
|
||||
int vBatMin() const;
|
||||
int vBatMax() const;
|
||||
|
||||
SimulatorOptions simulatorOptions() const;
|
||||
|
||||
// All the set definitions
|
||||
void name (const QString);
|
||||
void fwName (const QString);
|
||||
@@ -193,8 +196,6 @@ class Profile: protected CompStoreObj
|
||||
void channelOrder (const int);
|
||||
void defaultMode (const int);
|
||||
|
||||
void simuWinGeo (const QByteArray);
|
||||
|
||||
void beeper (const QString);
|
||||
void countryCode (const QString);
|
||||
void display (const QString);
|
||||
@@ -213,6 +214,8 @@ class Profile: protected CompStoreObj
|
||||
void vBatMin (const int);
|
||||
void vBatMax (const int);
|
||||
|
||||
void simulatorOptions (const SimulatorOptions &);
|
||||
|
||||
Profile();
|
||||
Profile& operator=(const Profile&);
|
||||
void remove();
|
||||
@@ -220,6 +223,7 @@ class Profile: protected CompStoreObj
|
||||
void init(int newIndex);
|
||||
void initFwVariables();
|
||||
void flush();
|
||||
QString groupId();
|
||||
};
|
||||
|
||||
#define BOOL_PROPERTY(name, dflt) \
|
||||
@@ -231,12 +235,12 @@ class Profile: protected CompStoreObj
|
||||
|
||||
class AppData: protected CompStoreObj
|
||||
{
|
||||
BOOL_PROPERTY(enableBackup, false)
|
||||
BOOL_PROPERTY(outputDisplayDetails, false)
|
||||
BOOL_PROPERTY(backupOnFlash, true)
|
||||
BOOL_PROPERTY(enableBackup, false)
|
||||
BOOL_PROPERTY(backupOnFlash, true)
|
||||
BOOL_PROPERTY(outputDisplayDetails, false)
|
||||
BOOL_PROPERTY(checkHardwareCompatibility, true)
|
||||
BOOL_PROPERTY(useCompanionNightlyBuilds, false)
|
||||
BOOL_PROPERTY(useFirmwareNightlyBuilds, false)
|
||||
BOOL_PROPERTY(useCompanionNightlyBuilds, false)
|
||||
BOOL_PROPERTY(useFirmwareNightlyBuilds, false)
|
||||
|
||||
// All the global variables
|
||||
public:
|
||||
@@ -261,9 +265,6 @@ class AppData: protected CompStoreObj
|
||||
QString _programmer;
|
||||
QString _sambaLocation;
|
||||
QString _sambaPort;
|
||||
QString _lastSimulator;
|
||||
QString _simuLastEepe;
|
||||
QString _simuLastFolder;
|
||||
|
||||
QString _backupDir;
|
||||
QString _gePath;
|
||||
@@ -315,9 +316,6 @@ class AppData: protected CompStoreObj
|
||||
QString programmer();
|
||||
QString sambaLocation();
|
||||
QString sambaPort();
|
||||
QString lastSimulator();
|
||||
QString simuLastEepe();
|
||||
QString simuLastFolder();
|
||||
|
||||
QString backupDir();
|
||||
QString gePath();
|
||||
@@ -368,9 +366,6 @@ class AppData: protected CompStoreObj
|
||||
void programmer (const QString);
|
||||
void sambaLocation (const QString);
|
||||
void sambaPort (const QString);
|
||||
void lastSimulator (const QString);
|
||||
void simuLastEepe (const QString);
|
||||
void simuLastFolder (const QString);
|
||||
|
||||
void backupDir (const QString);
|
||||
void gePath (const QString);
|
||||
|
||||
Reference in New Issue
Block a user