1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

feat(file_explorer): add API to use file explorer (#3601)

Co-authored-by: 100ask <team100ask@outlook.com>
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
Yobe Zhou 2022-09-04 22:57:15 +08:00 committed by GitHub
parent 3b7411893f
commit f09c04b935
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1477 additions and 0 deletions

14
Kconfig
View File

@ -1036,6 +1036,20 @@ menu "LVGL configuration"
help
Set the maximum number of candidate panels that can be displayed.
This needs to be adjusted according to the size of the screen.
config LV_USE_FILE_EXPLORER
bool "Enable file explorer"
default n
config LV_FILE_EXPLORER_PATH_MAX_LEN
int "Maximum length of path"
depends on LV_USE_FILE_EXPLORER
default 128
config LV_FILE_EXPLORER_QUICK_ACCESS
bool "Enable quick access bar"
depends on LV_USE_FILE_EXPLORER
default y
help
This can save some memory, but not much. After the quick access bar is created, it can be hidden by clicking the button at the top left corner of the browsing area, which is very useful for small screen devices.
endmenu
menu "Examples"

View File

@ -0,0 +1,161 @@
# File Explorer
`lv_file_explorer` provides an API to browse the contents of the file system. `lv_file_explorer` only provides the file browsing function, but does not provide the actual file operation function. In other words, you can't click a picture file to open and view the picture like a PC. `lv_file_explorer` will tell you the full path and name of the currently clicked file. The file operation function needs to be implemented by the user.
The file list in `lv_file_explorer` is based on [lv_table](/widgets/table), and the quick access bar is based on [lv_list](/widgets/list). Therefore, care should be taken to ensure that [lv_table](/widgets/table) and [lv_list](/widgets/list) are enabled.
<details>
<summary>中文</summary>
<p>
`lv_file_explorer` 提供API让我们可以浏览文件系统中的内容。`lv_file_explorer` 只提供了文件浏览功能并不提供实际的文件操作功能也就是说不能像PC那样点击一个图片文件就可以打开查看该图片。`lv_file_explorer` 会告诉您当前点击的文件的完整路径和名称,文件操作功能需要用户自己实现。
`lv_file_explorer` 中的文件列表基于 [lv_table](/widgets/table) 实现,快速访问栏基于 [lv_list](/widgets/list) 实现。因此,要注意确保使能了 `lv_table``lv_list`
</p>
</details>
## Usage
Enable `LV_USE_FILE_EXPLORER` in `lv_conf.h`.
First use `lv_file_explorer_create(lv_scr_act())` to create a file explorer, The default size is the screen size. After that, you can customize the style like widget.
<details>
<summary>中文</summary>
<p>
`lv_conf.h` 中打开 `LV_USE_FILE_EXPLORER`
首先,使用 `lv_file_explorer_create(lv_scr_act())` 函数创建一个文件浏览器,默认大小为屏幕大小,之后可以像组件那样自定义样式。
</p>
</details>
### Quick access
The quick access bar is optional. You can turn off `LV_FILE_EXPLORER_QUICK_ACCESS` in `lv_conf.h` so that the quick access bar will not be created. This can save some memory, but not much. After the quick access bar is created, it can be hidden by clicking the button at the top left corner of the browsing area, which is very useful for small screen devices.
You can use `lv_file_explorer_set_quick_access_path(file_explorer, LV_FILE_EXPLORER_QA_XX, "path")` to set the path of the quick access bar. The items of the quick access bar are fixed. Currently, there are the following items:
- `LV_FILE_EXPLORER_QA_HOME`
- `LV_FILE_EXPLORER_QA_MUSIC`
- `LV_FILE_EXPLORER_QA_PICTURES`
- `LV_FILE_EXPLORER_QA_VIDEO`
- `LV_FILE_EXPLORER_QA_DOCS`
- `LV_FILE_EXPLORER_QA_MNT`
- `LV_FILE_EXPLORER_QA_FS`
<details>
<summary>中文</summary>
<p>
快速访问栏是可选的,您可以在 `lv_conf.h` 中关闭 `LV_FILE_EXPLORER_QUICK_ACCESS`,这样快速访问栏就不会被创建出来,这能节省一些内存,但并不是很多。快速访问栏被创建出来之后,可以通过点击浏览区域顶部左上角的按钮隐藏起来,这对于小屏幕设备非常有用。
可以通过 `lv_file_explorer_set_quick_access_path(file_explorer, LV_FILE_EXPLORER_QA_XX, "path")` 设置快速访问栏的路径,快速访问栏的项目是固定的,目前有以下项目:
- `LV_FILE_EXPLORER_QA_HOME`
- `LV_FILE_EXPLORER_QA_MUSIC`
- `LV_FILE_EXPLORER_QA_PICTURES`
- `LV_FILE_EXPLORER_QA_VIDEO`
- `LV_FILE_EXPLORER_QA_DOCS`
- `LV_FILE_EXPLORER_QA_MNT`
- `LV_FILE_EXPLORER_QA_FS`
</p>
</details>
### Sort
You can use `lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_XX)` to set sorting method. There are the following sorting methods:
- `LV_EXPLORER_SORT_NONE`
- `LV_EXPLORER_SORT_KIND`
You can customize the sorting. Before custom sort, please set the default sorting to `LV_EXPLORER_SORT_NONE`. The default is `LV_EXPLORER_SORT_NONE`.
<details>
<summary>中文</summary>
<p>
可以通过 `lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_XX)` 设置排序方式,有以下排序方式:
- `LV_EXPLORER_SORT_NONE`
- `LV_EXPLORER_SORT_KIND`
您可以自定义排序规则,在这之前请先将排序规则设置为 `LV_EXPLORER_SORT_NONE` 然后在 `LV_EVENT_READY` 事件中处理。默认的排序规则是 `LV_EXPLORER_SORT_NONE`
</p>
</details>
## Event
- `LV_EVENT_READY` sent shen a directory is opened. You can customize the sort.
- `LV_EVENT_VALUE_CHANGED` sent when an item(file) in the file list is clicked.
You can use `lv_file_explorer_get_cur_path` to get the current path and `lv_file_explorer_get_sel_fn` to get the name of the currently selected file in the event processing function. For example:
```c
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char * cur_path = lv_file_explorer_get_cur_path(obj);
char * sel_fn = lv_file_explorer_get_sel_fn(obj);
LV_LOG_USER("%s%s", cur_path, sel_fn);
}
}
```
You can also save the obtained **path** and **file** name into an array through functions such as *strcpy* and *strcat* for later use.
<details>
<summary>中文</summary>
<p>
- 当打开一个目录后会发送 `LV_EVENT_READY` 事件。您可以在这里自定义排序规则。
- 当文件列表中的项目(文件)被点击时会发送 `LV_EVENT_VALUE_CHANGED` 事件。
可以在事件处理函数中通过 `lv_file_explorer_get_cur_path` 获取当前所在的路径,通过 `lv_file_explorer_get_sel_fn` 获取当前选中的文件的名称。比如:
```c
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char * cur_path = lv_file_explorer_get_cur_path(obj);
char * sel_fn = lv_file_explorer_get_sel_fn(obj);
LV_LOG_USER("%s%s", cur_path, sel_fn);
}
}
```
您还可以将获取到的 **路径****文件名称** 通过例如 strcpy 和 strcat 函数保存到一个数组中,方便后续使用。
</p>
</details>
## Example
```eval_rst
.. include:: ../../examples/others/file_explorer/index.rst
```
## API
```eval_rst
.. doxygenfile:: lv_file_explorer.h
:project: lvgl
```

View File

@ -9,6 +9,7 @@
snapshot
monkey
gridnav
file_explorer
fragment
msg
imgfont

View File

@ -0,0 +1,18 @@
Simple File Explorer
"""""""""""""""""""""""""
.. lv_example:: others/ime/lv_example_file_explorer_1
:language: c
Control File Explorer
"""""""""""""""""""""""""
.. lv_example:: others/ime/lv_example_file_explorer_2
:language: c
Custom sort
"""""""""""""""""""""""""
.. lv_example:: others/ime/lv_example_file_explorer_3
:language: c

View File

@ -0,0 +1,40 @@
/**
* @file lv_example_file_explorer.h
*
*/
#ifndef LV_EX_FILE_EXPLORER_H
#define LV_EX_FILE_EXPLORER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_example_file_explorer_1(void);
void lv_example_file_explorer_2(void);
void lv_example_file_explorer_3(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EX_FILE_EXPLORER_H*/

View File

@ -0,0 +1,61 @@
#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_USE_FILE_EXPLORER && (LV_USE_FS_STDIO || LV_USE_FS_POSIX || LV_USE_FS_WIN32 || LV_USE_FS_FATFS) && LV_BUILD_EXAMPLES
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char * cur_path = lv_file_explorer_get_current_path(obj);
const char * sel_fn = lv_file_explorer_get_selected_file_name(obj);
uint16_t path_len = strlen(cur_path);
uint16_t fn_len = strlen(sel_fn);
if((path_len + fn_len) <= LV_FILE_EXPLORER_PATH_MAX_LEN) {
char file_info[LV_FILE_EXPLORER_PATH_MAX_LEN];
strcpy(file_info, cur_path);
strcat(file_info, sel_fn);
LV_LOG_USER("%s", file_info);
}
else LV_LOG_USER("%s%s", cur_path, sel_fn);
}
}
void lv_example_file_explorer_1(void)
{
lv_obj_t * file_explorer = lv_file_explorer_create(lv_scr_act());
lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_KIND);
#if LV_USE_FS_WIN32
lv_file_explorer_open_dir(file_explorer, "D:");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:/Users/Public/Desktop");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:/Users/Public/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:/Users/Public/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:/Users/Public/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:/Users/Public/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "D:");
#endif
#else
/* linux */
lv_file_explorer_open_dir(file_explorer, "/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "/home");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "/home/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "/home/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "/home/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "/home/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "/");
#endif
#endif
lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL);
}
#endif

View File

@ -0,0 +1,121 @@
#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_USE_FILE_EXPLORER && (LV_USE_FS_STDIO || LV_USE_FS_POSIX || LV_USE_FS_WIN32 || LV_USE_FS_FATFS) && LV_BUILD_EXAMPLES
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char * cur_path = lv_file_explorer_get_current_path(obj);
const char * sel_fn = lv_file_explorer_get_selected_file_name(obj);
uint16_t path_len = strlen(cur_path);
uint16_t fn_len = strlen(sel_fn);
if((path_len + fn_len) <= LV_FILE_EXPLORER_PATH_MAX_LEN) {
char file_info[LV_FILE_EXPLORER_PATH_MAX_LEN];
strcpy(file_info, cur_path);
strcat(file_info, sel_fn);
LV_LOG_USER("%s", file_info);
}
else LV_LOG_USER("%s%s", cur_path, sel_fn);
}
}
static void btn_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * btn = lv_event_get_target(e);
lv_obj_t * file_explorer = lv_event_get_user_data(e);
if(code == LV_EVENT_VALUE_CHANGED) {
if(lv_obj_has_state(btn, LV_STATE_CHECKED))
lv_obj_add_flag(file_explorer, LV_OBJ_FLAG_HIDDEN);
else
lv_obj_clear_flag(file_explorer, LV_OBJ_FLAG_HIDDEN);
}
}
static void dd_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * dd = lv_event_get_target(e);
lv_obj_t * fe_quick_access_obj = lv_event_get_user_data(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char buf[32];
lv_dropdown_get_selected_str(dd, buf, sizeof(buf));
if(strcmp(buf, "NONE") == 0) {
lv_file_explorer_set_sort(fe_quick_access_obj, LV_EXPLORER_SORT_NONE);
}
else if(strcmp(buf, "KIND") == 0) {
lv_file_explorer_set_sort(fe_quick_access_obj, LV_EXPLORER_SORT_KIND);
}
}
}
void lv_example_file_explorer_2(void)
{
lv_obj_t * file_explorer = lv_file_explorer_create(lv_scr_act());
#if LV_USE_FS_WIN32
lv_file_explorer_open_dir(file_explorer, "D:");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:/Users/Public/Desktop");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:/Users/Public/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:/Users/Public/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:/Users/Public/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:/Users/Public/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "D:");
#endif
#else
/* linux */
lv_file_explorer_open_dir(file_explorer, "/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "/home");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "/home/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "/home/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "/home/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "/home/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "/");
#endif
#endif
lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL);
/*Quick access status control button*/
lv_obj_t * fe_quick_access_obj = lv_file_explorer_get_quick_access_area(file_explorer);
lv_obj_t * fe_header_obj = lv_file_explorer_get_header(file_explorer);
lv_obj_t * btn = lv_btn_create(fe_header_obj);
lv_obj_set_style_radius(btn, 2, 0);
lv_obj_set_style_pad_all(btn, 4, 0);
lv_obj_align(btn, LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_LIST);
lv_obj_center(label);
lv_obj_add_event_cb(btn, btn_event_handler, LV_EVENT_VALUE_CHANGED, fe_quick_access_obj);
/*Sort control*/
static const char * opts = "NONE\n"
"KIND";
lv_obj_t * dd = lv_dropdown_create(fe_header_obj);
lv_obj_set_style_radius(dd, 4, 0);
lv_obj_set_style_pad_all(dd, 0, 0);
lv_obj_set_size(dd, LV_PCT(30), LV_SIZE_CONTENT);
lv_dropdown_set_options_static(dd, opts);
lv_obj_align(dd, LV_ALIGN_RIGHT_MID, 0, 0);
//lv_obj_align_to(dd, btn, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
lv_obj_add_event_cb(dd, dd_event_handler, LV_EVENT_VALUE_CHANGED, file_explorer);
}
#endif

View File

@ -0,0 +1,107 @@
#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_USE_FILE_EXPLORER && (LV_USE_FS_STDIO || LV_USE_FS_POSIX || LV_USE_FS_WIN32 || LV_USE_FS_FATFS) && LV_BUILD_EXAMPLES
static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j)
{
const char * tmp;
tmp = lv_table_get_cell_value(tb, i, 0);
lv_table_set_cell_value(tb, 0, 2, tmp);
lv_table_set_cell_value(tb, i, 0, lv_table_get_cell_value(tb, j, 0));
lv_table_set_cell_value(tb, j, 0, lv_table_get_cell_value(tb, 0, 2));
tmp = lv_table_get_cell_value(tb, i, 1);
lv_table_set_cell_value(tb, 0, 2, tmp);
lv_table_set_cell_value(tb, i, 1, lv_table_get_cell_value(tb, j, 1));
lv_table_set_cell_value(tb, j, 1, lv_table_get_cell_value(tb, 0, 2));
}
/*Quick sort 3 way*/
static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi)
{
if(lo >= hi) return;
int16_t lt = lo;
int16_t i = lo + 1;
int16_t gt = hi;
const char * v = lv_table_get_cell_value(tb, lo, 1);
while(i <= gt) {
if(strcmp(lv_table_get_cell_value(tb, i, 1), v) < 0)
exch_table_item(tb, lt++, i++);
else if(strcmp(lv_table_get_cell_value(tb, i, 1), v) > 0)
exch_table_item(tb, i, gt--);
else
i++;
}
sort_by_file_kind(tb, lo, lt - 1);
sort_by_file_kind(tb, gt + 1, hi);
}
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char * cur_path = lv_file_explorer_get_current_path(obj);
const char * sel_fn = lv_file_explorer_get_selected_file_name(obj);
uint16_t path_len = strlen(cur_path);
uint16_t fn_len = strlen(sel_fn);
if((path_len + fn_len) <= LV_FILE_EXPLORER_PATH_MAX_LEN) {
char file_info[LV_FILE_EXPLORER_PATH_MAX_LEN];
strcpy(file_info, cur_path);
strcat(file_info, sel_fn);
LV_LOG_USER("%s", file_info);
}
else LV_LOG_USER("%s%s", cur_path, sel_fn);
}
else if(code == LV_EVENT_READY) {
lv_obj_t * tb = lv_file_explorer_get_file_table(obj);
uint16_t sum = lv_table_get_row_cnt(tb);
sort_by_file_kind(tb, 0, (sum - 1));
}
}
void lv_example_file_explorer_3(void)
{
lv_obj_t * file_explorer = lv_file_explorer_create(lv_scr_act());
/*Before custom sort, please set the default sorting to NONE. The default is NONE.*/
lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_NONE);
#if LV_USE_FS_WIN32
lv_file_explorer_open_dir(file_explorer, "D:");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:/Users/Public/Desktop");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:/Users/Public/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:/Users/Public/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:/Users/Public/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:/Users/Public/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "D:");
#endif
#else
/* linux */
lv_file_explorer_open_dir(file_explorer, "/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "/home");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "/home/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "/home/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "/home/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "/home/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "/");
#endif
#endif
lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL);
}
#endif

View File

@ -13,6 +13,7 @@ extern "C" {
/*********************
* INCLUDES
*********************/
#include "file_explorer/lv_example_file_explorer.h"
#include "fragment/lv_example_fragment.h"
#include "gridnav/lv_example_gridnav.h"
#include "ime/lv_example_ime_pinyin.h"

View File

@ -695,6 +695,17 @@
#endif // LV_IME_PINYIN_USE_K9_MODE
#endif
/*1: Enable file explorer*/
/*Requires: lv_table*/
#define LV_USE_FILE_EXPLORER 0
#if LV_USE_FILE_EXPLORER
/*Maximum length of path*/
#define LV_FILE_EXPLORER_PATH_MAX_LEN (128)
/*Quick access bar, 1:use, 0:not use*/
/*Requires: lv_list*/
#define LV_FILE_EXPLORER_QUICK_ACCESS 1
#endif
/*==================
* EXAMPLES
*==================*/

1
lvgl.h
View File

@ -83,6 +83,7 @@ extern "C" {
#include "src/others/imgfont/lv_imgfont.h"
#include "src/others/msg/lv_msg.h"
#include "src/others/ime/lv_ime_pinyin.h"
#include "src/others/file_explorer/lv_file_explorer.h"
#include "src/libs/bmp/lv_bmp.h"
#include "src/libs/fsdrv/lv_fsdrv.h"

View File

@ -2325,6 +2325,39 @@
#endif // LV_IME_PINYIN_USE_K9_MODE
#endif
/*1: Enable file explorer*/
/*Requires: lv_table*/
#ifndef LV_USE_FILE_EXPLORER
#ifdef CONFIG_LV_USE_FILE_EXPLORER
#define LV_USE_FILE_EXPLORER CONFIG_LV_USE_FILE_EXPLORER
#else
#define LV_USE_FILE_EXPLORER 0
#endif
#endif
#if LV_USE_FILE_EXPLORER
/*Maximum length of path*/
#ifndef LV_FILE_EXPLORER_PATH_MAX_LEN
#ifdef CONFIG_LV_FILE_EXPLORER_PATH_MAX_LEN
#define LV_FILE_EXPLORER_PATH_MAX_LEN CONFIG_LV_FILE_EXPLORER_PATH_MAX_LEN
#else
#define LV_FILE_EXPLORER_PATH_MAX_LEN (128)
#endif
#endif
/*Quick access bar, 1:use, 0:not use*/
/*Requires: lv_list*/
#ifndef LV_FILE_EXPLORER_QUICK_ACCESS
#ifdef _LV_KCONFIG_PRESENT
#ifdef CONFIG_LV_FILE_EXPLORER_QUICK_ACCESS
#define LV_FILE_EXPLORER_QUICK_ACCESS CONFIG_LV_FILE_EXPLORER_QUICK_ACCESS
#else
#define LV_FILE_EXPLORER_QUICK_ACCESS 0
#endif
#else
#define LV_FILE_EXPLORER_QUICK_ACCESS 1
#endif
#endif
#endif
/*==================
* EXAMPLES
*==================*/

View File

@ -0,0 +1,717 @@
/**
* @file lv_file_explorer.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_file_explorer.h"
#if LV_USE_FILE_EXPLORER != 0
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_file_explorer_class
#define FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH (22)
#define FILE_EXPLORER_BROWSER_AREA_WIDTH (100 - FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_file_explorer_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void browser_file_event_handler(lv_event_t * e);
#if LV_FILE_EXPLORER_QUICK_ACCESS
static void quick_access_event_handler(lv_event_t * e);
static void quick_access_area_event_handler(lv_event_t * e);
#endif
static void init_style(lv_obj_t * obj);
static void show_dir(lv_obj_t * obj, const char * path);
static void strip_ext(char * dir);
static void file_explorer_sort(lv_obj_t * obj);
static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi);
static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j);
static bool is_end_with(const char * str1, const char * str2);
/**********************
* STATIC VARIABLES
**********************/
static lv_style_t quick_access_list_btn_style;
const lv_obj_class_t lv_file_explorer_class = {
.constructor_cb = lv_file_explorer_constructor,
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_file_explorer_t),
.base_class = &lv_obj_class
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_obj_t * lv_file_explorer_create(lv_obj_t * parent)
{
LV_LOG_INFO("begin");
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
return obj;
}
/*=====================
* Setter functions
*====================*/
#if LV_FILE_EXPLORER_QUICK_ACCESS
void lv_file_explorer_set_quick_access_path(lv_obj_t * obj, lv_file_explorer_dir_t dir, const char * path)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
/*If path is unavailable */
if((path == NULL) || (strlen(path) <= 0)) return;
char ** dir_str = NULL;
switch(dir) {
case LV_EXPLORER_HOME_DIR:
dir_str = &(explorer->home_dir);
break;
case LV_EXPLORER_MUSIC_DIR:
dir_str = &(explorer->music_dir);
break;
case LV_EXPLORER_PICTURES_DIR:
dir_str = &(explorer->pictures_dir);
break;
case LV_EXPLORER_VIDEO_DIR:
dir_str = &(explorer->video_dir);
break;
case LV_EXPLORER_DOCS_DIR:
dir_str = &(explorer->docs_dir);
break;
case LV_EXPLORER_FS_DIR:
dir_str = &(explorer->fs_dir);
break;
default:
return;
break;
}
/*Free the old text*/
if(*dir_str != NULL) {
lv_free(*dir_str);
*dir_str = NULL;
}
/*Get the size of the text*/
size_t len = strlen(path) + 1;
/*Allocate space for the new text*/
*dir_str = lv_malloc(len);
LV_ASSERT_MALLOC(*dir_str);
if(*dir_str == NULL) return;
strcpy(*dir_str, path);
}
#endif
void lv_file_explorer_set_sort(lv_obj_t * obj, lv_file_explorer_sort_t sort)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
explorer->sort = sort;
file_explorer_sort(obj);
}
/*=====================
* Getter functions
*====================*/
const char * lv_file_explorer_get_selected_file_name(const lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->sel_fn;
}
const char * lv_file_explorer_get_current_path(const lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->current_path;
}
lv_obj_t * lv_file_explorer_get_file_table(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->file_table;
}
lv_obj_t * lv_file_explorer_get_header(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->head_area;
}
lv_obj_t * lv_file_explorer_get_quick_access_area(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->quick_access_area;
}
lv_obj_t * lv_file_explorer_get_path_label(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->path_label;
}
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_obj_t * lv_file_explorer_get_places_list(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->list_places;
}
lv_obj_t * lv_file_explorer_get_device_list(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->list_device;
}
#endif
lv_file_explorer_sort_t lv_file_explorer_get_sort(const lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
return explorer->sort;
}
/*=====================
* Other functions
*====================*/
void lv_file_explorer_open_dir(lv_obj_t * obj, const char * dir)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
show_dir(obj, dir);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_file_explorer_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_UNUSED(class_p);
LV_TRACE_OBJ_CREATE("begin");
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
#if LV_FILE_EXPLORER_QUICK_ACCESS
explorer->home_dir = NULL;
explorer->video_dir = NULL;
explorer->pictures_dir = NULL;
explorer->music_dir = NULL;
explorer->docs_dir = NULL;
explorer->fs_dir = NULL;
#endif
explorer->sort = LV_EXPLORER_SORT_NONE;
lv_memzero(explorer->current_path, sizeof(explorer->current_path));
lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN);
explorer->cont = lv_obj_create(obj);
lv_obj_set_width(explorer->cont, LV_PCT(100));
lv_obj_set_flex_grow(explorer->cont, 1);
#if LV_FILE_EXPLORER_QUICK_ACCESS
/*Quick access bar area on the left*/
explorer->quick_access_area = lv_obj_create(explorer->cont);
lv_obj_set_size(explorer->quick_access_area, LV_PCT(FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH), LV_PCT(100));
lv_obj_set_flex_flow(explorer->quick_access_area, LV_FLEX_FLOW_COLUMN);
lv_obj_add_event_cb(explorer->quick_access_area, quick_access_area_event_handler, LV_EVENT_ALL,
explorer);
#endif
/*File table area on the right*/
explorer->browser_area = lv_obj_create(explorer->cont);
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_obj_set_size(explorer->browser_area, LV_PCT(FILE_EXPLORER_BROWSER_AREA_WIDTH), LV_PCT(100));
#else
lv_obj_set_size(explorer->browser_area, LV_PCT(100), LV_PCT(100));
#endif
lv_obj_set_flex_flow(explorer->browser_area, LV_FLEX_FLOW_COLUMN);
/*The area displayed above the file browse list(head)*/
explorer->head_area = lv_obj_create(explorer->browser_area);
lv_obj_set_size(explorer->head_area, LV_PCT(100), LV_PCT(14));
lv_obj_clear_flag(explorer->head_area, LV_OBJ_FLAG_SCROLLABLE);
#if LV_FILE_EXPLORER_QUICK_ACCESS
/*Two lists of quick access bar*/
lv_obj_t * btn;
/*list 1*/
explorer->list_device = lv_list_create(explorer->quick_access_area);
lv_obj_set_size(explorer->list_device, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_color(lv_list_add_text(explorer->list_device, "DEVICE"), lv_palette_main(LV_PALETTE_ORANGE), 0);
btn = lv_list_add_btn(explorer->list_device, NULL, LV_SYMBOL_DRIVE " File System");
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
/*list 2*/
explorer->list_places = lv_list_create(explorer->quick_access_area);
lv_obj_set_size(explorer->list_places, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_color(lv_list_add_text(explorer->list_places, "PLACES"), lv_palette_main(LV_PALETTE_LIME), 0);
btn = lv_list_add_btn(explorer->list_places, NULL, LV_SYMBOL_HOME " HOME");
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
btn = lv_list_add_btn(explorer->list_places, NULL, LV_SYMBOL_VIDEO " Video");
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
btn = lv_list_add_btn(explorer->list_places, NULL, LV_SYMBOL_IMAGE " Pictures");
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
btn = lv_list_add_btn(explorer->list_places, NULL, LV_SYMBOL_AUDIO " Music");
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
btn = lv_list_add_btn(explorer->list_places, NULL, LV_SYMBOL_FILE " Documents");
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
#endif
/*Show current path*/
explorer->path_label = lv_label_create(explorer->head_area);
lv_label_set_text(explorer->path_label, LV_SYMBOL_EYE_OPEN"https://lvgl.io");
lv_obj_center(explorer->path_label);
/*Table showing the contents of the table of contents*/
explorer->file_table = lv_table_create(explorer->browser_area);
lv_obj_set_size(explorer->file_table, LV_PCT(100), LV_PCT(86));
lv_table_set_col_width(explorer->file_table, 0, LV_PCT(100));
lv_table_set_col_cnt(explorer->file_table, 1);
lv_obj_add_event_cb(explorer->file_table, browser_file_event_handler, LV_EVENT_ALL, obj);
/*only scroll up and down*/
lv_obj_set_scroll_dir(explorer->file_table, LV_DIR_TOP | LV_DIR_BOTTOM);
/*Initialize style*/
init_style(obj);
LV_TRACE_OBJ_CREATE("finished");
}
static void init_style(lv_obj_t * obj)
{
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
/*lv_file_explorer obj style*/
lv_obj_set_style_radius(obj, 0, 0);
lv_obj_set_style_bg_color(obj, lv_color_hex(0xf2f1f6), 0);
/*main container style*/
lv_obj_set_style_radius(explorer->cont, 0, 0);
lv_obj_set_style_bg_opa(explorer->cont, LV_OPA_0, 0);
lv_obj_set_style_border_width(explorer->cont, 0, 0);
lv_obj_set_style_outline_width(explorer->cont, 0, 0);
lv_obj_set_style_pad_column(explorer->cont, 0, 0);
lv_obj_set_style_pad_row(explorer->cont, 0, 0);
lv_obj_set_style_flex_flow(explorer->cont, LV_FLEX_FLOW_ROW, 0);
lv_obj_set_style_pad_all(explorer->cont, 0, 0);
lv_obj_set_style_layout(explorer->cont, LV_LAYOUT_FLEX, 0);
/*head cont style*/
lv_obj_set_style_radius(explorer->head_area, 0, 0);
lv_obj_set_style_border_width(explorer->head_area, 0, 0);
lv_obj_set_style_pad_top(explorer->head_area, 0, 0);
#if LV_FILE_EXPLORER_QUICK_ACCESS
/*Quick access bar container style*/
lv_obj_set_style_pad_all(explorer->quick_access_area, 0, 0);
lv_obj_set_style_pad_row(explorer->quick_access_area, 20, 0);
lv_obj_set_style_radius(explorer->quick_access_area, 0, 0);
lv_obj_set_style_border_width(explorer->quick_access_area, 1, 0);
lv_obj_set_style_outline_width(explorer->quick_access_area, 0, 0);
lv_obj_set_style_bg_color(explorer->quick_access_area, lv_color_hex(0xf2f1f6), 0);
#endif
/*File browser container style*/
lv_obj_set_style_pad_all(explorer->browser_area, 0, 0);
lv_obj_set_style_pad_row(explorer->browser_area, 0, 0);
lv_obj_set_style_radius(explorer->browser_area, 0, 0);
lv_obj_set_style_border_width(explorer->browser_area, 0, 0);
lv_obj_set_style_outline_width(explorer->browser_area, 0, 0);
lv_obj_set_style_bg_color(explorer->browser_area, lv_color_hex(0xffffff), 0);
/*Style of the table in the browser container*/
lv_obj_set_style_bg_color(explorer->file_table, lv_color_hex(0xffffff), 0);
lv_obj_set_style_pad_all(explorer->file_table, 0, 0);
lv_obj_set_style_radius(explorer->file_table, 0, 0);
lv_obj_set_style_border_width(explorer->file_table, 0, 0);
lv_obj_set_style_outline_width(explorer->file_table, 0, 0);
#if LV_FILE_EXPLORER_QUICK_ACCESS
/*Style of the list in the quick access bar*/
lv_obj_set_style_border_width(explorer->list_device, 0, 0);
lv_obj_set_style_outline_width(explorer->list_device, 0, 0);
lv_obj_set_style_radius(explorer->list_device, 0, 0);
lv_obj_set_style_pad_all(explorer->list_device, 0, 0);
lv_obj_set_style_border_width(explorer->list_places, 0, 0);
lv_obj_set_style_outline_width(explorer->list_places, 0, 0);
lv_obj_set_style_radius(explorer->list_places, 0, 0);
lv_obj_set_style_pad_all(explorer->list_places, 0, 0);
/*Style of the quick access list btn in the quick access bar*/
lv_style_init(&quick_access_list_btn_style);
lv_style_set_border_width(&quick_access_list_btn_style, 0);
lv_style_set_bg_color(&quick_access_list_btn_style, lv_color_hex(0xf2f1f6));
uint32_t i, j;
for(i = 0; i < lv_obj_get_child_cnt(explorer->quick_access_area); i++) {
lv_obj_t * child = lv_obj_get_child(explorer->quick_access_area, i);
if(lv_obj_check_type(child, &lv_list_class)) {
for(j = 0; j < lv_obj_get_child_cnt(child); j++) {
lv_obj_t * list_child = lv_obj_get_child(child, j);
if(lv_obj_check_type(list_child, &lv_list_btn_class)) {
lv_obj_add_style(list_child, &quick_access_list_btn_style, 0);
}
}
}
}
#endif
}
#if LV_FILE_EXPLORER_QUICK_ACCESS
static void quick_access_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * btn = lv_event_get_target(e);
lv_obj_t * obj = lv_event_get_user_data(e);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
if(code == LV_EVENT_CLICKED) {
char ** path = NULL;
lv_obj_t * label = lv_obj_get_child(btn, -1);
char * label_text = lv_label_get_text(label);
if((strcmp(label_text, LV_SYMBOL_HOME " HOME") == 0)) {
path = &(explorer->home_dir);
}
else if((strcmp(label_text, LV_SYMBOL_VIDEO " Video") == 0)) {
path = &(explorer->video_dir);
}
else if((strcmp(label_text, LV_SYMBOL_IMAGE " Pictures") == 0)) {
path = &(explorer->pictures_dir);
}
else if((strcmp(label_text, LV_SYMBOL_AUDIO " Music") == 0)) {
path = &(explorer->music_dir);
}
else if((strcmp(label_text, LV_SYMBOL_FILE " Documents") == 0)) {
path = &(explorer->docs_dir);
}
else if((strcmp(label_text, LV_SYMBOL_DRIVE " File System") == 0)) {
path = &(explorer->fs_dir);
}
if(path != NULL)
show_dir(obj, *path);
}
}
static void quick_access_area_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * area = lv_event_get_target(e);
lv_obj_t * obj = lv_event_get_user_data(e);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
if(code == LV_EVENT_LAYOUT_CHANGED) {
if(lv_obj_has_flag(area, LV_OBJ_FLAG_HIDDEN))
lv_obj_set_size(explorer->browser_area, LV_PCT(100), LV_PCT(100));
else
lv_obj_set_size(explorer->browser_area, LV_PCT(FILE_EXPLORER_BROWSER_AREA_WIDTH), LV_PCT(100));
}
}
#endif
static void browser_file_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_user_data(e);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
if(code == LV_EVENT_VALUE_CHANGED) {
char file_name[LV_FILE_EXPLORER_PATH_MAX_LEN];
const char * str_fn = NULL;
uint16_t row;
uint16_t col;
lv_memzero(file_name, sizeof(file_name));
lv_table_get_selected_cell(explorer->file_table, &row, &col);
str_fn = lv_table_get_cell_value(explorer->file_table, row, col);
str_fn = str_fn + 5;
if((strcmp(str_fn, ".") == 0)) return;
if((strcmp(str_fn, "..") == 0) && (strlen(explorer->current_path) > 3)) {
strip_ext(explorer->current_path);
/*Remove the last '/' character*/
strip_ext(explorer->current_path);
lv_snprintf_builtin((char *)file_name, sizeof(file_name), "%s", explorer->current_path);
}
else {
if(strcmp(str_fn, "..") != 0) {
lv_snprintf_builtin((char *)file_name, sizeof(file_name), "%s%s", explorer->current_path, str_fn);
}
}
lv_fs_dir_t dir;
if(lv_fs_dir_open(&dir, file_name) == LV_FS_RES_OK) {
lv_fs_dir_close(&dir);
show_dir(obj, (char *)file_name);
}
else {
if(strcmp(str_fn, "..") != 0) {
explorer->sel_fn = str_fn;
lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
}
}
}
else if(code == LV_EVENT_SIZE_CHANGED) {
lv_table_set_col_width(explorer->file_table, 0, lv_obj_get_width(explorer->file_table));
}
else if((code == LV_EVENT_CLICKED) || (code == LV_EVENT_RELEASED)) {
lv_event_send(obj, LV_EVENT_CLICKED, NULL);
}
}
static void show_dir(lv_obj_t * obj, const char * path)
{
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
char fn[LV_FILE_EXPLORER_PATH_MAX_LEN];
uint16_t index = 0;
lv_fs_dir_t dir;
lv_fs_res_t res;
res = lv_fs_dir_open(&dir, path);
if(res != LV_FS_RES_OK) {
LV_LOG_USER("Open dir error %d!", res);
return;
}
lv_table_set_cell_value_fmt(explorer->file_table, index++, 0, LV_SYMBOL_DIRECTORY " %s", ".");
lv_table_set_cell_value_fmt(explorer->file_table, index++, 0, LV_SYMBOL_DIRECTORY " %s", "..");
lv_table_set_cell_value(explorer->file_table, 0, 1, "0");
lv_table_set_cell_value(explorer->file_table, 1, 1, "0");
while(1) {
res = lv_fs_dir_read(&dir, fn);
if(res != LV_FS_RES_OK) {
LV_LOG_USER("Driver, file or directory is not exists %d!", res);
break;
}
/*fn is empty, if not more files to read*/
if(strlen(fn) == 0) {
LV_LOG_USER("Not more files to read!");
break;
}
if((is_end_with(fn, ".png") == true) || (is_end_with(fn, ".PNG") == true) || \
(is_end_with(fn, ".jpg") == true) || (is_end_with(fn, ".JPG") == true) || \
(is_end_with(fn, ".bmp") == true) || (is_end_with(fn, ".BMP") == true) || \
(is_end_with(fn, ".gif") == true) || (is_end_with(fn, ".GIF") == true)) {
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_IMAGE " %s", fn);
lv_table_set_cell_value(explorer->file_table, index, 1, "1");
}
else if((is_end_with(fn, ".mp3") == true) || (is_end_with(fn, ".MP3") == true)) {
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_AUDIO " %s", fn);
lv_table_set_cell_value(explorer->file_table, index, 1, "2");
}
else if((is_end_with(fn, ".mp4") == true) || (is_end_with(fn, ".MP4") == true)) {
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_VIDEO " %s", fn);
lv_table_set_cell_value(explorer->file_table, index, 1, "3");
}
else if((is_end_with(fn, ".") == true) || (is_end_with(fn, "..") == true)) {
/*is dir*/
continue;
}
else if(fn[0] == '/') {/*is dir*/
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_DIRECTORY " %s", fn + 1);
lv_table_set_cell_value(explorer->file_table, index, 1, "0");
}
else {
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_FILE " %s", fn);
lv_table_set_cell_value(explorer->file_table, index, 1, "4");
}
index++;
}
lv_fs_dir_close(&dir);
lv_table_set_row_cnt(explorer->file_table, index);
file_explorer_sort(obj);
lv_event_send(obj, LV_EVENT_READY, NULL);
/*Move the table to the top*/
lv_obj_scroll_to_y(explorer->file_table, 0, LV_ANIM_OFF);
lv_memzero(explorer->current_path, sizeof(explorer->current_path));
strcpy(explorer->current_path, path);
lv_label_set_text_fmt(explorer->path_label, LV_SYMBOL_EYE_OPEN" %s", path);
size_t current_path_len = strlen(explorer->current_path);
if((*((explorer->current_path) + current_path_len) != '/') && (current_path_len < LV_FILE_EXPLORER_PATH_MAX_LEN)) {
*((explorer->current_path) + current_path_len) = '/';
}
}
/*Remove the specified suffix*/
static void strip_ext(char * dir)
{
char * end = dir + strlen(dir);
while(end >= dir && *end != '/') {
--end;
}
if(end > dir) {
*end = '\0';
}
else if(end == dir) {
*(end + 1) = '\0';
}
}
static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j)
{
const char * tmp;
tmp = lv_table_get_cell_value(tb, i, 0);
lv_table_set_cell_value(tb, 0, 2, tmp);
lv_table_set_cell_value(tb, i, 0, lv_table_get_cell_value(tb, j, 0));
lv_table_set_cell_value(tb, j, 0, lv_table_get_cell_value(tb, 0, 2));
tmp = lv_table_get_cell_value(tb, i, 1);
lv_table_set_cell_value(tb, 0, 2, tmp);
lv_table_set_cell_value(tb, i, 1, lv_table_get_cell_value(tb, j, 1));
lv_table_set_cell_value(tb, j, 1, lv_table_get_cell_value(tb, 0, 2));
}
static void file_explorer_sort(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
uint16_t sum = lv_table_get_row_cnt(explorer->file_table);
if(sum > 1) {
switch(explorer->sort) {
case LV_EXPLORER_SORT_NONE:
break;
case LV_EXPLORER_SORT_KIND:
sort_by_file_kind(explorer->file_table, 0, (sum - 1));
break;
default:
break;
}
}
}
/*Quick sort 3 way*/
static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi)
{
if(lo >= hi) return;
int16_t lt = lo;
int16_t i = lo + 1;
int16_t gt = hi;
const char * v = lv_table_get_cell_value(tb, lo, 1);
while(i <= gt) {
if(strcmp(lv_table_get_cell_value(tb, i, 1), v) < 0)
exch_table_item(tb, lt++, i++);
else if(strcmp(lv_table_get_cell_value(tb, i, 1), v) > 0)
exch_table_item(tb, i, gt--);
else
i++;
}
sort_by_file_kind(tb, lo, lt - 1);
sort_by_file_kind(tb, gt + 1, hi);
}
static bool is_end_with(const char * str1, const char * str2)
{
if(str1 == NULL || str2 == NULL)
return false;
uint16_t len1 = strlen(str1);
uint16_t len2 = strlen(str2);
if((len1 < len2) || (len1 == 0 || len2 == 0))
return false;
while(len2 >= 1) {
if(str2[len2 - 1] != str1[len1 - 1])
return false;
len2--;
len1--;
}
return true;
}
#endif /*LV_USE_FILE_EXPLORER*/

View File

@ -0,0 +1,190 @@
/**
* @file lv_file_explorer.h
*
*/
#ifndef LV_FILE_EXPLORER_H
#define LV_FILE_EXPLORER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FILE_EXPLORER != 0
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_EXPLORER_SORT_NONE,
LV_EXPLORER_SORT_KIND,
} lv_file_explorer_sort_t;
#if LV_FILE_EXPLORER_QUICK_ACCESS
typedef enum {
LV_EXPLORER_HOME_DIR,
LV_EXPLORER_MUSIC_DIR,
LV_EXPLORER_PICTURES_DIR,
LV_EXPLORER_VIDEO_DIR,
LV_EXPLORER_DOCS_DIR,
LV_EXPLORER_FS_DIR,
} lv_file_explorer_dir_t;
#endif
/*Data of canvas*/
typedef struct {
lv_obj_t obj;
lv_obj_t * cont;
lv_obj_t * head_area;
lv_obj_t * browser_area;
lv_obj_t * file_table;
lv_obj_t * path_label;
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_obj_t * quick_access_area;
lv_obj_t * list_device;
lv_obj_t * list_places;
char * home_dir;
char * music_dir;
char * pictures_dir;
char * video_dir;
char * docs_dir;
char * fs_dir;
#endif
const char * sel_fn;
char current_path[LV_FILE_EXPLORER_PATH_MAX_LEN];
lv_file_explorer_sort_t sort;
} lv_file_explorer_t;
extern const lv_obj_class_t lv_file_explorer_class;
/***********************
* GLOBAL VARIABLES
***********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t * lv_file_explorer_create(lv_obj_t * parent);
/*=====================
* Setter functions
*====================*/
#if LV_FILE_EXPLORER_QUICK_ACCESS
/**
* Set file_explorer
* @param obj pointer to a label object
* @param dir the dir from 'lv_file_explorer_dir_t' enum.
*/
void lv_file_explorer_set_quick_access_path(lv_obj_t * obj, lv_file_explorer_dir_t dir, const char * path);
#endif
/**
* Set file_explorer sort
* @param obj pointer to a file explorer object
* @param sort the sort from 'lv_file_explorer_sort_t' enum.
*/
void lv_file_explorer_set_sort(lv_obj_t * obj, lv_file_explorer_sort_t sort);
/*=====================
* Getter functions
*====================*/
/**
* Get file explorer Selected file
* @param obj pointer to a file explorer object
* @return pointer to the file explorer selected file name
*/
const char * lv_file_explorer_get_selected_file_name(const lv_obj_t * obj);
/**
* Get file explorer cur path
* @param obj pointer to a file explorer object
* @return pointer to the file explorer cur path
*/
const char * lv_file_explorer_get_current_path(const lv_obj_t * obj);
/**
* Get file explorer head area obj
* @param obj pointer to a file explorer object
* @return pointer to the file explorer head area obj(lv_obj)
*/
lv_obj_t * lv_file_explorer_get_header(lv_obj_t * obj);
/**
* Get file explorer head area obj
* @param obj pointer to a file explorer object
* @return pointer to the file explorer quick access area obj(lv_obj)
*/
lv_obj_t * lv_file_explorer_get_quick_access_area(lv_obj_t * obj);
/**
* Get file explorer path obj(label)
* @param obj pointer to a file explorer object
* @return pointer to the file explorer path obj(lv_label)
*/
lv_obj_t * lv_file_explorer_get_path_label(lv_obj_t * obj);
#if LV_FILE_EXPLORER_QUICK_ACCESS
/**
* Get file explorer places list obj(lv_list)
* @param obj pointer to a file explorer object
* @return pointer to the file explorer places list obj(lv_list)
*/
lv_obj_t * lv_file_explorer_get_places_list(lv_obj_t * obj);
/**
* Get file explorer device list obj(lv_list)
* @param obj pointer to a file explorer object
* @return pointer to the file explorer device list obj(lv_list)
*/
lv_obj_t * lv_file_explorer_get_device_list(lv_obj_t * obj);
#endif
/**
* Get file explorer file list obj(lv_table)
* @param obj pointer to a file explorer object
* @return pointer to the file explorer file table obj(lv_table)
*/
lv_obj_t * lv_file_explorer_get_file_table(lv_obj_t * obj);
/**
* Set file_explorer sort
* @param obj pointer to a file explorer object
* @return the current mode from 'lv_file_explorer_sort_t'
*/
lv_file_explorer_sort_t lv_file_explorer_get_sort(const lv_obj_t * obj);
/*=====================
* Other functions
*====================*/
/**
* Open a specified path
* @param obj pointer to a file explorer object
* @param dir pointer to the path
*/
void lv_file_explorer_open_dir(lv_obj_t * obj, const char * dir);
/**********************
* MACROS
**********************/
#endif /*LV_USE_FILE_EXPLORER*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_FILE_EXPLORER_H*/

View File

@ -195,6 +195,7 @@ set(LVGL_TEST_OPTIONS_FULL_32BIT
-DLV_USE_IMGFONT=1
-DLV_USE_IME_PINYIN=1
-DLV_USE_MSG=1
-DLV_USE_FILE_EXPLORER=1
)
set(LVGL_TEST_OPTIONS_TEST_COMMON