feat: Interactive/progressive preflight checklist (#3564)

* initial version of clickable checklist

* do not display checkboxes for empty lines if checklist is shorter than screen size

* remove checklist exit after completing it
cannot exit menu from menuTextView as level above there is while loop that cannot be stopped from thic place in code

* menu entry to enable and disable interactive checklist

* only when complete interactive checklist is closed

* config updated & not display checkboxes when entered from "View Notes"

* add setup entry for colorlcd

* do not make interactive checkist when loaded from menu

* fix datastruct size after merge

* Companion support for interactive checklist

* mark checklist lines as non-checkable with '=' for B&W radios

* Process only items visible on screen
This is also crucial when it comes to analyse non-checkable items on a checklist, as in this way there is no need to load non-visible items from SD-card

* WIP fix merge problems

* update yaml datastructs

* restore most functionalities for interactive check lists on color LCD radios
currently no automatic line wrapping and you can always exit the checklist, even when it is not fully done

* finalise interactive checklists for color LCD

* fix: rebase/merge issues

* fix: model setup checklist section

* fix: fix 212 model setup

* Re-work of the some of the color lcd checklist code (#3787)

* Move checklist logic to sub-class.
Show model name instead of file name in title, show 'Preflight checks' in title2 for checklist.
Handle long line wrapping of text.
Don't indent lines without checkbox.
Add 'RTN' button when done.

* Code cleanup.

* Simplify code by storing a list of checkboxes instead of scanning LVGL object hierarchy.

* Indent checkboxes to make touch activation easier.
Keep 'RTN' button visible so last checkbox is further from bottom of screen (for touch activation).
'RTN' button is disabled until checklist complete.

* Add checkbox class constructor for preflight checks.

* Fix checkbox size.

---------

Co-authored-by: Piotr Rzeszut <piotrrze@gmail.com>
Co-authored-by: 3djc <lesitewebdejc@hotmail.com>
Co-authored-by: philmoz <philmoz@users.noreply.github.com>
Co-authored-by: Phil Mitchell <phil.a.mitchell@gmail.com>
This commit is contained in:
Malte Langermann
2023-08-29 19:18:39 +10:00
committed by GitHub
co-authored by Piotr Rzeszut 3djc philmoz Phil Mitchell
parent ceba62650e
commit 06712d9b97
44 changed files with 434 additions and 72 deletions
@@ -920,6 +920,7 @@ Node convert<ModelData>::encode(const ModelData& rhs)
node["extendedLimits"] = (int)rhs.extendedLimits;
node["extendedTrims"] = (int)rhs.extendedTrims;
node["throttleReversed"] = (int)rhs.throttleReversed;
node["checklistInteractive"] = (int)rhs.checklistInteractive;
for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
if (!rhs.flightModeData[i].isEmpty(i)) {
@@ -1201,6 +1202,7 @@ bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
node["extendedLimits"] >> rhs.extendedLimits;
node["extendedTrims"] >> rhs.extendedTrims;
node["throttleReversed"] >> rhs.throttleReversed;
node["checklistInteractive"] >> rhs.checklistInteractive;
node["flightModeData"] >> rhs.flightModeData;
node["mixData"] >> rhs.mixData;
+1
View File
@@ -145,6 +145,7 @@ class ModelData {
bool extendedLimits; // TODO xml
bool extendedTrims;
bool throttleReversed;
bool checklistInteractive;
FlightModeData flightModeData[CPN_MAX_FLIGHT_MODES];
MixData mixData[CPN_MAX_MIXERS];
LimitData limitData[CPN_MAX_CHNOUT];
+7
View File
@@ -1797,6 +1797,7 @@ void SetupPanel::update()
ui->extendedLimits->setChecked(model->extendedLimits);
ui->extendedTrims->setChecked(model->extendedTrims);
ui->displayText->setChecked(model->displayChecklist);
ui->checklistInteractive->setChecked(model->checklistInteractive);
ui->gfEnabled->setChecked(!model->noGlobalFunctions);
ui->jitterFilter->setCurrentIndex(model->jitterFilter);
@@ -1944,6 +1945,12 @@ void SetupPanel::on_displayText_toggled(bool checked)
emit modified();
}
void SetupPanel::on_checklistInteractive_toggled(bool checked)
{
model->checklistInteractive = checked;
emit modified();
}
void SetupPanel::on_gfEnabled_toggled(bool checked)
{
model->noGlobalFunctions = !checked;
+1
View File
@@ -191,6 +191,7 @@ class SetupPanel : public ModelPanel
void on_customThrottleWarningPosition_valueChanged(int value);
void on_throttleReverse_toggled(bool checked);
void on_displayText_toggled(bool checked);
void on_checklistInteractive_toggled(bool checked);
void on_gfEnabled_toggled(bool checked);
void on_image_currentIndexChanged(int index);
void on_trimIncrement_currentIndexChanged(int index);
+10
View File
@@ -579,6 +579,16 @@
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QCheckBox" name="checklistInteractive">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Interactive Checklist</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="label_jitterFilter">
<property name="font">
+2 -1
View File
@@ -678,7 +678,8 @@ PACK(struct ModelData {
uint8_t enableCustomThrottleWarning:1;
uint8_t disableTelemetryWarning:1;
uint8_t showInstanceIds:1;
uint8_t spare3:5 SKIP;
uint8_t checklistInteractive:1;
uint8_t spare3:4 SKIP; // padding to 8-bit aligment
int8_t customThrottleWarningPosition;
BeepANACenter beepANACenter;
MixData mixData[MAX_MIXERS] NO_IDX;
+6
View File
@@ -99,6 +99,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH,
ITEM_MODEL_SETUP_PREFLIGHT_LABEL,
ITEM_MODEL_SETUP_CHECKLIST_DISPLAY,
ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE,
ITEM_MODEL_SETUP_THROTTLE_WARNING,
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING,
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING_VALUE,
@@ -584,6 +585,7 @@ void menuModelSetup(event_t event)
0, // Preflight section
PREFLIGHT_ROW(0), // Checklist
PREFLIGHT_ROW(0), // Checklist interactive
PREFLIGHT_ROW(0), // Throttle warning
PREFLIGHT_ROW(0), // Custom position for throttle warning enable
PREFLIGHT_ROW(0), // Custom position for throttle warning value
@@ -923,6 +925,10 @@ void menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_CHECKLIST_DISPLAY:
g_model.displayChecklist = editCheckBox(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
break;
case ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE:
g_model.checklistInteractive = editCheckBox(g_model.checklistInteractive, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST_INTERACTIVE, attr, event);
break;
case ITEM_MODEL_SETUP_THROTTLE_WARNING:
g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLE_WARNING, attr, event);
+6
View File
@@ -87,6 +87,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH,
ITEM_MODEL_SETUP_PREFLIGHT_LABEL,
ITEM_MODEL_SETUP_CHECKLIST_DISPLAY,
ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE,
ITEM_MODEL_SETUP_THROTTLE_WARNING,
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING,
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING_VALUE,
@@ -528,6 +529,7 @@ void menuModelSetup(event_t event)
0, // Preflight section
PREFLIGHT_ROW(0), // Checklist
PREFLIGHT_ROW(0), // Checklist interactive
PREFLIGHT_ROW(0), // Throttle warning
PREFLIGHT_ROW(0), // Custom position for throttle warning enable
PREFLIGHT_ROW(0), // Custom position for throttle warning value
@@ -819,6 +821,10 @@ void menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_CHECKLIST_DISPLAY:
g_model.displayChecklist = editCheckBox(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
break;
case ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE:
g_model.checklistInteractive = editCheckBox(g_model.checklistInteractive, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST_INTERACTIVE, attr, event);
break;
case ITEM_MODEL_SETUP_THROTTLE_WARNING:
g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLE_WARNING, attr, event);
+12 -1
View File
@@ -118,7 +118,18 @@ PreflightChecks::PreflightChecks() : Page(ICON_MODEL_SETUP)
// Display checklist
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_CHECKLIST, 0, COLOR_THEME_PRIMARY1);
new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.displayChecklist));
auto chkList = new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.displayChecklist));
// Interactive checklist
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_CHECKLIST_INTERACTIVE, 0, COLOR_THEME_PRIMARY1);
auto interactiveChkList = new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.checklistInteractive));
if(!chkList->getValue())
interactiveChkList->disable();
chkList->setSetValueHandler([=](int32_t newValue) {
g_model.displayChecklist = newValue; SET_DIRTY();
(g_model.displayChecklist)?interactiveChkList->enable():interactiveChkList->disable();
});
// Throttle warning
line = form->newLine(&grid);
+50 -3
View File
@@ -82,7 +82,7 @@ typedef struct {
// Choice
lv_style_t choice_main;
// Checkbox
// Toggle switch
lv_style_t switch_knob;
// Table
@@ -103,6 +103,10 @@ typedef struct {
lv_style_t progress_main;
lv_style_t progress_indicator;
// Check Box
lv_style_t cb_marker;
lv_style_t cb_marker_checked;
} my_theme_styles_t;
/**********************
@@ -237,7 +241,7 @@ static void style_init(void)
lv_style_init(&styles.bg_color_transparent);
lv_style_set_bg_opa(&styles.bg_color_transparent, LV_OPA_TRANSP);
// Checkbox and slider knob rounding
// Toggle switch and slider knob rounding
lv_style_init(&styles.circle);
lv_style_set_radius(&styles.circle, LV_RADIUS_CIRCLE);
@@ -265,7 +269,7 @@ static void style_init(void)
lv_style_init(&styles.anim_fast);
lv_style_set_anim_time(&styles.anim_fast, 120);
// Checkbox
// Toggle switch
lv_style_init(&styles.switch_knob);
lv_style_set_pad_all(&styles.switch_knob, -3);
lv_style_set_bg_opa(&styles.switch_knob, LV_OPA_100);
@@ -315,6 +319,14 @@ static void style_init(void)
// Text align
lv_style_init(&styles.text_align_right);
lv_style_set_text_align(&styles.text_align_right, LV_TEXT_ALIGN_RIGHT);
// Check Box
lv_style_init(&styles.cb_marker);
lv_style_set_bg_opa(&styles.cb_marker, LV_OPA_COVER);
lv_style_set_pad_all(&styles.cb_marker, lv_disp_dpx(theme.disp, 3));
lv_style_init(&styles.cb_marker_checked);
lv_style_set_bg_img_src(&styles.cb_marker_checked, LV_SYMBOL_OK);
lv_style_set_text_font(&styles.cb_marker_checked, theme.font_small);
}
// Always update colors in case theme changes
@@ -377,6 +389,12 @@ static void style_init(void)
lv_style_set_bg_color(&styles.progress_main, makeLvColor(COLOR_THEME_SECONDARY2));
lv_style_set_bg_color(&styles.progress_indicator, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_border_color(&styles.cb_marker, makeLvColor(COLOR_THEME_SECONDARY2));
lv_style_set_bg_color(&styles.cb_marker, makeLvColor(COLOR_THEME_PRIMARY2));
lv_style_set_border_color(&styles.cb_marker_checked, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_bg_color(&styles.cb_marker_checked, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_text_color(&styles.cb_marker_checked, makeLvColor(COLOR_THEME_PRIMARY2));
}
/**********************
@@ -569,6 +587,17 @@ void etx_bar_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
lv_obj_add_style(obj, &styles.rounded, LV_PART_INDICATOR);
}
void etx_checkbox_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
lv_obj_add_style(obj, &styles.rounded, LV_PART_INDICATOR);
lv_obj_add_style(obj, &styles.pad_zero, LV_PART_INDICATOR);
lv_obj_add_style(obj, &styles.cb_marker, LV_PART_INDICATOR);
lv_obj_add_style(obj, &styles.cb_marker_checked, LV_PART_INDICATOR | LV_STATE_CHECKED);
lv_obj_add_style(obj, &styles.border, LV_PART_INDICATOR);
lv_obj_add_style(obj, &styles.focussed, LV_PART_INDICATOR | LV_STATE_FOCUSED);
lv_obj_add_style(obj, &styles.disabled, LV_PART_INDICATOR | LV_STATE_DISABLED);
}
}
// Object classes
@@ -754,6 +783,19 @@ const lv_obj_class_t etx_bar_class = {
.instance_size = sizeof(lv_bar_t),
};
const lv_obj_class_t etx_checkbox_class = {
.base_class = &lv_checkbox_class,
.constructor_cb = etx_checkbox_constructor,
.destructor_cb = nullptr,
.user_data = nullptr,
.event_cb = nullptr,
.width_def = lv_pct(100),
.height_def = lv_pct(100),
.editable = LV_OBJ_CLASS_EDITABLE_INHERIT,
.group_def = LV_OBJ_CLASS_GROUP_DEF_INHERIT,
.instance_size = sizeof(lv_checkbox_t),
};
// Event handlers
static void field_edit_event(const lv_obj_class_t* class_p, lv_event_t* e)
{
@@ -876,6 +918,11 @@ lv_obj_t* etx_bar_create(lv_obj_t* parent)
return etx_create(&etx_bar_class, parent);
}
lv_obj_t* etx_checkbox_create(lv_obj_t* parent)
{
return etx_create(&etx_checkbox_class, parent);
}
lv_obj_t* etx_modal_create(lv_obj_t* parent)
{
lv_obj_t* obj = window_create(parent);
+1 -1
View File
@@ -55,7 +55,7 @@ ViewMainMenu::ViewMainMenu(Window* parent, std::function<void()> closeHandler) :
if (modelHasNotes()) {
carousel->addButton(ICON_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES, [=]() -> uint8_t {
deleteLater();
readModelNotes();
readModelNotes(true);
return 0;
});
}
+237 -33
View File
@@ -24,6 +24,35 @@
#include "opentx.h"
#include "sdcard.h"
constexpr int maxTxtBuffSize = 64 * 1024;
ViewTextWindow::ViewTextWindow(const std::string path, const std::string name,
unsigned int icon) :
Page(icon), path(std::move(path)), name(std::move(name))
{
fullPath = this->path + std::string(PATH_SEPARATOR) + this->name;
extractNameSansExt();
header.setTitle(this->name);
lv_obj_add_event_cb(lvobj, ViewTextWindow::on_draw, LV_EVENT_DRAW_MAIN_BEGIN, nullptr);
};
void ViewTextWindow::on_draw(lv_event_t * e)
{
lv_obj_t* target = lv_event_get_target(e);
auto view = (ViewTextWindow*)lv_obj_get_user_data(target);
if (view) {
if (view->buffer == nullptr)
view->buildBody(&view->body);
}
}
void ViewTextWindow::onCancel()
{
Page::onCancel();
}
void ViewTextWindow::extractNameSansExt()
{
uint8_t nameLength;
@@ -32,14 +61,11 @@ void ViewTextWindow::extractNameSansExt()
const char *ext =
getFileExtension(name.c_str(), 0, 0, &nameLength, &extLength);
extension = std::string(ext);
if (nameLength > TEXT_FILENAME_MAXLEN) nameLength = TEXT_FILENAME_MAXLEN;
nameLength -= extLength;
name.substr(nameLength);
openFromEnd = !strcmp(ext, LOGS_EXT);
}
void ViewTextWindow::buildBody(Window *window)
bool ViewTextWindow::openFile()
{
FILINFO info;
@@ -61,30 +87,39 @@ void ViewTextWindow::buildBody(Window *window)
TRACE("info.fsize=%d\tbufSize=%d\toffset=%d", info.fsize, bufSize,
int(info.fsize) - bufSize + 1);
if (sdReadTextFileBlock(bufSize, offset) == FR_OK) {
auto obj = window->getLvObj();
lv_obj_add_flag(
obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW |
LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO);
// prevents resetting the group's edit mode
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
auto g = lv_group_get_default();
lb = lv_label_create(obj);
lv_obj_set_size(lb, lv_pct(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(lb, lv_dpx(8), 0);
lv_group_add_obj(g, obj);
lv_group_set_editing(g, true);
lv_label_set_text_static(lb, buffer);
if (openFromEnd)
lv_obj_scroll_to_y(obj, LV_COORD_MAX, LV_ANIM_OFF);
else
lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF);
return true;
}
}
}
return false;
}
void ViewTextWindow::buildBody(Window *window)
{
if (openFile()) {
auto obj = window->getLvObj();
lv_obj_add_flag(
obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW |
LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO);
// prevents resetting the group's edit mode
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
auto g = lv_group_get_default();
lb = lv_label_create(obj);
lv_obj_set_size(lb, lv_pct(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(lb, lv_dpx(8), 0);
lv_group_add_obj(g, obj);
lv_group_set_editing(g, true);
lv_label_set_text_static(lb, buffer);
if (openFromEnd)
lv_obj_scroll_to_y(obj, LV_COORD_MAX, LV_ANIM_OFF);
else
lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF);
}
}
FRESULT ViewTextWindow::sdReadTextFileBlock(const uint32_t bufSize,
@@ -172,10 +207,176 @@ void ViewTextWindow::onEvent(event_t event)
sdReadTextFileBlock(bufSize, offset);
lv_label_set_text_static(lb, buffer);
}
if(event == EVT_KEY_BREAK(KEY_EXIT))
onCancel();
#endif
}
#include "datastructs.h"
static void checkbox_event_handler(lv_event_t* e);
class ViewChecklistWindow : public ViewTextWindow
{
public:
ViewChecklistWindow(const std::string path, const std::string name,
unsigned int icon) :
ViewTextWindow(path, name, icon)
{
header.setTitle(g_model.header.name);
header.setTitle2(STR_PREFLIGHT);
}
#if defined(DEBUG_WINDOWS)
std::string getName() const override { return "ViewChecklistWindow"; };
#endif
void onCancel() override
{
if (allChecked())
ViewTextWindow::onCancel();
}
protected:
TextButton* closeButton = nullptr;
std::list<lv_obj_t*> checkBoxes;
void updateCheckboxes()
{
bool lastState = true;
for (auto it = checkBoxes.cbegin(); it != checkBoxes.cend(); ++it) {
auto cb = *it;
if (lastState)
{
lv_obj_clear_state(cb, LV_STATE_DISABLED);
if (!(lv_obj_get_state(cb) & LV_STATE_CHECKED))
lv_group_focus_obj(cb);
} else {
lv_obj_add_state(cb, LV_STATE_DISABLED);
lv_obj_clear_state(cb, LV_STATE_CHECKED);
}
lastState = lv_obj_get_state(cb) & LV_STATE_CHECKED;
}
setCloseState();
}
bool allChecked()
{
for (auto it = checkBoxes.cbegin(); it != checkBoxes.cend(); ++it) {
auto cb = *it;
if (!(lv_obj_get_state(cb) & LV_STATE_CHECKED))
return false;
}
return true;
}
void setCloseState()
{
if (allChecked()) {
lv_obj_clear_state(closeButton->getLvObj(), LV_STATE_DISABLED);
lv_group_focus_obj(closeButton->getLvObj());
} else {
lv_obj_add_state(closeButton->getLvObj(), LV_STATE_DISABLED);
}
}
void onEvent(event_t event) override
{
#if defined(HARDWARE_KEYS)
if(event == EVT_KEY_BREAK(KEY_EXIT))
onCancel();
#endif
}
static void checkbox_event_handler(lv_event_t* e)
{
lv_obj_t* target = lv_event_get_target(e);
ViewChecklistWindow* vtw = (ViewChecklistWindow*)lv_obj_get_user_data(target);
if (vtw) vtw->updateCheckboxes();
}
void buildBody(Window* window) override
{
if (openFile()) {
auto obj = window->getLvObj();
lv_obj_add_flag(
obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW |
LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO);
// prevents resetting the group's edit mode
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_set_layout(obj, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_pad_all(obj, 3, LV_PART_MAIN);
lv_obj_set_style_pad_row(obj, 0, LV_PART_MAIN);
auto g = lv_group_get_default();
checkBoxes.clear();
size_t cur = 0;
for(int i=0; i<bufSize; ++i)
{
if (buffer[i] == '\n' || buffer[i] == '\r') {
buffer[i] = 0;
if (buffer[i] == '\r' && buffer[i+1] == '\n')
i += 1;
lv_obj_t* row = lv_obj_create(obj);
lv_obj_set_layout(row, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_width(row, lv_pct(100));
lv_obj_set_height(row, LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(row, 3, 0);
lv_obj_set_style_pad_column(row, 6, 0);
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_coord_t w = lv_obj_get_content_width(obj) - 6;
if (buffer[cur] == '=') {
cur++;
w -= 46;
lv_obj_set_style_pad_left(row, 10, 0);
auto cb = etx_checkbox_create(row);
lv_checkbox_set_text_static(cb, "");
lv_obj_set_width(cb, 25);
lv_obj_set_height(cb, 25);
lv_group_add_obj(g, cb);
lv_obj_add_event_cb(cb, ViewChecklistWindow::checkbox_event_handler, LV_EVENT_VALUE_CHANGED, this);
lv_obj_set_user_data(cb, this);
checkBoxes.push_back(cb);
}
auto lbl = lv_label_create(row);
lv_obj_set_width(lbl, w);
lv_label_set_long_mode(lbl, LV_LABEL_LONG_WRAP);
lv_label_set_text_static(lbl, &buffer[cur]);
cur = i + 1;
}
}
auto box = new FormWindow(window, rect_t{0, 0, lv_pct(100), LV_SIZE_CONTENT});
box->padAll(8);
closeButton = new TextButton(box, rect_t{}, STR_EXIT, [=]() -> int8_t { this->onCancel(); return 0; });
closeButton->setWidth(lv_pct(100));
updateCheckboxes();
}
}
};
static void replaceSpaceWithUnderscore(std::string &name)
{
@@ -192,19 +393,22 @@ static void replaceSpaceWithUnderscore(std::string &name)
#define MODEL_FILE_EXT MODELS_EXT
#endif
bool openNotes(const char buf[], std::string modelNotesName)
static bool openNotes(const char buf[], std::string modelNotesName, bool fromMenu = false)
{
std::string fullPath = std::string(buf) + PATH_SEPARATOR + modelNotesName;
if (isFileAvailable(fullPath.c_str())) {
new ViewTextWindow(std::string(buf), modelNotesName, ICON_MODEL);
if (fromMenu || !g_model.checklistInteractive)
new ViewTextWindow(std::string(buf), modelNotesName, ICON_MODEL);
else
new ViewChecklistWindow(std::string(buf), modelNotesName, ICON_MODEL);
return true;
} else {
return false;
}
}
void readModelNotes()
void readModelNotes(bool fromMenu)
{
bool notesFound = false;
LED_ERROR_BEGIN();
@@ -213,10 +417,10 @@ void readModelNotes()
modelNotesName.append(TEXT_EXT);
const char buf[] = {MODELS_PATH};
notesFound = openNotes(buf, modelNotesName);
notesFound = openNotes(buf, modelNotesName, fromMenu);
if (!notesFound) {
replaceSpaceWithUnderscore(modelNotesName);
notesFound = openNotes(buf, modelNotesName);
notesFound = openNotes(buf, modelNotesName, fromMenu);
}
#if !defined(EEPROM)
@@ -226,11 +430,11 @@ void readModelNotes()
if (index != std::string::npos) {
modelNotesName.erase(index);
modelNotesName.append(TEXT_EXT);
notesFound = openNotes(buf, modelNotesName);
notesFound = openNotes(buf, modelNotesName, fromMenu);
}
if (!notesFound) {
replaceSpaceWithUnderscore(modelNotesName);
notesFound = openNotes(buf, modelNotesName);
notesFound = openNotes(buf, modelNotesName, fromMenu);
}
}
#endif
+9 -18
View File
@@ -21,29 +21,14 @@
#pragma once
#include "ff.h"
#include "lcd.h"
#include "menus.h"
#include "page.h"
#include "static.h"
#include "sdcard.h"
#include "LvglWrapper.h"
constexpr int maxTxtBuffSize = 64 * 1024;
class ViewTextWindow : public Page
{
public:
ViewTextWindow(const std::string path, const std::string name,
unsigned int icon = ICON_RADIO_SD_MANAGER) :
Page(icon), path(std::move(path)), name(std::move(name))
{
fullPath = this->path + std::string(PATH_SEPARATOR) + this->name;
extractNameSansExt();
header.setTitle(this->name);
buildBody(&body);
};
unsigned int icon = ICON_RADIO_SD_MANAGER);
FRESULT sdReadTextFileBlock(const uint32_t bufSize,
const uint32_t offset);
@@ -56,6 +41,8 @@ class ViewTextWindow : public Page
}
}
void onCancel() override;
#if defined(DEBUG_WINDOWS)
std::string getName() const override { return "ViewTextWindow"; };
#endif
@@ -75,9 +62,13 @@ class ViewTextWindow : public Page
bool openFromEnd;
void extractNameSansExt(void);
void buildBody(Window* window);
virtual void buildBody(Window* window);
bool openFile();
void onEvent(event_t event) override;
static void on_draw(lv_event_t * e);
};
void readModelNotes();
void readModelNotes(bool fromMenu = false);
+1 -2
View File
@@ -18,7 +18,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
void menuModelNotes(event_t event)
@@ -34,7 +33,7 @@ void menuModelNotes(event_t event)
strcpy(buf, TEXT_EXT);
}
}
reusableBuffer.viewText.pushMenu = true;
menuTextView(event);
}
+49 -3
View File
@@ -22,6 +22,8 @@
#include "opentx.h"
constexpr uint32_t TEXT_FILE_MAXSIZE = 2048;
constexpr char NON_CHECKABLE_PREFIX = '=';
int checklistPosition;
static void sdReadTextFile(const char * filename, char lines[TEXT_VIEWER_LINES][LCD_COLS + 1], int & lines_count)
{
@@ -102,7 +104,8 @@ void readModelNotes()
waitKeysReleased();
event_t event = EVT_ENTRY;
while (event != EVT_KEY_BREAK(KEY_EXIT)) {
reusableBuffer.viewText.pushMenu = false;
while (true) {
uint32_t power = pwrCheck();
if (power != e_power_press) {
lcdRefreshWait();
@@ -117,6 +120,7 @@ void readModelNotes()
}
event = getEvent();
WDG_RESET();
if (reusableBuffer.viewText.checklistComplete) break;
}
LED_ERROR_END();
@@ -126,6 +130,8 @@ void menuTextView(event_t event)
{
if (event == EVT_ENTRY) {
menuVerticalOffset = 0;
checklistPosition = 0;
reusableBuffer.viewText.checklistComplete = false;
reusableBuffer.viewText.linesCount = 0;
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
} else if (IS_PREVIOUS_EVENT(event)) {
@@ -138,12 +144,51 @@ void menuTextView(event_t event)
++menuVerticalOffset;
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
}
} else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
if (g_model.checklistInteractive && !reusableBuffer.viewText.pushMenu && checklistPosition-(int)menuVerticalOffset >= 0){
if (checklistPosition < reusableBuffer.viewText.linesCount) {
if (checklistPosition-(int)menuVerticalOffset < LCD_LINES-1) {
++checklistPosition;
if (checklistPosition-(int)menuVerticalOffset >= LCD_LINES-2 && menuVerticalOffset+LCD_LINES-1 < reusableBuffer.viewText.linesCount) {
++menuVerticalOffset;
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
}
}
}
else {
if (reusableBuffer.viewText.pushMenu == true) popMenu();
reusableBuffer.viewText.checklistComplete = true;
}
}
} else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
popMenu();
if (!g_model.checklistInteractive || reusableBuffer.viewText.pushMenu) {
if (reusableBuffer.viewText.pushMenu == true) popMenu();
reusableBuffer.viewText.checklistComplete = true;
}
}
for (int i=0; i<LCD_LINES-1; i++) {
lcdDrawText(0, i*FH+FH+1, reusableBuffer.viewText.lines[i], FIXEDWIDTH);
if (g_model.checklistInteractive){
if (reusableBuffer.viewText.lines[i][0] == NON_CHECKABLE_PREFIX) {
lcdDrawText(8, i*FH+FH+1, &reusableBuffer.viewText.lines[i][1], FIXEDWIDTH);
if (i == checklistPosition-(int)menuVerticalOffset){
++checklistPosition;
if (checklistPosition-(int)menuVerticalOffset == LCD_LINES-1 && menuVerticalOffset+LCD_LINES-1 < reusableBuffer.viewText.linesCount) {
++menuVerticalOffset;
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
i = 0; // Reset rendering of the display after changing the offest
}
}
}
else {
if (i < reusableBuffer.viewText.linesCount && !reusableBuffer.viewText.pushMenu)
drawCheckBox(0, i*FH+FH+1, i < checklistPosition-(int)menuVerticalOffset, i == checklistPosition-(int)menuVerticalOffset);
lcdDrawText(8, i*FH+FH+1, reusableBuffer.viewText.lines[i], FIXEDWIDTH);
}
}
else {
lcdDrawText(0, i*FH+FH+1, reusableBuffer.viewText.lines[i], FIXEDWIDTH);
}
}
char * title = reusableBuffer.viewText.filename;
@@ -164,6 +209,7 @@ void pushMenuTextView(const char *filename)
{
if (strlen(filename) < TEXT_FILENAME_MAXLEN) {
strcpy(reusableBuffer.viewText.filename, filename);
reusableBuffer.viewText.pushMenu = true;
pushMenu(menuTextView);
}
}
+2
View File
@@ -975,6 +975,8 @@ union ReusableBuffer
char filename[TEXT_FILENAME_MAXLEN];
char lines[NUM_BODY_LINES][LCD_COLS + 1];
int linesCount;
bool checklistComplete;
bool pushMenu;
} viewText;
#endif
@@ -788,7 +788,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -818,7 +818,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -786,7 +786,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -786,7 +786,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -825,7 +825,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -825,7 +825,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -789,7 +789,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -789,7 +789,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -786,7 +786,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -792,7 +792,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_PADDING( 4 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -40,6 +40,7 @@ lv_obj_t* etx_modal_create(lv_obj_t* parent);
lv_obj_t* etx_modal_content_create(lv_obj_t* parent);
lv_obj_t* etx_modal_title_create(lv_obj_t* parent);
lv_obj_t* etx_bar_create(lv_obj_t* parent);
lv_obj_t* etx_checkbox_create(lv_obj_t* parent);
lv_obj_t* input_mix_line_create(lv_obj_t* parent);
lv_obj_t* input_mix_group_create(lv_obj_t* parent);
+1
View File
@@ -608,6 +608,7 @@ const char STR_MODULE_PROTOCOL_WARN_LINE2[] = TR_MODULE_PROTOCOL_WARN_LINE2;
const char STR_SET[] = TR_SET;
const char STR_PREFLIGHT[] = TR_PREFLIGHT;
const char STR_CHECKLIST[] = TR_CHECKLIST;
const char STR_CHECKLIST_INTERACTIVE[] = TR_CHECKLIST_INTERACTIVE;
const char STR_VIEW_NOTES[] = TR_VIEW_NOTES;
const char STR_MODEL_SELECT[] = TR_MODEL_SELECT;
const char STR_RESET_SUBMENU[] = TR_RESET_SUBMENU;
+1
View File
@@ -1001,6 +1001,7 @@ extern const char STR_SET[];
extern const char* const STR_PREFLIGHT_POTSLIDER_CHECK[];
extern const char STR_PREFLIGHT[];
extern const char STR_CHECKLIST[];
extern const char STR_CHECKLIST_INTERACTIVE[];
extern const char STR_VIEW_NOTES[];
extern const char STR_MODEL_SELECT[];
extern const char STR_RESET_SUBMENU[];
+1
View File
@@ -900,6 +900,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "关闭","开启","自动"
#define TR_PREFLIGHT "初始位置检查"
#define TR_CHECKLIST TR(INDENT "显示列表", INDENT "显示列表")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "串口"
#define TR_AUX2_SERIAL_MODE "串口 2"
#define TR_AUX_SERIAL_PORT_POWER "串口供电"
+1
View File
@@ -915,6 +915,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Vyp","Zap","Auto"
#define TR_PREFLIGHT "Předletová kontrola"
#define TR_CHECKLIST TR(INDENT "Poznámky", INDENT "Zobrazit poznámky")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Seriový port"
#define TR_AUX2_SERIAL_MODE "Seriový port 2"
#define TR_AUX_SERIAL_PORT_POWER "Výkon portu"
+1
View File
@@ -910,6 +910,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Fra","Til","Auto"
#define TR_PREFLIGHT "Fly checkliste"
#define TR_CHECKLIST TR(INDENT "Checkliste", INDENT "Vis checkliste")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Seriel port"
#define TR_AUX2_SERIAL_MODE "Seriel port 2"
#define TR_AUX_SERIAL_PORT_POWER "Port strøm"
+1
View File
@@ -903,6 +903,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Aus","Ein","Auto"
#define TR_PREFLIGHT "Vorflug-Checkliste"
#define TR_CHECKLIST TR(INDENT "Checkliste", INDENT "Checkliste anzeigen") //9XR-Pro
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Serieller Port"
#define TR_AUX2_SERIAL_MODE "Serieller Port 2"
#define TR_AUX_SERIAL_PORT_POWER "Versorgung"
+1
View File
@@ -904,6 +904,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "OFF","ON","AUTO"
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Display checklist")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Serial port"
#define TR_AUX2_SERIAL_MODE "Serial port 2"
#define TR_AUX_SERIAL_PORT_POWER "Port power"
+1
View File
@@ -907,6 +907,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
#define TR_PREFLIGHT "Chequeos prevuelo"
#define TR_CHECKLIST TR(INDENT "Lista verif", INDENT "Lista verificación")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Puerto serie"
#define TR_AUX2_SERIAL_MODE "Puerto serie 2"
#define TR_AUX_SERIAL_PORT_POWER "Port power"
+1
View File
@@ -919,6 +919,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST INDENT "Display Checklist"
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Sarjaportti"
#define TR_AUX2_SERIAL_MODE "Sarjaportti 2"
#define TR_AUX_SERIAL_PORT_POWER "Virta"
+1
View File
@@ -915,6 +915,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
#define TR_PREFLIGHT "Vérifs avant vol"
#define TR_CHECKLIST TR(INDENT "checklist", INDENT "Afficher checklist")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Port série"
#define TR_AUX2_SERIAL_MODE "Port série 2"
#define TR_AUX_SERIAL_PORT_POWER "Port power"
+1
View File
@@ -903,6 +903,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
#define TR_PREFLIGHT "Controlli Prevolo"
#define TR_CHECKLIST INDENT "Mostra Checklist"
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Porta Seriale"
#define TR_AUX2_SERIAL_MODE "Porta Seriale 2"
#define TR_AUX_SERIAL_PORT_POWER "Potenza porta AUX"
+1
View File
@@ -905,6 +905,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "OFF","ON","自動"
#define TR_PREFLIGHT "飛行前チェック"
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "チェックリスト表示")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "シリアルポート"
#define TR_AUX2_SERIAL_MODE "シリアルポート 2"
#define TR_AUX_SERIAL_PORT_POWER "ポート出力"
+1
View File
@@ -906,6 +906,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Toon Checklist")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Seriele poort"
#define TR_AUX2_SERIAL_MODE "Seriele poort 2"
#define TR_AUX_SERIAL_PORT_POWER "Port power"
+1
View File
@@ -901,6 +901,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "WYŁ","ZAŁ","Auto"
#define TR_PREFLIGHT "Lista Ostrzeżeń"
#define TR_CHECKLIST TR(INDENT "Czeklista",INDENT "Pokaż Listę Ostrzeżeń")
#define TR_CHECKLIST_INTERACTIVE TR(INDENT "C-Interakt", INDENT "Interkatywna lista ostrż.")
#define TR_AUX_SERIAL_MODE "Port szreg."
#define TR_AUX2_SERIAL_MODE "Port szreg. 2"
#define TR_AUX_SERIAL_PORT_POWER "Zasil.portu"
+1
View File
@@ -907,6 +907,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "DESL","LIGA","AUTO"
#define TR_PREFLIGHT "Checagem PreVoo"
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Display checklist")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Serial port"
#define TR_AUX2_SERIAL_MODE "Serial port 2"
#define TR_AUX_SERIAL_PORT_POWER "Port power"
+1
View File
@@ -934,6 +934,7 @@
#define TR_PREFLIGHT "Startkontroller"
#define TR_PREFLIGHT_POTSLIDER_CHECK "Av","På","Auto"
#define TR_CHECKLIST TR(INDENT "Checklista", INDENT "Visa checklista")
#define TR_CHECKLIST_INTERACTIVE TR(INDENT "C-Interact", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "Serieport"
#define TR_AUX2_SERIAL_MODE "Serieport 2"
#define TR_AUX_SERIAL_PORT_POWER "Strömkälla"
+1
View File
@@ -904,6 +904,7 @@
#define TR_PREFLIGHT_POTSLIDER_CHECK "關閉","開啟","自動"
#define TR_PREFLIGHT "初始位置檢查"
#define TR_CHECKLIST TR(INDENT "顯示列表", INDENT "顯示列表")
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
#define TR_AUX_SERIAL_MODE "端口"
#define TR_AUX2_SERIAL_MODE "端口 2"
#define TR_AUX_SERIAL_PORT_POWER "端口供電"