Add a config system for remembering settings etc

.
Add a recent projects list to our welcome page which remembers what we open
This commit is contained in:
Andy Williams 2014-12-01 16:54:17 -06:00
parent 141a3a2107
commit 1fb649b732
9 changed files with 396 additions and 9 deletions

View File

@ -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 \

263
src/bin/edi_config.c Normal file
View File

@ -0,0 +1,263 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eet.h>
#include <Eina.h>
#include <Ecore_File.h>
#include <Efreet.h>
#include <Elementary.h>
#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();
}

49
src/bin/edi_config.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef _EDI_CONFIG_H_
# define _EDI_CONFIG_H_ 1
#include <Eina.h>
#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_ */

View File

@ -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);

View File

@ -6,6 +6,7 @@
#include <Elm_Code.h>
#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);

View File

@ -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;
}

View File

@ -1,6 +1,8 @@
#ifndef EDI_PRIVATE_H_
# define EDI_PRIVATE_H_
#include <Evas.h>
extern int _edi_lib_log_dom;
#ifdef CRIT

View File

@ -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 = "<color=#ffffff>";
@ -39,6 +38,8 @@ static Edi_Color EDI_COLOR_SEVIRITY_IGNORED = "<backing_color=#000000>";
static Edi_Color EDI_COLOR_SEVIRITY_NOTE = "<backing_color=#ff9900>";
static Edi_Color EDI_COLOR_SEVIRITY_WARNING = "<backing_color=#ff9900>";
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;

View File

@ -5,6 +5,8 @@
#include <Elementary.h>
#include "edi_welcome.h"
#include "edi_config.h"
#include "edi_private.h"
#include <stdlib.h>
@ -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 = "<align=right><color=#999><i>(%s)</i></color></align>";
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,