storage: fix uninstallation 66/235466/1
authorLukasz Stanislawski <lukasz.stanislawski@gmail.com>
Thu, 4 Jun 2020 16:34:24 +0000 (18:34 +0200)
committerLukasz Stanislawski <lukasz.stanislawski@gmail.com>
Thu, 4 Jun 2020 22:55:06 +0000 (00:55 +0200)
* fix layout bugs
* remove non-thread safe gui calls from non-ui thread
* fix data races

Change-Id: I7a002985f9d92aa012f0ad28bfd050ebc59e7c20

resource/setting-theme.edc
setting-common/include/setting-common-general-func.h
setting-common/src/setting-common-draw-popup.c
setting-common/src/setting-common-general-func.c
setting-storage/include/setting-storage.h
setting-storage/src/setting-storage-applications-utils.c
setting-storage/src/setting-storage-applications.c
setting-storage/src/setting-storage-utils.c

index 0f6ad6281971b3db57a209eeae57eb2608574fd9..fd8390af86d434a4d7125e437ee82efb8d95a872 100644 (file)
@@ -3810,7 +3810,7 @@ collections
                         type: SPACER;
                         scale: 1;
                         description { state: "default" 0.0;
-                               min: 0 90;
+                               min: 345 174;
                                fixed: 1 0;
                         }
                  }
@@ -3840,9 +3840,8 @@ collections
                         type: SWALLOW;
                         scale: 1;
                         description { state: "default" 0.0;
-                               fixed: 1 1;
-                               min: 36 36;
-                               max: 36 36;
+                               min: 30 30;
+                               max: 30 30;
                                rel1 {
                                   relative: 1.0 0.0;
                                   to_x: "pad_l";
index 63627b608c38189e5182efa50168236f21eb47c7..3adfd2db2a7761c3a7ba03acfbb61c9f53cf43fd 100755 (executable)
@@ -76,4 +76,8 @@ extern char *get_pa_backlight_time_value_str();
 extern const char *setting_get_resource_path(const char *filename);
 extern bool isZero(double val);
 
+typedef void *(transform_cb)(void *data, void *user_data);
+
+extern Eina_Array *eina_array_transform(Eina_Array *array, transform_cb cb, void *user_data);
+
 #endif                         /* __SETTING_COMMON_GENERAL_FUNC_H__ */
index 071b46369c6e7c462ade5007cb9efb764ce6d0f2..bbfcc801f5690bb30d8c110f9483d113d0437264 100755 (executable)
@@ -436,7 +436,7 @@ Evas_Object *setting_create_popup_with_progressbar(void *data,
        popup = elm_popup_add(parent);
        retv_if(NULL == popup, NULL);
 
-       elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
+       elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 0.5);
        evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND,
                        EVAS_HINT_EXPAND);
 
index b43cfaca84d3ba0e31487fd0b884abc3202b3b91..7a26d7452cdbc20f3e55c56663f2324e2ae17b79 100755 (executable)
@@ -934,3 +934,16 @@ extern bool isZero(double val)
        }
        return false;
 }
+
+EXPORT_PUBLIC
+extern Eina_Array *eina_array_transform(Eina_Array *array, transform_cb cb, void *user_data)
+{
+       unsigned int size = eina_array_count_get(array);
+
+       for (unsigned int idx = 0; idx < size; idx++) {
+               void *data = eina_array_data_get(array, idx);
+               eina_array_data_set(array, idx, cb(data, user_data));
+       }
+
+       return array;
+}
index 9809ec99e5766ec65041ec70b8bbfcb4b0bdb3dd..c06bda51e0f5b2bb74f80904c58b67add0f6ac3b 100755 (executable)
@@ -152,12 +152,14 @@ typedef struct _SettingStorage {
 
        Evas_Object *cancel_delete_btn;
        Evas_Object *done_delete_btn;
+       Evas_Object *more_btn;
 
        int mmc_status;
 
        media_content_noti_h h_mcdb_noti;
        char *launch_mode;
        int apps_to_move;
+       Eina_Array *packages_to_remove;
 } SettingStorage;
 
 typedef struct {
index 8005d3c2205ea88c6ed1a7c64418b78ea14ed130..baf626e651e288dc4f29037694b85d4392579298 100755 (executable)
@@ -284,11 +284,11 @@ void node_get_size_cb(const char *package_id, const package_size_info_h size_inf
                        size_to_str(info->total_size, desc, sizeof(desc));
                        info->size_str = strdup(desc);
 
-                       if (info->size_str) {
+                       if (info->size_str && info->data) {
                                free(info->data->sub_desc);
                                info->data->sub_desc = strdup(info->size_str);
+                               elm_genlist_item_update(info->data->item);
                        }
-                       elm_genlist_item_update(info->data->item);
                        return;
                }
        }
index 882cef1a6a087458769c05914005b1cb2ace27a5..f23fff4df2b9eefed92096f34f279af76876f8b7 100755 (executable)
@@ -127,6 +127,17 @@ static void _genlist_check_hide(SettingStorage *ad, bool hide)
        SETTING_TRACE_END;
 }
 
+static void _setting_storage_clear_misc_view(SettingStorage *ad)
+{
+       Node_Info *node = NULL;
+       Eina_List *cur = NULL;
+
+       EINA_LIST_FOREACH(ad->data_list, cur, node) {
+               node->data = NULL;
+       }
+       elm_genlist_clear(ad->misces_genlist);
+}
+
 /**
  * [UI-CALLBACK] 'Delete' button handler on ctxpopup
  */
@@ -140,7 +151,7 @@ static void _ctx_uninstall_click_cb(void *data, Evas_Object *ctxpopup,
 
        ad->select_mode = true;
        elm_ctxpopup_dismiss(ctxpopup);
-       elm_genlist_clear(ad->misces_genlist);
+       _setting_storage_clear_misc_view(ad);
        storage_append_select_all_item(ad, __select_all_cb,
                                                                        __select_all_chk_btn_cb);
        storage_apps_gl_append_removable_items(ad);
@@ -478,9 +489,9 @@ static void storage_apps_gl_append_removable_items(SettingStorage *ad)
                        continue;
 
                item_data = setting_create_Gendial_field_def(ad->misces_genlist,
-                               &(itc_1text_1icon),
+                               &(ad->itc_1text_1icon),
                                storage_apps_genlist_sel, ad,
-                               SWALLOW_Type_1CHECK_RIGHT_INVISIBLE,
+                               SWALLOW_Type_1CHECK,
                                node->l_icon, NULL,
                                0, node->name, node->size_str,
                                storage_apps_genlist_chk_cb);
@@ -549,7 +560,7 @@ static void _update_ui_list(SettingStorage *ad)
        ad->misces_checked = 0;
        ad->misces_is_select_all = EINA_FALSE;
 
-       elm_genlist_clear(ad->misces_genlist);
+       _setting_storage_clear_misc_view(ad);
        /* Add items to genlist */
        storage_apps_gl_append_items(ad);
 
@@ -615,51 +626,45 @@ static int _uninstall_app_thread_func(SettingStorage *ad)
 {
        SETTING_TRACE_BEGIN;
 
-       Node_Info *node = NULL;
-       Setting_GenGroupItem_Data *item_data = NULL;
-       Elm_Object_Item *it = NULL;
        package_manager_request_h req = NULL;
        int req_id = 0;
        int ret = 0;
 
        retv_if(NULL == ad, SETTING_GENERAL_ERR_NULL_DATA_PARAMETER);
+       retv_if(NULL == ad->packages_to_remove, SETTING_GENERAL_ERR_NULL_DATA_PARAMETER);
 
-       it = elm_genlist_first_item_get(ad->misces_genlist);
-       /* Skip "Select all" item: */
-       it = elm_genlist_item_next_get(it);
-       while (it) {
-               item_data = (Setting_GenGroupItem_Data *)elm_object_item_data_get(it);
-               if (!item_data->chk_status) {
-                       it = elm_genlist_item_next_get(it);
-                       continue;
-               }
+       Eina_Array *array = ad->packages_to_remove;
+       ad->packages_to_remove = NULL;
 
-               node = item_data->userdata;
-               req = NULL;
-               req_id = 0;
-               SETTING_TRACE("Trying to uninstall %s", node->name);
+       unsigned int size = eina_array_count_get(array);
+
+       for (unsigned int idx = 0; idx < size; idx++) {
+               char *pkgid = eina_array_data_get(array, idx);
+
+               SETTING_TRACE("Trying to uninstall '%s'", pkgid);
 
                ret = package_manager_request_create(&req);
                if (PACKAGE_MANAGER_ERROR_NONE != ret) {
                        SETTING_TRACE_ERROR("package_manager_request_create() %s",
                                                                get_error_message(ret));
-                       it = elm_genlist_item_next_get(it);
+                       free(pkgid);
                        continue;
                }
-               ret = package_manager_request_uninstall(req, node->id, &req_id);
+               ret = package_manager_request_uninstall(req, pkgid, &req_id);
                if (PACKAGE_MANAGER_ERROR_NONE != ret) {
                        SETTING_TRACE_ERROR("package_manager_request_uninstall() %s",
                                                                get_error_message(ret));
+                       free(pkgid);
                        package_manager_request_destroy(req);
-                       it = elm_genlist_item_next_get(it);
                        continue;
                }
-               package_manager_request_destroy(req);
-               it = elm_genlist_item_next_get(it);
                sleep(1);
                storage_STOP_POINT;
+               free(pkgid);
+               package_manager_request_destroy(req);
        }
 
+       eina_array_free(array);
        sleep(4);
 
        SETTING_TRACE_END;
@@ -667,53 +672,6 @@ static int _uninstall_app_thread_func(SettingStorage *ad)
        return SETTING_RETURN_SUCCESS;
 }
 
-/**
- * [UI] Done button -> create popup -> button handler
- */
-static void _apps_delete_popup_cb(void *data, Evas_Object *obj, void *event_info)
-{
-       SETTING_TRACE_BEGIN;
-
-       int response_type;
-       SettingStorage *ad = data;
-
-       ret_if(NULL == data);
-       ret_if(NULL == obj);
-
-       response_type = btn_type(obj);
-
-       evas_object_del(ad->popup);
-       ad->popup = NULL;
-
-       if (POPUP_RESPONSE_OK != response_type) {
-               SETTING_TRACE("CANCEL");
-               return;
-       }
-
-       SETTING_TRACE(">>>>> checked : %d before deletion ",
-                       ad->misces_checked);
-
-       if (ad->misces_checked) {
-               ad->popup = setting_create_popup_with_progressbar(ad,
-                               ad->md.window, PROGRESSBAR_STYLE,
-                                NULL, _("IDS_ST_POP_UNINSTALLING_ING"),
-                               storage_popup_del, 0, TRUE, TRUE,
-                               0);
-
-               if (ad->del_worker)
-                       storage_stop_async_worker(ad->del_worker);
-               ad->del_worker = storage_start_async_worker(
-                               _uninstall_app_thread_func,
-                               _uninstall_app_thread_func_cb, ad);
-       } else {
-               ad->popup = setting_create_popup(ad, ad->md.window, NULL,
-               STORAGE_STR_NO_SELECTED, storage_popup_del,
-               SETTING_STORAGE_POPUP_TIMER, FALSE, FALSE, 0);
-       }
-
-       SETTING_TRACE_END;
-}
-
 static void _move_request_cb(int id,
                const char *type,
                const char *package,
@@ -896,6 +854,40 @@ static void _move_to_sd(SettingStorage *ad)
        SETTING_TRACE_END;
 }
 
+/**
+ * @brief Gets list of selected nodes on ad->misces_genlist
+ * @note The retuned list should be free with @eina_list_free
+ */
+static Eina_Array *_setting_storage_get_selected_items(Evas_Object *genlist)
+{
+       Eina_Array *ret = NULL;
+       Setting_GenGroupItem_Data *item_data;
+       Elm_Object_Item *it = elm_genlist_first_item_get(genlist);
+
+       ret = eina_array_new(4);
+       if (!ret) return NULL;
+
+       /* Skip "Select all" item: */
+       it = elm_genlist_item_next_get(it);
+
+       while (it) {
+               item_data = (Setting_GenGroupItem_Data *)elm_object_item_data_get(it);
+               if (item_data->chk_status) {
+                       eina_array_push(ret, item_data);
+               }
+               it = elm_genlist_item_next_get(it);
+       }
+
+       return ret;
+}
+
+static void *_pkgid_from_item(void *data, void *user_data)
+{
+       Setting_GenGroupItem_Data *item_data = data;
+       Node_Info *node = item_data->userdata;
+       return node->id ? strdup(node->id) : strdup("");
+}
+
 /**
  * Done button handler for 'delete'
  */
@@ -919,9 +911,26 @@ static void _apps_delete_click_cb(void *data, Evas_Object *obj, void *event_info
                return;
        }
 
-       ad->popup = setting_create_popup(ad, ad->md.window, NULL,
-       STORAGE_STR_DELETE_Q, _apps_delete_popup_cb, 0, FALSE, FALSE,
-                       2, STORAGE_STR_DELETE, STORAGE_STR_CANCEL);
+       if (ad->misces_checked) {
+               ad->popup = setting_create_popup_with_progressbar(ad,
+                               ad->md.window, PROGRESSBAR_STYLE,
+                                NULL, _("IDS_ST_POP_UNINSTALLING_ING"),
+                               storage_popup_del, 0, TRUE, TRUE,
+                               0);
+
+               if (ad->del_worker)
+                       storage_stop_async_worker(ad->del_worker);
+               Eina_Array *selected = _setting_storage_get_selected_items(ad->misces_genlist);
+               // no better way to pass params to _uninstall_app_thread_func then this pseudo-global
+               ad->packages_to_remove = eina_array_transform(selected, _pkgid_from_item, NULL);
+               ad->del_worker = storage_start_async_worker(
+                               _uninstall_app_thread_func,
+                               _uninstall_app_thread_func_cb, ad);
+       } else {
+               ad->popup = setting_create_popup(ad, ad->md.window, NULL,
+               STORAGE_STR_NO_SELECTED, storage_popup_del,
+               SETTING_STORAGE_POPUP_TIMER, FALSE, FALSE, 0);
+       }
 
        SETTING_TRACE_END;
 }
@@ -944,6 +953,7 @@ static int storage_apps_create(void *data)
        ad->misces_genlist = elm_genlist_add(ad->md.naviframe);
        elm_genlist_mode_set(ad->misces_genlist, ELM_LIST_COMPRESS);
        elm_genlist_homogeneous_set(ad->misces_genlist, EINA_TRUE);
+       evas_object_smart_callback_add(ad->misces_genlist, "realized", __gl_realized_cb, &(ad->md));
 
        ad->select_mode = ad->launched_by_external_app;
 
index 7728c83b4b54f1348677b3c45b811a7e961d4bc4..4e5465a62b5e15cce0e9ec05283d33d14888d36f 100755 (executable)
@@ -376,26 +376,27 @@ void storage_gl_add_button_support(
        retm_if(ad == NULL, "SettingStorage *ad parameter is NULL");
 
        SETTING_TRACE_BEGIN;
-       Evas_Object *btn = NULL;
 
        /* Cancel Button */
        ad->cancel_delete_btn = setting_create_button(ad->md.naviframe,
-                       _("IDS_MSG_ACBUTTON_CANCEL_ABB"), "naviframe/title_left",
+                       _("IDS_MSG_ACBUTTON_CANCEL_ABB"), "textbutton",
                        cancel_btn_cb, ad);
+       evas_object_size_hint_min_set(ad->cancel_delete_btn, ELM_SCALE_SIZE(148), ELM_SCALE_SIZE(48));
        evas_object_hide(ad->cancel_delete_btn);
 
        /* Delete Button */
        ad->done_delete_btn = setting_create_button(ad->md.naviframe,
-                       _("IDS_MSG_ACBUTTON_DONE_ABB"), "naviframe/title_right",
+                       _("IDS_MSG_ACBUTTON_DONE_ABB"), "textbutton",
                        done_btn_cb, ad);
+       evas_object_size_hint_min_set(ad->done_delete_btn, ELM_SCALE_SIZE(148), ELM_SCALE_SIZE(48));
        evas_object_hide(ad->done_delete_btn);
 
        /* Add ctx popup handler */
-       btn = setting_create_button(ad->md.naviframe,
+       ad->more_btn = setting_create_button(ad->md.naviframe,
                                NULL, "naviframe/more",
                                more_btn_cb, ad);
        elm_object_item_part_content_set(ad->misces_navi_it, "title_content",
-                                       btn);
+                                       ad->more_btn);
        SETTING_TRACE_END;
 }
 
@@ -403,29 +404,15 @@ void storage_naviframe_update_buttons(SettingStorage *ad)
 {
        /*update delete item buttons*/
        if (ad->select_mode) {
-               if (elm_object_item_part_content_get(
-                               ad->misces_navi_it, "title_left_btn") == NULL) {
-                       elm_object_item_part_content_set(ad->misces_navi_it,
-                               "title_left_btn", ad->cancel_delete_btn);
-               }
-               if (elm_object_item_part_content_get(
-                       ad->misces_navi_it, "title_right_btn") == NULL) {
-                       elm_object_item_part_content_set(ad->misces_navi_it,
-                                       "title_right_btn", ad->done_delete_btn);
-               }
+               elm_object_item_part_content_unset(ad->misces_navi_it, "title_content");
+               evas_object_hide(ad->more_btn);
+               evas_object_show(ad->done_delete_btn);
+               elm_object_item_part_content_set(ad->misces_navi_it, "title_content", ad->done_delete_btn);
        } else {
-               if (elm_object_item_part_content_get(
-                               ad->misces_navi_it, "title_left_btn") != NULL) {
-                       elm_object_item_part_content_unset(ad->misces_navi_it,
-                                       "title_left_btn");
-                       evas_object_hide(ad->cancel_delete_btn);
-               }
-               if (elm_object_item_part_content_get(
-                       ad->misces_navi_it, "title_right_btn") != NULL) {
-                       elm_object_item_part_content_unset(ad->misces_navi_it,
-                                       "title_right_btn");
-                       evas_object_hide(ad->done_delete_btn);
-               }
+               elm_object_item_part_content_unset(ad->misces_navi_it, "title_content");
+               evas_object_hide(ad->done_delete_btn);
+               evas_object_show(ad->more_btn);
+               elm_object_item_part_content_set(ad->misces_navi_it, "title_content", ad->more_btn);
        }
 }
 
@@ -592,15 +579,13 @@ void storage_append_select_all_item(SettingStorage *ad,
                c2 = check_sel_cb;
 
        item_data = setting_create_Gendial_field_def(ad->misces_genlist,
-                       &(itc_1text_1icon), c1,
-                       ad, SWALLOW_Type_1ICON_1RADIO, NULL, NULL, 0,
+                       &(ad->itc_1text), c1,
+                       ad, SWALLOW_Type_1CHECK, NULL, NULL, 0,
                        _("IDS_ST_BODY_SELECT_ALL"), NULL, c2);
 
        if (item_data) {
                item_data->userdata = ad;
                item_data->isItemHideFlag = true;
-               elm_genlist_item_select_mode_set(item_data->item,
-                               ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
        } else {
                SETTING_TRACE_ERROR("item_data is NULL");
        }