nikawhite pushed a commit to branch master. http://git.enlightenment.org/tools/eflete.git/commit/?id=572bc5c4154c7d2a852994ec87e1c7ed2d16331f
commit 572bc5c4154c7d2a852994ec87e1c7ed2d16331f Author: Mykyta Biliavskyi <m.biliavs...@samsung.com> Date: Mon Aug 8 21:27:29 2016 +0300 Project manager: move open project to the Ecore_Thread usage. Created internal submodule project_manager_open. This submodule implements opening projects from *.pro files. Ecore_Thread_Feedback make possible to handling of the errors. Also it is more easy to send messages from thread into main loop. File project_manager_private.h will be used for connect all submodules into module project manager. All changes doesn't mean to change public API. --- src/bin/Makefile.am | 2 + src/bin/project_manager/project_manager.c | 53 +------ src/bin/project_manager/project_manager_open.c | 169 ++++++++++++++++++++++ src/bin/project_manager/project_manager_private.h | 142 ++++++++++++++++++ 4 files changed, 321 insertions(+), 45 deletions(-) diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 35201d5..6f57dab 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -28,6 +28,7 @@ includesub_HEADERS = \ logger/logger.h \ project_manager/group_manager.h \ project_manager/project_manager.h \ + project_manager/project_manager_private.h \ project_manager/resource_manager.h \ ui/cursor.h \ ui/history_ui.h \ @@ -64,6 +65,7 @@ libete_a_SOURCES = \ ../../src/bin/common/widget_list.c \ ../../src/bin/project_manager/group_manager.c \ ../../src/bin/project_manager/project_manager.c \ +../../src/bin/project_manager/project_manager_open.c \ ../../src/bin/project_manager/resource_manager.c \ ../../src/bin/logger/logger.c \ ../../src/bin/config/config.c \ diff --git a/src/bin/project_manager/project_manager.c b/src/bin/project_manager/project_manager.c index af8e16e..8a8be4e 100644 --- a/src/bin/project_manager/project_manager.c +++ b/src/bin/project_manager/project_manager.c @@ -18,22 +18,16 @@ */ #define _GNU_SOURCE #include "project_manager.h" +#include "project_manager_private.h" #include <fcntl.h> #ifndef _WIN32 #include <sys/wait.h> #else #include <win32.h> #endif -#define PROJECT_FILE_KEY "project" #include "change.h" -#define PROJECT_KEY_NAME "edje/name" -#define PROJECT_KEY_AUTHORS "edje/authors" -#define PROJECT_KEY_FILE_VERSION "edje/file_version" -#define PROJECT_KEY_LICENSE "edje/license" -#define PROJECT_KEY_COMMENT "edje/comment" - #define THREAD_CONTEXT_SWITCH_BEGIN ecore_thread_main_loop_begin() #define THREAD_CONTEXT_SWITCH_END ecore_thread_main_loop_end() @@ -54,36 +48,6 @@ typedef struct Ecore_Exe_Flags flags; } Edje_Exe_Data; -/* A handler for Project process. */ -typedef struct -{ - /** The handler of Project thread. */ - Eina_Thread thread; - /** The progress callback. See #PM_Project_Progress_Cb.*/ - PM_Project_Progress_Cb func_progress; - /** The end callback. See #PM_Project_End_Cb. */ - PM_Project_End_Cb func_end; - /** The project process result. */ - PM_Project_Result result; - /** The user data. */ - void *data; - /** The new project, was created in the Project process. This pointer will be - * NULL until the Project process finished it's job.*/ - Project *project; - /** Name of project what must be created. */ - const char *name; - /** Path to new project. */ - const char *path; - /** Path to imported edj file. */ - const char *edj; - /** Path to imported edc file. */ - const char *edc; - /** edje_cc options. Used for 'new project' and 'import from edc'. */ - const char *build_options; - /** The checked widgets. Used for loading just checked widgets. */ - Eina_List *widgets; -} Project_Thread; - static Project_Thread worker; #define WORKER_CREATE(FUNC_PROGRESS, FUNC_END, DATA, PROJECT, \ NAME, PATH, EDJ, EDC, BUILD_OPTIONS, WIDGET_LIST) \ @@ -161,9 +125,8 @@ _project_dev_file_create(Project *pro) return result; } -static Eet_Data_Descriptor *eed_project = NULL; -static Eina_Bool +Eina_Bool _lock_try(const char *path, Eina_Bool check) { struct flock lock, savelock; @@ -191,7 +154,7 @@ _lock_try(const char *path, Eina_Bool check) return true; } -static void +void _project_descriptor_init(void) { Eet_Data_Descriptor_Class eddc; @@ -212,7 +175,7 @@ _project_descriptor_init(void) EET_DATA_DESCRIPTOR_ADD_LIST_STRING(eed_project, Project, "fonts", res.fonts); } -static void +void _pm_project_descriptor_shutdown(void) { eet_data_descriptor_free(eed_project); @@ -232,7 +195,7 @@ _progress_send(void *data) free(message); } -static void +void _end_send(void *data __UNUSED__) { PM_Project_End_Cb func; @@ -396,7 +359,7 @@ _project_edj_file_copy(void) return result; } -static void +void _project_open_internal(Project *project) { assert(project != NULL); @@ -422,7 +385,7 @@ _project_open_internal(Project *project) edje_file_cache_flush(); } -static void +void _project_special_group_add(Project *project) { Evas *e; @@ -448,7 +411,7 @@ _project_special_group_add(Project *project) THREAD_CONTEXT_SWITCH_END; } -static void +void _project_dummy_image_add(Project *project) { Evas *e; diff --git a/src/bin/project_manager/project_manager_open.c b/src/bin/project_manager/project_manager_open.c new file mode 100644 index 0000000..3ef2de1 --- /dev/null +++ b/src/bin/project_manager/project_manager_open.c @@ -0,0 +1,169 @@ +/* + * Efl Edje Theme Editor + * Copyright (C) 2013-2016 Samsung Electronics. + * + * This file is part of Edje Theme Editor. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see www.gnu.org/licenses/lgpl.html. + */ +#include "project_manager.h" +#include "project_manager_private.h" + +void +_project_open_cancel_cb(void *data __UNUSED__, Ecore_Thread *th __UNUSED__) +{ + Project_Thread *ptd = (Project_Thread *)data; + ERR("Project opening process canceled"); + + /*Procedure of correct freing resources */ + _pm_project_descriptor_shutdown(); + + ptd->result = PM_PROJECT_ERROR; + _end_send(ptd); +} + +void +_project_open_end_cb(void *data, Ecore_Thread *th __UNUSED__) +{ + Project_Thread *ptd = (Project_Thread *)data; + /* Will replace with direct ptd pointer */ + _project_open_internal(ptd->project); +} + +void +_project_open_feedback_cb(void *data, + Ecore_Thread *th __UNUSED__, + void *msg_data) +{ + Project_Thread *ptd = (Project_Thread *)data; + Eina_Stringshare *message = (Eina_Stringshare *)msg_data; + assert(message != NULL); + assert(ptd != NULL); + + ptd->func_progress(NULL, message); + eina_stringshare_del(message); +} + + +void +_project_open_feedback_job(void *data, Ecore_Thread *th) +{ + Project_Thread *ptd = (Project_Thread *)data; + if (!eina_lock_take(&ptd->mutex)) + { + ERR("Failed access to the thread data"); + ecore_thread_cancel(th); + return; + } + + Eet_File *ef; + char *tmp; + int tmp_len; + Eina_Stringshare *message = NULL; + + assert(ptd->path != NULL); + + edje_file_cache_flush(); + + if (!_lock_try(ptd->path, true)) + { + /* really this case is unlickly, but we need handle it */ + eina_lock_release(&ptd->mutex); + ERR("Project file already locked by another application"); + ecore_thread_cancel(th); + return; + } + + message = eina_stringshare_printf(_("Opening project \"%s\""), ptd->path); + ecore_thread_feedback(th, message); + + _project_descriptor_init(); + ef = eet_open(ptd->path, EET_FILE_MODE_READ_WRITE); + if (!ef) + { + _pm_project_descriptor_shutdown(); + eina_lock_release(&ptd->mutex); + ERR("Failed to open project file handler"); + ecore_thread_cancel(th); + return; + } + + message = eina_stringshare_add(_("Reading project descriptor")); + ecore_thread_feedback(th, message); + + ptd->project = eet_data_read(ef, eed_project, PROJECT_FILE_KEY); + _pm_project_descriptor_shutdown(); + if (!ptd->project) + { + eina_lock_release(&ptd->mutex); + ERR("Failed to load project data"); + ecore_thread_cancel(th); + return; + } + + ptd->project->ef = ef; + ptd->project->pro_path = eina_stringshare_add(ptd->path); + + /* updating .dev file path */ + tmp = strdup(ptd->path); + tmp_len = strlen(tmp); + tmp[tmp_len - 3] = 'd'; + tmp[tmp_len - 2] = 'e'; + tmp[tmp_len - 1] = 'v'; + eina_stringshare_replace(&ptd->project->dev, tmp); + free(tmp); + /* updating .edj file path */ + tmp = strdup(ptd->path); + tmp[tmp_len - 3] = 'e'; + tmp[tmp_len - 2] = 'd'; + tmp[tmp_len - 1] = 'j'; + eina_stringshare_replace(&ptd->project->saved_edj, tmp); + free(tmp); + + message = eina_stringshare_add(_("Checking project version")); + ecore_thread_feedback(th, message); + + /* checking for older project versions and upgrading them version-by-version */ + if (ptd->project->version < 2) /* upgrade to version 2 */ + { + message = eina_stringshare_add(_("Updating project files to version 2")); + ecore_thread_feedback(th, message); + INFO("Updating project files to version 2"); + ecore_file_mv(ptd->project->dev, ptd->project->saved_edj); + ptd->project->version = 2; + } + if (ptd->project->version < 3) /* upgrade to version 3 */ + { + message = eina_stringshare_add(_("Updating project files to version 3")); + ecore_thread_feedback(th, message); + INFO("Updating project files to version 3"); + _project_special_group_add(ptd->project); + ptd->project->version = 3; + } + if (ptd->project->version < 4) /* upgrade to version 4 */ + { + message = eina_stringshare_add(_("Updating project files to version 4")); + ecore_thread_feedback(th, message); + INFO("Updating project files to version 4"); + _project_dummy_image_add(ptd->project); + ptd->project->version = 4; + } + TODO("Add crash recovery prompt here") + + pm_project_meta_data_get(ptd->project, &ptd->project->name, NULL, NULL, NULL, NULL); + if (!ptd->project->name) + ptd->project->name = ecore_file_strip_ext(ecore_file_file_get(ptd->project->dev)); + + eina_lock_release(&ptd->mutex); +} + diff --git a/src/bin/project_manager/project_manager_private.h b/src/bin/project_manager/project_manager_private.h new file mode 100644 index 0000000..337e050 --- /dev/null +++ b/src/bin/project_manager/project_manager_private.h @@ -0,0 +1,142 @@ +/* + * Efl Edje Theme Editor + * Copyright (C) 2013-2016 Samsung Electronics. + * + * This file is part of Edje Theme Editor. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see www.gnu.org/licenses/lgpl.html. + */ + +#ifndef PROJECT_MANAGER_PRIVATE_H +#define PROJECT_MANAGER_PRIVATE_H + +#include "eflete.h" +#include "logger.h" + +#define PROJECT_FILE_KEY "project" + +#define PROJECT_KEY_NAME "edje/name" +#define PROJECT_KEY_AUTHORS "edje/authors" +#define PROJECT_KEY_FILE_VERSION "edje/file_version" +#define PROJECT_KEY_LICENSE "edje/license" +#define PROJECT_KEY_COMMENT "edje/comment" + +Eet_Data_Descriptor *eed_project = NULL; + +/* A handler for Project process. */ +typedef struct +{ + /** The handler of Project thread. */ + Eina_Thread thread; + /** The progress callback. See #PM_Project_Progress_Cb.*/ + PM_Project_Progress_Cb func_progress; + /** The end callback. See #PM_Project_End_Cb. */ + PM_Project_End_Cb func_end; + /** The project process result. */ + PM_Project_Result result; + /** The user data. */ + void *data; + /** The new project, was created in the Project process. This pointer will be + * NULL until the Project process finished it's job.*/ + Project *project; + /** Name of project what must be created. */ + const char *name; + /** Path to new project. */ + const char *path; + /** Path to imported edj file. */ + const char *edj; + /** Path to imported edc file. */ + const char *edc; + /** edje_cc options. Used for 'new project' and 'import from edc'. */ + const char *build_options; + /** */ + const char *source_edj; + /** The checked widgets. Used for loading just checked widgets. */ + Eina_List *widgets; + /** The temporary directory. Should be stored here for a correct clean temporary files. */ + Eina_Tmpstr *tmp_dirname; + /** The group, which source should be exported into edc. */ + Group *group; + /** Temporary path, for deliver works path between pipes and threads */ + Eina_Stringshare *tmp_path; + + /** Handlers for monitoring events from exe pipes. */ + Ecore_Event_Handler *data_handler; + Ecore_Event_Handler *error_handler; + Ecore_Event_Handler *del_handler; + + /** Mutext for resolve multithread resource usage */ + Eina_Lock mutex; +} Project_Thread; + + +/* General funcions */ + +/* Send result of works one of project manager submodules. + * This function finalize process. It's mean clear data + * of Project_Thread structure. + * @param data - pointer to Project_Thread structure. + * */ +void _end_send(void *data); + +/* Prepare descriptor structure for reading *.pro file */ +void _project_descriptor_init(void); + +/* Destroy descriptor, that provide ability to read *.pro files */ +void _pm_project_descriptor_shutdown(void); + +/* Used for fill project structure with valid data. + * Open shared file handler for a *.dev file. + * Create global edje_edit object. + * Create and load all resource files. + * Load Group tree structure. + * + * @param project - allocated structure that will be filled by valid data. + */ +void _project_open_internal(Project *project); + +/* Try to lock *.pro file for avoid situations when two or more + * instances of Eflete works with the same project in the same time. + * + * @param path - *.pro file. + * @param check - If false - do not lock file, if true - file will be locked. + * + * @return true - file locked succesfull, else failed to lock. + */ +Eina_Bool _lock_try(const char *path, Eina_Bool check); + +/* Add dummy group with name ___eflete_internal_group___. + * This group will be used as pointer to edje_edit object, + * for manipulate Edje structures by using edje_edit API. + * + * @param project - valid struture, for add global_object. + */ +void _project_special_group_add(Project *project); + +/* Add dummy image with name ___eflete_dummy_image___. + * + * @param project - valid struture with global_object. + */ +void _project_dummy_image_add(Project *project); + + +/*------- Open Project functions --------*/ +void _project_open_cancel_cb(void *data, Ecore_Thread *th); + +void _project_open_end_cb(void *data, Ecore_Thread *th); + +void _project_open_feedback_cb(void *data, Ecore_Thread *th, void *msg_data); + +void _project_open_feedback_job(void *data, Ecore_Thread *th); + +#endif --