Fix bugs
[profile/tv/apps/native/filebrowser.git] / src / views / BaseView / FileGrid.cpp
1 /*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <Elementary.h>
18 #include <Eina.h>
19 #include <Ecore.h>
20 #include <aul.h>
21 #include "dbg.h"
22 #include "i18n.h"
23 #include "define.h"
24 #include "common.h"
25
26 #include <AppCommon.h>
27 #include "Mediadata.h"
28 #include "ExtNameInfo.h"
29 #include <SortMgr.h>
30 #include "GengridItemClass.h"
31 #include "InputHandler.h"
32 #include "FileGrid.h"
33 #include "Info.h"
34 #include <BaseView.h>
35 #include <InputHandler.h>
36 #include <ViewMgr.h>
37 #include "FbContextView.h"
38
39
40 #define GENGRID_ITEM_SIZE_W (263 + 20)
41 #define GENGRID_ITEM_SIZE_H (359 + 20)
42
43
44 static Elm_Object_Item *_find_item_by_id(Eina_List *list, char *fid)
45 {
46         Eina_List *l;
47         SItemInfo *pItemInfo;
48         void* obj;
49         char *id;
50
51         EINA_LIST_FOREACH(list, l, obj) {
52                 pItemInfo = (SItemInfo *)obj;
53                 id = pItemInfo->pInfo->Id();
54                 if (id && !strcmp(id, fid))
55                         return pItemInfo->item;
56         }
57
58         return NULL;
59 }
60
61 static SItemInfo *_find_item_info(Eina_List *list, Elm_Object_Item *item)
62 {
63         Eina_List *l;
64         SItemInfo *pItemInfo;
65         void* obj;
66
67         EINA_LIST_FOREACH(list, l, obj) {
68                 pItemInfo = (SItemInfo*)obj;
69                 if (pItemInfo->item == item)
70                         return pItemInfo;
71         }
72
73         return NULL;
74 }
75
76
77 struct SFileGrid {
78         CMediadata *pMediadata;
79
80         Evas_Object *eoWin;
81         Evas_Object *eoBase;
82         Evas_Object *eoGrid;
83
84         Eina_List   *elFile;
85         Eina_List   *elItemInfo;
86
87         CFileGrid::SCallback callback;
88
89         int depth;
90         SItemInfo *ctxt_itinfo;
91         SItemInfo *handle_itinfo;
92
93         char *fid;
94
95         CGengridItemClass *pGengridItemClass;
96
97         SFileGrid() {
98                 memset(this, 0, sizeof(SFileGrid));
99         }
100 };
101
102
103 void CFileGrid::sm_CbRealized(void *data, Evas_Object *obj, void *event_info)
104 {
105         _DBG();
106         if (!data || !obj || !event_info)
107                 return;
108
109         elm_object_item_signal_callback_add((Elm_Object_Item*)event_info,
110                 FBR_SIGNAL_BTN_CLICKED, FBR_BASE_VIEW,
111                 sm_CbSelectItem, data);
112 }
113
114 void CFileGrid::sm_CbUnrealized(void *data, Evas_Object *obj, void *event_info)
115 {
116         _DBG();
117         if (!data || !obj || !event_info)
118                 return;
119
120         elm_object_item_signal_callback_del((Elm_Object_Item*)event_info,
121                 FBR_SIGNAL_BTN_CLICKED, FBR_BASE_VIEW,
122                 sm_CbSelectItem);
123 }
124
125 void CFileGrid::Action(void)
126 {
127         _DBG();
128         m->handle_itinfo = m->ctxt_itinfo;
129         m_HandleSelection();
130         m_DeleteContextView();
131 }
132
133 void CFileGrid::m_DeleteContextView(void)
134 {
135         if(CViewMgr::GetInstance()->CheckTop(FBR_CONTEXT_VIEW))
136                 CViewMgr::GetInstance()->PopView();
137 }
138
139 void CFileGrid::sm_CbSelectItem(void *data, Elm_Object_Item *it, const char *emission, const char *source)
140 {
141         _DBG();
142         CFileGrid* root = (CFileGrid*)data;
143         SItemInfo *pItemInfo;
144
145         if (!data || !it)
146                 return;
147
148         pItemInfo = _find_item_info(root->m->elItemInfo, it);
149         if (!pItemInfo) {
150                 _ERR(" no item info found ");
151                 return;
152         }
153
154         root->m->handle_itinfo = pItemInfo;
155         root->m_HandleSelection();
156 }
157
158 void CFileGrid::m_HandleSelection(void)
159 {
160         char *path;
161         int type;
162         char *id;
163         SItemInfo *pItemInfo = m->handle_itinfo;
164
165         if (!pItemInfo)
166                 return;
167
168         type = pItemInfo->pInfo->Type();
169         if (type == E_GRP_FOLDER) {
170                 if (m->fid) {
171                         free(m->fid);
172                         m->fid = NULL;
173                 }
174                 id = pItemInfo->pInfo->Id();
175                 if (!id)
176                         return;
177
178                 m->fid = strdup(id);
179                 if (!m->fid)
180                         return;
181
182                 elm_object_tree_focus_allow_set(m->eoBase, EINA_FALSE);
183                 t_Update(m->fid, false);//_update_filegrid(m, m->fid, false);
184                 elm_object_tree_focus_allow_set(m->eoBase, EINA_TRUE);
185                 elm_object_focus_set(m->eoGrid, EINA_TRUE);
186         }
187         else {
188                 path = pItemInfo->pInfo->Path();
189                 if (!path)
190                         return;
191
192                 if (m->callback.cbLinkApp)
193                         m->callback.cbLinkApp(m->callback.cookie, type, CInfo::SourceType(), path);
194                 elm_gengrid_item_selected_set(pItemInfo->item, EINA_FALSE);
195         }
196 }
197
198 void CFileGrid::m_GetMediaList(char *fid)
199 {
200         bool ret;
201         ret = m->pMediadata->GetMediaList(fid, CInfo::GroupIndex(), CInfo::SourceType(), &m->elFile);
202         if (ret == false) {
203                 _ERR(" Fetching all list from file failed ");
204                 return;
205         }
206 }
207
208 void CFileGrid::m_GetFolderList(void)
209 {
210         bool ret;
211         ret = m->pMediadata->GetFolderList(CInfo::GroupIndex(), CInfo::SourceType(), &m->elFile);
212         if (ret == false) {
213                 _ERR(" Fetching all list from file failed ");
214                 return;
215         }
216 }
217
218 void CFileGrid::t_CreateFileGrid(void)
219 {
220         Evas_Object *grid;
221         
222         grid = elm_gengrid_add(m->eoBase);
223         if (!grid)
224                 return;
225         evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
226         elm_gengrid_align_set(grid, 0, 0);
227         elm_object_part_content_set(m->eoBase, FBR_PART_MEDIA_GRID, grid);
228
229         Connect(grid);
230
231         evas_object_smart_callback_add(grid, FBR_SIGNAL_REALIZED,      sm_CbRealized, this);
232         evas_object_smart_callback_add(grid, FBR_SIGNAL_UNREALIZED,    sm_CbUnrealized, this);
233         elm_gengrid_item_size_set(grid, elm_config_scale_get() * GENGRID_ITEM_SIZE_W, elm_config_scale_get() * GENGRID_ITEM_SIZE_H);
234
235         m->eoGrid = grid;
236
237         m->pGengridItemClass = new CGengridItemClass;
238         if (!m->pGengridItemClass->Create()) {
239                 delete m->pGengridItemClass;
240                 m->pGengridItemClass = NULL;
241                 evas_object_del(grid);
242                 _ERR(" elm_genlist_item_class_new failed ");
243                 return;
244         }
245
246         evas_object_show(grid);
247 }
248
249
250 void CFileGrid::t_Empty(bool sort_flag)
251 {
252         if (m->eoGrid) {
253                 elm_gengrid_clear(m->eoGrid);
254                 evas_object_del(m->eoGrid);
255                 m->eoGrid = NULL;
256         }
257
258         if (m->pGengridItemClass)
259         {
260                 m->pGengridItemClass->Destroy();
261                 delete m->pGengridItemClass;
262                 m->pGengridItemClass = NULL;
263         }
264
265         if (sort_flag == false && m->elFile != NULL) {
266                 eina_list_free(m->elFile);
267                 m->elFile = NULL;
268         }
269
270         m->elItemInfo = NULL;
271         if (m->callback.cbUpdateEmptyFocusSequence)
272                 m->callback.cbUpdateEmptyFocusSequence(m->callback.cookie);
273 }
274
275
276 void CFileGrid::t_Update(char *fid, bool sort_flag)
277 {
278         _DBG("fid: %s, sort_flag: %d", fid, sort_flag);
279
280         elm_gengrid_clear(m->eoGrid);
281         if (sort_flag == false && m->elFile != NULL) {
282                 eina_list_free(m->elFile);
283                 m->elFile = NULL;
284         }
285
286         m->elItemInfo = NULL;
287         if (m->callback.cbUpdateEmptyFocusSequence)
288                 m->callback.cbUpdateEmptyFocusSequence(m->callback.cookie);
289
290         if (sort_flag == false) {
291                 if (fid)
292                         m_GetMediaList(fid);
293                 else
294                         m_GetFolderList();
295         }
296         
297         const char* sortType;
298         switch(CInfo::SortType())
299         {
300                 case 0:
301                         sortType = SORT_BY_NAME_AZ;
302                         break;
303                 case 1:
304                         sortType = SORT_BY_NAME_ZA;
305                         break;
306                 case 2:
307                         sortType = SORT_BY_DATE_ASC;
308                         break;
309                 case 3:
310                         sortType = SORT_BY_DATE_DES;
311                         break;
312                 case 4:
313                         sortType = SORT_BY_SIZE_ASC;
314                         break;
315                 case 5:
316                         sortType = SORT_BY_SIZE_DES;
317                         break;
318                 default:
319                         _DBG("Fix your code : sortType is invalid");
320                         sortType = SORT_BY_NAME_AZ;
321                         break;
322         }
323
324         m->elFile = CSortMgr::Sort(m->elFile, sortType);
325         t_Fill();
326
327         if (fid)    // folder
328                 m->depth = 1;
329         else
330                 m->depth = 0;
331 }
332
333
334 void CFileGrid::t_Fill(void)
335 {
336         CExtNameInfo *pInfo;
337         Eina_List *l;
338         SItemInfo *pItemInfo;
339         void* obj;
340         int ts;
341
342         _DBG("grid: %x, flist: %x", m->eoGrid, m->elFile);
343         if (!m->eoGrid || !m->elFile)
344                 return;
345
346         ts = eina_list_count(m->elFile);
347         _DBG("count: %d", ts);
348         if (ts == 0) {
349                 return;
350         }
351
352         EINA_LIST_FOREACH(m->elFile, l, obj) {
353                 pInfo = (CExtNameInfo*)obj;
354                 pItemInfo = (SItemInfo *)calloc(1, sizeof(SItemInfo));
355                 if (!pItemInfo) {
356                         _DBG("Fail to allocate memory!!!!!!");
357                         return;
358                 }
359
360                 pItemInfo->pInfo = pInfo;
361                 pItemInfo->item = elm_gengrid_item_append(m->eoGrid, m->pGengridItemClass->Handle(), pItemInfo, NULL, m);
362                 m->elItemInfo = eina_list_append(m->elItemInfo, pItemInfo);
363         }
364
365         if (m->callback.cbUpdatedGrid)
366                 m->callback.cbUpdatedGrid(m->callback.cookie);
367 }
368
369
370 bool CFileGrid::Create(Evas_Object* win, Evas_Object *base, const SCallback *cb)
371 {
372         ASSERT(!m);
373         ASSERT(cb);
374
375         _CREATE_BEGIN{
376                 _CHECK(m = new SFileGrid)
377                 _CHECK(m->pMediadata = new CMediadata )
378                 _CHECK(m->pMediadata->Create())
379
380                 _WHEN_SUCCESS{
381                         m->eoWin    = win;
382                         m->eoBase   = base;
383                         m->callback = *cb;
384                         t_CreateFileGrid();
385                 }
386
387                 _CHECK_FAIL{ m->pMediadata->Destroy(); }
388                 _CHECK_FAIL{ delete m->pMediadata; }
389                 _CHECK_FAIL{ delete m; m = NULL; }
390         } _CREATE_END_AND_CATCH{ return false; }
391
392
393         return true;
394 }
395
396
397 void CFileGrid::Destroy(void)
398 {
399         ASSERT(m);
400
401         t_Empty(false);
402
403         m_DeleteContextView();
404
405         free(m->fid);
406
407         m->pMediadata->Destroy();
408         delete m->pMediadata;
409         delete m;
410         m = NULL;
411 }
412
413
414 void CFileGrid::Update(bool sort_flag)
415 {
416         ASSERT(m);
417
418         char* fid = NULL;
419         if (sort_flag == true) {
420                 fid = m->fid;
421         }
422         t_Update(fid, sort_flag);
423 }
424
425
426 void CFileGrid::SetFocus(Eina_Bool flag)
427 {
428         ASSERT(m);
429
430         elm_object_focus_set(m->eoGrid, flag);
431 }
432
433
434 Evas_Object* CFileGrid::Grid(void)
435 {
436         ASSERT(m);
437
438         return m->eoGrid;
439 }
440
441
442 void CFileGrid::OnKeyUp(int id, Evas *e, Evas_Object *obj, Evas_Event_Key_Up *ev) {
443         Elm_Object_Item *it;
444         SItemInfo *pItemInfo;
445
446         if(ev->keyname)
447                 _DBG("%s", ev->keyname);
448
449         if (!strcmp(ev->keyname, KEY_BACK) || !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
450                 if (m->depth == 0) {
451                         if (m->callback.cbUnsetFocus)
452                                 m->callback.cbUnsetFocus(m->callback.cookie);
453                 }
454                 else {
455                         t_Update(NULL, false);
456                         it = _find_item_by_id(m->elItemInfo, m->fid);
457                         elm_gengrid_item_show(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
458                         elm_object_item_focus_set(it, EINA_TRUE);
459                 }
460         }
461         else if (!strcmp(ev->keyname, KEY_ENTER) || !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
462                 it = elm_object_focused_item_get(obj);
463                 if (!it) {
464                         _ERR(" unable to get focused item ");
465                         return;
466                 }
467                 pItemInfo = _find_item_info(m->elItemInfo, it);
468                 if (!pItemInfo)
469                         return;
470
471                 m->handle_itinfo = pItemInfo;
472                 m_HandleSelection();
473         }
474         else if (!strcmp(ev->keyname, KEY_MENU) || !strcmp(ev->keyname, KEY_MENU_REMOTE)) {
475                 it = elm_object_focused_item_get(obj);
476                 if (!it) {
477                         _ERR(" unable to get focused item ");
478                         return;
479                 }
480                 pItemInfo = _find_item_info(m->elItemInfo, it);
481                 if (!pItemInfo)
482                         return;
483
484                 m->ctxt_itinfo = pItemInfo;
485
486                 CViewMgr::GetInstance()->PushView(FBR_CONTEXT_VIEW, pItemInfo->pInfo);
487         }
488 }
489
490
491 void CFileGrid::OnMouseMove(int id, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Move *ev) {
492         _DBG();
493         Elm_Object_Item *item;
494
495         if (!obj)
496                 return;
497
498         item = elm_gengrid_at_xy_item_get(obj, ev->cur.canvas.x,
499                 ev->cur.canvas.y, NULL, NULL);
500         if (!item)
501                 return;
502
503         elm_object_item_focus_set(item, EINA_TRUE);
504 }