From 17a03e6c1888c755642c1f97298b05f2ad84944a Mon Sep 17 00:00:00 2001 From: Max Paperno Date: Tue, 24 Jan 2017 01:54:12 -0500 Subject: [PATCH] [Simulator] Dyanamic Simulator virtual hardware generation and many other improvements (#4260) * Move simulator widgets to subfolder (no code changes). * [Simulator] Major Simulator re-structuring to reduce code redundancies and allow for fully dynamic simulated hardware setup: SimulatorDialog is no longer sub-classed by individual radio UIs, instead a new class is added which handles just the "skin," LCD, and navigation controls (also makes setting up new models much quicker); All radio switches/knobs/sliders are populated dynamically based on loaded hardware configuration data (eeprom/bin), including control types and names (in case of no hardware config data, reasonable "factory defaults" are loaded); Starting Horus sim with alternate path for RADIO and MODEL data folders is now supported (.otx file is WIP); 6-way switch now works properly and various other inconsistencies addressed (eg. some Horus analogs were backwards). * Add missing OpenTX headers to new files. * [Simulator] Fix loading of Horus hardware settings from Companion simulation. * Update Travis CI build environment to Qt 5.7. * [Simulator] Fix 9X missing colored side LCD images, an #include fix, and some cleanup. * [TravisCI] Set up for parallel Travis builds and use Qt5.7 (#4263) * Fix starting Simulator with non-existing file/folder structure (now properly creates new ones as needed, including Horus directories with default radio/model); Temporarily remove option for using .otx file with Horus (until that feature is added). * Load correct simulator skin for X7 when launching from Companion. * X7 hardware defaults changed to match production hardware * Fix minor compiler warning in mdichild.cpp, and some cleanup in eeprominterface.cpp. * [Simulator] Centralize radio UI flavor determination. * [Simulator] Updates: Add X7 UI flavor; Centralize LCD settings; Simplify drawing curved UI widgets; LCD color can be changed for any 1/4-bit display radio; Slight change on default LCD "off" color; Refactor LcdWidget to not use globals. * [Companion] X7 EEPROM import fix + cosmetics + compilation error fixed on Manjaro * [Companion] 9XR-PRO EEPROM import fix + cosmetics + compilation error fixed on Manjaro * Navigation fix French translations * [X7] Main view cosmetics * Fix switch/ana custom name import * [Simulator] Add white border above/below X7 bezel, and use white-colored padding on sides; Adjust X7 default LCD color. * Does this work? (#4269) Read an Horus SD card produces a temporary .otx file now * Bsongis/companion warning before automatic conversions (#4271) * Does this work? * Warning before automatic conversions * Force different file name after conversion (#4272) * Force different file name after conversion * More detailed instructions * [Companion] Files automatically named during XXX => Horus conversions --- companion/src/CMakeLists.txt | 4 +- companion/src/companion.qrc | 23 +- companion/src/constants.h | 6 +- companion/src/helpers.cpp | 59 +- companion/src/simulation/CMakeLists.txt | 49 +- companion/src/simulation/dialwidget.h | 45 - companion/src/simulation/radiouiaction.h | 161 +++ .../src/simulation/simulateduiwidget.cpp | 191 +++ companion/src/simulation/simulateduiwidget.h | 164 +++ .../src/simulation/simulateduiwidget9X.cpp | 94 ++ .../src/simulation/simulateduiwidget9X.ui | 198 +++ .../src/simulation/simulateduiwidgetX12.cpp | 85 ++ .../src/simulation/simulateduiwidgetX12.ui | 256 ++++ .../src/simulation/simulateduiwidgetX7.cpp | 57 + .../src/simulation/simulateduiwidgetX7.ui | 258 ++++ .../src/simulation/simulateduiwidgetX9.cpp | 89 ++ .../src/simulation/simulateduiwidgetX9.ui | 166 +++ .../src/simulation/simulatordialog-9x.ui | 986 -------------- .../simulation/simulatordialog-flamenco.ui | 900 ------------ .../src/simulation/simulatordialog-horus.ui | 1142 ---------------- .../src/simulation/simulatordialog-taranis.ui | 1201 ----------------- companion/src/simulation/simulatordialog.cpp | 1046 +++++++------- companion/src/simulation/simulatordialog.h | 300 ++-- companion/src/simulation/simulatordialog.ui | 407 ++++++ .../src/simulation/simulatordialog9x.cpp | 232 ---- .../simulation/simulatordialogflamenco.cpp | 161 --- .../src/simulation/simulatordialoghorus.cpp | 209 --- .../src/simulation/simulatordialogtaranis.cpp | 211 --- companion/src/simulation/simulatorimport.h | 27 +- companion/src/simulation/simulatorinterface.h | 13 +- companion/src/simulation/telemetrysimu.h | 3 +- .../simulation/{ => widgets}/buttonswidget.h | 90 +- .../src/simulation/{ => widgets}/lcdwidget.h | 47 +- .../src/simulation/widgets/radiofaderwidget.h | 69 + .../src/simulation/widgets/radioknobwidget.h | 127 ++ .../simulation/widgets/radioswitchwidget.h | 80 ++ .../src/simulation/widgets/radiowidget.h | 166 +++ .../simulation/{ => widgets}/sliderwidget.h | 4 +- .../{ => widgets}/virtualjoystickwidget.cpp | 0 .../{ => widgets}/virtualjoystickwidget.h | 0 companion/src/simulator.cpp | 163 ++- companion/src/storage/appdata.cpp | 3 + companion/src/storage/appdata.h | 3 + 43 files changed, 3561 insertions(+), 5934 deletions(-) delete mode 100644 companion/src/simulation/dialwidget.h create mode 100644 companion/src/simulation/radiouiaction.h create mode 100644 companion/src/simulation/simulateduiwidget.cpp create mode 100644 companion/src/simulation/simulateduiwidget.h create mode 100644 companion/src/simulation/simulateduiwidget9X.cpp create mode 100644 companion/src/simulation/simulateduiwidget9X.ui create mode 100644 companion/src/simulation/simulateduiwidgetX12.cpp create mode 100644 companion/src/simulation/simulateduiwidgetX12.ui create mode 100644 companion/src/simulation/simulateduiwidgetX7.cpp create mode 100644 companion/src/simulation/simulateduiwidgetX7.ui create mode 100644 companion/src/simulation/simulateduiwidgetX9.cpp create mode 100644 companion/src/simulation/simulateduiwidgetX9.ui delete mode 100644 companion/src/simulation/simulatordialog-9x.ui delete mode 100644 companion/src/simulation/simulatordialog-flamenco.ui delete mode 100644 companion/src/simulation/simulatordialog-horus.ui delete mode 100644 companion/src/simulation/simulatordialog-taranis.ui create mode 100644 companion/src/simulation/simulatordialog.ui delete mode 100644 companion/src/simulation/simulatordialog9x.cpp delete mode 100644 companion/src/simulation/simulatordialogflamenco.cpp delete mode 100644 companion/src/simulation/simulatordialoghorus.cpp delete mode 100644 companion/src/simulation/simulatordialogtaranis.cpp rename companion/src/simulation/{ => widgets}/buttonswidget.h (61%) rename companion/src/simulation/{ => widgets}/lcdwidget.h (87%) create mode 100644 companion/src/simulation/widgets/radiofaderwidget.h create mode 100644 companion/src/simulation/widgets/radioknobwidget.h create mode 100644 companion/src/simulation/widgets/radioswitchwidget.h create mode 100644 companion/src/simulation/widgets/radiowidget.h rename companion/src/simulation/{ => widgets}/sliderwidget.h (95%) rename companion/src/simulation/{ => widgets}/virtualjoystickwidget.cpp (100%) rename companion/src/simulation/{ => widgets}/virtualjoystickwidget.h (100%) diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index 0d6928b85..66dd94f2f 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -259,11 +259,13 @@ PrintTargetReport("${COMPANION_NAME}") set(simu_SRCS modeledit/node.cpp modeledit/edge.cpp + helpers.cpp simulator.cpp ) set(simu_MOC_HDRS modeledit/node.h + helpers.h ) qt5_wrap_cpp(simu_SRCS ${simu_MOC_HDRS} ) @@ -277,7 +279,7 @@ add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE WIN32 ${simu_SRCS} ${companion_RC add_dependencies(${SIMULATOR_NAME} gen_qrc) qt5_use_modules(${SIMULATOR_NAME} Core Widgets Multimedia) -target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation common storage qxtcommandoptions ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES}) +target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation common shared storage qxtcommandoptions ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES}) ############# Translations #################### diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index 65651a0f6..e9eb212ce 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -5,6 +5,13 @@ ../../CREDITS.txt ../../DONATIONS.txt ../releasenotes.txt + images/screenshot.png + images/splash.png + images/companion-title.png + images/maps.png + images/track.png + images/track0.png + images/taranison.png images/simulator/Horus/middle.png images/simulator/Horus/left.png images/simulator/Horus/right.png @@ -53,12 +60,6 @@ images/simulator/9X/9xcursmin.png images/simulator/9X/9xcursdown.png images/simulator/9X/9xcursphoto.png - images/screenshot.png - images/splash.png - images/companion-title.png - images/maps.png - images/track.png - images/track0.png images/simulator/Taranis/x9b0.png images/simulator/Taranis/x9l0.png images/simulator/Taranis/x9l1.png @@ -71,7 +72,15 @@ images/simulator/Taranis/x9r3.png images/simulator/Taranis/x9s0.png images/simulator/Taranis/x9t0.png - images/taranison.png + images/simulator/X7/bottom.png + images/simulator/X7/left.png + images/simulator/X7/left_exit.png + images/simulator/X7/left_menu.png + images/simulator/X7/left_page.png + images/simulator/X7/left_scrnshot.png + images/simulator/X7/right.png + images/simulator/X7/right_ent.png + images/simulator/X7/top.png images/wizard/ailerons.png images/wizard/airbrakes.png images/wizard/elevons.png diff --git a/companion/src/constants.h b/companion/src/constants.h index a31c33226..1b36b416c 100644 --- a/companion/src/constants.h +++ b/companion/src/constants.h @@ -72,9 +72,9 @@ enum BoardEnum { #define EEPE_EEPROM_FILE_HEADER "EEPE EEPROM FILE" #define EEPE_MODEL_FILE_HEADER "EEPE MODEL FILE" -const char * const ARROW_LEFT = "\xE2\x86\x90"; -const char * const ARROW_UP = "\xE2\x86\x91"; +const char * const ARROW_LEFT = "\xE2\x86\x90"; +const char * const ARROW_UP = "\xE2\x86\x91"; const char * const ARROW_RIGHT = "\xE2\x86\x92"; -const char * const ARROW_DOWN = "\xE2\x86\x93"; +const char * const ARROW_DOWN = "\xE2\x86\x93"; #endif // _CONSTANTS_H_ diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index 64eec85c4..d81d52ae4 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -202,7 +202,7 @@ void GVarGroup::valuesChanged() weight = round(dsb->value()/step); if (panel) emit panel->modified(); - + } } @@ -813,8 +813,6 @@ CompanionIcon::CompanionIcon(const QString &baseimage) void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx) { - QString settingsPath; - Firmware * firmware = getCurrentFirmware(); SimulatorInterface * simulator = getCurrentSimulator(); if (simulator) { #if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO) @@ -824,60 +822,31 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx) freopen("conout$", "w", stdout); freopen("conout$", "w", stderr); #endif + Firmware * firmware = getCurrentFirmware(); RadioData * simuData = new RadioData(radioData); + BoardEnum board = getCurrentBoard(); + QByteArray eeprom = QByteArray(); + QString sdPath = g.profile[g.id()].sdPath(); + QString settingsPath = ""; unsigned int flags = 0; + if (modelIdx >= 0) { flags |= SIMULATOR_FLAGS_NOTX; simuData->setCurrentModel(modelIdx); } - if (radioData.generalSettings.stickMode & 1) { - flags |= SIMULATOR_FLAGS_STICK_MODE_LEFT; - } - BoardEnum board = getCurrentBoard(); - SimulatorDialog * dialog; - if (board == BOARD_HORUS) { - dialog = new SimulatorDialogHorus(parent, simulator, flags); + if (IS_HORUS(board)) { QTemporaryDir tmpDir(QDir::tempPath() + "/otx-XXXXXX"); settingsPath = tmpDir.path(); tmpDir.setAutoRemove(false); - SdcardFormat sdcard(settingsPath); - sdcard.write(*simuData); - qDebug() << "Starting Horus simulation with SD path" << g.profile[g.id()].sdPath() << "and models/settings path" << settingsPath; - simulator->setSdPath(g.profile[g.id()].sdPath(), settingsPath); - dialog->start(NULL); - } - else if (board == BOARD_FLAMENCO) { - dialog = new SimulatorDialogFlamenco(parent, simulator, flags); - QByteArray eeprom(getEEpromSize(board), 0); - firmware->getEEpromInterface()->save((uint8_t *)eeprom.data(), *simuData); - simulator->setSdPath(g.profile[g.id()].sdPath(), ""); - dialog->start(eeprom); - } - else if (board == BOARD_TARANIS_X9D || board == BOARD_TARANIS_X9DP || board == BOARD_TARANIS_X9E) { - for (int i=0; igetCapability(Pots); i++) { - if (radioData.generalSettings.isPotAvailable(i)) { - flags |= (SIMULATOR_FLAGS_S1 << i); - if (radioData.generalSettings.potConfig[1] == GeneralSettings::POT_MULTIPOS_SWITCH ) { - flags |= (SIMULATOR_FLAGS_S1_MULTI << i); - } - } - } - dialog = new SimulatorDialogTaranis(parent, simulator, flags); - QByteArray eeprom(getEEpromSize(board), 0); - firmware->getEEpromInterface()->save((uint8_t *)eeprom.data(), *simuData); - qDebug() << "Starting Taranis simulation with SD path" << g.profile[g.id()].sdPath(); - simulator->setSdPath(g.profile[g.id()].sdPath(), ""); - dialog->start(eeprom); - } - else { - dialog = new SimulatorDialog9X(parent, simulator, flags); - QByteArray eeprom(getEEpromSize(board), 0); - firmware->getEEpromInterface()->save((uint8_t *)eeprom.data(), *simuData, 0, firmware->getCapability(SimulatorVariant)); - simulator->setSdPath(g.profile[g.id()].sdPath(), ""); // does 9X need SD card path? I think not. - dialog->start(eeprom); } + 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); + dialog->setRadioData(simuData); + dialog->start(); dialog->exec(); dialog->deleteLater(); if (!settingsPath.isEmpty()) { diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt index 00507c363..c29fb9225 100644 --- a/companion/src/simulation/CMakeLists.txt +++ b/companion/src/simulation/CMakeLists.txt @@ -1,31 +1,43 @@ set(simulation_SRCS + debugoutput.cpp simulatordialog.cpp + simulatorinterface.cpp + simulateduiwidget.cpp + simulateduiwidget9X.cpp + simulateduiwidgetX7.cpp + simulateduiwidgetX9.cpp + simulateduiwidgetX12.cpp telemetrysimu.cpp trainersimu.cpp - debugoutput.cpp - simulatorinterface.cpp - virtualjoystickwidget.cpp + widgets/virtualjoystickwidget.cpp ) set(simulation_UIS - simulatordialog-9x.ui - simulatordialog-taranis.ui - simulatordialog-horus.ui - simulatordialog-flamenco.ui + debugoutput.ui + simulatordialog.ui + simulateduiwidget9X.ui + simulateduiwidgetX7.ui + simulateduiwidgetX9.ui + simulateduiwidgetX12.ui telemetrysimu.ui trainersimu.ui - debugoutput.ui ) set(simulation_HDRS + debugoutput.h + radiouiaction.h simulatordialog.h - # lcdwidget.h - buttonswidget.h - sliderwidget.h + simulateduiwidget.h telemetrysimu.h trainersimu.h - debugoutput.h - virtualjoystickwidget.h + widgets/buttonswidget.h + widgets/lcdwidget.h + widgets/radiowidget.h + widgets/radiofaderwidget.h + widgets/radioknobwidget.h + widgets/radioswitchwidget.h + widgets/sliderwidget.h + widgets/virtualjoystickwidget.h ) if(SDL_FOUND) @@ -34,29 +46,30 @@ if(SDL_FOUND) joystick.cpp joystickdialog.cpp ) - + set(simulation_HDRS ${simulation_HDRS} joystick.h joystickdialog.h ) - + set(simulation_UIS ${simulation_UIS} joystickdialog.ui - ) -endif() + ) +endif() include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${PROJECT_SOURCE_DIR} ${COMPANION_SRC_DIRECTORY} ${COMPANION_SRC_DIRECTORY}/simulation + ${COMPANION_SRC_DIRECTORY}/simulation/widgets ${RADIO_SRC_DIRECTORY}/fonts/std ) qt5_wrap_ui(simulation_SRCS ${simulation_UIS}) qt5_wrap_cpp(simulation_SRCS ${simulation_HDRS}) -add_library(simulation ${simulation_SRCS}) +add_library(simulation ${simulation_SRCS} ${simulation_HDRS}) qt5_use_modules(simulation Widgets Xml) diff --git a/companion/src/simulation/dialwidget.h b/companion/src/simulation/dialwidget.h deleted file mode 100644 index bd28ac9b7..000000000 --- a/companion/src/simulation/dialwidget.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _DIALWIDGET_H_ -#define _DIALWIDGET_H_ - -class DialWidget : public QDial -{ - public: - - explicit DialWidget(QWidget * parent = 0): - QDial(parent) - { - } - - protected: - - void mousePressEvent(QMouseEvent * event) - { - if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) { - setValue(0); - event->accept(); - } - QDial::mousePressEvent(event); - } -}; - -#endif // _DIALWIDGET_H_ diff --git a/companion/src/simulation/radiouiaction.h b/companion/src/simulation/radiouiaction.h new file mode 100644 index 000000000..61bfb0ec0 --- /dev/null +++ b/companion/src/simulation/radiouiaction.h @@ -0,0 +1,161 @@ +/* + * 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 RADIOUIACTION_H +#define RADIOUIACTION_H + +#include +#include +#include + +/* + * This class is somewhat like a QAction but specific for the radio UI. + * Actions can have one or more keyboard shortcuts associated with them (currently single-key only, w/out modifiers). + */ +class RadioUiAction : public QObject +{ + Q_OBJECT + + public: + /* + * @param index Typically this is the hardware array index corresponding to button on current radio model, + * but it could be anything. Use -1 or any other negative value for non-hardware indices. + * @param key An optional Qt:Key code for shortcut. + * @param parent Parent widget, required for handling keyboard events. + * @param text Optional title for this action. The text and description are currently used in generated help text. + * @param descript Optional longer description text for this action. + */ + RadioUiAction(int index = -1, int key = 0, QWidget * parent = NULL, const QString &text = "", const QString &descript = ""): + m_hwIndex(index), + m_active(false), + m_keys(QList()), + m_text(text), + m_description(descript), + m_parent(parent) + { + if (key) + m_keys.append(key); + + init(); + } + /* + * @param keys QList of Qt:Key codes to use as shortcuts. + * [See above for other params.] + */ + RadioUiAction(int index, QList keys, QWidget * parent = NULL, const QString &text = "", const QString &descript = ""): + m_hwIndex(index), + m_active(false), + m_keys(keys), + m_text(text), + m_description(descript), + m_parent(parent) + { + init(); + } + + void init() + { + if (m_keys.size()) + addShortcut(); + } + + void addShortcut() + { + if (m_parent) + m_parent->installEventFilter(this); + } + + void setDescription(const QString & description) { m_description = description; } + void setText(QPair name_descript) { setText(name_descript.first, name_descript.second); } + + void setText(const QString & text, const QString & description = "") + { + m_text = text; + if (!description.isEmpty()) + setDescription(description); + } + + int getIndex() const { return m_hwIndex; } + bool isActive() const { return m_active; } + QString getDescription() const { return m_description; } + QString getText() const { return m_text; } + + bool eventFilter(QObject * obj, QEvent * event) + { + if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { + QKeyEvent *keyEvent = static_cast(event); + if ((!keyEvent->modifiers() || keyEvent->modifiers() == Qt::KeypadModifier) && m_keys.contains(keyEvent->key())) { + trigger(event->type() == QEvent::KeyPress); + return true; + } + } + return QObject::eventFilter(obj, event); + } + + public slots: + + // "toggle" is the most basic way to set the action status and emits only one "toggled" signal + bool toggle(bool active = true) + { + if (active != m_active) { + m_active = active; + emit toggled(m_hwIndex, active); + return true; + } + return false; + } + + // "trigger" indicates a user-initiated action and emits more signals than "toggle" does + void trigger(bool active = true) + { + if (toggle(active)) { + emit triggered(m_hwIndex, active); + if (active) + emit pushed(m_hwIndex); + } + } + + private: + + int m_hwIndex; + bool m_active; + QList m_keys; + QString m_text; + QString m_description; + QWidget * m_parent; + + + signals: + void toggled(int index, bool active); // on programmatic or user interaction change + void triggered(int index, bool active); // on user interaction change only + void pushed(int index); // only emitted on user interaction && when 'active' is true +}; + +#endif // RADIOUIACTION_H + + + + + + + + + + diff --git a/companion/src/simulation/simulateduiwidget.cpp b/companion/src/simulation/simulateduiwidget.cpp new file mode 100644 index 000000000..b0c8e48a7 --- /dev/null +++ b/companion/src/simulation/simulateduiwidget.cpp @@ -0,0 +1,191 @@ +/* + * 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 "simulateduiwidget.h" +#include "eeprominterface.h" +#include "lcdwidget.h" +#include "radiouiaction.h" +#include "simulatorinterface.h" + +SimulatedUIWidget::SimulatedUIWidget(SimulatorInterface * simulator, SimulatorDialog * simuDialog, QWidget * parent) : + QWidget(parent), + m_simulator(simulator), + m_simuDialog(simuDialog), + m_lcd(NULL), + m_scrollUpAction(NULL), + m_scrollDnAction(NULL), + m_rotEncClickAction(NULL), + m_board(getCurrentBoard()), + m_backLight(0), + m_lightOn(false), + m_beepShow(0), + m_beepVal(0) +{ + m_rotEncClickAction = addRadioUiAction(-1, 0, tr("Rotary encoder click")); + m_screenshotAction = addRadioUiAction(-1, Qt::Key_Print, tr("Take Screenshot")); + connect(m_screenshotAction, &RadioUiAction::pushed, this, &SimulatedUIWidget::saveScreenshot); +} + +SimulatedUIWidget::~SimulatedUIWidget() +{ + foreach (RadioUiAction * act, m_actions) { + if (act) + delete act; + } +} + +RadioUiAction * SimulatedUIWidget::addRadioUiAction(RadioUiAction * act) +{ + if (act) { + m_actions.append(act); + if (!act->getText().isEmpty() && !act->getDescription().isEmpty()) + m_keymapHelp.append(keymapHelp_t(act->getText(), act->getDescription())); + } + return act; +} + +RadioUiAction * SimulatedUIWidget::addRadioUiAction(int index, int key, const QString & text, const QString & descript) +{ + return addRadioUiAction(new RadioUiAction(index, key, m_simuDialog, text, descript)); +} + +RadioUiAction * SimulatedUIWidget::addRadioUiAction(int index, QList keys, const QString & text, const QString & descript) +{ + return addRadioUiAction(new RadioUiAction(index, keys, m_simuDialog, text, descript)); +} + +QPolygon SimulatedUIWidget::polyArc(int ctrX, int ctrY, int radius, int startAngle, int endAngle, int step) +{ + QPolygon polygon; + float st = qDegreesToRadians((float)startAngle - 90.0f); + float en = qDegreesToRadians((float)endAngle - 90.0f); + float sp = qDegreesToRadians((float)step); + for ( ; st < en; st += sp) { + polygon << QPoint((int)(ctrX + radius * cosf(st)), (int)(ctrY + radius * sinf(st))); + } + return polygon; +} + +void SimulatedUIWidget::timedUpdate(unsigned loop) +{ + if (m_lcd->isVisible()) { + bool lightEnable; + if (m_simulator->lcdChanged(lightEnable)) { + m_lcd->onLcdChanged(lightEnable); + if (m_lightOn != lightEnable) { + setLightOn(lightEnable); + m_lightOn = lightEnable; + } + } + } + /* TODO : beep indicator + if (!(loop % 5)) { + TxOutputs outputs; + simulator->getValues(outputs); + if (outputs.beep) { + beepVal = outputs.beep; + } + if (beepVal) { + beepShow = 20; + beepVal = 0; + QApplication::beep(); + } else if (beepShow) { + beepShow--; + } + ui->label_beep->setStyleSheet(beepShow ? CBEEP_ON : CBEEP_OFF); + } */ +} + +void SimulatedUIWidget::saveScreenshot(int idx) +{ + Q_UNUSED(idx) + QString fileName = ""; + if (!g.snapToClpbrd()) { + QString path = g.snapshotDir(); + if (path.isEmpty()) + path = "./"; + QDir dir(path); + if (!dir.exists() || !dir.isReadable()) { + m_simuDialog->traceCallback("SIMULATOR ERROR - Cannot open screenshot folder, check your settings.\n"); + return; + } + fileName += QString("%1screenshot_%2.png").arg(dir.absolutePath(), QDateTime::currentDateTime().toString("yy-MM-dd_HH-mm-ss")); + } + m_lcd->makeScreenshot(fileName); +} + +// steps can be negative or positive to determine direction (negative is UP/RIGHT scroll) +void SimulatedUIWidget::simulatorWheelEvent(qint8 steps) +{ + m_simulator->wheelEvent(steps); +} + +void SimulatedUIWidget::wheelEvent(QWheelEvent * event) +{ + if (event->angleDelta().isNull()) + return; + QPoint numSteps = event->angleDelta() / 8 / 15 * -1; // one step per 15deg + simulatorWheelEvent(numSteps.y()); +} + +void SimulatedUIWidget::mousePressEvent(QMouseEvent * event) +{ + if (event->button() == Qt::MidButton && m_rotEncClickAction) + m_rotEncClickAction->trigger(true); + else + event->ignore(); +} + +void SimulatedUIWidget::mouseReleaseEvent(QMouseEvent * event) +{ + if (event->button() == Qt::MidButton && m_rotEncClickAction) + m_rotEncClickAction->trigger(false); + else + event->ignore(); +} + +void SimulatedUIWidget::setLcd(LcdWidget * lcd) +{ + m_lcd = lcd; + Firmware * firmware = getCurrentFirmware(); + m_lcd->setData(m_simulator->getLcd(), firmware->getCapability(LcdWidth), firmware->getCapability(LcdHeight), firmware->getCapability(LcdDepth)); + + if (!m_backlightColors.size()) + return; + + m_backLight = g.backLight(); + if ((int)m_backLight >= m_backlightColors.size()) + m_backLight = 0; + + m_lcd->setBackgroundColor(m_backlightColors.at(m_backLight)); +} + +void SimulatedUIWidget::connectScrollActions() +{ + connect(m_scrollUpAction, &RadioUiAction::pushed, [this](void) { + this->simulatorWheelEvent(-1); + m_scrollUpAction->toggle(false); + }); + + connect(m_scrollDnAction, &RadioUiAction::pushed, [this](void) { + simulatorWheelEvent(1); + m_scrollDnAction->toggle(false); + }); +} diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h new file mode 100644 index 000000000..d957c3081 --- /dev/null +++ b/companion/src/simulation/simulateduiwidget.h @@ -0,0 +1,164 @@ +/* + * 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 SIMULATEDUIWIDGET_H +#define SIMULATEDUIWIDGET_H + +#include "constants.h" +#include "simulatordialog.h" + +#include +#include + +class SimulatorInterface; +class LcdWidget; +class RadioUiAction; + +/* + * 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). + * Sub-classes are responsible for building the actual UI form they need for presentation. + * This base class should not be instantiated directly. + */ +class SimulatedUIWidget : public QWidget +{ + Q_OBJECT + + protected: + + explicit SimulatedUIWidget(SimulatorInterface * simulator, SimulatorDialog * simuDialog = NULL, QWidget * parent = NULL); + ~SimulatedUIWidget(); + + public: + + RadioUiAction * addRadioUiAction(RadioUiAction * act); + RadioUiAction * addRadioUiAction(int index = -1, int key = 0, const QString &text = "", const QString &descript = ""); + RadioUiAction * addRadioUiAction(int index, QList keys, const QString &text = "", const QString &descript = ""); + + QVector * getKeymapHelp() { return &m_keymapHelp; } + QList getActions() const { return m_actions; } + RadioUiAction * getRotEncAction() const { return m_rotEncClickAction; } + + QPolygon polyArc(int ctrX, int ctrY, int radius, int startAngle = 0, int endAngle = 360, int step = 10); + + public slots: + + void timedUpdate(unsigned loop); + void saveScreenshot(int idx = -1); + void captureScreenshot() { saveScreenshot(); } + void simulatorWheelEvent(qint8 steps); + + void wheelEvent(QWheelEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + + protected: + void setLcd(LcdWidget * lcd); + void connectScrollActions(); + virtual void setLightOn(bool enable) { } + + SimulatorInterface * m_simulator; + SimulatorDialog * m_simuDialog; + LcdWidget * m_lcd; + QVector m_backlightColors; + QVector m_keymapHelp; + QList m_actions; + RadioUiAction * m_scrollUpAction; + RadioUiAction * m_scrollDnAction; + RadioUiAction * m_rotEncClickAction; + RadioUiAction * m_screenshotAction; + BoardEnum m_board; + unsigned int m_backLight; + bool m_lightOn; + int m_beepShow; + int m_beepVal; + +}; + + +// Each subclass is responsible for its own Ui +namespace Ui { + class SimulatedUIWidget9X; + class SimulatedUIWidgetX7; + class SimulatedUIWidgetX9; + class SimulatedUIWidgetX12; +} + +class SimulatedUIWidget9X: public SimulatedUIWidget +{ + Q_OBJECT + + public: + explicit SimulatedUIWidget9X(SimulatorInterface * simulator, SimulatorDialog * simuDialog = NULL, QWidget * parent = NULL); + virtual ~SimulatedUIWidget9X(); + + protected: + void setLightOn(bool enable); + + protected slots: + + private: + Ui::SimulatedUIWidget9X * ui; + +}; + +class SimulatedUIWidgetX7: public SimulatedUIWidget +{ + Q_OBJECT + + public: + explicit SimulatedUIWidgetX7(SimulatorInterface * simulator, SimulatorDialog * simuDialog = NULL, QWidget * parent = NULL); + virtual ~SimulatedUIWidgetX7(); + + protected: + + private: + Ui::SimulatedUIWidgetX7 * ui; +}; + +class SimulatedUIWidgetX9: public SimulatedUIWidget +{ + Q_OBJECT + + public: + explicit SimulatedUIWidgetX9(SimulatorInterface * simulator, SimulatorDialog * simuDialog = NULL, QWidget * parent = NULL); + virtual ~SimulatedUIWidgetX9(); + + protected: + + private: + Ui::SimulatedUIWidgetX9 * ui; +}; + +class SimulatedUIWidgetX12: public SimulatedUIWidget +{ + Q_OBJECT + + public: + explicit SimulatedUIWidgetX12(SimulatorInterface * simulator, SimulatorDialog * simuDialog = NULL, QWidget * parent = NULL); + virtual ~SimulatedUIWidgetX12(); + + protected: + + private: + Ui::SimulatedUIWidgetX12 * ui; +}; + +#endif // SIMULATEDUIWIDGET_H diff --git a/companion/src/simulation/simulateduiwidget9X.cpp b/companion/src/simulation/simulateduiwidget9X.cpp new file mode 100644 index 000000000..b512f8def --- /dev/null +++ b/companion/src/simulation/simulateduiwidget9X.cpp @@ -0,0 +1,94 @@ +/* + * 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 "simulateduiwidget.h" +#include "ui_simulateduiwidget9X.h" + +SimulatedUIWidget9X::SimulatedUIWidget9X(SimulatorInterface * simulator, SimulatorDialog * simuDialog, QWidget * parent): + SimulatedUIWidget(simulator, simuDialog, parent), + ui(new Ui::SimulatedUIWidget9X) +{ + RadioUiAction * act; + QPolygon polygon; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + int x = 68, y = 91, oR = 63; + + polygon << QPoint(x, y) << polyArc(x, y, oR, -45, 45); + act = addRadioUiAction(3, QList() << Qt::Key_Up << Qt::Key_PageUp, tr("UP/PG-UP"), tr("[ UP ]")); + ui->leftbuttons->addArea(polygon, "9X/9xcursup.png", act); + + polygon.clear(); + polygon << QPoint(x, y) << polyArc(x, y, oR, 135, 225); + act = addRadioUiAction(2, QList() << Qt::Key_Down << Qt::Key_PageDown, tr("DN/PG-DN"), tr("[ DN ]")); + ui->leftbuttons->addArea(polygon, "9X/9xcursdown.png", act); + + polygon.clear(); + polygon << QPoint(x, y) << polyArc(x, y, oR, 45, 135); + act = addRadioUiAction(4, QList() << Qt::Key_Right << Qt::Key_Plus << Qt::Key_Equal, tr("RIGHT/+"), tr("[ + ]")); + ui->leftbuttons->addArea(polygon, "9X/9xcursmin.png", act); + + polygon.clear(); + polygon << QPoint(x, y) << polyArc(x, y, oR, 225, 315); + act = addRadioUiAction(5, QList() << Qt::Key_Left << Qt::Key_Minus, tr("LEFT/-"), tr("[ - ]")); + ui->leftbuttons->addArea(polygon, "9X/9xcursplus.png", act); + + act = addRadioUiAction(0, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("[ MENU ]")); + m_rotEncClickAction = act; + ui->rightbuttons->addArea(25, 60, 71, 81, "9X/9xmenumenu.png", act); + + act = addRadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DEL/BKSP/ESC"), tr("[ EXIT ]")); + ui->rightbuttons->addArea(25, 117, 71, 139, "9X/9xmenuexit.png", act); + + ui->leftbuttons->addArea(-1, 148, 39, 182, "9X/9xcursphoto.png", m_screenshotAction); + + m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("[ UP ]/[ DN ] or Rotary Sel."))); + + m_backlightColors << QColor(159,165,247); + m_backlightColors << QColor(166,247,159); + m_backlightColors << QColor(247,159,166); + m_backlightColors << QColor(255,195,151); + m_backlightColors << QColor(247,242,159); + + setLcd(ui->lcd); +} + +SimulatedUIWidget9X::~SimulatedUIWidget9X() +{ + delete ui; +} + +void SimulatedUIWidget9X::setLightOn(bool enable) +{ + static QStringList list = QStringList() << "bl" << "gr" << "rd" << "or" << "yl"; + static QString bgfmt = "background:url(:/images/simulator/9X/9xd%1%2.png);"; + QString bg = ""; + if (enable && (int)m_backLight < list.size()) { + bg = "-" + list[m_backLight]; + } + ui->top->setStyleSheet(bgfmt.arg("t").arg(bg)); + ui->bottom->setStyleSheet(bgfmt.arg("b").arg(bg)); + ui->left->setStyleSheet(bgfmt.arg("l").arg(bg)); + ui->right->setStyleSheet(bgfmt.arg("r").arg(bg)); +} + diff --git a/companion/src/simulation/simulateduiwidget9X.ui b/companion/src/simulation/simulateduiwidget9X.ui new file mode 100644 index 000000000..639f3a5b0 --- /dev/null +++ b/companion/src/simulation/simulateduiwidget9X.ui @@ -0,0 +1,198 @@ + + + SimulatedUIWidget9X + + + + 0 + 0 + 569 + 186 + + + + + 0 + 0 + + + + + 569 + 186 + + + + + 569 + 186 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 128 + 186 + + + + true + + + background:url(:/images/simulator/9X/9xcurs.png); + + + + + + + + 0 + 0 + + + + + 41 + 186 + + + + background:url(:/images/simulator/9X/9xdl.png) + + + + + + + + 0 + 0 + + + + + 256 + 29 + + + + background:url(:/images/simulator/9X/9xdt.png) + + + + + + + + 0 + 0 + + + + + 55 + 186 + + + + background:url(:/images/simulator/9X/9xdr.png) + + + + + + + + 0 + 0 + + + + + 89 + 186 + + + + background:url(:/images/simulator/9X/9xmenu.png) + + + + + + + + 0 + 0 + + + + + 256 + 128 + + + + + + + + + 0 + 0 + + + + + 256 + 29 + + + + background:url(:/images/simulator/9X/9xdb.png) + + + + + + + + LcdWidget + QWidget +
lcdwidget.h
+ 1 +
+ + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+
+ + +
diff --git a/companion/src/simulation/simulateduiwidgetX12.cpp b/companion/src/simulation/simulateduiwidgetX12.cpp new file mode 100644 index 000000000..a6c0d7759 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetX12.cpp @@ -0,0 +1,85 @@ +/* + * 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 "simulateduiwidget.h" +#include "ui_simulateduiwidgetX12.h" + +SimulatedUIWidgetX12::SimulatedUIWidgetX12(SimulatorInterface *simulator, SimulatorDialog * simuDialog, QWidget * parent): + SimulatedUIWidget(simulator, simuDialog, parent), + ui(new Ui::SimulatedUIWidgetX12) +{ + RadioUiAction * act; + QPolygon polygon; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + int x = 74, y = 190, oR = 63, iR = 40; + + polygon << polyArc(x, y, oR, 225, 315) << polyArc(x, y, iR, 225, 315); + act = addRadioUiAction(0, QList() << Qt::Key_PageUp, tr("PG-UP"), tr("[ PgUp ]")); + ui->leftbuttons->addArea(polygon, "Horus/left_btn1.png", act); + + polygon.clear(); + polygon << polyArc(x, y, oR, 135, 225) << polyArc(x, y, iR, 135, 225); + act = addRadioUiAction(1, QList() << Qt::Key_PageDown, tr("PG-DN"), tr("[ PgDn ]")); + ui->leftbuttons->addArea(polygon, "Horus/left_btn2.png", act); + + polygon.clear(); + polygon << polyArc(x, y, oR, -45, 45) << polyArc(x, y, iR, -45, 45); + act = addRadioUiAction(3, QList() << Qt::Key_Up, tr("UP"), tr("[ MDL ]")); + ui->rightbuttons->addArea(polygon, "Horus/right_btnU.png", act); + + polygon.clear(); + polygon << polyArc(x, y, oR, 135, 225) << polyArc(x, y, iR, 135, 225); + act = addRadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DN/DEL/BKSP"), tr("[ RTN ]")); + ui->rightbuttons->addArea(polygon, "Horus/right_btnD.png", act); + + polygon.clear(); + polygon << polyArc(x, y, oR, 225, 315) << polyArc(x, y, iR, 225, 315); + act = addRadioUiAction(6, QList() << Qt::Key_Left, tr("LEFT"), tr("[ SYS ]")); + ui->rightbuttons->addArea(polygon, "Horus/right_btnL.png", act); + + polygon.clear(); + polygon << polyArc(x, y, oR, 45, 135) << polyArc(x, y, iR, 45, 135); + act = addRadioUiAction(5, QList() << Qt::Key_Right, tr("RIGHT"), tr("[ TELE ]")); + ui->rightbuttons->addArea(polygon, "Horus/right_btnR.png", act); + + m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("Rotary Selector"))); + + m_scrollUpAction = addRadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_X, tr("-/X"), tr("Rotary UP")); + m_scrollDnAction = addRadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_C, tr("+/C"), tr("Rotary DOWN")); + + act = addRadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("Selector Press")); + ui->rightbuttons->addArea(polyArc(x, y, iR), "Horus/right_ent.png", act); + + ui->leftbuttons->addArea(9, 259, 34, 282, "Horus/left_scrnsht.png", m_screenshotAction); + + m_backlightColors << QColor(47, 123, 227); + + setLcd(ui->lcd); + connectScrollActions(); +} + +SimulatedUIWidgetX12::~SimulatedUIWidgetX12() +{ + delete ui; +} diff --git a/companion/src/simulation/simulateduiwidgetX12.ui b/companion/src/simulation/simulateduiwidgetX12.ui new file mode 100644 index 000000000..693f8c9bc --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetX12.ui @@ -0,0 +1,256 @@ + + + SimulatedUIWidgetX12 + + + + 0 + 0 + 825 + 292 + + + + + 0 + 0 + + + + + 825 + 292 + + + + + 825 + 292 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 147 + 292 + + + + + 147 + 292 + + + + true + + + background:url(:/images/simulator/Horus/left.png); + + + + + + + + 0 + 0 + + + + + 24 + 292 + + + + + 24 + 292 + + + + background:url(:/images/simulator/Horus/led.png) + + + + + + + + 0 + 0 + + + + + 480 + 9 + + + + + 480 + 9 + + + + + 5 + + + + background:url(:/images/simulator/Horus/top.png) + + + + + + + + 0 + 0 + + + + + 27 + 292 + + + + + 27 + 292 + + + + background:url(:/images/simulator/Horus/border-right.png) + + + + + + + + 0 + 0 + + + + + 147 + 292 + + + + + 147 + 292 + + + + background:url(:/images/simulator/Horus/right.png) + + + + + + + + 0 + 0 + + + + + 480 + 272 + + + + + 480 + 272 + + + + + 5 + + + + + + + + + 0 + 0 + + + + + 480 + 11 + + + + + 480 + 11 + + + + + 5 + false + + + + background:url(:/images/simulator/Horus/bottom.png) + + + + + + + + LcdWidget + QWidget +
lcdwidget.h
+ 1 +
+ + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+
+ + +
diff --git a/companion/src/simulation/simulateduiwidgetX7.cpp b/companion/src/simulation/simulateduiwidgetX7.cpp new file mode 100644 index 000000000..03c855be2 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetX7.cpp @@ -0,0 +1,57 @@ +#include "simulateduiwidget.h" +#include "ui_simulateduiwidgetX7.h" + +SimulatedUIWidgetX7::SimulatedUIWidgetX7(SimulatorInterface *simulator, SimulatorDialog * simuDialog, QWidget * parent): + SimulatedUIWidget(simulator, simuDialog, parent), + ui(new Ui::SimulatedUIWidgetX7) +{ + RadioUiAction * act; + QPolygon polygon; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + QPoint ctr(70, 91); + polygon << polyArc(ctr.x(), ctr.y(), 50, -90, 90) << polyArc(ctr.x(), ctr.y(), 22, -90, 90); + act = addRadioUiAction(3, QList() << Qt::Key_PageUp, tr("PG-UP"), tr("[ PAGE ]")); + ui->leftbuttons->addArea(polygon, "X7/left_page.png", act); + + act = addRadioUiAction(0, QList() << Qt::Key_PageDown, tr("PG-DN"), tr("[ MENU ]")); + ui->leftbuttons->addArea(polyArc(ctr.x(), ctr.y(), 20), "X7/left_menu.png", act); + + polygon.clear(); + polygon << polyArc(ctr.x(), ctr.y(), 50, 90, 270) << polyArc(ctr.x(), ctr.y(), 22, 90, 270); + act = addRadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DEL/BKSP/ESC"), tr("[ EXIT ]")); + ui->leftbuttons->addArea(polygon, "X7/left_exit.png", act); + + m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("Rotary Selector"))); + m_scrollUpAction = addRadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Up, tr("-/UP"), tr("Rotary UP")); + m_scrollDnAction = addRadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Down, tr("+/DN"), tr("Rotary DOWN")); + connectScrollActions(); + + act = addRadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), tr("Selector Press")); + ui->rightbuttons->addArea(polyArc(88, 92, 33), "X7/right_ent.png", act); + + ui->leftbuttons->addArea(9, 154, 34, 177, "X7/left_scrnshot.png", m_screenshotAction); + + m_backlightColors << QColor(215, 243, 255); // X7 Blue + m_backlightColors << QColor(166,247,159); + m_backlightColors << QColor(247,159,166); + m_backlightColors << QColor(255,195,151); + m_backlightColors << QColor(247,242,159); + + setLcd(ui->lcd); + connectScrollActions(); + // try to match the gradient on the white radio images. + m_simuDialog->setUiAreaStyle("background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, " \ + "stop:0 rgba(255, 255, 255, 255), " \ + "stop:0.757062 rgba(241, 238, 238, 255), " \ + "stop:1 rgba(247, 245, 245, 255));"); +} + +SimulatedUIWidgetX7::~SimulatedUIWidgetX7() +{ + delete ui; +} + diff --git a/companion/src/simulation/simulateduiwidgetX7.ui b/companion/src/simulation/simulateduiwidgetX7.ui new file mode 100644 index 000000000..573be197b --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetX7.ui @@ -0,0 +1,258 @@ + + + SimulatedUIWidgetX7 + + + + 0 + 0 + 570 + 208 + + + + + 0 + 0 + + + + + 570 + 208 + + + + + 570 + 208 + + + + Taranis X7 Simulator + + + background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.757062 rgba(241, 238, 238, 255), stop:1 rgba(247, 245, 245, 255)); + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 157 + 186 + + + + + 157 + 186 + + + + background:url(:/images/simulator/X7/left.png); + + + + + + + + 0 + 0 + + + + + 256 + 128 + + + + + 424 + 128 + + + + background-color: rgb(215, 243, 255); + + + + + + + + 0 + 0 + + + + + 157 + 186 + + + + + 157 + 186 + + + + background:url(:/images/simulator/X7/right.png) + + + + + + + + 0 + 0 + + + + + 256 + 48 + + + + + 256 + 48 + + + + background:url(:/images/simulator/X7/top.png) + + + + + + + + 0 + 0 + + + + + 256 + 10 + + + + + 256 + 10 + + + + background:url(:/images/simulator/X7/bottom.png) + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + 16777215 + 12 + + + + + 0 + 12 + + + + background-color: rgb(255, 255, 255); + + + + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + 16777215 + 10 + + + + background-color: rgb(247, 245, 245); + + + + + + + + + + + LcdWidget + QWidget +
lcdwidget.h
+ 1 +
+ + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+
+ + +
diff --git a/companion/src/simulation/simulateduiwidgetX9.cpp b/companion/src/simulation/simulateduiwidgetX9.cpp new file mode 100644 index 000000000..bd3204207 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetX9.cpp @@ -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. + */ + +#include "simulateduiwidget.h" +#include "ui_simulateduiwidgetX9.h" + +SimulatedUIWidgetX9::SimulatedUIWidgetX9(SimulatorInterface *simulator, SimulatorDialog * simuDialog, QWidget * parent): + SimulatedUIWidget(simulator, simuDialog, parent), + ui(new Ui::SimulatedUIWidgetX9) +{ + RadioUiAction * act; + QPolygon polygon; + + ui->setupUi(this); + + //getCurrentFirmware()->getCapability(Capability(RotaryEncoders)); // not working for X9E ? + bool rotaryOnly = IS_TARANIS_X9E(m_board); + + // add actions in order of appearance on the help menu + + act = addRadioUiAction(0, QList() << Qt::Key_PageUp, tr("PG-UP"), tr("[ MENU ]")); + polygon.setPoints(6, 20, 59, 27, 50, 45, 52, 56, 59, 50, 71, 26, 72); + ui->leftbuttons->addArea(polygon, "Taranis/x9l1.png", act); + + act = addRadioUiAction(3, QList() << Qt::Key_PageDown, tr("PG-DN"), tr("[ PAGE ]")); + polygon.setPoints(6, 23, 107, 30, 99, 46, 100, 55, 106, 47, 117, 28, 117); + ui->leftbuttons->addArea(polygon, "Taranis/x9l2.png", act); + + act = addRadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr("DEL/BKSP/ESC"), tr("[ EXIT ]")); + polygon.setPoints(6, 24, 154, 32, 144, 46, 146, 57, 156, 46, 167, 29, 166); + ui->leftbuttons->addArea(polygon, "Taranis/x9l3.png", act); + + if (rotaryOnly) { + m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("Rotary Selector"))); + m_scrollUpAction = addRadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Up, tr("-/UP"), tr("Rotary UP")); + m_scrollDnAction = addRadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Down, tr("+/DN"), tr("Rotary DOWN")); + connectScrollActions(); + } + else { + m_scrollUpAction = addRadioUiAction(4, QList() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Up, tr("+/UP"), tr("[ + ]")); + m_scrollDnAction = addRadioUiAction(5, QList() << Qt::Key_Minus << Qt::Key_Down, tr("-/DN"), tr("[ - ]")); + } + + polygon.setPoints(6, 64, 60, 71, 50, 90, 50, 100, 60, 90, 73, 72, 73); + ui->rightbuttons->addArea(polygon, "Taranis/x9r1.png", m_scrollUpAction); + + polygon.setPoints(6, 63, 109, 73, 100, 88, 100, 98, 109, 88, 119, 72, 119); + ui->rightbuttons->addArea(polygon, "Taranis/x9r2.png", m_scrollDnAction); + + act = addRadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, tr("ENTER/MOUSE-MID"), (rotaryOnly ? tr("Selector Press") : tr("[ ENT ]"))); + polygon.setPoints(6, 63, 155, 72, 146, 90, 146, 98, 155, 88, 166, 72, 166); + ui->rightbuttons->addArea(polygon, "Taranis/x9r3.png", act); + + ui->leftbuttons->addArea(90, 177, 118, 197, "Taranis/x9l4.png", m_screenshotAction); + + if (!rotaryOnly) + m_keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("[ + ]/[ - ]"))); + + m_backlightColors << QColor(47, 123, 227); // Taranis Blue + m_backlightColors << QColor(166,247,159); + m_backlightColors << QColor(247,159,166); + m_backlightColors << QColor(255,195,151); + m_backlightColors << QColor(247,242,159); + + setLcd(ui->lcd); +} + +SimulatedUIWidgetX9::~SimulatedUIWidgetX9() +{ + delete ui; +} + diff --git a/companion/src/simulation/simulateduiwidgetX9.ui b/companion/src/simulation/simulateduiwidgetX9.ui new file mode 100644 index 000000000..4c668ddd6 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetX9.ui @@ -0,0 +1,166 @@ + + + SimulatedUIWidgetX9 + + + + 0 + 0 + 664 + 208 + + + + + 0 + 0 + + + + + 664 + 208 + + + + + 664 + 208 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 120 + 208 + + + + true + + + background:url(:/images/simulator/Taranis/x9l0.png); + + + + + + + + 0 + 0 + + + + + 424 + 38 + + + + background:url(:/images/simulator/Taranis/x9t0.png) + + + + + + + + 0 + 0 + + + + + 120 + 208 + + + + background:url(:/images/simulator/Taranis/x9r0.png) + + + + + + + + 0 + 0 + + + + + 424 + 128 + + + + + 424 + 128 + + + + + + + + + 0 + 0 + + + + + 424 + 42 + + + + background:url(:/images/simulator/Taranis/x9b0.png) + + + + + + + + LcdWidget + QWidget +
lcdwidget.h
+ 1 +
+ + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+
+ + +
diff --git a/companion/src/simulation/simulatordialog-9x.ui b/companion/src/simulation/simulatordialog-9x.ui deleted file mode 100644 index 7a365fdf6..000000000 --- a/companion/src/simulation/simulatordialog-9x.ui +++ /dev/null @@ -1,986 +0,0 @@ - - - SimulatorDialog9X - - - - 0 - 0 - 587 - 457 - - - - - 0 - 0 - - - - Companion Simulator - - - - :/icon.png:/icon.png - - - - 5 - - - 5 - - - 5 - - - 5 - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - QFrame::Panel - - - QFrame::Raised - - - 2 - - - - 5 - - - 5 - - - 4 - - - 6 - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - 0 - 0 - - - - - 1 - - - 1 - - - 1 - - - 1 - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - AIL - - - true - - - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - ELE - - - true - - - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - RUD - - - true - - - - - - - - 8 - - - - false - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - THR - - - true - - - - - - - - - - - 0 - 0 - - - - true - - - QFrame::Panel - - - QFrame::Raised - - - 2 - - - - 2 - - - 2 - - - 2 - - - 2 - - - - - - 0 - 0 - - - - BEEP - - - Qt::AlignCenter - - - - - - - - - - - 0 - 0 - - - - - 3 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 2 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 42 - 42 - - - - P1 - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - 0 % - - - Qt::AlignCenter - - - - - - - - - 2 - - - - - - 0 - 0 - - - - - 42 - 42 - - - - P3 - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - 0 % - - - Qt::AlignCenter - - - - - - - - - 2 - - - - - - 0 - 0 - - - - - 42 - 42 - - - - P2 - - - -1024 - - - 1024 - - - 128 - - - false - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - 0 % - - - Qt::AlignCenter - - - - - - - - - - - - - 0 - 0 - - - - - 1 - - - 1 - - - 1 - - - 1 - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - ID2 - - - true - - - true - - - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - ID1 - - - true - - - true - - - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - ID0 - - - true - - - true - - - true - - - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:checked { - background-color: #4CC417; - border-style: inset; - } - - - GEA - - - true - - - false - - - - - - - - 8 - - - - QPushButton { - background-color: #EEEEEE; - border-style: outset; - border-width: 1px; - border-radius: 4px; - border-color: black; - padding: 2px; - } - -QPushButton:pressed { - background-color: #4CC417; - border-style: inset; - } - - - TRN - - - - - - - - rightStickWidget - leftStickWidget - knobsWidget - switchesLeft - switchesRight - beep_frame - - - - - - true - - - - 0 - 0 - - - - 0 - - - - 9x Simulator - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QLayout::SetMinimumSize - - - 0 - - - - - - 0 - 0 - - - - - 256 - 29 - - - - background:url(:/images/simulator/9X/9xdt.png) - - - - - - - - 0 - 0 - - - - - 41 - 186 - - - - background:url(:/images/simulator/9X/9xdl.png) - - - - - - - - 0 - 0 - - - - - 89 - 186 - - - - background:url(:/images/simulator/9X/9xmenu.png) - - - - - - - - 0 - 0 - - - - - 256 - 128 - - - - - - - - - 0 - 0 - - - - - 256 - 29 - - - - background:url(:/images/simulator/9X/9xdb.png) - - - - - - - - 0 - 0 - - - - - 55 - 186 - - - - background:url(:/images/simulator/9X/9xdr.png) - - - - - - - - 0 - 0 - - - - - 128 - 186 - - - - true - - - background:url(:/images/simulator/9X/9xcurs.png); - - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - - - - - LcdWidget - QWidget -
lcdwidget.h
- 1 -
- - ButtonsWidget - QWidget -
buttonswidget.h
- 1 -
- - DialWidget - QDial -
dialwidget.h
-
-
- - - - -
diff --git a/companion/src/simulation/simulatordialog-flamenco.ui b/companion/src/simulation/simulatordialog-flamenco.ui deleted file mode 100644 index 321927744..000000000 --- a/companion/src/simulation/simulatordialog-flamenco.ui +++ /dev/null @@ -1,900 +0,0 @@ - - - SimulatorDialogFlamenco - - - - 0 - 0 - 608 - 546 - - - - - 0 - 0 - - - - Companion Simulator - - - - :/icon.png:/icon.png - - - - 5 - - - 5 - - - 5 - - - 5 - - - 0 - - - 3 - - - - - true - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - 0 - - - - Flamenco Simulator - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - QLayout::SetMinimumSize - - - 0 - - - - - - 0 - 0 - - - - - 120 - 208 - - - - true - - - background:url(:/images/x9l0.png); - - - - - - - - 0 - 0 - - - - - 120 - 208 - - - - background:url(:/images/x9r0.png) - - - - - - - - 0 - 0 - - - - - 320 - 240 - - - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - - - - - 0 - 0 - - - - QFrame::Panel - - - QFrame::Raised - - - 2 - - - - 0 - - - 0 - - - 0 - - - 0 - - - 7 - - - 0 - - - - - - 0 - - - 7 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - - - - 1 - - - 1 - - - 0 - - - 0 - - - Qt::Vertical - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - false - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - - - - 1 - - - 0 - - - 0 - - - Qt::Vertical - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - SF - - - Qt::AlignCenter - - - - - - - LS - - - Qt::AlignCenter - - - - - - - SE - - - Qt::AlignCenter - - - - - - - SA - - - Qt::AlignCenter - - - - - - - SB - - - Qt::AlignCenter - - - - - - - S1 - - - Qt::AlignCenter - - - - - - - S2 - - - Qt::AlignCenter - - - - - - - SC - - - Qt::AlignCenter - - - - - - - SD - - - Qt::AlignCenter - - - - - - - SG - - - Qt::AlignCenter - - - - - - - RS - - - Qt::AlignCenter - - - - - - - SH - - - Qt::AlignCenter - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - - - - LcdWidget - QWidget -
lcdwidget.h
- 1 -
- - ButtonsWidget - QWidget -
buttonswidget.h
- 1 -
-
- - - - -
diff --git a/companion/src/simulation/simulatordialog-horus.ui b/companion/src/simulation/simulatordialog-horus.ui deleted file mode 100644 index 7ada7458a..000000000 --- a/companion/src/simulation/simulatordialog-horus.ui +++ /dev/null @@ -1,1142 +0,0 @@ - - - SimulatorDialogHorus - - - - 0 - 0 - 843 - 636 - - - - - 0 - 0 - - - - Companion Simulator - - - - :/icon.png:/icon.png - - - - 5 - - - 5 - - - 5 - - - 5 - - - 0 - - - 3 - - - - - - 0 - 0 - - - - QFrame::Panel - - - QFrame::Raised - - - 2 - - - - 4 - - - 5 - - - 4 - - - 2 - - - 6 - - - 0 - - - - - - 0 - - - 7 - - - 0 - - - 5 - - - 6 - - - 4 - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 1 - - - 1 - - - 0 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 1 - - - 0 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - SF - - - Qt::AlignCenter - - - - - - - LS - - - Qt::AlignCenter - - - - - - - SE - - - Qt::AlignCenter - - - - - - - SA - - - Qt::AlignCenter - - - - - - - SB - - - Qt::AlignCenter - - - - - - - S1 - - - Qt::AlignCenter - - - - - - - S2 - - - Qt::AlignCenter - - - - - - - SC - - - Qt::AlignCenter - - - - - - - SD - - - Qt::AlignCenter - - - - - - - SG - - - Qt::AlignCenter - - - - - - - RS - - - Qt::AlignCenter - - - - - - - SH - - - Qt::AlignCenter - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - - - - - - 0 - 0 - - - - PF4 - Telemetry Simulator - - - - - - - - 0 - 0 - - - - PF5 - Trainer Simulator - - - - - - - - 0 - 0 - - - - PF6 - Debug Console Window - - - - - - - - 0 - 0 - - - - PF7 - Reload Lua Scripts - - - - - - - - - true - - - - 0 - 0 - - - - 0 - - - - Horus Simulator - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QLayout::SetFixedSize - - - 0 - - - - - - 0 - 0 - - - - - 147 - 292 - - - - - 147 - 292 - - - - true - - - background:url(:/images/simulator/Horus/left.png); - - - - - - - - 0 - 0 - - - - - 480 - 9 - - - - - 480 - 9 - - - - - 5 - - - - background:url(:/images/simulator/Horus/top.png) - - - - - - - - 0 - 0 - - - - - 480 - 272 - - - - - 480 - 272 - - - - - 5 - - - - - - - - - 0 - 0 - - - - - 480 - 11 - - - - - 480 - 11 - - - - - 5 - false - - - - background:url(:/images/simulator/Horus/bottom.png) - - - - - - - - 0 - 0 - - - - - 24 - 292 - - - - - 24 - 292 - - - - background:url(:/images/simulator/Horus/led.png) - - - - - - - - 0 - 0 - - - - - 27 - 292 - - - - - 27 - 292 - - - - background:url(:/images/simulator/Horus/border-right.png) - - - - - - - - 0 - 0 - - - - - 147 - 292 - - - - - 147 - 292 - - - - background:url(:/images/simulator/Horus/right.png) - - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - - - - - LcdWidget - QWidget -
lcdwidget.h
- 1 -
- - ButtonsWidget - QWidget -
buttonswidget.h
- 1 -
- - DialWidget - QDial -
dialwidget.h
-
-
- - - - - - - 5 - - - 5 - - - false - - - false - - - true - - -
diff --git a/companion/src/simulation/simulatordialog-taranis.ui b/companion/src/simulation/simulatordialog-taranis.ui deleted file mode 100644 index e7fe3f205..000000000 --- a/companion/src/simulation/simulatordialog-taranis.ui +++ /dev/null @@ -1,1201 +0,0 @@ - - - SimulatorDialogTaranis - - - - 0 - 0 - 682 - 575 - - - - - 0 - 0 - - - - Companion Simulator - - - - :/icon.png:/icon.png - - - - 5 - - - 5 - - - 5 - - - 5 - - - 0 - - - 3 - - - - - - 0 - 0 - - - - QFrame::Panel - - - QFrame::Raised - - - 2 - - - - 5 - - - 7 - - - 5 - - - 6 - - - 6 - - - 5 - - - - - - 0 - 0 - - - - - 5 - - - 4 - - - - - 5 - - - 4 - - - - - - 0 - 0 - - - - - 0 - 50 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 50 - - - - - 42 - 42 - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 50 - - - - - 42 - 42 - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 0 - 0 - - - - - 0 - 50 - - - - - 42 - 42 - - - - - - - -1024 - - - 1024 - - - 128 - - - 64.000000000000000 - - - true - - - - - - - - 42 - 0 - - - - S1 - - - Qt::AlignCenter - - - - - - - - 42 - 0 - - - - S2 - - - Qt::AlignCenter - - - - - - - - 42 - 0 - - - - S3 - - - Qt::AlignCenter - - - - - - - - 42 - 0 - - - - S4 - - - Qt::AlignCenter - - - - - - - - - Qt::Horizontal - - - - 13 - 47 - - - - - - - - SB - - - Qt::AlignCenter - - - - - - - - 16777215 - 50 - - - - -1024 - - - 1024 - - - Qt::Vertical - - - - - - - SE - - - Qt::AlignCenter - - - - - - - SF - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - 13 - 47 - - - - - - - - SD - - - Qt::AlignCenter - - - - - - - LS - - - Qt::AlignCenter - - - - - - - SG - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - Qt::Horizontal - - - - 13 - 47 - - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - Qt::Horizontal - - - - 13 - 47 - - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - - - - 1 - - - 1 - - - 0 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - - - - 1 - - - 0 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - SC - - - Qt::AlignCenter - - - - - - - RS - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - 13 - 47 - - - - - - - - SH - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 16777215 - 50 - - - - - - - 2 - - - 1 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBothSides - - - 1 - - - - - - - - 16777215 - 50 - - - - -1024 - - - 1024 - - - Qt::Vertical - - - - - - - SA - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - 13 - 47 - - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - - - true - - - - 0 - 0 - - - - 0 - - - - Taranis Simulator - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - QLayout::SetMinimumSize - - - 0 - - - - - - 0 - 0 - - - - - 120 - 208 - - - - true - - - background:url(:/images/simulator/Taranis/x9l0.png); - - - - - - - - 0 - 0 - - - - - 424 - 38 - - - - background:url(:/images/simulator/Taranis/x9t0.png) - - - - - - - - 0 - 0 - - - - - 120 - 208 - - - - background:url(:/images/simulator/Taranis/x9r0.png) - - - - - - - - 0 - 0 - - - - - 424 - 128 - - - - - - - - - 0 - 0 - - - - - 424 - 42 - - - - background:url(:/images/simulator/Taranis/x9b0.png) - - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - 0 - - - - - Qt::Horizontal - - - - 5 - 0 - - - - - - - - - - - - - - - - PF4 - Telemetry Simulator - - - - - - - PF5 - Trainer Simulator - - - - - - - PF6 - Debug Console Output - - - - - - - PF7 - Reload Lua Scripts - - - - - - - - - - LcdWidget - QWidget -
lcdwidget.h
- 1 -
- - ButtonsWidget - QWidget -
buttonswidget.h
- 1 -
- - DialWidget - QDial -
dialwidget.h
-
-
- - - - -
diff --git a/companion/src/simulation/simulatordialog.cpp b/companion/src/simulation/simulatordialog.cpp index 6b8c75c5d..8ef0c4a41 100644 --- a/companion/src/simulation/simulatordialog.cpp +++ b/companion/src/simulation/simulatordialog.cpp @@ -19,14 +19,29 @@ */ #include "simulatordialog.h" +#include "ui_simulatordialog.h" + #include "appdata.h" -#include "lcdwidget.h" -#include -#include "helpers.h" +#include "debugoutput.h" +#include "radiofaderwidget.h" +#include "radioknobwidget.h" +#include "radioswitchwidget.h" +#include "radiouiaction.h" +#include "sdcard.h" +#include "simulateduiwidget.h" #include "simulatorinterface.h" +//#include "storage.h" +#include "telemetrysimu.h" +#include "trainersimu.h" #include "virtualjoystickwidget.h" +#ifdef JOYSTICKS +#include "joystick.h" +#endif + +#include +#include +#include -int SimulatorDialog::screenshotIdx = 0; SimulatorDialog * traceCallbackInstance = 0; void traceCb(const char * text) @@ -37,37 +52,35 @@ void traceCb(const char * text) } } -SimulatorDialog::SimulatorDialog(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): +SimulatorDialog::SimulatorDialog(QWidget * parent, SimulatorInterface *simulator, quint8 flags): QDialog(parent), - flags(flags), - timer(NULL), - lightOn(false), + ui(new Ui::SimulatorDialog), simulator(simulator), + firmware(getCurrentFirmware()), + radioSettings(GeneralSettings()), + timer(NULL), + radioUiWidget(NULL), + vJoyLeft(NULL), + vJoyRight(NULL), + TelemetrySimu(NULL), + TrainerSimu(NULL), + DebugOut(NULL), + m_board(getCurrentBoard()), + flags(flags), radioProfileId(g.id()), lastPhase(-1), - beepVal(0), - TelemetrySimu(0), - TrainerSimu(0), - DebugOut(0), buttonPressed(0), trimPressed(TRIM_NONE), + eepromDataFromFile(false), middleButtonPressed(false) { setWindowFlags(Qt::Window); - new QShortcut(QKeySequence(Qt::Key_F1), this, SLOT(showHelp())); - new QShortcut(QKeySequence(Qt::Key_F4), this, SLOT(openTelemetrySimulator())); - new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(openTrainerSimulator())); - new QShortcut(QKeySequence(Qt::Key_F6), this, SLOT(openDebugOutput())); - new QShortcut(QKeySequence(Qt::Key_F7), this, SLOT(luaReload())); - - keymapHelp.append(keymapHelp_t(tr("F1"), tr("Show Help/Keymap"))); - keymapHelp.append(keymapHelp_t(tr("F4"), tr("Open Telemetry Simulator"))); - keymapHelp.append(keymapHelp_t(tr("F5"), tr("Open Trainer Simulator"))); - keymapHelp.append(keymapHelp_t(tr("F6"), tr("Open Debug Output"))); - keymapHelp.append(keymapHelp_t(tr("F7"), tr("Reload Lua Scripts"))); - + // install simulator TRACE hook traceCallbackInstance = this; + simulator->installTraceHook(traceCb); + + setupUi(); } SimulatorDialog::~SimulatorDialog() @@ -77,54 +90,95 @@ SimulatorDialog::~SimulatorDialog() delete simulator; } -void SimulatorDialog::closeEvent(QCloseEvent *) + +/* + * Public slots/setters + */ + +void SimulatorDialog::setRadioProfileId(int value) { - simulator->stop(); - timer->stop(); - g.profile[radioProfileId].simuWinGeo(saveGeometry()); + radioProfileId = value; + simulator->setVolumeGain(g.profile[radioProfileId].volumeGain()); + setPaths(g.profile[radioProfileId].sdPath(), radioDataPath); } -void SimulatorDialog::showEvent(QShowEvent * event) +void SimulatorDialog::setDataPath(const QString & dataPath) { - static bool firstShow = true; - if (firstShow) { - restoreGeometry(g.profile[radioProfileId].simuWinGeo()); + setPaths(sdCardPath, dataPath); +} - if (flags & SIMULATOR_FLAGS_STICK_MODE_LEFT || ((flags & SIMULATOR_FLAGS_STANDALONE) && (g.profile[radioProfileId].defaultMode() & 1))) { - vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true); - vJoyLeft->setStickY(1); - } - else { - vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true); - vJoyRight->setStickY(1); - } +void SimulatorDialog::setPaths(const QString & sdPath, const QString & dataPath) +{ + sdCardPath = sdPath; + radioDataPath = dataPath; + simulator->setSdPath(sdPath, dataPath); +} - firstShow = false; +void SimulatorDialog::setRadioSettings(const GeneralSettings settings) +{ + radioSettings = settings; +} + +void SimulatorDialog::setEepromData(const QByteArray & eeprom, 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 (QDir(QString(radioDataPath).append("/RADIO")).exists()) { + SdcardFormat sdcard(radioDataPath); + ret = sdcard.load(simuData); + if (!ret) + error = sdcard.error(); + } + } + 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)); + } + } + else if (!eeprom.isEmpty()) { + ret = firmware->getEEpromInterface()->load(simuData, (uint8_t *)eeprom.constData(), getEEpromSize(m_board)); + } + + if (!ret) { + if (error.isEmpty()) + error = tr("Could not load data, possibly wrong format."); + QMessageBox::critical(this, tr("Data Load Error"), error); + return; + } + + radioSettings = simuData.generalSettings; + eepromData = eeprom; + eepromDataFromFile = fromFile; +} + +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); + } + else { + SdcardFormat sdcard(radioDataPath); + sdcard.write(*radioData); + radioSettings = radioData->generalSettings; } } -void SimulatorDialog::mousePressEvent(QMouseEvent *event) +void SimulatorDialog::setUiAreaStyle(const QString & style) { - if (event->button() == Qt::MidButton) - middleButtonPressed = true; - else - event->ignore(); -} - -void SimulatorDialog::mouseReleaseEvent(QMouseEvent *event) -{ - if (event->button() == Qt::MidButton) - middleButtonPressed = false; - else - event->ignore(); -} - -void SimulatorDialog::wheelEvent(QWheelEvent *event) -{ - if (event->angleDelta().isNull()) - return; - QPoint numSteps = event->angleDelta() / 8 / 15 * -1; // one step per 15deg - simulator->wheelEvent(numSteps.y()); + ui->radioUiTab->setStyleSheet(style); } void SimulatorDialog::traceCallback(const char * text) @@ -138,171 +192,39 @@ void SimulatorDialog::traceCallback(const char * text) traceMutex.unlock(); } -void SimulatorDialog::setRadioProfileId(int value) -{ - radioProfileId = value; -} +/* + * Setup + */ -void SimulatorDialog::onTrimPressed(int which) -{ - trimPressed = which; -} - -void SimulatorDialog::onTrimReleased() -{ - trimPressed = TRIM_NONE; -} - -void SimulatorDialog::onTrimSliderMoved(int which, int value) -{ - simulator->setTrim(which, value); -} - -void SimulatorDialog::openTelemetrySimulator() -{ - // allow only one instance - if (TelemetrySimu == 0) { - TelemetrySimu = new TelemetrySimulator(this, simulator); - TelemetrySimu->show(); - } - else if (!TelemetrySimu->isVisible()) { - TelemetrySimu->show(); - } -} - -void SimulatorDialog::openTrainerSimulator() -{ - // allow only one instance - if (TrainerSimu == 0) { - TrainerSimu = new TrainerSimulator(this, simulator); - TrainerSimu->show(); - } - else if (!TrainerSimu->isVisible()) { - TrainerSimu->show(); - } -} - -void SimulatorDialog::openDebugOutput() -{ - // allow only one instance, but install signal handler to catch dialog destruction just in case - if (DebugOut == 0) { - DebugOut = new DebugOutput(this); - QObject::connect(DebugOut, SIGNAL(destroyed()), this, SLOT(onDebugOutputClose())); - DebugOut->traceCallback(traceBuffer); - DebugOut->show(); - } - else if (!DebugOut->isVisible()) { - DebugOut->show(); - } -} - -void SimulatorDialog::luaReload() -{ - // force a reload of the lua environment (as if a standalone script were run) - simulator->setLuaStateReloadPermanentScripts(); -} - -void SimulatorDialog::onDebugOutputClose() -{ - DebugOut = 0; -} - -void SimulatorDialog::showHelp() -{ - QString helpText = tr("Simulator Controls:"); - helpText += ""; - helpText += tr(""); - QString keyTemplate = ""; - foreach (keymapHelp_t pair, keymapHelp) - helpText += keyTemplate.arg(pair.first, pair.second); - helpText += "
Key/MouseAction
%1
%2
"; - - QMessageBox * msgBox = new QMessageBox(this); - msgBox->setAttribute(Qt::WA_DeleteOnClose); - msgBox->setWindowFlags(msgBox->windowFlags() | Qt::WindowStaysOnTopHint); - msgBox->setStandardButtons( QMessageBox::Ok ); - msgBox->setWindowTitle(tr("Simulator Help")); - msgBox->setText(helpText); - msgBox->setModal(false); - msgBox->show(); -} - -void SimulatorDialog::keyPressEvent (QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - buttonPressed = Qt::Key_Enter; - break; - case Qt::Key_Escape: - case Qt::Key_Backspace: - case Qt::Key_Delete: - buttonPressed = Qt::Key_Escape; - break; - case Qt::Key_Plus: - case Qt::Key_Equal: - buttonPressed = Qt::Key_Plus; - break; - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Right: - case Qt::Key_Left: - case Qt::Key_Minus: - case Qt::Key_PageDown: - case Qt::Key_PageUp: - case Qt::Key_X: - case Qt::Key_C: - buttonPressed = event->key(); - break; - default: - event->ignore(); - break; - } -} - -void SimulatorDialog::keyReleaseEvent(QKeyEvent * event) -{ - switch (event->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_Escape: - case Qt::Key_Backspace: - case Qt::Key_Delete: - case Qt::Key_Plus: - case Qt::Key_Equal: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Right: - case Qt::Key_Left: - case Qt::Key_Minus: - case Qt::Key_PageDown: - case Qt::Key_PageUp: - case Qt::Key_X: - case Qt::Key_C: - buttonPressed = 0; - break; - default: - event->ignore(); - break; - } -} - -template -void SimulatorDialog::initUi(T * ui) +void SimulatorDialog::setupUi() { ui->setupUi(this); - windowName = tr("Simulating Radio (%1)").arg(getCurrentFirmware()->getName()); + windowName = tr("Simulating Radio (%1)").arg(firmware->getName()); setWindowTitle(windowName); - lcd = ui->lcd; - lcd->setData(simulator->getLcd(), lcdWidth, lcdHeight, lcdDepth); + switch(m_board) { + case BOARD_TARANIS_X7 : + radioUiWidget = new SimulatedUIWidgetX7(simulator, this); + break; + case BOARD_TARANIS_X9D : + case BOARD_TARANIS_X9DP : + case BOARD_TARANIS_X9E : + radioUiWidget = new SimulatedUIWidgetX9(simulator, this); + break; + case BOARD_HORUS : + radioUiWidget = new SimulatedUIWidgetX12(simulator, this); + break; + default: + radioUiWidget = new SimulatedUIWidget9X(simulator, this); + break; + } - tabWidget = ui->tabWidget; - pots = findWidgets(this, "pot%1"); - potLabels = findWidgets(this, "potLabel%1"); - potValues = findWidgets(this, "potValue%1"); - sliders = findWidgets(this, "slider%1"); + keymapHelp.append(*radioUiWidget->getKeymapHelp()); + + ui->radioUiTab->layout()->addWidget(radioUiWidget); + ui->tabWidget->setTabText(0, firmware->getName()); + ui->tabWidget->setFixedHeight(radioUiWidget->height() + ui->tabWidget->tabBar()->height() - 8); vJoyLeft = new VirtualJoystickWidget(this, 'L'); ui->leftStickLayout->addWidget(vJoyLeft); @@ -310,6 +232,49 @@ void SimulatorDialog::initUi(T * ui) 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; jsensitivities[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))); connect(vJoyLeft, SIGNAL(trimButtonReleased()), this, SLOT(onTrimReleased())); connect(vJoyLeft, SIGNAL(trimSliderMoved(int,int)), this, SLOT(onTrimSliderMoved(int,int))); @@ -318,76 +283,114 @@ void SimulatorDialog::initUi(T * ui) connect(vJoyRight, SIGNAL(trimButtonReleased()), this, SLOT(onTrimReleased())); connect(vJoyRight, SIGNAL(trimSliderMoved(int,int)), this, SLOT(onTrimSliderMoved(int,int))); -#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; jsensitivities[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 + connect(ui->btn_help, SIGNAL(released()), this, SLOT(showHelp())); + 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())); - setupOutputsDisplay(); - setupGVarsDisplay(); - setTrims(); - - if (flags & SIMULATOR_FLAGS_NOTX) - tabWidget->setCurrentIndex(1); + 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())); + if (firmware->getCapability(Capability(SportTelemetry))) + keymapHelp.append(keymapHelp_t(ui->btn_luaReload->shortcut().toString(QKeySequence::NativeText), ui->btn_luaReload->statusTip())); + else + ui->btn_telemSim->hide(); + keymapHelp.append(keymapHelp_t(ui->btn_screenshot->shortcut().toString(QKeySequence::NativeText), ui->btn_screenshot->statusTip())); } -QFrame * SimulatorDialog::createLogicalSwitch(QWidget * parent, int switchNo, QVector & labels) +void SimulatorDialog::setupRadioWidgets() { - QFrame * swtch = new QFrame(parent); - swtch->setAutoFillBackground(true); - swtch->setFrameShape(QFrame::Panel); - swtch->setFrameShadow(QFrame::Raised); - swtch->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - swtch->setMaximumHeight(18); - QVBoxLayout * layout = new QVBoxLayout(swtch); - layout->setContentsMargins(2, 0, 2, 0); - QFont font; - font.setPointSize(8); - QLabel * label = new QLabel(swtch); - label->setFont(font); - label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, switchNo+1).toString()); - label->setAlignment(Qt::AlignCenter); - label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - labels << label; - layout->addWidget(label); - return swtch; + int i, midpos, aIdx; + QString wname; + BoardEnum board = firmware->getBoard(); + + // First clear out any existing widgets. + if (switches.size()) { + foreach (RadioWidget * w, switches) { + ui->radioWidgetsHTLayout->removeWidget(w); + w->deleteLater(); + } + } + if (analogs.size()) { + foreach (RadioWidget * w, analogs) { + if (w->getType() == RadioWidget::RADIO_WIDGET_KNOB) + ui->radioWidgetsHTLayout->removeWidget(w); + else + ui->VCGridLayout->removeWidget(w); + w->deleteLater(); + } + } + + // Now set up new widgets. + + // switches + Firmware::Switch swinfo; + // 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] == GeneralSettings::SWITCH_NONE) + continue; + + if ((wname = QString(radioSettings.switchName[i])).isEmpty()) { + swinfo = firmware->getSwitch(i); + wname = QString(swinfo.name); + } + RadioSwitchWidget * sw = new RadioSwitchWidget(GeneralSettings::SwitchConfig(radioSettings.switchConfig[i]), wname, 0, ui->radioWidgetsHT); + sw->setIndex(i); + ui->radioWidgetsHTLayout->addWidget(sw); + switches.append(sw); + } + + midpos = (int)floorf(switches.size() / 2.0f); + aIdx = 0; + + // pots in middle of switches + for (i = 0; i < firmware->getCapability(Pots) && i < CPN_MAX_POTS; ++i) { + if (!radioSettings.isPotAvailable(i)) + continue; + + if ((wname = QString(radioSettings.potName[i])).isEmpty()) + wname = firmware->getAnalogInputName(4 + aIdx + i); + + RadioKnobWidget * pot = new RadioKnobWidget(GeneralSettings::PotConfig(radioSettings.potConfig[i]), wname, 0, ui->radioWidgetsHT); + pot->setIndex(aIdx + i); + // FIXME : total hack here -- this needs to follow the exception in radio/src/mixer.cpp:evalInputs() + if (i == 0 && IS_TARANIS(board) && !IS_TARANIS_X7(board)) + pot->setInvertValue(true); + ui->radioWidgetsHTLayout->insertWidget(midpos++, pot); + analogs.append(pot); + } + + aIdx += i; + + // faders between sticks + int r = 0, c = 0; + for (i = 0; i < firmware->getCapability(Sliders) && i + aIdx < CPN_MAX_POTS; ++i) { + if (!radioSettings.isSliderAvailable(i)) + continue; + + if ((wname = QString(radioSettings.sliderName[i])).isEmpty()) + wname = firmware->getAnalogInputName(4 + aIdx + i); + + RadioFaderWidget * sl = new RadioFaderWidget(wname, 0, ui->radioWidgetsVC); + sl->setIndex(aIdx + i); + // FIXME : total hack here -- this needs to follow the exception in radio/src/mixer.cpp:evalInputs() + if (i == 0 && IS_TARANIS(board) && !IS_TARANIS_X7(board)) + sl->setInvertValue(true); + /* 2-row option + if (!(i % 2)) { + ++r; + c = 0; + } */ + ui->VCGridLayout->addWidget(sl, r, c++, 1, 1); + analogs.append(sl); + } } void SimulatorDialog::setupOutputsDisplay() @@ -421,19 +424,19 @@ void SimulatorDialog::setupOutputsDisplay() scrollArea->setWidget(channelsWidget); gridLayout->addWidget(scrollArea, 1, 0, 1, 1); - tabWidget->insertTab(1, outputsWidget, QString(tr("Outputs"))); + ui->tabWidget->insertTab(1, outputsWidget, QString(tr("Outputs"))); // populate outputs - int outputs = std::min(32, getCurrentFirmware()->getCapability(Outputs)); + int outputs = std::min(32, firmware->getCapability(Outputs)); int column = 0; for (int i=0; isetText(" " + RawSource(SOURCE_TYPE_CH, i).toString() + " "); label->setAlignment(Qt::AlignCenter); label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); channelsLayout->addWidget(label, 0, column, 1, 1); - QSlider * slider = new QSlider(tabWidget); + QSlider * slider = new QSlider(outputsWidget); slider->setEnabled(false); slider->setMinimum(-1024); slider->setMaximum(1024); @@ -444,7 +447,7 @@ void SimulatorDialog::setupOutputsDisplay() slider->setTickPosition(QSlider::TicksRight); slider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); - QLabel * value = new QLabel(tabWidget); + QLabel * value = new QLabel(outputsWidget); value->setMinimumSize(QSize(value->fontMetrics().size(Qt::TextSingleLine, "-100.0").width(), 0)); value->setAlignment(Qt::AlignCenter); value->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); @@ -457,32 +460,32 @@ void SimulatorDialog::setupOutputsDisplay() } // populate logical switches - int switches = getCurrentFirmware()->getCapability(LogicalSwitches); + int switches = firmware->getCapability(LogicalSwitches); int rows = switches / (switches > 16 ? 4 : 2); for (int i=0; iaddWidget(swtch, i / rows, i % rows, 1, 1); } } void SimulatorDialog::setupGVarsDisplay() { - int fmodes = getCurrentFirmware()->getCapability(FlightModes); - int gvars = getCurrentFirmware()->getCapability(Gvars); + int fmodes = firmware->getCapability(FlightModes); + int gvars = firmware->getCapability(Gvars); if (gvars>0) { // setup GVars tab QWidget * gvarsWidget = new QWidget(); QGridLayout * gvarsLayout = new QGridLayout(gvarsWidget); - tabWidget->addTab(gvarsWidget, QString(tr("GVars"))); + ui->tabWidget->addTab(gvarsWidget, QString(tr("GVars"))); for (int fm=0; fmsetText(QString("FM%1").arg(fm)); label->setAlignment(Qt::AlignCenter); gvarsLayout->addWidget(label, 0, fm+1); } for (int i=0; isetText(QString("GV%1").arg(i+1)); label->setAutoFillBackground(true); if ((i % 2) ==0 ) { @@ -490,7 +493,7 @@ void SimulatorDialog::setupGVarsDisplay() } gvarsLayout->addWidget(label, i+1, 0); for (int fm=0; fmsetAutoFillBackground(true); value->setAlignment(Qt::AlignRight | Qt::AlignVCenter); if ((i % 2) ==0 ) { @@ -504,98 +507,26 @@ void SimulatorDialog::setupGVarsDisplay() } } -void SimulatorDialog::onButtonPressed(int value) +QFrame * SimulatorDialog::createLogicalSwitch(QWidget * parent, int switchNo, QVector & labels) { - if (value == Qt::Key_Print) { - QString fileName = ""; - if (!g.snapToClpbrd()) { - fileName = QString("screenshot-%1.png").arg(++screenshotIdx); - } - lcd->makeScreenshot(fileName); - } - else { - buttonPressed = value; - } -} - -void SimulatorDialog::updateDebugOutput() -{ - traceMutex.lock(); - while (!traceList.isEmpty()) { - QString text = traceList.takeFirst(); - traceBuffer.append(text); - // limit the size of traceBuffer - if (traceBuffer.size() > 10*1024) { - traceBuffer.remove(0, 1*1024); - } - if (DebugOut) { - DebugOut->traceCallback(QString(text)); - } - } - traceMutex.unlock(); -} - -void SimulatorDialog::onTimerEvent() -{ - static unsigned int lcd_counter = 0; - if (!simulator->timer10ms()) { - QMessageBox::critical(this, "Companion", tr("Firmware %1 error: %2").arg(getCurrentFirmware()->getName()).arg(simulator->getError())); - timer->stop(); - return; - } - - getValues(); - - if (tabWidget->currentIndex()==0) { - bool lightEnable; - if (simulator->lcdChanged(lightEnable)) { - lcd->onLcdChanged(lightEnable); - if (lightOn != lightEnable) { - setLightOn(lightEnable); - lightOn = lightEnable; - } - } - } - - // display current flight mode in window title - unsigned int currentPhase = simulator->getPhase(); - if (currentPhase != lastPhase) { - lastPhase = currentPhase; - const char * phase_name = simulator->getPhaseName(currentPhase); - if (phase_name && phase_name[0]) { - setWindowTitle(windowName + QString(" - Flight Mode %1").arg(QString(phase_name))); - } - else { - setWindowTitle(windowName + QString(" - Flight Mode %1").arg(simulator->getPhase())); - } - } - - if (!(lcd_counter++ % 5)) { - - setValues(); - - setTrims(); - - centerSticks(); - - updateBeepButton(); - - if (beepVal) { - beepVal = 0; - QApplication::beep(); - } - - } - - updateDebugOutput(); -} - -void SimulatorDialog::startCommon() -{ - lastPhase = -1; - numGvars = getCurrentFirmware()->getCapability(Gvars); - numFlightModes = getCurrentFirmware()->getCapability(FlightModes); - simulator->setVolumeGain(g.profile[radioProfileId].volumeGain()); + QFrame * swtch = new QFrame(parent); + swtch->setAutoFillBackground(true); + swtch->setFrameShape(QFrame::Panel); + swtch->setFrameShadow(QFrame::Raised); + swtch->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + swtch->setMaximumHeight(18); + QVBoxLayout * layout = new QVBoxLayout(swtch); + layout->setContentsMargins(2, 0, 2, 0); + QFont font; + font.setPointSize(8); + QLabel * label = new QLabel(swtch); + label->setFont(font); + label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, switchNo+1).toString()); + label->setAlignment(Qt::AlignCenter); + label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + labels << label; + layout->addWidget(label); + return swtch; } void SimulatorDialog::setupTimer() @@ -605,31 +536,116 @@ void SimulatorDialog::setupTimer() timer->start(10); } -void SimulatorDialog::start(QByteArray & eeprom) +/* + * Startup + */ + +void SimulatorDialog::start() { - startCommon(); - simulator->start(eeprom, (flags & SIMULATOR_FLAGS_NOTX) ? false : true); - getValues(); + setupRadioWidgets(); + setupOutputsDisplay(); + setupGVarsDisplay(); + setTrims(); + + 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); + setupTimer(); + eepromData.clear(); // this is safe because simulator->start() makes copy of data/discards the file name } -void SimulatorDialog::start(const char * filename) +/* + * Input/Output handlers for SimulatorInterface + */ + +// Read various values from firmware simulator and populate values in this UI +void SimulatorDialog::setValues() { - startCommon(); - simulator->start(filename); - getValues(); - setupTimer(); + static const int numGvars = firmware->getCapability(Gvars); + static const int numFlightModes = firmware->getCapability(FlightModes); + static QString phase_name; + static TxOutputs prevOutputs; + static int prevPhase = -1; + int currentPhase; + + TxOutputs outputs; + simulator->getValues(outputs); + + for (int i = 0; i < channelSliders.size() && i < CPN_MAX_CHNOUT; i++) { + channelSliders[i]->setValue(qMin(1024, qMax(-1024, outputs.chans[i]))); + channelValues[i]->setText(QString("%1").arg((qreal)outputs.chans[i]*100/1024, 0, 'f', 1)); + } + + for (int i = 0; i < logicalSwitchLabels.size() && i < CPN_MAX_CSW; i++) { + if (prevOutputs.vsw[i] != outputs.vsw[i]) { + // setStyleSheet() is very CPU time consuming, doing it only on the actual + // switch state change brings down CPU usage time (for Taranis simulation) from 40% to 7% (Linux, one core usage) + logicalSwitchLabels[i]->setStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF); + } + } + + for (int gv = 0; gv < numGvars; gv++) { + for (int fm = 0; fm < numFlightModes; fm++) { + if (prevPhase != lastPhase || prevOutputs.gvars[fm][gv] != outputs.gvars[fm][gv]) { + // same trick for GVARS, but this has far less effect on CPU usage as setStyleSheet() + gvarValues[gv*numFlightModes+fm]->setText(QString((fm == lastPhase) ? "%1" : "%1").arg(outputs.gvars[fm][gv])); + } + } + } + + // display current flight mode in window title + currentPhase = simulator->getPhase(); + if (currentPhase != lastPhase) { + lastPhase = currentPhase; + phase_name = QString(simulator->getPhaseName(currentPhase)); + if (phase_name.isEmpty()) + phase_name = QString::number(currentPhase); + setWindowTitle(windowName + QString(" - Flight Mode %1").arg(phase_name)); + } + + prevOutputs = outputs; + prevPhase = lastPhase; } -void SimulatorDialog::centerSticks() +// "get" values from this UI and send them to the firmware simulator. +void SimulatorDialog::getValues() { - if (vJoyLeft) - vJoyLeft->centerStick(); + static const int numTrims = firmware->getCapability(NumTrimSwitches); + int i; - if (vJoyRight) - vJoyRight->centerStick(); + TxInputs inp; + memset(&inp, 0, sizeof(TxInputs)); + + inp.sticks[0] = int(1024 * vJoyLeft->getStickX()); // LEFT HORZ + inp.sticks[1] = int(-1024 * vJoyLeft->getStickY()); // LEFT VERT + inp.sticks[2] = int(-1024 * vJoyRight->getStickY()); // RGHT VERT + inp.sticks[3] = int(1024 * vJoyRight->getStickX()); // RGHT HORZ + + for (i = 0; i < analogs.size() && i < CPN_MAX_POTS; ++i) + inp.pots[analogs[i]->getIndex()] = analogs[i]->getValue(); + + for (i = 0; i < switches.size() && i < CPN_MAX_SWITCHES; ++i) + inp.switches[switches[i]->getIndex()] = switches[i]->getValue(); + + for (i = 0; i < numTrims; ++i) + inp.trims[i] = (trimPressed == i); + + foreach (RadioUiAction * act, radioUiWidget->getActions()) { + if (act->getIndex() > -1 && act->getIndex() < CPN_MAX_KEYS) + inp.keys[act->getIndex()] = act->isActive(); + } + + if (radioUiWidget->getRotEncAction()) + inp.rotenc = radioUiWidget->getRotEncAction()->isActive(); + + simulator->setValues(inp); } +// Read stick trim values from firmware simulator and set joystick widgets as needed. void SimulatorDialog::setTrims() { typedef VirtualJoystickWidget VJW; @@ -660,56 +676,187 @@ void SimulatorDialog::setTrims() lastTrims = trims; } -inline int chVal(int val) +/* + * Event handlers/private slots + */ + +void SimulatorDialog::closeEvent(QCloseEvent *) { - return qMin(1024, qMax(-1024, val)); + simulator->stop(); + timer->stop(); + g.profile[radioProfileId].simuWinGeo(saveGeometry()); } -void SimulatorDialog::setValues() +void SimulatorDialog::showEvent(QShowEvent *) { - static const int numOutputs = getCurrentFirmware()->getCapability(Outputs); - static const int numLogicalSwitches = getCurrentFirmware()->getCapability(LogicalSwitches); - static TxOutputs prevOutputs; - static unsigned int prevPhase = -1; + static bool firstShow = true; + if (firstShow) { + restoreGeometry(g.profile[radioProfileId].simuWinGeo()); - TxOutputs outputs; - simulator->getValues(outputs); - Trims trims; - simulator->getTrims(trims); + // 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) { + vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true); + vJoyLeft->setStickY(1); + } + else { + vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true); + vJoyRight->setStickY(1); + } - for (int i=0; isetValue(chVal(outputs.chans[i])); - channelValues[i]->setText(QString("%1").arg((qreal)outputs.chans[i]*100/1024, 0, 'f', 1)); + firstShow = false; + } +} + +void SimulatorDialog::mousePressEvent(QMouseEvent *event) +{ + if (radioUiWidget) + radioUiWidget->mousePressEvent(event); +} + +void SimulatorDialog::mouseReleaseEvent(QMouseEvent *event) +{ + if (radioUiWidget) + radioUiWidget->mouseReleaseEvent(event); +} + +void SimulatorDialog::wheelEvent(QWheelEvent *event) +{ + if (radioUiWidget) + radioUiWidget->wheelEvent(event); +} + +void SimulatorDialog::onTimerEvent() +{ + static unsigned int lcd_counter = 0; + + if (!simulator->timer10ms()) { + QMessageBox::critical(this, "Companion", tr("Firmware %1 error: %2").arg(firmware->getName()).arg(simulator->getError())); + timer->stop(); + return; + } + + getValues(); + + if (!(lcd_counter++ % 5)) { + setValues(); + setTrims(); + centerSticks(); + } + radioUiWidget->timedUpdate(lcd_counter); + updateDebugOutput(); +} + +void SimulatorDialog::onTrimPressed(int which) +{ + trimPressed = which; +} + +void SimulatorDialog::onTrimReleased() +{ + trimPressed = TRIM_NONE; +} + +void SimulatorDialog::onTrimSliderMoved(int which, int value) +{ + simulator->setTrim(which, value); +} + +void SimulatorDialog::centerSticks() +{ + if (vJoyLeft) + vJoyLeft->centerStick(); + + if (vJoyRight) + vJoyRight->centerStick(); +} + +void SimulatorDialog::openTelemetrySimulator() +{ + // allow only one instance + if (TelemetrySimu == 0) { + TelemetrySimu = new TelemetrySimulator(this, simulator); + TelemetrySimu->show(); + connect(TelemetrySimu, &TelemetrySimulator::destroyed, [this](QObject *) { + this->TelemetrySimu = NULL; + }); + } + else if (!TelemetrySimu->isVisible()) { + TelemetrySimu->show(); + } +} + +void SimulatorDialog::openTrainerSimulator() +{ + // allow only one instance + if (TrainerSimu == 0) { + TrainerSimu = new TrainerSimulator(this, simulator); + TrainerSimu->show(); + connect(TrainerSimu, &TrainerSimulator::destroyed, [this](QObject *) { + this->TrainerSimu = NULL; + }); + } + else if (!TrainerSimu->isVisible()) { + TrainerSimu->show(); + } +} + +void SimulatorDialog::openDebugOutput() +{ + // allow only one instance, but install signal handler to catch dialog destruction just in case + if (!DebugOut) { + DebugOut = new DebugOutput(this); + DebugOut->traceCallback(traceBuffer); + DebugOut->show(); + connect(DebugOut, &DebugOutput::destroyed, [this](QObject *) { + this->DebugOut = NULL; + }); + } + else if (!DebugOut->isVisible()) { + DebugOut->show(); + } +} + +void SimulatorDialog::updateDebugOutput() +{ + traceMutex.lock(); + while (!traceList.isEmpty()) { + QString text = traceList.takeFirst(); + traceBuffer.append(text); + // limit the size of traceBuffer + if (traceBuffer.size() > 10*1024) { + traceBuffer.remove(0, 1*1024); + } + if (DebugOut) { + DebugOut->traceCallback(QString(text)); } } + traceMutex.unlock(); +} - QString CSWITCH_ON = "QLabel { background-color: #4CC417 }"; - QString CSWITCH_OFF = "QLabel { }"; +void SimulatorDialog::luaReload() +{ + // force a reload of the lua environment + simulator->setLuaStateReloadPermanentScripts(); +} - for (int i=0; isetStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF); - } - } +void SimulatorDialog::showHelp() +{ + QString helpText = tr("Simulator Controls:"); + helpText += ""; + helpText += tr(""); + QString keyTemplate = ""; + foreach (keymapHelp_t pair, keymapHelp) + helpText += keyTemplate.arg(pair.first, pair.second); + helpText += "
Key/MouseAction
%1
%2
"; - for (unsigned int gv=0; gvsetText(QString((fm==lastPhase)?"%1":"%1").arg(outputs.gvars[fm][gv])); - } - } - } - - if (outputs.beep) { - beepVal = outputs.beep; - } - - prevOutputs = outputs; - prevPhase = lastPhase; + QMessageBox * msgBox = new QMessageBox(this); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setWindowFlags(msgBox->windowFlags() | Qt::WindowStaysOnTopHint); + msgBox->setStandardButtons( QMessageBox::Ok ); + msgBox->setWindowTitle(tr("Simulator Help")); + msgBox->setText(helpText); + msgBox->setModal(false); + msgBox->show(); } #ifdef JOYSTICKS @@ -734,24 +881,19 @@ void SimulatorDialog::onjoystickAxisValueChanged(int axis, int value) } if (stick==1 ) { vJoyRight->setStickY(-stickval/1024.0); - } + } else if (stick==2) { vJoyRight->setStickX(stickval/1024.0); - } + } else if (stick==3) { vJoyLeft->setStickY(-stickval/1024.0); - } + } else if (stick==4) { vJoyLeft->setStickX(stickval/1024.0); } - else if (stick >= 5 && stick < 5+pots.count()) { - pots[stick-5]->setValue(stickval); + else if (stick >= 5 && stick < 5 + analogs.count()) { + analogs[stick-5]->setValue(stickval); } } } #endif - -#include "simulatordialog9x.cpp" -#include "simulatordialogtaranis.cpp" -#include "simulatordialogflamenco.cpp" -#include "simulatordialoghorus.cpp" diff --git a/companion/src/simulation/simulatordialog.h b/companion/src/simulation/simulatordialog.h index b0409c585..3c9ff35f1 100644 --- a/companion/src/simulation/simulatordialog.h +++ b/companion/src/simulation/simulatordialog.h @@ -21,248 +21,148 @@ #ifndef _SIMULATORDIALOG_H_ #define _SIMULATORDIALOG_H_ -#include "modeledit/node.h" -#include "telemetrysimu.h" -#include "trainersimu.h" -#include "debugoutput.h" +#include "constants.h" +#include "helpers.h" +#include "radiodata.h" -#ifdef JOYSTICKS -#include "joystick.h" -#endif +#include +#include +#include -#define TMR_OFF 0 -#define TMR_RUNNING 1 -#define TMR_BEEPING 2 -#define TMR_STOPPED 3 +#define SIMULATOR_FLAGS_NOTX 0x01 // simulating a single model from Companion +#define SIMULATOR_FLAGS_STANDALONE 0x02 // started from stanalone simulator #define FLASH_DURATION 10 -namespace Ui { - class SimulatorDialog9X; - class SimulatorDialogTaranis; - class SimulatorDialogFlamenco; - class SimulatorDialogHorus; -} +#define CSWITCH_ON "QLabel { background-color: #4CC417 }" +#define CSWITCH_OFF "QLabel { }" +#define CBEEP_ON "QLabel { background-color: #FF364E }" +#define CBEEP_OFF "QLabel { }" -// TODO rename + move? -class LcdWidget; -class SliderWidget; -class VirtualJoystickWidget; - -#define SIMULATOR_FLAGS_NOTX 1 -#define SIMULATOR_FLAGS_STICK_MODE_LEFT 2 -#define SIMULATOR_FLAGS_S1 4 -#define SIMULATOR_FLAGS_S2 8 -#define SIMULATOR_FLAGS_S3 16 -#define SIMULATOR_FLAGS_S4 32 // reserved for the future -#define SIMULATOR_FLAGS_S1_MULTI 64 -#define SIMULATOR_FLAGS_S2_MULTI 128 -#define SIMULATOR_FLAGS_S3_MULTI 256 -#define SIMULATOR_FLAGS_S4_MULTI 512 // reserved for the future -#define SIMULATOR_FLAGS_STANDALONE 1024 // started from stanalone simulator +typedef QPair keymapHelp_t; void traceCb(const char * text); +class Firmware; +class SimulatorInterface; +class SimulatedUIWidget; +class TelemetrySimulator; +class TrainerSimulator; +class DebugOutput; +class RadioWidget; +class RadioSwitchWidget; +class VirtualJoystickWidget; +#ifdef JOYSTICKS +class Joystick; +#endif + +class QWidget; +class QSlider; +class QDial; +class QLabel; +class QFrame; + +namespace Ui { + class SimulatorDialog; +} + class SimulatorDialog : public QDialog { Q_OBJECT public: - explicit SimulatorDialog(QWidget * parent, SimulatorInterface *simulator, unsigned int flags=0); + explicit SimulatorDialog(QWidget * parent, SimulatorInterface *simulator, quint8 flags=0); virtual ~SimulatorDialog(); - void start(const char * filename); - void start(QByteArray & eeprom); void setRadioProfileId(int value); - virtual void traceCallback(const char * text); + 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 setRadioData(RadioData * radioData); + void setUiAreaStyle(const QString & style); + void traceCallback(const char * text); + void start(); - protected: - typedef QPair keymapHelp_t; - template void initUi(T * ui); - virtual void setLightOn(bool enable) { } - virtual void updateBeepButton() { } + private: + void setupUi(); + void setupRadioWidgets(); + void setupOutputsDisplay(); + void setupGVarsDisplay(); + QFrame * createLogicalSwitch(QWidget * parent, int switchNo, QVector & labels); + void setupTimer(); - unsigned int flags; - LcdWidget * lcd; - QVector pots; - QVector potLabels; - QVector potValues; - QVector sliders; - QTabWidget * tabWidget; - QVector logicalSwitchLabels; - QVector channelSliders; - QVector channelValues; - QVector gvarValues; + void setValues(); + void getValues(); + void setTrims(); - void init(); - VirtualJoystickWidget *vJoyLeft; - VirtualJoystickWidget *vJoyRight; - QTimer *timer; + + Ui::SimulatorDialog * ui; + SimulatorInterface * simulator; + Firmware * firmware; + GeneralSettings radioSettings; + + QTimer * timer; QString windowName; + QString traceBuffer; + QMutex traceMutex; + QList traceList; QVector keymapHelp; - unsigned int backLight; - bool lightOn; - int switches; - unsigned int numGvars; - unsigned int numFlightModes; + + SimulatedUIWidget * radioUiWidget; + VirtualJoystickWidget * vJoyLeft; + VirtualJoystickWidget * vJoyRight; + TelemetrySimulator * TelemetrySimu; + TrainerSimulator * TrainerSimu; + DebugOutput * DebugOut; + + QVector switches; + QVector analogs; + QVector logicalSwitchLabels; + QVector channelSliders; + QVector channelValues; + QVector gvarValues; + + QString sdCardPath; + QString radioDataPath; + QByteArray eepromData; + BoardEnum m_board; + quint8 flags; + int radioProfileId; + int lastPhase; + int buttonPressed; + int trimPressed; + bool eepromDataFromFile; + bool middleButtonPressed; + #ifdef JOYSTICKS Joystick *joystick; int jscal[8][4]; int jsmap[8]; #endif - SimulatorInterface *simulator; - int radioProfileId; - unsigned int lastPhase; - - QFrame * createLogicalSwitch(QWidget * parent, int switchNo, QVector & labels); - void setupOutputsDisplay(); - void setupGVarsDisplay(); - - void startCommon(); - void setupTimer(); - - void centerSticks(); - void setTrims(); - void setValues(); - virtual void getValues() = 0; - int getValue(qint8 i); - bool getSwitch(int swtch, bool nc, qint8 level=0); - - int beepVal; - - int lcdWidth; - int lcdHeight; - int lcdDepth; - TelemetrySimulator * TelemetrySimu; - TrainerSimulator * TrainerSimu; - DebugOutput * DebugOut; - - QString traceBuffer; - QMutex traceMutex; - QList traceList; - void updateDebugOutput(); - - virtual void closeEvent(QCloseEvent *); - virtual void showEvent(QShowEvent *event); - virtual void mousePressEvent(QMouseEvent *); - virtual void mouseReleaseEvent(QMouseEvent *); - virtual void wheelEvent(QWheelEvent *); - virtual void keyPressEvent(QKeyEvent *); - virtual void keyReleaseEvent(QKeyEvent *); - static int screenshotIdx; - int buttonPressed; - int trimPressed; - bool middleButtonPressed; - private slots: - void onButtonPressed(int value); + virtual void closeEvent(QCloseEvent *); + virtual void showEvent(QShowEvent *); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void wheelEvent(QWheelEvent *event); + void onTimerEvent(); void onTrimPressed(int which); void onTrimReleased(); void onTrimSliderMoved(int which, int value); + void centerSticks(); void openTelemetrySimulator(); void openTrainerSimulator(); void openDebugOutput(); - void onDebugOutputClose(); + void updateDebugOutput(); void luaReload(); void showHelp(); - #ifdef JOYSTICKS void onjoystickAxisValueChanged(int axis, int value); #endif - -}; -class SimulatorDialog9X: public SimulatorDialog -{ - Q_OBJECT - - public: - explicit SimulatorDialog9X(QWidget * parent, SimulatorInterface *simulator, unsigned int flags=0); - virtual ~SimulatorDialog9X(); - - protected: - virtual void getValues(); - virtual void setLightOn(bool enable); - virtual void updateBeepButton(); - void saveSwitches(void); - void restoreSwitches(void); - - protected slots: - void dialChanged(int index); - - private: - Ui::SimulatorDialog9X * ui; - static uint32_t switchstatus; - int beepShow; - -}; - -class SimulatorDialogTaranis: public SimulatorDialog -{ - Q_OBJECT - - public: - explicit SimulatorDialogTaranis(QWidget * parent, SimulatorInterface *simulator, unsigned int flags=0); - virtual ~SimulatorDialogTaranis(); - - protected: - virtual void getValues(); - void saveSwitches(void); - void restoreSwitches(void); - - private: - Ui::SimulatorDialogTaranis * ui; - static uint32_t switchstatus; - - private slots: - void resetSH(); - void on_switchH_sliderReleased(); -}; - -class SimulatorDialogFlamenco: public SimulatorDialog -{ - Q_OBJECT - - public: - explicit SimulatorDialogFlamenco(QWidget * parent, SimulatorInterface *simulator, unsigned int flags=0); - virtual ~SimulatorDialogFlamenco(); - - protected: - virtual void getValues(); - void saveSwitches(void); - void restoreSwitches(void); - - private: - Ui::SimulatorDialogFlamenco * ui; - static uint32_t switchstatus; - - private slots: - void resetSH(); - void on_switchH_sliderReleased(); -}; - -class SimulatorDialogHorus: public SimulatorDialog -{ - Q_OBJECT - - public: - explicit SimulatorDialogHorus(QWidget * parent, SimulatorInterface *simulator, unsigned int flags=0); - virtual ~SimulatorDialogHorus(); - - protected: - virtual void getValues(); - void saveSwitches(void); - void restoreSwitches(void); - - private: - Ui::SimulatorDialogHorus * ui; - static uint32_t switchstatus; - - private slots: - void resetSH(); - void on_switchH_sliderReleased(); }; #endif // _SIMULATORDIALOG_H_ diff --git a/companion/src/simulation/simulatordialog.ui b/companion/src/simulation/simulatordialog.ui new file mode 100644 index 000000000..bef8295b1 --- /dev/null +++ b/companion/src/simulation/simulatordialog.ui @@ -0,0 +1,407 @@ + + + SimulatorDialog + + + + 0 + 0 + 686 + 557 + + + + + 0 + 0 + + + + Companion Simulator + + + + :/icon.png:/icon.png + + + true + + + + 5 + + + 5 + + + 5 + + + 5 + + + 0 + + + 3 + + + + + + 0 + 0 + + + + QFrame::Panel + + + QFrame::Raised + + + 2 + + + + 5 + + + 7 + + + 5 + + + 6 + + + 6 + + + 5 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 16 + + + 9 + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 0 + 20 + + + + + + + + + + + + 0 + 0 + + + + + 11 + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + + + + 3 + + + + + Show Help/Keymap (F1) + + + Show Help/Keymap + + + Keymap + + + F1 + + + + + + + Open Telemetry Simulator window (F4) + + + Telemetry Simulator + + + Telemetry Simulator + + + F4 + + + + + + + Open Trainer Simulator window (F5) + + + Trainer Simulator + + + Trainer Simulator + + + F5 + + + + + + + Open Debug Console window (F6) + + + Debug Console + + + Debug Console + + + F6 + + + + + + + Reload Lua Scripts (F7) + + + Reload Lua Scripts + + + Reload Lua Scripts + + + F7 + + + + + + + Save a screenshot of the radio LCD screen (F8) + + + LCD Screenshot + + + LCD Screenshot + + + F8 + + + + + + + + + true + + + + 0 + 0 + + + + + 0 + 200 + + + + QTabWidget::pane, +QStackedWidget { + padding: 0px; + margin: 0px; +} +QTabWidget::tab-bar{ + margin-bottom: 0px; + padding-bottom: 0px; +} + + + 0 + + + false + + + + background-color: qlineargradient(spread:reflect, x1:0.22, y1:0, x2:0.55065, y2:0.54, stop:0 rgba(7, 7, 7, 250), stop:0.864407 rgba(66, 66, 66, 255)); +margin: 0; +padding: 0; + + + Radio Simulator + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + diff --git a/companion/src/simulation/simulatordialog9x.cpp b/companion/src/simulation/simulatordialog9x.cpp deleted file mode 100644 index bf4753dff..000000000 --- a/companion/src/simulation/simulatordialog9x.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "simulatordialog.h" -#include "ui_simulatordialog-9x.h" -#include "helpers.h" - - -uint32_t SimulatorDialog9X::switchstatus = 0; - -SimulatorDialog9X::SimulatorDialog9X(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): - SimulatorDialog(parent, simulator, flags), - ui(new Ui::SimulatorDialog9X), - beepShow(0) -{ - QPolygon polygon; - - lcdWidth = 128; - lcdHeight = 64; - lcdDepth = 1; - - initUi(ui); - - polygon.setPoints(6, 68, 83, 28, 45, 51, 32, 83, 32, 105, 45, 68, 83); - ui->leftbuttons->addArea(polygon, Qt::Key_Up, "9X/9xcursup.png"); - polygon.setPoints(6, 74, 90, 114, 51, 127, 80, 127, 106, 114, 130, 74, 90); - ui->leftbuttons->addArea(polygon, Qt::Key_Right, "9X/9xcursmin.png"); - polygon.setPoints(6, 68, 98, 28, 137, 51, 151, 83, 151, 105, 137, 68, 98); - ui->leftbuttons->addArea(polygon, Qt::Key_Down, "9X/9xcursdown.png"); - polygon.setPoints(6, 80, 90, 20, 51, 7, 80, 7, 106, 20, 130, 80, 90); - ui->leftbuttons->addArea(polygon, Qt::Key_Left, "9X/9xcursplus.png"); - ui->leftbuttons->addArea(5, 148, 39, 182, Qt::Key_Print, "9X/9xcursphoto.png"); - - ui->rightbuttons->addArea(25, 60, 71, 81, Qt::Key_Enter, "9X/9xmenumenu.png"); - ui->rightbuttons->addArea(25, 117, 71, 139, Qt::Key_Escape, "9X/9xmenuexit.png"); - - // install simulator TRACE hook - simulator->installTraceHook(traceCb); - - backLight = g.backLight(); - if (backLight > 4) backLight = 0; - switch (backLight) { - case 1: - ui->lcd->setBackgroundColor(166,247,159); - break; - case 2: - ui->lcd->setBackgroundColor(247,159,166); - break; - case 3: - ui->lcd->setBackgroundColor(255,195,151); - break; - case 4: - ui->lcd->setBackgroundColor(247,242,159); - break; - default: - ui->lcd->setBackgroundColor(159,165,247); - break; - } - - //restore switches - if (g.simuSW()) - restoreSwitches(); - - keymapHelp.append(keymapHelp_t(tr("UP/PG-UP"), tr("[ UP ]"))); - keymapHelp.append(keymapHelp_t(tr("DN/PG-DN"), tr("[ DN ]"))); - keymapHelp.append(keymapHelp_t(tr("LEFT/+"), tr("[ + ]"))); - keymapHelp.append(keymapHelp_t(tr("RIGHT/-"), tr("[ - ]"))); - keymapHelp.append(keymapHelp_t(tr("ENTER/MOUSE-MID"), tr("[ MENU ]"))); - keymapHelp.append(keymapHelp_t(tr("DEL/BKSP/ESC"), tr("[ EXIT ]"))); - keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("[ UP ]/[ DN ] or Rotary Sel."))); - - for (int i=0; isetProperty("index", i); - connect(pots[i], SIGNAL(valueChanged(int)), this, SLOT(dialChanged(int))); - } - connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); -} - -SimulatorDialog9X::~SimulatorDialog9X() -{ - saveSwitches(); - delete ui; -} - -void SimulatorDialog9X::dialChanged(int value) -{ - int index = sender()->property("index").toInt(); - potValues[index]->setText(QString("%1 %").arg((value*100)/1024)); -} - -void SimulatorDialog9X::setLightOn(bool enable) -{ - QString bg = ""; - if (enable) { - QStringList list; - list << "bl" << "gr" << "rd" << "or" << "yl"; - bg = QString("-") + list[backLight]; - } - ui->top->setStyleSheet(QString("background:url(:/images/simulator/9X/9xdt%1.png);").arg(bg)); - ui->bottom->setStyleSheet(QString("background:url(:/images/simulator/9X/9xdb%1.png);").arg(bg)); - ui->left->setStyleSheet(QString("background:url(:/images/simulator/9X/9xdl%1.png);").arg(bg)); - ui->right->setStyleSheet(QString("background:url(:/images/simulator/9X/9xdr%1.png);").arg(bg)); -} - -void SimulatorDialog9X::updateBeepButton() -{ - #define CBEEP_ON "QLabel { background-color: #FF364E }" - #define CBEEP_OFF "QLabel { }" - - if (beepVal) { - beepShow = 20; - } - - ui->label_beep->setStyleSheet(beepShow ? CBEEP_ON : CBEEP_OFF); - - if (beepShow) { - beepShow--; - } -} - - -void SimulatorDialog9X::getValues() -{ - TxInputs inputs = { - { - int(1024 * vJoyLeft->getStickX()), // LEFT HORZ - int(-1024 * vJoyLeft->getStickY()), // LEFT VERT - int(-1024 * vJoyRight->getStickY()), // RGHT VERT - int(1024 * vJoyRight->getStickX()) // RGHT HORZ - }, - - { - pots[0]->value(), - pots[1]->value(), - pots[2]->value() - }, - - { - ui->switchTHR->isChecked(), - ui->switchRUD->isChecked(), - ui->switchELE->isChecked(), - ui->switchID2->isChecked() ? 1 : (ui->switchID1->isChecked() ? 0 : -1), - ui->switchAIL->isChecked(), - ui->switchGEA->isChecked(), - ui->switchTRN->isDown(), - 0, 0, 0 - }, - - { - buttonPressed == Qt::Key_Enter || middleButtonPressed, - buttonPressed == Qt::Key_Escape, - buttonPressed == Qt::Key_Down || buttonPressed == Qt::Key_PageDown, - buttonPressed == Qt::Key_Up || buttonPressed == Qt::Key_PageUp, - buttonPressed == Qt::Key_Right || buttonPressed == Qt::Key_Plus, - buttonPressed == Qt::Key_Left || buttonPressed == Qt::Key_Minus, - }, - - middleButtonPressed, - - { - trimPressed == TRIM_LH_L, - trimPressed == TRIM_LH_R, - trimPressed == TRIM_LV_DN, - trimPressed == TRIM_LV_UP, - trimPressed == TRIM_RV_DN, - trimPressed == TRIM_RV_UP, - trimPressed == TRIM_RH_L, - trimPressed == TRIM_RH_R - } - }; - - simulator->setValues(inputs); -} - -void SimulatorDialog9X::saveSwitches(void) -{ - // qDebug() << "SimulatorDialog9X::saveSwitches()"; - switchstatus=ui->switchTHR->isChecked(); - switchstatus<<=1; - switchstatus+=(ui->switchRUD->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchID2->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchID1->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchID0->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchGEA->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchELE->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchAIL->isChecked()&0x1); -} - -void SimulatorDialog9X::restoreSwitches(void) -{ - // qDebug() << "SimulatorDialog9X::restoreSwitches()"; - ui->switchAIL->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchELE->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchGEA->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchID0->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchID1->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchID2->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchRUD->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchTHR->setChecked(switchstatus & 0x1); -} - diff --git a/companion/src/simulation/simulatordialogflamenco.cpp b/companion/src/simulation/simulatordialogflamenco.cpp deleted file mode 100644 index 58d23b8b2..000000000 --- a/companion/src/simulation/simulatordialogflamenco.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "simulatordialog.h" -#include "ui_simulatordialog-flamenco.h" -#include "helpers.h" - -uint32_t SimulatorDialogFlamenco::switchstatus = 0; - -SimulatorDialogFlamenco::SimulatorDialogFlamenco(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): - SimulatorDialog(parent, simulator, flags), - ui(new Ui::SimulatorDialogFlamenco) -{ - lcdWidth = 320; - lcdHeight = 240; - lcdDepth = 12; - - initUi(ui); - - // install simulator TRACE hook - simulator->installTraceHook(traceCb); - - // TODO dialP_4 = ui->dialP_4; - - ui->lcd->setBackgroundColor(47, 123, 227); - - //restore switches - if (g.simuSW()) - restoreSwitches(); - - connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); -} - -SimulatorDialogFlamenco::~SimulatorDialogFlamenco() -{ - saveSwitches(); - delete ui; -} - -void SimulatorDialogFlamenco::resetSH() -{ - ui->switchH->setValue(0); -} - -void SimulatorDialogFlamenco::on_switchH_sliderReleased() -{ - QTimer::singleShot(400, this, SLOT(resetSH())); -} - -void SimulatorDialogFlamenco::getValues() -{ - TxInputs inputs = { - { - int(1024 * vJoyLeft->getStickX()), // LEFT HORZ - int(-1024 * vJoyLeft->getStickY()), // LEFT VERT - int(-1024 * vJoyRight->getStickY()), // RGHT VERT - int(1024 * vJoyRight->getStickX()) // RGHT HORZ - }, - - { - -ui->dialP_1->value(), - ui->dialP_2->value(), - 0, - -ui->dialP_3->value(), - ui->dialP_4->value() - }, - - { - ui->switchA->value() - 1, - ui->switchB->value() - 1, - ui->switchC->value() - 1, - ui->switchD->value() - 1, - ui->switchE->value() - 1, - ui->switchF->value(), - ui->switchG->value() - 1, - ui->switchH->value(), 0, 0 - }, - - { - buttonPressed == Qt::Key_PageUp, - buttonPressed == Qt::Key_Escape, - buttonPressed == Qt::Key_Enter, - buttonPressed == Qt::Key_PageDown, - buttonPressed == Qt::Key_Plus, - buttonPressed == Qt::Key_Minus - }, - - middleButtonPressed, - - { - trimPressed == TRIM_LH_L, - trimPressed == TRIM_LH_R, - trimPressed == TRIM_LV_DN, - trimPressed == TRIM_LV_UP, - trimPressed == TRIM_RV_DN, - trimPressed == TRIM_RV_UP, - trimPressed == TRIM_RH_L, - trimPressed == TRIM_RH_R - } - }; - - simulator->setValues(inputs); -} - -void SimulatorDialogFlamenco::saveSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::saveSwitches()"; - switchstatus=ui->switchA->value(); - switchstatus<<=2; - switchstatus+=ui->switchB->value(); - switchstatus<<=2; - switchstatus+=ui->switchC->value(); - switchstatus<<=2; - switchstatus+=ui->switchD->value(); - switchstatus<<=2; - switchstatus+=ui->switchE->value(); - switchstatus<<=2; - switchstatus+=ui->switchF->value(); - switchstatus<<=2; - switchstatus+=ui->switchG->value(); - switchstatus<<=2; - switchstatus+=ui->switchH->value(); -} - -void SimulatorDialogFlamenco::restoreSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::restoreSwitches()"; - ui->switchH->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchG->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchF->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchE->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchD->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchC->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchB->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchA->setValue(switchstatus & 0x3); -} diff --git a/companion/src/simulation/simulatordialoghorus.cpp b/companion/src/simulation/simulatordialoghorus.cpp deleted file mode 100644 index e9b2f1a8f..000000000 --- a/companion/src/simulation/simulatordialoghorus.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "simulatordialog.h" -#include "ui_simulatordialog-horus.h" -#include "helpers.h" - -uint32_t SimulatorDialogHorus::switchstatus = 0; - -SimulatorDialogHorus::SimulatorDialogHorus(QWidget * parent, SimulatorInterface * simulator, unsigned int flags): - SimulatorDialog(parent, simulator, flags), - ui(new Ui::SimulatorDialogHorus) -{ - QPolygon polygon; - - lcdWidth = 480; - lcdHeight = 272; - lcdDepth = 16; - - initUi(ui); - - polygon.setPoints(20, 44,159, 30,144, 35,140, 43,135, 52,131, 62,128, 72,128, 80,128, 90,130, 97,132, 103,136, 110,140, 116,145, 101,158, 95,154, 85,150, 76,148, 67,148, 57,151, 49,154); - ui->rightbuttons->addArea(polygon, Qt::Key_Up, "Horus/right_btnU.png"); - polygon.setPoints(21, 105,160, 119,147, 126,156, 131,165, 134,177, 136,185, 135,196, 134,205, 131,213, 128,220, 124,226, 119,233, 105,219, 109,212, 113,205, 115,196, 116,189, 115,181, 112,174, 108,166, 104,161); - ui->rightbuttons->addArea(polygon, Qt::Key_Right, "Horus/right_btnR.png"); - polygon.setPoints(19, 30,236, 44,223, 52,228, 59,231, 67,233, 75,233, 82,233, 89,231, 95,228, 99,225, 103,223, 115,235, 108,241, 100,246, 89,250, 79,252, 67,252, 54,250, 42,245); - ui->rightbuttons->addArea(polygon, Qt::Key_Down, "Horus/right_btnD.png"); - polygon.setPoints(18, 27,233, 21,226, 17,217, 13,207, 11,192, 11,176, 15,166, 19,158, 24,152, 27,147, 41,161, 35,169, 31,181, 31,191, 31,201, 34,207, 37,215, 41,220); - ui->rightbuttons->addArea(polygon, Qt::Key_Left, "Horus/right_btnL.png"); - polygon.setPoints(30, 33,189, 35,177, 40,168, 44,161, 52,155, 60,152, 70,149, 82,150, 91,154, 98,158, 105,164, 110,173, 113,181, 114,190, 113,198, 111,204, 108,210, 105,215, 101,220, 96,223, 91,225, 86,228, 80,229, 72,230, 65,229, 56,226, 48,222, 42,216, 37,210, 34,200); - ui->rightbuttons->addArea(polygon, Qt::Key_Enter, "Horus/right_ent.png"); - polygon.setPoints(19, 29,232, 23,225, 19,218, 16,210, 14,200, 13,190, 14,179, 17,170, 20,162, 25,155, 30,149, 43,164, 37,172, 34,181, 33,190, 34,200, 37,209, 41,215, 44,219); - ui->leftbuttons->addArea(polygon, Qt::Key_PageUp, "Horus/left_btn1.png"); - polygon.setPoints(22, 32,234, 46,220, 52,225, 59,228, 68,230, 75,230, 83,229, 90,227, 95,224, 101,220, 114,234, 109,239, 103,242, 98,245, 91,248, 84,249, 77,250, 69,250, 60,249, 51,247, 44,243, 38,239); - ui->leftbuttons->addArea(polygon, Qt::Key_PageDown, "Horus/left_btn2.png"); - ui->leftbuttons->addArea(9, 259, 34, 282, Qt::Key_Print, "Horus/left_scrnsht.png"); - - // install simulator TRACE hook - simulator->installTraceHook(traceCb); - - // TODO dialP_4 = ui->dialP_4; - - ui->lcd->setBackgroundColor(47, 123, 227); - - //restore switches - if (g.simuSW()) - restoreSwitches(); - - keymapHelp.append(keymapHelp_t(tr("PG-UP"), tr("[ PgUp ]"))); - keymapHelp.append(keymapHelp_t(tr("PG-DN"), tr("[ PgDn ]"))); - keymapHelp.append(keymapHelp_t(tr("UP"), tr("[ MDL ]"))); - keymapHelp.append(keymapHelp_t(tr("DN/DEL/BKSP"), tr("[ RTN ]"))); - keymapHelp.append(keymapHelp_t(tr("LEFT"), tr("[ SYS ]"))); - keymapHelp.append(keymapHelp_t(tr("RIGHT"), tr("[ TELE ]"))); - keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("Rotary Selector"))); - keymapHelp.append(keymapHelp_t(tr("-/X"), tr("Rotary UP"))); - keymapHelp.append(keymapHelp_t(tr("+/C"), tr("Rotary DOWN"))); - keymapHelp.append(keymapHelp_t(tr("ENTER/MOUSE-MID"), tr("Selector Press"))); - - connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->teleSim, SIGNAL(released()), this, SLOT(openTelemetrySimulator())); - connect(ui->trainerSim, SIGNAL(released()), this, SLOT(openTrainerSimulator())); - connect(ui->debugConsole, SIGNAL(released()), this, SLOT(openDebugOutput())); - connect(ui->luaReload, SIGNAL(released()), this, SLOT(luaReload())); -} - -SimulatorDialogHorus::~SimulatorDialogHorus() -{ - saveSwitches(); - delete ui; -} - -void SimulatorDialogHorus::resetSH() -{ - ui->switchH->setValue(0); -} - -void SimulatorDialogHorus::on_switchH_sliderReleased() -{ - QTimer::singleShot(400, this, SLOT(resetSH())); -} - -void SimulatorDialogHorus::getValues() -{ - TxInputs inputs = { - { - int(1024 * vJoyLeft->getStickX()), // LEFT HORZ - int(-1024 * vJoyLeft->getStickY()), // LEFT VERT - int(-1024 * vJoyRight->getStickY()), // RGHT VERT - int(1024 * vJoyRight->getStickX()) // RGHT HORZ - }, - - { - -ui->dialP_1->value(), - ui->dialP_2->value(), - 0, - -ui->dialP_3->value(), - ui->dialP_4->value() - }, - - { - ui->switchA->value() - 1, - ui->switchB->value() - 1, - ui->switchC->value() - 1, - ui->switchD->value() - 1, - ui->switchE->value() - 1, - ui->switchF->value(), - ui->switchG->value() - 1, - ui->switchH->value(), 0, 0 - }, - - { - buttonPressed == Qt::Key_PageUp, - buttonPressed == Qt::Key_PageDown, - buttonPressed == Qt::Key_Enter || middleButtonPressed, - buttonPressed == Qt::Key_Up, - buttonPressed == Qt::Key_Down || buttonPressed == Qt::Key_Escape, - buttonPressed == Qt::Key_Right, - buttonPressed == Qt::Key_Left - }, - - middleButtonPressed, - - { - trimPressed == TRIM_LH_L, - trimPressed == TRIM_LH_R, - trimPressed == TRIM_LV_DN, - trimPressed == TRIM_LV_UP, - trimPressed == TRIM_RV_DN, - trimPressed == TRIM_RV_UP, - trimPressed == TRIM_RH_L, - trimPressed == TRIM_RH_R, - 0,0,0,0 - /*trimPressed == TRIM_T5_DN, - trimPressed == TRIM_T5_UP, - trimPressed == TRIM_T6_DN, - trimPressed == TRIM_T6_UP*/ - } - }; - - simulator->setValues(inputs); - - if (buttonPressed == Qt::Key_Plus || buttonPressed == Qt::Key_C) { - simulator->wheelEvent(1); - buttonPressed = 0; // debounce, important - } - else if (buttonPressed == Qt::Key_Minus || buttonPressed == Qt::Key_X) { - simulator->wheelEvent(-1); - buttonPressed = 0; // debounce, important - } -} - -void SimulatorDialogHorus::saveSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::saveSwitches()"; - switchstatus=ui->switchA->value(); - switchstatus<<=2; - switchstatus+=ui->switchB->value(); - switchstatus<<=2; - switchstatus+=ui->switchC->value(); - switchstatus<<=2; - switchstatus+=ui->switchD->value(); - switchstatus<<=2; - switchstatus+=ui->switchE->value(); - switchstatus<<=2; - switchstatus+=ui->switchF->value(); - switchstatus<<=2; - switchstatus+=ui->switchG->value(); - switchstatus<<=2; - switchstatus+=ui->switchH->value(); -} - -void SimulatorDialogHorus::restoreSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::restoreSwitches()"; - ui->switchH->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchG->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchF->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchE->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchD->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchC->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchB->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchA->setValue(switchstatus & 0x3); -} diff --git a/companion/src/simulation/simulatordialogtaranis.cpp b/companion/src/simulation/simulatordialogtaranis.cpp deleted file mode 100644 index f82fc802f..000000000 --- a/companion/src/simulation/simulatordialogtaranis.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "simulatordialog.h" -#include "ui_simulatordialog-taranis.h" -#include "helpers.h" - - -uint32_t SimulatorDialogTaranis::switchstatus = 0; - -SimulatorDialogTaranis::SimulatorDialogTaranis(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): - SimulatorDialog(parent, simulator, flags), - ui(new Ui::SimulatorDialogTaranis) -{ - QPolygon polygon; - - lcdWidth = 212; - lcdHeight = 64; - lcdDepth = 4; - - initUi(ui); - - polygon.setPoints(6, 20, 59, 27, 50, 45, 52, 56, 59, 50, 71, 26, 72); - ui->leftbuttons->addArea(polygon, Qt::Key_PageUp, "Taranis/x9l1.png"); - polygon.setPoints(6, 23, 107, 30, 99, 46, 100, 55, 106, 47, 117, 28, 117); - ui->leftbuttons->addArea(polygon, Qt::Key_PageDown, "Taranis/x9l2.png"); - polygon.setPoints(6, 24, 154, 32, 144, 46, 146, 57, 156, 46, 167, 29, 166); - ui->leftbuttons->addArea(polygon, Qt::Key_Escape, "Taranis/x9l3.png"); - ui->leftbuttons->addArea(90, 177, 118, 197, Qt::Key_Print, "Taranis/x9l4.png"); - polygon.setPoints(6, 64, 60, 71, 50, 90, 50, 100, 60, 90, 73, 72, 73); - ui->rightbuttons->addArea(polygon, Qt::Key_Plus, "Taranis/x9r1.png"); - polygon.setPoints(6, 63, 109, 73, 100, 88, 100, 98, 109, 88, 119, 72, 119); - ui->rightbuttons->addArea(polygon, Qt::Key_Minus, "Taranis/x9r2.png"); - polygon.setPoints(6, 63, 155, 72, 146, 90, 146, 98, 155, 88, 166, 72, 166); - ui->rightbuttons->addArea(polygon, Qt::Key_Enter, "Taranis/x9r3.png"); - - // install simulator TRACE hook - simulator->installTraceHook(traceCb); - - ui->lcd->setBackgroundColor(47, 123, 227); - - // restore switches - if (g.simuSW()) { - restoreSwitches(); - } - - for (int i=0; isetValue(-1024); - pots[i]->setSingleStep(2048/5); - pots[i]->setPageStep(2048/5); - } - else if (!(flags & (SIMULATOR_FLAGS_S1 << i))) { - pots[i]->hide(); - potLabels[i]->hide(); - } - } - - keymapHelp.append(keymapHelp_t(tr("PG-UP"), tr("[ MENU ]"))); - keymapHelp.append(keymapHelp_t(tr("PG-DN"), tr("[ PAGE ]"))); - keymapHelp.append(keymapHelp_t(tr("DEL/BKSP/ESC"), tr("[ EXIT ]"))); - keymapHelp.append(keymapHelp_t(tr("+/UP"), tr("[ + ]"))); - keymapHelp.append(keymapHelp_t(tr("-/DN"), tr("[ - ]"))); - keymapHelp.append(keymapHelp_t(tr("ENTER/MOUSE-MID"), tr("[ ENT ]"))); - keymapHelp.append(keymapHelp_t(tr("WHEEL/PAD SCRL"), tr("[ + ]/[ - ] or Rotary Sel."))); - - connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->teleSim, SIGNAL(released()), this, SLOT(openTelemetrySimulator())); - connect(ui->trainerSim, SIGNAL(released()), this, SLOT(openTrainerSimulator())); - connect(ui->debugConsole, SIGNAL(released()), this, SLOT(openDebugOutput())); - connect(ui->luaReload, SIGNAL(released()), this, SLOT(luaReload())); -} - -SimulatorDialogTaranis::~SimulatorDialogTaranis() -{ - saveSwitches(); - delete ui; -} - - -void SimulatorDialogTaranis::resetSH() -{ - ui->switchH->setValue(0); -} - -void SimulatorDialogTaranis::on_switchH_sliderReleased() -{ - QTimer::singleShot(400, this, SLOT(resetSH())); -} - -void SimulatorDialogTaranis::getValues() -{ - for (int i=0; ivalue()+1024)/(2048.0/5))*(2048.0/5)-1024; - pots[i]->setValue(s1); - } - } - - TxInputs inputs = { - { - int(1024 * vJoyLeft->getStickX()), // LEFT HORZ - int(-1024 * vJoyLeft->getStickY()), // LEFT VERT - int(-1024 * vJoyRight->getStickY()), // RGHT VERT - int(1024 * vJoyRight->getStickX()) // RGHT HORZ - }, - - { - -pots[0]->value(), - pots[1]->value(), - ((flags & SIMULATOR_FLAGS_S3) ? pots[2]->value() : 0), - -sliders[0]->value(), - sliders[1]->value() - }, - - { - ui->switchA->value() - 1, - ui->switchB->value() - 1, - ui->switchC->value() - 1, - ui->switchD->value() - 1, - ui->switchE->value() - 1, - ui->switchF->value(), - ui->switchG->value() - 1, - ui->switchH->value(), 0, 0 - }, - - { - buttonPressed == Qt::Key_PageUp, - buttonPressed == Qt::Key_Escape, - buttonPressed == Qt::Key_Enter || middleButtonPressed, - buttonPressed == Qt::Key_PageDown, - buttonPressed == Qt::Key_Plus || buttonPressed == Qt::Key_Up, - buttonPressed == Qt::Key_Minus || buttonPressed == Qt::Key_Down - }, - - middleButtonPressed, - - { - trimPressed == TRIM_LH_L, - trimPressed == TRIM_LH_R, - trimPressed == TRIM_LV_DN, - trimPressed == TRIM_LV_UP, - trimPressed == TRIM_RV_DN, - trimPressed == TRIM_RV_UP, - trimPressed == TRIM_RH_L, - trimPressed == TRIM_RH_R - } - }; - - simulator->setValues(inputs); -} - -void SimulatorDialogTaranis::saveSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::saveSwitches()"; - switchstatus=ui->switchA->value(); - switchstatus<<=2; - switchstatus+=ui->switchB->value(); - switchstatus<<=2; - switchstatus+=ui->switchC->value(); - switchstatus<<=2; - switchstatus+=ui->switchD->value(); - switchstatus<<=2; - switchstatus+=ui->switchE->value(); - switchstatus<<=2; - switchstatus+=ui->switchF->value(); - switchstatus<<=2; - switchstatus+=ui->switchG->value(); - switchstatus<<=2; - switchstatus+=ui->switchH->value(); -} - -void SimulatorDialogTaranis::restoreSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::restoreSwitches()"; - ui->switchH->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchG->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchF->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchE->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchD->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchC->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchB->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchA->setValue(switchstatus & 0x3); -} - - diff --git a/companion/src/simulation/simulatorimport.h b/companion/src/simulation/simulatorimport.h index 453e4b4c1..3ec4527fa 100644 --- a/companion/src/simulation/simulatorimport.h +++ b/companion/src/simulation/simulatorimport.h @@ -44,20 +44,21 @@ for (int i=0; iPIO_PDSR &= ~0x40; else PIOB->PIO_PDSR |= 0x40; -#endif - -#if defined(PCBFLAMENCO) || defined(PCBX9E) -if (inputs.rotenc) simuSetKey(KEY_ENTER, true); -#endif +#if defined(PCBGRUVIN9X) + pind = 0; + if (inputs.rotenc) + pind |= 0x20; +#elif defined(PCBSKY9X) + if (inputs.rotenc) + PIOB->PIO_PDSR &= ~0x40; + else + PIOB->PIO_PDSR |= 0x40; +#else + if (inputs.rotenc) + simuSetKey(KEY_ENTER, true); #endif +#endif // SETVALUES_IMPORT #ifdef GETVALUES_IMPORT #undef GETVALUES_IMPORT @@ -108,6 +109,6 @@ return main_thread_error; #ifdef SETTRAINER_IMPORT #undef SETTRAINER_IMPORT ppmInputValidityTimer = 100; - ppmInput[inputNumber] = LIMIT< ::int16_t>(-512, value, 512); + ppmInput[inputNumber] = qMin(qMax((int16_t)-512, value), (int16_t)512); #endif diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h index 289b306d6..5f1c20451 100644 --- a/companion/src/simulation/simulatorinterface.h +++ b/companion/src/simulation/simulatorinterface.h @@ -28,9 +28,6 @@ #include #include -// TODO can be removed? -template t LIMIT(t mi, t x, t ma) { return std::min(std::max(mi, x), ma); } - struct TxInputs { int sticks[CPN_MAX_STICKS]; /* lh lv rv rh */ @@ -38,7 +35,7 @@ struct TxInputs int switches[CPN_MAX_SWITCHES]; bool keys[CPN_MAX_KEYS]; bool rotenc; - bool trims[12]; + bool trims[(CPN_MAX_STICKS + CPN_MAX_AUX_TRIMS) * 2]; }; class TxOutputs @@ -62,11 +59,11 @@ class SimulatorInterface { public: - virtual ~SimulatorInterface() {}; + virtual ~SimulatorInterface() {} virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") { }; - virtual void setVolumeGain(int value) { }; + virtual void setVolumeGain(int value) { } virtual void start(QByteArray & eeprom, bool tests=true) = 0; @@ -89,10 +86,10 @@ class SimulatorInterface virtual void getTrims(Trims &trims) = 0; virtual unsigned int getPhase() = 0; - + virtual const char * getPhaseName(unsigned int phase) = 0; - virtual void wheelEvent(int steps) { }; + virtual void wheelEvent(int steps) { } virtual const char * getError() = 0; diff --git a/companion/src/simulation/telemetrysimu.h b/companion/src/simulation/telemetrysimu.h index f6483ab0f..b7387f39a 100644 --- a/companion/src/simulation/telemetrysimu.h +++ b/companion/src/simulation/telemetrysimu.h @@ -31,6 +31,7 @@ #include "simulatorinterface.h" static double const SPEEDS[] = { 0.2, 0.4, 0.6, 0.8, 1, 2, 3, 4, 5 }; +template t LIMIT(t mi, t x, t ma) { return std::min(std::max(mi, x), ma); } namespace Ui { class TelemetrySimulator; @@ -130,7 +131,7 @@ private: SimulatorInterface *simulator; void generateTelemetryFrame(); TelemetrySimulator::LogPlaybackController *logPlayback; - + private slots: void onSimulateToggled(bool isChecked); void onTimerEvent(); diff --git a/companion/src/simulation/buttonswidget.h b/companion/src/simulation/widgets/buttonswidget.h similarity index 61% rename from companion/src/simulation/buttonswidget.h rename to companion/src/simulation/widgets/buttonswidget.h index b7910fcd7..f67293d8c 100644 --- a/companion/src/simulation/buttonswidget.h +++ b/companion/src/simulation/widgets/buttonswidget.h @@ -21,6 +21,8 @@ #ifndef _BUTTONSWIDGET_H_ #define _BUTTONSWIDGET_H_ +#include "radiouiaction.h" + #include #include #include @@ -37,73 +39,87 @@ class ButtonsWidget : public QWidget { } - virtual void setStyleSheet(const QString & sheet) { defaultStyleSheet = sheet; QWidget::setStyleSheet(sheet); } - void addArea(int x1, int y1, int x2, int y2, int key, const char * bitmap) + void addArea(int x1, int y1, int x2, int y2, const char * image, RadioUiAction * action = NULL) { QPolygon polygon; polygon.setPoints(4, x1, y1, x1, y2, x2, y2, x2, y1); - addArea(polygon, key, bitmap); + addArea(polygon, image, action); } - void addArea(const QPolygon & polygon, int key, const char * bitmap) + void addArea(const QPolygon & polygon, const char * image, RadioUiAction * action = NULL) { - areas.push_back(Area(polygon, key, bitmap)); + areas.push_back(Area(polygon, image, action)); } protected: - - class Area { + + class Area + { public: - Area(const QPolygon & polygon, int key, const char * bitmap): + Area(const QPolygon & polygon, const QString &image, RadioUiAction * action = NULL): polygon(polygon), - key(key), - bitmap(bitmap) + imgFile(image), + action(action) { } + bool contains(int x, int y) { return polygon.containsPoint(QPoint(x, y), Qt::OddEvenFill); } - public: + QPolygon polygon; - int key; - const char * bitmap; + QString imgFile; + RadioUiAction * action; }; - - void setBitmap(const char * bitmap) + + void setBitmap(QString bitmap) { - if (bitmap) { + if (!bitmap.isEmpty()) { QWidget::setStyleSheet(QString("background:url(:/images/simulator/%1);").arg(bitmap)); } - } - - virtual void mousePressEvent(QMouseEvent * event) - { - int x = event->x(); - int y = event->y(); - setFocus(); - if (event->button() == Qt::LeftButton) { - foreach(Area area, areas) { - if (area.contains(x, y)) { - setBitmap(area.bitmap); - emit buttonPressed(area.key); - break; - } - } + else { + QWidget::setStyleSheet(defaultStyleSheet); } } - + + void onMouseButtonEvent(bool press, QMouseEvent * event) + { + bool trig; + QString img = ""; + int x = event->x(); + int y = event->y(); + + foreach(Area area, areas) { + trig = false; + if (press && event->button() == Qt::LeftButton && area.contains(x, y)) { + img = area.imgFile; + setFocus(); + trig = true; + } + if (area.action) + area.action->trigger(trig); + } + setBitmap(img); + } + + virtual void mousePressEvent(QMouseEvent * event) + { + onMouseButtonEvent(true, event); + } virtual void mouseReleaseEvent(QMouseEvent * event) { - QWidget::setStyleSheet(defaultStyleSheet); - setFocus(); - emit buttonPressed(0); + onMouseButtonEvent(false, event); + } + virtual void mouseLeaveEvent(QMouseEvent * event) + { + onMouseButtonEvent(false, event); } void paintEvent(QPaintEvent *) @@ -114,10 +130,6 @@ class ButtonsWidget : public QWidget style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } - signals: - - void buttonPressed(int button); - protected: QList areas; diff --git a/companion/src/simulation/lcdwidget.h b/companion/src/simulation/widgets/lcdwidget.h similarity index 87% rename from companion/src/simulation/lcdwidget.h rename to companion/src/simulation/widgets/lcdwidget.h index 7cc34b86b..b52b0de30 100644 --- a/companion/src/simulation/lcdwidget.h +++ b/companion/src/simulation/widgets/lcdwidget.h @@ -21,18 +21,26 @@ #ifndef _LCDWIDGET_H_ #define _LCDWIDGET_H_ +#include #include +#include +#include +#include +#include #include "appdata.h" class LcdWidget : public QWidget { + Q_OBJECT + public: LcdWidget(QWidget * parent = 0): QWidget(parent), lcdBuf(NULL), previousBuf(NULL), - lightEnable(false) + lightEnable(false), + bgDefaultColor(QColor(198, 208, 199)) { } @@ -57,11 +65,16 @@ class LcdWidget : public QWidget memset(previousBuf, 0, lcdSize); } - void setBackgroundColor(int red, int green, int blue) + void setBgDefaultColor(QColor color) { - _r = red; - _g = green; - _b = blue; + bgDefaultColor = color; + } + + void setBackgroundColor(QColor color) + { + _r = color.red(); + _g = color.green(); + _b = color.blue(); } void makeScreenshot(const QString & fileName) @@ -73,23 +86,18 @@ class LcdWidget : public QWidget } else { width = lcdWidth; - height = lcdHeight; + height = lcdHeight; } QPixmap buffer(width, height); QPainter p(&buffer); doPaint(p); - bool toclipboard = g.snapToClpbrd(); - if (toclipboard) { + if (fileName.isEmpty()) { + qDebug() << "Screenshot saved to clipboard"; QApplication::clipboard()->setPixmap( buffer ); } else { - QString path = g.snapshotDir(); - if (path.isEmpty() || !QDir(path).exists()) { - path = "."; - } - path.append(QDir::separator() + fileName); - qDebug() << "Screenshot" << path; - buffer.toImage().save(path); + qDebug() << "Screenshot" << fileName; + buffer.toImage().save(fileName); } } @@ -102,12 +110,6 @@ class LcdWidget : public QWidget } } - virtual void mousePressEvent(QMouseEvent * event) - { - setFocus(); - QWidget::mousePressEvent(event); - } - protected: int lcdWidth; @@ -120,6 +122,7 @@ class LcdWidget : public QWidget bool lightEnable; int _r, _g, _b; + QColor bgDefaultColor; inline void doPaint(QPainter & p) { @@ -149,7 +152,7 @@ class LcdWidget : public QWidget if (lightEnable) rgb = qRgb(_r, _g, _b); else - rgb = qRgb(161, 161, 161); + rgb = bgDefaultColor.rgba(); p.setBackground(QBrush(rgb)); p.eraseRect(0, 0, 2*lcdWidth, 2*lcdHeight); diff --git a/companion/src/simulation/widgets/radiofaderwidget.h b/companion/src/simulation/widgets/radiofaderwidget.h new file mode 100644 index 000000000..45537420f --- /dev/null +++ b/companion/src/simulation/widgets/radiofaderwidget.h @@ -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 _RADIOFADERWIDGET_H_ +#define _RADIOFADERWIDGET_H_ + +#include "radiowidget.h" +#include "sliderwidget.h" + +class RadioFaderWidget : public RadioWidget +{ + Q_OBJECT + + public: + + 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()) : + RadioWidget(labelText, value, parent, f) + { + init(); + } + + void init() + { + m_type = RADIO_WIDGET_FADER; + + SliderWidget * sl = new SliderWidget(this); + sl->setOrientation(Qt::Vertical); + sl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + sl->setMinimumHeight(75); + //sl->setMaximumHeight(75); + sl->setTickPosition(QSlider::TicksBothSides); + sl->setPageStep(128); + sl->setMinimum(-1024); + sl->setMaximum(1024); + sl->setTickInterval(65); + + connect(sl, &SliderWidget::valueChanged, this, &RadioWidget::setValue); + connect(this, &RadioWidget::valueChanged, sl, &QSlider::setValue); + + setWidget(sl); + } +}; + + + + +#endif // _RADIOFADERWIDGET_H_ diff --git a/companion/src/simulation/widgets/radioknobwidget.h b/companion/src/simulation/widgets/radioknobwidget.h new file mode 100644 index 000000000..6d3c5821f --- /dev/null +++ b/companion/src/simulation/widgets/radioknobwidget.h @@ -0,0 +1,127 @@ +/* + * 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 _RADIOKNOBWIDGET_H_ +#define _RADIOKNOBWIDGET_H_ + +#include "radiowidget.h" +#include "radiodata.h" + +#include +#include +#include +#include + +class RadioKnobWidget : public RadioWidget +{ + Q_OBJECT + + public: + + using potType_t = GeneralSettings::PotConfig; + + explicit RadioKnobWidget(potType_t type = potType_t::POT_WITH_DETENT, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) : + RadioWidget(parent, f), + m_potType(type) + { + init(); + } + explicit RadioKnobWidget(potType_t type, const QString &labelText, int value = 0, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) : + RadioWidget(labelText, value, parent, f), + m_potType(type) + { + init(); + } + + void init() + { + m_type = RADIO_WIDGET_KNOB; + + KnobWidget * pot = new KnobWidget(m_potType, this); + pot->setValue(m_value); + + connect(pot, &KnobWidget::valueChanged, this, &RadioWidget::setValue); + connect(this, &RadioWidget::valueChanged, pot, &KnobWidget::setValue); + + setWidget(pot); + } + + private: + + potType_t m_potType; + + + class KnobWidget : public QDial + { + friend class RadioKnobWidget; + using potType_t = RadioKnobWidget::potType_t; + + public: + + explicit KnobWidget(potType_t type, QWidget * parent = 0): + QDial(parent), + m_type(type), + m_positions(type == potType_t::POT_MULTIPOS_SWITCH ? 5 : 0) + { + setToolTip(tr("Right-double-click to reset to center.")); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setFixedSize(QSize(42, 42)); + setMinimum(-1024); + setMaximum(1024); + setNotchesVisible(true); + if (m_positions) { + // this is a bit of a hack to get the notch markers to display correctly + // the actual notches/value are constrained in setValue() + setSingleStep(2048 / m_positions / 10); + setPageStep(2048 / m_positions); + setNotchTarget(5.7); + } + else { + setPageStep(128); + setNotchTarget(64); + } + } + + void setValue(int value) + { + if (m_positions) { + value = ((int)roundf((value + 1024) / (2048.0f / m_positions)) * (2048.0f / m_positions) - 1024); + } + QDial::setValue(value); + } + + void mousePressEvent(QMouseEvent * event) + { + if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) { + setValue(0); + event->accept(); + return; + } + QDial::mousePressEvent(event); + } + + potType_t m_type; + quint8 m_positions; + }; + +}; + + +#endif // _RADIOKNOBWIDGET_H_ diff --git a/companion/src/simulation/widgets/radioswitchwidget.h b/companion/src/simulation/widgets/radioswitchwidget.h new file mode 100644 index 000000000..e4a6da625 --- /dev/null +++ b/companion/src/simulation/widgets/radioswitchwidget.h @@ -0,0 +1,80 @@ +/* + * 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 _RADIOSWITCHWIDGET_H_ +#define _RADIOSWITCHWIDGET_H_ + +#include "radiowidget.h" +#include "radiodata.h" + +#include +#include + +class RadioSwitchWidget : public RadioWidget +{ + Q_OBJECT + + public: + typedef GeneralSettings::SwitchConfig swType_t; + + explicit RadioSwitchWidget(swType_t type = swType_t::SWITCH_3POS, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) : + RadioWidget(parent, f), + swType(type) + { + init(); + } + explicit RadioSwitchWidget(swType_t type, const QString &labelText, int value = 0, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) : + RadioWidget(labelText, value, parent, f), + swType(type) + { + init(); + } + + void init() + { + m_type = RADIO_WIDGET_SWITCH; + + QSlider * sl = new QSlider(); + sl->setOrientation(Qt::Vertical); + sl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + sl->setFixedHeight(50); + sl->setInvertedAppearance(true); + sl->setInvertedControls(true); + sl->setTickPosition(QSlider::TicksBothSides); + sl->setPageStep(1); + sl->setMinimum((swType == swType_t::SWITCH_3POS ? -1 : 0)); + sl->setMaximum(1); + sl->setTickInterval(1); + sl->setValue(m_value); + + connect(sl, &QSlider::valueChanged, this, &RadioWidget::setValue); + connect(this, &RadioWidget::valueChanged, sl, &QSlider::setValue); + + setWidget(sl); + } + + private: + swType_t swType; +}; + + + + +#endif // _RADIOSWITCHWIDGET_H_ diff --git a/companion/src/simulation/widgets/radiowidget.h b/companion/src/simulation/widgets/radiowidget.h new file mode 100644 index 000000000..458d69ff0 --- /dev/null +++ b/companion/src/simulation/widgets/radiowidget.h @@ -0,0 +1,166 @@ +/* + * 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 _RADIOWIDGET_H_ +#define _RADIOWIDGET_H_ + +#include +#include +#include + +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(); + } + + void setIndex(int index) { m_index = index; } + void setInvertValue(bool invertValue) { m_invertValue = invertValue; } + + void setValue(int value) + { + if (value != m_value) { + m_value = value; + emit valueChanged(m_value); + } + } + + void setShowLabel(bool show) + { + if (show != m_showLabel) { + m_showLabel = show; + addLabel(); + } + } + + void setLabelText(const QString &labelText, bool showLabel = true) + { + m_labelText = labelText; + m_showLabel = showLabel; + addLabel(); + } + + void changeVisibility(bool visible) + { + static QSizePolicy oldSP = sizePolicy(); + setVisible(visible); + if (visible) { + setSizePolicy(oldSP); + } + else { + oldSP = sizePolicy(); + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + } + } + + int getValue() const { return m_value * (m_invertValue ? -1 : 1); } + int getIndex() const { return m_index; } + int getType() const { return m_type; } + + + 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); + } + } + + int m_value; + int m_index; + 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); + +}; + +#endif // _RADIOWIDGET_H_ + + + + + + diff --git a/companion/src/simulation/sliderwidget.h b/companion/src/simulation/widgets/sliderwidget.h similarity index 95% rename from companion/src/simulation/sliderwidget.h rename to companion/src/simulation/widgets/sliderwidget.h index 3c4c1c2f5..aa5140b82 100644 --- a/companion/src/simulation/sliderwidget.h +++ b/companion/src/simulation/widgets/sliderwidget.h @@ -21,9 +21,8 @@ #ifndef _SLIDERWIDGET_H_ #define _SLIDERWIDGET_H_ -#include #include -#include +#include class SliderWidget : public QSlider { @@ -34,6 +33,7 @@ class SliderWidget : public QSlider explicit SliderWidget(QWidget * parent = 0): QSlider(parent) { + setToolTip(tr("Right-double-click to reset to center.")); } protected: diff --git a/companion/src/simulation/virtualjoystickwidget.cpp b/companion/src/simulation/widgets/virtualjoystickwidget.cpp similarity index 100% rename from companion/src/simulation/virtualjoystickwidget.cpp rename to companion/src/simulation/widgets/virtualjoystickwidget.cpp diff --git a/companion/src/simulation/virtualjoystickwidget.h b/companion/src/simulation/widgets/virtualjoystickwidget.h similarity index 100% rename from companion/src/simulation/virtualjoystickwidget.h rename to companion/src/simulation/widgets/virtualjoystickwidget.h diff --git a/companion/src/simulator.cpp b/companion/src/simulator.cpp index 6049d302d..5c10192f0 100644 --- a/companion/src/simulator.cpp +++ b/companion/src/simulator.cpp @@ -33,10 +33,12 @@ #include #undef main #endif -#include "simulatordialog.h" + +#include "appdata.h" #include "constants.h" #include "eeprominterface.h" -#include "appdata.h" +#include "simulatordialog.h" +#include "storage.h" #include "qxtcommandoptions.h" #ifdef WIN32 @@ -69,6 +71,8 @@ typedef struct int profileId; QString firmwareId; QString eepromFileName; + QString dataFolder; + bool useFolder; } simulatorOptions_t; @@ -84,9 +88,13 @@ 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 = ""; + QString eepromFileName = "", ext = "bin"; QString radioId = firmwareId; int pos = firmwareId.indexOf("-"); if (pos > 0) { @@ -96,7 +104,10 @@ QString radioEepromFileName(QString firmwareId) radioId = radioId.mid(0, pos); } } - eepromFileName = QString("eeprom-%1.bin").arg(radioId); + if (usesCategorizedStorage(radioId)) + ext = "otx"; + + eepromFileName = QString("eeprom-%1.%2").arg(radioId, ext); eepromFileName = g_eepromDirectory.filePath(eepromFileName.toLatin1()); // qDebug() << "radioId" << radioId << "eepromFileName" << eepromFileName; @@ -133,16 +144,22 @@ bool startupOptionsDialog(simulatorOptions_t &opts) "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("EEPROM Image:"); + label = QObject::tr("Data File:"); QLineEdit * fwFile = new QLineEdit(opts.eepromFileName, dialog); - fwFile->setToolTip(QObject::tr("EEPROM image file to use. A new file with a default image will be created if necessary.
" \ + 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.
" \ "NOTE: 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 EEPROM image file...")); + fwBtn->setToolTip(QObject::tr("Select radio data...")); QWidget * fw = new QWidget(dialog); QHBoxLayout * hl = new QHBoxLayout(fw); hl->setContentsMargins(0, 0, 0, 0); @@ -151,6 +168,40 @@ bool startupOptionsDialog(simulatorOptions_t &opts) 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." \ + "
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); @@ -159,33 +210,64 @@ bool startupOptionsDialog(simulatorOptions_t &opts) 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(&QComboBox::currentIndexChanged), [cbProf, cbType](int index) { + QObject::connect(cbProf, static_cast(&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) + if (i > -1) { cbType->setCurrentIndex(i); + } } }); // set new default firmware file when radio type changes - QObject::connect(cbType, static_cast(&QComboBox::currentIndexChanged), [cbType, fwFile](int index) { + QObject::connect(cbType, static_cast(&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](bool) { - QString filter = QObject::tr((cbType->currentText().contains("horus") ? OTX_FILES_FILTER : EEPROM_FILES_FILTER)); + 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"), opts.eepromFileName, + QString file = QFileDialog::getSaveFileName(dialog, QObject::tr("Select EEPROM image"), fwFile->text(), filter, NULL, QFileDialog::DontConfirmOverwrite); - if (!file.isEmpty()) + 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 @@ -193,6 +275,8 @@ bool startupOptionsDialog(simulatorOptions_t &opts) opts.profileId = cbProf->currentData().toInt(); opts.firmwareId = cbType->currentText(); opts.eepromFileName = fwFile->text(); + opts.dataFolder = fwFolder->text(); + opts.useFolder = dsdirBtn->isChecked(); ret = true; } @@ -264,7 +348,6 @@ int main(int argc, char *argv[]) } #endif - SimulatorDialog *dialog; simulatorOptions_t simOptions; QxtCommandOptions cliOptions; bool cliOptsFound = false; @@ -295,7 +378,7 @@ int main(int argc, char *argv[]) if (cliOptions.count("help") || cliOptions.showUnrecognizedWarning()) { QString msg; QTextStream stream(&msg); - stream << QObject::tr("Usage: simulator [OPTION]... [EEPROM.BIN FILE] ") << endl << endl; + stream << QObject::tr("Usage: simulator [OPTION]... [EEPROM.BIN FILE OR DATA FOLDER] ") << endl << endl; stream << QObject::tr("Options:") << endl; cliOptions.showUsage(false, stream); sharedHelpText(stream); @@ -337,25 +420,34 @@ int main(int argc, char *argv[]) } if (!cliOptions.positional().isEmpty()) { - simOptions.eepromFileName = cliOptions.positional()[0]; + if (QString(cliOptions.positional().at(0)).contains(QRegExp(".*\\.[\\w]{2,6}$"))) { + simOptions.eepromFileName = cliOptions.positional()[0]; + } + else { + simOptions.dataFolder = cliOptions.positional()[0]; + simOptions.useFolder = true; + } 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()) { + if (!cliOptsFound || simOptions.profileId == -1 || simOptions.firmwareId.isEmpty() || (simOptions.eepromFileName.isEmpty() && simOptions.dataFolder.isEmpty())) { if (!startupOptionsDialog(simOptions)) { return finish(0); } } - qDebug() << "firmwareId" << simOptions.firmwareId << "profileId" << simOptions.profileId << "eepromFileName" << simOptions.eepromFileName; + qDebug() << "firmwareId" << simOptions.firmwareId << "profileId" << simOptions.profileId << "eepromFileName" \ + << simOptions.eepromFileName << "dataFolder" << simOptions.dataFolder << "useFolder" << simOptions.useFolder; - if (simOptions.profileId < 0 || simOptions.firmwareId.isEmpty() || simOptions.eepromFileName.isEmpty()) { - showMessage(QObject::tr("ERROR: Couldn't start simulator, missing radio/profile/EEPROM file.\nProfile ID: [%1]; Radio ID: [%2]\nEEPROM File: [%3]") + 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); return finish(1); } @@ -376,30 +468,29 @@ 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); - uint32_t flags = SIMULATOR_FLAGS_STANDALONE; - SimulatorInterface * simulator = factory->create(); - simulator->setSdPath(g.profile[simOptions.profileId].sdPath(), ""); - - if (factory->type() == BOARD_HORUS) - dialog = new SimulatorDialogHorus(NULL, simulator, flags); - else if (factory->type() == BOARD_FLAMENCO) - dialog = new SimulatorDialogFlamenco(NULL, simulator, flags); - else if (factory->type() == BOARD_TARANIS_X9D || factory->type() == BOARD_TARANIS_X9DP || factory->type() == BOARD_TARANIS_X9E) - dialog = new SimulatorDialogTaranis(NULL, simulator, flags | SIMULATOR_FLAGS_S1 | SIMULATOR_FLAGS_S2); - else - dialog = new SimulatorDialog9X(NULL, simulator, flags); - + SimulatorDialog * dialog = new SimulatorDialog(NULL, factory->create(), SIMULATOR_FLAGS_STANDALONE); dialog->setRadioProfileId(simOptions.profileId); - dialog->start(simOptions.eepromFileName.toLatin1().constData()); - + if (simOptions.useFolder && !simOptions.dataFolder.isEmpty()) { + dialog->setDataPath(simOptions.dataFolder); + dialog->setEepromData(); + } + else { + dialog->setEepromData(simOptions.eepromFileName.toLocal8Bit(), true); + } + dialog->start(); dialog->show(); int result = app.exec(); + g.id(oldProfId); dialog->deleteLater(); return finish(result); diff --git a/companion/src/storage/appdata.cpp b/companion/src/storage/appdata.cpp index 2ce399e5c..ffa8e80f7 100644 --- a/companion/src/storage/appdata.cpp +++ b/companion/src/storage/appdata.cpp @@ -538,6 +538,7 @@ 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; } @@ -589,6 +590,7 @@ void AppData::sambaLocation (const QString x) { store(x, _sambaLocation, 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" );} @@ -778,6 +780,7 @@ void AppData::init() getset( _sambaPort, "samba_port" ,"\\USBserial\\COM23" ); getset( _lastSimulator, "last_simulator" ,"" ); getset( _simuLastEepe, "simuLastEepe" ,"" ); + getset( _simuLastFolder, "simuLastFolder" ,"" ); getset( _backupDir, "backupPath" ,"" ); getset( _gePath, "gePath" ,"" ); diff --git a/companion/src/storage/appdata.h b/companion/src/storage/appdata.h index 5190503a8..6ac08d5ed 100644 --- a/companion/src/storage/appdata.h +++ b/companion/src/storage/appdata.h @@ -263,6 +263,7 @@ class AppData: protected CompStoreObj QString _sambaPort; QString _lastSimulator; QString _simuLastEepe; + QString _simuLastFolder; QString _backupDir; QString _gePath; @@ -316,6 +317,7 @@ class AppData: protected CompStoreObj QString sambaPort(); QString lastSimulator(); QString simuLastEepe(); + QString simuLastFolder(); QString backupDir(); QString gePath(); @@ -368,6 +370,7 @@ class AppData: protected CompStoreObj void sambaPort (const QString); void lastSimulator (const QString); void simuLastEepe (const QString); + void simuLastFolder (const QString); void backupDir (const QString); void gePath (const QString);