TizenRefApp-5644 Implement Export controller 64/59064/6
authorNataliia Sydorchuk <n.sydorchuk@samsung.com>
Thu, 11 Feb 2016 07:47:47 +0000 (09:47 +0200)
committerNataliia Sydorchuk <n.sydorchuk@samsung.com>
Thu, 11 Feb 2016 07:48:04 +0000 (09:48 +0200)
Change-Id: I1b9375a751c0d7c6306d1eca6149906dd93c7ab1
Signed-off-by: Nataliia Sydorchuk <n.sydorchuk@samsung.com>
CMakeLists.txt
lib-common/inc/Ui/ProgressController.h
lib-common/src/Ui/ProgressController.cpp
lib-contact/inc/Contacts/Common/Utils.h [new file with mode: 0644]
lib-contact/inc/Contacts/Settings/ExportController.h [new file with mode: 0644]
lib-contact/src/Contacts/Common/Utils.cpp [new file with mode: 0644]
lib-contact/src/Contacts/Settings/ExportController.cpp [new file with mode: 0644]
main-app/tizen-manifest.xml
packaging/org.tizen.contacts.spec

index 0b2c635..3c628df 100644 (file)
@@ -14,6 +14,7 @@ pkg_check_modules(TIZEN_PACKAGES REQUIRED
        feedback
        libtzplatform-config
        notification
+       storage
 )
 
 set(INCLUDES      "${TIZEN_PACKAGES_INCLUDE_DIRS};inc")
index 67dbc27..7257e10 100644 (file)
@@ -66,12 +66,13 @@ namespace Ui
                virtual bool onCancel();
 
                void cancel();
-               bool onProgress(int value);
+               bool onProgress(size_t value);
 
        private:
                void createProgressPopup(Evas_Object *parent, const char *title, int maxValue);
 
                static void onStart(void *data, Ecore_Thread *thread);
+               static void onNotify(void *data, Ecore_Thread *thread, void *msgData);
                static void onFinish(void *data, Ecore_Thread *thread);
                static void onCanceled(void *data, Ecore_Thread *thread);
 
index c635547..e4f85c6 100644 (file)
@@ -35,7 +35,7 @@ ProgressController::~ProgressController()
 
 void ProgressController::run()
 {
-       m_Thread = ecore_thread_run(onStart, onFinish, onCanceled, this);
+       m_Thread = ecore_thread_feedback_run(onStart, onNotify, onFinish, onCanceled, this, EINA_FALSE);
 }
 
 void ProgressController::setFinishCallback(FinishCallback callback)
@@ -53,9 +53,10 @@ void ProgressController::cancel()
        m_IsCanceled = true;
 }
 
-bool ProgressController::onProgress(int value)
+bool ProgressController::onProgress(size_t value)
 {
-       m_ProgressPopup->setProgress(value);
+       ecore_thread_feedback(m_Thread, (void *)value);
+
        return !m_IsCanceled;
 }
 
@@ -83,7 +84,15 @@ void ProgressController::onStart(void *data, Ecore_Thread *thread)
 {
        RETM_IF_ERR(!data, "invalid data");
        ProgressController *controller = (ProgressController *)data;
-       controller->onStart(controller->m_Thread);
+       controller->onStart(thread);
+}
+
+void ProgressController::onNotify(void *data, Ecore_Thread *thread, void *msgData)
+{
+       RETM_IF_ERR(!data || !msgData, "invalid data");
+       ProgressController *controller = (ProgressController *)data;
+
+       controller->m_ProgressPopup->setProgress((size_t)msgData);
 }
 
 void ProgressController::onFinish(void *data, Ecore_Thread *thread)
diff --git a/lib-contact/inc/Contacts/Common/Utils.h b/lib-contact/inc/Contacts/Common/Utils.h
new file mode 100644 (file)
index 0000000..eb35e45
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef CONTACTS_COMMON_UTILS_H
+#define CONTACTS_COMMON_UTILS_H
+
+#include <storage.h>
+#include <string>
+
+namespace Contacts
+{
+       namespace Common
+       {
+               /**
+                * @brief Gets root or certain storage directory path.
+                * @details If you want to get root storage directory path use STORAGE_DIRECTORY_MAX for @a dirType.
+                *
+                * @param[in]   storageType The storage Type
+                * @param[in]   dirType The directory type
+                *
+                * @return The directory path
+                */
+               std::string getDirectoryPath(storage_type_e storageType, storage_directory_e dirType);
+       }
+}
+
+#endif /* CONTACTS_COMMON_UTILS_H */
diff --git a/lib-contact/inc/Contacts/Settings/ExportController.h b/lib-contact/inc/Contacts/Settings/ExportController.h
new file mode 100644 (file)
index 0000000..b4001b7
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef CONTACTS_SETTINGS_EXPORT_CONTROLLER_H
+#define CONTACTS_SETTINGS_EXPORT_CONTROLLER_H
+
+#include <string>
+#include <vector>
+
+#include "Ui/ProgressController.h"
+#include "Contacts/Common/Utils.h"
+
+namespace Contacts
+{
+       namespace Settings
+       {
+               /**
+                * @brief Type of storage where vcard will be created.
+                */
+               enum TargetStorage
+               {
+                       TargetStorageDevice,
+                       TargetStorageSdCard,
+                       TargetStorageInternalOther
+               };
+
+               /**
+                * @brief Controller for Export ProgressPopup
+                */
+               class ExportController : public Ui::ProgressController
+               {
+               public:
+                       /**
+                        * @brief Create controller for Export ProgressPopup.
+                        * @param[in]   parent          Parent object.
+                        * @param[in]   title           Progress popup title.
+                        * @param[in]   personIdList    Person id list.
+                        * @param[in]   vcardStorage    Type of storage where vcard will be created.
+                        */
+                       ExportController(Evas_Object *parent, const char *title,
+                                       std::vector<int> personIdList, TargetStorage vcardStorage);
+
+               private:
+                       void createDirectory(const std::string &directoryPath);
+                       std::string getVcardDirectoryPath();
+                       std::string getVcardFilePath();
+
+                       virtual void onStart(Ecore_Thread *thread) override;
+                       virtual void onCanceled() override;
+
+               private:
+                       std::vector<int> m_PersonIdList;
+                       std::string m_VcardPath;
+                       TargetStorage m_VcardStorage;
+               };
+       }
+}
+
+#endif /* CONTACTS_SETTINGS_EXPORT_CONTROLLER_H */
diff --git a/lib-contact/src/Contacts/Common/Utils.cpp b/lib-contact/src/Contacts/Common/Utils.cpp
new file mode 100644 (file)
index 0000000..c6420d6
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 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 "Contacts/Common/Utils.h"
+#include "Utils/Logger.h"
+
+using namespace Contacts::Common;
+using namespace Contacts;
+
+namespace
+{
+       struct StorageData
+       {
+               storage_type_e m_Type;
+               int m_StorageId;
+       };
+
+       bool storageCb(int storageId, storage_type_e type, storage_state_e state, const char *path, void *userData)
+       {
+               RETVM_IF(!userData, false, "Empty user data");
+               StorageData *storageData = static_cast<StorageData *>(userData);
+
+               if (type == storageData->m_Type && STORAGE_STATE_MOUNTED == state) {
+                       storageData->m_StorageId = storageId;
+                       return false;
+               }
+               return true;
+       }
+
+       int getStorageId(storage_type_e storageType)
+       {
+               StorageData storageData {storageType, -1};
+               int error = storage_foreach_device_supported(storageCb, &storageData);
+               RETVM_IF_ERR(error, -1, "storage_foreach_device_supported() failed");
+
+               return storageData.m_StorageId;
+       }
+}
+
+std::string Common::getDirectoryPath(storage_type_e storageType, storage_directory_e dirType)
+{
+       char *dirPath = nullptr;
+       int error = STORAGE_ERROR_NONE;
+
+       if (dirType == STORAGE_DIRECTORY_MAX) {
+               error = storage_get_root_directory(getStorageId(storageType), &dirPath);
+       } else {
+               error = storage_get_directory(getStorageId(storageType), dirType, &dirPath);
+       }
+       RETVM_IF_ERR(error, std::string(), "failed to get directory path");
+
+       std::string res = dirPath;
+       free(dirPath);
+
+       return res;
+}
diff --git a/lib-contact/src/Contacts/Settings/ExportController.cpp b/lib-contact/src/Contacts/Settings/ExportController.cpp
new file mode 100644 (file)
index 0000000..abfc4f8
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 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 "Contacts/Common/Utils.h"
+#include "Contacts/Settings/ExportController.h"
+#include "Utils/Logger.h"
+
+#include <contacts.h>
+#include <notification.h>
+
+using namespace Contacts::Common;
+using namespace Contacts::Settings;
+
+#define BUFFER_SIZE        64
+
+#define RELATIVE_EXPORT_PATH   "/Device/Contacts/Exported"
+
+namespace
+{
+       struct {
+               storage_type_e type;
+               storage_directory_e directory;
+       } storageParam[] = {
+               /* [TargetStorageDevice]        = */    { STORAGE_TYPE_INTERNAL, STORAGE_DIRECTORY_MAX },
+               /* [TargetStorageSdCard]        = */    { STORAGE_TYPE_EXTERNAL, STORAGE_DIRECTORY_MAX },
+               /* [TargetStorageInternalOther] = */    { STORAGE_TYPE_INTERNAL, STORAGE_DIRECTORY_OTHERS }
+       };
+}
+
+ExportController::ExportController(Evas_Object *parent, const char *title,
+               std::vector<int> personIdList, TargetStorage vcardStorage)
+       : ProgressController(parent, title, personIdList.size()),
+         m_PersonIdList(std::move(personIdList)), m_VcardStorage(vcardStorage)
+{
+       m_VcardPath = getVcardFilePath();
+}
+
+void ExportController::createDirectory(const std::string &directoryPath)
+{
+       std::string command("mkdir -p ");
+       command.append(directoryPath);
+
+       WARN_IF(system(command.c_str()) == -1, "failed to create folder: %s", strerror(errno));
+}
+
+std::string ExportController::getVcardDirectoryPath()
+{
+       std::string directoryPath = getDirectoryPath(storageParam[m_VcardStorage].type, storageParam[m_VcardStorage].directory);
+
+       if ((storageParam[m_VcardStorage].directory == STORAGE_DIRECTORY_MAX)
+                       && !directoryPath.empty()) {
+               directoryPath.append(RELATIVE_EXPORT_PATH);
+               createDirectory(directoryPath);
+       }
+
+       return directoryPath;
+}
+
+std::string ExportController::getVcardFilePath()
+{
+       std::string directoryPath = getVcardDirectoryPath();
+       RETVM_IF(directoryPath.empty(), std::string(), "Cannot get directory path to storage");
+
+       const int vcardMaxNumber = 999;
+
+       for (int fileNumber = 1; fileNumber <= vcardMaxNumber; ++fileNumber) {
+               char path[BUFFER_SIZE] = { 0, };
+
+               if (fileNumber == 1) {
+                       snprintf(path, sizeof(path), "%s/Contacts.vcf", directoryPath.c_str());
+               } else {
+                       snprintf(path, sizeof(path), "%s/Contacts_%03d.vcf", directoryPath.c_str(), fileNumber);
+               }
+
+               struct stat buf;
+               if (stat(path, &buf) != 0) {
+                       return path;
+               }
+       }
+
+       ERR("Too many vcards. Delete some before creating new.");
+       notification_status_message_post(_("IDS_PB_POP_FAILED"));
+       return std::string();
+}
+
+void ExportController::onStart(Ecore_Thread *thread)
+{
+       FILE *file = fopen(m_VcardPath.c_str(), "a");
+       RETM_IF(!file, "fopen failed: %s", strerror(errno));
+       size_t currentCount = 0;
+
+       for (auto &&personId : m_PersonIdList) {
+               contacts_record_h personRecord = nullptr;
+               int err = contacts_db_get_record(_contacts_person._uri, personId, &personRecord);
+               LOG_IF_ERR(err, continue, "contacts_db_get_record failed: ");
+
+               char *vcardStream = nullptr;
+               err = contacts_vcard_make_from_person(personRecord, &vcardStream);
+               contacts_record_destroy(personRecord, true);
+               LOG_IF_ERR(err, continue, "contacts_vcard_make_from_person failed: ");
+
+               fputs(vcardStream, file);
+               free(vcardStream);
+
+               ++currentCount;
+               if (!onProgress(currentCount)) {
+                       ecore_thread_cancel(thread);
+                       break;
+               }
+       }
+       fclose(file);
+}
+
+void ExportController::onCanceled()
+{
+       if (!m_VcardPath.empty()) {
+               remove(m_VcardPath.c_str());
+       }
+
+       notification_status_message_post(_("IDS_PB_SBODY_EXPORTING_CANCELLED_M_STATUS_ABB"));
+}
index 1b6695d..de8d3d8 100644 (file)
         <privilege>http://tizen.org/privilege/callhistory.read</privilege>
         <privilege>http://tizen.org/privilege/contact.read</privilege>
         <privilege>http://tizen.org/privilege/contact.write</privilege>
+        <privilege>http://tizen.org/privilege/externalstorage</privilege>
         <privilege>http://tizen.org/privilege/mediastorage</privilege>
         <privilege>http://tizen.org/privilege/notification</privilege>
     </privileges>
index 2364593..3a334a1 100644 (file)
@@ -21,6 +21,7 @@ BuildRequires: pkgconfig(elementary)
 BuildRequires: pkgconfig(feedback)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(notification)
+BuildRequires: pkgconfig(storage)
 
 %description
 Contacts and Phone Reference Applications.