diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 043e645..e1b8eea 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -12,6 +12,7 @@ AM_CPPFLAGS = -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ @EFL_CFLAGS@ edi_SOURCES = \ +edi_config.c \ editor/edi_editor_search.c \ editor/edi_editor.c \ edi_content_provider.c \ diff --git a/src/bin/edi_config.c b/src/bin/edi_config.c new file mode 100644 index 0000000..8068d43 --- /dev/null +++ b/src/bin/edi_config.c @@ -0,0 +1,263 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "edi_config.h" + +#include "edi_private.h" + +# define EDI_CONFIG_LIMIT(v, min, max) \ + if (v > max) v = max; else if (v < min) v = min; + +# define EDI_CONFIG_DD_NEW(str, typ) \ + _edi_config_descriptor_new(str, sizeof(typ)) + +# define EDI_CONFIG_DD_FREE(eed) \ + if (eed) { eet_data_descriptor_free(eed); (eed) = NULL; } + +# define EDI_CONFIG_VAL(edd, type, member, dtype) \ + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, type, #member, member, dtype) + +# define EDI_CONFIG_SUB(edd, type, member, eddtype) \ + EET_DATA_DESCRIPTOR_ADD_SUB(edd, type, #member, member, eddtype) + +# define EDI_CONFIG_LIST(edd, type, member, eddtype) \ + EET_DATA_DESCRIPTOR_ADD_LIST(edd, type, #member, member, eddtype) + +# define EDI_CONFIG_HASH(edd, type, member, eddtype) \ + EET_DATA_DESCRIPTOR_ADD_HASH(edd, type, #member, member, eddtype) + +# define EDI_CONFIG_FILE_EPOCH 0x0001 +# define EDI_CONFIG_FILE_GENERATION 0x000a +# define EDI_CONFIG_FILE_VERSION \ + ((EDI_CONFIG_FILE_EPOCH << 16) | EDI_CONFIG_FILE_GENERATION) + +typedef Eet_Data_Descriptor Edi_Config_DD; + +/* local variables */ +static Edi_Config_DD *_edi_cfg_edd = NULL; +static Edi_Config_DD *_edi_cfg_proj_edd = NULL; + +/* external variables */ +Edi_Config *_edi_cfg = NULL; + +const char * +_edi_config_dir_get(void) +{ + static char dir[PATH_MAX]; + + if (!dir[0]) + snprintf(dir, sizeof(dir), "%s/edi", efreet_config_home_get()); + + return dir; +} + +/* local functions */ +static Edi_Config_DD * +_edi_config_descriptor_new(const char *name, int size) +{ + Eet_Data_Descriptor_Class eddc; + + if (!eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc), + name, size)) + return NULL; + + return (Edi_Config_DD *)eet_data_descriptor_stream_new(&eddc); +} + +static void +_edi_config_cb_free(void) +{ + Edi_Config_Project *proj; + + EINA_LIST_FREE(_edi_cfg->projects, proj) + { + if (proj->name) eina_stringshare_del(proj->name); + if (proj->path) eina_stringshare_del(proj->path); + free(proj); + } + + free(_edi_cfg); + _edi_cfg = NULL; +} + +static void * +_edi_config_domain_load(const char *domain, Edi_Config_DD *edd) +{ + Eet_File *ef; + char buff[PATH_MAX]; + + if (!domain) return NULL; + snprintf(buff, sizeof(buff), + "%s/%s.cfg", _edi_config_dir_get(), domain); + ef = eet_open(buff, EET_FILE_MODE_READ); + if (ef) + { + void *data; + + data = eet_data_read(ef, edd, "config"); + eet_close(ef); + if (data) return data; + } + return NULL; +} + +static Eina_Bool +_edi_config_domain_save(const char *domain, Edi_Config_DD *edd, const void *data) +{ + Eet_File *ef; + char buff[PATH_MAX]; + const char *configdir; + + if (!domain) return 0; + configdir = _edi_config_dir_get(); + snprintf(buff, sizeof(buff), "%s/", configdir); + if (!ecore_file_exists(buff)) ecore_file_mkpath(buff); + snprintf(buff, sizeof(buff), "%s/%s.tmp", configdir, domain); + ef = eet_open(buff, EET_FILE_MODE_WRITE); + if (ef) + { + char buff2[PATH_MAX]; + + snprintf(buff2, sizeof(buff2), "%s/%s.cfg", configdir, domain); + if (!eet_data_write(ef, edd, "config", data, 1)) + { + eet_close(ef); + return EINA_FALSE; + } + if (eet_close(ef) > 0) return EINA_FALSE; + if (!ecore_file_mv(buff, buff2)) return EINA_FALSE; + return EINA_TRUE; + } + + return EINA_FALSE; +} + +/* external functions */ +Eina_Bool +_edi_config_init(void) +{ + elm_need_efreet(); + if (!efreet_init()) return EINA_FALSE; + + _edi_cfg_proj_edd = EDI_CONFIG_DD_NEW("Config_Project", Edi_Config_Project); + #undef T + #undef D + #define T Edi_Config_Project + #define D _edi_cfg_proj_edd + EDI_CONFIG_VAL(D, T, name, EET_T_STRING); + EDI_CONFIG_VAL(D, T, path, EET_T_STRING); + + _edi_cfg_edd = EDI_CONFIG_DD_NEW("Config", Edi_Config); + #undef T + #undef D + #define T Edi_Config + #define D _edi_cfg_edd + EDI_CONFIG_VAL(D, T, version, EET_T_INT); + EDI_CONFIG_VAL(D, T, font.size, EET_T_INT); + EDI_CONFIG_VAL(D, T, gui.translucent, EET_T_UCHAR); + EDI_CONFIG_LIST(D, T, projects, _edi_cfg_proj_edd); + + _edi_config_load(); + + return EINA_TRUE; +} + +Eina_Bool +_edi_config_shutdown(void) +{ + _edi_config_cb_free(); + + EDI_CONFIG_DD_FREE(_edi_cfg_proj_edd); + EDI_CONFIG_DD_FREE(_edi_cfg_edd); + + efreet_shutdown(); + + return EINA_TRUE; +} + +void +_edi_config_load(void) +{ + Eina_Bool save = EINA_FALSE; + + _edi_cfg = _edi_config_domain_load(PACKAGE_NAME, _edi_cfg_edd); + if (_edi_cfg) + { + Eina_Bool reload = EINA_FALSE; + + if ((_edi_cfg->version >> 16) < EDI_CONFIG_FILE_EPOCH) + { + /* config too old */ + reload = EINA_TRUE; + } + else if (_edi_cfg->version > EDI_CONFIG_FILE_VERSION) + { + /* config too new, WTF ? */ + reload = EINA_TRUE; + } + + /* if too old or too new, clear it so we can create new */ + if (reload) _edi_config_cb_free(); + } + + if (!_edi_cfg) + { + _edi_cfg = malloc(sizeof(Edi_Config)); + save = EINA_TRUE; + } + + /* define some convenient macros */ +#define IFCFG(v) if ((_edi_cfg->version & 0xffff) < (v)) { +#define IFCFGELSE } else { +#define IFCFGEND } + + /* setup defaults */ + IFCFG(0x000a); + + _edi_cfg->font.size = 12; + _edi_cfg->gui.translucent = EINA_TRUE; + _edi_cfg->projects = NULL; + IFCFGEND; + + /* limit config values so they are sane */ + EDI_CONFIG_LIMIT(_edi_cfg->font.size, 8, 96); + + _edi_cfg->version = EDI_CONFIG_FILE_VERSION; + + if (save) _edi_config_save(); +} + +void +_edi_config_save(void) +{ + if (_edi_config_domain_save(PACKAGE_NAME, _edi_cfg_edd, _edi_cfg)) + { + /* perform any UI updates required */ + } +} + +void +_edi_config_project_add(const char *path) +{ + Edi_Config_Project *project; + Eina_List *list, *next; + + EINA_LIST_FOREACH_SAFE(_edi_cfg->projects, list, next, project) + { + if (!strncmp(project->path, path, strlen(project->path))) + _edi_cfg->projects = eina_list_remove_list(_edi_cfg->projects, list); + } + + project = malloc(sizeof(*project)); + project->path = eina_stringshare_add(path); + project->name = eina_stringshare_add(basename((char*) path)); + _edi_cfg->projects = eina_list_prepend(_edi_cfg->projects, project); + _edi_config_save(); +} diff --git a/src/bin/edi_config.h b/src/bin/edi_config.h new file mode 100644 index 0000000..e1f997f --- /dev/null +++ b/src/bin/edi_config.h @@ -0,0 +1,49 @@ +#ifndef _EDI_CONFIG_H_ +# define _EDI_CONFIG_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _Edi_Config_Project Edi_Config_Project; +typedef struct _Edi_Config Edi_Config; + +struct _Edi_Config_Project +{ + const char *name; + const char *path; +}; + +struct _Edi_Config +{ + int version; + + struct + { + int size; + } font; + + struct + { + Eina_Bool translucent; + } gui; + + Eina_List *projects; +}; + +extern Edi_Config *_edi_cfg; + +Eina_Bool _edi_config_init(void); +Eina_Bool _edi_config_shutdown(void); +void _edi_config_load(void); +void _edi_config_save(void); + +void _edi_config_project_add(const char *path); + +#ifdef __cplusplus +} +#endif + +#endif /* _EDI_CONFIG_H_ */ diff --git a/src/bin/edi_consolepanel.c b/src/bin/edi_consolepanel.c index ffaf4ce..235cda7 100644 --- a/src/bin/edi_consolepanel.c +++ b/src/bin/edi_consolepanel.c @@ -13,6 +13,7 @@ #include "edi_consolepanel.h" #include "mainview/edi_mainview.h" +#include "edi_config.h" #include "edi_private.h" @@ -339,7 +340,7 @@ void edi_testpanel_add(Evas_Object *parent) _edi_test_code = code; widget = elm_code_widget_add(parent, code); - elm_code_widget_font_size_set(widget, 12); + elm_code_widget_font_size_set(widget, _edi_cfg->font.size); evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL); diff --git a/src/bin/edi_logpanel.c b/src/bin/edi_logpanel.c index f87d9d8..3c7a40d 100644 --- a/src/bin/edi_logpanel.c +++ b/src/bin/edi_logpanel.c @@ -6,6 +6,7 @@ #include #include "edi_logpanel.h" +#include "edi_config.h" #include "edi_private.h" @@ -44,7 +45,7 @@ void edi_logpanel_add(Evas_Object *parent) code = elm_code_create(); widget = elm_code_widget_add(parent, code); - elm_code_widget_font_size_set(widget, 12); + elm_code_widget_font_size_set(widget, _edi_cfg->font.size); evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(widget); diff --git a/src/bin/edi_main.c b/src/bin/edi_main.c index 3e86bd9..7cd7d2a 100644 --- a/src/bin/edi_main.c +++ b/src/bin/edi_main.c @@ -13,6 +13,7 @@ #include "gettext.h" #include "Edi.h" +#include "edi_config.h" #include "edi_filepanel.h" #include "edi_logpanel.h" #include "edi_consolepanel.h" @@ -628,6 +629,8 @@ edi_open(const char *inputpath) evas_object_resize(win, 560 * elm_config_scale_get(), 420 * elm_config_scale_get()); evas_object_show(win); + _edi_config_project_add(path); + free(path); return win; } @@ -678,6 +681,9 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) textdomain(PACKAGE); #endif + if (!_edi_config_init()) + goto config_error; + edi_init(); args = ecore_getopt_parse(&optdesc, values, argc, argv); @@ -709,8 +715,11 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) elm_run(); end: - edi_shutdown(); elm_shutdown(); + edi_shutdown(); + + config_error: + _edi_config_shutdown(); return 0; } diff --git a/src/bin/edi_private.h b/src/bin/edi_private.h index 32d7ede..0cbe1f3 100644 --- a/src/bin/edi_private.h +++ b/src/bin/edi_private.h @@ -1,6 +1,8 @@ #ifndef EDI_PRIVATE_H_ # define EDI_PRIVATE_H_ +#include + extern int _edi_lib_log_dom; #ifdef CRIT diff --git a/src/bin/editor/edi_editor.c b/src/bin/editor/edi_editor.c index d103e43..6c21002 100644 --- a/src/bin/editor/edi_editor.c +++ b/src/bin/editor/edi_editor.c @@ -15,11 +15,10 @@ #endif #include "mainview/edi_mainview.h" +#include "edi_config.h" #include "edi_private.h" -#define EDITOR_FONT "DEFAULT='font=Monospace font_size=12'" - #define Edi_Color const char * static Edi_Color EDI_COLOR_FOREGROUND = ""; @@ -39,6 +38,8 @@ static Edi_Color EDI_COLOR_SEVIRITY_IGNORED = ""; static Edi_Color EDI_COLOR_SEVIRITY_NOTE = ""; static Edi_Color EDI_COLOR_SEVIRITY_WARNING = ""; +static char *_default_font; + typedef struct { unsigned int line; @@ -57,6 +58,21 @@ _update_lines(Edi_Editor *editor); static void _update_highlight(Edi_Editor *editor); +static const char * +_edi_editor_font_get() +{ + char *format; + + if (_default_font) + return _default_font; + + format = "DEFAULT='font=Monospace font_size=%d'"; + + _default_font = malloc(sizeof(char) * (strlen(format) + 4)); + snprintf(_default_font, strlen(format) + 4, format, _edi_cfg->font.size); + return _default_font; +} + static void _undo_do(Edi_Editor *editor, Elm_Entry_Change_Info *inf) { @@ -596,7 +612,7 @@ EAPI Evas_Object *edi_editor_add(Evas_Object *parent, Edi_Mainview_Item *item) elm_scroller_policy_set(lines, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); elm_entry_editable_set(lines, EINA_FALSE); - elm_entry_text_style_user_push(lines, EDITOR_FONT); + elm_entry_text_style_user_push(lines, _edi_editor_font_get()); evas_object_color_set(lines, 127, 127, 127, 255); evas_object_size_hint_weight_set(lines, 0.052, EVAS_HINT_EXPAND); @@ -608,7 +624,7 @@ EAPI Evas_Object *edi_editor_add(Evas_Object *parent, Edi_Mainview_Item *item) elm_entry_editable_set(txt, EINA_TRUE); elm_entry_scrollable_set(txt, EINA_TRUE); elm_entry_line_wrap_set(txt, EINA_FALSE); - elm_entry_text_style_user_push(txt, EDITOR_FONT); + elm_entry_text_style_user_push(txt, _edi_editor_font_get()); editor = calloc(1, sizeof(*editor)); editor->entry = txt; diff --git a/src/bin/welcome/edi_welcome.c b/src/bin/welcome/edi_welcome.c index f031c29..3c34f6c 100644 --- a/src/bin/welcome/edi_welcome.c +++ b/src/bin/welcome/edi_welcome.c @@ -5,6 +5,8 @@ #include #include "edi_welcome.h" +#include "edi_config.h" + #include "edi_private.h" #include @@ -200,6 +202,47 @@ _edi_welcome_exit(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EIN edi_close(); } +static void +_project_list_clicked(void *data, Evas_Object *li EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + _edi_welcome_project_open((const char *)data); +} + +static void +_edi_welcome_add_recent_projects(Evas_Object *box) +{ + Evas_Object *list, *label; + Eina_List *listitem; + Edi_Config_Project *project; + char *display, *format; + int displen; + + list = elm_list_add(box); + evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL); + + EINA_LIST_FOREACH(_edi_cfg->projects, listitem, project) + { + format = "(%s)"; + displen = strlen(project->path) + strlen(format) - 1; + display = malloc(sizeof(char) * displen); + snprintf(display, displen, format, project->path); + + label = elm_label_add(box); + elm_object_text_set(label, display); + evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(label); + + elm_list_item_append(list, project->name, NULL, label, _project_list_clicked, project->path); + + free(display); + } + elm_box_pack_end(box, list); + evas_object_show(list); +} + Evas_Object *edi_welcome_show() { Evas_Object *win, *hbx, *box, *button, *label, *image, *naviframe; @@ -232,11 +275,13 @@ Evas_Object *edi_welcome_show() label = elm_label_add(box); elm_object_text_set(label, "Recent Projects:"); - evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, label); evas_object_show(label); + _edi_welcome_add_recent_projects(box); + button = elm_button_add(box); elm_object_text_set(button, "Open Existing Project"); evas_object_smart_callback_add(button, "clicked", @@ -265,7 +310,7 @@ Evas_Object *edi_welcome_show() elm_box_pack_end(box, button); evas_object_show(button); - evas_object_resize(win, 320 * elm_config_scale_get(), 180 * elm_config_scale_get()); + evas_object_resize(win, 480 * elm_config_scale_get(), 260 * elm_config_scale_get()); evas_object_show(win); item = elm_naviframe_item_push(naviframe,