732eedb2a1e189646b59c647dbf04bd79df97b36
[apps/home/gallery.git] / src / features / gl-listview.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
4   * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 "gl-debug.h"
18 #include "gl-ui-util.h"
19 #include "gl-util.h"
20 #include "gl-albums.h"
21 #include "gl-listview.h"
22 #include "gl-ext-ug-load.h"
23 #include "gl-ext-exec.h"
24 #include "gl-db-handler.h"
25 #include "gl-progressbar.h"
26
27 /* Icon size of video in list view */
28 #define GL_VIDEO_ICON_WIDTH 168
29 #define GL_VIDEO_ICON_HEIGHT 124
30
31 #define GL_GENLIST_ITEM_STYLE_VIDEO "video_list"
32 #define GL_GENLIST_ITEM_STYLE_VIDEO_EDIT "video_list_edit"
33
34 static void
35 _gl_list_item_check_changed(void *data, Evas_Object * obj, void *event_info)
36 {
37         GL_CHECK(obj);
38         GL_CHECK(data);
39         gl_item *gitem = (gl_item *) data;
40         GL_CHECK(gitem);
41         GL_CHECK(gitem->item);
42         GL_CHECK(gitem->ad);
43         gl_appdata *ad = (gl_appdata *)gitem->ad;
44         int view_mode = gl_get_view_mode(ad);
45         gl_dbg("");
46
47         if (view_mode != GL_VIEW_VIDEOLIST_EDIT)
48         {
49                 gl_dbg("ViewMode.%d. now return.", view_mode);
50                 return;
51         }
52         else
53         {
54                 gl_dbg("Edit Mode");
55         }
56
57         int cnt = 0;
58         Eina_Bool checked = elm_check_state_get(obj);
59         gitem->checked = checked;
60         if (checked)
61         {
62                 gl_dbg("Append:%s", gitem->item->file_url);
63                 gl_db_selected_list_append(ad, gitem);
64         }
65         else
66         {
67                 gl_dbg("Remove:%s", gitem->item->file_url);
68                 gl_db_selected_list_remove(ad, gitem);
69         }
70
71         cnt = gl_db_selected_list_count(ad);
72
73         /* Display selectioninfo */
74         gl_ui_create_selinfo(ad, ad->gridinfo.edit_layout,
75                              ad->gridinfo.nf_it_edit, ad->listinfo.videos_cnt,
76                              cnt, false);
77 }
78
79 static Evas_Object *__gl_list_show_pbar(Evas_Object *parent, gl_item *gitem)
80 {
81         GL_CHECK_NULL(parent);
82         GL_CHECK_NULL(gitem);
83         GL_CHECK_NULL(gitem->item);
84         GL_CHECK_NULL(gitem->item->meta_info);
85         GL_CHECK_NULL(gitem->item->meta_info->video_info);
86
87         if (gitem->item->meta_info->video_info->last_played_pos == 0)
88                 return NULL;
89
90         unsigned int last_pos = gitem->item->meta_info->video_info->last_played_pos;
91         unsigned int v_dur = gitem->item->meta_info->video_info->duration;
92         double ratio = ((double)last_pos) / ((double)v_dur);
93         gl_dbg("Last play position ratio: %f.", ratio);
94
95         return gl_pb_add_list_pbar(parent, ratio);
96 }
97
98 static char *
99 _gl_list_text_get(void *data, Evas_Object * obj, const char *part)
100 {
101         GL_CHECK_NULL(part);
102         GL_CHECK_NULL(data);
103         gl_item *gitem = (gl_item *) data;
104         GL_CHECK_NULL(gitem->item);
105         GL_CHECK_NULL(gitem->ad);
106         char ret_str[GL_FILE_PATH_LEN_MAX] = { 0, };
107
108         if (!strcmp(part, "elm.text.title"))
109         {
110                 if (gitem->item->display_name)
111                 {
112                         return strdup(gitem->item->display_name);
113                 }
114                 else
115                 {
116                         gl_dbg("gitem->item->display_name, addr=%p", gitem->item->display_name);
117                         return NULL;
118                 }
119         }
120         else if (!strcmp(part, "elm.text.duration"))
121         {
122                 /* Running time of the video */
123                 if (gitem->item->meta_info == NULL ||
124                     gitem->item->meta_info->video_info == NULL)
125                 {
126                         gl_dbg("meta info is NULL");
127                         return NULL;
128                 }
129
130                 unsigned int v_dur = gitem->item->meta_info->video_info->duration;
131                 int duration = floor(v_dur / GL_TIME_MSEC_PER_SEC);
132                 int dur_hr = 0;
133                 int dur_min = 0;
134                 int dur_sec = 0;
135                 int tmp = 0;
136
137                 if (duration >= GL_TIME_SEC_PER_HOUR)
138                 {
139                         dur_sec = duration % GL_TIME_SEC_PER_MIN;
140                         tmp = floor(duration / GL_TIME_SEC_PER_MIN);
141                         dur_min = tmp % GL_TIME_MIN_PER_HOUR;
142                         dur_hr = floor(tmp / GL_TIME_MIN_PER_HOUR);
143                 }
144                 else if (duration >= GL_TIME_SEC_PER_MIN)
145                 {
146                         dur_hr = 0;
147                         dur_min = floor(duration / GL_TIME_SEC_PER_MIN);
148                         dur_sec = duration % GL_TIME_SEC_PER_MIN;
149                 }
150                 else
151                 {
152                         dur_hr = 0;
153                         dur_min = 0;
154                         dur_sec = duration % GL_TIME_SEC_PER_MIN;
155                 }
156
157                 snprintf(ret_str, GL_FILE_PATH_LEN_MAX,
158                         "%02d:%02d:%02d", dur_hr, dur_min, dur_sec);
159                 ret_str[strlen(ret_str)] = '\0';
160
161                 return strdup(ret_str);
162         }
163
164         return NULL;
165 }
166
167 static Evas_Object *
168 _gl_list_content_get(void *data, Evas_Object * obj, const char *part)
169 {
170         GL_CHECK_NULL(obj);
171         GL_CHECK_NULL(part);
172         GL_CHECK_NULL(data);
173         gl_item *gitem = (gl_item *) data;
174         GL_CHECK_NULL(gitem->item);
175         GL_CHECK_NULL(gitem->ad);
176         gl_appdata *ad = (gl_appdata *)gitem->ad;
177         Evas_Object *image = NULL;
178
179         if (!strcmp(part, "elm.swallow.checkbox"))
180         {
181                 Evas_Object *ck = NULL;
182
183                 if (gl_get_view_mode(ad) == GL_VIEW_VIDEOLIST_EDIT)
184                 {
185                         ck = elm_check_add(obj);
186                         GL_CHECK_NULL(ck);
187                         elm_object_style_set(ck, GL_CHECKBOX_STYLE_DEFAULT);
188                         evas_object_propagate_events_set(ck, EINA_FALSE);
189
190                         gitem->check_obj = ck;
191                         elm_check_state_set(ck, gitem->checked);
192                         evas_object_smart_callback_add(ck, "changed",
193                                 _gl_list_item_check_changed, data);
194                         evas_object_show(ck);
195                 }
196
197                 return ck;
198         }
199         else if (!strcmp(part, "elm.icon"))
200         {
201                 Evas *evas = evas_object_evas_get(obj);
202                 GL_CHECK_NULL(evas);
203                 image = evas_object_image_add(evas);
204                 GL_CHECK_NULL(image);
205                 evas_object_image_load_size_set(image,
206                                 GL_VIDEO_ICON_WIDTH, GL_VIDEO_ICON_HEIGHT);
207                 evas_object_image_fill_set(image, 0, 0,
208                                 GL_VIDEO_ICON_WIDTH, GL_VIDEO_ICON_HEIGHT);
209                 char *path = NULL;
210                 path = _gl_get_thumb(ad, gitem->item->file_url,
211                                      &gitem->item->thumb_url);
212                 if (path) {
213                         evas_object_image_file_set(image, path, NULL);
214                         free(path);
215                         path = NULL;
216                 } else {
217                         evas_object_image_file_set(image, gitem->item->thumb_url,
218                                                    NULL);
219                 }
220
221                 return image;
222         }
223         else if (!strcmp(part, "elm.bookmarkicon"))     // add bookmark icon
224         {
225                 if (gitem->item->type == MINFO_ITEM_VIDEO)
226                 {
227                         int bk_len = 0;
228                         if (gitem->item->meta_info == NULL ||
229                             gitem->item->meta_info->video_info == NULL)
230                         {
231                                 bk_len = 0;
232                         }
233                         else
234                         {
235                                 bk_len = g_list_length(gitem->item->meta_info->video_info->bookmarks);
236                         }
237                         gl_dbg("%s is video, containing %d bookmark(s)", gitem->item->file_url, bk_len);
238                         if (bk_len)
239                         {
240                                 Evas_Object *icon = elm_icon_add(obj);
241                                 GL_CHECK_NULL(icon);
242                                 elm_icon_file_set(icon, GL_LIST_BOOKMARK, NULL);
243                                 evas_object_show(icon);
244                                 return icon;
245                         }
246                         return NULL;
247                 }
248                 else
249                 {
250                         return NULL;
251                 }
252         } else if (!g_strcmp0(part, "elm.progressbar.icon")) {
253                 return __gl_list_show_pbar(obj, gitem);
254         }
255
256         return NULL;
257 }
258
259 static void
260 _gl_list_del(void *data, Evas_Object * obj)
261 {
262         gl_dbg("");
263 }
264
265 static void
266 _gl_list_genlist_sel(void *data, Evas_Object * obj, void *event_info)
267 {
268         gl_dbg("");
269 }
270
271 static void
272 _gl_list_sel(void *data, Evas_Object * obj, void *event_info)
273 {
274         GL_CHECK(obj);
275         GL_CHECK(data);
276         gl_item *gitem = (gl_item *) data;
277         GL_CHECK(gitem->item);
278         GL_CHECK(gitem->ad);
279         gl_appdata *ad = (gl_appdata *)gitem->ad;
280         int view_mode = gl_get_view_mode(ad);
281         gl_dbg("");
282
283         Elm_Object_Item *gen_item = elm_genlist_selected_item_get(obj);
284         if (gen_item)
285         {
286                 elm_genlist_item_selected_set(gen_item, EINA_FALSE);
287         }
288
289         if (data == NULL)
290         {
291                 gl_dbgE("Callabck data is NULL!");
292                 return;
293         }
294
295         int cnt = 0;
296
297         if (view_mode == GL_VIEW_VIDEOLIST_EDIT)
298         {
299                 if (gitem->check_obj == NULL)
300                 {
301                         gl_dbg("item or check_obj is NULL");
302                         return;
303                 }
304
305                 gitem->checked = !gitem->checked;
306                 elm_check_state_set(gitem->check_obj, gitem->checked);
307
308                 if (gitem->checked)
309                 {
310                         gl_dbg("Append:%s", gitem->item->file_url);
311                         gl_db_selected_list_append(ad, gitem);
312                 }
313                 else
314                 {
315                         gl_dbg("Remove:%s", gitem->item->file_url);
316                         gl_db_selected_list_remove(ad, gitem);
317                 }
318
319                 cnt = gl_db_selected_list_count(ad);
320                 /* Display selectioninfo */
321                 gl_ui_create_selinfo(ad, ad->gridinfo.edit_layout,
322                                      ad->gridinfo.nf_it_edit,
323                                      ad->listinfo.videos_cnt, cnt, false);
324         }
325         else
326         {
327                 GL_CHECK(gitem->item->uuid);
328                 if (ad->listinfo.played_uuid) {
329                         free(ad->listinfo.played_uuid);
330                         ad->listinfo.played_uuid = NULL;
331                 }
332                 ad->listinfo.played_uuid = strdup(gitem->item->uuid);
333                 /* Starting to play the video */
334                 gl_dbg("Starting to play the video");
335                 gl_ext_exec(data, GL_APP_VIDEOPLAYER);
336         }
337 }
338
339 static void
340 _gl_list_update_view(void *data, Evas_Object * obj, void *event_info)
341 {
342         GL_CHECK(obj);
343         GL_CHECK(data);
344         gl_appdata *ad = (gl_appdata *)data;
345         Evas_Object *genlist = obj;
346         int item_cnt = 0;
347         int view_mode = gl_get_view_mode(ad);
348         gl_dbg("");
349
350         elm_genlist_clear(genlist);
351
352         /* Get all medias count of current album */
353         int cnt = ad->maininfo.medias_cnt;
354         int i = 0;
355         gl_item *gitem = NULL;
356         bool it_showed = false;
357
358         for (i = 1; i <= cnt; i++)
359         {
360                 gl_db_get_item_by_index(ad, i, false, &gitem);
361                 if (gitem == NULL || gitem->item == NULL)
362                 {
363                         gl_dbg("gitem == NULL || gitem->item == NULL");
364                         continue;
365                 }
366                 if (gitem->item->type == MINFO_ITEM_VIDEO)
367                 {
368                         gl_dbg("%s inserted", gitem->item->file_url);
369                         gitem->elm_item = elm_genlist_item_append(genlist,
370                                                                         &(ad->listinfo.videolic),
371                                                                         (void *)gitem,
372                                                                         NULL,
373                                                                         ELM_GENLIST_ITEM_NONE,
374                                                                         _gl_list_sel,
375                                                                         gitem);
376                         item_cnt++;
377                         if (!it_showed && ad->listinfo.played_uuid &&
378                             !g_strcmp0(ad->listinfo.played_uuid, gitem->item->uuid)) {
379                                 it_showed = true;
380                                 /*Move played item to middle position of view */
381                                 elm_genlist_item_show(gitem->elm_item,
382                                                       ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
383                         }
384                 }
385         }
386
387         if (ad->listinfo.played_uuid) {
388                 free(ad->listinfo.played_uuid);
389                 ad->listinfo.played_uuid = NULL;
390         }
391
392         ad->listinfo.videos_cnt = item_cnt;
393         if (item_cnt > 0)
394         {
395                 evas_object_smart_callback_add(genlist,
396                         "selected", _gl_list_genlist_sel, NULL);
397
398                 if (view_mode != GL_VIEW_VIDEOLIST_EDIT)
399                 {
400                         if (ad->listinfo.video_nocontents)
401                         {
402                                 evas_object_hide(ad->listinfo.video_nocontents);
403                                 gl_list_clear_view(ad);
404                         }
405                         ad->listinfo.video_view = genlist;
406                 }
407                 else
408                 {
409                         ad->gridinfo.edit_view = genlist;
410                 }
411         }
412         else
413         {
414                 evas_object_del(genlist);
415
416                 if (view_mode == GL_VIEW_VIDEOLIST_EDIT)
417                 {
418                         ad->gridinfo.edit_view = NULL;
419                         ad->gridinfo.edit_layout = NULL;
420                         elm_naviframe_item_pop(ad->maininfo.navi_bar);
421                 }
422
423                 if (ad->listinfo.video_nocontents)
424                 {
425                         gl_dbg("Nocontents view already created...");
426                         return;
427                 }
428                 else
429                 {
430                         if (ad->listinfo.video_view)
431                         {
432                                 evas_object_hide(ad->listinfo.video_view);
433                                 gl_list_clear_view(ad);
434                         }
435
436                         gl_ui_disable_toolbar_item(ad, true, GL_NAVI_THUMBS, false);
437                         Evas_Object *noc = gl_ui_create_nocontents_full(ad);
438                         evas_object_show(noc);
439                         ad->listinfo.video_view = noc;
440                         ad->listinfo.video_nocontents = noc;
441
442                         elm_object_part_content_unset(ad->gridinfo.layout, "elm.swallow.view");
443                         elm_object_part_content_set(ad->gridinfo.layout, "elm.swallow.view",
444                                                ad->listinfo.video_view);
445                 }
446         }
447 }
448
449 int _gl_list_clear_data(void *data)
450 {
451         GL_CHECK_VAL(data, -1);
452         gl_appdata *ad = (gl_appdata *)data;
453         if (ad->listinfo.played_uuid) {
454                 free(ad->listinfo.played_uuid);
455                 ad->listinfo.played_uuid = NULL;
456         }
457         return 0;
458 }
459
460 Evas_Object *
461 gl_list_create_view(void *data, Evas_Object * parent)
462 {
463         GL_CHECK_NULL(data);
464         gl_appdata *ad = (gl_appdata *)data;
465         Evas_Object *genlist = NULL;
466         int item_cnt = 0;
467         gl_item *gitem = NULL;
468         /* Get all medias count of current album */
469         int cnt = ad->maininfo.medias_cnt;
470         int view_mode = gl_get_view_mode(ad);
471         int i = 0;
472
473         gl_dbg("view mode=%d", view_mode);
474         if (view_mode == GL_VIEW_VIDEOLIST_EDIT)
475         {
476                 ad->listinfo.videolic.item_style = GL_GENLIST_ITEM_STYLE_VIDEO_EDIT;
477         }
478         else
479         {
480                 ad->listinfo.videolic.item_style = GL_GENLIST_ITEM_STYLE_VIDEO;
481         }
482         ad->listinfo.videolic.func.text_get = _gl_list_text_get;
483         ad->listinfo.videolic.func.content_get = _gl_list_content_get;
484         ad->listinfo.videolic.func.del = _gl_list_del;
485         genlist = elm_genlist_add(parent);
486         if (view_mode == GL_VIEW_VIDEOLIST)
487         {
488                 elm_genlist_homogeneous_set(genlist, EINA_TRUE);
489         }
490
491         elm_object_style_set(genlist, GL_GENLIST_STYLE_DEFAULT);
492         evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
493         evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
494         for (i = 1; i <= cnt; i++)
495         {
496                 gl_db_get_item_by_index(ad, i, false, &gitem);
497                 if (gitem == NULL || gitem->item == NULL ||
498                     gitem->item->uuid == NULL ) {
499                         gl_dbgE("Invalid gitem!");
500                         continue;
501                 }
502                 if (gitem->item->type == MINFO_ITEM_VIDEO)
503                 {
504                         gl_dbg("%s inserted", gitem->item->file_url);
505                         gitem->elm_item = elm_genlist_item_append(genlist,
506                                                                         &(ad->listinfo.videolic),
507                                                                         (void *)gitem,
508                                                                         NULL,
509                                                                         ELM_GENLIST_ITEM_NONE,
510                                                                         _gl_list_sel,
511                                                                         gitem);
512                         item_cnt++;
513                 }
514
515         }
516
517         ad->listinfo.videos_cnt = item_cnt;
518
519         evas_object_smart_callback_add(genlist,
520                 "update,viedolist", _gl_list_update_view, ad);
521
522         if (item_cnt > 0)
523         {
524                 evas_object_smart_callback_add(genlist,
525                         "selected", _gl_list_genlist_sel, ad);
526                 ad->listinfo.video_nocontents = NULL;
527                 return genlist;
528         }
529         else
530         {
531                 evas_object_del(genlist);
532                 genlist = NULL;
533
534                 Evas_Object *noc = gl_ui_create_nocontents_full(ad);
535                 evas_object_show(noc);
536                 ad->listinfo.video_nocontents = noc;
537                 return noc;
538         }
539 }
540
541 int gl_list_clear_view(void *data)
542 {
543         GL_CHECK_VAL(data, -1);
544         gl_appdata *ad = (gl_appdata *)data;
545
546         if (ad->listinfo.played_uuid) {
547                 free(ad->listinfo.played_uuid);
548                 ad->listinfo.played_uuid = NULL;
549         }
550
551         if (ad->listinfo.video_view) {
552                 evas_object_del(ad->listinfo.video_view);
553                 ad->listinfo.video_view = NULL;
554                 ad->listinfo.video_nocontents = NULL;
555         }
556
557         return 0;
558 }
559
560 /* Update normal list view */
561 int gl_list_update_view(void *data)
562 {
563         GL_CHECK_VAL(data, -1);
564         gl_appdata *ad = (gl_appdata *)data;
565
566         if (ad->listinfo.video_view == NULL ||
567             ad->listinfo.video_nocontents) {
568                 gl_dbgW("Remove list nocontents view!");
569                 if (ad->listinfo.video_nocontents) {
570                         evas_object_hide(ad->listinfo.video_nocontents);
571                         gl_list_clear_view(ad);
572                 }
573
574                 Evas_Object *list_view = NULL;
575                 list_view = gl_list_create_view(ad, ad->maininfo.navi_bar);
576                 ad->listinfo.video_view = list_view;
577
578                 /* Enable edit button if it's not nocontents view */
579                 if (ad->listinfo.video_nocontents == NULL)
580                         gl_ui_disable_toolbar_item(ad, false, GL_NAVI_THUMBS,
581                                                    false);
582
583                 elm_object_part_content_unset(ad->gridinfo.layout,
584                                          "elm.swallow.view");
585                 evas_object_show(ad->listinfo.video_view);
586                 elm_object_part_content_set(ad->gridinfo.layout,
587                                        "elm.swallow.view",
588                                        ad->listinfo.video_view);
589         } else {
590                 _gl_list_update_view(ad, ad->listinfo.video_view, NULL);
591         }
592
593         return 0;
594 }
595
596 int gl_list_change_to_edit(void *data)
597 {
598         GL_CHECK_VAL(data, -1);
599         gl_appdata *ad = (gl_appdata *)data;
600         gl_dbg("");
601
602         gl_set_view_mode(ad, GL_VIEW_VIDEOLIST_EDIT);
603         ad->listinfo.videolic.item_style = GL_GENLIST_ITEM_STYLE_VIDEO_EDIT;
604
605         _gl_list_update_view(ad, ad->gridinfo.edit_view, NULL);
606
607         return 0;
608 }
609
610 int
611 gl_list_change_to_view(void *data)
612 {
613         GL_CHECK_VAL(data, -1);
614         gl_appdata *ad = (gl_appdata *)data;
615         gl_dbg("");
616
617         if (ad->uginfo.ug_called_by_me == NULL && ad->listinfo.video_view == NULL)
618         {
619                 //special process when cancel edit after hide effect in _gl_ext_destroy_ug()
620                 ad->listinfo.video_view = gl_list_create_view(ad, ad->maininfo.navi_bar);
621                 evas_object_show(ad->listinfo.video_view);
622                 elm_object_part_content_set(ad->gridinfo.layout,
623                                 "elm.swallow.view",
624                                 ad->listinfo.video_view);
625         }
626         else
627         {
628                 gl_set_view_mode(ad, GL_VIEW_VIDEOLIST);
629                 ad->listinfo.videolic.item_style = GL_GENLIST_ITEM_STYLE_VIDEO;
630
631                 _gl_list_update_view(ad, ad->listinfo.video_view, NULL);
632         }
633
634         return 0;
635 }