feat: Support opening large log files on colorlcd (#1625)
* Remove limit for the TXT file size for color LCD TX (#1612) * view log files * warning for long files and load speed-up
This commit is contained in:
@@ -30,6 +30,8 @@
|
||||
#include "view_text.h"
|
||||
#include "file_preview.h"
|
||||
|
||||
constexpr int WARN_FILE_LENGTH = 96000;
|
||||
|
||||
class FileNameEditWindow : public Page
|
||||
{
|
||||
public:
|
||||
@@ -279,16 +281,31 @@ void RadioSdManagerPage::build(FormWindow * window)
|
||||
// else if (isExtensionMatching(ext, BITMAPS_EXT)) {
|
||||
// // TODO
|
||||
// }
|
||||
else if (!strcasecmp(ext, TEXT_EXT)) {
|
||||
else if (!strcasecmp(ext, TEXT_EXT) || !strcasecmp(ext, LOGS_EXT)) {
|
||||
menu->addLine(STR_VIEW_TEXT, [=]() {
|
||||
static char lfn[FF_MAX_LFN + 1]; // TODO optimize that!
|
||||
f_getcwd((TCHAR *)lfn, FF_MAX_LFN);
|
||||
FIL file;
|
||||
std::string fileName =
|
||||
std::string(lfn) + "/" + std::string(name);
|
||||
if (FR_OK == f_open(&file, (TCHAR *)fileName.c_str(),
|
||||
FA_OPEN_EXISTING | FA_READ)) {
|
||||
const int fileLenght = file.obj.objsize;
|
||||
f_close(&file);
|
||||
|
||||
auto textView = new ViewTextWindow(lfn, name);
|
||||
textView->setCloseHandler([=]() {
|
||||
//window->clear();
|
||||
rebuild(window);
|
||||
});
|
||||
if (fileLenght > WARN_FILE_LENGTH) {
|
||||
char buf[64];
|
||||
sprintf(buf, " %s %dkB. %s", STR_FILE_SIZE,
|
||||
fileLenght / 1024, STR_FILE_OPEN);
|
||||
new ConfirmDialog(window, STR_WARNING, buf, [=] {
|
||||
auto textView = new ViewTextWindow(lfn, name);
|
||||
textView->setCloseHandler([=]() { rebuild(window); });
|
||||
});
|
||||
} else {
|
||||
auto textView = new ViewTextWindow(lfn, name);
|
||||
textView->setCloseHandler([=]() { rebuild(window); });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!READ_ONLY() && !strcasecmp(ext, FIRMWARE_EXT)) {
|
||||
|
||||
@@ -52,6 +52,7 @@ void ViewTextWindow::extractNameSansExt()
|
||||
|
||||
nameLength -= extLength;
|
||||
name.substr(nameLength);
|
||||
openFromEnd = !strcmp(ext, LOGS_EXT);
|
||||
}
|
||||
|
||||
void ViewTextWindow::buildBody(Window *window)
|
||||
@@ -59,6 +60,7 @@ void ViewTextWindow::buildBody(Window *window)
|
||||
GridLayout grid(window);
|
||||
grid.spacer();
|
||||
int i;
|
||||
FIL file;
|
||||
|
||||
// assume average characte is 10 pixels wide, round the string length to tens.
|
||||
// Font is not fixed width, so this is for the worst case...
|
||||
@@ -74,22 +76,26 @@ void ViewTextWindow::buildBody(Window *window)
|
||||
memclear(lines[i], maxLineLength + 1);
|
||||
}
|
||||
|
||||
longestLine = 0;
|
||||
loadFirstScreen();
|
||||
if (isInSetup) {
|
||||
if (FR_OK ==
|
||||
f_open(&file, (TCHAR *)fullPath.c_str(), FA_OPEN_EXISTING | FA_READ)) {
|
||||
const int fileLenght = file.obj.objsize;
|
||||
maxLines = 20 * fileLenght / maxLineLength;
|
||||
f_close(&file);
|
||||
|
||||
if (isInSetup == true) {
|
||||
textBottom = false;
|
||||
while (!textBottom) {
|
||||
sdReadTextFileBlock(fullPath.c_str(), readLinesCount);
|
||||
textVerticalOffset += 10;
|
||||
textBottom = false;
|
||||
longestLine = 0;
|
||||
loadOneScreen(maxLines);
|
||||
|
||||
maxPos =
|
||||
(maxLines - maxScreenLines) * (PAGE_LINE_HEIGHT + PAGE_LINE_SPACING);
|
||||
if (maxPos < body.getRect().h) maxPos = body.getRect().h;
|
||||
}
|
||||
maxPos =
|
||||
(maxLines - maxScreenLines) * (PAGE_LINE_HEIGHT + PAGE_LINE_SPACING);
|
||||
if (maxPos < body.getRect().h) maxPos = body.getRect().h;
|
||||
}
|
||||
|
||||
isInSetup = false;
|
||||
loadFirstScreen();
|
||||
textVerticalOffset = 0;
|
||||
loadOneScreen(openFromEnd ? (maxLines - maxScreenLines) : 0);
|
||||
|
||||
for (i = 0; i < maxScreenLines; i++) {
|
||||
new DynamicText(window, grid.getSlot(), [=]() {
|
||||
@@ -98,7 +104,7 @@ void ViewTextWindow::buildBody(Window *window)
|
||||
return std::string(str);
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
@@ -114,8 +120,8 @@ bool ViewTextWindow::onTouchSlide(coord_t x, coord_t y, coord_t startX,
|
||||
textVerticalOffset += lineStep;
|
||||
if (textVerticalOffset < 0) textVerticalOffset = 0;
|
||||
|
||||
// if (textBottom && lineStep > 0) textVerticalOffset -= lineStep;
|
||||
if (textVerticalOffset > maxLines) textVerticalOffset = maxLines;
|
||||
if (textVerticalOffset > maxLines - maxScreenLines)
|
||||
textVerticalOffset = maxLines - maxScreenLines;
|
||||
sdReadTextFileBlock(fullPath.c_str(), readLinesCount);
|
||||
}
|
||||
return Page::onTouchSlide(x, y, startX, startY, slideX, slideY);
|
||||
@@ -178,9 +184,9 @@ void ViewTextWindow::checkEvents()
|
||||
Page::checkEvents();
|
||||
}
|
||||
|
||||
void ViewTextWindow::loadFirstScreen()
|
||||
void ViewTextWindow::loadOneScreen(int offset)
|
||||
{
|
||||
textVerticalOffset = 0;
|
||||
textVerticalOffset = offset;
|
||||
readLinesCount = 0;
|
||||
sdReadTextFileBlock(fullPath.c_str(), readLinesCount);
|
||||
}
|
||||
@@ -204,11 +210,10 @@ void ViewTextWindow::sdReadTextFileBlock(const char *filename, int &lines_count)
|
||||
|
||||
result = f_open(&file, (TCHAR *)filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result == FR_OK) {
|
||||
for (int i = 0; i < TEXT_FILE_MAXSIZE &&
|
||||
f_read(&file, &c, 1, &sz) == FR_OK && sz == 1 &&
|
||||
(lines_count == 0 ||
|
||||
current_line - textVerticalOffset < maxScreenLines);
|
||||
i++) {
|
||||
while (f_read(&file, &c, 1, &sz) == FR_OK && sz == 1 &&
|
||||
(lines_count == 0 ||
|
||||
current_line - textVerticalOffset < maxScreenLines))
|
||||
{
|
||||
if (c == '\n' || line_length >= maxLineLength) {
|
||||
++current_line;
|
||||
line_length = 1;
|
||||
@@ -271,9 +276,8 @@ void ViewTextWindow::drawVerticalScrollbar(BitmapBuffer *dc)
|
||||
{
|
||||
int readPos = textVerticalOffset * (PAGE_LINE_HEIGHT + PAGE_LINE_SPACING);
|
||||
|
||||
if (readPos < header.getRect().h << 1) readPos = header.getRect().h << 1;
|
||||
|
||||
coord_t yofs = divRoundClosest(body.getRect().h * readPos, maxPos);
|
||||
coord_t yofs = divRoundClosest(body.getRect().h * readPos, maxPos)
|
||||
+ header.getRect().h + (int)PAGE_LINE_SPACING;
|
||||
coord_t yhgt = divRoundClosest(body.getRect().h * body.getRect().h, maxPos);
|
||||
if (yhgt < 15) yhgt = 15;
|
||||
if (yhgt + yofs > maxPos) yhgt = maxPos - yofs;
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include "page.h"
|
||||
#include "static.h"
|
||||
|
||||
constexpr uint16_t TEXT_FILE_MAXSIZE = 20480;
|
||||
|
||||
class ViewTextWindow : public Page
|
||||
{
|
||||
public:
|
||||
@@ -49,7 +47,7 @@ class ViewTextWindow : public Page
|
||||
};
|
||||
|
||||
void sdReadTextFileBlock(const char* filename, int& lines_count);
|
||||
void loadFirstScreen(void);
|
||||
void loadOneScreen(int offset);
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY,
|
||||
coord_t slideX, coord_t slideY) override;
|
||||
@@ -84,7 +82,6 @@ class ViewTextWindow : public Page
|
||||
std::string extension;
|
||||
unsigned int icon;
|
||||
|
||||
bool lastLine;
|
||||
uint16_t readCount;
|
||||
int longestLine;
|
||||
|
||||
@@ -98,6 +95,7 @@ class ViewTextWindow : public Page
|
||||
int maxLines;
|
||||
bool textBottom;
|
||||
bool isInSetup;
|
||||
bool openFromEnd;
|
||||
|
||||
void extractNameSansExt(void);
|
||||
void buildBody(Window* window);
|
||||
|
||||
@@ -767,6 +767,8 @@ const char STR_MODULE_RANGE[] = TR_MODULE_RANGE;
|
||||
const char STR_RECEIVER_OPTIONS[] = TR_RECEIVER_OPTIONS;
|
||||
const char STR_SPORT_UPDATE_POWER_MODE[] = TR_SPORT_UPDATE_POWER_MODE;
|
||||
const char STR_TOUCH_PANEL[] = TR_TOUCH_PANEL;
|
||||
const char STR_FILE_SIZE[] = TR_FILE_SIZE;
|
||||
const char STR_FILE_OPEN[] = TR_FILE_OPEN;
|
||||
|
||||
#if defined(COLORLCD)
|
||||
const char STR_ASSIGN_SPLASH[] = TR_ASSIGN_SPLASH;
|
||||
|
||||
@@ -196,6 +196,8 @@ extern const char STR_VPREC[];
|
||||
extern const char STR_VCELLINDEX[];
|
||||
extern const char STR_TOUCH_PANEL[];
|
||||
extern const char STR_ADCFILTERVALUES[];
|
||||
extern const char STR_FILE_SIZE[];
|
||||
extern const char STR_FILE_OPEN[];
|
||||
|
||||
extern const char STR_BLUETOOTH[];
|
||||
extern const char STR_BLUETOOTH_DISC[];
|
||||
|
||||
@@ -993,6 +993,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "自动""开启"
|
||||
#define TR_NO_TELEMETRY_SCREENS "无回传页面"
|
||||
#define TR_TOUCH_PANEL "触摸屏:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "名称"
|
||||
|
||||
@@ -1043,6 +1043,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Název"
|
||||
|
||||
@@ -1049,6 +1049,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis specific column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Name "
|
||||
|
||||
@@ -1049,6 +1049,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Name"
|
||||
|
||||
@@ -1049,6 +1049,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS TR("No hay pant. telemetría", "No hay pantallas de telemetría")
|
||||
#define TR_TOUCH_PANEL "Pantalla táctil:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Nombre"
|
||||
|
||||
@@ -1061,6 +1061,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Name"
|
||||
|
||||
@@ -1073,6 +1073,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Nom"
|
||||
|
||||
@@ -1068,6 +1068,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "Nessuno Schermo Telemetria"
|
||||
#define TR_TOUCH_PANEL "Schermo touch:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Nome"
|
||||
|
||||
@@ -1058,6 +1058,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Name"
|
||||
|
||||
@@ -1064,6 +1064,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Nazwa"
|
||||
|
||||
@@ -1072,6 +1072,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Name"
|
||||
|
||||
@@ -1072,6 +1072,8 @@
|
||||
#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
|
||||
#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
|
||||
#define TR_TOUCH_PANEL "Touch panel:"
|
||||
#define TR_FILE_SIZE "File size"
|
||||
#define TR_FILE_OPEN "Open anyway?"
|
||||
|
||||
// Horus and Taranis column headers
|
||||
#define TR_PHASES_HEADERS_NAME "Namn"
|
||||
|
||||
Reference in New Issue
Block a user