Merge with latest 2.3
12
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: ['PayPal.Me/opentx']
|
|
@ -6,7 +6,7 @@ set(VERSION_REVISION "0")
|
||||||
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
|
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
|
||||||
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
|
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
|
||||||
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
|
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
|
||||||
set(SDCARD_REVISION "0026")
|
set(SDCARD_REVISION "0028")
|
||||||
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
|
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
30
CREDITS.txt
|
@ -11,6 +11,7 @@ Arne Schwabe (schwabe)
|
||||||
|
|
||||||
[Translators]
|
[Translators]
|
||||||
[fr] Sebastien Charpentier (LapinFou)
|
[fr] Sebastien Charpentier (LapinFou)
|
||||||
|
[es] Daniel Gorbea (dgatf)
|
||||||
|
|
||||||
[Other contributors]
|
[Other contributors]
|
||||||
Rob Thomson
|
Rob Thomson
|
||||||
|
@ -422,7 +423,6 @@ Pablo Gomez Martinez
|
||||||
Alan Thoren
|
Alan Thoren
|
||||||
Jack Clodfelter
|
Jack Clodfelter
|
||||||
William Simon
|
William Simon
|
||||||
James Houck
|
|
||||||
Peter Fithern
|
Peter Fithern
|
||||||
Thomas Svedman
|
Thomas Svedman
|
||||||
TechFixPros
|
TechFixPros
|
||||||
|
@ -687,7 +687,6 @@ Shaun Currier
|
||||||
Danilo Schiara
|
Danilo Schiara
|
||||||
John Hennig
|
John Hennig
|
||||||
RK Custom Homes
|
RK Custom Homes
|
||||||
James Houck
|
|
||||||
Piet Teekens
|
Piet Teekens
|
||||||
Tommy Widenflycht
|
Tommy Widenflycht
|
||||||
Johan Petrus Theophilus
|
Johan Petrus Theophilus
|
||||||
|
@ -1707,3 +1706,30 @@ Fabrice Debonnet
|
||||||
James Laver
|
James Laver
|
||||||
Kevin Bowens
|
Kevin Bowens
|
||||||
David Frech
|
David Frech
|
||||||
|
Udo Kastenholz
|
||||||
|
Julio Margarido
|
||||||
|
Uwe Muendelein
|
||||||
|
James Jewitt
|
||||||
|
Daniel Ferreira
|
||||||
|
Michael Charlston
|
||||||
|
Leopoldo Cicero
|
||||||
|
Tom Van Driel
|
||||||
|
Karl Vetter
|
||||||
|
Johannes Janssen
|
||||||
|
François Blondé
|
||||||
|
Precision Aero
|
||||||
|
Thomas Håkansson
|
||||||
|
Gordon Evans
|
||||||
|
Benny Simonsen
|
||||||
|
George Kennedy
|
||||||
|
Stefano Boggia
|
||||||
|
Maksym Arshynkin
|
||||||
|
Tomas Sodergren
|
||||||
|
Jörg Lemnitz
|
||||||
|
TMac FPV
|
||||||
|
Josef Schaeffler
|
||||||
|
Mike Frizell
|
||||||
|
MeCodeGoodSomeday
|
||||||
|
Timothy Fry
|
||||||
|
John Beech
|
||||||
|
Wojciech Winiarski
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
## OpenTX 2.3 Branch
|
## OpenTX 2.3 Branch
|
||||||
|
|
||||||
[](https://travis-ci.org/opentx/opentx)
|
[](https://travis-ci.org/opentx/opentx)
|
||||||
[](https://discord.gg/pAmmCp2)
|
[](https://discord.gg/CZCwVx2)
|
||||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DJ9MASSKVW8WN)
|
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DJ9MASSKVW8WN)
|
||||||
|
|
||||||
The ongoing development on 2.3.x is done in this branch.
|
The ongoing development on 2.3.x is done in this branch.
|
||||||
|
|
|
@ -250,6 +250,7 @@ set(companion_SRCS
|
||||||
wizarddialog.cpp
|
wizarddialog.cpp
|
||||||
styleeditdialog.cpp
|
styleeditdialog.cpp
|
||||||
dialogs/filesyncdialog.cpp # TODO move to own lib with other dialogs
|
dialogs/filesyncdialog.cpp # TODO move to own lib with other dialogs
|
||||||
|
profilechooser.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(companion_MOC_HDRS
|
set(companion_MOC_HDRS
|
||||||
|
@ -284,6 +285,7 @@ set(companion_MOC_HDRS
|
||||||
styleeditdialog.h
|
styleeditdialog.h
|
||||||
helpers_html.h
|
helpers_html.h
|
||||||
dialogs/filesyncdialog.h
|
dialogs/filesyncdialog.h
|
||||||
|
profilechooser.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(companion_UIS
|
set(companion_UIS
|
||||||
|
@ -305,6 +307,7 @@ set(companion_UIS
|
||||||
flasheepromdialog.ui
|
flasheepromdialog.ui
|
||||||
radionotfound.ui
|
radionotfound.ui
|
||||||
styleeditdialog.ui
|
styleeditdialog.ui
|
||||||
|
profilechooser.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
|
@ -73,6 +73,7 @@ void AppPreferencesDialog::accept()
|
||||||
g.OpenTxBranch(AppData::DownloadBranchType(ui->OpenTxBranch->currentIndex()));
|
g.OpenTxBranch(AppData::DownloadBranchType(ui->OpenTxBranch->currentIndex()));
|
||||||
g.autoCheckFw(ui->autoCheckFirmware->isChecked());
|
g.autoCheckFw(ui->autoCheckFirmware->isChecked());
|
||||||
g.showSplash(ui->showSplash->isChecked());
|
g.showSplash(ui->showSplash->isChecked());
|
||||||
|
g.promptProfile(ui->chkPromptProfile->isChecked());
|
||||||
g.simuSW(ui->simuSW->isChecked());
|
g.simuSW(ui->simuSW->isChecked());
|
||||||
g.removeModelSlots(ui->opt_removeBlankSlots->isChecked());
|
g.removeModelSlots(ui->opt_removeBlankSlots->isChecked());
|
||||||
g.newModelAction(ui->opt_newMdl_useWizard->isChecked() ? AppData::MODEL_ACT_WIZARD : ui->opt_newMdl_useEditor->isChecked() ? AppData::MODEL_ACT_EDITOR : AppData::MODEL_ACT_NONE);
|
g.newModelAction(ui->opt_newMdl_useWizard->isChecked() ? AppData::MODEL_ACT_WIZARD : ui->opt_newMdl_useEditor->isChecked() ? AppData::MODEL_ACT_EDITOR : AppData::MODEL_ACT_NONE);
|
||||||
|
@ -185,6 +186,7 @@ void AppPreferencesDialog::initSettings()
|
||||||
ui->autoCheckCompanion->setChecked(g.autoCheckApp());
|
ui->autoCheckCompanion->setChecked(g.autoCheckApp());
|
||||||
ui->autoCheckFirmware->setChecked(g.autoCheckFw());
|
ui->autoCheckFirmware->setChecked(g.autoCheckFw());
|
||||||
ui->showSplash->setChecked(g.showSplash());
|
ui->showSplash->setChecked(g.showSplash());
|
||||||
|
ui->chkPromptProfile->setChecked(g.promptProfile());
|
||||||
ui->historySize->setValue(g.historySize());
|
ui->historySize->setValue(g.historySize());
|
||||||
ui->backLightColor->setCurrentIndex(g.backLight());
|
ui->backLightColor->setCurrentIndex(g.backLight());
|
||||||
ui->volumeGain->setValue(profile.volumeGain() / 10.0);
|
ui->volumeGain->setValue(profile.volumeGain() / 10.0);
|
||||||
|
@ -352,6 +354,13 @@ void AppPreferencesDialog::on_ge_pathButton_clicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppPreferencesDialog::on_btnClearPos_clicked()
|
||||||
|
{
|
||||||
|
SimulatorOptions opts = g.profile[g.sessionId()].simulatorOptions();
|
||||||
|
opts.controlsState.clear();
|
||||||
|
g.profile[g.sessionId()].simulatorOptions(opts);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(JOYSTICKS)
|
#if defined(JOYSTICKS)
|
||||||
void AppPreferencesDialog::on_joystickChkB_clicked() {
|
void AppPreferencesDialog::on_joystickChkB_clicked() {
|
||||||
if (ui->joystickChkB->isChecked()) {
|
if (ui->joystickChkB->isChecked()) {
|
||||||
|
|
|
@ -66,6 +66,7 @@ class AppPreferencesDialog : public QDialog
|
||||||
void on_SplashSelect_clicked();
|
void on_SplashSelect_clicked();
|
||||||
void on_clearImageButton_clicked();
|
void on_clearImageButton_clicked();
|
||||||
void on_btn_appLogsDir_clicked();
|
void on_btn_appLogsDir_clicked();
|
||||||
|
void on_btnClearPos_clicked();
|
||||||
|
|
||||||
#if defined(JOYSTICKS)
|
#if defined(JOYSTICKS)
|
||||||
void on_joystickChkB_clicked();
|
void on_joystickChkB_clicked();
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>741</width>
|
<width>864</width>
|
||||||
<height>668</height>
|
<height>668</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="profileTab">
|
<widget class="QWidget" name="profileTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
@ -61,22 +61,40 @@
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="optionsLayout">
|
<layout class="QGridLayout" name="optionsLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<property name="horizontalSpacing">
|
<property name="horizontalSpacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="verticalSpacing">
|
<property name="verticalSpacing">
|
||||||
<number>4</number>
|
<number>4</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0" colspan="4">
|
<item row="7" column="0" colspan="4">
|
||||||
<widget class="QWidget" name="widget_splashImage" native="true">
|
<widget class="QWidget" name="widget_splashImage" native="true">
|
||||||
<layout class="QGridLayout" name="gridLayout_5">
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
<property name="margin">
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
|
@ -704,29 +722,90 @@ Mode 4:
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="7" column="1">
|
<item row="15" column="1">
|
||||||
<layout class="QVBoxLayout" name="updatesLayout">
|
<widget class="QCheckBox" name="backupEnable">
|
||||||
<item>
|
<property name="sizePolicy">
|
||||||
<widget class="QCheckBox" name="autoCheckFirmware">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
<property name="text">
|
<horstretch>0</horstretch>
|
||||||
<string>Automatic check for OpenTX firmware updates</string>
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>Enable automatic backup before writing firmware</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="22" column="0">
|
||||||
<widget class="QCheckBox" name="autoCheckCompanion">
|
<widget class="QLabel" name="ge_label">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Automatic check for Companion updates</string>
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>Google Earth Executable</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="9" column="1">
|
||||||
|
<widget class="QComboBox" name="OpenTxBranch">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Releases (stable)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Release candidates (testing)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Nightly builds (unstable)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="18" column="1">
|
||||||
|
<widget class="QComboBox" name="splashincludeCB">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Only show user splash images</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Show user and companion splash images</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="12" column="0" rowspan="2" colspan="2">
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="16" column="0" rowspan="2" colspan="2">
|
||||||
|
<widget class="Line" name="line_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_10" stretch="0,1">
|
<layout class="QHBoxLayout" name="horizontalLayout_10" stretch="0,1">
|
||||||
|
@ -764,120 +843,27 @@ Mode 4:
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" rowspan="2">
|
|
||||||
<widget class="QLabel" name="label_16">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Startup Settings</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="21" column="0">
|
|
||||||
<widget class="QLabel" name="ge_label">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Google Earth Executable</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="0" rowspan="2" colspan="2">
|
|
||||||
<widget class="Line" name="line_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QCheckBox" name="showSplash">
|
<widget class="QCheckBox" name="showSplash">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show splash screen when Companion starts</string>
|
<string>Show splash screen</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="0">
|
<item row="22" column="1">
|
||||||
<widget class="QLabel" name="label_17">
|
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Automatic Backup Folder</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Remember</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="13" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="backupPath">
|
<widget class="QLineEdit" name="ge_lineedit">
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="backupPathButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Select Folder</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0" rowspan="2" colspan="2">
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="18" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="libraryPath">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="libraryPathButton">
|
<widget class="QPushButton" name="ge_pathButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -885,49 +871,13 @@ Mode 4:
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Select Folder</string>
|
<string>Select Executable</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QCheckBox" name="opt_removeBlankSlots">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Remove empty model slots when deleting models (only applies for radios w/out categories)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="24" column="0">
|
|
||||||
<widget class="QLabel" name="lbl_appLogsDir">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Output Logs Folder</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="23" column="0">
|
|
||||||
<widget class="QLabel" name="label_12">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Debug Output Logging</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="opt_newMdl_useWizard">
|
<widget class="QRadioButton" name="opt_newMdl_useWizard">
|
||||||
|
@ -962,90 +912,22 @@ Mode 4:
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="14" column="1">
|
<item row="14" column="1">
|
||||||
<widget class="QCheckBox" name="backupEnable">
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Enable automatic backup before writing firmware</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="19" column="0" rowspan="2" colspan="2">
|
|
||||||
<widget class="Line" name="line_7">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="17" column="1">
|
|
||||||
<widget class="QComboBox" name="splashincludeCB">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<widget class="QLineEdit" name="backupPath">
|
||||||
<string>Only show user splash images</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Show user and companion splash images</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="15" column="0" rowspan="2" colspan="2">
|
|
||||||
<widget class="Line" name="line_5">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="21" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="ge_lineedit">
|
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="ge_pathButton">
|
<widget class="QPushButton" name="backupPathButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
|
||||||
<string>Select Executable</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="24" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="appLogsDir">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_appLogsDir">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Select Folder</string>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1053,14 +935,56 @@ Mode 4:
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="22" column="0" colspan="2">
|
<item row="3" column="0">
|
||||||
<widget class="Line" name="line_4">
|
<widget class="QLabel" name="label_5">
|
||||||
<property name="orientation">
|
<property name="sizePolicy">
|
||||||
<enum>Qt::Horizontal</enum>
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Remember</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="18" column="0">
|
<item row="25" column="0">
|
||||||
|
<widget class="QLabel" name="lbl_appLogsDir">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Output Logs Folder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0" rowspan="3">
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Startup Settings</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="1">
|
||||||
|
<widget class="QCheckBox" name="opt_removeBlankSlots">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove empty model slots when deleting models (only applies for radios w/out categories)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="19" column="0">
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
@ -1073,33 +997,7 @@ Mode 4:
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="17" column="0">
|
<item row="24" column="1">
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Splash Screen Library</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Action on New Model</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="23" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="opt_appDebugLog">
|
<widget class="QCheckBox" name="opt_appDebugLog">
|
||||||
|
@ -1123,36 +1021,163 @@ Mode 4:
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
<item row="25" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="appLogsDir">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_appLogsDir">
|
||||||
|
<property name="text">
|
||||||
|
<string>Select Folder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Action on New Model</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="19" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="libraryPath">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="libraryPathButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Select Folder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="18" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Splash Screen Library</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
<widget class="QLabel" name="label_18">
|
<widget class="QLabel" name="label_18">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Release channel</string>
|
<string>Release channel</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="4" column="0" rowspan="2" colspan="2">
|
||||||
<widget class="QComboBox" name="OpenTxBranch">
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="24" column="0">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Releases (stable)</string>
|
<string>Debug Output Logging</string>
|
||||||
</property>
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="23" column="0" colspan="2">
|
||||||
|
<widget class="Line" name="line_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="14" column="0">
|
||||||
|
<widget class="QLabel" name="label_17">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Automatic Backup Folder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="updatesLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="autoCheckFirmware">
|
||||||
|
<property name="text">
|
||||||
|
<string>Automatic check for OpenTX firmware updates</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
<widget class="QCheckBox" name="autoCheckCompanion">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Release candidates (testing)</string>
|
<string>Automatic check for Companion updates</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="20" column="0" rowspan="2" colspan="2">
|
||||||
|
<widget class="Line" name="line_7">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QCheckBox" name="chkPromptProfile">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Nightly builds (unstable)</string>
|
<string>Prompt for radio profile</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -1180,7 +1205,38 @@ Mode 4:
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="5" column="1">
|
<item row="10" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="volumeGain">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.500000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>3.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
<widget class="QComboBox" name="joystickCB">
|
<widget class="QComboBox" name="joystickCB">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
@ -1193,14 +1249,20 @@ Mode 4:
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="3">
|
<item row="0" column="0">
|
||||||
<widget class="QPushButton" name="joystickcalButton">
|
<widget class="QLabel" name="label_19">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Calibrate</string>
|
<string>Screenshot capture folder</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="7" column="1">
|
||||||
<widget class="QComboBox" name="backLightColor">
|
<widget class="QComboBox" name="backLightColor">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
|
@ -1235,31 +1297,22 @@ Mode 4:
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="9" column="3">
|
||||||
<widget class="QLabel" name="label_19">
|
<widget class="QPushButton" name="joystickcalButton">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Screenshot capture folder</string>
|
<string>Calibrate</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="0" column="3">
|
||||||
<spacer name="verticalSpacer">
|
<widget class="QPushButton" name="snapshotPathButton">
|
||||||
<property name="orientation">
|
<property name="text">
|
||||||
<enum>Qt::Vertical</enum>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="flat">
|
||||||
<size>
|
<bool>false</bool>
|
||||||
<width>20</width>
|
|
||||||
<height>5</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" colspan="3">
|
<item row="1" column="1" colspan="3">
|
||||||
<widget class="QCheckBox" name="snapshotClipboardCKB">
|
<widget class="QCheckBox" name="snapshotClipboardCKB">
|
||||||
|
@ -1274,7 +1327,7 @@ Mode 4:
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="2">
|
<item row="9" column="2">
|
||||||
<widget class="QCheckBox" name="joystickChkB">
|
<widget class="QCheckBox" name="joystickChkB">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
@ -1287,17 +1340,20 @@ Mode 4:
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="12" column="1">
|
||||||
<widget class="QPushButton" name="snapshotPathButton">
|
<spacer name="verticalSpacer">
|
||||||
<property name="text">
|
<property name="orientation">
|
||||||
<string>Select Folder</string>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="flat">
|
<property name="sizeHint" stdset="0">
|
||||||
<bool>false</bool>
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>5</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="9" column="0">
|
||||||
<widget class="QLabel" name="label_11">
|
<widget class="QLabel" name="label_11">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
@ -1310,7 +1366,20 @@ Mode 4:
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="10" column="0">
|
||||||
|
<widget class="QLabel" name="label_volumeGain">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Simulator Volume Gain</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
@ -1348,60 +1417,30 @@ Mode 4:
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" colspan="3">
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_20">
|
||||||
|
<property name="text">
|
||||||
|
<string>Simulator controls</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="simuSW">
|
<widget class="QCheckBox" name="simuSW">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Remember simulator switch values</string>
|
<string>Save switch/pot positions on simulator exit</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="2" column="3">
|
||||||
<widget class="QLabel" name="label_volumeGain">
|
<widget class="QPushButton" name="btnClearPos">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Simulator Volume Gain</string>
|
<string>Clear saved positions</string>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="volumeGain">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>50</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="decimals">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>3.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<double>1.000000000000000</double>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
set(firmwares_SRCS
|
set(firmwares_SRCS
|
||||||
|
adjustmentreference.cpp
|
||||||
boards.cpp
|
boards.cpp
|
||||||
curvereference.cpp
|
curvereference.cpp
|
||||||
customfunctiondata.cpp
|
customfunctiondata.cpp
|
||||||
|
|
81
companion/src/firmwares/adjustmentreference.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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 "adjustmentreference.h"
|
||||||
|
#include "radiodata.h" // for ModelData
|
||||||
|
|
||||||
|
AdjustmentReference::AdjustmentReference(int value)
|
||||||
|
{
|
||||||
|
int val = value;
|
||||||
|
if (abs(val) > ADJUST_REF_GVAR_BASE && abs(val) <= ADJUST_REF_GVAR_BASE + CPN_MAX_GVARS) {
|
||||||
|
type = ADJUST_REF_GVAR;
|
||||||
|
val = val >= 0 ? val - ADJUST_REF_GVAR_BASE : val + ADJUST_REF_GVAR_BASE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->type = ADJUST_REF_VALUE;
|
||||||
|
|
||||||
|
this->value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdjustmentReference::AdjustmentReference(AdjustRefType type, int value)
|
||||||
|
{
|
||||||
|
this->type = type;
|
||||||
|
if (isValid(value))
|
||||||
|
this->value = value;
|
||||||
|
else
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdjustmentReference::isValid(const int value) const
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case ADJUST_REF_VALUE:
|
||||||
|
if (abs(value) < ADJUST_REF_GVAR_BASE)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case ADJUST_REF_GVAR:
|
||||||
|
if (abs(value) > 0 && abs(value) <= CPN_MAX_GVARS);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AdjustmentReference::toString(const ModelData * model, const bool sign) const
|
||||||
|
{
|
||||||
|
QString ret;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case ADJUST_REF_GVAR:
|
||||||
|
ret = RawSource(SOURCE_TYPE_GVAR, abs(value) - 1).toString(model);
|
||||||
|
if (value < 0)
|
||||||
|
ret.prepend("-");
|
||||||
|
else if (sign)
|
||||||
|
ret.prepend("+");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = "%1%";
|
||||||
|
if (sign && value > 0)
|
||||||
|
ret.prepend("+");
|
||||||
|
ret = ret.arg(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
69
companion/src/firmwares/adjustmentreference.h
Normal file
|
@ -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 ADJUSTMENTREFERENCE_H
|
||||||
|
#define ADJUSTMENTREFERENCE_H
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
class ModelData;
|
||||||
|
|
||||||
|
constexpr int ADJUST_REF_GVAR_BASE { 10000 };
|
||||||
|
|
||||||
|
class AdjustmentReference {
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(AdjustmentReference)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum AdjustRefType {
|
||||||
|
ADJUST_REF_VALUE,
|
||||||
|
ADJUST_REF_GVAR,
|
||||||
|
};
|
||||||
|
|
||||||
|
AdjustmentReference() { clear(); }
|
||||||
|
explicit AdjustmentReference(int value);
|
||||||
|
AdjustmentReference(const AdjustRefType type, const int value);
|
||||||
|
|
||||||
|
void clear() { memset(this, 0, sizeof(AdjustmentReference)); }
|
||||||
|
|
||||||
|
bool isSet() const { return type != ADJUST_REF_VALUE || value != 0; }
|
||||||
|
bool isValid(const int value) const;
|
||||||
|
QString toString(const ModelData * model = nullptr, const bool sign = false) const;
|
||||||
|
|
||||||
|
inline const int toValue() const
|
||||||
|
{
|
||||||
|
if (type == ADJUST_REF_GVAR)
|
||||||
|
return value >= 0 ? value + ADJUST_REF_GVAR_BASE : value - ADJUST_REF_GVAR_BASE;
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== ( const AdjustmentReference & other) const {
|
||||||
|
return (this->type == other.type) && (this->value == other.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= ( const AdjustmentReference & other) const {
|
||||||
|
return (this->type != other.type) || (this->value != other.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
AdjustRefType type;
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ADJUSTMENTREFERENCE_H
|
|
@ -50,6 +50,7 @@ class CurveReference {
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
QString toString(const ModelData * model = NULL, bool verbose = true) const;
|
QString toString(const ModelData * model = NULL, bool verbose = true) const;
|
||||||
|
bool isSet() const { return type != CURVE_REF_DIFF || value != 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CURVEREFERENCE_H
|
#endif // CURVEREFERENCE_H
|
||||||
|
|
|
@ -100,6 +100,8 @@ enum Capability {
|
||||||
GvarsName,
|
GvarsName,
|
||||||
NoTelemetryProtocol,
|
NoTelemetryProtocol,
|
||||||
TelemetryCustomScreens,
|
TelemetryCustomScreens,
|
||||||
|
TelemetryCustomScreensBars,
|
||||||
|
TelemetryCustomScreensLines,
|
||||||
TelemetryCustomScreensFieldsPerLine,
|
TelemetryCustomScreensFieldsPerLine,
|
||||||
TelemetryMaxMultiplier,
|
TelemetryMaxMultiplier,
|
||||||
HasVario,
|
HasVario,
|
||||||
|
@ -149,7 +151,8 @@ enum Capability {
|
||||||
DangerousFunctions,
|
DangerousFunctions,
|
||||||
HasModelCategories,
|
HasModelCategories,
|
||||||
HasSwitchableJack,
|
HasSwitchableJack,
|
||||||
PwrButtonPress
|
PwrButtonPress,
|
||||||
|
Sensors
|
||||||
};
|
};
|
||||||
|
|
||||||
class EEPROMInterface
|
class EEPROMInterface
|
||||||
|
|
|
@ -123,6 +123,12 @@ GeneralSettings::GeneralSettings()
|
||||||
strcpy(bluetoothName, "taranis");
|
strcpy(bluetoothName, "taranis");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
|
trainer.mix[i].mode = 2; // replace (:=)
|
||||||
|
trainer.mix[i].src = i;
|
||||||
|
trainer.mix[i].weight = 100;
|
||||||
|
}
|
||||||
|
|
||||||
templateSetup = g.profile[g.sessionId()].channelOrder();
|
templateSetup = g.profile[g.sessionId()].channelOrder();
|
||||||
stickMode = g.profile[g.sessionId()].defaultMode();
|
stickMode = g.profile[g.sessionId()].defaultMode();
|
||||||
|
|
||||||
|
|
|
@ -90,3 +90,8 @@ float GVarData::getMaxPrec() const
|
||||||
{
|
{
|
||||||
return getMax() * multiplierGet();
|
return getMax() * multiplierGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GVarData::isEmpty() const
|
||||||
|
{
|
||||||
|
return (name[0] == '\0' && min == 0 && max == 0 && (!popup) && prec == 0 && unit == 0);
|
||||||
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class GVarData {
|
||||||
GVAR_PREC_MUL1
|
GVAR_PREC_MUL1
|
||||||
};
|
};
|
||||||
|
|
||||||
char name[GVAR_NAME_LEN+1];
|
char name[GVAR_NAME_LEN + 1];
|
||||||
int min;
|
int min;
|
||||||
int max;
|
int max;
|
||||||
bool popup;
|
bool popup;
|
||||||
|
@ -62,6 +62,7 @@ class GVarData {
|
||||||
int getMax() const;
|
int getMax() const;
|
||||||
float getMinPrec() const;
|
float getMinPrec() const;
|
||||||
float getMaxPrec() const;
|
float getMaxPrec() const;
|
||||||
|
bool isEmpty() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,10 @@ void ExpoData::convert(RadioDataConversionState & cstate)
|
||||||
swtch.convert(cstate);
|
swtch.convert(cstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExpoData::isEmpty() const
|
||||||
|
{
|
||||||
|
return (chn == 0 && mode == INPUT_MODE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MixData
|
* MixData
|
||||||
|
@ -48,6 +52,10 @@ void MixData::convert(RadioDataConversionState & cstate)
|
||||||
swtch.convert(cstate);
|
swtch.convert(cstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MixData::isEmpty() const
|
||||||
|
{
|
||||||
|
return (destCh == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LimitData
|
* LimitData
|
||||||
|
@ -87,17 +95,16 @@ void LimitData::clear()
|
||||||
|
|
||||||
bool LimitData::isEmpty() const
|
bool LimitData::isEmpty() const
|
||||||
{
|
{
|
||||||
return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0');
|
return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0' && !curve.isSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CurveData
|
* CurveData
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CurveData::CurveData()
|
CurveData::CurveData()
|
||||||
{
|
{
|
||||||
clear(5);
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurveData::clear(int count)
|
void CurveData::clear(int count)
|
||||||
|
@ -126,22 +133,20 @@ QString CurveData::nameToString(const int idx) const
|
||||||
* FlightModeData
|
* FlightModeData
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void FlightModeData::clear(const int phase)
|
void FlightModeData::clear(const int phaseIdx)
|
||||||
{
|
{
|
||||||
memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData));
|
memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData));
|
||||||
if (phase != 0) {
|
for (int i = 0; i < CPN_MAX_GVARS; i++) {
|
||||||
for (int idx=0; idx<CPN_MAX_GVARS; idx++) {
|
gvars[i] = linkedGVarFlightModeZero(phaseIdx);
|
||||||
gvars[idx] = 1025;
|
|
||||||
}
|
|
||||||
for (int idx=0; idx<CPN_MAX_ENCODERS; idx++) {
|
|
||||||
rotaryEncoders[idx] = 1025;
|
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < CPN_MAX_ENCODERS; i++) {
|
||||||
|
rotaryEncoders[i] = linkedREncFlightModeZero(phaseIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FlightModeData::nameToString(int index) const
|
QString FlightModeData::nameToString(int phaseIdx) const
|
||||||
{
|
{
|
||||||
return RadioData::getElementName(tr("FM"), index, name); // names are zero-based, FM0, FM1, etc
|
return RadioData::getElementName(tr("FM"), phaseIdx, name); // names are zero-based, FM0, FM1, etc
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlightModeData::convert(RadioDataConversionState & cstate)
|
void FlightModeData::convert(RadioDataConversionState & cstate)
|
||||||
|
@ -150,3 +155,53 @@ void FlightModeData::convert(RadioDataConversionState & cstate)
|
||||||
cstate.setSubComp(nameToString(cstate.subCompIdx));
|
cstate.setSubComp(nameToString(cstate.subCompIdx));
|
||||||
swtch.convert(cstate);
|
swtch.convert(cstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FlightModeData::isEmpty(int phaseIdx) const
|
||||||
|
{
|
||||||
|
if (name[0] != '\0' || swtch.isSet() || fadeIn != 0 || fadeOut != 0)
|
||||||
|
return false;
|
||||||
|
for (int i = 0; i < CPN_MAX_TRIMS; i++) {
|
||||||
|
if (trim[i] != 0 || trimRef[i] != 0 || trimMode[i] != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < CPN_MAX_GVARS; i++) {
|
||||||
|
if (!isGVarEmpty(phaseIdx, i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < CPN_MAX_ENCODERS; i++) {
|
||||||
|
if (!isREncEmpty(phaseIdx, i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlightModeData::isGVarEmpty(int phaseIdx, int gvIdx) const
|
||||||
|
{
|
||||||
|
if ((phaseIdx == 0 && gvars[gvIdx] == 0) || (phaseIdx != 0 && gvars[gvIdx] == linkedGVarFlightModeZero(phaseIdx)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlightModeData::isREncEmpty(int phaseIdx, int reIdx) const
|
||||||
|
{
|
||||||
|
if ((phaseIdx == 0 && rotaryEncoders[reIdx] == 0) || (phaseIdx != 0 && rotaryEncoders[reIdx] == linkedREncFlightModeZero(phaseIdx)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlightModeData::linkedFlightModeZero(int phaseIdx, int maxOwnValue) const
|
||||||
|
{
|
||||||
|
if (phaseIdx == 0)
|
||||||
|
return 0;
|
||||||
|
return maxOwnValue + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlightModeData::linkedGVarFlightModeZero(int phaseIdx) const
|
||||||
|
{
|
||||||
|
return linkedFlightModeZero(phaseIdx, GVAR_MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlightModeData::linkedREncFlightModeZero(int phaseIdx) const
|
||||||
|
{
|
||||||
|
return linkedFlightModeZero(phaseIdx, RENC_MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ enum InputMode {
|
||||||
INPUT_MODE_BOTH
|
INPUT_MODE_BOTH
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define EXPODATA_NAME_LEN 10
|
||||||
|
|
||||||
class ExpoData {
|
class ExpoData {
|
||||||
Q_DECLARE_TR_FUNCTIONS(ExpoData)
|
Q_DECLARE_TR_FUNCTIONS(ExpoData)
|
||||||
|
|
||||||
|
@ -52,9 +54,10 @@ class ExpoData {
|
||||||
int offset;
|
int offset;
|
||||||
CurveReference curve;
|
CurveReference curve;
|
||||||
int carryTrim;
|
int carryTrim;
|
||||||
char name[10+1];
|
char name[EXPODATA_NAME_LEN+1];
|
||||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
|
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
|
||||||
void convert(RadioDataConversionState & cstate);
|
void convert(RadioDataConversionState & cstate);
|
||||||
|
bool isEmpty() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MltpxValue {
|
enum MltpxValue {
|
||||||
|
@ -90,8 +93,11 @@ class MixData {
|
||||||
char name[MIXDATA_NAME_LEN+1];
|
char name[MIXDATA_NAME_LEN+1];
|
||||||
|
|
||||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
|
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
|
||||||
|
bool isEmpty() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LIMITDATA_NAME_LEN 6
|
||||||
|
|
||||||
class LimitData {
|
class LimitData {
|
||||||
Q_DECLARE_TR_FUNCTIONS(LimitData)
|
Q_DECLARE_TR_FUNCTIONS(LimitData)
|
||||||
|
|
||||||
|
@ -103,7 +109,7 @@ class LimitData {
|
||||||
int offset;
|
int offset;
|
||||||
int ppmCenter;
|
int ppmCenter;
|
||||||
bool symetrical;
|
bool symetrical;
|
||||||
char name[6+1];
|
char name[LIMITDATA_NAME_LEN+1];
|
||||||
CurveReference curve;
|
CurveReference curve;
|
||||||
QString minToString() const;
|
QString minToString() const;
|
||||||
QString maxToString() const;
|
QString maxToString() const;
|
||||||
|
@ -120,6 +126,8 @@ class CurvePoint {
|
||||||
int8_t y;
|
int8_t y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CURVEDATA_NAME_LEN 6
|
||||||
|
|
||||||
class CurveData {
|
class CurveData {
|
||||||
Q_DECLARE_TR_FUNCTIONS(CurveData)
|
Q_DECLARE_TR_FUNCTIONS(CurveData)
|
||||||
|
|
||||||
|
@ -131,7 +139,7 @@ class CurveData {
|
||||||
};
|
};
|
||||||
|
|
||||||
CurveData();
|
CurveData();
|
||||||
void clear(int count);
|
void clear(int count = 5);
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
QString nameToString(const int idx) const;
|
QString nameToString(const int idx) const;
|
||||||
|
|
||||||
|
@ -139,9 +147,13 @@ class CurveData {
|
||||||
bool smooth;
|
bool smooth;
|
||||||
int count;
|
int count;
|
||||||
CurvePoint points[CPN_MAX_POINTS];
|
CurvePoint points[CPN_MAX_POINTS];
|
||||||
char name[6+1];
|
char name[CURVEDATA_NAME_LEN+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FLIGHTMODE_NAME_LEN 10
|
||||||
|
#define RENC_MAX_VALUE 1024
|
||||||
|
#define RENC_MIN_VALUE -RENC_MAX_VALUE
|
||||||
|
|
||||||
class FlightModeData {
|
class FlightModeData {
|
||||||
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
|
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
|
||||||
|
|
||||||
|
@ -151,14 +163,20 @@ class FlightModeData {
|
||||||
int trimRef[CPN_MAX_TRIMS];
|
int trimRef[CPN_MAX_TRIMS];
|
||||||
int trim[CPN_MAX_TRIMS];
|
int trim[CPN_MAX_TRIMS];
|
||||||
RawSwitch swtch;
|
RawSwitch swtch;
|
||||||
char name[10+1];
|
char name[FLIGHTMODE_NAME_LEN+1];
|
||||||
unsigned int fadeIn;
|
unsigned int fadeIn;
|
||||||
unsigned int fadeOut;
|
unsigned int fadeOut;
|
||||||
int rotaryEncoders[CPN_MAX_ENCODERS];
|
int rotaryEncoders[CPN_MAX_ENCODERS];
|
||||||
int gvars[CPN_MAX_GVARS];
|
int gvars[CPN_MAX_GVARS];
|
||||||
void clear(const int phase);
|
void clear(const int phaseIdx);
|
||||||
QString nameToString(int index) const;
|
QString nameToString(int phaseIdx) const;
|
||||||
void convert(RadioDataConversionState & cstate);
|
void convert(RadioDataConversionState & cstate);
|
||||||
|
bool isEmpty(int phaseIdx) const;
|
||||||
|
bool isGVarEmpty(int phaseIdx, int gvIdx) const;
|
||||||
|
bool isREncEmpty(int phaseIdx, int reIdx) const;
|
||||||
|
int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
|
||||||
|
int linkedGVarFlightModeZero(int phaseIdx) const;
|
||||||
|
int linkedREncFlightModeZero(int phaseIdx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SwashRingData {
|
class SwashRingData {
|
||||||
|
|
|
@ -76,6 +76,8 @@ class TimerData {
|
||||||
int pvalue;
|
int pvalue;
|
||||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData)); mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
|
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData)); mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
|
||||||
void convert(RadioDataConversionState & cstate);
|
void convert(RadioDataConversionState & cstate);
|
||||||
|
bool isEmpty();
|
||||||
|
bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CPN_MAX_SCRIPTS 9
|
#define CPN_MAX_SCRIPTS 9
|
||||||
|
@ -128,6 +130,8 @@ enum TrainerMode {
|
||||||
TRAINER_MODE_MULTI
|
TRAINER_MODE_MULTI
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define INPUT_NAME_LEN 4
|
||||||
|
|
||||||
class ModelData {
|
class ModelData {
|
||||||
Q_DECLARE_TR_FUNCTIONS(ModelData)
|
Q_DECLARE_TR_FUNCTIONS(ModelData)
|
||||||
|
|
||||||
|
@ -170,7 +174,7 @@ class ModelData {
|
||||||
MixData mixData[CPN_MAX_MIXERS];
|
MixData mixData[CPN_MAX_MIXERS];
|
||||||
LimitData limitData[CPN_MAX_CHNOUT];
|
LimitData limitData[CPN_MAX_CHNOUT];
|
||||||
|
|
||||||
char inputNames[CPN_MAX_INPUTS][4+1];
|
char inputNames[CPN_MAX_INPUTS][INPUT_NAME_LEN+1];
|
||||||
ExpoData expoData[CPN_MAX_EXPOS];
|
ExpoData expoData[CPN_MAX_EXPOS];
|
||||||
|
|
||||||
CurveData curves[CPN_MAX_CURVES];
|
CurveData curves[CPN_MAX_CURVES];
|
||||||
|
@ -219,11 +223,23 @@ class ModelData {
|
||||||
void setTrimValue(int phaseIdx, int trimIdx, int value);
|
void setTrimValue(int phaseIdx, int trimIdx, int value);
|
||||||
|
|
||||||
bool isGVarLinked(int phaseIdx, int gvarIdx);
|
bool isGVarLinked(int phaseIdx, int gvarIdx);
|
||||||
int getGVarFieldValue(int phaseIdx, int gvarIdx);
|
bool isGVarLinkedCircular(int phaseIdx, int gvarIdx);
|
||||||
float getGVarFieldValuePrec(int phaseIdx, int gvarIdx);
|
int getGVarValue(int phaseIdx, int gvarIdx);
|
||||||
|
float getGVarValuePrec(int phaseIdx, int gvarIdx);
|
||||||
|
int getGVarFlightModeIndex(const int phaseIdx, const int gvarIdx);
|
||||||
|
void setGVarFlightModeIndexToValue(const int phaseIdx, const int gvarIdx, const int useFmIdx);
|
||||||
|
|
||||||
|
bool isREncLinked(int phaseIdx, int reIdx);
|
||||||
|
bool isREncLinkedCircular(int phaseIdx, int reIdx);
|
||||||
|
int getREncValue(int phaseIdx, int reIdx);
|
||||||
|
int getREncFlightModeIndex(const int phaseIdx, const int reIdx);
|
||||||
|
void setREncFlightModeIndexToValue(const int phaseIdx, const int reIdx, const int useFmIdx);
|
||||||
|
|
||||||
ModelData removeGlobalVars();
|
ModelData removeGlobalVars();
|
||||||
|
|
||||||
|
int linkedFlightModeIndexToValue(const int phaseIdx, const int useFmIdx, const int maxOwnValue);
|
||||||
|
int linkedFlightModeValueToIndex(const int phaseIdx, const int val, const int maxOwnValue);
|
||||||
|
|
||||||
void clearMixes();
|
void clearMixes();
|
||||||
void clearInputs();
|
void clearInputs();
|
||||||
|
|
||||||
|
@ -231,8 +247,95 @@ class ModelData {
|
||||||
|
|
||||||
bool isAvailable(const RawSwitch & swtch) const;
|
bool isAvailable(const RawSwitch & swtch) const;
|
||||||
|
|
||||||
|
enum ReferenceUpdateAction {
|
||||||
|
REF_UPD_ACT_CLEAR,
|
||||||
|
REF_UPD_ACT_SHIFT,
|
||||||
|
REF_UPD_ACT_SWAP,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ReferenceUpdateType {
|
||||||
|
REF_UPD_TYPE_CHANNEL,
|
||||||
|
REF_UPD_TYPE_CURVE,
|
||||||
|
REF_UPD_TYPE_FLIGHT_MODE,
|
||||||
|
REF_UPD_TYPE_GLOBAL_VARIABLE,
|
||||||
|
REF_UPD_TYPE_INPUT,
|
||||||
|
REF_UPD_TYPE_LOGICAL_SWITCH,
|
||||||
|
REF_UPD_TYPE_SCRIPT,
|
||||||
|
REF_UPD_TYPE_SENSOR,
|
||||||
|
REF_UPD_TYPE_TIMER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UpdateReferenceParams
|
||||||
|
{
|
||||||
|
ReferenceUpdateType type;
|
||||||
|
ReferenceUpdateAction action;
|
||||||
|
int index1;
|
||||||
|
int index2;
|
||||||
|
int shift;
|
||||||
|
|
||||||
|
UpdateReferenceParams() {}
|
||||||
|
UpdateReferenceParams(ReferenceUpdateType t, ReferenceUpdateAction a, int i1, int i2 = 0, int s = 0) :
|
||||||
|
type(t), action(a), index1(i1), index2(i2), shift(s) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
int updateAllReferences(const ReferenceUpdateType type, const ReferenceUpdateAction action, const int index1, const int index2 = 0, const int shift = 0);
|
||||||
|
bool isExpoParent(const int index);
|
||||||
|
bool isExpoChild(const int index);
|
||||||
|
bool hasExpoChildren(const int index);
|
||||||
|
bool hasExpoSiblings(const int index);
|
||||||
|
void removeMix(const int idx);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void removeGlobalVar(int & var);
|
void removeGlobalVar(int & var);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<UpdateReferenceParams> *updRefList = nullptr;
|
||||||
|
|
||||||
|
struct UpdateReferenceInfo
|
||||||
|
{
|
||||||
|
ReferenceUpdateType type;
|
||||||
|
ReferenceUpdateAction action;
|
||||||
|
int index1;
|
||||||
|
int index2;
|
||||||
|
int shift;
|
||||||
|
int updcnt;
|
||||||
|
int maxindex;
|
||||||
|
RawSourceType srcType;
|
||||||
|
RawSwitchType swtchType;
|
||||||
|
};
|
||||||
|
UpdateReferenceInfo updRefInfo;
|
||||||
|
|
||||||
|
int updateReference();
|
||||||
|
void appendUpdateReferenceParams(const ReferenceUpdateType type, const ReferenceUpdateAction action, const int index1, const int index2 = 0, const int shift = 0);
|
||||||
|
template <class R, typename T>
|
||||||
|
void updateTypeIndexRef(R & curref, const T type, const int idxAdj = 0, const bool defClear = true, const int defType = 0, const int defIndex = 0);
|
||||||
|
template <class R, typename T>
|
||||||
|
void updateTypeValueRef(R & curref, const T type, const int idxAdj = 0, const bool defClear = true, const int defType = 0, const int defValue = 0);
|
||||||
|
void updateAdjustRef(int & adj);
|
||||||
|
void updateAssignFunc(CustomFunctionData * cfd);
|
||||||
|
void updateCurveRef(CurveReference & crv);
|
||||||
|
void updateDestCh(MixData * md);
|
||||||
|
void updateLimitCurveRef(CurveReference & crv);
|
||||||
|
void updateFlightModeFlags(unsigned int & flags);
|
||||||
|
void updateTelemetryRef(unsigned int & idx);
|
||||||
|
void updateModuleFailsafes(ModuleData * md);
|
||||||
|
inline void updateSourceRef(RawSource & src) { updateTypeIndexRef<RawSource, RawSourceType>(src, updRefInfo.srcType); }
|
||||||
|
inline void updateSwitchRef(RawSwitch & swtch) { updateTypeIndexRef<RawSwitch, RawSwitchType>(swtch, updRefInfo.swtchType, 1); }
|
||||||
|
inline void updateTimerMode(RawSwitch & swtch) { updateTypeIndexRef<RawSwitch, RawSwitchType>(swtch, updRefInfo.swtchType, 1, false, (int)SWITCH_TYPE_TIMER_MODE, 0); }
|
||||||
|
inline void updateSourceIntRef(int & value)
|
||||||
|
{
|
||||||
|
RawSource src = RawSource(value);
|
||||||
|
updateTypeIndexRef<RawSource, RawSourceType>(src, updRefInfo.srcType);
|
||||||
|
if (value != src.toValue())
|
||||||
|
value = src.toValue();
|
||||||
|
}
|
||||||
|
inline void updateSwitchIntRef(int & value)
|
||||||
|
{
|
||||||
|
RawSwitch swtch = RawSwitch(value);
|
||||||
|
updateTypeIndexRef<RawSwitch, RawSwitchType>(swtch, updRefInfo.swtchType, 1);
|
||||||
|
if (value != swtch.toValue())
|
||||||
|
value = swtch.toValue();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MODELDATA_H
|
#endif // MODELDATA_H
|
||||||
|
|
|
@ -181,3 +181,59 @@ QStringList ModuleData::powerValueStrings(int subType, Firmware * fw)
|
||||||
strIdx += 2;
|
strIdx += 2;
|
||||||
return strings[strIdx];
|
return strings[strIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ModuleData::hasFailsafes(Firmware * fw) const
|
||||||
|
{
|
||||||
|
return fw->getCapability(HasFailsafe) && (
|
||||||
|
protocol == PULSES_ACCESS_ISRM ||
|
||||||
|
protocol == PULSES_ACCST_ISRM_D16 ||
|
||||||
|
protocol == PULSES_PXX_XJT_X16 ||
|
||||||
|
protocol == PULSES_PXX_R9M ||
|
||||||
|
protocol == PULSES_ACCESS_R9M ||
|
||||||
|
protocol == PULSES_ACCESS_R9M_LITE ||
|
||||||
|
protocol == PULSES_ACCESS_R9M_LITE_PRO ||
|
||||||
|
protocol == PULSES_XJT_LITE_X16 ||
|
||||||
|
protocol == PULSES_MULTIMODULE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModuleData::getMaxChannelCount()
|
||||||
|
{
|
||||||
|
switch (protocol) {
|
||||||
|
case PULSES_ACCESS_ISRM:
|
||||||
|
return 24;
|
||||||
|
case PULSES_PXX_R9M:
|
||||||
|
case PULSES_ACCESS_R9M:
|
||||||
|
case PULSES_ACCESS_R9M_LITE:
|
||||||
|
case PULSES_ACCESS_R9M_LITE_PRO:
|
||||||
|
case PULSES_ACCST_ISRM_D16:
|
||||||
|
case PULSES_XJT_LITE_X16:
|
||||||
|
case PULSES_PXX_XJT_X16:
|
||||||
|
case PULSES_CROSSFIRE:
|
||||||
|
case PULSES_SBUS:
|
||||||
|
case PULSES_PPM:
|
||||||
|
return 16;
|
||||||
|
case PULSES_XJT_LITE_LR12:
|
||||||
|
case PULSES_PXX_XJT_LR12:
|
||||||
|
return 12;
|
||||||
|
case PULSES_PXX_DJT:
|
||||||
|
case PULSES_XJT_LITE_D8:
|
||||||
|
case PULSES_PXX_XJT_D8:
|
||||||
|
return 8;
|
||||||
|
case PULSES_LP45:
|
||||||
|
case PULSES_DSM2:
|
||||||
|
case PULSES_DSMX:
|
||||||
|
return 6;
|
||||||
|
case PULSES_MULTIMODULE:
|
||||||
|
if (multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
|
||||||
|
return 12;
|
||||||
|
else
|
||||||
|
return 16;
|
||||||
|
break;
|
||||||
|
case PULSES_OFF:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
|
@ -119,7 +119,20 @@ enum MultiModuleRFProtocols {
|
||||||
MODULE_SUBTYPE_MULTI_AFHDS2A_RX,
|
MODULE_SUBTYPE_MULTI_AFHDS2A_RX,
|
||||||
MODULE_SUBTYPE_MULTI_HOTT,
|
MODULE_SUBTYPE_MULTI_HOTT,
|
||||||
MODULE_SUBTYPE_MULTI_FX816,
|
MODULE_SUBTYPE_MULTI_FX816,
|
||||||
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_FX816
|
MODULE_SUBTYPE_MULTI_BAYANG_RX,
|
||||||
|
MODULE_SUBTYPE_MULTI_PELIKAN,
|
||||||
|
MODULE_SUBTYPE_MULTI_TIGER,
|
||||||
|
MODULE_SUBTYPE_MULTI_XK,
|
||||||
|
MODULE_SUBTYPE_MULTI_XN297DUMP,
|
||||||
|
MODULE_SUBTYPE_MULTI_FRSKYX2,
|
||||||
|
MODULE_SUBTYPE_MULTI_FRSKY_R9,
|
||||||
|
MODULE_SUBTYPE_MULTI_PROPEL,
|
||||||
|
MODULE_SUBTYPE_MULTI_FRSKYL,
|
||||||
|
MODULE_SUBTYPE_MULTI_SKYARTEC,
|
||||||
|
MODULE_SUBTYPE_MULTI_ESKY150V2,
|
||||||
|
MODULE_SUBTYPE_MULTI_DSM_RX,
|
||||||
|
MODULE_SUBTYPE_MULTI_JJRC345,
|
||||||
|
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_JJRC345
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TrainerProtocol {
|
enum TrainerProtocol {
|
||||||
|
@ -197,6 +210,8 @@ class ModuleData {
|
||||||
static QString indexToString(int index, Firmware * fw);
|
static QString indexToString(int index, Firmware * fw);
|
||||||
static QString protocolToString(unsigned protocol);
|
static QString protocolToString(unsigned protocol);
|
||||||
static QStringList powerValueStrings(int subType, Firmware * fw);
|
static QStringList powerValueStrings(int subType, Firmware * fw);
|
||||||
|
bool hasFailsafes(Firmware * fw) const;
|
||||||
|
int getMaxChannelCount();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MODULEDATA_H
|
#endif // MODULEDATA_H
|
||||||
|
|
|
@ -39,7 +39,7 @@ static const QStringList STR_SUBTYPE_CUSTOM ({
|
||||||
});
|
});
|
||||||
static const QStringList STR_SUBTYPE_FLYSKY {"Standard", "V9x9", "V6x6", "V912", "CX20"};
|
static const QStringList STR_SUBTYPE_FLYSKY {"Standard", "V9x9", "V6x6", "V912", "CX20"};
|
||||||
static const QStringList STR_SUBTYPE_HUBSAN {"H107", "H301", "H501"};
|
static const QStringList STR_SUBTYPE_HUBSAN {"H107", "H301", "H501"};
|
||||||
static const QStringList STR_SUBTYPE_FRSKY {"D16", "D8", "D16 8ch", "V8", "D16 EU-LBT", "D16 EU-LBT 8ch"};
|
static const QStringList STR_SUBTYPE_FRSKY {"D16", "D8", "D16 8ch", "V8", "D16 EU-LBT", "D16 EU-LBT 8ch", "D8 Cloned", "D16 Cloned"};
|
||||||
static const QStringList STR_SUBTYPE_HISKY {"Standard", "HK310"};
|
static const QStringList STR_SUBTYPE_HISKY {"Standard", "HK310"};
|
||||||
static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506"};
|
static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506"};
|
||||||
static const QStringList STR_SUBTYPE_DSM {"DSM2 22ms", "DSM2 11ms", "DSMX 22ms", "DSMX 11ms"};
|
static const QStringList STR_SUBTYPE_DSM {"DSM2 22ms", "DSM2 11ms", "DSMX 22ms", "DSMX 11ms"};
|
||||||
|
@ -51,6 +51,7 @@ static const QStringList STR_SUBTYPE_SLT {"V1 (6 Channel)", "V2 (8 Channel
|
||||||
static const QStringList STR_SUBTYPE_CX10 {"Green", "Blue", "DM007", "-", "JC3015a", "JC3015b", "MK33041"};
|
static const QStringList STR_SUBTYPE_CX10 {"Green", "Blue", "DM007", "-", "JC3015a", "JC3015b", "MK33041"};
|
||||||
static const QStringList STR_SUBTYPE_CG023 {"Standard", "YD829"};
|
static const QStringList STR_SUBTYPE_CG023 {"Standard", "YD829"};
|
||||||
static const QStringList STR_SUBTYPE_BAYANG {"Standard", "H8S3D", "X16 AH", "IRDRONE", "DHD D4"};
|
static const QStringList STR_SUBTYPE_BAYANG {"Standard", "H8S3D", "X16 AH", "IRDRONE", "DHD D4"};
|
||||||
|
static const QStringList STR_SUBTYPE_ESky {"Standard", "ET4"};
|
||||||
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
|
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
|
||||||
static const QStringList STR_SUBTYPE_MJXQ {"WLH08", "X600", "X800", "H26D", "E010", "H26WH", "Phoenix"};
|
static const QStringList STR_SUBTYPE_MJXQ {"WLH08", "X600", "X800", "H26D", "E010", "H26WH", "Phoenix"};
|
||||||
static const QStringList STR_SUBTYPE_FY326 {"Standard", "FY319"};
|
static const QStringList STR_SUBTYPE_FY326 {"Standard", "FY319"};
|
||||||
|
@ -60,20 +61,29 @@ static const QStringList STR_SUBTYPE_Q2X2 {"Q222", "Q242", "Q282"};
|
||||||
static const QStringList STR_SUBTYPE_WK2x01 {"WK2801", "WK2401", "W6_5_1", "W6_6_1", "W6_HEL", "W6_HEL_I"};
|
static const QStringList STR_SUBTYPE_WK2x01 {"WK2801", "WK2401", "W6_5_1", "W6_6_1", "W6_HEL", "W6_HEL_I"};
|
||||||
static const QStringList STR_SUBTYPE_Q303 {"Standard", "CX35", "CX10D", "CX10WD"};
|
static const QStringList STR_SUBTYPE_Q303 {"Standard", "CX35", "CX10D", "CX10WD"};
|
||||||
static const QStringList STR_SUBTYPE_CABELL {"Cabell V3", "Cab V3 Telem", "-", "-", "-", "-", "Set FailSafe", "Unbind"};
|
static const QStringList STR_SUBTYPE_CABELL {"Cabell V3", "Cab V3 Telem", "-", "-", "-", "-", "Set FailSafe", "Unbind"};
|
||||||
|
static const QStringList STR_SUBTYPE_ESKY150 {"4 Channel", "7 Channel"};
|
||||||
static const QStringList STR_SUBTYPE_H83D {"H8 Mini 3D", "H20H", "H20 Mini", "H30 Mini"};
|
static const QStringList STR_SUBTYPE_H83D {"H8 Mini 3D", "H20H", "H20 Mini", "H30 Mini"};
|
||||||
static const QStringList STR_SUBTYPE_CORONA {"Corona V1", "Corona V2", "Flydream V3"};
|
static const QStringList STR_SUBTYPE_CORONA {"Corona V1", "Corona V2", "Flydream V3"};
|
||||||
static const QStringList STR_SUBTYPE_HITEC {"Optima", "Optima Hub Telem", "Minima"};
|
static const QStringList STR_SUBTYPE_HITEC {"Optima", "Optima Hub Telem", "Minima"};
|
||||||
static const QStringList STR_SUBTYPE_TRAXXAS {"6519 RX"};
|
static const QStringList STR_SUBTYPE_WFLY {"WFR0xS"};
|
||||||
static const QStringList STR_SUBTYPE_BUGS_MINI {"Standard", "Bugs 3H"};
|
static const QStringList STR_SUBTYPE_BUGS_MINI {"Standard", "Bugs 3H"};
|
||||||
|
static const QStringList STR_SUBTYPE_TRAXXAS {"6519 RX"};
|
||||||
static const QStringList STR_SUBTYPE_E01X {"E012", "E015", "E016H"};
|
static const QStringList STR_SUBTYPE_E01X {"E012", "E015", "E016H"};
|
||||||
|
static const QStringList STR_SUBTYPE_V911S {"Standard", "E119"};
|
||||||
static const QStringList STR_SUBTYPE_GD00X {"GD V1", "GD V2"};
|
static const QStringList STR_SUBTYPE_GD00X {"GD V1", "GD V2"};
|
||||||
static const QStringList STR_SUBTYPE_REDPINE {"Fast", "Slow"};
|
static const QStringList STR_SUBTYPE_REDPINE {"Fast", "Slow"};
|
||||||
static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"};
|
static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"};
|
||||||
static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"};
|
static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"};
|
||||||
static const QStringList STR_SUBTYPE_FLYZONE {"FZ-410 TX"};
|
static const QStringList STR_SUBTYPE_FLYZONE {"FZ-410 TX"};
|
||||||
static const QStringList STR_SUBTYPE_FRSKYX_RX {"D16 FCC", "D16 LBT"};
|
static const QStringList STR_SUBTYPE_FRSKYX_RX {"RX", "Clone TX"};
|
||||||
static const QStringList STR_SUBTYPE_FX816 {"P38"};
|
static const QStringList STR_SUBTYPE_FX816 {"P38"};
|
||||||
static const QStringList STR_SUBTYPE_ESKY150 {"4CH", "7CH"};
|
static const QStringList STR_SUBTYPE_XK {"X450", "X420"};
|
||||||
|
static const QStringList STR_SUBTYPE_XN297DUMP {"250K", "1M", "2M", "AUTO"};
|
||||||
|
static const QStringList STR_SUBTYPE_FRSKYX2 {"D16", "D16 8ch", "D16 EU-LBT", "D16 EU-LBT 8ch", "D16 Cloned"};
|
||||||
|
static const QStringList STR_SUBTYPE_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel"};
|
||||||
|
static const QStringList STR_SUBTYPE_PROPEL {"74-Z"};
|
||||||
|
static const QStringList STR_SUBTYPE_FRSKYL {"LR12", "LR12 6-Channel"};
|
||||||
|
static const QStringList STR_SUBTYPE_ESKY150V2 {"150 V2"};
|
||||||
|
|
||||||
static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
|
static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
|
||||||
|
|
||||||
|
@ -83,7 +93,7 @@ static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
|
||||||
const Multiprotocols multiProtocols {
|
const Multiprotocols multiProtocols {
|
||||||
{MODULE_SUBTYPE_MULTI_FLYSKY, 4, false, STR_SUBTYPE_FLYSKY, nullptr},
|
{MODULE_SUBTYPE_MULTI_FLYSKY, 4, false, STR_SUBTYPE_FLYSKY, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
|
{MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
|
||||||
{MODULE_SUBTYPE_MULTI_FRSKY, 5, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_FRSKY, 7, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_HISKY, 1, false, STR_SUBTYPE_HISKY, nullptr},
|
{MODULE_SUBTYPE_MULTI_HISKY, 1, false, STR_SUBTYPE_HISKY, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_V2X2, 1, false, STR_SUBTYPE_V2X2, nullptr},
|
{MODULE_SUBTYPE_MULTI_V2X2, 1, false, STR_SUBTYPE_V2X2, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_DSM2, 3, false, STR_SUBTYPE_DSM, nullptr},
|
{MODULE_SUBTYPE_MULTI_DSM2, 3, false, STR_SUBTYPE_DSM, nullptr},
|
||||||
|
@ -91,14 +101,16 @@ const Multiprotocols multiProtocols {
|
||||||
{MODULE_SUBTYPE_MULTI_YD717, 4, false, STR_SUBTYPE_YD717, nullptr},
|
{MODULE_SUBTYPE_MULTI_YD717, 4, false, STR_SUBTYPE_YD717, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_KN, 1, false, STR_SUBTYPE_KN, nullptr},
|
{MODULE_SUBTYPE_MULTI_KN, 1, false, STR_SUBTYPE_KN, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_SYMAX, 1, false, STR_SUBTYPE_SYMAX, nullptr},
|
{MODULE_SUBTYPE_MULTI_SYMAX, 1, false, STR_SUBTYPE_SYMAX, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_SLT, 4, false, STR_SUBTYPE_SLT, nullptr},
|
{MODULE_SUBTYPE_MULTI_SLT, 4, false, STR_SUBTYPE_SLT, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_CX10, 6, false, STR_SUBTYPE_CX10, nullptr},
|
{MODULE_SUBTYPE_MULTI_CX10, 6, false, STR_SUBTYPE_CX10, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_CG023, 1, false, STR_SUBTYPE_CG023, nullptr},
|
{MODULE_SUBTYPE_MULTI_CG023, 1, false, STR_SUBTYPE_CG023, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_BAYANG, 4, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
|
{MODULE_SUBTYPE_MULTI_BAYANG, 4, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
|
||||||
|
{MODULE_SUBTYPE_MULTI_ESky, 1, false, STR_SUBTYPE_ESky, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_MT99XX, 4, false, STR_SUBTYPE_MT99, nullptr},
|
{MODULE_SUBTYPE_MULTI_MT99XX, 4, false, STR_SUBTYPE_MT99, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_MJXQ, 6, false, STR_SUBTYPE_MJXQ, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_MJXQ, 6, false, STR_SUBTYPE_MJXQ, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_FY326, 1, false, STR_SUBTYPE_FY326, nullptr},
|
{MODULE_SUBTYPE_MULTI_FY326, 1, false, STR_SUBTYPE_FY326, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_SFHSS, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_SFHSS, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
||||||
|
{MODULE_SUBTYPE_MULTI_J6PRO, 0, false, NO_SUBTYPE, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_HONTAI, 3, false, STR_SUBTYPE_HONTAI, nullptr},
|
{MODULE_SUBTYPE_MULTI_HONTAI, 3, false, STR_SUBTYPE_HONTAI, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_OLRS, 0, false, NO_SUBTYPE, STR_MULTI_RFPOWER},
|
{MODULE_SUBTYPE_MULTI_OLRS, 0, false, NO_SUBTYPE, STR_MULTI_RFPOWER},
|
||||||
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 3, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
|
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 3, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
|
||||||
|
@ -106,25 +118,32 @@ const Multiprotocols multiProtocols {
|
||||||
{MODULE_SUBTYPE_MULTI_WK_2X01, 5, false, STR_SUBTYPE_WK2x01, nullptr},
|
{MODULE_SUBTYPE_MULTI_WK_2X01, 5, false, STR_SUBTYPE_WK2x01, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_Q303, 3, false, STR_SUBTYPE_Q303, nullptr},
|
{MODULE_SUBTYPE_MULTI_Q303, 3, false, STR_SUBTYPE_Q303, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_CABELL, 7, false, STR_SUBTYPE_CABELL, STR_MULTI_OPTION},
|
{MODULE_SUBTYPE_MULTI_CABELL, 7, false, STR_SUBTYPE_CABELL, STR_MULTI_OPTION},
|
||||||
|
{MODULE_SUBTYPE_MULTI_ESKY150, 1, false, STR_SUBTYPE_ESKY150, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_H83D, 3, false, STR_SUBTYPE_H83D, nullptr},
|
{MODULE_SUBTYPE_MULTI_H83D, 3, false, STR_SUBTYPE_H83D, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_CORONA, 2, false, STR_SUBTYPE_CORONA, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_CORONA, 2, false, STR_SUBTYPE_CORONA, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_HITEC, 2, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_HITEC, 2, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE},
|
||||||
|
{MODULE_SUBTYPE_MULTI_WFLY, 0, false, STR_SUBTYPE_WFLY, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_BUGS_MINI, 1, false, STR_SUBTYPE_BUGS_MINI, nullptr},
|
{MODULE_SUBTYPE_MULTI_BUGS_MINI, 1, false, STR_SUBTYPE_BUGS_MINI, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_TRAXXAS, 0, false, STR_SUBTYPE_TRAXXAS, nullptr},
|
{MODULE_SUBTYPE_MULTI_TRAXXAS, 0, false, STR_SUBTYPE_TRAXXAS, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION},
|
{MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION},
|
||||||
{MODULE_SUBTYPE_MULTI_V911S, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_V911S, 1, false, STR_SUBTYPE_V911S, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_GD00X, 1, false, STR_SUBTYPE_GD00X, nullptr},
|
{MODULE_SUBTYPE_MULTI_GD00X, 1, false, STR_SUBTYPE_GD00X, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_KF606, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_KF606, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr},
|
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_ZSX, 0, false, STR_SUBTYPE_ZSX, nullptr},
|
{MODULE_SUBTYPE_MULTI_ZSX, 0, false, STR_SUBTYPE_ZSX, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, STR_SUBTYPE_FLYZONE, nullptr},
|
{MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, STR_SUBTYPE_FLYZONE, nullptr},
|
||||||
{MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE},
|
||||||
{MODULE_SUBTYPE_MULTI_ESky, 0, false, NO_SUBTYPE, nullptr},
|
|
||||||
{MODULE_SUBTYPE_MULTI_J6PRO, 0, false, NO_SUBTYPE, nullptr},
|
|
||||||
{MODULE_SUBTYPE_MULTI_ESKY150, 1, false, STR_SUBTYPE_ESKY150, nullptr},
|
|
||||||
{MODULE_SUBTYPE_MULTI_FX816, 0, false, STR_SUBTYPE_FX816, nullptr},
|
|
||||||
{MODULE_SUBTYPE_MULTI_HOTT, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
{MODULE_SUBTYPE_MULTI_HOTT, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
||||||
|
{MODULE_SUBTYPE_MULTI_FX816, 0, false, STR_SUBTYPE_FX816, nullptr},
|
||||||
|
{MODULE_SUBTYPE_MULTI_XK, 1, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE},
|
||||||
|
{MODULE_SUBTYPE_MULTI_XN297DUMP, 3, false, STR_SUBTYPE_XN297DUMP, nullptr},
|
||||||
|
{MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
|
||||||
|
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, STR_SUBTYPE_FRSKYR9, nullptr},
|
||||||
|
{MODULE_SUBTYPE_MULTI_PROPEL, 0, false, STR_SUBTYPE_PROPEL, nullptr},
|
||||||
|
{MODULE_SUBTYPE_MULTI_FRSKYL, 1, false, STR_SUBTYPE_FRSKYL, STR_MULTI_RFTUNE},
|
||||||
|
{MODULE_SUBTYPE_MULTI_SKYARTEC, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
||||||
|
{MODULE_SUBTYPE_MULTI_ESKY150V2, 0, false, STR_SUBTYPE_ESKY150V2, STR_MULTI_RFTUNE},
|
||||||
{MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION},
|
{MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION},
|
||||||
|
|
||||||
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
|
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
|
||||||
|
@ -165,14 +184,13 @@ QString Multiprotocols::protocolToString(int protocol, bool custom)
|
||||||
static const QStringList strings({
|
static const QStringList strings({
|
||||||
"FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
|
"FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
|
||||||
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
|
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
|
||||||
"FlySky AFHDS2A", "Q2x2", "Walkera", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie",
|
"FlySky AFHDS2A", "Q2x2", "WK2x01", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie",
|
||||||
"Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "WL Heli V911S", "GD00X", "Volantex V761",
|
"Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "WL Heli V911S", "GD00X", "Volantex V761",
|
||||||
"KFPlan KF606", "Redpine", "Potensic", "ZXS", "FlyZone", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816"
|
"KFPlan KF606", "Redpine", "Potensic", "ZSX", "FlyZone", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816",
|
||||||
|
"Bayang RX", "Pelikan", "Tiger", "XK", "XN297 Dump", "FrSky X 2.1", "FrSky R9", "Propel", "FrSky L", "Skyartec",
|
||||||
|
"ESky 150v2", "DSM RX", "JJRC345"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (protocol == MM_RF_CUSTOM_SELECTED || custom)
|
|
||||||
return tr("Custom - proto %1)").arg(protocol);
|
|
||||||
else
|
|
||||||
return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);
|
return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -693,11 +693,13 @@ class FlightModeField: public TransformedField {
|
||||||
internalField.Append(new UnsignedField<8>(this, phase.fadeIn));
|
internalField.Append(new UnsignedField<8>(this, phase.fadeIn));
|
||||||
internalField.Append(new UnsignedField<8>(this, phase.fadeOut));
|
internalField.Append(new UnsignedField<8>(this, phase.fadeOut));
|
||||||
|
|
||||||
for (int i=0; i<rotencCount; i++) {
|
if (version < 219) {
|
||||||
|
for (int i = 0; i < rotencCount; i++) {
|
||||||
internalField.Append(new SignedField<16>(this, phase.rotaryEncoders[i]));
|
internalField.Append(new SignedField<16>(this, phase.rotaryEncoders[i]));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<MAX_GVARS(board, version); i++) {
|
for (int i = 0; i < MAX_GVARS(board, version); i++) {
|
||||||
internalField.Append(new SignedField<16>(this, phase.gvars[i]));
|
internalField.Append(new SignedField<16>(this, phase.gvars[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1914,7 +1916,7 @@ class SensorField: public TransformedField {
|
||||||
internalField.Append(new UnsignedField<32>(this, _param, "param"));
|
internalField.Append(new UnsignedField<32>(this, _param, "param"));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void beforeExport()
|
void beforeExport() override
|
||||||
{
|
{
|
||||||
if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) {
|
if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) {
|
||||||
_id = sensor.id;
|
_id = sensor.id;
|
||||||
|
@ -2037,7 +2039,7 @@ class ModuleUnionField: public UnionField<unsigned int> {
|
||||||
module(module),
|
module(module),
|
||||||
rfProtExtra(0)
|
rfProtExtra(0)
|
||||||
{
|
{
|
||||||
ModuleData::Multi& multi = module.multi;
|
ModuleData::Multi & multi = module.multi;
|
||||||
internalField.Append(new UnsignedField<3>(this, rfProtExtra));
|
internalField.Append(new UnsignedField<3>(this, rfProtExtra));
|
||||||
internalField.Append(new BoolField<1>(this, multi.disableTelemetry));
|
internalField.Append(new BoolField<1>(this, multi.disableTelemetry));
|
||||||
internalField.Append(new BoolField<1>(this, multi.disableMapping));
|
internalField.Append(new BoolField<1>(this, multi.disableMapping));
|
||||||
|
@ -2054,22 +2056,17 @@ class ModuleUnionField: public UnionField<unsigned int> {
|
||||||
|
|
||||||
void beforeExport() override
|
void beforeExport() override
|
||||||
{
|
{
|
||||||
if (module.multi.rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
|
|
||||||
module.multi.rfProtocol += 3;
|
|
||||||
rfProtExtra = (module.multi.rfProtocol & 0x70) >> 4;
|
rfProtExtra = (module.multi.rfProtocol & 0x70) >> 4;
|
||||||
module.multi.rfProtocol &= 0x0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void afterImport() override
|
void afterImport() override
|
||||||
{
|
{
|
||||||
module.multi.rfProtocol = (rfProtExtra << 4) + (module.rfProtocol & 0xf);
|
module.multi.rfProtocol = (rfProtExtra << 4) + (module.rfProtocol & 0xf);
|
||||||
if (module.multi.rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
|
|
||||||
module.multi.rfProtocol -= 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StructField internalField;
|
StructField internalField;
|
||||||
ModuleData& module;
|
ModuleData & module;
|
||||||
unsigned int rfProtExtra;
|
unsigned int rfProtExtra;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2133,7 +2130,8 @@ class ModuleUnionField: public UnionField<unsigned int> {
|
||||||
memset(receiverName, 0, sizeof(receiverName));
|
memset(receiverName, 0, sizeof(receiverName));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool select(const unsigned int& attr) const override {
|
bool select(const unsigned int& attr) const override
|
||||||
|
{
|
||||||
return attr >= PULSES_ACCESS_ISRM && attr <= PULSES_ACCESS_R9M_LITE_PRO;
|
return attr >= PULSES_ACCESS_ISRM && attr <= PULSES_ACCESS_R9M_LITE_PRO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2141,7 +2139,6 @@ class ModuleUnionField: public UnionField<unsigned int> {
|
||||||
{
|
{
|
||||||
for (int i=0; i<PXX2_MAX_RECEIVERS_PER_MODULE; i++) {
|
for (int i=0; i<PXX2_MAX_RECEIVERS_PER_MODULE; i++) {
|
||||||
for (int pos=0; pos<PXX2_LEN_RX_NAME+1; pos++) {
|
for (int pos=0; pos<PXX2_LEN_RX_NAME+1; pos++) {
|
||||||
|
|
||||||
if (pos == PXX2_LEN_RX_NAME || module.access.receiverName[i][pos] == '\0') {
|
if (pos == PXX2_LEN_RX_NAME || module.access.receiverName[i][pos] == '\0') {
|
||||||
memset(module.access.receiverName[i]+pos,'\0',PXX2_LEN_RX_NAME-pos);
|
memset(module.access.receiverName[i]+pos,'\0',PXX2_LEN_RX_NAME-pos);
|
||||||
break;
|
break;
|
||||||
|
@ -2222,7 +2219,7 @@ class ModuleField: public TransformedField {
|
||||||
module.subType = module.protocol - PULSES_PXX_XJT_X16;
|
module.subType = module.protocol - PULSES_PXX_XJT_X16;
|
||||||
}
|
}
|
||||||
else if (module.protocol == PULSES_MULTIMODULE) {
|
else if (module.protocol == PULSES_MULTIMODULE) {
|
||||||
module.rfProtocol = module.multi.rfProtocol & 0xf;
|
module.rfProtocol = module.multi.rfProtocol & 0x0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -564,7 +564,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
|
||||||
case SoundPitch:
|
case SoundPitch:
|
||||||
return 1;
|
return 1;
|
||||||
case Haptic:
|
case Haptic:
|
||||||
return (IS_2560(board) || IS_SKY9X(board) || IS_TARANIS_PLUS(board) || IS_TARANIS_SMALL(board) || IS_TARANIS_X9E(board) || IS_FAMILY_HORUS_OR_T16(board) || IS_JUMPER_T12(board) || id.contains("haptic"));
|
return board != Board::BOARD_TARANIS_X9D || id.contains("haptic");
|
||||||
case ModelTrainerEnable:
|
case ModelTrainerEnable:
|
||||||
if (IS_HORUS_OR_TARANIS(board) && board!=Board::BOARD_TARANIS_XLITE)
|
if (IS_HORUS_OR_TARANIS(board) && board!=Board::BOARD_TARANIS_XLITE)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -616,6 +616,10 @@ int OpenTxFirmware::getCapability(::Capability capability)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return IS_ARM(board) ? 4 : 2;
|
return IS_ARM(board) ? 4 : 2;
|
||||||
|
case TelemetryCustomScreensBars:
|
||||||
|
return (getCapability(TelemetryCustomScreens) ? 4 : 0);
|
||||||
|
case TelemetryCustomScreensLines:
|
||||||
|
return (getCapability(TelemetryCustomScreens) ? 4 : 0);
|
||||||
case TelemetryCustomScreensFieldsPerLine:
|
case TelemetryCustomScreensFieldsPerLine:
|
||||||
return HAS_LARGE_LCD(board) ? 3 : 2;
|
return HAS_LARGE_LCD(board) ? 3 : 2;
|
||||||
case NoTelemetryProtocol:
|
case NoTelemetryProtocol:
|
||||||
|
@ -754,6 +758,11 @@ int OpenTxFirmware::getCapability(::Capability capability)
|
||||||
return IS_TARANIS_XLITES(board);
|
return IS_TARANIS_XLITES(board);
|
||||||
case PwrButtonPress:
|
case PwrButtonPress:
|
||||||
return IS_HORUS_OR_TARANIS(board) && (board!=Board::BOARD_TARANIS_X9D) && (board!=Board::BOARD_TARANIS_X9DP);
|
return IS_HORUS_OR_TARANIS(board) && (board!=Board::BOARD_TARANIS_X9D) && (board!=Board::BOARD_TARANIS_X9DP);
|
||||||
|
case Sensors:
|
||||||
|
if (IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board))
|
||||||
|
return 60;
|
||||||
|
else
|
||||||
|
return 40;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -793,7 +802,7 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
|
||||||
case PULSES_ACCST_ISRM_D16:
|
case PULSES_ACCST_ISRM_D16:
|
||||||
return IS_ACCESS_RADIO(board, id);
|
return IS_ACCESS_RADIO(board, id);
|
||||||
case PULSES_MULTIMODULE:
|
case PULSES_MULTIMODULE:
|
||||||
return id.contains("internalmulti");
|
return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1252,6 +1261,7 @@ void registerOpenTxFirmwares()
|
||||||
|
|
||||||
/* FrSky Taranis X9D board */
|
/* FrSky Taranis X9D board */
|
||||||
firmware = new OpenTxFirmware("opentx-x9d", Firmware::tr("FrSky Taranis X9D"), BOARD_TARANIS_X9D);
|
firmware = new OpenTxFirmware("opentx-x9d", Firmware::tr("FrSky Taranis X9D"), BOARD_TARANIS_X9D);
|
||||||
|
firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
|
||||||
firmware->addOption("haptic", Firmware::tr("Haptic module installed"));
|
firmware->addOption("haptic", Firmware::tr("Haptic module installed"));
|
||||||
addOpenTxTaranisOptions(firmware);
|
addOpenTxTaranisOptions(firmware);
|
||||||
addPPMInternalModuleHack(firmware);
|
addPPMInternalModuleHack(firmware);
|
||||||
|
@ -1331,7 +1341,6 @@ void registerOpenTxFirmwares()
|
||||||
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
|
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
|
||||||
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
|
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
|
||||||
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
|
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
|
||||||
firmware->addOption("flexr9m", Firmware::tr("Enable non certified R9M firmwares"));
|
|
||||||
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
|
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
|
||||||
addOpenTxFontOptions(firmware);
|
addOpenTxFontOptions(firmware);
|
||||||
registerOpenTxFirmware(firmware);
|
registerOpenTxFirmware(firmware);
|
||||||
|
@ -1342,15 +1351,17 @@ void registerOpenTxFirmwares()
|
||||||
addOpenTxFrskyOptions(firmware);
|
addOpenTxFrskyOptions(firmware);
|
||||||
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
|
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
|
||||||
firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
|
firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
|
||||||
registerOpenTxFirmware(firmware);
|
|
||||||
addOpenTxRfOptions(firmware, FLEX);
|
addOpenTxRfOptions(firmware, FLEX);
|
||||||
|
registerOpenTxFirmware(firmware);
|
||||||
|
|
||||||
// TX16S is unavailable until finalized
|
/* Radiomaster TX16S board */
|
||||||
/* Radiomaster TX16S board
|
|
||||||
firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16s / TX16s Hall / TX16s Masterfire"), BOARD_RADIOMASTER_TX16S);
|
firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16s / TX16s Hall / TX16s Masterfire"), BOARD_RADIOMASTER_TX16S);
|
||||||
addOpenTxFrskyOptions(firmware);
|
addOpenTxFrskyOptions(firmware);
|
||||||
firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
|
addOpenTxRfOptions(firmware, FLEX);
|
||||||
registerOpenTxFirmware(firmware);*/
|
static const Firmware::Option opt_bt("bluetooth", Firmware::tr("Support for bluetooth module"));
|
||||||
|
static const Firmware::Option opt_internal_gps("internalgps", Firmware::tr("Support internal GPS"));
|
||||||
|
firmware->addOptionsGroup({opt_bt, opt_internal_gps});
|
||||||
|
registerOpenTxFirmware(firmware);
|
||||||
|
|
||||||
/* 9XR-Pro */
|
/* 9XR-Pro */
|
||||||
firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO);
|
firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO);
|
||||||
|
|
|
@ -227,11 +227,7 @@ class RawSource {
|
||||||
AllSourceGroups = InputSourceGroups | GVarsGroup | TelemGroup | ScriptsGroup
|
AllSourceGroups = InputSourceGroups | GVarsGroup | TelemGroup | ScriptsGroup
|
||||||
};
|
};
|
||||||
|
|
||||||
RawSource():
|
RawSource() { clear(); }
|
||||||
type(SOURCE_TYPE_NONE),
|
|
||||||
index(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit RawSource(int value):
|
explicit RawSource(int value):
|
||||||
type(RawSourceType(abs(value)/65536)),
|
type(RawSourceType(abs(value)/65536)),
|
||||||
|
@ -258,6 +254,8 @@ class RawSource {
|
||||||
bool isSlider(int * sliderIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
bool isSlider(int * sliderIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||||
bool isTimeBased(Board::Type board = Board::BOARD_UNKNOWN) const;
|
bool isTimeBased(Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||||
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||||
|
bool isSet() const { return type != SOURCE_TYPE_NONE || index != 0; }
|
||||||
|
void clear() { type = SOURCE_TYPE_NONE; index = 0; }
|
||||||
|
|
||||||
bool operator == ( const RawSource & other) const {
|
bool operator == ( const RawSource & other) const {
|
||||||
return (this->type == other.type) && (this->index == other.index);
|
return (this->type == other.type) && (this->index == other.index);
|
||||||
|
|
|
@ -65,11 +65,7 @@ class RawSwitch {
|
||||||
AllSwitchContexts = AllModelContexts | GlobalFunctionsContext
|
AllSwitchContexts = AllModelContexts | GlobalFunctionsContext
|
||||||
};
|
};
|
||||||
|
|
||||||
RawSwitch():
|
RawSwitch() { clear(); }
|
||||||
type(SWITCH_TYPE_NONE),
|
|
||||||
index(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit RawSwitch(int value):
|
explicit RawSwitch(int value):
|
||||||
type(RawSwitchType(abs(value)/256)),
|
type(RawSwitchType(abs(value)/256)),
|
||||||
|
@ -91,6 +87,8 @@ class RawSwitch {
|
||||||
RawSwitch convert(RadioDataConversionState & cstate);
|
RawSwitch convert(RadioDataConversionState & cstate);
|
||||||
QString toString(Board::Type board = Board::BOARD_UNKNOWN, const GeneralSettings * const generalSettings = NULL, const ModelData * const modelData = NULL) const;
|
QString toString(Board::Type board = Board::BOARD_UNKNOWN, const GeneralSettings * const generalSettings = NULL, const ModelData * const modelData = NULL) const;
|
||||||
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||||
|
bool isSet() const { return type != SWITCH_TYPE_NONE || index != 0; }
|
||||||
|
void clear() { type = SWITCH_TYPE_NONE; index = 0; }
|
||||||
|
|
||||||
bool operator== ( const RawSwitch& other) const {
|
bool operator== ( const RawSwitch& other) const {
|
||||||
return (this->type == other.type) && (this->index == other.index);
|
return (this->type == other.type) && (this->index == other.index);
|
||||||
|
@ -100,7 +98,6 @@ class RawSwitch {
|
||||||
return (this->type != other.type) || (this->index != other.index);
|
return (this->type != other.type) || (this->index != other.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RawSwitchType type;
|
RawSwitchType type;
|
||||||
int index;
|
int index;
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,6 +82,8 @@ QString SensorData::unitString() const
|
||||||
return tr("seconds");
|
return tr("seconds");
|
||||||
case UNIT_CELLS:
|
case UNIT_CELLS:
|
||||||
return tr("V");
|
return tr("V");
|
||||||
|
case UNIT_MILLILITERS_PER_MINUTE:
|
||||||
|
return tr("ml/minute");
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ class SensorData {
|
||||||
UNIT_RADIANS,
|
UNIT_RADIANS,
|
||||||
UNIT_MILLILITERS,
|
UNIT_MILLILITERS,
|
||||||
UNIT_FLOZ,
|
UNIT_FLOZ,
|
||||||
|
UNIT_MILLILITERS_PER_MINUTE,
|
||||||
UNIT_HOURS,
|
UNIT_HOURS,
|
||||||
UNIT_MINUTES,
|
UNIT_MINUTES,
|
||||||
UNIT_SECONDS,
|
UNIT_SECONDS,
|
||||||
|
|
|
@ -1124,7 +1124,7 @@ p, li { white-space: pre-wrap; }
|
||||||
<item row="19" column="1">
|
<item row="19" column="1">
|
||||||
<widget class="QLineEdit" name="registrationId">
|
<widget class="QLineEdit" name="registrationId">
|
||||||
<property name="inputMask">
|
<property name="inputMask">
|
||||||
<string>aaaaaaAA</string>
|
<string>nnnnnnNN</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="maxLength">
|
<property name="maxLength">
|
||||||
<number>8</number>
|
<number>8</number>
|
||||||
|
|
0
companion/src/images/simulator/TX16S/bottom.png
Executable file → Normal file
Before Width: | Height: | Size: 250 B After Width: | Height: | Size: 250 B |
BIN
companion/src/images/simulator/TX16S/left.png
Executable file → Normal file
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 31 KiB |
BIN
companion/src/images/simulator/TX16S/left_page.png
Executable file → Normal file
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 31 KiB |
BIN
companion/src/images/simulator/TX16S/left_page2.png
Executable file → Normal file
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 31 KiB |
BIN
companion/src/images/simulator/TX16S/left_rtn.png
Executable file → Normal file
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 31 KiB |
BIN
companion/src/images/simulator/TX16S/left_sys.png
Executable file → Normal file
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 31 KiB |
BIN
companion/src/images/simulator/TX16S/left_tele.png
Executable file → Normal file
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 31 KiB |
0
companion/src/images/simulator/TX16S/right.png
Executable file → Normal file
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
0
companion/src/images/simulator/TX16S/right_ent.png
Executable file → Normal file
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
0
companion/src/images/simulator/TX16S/right_mdl.png
Executable file → Normal file
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
0
companion/src/images/simulator/TX16S/top.png
Executable file → Normal file
Before Width: | Height: | Size: 439 B After Width: | Height: | Size: 439 B |
|
@ -1,500 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>preferencesDialog</class>
|
|
||||||
<widget class="QDialog" name="preferencesDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>685</width>
|
|
||||||
<height>432</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>685</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Preferences</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="1">
|
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetMinimumSize</enum>
|
|
||||||
</property>
|
|
||||||
<property name="verticalSpacing">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>4</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>8</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="snapshotPath">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Simu BackLight</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_19">
|
|
||||||
<property name="text">
|
|
||||||
<string>Simulator capture folder</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_11">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Joystick</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remember simulator switches</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QCheckBox" name="simuSW">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="joystickCB">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="joystickChkB">
|
|
||||||
<property name="text">
|
|
||||||
<string>Enable</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QCheckBox" name="snapshotClipboardCKB">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use clipboard only</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QPushButton" name="joystickcalButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Calibrate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="backLightColor">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Blue</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Green</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Red</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Orange</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Yellow</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QPushButton" name="snapshotPathButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open Folder</string>
|
|
||||||
</property>
|
|
||||||
<property name="flat">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_7">
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Personal splash library</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="libraryPath">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="libraryPathButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open Folder</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="splashincludeCB">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Include companion splashes</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Only user defined splashes</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Splash library behaviour</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Custom TX splash screen</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="SplashFileName">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="SplashSelect">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Open Image</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="SplashLibraryDialogButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="clearImageButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="InvertPixels">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Invert Pixels</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="imageLabel">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>128</width>
|
|
||||||
<height>64</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>128</width>
|
|
||||||
<height>64</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::Panel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Raised</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="scaledContents">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_3">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<tabstops>
|
|
||||||
<tabstop>backLightColor</tabstop>
|
|
||||||
<tabstop>joystickCB</tabstop>
|
|
||||||
<tabstop>joystickChkB</tabstop>
|
|
||||||
<tabstop>joystickcalButton</tabstop>
|
|
||||||
<tabstop>simuSW</tabstop>
|
|
||||||
<tabstop>snapshotPath</tabstop>
|
|
||||||
<tabstop>snapshotPathButton</tabstop>
|
|
||||||
<tabstop>snapshotClipboardCKB</tabstop>
|
|
||||||
<tabstop>libraryPath</tabstop>
|
|
||||||
<tabstop>libraryPathButton</tabstop>
|
|
||||||
<tabstop>splashincludeCB</tabstop>
|
|
||||||
<tabstop>SplashFileName</tabstop>
|
|
||||||
<tabstop>SplashSelect</tabstop>
|
|
||||||
<tabstop>SplashLibraryDialogButton</tabstop>
|
|
||||||
<tabstop>clearImageButton</tabstop>
|
|
||||||
<tabstop>InvertPixels</tabstop>
|
|
||||||
<tabstop>buttonBox</tabstop>
|
|
||||||
</tabstops>
|
|
||||||
<resources>
|
|
||||||
<include location="companion.qrc"/>
|
|
||||||
</resources>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>preferencesDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>370</x>
|
|
||||||
<y>49</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>preferencesDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>390</x>
|
|
||||||
<y>55</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "translations.h"
|
#include "translations.h"
|
||||||
|
|
||||||
#include "dialogs/filesyncdialog.h"
|
#include "dialogs/filesyncdialog.h"
|
||||||
|
#include "profilechooser.h"
|
||||||
|
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
@ -130,11 +131,17 @@ MainWindow::MainWindow():
|
||||||
else {
|
else {
|
||||||
if (!g.previousVersion().isEmpty())
|
if (!g.previousVersion().isEmpty())
|
||||||
g.warningId(g.warningId() | AppMessages::MSG_UPGRADED);
|
g.warningId(g.warningId() | AppMessages::MSG_UPGRADED);
|
||||||
|
if (g.promptProfile()) {
|
||||||
|
QTimer::singleShot(updateDelay, this, SLOT(chooseProfile())); // add an extra second to give mainwindow time to load
|
||||||
|
updateDelay += 5000; // give user time to select profile before warnings
|
||||||
|
}
|
||||||
|
else {
|
||||||
if (checkProfileRadioExists(g.sessionId()))
|
if (checkProfileRadioExists(g.sessionId()))
|
||||||
QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
|
QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
|
||||||
else
|
else
|
||||||
g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
|
g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
QTimer::singleShot(updateDelay, this, SLOT(displayWarnings()));
|
QTimer::singleShot(updateDelay, this, SLOT(displayWarnings()));
|
||||||
|
|
||||||
QStringList strl = QApplication::arguments();
|
QStringList strl = QApplication::arguments();
|
||||||
|
@ -916,14 +923,15 @@ void MainWindow::changelog()
|
||||||
|
|
||||||
void MainWindow::customizeSplash()
|
void MainWindow::customizeSplash()
|
||||||
{
|
{
|
||||||
CustomizeSplashDialog * dialog = new CustomizeSplashDialog(this);
|
auto * dialog = new CustomizeSplashDialog(this);
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
dialog->deleteLater();
|
dialog->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::writeEeprom()
|
void MainWindow::writeEeprom()
|
||||||
{
|
{
|
||||||
if (activeMdiChild()) activeMdiChild()->writeEeprom();
|
if (activeMdiChild())
|
||||||
|
activeMdiChild()->writeEeprom();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::readEeprom()
|
void MainWindow::readEeprom()
|
||||||
|
@ -1806,3 +1814,20 @@ void MainWindow::autoClose()
|
||||||
{
|
{
|
||||||
this->close();
|
this->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::chooseProfile()
|
||||||
|
{
|
||||||
|
QMap<int, QString> active;
|
||||||
|
active = g.getActiveProfiles();
|
||||||
|
if (active.size() > 1) {
|
||||||
|
ProfileChooserDialog *pcd = new ProfileChooserDialog(this);
|
||||||
|
connect(pcd, &ProfileChooserDialog::profileChanged, this, &MainWindow::loadProfileId);
|
||||||
|
pcd->exec();
|
||||||
|
delete pcd;
|
||||||
|
// doi here as need to wait until dialog dismissed and current radio type is set
|
||||||
|
if (checkProfileRadioExists(g.sessionId()))
|
||||||
|
doAutoUpdates();
|
||||||
|
else
|
||||||
|
g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ class MainWindow : public QMainWindow
|
||||||
void exportSettings();
|
void exportSettings();
|
||||||
void importSettings();
|
void importSettings();
|
||||||
void autoClose();
|
void autoClose();
|
||||||
|
void chooseProfile();
|
||||||
|
|
||||||
void openUpdatesWaitDialog();
|
void openUpdatesWaitDialog();
|
||||||
void closeUpdatesWaitDialog();
|
void closeUpdatesWaitDialog();
|
||||||
|
|
|
@ -1490,18 +1490,18 @@ bool MdiChild::convertStorage(Board::Type from, Board::Type to, bool newFile)
|
||||||
isUntitled = true;
|
isUntitled = true;
|
||||||
|
|
||||||
if (cstate.hasLogEntries(RadioDataConversionState::EVT_INF)) {
|
if (cstate.hasLogEntries(RadioDataConversionState::EVT_INF)) {
|
||||||
QDialog * msgBox = new QDialog(Q_NULLPTR, Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
|
auto * msgBox = new QDialog(Q_NULLPTR, Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
|
||||||
|
|
||||||
ExportableTableView * tv = new ExportableTableView(msgBox);
|
auto * tv = new ExportableTableView(msgBox);
|
||||||
tv->setSortingEnabled(true);
|
tv->setSortingEnabled(true);
|
||||||
tv->verticalHeader()->hide();
|
tv->verticalHeader()->hide();
|
||||||
tv->setModel(cstate.getLogModel(RadioDataConversionState::EVT_INF, tv));
|
tv->setModel(cstate.getLogModel(RadioDataConversionState::EVT_INF, tv));
|
||||||
tv->resizeColumnsToContents();
|
tv->resizeColumnsToContents();
|
||||||
tv->resizeRowsToContents();
|
tv->resizeRowsToContents();
|
||||||
|
|
||||||
QDialogButtonBox * btnBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);
|
auto * btnBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);
|
||||||
|
|
||||||
QVBoxLayout * lo = new QVBoxLayout(msgBox);
|
auto * lo = new QVBoxLayout(msgBox);
|
||||||
lo->addWidget(new QLabel(tr("<b>The conversion generated some important messages, please review them below.</b>")));
|
lo->addWidget(new QLabel(tr("<b>The conversion generated some important messages, please review them below.</b>")));
|
||||||
lo->addWidget(tv);
|
lo->addWidget(tv);
|
||||||
lo->addWidget(btnBox);
|
lo->addWidget(btnBox);
|
||||||
|
|
|
@ -120,7 +120,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
|
||||||
|
|
||||||
s1.report("header");
|
s1.report("header");
|
||||||
|
|
||||||
for (int i=0; i<chnCapability; i++) {
|
for (int i = 0; i < chnCapability; i++) {
|
||||||
int col = 0;
|
int col = 0;
|
||||||
|
|
||||||
// Channel label
|
// Channel label
|
||||||
|
@ -131,7 +131,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
|
||||||
label->setContextMenuPolicy(Qt::CustomContextMenu);
|
label->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
label->setToolTip(tr("Popup menu available"));
|
label->setToolTip(tr("Popup menu available"));
|
||||||
label->setMouseTracking(true);
|
label->setMouseTracking(true);
|
||||||
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(chn_customContextMenuRequested(QPoint)));
|
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
|
||||||
tableLayout->addWidget(i, col++, label);
|
tableLayout->addWidget(i, col++, label);
|
||||||
|
|
||||||
// Channel name
|
// Channel name
|
||||||
|
@ -204,7 +204,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
|
||||||
Channels::~Channels()
|
Channels::~Channels()
|
||||||
{
|
{
|
||||||
// compiler warning if delete[]
|
// compiler warning if delete[]
|
||||||
for (int i=0; i<CPN_MAX_CHNOUT;i++) {
|
for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
|
||||||
delete name[i];
|
delete name[i];
|
||||||
delete chnOffset[i];
|
delete chnOffset[i];
|
||||||
delete chnMin[i];
|
delete chnMin[i];
|
||||||
|
@ -240,7 +240,7 @@ void Channels::refreshExtendedLimits()
|
||||||
{
|
{
|
||||||
int channelMax = model->getChannelsMax();
|
int channelMax = model->getChannelsMax();
|
||||||
|
|
||||||
for (int i=0 ; i<CPN_MAX_CHNOUT; i++) {
|
for (int i = 0 ; i < CPN_MAX_CHNOUT; i++) {
|
||||||
chnOffset[i]->updateMinMax(10 * channelMax);
|
chnOffset[i]->updateMinMax(10 * channelMax);
|
||||||
chnMin[i]->updateMinMax(10 * channelMax);
|
chnMin[i]->updateMinMax(10 * channelMax);
|
||||||
chnMax[i]->updateMinMax(10 * channelMax);
|
chnMax[i]->updateMinMax(10 * channelMax);
|
||||||
|
@ -280,7 +280,7 @@ void Channels::ppmcenterEdited()
|
||||||
|
|
||||||
void Channels::update()
|
void Channels::update()
|
||||||
{
|
{
|
||||||
for (int i=0; i<chnCapability; i++) {
|
for (int i = 0; i < chnCapability; i++) {
|
||||||
updateLine(i);
|
updateLine(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,7 +298,7 @@ void Channels::updateLine(int i)
|
||||||
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
|
if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
|
||||||
int numcurves = firmware->getCapability(NumCurves);
|
int numcurves = firmware->getCapability(NumCurves);
|
||||||
curveCB[i]->clear();
|
curveCB[i]->clear();
|
||||||
for (int j=-numcurves; j<=numcurves; j++) {
|
for (int j = -numcurves; j <= numcurves; j++) {
|
||||||
curveCB[i]->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(model, false), j);
|
curveCB[i]->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(model, false), j);
|
||||||
}
|
}
|
||||||
curveCB[i]->setCurrentIndex(model->limitData[i].curve.value + numcurves);
|
curveCB[i]->setCurrentIndex(model->limitData[i].curve.value + numcurves);
|
||||||
|
@ -312,118 +312,140 @@ void Channels::updateLine(int i)
|
||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnPaste()
|
void Channels::cmPaste()
|
||||||
{
|
{
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
QByteArray data;
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
if (hasClipboardData(&data)) {
|
||||||
if (mimeData->hasFormat(MIMETYPE_CHN)) {
|
memcpy(&model->limitData[selectedIndex], data.constData(), sizeof(LimitData));
|
||||||
QByteArray chnData = mimeData->data(MIMETYPE_CHN);
|
updateLine(selectedIndex);
|
||||||
LimitData *chn = &model->limitData[selectedChannel];
|
|
||||||
memcpy(chn, chnData.constData(), sizeof(LimitData));
|
|
||||||
updateLine(selectedChannel);
|
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnDelete()
|
void Channels::cmDelete()
|
||||||
{
|
{
|
||||||
int maxidx = chnCapability - 1;
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
for (int i=selectedChannel; i<maxidx; i++) {
|
return;
|
||||||
if (!model->limitData[i].isEmpty() || !model->limitData[i+1].isEmpty()) {
|
|
||||||
LimitData *chn1 = &model->limitData[i];
|
memmove(&model->limitData[selectedIndex], &model->limitData[selectedIndex + 1], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData));
|
||||||
LimitData *chn2 = &model->limitData[i+1];
|
model->limitData[chnCapability - 1].clear();
|
||||||
memcpy(chn1, chn2, sizeof(LimitData));
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
|
||||||
|
|
||||||
|
for (int i = selectedIndex; i < chnCapability; i++) {
|
||||||
updateLine(i);
|
updateLine(i);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
model->limitData[maxidx].clear();
|
|
||||||
updateLine(maxidx);
|
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnCopy()
|
void Channels::cmCopy()
|
||||||
{
|
{
|
||||||
QByteArray chnData;
|
QByteArray data;
|
||||||
chnData.append((char*)&model->limitData[selectedChannel],sizeof(LimitData));
|
data.append((char*)&model->limitData[selectedIndex], sizeof(LimitData));
|
||||||
QMimeData *mimeData = new QMimeData;
|
QMimeData *mimeData = new QMimeData;
|
||||||
mimeData->setData(MIMETYPE_CHN, chnData);
|
mimeData->setData(MIMETYPE_CHANNEL, data);
|
||||||
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnCut()
|
void Channels::cmCut()
|
||||||
{
|
{
|
||||||
chnCopy();
|
cmCopy();
|
||||||
chnClear();
|
cmClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chn_customContextMenuRequested(QPoint pos)
|
void Channels::onCustomContextMenuRequested(QPoint pos)
|
||||||
{
|
{
|
||||||
QLabel *label = (QLabel *)sender();
|
QLabel *label = (QLabel *)sender();
|
||||||
selectedChannel = label->property("index").toInt();
|
selectedIndex = label->property("index").toInt();
|
||||||
|
|
||||||
QPoint globalPos = label->mapToGlobal(pos);
|
QPoint globalPos = label->mapToGlobal(pos);
|
||||||
|
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
|
||||||
bool hasData = mimeData->hasFormat(MIMETYPE_CHN);
|
|
||||||
bool moveUpAllowed = (selectedChannel > 0);
|
|
||||||
bool moveDownAllowed = (selectedChannel < (chnCapability - 1));
|
|
||||||
bool insertAllowed = (selectedChannel < (chnCapability - 1)) && (model->limitData[chnCapability - 1].isEmpty());
|
|
||||||
|
|
||||||
QMenu contextMenu;
|
QMenu contextMenu;
|
||||||
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(chnCopy()));
|
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
|
||||||
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(chnCut()));
|
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
|
||||||
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(chnPaste()))->setEnabled(hasData);
|
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
|
||||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(chnClear()));
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(chnInsert()))->setEnabled(insertAllowed);
|
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(cmInsert()))->setEnabled(insertAllowed());
|
||||||
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(chnDelete()));
|
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(cmDelete()));
|
||||||
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(chnMoveUp()))->setEnabled(moveUpAllowed);
|
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
|
||||||
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(chnMoveDown()))->setEnabled(moveDownAllowed);
|
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(chnClearAll()));
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
|
||||||
|
|
||||||
contextMenu.exec(globalPos);
|
contextMenu.exec(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnMoveUp()
|
bool Channels::hasClipboardData(QByteArray * data) const
|
||||||
{
|
{
|
||||||
swapChnData(selectedChannel, selectedChannel - 1);
|
const QClipboard * clipboard = QApplication::clipboard();
|
||||||
|
const QMimeData * mimeData = clipboard->mimeData();
|
||||||
|
if (mimeData->hasFormat(MIMETYPE_CHANNEL)) {
|
||||||
|
if (data)
|
||||||
|
data->append(mimeData->data(MIMETYPE_CHANNEL));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnMoveDown()
|
bool Channels::insertAllowed() const
|
||||||
{
|
{
|
||||||
swapChnData(selectedChannel, selectedChannel + 1);
|
return ((selectedIndex < chnCapability - 1) && (model->limitData[chnCapability - 1].isEmpty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnClear()
|
bool Channels::moveDownAllowed() const
|
||||||
{
|
{
|
||||||
model->limitData[selectedChannel].clear();
|
return selectedIndex < chnCapability - 1;
|
||||||
updateLine(selectedChannel);
|
}
|
||||||
|
|
||||||
|
bool Channels::moveUpAllowed() const
|
||||||
|
{
|
||||||
|
return selectedIndex > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channels::cmMoveUp()
|
||||||
|
{
|
||||||
|
swapData(selectedIndex, selectedIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channels::cmMoveDown()
|
||||||
|
{
|
||||||
|
swapData(selectedIndex, selectedIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channels::cmClear()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
model->limitData[selectedIndex].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
|
||||||
|
updateLine(selectedIndex);
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnClearAll()
|
void Channels::cmClearAll()
|
||||||
{
|
{
|
||||||
for (int i=0; i<chnCapability; i++) {
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Channels. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < chnCapability; i++) {
|
||||||
model->limitData[i].clear();
|
model->limitData[i].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, i);
|
||||||
updateLine(i);
|
updateLine(i);
|
||||||
}
|
}
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::chnInsert()
|
void Channels::cmInsert()
|
||||||
{
|
{
|
||||||
for (int i=(chnCapability - 1); i>selectedChannel; i--) {
|
memmove(&model->limitData[selectedIndex + 1], &model->limitData[selectedIndex], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData));
|
||||||
if (!model->limitData[i].isEmpty() || !model->limitData[i-1].isEmpty()) {
|
model->limitData[selectedIndex].clear();
|
||||||
memcpy(&model->limitData[i], &model->limitData[i-1], sizeof(LimitData));
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
|
||||||
updateLine(i);
|
update();
|
||||||
}
|
emit modified();
|
||||||
}
|
|
||||||
chnClear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channels::swapChnData(int idx1, int idx2)
|
void Channels::swapData(int idx1, int idx2)
|
||||||
{
|
{
|
||||||
if ((idx1 != idx2) && (!model->limitData[idx1].isEmpty() || !model->limitData[idx2].isEmpty())) {
|
if ((idx1 != idx2) && (!model->limitData[idx1].isEmpty() || !model->limitData[idx2].isEmpty())) {
|
||||||
LimitData chntmp = model->limitData[idx2];
|
LimitData chntmp = model->limitData[idx2];
|
||||||
|
@ -431,6 +453,7 @@ void Channels::swapChnData(int idx1, int idx2)
|
||||||
LimitData *chn2 = &model->limitData[idx2];
|
LimitData *chn2 = &model->limitData[idx2];
|
||||||
memcpy(chn2, chn1, sizeof(LimitData));
|
memcpy(chn2, chn1, sizeof(LimitData));
|
||||||
memcpy(chn1, &chntmp, sizeof(LimitData));
|
memcpy(chn1, &chntmp, sizeof(LimitData));
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
|
||||||
updateLine(idx1);
|
updateLine(idx1);
|
||||||
updateLine(idx2);
|
updateLine(idx2);
|
||||||
emit modified();
|
emit modified();
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
|
|
||||||
constexpr char MIMETYPE_CHN[] = "application/x-companion-chn";
|
constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel";
|
||||||
|
|
||||||
class GVarGroup;
|
class GVarGroup;
|
||||||
|
|
||||||
|
@ -68,19 +68,23 @@ class Channels : public ModelPanel
|
||||||
void ppmcenterEdited();
|
void ppmcenterEdited();
|
||||||
void update();
|
void update();
|
||||||
void updateLine(int index);
|
void updateLine(int index);
|
||||||
void chnDelete();
|
void cmDelete();
|
||||||
void chnCopy();
|
void cmCopy();
|
||||||
void chnPaste();
|
void cmPaste();
|
||||||
void chnCut();
|
void cmCut();
|
||||||
void chnMoveUp();
|
void cmMoveUp();
|
||||||
void chnMoveDown();
|
void cmMoveDown();
|
||||||
void chnInsert();
|
void cmInsert();
|
||||||
void chnClear();
|
void cmClear();
|
||||||
void chnClearAll();
|
void cmClearAll();
|
||||||
void chn_customContextMenuRequested(QPoint pos);
|
void onCustomContextMenuRequested(QPoint pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void swapChnData(int idx1, int idx2);
|
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool insertAllowed() const;
|
||||||
|
bool moveDownAllowed() const;
|
||||||
|
bool moveUpAllowed() const;
|
||||||
|
void swapData(int idx1, int idx2);
|
||||||
QLineEdit *name[CPN_MAX_CHNOUT];
|
QLineEdit *name[CPN_MAX_CHNOUT];
|
||||||
LimitsGroup *chnOffset[CPN_MAX_CHNOUT];
|
LimitsGroup *chnOffset[CPN_MAX_CHNOUT];
|
||||||
LimitsGroup *chnMin[CPN_MAX_CHNOUT];
|
LimitsGroup *chnMin[CPN_MAX_CHNOUT];
|
||||||
|
@ -89,7 +93,7 @@ class Channels : public ModelPanel
|
||||||
QComboBox *curveCB[CPN_MAX_CHNOUT];
|
QComboBox *curveCB[CPN_MAX_CHNOUT];
|
||||||
QSpinBox *centerSB[CPN_MAX_CHNOUT];
|
QSpinBox *centerSB[CPN_MAX_CHNOUT];
|
||||||
QCheckBox *symlimitsChk[CPN_MAX_CHNOUT];
|
QCheckBox *symlimitsChk[CPN_MAX_CHNOUT];
|
||||||
int selectedChannel;
|
int selectedIndex;
|
||||||
int chnCapability;
|
int chnCapability;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,12 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
|
||||||
|
|
||||||
lock = true;
|
lock = true;
|
||||||
|
|
||||||
if (!firmware->getCapability(HasCvNames)) {
|
maxCurves = firmware->getCapability(NumCurves);
|
||||||
|
hasNames = firmware->getCapability(HasCvNames);
|
||||||
|
hasEnhanced = firmware->getCapability(EnhancedCurves);
|
||||||
|
maxPoints = firmware->getCapability(NumCurvePoints);
|
||||||
|
|
||||||
|
if (!hasNames) {
|
||||||
ui->curveName->hide();
|
ui->curveName->hide();
|
||||||
ui->curveNameLabel->hide();
|
ui->curveNameLabel->hide();
|
||||||
}
|
}
|
||||||
|
@ -127,14 +132,14 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
|
||||||
connect(scene, SIGNAL(newPoint(int, int)), this, SLOT(onSceneNewPoint(int, int)));
|
connect(scene, SIGNAL(newPoint(int, int)), this, SLOT(onSceneNewPoint(int, int)));
|
||||||
|
|
||||||
ui->curvePreview->setScene(scene);
|
ui->curvePreview->setScene(scene);
|
||||||
int numcurves=firmware->getCapability(NumCurves);
|
|
||||||
int limit;
|
int limit;
|
||||||
if (numcurves>16) {
|
if (maxCurves > 16) {
|
||||||
limit=numcurves/2;
|
limit = maxCurves / 2;
|
||||||
} else {
|
} else {
|
||||||
limit=numcurves;
|
limit = maxCurves;
|
||||||
}
|
}
|
||||||
for (int i=0; i<numcurves; i++) {
|
for (int i = 0; i < maxCurves; i++) {
|
||||||
visibleCurves[i] = false;
|
visibleCurves[i] = false;
|
||||||
|
|
||||||
// The edit curve button
|
// The edit curve button
|
||||||
|
@ -151,15 +156,15 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
|
||||||
edit->setStyleSheet(QString("background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; border-radius: 2px; border-color: inherit;").arg(colors[i].name()));
|
edit->setStyleSheet(QString("background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; border-radius: 2px; border-color: inherit;").arg(colors[i].name()));
|
||||||
#endif
|
#endif
|
||||||
edit->setPalette(palette);
|
edit->setPalette(palette);
|
||||||
edit->setText(tr("Curve %1").arg(i+1));
|
edit->setText(tr("Curve %1").arg(i + 1));
|
||||||
edit->setContextMenuPolicy(Qt::CustomContextMenu);
|
edit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
edit->setToolTip(tr("Popup menu available"));
|
edit->setToolTip(tr("Popup menu available"));
|
||||||
connect(edit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ShowContextMenu(const QPoint&)));
|
connect(edit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onCustomContextMenuRequested(const QPoint&)));
|
||||||
connect(edit, SIGNAL(clicked()), this, SLOT(editCurve()));
|
connect(edit, SIGNAL(clicked()), this, SLOT(editCurve()));
|
||||||
if (i<limit) {
|
if (i < limit) {
|
||||||
ui->curvesLayout->addWidget(edit, i, 1, 1, 1);
|
ui->curvesLayout->addWidget(edit, i, 1, 1, 1);
|
||||||
} else {
|
} else {
|
||||||
ui->curvesLayout2->addWidget(edit, i-limit, 2, 1, 1);
|
ui->curvesLayout2->addWidget(edit, i - limit, 2, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The curve plot checkbox
|
// The curve plot checkbox
|
||||||
|
@ -167,7 +172,7 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
|
||||||
plot->setProperty("index", i);
|
plot->setProperty("index", i);
|
||||||
plot->setPalette(palette);
|
plot->setPalette(palette);
|
||||||
connect(plot, SIGNAL(toggled(bool)), this, SLOT(plotCurve(bool)));
|
connect(plot, SIGNAL(toggled(bool)), this, SLOT(plotCurve(bool)));
|
||||||
if (i<limit) {
|
if (i < limit) {
|
||||||
ui->curvesLayout->addWidget(plot, i, 2, 1, 1);
|
ui->curvesLayout->addWidget(plot, i, 2, 1, 1);
|
||||||
} else {
|
} else {
|
||||||
ui->curvesLayout2->addWidget(plot, i-limit, 1, 1, 1);
|
ui->curvesLayout2->addWidget(plot, i-limit, 1, 1, 1);
|
||||||
|
@ -175,13 +180,13 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
|
||||||
}
|
}
|
||||||
QSpacerItem * item = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
|
QSpacerItem * item = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||||
|
|
||||||
ui->curvesLayout->addItem(item,limit+1,1,1,1,0);
|
ui->curvesLayout->addItem(item,limit + 1, 1, 1, 1, 0);
|
||||||
if (limit!=numcurves) {
|
if (limit != maxCurves) {
|
||||||
QSpacerItem * item2 = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
|
QSpacerItem * item2 = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||||
ui->curvesLayout2->addItem(item2,limit+1,1,1,1,0);
|
ui->curvesLayout2->addItem(item2,limit + 1, 1, 1, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<CPN_MAX_POINTS; i++) {
|
for (int i = 0; i < CPN_MAX_POINTS; i++) {
|
||||||
spnx[i] = new QSpinBox(this);
|
spnx[i] = new QSpinBox(this);
|
||||||
spnx[i]->setProperty("index", i);
|
spnx[i]->setProperty("index", i);
|
||||||
spnx[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
spnx[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||||
|
@ -199,14 +204,14 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
|
||||||
ui->pointsLayout->addWidget(spny[i], i, 1, 1, 1);
|
ui->pointsLayout->addWidget(spny[i], i, 1, 1, 1);
|
||||||
|
|
||||||
bool insert;
|
bool insert;
|
||||||
if (firmware->getCapability(EnhancedCurves)) {
|
if (hasEnhanced) {
|
||||||
insert = (i >= 1);
|
insert = (i >= 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
insert = (i==2 || i==4 || i==8 || i==16);
|
insert = (i == 2 || i == 4 || i ==8 || i == 16);
|
||||||
}
|
}
|
||||||
if (insert) {
|
if (insert) {
|
||||||
ui->curvePoints->addItem(tr("%1 points").arg(i+1), i+1);
|
ui->curvePoints->addItem(tr("%1 points").arg(i + 1), i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +255,7 @@ void Curves::update()
|
||||||
{
|
{
|
||||||
lock = true;
|
lock = true;
|
||||||
|
|
||||||
if (firmware->getCapability(HasCvNames)) {
|
if (hasNames) {
|
||||||
ui->curveName->setText(model->curves[currentCurve].name);
|
ui->curveName->setText(model->curves[currentCurve].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +277,7 @@ void Curves::updateCurveType()
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
if (firmware->getCapability(EnhancedCurves)) {
|
if (hasEnhanced) {
|
||||||
index = model->curves[currentCurve].count - 2;
|
index = model->curves[currentCurve].count - 2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -305,35 +310,34 @@ void Curves::updateCurve()
|
||||||
qreal width = scene->sceneRect().width();
|
qreal width = scene->sceneRect().width();
|
||||||
qreal height = scene->sceneRect().height();
|
qreal height = scene->sceneRect().height();
|
||||||
|
|
||||||
qreal centerX = scene->sceneRect().left() + width/2;
|
qreal centerX = scene->sceneRect().left() + width / 2;
|
||||||
qreal centerY = scene->sceneRect().top() + height/2;
|
qreal centerY = scene->sceneRect().top() + height / 2;
|
||||||
|
|
||||||
QGraphicsSimpleTextItem *ti = scene->addSimpleText(tr("Editing curve %1").arg(currentCurve+1));
|
QGraphicsSimpleTextItem *ti = scene->addSimpleText(tr("Editing curve %1").arg(currentCurve + 1));
|
||||||
ti->setPos(3, 3);
|
ti->setPos(3, 3);
|
||||||
|
|
||||||
scene->addLine(centerX, GFX_MARGIN, centerX, height+GFX_MARGIN);
|
scene->addLine(centerX, GFX_MARGIN, centerX, height + GFX_MARGIN);
|
||||||
scene->addLine(GFX_MARGIN, centerY, width+GFX_MARGIN, centerY);
|
scene->addLine(GFX_MARGIN, centerY, width + GFX_MARGIN, centerY);
|
||||||
|
|
||||||
QPen pen;
|
QPen pen;
|
||||||
pen.setWidth(1);
|
pen.setWidth(1);
|
||||||
pen.setStyle(Qt::SolidLine);
|
pen.setStyle(Qt::SolidLine);
|
||||||
|
|
||||||
int numcurves = firmware->getCapability(NumCurves);
|
for (int k = 0; k < maxCurves; k++) {
|
||||||
for (int k=0; k<numcurves; k++) {
|
|
||||||
pen.setColor(colors[k]);
|
pen.setColor(colors[k]);
|
||||||
if (currentCurve!=k && visibleCurves[k]) {
|
if (currentCurve != k && visibleCurves[k]) {
|
||||||
int numpoints = model->curves[k].count;
|
int numpoints = model->curves[k].count;
|
||||||
for (int i=0; i<numpoints-1; i++) {
|
for (int i = 0; i < numpoints - 1; i++) {
|
||||||
if (model->curves[k].type == CurveData::CURVE_TYPE_CUSTOM)
|
if (model->curves[k].type == CurveData::CURVE_TYPE_CUSTOM)
|
||||||
scene->addLine(centerX + (qreal)model->curves[k].points[i].x*width/200,centerY - (qreal)model->curves[k].points[i].y*height/200,centerX + (qreal)model->curves[k].points[i+1].x*width/200,centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
|
scene->addLine(centerX + (qreal)model->curves[k].points[i].x*width/200, centerY - (qreal)model->curves[k].points[i].y*height/200,centerX + (qreal)model->curves[k].points[i+1].x*width/200,centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
|
||||||
else
|
else
|
||||||
scene->addLine(GFX_MARGIN + i*width/(numpoints-1),centerY - (qreal)model->curves[k].points[i].y*height/200,GFX_MARGIN + (i+1)*width/(numpoints-1),centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
|
scene->addLine(GFX_MARGIN + i*width/(numpoints-1), centerY - (qreal)model->curves[k].points[i].y*height/200,GFX_MARGIN + (i+1)*width/(numpoints-1),centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int numpoints = model->curves[currentCurve].count;
|
int numpoints = model->curves[currentCurve].count;
|
||||||
for (int i=0; i<numpoints; i++) {
|
for (int i = 0; i < numpoints; i++) {
|
||||||
nodel = nodex;
|
nodel = nodex;
|
||||||
nodex = new Node();
|
nodex = new Node();
|
||||||
nodex->setProperty("index", i);
|
nodex->setProperty("index", i);
|
||||||
|
@ -341,26 +345,27 @@ void Curves::updateCurve()
|
||||||
nodex->setBallSize(ui->pointSize->value());
|
nodex->setBallSize(ui->pointSize->value());
|
||||||
nodex->setBallHeight(0);
|
nodex->setBallHeight(0);
|
||||||
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
|
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
|
||||||
if (i>0 && i<numpoints-1) {
|
if (i > 0 && i < numpoints - 1) {
|
||||||
nodex->setFixedX(false);
|
nodex->setFixedX(false);
|
||||||
nodex->setMinX(model->curves[currentCurve].points[i-1].x);
|
nodex->setMinX(model->curves[currentCurve].points[i - 1].x);
|
||||||
nodex->setMaxX(model->curves[currentCurve].points[i+1].x);
|
nodex->setMaxX(model->curves[currentCurve].points[i + 1].x);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nodex->setFixedX(true);
|
nodex->setFixedX(true);
|
||||||
}
|
}
|
||||||
nodex->setPos(centerX + (qreal)model->curves[currentCurve].points[i].x*width/200,centerY - (qreal)model->curves[currentCurve].points[i].y*height/200);
|
nodex->setPos(centerX + (qreal)model->curves[currentCurve].points[i].x * width / 200, centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nodex->setFixedX(true);
|
nodex->setFixedX(true);
|
||||||
nodex->setPos(GFX_MARGIN + i*width/(numpoints-1), centerY - (qreal)model->curves[currentCurve].points[i].y*height/200);
|
nodex->setPos(GFX_MARGIN + i * width / (numpoints - 1), centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200);
|
||||||
}
|
}
|
||||||
connect(nodex, SIGNAL(moved(int, int)), this, SLOT(onNodeMoved(int, int)));
|
connect(nodex, SIGNAL(moved(int, int)), this, SLOT(onNodeMoved(int, int)));
|
||||||
connect(nodex, SIGNAL(focus()), this, SLOT(onNodeFocus()));
|
connect(nodex, SIGNAL(focus()), this, SLOT(onNodeFocus()));
|
||||||
connect(nodex, SIGNAL(unfocus()), this, SLOT(onNodeUnfocus()));
|
connect(nodex, SIGNAL(unfocus()), this, SLOT(onNodeUnfocus()));
|
||||||
connect(nodex, SIGNAL(deleteMe()), this, SLOT(onNodeDelete()));
|
connect(nodex, SIGNAL(deleteMe()), this, SLOT(onNodeDelete()));
|
||||||
scene->addItem(nodex);
|
scene->addItem(nodex);
|
||||||
if (i>0) scene->addItem(new Edge(nodel, nodex));
|
if (i > 0)
|
||||||
|
scene->addItem(new Edge(nodel, nodex));
|
||||||
}
|
}
|
||||||
|
|
||||||
lock = false;
|
lock = false;
|
||||||
|
@ -371,20 +376,20 @@ void Curves::updateCurvePoints()
|
||||||
lock = true;
|
lock = true;
|
||||||
|
|
||||||
int count = model->curves[currentCurve].count;
|
int count = model->curves[currentCurve].count;
|
||||||
for (int i=0; i<count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
spny[i]->show();
|
spny[i]->show();
|
||||||
spny[i]->setValue(model->curves[currentCurve].points[i].y);
|
spny[i]->setValue(model->curves[currentCurve].points[i].y);
|
||||||
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
|
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
|
||||||
spnx[i]->show();
|
spnx[i]->show();
|
||||||
if (i==0 || i==model->curves[currentCurve].count-1) {
|
if (i == 0 || i == model->curves[currentCurve].count - 1) {
|
||||||
spnx[i]->setDisabled(true);
|
spnx[i]->setDisabled(true);
|
||||||
spnx[i]->setMaximum(+100);
|
spnx[i]->setMaximum(+100);
|
||||||
spnx[i]->setMinimum(-100);
|
spnx[i]->setMinimum(-100);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
spnx[i]->setDisabled(false);
|
spnx[i]->setDisabled(false);
|
||||||
spnx[i]->setMaximum(model->curves[currentCurve].points[i+1].x);
|
spnx[i]->setMaximum(model->curves[currentCurve].points[i + 1].x);
|
||||||
spnx[i]->setMinimum(model->curves[currentCurve].points[i-1].x);
|
spnx[i]->setMinimum(model->curves[currentCurve].points[i - 1].x);
|
||||||
}
|
}
|
||||||
spnx[i]->setValue(model->curves[currentCurve].points[i].x);
|
spnx[i]->setValue(model->curves[currentCurve].points[i].x);
|
||||||
}
|
}
|
||||||
|
@ -392,7 +397,7 @@ void Curves::updateCurvePoints()
|
||||||
spnx[i]->hide();
|
spnx[i]->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=count; i<CPN_MAX_POINTS; i++) {
|
for (int i = count; i < CPN_MAX_POINTS; i++) {
|
||||||
spny[i]->hide();
|
spny[i]->hide();
|
||||||
spnx[i]->hide();
|
spnx[i]->hide();
|
||||||
}
|
}
|
||||||
|
@ -421,9 +426,9 @@ void Curves::onNodeMoved(int x, int y)
|
||||||
spnx[index]->setValue(x);
|
spnx[index]->setValue(x);
|
||||||
spny[index]->setValue(y);
|
spny[index]->setValue(y);
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
spnx[index-1]->setMaximum(x);
|
spnx[index - 1]->setMaximum(x);
|
||||||
if (index < model->curves[currentCurve].count-1)
|
if (index < model->curves[currentCurve].count - 1)
|
||||||
spnx[index+1]->setMinimum(x);
|
spnx[index + 1]->setMinimum(x);
|
||||||
emit modified();
|
emit modified();
|
||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
@ -444,17 +449,14 @@ void Curves::onNodeUnfocus()
|
||||||
|
|
||||||
bool Curves::allowCurveType(int points, CurveData::CurveType type)
|
bool Curves::allowCurveType(int points, CurveData::CurveType type)
|
||||||
{
|
{
|
||||||
int numcurves = firmware->getCapability(NumCurves);
|
|
||||||
|
|
||||||
int totalpoints = 0;
|
int totalpoints = 0;
|
||||||
for (int i=0; i<numcurves; i++) {
|
for (int i = 0; i < maxCurves; i++) {
|
||||||
int cvPoints = (i==currentCurve ? points : model->curves[i].count);
|
int cvPoints = (i == currentCurve ? points : model->curves[i].count);
|
||||||
CurveData::CurveType cvType = (i==currentCurve ? type : model->curves[i].type);
|
CurveData::CurveType cvType = (i == currentCurve ? type : model->curves[i].type);
|
||||||
totalpoints += cvPoints + (cvType==CurveData::CURVE_TYPE_CUSTOM ? cvPoints-2 : 0);
|
totalpoints += cvPoints + (cvType == CurveData::CURVE_TYPE_CUSTOM ? cvPoints - 2 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fwpoints = firmware->getCapability(NumCurvePoints);
|
if (totalpoints > maxPoints) {
|
||||||
if (totalpoints > fwpoints) {
|
|
||||||
QMessageBox::warning(this, "companion", tr("Not enough free points in EEPROM to store the curve."));
|
QMessageBox::warning(this, "companion", tr("Not enough free points in EEPROM to store the curve."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -472,8 +474,8 @@ void Curves::on_curvePoints_currentIndexChanged(int index)
|
||||||
model->curves[currentCurve].count = numpoints;
|
model->curves[currentCurve].count = numpoints;
|
||||||
|
|
||||||
// TODO something better + reuse!
|
// TODO something better + reuse!
|
||||||
for (int i=0; i<CPN_MAX_POINTS; i++) {
|
for (int i = 0; i < CPN_MAX_POINTS; i++) {
|
||||||
model->curves[currentCurve].points[i].x = (i >= numpoints-1 ? +100 : -100 + (200*i)/(numpoints-1));
|
model->curves[currentCurve].points[i].x = (i >= numpoints - 1 ? +100 : -100 + (200 * i) / (numpoints - 1));
|
||||||
model->curves[currentCurve].points[i].y = 0;
|
model->curves[currentCurve].points[i].y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,12 +493,13 @@ void Curves::on_curveCustom_currentIndexChanged(int index)
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
CurveData::CurveType type = (CurveData::CurveType)index;
|
CurveData::CurveType type = (CurveData::CurveType)index;
|
||||||
int numpoints = ui->curvePoints->itemData(ui->curvePoints->currentIndex()).toInt();
|
int numpoints = ui->curvePoints->itemData(ui->curvePoints->currentIndex()).toInt();
|
||||||
|
|
||||||
if (allowCurveType(model->curves[currentCurve].count, type)) {
|
if (allowCurveType(model->curves[currentCurve].count, type)) {
|
||||||
model->curves[currentCurve].type = type;
|
model->curves[currentCurve].type = type;
|
||||||
|
|
||||||
// TODO something better + reuse!
|
// TODO something better + reuse!
|
||||||
for (int i=0; i<CPN_MAX_POINTS; i++) {
|
for (int i = 0; i < CPN_MAX_POINTS; i++) {
|
||||||
model->curves[currentCurve].points[i].x = (i >= numpoints-1 ? +100 : -100 + (200*i)/(numpoints-1));
|
model->curves[currentCurve].points[i].x = (i >= numpoints - 1 ? +100 : -100 + (200 * i) / (numpoints - 1));
|
||||||
model->curves[currentCurve].points[i].y = 0;
|
model->curves[currentCurve].points[i].y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +528,7 @@ void Curves::on_curveName_editingFinished()
|
||||||
void Curves::resizeEvent(QResizeEvent *event)
|
void Curves::resizeEvent(QResizeEvent *event)
|
||||||
{
|
{
|
||||||
QRect qr = ui->curvePreview->contentsRect();
|
QRect qr = ui->curvePreview->contentsRect();
|
||||||
ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width()-GFX_MARGIN*2, qr.height()-GFX_MARGIN*2);
|
ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width() - GFX_MARGIN * 2, qr.height() - GFX_MARGIN * 2);
|
||||||
updateCurve();
|
updateCurve();
|
||||||
ModelPanel::resizeEvent(event);
|
ModelPanel::resizeEvent(event);
|
||||||
}
|
}
|
||||||
|
@ -559,12 +562,12 @@ void Curves::on_curveApply_clicked()
|
||||||
int index = ui->curveType->currentIndex();
|
int index = ui->curveType->currentIndex();
|
||||||
int numpoints = model->curves[currentCurve].count;
|
int numpoints = model->curves[currentCurve].count;
|
||||||
|
|
||||||
for (int i=0; i<numpoints; i++) {
|
for (int i = 0; i < numpoints; i++) {
|
||||||
float x;
|
float x;
|
||||||
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM)
|
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM)
|
||||||
x = model->curves[currentCurve].points[i].x;
|
x = model->curves[currentCurve].points[i].x;
|
||||||
else
|
else
|
||||||
x = -100.0 + (200.0/(numpoints-1))*i;
|
x = -100.0 + (200.0 / (numpoints - 1)) * i;
|
||||||
|
|
||||||
bool apply = false;
|
bool apply = false;
|
||||||
switch (ui->curveSide->currentIndex()) {
|
switch (ui->curveSide->currentIndex()) {
|
||||||
|
@ -572,11 +575,11 @@ void Curves::on_curveApply_clicked()
|
||||||
apply = true;
|
apply = true;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (x>=0)
|
if (x >= 0)
|
||||||
apply = true;
|
apply = true;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (x<0)
|
if (x < 0)
|
||||||
apply = true;
|
apply = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -591,68 +594,6 @@ void Curves::on_curveApply_clicked()
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curves::ShowContextMenu(const QPoint& pos) // this is a slot
|
|
||||||
{
|
|
||||||
QPushButton *button = (QPushButton *)sender();
|
|
||||||
int index = button->property("index").toInt();
|
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
|
||||||
QPoint globalPos = button->mapToGlobal(pos);
|
|
||||||
QMenu myMenu;
|
|
||||||
QAction *action;
|
|
||||||
action = myMenu.addAction(CompanionIcon("copy.png"),tr("Copy"));
|
|
||||||
action->setProperty("index", CURVE_COPY);
|
|
||||||
|
|
||||||
action = myMenu.addAction(CompanionIcon("paste.png"),tr("Paste"));
|
|
||||||
if (!mimeData->hasFormat("application/x-companion-curve-item")) {
|
|
||||||
action->setEnabled(false);
|
|
||||||
}
|
|
||||||
action->setProperty("index", CURVE_PASTE);
|
|
||||||
|
|
||||||
action = myMenu.addAction(CompanionIcon("clear.png"),tr("Clear"));
|
|
||||||
action->setProperty("index", CURVE_RESET);
|
|
||||||
action = myMenu.addAction(CompanionIcon("clear.png"),tr("Clear all curves"));
|
|
||||||
action->setProperty("index", CURVE_RESETALL);
|
|
||||||
|
|
||||||
QAction* selectedItem = myMenu.exec(globalPos);
|
|
||||||
if (selectedItem) {
|
|
||||||
int action=selectedItem->property("index").toInt();
|
|
||||||
if (action==CURVE_COPY) {
|
|
||||||
QByteArray curveData;
|
|
||||||
QMimeData *mimeData2 = new QMimeData;
|
|
||||||
curveData.append((char*)&model->curves[index], sizeof(CurveData));
|
|
||||||
mimeData2->setData("application/x-companion-curve-item", curveData);
|
|
||||||
QApplication::clipboard()->setMimeData(mimeData2, QClipboard::Clipboard);
|
|
||||||
}
|
|
||||||
else if (action==CURVE_PASTE) {
|
|
||||||
QByteArray curveData = mimeData->data("application/x-companion-curve-item");
|
|
||||||
CurveData *curve = &model->curves[index];
|
|
||||||
memcpy(curve, curveData.constData(), sizeof(CurveData));
|
|
||||||
update();
|
|
||||||
emit modified();
|
|
||||||
}
|
|
||||||
else if (action==CURVE_RESET) {
|
|
||||||
int res = QMessageBox::question(this, "companion", tr("Are you sure you want to reset curve %1?").arg(index+1), QMessageBox::Yes | QMessageBox::No);
|
|
||||||
if (res == QMessageBox::Yes) {
|
|
||||||
model->curves[index].clear(5);
|
|
||||||
update();
|
|
||||||
emit modified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (action==CURVE_RESETALL) {
|
|
||||||
int res = QMessageBox::question(this, "companion", tr("Are you sure you want to reset all curves?"), QMessageBox::Yes | QMessageBox::No);
|
|
||||||
if (res == QMessageBox::Yes) {
|
|
||||||
int numcurves = firmware->getCapability(NumCurves);
|
|
||||||
for (int i=0; i<numcurves; i++) {
|
|
||||||
model->curves[i].clear(5);
|
|
||||||
}
|
|
||||||
update();
|
|
||||||
emit modified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Curves::onPointSizeEdited()
|
void Curves::onPointSizeEdited()
|
||||||
{
|
{
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
|
@ -690,7 +631,7 @@ void Curves::onSceneNewPoint(int x, int y)
|
||||||
newidx = numpoints;
|
newidx = numpoints;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<numpoints; i++) {
|
for (int i = 0; i < numpoints; i++) {
|
||||||
if (x < model->curves[currentCurve].points[i].x) {
|
if (x < model->curves[currentCurve].points[i].x) {
|
||||||
newidx = i;
|
newidx = i;
|
||||||
break;
|
break;
|
||||||
|
@ -699,8 +640,8 @@ void Curves::onSceneNewPoint(int x, int y)
|
||||||
}
|
}
|
||||||
numpoints++;
|
numpoints++;
|
||||||
model->curves[currentCurve].count = numpoints;
|
model->curves[currentCurve].count = numpoints;
|
||||||
for (int idx=(numpoints-1); idx>(newidx); idx--) {
|
for (int idx = (numpoints - 1); idx > newidx; idx--) {
|
||||||
model->curves[currentCurve].points[idx] = model->curves[currentCurve].points[idx-1];
|
model->curves[currentCurve].points[idx] = model->curves[currentCurve].points[idx - 1];
|
||||||
}
|
}
|
||||||
model->curves[currentCurve].points[newidx].x = x;
|
model->curves[currentCurve].points[newidx].x = x;
|
||||||
model->curves[currentCurve].points[newidx].y = y;
|
model->curves[currentCurve].points[newidx].y = y;
|
||||||
|
@ -709,6 +650,150 @@ void Curves::onSceneNewPoint(int x, int y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curves::onCustomContextMenuRequested(QPoint pos)
|
||||||
|
{
|
||||||
|
QPushButton *button = (QPushButton *)sender();
|
||||||
|
selectedIndex = button->property("index").toInt();
|
||||||
|
QPoint globalPos = button->mapToGlobal(pos);
|
||||||
|
|
||||||
|
QMenu contextMenu;
|
||||||
|
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmCopy()));
|
||||||
|
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmCut()));
|
||||||
|
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmPaste()))->setEnabled(hasClipboardData());
|
||||||
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmClear()));
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmInsert()))->setEnabled(insertAllowed());
|
||||||
|
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmDelete()));
|
||||||
|
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
|
||||||
|
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(cmClearAll()));
|
||||||
|
|
||||||
|
contextMenu.exec(globalPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Curves::hasClipboardData(QByteArray * data) const
|
||||||
|
{
|
||||||
|
const QClipboard * clipboard = QApplication::clipboard();
|
||||||
|
const QMimeData * mimeData = clipboard->mimeData();
|
||||||
|
if (mimeData->hasFormat(MIMETYPE_CURVE)) {
|
||||||
|
if (data)
|
||||||
|
data->append(mimeData->data(MIMETYPE_CURVE));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Curves::insertAllowed() const
|
||||||
|
{
|
||||||
|
return ((selectedIndex < maxCurves - 1) && (model->curves[maxCurves - 1].isEmpty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Curves::moveDownAllowed() const
|
||||||
|
{
|
||||||
|
return selectedIndex < maxCurves - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Curves::moveUpAllowed() const
|
||||||
|
{
|
||||||
|
return selectedIndex > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmClear()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
model->curves[selectedIndex].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmClearAll()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Curves. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < maxCurves; i++) {
|
||||||
|
model->curves[i].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, i);
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmCopy()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
data.append((char*)&model->curves[selectedIndex], sizeof(CurveData));
|
||||||
|
QMimeData *mimeData = new QMimeData;
|
||||||
|
mimeData->setData(MIMETYPE_CURVE, data);
|
||||||
|
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmCut()
|
||||||
|
{
|
||||||
|
cmCopy();
|
||||||
|
cmClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmDelete()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memmove(&model->curves[selectedIndex], &model->curves[selectedIndex + 1], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData));
|
||||||
|
model->curves[maxCurves - 1].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmInsert()
|
||||||
|
{
|
||||||
|
memmove(&model->curves[selectedIndex + 1], &model->curves[selectedIndex], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData));
|
||||||
|
model->curves[selectedIndex].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmMoveDown()
|
||||||
|
{
|
||||||
|
swapData(selectedIndex, selectedIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmMoveUp()
|
||||||
|
{
|
||||||
|
swapData(selectedIndex, selectedIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::cmPaste()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
if (hasClipboardData(&data)) {
|
||||||
|
CurveData *cd = &model->curves[selectedIndex];
|
||||||
|
memcpy(cd, data.constData(), sizeof(CurveData));
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curves::swapData(int idx1, int idx2)
|
||||||
|
{
|
||||||
|
if ((idx1 != idx2) && (!model->curves[idx1].isEmpty() || !model->curves[idx2].isEmpty())) {
|
||||||
|
CurveData cdtmp = model->curves[idx2];
|
||||||
|
CurveData *cd1 = &model->curves[idx1];
|
||||||
|
CurveData *cd2 = &model->curves[idx2];
|
||||||
|
memcpy(cd2, cd1, sizeof(CurveData));
|
||||||
|
memcpy(cd1, &cdtmp, sizeof(CurveData));
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CustomScene::CustomScene(QGraphicsView * view) :
|
CustomScene::CustomScene(QGraphicsView * view) :
|
||||||
QGraphicsScene(view)
|
QGraphicsScene(view)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,12 +26,7 @@
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
|
||||||
enum CopyAction {
|
constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve";
|
||||||
CURVE_COPY,
|
|
||||||
CURVE_PASTE,
|
|
||||||
CURVE_RESET,
|
|
||||||
CURVE_RESETALL
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Curves;
|
class Curves;
|
||||||
|
@ -71,7 +66,6 @@ class Curves : public ModelPanel
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void editCurve();
|
void editCurve();
|
||||||
void ShowContextMenu(const QPoint& pos);
|
|
||||||
void plotCurve(bool checked);
|
void plotCurve(bool checked);
|
||||||
void on_curveName_editingFinished();
|
void on_curveName_editingFinished();
|
||||||
void on_curvePoints_currentIndexChanged(int index);
|
void on_curvePoints_currentIndexChanged(int index);
|
||||||
|
@ -86,6 +80,16 @@ class Curves : public ModelPanel
|
||||||
void onSceneNewPoint(int x, int y);
|
void onSceneNewPoint(int x, int y);
|
||||||
void onPointSizeEdited();
|
void onPointSizeEdited();
|
||||||
void onNodeDelete();
|
void onNodeDelete();
|
||||||
|
void onCustomContextMenuRequested(QPoint pos);
|
||||||
|
void cmClear();
|
||||||
|
void cmClearAll();
|
||||||
|
void cmCopy();
|
||||||
|
void cmCut();
|
||||||
|
void cmDelete();
|
||||||
|
void cmInsert();
|
||||||
|
void cmPaste();
|
||||||
|
void cmMoveDown();
|
||||||
|
void cmMoveUp();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void resizeEvent(QResizeEvent *event);
|
virtual void resizeEvent(QResizeEvent *event);
|
||||||
|
@ -105,6 +109,16 @@ class Curves : public ModelPanel
|
||||||
bool allowCurveType(int points, CurveData::CurveType type);
|
bool allowCurveType(int points, CurveData::CurveType type);
|
||||||
void setPointY(int i, int x, int y);
|
void setPointY(int i, int x, int y);
|
||||||
CustomScene * scene;
|
CustomScene * scene;
|
||||||
|
int maxCurves;
|
||||||
|
int hasNames;
|
||||||
|
int hasEnhanced;
|
||||||
|
int maxPoints;
|
||||||
|
int selectedIndex;
|
||||||
|
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool insertAllowed() const;
|
||||||
|
bool moveDownAllowed() const;
|
||||||
|
bool moveUpAllowed() const;
|
||||||
|
void swapData(int idx1, int idx2);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _CURVES_H_
|
#endif // _CURVES_H_
|
||||||
|
|
|
@ -127,7 +127,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
|
||||||
else
|
else
|
||||||
label->setText(tr("GF%1").arg(i+1));
|
label->setText(tr("GF%1").arg(i+1));
|
||||||
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
||||||
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(fsw_customContextMenuRequested(QPoint)));
|
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
|
||||||
tableLayout->addWidget(i, 0, label);
|
tableLayout->addWidget(i, 0, label);
|
||||||
// s1.report("label");
|
// s1.report("label");
|
||||||
|
|
||||||
|
@ -608,76 +608,63 @@ void CustomFunctionsPanel::update()
|
||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswPaste()
|
void CustomFunctionsPanel::cmPaste()
|
||||||
{
|
{
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
QByteArray data;
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
if (hasClipboardData(&data)) {
|
||||||
if (mimeData->hasFormat(MIMETYPE_FSW)) {
|
memcpy(&functions[selectedIndex], data.constData(), sizeof(CustomFunctionData));
|
||||||
QByteArray fswData = mimeData->data(MIMETYPE_FSW);
|
resetCBsAndRefresh(selectedIndex);
|
||||||
CustomFunctionData *fsw = &functions[selectedFunction];
|
|
||||||
memcpy(fsw, fswData.constData(), sizeof(CustomFunctionData));
|
|
||||||
resetCBsAndRefresh(selectedFunction);
|
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswDelete()
|
void CustomFunctionsPanel::cmDelete()
|
||||||
{
|
{
|
||||||
int maxidx = fswCapability - 1;
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Special Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
for (int i=selectedFunction; i<maxidx; i++) {
|
return;
|
||||||
if (!functions[i].isEmpty() || !functions[i+1].isEmpty()) {
|
|
||||||
CustomFunctionData *fsw1 = &functions[i];
|
memmove(&functions[selectedIndex], &functions[selectedIndex + 1], (CPN_MAX_SPECIAL_FUNCTIONS - (selectedIndex + 1)) * sizeof(CustomFunctionData));
|
||||||
CustomFunctionData *fsw2 = &functions[i+1];
|
functions[fswCapability - 1].clear();
|
||||||
memcpy(fsw1, fsw2, sizeof(CustomFunctionData));
|
|
||||||
|
for (int i = selectedIndex; i < (fswCapability - 1); i++) {
|
||||||
resetCBsAndRefresh(i);
|
resetCBsAndRefresh(i);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
functions[maxidx].clear();
|
|
||||||
resetCBsAndRefresh(maxidx);
|
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswCopy()
|
void CustomFunctionsPanel::cmCopy()
|
||||||
{
|
{
|
||||||
QByteArray fswData;
|
QByteArray data;
|
||||||
fswData.append((char*)&functions[selectedFunction], sizeof(CustomFunctionData));
|
data.append((char*)&functions[selectedIndex], sizeof(CustomFunctionData));
|
||||||
QMimeData *mimeData = new QMimeData;
|
QMimeData *mimeData = new QMimeData;
|
||||||
mimeData->setData(MIMETYPE_FSW, fswData);
|
mimeData->setData(MIMETYPE_CUSTOM_FUNCTION, data);
|
||||||
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
|
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswCut()
|
void CustomFunctionsPanel::cmCut()
|
||||||
{
|
{
|
||||||
fswCopy();
|
cmCopy();
|
||||||
fswClear();
|
cmClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fsw_customContextMenuRequested(QPoint pos)
|
void CustomFunctionsPanel::onCustomContextMenuRequested(QPoint pos)
|
||||||
{
|
{
|
||||||
QLabel *label = (QLabel *)sender();
|
QLabel *label = (QLabel *)sender();
|
||||||
selectedFunction = label->property("index").toInt();
|
selectedIndex = label->property("index").toInt();
|
||||||
|
|
||||||
QPoint globalPos = label->mapToGlobal(pos);
|
QPoint globalPos = label->mapToGlobal(pos);
|
||||||
|
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
|
||||||
bool hasData = mimeData->hasFormat(MIMETYPE_FSW);
|
|
||||||
bool moveUpAllowed = (selectedFunction > 0);
|
|
||||||
bool moveDownAllowed = (selectedFunction < (fswCapability - 1));
|
|
||||||
bool insertAllowed = (selectedFunction < (fswCapability - 1)) && (functions[fswCapability - 1].isEmpty());
|
|
||||||
|
|
||||||
QMenu contextMenu;
|
QMenu contextMenu;
|
||||||
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(fswCopy()));
|
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
|
||||||
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(fswCut()));
|
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
|
||||||
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(fswPaste()))->setEnabled(hasData);
|
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
|
||||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(fswClear()));
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(fswInsert()))->setEnabled(insertAllowed);
|
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(cmInsert()))->setEnabled(insertAllowed());
|
||||||
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(fswDelete()));
|
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(cmDelete()));
|
||||||
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(fswMoveUp()))->setEnabled(moveUpAllowed);
|
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
|
||||||
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(fswMoveDown()))->setEnabled(moveDownAllowed);
|
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(fswClearAll()));
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
|
||||||
|
|
||||||
contextMenu.exec(globalPos);
|
contextMenu.exec(globalPos);
|
||||||
}
|
}
|
||||||
|
@ -762,25 +749,31 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswMoveUp()
|
void CustomFunctionsPanel::cmMoveUp()
|
||||||
{
|
{
|
||||||
swapFuncData(selectedFunction, selectedFunction - 1);
|
swapData(selectedIndex, selectedIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswMoveDown()
|
void CustomFunctionsPanel::cmMoveDown()
|
||||||
{
|
{
|
||||||
swapFuncData(selectedFunction, selectedFunction + 1);
|
swapData(selectedIndex, selectedIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswClear()
|
void CustomFunctionsPanel::cmClear()
|
||||||
{
|
{
|
||||||
functions[selectedFunction].clear();
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Special Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
resetCBsAndRefresh(selectedFunction);
|
return;
|
||||||
|
|
||||||
|
functions[selectedIndex].clear();
|
||||||
|
resetCBsAndRefresh(selectedIndex);
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswClearAll()
|
void CustomFunctionsPanel::cmClearAll()
|
||||||
{
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Special Functions. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
for (int i=0; i<fswCapability; i++) {
|
for (int i=0; i<fswCapability; i++) {
|
||||||
functions[i].clear();
|
functions[i].clear();
|
||||||
resetCBsAndRefresh(i);
|
resetCBsAndRefresh(i);
|
||||||
|
@ -788,18 +781,17 @@ void CustomFunctionsPanel::fswClearAll()
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::fswInsert()
|
void CustomFunctionsPanel::cmInsert()
|
||||||
{
|
{
|
||||||
for (int i=(fswCapability - 1); i>selectedFunction; i--) {
|
memmove(&functions[selectedIndex + 1], &functions[selectedIndex], (CPN_MAX_SPECIAL_FUNCTIONS - (selectedIndex + 1)) * sizeof(CustomFunctionData));
|
||||||
if (!functions[i].isEmpty() || !functions[i-1].isEmpty()) {
|
functions[selectedIndex].clear();
|
||||||
memcpy(&functions[i], &functions[i-1], sizeof(CustomFunctionData));
|
|
||||||
|
for (int i = selectedIndex; i < (fswCapability - 1); i++) {
|
||||||
resetCBsAndRefresh(i);
|
resetCBsAndRefresh(i);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
fswClear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFunctionsPanel::swapFuncData(int idx1, int idx2)
|
void CustomFunctionsPanel::swapData(int idx1, int idx2)
|
||||||
{
|
{
|
||||||
if ((idx1 != idx2) && (!functions[idx1].isEmpty() || !functions[idx2].isEmpty())) {
|
if ((idx1 != idx2) && (!functions[idx1].isEmpty() || !functions[idx2].isEmpty())) {
|
||||||
CustomFunctionData fswtmp = functions[idx2];
|
CustomFunctionData fswtmp = functions[idx2];
|
||||||
|
@ -823,3 +815,30 @@ void CustomFunctionsPanel::resetCBsAndRefresh(int idx)
|
||||||
refreshCustomFunction(idx);
|
refreshCustomFunction(idx);
|
||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CustomFunctionsPanel::hasClipboardData(QByteArray * data) const
|
||||||
|
{
|
||||||
|
const QClipboard * clipboard = QApplication::clipboard();
|
||||||
|
const QMimeData * mimeData = clipboard->mimeData();
|
||||||
|
if (mimeData->hasFormat(MIMETYPE_CUSTOM_FUNCTION)) {
|
||||||
|
if (data)
|
||||||
|
data->append(mimeData->data(MIMETYPE_CUSTOM_FUNCTION));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CustomFunctionsPanel::insertAllowed() const
|
||||||
|
{
|
||||||
|
return ((selectedIndex < fswCapability - 1) && (model->curves[fswCapability - 1].isEmpty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CustomFunctionsPanel::moveDownAllowed() const
|
||||||
|
{
|
||||||
|
return selectedIndex < fswCapability - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CustomFunctionsPanel::moveUpAllowed() const
|
||||||
|
{
|
||||||
|
return selectedIndex > 0;
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class RawSourceFilterItemModel;
|
||||||
class RawSwitchFilterItemModel;
|
class RawSwitchFilterItemModel;
|
||||||
class TimerEdit;
|
class TimerEdit;
|
||||||
|
|
||||||
constexpr char MIMETYPE_FSW[] = "application/x-companion-fsw";
|
constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function";
|
||||||
|
|
||||||
class RepeatComboBox: public QComboBox
|
class RepeatComboBox: public QComboBox
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ class CustomFunctionsPanel : public GenericPanel
|
||||||
void updateDataModels();
|
void updateDataModels();
|
||||||
void customFunctionEdited();
|
void customFunctionEdited();
|
||||||
void functionEdited();
|
void functionEdited();
|
||||||
void fsw_customContextMenuRequested(QPoint pos);
|
void onCustomContextMenuRequested(QPoint pos);
|
||||||
void refreshCustomFunction(int index, bool modified=false);
|
void refreshCustomFunction(int index, bool modified=false);
|
||||||
void onChildModified();
|
void onChildModified();
|
||||||
bool playSound(int index);
|
bool playSound(int index);
|
||||||
|
@ -75,21 +75,25 @@ class CustomFunctionsPanel : public GenericPanel
|
||||||
void toggleSound(bool play);
|
void toggleSound(bool play);
|
||||||
void onMediaPlayerStateChanged(QMediaPlayer::State state);
|
void onMediaPlayerStateChanged(QMediaPlayer::State state);
|
||||||
void onMediaPlayerError(QMediaPlayer::Error error);
|
void onMediaPlayerError(QMediaPlayer::Error error);
|
||||||
void fswDelete();
|
void cmDelete();
|
||||||
void fswCopy();
|
void cmCopy();
|
||||||
void fswPaste();
|
void cmPaste();
|
||||||
void fswCut();
|
void cmCut();
|
||||||
void fswMoveUp();
|
void cmMoveUp();
|
||||||
void fswMoveDown();
|
void cmMoveDown();
|
||||||
void fswInsert();
|
void cmInsert();
|
||||||
void fswClear();
|
void cmClear();
|
||||||
void fswClearAll();
|
void cmClearAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void populateFuncCB(QComboBox *b, unsigned int value);
|
void populateFuncCB(QComboBox *b, unsigned int value);
|
||||||
void populateGVmodeCB(QComboBox *b, unsigned int value);
|
void populateGVmodeCB(QComboBox *b, unsigned int value);
|
||||||
void populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode=0);
|
void populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode=0);
|
||||||
void swapFuncData(int idx1, int idx2);
|
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool insertAllowed() const;
|
||||||
|
bool moveDownAllowed() const;
|
||||||
|
bool moveUpAllowed() const;
|
||||||
|
void swapData(int idx1, int idx2);
|
||||||
void resetCBsAndRefresh(int idx);
|
void resetCBsAndRefresh(int idx);
|
||||||
RawSwitchFilterItemModel * rawSwitchItemModel;
|
RawSwitchFilterItemModel * rawSwitchItemModel;
|
||||||
RawSourceFilterItemModel * rawSrcAllItemModel;
|
RawSourceFilterItemModel * rawSrcAllItemModel;
|
||||||
|
@ -113,7 +117,7 @@ class CustomFunctionsPanel : public GenericPanel
|
||||||
QSlider * fswtchBLcolor[CPN_MAX_SPECIAL_FUNCTIONS];
|
QSlider * fswtchBLcolor[CPN_MAX_SPECIAL_FUNCTIONS];
|
||||||
QMediaPlayer * mediaPlayer;
|
QMediaPlayer * mediaPlayer;
|
||||||
|
|
||||||
int selectedFunction;
|
int selectedIndex;
|
||||||
int fswCapability;
|
int fswCapability;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
|
|
||||||
class RawSwitchFilterItemModel;
|
class RawSwitchFilterItemModel;
|
||||||
|
|
||||||
|
constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode";
|
||||||
|
constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params";
|
||||||
|
constexpr char MIMETYPE_GVAR_VALUE[] = "application/x-companion-gvar-value";
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class FlightMode;
|
class FlightMode;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +46,7 @@ class FlightModePanel : public ModelPanel
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void nameModified();
|
void nameModified();
|
||||||
|
void datachanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void phaseName_editingFinished();
|
void phaseName_editingFinished();
|
||||||
|
@ -61,18 +66,36 @@ class FlightModePanel : public ModelPanel
|
||||||
void phaseGVMax_editingFinished();
|
void phaseGVMax_editingFinished();
|
||||||
void phaseREValue_editingFinished();
|
void phaseREValue_editingFinished();
|
||||||
void phaseREUse_currentIndexChanged(int index);
|
void phaseREUse_currentIndexChanged(int index);
|
||||||
void name_customContextMenuRequested(const QPoint & pos);
|
void onCustomContextMenuRequested(QPoint pos);
|
||||||
void fmClear();
|
void cmClear();
|
||||||
void gvLabel_customContextMenuRequested(const QPoint & pos);
|
void cmClearAll();
|
||||||
void gvClear();
|
void cmCopy();
|
||||||
|
void cmCut();
|
||||||
|
void cmDelete();
|
||||||
|
void cmInsert();
|
||||||
|
void cmPaste();
|
||||||
|
void cmMoveDown();
|
||||||
|
void cmMoveUp();
|
||||||
|
void gvOnCustomContextMenuRequested(QPoint pos);
|
||||||
|
void gvCmClear();
|
||||||
|
void gvCmClearAll();
|
||||||
|
void gvCmCopy();
|
||||||
|
void gvCmCut();
|
||||||
|
void gvCmDelete();
|
||||||
|
void gvCmInsert();
|
||||||
|
void gvCmPaste();
|
||||||
|
void gvCmMoveDown();
|
||||||
|
void gvCmMoveUp();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FlightMode *ui;
|
Ui::FlightMode *ui;
|
||||||
int phaseIdx;
|
int phaseIdx;
|
||||||
FlightModeData & phase;
|
FlightModeData & phase;
|
||||||
|
int fmCount;
|
||||||
int reCount;
|
int reCount;
|
||||||
int gvCount;
|
int gvCount;
|
||||||
int gvIdx;
|
int gvIdx;
|
||||||
|
int trimCount;
|
||||||
QVector<QLabel *> trimsLabel;
|
QVector<QLabel *> trimsLabel;
|
||||||
QLineEdit * gvNames[CPN_MAX_GVARS];
|
QLineEdit * gvNames[CPN_MAX_GVARS];
|
||||||
QDoubleSpinBox * gvValues[CPN_MAX_GVARS];
|
QDoubleSpinBox * gvValues[CPN_MAX_GVARS];
|
||||||
|
@ -88,12 +111,27 @@ class FlightModePanel : public ModelPanel
|
||||||
QVector<QSpinBox *> trimsValue;
|
QVector<QSpinBox *> trimsValue;
|
||||||
QVector<QSlider *> trimsSlider;
|
QVector<QSlider *> trimsSlider;
|
||||||
RawSwitchFilterItemModel * rawSwitchItemModel;
|
RawSwitchFilterItemModel * rawSwitchItemModel;
|
||||||
|
Board::Type board;
|
||||||
|
|
||||||
void trimUpdate(unsigned int trim);
|
void trimUpdate(unsigned int trim);
|
||||||
void updateGVar(int index);
|
void updateGVar(int index);
|
||||||
|
void updateRotaryEncoder(int index);
|
||||||
void setGVSB(QDoubleSpinBox * spinBox, int min, int max, int val);
|
void setGVSB(QDoubleSpinBox * spinBox, int min, int max, int val);
|
||||||
void populateGvarUnitCB(QComboBox * cb);
|
void populateGvarUnitCB(QComboBox * cb);
|
||||||
void populateGvarPrecCB(QComboBox * cb);
|
void populateGvarPrecCB(QComboBox * cb);
|
||||||
|
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool insertAllowed() const;
|
||||||
|
bool moveDownAllowed() const;
|
||||||
|
bool moveUpAllowed() const;
|
||||||
|
void swapData(int idx1, int idx2);
|
||||||
|
bool gvHasClipboardData() const;
|
||||||
|
bool gvHasDefnClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool gvHasValueClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool gvDeleteAllowed() const;
|
||||||
|
bool gvInsertAllowed() const;
|
||||||
|
bool gvMoveDownAllowed() const;
|
||||||
|
bool gvMoveUpAllowed() const;
|
||||||
|
void gvSwapData(int idx1, int idx2);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FlightModesPanel : public ModelPanel
|
class FlightModesPanel : public ModelPanel
|
||||||
|
|
|
@ -47,18 +47,18 @@ InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & g
|
||||||
qbClear->setText(tr("Clear All Inputs"));
|
qbClear->setText(tr("Clear All Inputs"));
|
||||||
qbClear->setIcon(CompanionIcon("clear.png"));
|
qbClear->setIcon(CompanionIcon("clear.png"));
|
||||||
|
|
||||||
exposLayout->addWidget(ExposlistWidget,1,1,1,3);
|
exposLayout->addWidget(ExposlistWidget, 1, 1, 1, 3);
|
||||||
exposLayout->addWidget(qbUp,2,1);
|
exposLayout->addWidget(qbUp, 2, 1);
|
||||||
exposLayout->addWidget(qbClear,2,2);
|
exposLayout->addWidget(qbClear, 2, 2);
|
||||||
exposLayout->addWidget(qbDown,2,3);
|
exposLayout->addWidget(qbDown, 2, 3);
|
||||||
|
|
||||||
connect(ExposlistWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(expolistWidget_customContextMenuRequested(QPoint)));
|
connect(ExposlistWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(expolistWidget_customContextMenuRequested(QPoint)));
|
||||||
connect(ExposlistWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(expolistWidget_doubleClicked(QModelIndex)));
|
connect(ExposlistWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(expolistWidget_doubleClicked(QModelIndex)));
|
||||||
connect(ExposlistWidget, SIGNAL(mimeDropped(int,const QMimeData*,Qt::DropAction)), this, SLOT(mimeExpoDropped(int, const QMimeData*, Qt::DropAction)));
|
connect(ExposlistWidget, SIGNAL(mimeDropped(int, const QMimeData*,Qt::DropAction)), this, SLOT(mimeExpoDropped(int, const QMimeData*, Qt::DropAction)));
|
||||||
|
|
||||||
connect(qbUp, SIGNAL(pressed()),SLOT(moveExpoUp()));
|
connect(qbUp, SIGNAL(pressed()), SLOT(moveExpoUp()));
|
||||||
connect(qbDown, SIGNAL(pressed()),SLOT(moveExpoDown()));
|
connect(qbDown, SIGNAL(pressed()), SLOT(moveExpoDown()));
|
||||||
connect(qbClear, SIGNAL(pressed()),SLOT(clearExpos()));
|
connect(qbClear, SIGNAL(pressed()), SLOT(clearExpos()));
|
||||||
|
|
||||||
connect(ExposlistWidget, SIGNAL(keyWasPressed(QKeyEvent*)), this, SLOT(expolistWidget_KeyPress(QKeyEvent*)));
|
connect(ExposlistWidget, SIGNAL(keyWasPressed(QKeyEvent*)), this, SLOT(expolistWidget_KeyPress(QKeyEvent*)));
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,9 @@ void InputsPanel::update()
|
||||||
{
|
{
|
||||||
lock = true;
|
lock = true;
|
||||||
ExposlistWidget->clear();
|
ExposlistWidget->clear();
|
||||||
for (int i=0; i < inputsCount; ++i) {
|
for (int i = 0; i < inputsCount; ++i) {
|
||||||
bool filled = false;
|
bool filled = false;
|
||||||
for (uint j=0; j < CPN_MAX_EXPOS; ++j) {
|
for (uint j = 0; j < CPN_MAX_EXPOS; ++j) {
|
||||||
const ExpoData & ed = model->expoData[j];
|
const ExpoData & ed = model->expoData[j];
|
||||||
if ((int)ed.chn == i && ed.mode) {
|
if ((int)ed.chn == i && ed.mode) {
|
||||||
AddInputLine(j);
|
AddInputLine(j);
|
||||||
|
@ -81,7 +81,7 @@ void InputsPanel::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!filled) {
|
if (!filled) {
|
||||||
AddInputLine(-i-1);
|
AddInputLine(-i - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lock = false;
|
lock = false;
|
||||||
|
@ -108,9 +108,8 @@ void InputsPanel::AddInputLine(int dest)
|
||||||
const ExpoData &md = model->expoData[dest];
|
const ExpoData &md = model->expoData[dest];
|
||||||
qba.append((const char*)&md, sizeof(ExpoData));
|
qba.append((const char*)&md, sizeof(ExpoData));
|
||||||
destId = md.chn + 1;
|
destId = md.chn + 1;
|
||||||
const QVector<const ExpoData *> expos = model->expos(md.chn);
|
newChan = model->isExpoParent(dest);
|
||||||
newChan = (expos.constFirst() == &md);
|
hasSibs = (model->hasExpoChildren(dest) || model->hasExpoSiblings(dest));
|
||||||
hasSibs = (expos.constLast() != &md);
|
|
||||||
}
|
}
|
||||||
QListWidgetItem *itm = new QListWidgetItem(getInputText(dest, newChan));
|
QListWidgetItem *itm = new QListWidgetItem(getInputText(dest, newChan));
|
||||||
itm->setData(Qt::UserRole, qba);
|
itm->setData(Qt::UserRole, qba);
|
||||||
|
@ -133,10 +132,10 @@ QString InputsPanel::getInputText(int dest, bool newChan)
|
||||||
{
|
{
|
||||||
QString str;
|
QString str;
|
||||||
if (dest < 0) {
|
if (dest < 0) {
|
||||||
str = modelPrinter.printInputName(-dest-1);
|
str = modelPrinter.printInputName(-dest - 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const ExpoData & input = model->expoData[dest];
|
const ExpoData &input = model->expoData[dest];
|
||||||
const int nameChars = (firmware->getCapability(VirtualInputs) ? 10 : 4);
|
const int nameChars = (firmware->getCapability(VirtualInputs) ? 10 : 4);
|
||||||
if (newChan)
|
if (newChan)
|
||||||
str = QString("%1").arg(modelPrinter.printInputName(input.chn), -nameChars, QChar(' '));
|
str = QString("%1").arg(modelPrinter.printInputName(input.chn), -nameChars, QChar(' '));
|
||||||
|
@ -150,14 +149,14 @@ QString InputsPanel::getInputText(int dest, bool newChan)
|
||||||
|
|
||||||
bool InputsPanel::gm_insertExpo(int idx)
|
bool InputsPanel::gm_insertExpo(int idx)
|
||||||
{
|
{
|
||||||
if (idx<0 || idx>=CPN_MAX_EXPOS || model->expoData[CPN_MAX_EXPOS-1].mode > 0) {
|
if (idx < 0 || idx >= CPN_MAX_EXPOS || model->expoData[CPN_MAX_EXPOS-1].mode > 0) {
|
||||||
QMessageBox::information(this, CPN_STR_APP_NAME, tr("Not enough available inputs!"));
|
QMessageBox::information(this, CPN_STR_APP_NAME, tr("Not enough available Inputs!"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int chn = model->expoData[idx].chn;
|
int chn = model->expoData[idx].chn;
|
||||||
|
|
||||||
ExpoData * newExpo = model->insertInput(idx);
|
ExpoData *newExpo = model->insertInput(idx);
|
||||||
newExpo->chn = chn;
|
newExpo->chn = chn;
|
||||||
newExpo->weight = 100;
|
newExpo->weight = 100;
|
||||||
newExpo->mode = INPUT_MODE_BOTH;
|
newExpo->mode = INPUT_MODE_BOTH;
|
||||||
|
@ -172,19 +171,20 @@ void InputsPanel::gm_deleteExpo(int index, bool clearName)
|
||||||
|
|
||||||
void InputsPanel::gm_openExpo(int index)
|
void InputsPanel::gm_openExpo(int index)
|
||||||
{
|
{
|
||||||
if(index<0 || index>=CPN_MAX_EXPOS) return;
|
if (index < 0 || index >= CPN_MAX_EXPOS)
|
||||||
|
return;
|
||||||
|
|
||||||
ExpoData mixd(model->expoData[index]);
|
ExpoData ed(model->expoData[index]);
|
||||||
|
|
||||||
QString inputName;
|
QString inputName;
|
||||||
if (firmware->getCapability(VirtualInputs))
|
if (firmware->getCapability(VirtualInputs))
|
||||||
inputName = model->inputNames[mixd.chn];
|
inputName = model->inputNames[ed.chn];
|
||||||
|
|
||||||
ExpoDialog *g = new ExpoDialog(this, *model, &mixd, generalSettings, firmware, inputName);
|
ExpoDialog *g = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName);
|
||||||
if (g->exec()) {
|
if (g->exec()) {
|
||||||
model->expoData[index] = mixd;
|
model->expoData[index] = ed;
|
||||||
if (firmware->getCapability(VirtualInputs))
|
if (firmware->getCapability(VirtualInputs))
|
||||||
strncpy(model->inputNames[mixd.chn], inputName.toLatin1().data(), 4);
|
strncpy(model->inputNames[ed.chn], inputName.toLatin1().data(), INPUT_NAME_LEN);
|
||||||
emit modified();
|
emit modified();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -200,28 +200,29 @@ void InputsPanel::gm_openExpo(int index)
|
||||||
int InputsPanel::getExpoIndex(unsigned int dch)
|
int InputsPanel::getExpoIndex(unsigned int dch)
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
while (model->expoData[i].chn<=dch && model->expoData[i].mode && i<CPN_MAX_EXPOS) i++;
|
while (model->expoData[i].chn <= dch && model->expoData[i].mode && i < CPN_MAX_EXPOS)
|
||||||
if(i==CPN_MAX_EXPOS) return -1;
|
i++;
|
||||||
|
if (i == CPN_MAX_EXPOS)
|
||||||
|
return -1;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QList<int> InputsPanel::createExpoListFromSelected()
|
QList<int> InputsPanel::createExpoListFromSelected()
|
||||||
{
|
{
|
||||||
QList<int> list;
|
QList<int> list;
|
||||||
foreach(QListWidgetItem *item, ExposlistWidget->selectedItems()) {
|
foreach (QListWidgetItem *item, ExposlistWidget->selectedItems()) {
|
||||||
int idx= item->data(Qt::UserRole).toByteArray().at(0);
|
int idx = item->data(Qt::UserRole).toByteArray().at(0);
|
||||||
if(idx>=0 && idx<CPN_MAX_EXPOS) list << idx;
|
if (idx >= 0 && idx < CPN_MAX_EXPOS)
|
||||||
|
list << idx;
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InputsPanel::setSelectedByExpoList(QList<int> list)
|
void InputsPanel::setSelectedByExpoList(QList<int> list)
|
||||||
{
|
{
|
||||||
for(int i=0; i<ExposlistWidget->count(); i++) {
|
for (int i = 0; i < ExposlistWidget->count(); i++) {
|
||||||
int t = ExposlistWidget->item(i)->data(Qt::UserRole).toByteArray().at(0);
|
int t = ExposlistWidget->item(i)->data(Qt::UserRole).toByteArray().at(0);
|
||||||
if(list.contains(t))
|
if (list.contains(t))
|
||||||
ExposlistWidget->item(i)->setSelected(true);
|
ExposlistWidget->item(i)->setSelected(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,15 +230,13 @@ void InputsPanel::setSelectedByExpoList(QList<int> list)
|
||||||
void InputsPanel::exposDelete(bool ask)
|
void InputsPanel::exposDelete(bool ask)
|
||||||
{
|
{
|
||||||
QList<int> list = createExpoListFromSelected();
|
QList<int> list = createExpoListFromSelected();
|
||||||
if(list.isEmpty()) return;
|
if (list.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
QMessageBox::StandardButton ret = QMessageBox::No;
|
QMessageBox::StandardButton ret = QMessageBox::No;
|
||||||
|
|
||||||
if(ask)
|
if (ask)
|
||||||
ret = QMessageBox::warning(this, "companion",
|
ret = QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Delete selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No);
|
||||||
tr("Delete Selected Inputs?"),
|
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
|
||||||
|
|
||||||
|
|
||||||
if ((ret == QMessageBox::Yes) || (!ask)) {
|
if ((ret == QMessageBox::Yes) || (!ask)) {
|
||||||
exposDeleteList(list, ask);
|
exposDeleteList(list, ask);
|
||||||
|
@ -256,23 +255,23 @@ void InputsPanel::exposCopy()
|
||||||
{
|
{
|
||||||
QList<int> list = createExpoListFromSelected();
|
QList<int> list = createExpoListFromSelected();
|
||||||
|
|
||||||
QByteArray mxData;
|
QByteArray exData;
|
||||||
foreach(int idx, list) {
|
foreach (int idx, list) {
|
||||||
mxData.append((char*)&model->expoData[idx], sizeof(ExpoData));
|
exData.append((char*)&model->expoData[idx], sizeof(ExpoData));
|
||||||
}
|
}
|
||||||
|
|
||||||
QMimeData *mimeData = new QMimeData;
|
QMimeData *mimeData = new QMimeData;
|
||||||
mimeData->setData("application/x-companion-expo", mxData);
|
mimeData->setData(MIMETYPE_EXPO, exData);
|
||||||
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputsPanel::mimeExpoDropped(int index, const QMimeData *data, Qt::DropAction action)
|
void InputsPanel::mimeExpoDropped(int index, const QMimeData *data, Qt::DropAction action)
|
||||||
{
|
{
|
||||||
int idx = ExposlistWidget->item(index)->data(Qt::UserRole).toByteArray().at(0);
|
int idx = ExposlistWidget->item(index)->data(Qt::UserRole).toByteArray().at(0);
|
||||||
if (action==Qt::CopyAction) {
|
if (action == Qt::CopyAction) {
|
||||||
pasteExpoMimeData(data, idx);
|
pasteExpoMimeData(data, idx);
|
||||||
}
|
}
|
||||||
else if (action==Qt::MoveAction) {
|
else if (action == Qt::MoveAction) {
|
||||||
QList<int> list = createExpoListFromSelected();
|
QList<int> list = createExpoListFromSelected();
|
||||||
exposDeleteList(list, false);
|
exposDeleteList(list, false);
|
||||||
foreach (const int del, list) {
|
foreach (const int del, list) {
|
||||||
|
@ -285,30 +284,31 @@ void InputsPanel::mimeExpoDropped(int index, const QMimeData *data, Qt::DropActi
|
||||||
|
|
||||||
void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx)
|
void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx)
|
||||||
{
|
{
|
||||||
if (mimeData->hasFormat("application/x-companion-expo")) {
|
if (mimeData->hasFormat(MIMETYPE_EXPO)) {
|
||||||
int idx; // mixer index
|
int idx; // expo index
|
||||||
int dch;
|
int dch;
|
||||||
|
|
||||||
if (destIdx < 0) {
|
if (destIdx < 0) {
|
||||||
dch = -destIdx - 1;
|
dch = -destIdx - 1;
|
||||||
idx = getExpoIndex(dch) - 1; //get expo index to insert
|
idx = getExpoIndex(dch) - 1; //get expo index to insert
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
idx = destIdx;
|
idx = destIdx;
|
||||||
dch = model->expoData[idx].chn;
|
dch = model->expoData[idx].chn;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray mxData = mimeData->data("application/x-companion-expo");
|
QByteArray exData = mimeData->data(MIMETYPE_EXPO);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < mxData.size()) {
|
while (i < exData.size()) {
|
||||||
idx++;
|
idx++;
|
||||||
if (!gm_insertExpo(idx))
|
if (!gm_insertExpo(idx))
|
||||||
break;
|
break;
|
||||||
ExpoData *md = &model->expoData[idx];
|
ExpoData *ed = &model->expoData[idx];
|
||||||
memcpy(md, mxData.mid(i, sizeof(ExpoData)).constData(), sizeof(ExpoData));
|
memcpy(ed, exData.mid(i, sizeof(ExpoData)).constData(), sizeof(ExpoData));
|
||||||
const int oldChan = md->chn;
|
const int oldChan = ed->chn;
|
||||||
md->chn = dch;
|
ed->chn = dch;
|
||||||
maybeCopyInputName(oldChan, md->chn);
|
maybeCopyInputName(oldChan, ed->chn);
|
||||||
i += sizeof(ExpoData);
|
i += sizeof(ExpoData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,22 +334,22 @@ void InputsPanel::exposDuplicate()
|
||||||
exposPaste();
|
exposPaste();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InputsPanel::expoOpen(QListWidgetItem *item)
|
void InputsPanel::expoOpen(QListWidgetItem *item)
|
||||||
{
|
{
|
||||||
if (!item)
|
if (!item)
|
||||||
item = ExposlistWidget->currentItem();
|
item = ExposlistWidget->currentItem();
|
||||||
|
|
||||||
int idx = item->data(Qt::UserRole).toByteArray().at(0);
|
int idx = item->data(Qt::UserRole).toByteArray().at(0);
|
||||||
if (idx<0) {
|
if (idx < 0) {
|
||||||
int ch = -idx-1;
|
int ch = -idx - 1;
|
||||||
idx = getExpoIndex(ch); // get expo index to insert
|
idx = getExpoIndex(ch); // get expo index to insert
|
||||||
if (!gm_insertExpo(idx))
|
if (!gm_insertExpo(idx))
|
||||||
return;
|
return;
|
||||||
model->expoData[idx].chn = ch;
|
model->expoData[idx].chn = ch;
|
||||||
expoInserted=true;
|
expoInserted = true;
|
||||||
} else {
|
}
|
||||||
expoInserted=false;
|
else {
|
||||||
|
expoInserted = false;
|
||||||
}
|
}
|
||||||
gm_openExpo(idx);
|
gm_openExpo(idx);
|
||||||
}
|
}
|
||||||
|
@ -358,14 +358,15 @@ void InputsPanel::expoAdd()
|
||||||
{
|
{
|
||||||
int index = ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
|
int index = ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
|
||||||
|
|
||||||
if(index<0) { // if empty then return relevant index
|
if (index < 0) { // if empty then return relevant index
|
||||||
expoOpen();
|
expoOpen();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
index++;
|
index++;
|
||||||
if (!gm_insertExpo(index))
|
if (!gm_insertExpo(index))
|
||||||
return;
|
return;
|
||||||
model->expoData[index].chn = model->expoData[index-1].chn;
|
model->expoData[index].chn = model->expoData[index-1].chn;
|
||||||
expoInserted=true;
|
expoInserted = true;
|
||||||
}
|
}
|
||||||
gm_openExpo(index);
|
gm_openExpo(index);
|
||||||
}
|
}
|
||||||
|
@ -376,41 +377,61 @@ void InputsPanel::expolistWidget_customContextMenuRequested(QPoint pos)
|
||||||
|
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
const QClipboard *clipboard = QApplication::clipboard();
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
const QMimeData *mimeData = clipboard->mimeData();
|
||||||
bool hasData = mimeData->hasFormat("application/x-companion-expo");
|
bool hasData = mimeData->hasFormat(MIMETYPE_EXPO);
|
||||||
|
|
||||||
|
selectedIdx = getIndexFromSelected();
|
||||||
|
inputIdx = getInputIndexFromSelected();
|
||||||
|
|
||||||
QMenu contextMenu;
|
QMenu contextMenu;
|
||||||
contextMenu.addAction(CompanionIcon("add.png"), tr("&Add"),this,SLOT(expoAdd()),tr("Ctrl+A"));
|
QMenu *contextMenuLines = contextMenu.addMenu(tr("Lines"));
|
||||||
contextMenu.addAction(CompanionIcon("edit.png"), tr("&Edit"),this,SLOT(expoOpen()),tr("Enter"));
|
contextMenuLines->addAction(CompanionIcon("add.png"), tr("&Add"), this, SLOT(expoAdd()), tr("Ctrl+A"));
|
||||||
|
contextMenuLines->addAction(CompanionIcon("edit.png"), tr("&Edit"), this, SLOT(expoOpen()), tr("Enter"));
|
||||||
|
contextMenuLines->addSeparator();
|
||||||
|
contextMenuLines->addAction(CompanionIcon("clear.png"), tr("&Delete"), this, SLOT(exposDelete()), tr("Delete"));
|
||||||
|
contextMenuLines->addAction(CompanionIcon("copy.png"), tr("&Copy"), this, SLOT(exposCopy()), tr("Ctrl+C"));
|
||||||
|
contextMenuLines->addAction(CompanionIcon("cut.png"), tr("&Cut"), this, SLOT(exposCut()), tr("Ctrl+X"));
|
||||||
|
contextMenuLines->addAction(CompanionIcon("paste.png"), tr("&Paste"), this, SLOT(exposPaste()), tr("Ctrl+V"))->setEnabled(hasData);
|
||||||
|
contextMenuLines->addAction(CompanionIcon("duplicate.png"), tr("Du&plicate"), this, SLOT(exposDuplicate()), tr("Ctrl+U"));
|
||||||
|
contextMenuLines->addSeparator();
|
||||||
|
contextMenuLines->addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(moveExpoUp()), tr("Ctrl+Up"));
|
||||||
|
contextMenuLines->addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(moveExpoDown()), tr("Ctrl+Down"));
|
||||||
|
|
||||||
|
QMenu *contextMenuInputs = contextMenu.addMenu(tr("Input"));
|
||||||
|
contextMenuInputs->addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmInputInsert()))->setEnabled(cmInputInsertAllowed());
|
||||||
|
contextMenuInputs->addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmInputDelete()));
|
||||||
|
contextMenuInputs->addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmInputMoveUp()))->setEnabled(cmInputMoveUpAllowed());
|
||||||
|
contextMenuInputs->addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmInputMoveDown()))->setEnabled(cmInputMoveDownAllowed());
|
||||||
|
contextMenuInputs->addSeparator();
|
||||||
|
contextMenuInputs->addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmInputClear()))->setEnabled(isExpoIndex(selectedIdx));
|
||||||
|
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("&Delete"),this,SLOT(exposDelete()),tr("Delete"));
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(clearExpos()));
|
||||||
contextMenu.addAction(CompanionIcon("copy.png"), tr("&Copy"),this,SLOT(exposCopy()),tr("Ctrl+C"));
|
|
||||||
contextMenu.addAction(CompanionIcon("cut.png"), tr("&Cut"),this,SLOT(exposCut()),tr("Ctrl+X"));
|
|
||||||
contextMenu.addAction(CompanionIcon("paste.png"), tr("&Paste"),this,SLOT(exposPaste()),tr("Ctrl+V"))->setEnabled(hasData);
|
|
||||||
contextMenu.addAction(CompanionIcon("duplicate.png"), tr("Du&plicate"),this,SLOT(exposDuplicate()),tr("Ctrl+U"));
|
|
||||||
contextMenu.addSeparator();
|
|
||||||
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(moveExpoUp()),tr("Ctrl+Up"));
|
|
||||||
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(moveExpoDown()),tr("Ctrl+Down"));
|
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
contextMenu.addActions(ExposlistWidget->actions());
|
contextMenu.addActions(ExposlistWidget->actions());
|
||||||
|
|
||||||
contextMenu.exec(globalPos);
|
contextMenu.exec(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InputsPanel::expolistWidget_KeyPress(QKeyEvent *event)
|
void InputsPanel::expolistWidget_KeyPress(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if(event->matches(QKeySequence::SelectAll)) expoAdd(); //Ctrl A
|
if (event->matches(QKeySequence::SelectAll))
|
||||||
if(event->matches(QKeySequence::Delete)) exposDelete();
|
expoAdd(); //Ctrl A
|
||||||
if(event->matches(QKeySequence::Copy)) exposCopy();
|
if (event->matches(QKeySequence::Delete))
|
||||||
if(event->matches(QKeySequence::Cut)) exposCut();
|
exposDelete();
|
||||||
if(event->matches(QKeySequence::Paste)) exposPaste();
|
if (event->matches(QKeySequence::Copy))
|
||||||
if(event->matches(QKeySequence::Underline)) exposDuplicate();
|
exposCopy();
|
||||||
|
if (event->matches(QKeySequence::Cut))
|
||||||
|
exposCut();
|
||||||
|
if (event->matches(QKeySequence::Paste))
|
||||||
|
exposPaste();
|
||||||
|
if (event->matches(QKeySequence::Underline))
|
||||||
|
exposDuplicate();
|
||||||
|
|
||||||
if(event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter) expoOpen();
|
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||||
if(event->matches(QKeySequence::MoveToNextLine))
|
expoOpen();
|
||||||
ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow()+1);
|
if (event->matches(QKeySequence::MoveToNextLine))
|
||||||
if(event->matches(QKeySequence::MoveToPreviousLine))
|
ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow() + 1);
|
||||||
ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow()-1);
|
if (event->matches(QKeySequence::MoveToPreviousLine))
|
||||||
|
ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up
|
int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up
|
||||||
|
@ -418,7 +439,7 @@ int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up
|
||||||
if (idx >= CPN_MAX_EXPOS || idx < 0 || (dir && idx >= CPN_MAX_EXPOS - 1) || (!dir && !idx))
|
if (idx >= CPN_MAX_EXPOS || idx < 0 || (dir && idx >= CPN_MAX_EXPOS - 1) || (!dir && !idx))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const int tdx = dir ? idx+1 : idx-1;
|
const int tdx = dir ? idx + 1 : idx-1;
|
||||||
ExpoData temp;
|
ExpoData temp;
|
||||||
ExpoData &src = model->expoData[idx];
|
ExpoData &src = model->expoData[idx];
|
||||||
ExpoData &tgt = model->expoData[tdx];
|
ExpoData &tgt = model->expoData[tdx];
|
||||||
|
@ -432,7 +453,7 @@ int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up
|
||||||
|
|
||||||
if (tgt.chn != src.chn || tgtempty) {
|
if (tgt.chn != src.chn || tgtempty) {
|
||||||
const int oldChan = src.chn;
|
const int oldChan = src.chn;
|
||||||
if (dir && src.chn < unsigned(inputsCount-1))
|
if (dir && src.chn < unsigned(inputsCount - 1))
|
||||||
src.chn++;
|
src.chn++;
|
||||||
else if (!dir && src.chn > 0)
|
else if (!dir && src.chn > 0)
|
||||||
src.chn--;
|
src.chn--;
|
||||||
|
@ -452,7 +473,7 @@ void InputsPanel::moveExpoList(bool down)
|
||||||
QList<int> list = createExpoListFromSelected();
|
QList<int> list = createExpoListFromSelected();
|
||||||
QList<int> highlightList;
|
QList<int> highlightList;
|
||||||
bool mod = false;
|
bool mod = false;
|
||||||
foreach(int idx, list) {
|
foreach (int idx, list) {
|
||||||
const int newIdx = gm_moveExpo(idx, down);
|
const int newIdx = gm_moveExpo(idx, down);
|
||||||
if (newIdx > -1) {
|
if (newIdx > -1) {
|
||||||
highlightList << newIdx;
|
highlightList << newIdx;
|
||||||
|
@ -486,7 +507,7 @@ void InputsPanel::exposDeleteList(QList<int> list, bool clearName)
|
||||||
std::sort(list.begin(), list.end());
|
std::sort(list.begin(), list.end());
|
||||||
|
|
||||||
int iDec = 0;
|
int iDec = 0;
|
||||||
foreach(int idx, list) {
|
foreach (int idx, list) {
|
||||||
gm_deleteExpo(idx-iDec, clearName);
|
gm_deleteExpo(idx-iDec, clearName);
|
||||||
iDec++;
|
iDec++;
|
||||||
}
|
}
|
||||||
|
@ -494,8 +515,11 @@ void InputsPanel::exposDeleteList(QList<int> list, bool clearName)
|
||||||
|
|
||||||
void InputsPanel::clearExpos()
|
void InputsPanel::clearExpos()
|
||||||
{
|
{
|
||||||
if (QMessageBox::question(this, tr("Clear Inputs?"), tr("Really clear all the inputs?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||||
model->clearInputs();
|
model->clearInputs();
|
||||||
|
for (int i = 0; i < inputsCount; i++) {
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, i);
|
||||||
|
}
|
||||||
emit modified();
|
emit modified();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -512,8 +536,172 @@ void InputsPanel::maybeCopyInputName(int srcChan, int destChan)
|
||||||
if (srcEmpty) {
|
if (srcEmpty) {
|
||||||
// if destination input name is empty, copy it from source expo input
|
// if destination input name is empty, copy it from source expo input
|
||||||
if (!strlen(model->inputNames[destChan]))
|
if (!strlen(model->inputNames[destChan]))
|
||||||
strncpy(model->inputNames[destChan], model->inputNames[srcChan], 5);
|
strncpy(model->inputNames[destChan], model->inputNames[srcChan], INPUT_NAME_LEN);
|
||||||
// clear the emptry source channel name
|
// clear the emptry source channel name
|
||||||
model->inputNames[srcChan][0] = 0;
|
model->inputNames[srcChan][0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InputsPanel::cmInputInsertAllowed() const
|
||||||
|
{
|
||||||
|
return ((!model->hasExpos(inputsCount - 1)) && (inputIdx < inputsCount - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputsPanel::cmInputMoveDownAllowed() const
|
||||||
|
{
|
||||||
|
return (inputIdx >= 0 && (inputIdx < inputsCount - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputsPanel::cmInputMoveUpAllowed() const
|
||||||
|
{
|
||||||
|
return inputIdx > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputsPanel::cmInputClear()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) {
|
||||||
|
ExpoData *ed = &model->expoData[i];
|
||||||
|
if ((int)ed->chn == inputIdx)
|
||||||
|
model->removeInput(i);
|
||||||
|
}
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, inputIdx);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputsPanel::cmInputDelete()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < CPN_MAX_EXPOS; i++) {
|
||||||
|
ExpoData *ed = &model->expoData[i];
|
||||||
|
if ((int)ed->chn == inputIdx)
|
||||||
|
model->removeInput(i);
|
||||||
|
else if ((int)ed->chn > inputIdx)
|
||||||
|
ed->chn--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = inputIdx; i < inputsCount; i++) {
|
||||||
|
strncpy(model->inputNames[i], model->inputNames[i + 1], sizeof(model->inputNames[i]) - 1);
|
||||||
|
}
|
||||||
|
model->inputNames[inputsCount - 1][0] = 0;
|
||||||
|
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SHIFT, inputIdx, 0, -1);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputsPanel::cmInputInsert()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CPN_MAX_EXPOS; i++) {
|
||||||
|
ExpoData *ed = &model->expoData[i];
|
||||||
|
if ((int)ed->chn >= inputIdx)
|
||||||
|
ed->chn++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = inputsCount - 1; i > inputIdx; i--) {
|
||||||
|
strncpy(model->inputNames[i], model->inputNames[i - 1], sizeof(model->inputNames[i]) - 1);
|
||||||
|
}
|
||||||
|
model->inputNames[inputIdx][0] = 0;
|
||||||
|
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SHIFT, inputIdx, 0, 1);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputsPanel::cmInputMoveDown()
|
||||||
|
{
|
||||||
|
cmInputSwapData(inputIdx, inputIdx + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputsPanel::cmInputMoveUp()
|
||||||
|
{
|
||||||
|
cmInputSwapData(inputIdx - 1, inputIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputsPanel::cmInputSwapData(int idx1, int idx2)
|
||||||
|
{
|
||||||
|
if (idx1 >= idx2 || (!model->hasExpos(idx1) && !model->hasExpos(idx2)))
|
||||||
|
return;
|
||||||
|
// save expos
|
||||||
|
int expoidx = -1;
|
||||||
|
QVector<ExpoData> edtmp;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < CPN_MAX_EXPOS; i++) {
|
||||||
|
ExpoData *ed = &model->expoData[i];
|
||||||
|
if ((int)ed->chn == idx1) {
|
||||||
|
edtmp << model->expoData[i];
|
||||||
|
if (expoidx < 0)
|
||||||
|
expoidx = i;
|
||||||
|
}
|
||||||
|
else if ((int)ed->chn > idx1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// move expos up
|
||||||
|
const int offset = i - expoidx;
|
||||||
|
int expocnt;
|
||||||
|
for (int j = i; j < CPN_MAX_EXPOS; j++) {
|
||||||
|
ExpoData *ed = &model->expoData[j];
|
||||||
|
if ((int)ed->chn == idx2) {
|
||||||
|
ExpoData *dest = &model->expoData[j - offset];
|
||||||
|
memcpy(dest, &model->expoData[j], sizeof(ExpoData));
|
||||||
|
dest->chn = idx1;
|
||||||
|
expocnt++;
|
||||||
|
}
|
||||||
|
else if ((int)ed->chn > idx2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// copy back saved expos
|
||||||
|
int cnt = 0;
|
||||||
|
foreach (ExpoData ed, edtmp) {
|
||||||
|
ExpoData *dest = &model->expoData[expoidx + expocnt + cnt];
|
||||||
|
memcpy(dest, &ed, sizeof(ExpoData));
|
||||||
|
dest->chn = idx2;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap names
|
||||||
|
QByteArray *tname = new QByteArray(model->inputNames[idx2]);
|
||||||
|
strncpy(model->inputNames[idx2], model->inputNames[idx1], sizeof(model->inputNames[idx2]) - 1);
|
||||||
|
strncpy(model->inputNames[idx1], tname->data(), sizeof(model->inputNames[idx1]) - 1);
|
||||||
|
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputsPanel::isInputIndex(const int index)
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputsPanel::isExpoIndex(const int index)
|
||||||
|
{
|
||||||
|
return !isInputIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputsPanel::getIndexFromSelected()
|
||||||
|
{
|
||||||
|
return ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputsPanel::getInputIndexFromSelected()
|
||||||
|
{
|
||||||
|
const int selidx = getIndexFromSelected();
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if (isInputIndex(selidx))
|
||||||
|
idx = -selidx - 1;
|
||||||
|
else {
|
||||||
|
const ExpoData *ed = &model->expoData[selidx];
|
||||||
|
idx = ed->chn;
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "mixerslistwidget.h"
|
#include "mixerslistwidget.h"
|
||||||
#include "modelprinter.h"
|
#include "modelprinter.h"
|
||||||
|
|
||||||
|
constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo";
|
||||||
|
|
||||||
class InputsPanel : public ModelPanel
|
class InputsPanel : public ModelPanel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -52,12 +54,19 @@ class InputsPanel : public ModelPanel
|
||||||
void expoOpen(QListWidgetItem *item = NULL);
|
void expoOpen(QListWidgetItem *item = NULL);
|
||||||
void expoAdd();
|
void expoAdd();
|
||||||
void maybeCopyInputName(int srcChan, int destChan);
|
void maybeCopyInputName(int srcChan, int destChan);
|
||||||
|
void cmInputClear();
|
||||||
|
void cmInputDelete();
|
||||||
|
void cmInputInsert();
|
||||||
|
void cmInputMoveDown();
|
||||||
|
void cmInputMoveUp();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool expoInserted;
|
bool expoInserted;
|
||||||
MixersListWidget *ExposlistWidget;
|
MixersListWidget *ExposlistWidget;
|
||||||
int inputsCount;
|
int inputsCount;
|
||||||
ModelPrinter modelPrinter;
|
ModelPrinter modelPrinter;
|
||||||
|
int selectedIdx;
|
||||||
|
int inputIdx;
|
||||||
|
|
||||||
int getExpoIndex(unsigned int dch);
|
int getExpoIndex(unsigned int dch);
|
||||||
bool gm_insertExpo(int idx);
|
bool gm_insertExpo(int idx);
|
||||||
|
@ -70,7 +79,14 @@ class InputsPanel : public ModelPanel
|
||||||
void pasteExpoMimeData(const QMimeData * mimeData, int destIdx);
|
void pasteExpoMimeData(const QMimeData * mimeData, int destIdx);
|
||||||
void AddInputLine(int dest);
|
void AddInputLine(int dest);
|
||||||
QString getInputText(int dest, bool newChan);
|
QString getInputText(int dest, bool newChan);
|
||||||
|
bool cmInputInsertAllowed() const;
|
||||||
|
bool cmInputMoveDownAllowed() const;
|
||||||
|
bool cmInputMoveUpAllowed() const;
|
||||||
|
void cmInputSwapData(int idx1, int idx2);
|
||||||
|
bool isInputIndex(const int index);
|
||||||
|
bool isExpoIndex(const int index);
|
||||||
|
int getIndexFromSelected();
|
||||||
|
int getInputIndexFromSelected();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _INPUTS_H_
|
#endif // _INPUTS_H_
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
|
LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
|
||||||
ModelPanel(parent, model, generalSettings, firmware),
|
ModelPanel(parent, model, generalSettings, firmware),
|
||||||
selectedSwitch(0)
|
selectedIndex(0)
|
||||||
{
|
{
|
||||||
Stopwatch s1("LogicalSwitchesPanel");
|
Stopwatch s1("LogicalSwitchesPanel");
|
||||||
|
|
||||||
|
@ -35,19 +35,22 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
|
||||||
const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup);
|
const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup);
|
||||||
rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, srcGroups, this);
|
rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, srcGroups, this);
|
||||||
|
|
||||||
|
lsCapability = firmware->getCapability(LogicalSwitches);
|
||||||
|
lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt);
|
||||||
|
|
||||||
QStringList headerLabels;
|
QStringList headerLabels;
|
||||||
headerLabels << "#" << tr("Function") << tr("V1") << tr("V2") << tr("AND Switch");
|
headerLabels << "#" << tr("Function") << tr("V1") << tr("V2") << tr("AND Switch");
|
||||||
if (firmware->getCapability(LogicalSwitchesExt)) {
|
if (lsCapabilityExt) {
|
||||||
headerLabels << tr("Duration") << tr("Delay");
|
headerLabels << tr("Duration") << tr("Delay");
|
||||||
}
|
}
|
||||||
TableLayout * tableLayout = new TableLayout(this, firmware->getCapability(LogicalSwitches), headerLabels);
|
TableLayout * tableLayout = new TableLayout(this, lsCapability, headerLabels);
|
||||||
|
|
||||||
s1.report("header");
|
s1.report("header");
|
||||||
|
|
||||||
const int channelsMax = model.getChannelsMax(true);
|
const int channelsMax = model.getChannelsMax(true);
|
||||||
|
|
||||||
lock = true;
|
lock = true;
|
||||||
for (int i=0; i<firmware->getCapability(LogicalSwitches); i++) {
|
for (int i=0; i<lsCapability; i++) {
|
||||||
// The label
|
// The label
|
||||||
QLabel * label = new QLabel(this);
|
QLabel * label = new QLabel(this);
|
||||||
label->setProperty("index", i);
|
label->setProperty("index", i);
|
||||||
|
@ -56,96 +59,96 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
|
||||||
label->setToolTip(tr("Popup menu available"));
|
label->setToolTip(tr("Popup menu available"));
|
||||||
label->setMouseTracking(true);
|
label->setMouseTracking(true);
|
||||||
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
||||||
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(csw_customContextMenuRequested(QPoint)));
|
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
|
||||||
tableLayout->addWidget(i, 0, label);
|
tableLayout->addWidget(i, 0, label);
|
||||||
|
|
||||||
// The function
|
// The function
|
||||||
csw[i] = new QComboBox(this);
|
cbFunction[i] = new QComboBox(this);
|
||||||
csw[i]->setProperty("index", i);
|
cbFunction[i]->setProperty("index", i);
|
||||||
populateCSWCB(csw[i]);
|
populateFunctionCB(cbFunction[i]);
|
||||||
connect(csw[i], SIGNAL(currentIndexChanged(int)), this, SLOT(functionChanged()));
|
connect(cbFunction[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onFunctionChanged()));
|
||||||
tableLayout->addWidget(i, 1, csw[i]);
|
tableLayout->addWidget(i, 1, cbFunction[i]);
|
||||||
|
|
||||||
// V1
|
// V1
|
||||||
QHBoxLayout *v1Layout = new QHBoxLayout();
|
QHBoxLayout *v1Layout = new QHBoxLayout();
|
||||||
cswitchSource1[i] = new QComboBox(this);
|
cbSource1[i] = new QComboBox(this);
|
||||||
cswitchSource1[i]->setProperty("index",i);
|
cbSource1[i]->setProperty("index",i);
|
||||||
connect(cswitchSource1[i], SIGNAL(currentIndexChanged(int)), this, SLOT(v1Edited(int)));
|
connect(cbSource1[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onV1Changed(int)));
|
||||||
v1Layout->addWidget(cswitchSource1[i]);
|
v1Layout->addWidget(cbSource1[i]);
|
||||||
cswitchSource1[i]->setVisible(false);
|
cbSource1[i]->setVisible(false);
|
||||||
cswitchValue[i] = new QDoubleSpinBox(this);
|
dsbValue[i] = new QDoubleSpinBox(this);
|
||||||
cswitchValue[i]->setMaximum(channelsMax);
|
dsbValue[i]->setMaximum(channelsMax);
|
||||||
cswitchValue[i]->setMinimum(-channelsMax);
|
dsbValue[i]->setMinimum(-channelsMax);
|
||||||
cswitchValue[i]->setAccelerated(true);
|
dsbValue[i]->setAccelerated(true);
|
||||||
cswitchValue[i]->setDecimals(0);
|
dsbValue[i]->setDecimals(0);
|
||||||
cswitchValue[i]->setProperty("index", i);
|
dsbValue[i]->setProperty("index", i);
|
||||||
connect(cswitchValue[i], SIGNAL(editingFinished()), this, SLOT(offsetEdited()));
|
connect(dsbValue[i], SIGNAL(editingFinished()), this, SLOT(onOffsetChanged()));
|
||||||
v1Layout->addWidget(cswitchValue[i]);
|
v1Layout->addWidget(dsbValue[i]);
|
||||||
cswitchValue[i]->setVisible(false);
|
dsbValue[i]->setVisible(false);
|
||||||
tableLayout->addLayout(i, 2, v1Layout);
|
tableLayout->addLayout(i, 2, v1Layout);
|
||||||
|
|
||||||
// V2
|
// V2
|
||||||
QHBoxLayout *v2Layout = new QHBoxLayout();
|
QHBoxLayout *v2Layout = new QHBoxLayout();
|
||||||
cswitchSource2[i] = new QComboBox(this);
|
cbSource2[i] = new QComboBox(this);
|
||||||
cswitchSource2[i]->setProperty("index", i);
|
cbSource2[i]->setProperty("index", i);
|
||||||
connect(cswitchSource2[i], SIGNAL(currentIndexChanged(int)), this, SLOT(v2Edited(int)));
|
connect(cbSource2[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onV2Changed(int)));
|
||||||
v2Layout->addWidget(cswitchSource2[i]);
|
v2Layout->addWidget(cbSource2[i]);
|
||||||
cswitchSource2[i]->setVisible(false);
|
cbSource2[i]->setVisible(false);
|
||||||
cswitchOffset[i] = new QDoubleSpinBox(this);
|
dsbOffset[i] = new QDoubleSpinBox(this);
|
||||||
cswitchOffset[i]->setProperty("index",i);
|
dsbOffset[i]->setProperty("index",i);
|
||||||
cswitchOffset[i]->setMaximum(channelsMax);
|
dsbOffset[i]->setMaximum(channelsMax);
|
||||||
cswitchOffset[i]->setMinimum(-channelsMax);
|
dsbOffset[i]->setMinimum(-channelsMax);
|
||||||
cswitchOffset[i]->setAccelerated(true);
|
dsbOffset[i]->setAccelerated(true);
|
||||||
cswitchOffset[i]->setDecimals(0);
|
dsbOffset[i]->setDecimals(0);
|
||||||
connect(cswitchOffset[i], SIGNAL(editingFinished()), this, SLOT(offsetEdited()));
|
connect(dsbOffset[i], SIGNAL(editingFinished()), this, SLOT(onOffsetChanged()));
|
||||||
cswitchOffset[i]->setVisible(false);
|
dsbOffset[i]->setVisible(false);
|
||||||
v2Layout->addWidget(cswitchOffset[i]);
|
v2Layout->addWidget(dsbOffset[i]);
|
||||||
cswitchOffset2[i] = new QDoubleSpinBox(this);
|
dsbOffset2[i] = new QDoubleSpinBox(this);
|
||||||
cswitchOffset2[i]->setProperty("index",i);
|
dsbOffset2[i]->setProperty("index",i);
|
||||||
cswitchOffset2[i]->setMaximum(channelsMax);
|
dsbOffset2[i]->setMaximum(channelsMax);
|
||||||
cswitchOffset2[i]->setMinimum(-channelsMax);
|
dsbOffset2[i]->setMinimum(-channelsMax);
|
||||||
cswitchOffset2[i]->setAccelerated(true);
|
dsbOffset2[i]->setAccelerated(true);
|
||||||
cswitchOffset2[i]->setDecimals(0);
|
dsbOffset2[i]->setDecimals(0);
|
||||||
cswitchOffset2[i]->setSpecialValueText(" " + tr("(instant)"));
|
dsbOffset2[i]->setSpecialValueText(" " + tr("(instant)"));
|
||||||
connect(cswitchOffset2[i], SIGNAL(editingFinished()), this, SLOT(offsetEdited()));
|
connect(dsbOffset2[i], SIGNAL(editingFinished()), this, SLOT(onOffsetChanged()));
|
||||||
cswitchOffset2[i]->setVisible(false);
|
dsbOffset2[i]->setVisible(false);
|
||||||
v2Layout->addWidget(cswitchOffset2[i]);
|
v2Layout->addWidget(dsbOffset2[i]);
|
||||||
cswitchTOffset[i] = new TimerEdit(this);
|
teOffset[i] = new TimerEdit(this);
|
||||||
cswitchTOffset[i]->setProperty("index",i);
|
teOffset[i]->setProperty("index",i);
|
||||||
connect(cswitchTOffset[i],SIGNAL(editingFinished()),this,SLOT(offsetEdited()));
|
connect(teOffset[i],SIGNAL(editingFinished()),this,SLOT(onOffsetChanged()));
|
||||||
v2Layout->addWidget(cswitchTOffset[i]);
|
v2Layout->addWidget(teOffset[i]);
|
||||||
cswitchTOffset[i]->setVisible(false);
|
teOffset[i]->setVisible(false);
|
||||||
tableLayout->addLayout(i, 3, v2Layout);
|
tableLayout->addLayout(i, 3, v2Layout);
|
||||||
|
|
||||||
// AND
|
// AND
|
||||||
cswitchAnd[i] = new QComboBox(this);
|
cbAndSwitch[i] = new QComboBox(this);
|
||||||
cswitchAnd[i]->setProperty("index", i);
|
cbAndSwitch[i]->setProperty("index", i);
|
||||||
populateAndSwitchCB(cswitchAnd[i]);
|
populateAndSwitchCB(cbAndSwitch[i]);
|
||||||
connect(cswitchAnd[i], SIGNAL(currentIndexChanged(int)), this, SLOT(andEdited(int)));
|
connect(cbAndSwitch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onAndSwitchChanged(int)));
|
||||||
tableLayout->addWidget(i, 4, cswitchAnd[i]);
|
tableLayout->addWidget(i, 4, cbAndSwitch[i]);
|
||||||
|
|
||||||
if (firmware->getCapability(LogicalSwitchesExt)) {
|
if (lsCapabilityExt) {
|
||||||
// Duration
|
// Duration
|
||||||
cswitchDuration[i] = new QDoubleSpinBox(this);
|
dsbDuration[i] = new QDoubleSpinBox(this);
|
||||||
cswitchDuration[i]->setProperty("index", i);
|
dsbDuration[i]->setProperty("index", i);
|
||||||
cswitchDuration[i]->setSingleStep(0.1);
|
dsbDuration[i]->setSingleStep(0.1);
|
||||||
cswitchDuration[i]->setMaximum(25);
|
dsbDuration[i]->setMaximum(25);
|
||||||
cswitchDuration[i]->setMinimum(0);
|
dsbDuration[i]->setMinimum(0);
|
||||||
cswitchDuration[i]->setAccelerated(true);
|
dsbDuration[i]->setAccelerated(true);
|
||||||
cswitchDuration[i]->setDecimals(1);
|
dsbDuration[i]->setDecimals(1);
|
||||||
connect(cswitchDuration[i], SIGNAL(valueChanged(double)), this, SLOT(durationEdited(double)));
|
connect(dsbDuration[i], SIGNAL(valueChanged(double)), this, SLOT(onDurationChanged(double)));
|
||||||
tableLayout->addWidget(i, 5, cswitchDuration[i]);
|
tableLayout->addWidget(i, 5, dsbDuration[i]);
|
||||||
|
|
||||||
// Delay
|
// Delay
|
||||||
cswitchDelay[i] = new QDoubleSpinBox(this);
|
dsbDelay[i] = new QDoubleSpinBox(this);
|
||||||
cswitchDelay[i]->setProperty("index", i);
|
dsbDelay[i]->setProperty("index", i);
|
||||||
cswitchDelay[i]->setSingleStep(0.1);
|
dsbDelay[i]->setSingleStep(0.1);
|
||||||
cswitchDelay[i]->setMaximum(25);
|
dsbDelay[i]->setMaximum(25);
|
||||||
cswitchDelay[i]->setMinimum(0);
|
dsbDelay[i]->setMinimum(0);
|
||||||
cswitchDelay[i]->setAccelerated(true);
|
dsbDelay[i]->setAccelerated(true);
|
||||||
cswitchDelay[i]->setDecimals(1);
|
dsbDelay[i]->setDecimals(1);
|
||||||
connect(cswitchDelay[i], SIGNAL(valueChanged(double)), this, SLOT(delayEdited(double)));
|
connect(dsbDelay[i], SIGNAL(valueChanged(double)), this, SLOT(onDelayChanged(double)));
|
||||||
tableLayout->addWidget(i, 6, cswitchDelay[i]);
|
tableLayout->addWidget(i, 6, dsbDelay[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +158,7 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
|
||||||
lock = false;
|
lock = false;
|
||||||
update();
|
update();
|
||||||
tableLayout->resizeColumnsToContents();
|
tableLayout->resizeColumnsToContents();
|
||||||
tableLayout->pushRowsUp(firmware->getCapability(LogicalSwitches)+1);
|
tableLayout->pushRowsUp(lsCapability+1);
|
||||||
s1.report("end");
|
s1.report("end");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,10 +175,10 @@ void LogicalSwitchesPanel::updateDataModels()
|
||||||
lock = oldLock;
|
lock = oldLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::functionChanged()
|
void LogicalSwitchesPanel::onFunctionChanged()
|
||||||
{
|
{
|
||||||
int i = sender()->property("index").toInt();
|
int i = sender()->property("index").toInt();
|
||||||
unsigned newFunc = csw[i]->currentData().toUInt();
|
unsigned newFunc = cbFunction[i]->currentData().toUInt();
|
||||||
|
|
||||||
if (model->logicalSw[i].func == newFunc)
|
if (model->logicalSw[i].func == newFunc)
|
||||||
return;
|
return;
|
||||||
|
@ -204,13 +207,13 @@ void LogicalSwitchesPanel::functionChanged()
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::v1Edited(int value)
|
void LogicalSwitchesPanel::onV1Changed(int value)
|
||||||
{
|
{
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
int i = sender()->property("index").toInt();
|
int i = sender()->property("index").toInt();
|
||||||
model->logicalSw[i].val1 = cswitchSource1[i]->itemData(value).toInt();
|
model->logicalSw[i].val1 = cbSource1[i]->itemData(value).toInt();
|
||||||
if (model->logicalSw[i].getFunctionFamily() == LS_FAMILY_VOFS) {
|
if (model->logicalSw[i].getFunctionFamily() == LS_FAMILY_VOFS) {
|
||||||
if (!offsetEditedAt(i))
|
if (!offsetChangedAt(i))
|
||||||
updateLine(i);
|
updateLine(i);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -219,25 +222,25 @@ void LogicalSwitchesPanel::v1Edited(int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::v2Edited(int value)
|
void LogicalSwitchesPanel::onV2Changed(int value)
|
||||||
{
|
{
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
int i = sender()->property("index").toInt();
|
int i = sender()->property("index").toInt();
|
||||||
model->logicalSw[i].val2 = cswitchSource2[i]->itemData(value).toInt();
|
model->logicalSw[i].val2 = cbSource2[i]->itemData(value).toInt();
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::andEdited(int value)
|
void LogicalSwitchesPanel::onAndSwitchChanged(int value)
|
||||||
{
|
{
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
int index = sender()->property("index").toInt();
|
int index = sender()->property("index").toInt();
|
||||||
model->logicalSw[index].andsw = cswitchAnd[index]->itemData(value).toInt();
|
model->logicalSw[index].andsw = cbAndSwitch[index]->itemData(value).toInt();
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::durationEdited(double duration)
|
void LogicalSwitchesPanel::onDurationChanged(double duration)
|
||||||
{
|
{
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
int index = sender()->property("index").toInt();
|
int index = sender()->property("index").toInt();
|
||||||
|
@ -246,7 +249,7 @@ void LogicalSwitchesPanel::durationEdited(double duration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::delayEdited(double delay)
|
void LogicalSwitchesPanel::onDelayChanged(double delay)
|
||||||
{
|
{
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
int index = sender()->property("index").toInt();
|
int index = sender()->property("index").toInt();
|
||||||
|
@ -255,12 +258,12 @@ void LogicalSwitchesPanel::delayEdited(double delay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::offsetEdited()
|
void LogicalSwitchesPanel::onOffsetChanged()
|
||||||
{
|
{
|
||||||
offsetEditedAt(sender()->property("index").toInt());
|
offsetChangedAt(sender()->property("index").toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LogicalSwitchesPanel::offsetEditedAt(int index)
|
bool LogicalSwitchesPanel::offsetChangedAt(int index)
|
||||||
{
|
{
|
||||||
if (lock)
|
if (lock)
|
||||||
return false;
|
return false;
|
||||||
|
@ -275,7 +278,7 @@ bool LogicalSwitchesPanel::offsetEditedAt(int index)
|
||||||
{
|
{
|
||||||
RawSource source = RawSource(model->logicalSw[index].val1);
|
RawSource source = RawSource(model->logicalSw[index].val1);
|
||||||
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[index].getRangeFlags());
|
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[index].getRangeFlags());
|
||||||
double currVal = source.isTimeBased() ? cswitchTOffset[index]->timeInSeconds() : cswitchOffset[index]->value();
|
double currVal = source.isTimeBased() ? teOffset[index]->timeInSeconds() : dsbOffset[index]->value();
|
||||||
value = round((currVal - range.offset) / range.step);
|
value = round((currVal - range.offset) / range.step);
|
||||||
mod = (mod || value != model->logicalSw[index].val2);
|
mod = (mod || value != model->logicalSw[index].val2);
|
||||||
model->logicalSw[index].val2 = value;
|
model->logicalSw[index].val2 = value;
|
||||||
|
@ -283,22 +286,22 @@ bool LogicalSwitchesPanel::offsetEditedAt(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
case LS_FAMILY_TIMER:
|
case LS_FAMILY_TIMER:
|
||||||
value = TimToVal(cswitchValue[index]->value());
|
value = TimToVal(dsbValue[index]->value());
|
||||||
mod = (mod || value != model->logicalSw[index].val1);
|
mod = (mod || value != model->logicalSw[index].val1);
|
||||||
model->logicalSw[index].val1 = value;
|
model->logicalSw[index].val1 = value;
|
||||||
value = TimToVal(cswitchOffset[index]->value());
|
value = TimToVal(dsbOffset[index]->value());
|
||||||
mod = (mod || value != model->logicalSw[index].val2);
|
mod = (mod || value != model->logicalSw[index].val2);
|
||||||
model->logicalSw[index].val2 = value;
|
model->logicalSw[index].val2 = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LS_FAMILY_EDGE:
|
case LS_FAMILY_EDGE:
|
||||||
if (sender() == cswitchOffset[index]) {
|
if (sender() == dsbOffset[index]) {
|
||||||
value = TimToVal(cswitchOffset[index]->value());
|
value = TimToVal(dsbOffset[index]->value());
|
||||||
mod = (mod || value != model->logicalSw[index].val2);
|
mod = (mod || value != model->logicalSw[index].val2);
|
||||||
model->logicalSw[index].val2 = value;
|
model->logicalSw[index].val2 = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value = TimToVal(cswitchOffset2[index]->value()) - model->logicalSw[index].val2;
|
value = TimToVal(dsbOffset2[index]->value()) - model->logicalSw[index].val2;
|
||||||
mod = (mod || value != model->logicalSw[index].val3);
|
mod = (mod || value != model->logicalSw[index].val3);
|
||||||
model->logicalSw[index].val3 = value;
|
model->logicalSw[index].val3 = value;
|
||||||
}
|
}
|
||||||
|
@ -347,8 +350,8 @@ void LogicalSwitchesPanel::updateLine(int i)
|
||||||
lock = true;
|
lock = true;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
|
|
||||||
csw[i]->setCurrentIndex(csw[i]->findData(model->logicalSw[i].func));
|
cbFunction[i]->setCurrentIndex(cbFunction[i]->findData(model->logicalSw[i].func));
|
||||||
cswitchAnd[i]->setCurrentIndex(cswitchAnd[i]->findData(RawSwitch(model->logicalSw[i].andsw).toValue()));
|
cbAndSwitch[i]->setCurrentIndex(cbAndSwitch[i]->findData(RawSwitch(model->logicalSw[i].andsw).toValue()));
|
||||||
|
|
||||||
if (!model->logicalSw[i].func) {
|
if (!model->logicalSw[i].func) {
|
||||||
mask = 0;
|
mask = 0;
|
||||||
|
@ -364,27 +367,27 @@ void LogicalSwitchesPanel::updateLine(int i)
|
||||||
RawSource source = RawSource(model->logicalSw[i].val1);
|
RawSource source = RawSource(model->logicalSw[i].val1);
|
||||||
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[i].getRangeFlags());
|
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[i].getRangeFlags());
|
||||||
double value = range.step * model->logicalSw[i].val2 + range.offset; /* TODO+source.getRawOffset(model)*/
|
double value = range.step * model->logicalSw[i].val2 + range.offset; /* TODO+source.getRawOffset(model)*/
|
||||||
cswitchSource1[i]->setModel(rawSourceItemModel);
|
cbSource1[i]->setModel(rawSourceItemModel);
|
||||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(source.toValue()));
|
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(source.toValue()));
|
||||||
if (source.isTimeBased()) {
|
if (source.isTimeBased()) {
|
||||||
mask |= VALUE_TO_VISIBLE;
|
mask |= VALUE_TO_VISIBLE;
|
||||||
cswitchTOffset[i]->setTimeRange(range.min, range.max);
|
teOffset[i]->setTimeRange(range.min, range.max);
|
||||||
cswitchTOffset[i]->setSingleStep(range.step);
|
teOffset[i]->setSingleStep(range.step);
|
||||||
cswitchTOffset[i]->setPageStep(range.step * 60);
|
teOffset[i]->setPageStep(range.step * 60);
|
||||||
cswitchTOffset[i]->setShowSeconds(range.step != 60);
|
teOffset[i]->setShowSeconds(range.step != 60);
|
||||||
cswitchTOffset[i]->setTime((int)value);
|
teOffset[i]->setTime((int)value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mask |= VALUE2_VISIBLE;
|
mask |= VALUE2_VISIBLE;
|
||||||
if (range.unit.isEmpty())
|
if (range.unit.isEmpty())
|
||||||
cswitchOffset[i]->setSuffix("");
|
dsbOffset[i]->setSuffix("");
|
||||||
else
|
else
|
||||||
cswitchOffset[i]->setSuffix(" " + range.unit);
|
dsbOffset[i]->setSuffix(" " + range.unit);
|
||||||
cswitchOffset[i]->setDecimals(range.decimals);
|
dsbOffset[i]->setDecimals(range.decimals);
|
||||||
cswitchOffset[i]->setMinimum(range.min);
|
dsbOffset[i]->setMinimum(range.min);
|
||||||
cswitchOffset[i]->setMaximum(range.max);
|
dsbOffset[i]->setMaximum(range.max);
|
||||||
cswitchOffset[i]->setSingleStep(range.step);
|
dsbOffset[i]->setSingleStep(range.step);
|
||||||
cswitchOffset[i]->setValue(value);
|
dsbOffset[i]->setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -393,58 +396,58 @@ void LogicalSwitchesPanel::updateLine(int i)
|
||||||
case LS_FAMILY_STICKY: // no break
|
case LS_FAMILY_STICKY: // no break
|
||||||
case LS_FAMILY_VBOOL:
|
case LS_FAMILY_VBOOL:
|
||||||
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
|
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
|
||||||
cswitchSource1[i]->setModel(rawSwitchItemModel);
|
cbSource1[i]->setModel(rawSwitchItemModel);
|
||||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
|
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
|
||||||
cswitchSource2[i]->setModel(rawSwitchItemModel);
|
cbSource2[i]->setModel(rawSwitchItemModel);
|
||||||
cswitchSource2[i]->setCurrentIndex(cswitchSource2[i]->findData(model->logicalSw[i].val2));
|
cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LS_FAMILY_EDGE:
|
case LS_FAMILY_EDGE:
|
||||||
mask |= SOURCE1_VISIBLE | VALUE2_VISIBLE | VALUE3_VISIBLE;
|
mask |= SOURCE1_VISIBLE | VALUE2_VISIBLE | VALUE3_VISIBLE;
|
||||||
mask &= ~DELAY_ENABLED;
|
mask &= ~DELAY_ENABLED;
|
||||||
cswitchSource1[i]->setModel(rawSwitchItemModel);
|
cbSource1[i]->setModel(rawSwitchItemModel);
|
||||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
|
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
|
||||||
updateTimerParam(cswitchOffset[i], model->logicalSw[i].val2, 0.0);
|
updateTimerParam(dsbOffset[i], model->logicalSw[i].val2, 0.0);
|
||||||
updateTimerParam(cswitchOffset2[i], model->logicalSw[i].val2+model->logicalSw[i].val3, ValToTim(TimToVal(cswitchOffset[i]->value())-1));
|
updateTimerParam(dsbOffset2[i], model->logicalSw[i].val2+model->logicalSw[i].val3, ValToTim(TimToVal(dsbOffset[i]->value())-1));
|
||||||
cswitchOffset2[i]->setSuffix((model->logicalSw[i].val3) ? "" : tr(" (infinite)"));
|
dsbOffset2[i]->setSuffix((model->logicalSw[i].val3) ? "" : tr(" (infinite)"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LS_FAMILY_VCOMP:
|
case LS_FAMILY_VCOMP:
|
||||||
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
|
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
|
||||||
cswitchSource1[i]->setModel(rawSourceItemModel);
|
cbSource1[i]->setModel(rawSourceItemModel);
|
||||||
cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
|
cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
|
||||||
cswitchSource2[i]->setModel(rawSourceItemModel);
|
cbSource2[i]->setModel(rawSourceItemModel);
|
||||||
cswitchSource2[i]->setCurrentIndex(cswitchSource2[i]->findData(model->logicalSw[i].val2));
|
cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LS_FAMILY_TIMER:
|
case LS_FAMILY_TIMER:
|
||||||
mask |= VALUE1_VISIBLE | VALUE2_VISIBLE;
|
mask |= VALUE1_VISIBLE | VALUE2_VISIBLE;
|
||||||
updateTimerParam(cswitchValue[i], model->logicalSw[i].val1, 0.1);
|
updateTimerParam(dsbValue[i], model->logicalSw[i].val1, 0.1);
|
||||||
updateTimerParam(cswitchOffset[i], model->logicalSw[i].val2, 0.1);
|
updateTimerParam(dsbOffset[i], model->logicalSw[i].val2, 0.1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cswitchSource1[i]->setVisible(mask & SOURCE1_VISIBLE);
|
cbSource1[i]->setVisible(mask & SOURCE1_VISIBLE);
|
||||||
cswitchSource2[i]->setVisible(mask & SOURCE2_VISIBLE);
|
cbSource2[i]->setVisible(mask & SOURCE2_VISIBLE);
|
||||||
cswitchValue[i]->setVisible(mask & VALUE1_VISIBLE);
|
dsbValue[i]->setVisible(mask & VALUE1_VISIBLE);
|
||||||
cswitchOffset[i]->setVisible(mask & VALUE2_VISIBLE);
|
dsbOffset[i]->setVisible(mask & VALUE2_VISIBLE);
|
||||||
cswitchOffset2[i]->setVisible(mask & VALUE3_VISIBLE);
|
dsbOffset2[i]->setVisible(mask & VALUE3_VISIBLE);
|
||||||
cswitchTOffset[i]->setVisible(mask & VALUE_TO_VISIBLE);
|
teOffset[i]->setVisible(mask & VALUE_TO_VISIBLE);
|
||||||
cswitchAnd[i]->setVisible(mask & LINE_ENABLED);
|
cbAndSwitch[i]->setVisible(mask & LINE_ENABLED);
|
||||||
if (firmware->getCapability(LogicalSwitchesExt)) {
|
if (lsCapabilityExt) {
|
||||||
cswitchDuration[i]->setVisible(mask & DURATION_ENABLED);
|
dsbDuration[i]->setVisible(mask & DURATION_ENABLED);
|
||||||
cswitchDelay[i]->setVisible(mask & DELAY_ENABLED);
|
dsbDelay[i]->setVisible(mask & DELAY_ENABLED);
|
||||||
if (mask & DURATION_ENABLED)
|
if (mask & DURATION_ENABLED)
|
||||||
cswitchDuration[i]->setValue(model->logicalSw[i].duration/10.0);
|
dsbDuration[i]->setValue(model->logicalSw[i].duration/10.0);
|
||||||
if (mask & DELAY_ENABLED)
|
if (mask & DELAY_ENABLED)
|
||||||
cswitchDelay[i]->setValue(model->logicalSw[i].delay/10.0);
|
dsbDelay[i]->setValue(model->logicalSw[i].delay/10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::populateCSWCB(QComboBox *b)
|
void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b)
|
||||||
{
|
{
|
||||||
int order[] = {
|
int order[] = {
|
||||||
LS_FN_OFF,
|
LS_FN_OFF,
|
||||||
|
@ -514,63 +517,150 @@ void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b)
|
||||||
void LogicalSwitchesPanel::update()
|
void LogicalSwitchesPanel::update()
|
||||||
{
|
{
|
||||||
updateDataModels();
|
updateDataModels();
|
||||||
for (int i=0; i<firmware->getCapability(LogicalSwitches); i++) {
|
for (int i=0; i<lsCapability; i++) {
|
||||||
updateLine(i);
|
updateLine(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::cswPaste()
|
void LogicalSwitchesPanel::cmPaste()
|
||||||
{
|
{
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
QByteArray data;
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
if (hasClipboardData(&data)) {
|
||||||
if (mimeData->hasFormat("application/x-companion-csw")) {
|
memcpy(&model->logicalSw[selectedIndex], data.constData(), sizeof(LogicalSwitchData));
|
||||||
QByteArray cswData = mimeData->data("application/x-companion-csw");
|
updateDataModels();
|
||||||
LogicalSwitchData *csw = &model->logicalSw[selectedSwitch];
|
updateLine(selectedIndex);
|
||||||
memcpy(csw, cswData.constData(), sizeof(LogicalSwitchData));
|
|
||||||
update();
|
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::cswDelete()
|
void LogicalSwitchesPanel::cmDelete()
|
||||||
{
|
{
|
||||||
model->logicalSw[selectedSwitch].clear();
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Logical Switch. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memmove(&model->logicalSw[selectedIndex], &model->logicalSw[selectedIndex + 1], (CPN_MAX_LOGICAL_SWITCHES - (selectedIndex + 1)) * sizeof(LogicalSwitchData));
|
||||||
|
model->logicalSw[lsCapability - 1].clear();
|
||||||
|
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
|
||||||
|
update();
|
||||||
emit modified();
|
emit modified();
|
||||||
updateLine(selectedSwitch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::cswCopy()
|
void LogicalSwitchesPanel::cmCopy()
|
||||||
{
|
{
|
||||||
QByteArray cswData;
|
QByteArray data;
|
||||||
cswData.append((char*)&model->logicalSw[selectedSwitch],sizeof(LogicalSwitchData));
|
data.append((char*)&model->logicalSw[selectedIndex], sizeof(LogicalSwitchData));
|
||||||
QMimeData *mimeData = new QMimeData;
|
QMimeData *mimeData = new QMimeData;
|
||||||
mimeData->setData("application/x-companion-csw", cswData);
|
mimeData->setData(MIMETYPE_LOGICAL_SWITCH, data);
|
||||||
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicalSwitchesPanel::cswCut()
|
void LogicalSwitchesPanel::cmCut()
|
||||||
{
|
{
|
||||||
cswCopy();
|
cmCopy();
|
||||||
cswDelete();
|
cmClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO make something generic here!
|
// TODO make something generic here!
|
||||||
void LogicalSwitchesPanel::csw_customContextMenuRequested(QPoint pos)
|
void LogicalSwitchesPanel::onCustomContextMenuRequested(QPoint pos)
|
||||||
{
|
{
|
||||||
QLabel *label = (QLabel *)sender();
|
QLabel *label = (QLabel *)sender();
|
||||||
selectedSwitch = label->property("index").toInt();
|
selectedIndex = label->property("index").toInt();
|
||||||
|
|
||||||
QPoint globalPos = label->mapToGlobal(pos);
|
QPoint globalPos = label->mapToGlobal(pos);
|
||||||
|
|
||||||
const QClipboard * clipboard = QApplication::clipboard();
|
|
||||||
const QMimeData * mimeData = clipboard->mimeData();
|
|
||||||
bool hasData = mimeData->hasFormat("application/x-companion-csw");
|
|
||||||
|
|
||||||
QMenu contextMenu;
|
QMenu contextMenu;
|
||||||
contextMenu.addAction(CompanionIcon("copy.png"), tr("&Copy"),this,SLOT(cswCopy()));
|
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
|
||||||
contextMenu.addAction(CompanionIcon("cut.png"), tr("&Cut"),this,SLOT(cswCut()));
|
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
|
||||||
contextMenu.addAction(CompanionIcon("paste.png"), tr("&Paste"),this,SLOT(cswPaste()))->setEnabled(hasData);
|
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
|
||||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("&Delete"),this,SLOT(cswDelete()));
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(cmInsert()))->setEnabled(insertAllowed());
|
||||||
|
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(cmDelete()));
|
||||||
|
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
|
||||||
|
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
|
||||||
|
|
||||||
contextMenu.exec(globalPos);
|
contextMenu.exec(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LogicalSwitchesPanel::hasClipboardData(QByteArray * data) const
|
||||||
|
{
|
||||||
|
const QClipboard * clipboard = QApplication::clipboard();
|
||||||
|
const QMimeData * mimeData = clipboard->mimeData();
|
||||||
|
if (mimeData->hasFormat(MIMETYPE_LOGICAL_SWITCH)) {
|
||||||
|
if (data)
|
||||||
|
data->append(mimeData->data(MIMETYPE_LOGICAL_SWITCH));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LogicalSwitchesPanel::insertAllowed() const
|
||||||
|
{
|
||||||
|
return ((selectedIndex < lsCapability - 1) && (model->logicalSw[lsCapability - 1].isEmpty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LogicalSwitchesPanel::moveDownAllowed() const
|
||||||
|
{
|
||||||
|
return selectedIndex < lsCapability - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LogicalSwitchesPanel::moveUpAllowed() const
|
||||||
|
{
|
||||||
|
return selectedIndex > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogicalSwitchesPanel::cmMoveUp()
|
||||||
|
{
|
||||||
|
swapData(selectedIndex, selectedIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogicalSwitchesPanel::cmMoveDown()
|
||||||
|
{
|
||||||
|
swapData(selectedIndex, selectedIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogicalSwitchesPanel::cmClear()
|
||||||
|
{
|
||||||
|
model->logicalSw[selectedIndex].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogicalSwitchesPanel::cmClearAll()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Logical Switches. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i=0; i<lsCapability; i++) {
|
||||||
|
model->logicalSw[i].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, i);
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogicalSwitchesPanel::cmInsert()
|
||||||
|
{
|
||||||
|
memmove(&model->logicalSw[selectedIndex + 1], &model->logicalSw[selectedIndex], (CPN_MAX_LOGICAL_SWITCHES - (selectedIndex + 1)) * sizeof(LogicalSwitchData));
|
||||||
|
model->logicalSw[selectedIndex].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogicalSwitchesPanel::swapData(int idx1, int idx2)
|
||||||
|
{
|
||||||
|
if ((idx1 != idx2) && (!model->logicalSw[idx1].isEmpty() || !model->logicalSw[idx2].isEmpty())) {
|
||||||
|
LogicalSwitchData lstmp = model->logicalSw[idx2];
|
||||||
|
LogicalSwitchData *lsw1 = &model->logicalSw[idx1];
|
||||||
|
LogicalSwitchData *lsw2 = &model->logicalSw[idx2];
|
||||||
|
memcpy(lsw2, lsw1, sizeof(LogicalSwitchData));
|
||||||
|
memcpy(lsw1, &lstmp, sizeof(LogicalSwitchData));
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ class RawSwitchFilterItemModel;
|
||||||
class RawSourceFilterItemModel;
|
class RawSourceFilterItemModel;
|
||||||
class TimerEdit;
|
class TimerEdit;
|
||||||
|
|
||||||
|
constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch";
|
||||||
|
|
||||||
class LogicalSwitchesPanel : public ModelPanel
|
class LogicalSwitchesPanel : public ModelPanel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -40,40 +42,50 @@ class LogicalSwitchesPanel : public ModelPanel
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateDataModels();
|
void updateDataModels();
|
||||||
void functionChanged();
|
void onFunctionChanged();
|
||||||
void v1Edited(int value);
|
void onV1Changed(int value);
|
||||||
void v2Edited(int value);
|
void onV2Changed(int value);
|
||||||
void andEdited(int value);
|
void onAndSwitchChanged(int value);
|
||||||
void durationEdited(double duration);
|
void onDurationChanged(double duration);
|
||||||
void delayEdited(double delay);
|
void onDelayChanged(double delay);
|
||||||
void offsetEdited();
|
void onOffsetChanged();
|
||||||
bool offsetEditedAt(int index);
|
bool offsetChangedAt(int index);
|
||||||
void updateLine(int index);
|
void updateLine(int index);
|
||||||
void csw_customContextMenuRequested(QPoint pos);
|
void onCustomContextMenuRequested(QPoint pos);
|
||||||
void cswDelete();
|
void cmDelete();
|
||||||
void cswCopy();
|
void cmCopy();
|
||||||
void cswPaste();
|
void cmPaste();
|
||||||
void cswCut();
|
void cmCut();
|
||||||
|
void cmMoveUp();
|
||||||
|
void cmMoveDown();
|
||||||
|
void cmInsert();
|
||||||
|
void cmClear();
|
||||||
|
void cmClearAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QComboBox * csw[CPN_MAX_LOGICAL_SWITCHES];
|
QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QDoubleSpinBox * cswitchValue[CPN_MAX_LOGICAL_SWITCHES];
|
QDoubleSpinBox * dsbValue[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QDoubleSpinBox * cswitchOffset[CPN_MAX_LOGICAL_SWITCHES];
|
QDoubleSpinBox * dsbOffset[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QDoubleSpinBox * cswitchOffset2[CPN_MAX_LOGICAL_SWITCHES];
|
QDoubleSpinBox * dsbOffset2[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
TimerEdit * cswitchTOffset[CPN_MAX_LOGICAL_SWITCHES];
|
TimerEdit * teOffset[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QComboBox * cswitchAnd[CPN_MAX_LOGICAL_SWITCHES];
|
QComboBox * cbAndSwitch[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QDoubleSpinBox * cswitchDuration[CPN_MAX_LOGICAL_SWITCHES];
|
QDoubleSpinBox * dsbDuration[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QDoubleSpinBox * cswitchDelay[CPN_MAX_LOGICAL_SWITCHES];
|
QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QComboBox * cswitchSource1[CPN_MAX_LOGICAL_SWITCHES];
|
QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
QComboBox * cswitchSource2[CPN_MAX_LOGICAL_SWITCHES];
|
QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES];
|
||||||
RawSwitchFilterItemModel * rawSwitchItemModel;
|
RawSwitchFilterItemModel * rawSwitchItemModel;
|
||||||
RawSourceFilterItemModel * rawSourceItemModel;
|
RawSourceFilterItemModel * rawSourceItemModel;
|
||||||
int selectedSwitch;
|
int selectedIndex;
|
||||||
|
void populateFunctionCB(QComboBox *b);
|
||||||
void populateCSWCB(QComboBox *b);
|
|
||||||
void populateAndSwitchCB(QComboBox *b);
|
void populateAndSwitchCB(QComboBox *b);
|
||||||
void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0);
|
void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0);
|
||||||
|
int lsCapability;
|
||||||
|
int lsCapabilityExt;
|
||||||
|
void swapData(int idx1, int idx2);
|
||||||
|
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool insertAllowed() const;
|
||||||
|
bool moveDownAllowed() const;
|
||||||
|
bool moveUpAllowed() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _LOGICALSWITCHES_H_
|
#endif // _LOGICALSWITCHES_H_
|
||||||
|
|
|
@ -49,7 +49,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ui->name->setMaxLength(length);
|
ui->name->setMaxLength(length);
|
||||||
ui->name->setText(timer.name);
|
//ui->name->setText(timer.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode
|
// Mode
|
||||||
|
@ -85,6 +85,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
|
||||||
QWidget::setTabOrder(ui->countdownBeep, ui->minuteBeep);
|
QWidget::setTabOrder(ui->countdownBeep, ui->minuteBeep);
|
||||||
QWidget::setTabOrder(ui->minuteBeep, ui->persistent);
|
QWidget::setTabOrder(ui->minuteBeep, ui->persistent);
|
||||||
|
|
||||||
|
update();
|
||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +96,9 @@ TimerPanel::~TimerPanel()
|
||||||
|
|
||||||
void TimerPanel::update()
|
void TimerPanel::update()
|
||||||
{
|
{
|
||||||
|
lock = true;
|
||||||
|
ui->name->setText(timer.name);
|
||||||
|
|
||||||
int hour = timer.val / 3600;
|
int hour = timer.val / 3600;
|
||||||
int min = (timer.val - (hour * 3600)) / 60;
|
int min = (timer.val - (hour * 3600)) / 60;
|
||||||
int sec = (timer.val - (hour * 3600)) % 60;
|
int sec = (timer.val - (hour * 3600)) % 60;
|
||||||
|
@ -116,7 +120,10 @@ void TimerPanel::update()
|
||||||
ui->persistentValue->setText(QString(" %1(%2:%3:%4)").arg(sign<0 ? "-" :" ").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
|
ui->persistentValue->setText(QString(" %1(%2:%3:%4)").arg(sign<0 ? "-" :" ").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->countdownBeep->updateValue();
|
||||||
ui->minuteBeep->setChecked(timer.minuteBeep);
|
ui->minuteBeep->setChecked(timer.minuteBeep);
|
||||||
|
ui->persistent->updateValue();
|
||||||
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget * TimerPanel::getLastFocus()
|
QWidget * TimerPanel::getLastFocus()
|
||||||
|
@ -126,39 +133,44 @@ QWidget * TimerPanel::getLastFocus()
|
||||||
|
|
||||||
void TimerPanel::on_value_editingFinished()
|
void TimerPanel::on_value_editingFinished()
|
||||||
{
|
{
|
||||||
|
if (!lock) {
|
||||||
unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
|
unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
|
||||||
if (timer.val != val) {
|
if (timer.val != val) {
|
||||||
timer.val = val;
|
timer.val = val;
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerPanel::onModeChanged(int index)
|
void TimerPanel::onModeChanged(int index)
|
||||||
{
|
{
|
||||||
if (lock)
|
if (!lock) {
|
||||||
return;
|
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
const RawSwitch rs(ui->mode->itemData(index).toInt(&ok));
|
const RawSwitch rs(ui->mode->itemData(index).toInt(&ok));
|
||||||
if (ok && timer.mode.toValue() != rs.toValue()) {
|
if (ok && timer.mode.toValue() != rs.toValue()) {
|
||||||
timer.mode = rs;
|
timer.mode = rs;
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerPanel::on_minuteBeep_toggled(bool checked)
|
void TimerPanel::on_minuteBeep_toggled(bool checked)
|
||||||
{
|
{
|
||||||
|
if (!lock) {
|
||||||
timer.minuteBeep = checked;
|
timer.minuteBeep = checked;
|
||||||
emit modified();
|
emit modified();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerPanel::on_name_editingFinished()
|
void TimerPanel::on_name_editingFinished()
|
||||||
{
|
{
|
||||||
|
if (!lock) {
|
||||||
if (QString(timer.name) != ui->name->text()) {
|
if (QString(timer.name) != ui->name->text()) {
|
||||||
int length = ui->name->maxLength();
|
int length = ui->name->maxLength();
|
||||||
strncpy(timer.name, ui->name->text().toLatin1(), length);
|
strncpy(timer.name, ui->name->text().toLatin1(), length);
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -273,27 +285,12 @@ ModulePanel::~ModulePanel()
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModulePanel::moduleHasFailsafes()
|
|
||||||
{
|
|
||||||
return firmware->getCapability(HasFailsafe) && (
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_ISRM ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCST_ISRM_D16 ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_XJT_X16 ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_R9M ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M_LITE ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M_LITE_PRO ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_XJT_LITE_X16 ||
|
|
||||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_MULTIMODULE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModulePanel::setupFailsafes()
|
void ModulePanel::setupFailsafes()
|
||||||
{
|
{
|
||||||
ChannelFailsafeWidgetsGroup grp;
|
ChannelFailsafeWidgetsGroup grp;
|
||||||
const int start = module.channelsStart;
|
const int start = module.channelsStart;
|
||||||
const int end = start + module.channelsCount;
|
const int end = start + module.channelsCount;
|
||||||
const bool hasFailsafe = moduleHasFailsafes();
|
const bool hasFailsafe = module.hasFailsafes(firmware);
|
||||||
|
|
||||||
lock = true;
|
lock = true;
|
||||||
|
|
||||||
|
@ -382,48 +379,6 @@ void ModulePanel::setupFailsafes()
|
||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ModulePanel::getMaxChannelCount()
|
|
||||||
{
|
|
||||||
const PulsesProtocol protocol = (PulsesProtocol)module.protocol;
|
|
||||||
switch (protocol) {
|
|
||||||
case PULSES_ACCESS_ISRM:
|
|
||||||
return 24;
|
|
||||||
case PULSES_PXX_R9M:
|
|
||||||
case PULSES_ACCESS_R9M:
|
|
||||||
case PULSES_ACCESS_R9M_LITE:
|
|
||||||
case PULSES_ACCESS_R9M_LITE_PRO:
|
|
||||||
case PULSES_ACCST_ISRM_D16:
|
|
||||||
case PULSES_XJT_LITE_X16:
|
|
||||||
case PULSES_PXX_XJT_X16:
|
|
||||||
case PULSES_CROSSFIRE:
|
|
||||||
case PULSES_SBUS:
|
|
||||||
case PULSES_PPM:
|
|
||||||
return 16;
|
|
||||||
case PULSES_XJT_LITE_LR12:
|
|
||||||
case PULSES_PXX_XJT_LR12:
|
|
||||||
return 12;
|
|
||||||
case PULSES_PXX_DJT:
|
|
||||||
case PULSES_XJT_LITE_D8:
|
|
||||||
case PULSES_PXX_XJT_D8:
|
|
||||||
return 8;
|
|
||||||
case PULSES_LP45:
|
|
||||||
case PULSES_DSM2:
|
|
||||||
case PULSES_DSMX:
|
|
||||||
return 6;
|
|
||||||
case PULSES_MULTIMODULE:
|
|
||||||
if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
|
|
||||||
return 12;
|
|
||||||
else
|
|
||||||
return 16;
|
|
||||||
break;
|
|
||||||
case PULSES_OFF:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModulePanel::update()
|
void ModulePanel::update()
|
||||||
{
|
{
|
||||||
const PulsesProtocol protocol = (PulsesProtocol)module.protocol;
|
const PulsesProtocol protocol = (PulsesProtocol)module.protocol;
|
||||||
|
@ -510,7 +465,7 @@ void ModulePanel::update()
|
||||||
mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
|
mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleHasFailsafes()) {
|
if (module.hasFailsafes(firmware)) {
|
||||||
mask |= MASK_FAILSAFES;
|
mask |= MASK_FAILSAFES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +482,7 @@ void ModulePanel::update()
|
||||||
ui->label_channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
|
ui->label_channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
|
||||||
ui->channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
|
ui->channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
|
||||||
ui->channelsCount->setEnabled(mask & MASK_CHANNELS_COUNT);
|
ui->channelsCount->setEnabled(mask & MASK_CHANNELS_COUNT);
|
||||||
ui->channelsCount->setMaximum(getMaxChannelCount());
|
ui->channelsCount->setMaximum(module.getMaxChannelCount());
|
||||||
ui->channelsCount->setValue(module.channelsCount);
|
ui->channelsCount->setValue(module.channelsCount);
|
||||||
ui->channelsCount->setSingleStep(firmware->getCapability(HasPPMStart) ? 1 : 2);
|
ui->channelsCount->setSingleStep(firmware->getCapability(HasPPMStart) ? 1 : 2);
|
||||||
|
|
||||||
|
@ -695,7 +650,7 @@ void ModulePanel::onProtocolChanged(int index)
|
||||||
{
|
{
|
||||||
if (!lock && module.protocol != ui->protocol->itemData(index).toUInt()) {
|
if (!lock && module.protocol != ui->protocol->itemData(index).toUInt()) {
|
||||||
module.protocol = ui->protocol->itemData(index).toInt();
|
module.protocol = ui->protocol->itemData(index).toInt();
|
||||||
module.channelsCount = getMaxChannelCount();
|
module.channelsCount = module.getMaxChannelCount();
|
||||||
update();
|
update();
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
@ -790,7 +745,7 @@ void ModulePanel::onMultiProtocolChanged(int index)
|
||||||
if (rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
|
if (rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
|
||||||
maxSubTypes=8;
|
maxSubTypes=8;
|
||||||
module.subType = std::min(module.subType, maxSubTypes -1);
|
module.subType = std::min(module.subType, maxSubTypes -1);
|
||||||
module.channelsCount = getMaxChannelCount();
|
module.channelsCount = module.getMaxChannelCount();
|
||||||
update();
|
update();
|
||||||
emit modified();
|
emit modified();
|
||||||
lock = false;
|
lock = false;
|
||||||
|
@ -1064,16 +1019,28 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
||||||
RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::TimersContext, this);
|
RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::TimersContext, this);
|
||||||
connect(this, &SetupPanel::updated, swModel, &RawSwitchFilterItemModel::update);
|
connect(this, &SetupPanel::updated, swModel, &RawSwitchFilterItemModel::update);
|
||||||
|
|
||||||
for (int i=0; i<CPN_MAX_TIMERS; i++) {
|
timersCount = firmware->getCapability(Timers);
|
||||||
if (i<firmware->getCapability(Timers)) {
|
|
||||||
|
for (int i = 0; i < CPN_MAX_TIMERS; i++) {
|
||||||
|
if (i < timersCount) {
|
||||||
timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, swModel);
|
timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, swModel);
|
||||||
ui->gridLayout->addWidget(timers[i], 1+i, 1);
|
ui->gridLayout->addWidget(timers[i], 1+i, 1);
|
||||||
connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified);
|
connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified);
|
||||||
connect(this, &SetupPanel::updated, timers[i], &TimerPanel::update);
|
connect(this, &SetupPanel::updated, timers[i], &TimerPanel::update);
|
||||||
|
connect(this, &SetupPanel::timerUpdated, timers[i], &TimerPanel::update);
|
||||||
prevFocus = timers[i]->getLastFocus();
|
prevFocus = timers[i]->getLastFocus();
|
||||||
|
// TODO more reliable method required
|
||||||
|
QLabel *label = findChild<QLabel *>(QString("label_timer%1").arg(i + 1));
|
||||||
|
if (label) { // to stop crashing if not found
|
||||||
|
label->setProperty("index", i);
|
||||||
|
label->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
label->setToolTip(tr("Popup menu available"));
|
||||||
|
label->setMouseTracking(true);
|
||||||
|
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onTimerCustomContextMenuRequested(QPoint)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
foreach(QLabel *label, findChildren<QLabel *>(QRegularExpression(QString("label_timer%1").arg(i+1)))) {
|
foreach(QLabel *label, findChildren<QLabel *>(QRegularExpression(QString("label_timer%1").arg(i + 1 )))) { //TODO more reliable method required
|
||||||
label->hide();
|
label->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1081,9 +1048,9 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
||||||
|
|
||||||
if (firmware->getCapability(HasTopLcd)) {
|
if (firmware->getCapability(HasTopLcd)) {
|
||||||
ui->toplcdTimer->setField(model.toplcdTimer, this);
|
ui->toplcdTimer->setField(model.toplcdTimer, this);
|
||||||
for (int i=0; i<CPN_MAX_TIMERS; i++) {
|
for (int i = 0; i < CPN_MAX_TIMERS; i++) {
|
||||||
if (i<firmware->getCapability(Timers)) {
|
if (i<timersCount) {
|
||||||
ui->toplcdTimer->addItem(tr("Timer %1").arg(i+1), i);
|
ui->toplcdTimer->addItem(tr("Timer %1").arg(i + 1), i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1528,3 +1495,155 @@ void SetupPanel::on_editText_clicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetupPanel::onTimerCustomContextMenuRequested(QPoint pos)
|
||||||
|
{
|
||||||
|
QLabel *label = (QLabel *)sender();
|
||||||
|
selectedTimerIndex = label->property("index").toInt();
|
||||||
|
QPoint globalPos = label->mapToGlobal(pos);
|
||||||
|
|
||||||
|
QMenu contextMenu;
|
||||||
|
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmTimerCopy()));
|
||||||
|
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmTimerCut()));
|
||||||
|
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmTimerPaste()))->setEnabled(hasTimerClipboardData());
|
||||||
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmTimerClear()));
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmTimerInsert()))->setEnabled(insertTimerAllowed());
|
||||||
|
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmTimerDelete()));
|
||||||
|
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmTimerMoveUp()))->setEnabled(moveTimerUpAllowed());
|
||||||
|
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmTimerMoveDown()))->setEnabled(moveTimerDownAllowed());
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(cmTimerClearAll()));
|
||||||
|
|
||||||
|
contextMenu.exec(globalPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetupPanel::hasTimerClipboardData(QByteArray * data) const
|
||||||
|
{
|
||||||
|
const QClipboard * clipboard = QApplication::clipboard();
|
||||||
|
const QMimeData * mimeData = clipboard->mimeData();
|
||||||
|
if (mimeData->hasFormat(MIMETYPE_TIMER)) {
|
||||||
|
if (data)
|
||||||
|
data->append(mimeData->data(MIMETYPE_TIMER));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetupPanel::insertTimerAllowed() const
|
||||||
|
{
|
||||||
|
return ((selectedTimerIndex < timersCount - 1) && (model->timers[timersCount - 1].isEmpty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetupPanel::moveTimerDownAllowed() const
|
||||||
|
{
|
||||||
|
return selectedTimerIndex < timersCount - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetupPanel::moveTimerUpAllowed() const
|
||||||
|
{
|
||||||
|
return selectedTimerIndex > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerClear()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
model->timers[selectedTimerIndex].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex);
|
||||||
|
emit timerUpdated();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerClearAll()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Timers. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < timersCount; i++) {
|
||||||
|
model->timers[i].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, i);
|
||||||
|
}
|
||||||
|
emit timerUpdated();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerCopy()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
data.append((char*)&model->timers[selectedTimerIndex], sizeof(TimerData));
|
||||||
|
QMimeData *mimeData = new QMimeData;
|
||||||
|
mimeData->setData(MIMETYPE_TIMER, data);
|
||||||
|
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerCut()
|
||||||
|
{
|
||||||
|
cmTimerCopy();
|
||||||
|
cmTimerClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerDelete()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int maxidx = timersCount - 1;
|
||||||
|
for (int i = selectedTimerIndex; i < maxidx; i++) {
|
||||||
|
if (!model->timers[i].isEmpty() || !model->timers[i + 1].isEmpty()) {
|
||||||
|
memcpy(&model->timers[i], &model->timers[i+1], sizeof(TimerData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model->timers[maxidx].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, -1);
|
||||||
|
emit timerUpdated();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerInsert()
|
||||||
|
{
|
||||||
|
for (int i = (timersCount - 1); i > selectedTimerIndex; i--) {
|
||||||
|
if (!model->timers[i].isEmpty() || !model->timers[i-1].isEmpty()) {
|
||||||
|
memcpy(&model->timers[i], &model->timers[i-1], sizeof(TimerData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model->timers[selectedTimerIndex].clear();
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, 1);
|
||||||
|
emit timerUpdated();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerMoveDown()
|
||||||
|
{
|
||||||
|
swapTimerData(selectedTimerIndex, selectedTimerIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerMoveUp()
|
||||||
|
{
|
||||||
|
swapTimerData(selectedTimerIndex, selectedTimerIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::cmTimerPaste()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
if (hasTimerClipboardData(&data)) {
|
||||||
|
TimerData *td = &model->timers[selectedTimerIndex];
|
||||||
|
memcpy(td, data.constData(), sizeof(TimerData));
|
||||||
|
emit timerUpdated();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPanel::swapTimerData(int idx1, int idx2)
|
||||||
|
{
|
||||||
|
if ((idx1 != idx2) && (!model->timers[idx1].isEmpty() || !model->timers[idx2].isEmpty())) {
|
||||||
|
TimerData tdtmp = model->timers[idx2];
|
||||||
|
TimerData *td1 = &model->timers[idx1];
|
||||||
|
TimerData *td2 = &model->timers[idx2];
|
||||||
|
memcpy(td2, td1, sizeof(TimerData));
|
||||||
|
memcpy(td1, &tdtmp, sizeof(TimerData));
|
||||||
|
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
|
||||||
|
emit timerUpdated();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "modeledit.h"
|
#include "modeledit.h"
|
||||||
#include "eeprominterface.h"
|
#include "eeprominterface.h"
|
||||||
|
|
||||||
|
constexpr char MIMETYPE_TIMER[] = "application/x-companion-timer";
|
||||||
|
|
||||||
class RawSwitchFilterItemModel;
|
class RawSwitchFilterItemModel;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -62,7 +64,6 @@ class ModulePanel : public ModelPanel
|
||||||
ModulePanel(QWidget *parent, ModelData & model, ModuleData & module, GeneralSettings & generalSettings, Firmware * firmware, int moduleIdx);
|
ModulePanel(QWidget *parent, ModelData & model, ModuleData & module, GeneralSettings & generalSettings, Firmware * firmware, int moduleIdx);
|
||||||
virtual ~ModulePanel();
|
virtual ~ModulePanel();
|
||||||
virtual void update();
|
virtual void update();
|
||||||
bool moduleHasFailsafes();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onExtendedLimitsToggled();
|
void onExtendedLimitsToggled();
|
||||||
|
@ -71,7 +72,6 @@ class ModulePanel : public ModelPanel
|
||||||
void channelsRangeChanged();
|
void channelsRangeChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
int getMaxChannelCount();
|
|
||||||
void setupFailsafes();
|
void setupFailsafes();
|
||||||
void on_trainerMode_currentIndexChanged(int index);
|
void on_trainerMode_currentIndexChanged(int index);
|
||||||
void onProtocolChanged(int index);
|
void onProtocolChanged(int index);
|
||||||
|
@ -129,6 +129,7 @@ class SetupPanel : public ModelPanel
|
||||||
signals:
|
signals:
|
||||||
void extendedLimitsToggled();
|
void extendedLimitsToggled();
|
||||||
void updated();
|
void updated();
|
||||||
|
void timerUpdated();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_name_editingFinished();
|
void on_name_editingFinished();
|
||||||
|
@ -148,6 +149,16 @@ class SetupPanel : public ModelPanel
|
||||||
void potWarningToggled(bool checked);
|
void potWarningToggled(bool checked);
|
||||||
void on_potWarningMode_currentIndexChanged(int index);
|
void on_potWarningMode_currentIndexChanged(int index);
|
||||||
void on_editText_clicked();
|
void on_editText_clicked();
|
||||||
|
void onTimerCustomContextMenuRequested(QPoint pos);
|
||||||
|
void cmTimerClear();
|
||||||
|
void cmTimerClearAll();
|
||||||
|
void cmTimerCopy();
|
||||||
|
void cmTimerCut();
|
||||||
|
void cmTimerDelete();
|
||||||
|
void cmTimerInsert();
|
||||||
|
void cmTimerPaste();
|
||||||
|
void cmTimerMoveDown();
|
||||||
|
void cmTimerMoveUp();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::Setup *ui;
|
Ui::Setup *ui;
|
||||||
|
@ -161,6 +172,13 @@ class SetupPanel : public ModelPanel
|
||||||
void updatePotWarnings();
|
void updatePotWarnings();
|
||||||
void updateBeepCenter();
|
void updateBeepCenter();
|
||||||
void populateThrottleSourceCB();
|
void populateThrottleSourceCB();
|
||||||
|
int timersCount;
|
||||||
|
int selectedTimerIndex;
|
||||||
|
bool hasTimerClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
bool insertTimerAllowed() const;
|
||||||
|
bool moveTimerDownAllowed() const;
|
||||||
|
bool moveTimerUpAllowed() const;
|
||||||
|
void swapTimerData(int idx1, int idx2);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _SETUP_H_
|
#endif // _SETUP_H_
|
||||||
|
|
|
@ -590,7 +590,7 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_timer3_2">
|
<widget class="QLabel" name="label_timer3">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<weight>50</weight>
|
<weight>50</weight>
|
||||||
|
|
|
@ -592,13 +592,28 @@ void TelemetryCustomScreen::barTimeChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
|
/******************************************************/
|
||||||
|
|
||||||
|
TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
|
||||||
ModelPanel(parent, model, generalSettings, firmware),
|
ModelPanel(parent, model, generalSettings, firmware),
|
||||||
ui(new Ui::TelemetrySensor),
|
ui(new Ui::TelemetrySensor),
|
||||||
sensor(sensor),
|
sensor(sensor),
|
||||||
lock(false)
|
lock(false),
|
||||||
|
sensorIndex(sensorIndex),
|
||||||
|
selectedIndex(0)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
ui->numLabel->setText(tr("TELE%1").arg(sensorIndex + 1));
|
||||||
|
ui->numLabel->setProperty("index", sensorIndex);
|
||||||
|
ui->numLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||||
|
QFontMetrics *f = new QFontMetrics(QFont());
|
||||||
|
QSize sz;
|
||||||
|
sz = f->size(Qt::TextSingleLine, "TELE00");
|
||||||
|
ui->numLabel->setMinimumWidth(sz.width());
|
||||||
|
ui->numLabel->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
ui->numLabel->setToolTip(tr("Popup menu available"));
|
||||||
|
ui->numLabel->setMouseTracking(true);
|
||||||
|
connect(ui->numLabel, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(on_customContextMenuRequested(QPoint)));
|
||||||
ui->id->setField(sensor.id, this);
|
ui->id->setField(sensor.id, this);
|
||||||
ui->instance->setField(sensor.instance, this);
|
ui->instance->setField(sensor.instance, this);
|
||||||
ui->ratio->setField(sensor.ratio, this);
|
ui->ratio->setField(sensor.ratio, this);
|
||||||
|
@ -613,7 +628,7 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor,
|
||||||
ui->ampsSensor->setField(sensor.amps, this);
|
ui->ampsSensor->setField(sensor.amps, this);
|
||||||
ui->cellsSensor->setField(sensor.source, this);
|
ui->cellsSensor->setField(sensor.source, this);
|
||||||
ui->cellsIndex->addItem(tr("Lowest"), SensorData::TELEM_CELL_INDEX_LOWEST);
|
ui->cellsIndex->addItem(tr("Lowest"), SensorData::TELEM_CELL_INDEX_LOWEST);
|
||||||
for (int i=1; i<=6; i++)
|
for (int i = 1; i <= 6; i++)
|
||||||
ui->cellsIndex->addItem(tr("Cell %1").arg(i), i);
|
ui->cellsIndex->addItem(tr("Cell %1").arg(i), i);
|
||||||
ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST);
|
ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST);
|
||||||
ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA);
|
ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA);
|
||||||
|
@ -622,6 +637,7 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor,
|
||||||
ui->source2->setField(sensor.sources[1], this);
|
ui->source2->setField(sensor.sources[1], this);
|
||||||
ui->source3->setField(sensor.sources[2], this);
|
ui->source3->setField(sensor.sources[2], this);
|
||||||
ui->source4->setField(sensor.sources[3], this);
|
ui->source4->setField(sensor.sources[3], this);
|
||||||
|
ui->prec->setField(sensor.prec, 0, 2, false, "", this);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,7 +661,21 @@ void TelemetrySensorPanel::update()
|
||||||
ui->name->setText(sensor.label);
|
ui->name->setText(sensor.label);
|
||||||
ui->type->setCurrentIndex(sensor.type);
|
ui->type->setCurrentIndex(sensor.type);
|
||||||
ui->unit->setCurrentIndex(sensor.unit);
|
ui->unit->setCurrentIndex(sensor.unit);
|
||||||
ui->prec->setValue(sensor.prec);
|
ui->id->updateValue();
|
||||||
|
ui->instance->updateValue();
|
||||||
|
ui->ratio->updateValue();
|
||||||
|
ui->offset->updateValue();
|
||||||
|
ui->autoOffset->updateValue();
|
||||||
|
ui->filter->updateValue();
|
||||||
|
ui->logs->updateValue();
|
||||||
|
ui->persistent->updateValue();
|
||||||
|
ui->onlyPositive->updateValue();
|
||||||
|
ui->gpsSensor->updateValue();
|
||||||
|
ui->altSensor->updateValue();
|
||||||
|
ui->ampsSensor->updateValue();
|
||||||
|
ui->cellsSensor->updateValue();
|
||||||
|
ui->cellsIndex->updateValue();
|
||||||
|
ui->prec->updateValue();
|
||||||
|
|
||||||
if (sensor.type == SensorData::TELEM_TYPE_CALCULATED) {
|
if (sensor.type == SensorData::TELEM_TYPE_CALCULATED) {
|
||||||
sensor.updateUnit();
|
sensor.updateUnit();
|
||||||
|
@ -825,15 +855,85 @@ void TelemetrySensorPanel::on_unit_currentIndexChanged(int index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelemetrySensorPanel::on_prec_valueChanged(double value)
|
void TelemetrySensorPanel::on_prec_valueChanged()
|
||||||
{
|
{
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
sensor.prec = value;
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelemetrySensorPanel::on_customContextMenuRequested(QPoint pos)
|
||||||
|
{
|
||||||
|
QLabel *label = (QLabel *)sender();
|
||||||
|
selectedIndex = label->property("index").toInt();
|
||||||
|
QPoint globalPos = label->mapToGlobal(pos);
|
||||||
|
|
||||||
|
QMenu contextMenu;
|
||||||
|
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
|
||||||
|
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
|
||||||
|
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
|
||||||
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
|
||||||
|
|
||||||
|
contextMenu.exec(globalPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TelemetrySensorPanel::hasClipboardData(QByteArray * data) const
|
||||||
|
{
|
||||||
|
const QClipboard * clipboard = QApplication::clipboard();
|
||||||
|
const QMimeData * mimeData = clipboard->mimeData();
|
||||||
|
if (mimeData->hasFormat(MIMETYPE_TELE_SENSOR)) {
|
||||||
|
if (data)
|
||||||
|
data->append(mimeData->data(MIMETYPE_TELE_SENSOR));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelemetrySensorPanel::cmCopy()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
data.append((char*)&sensor, sizeof(SensorData));
|
||||||
|
QMimeData *mimeData = new QMimeData;
|
||||||
|
mimeData->setData(MIMETYPE_TELE_SENSOR, data);
|
||||||
|
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelemetrySensorPanel::cmCut()
|
||||||
|
{
|
||||||
|
cmCopy();
|
||||||
|
cmClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelemetrySensorPanel::cmPaste()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
if (hasClipboardData(&data)) {
|
||||||
|
memcpy(&sensor, data.constData(), sizeof(SensorData));
|
||||||
emit dataModified();
|
emit dataModified();
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TelemetrySensorPanel::cmClear()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sensor.clear();
|
||||||
|
emit dataModified();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelemetrySensorPanel::cmClearAll()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Telemetry Sensors. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
emit clearAllSensors();
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
|
|
||||||
TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
|
TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
|
||||||
|
@ -851,12 +951,13 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
|
||||||
ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this);
|
ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this);
|
||||||
ui->A1GB->hide();
|
ui->A1GB->hide();
|
||||||
ui->A2GB->hide();
|
ui->A2GB->hide();
|
||||||
for (unsigned i=0; i<CPN_MAX_SENSORS; ++i) {
|
for (unsigned i= 0; i < CPN_MAX_SENSORS; ++i) {
|
||||||
TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], model, generalSettings, firmware);
|
TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, model, generalSettings, firmware);
|
||||||
ui->sensorsLayout->addWidget(panel);
|
ui->sensorsLayout->addWidget(panel);
|
||||||
sensorPanels[i] = panel;
|
sensorPanels[i] = panel;
|
||||||
connect(panel, SIGNAL(dataModified()), this, SLOT(update()));
|
connect(panel, SIGNAL(dataModified()), this, SLOT(update()));
|
||||||
connect(panel, SIGNAL(modified()), this, SLOT(onModified()));
|
connect(panel, SIGNAL(modified()), this, SLOT(onModified()));
|
||||||
|
connect(panel, SIGNAL(clearAllSensors()), this, SLOT(on_clearAllSensors()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -881,7 +982,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
|
||||||
RawSourceFilterItemModel * srcModel = (new RawSourceFilterItemModel(&generalSettings, &model, this));
|
RawSourceFilterItemModel * srcModel = (new RawSourceFilterItemModel(&generalSettings, &model, this));
|
||||||
connect(this, &TelemetryPanel::updated, srcModel, &RawSourceFilterItemModel::update);
|
connect(this, &TelemetryPanel::updated, srcModel, &RawSourceFilterItemModel::update);
|
||||||
|
|
||||||
for (int i=0; i<firmware->getCapability(TelemetryCustomScreens); i++) {
|
for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) {
|
||||||
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, srcModel);
|
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, srcModel);
|
||||||
ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i+1));
|
ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i+1));
|
||||||
telemetryCustomScreens[i] = tab;
|
telemetryCustomScreens[i] = tab;
|
||||||
|
@ -1198,3 +1299,13 @@ void TelemetryPanel::on_mahCount_ChkB_toggled(bool checked)
|
||||||
ui->mahCount_SB->setDisabled(!checked);
|
ui->mahCount_SB->setDisabled(!checked);
|
||||||
emit modified();
|
emit modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TelemetryPanel::on_clearAllSensors()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CPN_MAX_SENSORS; i++) {
|
||||||
|
model->sensorData[i].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
emit modified();
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "modeledit.h"
|
#include "modeledit.h"
|
||||||
#include "eeprominterface.h"
|
#include "eeprominterface.h"
|
||||||
|
|
||||||
|
constexpr char MIMETYPE_TELE_SENSOR[] = "application/x-companion-tele-sensor";
|
||||||
|
|
||||||
class AutoComboBox;
|
class AutoComboBox;
|
||||||
class RawSourceFilterItemModel;
|
class RawSourceFilterItemModel;
|
||||||
class TimerEdit;
|
class TimerEdit;
|
||||||
|
@ -103,19 +105,27 @@ class TelemetrySensorPanel: public ModelPanel
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
|
TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
|
||||||
~TelemetrySensorPanel();
|
~TelemetrySensorPanel();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataModified();
|
void dataModified();
|
||||||
|
void clearAllSensors();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void on_name_editingFinished();
|
void on_name_editingFinished();
|
||||||
void on_type_currentIndexChanged(int index);
|
void on_type_currentIndexChanged(int index);
|
||||||
void on_formula_currentIndexChanged(int index);
|
void on_formula_currentIndexChanged(int index);
|
||||||
void on_unit_currentIndexChanged(int index);
|
void on_unit_currentIndexChanged(int index);
|
||||||
void on_prec_valueChanged(double value);
|
void on_prec_valueChanged();
|
||||||
|
void on_customContextMenuRequested(QPoint pos);
|
||||||
|
bool hasClipboardData(QByteArray * data = nullptr) const;
|
||||||
|
void cmCopy();
|
||||||
|
void cmCut();
|
||||||
|
void cmPaste();
|
||||||
|
void cmClear();
|
||||||
|
void cmClearAll();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateSourcesComboBox(AutoComboBox * cb, bool negative);
|
void updateSourcesComboBox(AutoComboBox * cb, bool negative);
|
||||||
|
@ -123,7 +133,9 @@ class TelemetrySensorPanel: public ModelPanel
|
||||||
private:
|
private:
|
||||||
Ui::TelemetrySensor * ui;
|
Ui::TelemetrySensor * ui;
|
||||||
SensorData & sensor;
|
SensorData & sensor;
|
||||||
bool lock;
|
bool lock = false;
|
||||||
|
int sensorIndex = 0;
|
||||||
|
int selectedIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TelemetryPanel : public ModelPanel
|
class TelemetryPanel : public ModelPanel
|
||||||
|
@ -154,6 +166,7 @@ class TelemetryPanel : public ModelPanel
|
||||||
void on_fasOffset_DSB_editingFinished();
|
void on_fasOffset_DSB_editingFinished();
|
||||||
void on_mahCount_SB_editingFinished();
|
void on_mahCount_SB_editingFinished();
|
||||||
void on_mahCount_ChkB_toggled(bool checked);
|
void on_mahCount_ChkB_toggled(bool checked);
|
||||||
|
void on_clearAllSensors();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::Telemetry *ui;
|
Ui::Telemetry *ui;
|
||||||
|
|
|
@ -13,13 +13,32 @@
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,0,0,1,0,0,1,1,1,0,0,1,0,1,0,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1,0,0,0,1,0,0,1,1,1,0,0,1,0,1,0,1,1,1,1,1,1,0,0,0,0,1,0,0,1,0,0,0,0,0">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="numLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>TELE##</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="name">
|
<widget class="QLineEdit" name="name">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -520,6 +539,11 @@
|
||||||
<string>US fl.Oz.</string>
|
<string>US fl.Oz.</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>ml/min</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -536,23 +560,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDoubleSpinBox" name="prec">
|
<widget class="AutoPrecisionComboBox" name="prec"/>
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="decimals">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>2.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="ratioLabel">
|
<widget class="QLabel" name="ratioLabel">
|
||||||
|
@ -711,6 +719,11 @@
|
||||||
<extends>QSpinBox</extends>
|
<extends>QSpinBox</extends>
|
||||||
<header>autohexspinbox.h</header>
|
<header>autohexspinbox.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>AutoPrecisionComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>autoprecisioncombobox.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
62
companion/src/profilechooser.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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 "profilechooser.h"
|
||||||
|
#include "ui_profilechooser.h"
|
||||||
|
#include "appdata.h"
|
||||||
|
|
||||||
|
ProfileChooserDialog::ProfileChooserDialog(QWidget * parent):
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::ProfileChooserDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowIcon(QIcon(":/icon.png"));
|
||||||
|
QComboBox *prof = ui->cboProfiles;
|
||||||
|
prof->clear();
|
||||||
|
|
||||||
|
QMap<int, QString> active;
|
||||||
|
active = g.getActiveProfiles();
|
||||||
|
QMapIterator<int, QString> i(active);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
prof->addItem(i.value(), i.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
prof->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
|
prof->setCurrentIndex(prof->findData(g.id()));
|
||||||
|
connect(prof, SIGNAL(currentIndexChanged(int)), this, SLOT(on_cboProfilesCurrentIndexChanged(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileChooserDialog::~ProfileChooserDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileChooserDialog::on_cboProfilesCurrentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
QComboBox *prof = ui->cboProfiles;
|
||||||
|
|
||||||
|
if ((prof->currentIndex() > -1)) {
|
||||||
|
int oldid = g.id();
|
||||||
|
int newid = prof->currentData().toInt();
|
||||||
|
if (oldid != newid)
|
||||||
|
emit profileChanged(newid);
|
||||||
|
}
|
||||||
|
}
|
47
companion/src/profilechooser.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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 _PROFILECHOOSER_H_
|
||||||
|
#define _PROFILECHOOSER_H_
|
||||||
|
|
||||||
|
#include <QtWidgets>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ProfileChooserDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileChooserDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProfileChooserDialog(QWidget * parent = 0);
|
||||||
|
~ProfileChooserDialog();
|
||||||
|
signals:
|
||||||
|
void profileChanged(int newid);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_cboProfilesCurrentIndexChanged(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ProfileChooserDialog *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _PROFILECHOOSER_H_
|
110
companion/src/profilechooser.ui
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ProfileChooserDialog</class>
|
||||||
|
<widget class="QDialog" name="ProfileChooserDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>352</width>
|
||||||
|
<height>102</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Select Profile</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>20</x>
|
||||||
|
<y>20</y>
|
||||||
|
<width>311</width>
|
||||||
|
<height>66</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Profile</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cboProfiles">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
<property name="centerButtons">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>ProfileChooserDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>ProfileChooserDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -15,6 +15,7 @@ set(shared_HDRS
|
||||||
autolineedit.h
|
autolineedit.h
|
||||||
genericpanel.h
|
genericpanel.h
|
||||||
hexspinbox.h
|
hexspinbox.h
|
||||||
|
autoprecisioncombobox.h
|
||||||
)
|
)
|
||||||
|
|
||||||
qt5_wrap_cpp(shared_SRCS ${shared_HDRS})
|
qt5_wrap_cpp(shared_SRCS ${shared_HDRS})
|
||||||
|
|
257
companion/src/shared/autoprecisioncombobox.h
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) OpenTX
|
||||||
|
*
|
||||||
|
* Based on code named
|
||||||
|
* th9x - http://code.google.com/p/th9x
|
||||||
|
* er9x - http://code.google.com/p/er9x
|
||||||
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||||
|
*
|
||||||
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _AUTOPRECISIONCOMBOBOX_H_
|
||||||
|
#define _AUTOPRECISIONCOMBOBOX_H_
|
||||||
|
|
||||||
|
#include "genericpanel.h"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class AutoPrecisionComboBox: public QComboBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
//! \property minDecimals Determines the first list item
|
||||||
|
Q_PROPERTY(unsigned int minDecimals READ minDecimals WRITE setMinDecimals)
|
||||||
|
//! \property maxDecimals Determines the last list item
|
||||||
|
Q_PROPERTY(unsigned int maxDecimals READ maxDecimals WRITE setMaxDecimals)
|
||||||
|
//! \property padding If true, add trailing underscore placeholders to each list item
|
||||||
|
Q_PROPERTY(bool padding READ padding WRITE setPadding)
|
||||||
|
//! \property suffix Optional text suffix to each list value
|
||||||
|
Q_PROPERTY(QString suffix READ suffix WRITE setSuffix)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AutoPrecisionComboBox(QWidget * parent = nullptr):
|
||||||
|
QComboBox(parent)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr):
|
||||||
|
QComboBox(parent)
|
||||||
|
{
|
||||||
|
setField(field, minDecimals, maxDecimals, padding, suffix, panel);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit AutoPrecisionComboBox(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr):
|
||||||
|
QComboBox(parent)
|
||||||
|
{
|
||||||
|
setField(field, minDecimals, maxDecimals, padding, suffix, panel);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int minDecimals() const { return m_minDecimals; }
|
||||||
|
inline int maxDecimals() const { return m_maxDecimals; }
|
||||||
|
inline bool padding() const { return m_padding; }
|
||||||
|
inline QString suffix() const { return m_suffix; }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setField(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr)
|
||||||
|
{
|
||||||
|
m_field = reinterpret_cast<unsigned int *>(&field);
|
||||||
|
initField(minDecimals, maxDecimals, padding, suffix);
|
||||||
|
setPanel(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setField(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr)
|
||||||
|
{
|
||||||
|
m_field = &field;
|
||||||
|
initField(minDecimals, maxDecimals, padding, suffix);
|
||||||
|
setPanel(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMinDecimals(unsigned int minDecimals)
|
||||||
|
{
|
||||||
|
m_minDecimals = rangecheckDecimals(minDecimals);
|
||||||
|
if (m_minDecimals > m_maxDecimals)
|
||||||
|
m_minDecimals = m_maxDecimals;
|
||||||
|
if (!m_lock)
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMaxDecimals(unsigned int maxDecimals)
|
||||||
|
{
|
||||||
|
m_maxDecimals = rangecheckDecimals(maxDecimals);
|
||||||
|
if (m_maxDecimals < m_minDecimals)
|
||||||
|
m_maxDecimals = m_minDecimals;
|
||||||
|
if (!m_lock)
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPadding(bool padding)
|
||||||
|
{
|
||||||
|
m_padding = padding;
|
||||||
|
if (!m_lock)
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSuffix(QString suffix)
|
||||||
|
{
|
||||||
|
m_suffix = suffix.trimmed();
|
||||||
|
if (!m_lock)
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPanel(GenericPanel * panel)
|
||||||
|
{
|
||||||
|
m_panel = panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(int value)
|
||||||
|
{
|
||||||
|
if (!m_field)
|
||||||
|
return;
|
||||||
|
const unsigned int val = (unsigned int)value;
|
||||||
|
if (*m_field != val) {
|
||||||
|
*m_field = rangecheckDecimals(val);
|
||||||
|
updateValue();
|
||||||
|
emit valueChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(unsigned int value)
|
||||||
|
{
|
||||||
|
if (!m_field)
|
||||||
|
return;
|
||||||
|
if (*m_field != value) {
|
||||||
|
*m_field = rangecheckDecimals(value);
|
||||||
|
updateValue();
|
||||||
|
emit valueChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateValue()
|
||||||
|
{
|
||||||
|
if (!m_field)
|
||||||
|
return;
|
||||||
|
if (!isValidDecimals(*m_field))
|
||||||
|
return;
|
||||||
|
if (*m_field > m_maxDecimals) {
|
||||||
|
setMaxDecimals(*m_field);
|
||||||
|
}
|
||||||
|
const bool savedlock = setLocked(true);
|
||||||
|
setCurrentIndex(findData(*m_field));
|
||||||
|
setLocked(savedlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAutoIndexes()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count(); ++i)
|
||||||
|
setItemData(i, i);
|
||||||
|
updateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void valueChanged();
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
connect(this, QOverload<int>::of(&AutoPrecisionComboBox::currentIndexChanged), this, &AutoPrecisionComboBox::onCurrentIndexChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initField(unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix)
|
||||||
|
{
|
||||||
|
const bool savedlock = setLocked(true);
|
||||||
|
setMinDecimals(minDecimals);
|
||||||
|
setMaxDecimals(maxDecimals);
|
||||||
|
setPadding(padding);
|
||||||
|
setSuffix(suffix);
|
||||||
|
setLocked(savedlock);
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateList()
|
||||||
|
{
|
||||||
|
const bool savedlock = setLocked(true);
|
||||||
|
unsigned int i;
|
||||||
|
int j;
|
||||||
|
clear();
|
||||||
|
|
||||||
|
for (i = APCB_DECIMALS_MIN, j = (int)m_maxDecimals; j >= 0; i++, j--) {
|
||||||
|
if (i >= m_minDecimals) {
|
||||||
|
QString str = QString("0.%1").arg(QString(i, '0'));
|
||||||
|
if (m_padding)
|
||||||
|
str.append(QString(j, '_'));
|
||||||
|
if (m_suffix != "")
|
||||||
|
str.append(QString(" %1").arg(m_suffix));
|
||||||
|
addItem(str, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
|
setLocked(savedlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onCurrentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
if (m_field && !m_lock) {
|
||||||
|
*m_field = itemData(index).toUInt();
|
||||||
|
if (m_panel)
|
||||||
|
emit m_panel->modified();
|
||||||
|
emit valueChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int rangecheckDecimals(unsigned int decimals)
|
||||||
|
{
|
||||||
|
unsigned int ret;
|
||||||
|
if (decimals < APCB_DECIMALS_MIN)
|
||||||
|
ret = APCB_DECIMALS_MIN;
|
||||||
|
else if (decimals > APCB_DECIMALS_MAX)
|
||||||
|
ret = APCB_DECIMALS_MAX;
|
||||||
|
else
|
||||||
|
ret = decimals;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValidDecimals(unsigned int value)
|
||||||
|
{
|
||||||
|
if (value >= APCB_DECIMALS_MIN && value <= APCB_DECIMALS_MAX)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setLocked(bool lock)
|
||||||
|
{
|
||||||
|
const bool ret = m_lock;
|
||||||
|
m_lock = lock;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
constexpr static unsigned int APCB_DECIMALS_MIN = {0};
|
||||||
|
constexpr static unsigned int APCB_DECIMALS_MAX = {6};
|
||||||
|
|
||||||
|
unsigned int * m_field = nullptr;
|
||||||
|
GenericPanel * m_panel = nullptr;
|
||||||
|
unsigned int m_minDecimals = 0;
|
||||||
|
unsigned int m_maxDecimals = 0;
|
||||||
|
bool m_padding = false;
|
||||||
|
QString m_suffix = "";
|
||||||
|
bool m_lock = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _AUTOPRECISIONCOMBOBOX_H_
|
|
@ -39,6 +39,7 @@ class GenericPanel : public QWidget
|
||||||
friend class AutoHexSpinBox;
|
friend class AutoHexSpinBox;
|
||||||
friend class AutoLineEdit;
|
friend class AutoLineEdit;
|
||||||
friend class GVarGroup;
|
friend class GVarGroup;
|
||||||
|
friend class AutoPrecisionComboBox;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware);
|
GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware);
|
||||||
|
|
|
@ -99,9 +99,10 @@ void Joystick::processEvents()
|
||||||
axes[i] = moved;
|
axes[i] = moved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
axisRepeatTimers[i].restart();
|
axisRepeatTimers[i].restart();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
emit axisValueChanged(i, 0);
|
emit axisValueChanged(i, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ SimulatedUIWidgetTX16S::SimulatedUIWidgetTX16S(SimulatorInterface *simulator, QW
|
||||||
// add actions in order of appearance on the help menu
|
// add actions in order of appearance on the help menu
|
||||||
|
|
||||||
act = new RadioUiAction(3, QList<int>() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
|
act = new RadioUiAction(3, QList<int>() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
|
||||||
addRadioWidget(ui->rightbuttons->addArea(QRect(10, 0, 80, 35), "TX16S/right_mdl.png", act));
|
addRadioWidget(ui->rightbuttons->addArea(QRect(40, 0, 110, 35), "TX16S/right_mdl.png", act));
|
||||||
|
|
||||||
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
|
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
|
||||||
addRadioWidget(ui->rightbuttons->addArea(QRect(45, 70, 100, 160), "TX16S/right_ent.png", m_mouseMidClickAction));
|
addRadioWidget(ui->rightbuttons->addArea(QRect(45, 70, 100, 160), "TX16S/right_ent.png", m_mouseMidClickAction));
|
||||||
|
@ -59,7 +59,7 @@ SimulatedUIWidgetTX16S::SimulatedUIWidgetTX16S(SimulatorInterface *simulator, QW
|
||||||
m_scrollDnAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
|
m_scrollDnAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
|
||||||
connectScrollActions();
|
connectScrollActions();
|
||||||
|
|
||||||
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 252, 30, 30), "TX16S/left_scrnsht.png", m_screenshotAction));
|
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 245, 30, 30), "TX16S/left_scrnsht.png", m_screenshotAction));
|
||||||
|
|
||||||
m_backlightColors << QColor(47, 123, 227);
|
m_backlightColors << QColor(47, 123, 227);
|
||||||
|
|
||||||
|
|
|
@ -699,10 +699,12 @@ void SimulatorWidget::restoreRadioWidgetsState()
|
||||||
void SimulatorWidget::saveRadioWidgetsState(QList<QByteArray> & state)
|
void SimulatorWidget::saveRadioWidgetsState(QList<QByteArray> & state)
|
||||||
{
|
{
|
||||||
if (m_radioWidgets.size()) {
|
if (m_radioWidgets.size()) {
|
||||||
|
if (g.simuSW()) {
|
||||||
state.clear();
|
state.clear();
|
||||||
foreach (RadioWidget * rw, m_radioWidgets)
|
foreach (RadioWidget * rw, m_radioWidgets)
|
||||||
state.append(rw->getStateData());
|
state.append(rw->getStateData());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -575,6 +575,7 @@ class AppData: public CompStoreObj
|
||||||
PROPERTY4(bool, snapToClpbrd, "snapshot_to_clipboard", false)
|
PROPERTY4(bool, snapToClpbrd, "snapshot_to_clipboard", false)
|
||||||
PROPERTY4(bool, autoCheckApp, "startup_check_companion", true)
|
PROPERTY4(bool, autoCheckApp, "startup_check_companion", true)
|
||||||
PROPERTY4(bool, autoCheckFw, "startup_check_fw", true)
|
PROPERTY4(bool, autoCheckFw, "startup_check_fw", true)
|
||||||
|
PROPERTY4(bool, promptProfile, "startup_prompt_profile", false)
|
||||||
|
|
||||||
PROPERTY(bool, enableBackup, false)
|
PROPERTY(bool, enableBackup, false)
|
||||||
PROPERTY(bool, backupOnFlash, true)
|
PROPERTY(bool, backupOnFlash, true)
|
||||||
|
|
|
@ -10184,7 +10184,7 @@ We recommend you view the release notes using the button below to learn about an
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="1491"/>
|
<location filename="../mainwindow.cpp" line="1491"/>
|
||||||
<source>Set Menu Language</source>
|
<source>Set Menu Language</source>
|
||||||
<translation>Inposta Menu Lingua</translation>
|
<translation>Menù Impostazione Lingua</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="1230"/>
|
<location filename="../mainwindow.cpp" line="1230"/>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
;Include Modern UI
|
;Include Modern UI
|
||||||
|
|
||||||
!include "MUI2.nsh"
|
!include "MUI2.nsh"
|
||||||
|
!include "nsDialogs.nsh"
|
||||||
!include "@CMAKE_CURRENT_SOURCE_DIR@\..\targets\windows\FileAssociation.nsh"
|
!include "@CMAKE_CURRENT_SOURCE_DIR@\..\targets\windows\FileAssociation.nsh"
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
|
@ -32,6 +33,10 @@
|
||||||
;Variables
|
;Variables
|
||||||
|
|
||||||
Var StartMenuFolder
|
Var StartMenuFolder
|
||||||
|
Var StartMenuLocationDialog
|
||||||
|
Var StartMenuLocationRadioCurrent
|
||||||
|
Var StartMenuLocationRadioAll
|
||||||
|
Var StartMenuLocationValue ; "current_user" or "all_users"
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
;Interface Settings
|
;Interface Settings
|
||||||
|
@ -68,9 +73,11 @@
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU"
|
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU"
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\OpenTX\Companion @VERSION_FAMILY@"
|
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\OpenTX\Companion @VERSION_FAMILY@"
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
|
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
|
||||||
|
|
||||||
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
|
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
|
||||||
|
|
||||||
|
;Start Menu Folder for current user or all users?
|
||||||
|
Page custom StartMenuLocationCreator StartMenuLocationLeave
|
||||||
|
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
|
||||||
# These indented statements modify settings for MUI_PAGE_FINISH
|
# These indented statements modify settings for MUI_PAGE_FINISH
|
||||||
|
@ -117,6 +124,7 @@ Section "OpenTX Companion @VERSION_FAMILY@" SecDummy
|
||||||
|
|
||||||
;Registry information for add/remove programs
|
;Registry information for add/remove programs
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayName" "OpenTX Companion @VERSION_FAMILY@"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayName" "OpenTX Companion @VERSION_FAMILY@"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayVersion" "@VERSION@"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayIcon" "$\"$INSTDIR\companion.exe$\""
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayIcon" "$\"$INSTDIR\companion.exe$\""
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "Publisher" "OpenTX"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "Publisher" "OpenTX"
|
||||||
|
@ -126,10 +134,14 @@ Section "OpenTX Companion @VERSION_FAMILY@" SecDummy
|
||||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||||
|
|
||||||
;Create shortcuts
|
;Create shortcuts
|
||||||
|
${If} $StartMenuLocationValue == "all_users"
|
||||||
|
SetShellVarContext all
|
||||||
|
${Endif}
|
||||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
||||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk" "$INSTDIR\companion.exe"
|
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk" "$INSTDIR\companion.exe"
|
||||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk" "$INSTDIR\simulator.exe"
|
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk" "$INSTDIR\simulator.exe"
|
||||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk" "$INSTDIR\Uninstall.exe"
|
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk" "$INSTDIR\Uninstall.exe"
|
||||||
|
SetShellVarContext current
|
||||||
|
|
||||||
!insertmacro MUI_STARTMENU_WRITE_END
|
!insertmacro MUI_STARTMENU_WRITE_END
|
||||||
|
|
||||||
|
@ -141,6 +153,14 @@ SectionEnd
|
||||||
;Language strings
|
;Language strings
|
||||||
LangString DESC_SecDummy ${LANG_ENGLISH} "Models and settings editor for OpenTX"
|
LangString DESC_SecDummy ${LANG_ENGLISH} "Models and settings editor for OpenTX"
|
||||||
LangString DESC_SecDummy ${LANG_FRENCH} "Editeur de r<>glages et mod<6F>les pour OpenTX"
|
LangString DESC_SecDummy ${LANG_FRENCH} "Editeur de r<>glages et mod<6F>les pour OpenTX"
|
||||||
|
LangString SML_SubTitle ${LANG_ENGLISH} "Choose a location for the Start Menu shortcuts"
|
||||||
|
LangString SML_SubTitle ${LANG_FRENCH} "Choisissez un emplacement pour les raccourcis de l'application"
|
||||||
|
LangString SML_MainLabel ${LANG_ENGLISH} "Create start menu shortcuts for:"
|
||||||
|
LangString SML_MainLabel ${LANG_FRENCH} "Emplacement pour les raccourcis de l'application:"
|
||||||
|
LangString SML_RadioCurrent ${LANG_ENGLISH} "Current user only"
|
||||||
|
LangString SML_RadioCurrent ${LANG_FRENCH} "Utilisateur actuel"
|
||||||
|
LangString SML_RadioAll ${LANG_ENGLISH} "All users"
|
||||||
|
LangString SML_RadioAll ${LANG_FRENCH} "Tous les utilisateurs"
|
||||||
|
|
||||||
;Assign language strings to sections
|
;Assign language strings to sections
|
||||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||||
|
@ -203,6 +223,13 @@ Section "un.OpenTX Companion @VERSION_FAMILY@"
|
||||||
|
|
||||||
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
|
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
|
||||||
|
|
||||||
|
; Always remove start menu folder for both locations: current user and all users
|
||||||
|
SetShellVarContext all
|
||||||
|
Delete "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk"
|
||||||
|
Delete "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk"
|
||||||
|
Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk"
|
||||||
|
RMDir "$SMPROGRAMS\$StartMenuFolder"
|
||||||
|
SetShellVarContext current
|
||||||
Delete "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk"
|
Delete "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk"
|
||||||
Delete "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk"
|
Delete "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk"
|
||||||
Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk"
|
Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk"
|
||||||
|
@ -218,3 +245,58 @@ SectionEnd
|
||||||
Function LaunchLink
|
Function LaunchLink
|
||||||
ExecShell "" "$INSTDIR\companion.exe"
|
ExecShell "" "$INSTDIR\companion.exe"
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
|
|
||||||
|
; Custom page with radio buttons, if the start menu entries shall be created
|
||||||
|
; for the current user or for all users.
|
||||||
|
Function StartMenuLocationCreator
|
||||||
|
; Set default value if not already set. Do this before we might "abort" this page.
|
||||||
|
${If} $StartMenuLocationValue == ""
|
||||||
|
StrCpy $StartMenuLocationValue "current_user"
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
; If the folder starts with >, the user has chosen not to create a shortcut (see NSIS/StartMenu.nsh)
|
||||||
|
StrCpy $R0 $StartMenuFolder 1
|
||||||
|
${If} $R0 == ">"
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
!insertmacro MUI_HEADER_TEXT_PAGE $(MUI_TEXT_STARTMENU_TITLE) $(SML_SubTitle)
|
||||||
|
|
||||||
|
nsDialogs::Create 1018
|
||||||
|
Pop $StartMenuLocationDialog
|
||||||
|
|
||||||
|
${If} $StartMenuLocationDialog == error
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${NSD_CreateLabel} 0u 0u 100% 12u $(SML_MainLabel)
|
||||||
|
Pop $R0
|
||||||
|
|
||||||
|
${NSD_CreateRadioButton} 8u 20u 100% 12u $(SML_RadioCurrent)
|
||||||
|
Pop $StartMenuLocationRadioCurrent
|
||||||
|
${NSD_AddStyle} $StartMenuLocationRadioCurrent ${WS_GROUP}
|
||||||
|
|
||||||
|
${NSD_CreateRadioButton} 8u 40u 100% 12u $(SML_RadioAll)
|
||||||
|
Pop $StartMenuLocationRadioAll
|
||||||
|
|
||||||
|
${If} $StartMenuLocationValue == "all_users"
|
||||||
|
${NSD_SetState} $StartMenuLocationRadioAll ${BST_CHECKED}
|
||||||
|
${Else}
|
||||||
|
${NSD_SetState} $StartMenuLocationRadioCurrent ${BST_CHECKED}
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${NSD_OnBack} StartMenuLocationLeave
|
||||||
|
|
||||||
|
nsDialogs::Show
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
; Converts the radio button state back into a value for "StartMenuLocationValue"
|
||||||
|
Function StartMenuLocationLeave
|
||||||
|
${NSD_GetState} $StartMenuLocationRadioAll $R0
|
||||||
|
${If} $R0 == ${BST_CHECKED}
|
||||||
|
StrCpy $StartMenuLocationValue "all_users"
|
||||||
|
${Else}
|
||||||
|
StrCpy $StartMenuLocationValue "current_user"
|
||||||
|
${Endif}
|
||||||
|
FunctionEnd
|
||||||
|
|
|
@ -489,7 +489,7 @@ end
|
||||||
local function runPopupPage(event)
|
local function runPopupPage(event)
|
||||||
local result
|
local result
|
||||||
if fieldPopup.status == 3 then
|
if fieldPopup.status == 3 then
|
||||||
result = popupConfirmation(fieldPopup.info, event)
|
result = popupConfirmation("Confirmation", fieldPopup.info, event)
|
||||||
else
|
else
|
||||||
result = popupWarning(fieldPopup.info, event)
|
result = popupWarning(fieldPopup.info, event)
|
||||||
end
|
end
|
||||||
|
|
157
radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
|
||||||
|
1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
|
||||||
|
1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
|
||||||
|
1,3,Flysky,V912,1,BtmBtn,TopBtn
|
||||||
|
1,4,Flysky,CX20,0,CH5,CH6,CH7
|
||||||
|
28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
53,0,Flyzone,FZ-410,0
|
||||||
|
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
||||||
|
2,1,Hubsan,H301,0,RTH,Light,Stab,Video
|
||||||
|
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
|
||||||
|
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
|
||||||
|
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
||||||
|
37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
|
||||||
|
37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
|
||||||
|
37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
|
||||||
|
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
|
||||||
|
3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
|
||||||
|
3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
|
||||||
|
67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
67,1,FrSkyL,LR12_6CH,0,CH5,CH6
|
||||||
|
15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||||
|
15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
|
||||||
|
15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||||
|
64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
|
||||||
|
64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
55,1,FrSkyRX,CloneTX,0
|
||||||
|
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
|
||||||
|
68,0,Skyartec,Std,0,CH5,CH6,CH7
|
||||||
|
7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
|
||||||
|
7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
7,3,Devo,6CH,0,CH5,CH6
|
||||||
|
7,4,Devo,7CH,0,CH5,CH6,CH7
|
||||||
|
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
|
||||||
|
30,1,WK2x01,WK2401,0
|
||||||
|
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
|
||||||
|
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
|
||||||
|
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
|
||||||
|
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
|
||||||
|
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
24,0,Assan,Std,0,CH5,CH6,CH7,CH8
|
||||||
|
14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
|
||||||
|
14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
|
||||||
|
14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
|
||||||
|
14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||||
|
14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||||
|
59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
|
||||||
|
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
|
||||||
|
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
|
||||||
|
34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
|
||||||
|
13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
|
||||||
|
12,0,CX10,Green,1,Flip,Rate
|
||||||
|
12,1,CX10,Blue,1,Flip,Rate,Pict,Video
|
||||||
|
12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
|
||||||
|
12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
|
||||||
|
12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
|
||||||
|
12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
|
||||||
|
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
|
||||||
|
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
|
||||||
|
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
|
||||||
|
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
|
||||||
|
16,0,ESKY,Std,0,Gyro,Pitch
|
||||||
|
16,1,ESKY,ET4,0,Gyro,Pitch
|
||||||
|
35,0,ESKY150,4CH,0
|
||||||
|
35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
|
||||||
|
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
||||||
|
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
||||||
|
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
|
||||||
|
32,0,GW008,FY326,1,Flip
|
||||||
|
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
|
||||||
|
36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
|
||||||
|
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||||
|
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||||
|
26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
|
||||||
|
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
|
||||||
|
44,0,NCC1701,Std,1,Warp
|
||||||
|
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
|
||||||
|
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
|
||||||
|
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
|
||||||
|
29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||||
|
29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||||
|
31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
|
||||||
|
31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
|
||||||
|
31,2,Q303,CX10D,1,Arm,Flip
|
||||||
|
31,3,Q303,CX10WD,1,Arm,Flip
|
||||||
|
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
|
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
|
11,0,SLT,V1,0,Gear,Pitch
|
||||||
|
11,1,SLT,V2,0,CH5,CH6,CH7,CH8
|
||||||
|
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
|
||||||
|
11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
|
||||||
|
11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
|
||||||
|
10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
|
||||||
|
10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
|
||||||
|
5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
|
||||||
|
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
|
||||||
|
61,0,Tiger,Std,1,Flip,Light
|
||||||
|
46,0,V911s,Std,1,Calib
|
||||||
|
46,1,E119,Std,1,Calib
|
||||||
|
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||||
|
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||||
|
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
|
||||||
|
65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
19,0,Shenqi,Cycle,1
|
||||||
|
4,1,Hisky,HK310,0,Aux
|
||||||
|
43,0,Traxxas,6519,0
|
||||||
|
52,0,ZSX,280,1,Light
|
||||||
|
48,0,V761,Std,1,Gyro
|
||||||
|
49,0,KF606,Std,1,Trim
|
||||||
|
47,0,GD00x,V1,1,Trim,LED,Rate
|
||||||
|
47,1,GD00x,V2,1,Trim,LED,Rate
|
||||||
|
58,0,FX816,P38,1
|
302
radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
|
||||||
|
local toolName = "TNS|Multi chan namer|TNE"
|
||||||
|
|
||||||
|
---- #########################################################################
|
||||||
|
---- # #
|
||||||
|
---- # Copyright (C) OpenTX #
|
||||||
|
-----# #
|
||||||
|
---- # 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. #
|
||||||
|
---- # #
|
||||||
|
---- #########################################################################
|
||||||
|
|
||||||
|
local protocol_name = ""
|
||||||
|
local sub_protocol_name = ""
|
||||||
|
local bind_ch = 0
|
||||||
|
local module_conf = {}
|
||||||
|
local module_pos = "Internal"
|
||||||
|
local file_ok = 0
|
||||||
|
local done = 0
|
||||||
|
local protocol = 0
|
||||||
|
local sub_protocol = 0
|
||||||
|
local f_seek = 0
|
||||||
|
local channel_names={}
|
||||||
|
local num_search = "Searching"
|
||||||
|
|
||||||
|
local function drawScreenTitle(title)
|
||||||
|
if LCD_W == 480 then
|
||||||
|
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||||
|
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||||
|
else
|
||||||
|
lcd.drawScreenTitle(title, 0, 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bitand(a, b)
|
||||||
|
local result = 0
|
||||||
|
local bitval = 1
|
||||||
|
while a > 0 and b > 0 do
|
||||||
|
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
|
||||||
|
result = result + bitval -- set the current bit
|
||||||
|
end
|
||||||
|
bitval = bitval * 2 -- shift left
|
||||||
|
a = math.floor(a/2) -- shift right
|
||||||
|
b = math.floor(b/2)
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Multi_Draw_LCD(event)
|
||||||
|
local line = 0
|
||||||
|
|
||||||
|
lcd.clear()
|
||||||
|
drawScreenTitle("Multi channels namer")
|
||||||
|
|
||||||
|
--Display settings
|
||||||
|
local lcd_opt = 0
|
||||||
|
if LCD_W == 480 then
|
||||||
|
x_pos = 10
|
||||||
|
y_pos = 32
|
||||||
|
y_inc = 20
|
||||||
|
else
|
||||||
|
x_pos = 0
|
||||||
|
y_pos = 9
|
||||||
|
y_inc = 8
|
||||||
|
lcd_opt = SMLSIZE
|
||||||
|
end
|
||||||
|
|
||||||
|
--Multi Module detection
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
if LCD_W == 480 then
|
||||||
|
lcd.drawText(10,50,"No Multi module configured...", BLINK)
|
||||||
|
else
|
||||||
|
--Draw on LCD_W=128
|
||||||
|
lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
else
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--Channel order
|
||||||
|
if (ch_order == -1) then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--Can't open file MultiChan.txt
|
||||||
|
if file_ok == 0 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
|
||||||
|
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||||
|
if f == nil then return end
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
|
||||||
|
num_search = num_search .. "."
|
||||||
|
if #num_search > 15 then
|
||||||
|
num_search = string.sub(num_search,1,9)
|
||||||
|
end
|
||||||
|
local proto = 0
|
||||||
|
local sub_proto = 0
|
||||||
|
local proto_name = ""
|
||||||
|
local sub_proto_name = ""
|
||||||
|
local channels = ""
|
||||||
|
local nbr_try = 0
|
||||||
|
local nbr_car = 0
|
||||||
|
repeat
|
||||||
|
io.seek(f, f_seek)
|
||||||
|
local data = io.read(f, 100) -- read 100 characters
|
||||||
|
if #data ==0 then
|
||||||
|
f_seek = -1 -- end of file
|
||||||
|
break
|
||||||
|
end
|
||||||
|
proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
|
||||||
|
if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
|
||||||
|
if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
|
||||||
|
protocol_name = proto_name
|
||||||
|
sub_protocol_name = sub_proto_name
|
||||||
|
bind_ch = tonumber(bind_ch)
|
||||||
|
if channels ~= nil then
|
||||||
|
--extract channel names
|
||||||
|
nbr_car = string.find(channels, "\r")
|
||||||
|
if nbr_car == nil then nbr_car = string.find(channels, "\n") end
|
||||||
|
if nbr_car ~= nil then
|
||||||
|
channels = string.sub(channels,1,nbr_car-1)
|
||||||
|
end
|
||||||
|
local i = 5
|
||||||
|
for k in string.gmatch(channels, ",([%w-_ ]+)") do
|
||||||
|
channel_names[i] = k
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f_seek = -1 -- protocol found
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if f_seek ~= -1 then
|
||||||
|
nbr_car = string.find(data, "\n")
|
||||||
|
if nbr_car == nil then nbr_car = string.find(data, "\r") end
|
||||||
|
if nbr_car == nil then
|
||||||
|
f_seek = -1 -- end of file
|
||||||
|
break
|
||||||
|
end
|
||||||
|
f_seek = f_seek + nbr_car -- seek to next line
|
||||||
|
nbr_try = nbr_try + 1
|
||||||
|
end
|
||||||
|
until nbr_try > 20 or f_seek == -1
|
||||||
|
io.close(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
if f_seek ~= -1 then
|
||||||
|
return -- continue searching...
|
||||||
|
end
|
||||||
|
|
||||||
|
--Protocol & Sub_protocol
|
||||||
|
if protocol_name == "" or sub_protocol_name == "" then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
|
||||||
|
return
|
||||||
|
elseif LCD_W > 128 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
else
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
text1=""
|
||||||
|
text2=""
|
||||||
|
for i,v in ipairs(channel_names) do
|
||||||
|
if i<=8 then
|
||||||
|
if i==1 then
|
||||||
|
text1 = v
|
||||||
|
else
|
||||||
|
text1=text1 .. "," .. v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if i==9 then
|
||||||
|
text2 = v
|
||||||
|
else
|
||||||
|
text2=text2 .. "," .. v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if LCD_W > 128 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
if text2 ~= "" then
|
||||||
|
lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if event ~= EVT_VIRTUAL_ENTER and done == 0 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"<ENT> Save", lcd_opt + INVERS + BLINK)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
local output, nbr
|
||||||
|
if done == 0 then
|
||||||
|
for i,v in ipairs(channel_names) do
|
||||||
|
output = model.getOutput(i-1)
|
||||||
|
output["name"] = v
|
||||||
|
model.setOutput(i-1,output)
|
||||||
|
nbr = i
|
||||||
|
end
|
||||||
|
for i = nbr, 15 do
|
||||||
|
output = model.getOutput(i)
|
||||||
|
output["name"] = "n-a"
|
||||||
|
model.setOutput(i,output)
|
||||||
|
end
|
||||||
|
if bind_ch == 1 then
|
||||||
|
output = model.getOutput(15)
|
||||||
|
output["name"] = "BindCH"
|
||||||
|
model.setOutput(15,output)
|
||||||
|
end
|
||||||
|
done = 1
|
||||||
|
end
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Init
|
||||||
|
local function Multi_Init()
|
||||||
|
module_conf = model.getModule(0)
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
module_pos = "External"
|
||||||
|
module_conf = model.getModule(1)
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protocol = module_conf["protocol"]
|
||||||
|
sub_protocol = module_conf["subProtocol"]
|
||||||
|
|
||||||
|
--Exceptions on first 4 channels...
|
||||||
|
local stick_names = { "Rud", "Ele", "Thr", "Ail" }
|
||||||
|
if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
|
||||||
|
stick_names[2] = "n-a"
|
||||||
|
stick_names[4] = "n-a"
|
||||||
|
elseif protocol == 43 then -- Traxxas
|
||||||
|
stick_names[2] = "Aux4"
|
||||||
|
stick_names[4] = "Aux3"
|
||||||
|
elseif protocol == 48 then -- V761
|
||||||
|
stick_names[4] = "n-a"
|
||||||
|
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
|
||||||
|
stick_names[1] = "n-a"
|
||||||
|
stick_names[2] = "n-a"
|
||||||
|
end
|
||||||
|
|
||||||
|
--Determine fist 4 channels order
|
||||||
|
local ch_order=module_conf["channelsOrder"]
|
||||||
|
if (ch_order == -1) then
|
||||||
|
channel_names[1] = stick_names[defaultChannel(0)+1]
|
||||||
|
channel_names[2] = stick_names[defaultChannel(1)+1]
|
||||||
|
channel_names[3] = stick_names[defaultChannel(2)+1]
|
||||||
|
channel_names[4] = stick_names[defaultChannel(3)+1]
|
||||||
|
else
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[4]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[2]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[3]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[1]
|
||||||
|
end
|
||||||
|
--Check MultiChan.txt
|
||||||
|
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||||
|
if f == nil then return end
|
||||||
|
file_ok = 1
|
||||||
|
io.close(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main
|
||||||
|
local function Multi_Run(event)
|
||||||
|
if event == nil then
|
||||||
|
error("Cannot be run as a model script!")
|
||||||
|
return 2
|
||||||
|
else
|
||||||
|
Multi_Draw_LCD(event)
|
||||||
|
if event == EVT_VIRTUAL_EXIT then
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return { init=Multi_Init, run=Multi_Run }
|
BIN
radio/sdcard/horus/THEMES/Darkblue/tx16s.bmp
Executable file → Normal file
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 161 KiB |
|
@ -19,7 +19,8 @@
|
||||||
-- Horus Widget to display the levels of lipo battery with per cell indication
|
-- Horus Widget to display the levels of lipo battery with per cell indication
|
||||||
-- 3djc & Offer Shmuely
|
-- 3djc & Offer Shmuely
|
||||||
-- Date: 2020
|
-- Date: 2020
|
||||||
-- ver: 0.4
|
-- ver: 0.5
|
||||||
|
local version = "v0.5"
|
||||||
|
|
||||||
local _options = {
|
local _options = {
|
||||||
{ "Sensor", SOURCE, 0 }, -- default to 'Cels'
|
{ "Sensor", SOURCE, 0 }, -- default to 'Cels'
|
||||||
|
@ -28,6 +29,40 @@ local _options = {
|
||||||
{ "LowestCell", BOOL, 1 } -- 0=main voltage display shows all-cell-voltage, 1=main voltage display shows lowest-cell
|
{ "LowestCell", BOOL, 1 } -- 0=main voltage display shows all-cell-voltage, 1=main voltage display shows lowest-cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Data gathered from commercial lipo sensors
|
||||||
|
|
||||||
|
local _lipoPercentListSplit = {
|
||||||
|
{ { 3, 0 }, { 3.093, 1 }, { 3.196, 2 }, { 3.301, 3 }, { 3.401, 4 }, { 3.477, 5 }, { 3.544, 6 }, { 3.601, 7 }, { 3.637, 8 }, { 3.664, 9 }, { 3.679, 10 }, { 3.683, 11 }, { 3.689, 12 }, { 3.692, 13 } },
|
||||||
|
{ { 3.705, 14 }, { 3.71, 15 }, { 3.713, 16 }, { 3.715, 17 }, { 3.72, 18 }, { 3.731, 19 }, { 3.735, 20 }, { 3.744, 21 }, { 3.753, 22 }, { 3.756, 23 }, { 3.758, 24 }, { 3.762, 25 }, { 3.767, 26 } },
|
||||||
|
{ { 3.774, 27 }, { 3.78, 28 }, { 3.783, 29 }, { 3.786, 30 }, { 3.789, 31 }, { 3.794, 32 }, { 3.797, 33 }, { 3.8, 34 }, { 3.802, 35 }, { 3.805, 36 }, { 3.808, 37 }, { 3.811, 38 }, { 3.815, 39 } },
|
||||||
|
{ { 3.818, 40 }, { 3.822, 41 }, { 3.825, 42 }, { 3.829, 43 }, { 3.833, 44 }, { 3.836, 45 }, { 3.84, 46 }, { 3.843, 47 }, { 3.847, 48 }, { 3.85, 49 }, { 3.854, 50 }, { 3.857, 51 }, { 3.86, 52 } },
|
||||||
|
{ { 3.863, 53 }, { 3.866, 54 }, { 3.87, 55 }, { 3.874, 56 }, { 3.879, 57 }, { 3.888, 58 }, { 3.893, 59 }, { 3.897, 60 }, { 3.902, 61 }, { 3.906, 62 }, { 3.911, 63 }, { 3.918, 64 } },
|
||||||
|
{ { 3.923, 65 }, { 3.928, 66 }, { 3.939, 67 }, { 3.943, 68 }, { 3.949, 69 }, { 3.955, 70 }, { 3.961, 71 }, { 3.968, 72 }, { 3.974, 73 }, { 3.981, 74 }, { 3.987, 75 }, { 3.994, 76 } },
|
||||||
|
{ { 4.001, 77 }, { 4.007, 78 }, { 4.014, 79 }, { 4.021, 80 }, { 4.029, 81 }, { 4.036, 82 }, { 4.044, 83 }, { 4.052, 84 }, { 4.062, 85 }, { 4.074, 86 }, { 4.085, 87 }, { 4.095, 88 } },
|
||||||
|
{ { 4.105, 89 }, { 4.111, 90 }, { 4.116, 91 }, { 4.12, 92 }, { 4.125, 93 }, { 4.129, 94 }, { 4.135, 95 }, { 4.145, 96 }, { 4.176, 97 }, { 4.179, 98 }, { 4.193, 99 }, { 4.2, 100 } },
|
||||||
|
}
|
||||||
|
|
||||||
|
local function periodicInit(t, durationMili)
|
||||||
|
t.startTime = getTime();
|
||||||
|
t.durationMili = durationMili;
|
||||||
|
end
|
||||||
|
local function periodicReset(t)
|
||||||
|
t.startTime = getTime();
|
||||||
|
end
|
||||||
|
local function periodicHasPassed(t)
|
||||||
|
local elapsed = getTime() - t.startTime;
|
||||||
|
local elapsedMili = elapsed * 10;
|
||||||
|
if (elapsedMili < t.durationMili) then
|
||||||
|
return false;
|
||||||
|
end
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
local function periodicGetElapsedTime(t)
|
||||||
|
local elapsed = getTime() - t.startTime;
|
||||||
|
local elapsedMili = elapsed * 10;
|
||||||
|
return elapsedMili;
|
||||||
|
end
|
||||||
|
|
||||||
-- This function is run once at the creation of the widget
|
-- This function is run once at the creation of the widget
|
||||||
local function create(zone, options)
|
local function create(zone, options)
|
||||||
local wgt = {
|
local wgt = {
|
||||||
|
@ -40,8 +75,8 @@ local function create(zone, options)
|
||||||
telemResetLowestMinRSSI = 101,
|
telemResetLowestMinRSSI = 101,
|
||||||
no_telem_blink = 0,
|
no_telem_blink = 0,
|
||||||
isDataAvailable = 0,
|
isDataAvailable = 0,
|
||||||
cellDataLive = {0,0,0,0,0,0},
|
cellDataLive = { 0, 0, 0, 0, 0, 0 },
|
||||||
cellDataHistoryLowest = {5,5,5,5,5,5},
|
cellDataHistoryLowest = { 5, 5, 5, 5, 5, 5 },
|
||||||
cellDataHistoryCellLowest = 5,
|
cellDataHistoryCellLowest = 5,
|
||||||
cellMax = 0,
|
cellMax = 0,
|
||||||
cellMin = 0,
|
cellMin = 0,
|
||||||
|
@ -50,7 +85,10 @@ local function create(zone, options)
|
||||||
cellCount = 0,
|
cellCount = 0,
|
||||||
cellSum = 0,
|
cellSum = 0,
|
||||||
mainValue = 0,
|
mainValue = 0,
|
||||||
secondaryValue = 0
|
secondaryValue = 0,
|
||||||
|
periodic1 = { startTime = getTime(), durationMili = 1000 },
|
||||||
|
periodicProfiler = { startTime = getTime(), durationMili = 5000 },
|
||||||
|
profTimes = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
-- use default if user did not set, So widget is operational on "select widget"
|
-- use default if user did not set, So widget is operational on "select widget"
|
||||||
|
@ -65,7 +103,9 @@ end
|
||||||
|
|
||||||
-- This function allow updates when you change widgets settings
|
-- This function allow updates when you change widgets settings
|
||||||
local function update(wgt, options)
|
local function update(wgt, options)
|
||||||
if (wgt == nil) then return end
|
if (wgt == nil) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
wgt.options = options
|
wgt.options = options
|
||||||
|
|
||||||
|
@ -83,8 +123,8 @@ end
|
||||||
local function onTelemetryResetEvent(wgt)
|
local function onTelemetryResetEvent(wgt)
|
||||||
wgt.telemResetCount = wgt.telemResetCount + 1
|
wgt.telemResetCount = wgt.telemResetCount + 1
|
||||||
|
|
||||||
wgt.cellDataLive = {0,0,0,0,0,0}
|
wgt.cellDataLive = { 0, 0, 0, 0, 0, 0 }
|
||||||
wgt.cellDataHistoryLowest = {5,5,5,5,5,5}
|
wgt.cellDataHistoryLowest = { 5, 5, 5, 5, 5, 5 }
|
||||||
wgt.cellDataHistoryCellLowest = 5
|
wgt.cellDataHistoryCellLowest = 5
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -99,9 +139,12 @@ end
|
||||||
local function detectResetEvent(wgt)
|
local function detectResetEvent(wgt)
|
||||||
|
|
||||||
local currMinRSSI = getValue('RSSI-')
|
local currMinRSSI = getValue('RSSI-')
|
||||||
if (currMinRSSI == nil) then return
|
if (currMinRSSI == nil) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if (currMinRSSI == wgt.telemResetLowestMinRSSI) then
|
||||||
|
return
|
||||||
end
|
end
|
||||||
if (currMinRSSI == wgt.telemResetLowestMinRSSI) then return end
|
|
||||||
|
|
||||||
if (currMinRSSI < wgt.telemResetLowestMinRSSI) then
|
if (currMinRSSI < wgt.telemResetLowestMinRSSI) then
|
||||||
-- rssi just got lower, record it
|
-- rssi just got lower, record it
|
||||||
|
@ -118,28 +161,28 @@ local function detectResetEvent(wgt)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- This function return the percentage remaining in a single Lipo cel
|
--- This function return the percentage remaining in a single Lipo cel
|
||||||
local function getCellPercent(cellValue)
|
--- since running on long array found to be very intensive to hrous cpu, we are splitting the list to small lists
|
||||||
|
local function getCellPercent(wgt, cellValue)
|
||||||
if cellValue == nil then
|
if cellValue == nil then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
local result = 0;
|
||||||
|
|
||||||
-- in case somehow voltage is higher, don't return nil
|
for i1, v1 in ipairs(_lipoPercentListSplit) do
|
||||||
if (cellValue > 4.2) then
|
--is the cellVal < last-value-on-sub-list? (first-val:v1[1], last-val:v1[#v1])
|
||||||
return 100
|
if (cellValue <= v1[#v1][1]) then
|
||||||
end
|
-- cellVal is in this sub-list, find the exact value
|
||||||
|
for i2, v2 in ipairs(v1) do
|
||||||
-- Data gathered from commercial lipo sensors
|
if v2[1] >= cellValue then
|
||||||
local myArrayPercentList = { {3,0},{3.093,1},{3.196,2},{3.301,3},{3.401,4},{3.477,5},{3.544,6},{3.601,7},{3.637,8},{3.664,9},{3.679,10},{3.683,11},{3.689,12},{3.692,13},{3.705,14},{3.71,15},{3.713,16},{3.715,17},{3.72,18},{3.731,19},{3.735,20},{3.744,21},{3.753,22},{3.756,23},{3.758,24},{3.762,25},{3.767,26},{3.774,27},{3.78,28},{3.783,29},{3.786,30},{3.789,31},{3.794,32},{3.797,33},{3.8,34},{3.802,35},{3.805,36},{3.808,37},{3.811,38},{3.815,39},{3.818,40},{3.822,41},{3.825,42},{3.829,43},{3.833,44},{3.836,45},{3.84,46},{3.843,47},{3.847,48},{3.85,49},{3.854,50},{3.857,51},{3.86,52},{3.863,53},{3.866,54},{3.87,55},{3.874,56},{3.879,57},{3.888,58},{3.893,59},{3.897,60},{3.902,61},{3.906,62},{3.911,63},{3.918,64},{3.923,65},{3.928,66},{3.939,67},{3.943,68},{3.949,69},{3.955,70},{3.961,71},{3.968,72},{3.974,73},{3.981,74},{3.987,75},{3.994,76},{4.001,77},{4.007,78},{4.014,79},{4.021,80},{4.029,81},{4.036,82},{4.044,83},{4.052,84},{4.062,85},{4.074,86},{4.085,87},{4.095,88},{4.105,89},{4.111,90},{4.116,91},{4.12,92},{4.125,93},{4.129,94},{4.135,95},{4.145,96},{4.176,97},{4.179,98},{4.193,99},{4.2,100} }
|
result = v2[2]
|
||||||
|
|
||||||
for i, v in ipairs(myArrayPercentList) do
|
|
||||||
if v[1] >= cellValue then
|
|
||||||
result = v[2]
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return result
|
return result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- in case somehow voltage is too high (>4.2), don't return nil
|
||||||
|
return 100
|
||||||
end
|
end
|
||||||
|
|
||||||
--- This function returns a table with cels values
|
--- This function returns a table with cels values
|
||||||
|
@ -152,20 +195,13 @@ local function calculateBatteryData(wgt)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- this is necessary for simu where cell-count can change
|
|
||||||
if #wgt.cellDataHistoryLowest ~= #newCellData then
|
|
||||||
wgt.cellDataHistoryLowest = {}
|
|
||||||
for k, v in pairs(newCellData) do
|
|
||||||
wgt.cellDataHistoryLowest[k] = 5 -- invalid reading, set high value so the min() will update it soon
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local cellMax = 0
|
local cellMax = 0
|
||||||
local cellMin = 5
|
local cellMin = 5
|
||||||
local cellSum = 0
|
local cellSum = 0
|
||||||
for k, v in pairs(newCellData) do
|
for k, v in pairs(newCellData) do
|
||||||
-- stores the lowest cell values in historical table
|
-- stores the lowest cell values in historical table
|
||||||
if v > 1 and v < wgt.cellDataHistoryLowest[k] then -- min 1v to consider a valid reading
|
if v > 1 and v < wgt.cellDataHistoryLowest[k] then
|
||||||
|
-- min 1v to consider a valid reading
|
||||||
wgt.cellDataHistoryLowest[k] = v
|
wgt.cellDataHistoryLowest[k] = v
|
||||||
|
|
||||||
--- calc history lowest of all cells
|
--- calc history lowest of all cells
|
||||||
|
@ -181,7 +217,8 @@ local function calculateBatteryData(wgt)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- calc lowest of all cells
|
--- calc lowest of all cells
|
||||||
if v < cellMin and v > 1 then -- min 1v to consider a valid reading
|
if v < cellMin and v > 1 then
|
||||||
|
-- min 1v to consider a valid reading
|
||||||
cellMin = v
|
cellMin = v
|
||||||
end
|
end
|
||||||
--- sum of all cells
|
--- sum of all cells
|
||||||
|
@ -197,7 +234,6 @@ local function calculateBatteryData(wgt)
|
||||||
|
|
||||||
--- average of all cells
|
--- average of all cells
|
||||||
wgt.cellAvg = wgt.cellSum / wgt.cellCount
|
wgt.cellAvg = wgt.cellSum / wgt.cellCount
|
||||||
wgt.cellPercent = getCellPercent(wgt.cellMin)
|
|
||||||
|
|
||||||
wgt.cellDataLive = newCellData
|
wgt.cellDataLive = newCellData
|
||||||
|
|
||||||
|
@ -219,13 +255,19 @@ local function calculateBatteryData(wgt)
|
||||||
wgt.secondaryValue = "-2"
|
wgt.secondaryValue = "-2"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
wgt.isDataAvailable = true
|
wgt.isDataAvailable = true
|
||||||
|
|
||||||
|
-- calculate intensive CPU data
|
||||||
|
if (periodicHasPassed(wgt.periodic1) or wgt.cellPercent == 0) then
|
||||||
|
|
||||||
|
--wgt.cellPercent = getCellPercent(wgt, wgt.cellMin) -- use batt percentage by lowest cell voltage
|
||||||
|
wgt.cellPercent = getCellPercent(wgt, wgt.cellAvg) -- use batt percentage by average cell voltage
|
||||||
|
|
||||||
|
periodicReset(wgt.periodic1)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- color for battery
|
-- color for battery
|
||||||
-- This function returns green at 100%, red bellow 30% and graduate in between
|
-- This function returns green at 100%, red bellow 30% and graduate in between
|
||||||
local function getPercentColor(percent)
|
local function getPercentColor(percent)
|
||||||
|
@ -242,34 +284,46 @@ end
|
||||||
-- This function returns green at gvalue, red at rvalue and graduate in between
|
-- This function returns green at gvalue, red at rvalue and graduate in between
|
||||||
local function getRangeColor(value, green_value, red_value)
|
local function getRangeColor(value, green_value, red_value)
|
||||||
local range = math.abs(green_value - red_value)
|
local range = math.abs(green_value - red_value)
|
||||||
if range==0 then return lcd.RGB(0, 0xdf, 0) end
|
if range == 0 then
|
||||||
|
return lcd.RGB(0, 0xdf, 0)
|
||||||
|
end
|
||||||
|
if value == nil then
|
||||||
|
return lcd.RGB(0, 0xdf, 0)
|
||||||
|
end
|
||||||
|
|
||||||
if green_value > red_value then
|
if green_value > red_value then
|
||||||
if value > green_value then return lcd.RGB(0, 0xdf, 0) end
|
if value > green_value then
|
||||||
if value < red_value then return lcd.RGB(0xdf, 0, 0) end
|
return lcd.RGB(0, 0xdf, 0)
|
||||||
|
end
|
||||||
|
if value < red_value then
|
||||||
|
return lcd.RGB(0xdf, 0, 0)
|
||||||
|
end
|
||||||
g = math.floor(0xdf * (value - red_value) / range)
|
g = math.floor(0xdf * (value - red_value) / range)
|
||||||
r = 0xdf - g
|
r = 0xdf - g
|
||||||
return lcd.RGB(r, g, 0)
|
return lcd.RGB(r, g, 0)
|
||||||
else
|
else
|
||||||
if value > green_value then return lcd.RGB(0, 0xdf, 0) end
|
if value > green_value then
|
||||||
if value < red_value then return lcd.RGB(0xdf, 0, 0) end
|
return lcd.RGB(0, 0xdf, 0)
|
||||||
|
end
|
||||||
|
if value < red_value then
|
||||||
|
return lcd.RGB(0xdf, 0, 0)
|
||||||
|
end
|
||||||
r = math.floor(0xdf * (value - green_value) / range)
|
r = math.floor(0xdf * (value - green_value) / range)
|
||||||
g = 0xdf - r
|
g = 0xdf - r
|
||||||
return lcd.RGB(r, g, 0)
|
return lcd.RGB(r, g, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Zone size: 70x39 1/8th top bar
|
--- Zone size: 70x39 1/8th top bar
|
||||||
local function refreshZoneTiny(wgt)
|
local function refreshZoneTiny(wgt)
|
||||||
local myString = string.format("%2.1fV", wgt.mainValue)
|
local myString = string.format("%2.1fV", wgt.mainValue)
|
||||||
lcd.drawText(wgt.zone.x + wgt.zone.w -25, wgt.zone.y + 5, wgt.cellPercent .. "%", RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
lcd.drawText(wgt.zone.x + wgt.zone.w - 25, wgt.zone.y + 5, wgt.cellPercent .. "%", RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
||||||
lcd.drawText(wgt.zone.x + wgt.zone.w -25, wgt.zone.y + 20, myString, RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
lcd.drawText(wgt.zone.x + wgt.zone.w - 25, wgt.zone.y + 20, myString, RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
||||||
-- draw batt
|
-- draw batt
|
||||||
lcd.drawRectangle(wgt.zone.x + 50, wgt.zone.y + 9, 16, 25, CUSTOM_COLOR, 2)
|
lcd.drawRectangle(wgt.zone.x + 50, wgt.zone.y + 9, 16, 25, CUSTOM_COLOR, 2)
|
||||||
lcd.drawFilledRectangle(wgt.zone.x +50 + 4, wgt.zone.y + 7, 6, 3, CUSTOM_COLOR)
|
lcd.drawFilledRectangle(wgt.zone.x + 50 + 4, wgt.zone.y + 7, 6, 3, CUSTOM_COLOR)
|
||||||
local rect_h = math.floor(25 * wgt.cellPercent / 100)
|
local rect_h = math.floor(25 * wgt.cellPercent / 100)
|
||||||
lcd.drawFilledRectangle(wgt.zone.x +50, wgt.zone.y + 9 + 25 - rect_h, 16, rect_h, CUSTOM_COLOR + wgt.no_telem_blink)
|
lcd.drawFilledRectangle(wgt.zone.x + 50, wgt.zone.y + 9 + 25 - rect_h, 16, rect_h, CUSTOM_COLOR + wgt.no_telem_blink)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Zone size: 160x32 1/8th
|
--- Zone size: 160x32 1/8th
|
||||||
|
@ -307,13 +361,13 @@ local function refreshZoneMedium(wgt)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw values
|
-- draw values
|
||||||
lcd.drawText(wgt.zone.x, wgt.zone.y + 35, string.format("%2.1fV", wgt.mainValue), DBLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
|
lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y, string.format("%2.1fV", wgt.mainValue), DBLSIZE + CUSTOM_COLOR + RIGHT + wgt.shadowed + wgt.no_telem_blink)
|
||||||
|
|
||||||
-- more info if 1/4 is high enough (without trim & slider)
|
-- more info if 1/4 is high enough (without trim & slider)
|
||||||
if wgt.zone.h > 80 then
|
if wgt.zone.h > 80 then
|
||||||
lcd.drawText(wgt.zone.x , wgt.zone.y + 70, string.format("%2.2fV" , wgt.secondaryValue), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
--lcd.drawText(wgt.zone.x + 50 , wgt.zone.y + 70, string.format("%2.2fV" , wgt.secondaryValue), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
||||||
lcd.drawText(wgt.zone.x + 50, wgt.zone.y + 70, string.format("dV %2.2fV", wgt.cellMax - wgt.cellMin), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
lcd.drawText(wgt.zone.x, wgt.zone.y + 70, string.format("dV %2.2fV", wgt.cellMax - wgt.cellMin), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
||||||
lcd.drawText(wgt.zone.x , wgt.zone.y + 84, string.format("Min %2.2fV", wgt.cellDataHistoryCellLowest), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
lcd.drawText(wgt.zone.x, wgt.zone.y + 84, string.format("Min %2.2fV", wgt.cellDataHistoryCellLowest), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- fill batt
|
-- fill batt
|
||||||
|
@ -321,28 +375,21 @@ local function refreshZoneMedium(wgt)
|
||||||
lcd.drawGauge(wgt.zone.x + myBatt.x, wgt.zone.y + myBatt.y, myBatt.w, myBatt.h, wgt.cellPercent, 100, CUSTOM_COLOR)
|
lcd.drawGauge(wgt.zone.x + myBatt.x, wgt.zone.y + myBatt.y, myBatt.w, myBatt.h, wgt.cellPercent, 100, CUSTOM_COLOR)
|
||||||
|
|
||||||
-- draw cells
|
-- draw cells
|
||||||
local cellH = wgt.zone.h / wgt.cellCount
|
local cellH = 19
|
||||||
if cellH > 20 then cellH =20 end
|
|
||||||
local cellX = 118
|
local cellX = 118
|
||||||
local cellW = 58
|
local cellW = wgt.zone.w / 3
|
||||||
|
|
||||||
|
local pos = { { x = 0, y = 38 }, { x = cellW, y = 38 }, { x = 2 * cellW, y = 38 }, { x = 0, y = 57 }, { x = cellW, y = 57 }, { x = 2 * cellW, y = 57 } }
|
||||||
for i = 1, wgt.cellCount, 1 do
|
for i = 1, wgt.cellCount, 1 do
|
||||||
local cellY = wgt.zone.y + (i-1)* (cellH -1)
|
local cellY = wgt.zone.y + (i - 1) * (cellH - 1)
|
||||||
|
|
||||||
-- fill current cell
|
-- fill current cell
|
||||||
lcd.setColor(CUSTOM_COLOR, getRangeColor(wgt.cellDataLive[i], wgt.cellMax, wgt.cellMax - 0.2))
|
|
||||||
--lcd.drawFilledRectangle(wgt.zone.x + cellX , cellY, 58, cellH, CUSTOM_COLOR)
|
--lcd.drawFilledRectangle(wgt.zone.x + cellX , cellY, 58, cellH, CUSTOM_COLOR)
|
||||||
local percentCurrent = getCellPercent(wgt.cellDataLive[i])
|
lcd.setColor(CUSTOM_COLOR, getRangeColor(wgt.cellDataLive[i], wgt.cellMax, wgt.cellMax - 0.2))
|
||||||
local percentMin = getCellPercent(wgt.cellDataHistoryLowest[i])
|
lcd.drawFilledRectangle(wgt.zone.x + pos[i].x, wgt.zone.y + pos[i].y, cellW - 1, 20, CUSTOM_COLOR)
|
||||||
|
|
||||||
lcd.drawFilledRectangle(wgt.zone.x + cellX , cellY, cellW * percentCurrent / 100, cellH, CUSTOM_COLOR)
|
|
||||||
|
|
||||||
-- fill min
|
|
||||||
lcd.setColor(CUSTOM_COLOR, getRangeColor(wgt.cellDataHistoryLowest[i], wgt.cellMax, wgt.cellMax - 0.2))
|
|
||||||
lcd.drawFilledRectangle(wgt.zone.x + cellX + ((percentCurrent - percentMin) / 100) , cellY, cellW - (cellW * (percentCurrent - percentMin) / 100), cellH, CUSTOM_COLOR)
|
|
||||||
|
|
||||||
lcd.setColor(CUSTOM_COLOR, WHITE)
|
lcd.setColor(CUSTOM_COLOR, WHITE)
|
||||||
lcd.drawText (wgt.zone.x + cellX + 10, cellY, string.format("%.2f", wgt.cellDataLive[i]), SMLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
|
lcd.drawText(wgt.zone.x + pos[i].x + 10, wgt.zone.y + pos[i].y, string.format("%.2f", wgt.cellDataLive[i]), CUSTOM_COLOR + wgt.shadowed)
|
||||||
lcd.drawRectangle (wgt.zone.x + cellX , cellY, 59, cellH, CUSTOM_COLOR , 1)
|
lcd.drawRectangle(wgt.zone.x + pos[i].x, wgt.zone.y + pos[i].y, cellW, 20, CUSTOM_COLOR, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draws bat
|
-- draws bat
|
||||||
|
@ -447,7 +494,9 @@ end
|
||||||
|
|
||||||
-- This function allow recording of lowest cells when widget is in background
|
-- This function allow recording of lowest cells when widget is in background
|
||||||
local function background(wgt)
|
local function background(wgt)
|
||||||
if (wgt == nil) then return end
|
if (wgt == nil) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
detectResetEvent(wgt)
|
detectResetEvent(wgt)
|
||||||
|
|
||||||
|
@ -456,11 +505,21 @@ local function background(wgt)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function refresh(wgt)
|
local function refresh(wgt)
|
||||||
|
if (wgt == nil) then
|
||||||
if (wgt == nil) then return end
|
return
|
||||||
if (wgt.options == nil) then return end
|
end
|
||||||
if (wgt.zone == nil) then return end
|
if type(wgt) ~= "table" then
|
||||||
if (wgt.options.LowestCell == nil) then return end
|
return
|
||||||
|
end
|
||||||
|
if (wgt.options == nil) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if (wgt.zone == nil) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if (wgt.options.LowestCell == nil) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if wgt.options.Shadow == 1 then
|
if wgt.options.Shadow == 1 then
|
||||||
wgt.shadowed = SHADOWED
|
wgt.shadowed = SHADOWED
|
||||||
|
@ -478,14 +537,17 @@ local function refresh(wgt)
|
||||||
wgt.no_telem_blink = INVERS + BLINK
|
wgt.no_telem_blink = INVERS + BLINK
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if wgt.zone.w > 380 and wgt.zone.h > 165 then
|
||||||
if wgt.zone.w > 380 and wgt.zone.h > 165 then refreshZoneXLarge(wgt)
|
refreshZoneXLarge(wgt)
|
||||||
elseif wgt.zone.w > 180 and wgt.zone.h > 145 then refreshZoneLarge(wgt)
|
elseif wgt.zone.w > 180 and wgt.zone.h > 145 then
|
||||||
elseif wgt.zone.w > 170 and wgt.zone.h > 65 then refreshZoneMedium(wgt)
|
refreshZoneLarge(wgt)
|
||||||
elseif wgt.zone.w > 150 and wgt.zone.h > 28 then refreshZoneSmall(wgt)
|
elseif wgt.zone.w > 170 and wgt.zone.h > 65 then
|
||||||
elseif wgt.zone.w > 65 and wgt.zone.h > 35 then refreshZoneTiny(wgt)
|
refreshZoneMedium(wgt)
|
||||||
|
elseif wgt.zone.w > 150 and wgt.zone.h > 28 then
|
||||||
|
refreshZoneSmall(wgt)
|
||||||
|
elseif wgt.zone.w > 65 and wgt.zone.h > 35 then
|
||||||
|
refreshZoneTiny(wgt)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return { name="BattCheck", options=_options, create=create, update=update, background=background, refresh=refresh }
|
return { name = "BattCheck", options = _options, create = create, update = update, background = background, refresh = refresh }
|
157
radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
|
||||||
|
1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
|
||||||
|
1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
|
||||||
|
1,3,Flysky,V912,1,BtmBtn,TopBtn
|
||||||
|
1,4,Flysky,CX20,0,CH5,CH6,CH7
|
||||||
|
28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
53,0,Flyzone,FZ-410,0
|
||||||
|
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
||||||
|
2,1,Hubsan,H301,0,RTH,Light,Stab,Video
|
||||||
|
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
|
||||||
|
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
|
||||||
|
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
||||||
|
37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
|
||||||
|
37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
|
||||||
|
37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
|
||||||
|
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
|
||||||
|
3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
|
||||||
|
3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
|
||||||
|
67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
67,1,FrSkyL,LR12_6CH,0,CH5,CH6
|
||||||
|
15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||||
|
15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
|
||||||
|
15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||||
|
64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
|
||||||
|
64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
55,1,FrSkyRX,CloneTX,0
|
||||||
|
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
|
||||||
|
68,0,Skyartec,Std,0,CH5,CH6,CH7
|
||||||
|
7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
|
||||||
|
7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
7,3,Devo,6CH,0,CH5,CH6
|
||||||
|
7,4,Devo,7CH,0,CH5,CH6,CH7
|
||||||
|
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
|
||||||
|
30,1,WK2x01,WK2401,0
|
||||||
|
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
|
||||||
|
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
|
||||||
|
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
|
||||||
|
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
|
||||||
|
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
24,0,Assan,Std,0,CH5,CH6,CH7,CH8
|
||||||
|
14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
|
||||||
|
14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
|
||||||
|
14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
|
||||||
|
14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||||
|
14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||||
|
59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
|
||||||
|
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
|
||||||
|
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
|
||||||
|
34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
|
||||||
|
13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
|
||||||
|
12,0,CX10,Green,1,Flip,Rate
|
||||||
|
12,1,CX10,Blue,1,Flip,Rate,Pict,Video
|
||||||
|
12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
|
||||||
|
12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
|
||||||
|
12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
|
||||||
|
12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
|
||||||
|
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
|
||||||
|
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
|
||||||
|
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
|
||||||
|
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
|
||||||
|
16,0,ESKY,Std,0,Gyro,Pitch
|
||||||
|
16,1,ESKY,ET4,0,Gyro,Pitch
|
||||||
|
35,0,ESKY150,4CH,0
|
||||||
|
35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
|
||||||
|
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
||||||
|
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
||||||
|
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
|
||||||
|
32,0,GW008,FY326,1,Flip
|
||||||
|
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
|
||||||
|
36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
|
||||||
|
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||||
|
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||||
|
26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
|
||||||
|
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
|
||||||
|
44,0,NCC1701,Std,1,Warp
|
||||||
|
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
|
||||||
|
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
|
||||||
|
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
|
||||||
|
29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||||
|
29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||||
|
31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
|
||||||
|
31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
|
||||||
|
31,2,Q303,CX10D,1,Arm,Flip
|
||||||
|
31,3,Q303,CX10WD,1,Arm,Flip
|
||||||
|
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
|
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
|
11,0,SLT,V1,0,Gear,Pitch
|
||||||
|
11,1,SLT,V2,0,CH5,CH6,CH7,CH8
|
||||||
|
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
|
||||||
|
11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
|
||||||
|
11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
|
||||||
|
10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
|
||||||
|
10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
|
||||||
|
5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
|
||||||
|
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
|
||||||
|
61,0,Tiger,Std,1,Flip,Light
|
||||||
|
46,0,V911s,Std,1,Calib
|
||||||
|
46,1,E119,Std,1,Calib
|
||||||
|
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||||
|
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||||
|
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
|
||||||
|
65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
19,0,Shenqi,Cycle,1
|
||||||
|
4,1,Hisky,HK310,0,Aux
|
||||||
|
43,0,Traxxas,6519,0
|
||||||
|
52,0,ZSX,280,1,Light
|
||||||
|
48,0,V761,Std,1,Gyro
|
||||||
|
49,0,KF606,Std,1,Trim
|
||||||
|
47,0,GD00x,V1,1,Trim,LED,Rate
|
||||||
|
47,1,GD00x,V2,1,Trim,LED,Rate
|
||||||
|
58,0,FX816,P38,1
|
302
radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
|
||||||
|
local toolName = "TNS|Multi chan namer|TNE"
|
||||||
|
|
||||||
|
---- #########################################################################
|
||||||
|
---- # #
|
||||||
|
---- # Copyright (C) OpenTX #
|
||||||
|
-----# #
|
||||||
|
---- # 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. #
|
||||||
|
---- # #
|
||||||
|
---- #########################################################################
|
||||||
|
|
||||||
|
local protocol_name = ""
|
||||||
|
local sub_protocol_name = ""
|
||||||
|
local bind_ch = 0
|
||||||
|
local module_conf = {}
|
||||||
|
local module_pos = "Internal"
|
||||||
|
local file_ok = 0
|
||||||
|
local done = 0
|
||||||
|
local protocol = 0
|
||||||
|
local sub_protocol = 0
|
||||||
|
local f_seek = 0
|
||||||
|
local channel_names={}
|
||||||
|
local num_search = "Searching"
|
||||||
|
|
||||||
|
local function drawScreenTitle(title)
|
||||||
|
if LCD_W == 480 then
|
||||||
|
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||||
|
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||||
|
else
|
||||||
|
lcd.drawScreenTitle(title, 0, 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bitand(a, b)
|
||||||
|
local result = 0
|
||||||
|
local bitval = 1
|
||||||
|
while a > 0 and b > 0 do
|
||||||
|
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
|
||||||
|
result = result + bitval -- set the current bit
|
||||||
|
end
|
||||||
|
bitval = bitval * 2 -- shift left
|
||||||
|
a = math.floor(a/2) -- shift right
|
||||||
|
b = math.floor(b/2)
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Multi_Draw_LCD(event)
|
||||||
|
local line = 0
|
||||||
|
|
||||||
|
lcd.clear()
|
||||||
|
drawScreenTitle("Multi channels namer")
|
||||||
|
|
||||||
|
--Display settings
|
||||||
|
local lcd_opt = 0
|
||||||
|
if LCD_W == 480 then
|
||||||
|
x_pos = 10
|
||||||
|
y_pos = 32
|
||||||
|
y_inc = 20
|
||||||
|
else
|
||||||
|
x_pos = 0
|
||||||
|
y_pos = 9
|
||||||
|
y_inc = 8
|
||||||
|
lcd_opt = SMLSIZE
|
||||||
|
end
|
||||||
|
|
||||||
|
--Multi Module detection
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
if LCD_W == 480 then
|
||||||
|
lcd.drawText(10,50,"No Multi module configured...", BLINK)
|
||||||
|
else
|
||||||
|
--Draw on LCD_W=128
|
||||||
|
lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
else
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--Channel order
|
||||||
|
if (ch_order == -1) then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--Can't open file MultiChan.txt
|
||||||
|
if file_ok == 0 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
|
||||||
|
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||||
|
if f == nil then return end
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
|
||||||
|
num_search = num_search .. "."
|
||||||
|
if #num_search > 15 then
|
||||||
|
num_search = string.sub(num_search,1,9)
|
||||||
|
end
|
||||||
|
local proto = 0
|
||||||
|
local sub_proto = 0
|
||||||
|
local proto_name = ""
|
||||||
|
local sub_proto_name = ""
|
||||||
|
local channels = ""
|
||||||
|
local nbr_try = 0
|
||||||
|
local nbr_car = 0
|
||||||
|
repeat
|
||||||
|
io.seek(f, f_seek)
|
||||||
|
local data = io.read(f, 100) -- read 100 characters
|
||||||
|
if #data ==0 then
|
||||||
|
f_seek = -1 -- end of file
|
||||||
|
break
|
||||||
|
end
|
||||||
|
proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
|
||||||
|
if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
|
||||||
|
if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
|
||||||
|
protocol_name = proto_name
|
||||||
|
sub_protocol_name = sub_proto_name
|
||||||
|
bind_ch = tonumber(bind_ch)
|
||||||
|
if channels ~= nil then
|
||||||
|
--extract channel names
|
||||||
|
nbr_car = string.find(channels, "\r")
|
||||||
|
if nbr_car == nil then nbr_car = string.find(channels, "\n") end
|
||||||
|
if nbr_car ~= nil then
|
||||||
|
channels = string.sub(channels,1,nbr_car-1)
|
||||||
|
end
|
||||||
|
local i = 5
|
||||||
|
for k in string.gmatch(channels, ",([%w-_ ]+)") do
|
||||||
|
channel_names[i] = k
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f_seek = -1 -- protocol found
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if f_seek ~= -1 then
|
||||||
|
nbr_car = string.find(data, "\n")
|
||||||
|
if nbr_car == nil then nbr_car = string.find(data, "\r") end
|
||||||
|
if nbr_car == nil then
|
||||||
|
f_seek = -1 -- end of file
|
||||||
|
break
|
||||||
|
end
|
||||||
|
f_seek = f_seek + nbr_car -- seek to next line
|
||||||
|
nbr_try = nbr_try + 1
|
||||||
|
end
|
||||||
|
until nbr_try > 20 or f_seek == -1
|
||||||
|
io.close(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
if f_seek ~= -1 then
|
||||||
|
return -- continue searching...
|
||||||
|
end
|
||||||
|
|
||||||
|
--Protocol & Sub_protocol
|
||||||
|
if protocol_name == "" or sub_protocol_name == "" then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
|
||||||
|
return
|
||||||
|
elseif LCD_W > 128 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
else
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
text1=""
|
||||||
|
text2=""
|
||||||
|
for i,v in ipairs(channel_names) do
|
||||||
|
if i<=8 then
|
||||||
|
if i==1 then
|
||||||
|
text1 = v
|
||||||
|
else
|
||||||
|
text1=text1 .. "," .. v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if i==9 then
|
||||||
|
text2 = v
|
||||||
|
else
|
||||||
|
text2=text2 .. "," .. v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if LCD_W > 128 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
if text2 ~= "" then
|
||||||
|
lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if event ~= EVT_VIRTUAL_ENTER and done == 0 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"<ENT> Save", lcd_opt + INVERS + BLINK)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
local output, nbr
|
||||||
|
if done == 0 then
|
||||||
|
for i,v in ipairs(channel_names) do
|
||||||
|
output = model.getOutput(i-1)
|
||||||
|
output["name"] = v
|
||||||
|
model.setOutput(i-1,output)
|
||||||
|
nbr = i
|
||||||
|
end
|
||||||
|
for i = nbr, 15 do
|
||||||
|
output = model.getOutput(i)
|
||||||
|
output["name"] = "n-a"
|
||||||
|
model.setOutput(i,output)
|
||||||
|
end
|
||||||
|
if bind_ch == 1 then
|
||||||
|
output = model.getOutput(15)
|
||||||
|
output["name"] = "BindCH"
|
||||||
|
model.setOutput(15,output)
|
||||||
|
end
|
||||||
|
done = 1
|
||||||
|
end
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Init
|
||||||
|
local function Multi_Init()
|
||||||
|
module_conf = model.getModule(0)
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
module_pos = "External"
|
||||||
|
module_conf = model.getModule(1)
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protocol = module_conf["protocol"]
|
||||||
|
sub_protocol = module_conf["subProtocol"]
|
||||||
|
|
||||||
|
--Exceptions on first 4 channels...
|
||||||
|
local stick_names = { "Rud", "Ele", "Thr", "Ail" }
|
||||||
|
if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
|
||||||
|
stick_names[2] = "n-a"
|
||||||
|
stick_names[4] = "n-a"
|
||||||
|
elseif protocol == 43 then -- Traxxas
|
||||||
|
stick_names[2] = "Aux4"
|
||||||
|
stick_names[4] = "Aux3"
|
||||||
|
elseif protocol == 48 then -- V761
|
||||||
|
stick_names[4] = "n-a"
|
||||||
|
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
|
||||||
|
stick_names[1] = "n-a"
|
||||||
|
stick_names[2] = "n-a"
|
||||||
|
end
|
||||||
|
|
||||||
|
--Determine fist 4 channels order
|
||||||
|
local ch_order=module_conf["channelsOrder"]
|
||||||
|
if (ch_order == -1) then
|
||||||
|
channel_names[1] = stick_names[defaultChannel(0)+1]
|
||||||
|
channel_names[2] = stick_names[defaultChannel(1)+1]
|
||||||
|
channel_names[3] = stick_names[defaultChannel(2)+1]
|
||||||
|
channel_names[4] = stick_names[defaultChannel(3)+1]
|
||||||
|
else
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[4]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[2]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[3]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[1]
|
||||||
|
end
|
||||||
|
--Check MultiChan.txt
|
||||||
|
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||||
|
if f == nil then return end
|
||||||
|
file_ok = 1
|
||||||
|
io.close(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main
|
||||||
|
local function Multi_Run(event)
|
||||||
|
if event == nil then
|
||||||
|
error("Cannot be run as a model script!")
|
||||||
|
return 2
|
||||||
|
else
|
||||||
|
Multi_Draw_LCD(event)
|
||||||
|
if event == EVT_VIRTUAL_EXIT then
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return { init=Multi_Init, run=Multi_Run }
|
157
radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
|
||||||
|
1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
|
||||||
|
1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
|
||||||
|
1,3,Flysky,V912,1,BtmBtn,TopBtn
|
||||||
|
1,4,Flysky,CX20,0,CH5,CH6,CH7
|
||||||
|
28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
53,0,Flyzone,FZ-410,0
|
||||||
|
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
||||||
|
2,1,Hubsan,H301,0,RTH,Light,Stab,Video
|
||||||
|
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
|
||||||
|
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
|
||||||
|
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
||||||
|
37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
|
||||||
|
37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
|
||||||
|
37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
|
||||||
|
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
|
||||||
|
3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
|
||||||
|
3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
|
||||||
|
67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
67,1,FrSkyL,LR12_6CH,0,CH5,CH6
|
||||||
|
15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||||
|
15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
|
||||||
|
15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||||
|
64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
|
||||||
|
64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
55,1,FrSkyRX,CloneTX,0
|
||||||
|
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
|
||||||
|
68,0,Skyartec,Std,0,CH5,CH6,CH7
|
||||||
|
7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
|
||||||
|
7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
7,3,Devo,6CH,0,CH5,CH6
|
||||||
|
7,4,Devo,7CH,0,CH5,CH6,CH7
|
||||||
|
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
|
||||||
|
30,1,WK2x01,WK2401,0
|
||||||
|
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
|
||||||
|
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
|
||||||
|
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
|
||||||
|
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
|
||||||
|
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||||
|
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
|
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
|
||||||
|
24,0,Assan,Std,0,CH5,CH6,CH7,CH8
|
||||||
|
14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
|
||||||
|
14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
|
||||||
|
14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
|
||||||
|
14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||||
|
14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||||
|
59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
|
||||||
|
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
|
||||||
|
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
|
||||||
|
34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
|
||||||
|
13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
|
||||||
|
12,0,CX10,Green,1,Flip,Rate
|
||||||
|
12,1,CX10,Blue,1,Flip,Rate,Pict,Video
|
||||||
|
12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
|
||||||
|
12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
|
||||||
|
12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
|
||||||
|
12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
|
||||||
|
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
|
||||||
|
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
|
||||||
|
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
|
||||||
|
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
|
||||||
|
16,0,ESKY,Std,0,Gyro,Pitch
|
||||||
|
16,1,ESKY,ET4,0,Gyro,Pitch
|
||||||
|
35,0,ESKY150,4CH,0
|
||||||
|
35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
|
||||||
|
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
||||||
|
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
||||||
|
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
|
||||||
|
32,0,GW008,FY326,1,Flip
|
||||||
|
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
|
||||||
|
36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||||
|
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
|
||||||
|
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||||
|
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||||
|
26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
|
18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
|
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
|
||||||
|
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
|
||||||
|
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
|
||||||
|
44,0,NCC1701,Std,1,Warp
|
||||||
|
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
|
||||||
|
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
|
||||||
|
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
|
||||||
|
29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||||
|
29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||||
|
31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
|
||||||
|
31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
|
||||||
|
31,2,Q303,CX10D,1,Arm,Flip
|
||||||
|
31,3,Q303,CX10WD,1,Arm,Flip
|
||||||
|
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
|
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
|
11,0,SLT,V1,0,Gear,Pitch
|
||||||
|
11,1,SLT,V2,0,CH5,CH6,CH7,CH8
|
||||||
|
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
|
||||||
|
11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
|
||||||
|
11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
|
||||||
|
10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
|
||||||
|
10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
|
||||||
|
5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
|
||||||
|
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
|
||||||
|
61,0,Tiger,Std,1,Flip,Light
|
||||||
|
46,0,V911s,Std,1,Calib
|
||||||
|
46,1,E119,Std,1,Calib
|
||||||
|
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||||
|
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||||
|
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
|
||||||
|
8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
|
||||||
|
65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
|
||||||
|
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
|
19,0,Shenqi,Cycle,1
|
||||||
|
4,1,Hisky,HK310,0,Aux
|
||||||
|
43,0,Traxxas,6519,0
|
||||||
|
52,0,ZSX,280,1,Light
|
||||||
|
48,0,V761,Std,1,Gyro
|
||||||
|
49,0,KF606,Std,1,Trim
|
||||||
|
47,0,GD00x,V1,1,Trim,LED,Rate
|
||||||
|
47,1,GD00x,V2,1,Trim,LED,Rate
|
||||||
|
58,0,FX816,P38,1
|
302
radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
|
||||||
|
local toolName = "TNS|Multi chan namer|TNE"
|
||||||
|
|
||||||
|
---- #########################################################################
|
||||||
|
---- # #
|
||||||
|
---- # Copyright (C) OpenTX #
|
||||||
|
-----# #
|
||||||
|
---- # 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. #
|
||||||
|
---- # #
|
||||||
|
---- #########################################################################
|
||||||
|
|
||||||
|
local protocol_name = ""
|
||||||
|
local sub_protocol_name = ""
|
||||||
|
local bind_ch = 0
|
||||||
|
local module_conf = {}
|
||||||
|
local module_pos = "Internal"
|
||||||
|
local file_ok = 0
|
||||||
|
local done = 0
|
||||||
|
local protocol = 0
|
||||||
|
local sub_protocol = 0
|
||||||
|
local f_seek = 0
|
||||||
|
local channel_names={}
|
||||||
|
local num_search = "Searching"
|
||||||
|
|
||||||
|
local function drawScreenTitle(title)
|
||||||
|
if LCD_W == 480 then
|
||||||
|
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||||
|
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||||
|
else
|
||||||
|
lcd.drawScreenTitle(title, 0, 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bitand(a, b)
|
||||||
|
local result = 0
|
||||||
|
local bitval = 1
|
||||||
|
while a > 0 and b > 0 do
|
||||||
|
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
|
||||||
|
result = result + bitval -- set the current bit
|
||||||
|
end
|
||||||
|
bitval = bitval * 2 -- shift left
|
||||||
|
a = math.floor(a/2) -- shift right
|
||||||
|
b = math.floor(b/2)
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Multi_Draw_LCD(event)
|
||||||
|
local line = 0
|
||||||
|
|
||||||
|
lcd.clear()
|
||||||
|
drawScreenTitle("Multi channels namer")
|
||||||
|
|
||||||
|
--Display settings
|
||||||
|
local lcd_opt = 0
|
||||||
|
if LCD_W == 480 then
|
||||||
|
x_pos = 10
|
||||||
|
y_pos = 32
|
||||||
|
y_inc = 20
|
||||||
|
else
|
||||||
|
x_pos = 0
|
||||||
|
y_pos = 9
|
||||||
|
y_inc = 8
|
||||||
|
lcd_opt = SMLSIZE
|
||||||
|
end
|
||||||
|
|
||||||
|
--Multi Module detection
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
if LCD_W == 480 then
|
||||||
|
lcd.drawText(10,50,"No Multi module configured...", BLINK)
|
||||||
|
else
|
||||||
|
--Draw on LCD_W=128
|
||||||
|
lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
else
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--Channel order
|
||||||
|
if (ch_order == -1) then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--Can't open file MultiChan.txt
|
||||||
|
if file_ok == 0 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
|
||||||
|
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||||
|
if f == nil then return end
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
|
||||||
|
num_search = num_search .. "."
|
||||||
|
if #num_search > 15 then
|
||||||
|
num_search = string.sub(num_search,1,9)
|
||||||
|
end
|
||||||
|
local proto = 0
|
||||||
|
local sub_proto = 0
|
||||||
|
local proto_name = ""
|
||||||
|
local sub_proto_name = ""
|
||||||
|
local channels = ""
|
||||||
|
local nbr_try = 0
|
||||||
|
local nbr_car = 0
|
||||||
|
repeat
|
||||||
|
io.seek(f, f_seek)
|
||||||
|
local data = io.read(f, 100) -- read 100 characters
|
||||||
|
if #data ==0 then
|
||||||
|
f_seek = -1 -- end of file
|
||||||
|
break
|
||||||
|
end
|
||||||
|
proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
|
||||||
|
if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
|
||||||
|
if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
|
||||||
|
protocol_name = proto_name
|
||||||
|
sub_protocol_name = sub_proto_name
|
||||||
|
bind_ch = tonumber(bind_ch)
|
||||||
|
if channels ~= nil then
|
||||||
|
--extract channel names
|
||||||
|
nbr_car = string.find(channels, "\r")
|
||||||
|
if nbr_car == nil then nbr_car = string.find(channels, "\n") end
|
||||||
|
if nbr_car ~= nil then
|
||||||
|
channels = string.sub(channels,1,nbr_car-1)
|
||||||
|
end
|
||||||
|
local i = 5
|
||||||
|
for k in string.gmatch(channels, ",([%w-_ ]+)") do
|
||||||
|
channel_names[i] = k
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f_seek = -1 -- protocol found
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if f_seek ~= -1 then
|
||||||
|
nbr_car = string.find(data, "\n")
|
||||||
|
if nbr_car == nil then nbr_car = string.find(data, "\r") end
|
||||||
|
if nbr_car == nil then
|
||||||
|
f_seek = -1 -- end of file
|
||||||
|
break
|
||||||
|
end
|
||||||
|
f_seek = f_seek + nbr_car -- seek to next line
|
||||||
|
nbr_try = nbr_try + 1
|
||||||
|
end
|
||||||
|
until nbr_try > 20 or f_seek == -1
|
||||||
|
io.close(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
if f_seek ~= -1 then
|
||||||
|
return -- continue searching...
|
||||||
|
end
|
||||||
|
|
||||||
|
--Protocol & Sub_protocol
|
||||||
|
if protocol_name == "" or sub_protocol_name == "" then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
|
||||||
|
return
|
||||||
|
elseif LCD_W > 128 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
else
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
text1=""
|
||||||
|
text2=""
|
||||||
|
for i,v in ipairs(channel_names) do
|
||||||
|
if i<=8 then
|
||||||
|
if i==1 then
|
||||||
|
text1 = v
|
||||||
|
else
|
||||||
|
text1=text1 .. "," .. v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if i==9 then
|
||||||
|
text2 = v
|
||||||
|
else
|
||||||
|
text2=text2 .. "," .. v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if LCD_W > 128 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
if text2 ~= "" then
|
||||||
|
lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if event ~= EVT_VIRTUAL_ENTER and done == 0 then
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"<ENT> Save", lcd_opt + INVERS + BLINK)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
local output, nbr
|
||||||
|
if done == 0 then
|
||||||
|
for i,v in ipairs(channel_names) do
|
||||||
|
output = model.getOutput(i-1)
|
||||||
|
output["name"] = v
|
||||||
|
model.setOutput(i-1,output)
|
||||||
|
nbr = i
|
||||||
|
end
|
||||||
|
for i = nbr, 15 do
|
||||||
|
output = model.getOutput(i)
|
||||||
|
output["name"] = "n-a"
|
||||||
|
model.setOutput(i,output)
|
||||||
|
end
|
||||||
|
if bind_ch == 1 then
|
||||||
|
output = model.getOutput(15)
|
||||||
|
output["name"] = "BindCH"
|
||||||
|
model.setOutput(15,output)
|
||||||
|
end
|
||||||
|
done = 1
|
||||||
|
end
|
||||||
|
lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
|
||||||
|
line = line + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Init
|
||||||
|
local function Multi_Init()
|
||||||
|
module_conf = model.getModule(0)
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
module_pos = "External"
|
||||||
|
module_conf = model.getModule(1)
|
||||||
|
if module_conf["Type"] ~= 6 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protocol = module_conf["protocol"]
|
||||||
|
sub_protocol = module_conf["subProtocol"]
|
||||||
|
|
||||||
|
--Exceptions on first 4 channels...
|
||||||
|
local stick_names = { "Rud", "Ele", "Thr", "Ail" }
|
||||||
|
if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
|
||||||
|
stick_names[2] = "n-a"
|
||||||
|
stick_names[4] = "n-a"
|
||||||
|
elseif protocol == 43 then -- Traxxas
|
||||||
|
stick_names[2] = "Aux4"
|
||||||
|
stick_names[4] = "Aux3"
|
||||||
|
elseif protocol == 48 then -- V761
|
||||||
|
stick_names[4] = "n-a"
|
||||||
|
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
|
||||||
|
stick_names[1] = "n-a"
|
||||||
|
stick_names[2] = "n-a"
|
||||||
|
end
|
||||||
|
|
||||||
|
--Determine fist 4 channels order
|
||||||
|
local ch_order=module_conf["channelsOrder"]
|
||||||
|
if (ch_order == -1) then
|
||||||
|
channel_names[1] = stick_names[defaultChannel(0)+1]
|
||||||
|
channel_names[2] = stick_names[defaultChannel(1)+1]
|
||||||
|
channel_names[3] = stick_names[defaultChannel(2)+1]
|
||||||
|
channel_names[4] = stick_names[defaultChannel(3)+1]
|
||||||
|
else
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[4]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[2]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[3]
|
||||||
|
ch_order = math.floor(ch_order/4)
|
||||||
|
channel_names[bitand(ch_order,3)+1] = stick_names[1]
|
||||||
|
end
|
||||||
|
--Check MultiChan.txt
|
||||||
|
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||||
|
if f == nil then return end
|
||||||
|
file_ok = 1
|
||||||
|
io.close(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main
|
||||||
|
local function Multi_Run(event)
|
||||||
|
if event == nil then
|
||||||
|
error("Cannot be run as a model script!")
|
||||||
|
return 2
|
||||||
|
else
|
||||||
|
Multi_Draw_LCD(event)
|
||||||
|
if event == EVT_VIRTUAL_EXIT then
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return { init=Multi_Init, run=Multi_Run }
|
|
@ -381,9 +381,12 @@ endif()
|
||||||
|
|
||||||
add_definitions(-DPOPUP_LEVEL=${POPUP_LEVEL})
|
add_definitions(-DPOPUP_LEVEL=${POPUP_LEVEL})
|
||||||
|
|
||||||
if(BOOTLOADER)
|
if(INTERNAL_MODULE_MULTI)
|
||||||
add_definitions(-DBOOTLOADER)
|
set(DEFAULT_TEMPLATE_SETUP 21 CACHE STRING "")
|
||||||
endif(BOOTLOADER)
|
else()
|
||||||
|
set(DEFAULT_TEMPLATE_SETUP 0 CACHE STRING "")
|
||||||
|
endif()
|
||||||
|
add_definitions(-DDEFAULT_TEMPLATE_SETUP=${DEFAULT_TEMPLATE_SETUP})
|
||||||
|
|
||||||
set(SRC
|
set(SRC
|
||||||
${SRC}
|
${SRC}
|
||||||
|
@ -444,7 +447,6 @@ endif()
|
||||||
|
|
||||||
set(SRC ${SRC} ${FIRMWARE_SRC})
|
set(SRC ${SRC} ${FIRMWARE_SRC})
|
||||||
|
|
||||||
|
|
||||||
##### firmware target #####
|
##### firmware target #####
|
||||||
|
|
||||||
option(FIRMWARE_TARGET "Configure Firmware target (can be turned of for compiling Companion only)" ON)
|
option(FIRMWARE_TARGET "Configure Firmware target (can be turned of for compiling Companion only)" ON)
|
||||||
|
|
Before Width: | Height: | Size: 601 B After Width: | Height: | Size: 310 B |
BIN
radio/src/bitmaps/480x272/mask_txbat_charging.png
Executable file → Normal file
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 553 B |
|
@ -315,7 +315,7 @@ void Bluetooth::wakeup(void)
|
||||||
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
|
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
*cur++ = char2lower(zchar2char(g_eeGeneral.bluetoothName[i]));
|
*cur++ = char2lower(g_eeGeneral.bluetoothName[i]);
|
||||||
}
|
}
|
||||||
*cur = '\0';
|
*cur = '\0';
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ void Bluetooth::wakeup()
|
||||||
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
|
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
*cur++ = char2lower(zchar2char(g_eeGeneral.bluetoothName[i]));
|
*cur++ = char2lower(g_eeGeneral.bluetoothName[i]);
|
||||||
}
|
}
|
||||||
*cur = '\0';
|
*cur = '\0';
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
#define _BUZZER_H_
|
#define _BUZZER_H_
|
||||||
|
|
||||||
#if defined(BUZZER)
|
#if defined(BUZZER)
|
||||||
extern uint8_t g_beepCnt;
|
|
||||||
extern uint8_t beepAgain;
|
|
||||||
extern uint8_t beepAgainOrig;
|
extern uint8_t beepAgainOrig;
|
||||||
extern uint8_t beepOn;
|
extern uint8_t beepOn;
|
||||||
extern bool warble;
|
extern bool warble;
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
#include "opentx.h"
|
#include "opentx.h"
|
||||||
|
|
||||||
uint8_t s_curveChan;
|
|
||||||
int8_t * curveEnd[MAX_CURVES];
|
int8_t * curveEnd[MAX_CURVES];
|
||||||
|
|
||||||
void loadCurves()
|
void loadCurves()
|
||||||
|
@ -120,7 +119,7 @@ bool isCurveUsed(uint8_t index)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CUSTOM_POINT_X(points, count, idx) ((idx)==0 ? -100 : (((idx)==(count)-1) ? 100 : points[(count)+(idx)-1]))
|
#define CUSTOM_POINT_X(points, count, idx) ((idx)==0 ? -100 : (((idx)==(count)-1) ? 100 : points[(count)+(idx)-1]))
|
||||||
int32_t compute_tangent(CurveHeader * crv, int8_t * points, int i)
|
int32_t compute_tangent(CurveHeader * crv, const int8_t * points, int i)
|
||||||
{
|
{
|
||||||
int32_t m=0;
|
int32_t m=0;
|
||||||
uint8_t num_points = crv->points + 5;
|
uint8_t num_points = crv->points + 5;
|
||||||
|
@ -240,7 +239,7 @@ int intpol(int x, uint8_t idx) // -100, -75, -50, -25, 0 ,25 ,50, 75, 100
|
||||||
int8_t * points = curveAddress(idx);
|
int8_t * points = curveAddress(idx);
|
||||||
uint8_t count = crv.points+5;
|
uint8_t count = crv.points+5;
|
||||||
bool custom = (crv.type == CURVE_TYPE_CUSTOM);
|
bool custom = (crv.type == CURVE_TYPE_CUSTOM);
|
||||||
int16_t erg = 0;
|
int16_t erg;
|
||||||
|
|
||||||
x += RESXu;
|
x += RESXu;
|
||||||
|
|
||||||
|
@ -339,11 +338,6 @@ int applyCustomCurve(int x, uint8_t idx)
|
||||||
return intpol(x, idx);
|
return intpol(x, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
point_t getPoint(uint8_t index)
|
|
||||||
{
|
|
||||||
return getPoint(s_curveChan, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
point_t getPoint(uint8_t curveIndex, uint8_t index)
|
point_t getPoint(uint8_t curveIndex, uint8_t index)
|
||||||
{
|
{
|
||||||
point_t result = {0, 0};
|
point_t result = {0, 0};
|
||||||
|
@ -363,7 +357,14 @@ point_t getPoint(uint8_t curveIndex, uint8_t index)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(COLORLCD)
|
||||||
|
point_t getPoint(uint8_t index)
|
||||||
|
{
|
||||||
|
return getPoint(s_currIdxSubMenu, index);
|
||||||
|
}
|
||||||
|
|
||||||
int applyCurrentCurve(int x)
|
int applyCurrentCurve(int x)
|
||||||
{
|
{
|
||||||
return applyCustomCurve(x, s_curveChan);
|
return applyCustomCurve(x, s_currIdxSubMenu);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -208,6 +208,16 @@ enum TrainerMode {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(RADIO_FAMILY_T16) || (defined(RADIO_T12) && defined(INTERNAL_MODULE_MULTI)) || defined(ALLOW_TRAINER_MULTI)
|
||||||
|
#define TRAINER_MODE_MAX() TRAINER_MODE_MULTI
|
||||||
|
#elif defined(BLUETOOTH)
|
||||||
|
#define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE_BLUETOOTH
|
||||||
|
#elif defined(PCBX7) || defined(PCBXLITE)
|
||||||
|
#define TRAINER_MODE_MAX() TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE
|
||||||
|
#else
|
||||||
|
#define TRAINER_MODE_MAX() HAS_WIRELESS_TRAINER_HARDWARE() ? TRAINER_MODE_MASTER_BATTERY_COMPARTMENT : TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HARDWARE_INTERNAL_MODULE)
|
#if defined(HARDWARE_INTERNAL_MODULE)
|
||||||
#define IS_INTERNAL_MODULE_ENABLED() (g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE)
|
#define IS_INTERNAL_MODULE_ENABLED() (g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "dataconstants.h"
|
#include "dataconstants.h"
|
||||||
#include "definitions.h"
|
#include "definitions.h"
|
||||||
#include "opentx_types.h"
|
#include "opentx_types.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
#if defined(PCBTARANIS)
|
#if defined(PCBTARANIS)
|
||||||
#define N_TARANIS_FIELD(x)
|
#define N_TARANIS_FIELD(x)
|
||||||
|
@ -331,10 +332,10 @@ PACK(struct TelemetrySensor {
|
||||||
NOBACKUP(uint16_t persistentValue);
|
NOBACKUP(uint16_t persistentValue);
|
||||||
} NAME(id1) FUNC(select_id1);
|
} NAME(id1) FUNC(select_id1);
|
||||||
union {
|
union {
|
||||||
PACK(struct {
|
NOBACKUP(PACK(struct {
|
||||||
uint8_t physID:5;
|
uint8_t physID:5;
|
||||||
uint8_t rxIndex:3; // 1 bit for module index, 2 bits for receiver index
|
uint8_t rxIndex:3; // 1 bit for module index, 2 bits for receiver index
|
||||||
}) frskyInstance;
|
}) frskyInstance);
|
||||||
uint8_t instance;
|
uint8_t instance;
|
||||||
NOBACKUP(uint8_t formula);
|
NOBACKUP(uint8_t formula);
|
||||||
} NAME(id2) FUNC(select_id2);
|
} NAME(id2) FUNC(select_id2);
|
||||||
|
@ -513,8 +514,6 @@ PACK(struct ModuleData {
|
||||||
* Model structure
|
* Model structure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef uint16_t BeepANACenter;
|
|
||||||
|
|
||||||
#if LEN_BITMAP_NAME > 0
|
#if LEN_BITMAP_NAME > 0
|
||||||
#define MODEL_HEADER_BITMAP_FIELD NOBACKUP(char bitmap[LEN_BITMAP_NAME]);
|
#define MODEL_HEADER_BITMAP_FIELD NOBACKUP(char bitmap[LEN_BITMAP_NAME]);
|
||||||
#else
|
#else
|
||||||
|
@ -697,7 +696,8 @@ PACK(struct TrainerData {
|
||||||
|
|
||||||
#if defined(PCBHORUS) || defined(PCBNV14)
|
#if defined(PCBHORUS) || defined(PCBNV14)
|
||||||
#define EXTRA_GENERAL_FIELDS \
|
#define EXTRA_GENERAL_FIELDS \
|
||||||
NOBACKUP(uint8_t auxSerialMode); \
|
NOBACKUP(uint8_t auxSerialMode:4); \
|
||||||
|
NOBACKUP(uint8_t aux2SerialMode:4); \
|
||||||
swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \
|
swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \
|
||||||
uint16_t potsConfig ARRAY(2,struct_potConfig,nullptr); /* two bits per pot */ \
|
uint16_t potsConfig ARRAY(2,struct_potConfig,nullptr); /* two bits per pot */ \
|
||||||
uint8_t slidersConfig ARRAY(1,struct_sliderConfig,nullptr); /* 1 bit per slider */ \
|
uint8_t slidersConfig ARRAY(1,struct_sliderConfig,nullptr); /* 1 bit per slider */ \
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
extern volatile uint32_t g_tmr10ms;
|
extern volatile uint32_t g_tmr10ms;
|
||||||
|
|
||||||
uint8_t auxSerialTracesEnabled();
|
uint8_t auxSerialTracesEnabled();
|
||||||
|
uint8_t aux2SerialTracesEnabled();
|
||||||
|
|
||||||
#if defined(SIMU)
|
#if defined(SIMU)
|
||||||
typedef void (*traceCallbackFunc)(const char * text);
|
typedef void (*traceCallbackFunc)(const char * text);
|
||||||
|
|
Before Width: | Height: | Size: 155 B After Width: | Height: | Size: 143 B |
Before Width: | Height: | Size: 155 B After Width: | Height: | Size: 150 B |
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 190 B |
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 250 B |