Опубликован: 22.12.2015 | Доступ: свободный | Студентов: 253 / 40 | Длительность: 14:40:00
Лекция 12:

Запрос списка файлов

< Лекция 11 || Лекция 12 || Лекция 13 >

Регистрация привилегии

Получение списка файлов — это очень важная возможность для приложений, работающих с контентом, например, с фотографиями, аудио или видео. В этом разделе мы поговорим о том, как построить приложение, которое будет получать список файлов и выводить его в список.

Создайте новый проект 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


< Лекция 11 || Лекция 12 || Лекция 13 >