[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
This commit is contained in:
Max Paperno
2017-01-24 07:54:12 +01:00
committed by Bertrand Songis
parent b3f4870da7
commit 17a03e6c18
43 changed files with 3561 additions and 5934 deletions
@@ -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<int> 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);
});
}