Apply the modification of CSortMgr
[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,
226                 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
227         elm_gengrid_align_set(grid, 0, 0);
228         elm_object_part_content_set(m->eoBase, FBR_PART_MEDIA_GRID, grid);
229
230
231         Connect(grid);
232
233         evas_object_smart_callback_add(grid, FBR_SIGNAL_REALIZED,      sm_CbRealized, this);
234         evas_object_smart_callback_add(grid, FBR_SIGNAL_UNREALIZED,    sm_CbUnrealized, this);
235         elm_gengrid_item_size_set(grid,
236                 elm_config_scale_get() * GENGRID_ITEM_SIZE_W,
237                 elm_config_scale_get() * GENGRID_ITEM_SIZE_H);
238
239         m->eoGrid = grid;
240
241         m->pGengridItemClass = new CGengridItemClass;
242         if (!m->pGengridItemClass->Create()) {
243                 delete m->pGengridItemClass;
244                 m->pGengridItemClass = NULL;
245                 evas_object_del(grid);
246                 _ERR(" elm_genlist_item_class_new failed ");
247                 return;
248         }
249         
250         evas_object_show(grid);
251 }
252
253
254 void CFileGrid::t_Empty(bool sort_flag)
255 {
256         if (m->eoGrid) {
257                 elm_gengrid_clear(m->eoGrid);
258                 evas_object_del(m->eoGrid);
259                 m->eoGrid = NULL;
260         }
261
262         if (m->pGengridItemClass)
263         {
264                 m->pGengridItemClass->Destroy();
265                 delete m->pGengridItemClass;
266                 m->pGengridItemClass = NULL;
267         }
268
269         if (sort_flag == false && m->elFile != NULL) {
270                 eina_list_free(m->elFile);
271                 m->elFile = NULL;
272         }
273
274         m->elItemInfo = NULL;
275         if (m->callback.cbUpdateEmptyFocusSequence)
276                 m->callback.cbUpdateEmptyFocusSequence(m->callback.cookie);
277 }
278
279
280 void CFileGrid::t_Update(char *fid, bool sort_flag)
281 {
282         _DBG("fid: %s, sort_flag: %d", fid, sort_flag);
283         t_Empty(sort_flag);
284         t_CreateFileGrid();
285
286         if (sort_flag == false) {
287                 if (fid)
288                         m_GetMediaList(fid);
289                 else
290                         m_GetFolderList();
291         }
292         
293         const char* sortType;
294         switch(CInfo::SortType())
295         {
296                 case 0:
297                         sortType = SORT_BY_NAME_AZ;
298                         break;
299                 case 1:
300                         sortType = SORT_BY_NAME_ZA;
301                         break;
302                 case 2:
303                         sortType = SORT_BY_DATE_ASC;
304                         break;
305                 case 3:
306                         sortType = SORT_BY_DATE_DES;
307                         break;
308                 case 4:
309                         sortType = SORT_BY_SIZE_ASC;
310                         break;
311                 case 5:
312                         sortType = SORT_BY_SIZE_DES;
313                         break;
314                 default:
315                         _DBG("Fix your code : sortType is invalid");
316                         sortType = SORT_BY_NAME_AZ;
317                         break;
318         }
319
320         //ASSERT(m->elFile);
321
322         m->elFile = CSortMgr::Sort(m->elFile, sortType);
323         t_Fill();
324
325         if (fid)    // folder
326                 m->depth = 1;
327         else
328                 m->depth = 0;
329 }
330
331
332 void CFileGrid::t_Fill(void)
333 {
334         CExtNameInfo *pInfo;
335         Eina_List *l;
336         SItemInfo *pItemInfo;
337         void* obj;
338         int ts;
339
340         _DBG("grid: %x, flist: %x", m->eoGrid, m->elFile);
341         if (!m->eoGrid || !m->elFile)
342                 return;
343
344         ts = eina_list_count(m->elFile);
345         _DBG("count: %d", ts);
346         if (ts == 0) {
347                 t_Empty(false);
348                 return;
349         }
350
351         EINA_LIST_FOREACH(m->elFile, l, obj) {
352                 pInfo = (CExtNameInfo*)obj;
353                 pItemInfo = (SItemInfo *)calloc(1, sizeof(SItemInfo));
354                 if (!pItemInfo) {
355                         t_Empty(false);
356                         return;
357                 }
358
359                 pItemInfo->pInfo = pInfo;
360                 pItemInfo->item = elm_gengrid_item_append(m->eoGrid, m->pGengridItemClass->Handle(), pItemInfo, NULL, m);
361                 m->elItemInfo = eina_list_append(m->elItemInfo, pItemInfo);
362         }
363
364         if (m->callback.cbUpdatedGrid)
365                 m->callback.cbUpdatedGrid(m->callback.cookie);
366 }
367
368
369 bool CFileGrid::Create(Evas_Object* win, Evas_Object *base, const SCallback *cb)
370 {
371         ASSERT(!m);
372         ASSERT(cb);
373
374         _CREATE_BEGIN{
375                 _CHECK(m = new SFileGrid)
376                 _CHECK(m->pMediadata = new CMediadata )
377                 _CHECK(m->pMediadata->Create())
378
379                 _WHEN_SUCCESS{}
380
381                 _CHECK_FAIL{ m->pMediadata->Destroy(); }
382                 _CHECK_FAIL{ delete m->pMediadata; }
383                 _CHECK_FAIL{ delete m; m = NULL; }
384         } _CREATE_END_AND_CATCH{ return false; }
385
386         m->eoWin    = win;
387         m->eoBase   = base;
388         m->callback = *cb;
389
390         return true;
391 }
392
393
394 void CFileGrid::Destroy(void)
395 {
396         ASSERT(m);
397
398         t_Empty(false);
399
400         m_DeleteContextView();
401
402         free(m->fid);
403
404         m->pMediadata->Destroy();
405         delete m->pMediadata;
406         delete m;
407         m = NULL;
408 }
409
410
411 void CFileGrid::Update(bool sort_flag)
412 {
413         ASSERT(m);
414
415         char* fid = NULL;
416         if (sort_flag == true) {
417                 fid = m->fid;
418         }
419         t_Update(fid, sort_flag);
420 }
421
422
423 void CFileGrid::SetFocus(Eina_Bool flag)
424 {
425         ASSERT(m);
426
427         elm_object_focus_set(m->eoGrid, flag);
428 }
429
430
431 Evas_Object* CFileGrid::Grid(void)
432 {
433         ASSERT(m);
434
435         return m->eoGrid;
436 }
437
438
439 void CFileGrid::OnKeyUp(int id, Evas *e, Evas_Object *obj, Evas_Event_Key_Up *ev) {
440         Elm_Object_Item *it;
441         SItemInfo *pItemInfo;
442         
443         if(ev->keyname)
444                 _DBG("%s", ev->keyname);
445
446         if (!strcmp(ev->keyname, KEY_BACK) || !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
447                 if (m->depth == 0) {
448                         if (m->callback.cbUnsetFocus)
449                                 m->callback.cbUnsetFocus(m->callback.cookie);
450                 }
451                 else {
452                         t_Update(NULL, false);
453                         it = _find_item_by_id(m->elItemInfo, m->fid);
454                         elm_gengrid_item_show(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
455                         elm_object_item_focus_set(it, EINA_TRUE);
456                 }
457         }
458         else if (!strcmp(ev->keyname, KEY_ENTER) || !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
459                 it = elm_object_focused_item_get(obj);
460                 if (!it) {
461                         _ERR(" unable to get focused item ");
462                         return;
463                 }
464                 pItemInfo = _find_item_info(m->elItemInfo, it);
465                 if (!pItemInfo)
466                         return;
467
468                 m->handle_itinfo = pItemInfo;
469                 m_HandleSelection();
470         }
471         else if (!strcmp(ev->keyname, KEY_MENU) || !strcmp(ev->keyname, KEY_MENU_REMOTE)) {
472                 it = elm_object_focused_item_get(obj);
473                 if (!it) {
474                         _ERR(" unable to get focused item ");
475                         return;
476                 }
477                 pItemInfo = _find_item_info(m->elItemInfo, it);
478                 if (!pItemInfo)
479                         return;
480
481                 m->ctxt_itinfo = pItemInfo;
482
483                 CViewMgr::GetInstance()->PushView(FBR_CONTEXT_VIEW, pItemInfo->pInfo);
484         }
485 }
486
487
488 void CFileGrid::OnMouseMove(int id, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Move *ev) {
489         _DBG();
490         Elm_Object_Item *item;
491
492         if (!obj)
493                 return;
494
495         item = elm_gengrid_at_xy_item_get(obj, ev->cur.canvas.x,
496                 ev->cur.canvas.y, NULL, NULL);
497         if (!item)
498                 return;
499
500         elm_object_item_focus_set(item, EINA_TRUE);
501 }