File Manager / src / view /
list-view.c
/*
* Copyright 2014 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "view/list-view.h"
#include "view/ctrl-bar-view.h"
#include "view/genlist-widget.h"
#include "view/navi-path-widget.h"
#include "view/navi-bar-title.h"
#include "view/navigator.h"
#include "view/popup.h"
#include "utils/app-types.h"
#include "utils/ui-utils.h"
#include "utils/common-utils.h"
#include "utils/model-utils.h"
#include "utils/config.h"
#include "utils/logger.h"
#include "model/fs-manager.h"
#include "model/clipboard.h"
#include "model/navi-path-storage.h"
#include "main-app.h"
typedef struct {
view_data list_view;
title_widget *title_wgt;
genlist_widget *genlist_wgt;
ctrl_bar_widget *ctrl_bar_wgt;
navi_path_widget *navi_path_wgt;
Eina_List *file_list;
} list_view_data;
typedef struct {
list_view_data *list_view;
Evas_Object *wait_popup;
} oper_callback_data;
static const char *const PROGRESS_TEXT = "Operation in progress";
static int _list_view_create_widgets(list_view_data *lv_data);
static int _list_view_update_content(list_view_data *lv_data);
static void _list_view_destroy(list_view_data *lv_data);
static void _list_view_del_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);
static void _list_view_operation_complete(void *data, int result);
static void _list_view_operation_move_cb(void *data, int result);
static void _list_view_operation_copy_cb(void *data, int result);
static void _list_view_operation_delete_cb(void *data, int result);
static oper_callback_data *_list_view_oper_cb_data_create(list_view_data* lv_data);
static void _list_view_oper_cb_data_destroy(oper_callback_data *data);
static Evas_Object *_list_view_progress_popup_create(list_view_data *lv_data);
static void _progress_popup_back_button_cb(void *data, Evas_Object *obj, void *event_info);
int list_view_add(app_data *app, Evas_Object *parent, const char *path, const char *dir_name)
{
RETVM_IF(!app, RESULT_TYPE_INVALID_ARG, "App object is NULL");
RETVM_IF(!parent, RESULT_TYPE_INVALID_ARG, "Parent object is NULL");
RETVM_IF(!path, RESULT_TYPE_INVALID_ARG, "Path is NULL");
app->status.is_mainview = EINA_FALSE;
list_view_data *data = calloc(1, sizeof(list_view_data));
RETVM_IF(!data, RESULT_TYPE_FAIL_ALLOCATE_MEMORY, "Fail allocate memory");
data->list_view.app = app;
data->list_view.navi = parent;
data->list_view.curr_path = (dir_name) ? common_util_strconcat(path, "/", dir_name, NULL)
: strdup(path);
data->list_view.is_root = model_utils_is_root_path(data->list_view.curr_path);
data->file_list = NULL;
data->list_view.navi_layout = ui_utils_layout_add(data->list_view.navi, _list_view_del_cb, data);
if (!data->list_view.navi_layout) {
ERR("Fail to create Layout");
_list_view_destroy(data);
return RESULT_TYPE_FAIL;
}
elm_layout_file_set(data->list_view.navi_layout, ui_utils_get_resource(FM_LAYOUT_EDJ), "navi_layout");
int result = fs_manager_get_file_list(data->list_view.app->manager, data->list_view.curr_path, &data->file_list);
if (result != RESULT_TYPE_OK) {
ERR("Fail to get file list");
evas_object_del(data->list_view.navi_layout);
return result;
}
const char *title = ui_utils_title_get(data->list_view.curr_path);
result = navigator_add_view(data->list_view.app->navigator, title, &data->list_view);
if (result != RESULT_TYPE_OK) {
ERR("Fail to add view to naviframe");
evas_object_del(data->list_view.navi_layout);
return result;
}
result = _list_view_create_widgets(data);
if (result != RESULT_TYPE_OK) {
ERR("Fail to create widgets");
evas_object_del(data->list_view.navi_layout);
return result;
}
Eina_List *path_list = NULL;
int res = navi_path_storage_get_path_list(app->path_storage, &path_list);
RETVM_IF(res != RESULT_TYPE_OK, res, "Fail get folders list for navigation widget");
navi_path_widget_content_set(data->navi_path_wgt, path_list);
elm_object_item_data_set(data->list_view.navi_item, data);
return RESULT_TYPE_OK;
}
int list_view_update(Elm_Object_Item *navi_item, int update_options)
{
RETVM_IF(!navi_item, RESULT_TYPE_INVALID_ARG, "View object is NULL");
list_view_data *data = elm_object_item_data_get(navi_item);
RETVM_IF(!data, RESULT_TYPE_INVALID_ARG, "Data is NULL");
RETVM_IF(!data->genlist_wgt, RESULT_TYPE_INVALID_ARG, "Genlist widget is NULL");
RETVM_IF(!data->ctrl_bar_wgt, RESULT_TYPE_INVALID_ARG, "Ctrl bar widget is NULL");
if (update_options & UPDATE_TYPE_VIEW) {
RETVM_IF(_list_view_update_content(data) != RESULT_TYPE_OK,
RESULT_TYPE_FAIL, "Fail to update view content");
}
if (update_options & UPDATE_TYPE_GENLIST) {
RETVM_IF(genlist_widget_update(data->genlist_wgt) != RESULT_TYPE_OK,
RESULT_TYPE_FAIL, "Fail to update genlist widget");
}
if (update_options & UPDATE_TYPE_CTRL_BAR_MODE) {
RETVM_IF(ctrl_bar_widget_mode_update(data->ctrl_bar_wgt) != RESULT_TYPE_OK,
RESULT_TYPE_FAIL, "Fail to update ctrl bar");
}
if (update_options & UPDATE_TYPE_CTRL_BAR_STATE) {
RETVM_IF(ctrl_bar_widget_state_update(data->ctrl_bar_wgt) != RESULT_TYPE_OK,
RESULT_TYPE_FAIL, "Fail to update ctrl bar");
}
return RESULT_TYPE_OK;
}
unsigned int list_view_items_count_get(view_data *view)
{
list_view_data *data = (list_view_data *)view;
return eina_list_count(data->file_list);
}
int list_view_create_folder(view_data *view, const char *folder_name)
{
RETVM_IF(!view, RESULT_TYPE_INVALID_ARG, "View object is NULL");
char *new_folder = common_util_strconcat(view->curr_path, "/", folder_name, NULL);
int res = fs_manager_create_folder(view->app->manager, new_folder);
free(new_folder);
RETVM_IF(res != RESULT_TYPE_OK, res, "Model create folder Fail");
return RESULT_TYPE_OK;
}
static void _progress_popup_back_button_cb(void *data, Evas_Object *obj, void *event_info)
{
}
Evas_Object *_list_view_progress_popup_create(list_view_data *lv_data)
{
RETVM_IF(!lv_data, NULL, "View obj is NULL");
Evas_Object *popup = elm_popup_add(lv_data->list_view.navi);
RETVM_IF(!popup, NULL, "Fail to create popup");
elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
Evas_Object *layout = ui_utils_layout_add(popup, NULL, NULL);
if (!layout) {
ERR("Fail to create layout");
evas_object_del(popup);
return NULL;
}
elm_layout_file_set(layout, ui_utils_get_resource(FM_LAYOUT_EDJ), "processing_view");
Evas_Object *progressbar = elm_progressbar_add(layout);
if (!progressbar) {
ERR("Fail to create process bar");
evas_object_del(popup);
return NULL;
}
elm_object_style_set(progressbar, "process_medium");
elm_progressbar_pulse(progressbar, EINA_TRUE);
evas_object_show(progressbar);
elm_object_part_content_set(layout, "processing", progressbar);
elm_object_part_text_set(layout, "elm.text", PROGRESS_TEXT);
evas_object_show(layout);
eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, _progress_popup_back_button_cb, NULL);
elm_object_content_set(popup, layout);
evas_object_show(popup);
return popup;
}
static oper_callback_data *_list_view_oper_cb_data_create(list_view_data* lv_data)
{
RETVM_IF(!lv_data, NULL, "View data is NULL");
oper_callback_data *cb_data = calloc(1, sizeof(oper_callback_data));
RETVM_IF(!cb_data, NULL, "Failed to allocate memory for callback data");
Evas_Object *progress_popup = _list_view_progress_popup_create(lv_data);
if (!progress_popup) {
ERR("Failed to create progress popup");
_list_view_oper_cb_data_destroy(cb_data);
return NULL;
}
cb_data->list_view = lv_data;
cb_data->wait_popup = progress_popup;
return cb_data;
}
static void _list_view_oper_cb_data_destroy(oper_callback_data *data)
{
if (data) {
evas_object_del(data->wait_popup);
free(data);
}
}
int list_view_delete_items(view_data *view)
{
RETVM_IF(!view, RESULT_TYPE_INVALID_ARG, "View object is NULL");
list_view_data *list_data = (list_view_data *)view;
oper_callback_data *cb_data = _list_view_oper_cb_data_create(list_data);
RETVM_IF(!cb_data, RESULT_TYPE_FAIL, "Failed to create callback data");
int res = fs_manager_delete_files(list_data->list_view.app->manager,
list_data->file_list,
_list_view_operation_delete_cb,
cb_data);
if (res != RESULT_TYPE_OK) {
ERR("Failed to delete selected files");
_list_view_oper_cb_data_destroy(cb_data);
return res;
}
return res;
}
int list_view_copy_items(view_data *view)
{
RETVM_IF(!view, RESULT_TYPE_INVALID_ARG, "View object is NULL");
list_view_data *list_data = (list_view_data *)view;
app_data *app = list_data->list_view.app;
int res = clipboard_add_data(app->clipboard, list_data->file_list);
RETVM_IF(res != RESULT_TYPE_OK, res, "Fail to copy files");
res = clipboard_set_operation(app->clipboard, OPERATION_TYPE_COPY);
RETVM_IF(res != RESULT_TYPE_OK, res, "Fail to set operation");
return RESULT_TYPE_OK;
}
int list_view_move_items(view_data *view)
{
RETVM_IF(!view, RESULT_TYPE_INVALID_ARG, "View object is NULL");
list_view_data *list_data = (list_view_data *)view;
app_data *app = list_data->list_view.app;
int res = clipboard_add_data(app->clipboard, list_data->file_list);
RETVM_IF(res != RESULT_TYPE_OK, res, "Fail to copy files");
res = clipboard_set_operation(app->clipboard, OPERATION_TYPE_MOVE);
RETVM_IF(res != RESULT_TYPE_OK, res, "Fail to set operation");
return RESULT_TYPE_OK;
}
int list_view_past_items(view_data *view)
{
RETVM_IF(!view, RESULT_TYPE_INVALID_ARG, "View object is NULL");
list_view_data *list_data = (list_view_data *)view;
app_data *app = list_data->list_view.app;
Eina_List *clipboard_list = NULL;
int res = clipboard_get_data(app->clipboard, &clipboard_list);
RETVM_IF(res != RESULT_TYPE_OK || !clipboard_list, res, "Fail to get files from clipboard");
operation_type operation = OPERATION_TYPE_NONE;
res = clipboard_get_operation(app->clipboard, &operation);
RETVM_IF(res != RESULT_TYPE_OK, res, "Fail to get operation type");
oper_callback_data *cb_data = _list_view_oper_cb_data_create(list_data);
RETVM_IF(!cb_data, RESULT_TYPE_FAIL, "Failed to create callback data");
if (operation == OPERATION_TYPE_COPY) {
res = fs_manager_copy_files(app->manager,
clipboard_list,
list_data->list_view.curr_path,
_list_view_operation_copy_cb,
cb_data);
} else if (operation == OPERATION_TYPE_MOVE) {
res = fs_manager_move_files(app->manager,
clipboard_list,
list_data->list_view.curr_path,
_list_view_operation_move_cb,
cb_data);
} else {
ERR("Wrong operation type");
res = RESULT_TYPE_FAIL;
}
if (res != RESULT_TYPE_OK) {
ERR("Failed to paste selected files");
_list_view_oper_cb_data_destroy(cb_data);
return res;
}
return res;
}
int list_view_select_all(view_data *view, Eina_Bool state)
{
RETVM_IF(!view, RESULT_TYPE_INVALID_ARG, "View object is NULL");
list_view_data *data = (list_view_data *)view;
Eina_List *list = NULL;
void *item = NULL;
EINA_LIST_FOREACH(data->file_list, list, item) {
node_info *node = item;
node->is_selected = state;
}
return RESULT_TYPE_OK;
}
static int _list_view_create_widgets(list_view_data *lv_data)
{
lv_data->navi_path_wgt = navi_path_widget_add((view_data *)lv_data);
RETVM_IF(!lv_data->navi_path_wgt, RESULT_TYPE_FAIL, "Fail to create navigation widget");
lv_data->genlist_wgt = genlist_widget_add((view_data *)lv_data);
RETVM_IF(!lv_data->genlist_wgt, RESULT_TYPE_FAIL, "Fail to create genlist widget");
genlist_widget_content_set(lv_data->genlist_wgt, lv_data->file_list);
lv_data->ctrl_bar_wgt = ctrl_bar_widget_add((view_data *)lv_data);
RETVM_IF(!lv_data->ctrl_bar_wgt, RESULT_TYPE_FAIL, "Fail to create ctrl bar widget");
if (!lv_data->list_view.is_root) {
lv_data->title_wgt = navi_bar_title_widget_add((view_data *)lv_data);
RETVM_IF(!lv_data->title_wgt, RESULT_TYPE_FAIL, "Fail to create title widget");
}
return RESULT_TYPE_OK;
}
static int _list_view_update_content(list_view_data *lv_data)
{
common_util_clear_file_list(&lv_data->file_list);
int result = fs_manager_get_file_list(lv_data->list_view.app->manager, lv_data->list_view.curr_path, &lv_data->file_list);
RETVM_IF(result != RESULT_TYPE_OK, result, "Fail to get file list");
genlist_widget_clear(lv_data->genlist_wgt);
genlist_widget_content_set(lv_data->genlist_wgt, lv_data->file_list);
return RESULT_TYPE_OK;
}
static void _list_view_operation_move_cb(void *data, int result)
{
_list_view_operation_complete(data, result);
}
static void _list_view_operation_copy_cb(void *data, int result)
{
_list_view_operation_complete(data, result);
}
static void _list_view_operation_delete_cb(void *data, int result)
{
RETM_IF(!data, "Data is NULL");
oper_callback_data *cb_data = (oper_callback_data *)data;
list_view_data *list_data = cb_data->list_view;
_list_view_oper_cb_data_destroy(cb_data);
if (result != RESULT_TYPE_OK) {
RETM_IF(popup_create((view_data *)list_data, POPUP_TYPE_ERROR), "Fail to create error popup");
} else {
list_data->list_view.app->status.curr_mode = MODE_DEFAULT;
int res = list_view_update(list_data->list_view.navi_item,
UPDATE_TYPE_GENLIST |
UPDATE_TYPE_CTRL_BAR_MODE |
UPDATE_TYPE_VIEW);
RETM_IF(res != RESULT_TYPE_OK, "Fail to update view");
}
}
static void _list_view_operation_complete(void *data, int result)
{
RETM_IF(!data, "Data is NULL");
oper_callback_data *cb_data = (oper_callback_data *)data;
list_view_data *list_data = cb_data->list_view;
_list_view_oper_cb_data_destroy(cb_data);
if (result != RESULT_TYPE_OK) {
ERR("File operation failed");
operation_type operation = OPERATION_TYPE_NONE;
int res = clipboard_get_operation(list_data->list_view.app->clipboard, &operation);
if (res != RESULT_TYPE_OK) {
ERR("Fail to get operation type");
res = popup_create((view_data *)list_data, POPUP_TYPE_ERROR);
} else {
switch (operation) {
case OPERATION_TYPE_MOVE:
if (result == RESULT_TYPE_OPERATION_INVALID_DEST) {
res = popup_create((view_data *)list_data, POPUP_TYPE_MOVE_RECURSIVE_FAIL);
} else {
res = popup_create((view_data *)list_data, POPUP_TYPE_FAIL_TO_MOVE);
}
break;
case OPERATION_TYPE_COPY:
if (result == RESULT_TYPE_OPERATION_INVALID_DEST) {
res = popup_create((view_data *)list_data, POPUP_TYPE_COPY_RECURSIVE_FAIL);
} else {
res = popup_create((view_data *)list_data, POPUP_TYPE_FAIL_TO_COPY);
}
break;
default:
res = popup_create((view_data *)list_data, POPUP_TYPE_ERROR);
break;
}
}
if (res != RESULT_TYPE_OK) {
ERR("Fail to create error popup");
}
} else {
list_data->list_view.app->status.curr_mode = MODE_DEFAULT;
int res = list_view_update(list_data->list_view.navi_item,
UPDATE_TYPE_GENLIST |
UPDATE_TYPE_CTRL_BAR_MODE |
UPDATE_TYPE_VIEW);
if (res != RESULT_TYPE_OK) {
ERR("Fail to update view");
}
}
if (result != RESULT_TYPE_OPERATION_INVALID_DEST) {
result = clipboard_clear(list_data->list_view.app->clipboard);
RETM_IF(result != RESULT_TYPE_OK, "Fail to clear clipboard");
}
}
static void _list_view_destroy(list_view_data *lv_data)
{
if (lv_data) {
app_data *app = lv_data->list_view.app;
app->status.curr_mode = MODE_DEFAULT;
common_util_clear_file_list(&lv_data->file_list);
free(lv_data->list_view.curr_path);
free(lv_data);
}
}
static void _list_view_del_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)
{
_list_view_destroy(data);
}