Skip to content

Commit

Permalink
feat: Interactive/progressive preflight checklist (#3564)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: 3djc <[email protected]>
Co-authored-by: philmoz <[email protected]>
Co-authored-by: Phil Mitchell <[email protected]>
  • Loading branch information
5 people authored Aug 29, 2023
1 parent ceba626 commit 06712d9
Show file tree
Hide file tree
Showing 44 changed files with 434 additions and 72 deletions.
2 changes: 2 additions & 0 deletions companion/src/firmwares/edgetx/yaml_modeldata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions companion/src/firmwares/modeldata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
7 changes: 7 additions & 0 deletions companion/src/modeledit/setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions companion/src/modeledit/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions companion/src/modeledit/setup.ui
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
3 changes: 2 additions & 1 deletion radio/src/datastructs_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions radio/src/gui/128x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions radio/src/gui/212x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
13 changes: 12 additions & 1 deletion radio/src/gui/colorlcd/preflight_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
53 changes: 50 additions & 3 deletions radio/src/gui/colorlcd/themes/etx_lv_theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ typedef struct {
// Choice
lv_style_t choice_main;

// Checkbox
// Toggle switch
lv_style_t switch_knob;

// Table
Expand All @@ -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;

/**********************
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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));
}

/**********************
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion radio/src/gui/colorlcd/view_main_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});
}
Expand Down
Loading

0 comments on commit 06712d9

Please sign in to comment.