feat(color): move model notes to model setup group in quick menu (#6737)
This commit is contained in:
@@ -34,6 +34,7 @@ SwitchWarnDialog::SwitchWarnDialog() :
|
||||
|
||||
void SwitchWarnDialog::delayedInit()
|
||||
{
|
||||
FullScreenDialog::delayedInit();
|
||||
lv_label_set_long_mode(messageLabel->getLvObj(), LV_LABEL_LONG_WRAP);
|
||||
AUDIO_ERROR_MESSAGE(AU_SWITCH_ALERT);
|
||||
}
|
||||
@@ -103,6 +104,7 @@ ThrottleWarnDialog::ThrottleWarnDialog(const char* msg) :
|
||||
|
||||
void ThrottleWarnDialog::delayedInit()
|
||||
{
|
||||
FullScreenDialog::delayedInit();
|
||||
lv_label_set_long_mode(messageLabel->getLvObj(), LV_LABEL_LONG_WRAP);
|
||||
AUDIO_ERROR_MESSAGE(AU_THROTTLE_ALERT);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class SwitchWarnDialog : public FullScreenDialog
|
||||
uint16_t last_bad_pots;
|
||||
|
||||
bool warningInactive();
|
||||
|
||||
|
||||
void delayedInit() override;
|
||||
|
||||
void checkEvents() override;
|
||||
@@ -56,6 +56,6 @@ class ThrottleWarnDialog : public FullScreenDialog
|
||||
|
||||
protected:
|
||||
bool warningInactive();
|
||||
|
||||
|
||||
void delayedInit() override;
|
||||
};
|
||||
|
||||
@@ -49,11 +49,14 @@ FullScreenDialog::FullScreenDialog(
|
||||
|
||||
bringToTop();
|
||||
|
||||
build();
|
||||
|
||||
delayLoad();
|
||||
}
|
||||
|
||||
void FullScreenDialog::delayedInit()
|
||||
{
|
||||
build();
|
||||
}
|
||||
|
||||
void FullScreenDialog::build()
|
||||
{
|
||||
auto div = new Window(this, {0, ALERT_FRAME_TOP, LCD_W, ALERT_FRAME_HEIGHT});
|
||||
|
||||
@@ -27,63 +27,65 @@ class StaticText;
|
||||
|
||||
class FullScreenDialog : public Window
|
||||
{
|
||||
public:
|
||||
FullScreenDialog(uint8_t type, std::string title, std::string message = "",
|
||||
std::string action = "",
|
||||
const std::function<void(void)>& confirmHandler = nullptr);
|
||||
public:
|
||||
FullScreenDialog(uint8_t type, std::string title, std::string message = "",
|
||||
std::string action = "",
|
||||
const std::function<void(void)>& confirmHandler = nullptr);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
{
|
||||
return "FullScreenDialog";
|
||||
}
|
||||
std::string getName() const override
|
||||
{
|
||||
return "FullScreenDialog";
|
||||
}
|
||||
#endif
|
||||
|
||||
void setMessage(std::string text);
|
||||
void setMessage(std::string text);
|
||||
|
||||
void onEvent(event_t event) override;
|
||||
void onCancel() override;
|
||||
bool onLongPress() override;
|
||||
void onEvent(event_t event) override;
|
||||
void onCancel() override;
|
||||
bool onLongPress() override;
|
||||
|
||||
void deleteLater(bool detach = true, bool trash = true) override;
|
||||
void deleteLater(bool detach = true, bool trash = true) override;
|
||||
|
||||
void checkEvents() override;
|
||||
void checkEvents() override;
|
||||
|
||||
void setCloseCondition(std::function<bool(void)> handler)
|
||||
{
|
||||
closeCondition = std::move(handler);
|
||||
}
|
||||
void setCloseCondition(std::function<bool(void)> handler)
|
||||
{
|
||||
closeCondition = std::move(handler);
|
||||
}
|
||||
|
||||
void runForever(bool checkPwr = true);
|
||||
void runForever(bool checkPwr = true);
|
||||
|
||||
void closeDialog();
|
||||
void closeDialog();
|
||||
|
||||
static LAYOUT_SIZE_SCALED(ALERT_FRAME_TOP, 50, 70)
|
||||
static LAYOUT_SIZE(ALERT_FRAME_HO, LAYOUT_SCALE(120), 2 * ALERT_FRAME_TOP)
|
||||
static constexpr coord_t ALERT_FRAME_HEIGHT = LCD_H - ALERT_FRAME_HO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_BMO, 25, 15)
|
||||
static constexpr coord_t ALERT_BITMAP_TOP = ALERT_FRAME_TOP + ALERT_BMO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_BITMAP_LEFT, 20, 15)
|
||||
static LAYOUT_SIZE_SCALED(ALERT_TO, 5, 10)
|
||||
static constexpr coord_t ALERT_TITLE_TOP = ALERT_FRAME_TOP + ALERT_TO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_TITLE_LEFT, 146, 140)
|
||||
static LAYOUT_SIZE_SCALED(ALERT_MO, 85, 130)
|
||||
static constexpr coord_t ALERT_MESSAGE_TOP = ALERT_TITLE_TOP + ALERT_MO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_MESSAGE_LEFT, 146, 15)
|
||||
static LAYOUT_VAL_SCALED(ONEBTN_W, 280)
|
||||
static LAYOUT_VAL_SCALED(ONEBTN_H, 40)
|
||||
static LAYOUT_VAL_SCALED(TWOBTN_W, 100)
|
||||
static LAYOUT_VAL_SCALED(TWOBTN_H, 40)
|
||||
static LAYOUT_SIZE_SCALED(ALERT_FRAME_TOP, 50, 70)
|
||||
static LAYOUT_SIZE(ALERT_FRAME_HO, LAYOUT_SCALE(120), 2 * ALERT_FRAME_TOP)
|
||||
static constexpr coord_t ALERT_FRAME_HEIGHT = LCD_H - ALERT_FRAME_HO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_BMO, 25, 15)
|
||||
static constexpr coord_t ALERT_BITMAP_TOP = ALERT_FRAME_TOP + ALERT_BMO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_BITMAP_LEFT, 20, 15)
|
||||
static LAYOUT_SIZE_SCALED(ALERT_TO, 5, 10)
|
||||
static constexpr coord_t ALERT_TITLE_TOP = ALERT_FRAME_TOP + ALERT_TO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_TITLE_LEFT, 146, 140)
|
||||
static LAYOUT_SIZE_SCALED(ALERT_MO, 85, 130)
|
||||
static constexpr coord_t ALERT_MESSAGE_TOP = ALERT_TITLE_TOP + ALERT_MO;
|
||||
static LAYOUT_SIZE_SCALED(ALERT_MESSAGE_LEFT, 146, 15)
|
||||
static LAYOUT_VAL_SCALED(ONEBTN_W, 280)
|
||||
static LAYOUT_VAL_SCALED(ONEBTN_H, 40)
|
||||
static LAYOUT_VAL_SCALED(TWOBTN_W, 100)
|
||||
static LAYOUT_VAL_SCALED(TWOBTN_H, 40)
|
||||
|
||||
protected:
|
||||
uint8_t type;
|
||||
std::string title;
|
||||
std::string message;
|
||||
std::string action;
|
||||
bool running = false;
|
||||
std::function<bool(void)> closeCondition;
|
||||
std::function<void(void)> confirmHandler;
|
||||
StaticText* messageLabel;
|
||||
protected:
|
||||
uint8_t type;
|
||||
std::string title;
|
||||
std::string message;
|
||||
std::string action;
|
||||
bool running = false;
|
||||
std::function<bool(void)> closeCondition;
|
||||
std::function<void(void)> confirmHandler;
|
||||
StaticText* messageLabel;
|
||||
|
||||
void build();
|
||||
void build();
|
||||
|
||||
void delayedInit() override;
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "fullscreen_dialog.h"
|
||||
#include "lib_file.h"
|
||||
|
||||
// Used on startup to block until checlist is closed.
|
||||
// Used on startup to block until checklist is closed.
|
||||
static bool checkListOpen = false;
|
||||
|
||||
// Check Box
|
||||
@@ -67,198 +67,236 @@ static lv_obj_t* checkbox_create(lv_obj_t* parent)
|
||||
|
||||
constexpr int maxTxtBuffSize = 64 * 1024;
|
||||
|
||||
class TextViewer
|
||||
{
|
||||
public:
|
||||
TextViewer(const std::string path, const std::string name) : name(std::move(name))
|
||||
{
|
||||
fullPath = path + std::string(PATH_SEPARATOR) + name;
|
||||
extractNameSansExt();
|
||||
}
|
||||
|
||||
~TextViewer()
|
||||
{
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void onEvent(event_t event)
|
||||
{
|
||||
#if defined(HARDWARE_KEYS)
|
||||
if (int(bufSize) < fileLength) {
|
||||
if (event == EVT_KEY_BREAK(KEY_PAGEDN)) {
|
||||
offset += bufSize;
|
||||
}
|
||||
|
||||
if (event == EVT_KEY_BREAK(KEY_PAGEUP)) {
|
||||
offset -= bufSize;
|
||||
}
|
||||
|
||||
offset = std::max(offset, 0);
|
||||
offset = std::min(offset, fileLength - (int)bufSize);
|
||||
|
||||
sdReadTextFileBlock(bufSize, offset);
|
||||
lv_label_set_text_static(lb, buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void build(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);
|
||||
etx_scrollbar(obj);
|
||||
// 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);
|
||||
etx_obj_add_style(lb, styles->pad_medium, LV_PART_MAIN);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string name;
|
||||
std::string fullPath;
|
||||
|
||||
lv_obj_t* lb;
|
||||
|
||||
int offset = 0;
|
||||
char* buffer = nullptr;
|
||||
size_t bufSize = 0;
|
||||
int fileLength = 0;
|
||||
bool openFromEnd;
|
||||
|
||||
void extractNameSansExt()
|
||||
{
|
||||
uint8_t nameLength;
|
||||
uint8_t extLength;
|
||||
|
||||
const char* ext =
|
||||
getFileExtension(name.c_str(), 0, 0, &nameLength, &extLength);
|
||||
|
||||
openFromEnd = !strcmp(ext, LOGS_EXT);
|
||||
}
|
||||
|
||||
bool openFile()
|
||||
{
|
||||
FILINFO info;
|
||||
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
bufSize = 0;
|
||||
}
|
||||
|
||||
auto res = f_stat((TCHAR*)fullPath.c_str(), &info);
|
||||
if (res == FR_OK) {
|
||||
fileLength = int(info.fsize);
|
||||
bufSize = std::min(fileLength, maxTxtBuffSize) + 1;
|
||||
|
||||
buffer = (char*)malloc(bufSize);
|
||||
if (buffer) {
|
||||
offset = std::max(int(openFromEnd ? int(info.fsize) - bufSize + 1 : 0), 0);
|
||||
if (sdReadTextFileBlock(bufSize, offset) == FR_OK) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FRESULT sdReadTextFileBlock(const uint32_t bufSize, const uint32_t offset)
|
||||
{
|
||||
FIL file;
|
||||
char escape_chars[4];
|
||||
int escape = 0;
|
||||
|
||||
auto res =
|
||||
f_open(&file, (TCHAR*)fullPath.c_str(), FA_OPEN_EXISTING | FA_READ);
|
||||
if (res == FR_OK) {
|
||||
res = f_lseek(&file, offset);
|
||||
if (res == FR_OK) {
|
||||
UINT br;
|
||||
char c;
|
||||
char* ptr = buffer;
|
||||
for (int i = 0; i < (int)bufSize; i++) {
|
||||
res = f_read(&file, &c, 1, &br);
|
||||
if (res == FR_OK && br == 1) {
|
||||
if (c == '\\' && escape == 0) {
|
||||
escape = 1;
|
||||
continue;
|
||||
} else if (c != '\\' && escape > 0 &&
|
||||
escape < (int)sizeof(escape_chars)) {
|
||||
escape_chars[escape - 1] = c;
|
||||
|
||||
if (escape == 2 && !strncmp(escape_chars, "up", 2)) {
|
||||
*ptr++ = STR_CHAR_UP[0];
|
||||
c = STR_CHAR_UP[1];
|
||||
escape = 0;
|
||||
} else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) {
|
||||
*ptr++ = STR_CHAR_DOWN[0];
|
||||
c = STR_CHAR_DOWN[1];
|
||||
escape = 0;
|
||||
} else if (escape == 3) {
|
||||
int val = atoi(escape_chars);
|
||||
if (val >= 200 && val < 225) {
|
||||
*ptr++ = '\302';
|
||||
c = '\200' + val - 200;
|
||||
}
|
||||
} else if (escape == 1 && c == '~') {
|
||||
c = 'z' + 1;
|
||||
} else {
|
||||
escape++;
|
||||
continue;
|
||||
}
|
||||
} else if (c == '\t') {
|
||||
c = 0x1D; // tab
|
||||
}
|
||||
escape = 0;
|
||||
|
||||
if (c == 0xA && *(ptr - 1) == 0xD) {
|
||||
*(ptr - 1) = '\n';
|
||||
continue;
|
||||
}
|
||||
*ptr++ = c;
|
||||
}
|
||||
}
|
||||
*ptr = '\0';
|
||||
}
|
||||
f_close(&file);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
ViewTextWindow::ViewTextWindow(const std::string path, const std::string name,
|
||||
EdgeTxIcon icon) :
|
||||
Page(icon, PAD_ZERO), path(std::move(path)), name(std::move(name))
|
||||
Page(icon, PAD_ZERO)
|
||||
{
|
||||
fullPath = this->path + std::string(PATH_SEPARATOR) + this->name;
|
||||
extractNameSansExt();
|
||||
textViewer = new TextViewer(path, name);
|
||||
|
||||
header->setTitle(this->name);
|
||||
header->setTitle(name);
|
||||
|
||||
delayLoad();
|
||||
};
|
||||
|
||||
void ViewTextWindow::delayedInit()
|
||||
{
|
||||
if (buffer == nullptr) buildBody(body);
|
||||
textViewer->build(body);
|
||||
}
|
||||
|
||||
void ViewTextWindow::onCancel()
|
||||
{
|
||||
if (textViewer) delete textViewer;
|
||||
Page::onCancel();
|
||||
checkListOpen = false;
|
||||
}
|
||||
|
||||
void ViewTextWindow::extractNameSansExt()
|
||||
{
|
||||
uint8_t nameLength;
|
||||
uint8_t extLength;
|
||||
|
||||
const char* ext =
|
||||
getFileExtension(name.c_str(), 0, 0, &nameLength, &extLength);
|
||||
extension = std::string(ext);
|
||||
|
||||
openFromEnd = !strcmp(ext, LOGS_EXT);
|
||||
}
|
||||
|
||||
bool ViewTextWindow::openFile()
|
||||
{
|
||||
FILINFO info;
|
||||
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
bufSize = 0;
|
||||
}
|
||||
|
||||
auto res = f_stat((TCHAR*)fullPath.c_str(), &info);
|
||||
if (res == FR_OK) {
|
||||
fileLength = int(info.fsize);
|
||||
bufSize = std::min(fileLength, maxTxtBuffSize) + 1;
|
||||
|
||||
buffer = (char*)malloc(bufSize);
|
||||
if (buffer) {
|
||||
offset =
|
||||
std::max(int(openFromEnd ? int(info.fsize) - bufSize + 1 : 0), 0);
|
||||
TRACE("info.fsize=%d\tbufSize=%d\toffset=%d", info.fsize, bufSize,
|
||||
int(info.fsize) - bufSize + 1);
|
||||
if (sdReadTextFileBlock(bufSize, offset) == FR_OK) {
|
||||
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);
|
||||
etx_scrollbar(obj);
|
||||
// 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);
|
||||
etx_obj_add_style(lb, styles->pad_medium, LV_PART_MAIN);
|
||||
|
||||
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,
|
||||
const uint32_t offset)
|
||||
{
|
||||
FIL file;
|
||||
char escape_chars[4];
|
||||
int escape = 0;
|
||||
|
||||
auto res =
|
||||
f_open(&file, (TCHAR*)fullPath.c_str(), FA_OPEN_EXISTING | FA_READ);
|
||||
if (res == FR_OK) {
|
||||
res = f_lseek(&file, offset);
|
||||
if (res == FR_OK) {
|
||||
UINT br;
|
||||
char c;
|
||||
char* ptr = buffer;
|
||||
for (int i = 0; i < (int)bufSize; i++) {
|
||||
res = f_read(&file, &c, 1, &br);
|
||||
if (res == FR_OK && br == 1) {
|
||||
if (c == '\\' && escape == 0) {
|
||||
escape = 1;
|
||||
continue;
|
||||
} else if (c != '\\' && escape > 0 &&
|
||||
escape < (int)sizeof(escape_chars)) {
|
||||
escape_chars[escape - 1] = c;
|
||||
|
||||
if (escape == 2 && !strncmp(escape_chars, "up", 2)) {
|
||||
*ptr++ = STR_CHAR_UP[0];
|
||||
c = STR_CHAR_UP[1];
|
||||
escape = 0;
|
||||
} else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) {
|
||||
*ptr++ = STR_CHAR_DOWN[0];
|
||||
c = STR_CHAR_DOWN[1];
|
||||
escape = 0;
|
||||
} else if (escape == 3) {
|
||||
int val = atoi(escape_chars);
|
||||
if (val >= 200 && val < 225) {
|
||||
*ptr++ = '\302';
|
||||
c = '\200' + val - 200;
|
||||
}
|
||||
} else if (escape == 1 && c == '~') {
|
||||
c = 'z' + 1;
|
||||
} else {
|
||||
escape++;
|
||||
continue;
|
||||
}
|
||||
} else if (c == '\t') {
|
||||
c = 0x1D; // tab
|
||||
}
|
||||
escape = 0;
|
||||
|
||||
if (c == 0xA && *(ptr - 1) == 0xD) {
|
||||
*(ptr - 1) = '\n';
|
||||
continue;
|
||||
}
|
||||
*ptr++ = c;
|
||||
}
|
||||
}
|
||||
*ptr = '\0';
|
||||
}
|
||||
f_close(&file);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void ViewTextWindow::onEvent(event_t event)
|
||||
{
|
||||
#if defined(HARDWARE_KEYS)
|
||||
if (int(bufSize) < fileLength) {
|
||||
TRACE("BEFORE offset=%d", offset);
|
||||
if (event == EVT_KEY_BREAK(KEY_PAGEDN)) {
|
||||
offset += bufSize;
|
||||
TRACE("event=DOWN");
|
||||
}
|
||||
|
||||
if (event == EVT_KEY_BREAK(KEY_PAGEUP)) {
|
||||
TRACE("event=UP");
|
||||
offset -= bufSize;
|
||||
}
|
||||
|
||||
offset = std::max(offset, 0);
|
||||
offset = std::min(offset, fileLength - (int)bufSize);
|
||||
|
||||
TRACE("AFTER offset=%d", offset);
|
||||
sdReadTextFileBlock(bufSize, offset);
|
||||
lv_label_set_text_static(lb, buffer);
|
||||
}
|
||||
if (textViewer) textViewer->onEvent(event);
|
||||
|
||||
if (event == EVT_KEY_BREAK(KEY_EXIT)) onCancel();
|
||||
#endif
|
||||
}
|
||||
|
||||
class ViewChecklistWindow : public ViewTextWindow
|
||||
class ViewChecklistWindow : public Page, public TextViewer
|
||||
{
|
||||
public:
|
||||
ViewChecklistWindow(const std::string path, const std::string name,
|
||||
EdgeTxIcon icon) :
|
||||
ViewTextWindow(path, name, icon)
|
||||
Page(icon, PAD_ZERO), TextViewer(path, name)
|
||||
{
|
||||
header->setTitle(g_model.header.name);
|
||||
header->setTitle2(STR_PREFLIGHT);
|
||||
|
||||
fullPath = path + std::string(PATH_SEPARATOR) + name;
|
||||
extractNameSansExt();
|
||||
|
||||
delayLoad();
|
||||
}
|
||||
|
||||
void delayedInit() override
|
||||
{
|
||||
if (buffer == nullptr) buildBody(body);
|
||||
}
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
@@ -267,7 +305,10 @@ class ViewChecklistWindow : public ViewTextWindow
|
||||
|
||||
void onCancel() override
|
||||
{
|
||||
if (allChecked()) ViewTextWindow::onCancel();
|
||||
if (allChecked()) {
|
||||
Page::onCancel();
|
||||
checkListOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -330,7 +371,7 @@ class ViewChecklistWindow : public ViewTextWindow
|
||||
if (vtw) vtw->updateCheckboxes();
|
||||
}
|
||||
|
||||
void buildBody(Window* window) override
|
||||
void buildBody(Window* window)
|
||||
{
|
||||
if (openFile()) {
|
||||
auto obj = window->getLvObj();
|
||||
@@ -456,27 +497,19 @@ static std::string getModelNotesFile()
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
static bool openNotes(std::string modelNotesName,
|
||||
bool fromMenu = false)
|
||||
{
|
||||
std::string fullPath = std::string(MODELS_PATH) + PATH_SEPARATOR + modelNotesName;
|
||||
|
||||
if (isFileAvailable(fullPath.c_str())) {
|
||||
if (fromMenu || !g_model.checklistInteractive)
|
||||
new ViewTextWindow(std::string(MODELS_PATH), modelNotesName, ICON_MODEL);
|
||||
else
|
||||
new ViewChecklistWindow(std::string(MODELS_PATH), modelNotesName, ICON_MODEL);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void readModelNotes(bool fromMenu)
|
||||
{
|
||||
std::string modelNotesName = getModelNotesFile();
|
||||
if (!modelNotesName.empty()) {
|
||||
openNotes(modelNotesName, fromMenu);
|
||||
std::string fullPath = std::string(MODELS_PATH) + PATH_SEPARATOR + modelNotesName;
|
||||
|
||||
if (isFileAvailable(fullPath.c_str())) {
|
||||
if (fromMenu || !g_model.checklistInteractive)
|
||||
new ViewTextWindow(std::string(MODELS_PATH), modelNotesName, ICON_MODEL);
|
||||
else
|
||||
new ViewChecklistWindow(std::string(MODELS_PATH), modelNotesName, ICON_MODEL);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,8 +533,10 @@ class CheckListDialog : public FullScreenDialog
|
||||
|
||||
bool warningInactive()
|
||||
{
|
||||
if (!checkListOpen)
|
||||
if (!checkListOpen) {
|
||||
LED_ERROR_END();
|
||||
deleteLater();
|
||||
}
|
||||
return !checkListOpen;
|
||||
}
|
||||
};
|
||||
@@ -515,3 +550,19 @@ void readChecklist()
|
||||
dialog->runForever();
|
||||
}
|
||||
}
|
||||
|
||||
ModelNotesPage::ModelNotesPage(PageDef& pageDef) : PageGroupItem(pageDef, PAD_ZERO)
|
||||
{
|
||||
}
|
||||
|
||||
void ModelNotesPage::build(Window* window)
|
||||
{
|
||||
if (!textViewer) textViewer = new TextViewer(MODELS_PATH, getModelNotesFile());
|
||||
if (textViewer) textViewer->build(window);
|
||||
}
|
||||
|
||||
void ModelNotesPage::cleanup()
|
||||
{
|
||||
if (textViewer) delete textViewer;
|
||||
textViewer = nullptr;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ff.h"
|
||||
#include "page.h"
|
||||
#include "pagegroup.h"
|
||||
#include "gui_common.h"
|
||||
|
||||
class TextViewer;
|
||||
|
||||
class ViewTextWindow : public Page
|
||||
{
|
||||
@@ -32,42 +35,33 @@ class ViewTextWindow : public Page
|
||||
FRESULT sdReadTextFileBlock(const uint32_t bufSize,
|
||||
const uint32_t offset);
|
||||
|
||||
~ViewTextWindow()
|
||||
{
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void onCancel() override;
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override { return "ViewTextWindow"; };
|
||||
#endif
|
||||
|
||||
void delayedInit() override;
|
||||
|
||||
protected:
|
||||
std::string path;
|
||||
std::string name;
|
||||
std::string fullPath;
|
||||
std::string extension;
|
||||
|
||||
lv_obj_t* lb;
|
||||
|
||||
int offset = 0;
|
||||
char* buffer = nullptr;
|
||||
size_t bufSize = 0;
|
||||
int fileLength = 0;
|
||||
bool openFromEnd;
|
||||
|
||||
void extractNameSansExt(void);
|
||||
virtual void buildBody(Window* window);
|
||||
|
||||
bool openFile();
|
||||
TextViewer* textViewer = nullptr;
|
||||
|
||||
void onEvent(event_t event) override;
|
||||
};
|
||||
|
||||
void delayedInit() override;
|
||||
class ModelNotesPage : public PageGroupItem
|
||||
{
|
||||
public:
|
||||
ModelNotesPage(PageDef& pageDef);
|
||||
|
||||
bool isVisible() const override { return modelHasNotes(); }
|
||||
|
||||
void build(Window* window) override;
|
||||
|
||||
void cleanup() override;
|
||||
|
||||
protected:
|
||||
TextViewer* textViewer = nullptr;
|
||||
};
|
||||
|
||||
void readModelNotes(bool fromMenu = false);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "model_setup.h"
|
||||
#include "model_telemetry.h"
|
||||
#include "special_functions.h"
|
||||
#include "view_text.h"
|
||||
|
||||
PageDef modelMenuItems[] = {
|
||||
{ ICON_MODEL_SETUP, STR_QM_GEN_SETTINGS, STR_MAIN_MENU_SETTINGS, PAGE_CREATE, QuickMenu::MODEL_SETUP, [](PageDef& pageDef) { return new ModelSetupPage(pageDef); }},
|
||||
@@ -52,5 +53,6 @@ PageDef modelMenuItems[] = {
|
||||
{ ICON_MODEL_LUA_SCRIPTS, STR_QM_CUSTOM_LUA, STR_MENUCUSTOMSCRIPTS, PAGE_CREATE, QuickMenu::MODEL_SCRIPTS, [](PageDef& pageDef) { return new ModelMixerScriptsPage(pageDef); }, modelCustomScriptsEnabled},
|
||||
#endif
|
||||
{ ICON_MODEL_TELEMETRY, STR_QM_TELEM, STR_MENUTELEMETRY, PAGE_CREATE, QuickMenu::MODEL_TELEMETRY, [](PageDef& pageDef) { return new ModelTelemetryPage(pageDef); }, modelTelemetryEnabled},
|
||||
{ ICON_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES, PAGE_CREATE, QuickMenu::MODEL_NOTES, [](PageDef& pageDef) { return new ModelNotesPage(pageDef); }, modelHasNotes},
|
||||
{ EDGETX_ICONS_COUNT }
|
||||
};
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "edgetx.h"
|
||||
#include "quick_menu_group.h"
|
||||
#include "etx_lv_theme.h"
|
||||
#include "view_text.h"
|
||||
#include "view_main.h"
|
||||
#include "screen_setup.h"
|
||||
#include "theme_manager.h"
|
||||
@@ -245,16 +244,6 @@ QuickMenu::QuickMenu() :
|
||||
sub = new QuickSubMenu(box, this, ICON_RADIO_TOOLS, STR_QM_TOOLS, STR_QM_TOOLS, toolsMenuItems);
|
||||
sub->addButton();
|
||||
subMenus.emplace_back(sub);
|
||||
|
||||
mainMenu->addButton(ICON_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES,
|
||||
[=]() -> uint8_t {
|
||||
onSelect(true);
|
||||
readModelNotes(true);
|
||||
return 0;
|
||||
},
|
||||
[=]() -> bool {
|
||||
return modelHasNotes();
|
||||
});
|
||||
}
|
||||
|
||||
void QuickMenu::deleteLater(bool detach, bool trash)
|
||||
@@ -288,7 +277,7 @@ void QuickMenu::openQM(std::function<void()> cancelHandler,
|
||||
setFocus(curPage);
|
||||
} else {
|
||||
pageGroup = nullptr;
|
||||
if (curPage > QuickMenu::MANAGE_MODELS) {
|
||||
if (curPage >= QuickMenu::FIRST_SUB_MENU_ITEM) {
|
||||
mainMenu->setDisabled(false);
|
||||
mainMenu->clearFocus();
|
||||
setFocus(curPage);
|
||||
|
||||
@@ -45,8 +45,9 @@ class QuickMenu : public NavWindow
|
||||
enum SubMenu {
|
||||
NONE = 0,
|
||||
MANAGE_MODELS,
|
||||
FIRST_SUB_MENU_ITEM,
|
||||
// Model menu
|
||||
MODEL_SETUP,
|
||||
MODEL_SETUP = FIRST_SUB_MENU_ITEM,
|
||||
MODEL_HELI,
|
||||
MODEL_FLIGHTMODES,
|
||||
MODEL_INPUTS,
|
||||
@@ -58,6 +59,7 @@ class QuickMenu : public NavWindow
|
||||
MODEL_SF,
|
||||
MODEL_SCRIPTS,
|
||||
MODEL_TELEMETRY,
|
||||
MODEL_NOTES,
|
||||
// Radio menu
|
||||
RADIO_SETUP,
|
||||
RADIO_GF,
|
||||
|
||||
Reference in New Issue
Block a user