Запрос списка файлов
Регистрация привилегии
Получение списка файлов — это очень важная возможность для приложений, работающих с контентом, например, с фотографиями, аудио или видео. В этом разделе мы поговорим о том, как построить приложение, которое будет получать список файлов и выводить его в список.
Создайте новый проект FileList. Зарегистрируйте привилегию http://tizen.org/privilege/mediastorage.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.example.filelist" version="1.0.0"> <profile name="mobile" /> <ui-application appid="org.example.filelist" exec="filelist" type="capp" multiple="false" taskmanage="true" nodisplay="false"> <icon>filelist.png</icon> <label>filelist</label> </ui-application> <privileges> <privilege>http://tizen.org/privilege/mediastorage</privilege> </privileges> </manifest>
Общая память эмулятора обычно имеет разделенные папки, однако в этих папках нет файлов. Для проверки данной возможности мы собираемся скопировать несколько файлов в память эмулятора. Вы можете проверить список папок в древовидной структуре Connection Explorer в нижней левой части Eclipse. Путь к общей папке для хранения изображений - /opt/usr/media/Images. Выберите эту папку, выберите пункт 'Push the file to the connected target device' из tool bar в верхней части. Когда появится всплывающее окно для выбора файлов, перейдите в дополнение /Image, выберите три файла изображений (0.jpg, 1.jpg, and 2.jpg), и нажмите кнопку OK. Вы можете выбрать любой файл по вашему усмотрению. После закрытия всплывающего окна выбранные файлы будут скопированы в папку /Images.
Запрос списка папок из внутренней памяти
В этом разделе мы собираемся запросить список файлов из внутренней памяти эмулятора. Откройте файл исходного кода и внесите в него следующие изменения
#include "filelist.h" #define FM_PHONE_FOLDER "/opt/usr/media" #define FM_MEMORY_FOLDER "/opt/storage/sdcard" typedef struct appdata { Evas_Object *win; Evas_Object *conform; Evas_Object *label; Evas_Object *list; char *current_path; } appdata_s;
"/opt/usr/media" - это корневой каталог общей папки внутренней памяти.
"/opt/storage/sdcard" - это корневой каталог внешней памяти.
List — это переменная элемента управления List для отображения списка файлов.
current_path — это строковая переменная, в которой хранится абсолютный путь текущей папки.
Добавьте новый код в конце функции create_base_gui().
/* Show window after base gui is set up */ evas_object_show(ad->win); ad->current_path = calloc(PATH_MAX, sizeof(char)); strcpy(ad->current_path, FM_PHONE_FOLDER ); read_dir( ad ); }
Выделите память для current_path и скопировать путь корневого каталога внутреннего памяти.
read_dir () - это функция, которая запрашивает список файлов в определенной папке.
Теперь мы собираемся построить пример. Добавить новую функцию выше функции create_base_gui().
static void read_dir(appdata_s *ad) { DIR *dir = opendir(ad->current_path); if( !dir ) return; struct dirent *pDirent = NULL; char buf[100]; while ((pDirent = readdir(dir)) != NULL) { if( pDirent->d_type == DT_DIR ) { dlog_print(DLOG_INFO, "tag", "[Folder] %s", pDirent->d_name); } else { dlog_print(DLOG_INFO, "tag", "[File] %s", pDirent->d_name); } } closedir(dir); }
DIR — это структура, управляющая папками. Она может читать или удалять список файлов и создавать папки.
opendir(char *) - это API, который возвращает объект DIR для управления определенной папкой .
dirent — это структура для сохранения информации о файле (или папке). Среди свойств имя файла сохраняется в переменной d_name. Тип файла сохраняется в переменной d_type. DT_DIR показывает папку, с другой стороны, объект — это файл.
readdir(DIR *) - это API, который считывает список файла из определенной папки и возвращает ее как тип. При достижении конца списка файлов возвращается значение NULL. Далее, мы собираемся построить код, различающий парки и файлы и выдающий результат в журнале сообщения.
closedir(DIR *) - это API, который закрывает DIR.
Запустите пример. Список файлов и папок, имеющихся в общей папке общей памяти, появится в панели Log.
Добавление списка файлов в контрол List
Теперь, мы добавим список файлов к контролу List как элемент. Добавьте код создания контролов Box- и List в функцию create_base_gui().
/* Conformant */ ad->conform = elm_conformant_add(ad->win); elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW); elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE); evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, ad->conform); evas_object_show(ad->conform); { /* Box */ Evas_Object *box = elm_box_add(ad->win); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_content_set(ad->conform, box); evas_object_show(box); { /* List */ ad->list = elm_list_add(ad->conform); elm_list_mode_set(ad->list, ELM_LIST_COMPRESS); evas_object_size_hint_weight_set(ad->list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->list, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, ad->list); evas_object_show(ad->list); } } /* Show window after base gui is set up */ evas_object_show(ad->win);
Измените функцию read_dir() следующим образом:
static void read_dir(appdata_s *ad) { DIR *dir = opendir(ad->current_path); if( !dir ) return; struct dirent *pDirent = NULL; char buf[100]; elm_list_clear(ad->list); while ((pDirent = readdir(dir)) != NULL) { if( pDirent->d_type == DT_DIR ) { dlog_print(DLOG_INFO, "tag", "[Folder] %s", pDirent->d_name); sprintf(buf, "[ %s", pDirent->d_name); } else { dlog_print(DLOG_INFO, "tag", "[File] %s", pDirent->d_name); sprintf(buf, "# %s", pDirent->d_name); } elm_list_item_append(ad->list, buf, NULL, NULL, NULL, ad); } closedir(dir); }
elm_list_clear(Evas_Object *) - это API, который удаляет все элементы из контрола List.
Для того, чтобы отличить файлы от папок используется символ '[' перед названием папки и символ '#' перед названием файла.
elm_list_item_append(Evas_Object *, char *, Evas_Object *, Evas_Object *, Evas_Smart_Cb , void *) - это API, который добавляет новый элемент к контролу List.
Запустите пример. Убедитесь, что вы можете осуществлять навигацию по папкам.
Перемещение по папкам
Мы реализуем возможность того, что когда пользователь выбирает элемент из списка, направлять пользователя в папку. Для этого нам необходимо сделать следующее.
- Функция-обработчик события выбора элемента из списка должна удалит символы '.' и '..' из списка контента
- В текущей папке, которая не является корневой паркой, должны появиться символы '..' в виде первого элемента. Добавьте код в функцию read_dir().
static void read_dir(appdata_s *ad) { DIR *dir = opendir(ad->current_path); if( !dir ) return; struct dirent *pDirent = NULL; char buf[100]; elm_list_clear(ad->list); if( strcmp(ad->current_path, FM_PHONE_FOLDER) != 0 ) elm_list_item_append(ad->list, "..", NULL, NULL, list_item_clicked, ad); while ((pDirent = readdir(dir)) != NULL) { if( strcmp(pDirent->d_name, ".") == 0 ) continue; if( strcmp(pDirent->d_name, "..") == 0 ) continue; if( pDirent->d_type == DT_DIR ) { dlog_print(DLOG_INFO, "tag", "[Folder] %s", pDirent->d_name); sprintf(buf, "[ %s", pDirent->d_name); } else { dlog_print(DLOG_INFO, "tag", "[File] %s", pDirent->d_name); sprintf(buf, "# %s", pDirent->d_name); } elm_list_item_append(ad->list, buf, NULL, NULL, list_item_clicked, ad); //elm_list_item_append(ad->list, buf, NULL, NULL, NULL, ad); } closedir(dir); }
Если текущая папка является корневой папкой внутренней памяти, добавьте значок '..' в качестве первого элемента контрола List. Если имя содержимого - '.' или '..', его можно просто игнорировать. Определим имя функции вызова события выбора элемента как list_item_clicked. Теперь мы должны построить эту функцию. Создайте три функции выше read_dir().
static char* get_file_name(const char* item_text, bool *is_file) { if( item_text[0] == '#' ) *is_file = true; else *is_file = false; if( strcmp(item_text, "..") == 0 ) return item_text; return item_text + 2; } static char* get_new_path(char *current_path, const char *folder_name) { if( strcmp(folder_name, "..") == 0) { int pos = strlen( current_path ) - strlen( strrchr( current_path, '/') ); current_path[pos] = '\0'; } else sprintf(current_path, "%s/%s", current_path, folder_name); return current_path; } static void list_item_clicked(void *data, Evas_Object *obj, void *event_info) { Elm_Object_Item *it = event_info; const char *item_text = elm_object_item_text_get(it); bool is_file; char *file_name = get_file_name(item_text, &is_file); if( is_file ) return; appdata_s *ad = data; ad->current_path = get_new_path(ad->current_path, file_name); read_dir( ad ); }
get_file_name() - это функция, которая принимает текст элемента контрола List , удаляет символы и отличает папки от файлов.
get_new_path() - это функция, которая запрашивает полный путь к файлу, получая путь к текущей папке и имя новой папки.
list_item_clicked() - это функция — обработчик события выбора элемента из списка.
Перейдите вверх исходного файла и добавьте объявление функции read_dir().
typedef struct appdata { Evas_Object *win; Evas_Object *conform; Evas_Object *label; Evas_Object *list; char *current_path; } appdata_s; static void read_dir(appdata_s *ad);
Запустите пример. Убедитесь в том, что значки '.' и '..' используются корректно.
Селектор файлов ELM
Вы можете легко реализовать файл-менеджер с помощью элемента управления ELM File Selector. Создайте новый проект ElmFileSelectorEx. Добавьте привилегию http://tizen.org/privilege/mediastorage.
Откройте файл исходного кода и добавьте код в функцию create_base_gui(). Этот код создает элементы управления Box и FileSelector. Удалите код, создающий метку.
/* Conformant */ ad->conform = elm_conformant_add(ad->win); elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW); elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE); evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, ad->conform); evas_object_show(ad->conform); { /* Box */ Evas_Object *box = elm_box_add(ad->win); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_content_set(ad->conform, box); evas_object_show(box); { Evas_Object *fs = elm_fileselector_add(ad->conform); evas_object_size_hint_weight_set(fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(fs, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, fs); evas_object_show(fs); //elm_fileselector_path_set(fs, FM_PHONE_FOLDER); //elm_fileselector_expandable_set(fs, EINA_TRUE); elm_fileselector_is_save_set(fs, EINA_FALSE); elm_fileselector_mode_set(fs, ELM_FILESELECTOR_LIST); elm_fileselector_folder_only_set(fs, EINA_FALSE); } } /* Show window after base gui is set up */ evas_object_show(ad->win); }
Постройте и запустите приложение. Убедитесь, что список файлов и папок отображается корректно. Изучите следующую информацию об использовании контрола fileselector.
https://docs.enlightenment.org/elementary/1.15.0/fileselector_example.html
https://docs.enlightenment.org/elementary/1.15.0/group__Fileselector.html