mirror of
https://github.com/zlgopen/awtk.git
synced 2025-05-08 19:44:45 +08:00
improve app_conf, fix issue #898
This commit is contained in:
parent
060e08884b
commit
a5889f0a10
@ -1,5 +1,8 @@
|
||||
# 最新动态
|
||||
|
||||
2024/09/17
|
||||
* app_conf初始化时,不拷贝默认配置到用户配置,而是优先读取用户配置,再读取默认配置。
|
||||
|
||||
2024/09/14
|
||||
* edit控件得到焦点时才响应鼠标滚轮事件(感谢雨欣提供补丁)
|
||||
|
||||
|
@ -24,6 +24,8 @@ AWTK 提供了 [app_conf](https://github.com/zlgopen/awtk/blob/master/docs/manua
|
||||
|
||||
* Flash(TODO)
|
||||
|
||||
> 为了方便软件升级时,保留用户配置,先从用户配置读取,如果配置不存在,再读取默认配置。
|
||||
|
||||
## 2. 初始化(任意选一种格式即可)
|
||||
|
||||
[app_conf](https://github.com/zlgopen/awtk/blob/master/docs/manual/app_conf_t.md) 作为可选组件,需要开发者自己初始化。
|
||||
@ -467,7 +469,7 @@ app_conf_on_changed(app_conf_changed, NULL);
|
||||
|
||||
3.8 恢复出厂设置
|
||||
|
||||
用默认配置文件替换当前配置文件,并重新加载。
|
||||
删除用户配置文件,并重新加载。
|
||||
|
||||
```c
|
||||
/**
|
||||
@ -615,7 +617,7 @@ ret_t application_exit() {
|
||||
ENSURE(app_conf_init_json("demo") == RET_OK);
|
||||
```
|
||||
|
||||
> 在初始化时,如果配置文件不存在,则将缺省配置拷贝到配置文件。
|
||||
> 优先读取用户配置,如果没有读到,再读取默认配置。
|
||||
|
||||
## 9. 注意事项
|
||||
|
||||
|
@ -23,34 +23,13 @@
|
||||
#include "tkc/mem.h"
|
||||
#include "tkc/path.h"
|
||||
#include "tkc/utils.h"
|
||||
|
||||
#include "conf_io/conf_obj.h"
|
||||
#include "conf_io/object_app_conf.inc"
|
||||
#include "conf_io/app_conf_init.h"
|
||||
#include "tkc/data_reader_factory.h"
|
||||
#include "tkc/data_writer_factory.h"
|
||||
|
||||
static bool_t app_conf_file_exist(const char* url) {
|
||||
bool_t exist = FALSE;
|
||||
data_reader_t* reader = data_reader_factory_create_reader(data_reader_factory(), url);
|
||||
|
||||
if (reader != NULL) {
|
||||
if (data_reader_get_size(reader) > 0) {
|
||||
exist = TRUE;
|
||||
}
|
||||
data_reader_destroy(reader);
|
||||
}
|
||||
|
||||
return exist;
|
||||
}
|
||||
|
||||
static ret_t app_conf_prepare_default(const char* url, const char* default_url) {
|
||||
ret_t ret = RET_OK;
|
||||
if (!app_conf_file_exist(url)) {
|
||||
ret = data_url_copy(url, default_url);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ret_t app_conf_get_url(char url[MAX_PATH + 1], const char* app_name, const char* extname) {
|
||||
char path[MAX_PATH + 1];
|
||||
char app_dir[MAX_PATH + 1];
|
||||
@ -77,7 +56,10 @@ static ret_t app_conf_get_url(char url[MAX_PATH + 1], const char* app_name, cons
|
||||
}
|
||||
|
||||
ret_t app_conf_init(conf_load_t load, const char* app_name, const char* extname) {
|
||||
ret_t ret = RET_FAIL;
|
||||
tk_object_t* obj = NULL;
|
||||
tk_object_t* default_obj = NULL;
|
||||
tk_object_t* user_obj = NULL;
|
||||
char path[MAX_PATH + 1];
|
||||
#ifdef APP_CONF_URL
|
||||
const char* app_conf_name = APP_CONF_URL;
|
||||
@ -88,24 +70,35 @@ ret_t app_conf_init(conf_load_t load, const char* app_name, const char* extname)
|
||||
|
||||
log_info("app conf: %s\n", app_conf_name);
|
||||
tk_snprintf(path, MAX_PATH, "asset://data/%s.%s", app_name, extname);
|
||||
app_conf_prepare_default(app_conf_name, path);
|
||||
|
||||
obj = load(app_conf_name, TRUE);
|
||||
return_value_if_fail(obj != NULL, RET_FAIL);
|
||||
log_info("load default conf: %s\n", path);
|
||||
default_obj = load(path, TRUE);
|
||||
goto_error_if_fail(default_obj != NULL);
|
||||
|
||||
log_info("load user conf: %s\n", app_conf_name);
|
||||
user_obj = load(app_conf_name, TRUE);
|
||||
goto_error_if_fail(user_obj != NULL);
|
||||
|
||||
obj = object_app_conf_create(user_obj, default_obj);
|
||||
goto_error_if_fail(obj != NULL);
|
||||
|
||||
app_conf_set_instance(obj);
|
||||
app_conf_set_str(CONF_OBJ_PROP_DEFAULT_URL, path);
|
||||
|
||||
TK_OBJECT_UNREF(obj);
|
||||
|
||||
return RET_OK;
|
||||
error:
|
||||
TK_OBJECT_UNREF(obj);
|
||||
TK_OBJECT_UNREF(user_obj);
|
||||
TK_OBJECT_UNREF(default_obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret_t app_conf_reset(void) {
|
||||
const char* url = app_conf_get_str(CONF_OBJ_PROP_URL, NULL);
|
||||
const char* default_url = app_conf_get_str(CONF_OBJ_PROP_DEFAULT_URL, NULL);
|
||||
|
||||
return_value_if_fail(url != NULL && default_url != NULL, RET_BAD_PARAMS);
|
||||
return_value_if_fail(data_url_copy(url, default_url) == RET_OK, RET_BAD_PARAMS);
|
||||
return_value_if_fail(url != NULL, RET_BAD_PARAMS);
|
||||
data_writer_write_all(url, "\0", 1);
|
||||
return_value_if_fail(app_conf_reload() == RET_OK, RET_BAD_PARAMS);
|
||||
|
||||
return RET_OK;
|
||||
|
78
src/conf_io/object_app_conf.h
Normal file
78
src/conf_io/object_app_conf.h
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* File: object_app_conf.h
|
||||
* Author: AWTK Develop Team
|
||||
* Brief: object app conf
|
||||
*
|
||||
* Copyright (c) 2020 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd.
|
||||
*
|
||||
* 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
|
||||
* License file for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* History:
|
||||
* ================================================================
|
||||
* 2024-09-17 Li XianJing <xianjimli@hotmail.com> created
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TK_OBJECT_APP_CONF_H
|
||||
#define TK_OBJECT_APP_CONF_H
|
||||
|
||||
#include "tkc/object.h"
|
||||
#include "tkc/mutex_nest.h"
|
||||
|
||||
BEGIN_C_DECLS
|
||||
|
||||
/**
|
||||
* @class object_app_conf_t
|
||||
* @parent tk_object_t
|
||||
*
|
||||
* * 将用户配置和默认配置包装起来。
|
||||
* * 优先读取用户配置。
|
||||
* * 默认配置只读,用户配置可读写。
|
||||
*
|
||||
*/
|
||||
typedef struct _object_app_conf_t {
|
||||
tk_object_t object;
|
||||
|
||||
/*private*/
|
||||
tk_object_t* user_obj;
|
||||
tk_object_t* default_obj;
|
||||
} object_app_conf_t;
|
||||
|
||||
/**
|
||||
* @method object_app_conf_create
|
||||
*
|
||||
* 创建对象。
|
||||
*
|
||||
* @annotation ["constructor"]
|
||||
*
|
||||
* @param {tk_object_t*} user_obj 用户配置。
|
||||
* @param {tk_object_t*} default_obj 默认配置。
|
||||
*
|
||||
* @return {tk_object_t*} 返回object对象。
|
||||
*
|
||||
*/
|
||||
tk_object_t* object_app_conf_create(tk_object_t* user_obj, tk_object_t* default_obj);
|
||||
|
||||
/**
|
||||
* @method object_app_conf_cast
|
||||
* 转换为object_app_conf对象。
|
||||
* @annotation ["cast"]
|
||||
* @param {tk_object_t*} obj object_app_conf对象。
|
||||
*
|
||||
* @return {object_app_conf_t*} object_app_conf对象。
|
||||
*/
|
||||
object_app_conf_t* object_app_conf_cast(tk_object_t* obj);
|
||||
|
||||
#define OBJECT_APP_CONF(obj) object_app_conf_cast(obj)
|
||||
|
||||
#define OBJECT_APP_CONF_TYPE "object_app_conf"
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
#endif /*TK_OBJECT_APP_CONF_H*/
|
140
src/conf_io/object_app_conf.inc
Normal file
140
src/conf_io/object_app_conf.inc
Normal file
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* File: object_app_conf.h
|
||||
* Author: AWTK Develop Team
|
||||
* Brief: object app conf
|
||||
*
|
||||
* Copyright (c) 2020 - 2024 Guangzhou ZHIYUAN Electronics Co.,Ltd.
|
||||
*
|
||||
* 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
|
||||
* License file for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* History:
|
||||
* ================================================================
|
||||
* 2024-09-17 Li XianJing <xianjimli@hotmail.com> created
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tkc/mem.h"
|
||||
#include "tkc/value.h"
|
||||
#include "tkc/utils.h"
|
||||
|
||||
#include "object_app_conf.h"
|
||||
|
||||
static ret_t object_app_conf_on_destroy(tk_object_t* obj) {
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL && o->user_obj != NULL, RET_BAD_PARAMS);
|
||||
emitter_off_by_ctx(EMITTER(o->user_obj), o);
|
||||
TK_OBJECT_UNREF(o->user_obj);
|
||||
TK_OBJECT_UNREF(o->default_obj);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int32_t object_app_conf_compare(tk_object_t* obj, tk_object_t* other) {
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL && o->user_obj != NULL, -1);
|
||||
return tk_object_compare(o->user_obj, other);
|
||||
}
|
||||
|
||||
static ret_t object_app_conf_remove_prop(tk_object_t* obj, const char* name) {
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
return tk_object_remove_prop(o->user_obj, name);
|
||||
}
|
||||
|
||||
static ret_t object_app_conf_set_prop(tk_object_t* obj, const char* name, const value_t* v) {
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
return tk_object_set_prop(o->user_obj, name, v);
|
||||
}
|
||||
|
||||
static ret_t object_app_conf_get_prop(tk_object_t* obj, const char* name, value_t* v) {
|
||||
ret_t ret = RET_NOT_FOUND;
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
ret = tk_object_get_prop(o->user_obj, name, v);
|
||||
if (ret != RET_OK) {
|
||||
ret = tk_object_get_prop(o->default_obj, name, v);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ret_t object_app_conf_foreach_prop(tk_object_t* obj, tk_visit_t on_prop, void* ctx) {
|
||||
ret_t ret = RET_OK;
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
ret = tk_object_foreach_prop(o->user_obj, on_prop, ctx);
|
||||
if (ret != RET_STOP) {
|
||||
ret = tk_object_foreach_prop(o->default_obj, on_prop, ctx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool_t object_app_conf_can_exec(tk_object_t* obj, const char* name, const char* args) {
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
return tk_object_can_exec(o->user_obj, name, args);
|
||||
}
|
||||
|
||||
static ret_t object_app_conf_exec(tk_object_t* obj, const char* name, const char* args) {
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
return tk_object_exec(o->user_obj, name, args);
|
||||
}
|
||||
|
||||
static const object_vtable_t s_object_app_conf_vtable = {.type = OBJECT_APP_CONF_TYPE,
|
||||
.desc = OBJECT_APP_CONF_TYPE,
|
||||
.size = sizeof(object_app_conf_t),
|
||||
.is_collection = FALSE,
|
||||
.on_destroy = object_app_conf_on_destroy,
|
||||
.exec = object_app_conf_exec,
|
||||
.can_exec = object_app_conf_can_exec,
|
||||
.compare = object_app_conf_compare,
|
||||
.get_prop = object_app_conf_get_prop,
|
||||
.set_prop = object_app_conf_set_prop,
|
||||
.remove_prop = object_app_conf_remove_prop,
|
||||
.foreach_prop = object_app_conf_foreach_prop};
|
||||
|
||||
static ret_t object_app_conf_forward_events(void* ctx, event_t* e) {
|
||||
object_app_conf_t* o = OBJECT_APP_CONF(ctx);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
emitter_dispatch_simple_event(EMITTER(o), e->type);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
tk_object_t* object_app_conf_create(tk_object_t* user_obj, tk_object_t* default_obj) {
|
||||
tk_object_t* o = NULL;
|
||||
object_app_conf_t* wrapper = NULL;
|
||||
return_value_if_fail(user_obj != NULL, NULL);
|
||||
o = tk_object_create(&s_object_app_conf_vtable);
|
||||
return_value_if_fail(o != NULL, NULL);
|
||||
wrapper = OBJECT_APP_CONF(o);
|
||||
return_value_if_fail(wrapper != NULL, NULL);
|
||||
|
||||
wrapper->user_obj = tk_object_ref(user_obj);
|
||||
wrapper->default_obj = tk_object_ref(default_obj);
|
||||
emitter_on(EMITTER(user_obj), EVT_ITEMS_CHANGED, object_app_conf_forward_events, o);
|
||||
emitter_on(EMITTER(user_obj), EVT_PROPS_CHANGED, object_app_conf_forward_events, o);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
object_app_conf_t* object_app_conf_cast(tk_object_t* obj) {
|
||||
return_value_if_fail(obj != NULL && obj->vt == &s_object_app_conf_vtable, NULL);
|
||||
|
||||
return (object_app_conf_t*)(obj);
|
||||
}
|
@ -111,6 +111,12 @@ TEST(AppConf, reset) {
|
||||
|
||||
ASSERT_STREQ(app_conf_get_str("name", NULL), "test");
|
||||
ASSERT_EQ(app_conf_get_int("age", 0), 100);
|
||||
|
||||
ASSERT_EQ(app_conf_set_str("name", "awtk"), RET_OK);
|
||||
ASSERT_EQ(app_conf_set_int("age", 200), RET_OK);
|
||||
|
||||
ASSERT_STREQ(app_conf_get_str("name", NULL), "awtk");
|
||||
ASSERT_EQ(app_conf_get_int("age", 0), 200);
|
||||
|
||||
ASSERT_EQ(app_conf_deinit(), RET_OK);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user