yakov pushed a commit to branch master. http://git.enlightenment.org/tools/erigo.git/commit/?id=12445b31747d5f2369707b261b4293f325d3a809
commit 12445b31747d5f2369707b261b4293f325d3a809 Author: Yakov Goldberg <yako...@samsung.com> Date: Sun Nov 15 14:09:29 2015 +0200 Autosave implemented Implemented autosave feature. Project is automatically saved every 10 seconds into file ".project.swp_erigo" When user opens a project and swap file exists, user will be asked what he wants to open: swap or original file. --- src/bin/gui/CMakeLists.txt | 1 + src/bin/gui/autosave.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ src/bin/gui/autosave.h | 23 +++++++++++ src/bin/gui/editor.c | 6 +++ src/bin/gui/egui_logic.c | 57 +++++++++++++++++++++++++- 5 files changed, 185 insertions(+), 1 deletion(-) diff --git a/src/bin/gui/CMakeLists.txt b/src/bin/gui/CMakeLists.txt index e1abcf8..8b17ca7 100644 --- a/src/bin/gui/CMakeLists.txt +++ b/src/bin/gui/CMakeLists.txt @@ -70,6 +70,7 @@ add_executable(${TARGET} dnd.c key_bindings.c popup.c + autosave.c ) add_dependencies(${TARGET} erigo_cmd) diff --git a/src/bin/gui/autosave.c b/src/bin/gui/autosave.c new file mode 100644 index 0000000..0836719 --- /dev/null +++ b/src/bin/gui/autosave.c @@ -0,0 +1,99 @@ + +#include "autosave.h" +#include "gui_widget.h" +#include "json_generator.h" +#include "egui_log.h" + + +static int _init_counter = 0; +static Eina_List *_ctxs_to_save = NULL; + +typedef struct +{ + const Gui_Context *ctx; + const Memento *mem_autosaved; +} Autosave_Info; + +static Ecore_Timer *_autosave_timer; + +void +autosave_context_add(const Gui_Context *ctx) +{ + if (!_init_counter) + { + ERR("Autosave module was not initialized"); + return; + } + Autosave_Info *ai = calloc(1, sizeof(Autosave_Info)); + ai->ctx = ctx; + _ctxs_to_save = eina_list_append(_ctxs_to_save, ai); +} + +void +autosave_context_remove(const Gui_Context *ctx) +{ + if (!_init_counter) + { + ERR("Autosave module was not initialized"); + return; + } + Eina_List *itr; + Autosave_Info *ai; + EINA_LIST_FOREACH(_ctxs_to_save, itr, ai) + { + if (ai->ctx == ctx) break; + } + _ctxs_to_save = eina_list_remove(_ctxs_to_save, ai); + free(ai); +} + +static Eina_Bool +_autosave_cb(void *data EINA_UNUSED) +{ + Eina_List *itr; + Autosave_Info *ai; + EINA_LIST_FOREACH(_ctxs_to_save, itr, ai) + { + if (context_current_memento_get(ai->ctx) == context_saved_memento_get(ai->ctx) || + context_current_memento_get(ai->ctx) == ai->mem_autosaved) continue; + + ai->mem_autosaved = context_current_memento_get(ai->ctx); + + const char *path = gui_context_project_path_get(ai->ctx); + const char *filename = gui_context_project_filename_get(ai->ctx); + char swap_file[PATH_MAX]; + + sprintf(swap_file, "%s/.%s.erigo_swp", path, filename); + json_file_generate(ai->ctx, swap_file); + } + return ECORE_CALLBACK_RENEW; +} + +char * +autosave_ctx_swapfile_name_get(const char *filename) +{ + char *path = ecore_file_dir_get(filename); + const char *name = ecore_file_file_get(filename); + char *swap_file = calloc(strlen(path) + strlen(name) + 13, 1); + sprintf(swap_file, "%s/.%s.erigo_swp", path, name); + free(path); + return swap_file; +} + +Eina_Bool +autosave_init() +{ + if (_init_counter++) return EINA_TRUE; + _autosave_timer = ecore_timer_add(10, _autosave_cb, NULL); + return EINA_TRUE; +} + +void +autosave_shutdown() +{ + if (--_init_counter) + { + ecore_timer_del(_autosave_timer); + _autosave_timer = NULL; + } +} diff --git a/src/bin/gui/autosave.h b/src/bin/gui/autosave.h new file mode 100644 index 0000000..7f84ff4 --- /dev/null +++ b/src/bin/gui/autosave.h @@ -0,0 +1,23 @@ + +#ifndef _AUTOSAVE_H +#define _AUTOSAVE_H + +#include "gui_widget.h" + +Eina_Bool +autosave_init(); + +void +autosave_shutdown(); + +void +autosave_context_add(const Gui_Context *ctx); + +void +autosave_context_remove(const Gui_Context *ctx); + +char * +autosave_ctx_swapfile_name_get(const char *filename); + + +#endif diff --git a/src/bin/gui/editor.c b/src/bin/gui/editor.c index b659758..b8a6ba9 100644 --- a/src/bin/gui/editor.c +++ b/src/bin/gui/editor.c @@ -15,6 +15,8 @@ #include "key_bindings.h" #include "settings.h" #include "updater.h" +#include "autosave.h" +#include "popup.h" #include "dnd.h" @@ -2888,6 +2890,7 @@ editor_shutdown() target_db_shutdown(); proplayout_shutdown(); objtree_shutdown(); + autosave_shutdown(); void *p = (void *) propview_cbs_get(); free(p); @@ -3909,6 +3912,7 @@ _project_close(const Gui_Context *ctx) } session_del(editor_session); + autosave_context_remove(ctx); gui_context_del((Gui_Context *) ctx); } } @@ -3973,6 +3977,7 @@ _project_new(const char *filename) /* FIXME: handle return values */ _active_context_set(ctx); objtree_context_set(ctx); + autosave_context_add(ctx); /* Assign new editor session to context */ Gui_Session *session = session_new(MODE_EDITOR, EINA_TRUE); @@ -4304,6 +4309,7 @@ editor_init(GuiLogicCbs *_guilogic_cbs) objtree_init(); proplayout_init(); target_db_init(); + autosave_init(); ecore_idle_enterer_add(_wdg_border_draw_on_idle, NULL); DnD_Main_Obj_Info *di = calloc (1, sizeof(DnD_Main_Obj_Info)); diff --git a/src/bin/gui/egui_logic.c b/src/bin/gui/egui_logic.c index 879812b..02a1a40 100644 --- a/src/bin/gui/egui_logic.c +++ b/src/bin/gui/egui_logic.c @@ -20,6 +20,7 @@ #include "key_bindings.h" #include "settings.h" #include "simulator.h" +#include "autosave.h" /*FIXME: remove this include */ #include "objtree.h" @@ -149,6 +150,21 @@ static void _context_save(const Gui_Context *ctx) { generator_ctx_source_generate(ctx, GENERATE_JSON, EINA_FALSE); + + const char *path = gui_context_project_path_get(ctx); + const char *filename = gui_context_project_filename_get(ctx); + char full_path[PATH_MAX]; + sprintf(full_path, "%s/%s", path, filename); + + char *swap_file = autosave_ctx_swapfile_name_get(full_path); + if (swap_file) + { + if (ecore_file_exists(swap_file)) + { + ecore_file_remove(swap_file); + } + free(swap_file); + } context_saved_memento_set((Gui_Context *) ctx, context_current_memento_get(ctx)); _canvas_name_update(ctx, EINA_FALSE); } @@ -221,12 +237,51 @@ _project_open_create_internal(const char *filename, int fs_mode, const char *dir return ctx; } +/* Callback for swapfile popup window */ +static void +_swapfile_popup_cb(Popup_Button_Type button_type, void *data) +{ + char *path = data; + /* If OK button pressed open swapped file */ + if (button_type == POPUP_OK_BUTTON) + { + char *swap_file = autosave_ctx_swapfile_name_get(path); + Gui_Context *ctx = _project_open_create_internal(swap_file, ITEM_OPEN, NULL, NULL, NULL); + free(swap_file); + + /* After openning swap file, apply original filename to context + * and update canvas name to show star*/ + const char *original_filename = ecore_file_file_get(path); + gui_context_project_filename_set(ctx, original_filename); + + _canvas_name_update(ctx, EINA_TRUE); + } + else + { + _project_open_create_internal(path, ITEM_OPEN, NULL, NULL, NULL); + } + free(path); +} + +/* Wrapper for _project_open_create_internal() func. + * Has to check if swap file exists and show popup if needed. */ void project_open_create(const char *filename, int fs_mode, const char *dir, const char *file_name, const char *project_name) { + Eina_Bool ret = EINA_FALSE; if (fs_mode == ITEM_OPEN) { - _project_new_mode_internal(filename, fs_mode, NULL, NULL, NULL); + char *swap_file = autosave_ctx_swapfile_name_get(filename); + if (swap_file && ecore_file_exists(swap_file)) + { + const char *title = "Warning"; + const char *text = "Swap file exists for current project. Looks like file was not properly saved. Do you want to open swap file instead of original ?"; + popup_show(g_main_wdgs->main_win->main_win, title, text, POPUP_OK_BUTTON | POPUP_CANCEL_BUTTON, _swapfile_popup_cb, strdup(filename)); + free(swap_file); + ret = EINA_TRUE; + } + if (ret) return; + _project_open_create_internal(filename, fs_mode, NULL, NULL, NULL); } else if (fs_mode == ITEM_NEW) { --