同步主线代码

This commit is contained in:
tianshaoshuai 2024-09-05 15:24:12 +08:00
parent 26b5d64117
commit c818bcb574
36 changed files with 3458 additions and 303 deletions

1
debian/control vendored
View File

@ -186,6 +186,7 @@ Package: libkysdk-conf2-tools
Architecture: any
Section: utils
Depends: libkysdk-conf2 (= ${binary:Version}),
python3-tk,
${misc:Depends},
${shlibs:Depends}
Multi-Arch: same

View File

@ -1,3 +1,4 @@
usr/bin/kconf2 usr/bin
usr/bin/kconf2-editor usr/bin
src/conf2/tools/gschema_xml2yaml.py usr/bin
src/conf2/tools/kconf2-editor usr/bin
src/conf2/tools/health-check usr/bin
src/conf2/tools/gschema_xml2yaml usr/bin

View File

@ -3,10 +3,23 @@ src/conf2/service/conf2Utils.py usr/bin
src/conf2/service/conf2-server.py usr/bin
src/conf2/service/kysdk-conf2.conf etc/dbus-1/system.d
src/conf2/service/kysdk-conf2.service lib/systemd/system
src/conf2/service/conf2-session-server.py usr/bin
src/conf2/service/kysdk-conf2.desktop etc/xdg/autostart/
src/conf2/configs/conf2.yaml etc/kylin-config/
# dbus control
src/conf2/service/com.kylin.kysdk.conf2.limit etc/dbus-1/conf
src/conf2/service/com.kylin.kysdk.conf2.limit usr/share/dbus-1/conf
src/conf2/service/com.kylin.kysdk.conf2.limit.verify etc/dbus-1/conf
src/conf2/service/com.kylin.kysdk.conf2.limit.verify usr/share/dbus-1/conf
src/conf2/service/conf2-session-server.py usr/bin
src/conf2/service/kysdk-conf2.desktop etc/xdg/autostart/
src/conf2/configs/conf2.yaml etc/kylin-config/
# sync-config
bin/sync-config-system usr/bin
src/conf2/sync-config/com.kylin.kysdk.SyncConfig.conf etc/dbus-1/system.d
src/conf2/sync-config/com.kylin.kysdk.SyncConfig.service lib/systemd/system
bin/sync-config-session usr/bin
src/conf2/sync-config/com.kylin.kysdk.SyncConfig.desktop etc/xdg/autostart/
# update-db
src/conf2/service/conf2-update.py usr/bin
src/conf2/service/conf2-update-db.service lib/systemd/system

View File

@ -1,8 +1,8 @@
base_version=2.4.0
base_version=2.5.0
Name: libkysdk-config
Description: kysdk base layer config component
Requires: kysdk-utils
Version: 2.5.0
Cflags: -I/usr/include/kysdk/kysdk-base/
Libs: -lkyconf
Libs: -lkyconf

View File

@ -1,16 +1,19 @@
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLIB REQUIRED glib-2.0 gio-2.0 gtk+-3.0)
pkg_check_modules(GTK REQUIRED gtk+-3.0)
pkg_check_modules(GLIB REQUIRED glib-2.0 gio-2.0)
# pkg_check_modules(GTK REQUIRED gtk+-3.0)
include_directories(${GLIB_INCLUDE_DIRS} )
include_directories(api)
add_subdirectory(api)
add_subdirectory(sync-config)
add_executable(kconf2 tools/kconf2-tool.c )
target_link_libraries(kconf2 kyconf2)
add_executable(kconf2-editor tools/kconf2-editor.c )
target_link_libraries(kconf2-editor kyconf2 ${GTK_LIBRARIES})
# add_executable(kconf2-editor tools/kconf2-editor.c )
# target_link_libraries(kconf2-editor kyconf2 ${GTK_LIBRARIES})
add_executable(kyconf2-test test/kyconf2-test.c)
target_link_libraries(kyconf2-test kyconf2)
@ -18,8 +21,8 @@ target_link_libraries(kyconf2-test kyconf2)
install(TARGETS kconf2
DESTINATION /usr/bin)
install(TARGETS kconf2-editor
DESTINATION /usr/bin)
# install(TARGETS kconf2-editor
# DESTINATION /usr/bin)
install(TARGETS kyconf2-test
DESTINATION /usr/bin)

View File

@ -282,7 +282,9 @@ static KSettingsSchema *_get_schema(const char *id, const char *version)
int rc = sqlite3_open(db_file, &db);
if (rc != SQLITE_OK)
{
if (0 == strcmp(db_file, "/root/.config/kylin-config/user.db"))
if ((0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) ||
(0 == strcmp(db_file, "/home/lightdm/.config/kylin-config/user.db")) ||
(0 == strcmp(db_file, "/home/messagebus/.config/kylin-config/user.db")))
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed! %s try to open /etc/kylin-config/user.db.\n", __func__, db_file, sqlite3_errmsg(db));
rc = sqlite3_open("/etc/kylin-config/user.db", &db);
@ -378,6 +380,30 @@ out:
return schema;
}
static char *_get_db_file_path(char *buffer, size_t size)
{
uid_t uid = getuid(); // 获取当前进程的用户ID
char user_name[128] = {0};
struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体
if (NULL == pw)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__);
return NULL;
}
else
{
strcpy(user_name, pw->pw_name);
endpwent();
}
char db_file[PATH_MAX];
if (0 == strcmp(user_name, "root"))
snprintf(buffer, size, "/root/.config/kylin-config/user.db");
else
snprintf(buffer, size, "/home/%s/.config/kylin-config/user.db", user_name);
return buffer;
}
static void _get_schemas()
{
char ***apps = NULL, ***versions = NULL, ***configures = NULL;
@ -387,7 +413,7 @@ static void _get_schemas()
struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体
if (NULL == pw)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__);
strcpy(user_name, "root");
}
else
@ -401,7 +427,7 @@ static void _get_schemas()
sprintf(db_file, "/root/.config/kylin-config/user.db");
else
sprintf(db_file, "/home/%s/.config/kylin-config/user.db", user_name);
// syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s \n", __func__, db_file);
// syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :open %s \n", __func__, db_file);
// 读取数据库数据
sqlite3 *db = NULL;
@ -411,9 +437,12 @@ static void _get_schemas()
int rc = sqlite3_open(db_file, &db);
if (rc != SQLITE_OK)
{
if (0 == strcmp(db_file, "/root/.config/kylin-config/user.db"))
// 华为云项目中,systemd屏蔽用户目录;lighdm没有用户目录 所以读取etc下的数据
if ((0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) ||
(0 == strcmp(db_file, "/home/lightdm/.config/kylin-config/user.db")) ||
(0 == strcmp(db_file, "/home/messagebus/.config/kylin-config/user.db")))
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed! %s try to open /etc/kylin-config/user.db.\n", __func__, db_file, sqlite3_errmsg(db));
syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed : %s! try to open /etc/kylin-config/user.db.\n", __func__, db_file, sqlite3_errmsg(db));
rc = sqlite3_open("/etc/kylin-config/user.db", &db);
if (rc != SQLITE_OK)
{
@ -422,9 +451,12 @@ static void _get_schemas()
}
}
else
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed : %s\n", __func__, db_file, sqlite3_errmsg(db));
return;
}
}
char sql[100];
rc = sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &err_msg);
if (rc != SQLITE_OK)
@ -468,7 +500,7 @@ static void _get_schemas()
}
sqlite3_close(db);
if (!apps || !versions || ! configures)
if (!apps || !versions || !configures)
return;
// 顶层hash 元素为appData:hash(versionData:hash(s:KSettingsSchema))
@ -476,7 +508,7 @@ static void _get_schemas()
schemas_table = g_hash_table_new_full(data_hash, data_equal, app_data_destroy, (GDestroyNotify)g_hash_table_destroy);
if (NULL == schemas_table)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :Creat hash Table failed\n", __func__);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Creat hash Table failed\n", __func__);
goto out;
}
@ -496,7 +528,7 @@ static void _get_schemas()
{
AppData *app_data = NULL;
VersionData *version_data = NULL;
syslog(LOG_INFO, "[kysdk-conf2] %s -> Read a new version id %s, old id is %d\n", __func__, configures[i][1], version_id);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read a new version id %s, old id is %d\n", __func__, configures[i][1], version_id);
version_id = atoi(configures[i][1]);
version_data = calloc(1, sizeof *version_data);
@ -506,7 +538,7 @@ static void _get_schemas()
// 版本id对应的应用id改变
if (app_id != atoi(VER_COLUMN[1]))
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> Read a new app id %s, old id is %d\n", __func__, VER_COLUMN[1], app_id);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read a new app id %s, old id is %d\n", __func__, VER_COLUMN[1], app_id);
app_id = atoi(VER_COLUMN[1]);
app_data = calloc(1, sizeof *app_data);
@ -519,7 +551,7 @@ static void _get_schemas()
version = g_hash_table_new_full(data_hash, data_equal, version_data_destroy, (GDestroyNotify)g_hash_table_destroy);
if (NULL == version)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :Creat hash2 Table failed\n", __func__);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Creat hash2 Table failed\n", __func__);
app_data_destroy(app_data);
version_data_destroy(version_data);
goto out;
@ -537,19 +569,19 @@ static void _get_schemas()
g_hash_table_insert(version, version_data, schemas);
if (NULL == schemas)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :Creat schemas hash Table failed\n", __func__);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Creat schemas hash Table failed\n", __func__);
version_data_destroy(version_data);
goto out;
}
}
else
version_data_destroy(version_data);
syslog(LOG_INFO, "[kysdk-conf2] %s -> Read %s configure wiht version number %s\n", __func__, APP_COLUMN[1], VER_COLUMN[2]);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read %s configure wiht version number %s\n", __func__, APP_COLUMN[1], VER_COLUMN[2]);
schema = g_hash_table_lookup(schemas, APP_COLUMN[1]);
if (NULL == schema)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> Creat node %s\n", __func__, APP_COLUMN[1]);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Creat node %s\n", __func__, APP_COLUMN[1]);
schema = calloc(1, sizeof *schema);
if (NULL == schema)
goto out;
@ -560,7 +592,7 @@ static void _get_schemas()
}
else
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]);
if (schema->values)
{
g_hash_table_destroy(schema->values);
@ -604,7 +636,7 @@ static void _get_schemas()
}
sprintf(parent_name, "%s%s", APP_COLUMN[1], tmp);
}
syslog(LOG_INFO, "[kysdk-conf2] %s -> %s's parent name %s\n", __func__, node_name, parent_name);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> %s's parent name %s\n", __func__, node_name, parent_name);
// 给父组件增加子组件名
KSettingsSchema *parent_schema = g_hash_table_lookup(schemas, parent_name);
@ -624,7 +656,7 @@ static void _get_schemas()
schema = g_hash_table_lookup(schemas, schema_name);
if (NULL == schema)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> Creat node %s\n", __func__, schema_name);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Creat node %s\n", __func__, schema_name);
schema = calloc(1, sizeof *schema);
if (NULL == schema)
{
@ -646,7 +678,7 @@ static void _get_schemas()
}
else
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]);
if (schema->values)
{
g_hash_table_destroy(schema->values);
@ -673,7 +705,7 @@ static void _get_schemas()
}
else if (0 == strcmp(node_type, "key"))
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> Read %s configure %s wiht version number %s\n", __func__, schema->id, node_name, schema->version);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read %s configure %s wiht version number %s\n", __func__, schema->id, node_name, schema->version);
// hash表 shashs:s
if (NULL == schema->values)
schema->values = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy);
@ -769,22 +801,24 @@ KSettingsSchema *kdk_conf2_schema_table_lookup(const char *id, const char *versi
GHashTableIter iter;
g_hash_table_iter_init(&iter, schemas_table);
while (g_hash_table_iter_next(&iter, (gpointer*)(&app_data), (gpointer*)(&version_hash)))
while (g_hash_table_iter_next(&iter, (gpointer*)&app_data, (gpointer*)&version_hash))
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> find %s\n", __func__, app_data->name);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find %s\n", __func__, app_data->name);
if (0 == strcmp(app_data->name, list[0]))
{
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find app :%s\n", __func__, app_data->name);
VersionData *version_data = NULL;
GHashTable *schemas = NULL;
version = version ? version : app_data->default_version;
GHashTableIter iter_version;
g_hash_table_iter_init(&iter_version, version_hash);
while (g_hash_table_iter_next(&iter_version, (gpointer*)(&version_data), (gpointer*)(&schemas)))
while (g_hash_table_iter_next(&iter_version, (gpointer*)&version_data, (gpointer*)&schemas))
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> find %s '%s configure\n", __func__, app_data->name, version_data->name);
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find %s '%s configure\n", __func__, app_data->name, version_data->name);
if (0 == strcmp(version_data->name, version))
{
syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find version :%s\n", __func__, version_data->name);
result = g_hash_table_lookup(schemas, id);
break;
}
@ -1055,6 +1089,20 @@ void kdk_conf2_schema_update_schemas_table()
_get_schemas();
}
void kdk_conf2_schema_key_set_value(GHashTable *key, char *value)
{
if (g_hash_table_contains(key, "custom_value"))
g_hash_table_replace(key, "custom_value", strdup(value));
else
g_hash_table_insert(key, "custom_value", strdup(value));
}
void kdk_conf2_schema_key_reset(GHashTable *key)
{
if (g_hash_table_contains(key, "custom_value"))
g_hash_table_remove(key, "custom_value");
}
// 重新读取某个schema的配置
KSettingsSchema *kdk_conf2_schema_reload(const char *id, const char *version)
{
@ -1066,7 +1114,7 @@ KSettingsSchema *kdk_conf2_schema_reload(const char *id, const char *version)
GHashTableIter iter;
g_hash_table_iter_init(&iter, schemas_table);
while (g_hash_table_iter_next(&iter, (gpointer*)(&app_data), (gpointer*)(&version_hash)))
while (g_hash_table_iter_next(&iter, (gpointer*)&app_data, (gpointer*)&version_hash))
{
if (0 == strcmp(app_data->name, list[0]))
{
@ -1075,7 +1123,7 @@ KSettingsSchema *kdk_conf2_schema_reload(const char *id, const char *version)
GHashTableIter iter_version;
g_hash_table_iter_init(&iter_version, version_hash);
while (g_hash_table_iter_next(&iter_version, (gpointer*)(&version_data), (gpointer*)(&schemas)))
while (g_hash_table_iter_next(&iter_version, (gpointer*)&version_data, (gpointer*)&schemas))
{
if (0 == strcmp(version_data->name, version))
{

View File

@ -96,6 +96,10 @@ extern "C"
void kdk_conf2_schema_update_schemas_table();
void kdk_conf2_schema_key_set_value(GHashTable *key, char *value);
void kdk_conf2_schema_key_reset(GHashTable *key);
#if __cplusplus
}
#endif

View File

@ -28,7 +28,6 @@
#include <stdarg.h>
#include <sys/stat.h>
#include <pwd.h>
#include <gio/gsettings.h>
#include "libkysettings.h"
#include "ksettingsschema.h"
@ -46,7 +45,6 @@ typedef struct _KSettingsPrivate
GMainContext *main_context;
KSettingsSchema *schema;
GDBusConnection *conn;
GSettings *gsettings;
guint sub_id[2];
} KSettingsPrivate;
@ -107,11 +105,6 @@ static void k_settings_finalize(GObject *object)
g_dbus_connection_signal_unsubscribe(ksettings->priv->conn, ksettings->priv->sub_id[SIGNAL_CHANGED]);
g_dbus_connection_signal_unsubscribe(ksettings->priv->conn, ksettings->priv->sub_id[SIGNAL_RELOAD]);
g_object_unref(ksettings->priv->conn);
if (ksettings->priv->gsettings)
{
g_settings_sync();
g_object_unref(ksettings->priv->gsettings);
}
}
G_OBJECT_CLASS(k_settings_parent_class)->finalize(object);
@ -164,20 +157,6 @@ static void *_g_main_loop_thread(void *data)
return NULL;
}
static void _on_gsettings_key_changed(GSettings *setting, const char *key, void *user_data)
{
GVariant *value = g_settings_get_value(setting, key);
KSettings *ksetting = (KSettings *)user_data;
char *conf2_value = kdk_conf2_get_value(ksetting, key);
if (0 == strcmp(conf2_value, g_variant_print(value, TRUE)))
return;
if (kdk_conf2_set_value(ksetting, key, g_variant_print(value, TRUE)))
{
// g_signal_emit(ksetting, k_settings_signals[SIGNAL_CHANGED], g_quark_from_string(key), key);
}
g_variant_unref(value);
}
/**
* @brief _on_key_changed DBus服务中key_changed信号响应函数
* @param connection
@ -206,34 +185,9 @@ static void _on_key_changed(GDBusConnection *connection,
ksettings->priv->schema = kdk_conf2_schema_reload(id, version);
g_signal_emit(ksettings, k_settings_signals[SIGNAL_CHANGED], g_quark_from_string(key), key);
syslog(LOG_INFO, "[kysdk-conf2] %s changed signal\n", key);
if (ksettings->priv->gsettings)
{
const gchar *endptr = NULL;
GError *error = NULL;
GVariant *gsetting_value = g_settings_get_value(ksettings->priv->gsettings, key);
if (NULL != gsetting_value)
{
char *value = kdk_conf2_get_value(ksettings, key);
if (0 != strcmp(value, g_variant_print(gsetting_value, TRUE)))
{
char *type = kdk_conf2_get_type(ksettings, key);
GVariant *variant = g_variant_parse(G_VARIANT_TYPE(type), value, NULL, &endptr, &error);
if (NULL == variant)
{
klog_err("[kysdk-conf2] %s -> %s\n", __func__, error->message);
return;
}
g_settings_set_value(ksettings->priv->gsettings, key, variant);
g_settings_sync();
g_variant_unref(variant);
}
g_variant_unref(gsetting_value);
}
}
}
g_free(schema_id);
g_free(schema_version);
mutex = 0;
}
/**
@ -386,6 +340,124 @@ static int _call_method(const char *method, const char *id, const char *version,
return response;
}
static int _compare_versions(char *version1, char *version2)
{
if (version1 != NULL && version2 == NULL)
return 1;
else if (version1 == NULL && version2 != NULL)
return -1;
else if (version1 == NULL && version2 == NULL)
return 0;
int result = 0;
char v1[64], v2[64];
memset(v1, 0, 64);
strcpy(v1, version1);
memset(v2, 0, 64);
strcpy(v2, version2);
char *save_ptr1 = NULL;
char *save_ptr2 = NULL;
char *token1;
char *token2;
token1 = strtok_r(v1, ".-k", &save_ptr1);
token2 = strtok_r(v2, ".-k", &save_ptr2);
while (1)
{
if (token1 != NULL && token2 != NULL)
{
int num1 = atoi(token1);
int num2 = atoi(token2);
if (num1 > num2)
{
result = 1;
break;
}
else if (num1 < num2)
{
result = -1;
break;
}
}
else if (token1 == NULL && token2 != NULL)
{
result = -1;
break;
}
else if (token1 != NULL && token2 == NULL)
{
result = 1;
break;
}
else if (token1 == NULL && token2 == NULL)
break;
token1 = strtok_r(NULL, ".-k", &save_ptr1);
token2 = strtok_r(NULL, ".-k", &save_ptr2);
}
return result;
}
static char *_check_version(const char *id, const char *version)
{
if (version != NULL)
return version;
AppData *app_data = NULL;
GHashTable *version_hash = NULL;
char app[64];
int size = 0;
char *p = id;
while (*p != '.' && *p != '\0')
{
size++;
p++;
}
strncpy(app, id, size);
GHashTableIter iter;
g_hash_table_iter_init(&iter, schemas_table);
while (g_hash_table_iter_next(&iter, (gpointer*)&app_data, (gpointer*)&version_hash))
{
if (0 == strcmp(app_data->name, app))
{
VersionData *version_data = NULL;
GHashTable *schemas = NULL;
// TODO: 读取配置文件获取最大最小版本
char *min_version = "1.2.0.0-0k0.0";
char *max_version = "2.5.1.0-0k0.0";
if ((-1 == _compare_versions(min_version, app_data->default_version)) &&
(1 == _compare_versions(max_version, app_data->default_version)))
{
return app_data->default_version;
}
GHashTableIter iter_version;
g_hash_table_iter_init(&iter_version, version_hash);
char *tmp = NULL;
while (g_hash_table_iter_next(&iter_version, (gpointer*)&version_data, (gpointer*)&schemas))
{
if (0 == strcmp(version_data->name, app_data->default_version))
{
continue;
}
if ((-1 == _compare_versions(min_version, version_data->name)) &&
(1 == _compare_versions(max_version, version_data->name)))
{
// 返回符合要求的版本中,最高的版本
tmp = _compare_versions(version_data->name, tmp) > 0 ? version_data->name : tmp;
}
}
return tmp;
}
}
return NULL;
}
KSettings *kdk_conf2_new(const char *id, const char *version)
{
if (NULL == id)
@ -403,6 +475,14 @@ KSettings *kdk_conf2_new(const char *id, const char *version)
return NULL;
}
// version = _check_version(id, version);
// if (NULL == version)
// {
// syslog(LOG_INFO, "[kysdk-conf2] There is no version number that meets the requirements\n");
// return NULL;
// }
// syslog(LOG_INFO, "[kysdk-conf2] Use the %s version of the configuration file\n", version);
KSettingsSchema *schema = kdk_conf2_schema_table_lookup(id, version);
if (NULL == schema)
{
@ -417,88 +497,87 @@ KSettings *kdk_conf2_new(const char *id, const char *version)
return NULL;
}
const char * const *gsettings_schemas = g_settings_list_schemas();
if (gsettings_schemas)
{
for (int i = 0; gsettings_schemas[i]; i++)
{
char *p = strstr(gsettings_schemas[i], id);
if (NULL == p)
continue;
int len = strlen(id);
if (*(p + len) == '\0')
{
ksettings->priv->gsettings = g_settings_new(gsettings_schemas[i]);
g_signal_connect(ksettings->priv->gsettings, "changed", G_CALLBACK(_on_gsettings_key_changed), ksettings);
}
}
}
ksettings->priv->schema = schema;
uid_t uid = getuid(); // 获取当前进程的用户ID
char user_name[128] = {0};
struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体
if (NULL == pw)
int is_dbus_daemon = 0;
char process_name[256];
FILE *fp = fopen("/proc/self/comm", "r");
if (fp != NULL)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__);
strcpy(user_name, "root");
}
else
{
strcpy(user_name, pw->pw_name);
endpwent();
fgets(process_name, sizeof(process_name), fp);
fclose(fp);
// 去除末尾换行符
process_name[strcspn(process_name, "\n")] = 0;
if (0 == strcmp(process_name, "dbus-daemon"))
is_dbus_daemon = 1;
}
// 创建dbus服务的链接用于调用接口及接收信号
GError *error = NULL;
if (0 == strcmp(user_name, "root"))
ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
else
ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (error != NULL)
if (!is_dbus_daemon)
{
syslog(LOG_INFO, "[kysdk-conf2] Connection Error: %s\n", error->message);
g_object_unref(ksettings);
ksettings = NULL;
g_error_free(error);
return NULL;
}
uid_t uid = getuid(); // 获取当前进程的用户ID
char user_name[128] = {0};
struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体
if (NULL == pw)
{
syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__);
strcpy(user_name, "root");
}
else
{
strcpy(user_name, pw->pw_name);
endpwent();
}
// 监听key_changed信号
ksettings->priv->sub_id[0] = g_dbus_connection_signal_subscribe(ksettings->priv->conn,
"com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意)
"com.kylin.kysdk.conf2", // 接口名称
"key_changed", // 信号名称
"/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意)
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
_on_key_changed,
ksettings,
NULL);
// 监听重载信号
ksettings->priv->sub_id[1] = g_dbus_connection_signal_subscribe(ksettings->priv->conn,
"com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意)
"com.kylin.kysdk.conf2", // 接口名称
"updated", // 信号名称
"/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意)
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
_on_updated,
ksettings,
NULL);
// 创建dbus服务的链接用于调用接口及接收信号
GError *error = NULL;
if (0 == strcmp(user_name, "root"))
ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
else
ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (error != NULL)
{
syslog(LOG_INFO, "[kysdk-conf2] Connection Error: %s\n", error->message);
g_object_unref(ksettings);
ksettings = NULL;
g_error_free(error);
return NULL;
}
// 创建glib的事件处理循环单独起线程。
// 如果循环已经启动增加dbus_signal_loop的引用计数
if (NULL == dbus_signal_loop)
{
dbus_signal_loop = g_main_loop_new(NULL, FALSE);
pthread_t thread;
pthread_create(&thread, NULL, _g_main_loop_thread, NULL);
// 监听key_changed信号
ksettings->priv->sub_id[0] = g_dbus_connection_signal_subscribe(ksettings->priv->conn,
"com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意)
"com.kylin.kysdk.conf2", // 接口名称
"key_changed", // 信号名称
"/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意)
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
_on_key_changed,
ksettings,
NULL);
// 监听重载信号
ksettings->priv->sub_id[1] = g_dbus_connection_signal_subscribe(ksettings->priv->conn,
"com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意)
"com.kylin.kysdk.conf2", // 接口名称
"updated", // 信号名称
"/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意)
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
_on_updated,
ksettings,
NULL);
// 创建glib的事件处理循环单独起线程。
// 如果循环已经启动增加dbus_signal_loop的引用计数
if (NULL == dbus_signal_loop)
{
dbus_signal_loop = g_main_loop_new(NULL, FALSE);
pthread_t thread;
pthread_create(&thread, NULL, _g_main_loop_thread, NULL);
}
else
g_main_loop_ref(dbus_signal_loop);
ref_count++;
}
else
g_main_loop_ref(dbus_signal_loop);
ref_count++;
return ksettings;
}
@ -509,12 +588,30 @@ void kdk_conf2_ksettings_destroy(KSettings *ksettings)
g_object_unref(ksettings);
// 减少dbus_signal_loop的引用计数
// 如果归零则停止事件循环
g_main_loop_unref(dbus_signal_loop);
int is_dbus_daemon = 0;
char process_name[256];
FILE *fp = fopen("/proc/self/comm", "r");
if (fp != NULL)
{
fgets(process_name, sizeof(process_name), fp);
fclose(fp);
// 去除末尾换行符
process_name[strcspn(process_name, "\n")] = 0;
if (0 == strcmp(process_name, "dbus-daemon"))
is_dbus_daemon = 1;
}
if (!is_dbus_daemon)
{
// 减少dbus_signal_loop的引用计数
// 如果归零则停止事件循环
g_main_loop_unref(dbus_signal_loop);
}
if (0 == (--ref_count))
{
g_main_loop_quit(dbus_signal_loop);
g_hash_table_destroy(schemas_table);
schemas_table = NULL;
// g_main_loop_quit(dbus_signal_loop);
dbus_signal_loop = NULL;
}
}
@ -620,16 +717,22 @@ int kdk_conf2_set_value(KSettings *ksettings, const char *key, const char *value
char *id = kdk_conf2_schema_get_id(ksettings->priv->schema);
char *version = kdk_conf2_schema_get_version(ksettings->priv->schema);
if (NULL == curr_value || 0 != strcmp(curr_value, value))
{
result = _call_method("set",
id,
version,
key, value);
if (result)
{
key_hash = kdk_conf2_schema_get_key(ksettings->priv->schema, key);
kdk_conf2_schema_key_set_value(key_hash, value);
}
}
else
result = TRUE;
g_free(id);
g_free(version);
g_free(curr_value);
syslog(LOG_INFO, "[kysdk-conf2] %s -> Set value finished. Return %s\n", __func__, result ? "true" : "false");
return result;
}
@ -1130,10 +1233,15 @@ void kdk_conf2_reset(KSettings *ksettings, const char *key)
syslog(LOG_INFO, "[kysdk-conf2] %s -> :reset %s value\n", __func__, key);
char *id = kdk_conf2_schema_get_id(ksettings->priv->schema);
char *version = kdk_conf2_schema_get_version(ksettings->priv->schema);
_call_method("reset",
id,
version,
key, NULL);
int result = _call_method("reset",
id,
version,
key, NULL);
if (result)
{
GHashTable *key_hash = kdk_conf2_schema_get_key(ksettings->priv->schema, key);
kdk_conf2_schema_key_reset(key_hash);
}
g_free(id);
g_free(version);
}
@ -1217,6 +1325,11 @@ char **kdk_conf2_list_schemas(const char *app, const char *version)
tmp = tmp->next;
}
if (0 == ref_count)
{
g_hash_table_destroy(schemas_table);
schemas_table = NULL;
}
return result;
}

View File

@ -29,172 +29,546 @@ extern "C"
typedef struct _KSettings KSettings;
typedef void (*KCallBack) (void);
// typedef void (*KCallBack) (KSettings *ksettings,
// const char *key,
// void *user_data);
/**
* @brief idversion的配置句柄
*
* @param id id"."
* @param version
* @return KSettings*
*/
KSettings * kdk_conf2_new (const char *id,
const char *version);
/**
* @brief
*
* @param ksettings
*/
void kdk_conf2_ksettings_destroy (KSettings *ksettings);
/**
* @brief id
*
* @param ksettings
* @return char* idNULL
*/
char * kdk_conf2_get_id (KSettings *ksettings);
/**
* @brief
*
* @param ksettings
* @return char* NULL
*/
char * kdk_conf2_get_version (KSettings *ksettings);
/**
* @brief
*
* @param ksettings
* @param name
* @return KSettings*
*/
KSettings * kdk_conf2_get_child (KSettings *ksettings,
const char *name);
/**
* @brief
*
* @param ksettings
* @return char** NULL
*/
char ** kdk_conf2_list_children (KSettings *ksettings);
/**
* @brief
*
* @param ksettings
* @return char** NULL
*/
char ** kdk_conf2_list_keys (KSettings *ksettings);
/**
* @brief
*
* @param ksettings
* @param key
* @return char* "[min,max]","{nick : value}"
*/
char * kdk_conf2_get_range (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_range_check (KSettings *ksettings,
const char *key,
const char *value);
/**
* @brief
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_value (KSettings *ksettings,
const char *key,
const char *value);
/**
* @brief
*
* @param ksettings
* @param key
* @return char* glib类型标签的数据字符串NULL
*/
char * kdk_conf2_get_value (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return char* glib类型标签的数据字符串NULL
*/
char * kdk_conf2_get_default_value (KSettings *ksettings,
const char *key);
/**
* @brief bool类型的键值
*
* @param ksettings
* @param key
* @param value bool类型01
* @return int bool类型01
*/
int kdk_conf2_set_boolean (KSettings *ksettings,
const char *key,
int value);
/**
* @brief bool类型的键值
*
* @param ksettings
* @param key
* @return int 0FALSE1TRUE
*/
int kdk_conf2_get_boolean (KSettings *ksettings,
const char *key);
/**
* @brief bool类型的键默认值
*
* @param ksettings
* @param key
* @return int 0FALSE1TRUE
*/
int kdk_conf2_get_default_boolean (KSettings *ksettings,
const char *key);
/**
* @brief double类型的键值
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_double (KSettings *ksettings,
const char *key,
double value);
/**
* @brief double类型的键值
*
* @param ksettings
* @param key
* @return double
*/
double kdk_conf2_get_double (KSettings *ksettings,
const char *key);
/**
* @brief double类型的键默认值
*
* @param ksettings
* @param key
* @return double
*/
double kdk_conf2_get_default_double (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_enum (KSettings *ksettings,
const char *key,
int value);
/**
* @brief
*
* @param ksettings
* @param key
* @return int
*/
int kdk_conf2_get_enum (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return int
*/
int kdk_conf2_get_default_enum (KSettings *ksettings,
const char *key);
/**
* @brief int类型的键值
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_int (KSettings *ksettings,
const char *key,
int value);
/**
* @brief int类型的键值
*
* @param ksettings
* @param key
* @return int
*/
int kdk_conf2_get_int (KSettings *ksettings,
const char *key);
/**
* @brief int类型的键默认值
*
* @param ksettings
* @param key
* @return int
*/
int kdk_conf2_get_default_int (KSettings *ksettings,
const char *key);
/**
* @brief int64类型的键值
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_int64 (KSettings *ksettings,
const char *key,
long value);
/**
* @brief int64类型的键值
*
* @param ksettings
* @param key
* @return long
*/
long kdk_conf2_get_int64 (KSettings *ksettings,
const char *key);
/**
* @brief int64类型的键默认值
*
* @param ksettings
* @param key
* @return long
*/
long kdk_conf2_get_default_int64 (KSettings *ksettings,
const char *key);
/**
* @brief uint类型的键值
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_uint (KSettings *ksettings,
const char *key,
unsigned int value);
/**
* @brief uint类型的键值
*
* @param ksettings
* @param key
* @return unsigned int
*/
unsigned int kdk_conf2_get_uint (KSettings *ksettings,
const char *key);
/**
* @brief uint类型的键默认值
*
* @param ksettings
* @param key
* @return unsigned int
*/
unsigned int kdk_conf2_get_default_uint (KSettings *ksettings,
const char *key);
/**
* @brief uint64类型的键值
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_uint64 (KSettings *ksettings,
const char *key,
unsigned long value);
/**
* @brief uint64类型的键值
*
* @param ksettings
* @param key
* @return unsigned long
*/
unsigned long kdk_conf2_get_uint64 (KSettings *ksettings,
const char *key);
/**
* @brief uint64类型的键默认值
*
* @param ksettings
* @param key
* @return unsigned long
*/
unsigned long kdk_conf2_get_default_uint64 (KSettings *ksettings,
const char *key);
/**
* @brief string类型的键值
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_string (KSettings *ksettings,
const char *key,
const char *value);
/**
* @brief string类型的键值
*
* @param ksettings
* @param key
* @return char* NULL
*/
char * kdk_conf2_get_string (KSettings *ksettings,
const char *key);
/**
* @brief string类型的键默认值
*
* @param ksettings
* @param key
* @return char* NULL
*/
char * kdk_conf2_get_default_string (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @param value
* @return int bool类型01
*/
int kdk_conf2_set_strv (KSettings *ksettings,
const char *key,
const char * const *value);
/**
* @brief
*
* @param ksettings
* @param key
* @return char** NULL
*/
char ** kdk_conf2_get_strv (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return char** NULL
*/
char ** kdk_conf2_get_default_strv (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return char* NULL
*/
char * kdk_conf2_get_descrition (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return char* NULL
*/
char * kdk_conf2_get_summary (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return char*
*/
char * kdk_conf2_get_type (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
*/
void kdk_conf2_reset (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return int bool类型01
*/
int kdk_conf2_is_writable (KSettings *ksettings,
const char *key);
/**
* @brief
*
* @param ksettings
* @param key
* @return int bool类型01
*/
int kdk_conf2_has_key (KSettings *ksettings,
const char *key);
/**
* @brief changed信号的回调原型KCallBack类型
*
*/
typedef void (*changed) (KSettings *ksettings,
const char *key,
void *user_data);
/**
* @brief KCallBack类型
*
* @param ksettings
* @param signal_name "changed""changed:key"
* @param handler
* @param user_data
* @return unsigned long id
*/
unsigned long kdk_conf2_connect_signal (KSettings *ksettings,
const char *signal_name,
KCallBack handler,
void *user_data);
/**
* @brief
*
*/
void kdk_conf2_reload (void);
/**
* @brief appversion的所有id
*
* @param app
* @param version
* @return char** id列表NULL
*/
char ** kdk_conf2_list_schemas (const char *app,
const char *version);
/**
* @brief app为单位生成配置文件到指定目录
*
* @param path
* @return int bool类型01
*/
int kdk_conf2_save_user_configure (const char *path);
/**
* @brief id的配置为模板id
*
* @param old_id id
* @param new_id id
* @param version id的版本号id将自动创建在这个版本号下
* @return KSettings* id的配置句柄,NULL
*/
KSettings * kdk_conf2_new_extends_id (const char *old_id,
const char *new_id,
const char *version);
/**
* @brief id是否存在
*
* @param id id
* @param version
* @return int bool类型01
*/
int kdk_conf2_is_schema (const char *id,
const char *version);
/**
* @brief
*
* @param ksettings
* @return char* NULL
*/
char * kdk_conf2_get_schema_summary (KSettings *ksettings);
/**
* @brief
*
* @param ksettings
* @return char* NULL
*/
char * kdk_conf2_get_schema_desription (KSettings *ksettings);
#if __cplusplus
}

View File

@ -5,4 +5,6 @@ key4 = /usr/bin/ukui-settings-daemon
key5 = /usr/sbin/lightdm
key6 = /usr/bin/ukui-screensaver-dialog
key7 = /usr/sbin/ukui-greeter
key8 = /lib/systemd/systemd-logind
key8 = /lib/systemd/systemd-logind
key9 = /usr/bin/sync-config-system
key10 = /usr/bin/sync-config-session

View File

@ -1 +1 @@
f45558b6a1cb69ceb6e4e58d8b9a47b551db8543
40a1a38e65f5ae16cbe035b6812e4326741366ac

View File

@ -43,7 +43,7 @@ class KYSettingsDBusService(dbus.service.Object):
self._converter = conf2Utils.Converter(logger)
self._watchdog = conf2Utils.FileWatche('/etc/kylin-config/basic', self)
self._reload()
# self._reload()
if os.path.exists('/etc/dbus-1/conf/com.kylin.kysdk.conf2.limit'):
conf = ConfigParser()
@ -55,43 +55,6 @@ class KYSettingsDBusService(dbus.service.Object):
logger.info(f'DBus Class init end')
def isAllowedCaller(self,sender):
if sender is None:
return
pid = self.getSenderPid(sender)
self.checkSenderEnv(pid)
exe_file = '/proc/%u/exe' % pid
real_file = os.readlink(exe_file)
if real_file.startswith('/usr/bin/python'):
cmd_file = '/proc/%u/cmdline' % pid
with open(cmd_file, 'r') as cf:
cmd_line = cf.readline()
cmds = cmd_line.split('\0')
if len(cmds) >= 2:
real_file = cmds[1]
if real_file not in programWhiteList:
raise dbus.exceptions.DBusException('[%s] dbus method control,operation not permitted' % real_file)
def getSenderPid(self,sender):
system_bus = dbus.SystemBus()
dbus_obj = system_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
inter_obj = dbus.Interface(dbus_obj, dbus_interface='org.freedesktop.DBus')
try:
pid = inter_obj.GetConnectionUnixProcessID(sender)
except dbus.DBusException as e:
raise dbus.exceptions.DBusException('[%s] dbus method control,operation not permitted' % sender)
return pid
def checkSenderEnv(self, pid):
env_file = '/proc/%u/environ' % pid
with open(env_file, 'r') as ef:
env_lines = ef.readline()
env_details = env_lines.replace('\0', '\n').split('\n')
for env_detail in env_details:
key = env_detail.split('=')[0]
if key in envBlackList:
raise dbus.exceptions.DBusException('[%u] dbus method control,env forbidden' % pid)
# 重载
def _reload(self):
if self._converter.update_read_only_db():
@ -112,7 +75,6 @@ class KYSettingsDBusService(dbus.service.Object):
# 设置一个配置的值
@dbus.service.method("com.kylin.kysdk.conf2", in_signature='sssss', out_signature='i', sender_keyword='sender')
def set(self, user, id, version, key, value, sender = None):
# self.isAllowedCaller(sender)
success = False
if user == 'root':
success = self._converter.set('/root/.config/kylin-config/user.db', id, version, key, value)
@ -127,7 +89,6 @@ class KYSettingsDBusService(dbus.service.Object):
# 恢复单个默认值
@dbus.service.method("com.kylin.kysdk.conf2", in_signature='ssss', out_signature='i', sender_keyword='sender')
def reset(self,user, id, version, key, sender = None):
# self.isAllowedCaller(sender)
success = False
if user == 'root':
success = self._converter.reset('/root/.config/kylin-config/user.db', id, version, key)
@ -142,14 +103,12 @@ class KYSettingsDBusService(dbus.service.Object):
# 恢复整个id的默认值
@dbus.service.method("com.kylin.kysdk.conf2", in_signature='', out_signature='i', sender_keyword='sender')
def reload(self, sender = None):
# self.isAllowedCaller(sender)
success = self._reload()
self.updated() if success else None
return success
@dbus.service.method("com.kylin.kysdk.conf2", in_signature='ss', out_signature='b', sender_keyword='sender')
def save(self, user, path, sender = None):
# self.isAllowedCaller(sender)
success = False
if user == 'root':
success = self._converter.save('/root/.config/kylin-config/user.db', path)
@ -160,7 +119,6 @@ class KYSettingsDBusService(dbus.service.Object):
#复制old_id的配置到new_id的位置并将新的数据写入到数据库
@dbus.service.method("com.kylin.kysdk.conf2", in_signature='ssss', out_signature='b', sender_keyword='sender')
def extends_id(self, old_id:str, new_id:str, version:str, user:str, sender = None):
# self.isAllowedCaller(sender)
success = False
if user == 'root':
success = self._converter.extends_id(old_id, new_id, version, '/root/.config/kylin-config/user.db')

View File

@ -0,0 +1,9 @@
[Unit]
Description=KYLIN CONF2 UPDATE DB
[Service]
Type=oneshot
ExecStart=/usr/bin/conf2-update.py
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,17 @@
#!/usr/bin/python3.8
import os
import logging
import conf2Utils
os.makedirs('/etc/kylin-config', exist_ok=True)
logging.basicConfig(filename='/etc/kylin-config/systembus.log',
level=logging.DEBUG,
format='%(asctime)s.%(msecs)03d - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
logger = logging.getLogger()
converter = conf2Utils.Converter(logger)
logger.info('update db start')
if converter.update_read_only_db():
converter.update_user_db('/root/.config/kylin-config/user.db')
logger.info('update db end')

View File

@ -28,6 +28,7 @@ class Converter:
def update_user_db(self, path):
if not os.path.exists(self._ro_db):
self.logger.info(f'/etc/kylin-config/user.db not existed')
return False
existed = self._update_table_structure(path)
@ -37,6 +38,8 @@ class Converter:
self._user_dict = self._db2dict(path)
else:
data = self._db2dict(self._ro_db)
if self._user_dict == {}:
self._user_dict = self._db2dict(path)
self._del_discarded_key(self._user_dict, data)
self._merge_dict(self._user_dict, data)
@ -186,16 +189,16 @@ class Converter:
return False
# 用于kconf2-editor保存文件仅有普通用户权限root用户没有图形化界面
def editor_save(self, data, dest_path):
def editor_save(self, apps:list, data, dest_path):
try:
self.logger.info(f'editor_save begin')
#将用户配置写入到复制的只读视图里
self._value_override_default(data)
for key in data:
with open(f'{dest_path}/{key}.yaml', 'w') as yaml_file:
yaml_file.write(yaml.safe_dump({key:data[key]}, allow_unicode = True))
for app in apps:
with open(f'{dest_path}/{app}.yaml', 'w') as yaml_file:
yaml_file.write(yaml.safe_dump({app:data[app]}, allow_unicode = True))
self.logger.info(f'editor_save end')
return True
@ -601,7 +604,21 @@ class Converter:
num = int(num, 10)
enum_range[element['_nick']] = num
range = str(enum_range)
elif value_type == 'bool':
value_type = 'b'
elif value_type == 'int':
value_type = 'i'
elif value_type == 'int64':
value_type = 'x'
elif value_type == 'uint':
value_type = 'u'
elif value_type == 'uint64':
value_type = 't'
elif value_type == 'double':
value_type = 'd'
elif value_type == 'string':
value_type = 's'
cursor.execute('''INSERT INTO configures
(version_id, node_name, node_type, permission, description, summary, parent, value_type, custom_value, default_value, range)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',

View File

@ -3,7 +3,8 @@ Type=Application
Exec=/usr/bin/conf2-session-server.py
TryExec=/usr/bin/conf2-session-server.py
Name=KYSDK-CONF2-SESSION-BUS
X-UKUI-Autostart-Phase=Initialization
Icon=
Keywords=session;kysdk-conf2-session
Comment=This session date you into sdk
NoDisplay=true
NoDisplay=true

View File

@ -1,6 +1,6 @@
[Unit]
Description=KYLIN CONF2 DBUS
Before=systemd-logind.service
Before=systemd-logind.service com.kylin.kysdk.SyncConfig.service
[Service]
Type=dbus

View File

@ -0,0 +1,26 @@
add_executable(sync-config-system system.c sync-dbus-server.c gdbus/libsyncconfig.c)
target_link_libraries(sync-config-system ${GLIB_LIBRARIES} ${GIO_LIBRARIES} kyconf2 kylog)
add_executable(sync-config-session session.c sync-dbus-server.c gdbus/libsyncconfig.c)
target_link_libraries(sync-config-session ${GLIB_LIBRARIES} ${GIO_LIBRARIES} kyconf2 kylog)
# GNU
include(GNUInstallDirs)
# CMAKE_INSTALL_LIBDIR
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "armv8l")
set(CMAKE_INSTALL_LIBDIR "/usr/lib/arm-linux-gnueabihf/")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "mips64")
set(CMAKE_INSTALL_LIBDIR "/usr/lib/mips64el-linux-gnuabi64/")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i686")
set(CMAKE_INSTALL_LIBDIR "/usr/lib/i386-linux-gnu/")
else()
set(CMAKE_INSTALL_LIBDIR "/usr/lib/${CMAKE_HOST_SYSTEM_PROCESSOR}-linux-gnu/")
endif()
#
install(TARGETS sync-config-session
DESTINATION /usr/bin)
install(TARGETS sync-config-system
DESTINATION /usr/bin)

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Only user root can own the alsa service -->
<policy user="root">
<allow own="com.kylin.kysdk.SyncConfig" />
<allow send_destination="com.kylin.kysdk.SyncConfig" />
<allow receive_sender="com.kylin.kysdk.SyncConfig" />
</policy>
<policy context="default">
<allow send_destination="com.kylin.kysdk.SyncConfig" />
<!-- remove the following line for debug -->
<!--
<allow send_interface="com.jd.ccis"/>
-->
</policy>
</busconfig>

View File

@ -0,0 +1,10 @@
[Desktop Entry]
Type=Application
Exec=/usr/bin/sync-config-session
TryExec=/usr/bin/sync-config-session
Name=KYSDK-CONF2-SYNC-CONFIG-BUS
X-UKUI-Autostart-Phase=Initialization
Icon=
Keywords=session;
Comment=This session date you into sdk
NoDisplay=true

View File

@ -0,0 +1,12 @@
[Unit]
Description=KYLIN CONF2 SYNC DBUS
[Service]
Type=dbus
Restart=always
RestartSec=1
BusName=com.kylin.kysdk.SyncConfig
ExecStart=/usr/bin/sync-config-system
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<node>
<interface name="com.kylin.kysdk.SyncConfig">
<signal name="state">
<arg name="state" type="i"/>
</signal>
<method name="RegisterSchema">
<arg name="Conf2Id" direction="in" type="s"/>
<arg name="SchemaId" direction="in" type="s"/>
<arg name="SchemaPath" direction="in" type="s"/>
<arg name="ArgOut" direction="out" type="b"/>
</method>
<method name="UnregisterSchema">
<arg name="SchemaId" direction="in" type="s"/>
<arg name="SchemaPath" direction="in" type="s"/>
<arg name="ArgOut" direction="out" type="b"/>
</method>
</interface>
</node>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,234 @@
/*
* This file is generated by gdbus-codegen, do not modify it.
*
* The license of this code is the same as for the D-Bus interface description
* it was derived from. Note that it links to GLib, so must comply with the
* LGPL linking clauses.
*/
#ifndef __LIBSYNCCONFIG_H__
#define __LIBSYNCCONFIG_H__
#include <gio/gio.h>
G_BEGIN_DECLS
/* ------------------------------------------------------------------------ */
/* Declarations for com.kylin.kysdk.SyncConfig */
#define SYNC_CONFIG_TYPE_ (sync_config__get_type ())
#define SYNC_CONFIG_(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNC_CONFIG_TYPE_, SyncConfig))
#define SYNC_CONFIG_IS_(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNC_CONFIG_TYPE_))
#define SYNC_CONFIG__GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), SYNC_CONFIG_TYPE_, SyncConfigIface))
struct _SyncConfig;
typedef struct _SyncConfig SyncConfig;
typedef struct _SyncConfigIface SyncConfigIface;
struct _SyncConfigIface
{
GTypeInterface parent_iface;
gboolean (*handle_register_schema) (
SyncConfig *object,
GDBusMethodInvocation *invocation,
const gchar *arg_Conf2Id,
const gchar *arg_SchemaId,
const gchar *arg_SchemaPath);
gboolean (*handle_unregister_schema) (
SyncConfig *object,
GDBusMethodInvocation *invocation,
const gchar *arg_SchemaId,
const gchar *arg_SchemaPath);
void (*state) (
SyncConfig *object,
gint arg_state);
};
GType sync_config__get_type (void) G_GNUC_CONST;
GDBusInterfaceInfo *sync_config__interface_info (void);
guint sync_config__override_properties (GObjectClass *klass, guint property_id_begin);
/* D-Bus method call completion functions: */
void sync_config__complete_register_schema (
SyncConfig *object,
GDBusMethodInvocation *invocation,
gboolean ArgOut);
void sync_config__complete_unregister_schema (
SyncConfig *object,
GDBusMethodInvocation *invocation,
gboolean ArgOut);
/* D-Bus signal emissions functions: */
void sync_config__emit_state (
SyncConfig *object,
gint arg_state);
/* D-Bus method calls: */
void sync_config__call_register_schema (
SyncConfig *proxy,
const gchar *arg_Conf2Id,
const gchar *arg_SchemaId,
const gchar *arg_SchemaPath,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean sync_config__call_register_schema_finish (
SyncConfig *proxy,
gboolean *out_ArgOut,
GAsyncResult *res,
GError **error);
gboolean sync_config__call_register_schema_sync (
SyncConfig *proxy,
const gchar *arg_Conf2Id,
const gchar *arg_SchemaId,
const gchar *arg_SchemaPath,
gboolean *out_ArgOut,
GCancellable *cancellable,
GError **error);
void sync_config__call_unregister_schema (
SyncConfig *proxy,
const gchar *arg_SchemaId,
const gchar *arg_SchemaPath,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean sync_config__call_unregister_schema_finish (
SyncConfig *proxy,
gboolean *out_ArgOut,
GAsyncResult *res,
GError **error);
gboolean sync_config__call_unregister_schema_sync (
SyncConfig *proxy,
const gchar *arg_SchemaId,
const gchar *arg_SchemaPath,
gboolean *out_ArgOut,
GCancellable *cancellable,
GError **error);
/* ---- */
#define SYNC_CONFIG_TYPE__PROXY (sync_config__proxy_get_type ())
#define SYNC_CONFIG__PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNC_CONFIG_TYPE__PROXY, SyncConfigProxy))
#define SYNC_CONFIG__PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SYNC_CONFIG_TYPE__PROXY, SyncConfigProxyClass))
#define SYNC_CONFIG__PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SYNC_CONFIG_TYPE__PROXY, SyncConfigProxyClass))
#define SYNC_CONFIG_IS__PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNC_CONFIG_TYPE__PROXY))
#define SYNC_CONFIG_IS__PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SYNC_CONFIG_TYPE__PROXY))
typedef struct _SyncConfigProxy SyncConfigProxy;
typedef struct _SyncConfigProxyClass SyncConfigProxyClass;
typedef struct _SyncConfigProxyPrivate SyncConfigProxyPrivate;
struct _SyncConfigProxy
{
/*< private >*/
GDBusProxy parent_instance;
SyncConfigProxyPrivate *priv;
};
struct _SyncConfigProxyClass
{
GDBusProxyClass parent_class;
};
GType sync_config__proxy_get_type (void) G_GNUC_CONST;
#if GLIB_CHECK_VERSION(2, 44, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SyncConfigProxy, g_object_unref)
#endif
void sync_config__proxy_new (
GDBusConnection *connection,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
SyncConfig *sync_config__proxy_new_finish (
GAsyncResult *res,
GError **error);
SyncConfig *sync_config__proxy_new_sync (
GDBusConnection *connection,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GError **error);
void sync_config__proxy_new_for_bus (
GBusType bus_type,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
SyncConfig *sync_config__proxy_new_for_bus_finish (
GAsyncResult *res,
GError **error);
SyncConfig *sync_config__proxy_new_for_bus_sync (
GBusType bus_type,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GError **error);
/* ---- */
#define SYNC_CONFIG_TYPE__SKELETON (sync_config__skeleton_get_type ())
#define SYNC_CONFIG__SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNC_CONFIG_TYPE__SKELETON, SyncConfigSkeleton))
#define SYNC_CONFIG__SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SYNC_CONFIG_TYPE__SKELETON, SyncConfigSkeletonClass))
#define SYNC_CONFIG__SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SYNC_CONFIG_TYPE__SKELETON, SyncConfigSkeletonClass))
#define SYNC_CONFIG_IS__SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNC_CONFIG_TYPE__SKELETON))
#define SYNC_CONFIG_IS__SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SYNC_CONFIG_TYPE__SKELETON))
typedef struct _SyncConfigSkeleton SyncConfigSkeleton;
typedef struct _SyncConfigSkeletonClass SyncConfigSkeletonClass;
typedef struct _SyncConfigSkeletonPrivate SyncConfigSkeletonPrivate;
struct _SyncConfigSkeleton
{
/*< private >*/
GDBusInterfaceSkeleton parent_instance;
SyncConfigSkeletonPrivate *priv;
};
struct _SyncConfigSkeletonClass
{
GDBusInterfaceSkeletonClass parent_class;
};
GType sync_config__skeleton_get_type (void) G_GNUC_CONST;
#if GLIB_CHECK_VERSION(2, 44, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SyncConfigSkeleton, g_object_unref)
#endif
SyncConfig *sync_config__skeleton_new (void);
G_END_DECLS
#endif /* __LIBSYNCCONFIG_H__ */

View File

@ -0,0 +1,8 @@
#include "sync-dbus-server.h"
int main(int argc, char const *argv[])
{
monitoring_requires_synchronized_configuration();
init_gdbus_server(G_BUS_TYPE_SESSION);
return 0;
}

View File

@ -0,0 +1,464 @@
#include "sync-dbus-server.h"
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <gio/gsettings.h>
#include <libkylog.h>
#include <../api/libkysettings.h>
/***************************************dbus服务********************************************/
static SyncConfig *skeleton = NULL;
static gboolean on_handle_register_schema(SyncConfig *skeleton, GDBusMethodInvocation *invocation,
const gchar *arg_Conf2Id,
const gchar *arg_SchemaId,
const gchar *arg_Path,
gpointer user_data)
{
printf("Regester call %s\n", arg_Conf2Id);
sync_config__complete_register_schema(skeleton, invocation, TRUE);
return TRUE;
}
static gboolean on_handle_unregister_schema(SyncConfig *skeleton, GDBusMethodInvocation *invocation,
const gchar *arg_SchemaId,
const gchar *arg_Path,
gpointer user_data)
{
printf("Unregester call\n");
sync_config__complete_unregister_schema(skeleton, invocation, TRUE);
return TRUE;
}
/**
* bus daemon的回调
**/
void on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
{
klog_info("on_bus_acquired has been invoked, name is %s\n", name);
GError *error = NULL;
skeleton = sync_config__skeleton_new();
// 连接方法同步处理函数
g_signal_connect(G_OBJECT(skeleton), "handle-register-schema", G_CALLBACK(on_handle_register_schema), NULL);
g_signal_connect(G_OBJECT(skeleton), "handle-unregister-schema", G_CALLBACK(on_handle_unregister_schema), NULL);
// 发布服务到总线
g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skeleton), connection, "/com/kylin/kysdk/syncConfig", &error);
if (error != NULL)
{
klog_err("Error: Failed to export object. Reason: %s.\n", error->message);
g_error_free(error);
}
}
/**
* busName的回调
**/
void on_bus_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
{
}
/**
* busName丢失的回调server挂了
**/
void on_bus_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
{
}
/**
* Hello.h自动生成的方法
**/
static gint status_value = 1;
static gboolean emit_test_state_signal(gconstpointer p)
{
printf("emit_test_status_signal invoked\n");
if (skeleton != NULL)
{
sync_config__emit_state(skeleton, status_value);
}
status_value++;
}
gboolean init_gdbus_server(GBusType type)
{
guint owner_id;
GMainLoop *loop;
#if !GLIB_CHECK_VERSION(2, 35, 0)
g_type_init();
#endif
owner_id = g_bus_own_name(type, "com.kylin.kysdk.SyncConfig",
G_BUS_NAME_OWNER_FLAGS_NONE,
on_bus_acquired, on_bus_name_acquired, on_bus_name_lost, NULL, NULL);
// 测试每3s发一次signal
// g_timeout_add(3000, (GSourceFunc)emit_test_state_signal, NULL);
// 主线程进入循环
loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_bus_unown_name(owner_id);
return TRUE;
}
/***************************************同步配置********************************************/
#define OUT
#define KPATH_LEN 512
#define APP_LEN 128
#define VER_LEN 32
#define LINE_LEN 4096
struct _conf2_gsetting_handle_duple
{
KSettings *ksetting;
GSettings *gsetting;
};
// static GPtrArray *handle_array = g_ptr_array_new();
static void _on_gsettings_key_changed(GSettings *gsetting, const char *key, void *user_data)
{
GVariant *value = g_settings_get_value(gsetting, key);
KSettings *ksetting = (KSettings *)user_data;
char *conf2_value = kdk_conf2_get_value(ksetting, key);
if (0 == strcmp(conf2_value, g_variant_print(value, TRUE)))
return;
int ret = kdk_conf2_set_value(ksetting, key, g_variant_print(value, TRUE));
if (ret)
{
printf("_on_gsettings_key_changed\n");
// g_signal_emit(ksetting, k_settings_signals[SIGNAL_CHANGED], g_quark_from_string(key), key);
}
g_variant_unref(value);
}
static void _on_conf2_key_changed(KSettings *ksetting, const char *key, void *user_data)
{
GSettings *gsetting = (GSettings*)user_data;
const gchar *endptr = NULL;
GError *error = NULL;
GVariant *gsetting_value = g_settings_get_value(gsetting, key);
if (NULL != gsetting_value)
{
char *value = kdk_conf2_get_value(ksetting, key);
if (0 != strcmp(value, g_variant_print(gsetting_value, TRUE)))
{
char *type = kdk_conf2_get_type(ksetting, key);
GVariant *variant = g_variant_parse(G_VARIANT_TYPE(type), value, NULL, &endptr, &error);
if (NULL == variant)
{
// klog_err("[kysdk-conf2] %s -> %s\n", __func__, error->message);
return;
}
printf("_on_conf2_key_changed\n");
g_settings_set_value(gsetting, key, variant);
g_settings_sync();
g_variant_unref(variant);
}
g_variant_unref(gsetting_value);
}
}
static char *_conf2_id_in_gsetting_schemas(const char *conf2_id, const char **gsetting_schemas)
{
for(; *gsetting_schemas; gsetting_schemas++)
{
if (g_str_has_suffix(*gsetting_schemas, conf2_id))
return *gsetting_schemas;
}
return NULL;
}
/**
* @brief
*
* @param version1
* @param version2
* @return int version1大于version时返回1 0 -1
*/
static int _compare_versions(char *version1, char *version2)
{
if (version1 != NULL && version2 == NULL)
return 1;
else if (version1 == NULL && version2 != NULL)
return -1;
else if (version1 == NULL && version2 == NULL)
return 0;
int result = 0;
char v1[64], v2[64];
memset(v1, 0, 64);
strcpy(v1, version1);
memset(v2, 0, 64);
strcpy(v2, version2);
char *save_ptr1 = NULL;
char *save_ptr2 = NULL;
char *token1;
char *token2;
token1 = strtok_r(v1, ".-k", &save_ptr1);
token2 = strtok_r(v2, ".-k", &save_ptr2);
while (1)
{
if (token1 != NULL && token2 != NULL)
{
int num1 = atoi(token1);
int num2 = atoi(token2);
if (num1 > num2)
{
result = 1;
break;
}
else if (num1 < num2)
{
result = -1;
break;
}
}
else if (token1 == NULL && token2 != NULL)
{
result = -1;
break;
}
else if (token1 != NULL && token2 == NULL)
{
result = 1;
break;
}
else if (token1 == NULL && token2 == NULL)
break;
token1 = strtok_r(NULL, ".-k", &save_ptr1);
token2 = strtok_r(NULL, ".-k", &save_ptr2);
}
return result;
}
static inline gboolean _copy_str_check(char *dest, char *src, size_t length)
{
// 去掉前面空格
g_strchug(src);
/*本行内容应该是 【应用名:】,如果不是以":"结尾,说明文件内容格式错误*/
char *dot = strchr(src, ':');
if (NULL != dot)
{
int len = dot - src;
strncpy(dest, src, len < length - 1 ? len : length);
return TRUE;
}
return FALSE;
}
static gboolean _get_conf2_app(FILE *fp, OUT char *app)
{
gboolean result = FALSE;
char line[LINE_LEN], *dot = NULL;
int version_indent = 0;
while (fgets(line, LINE_LEN, fp))
{
// 无缩进且不是注释,既第一行内容
dot = strchr("#\t ", line[0]);
if (NULL == dot)
{
result = _copy_str_check(app, line, APP_LEN);
break;
}
}
return result;
}
static gboolean _get_conf2_version(FILE *fp, OUT char *version)
{
gboolean result = FALSE;
char line[LINE_LEN], *dot = NULL;
int version_indent = 0;
while (fgets(line, LINE_LEN, fp))
{
// 获取版本号的缩进,缩进最短的正文既版本号
if (0 == version_indent)
{
for (;; version_indent++)
{
// line[version_indent]不是空格
if (NULL == strchr("\t ", line[version_indent]))
{
// 注释行,缩进计数归零
if ('#' == line[version_indent])
version_indent = 0;
else
{
// 这行正文既一个版本号
if (FALSE == _copy_str_check(version, line, VER_LEN))
{
printf("111%s\n", line);
return result;
}
}
break; // for循环
}
}
continue; // while循环
}
// 检查这一行是不是版本号
int i = 0;
for (; i < version_indent; i++)
{
// 空格不够
if (NULL == strchr("\t ", line[i]))
{
// 注释行或空行
if (NULL != strchr("#\n", line[i]))
break; // for循环
else
{
// TODO: log 文件缩进格式错误
printf("222%s\n", line);
return result;
}
}
}
if (i == version_indent)
{
if((line[i] != '#') && (line[i] != ' ') && (line[i] != '\t'))
{
char tmp[VER_LEN];
memset(tmp, 0, VER_LEN);
if (FALSE == _copy_str_check(tmp, line, VER_LEN))
{
// TODO: log 文件格式错误
printf("333%s\n", line);
return result;
}
if ( -1 == _compare_versions(version, tmp))
{
strcpy(version, tmp);
}
}
}
}
result = TRUE;
return result;
}
/*
yaml格式文件
:dbus-daemon会把自己的文件安装到basic目录yaml
yaml格式
*/
static gboolean _get_conf2_app_and_version(const char *file, OUT char *app, OUT char *version)
{
gboolean result = FALSE;
memset(app, 0, APP_LEN);
memset(version, 0, VER_LEN);
FILE *fp = fopen(file, "r");
if (NULL == fp)
{
// TODO: 文件打开失败
return result;
}
result = _get_conf2_app(fp, app);
if (FALSE == result)
{
// TODO: log 文件内容不符合yaml格式
goto out;
}
result = _get_conf2_version(fp, version);
if (FALSE == result)
{
// TODO: log 文件内容不符合yaml格式
goto out;
}
out:
fclose(fp);
return result;
}
static gboolean _connect_signal_sync_config(const char *conf2_id, const char *conf2_version, const char *gsetting_id, const char *gsetting_path)
{
GSettings *gsetting = NULL;
KSettings *ksetting = NULL;
if ( NULL == gsetting_path)
gsetting = g_settings_new(gsetting_id);
else
gsetting = g_settings_new_with_path(gsetting_id, gsetting_path);
ksetting = kdk_conf2_new(conf2_id, conf2_version);
if (!(gsetting && ksetting))
{
// TODO: log 创建句柄失败
g_object_unref(gsetting);
kdk_conf2_ksettings_destroy(ksetting);
return FALSE;
}
g_signal_connect(gsetting, "changed", G_CALLBACK(_on_gsettings_key_changed), ksetting);
kdk_conf2_connect_signal(ksetting, "changed", (KCallBack)_on_conf2_key_changed, gsetting);
return TRUE;
}
int monitoring_requires_synchronized_configuration()
{
const char * const *gsetting_schemas = g_settings_list_schemas();
DIR *dir = NULL;
struct dirent *dire = NULL;
dir = opendir("/etc/kylin-config/basic");
if (NULL == dir)
{
return -1;
}
while (NULL != (dire = readdir(dir)))
{
char file_name[KPATH_LEN];
memset(file_name, 0, KPATH_LEN);
char *dot = strrchr(dire->d_name, '.');
if (NULL == dot)
{
// log
continue;
}
size_t len = dot - dire->d_name;
strncpy(file_name, dire->d_name, len);
// 文件名与gsetting的id相同需要同步
if (g_strv_contains(gsetting_schemas, file_name))
{
// 获取应用名和版本号
g_snprintf(file_name, KPATH_LEN, "/etc/kylin-config/basic/%s", dire->d_name);
char app[APP_LEN], version[VER_LEN];
memset(app, 0, APP_LEN);
memset(version, 0, VER_LEN);
if (FALSE == _get_conf2_app_and_version(file_name, app, version))
{
// TODO: 记录日志读取文件内应用与app失败
continue;
}
char **ksetting_schemas = kdk_conf2_list_schemas(app, version);
if (NULL == ksetting_schemas)
{
//TODO: log 获取conf2中app的version版本的id列表失败
continue;
}
for(char **tmp = ksetting_schemas; *tmp; tmp++)
{
char *gsetting_id = NULL;
if(NULL != (gsetting_id = _conf2_id_in_gsetting_schemas(*tmp, gsetting_schemas)))
_connect_signal_sync_config(*tmp, version, gsetting_id, NULL);
}
g_strfreev(ksetting_schemas);
}
}
closedir(dir);
}

View File

@ -0,0 +1,19 @@
#ifndef SYNC_DBUS_SERVER_H
#define SYNC_DBUS_SERVER_H
#include "gdbus/libsyncconfig.h"
#ifdef __cplusplus
extern "C"
{
#endif
int monitoring_requires_synchronized_configuration();
gboolean init_gdbus_server(GBusType type);
#ifdef __cplusplus
}
#endif
#endif // SYNC_DBUS_SERVER_H

View File

@ -0,0 +1,8 @@
#include "sync-dbus-server.h"
int main(int argc, char const *argv[])
{
monitoring_requires_synchronized_configuration();
init_gdbus_server(G_BUS_TYPE_SYSTEM);
return 0;
}

View File

@ -49,7 +49,7 @@ int main(int argc, char *argv[])
*
*
*/
// kdk_conf2_connect_signal(setting, "changed::int", (KCallBack)on_key_changed, NULL);
// kdk_conf2_connect_signal(setting, "changed::int", on_key_changed, NULL);
char *schema_summary = kdk_conf2_get_schema_summary(setting);
if (schema_summary)
@ -171,39 +171,39 @@ int main(int argc, char *argv[])
}
/**********长整形读写**********/
long l = kdk_conf2_get_default_int(setting, "long");
long l = kdk_conf2_get_default_int64(setting, "long");
printf("Long default value is %d\n", l);
l = kdk_conf2_get_int(setting, "long");
l = kdk_conf2_get_int64(setting, "long");
printf("Long value is %d\n", l);
success = kdk_conf2_set_int(setting, "long", l + 1);
success = kdk_conf2_set_int64(setting, "long", l + 1);
if (0 == success)
{
printf("set long failed\n");
}
/**********无符号整形读写**********/
unsigned int u = kdk_conf2_get_default_int(setting, "uint");
unsigned int u = kdk_conf2_get_default_uint(setting, "uint");
printf("Uint default value is %d\n", u);
u = kdk_conf2_get_int(setting, "uint");
u = kdk_conf2_get_uint(setting, "uint");
printf("Uint value is %d\n", u);
success = kdk_conf2_set_int(setting, "uint", u + 1);
success = kdk_conf2_set_uint(setting, "uint", u + 1);
if (0 == success)
{
printf("set uint failed\n");
}
/**********无符号长整形读写**********/
unsigned long t = kdk_conf2_get_default_int(setting, "ulong");
unsigned long t = kdk_conf2_get_default_uint64(setting, "ulong");
printf("Ulong default value is %d\n", t);
t = kdk_conf2_get_int(setting, "ulong");
t = kdk_conf2_get_uint64(setting, "ulong");
printf("Ulong value is %d\n", t);
success = kdk_conf2_set_int(setting, "ulong", t + 1);
success = kdk_conf2_set_uint64(setting, "ulong", t + 1);
if (0 == success)
{
printf("set ulong failed\n");
@ -304,7 +304,7 @@ int main(int argc, char *argv[])
int writable = kdk_conf2_is_writable(setting, "int");
printf("Int is %s\n", writable ? "writable" : "not writable");
// kdk_conf2_connect_signal(setting, "reload", (KCallBack)on_reload, NULL);
// kdk_conf2_connect_signal(setting, "reload", on_reload, NULL);
kdk_conf2_reload();
char **schemas = kdk_conf2_list_schemas("test", NULL);

View File

@ -26,6 +26,14 @@ import re
import sys
import xml.etree.ElementTree as ET
import yaml
import argparse
id_help = "指定一个gschema.xml的一个id,例如org.ukui.control-center。"\
"工具会将这个id以及其子id(例如org.ukui.control-center.apt.prox)转为yaml格式,并生成yaml文件。"
version_help = "指定生成yaml文件的配置版本,如果不指定版本则默认版本为2.0.0.0-0k0.0"
path_help = "指定yaml文件的生成目录,如果不指定生成在${HOME}/yaml目录中"
def convert_one_file(data:dict, path:str, file:str):
@ -92,14 +100,24 @@ def convert_one_file(data:dict, path:str, file:str):
print(f'{path}/{file} not exists')
if __name__ == '__main__':
app = sys.argv[1]
parser = argparse.ArgumentParser(description='这是一个将gschema.xml文件转化为yaml格式的程序, 例如: python3 src/conf2/tools/gschema_xml2yaml.py -i org.ukui.control-center -v 3.2.1.0-0k0.15 -p /home/kylin')
parser.add_argument('--id', '-i', type=str, help=id_help)
parser.add_argument('--version', '-v', type=str, help=version_help)
parser.add_argument('--path', '-p', type=str, help=path_help)
args = parser.parse_args()
app = args.id
version = '2.0.0-0k0.0'
if 3 == len(sys.argv):
version = sys.argv[2]
if args.version:
version = args.version
path = '/usr/share/glib-2.0/schemas'
if len(sys.argv) > 3:
path = sys.argv[3]
home = os.getenv('HOME')
out_path = f'{home}/yaml'
if args.path:
out_path = args.path
organization = app.rsplit('.', 1)[0]
@ -122,8 +140,7 @@ if __name__ == '__main__':
yaml_data = yaml.safe_dump(result, allow_unicode = True)
# 将YAML数据写入文件
home = os.getenv('HOME')
file = f"{home}/yaml/{app}.yaml"
file = f"{out_path}/{app}.yaml"
if not os.path.exists(os.path.dirname(file)):
os.makedirs(os.path.dirname(file), exist_ok=True)

View File

@ -0,0 +1,210 @@
#!/usr/bin/python3
import os
import re
import sys
import yaml
override_dirs = ['/etc/kylin-config/industry']
output_file = ''
# 每个问题类型声明一个列表存储对应的问题类型
# 键值类型改变
type_list = []
# 键值权限改变
permission_list = []
# 取值范围改变
range_list = []
# 版本不在应用支持范围
version_list = []
# 打印报告
def print_err():
with open(output_file, 'w') as file:
if type_list:
file.write('键值类型改变\n')
file.write(' ' * 4 + '描述\n')
file.write(' ' * 8 + '键值类型变化会导致应用读取数据是读不到数据或读到错误数据,导致应用运行结果异常\n')
file.write(' ' * 4 + '如何修复\n')
file.write(' ' * 8 + '联系应用调查原因,商讨修改方案\n')
file.write(' ' * 4 + '问题上下文\n')
for basic_file, override_file, path in type_list:
file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n')
if permission_list:
file.write('键值权限改变\n')
file.write(' ' * 4 + '描述\n')
file.write(' ' * 8 + '键值权限改变可能会导致定制文件的内容无法覆盖应用文件的内容,导致定制内容不生效\n')
file.write(' ' * 4 + '如何修复\n')
file.write(' ' * 8 + '联系应用调查原因,商讨修改方案\n')
file.write(' ' * 4 + '问题上下文\n')
for basic_file, override_file, path in permission_list:
file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n')
if range_list:
file.write('取值范围改变改变\n')
file.write(' ' * 4 + '描述\n')
file.write(' ' * 8 + '取值范围改变,可能会导致应用在读/写数据是读到/写入无意义的数据,导致应用运行出错或设置数据失败\n')
file.write(' ' * 4 + '如何修复\n')
file.write(' ' * 8 + '联系应用调查原因,商讨修改方案\n')
file.write(' ' * 4 + '问题上下文\n')
for basic_file, override_file, path in range_list:
file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n')
if version_list:
file.write('版本不在应用规定范围\n')
file.write(' ' * 4 + '描述\n')
file.write(' ' * 8 + '如果版本不在应用指定支持的版本范围内无法确定配置应用读取的配置是否存在与该版本的配置内容中,可能会导致应用运行错误\n')
file.write(' ' * 4 + '如何修复\n')
file.write(' ' * 8 + '调查文件来源,如果可以删除建议删除,不能删除的话联系应用与定制包的负责人,商讨修改方案\n')
file.write(' ' * 4 + '问题上下文\n')
for basic_file, override_file, path in version_list:
file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n')
# 查询枚举类型数据的枚举定义
def _recursive_search(dictionary, key):
if key in dictionary:
return dictionary[key]
else:
for value in dictionary.values():
if isinstance(value, dict):
result = _recursive_search(value, key)
if result is not None:
return result
return None
def _compare_versions(src, dest):
src_nums = re.findall(r'\d+', src)
dest_nums = re.findall(r'\d+', dest)
lengh = len(src_nums) if len(src_nums) > len(dest_nums) else len(dest_nums)
ret = -1 if len(src_nums) > len(dest_nums) else 1 if len(src_nums) < len(dest_nums) else 0
for i in range(0, lengh):
if dest_nums[i] > src_nums[i]:
return 1
if dest_nums[i] < src_nums[i]:
return -1
return ret
def _calculate_default_version(data:dict):
versions = list(data.keys())
if '_default_version' in versions:
return data.get('_default_version')
default_version = ''
for version in versions:
if default_version == '':
default_version = version
continue
if 1 == _compare_versions(default_version, version):
default_version = version
return default_version
def check_value_type(basic_data:dict, override_data:dict, path:str, app, version, basic_file, override_file):
basic_group = basic_data
override_group = override_data
for group in path.split('.'):
basic_group = basic_group[group]
override_group = override_group[group]
result = []
for key, value in override_group.items():
if key in basic_group:
if not isinstance(value, dict):
continue
basic_key_is_group = True if '_default' in next(iter(value.values())) else False
override_key_is_group = True if '_default' in next(iter(value.values())) else False
# 同名但是一个是组,一个是键
if basic_key_is_group != override_key_is_group:
result.append((basic_file, override_file, f'{app}/{version}/{path}/{key}'))
else:
# 组
if basic_key_is_group and override_key_is_group:
check_value_type(basic_data, override_data, f'{path}.{key}', app, version, basic_file, override_file)
else:
basic_key_type = basic_group[key]['_type']
override_key_type = override_group[key]['_type']
if basic_key_type != override_key_type:
type_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}'))
# 获取组的权限,未声明默认'public'
basic_key_permission = basic_group.get('_permission', 'public')
override_key_permission = override_group.get('_permission', 'public')
# 读取键的权限,未声明则使用组权限
basic_key_permission = basic_group[key].get('_permission', basic_key_permission)
override_key_permission = override_group[key].get('_permission', override_key_permission)
if basic_key_permission != override_key_permission:
permission_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}'))
basic_key_range = basic_group[key].get('_range', '')
override_key_range = override_group[key].get('_range', '')
if basic_key_range and override_key_range:
if basic_key_type == 'enum':
basic_key_range = _recursive_search(basic_data, basic_key_range[1:])
override_key_range = _recursive_search(override_data, override_key_range[1:])
if basic_key_range != override_key_range:
range_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}'))
# elif basic_key_range == '' and override_key_range != '':
# range_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}'))
# elif basic_key_range != '' and override_key_range == '':
# range_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}'))
return result
# 检查组配置文件
def check_group_config(basic_data, override_data, basic_file, override_file):
for app, app_data in basic_data.items():
for version, version_data in app_data.items():
groups = set(override_data.keys())
for group in groups:
if group in version_data:
if not isinstance(version_data[group], dict):
continue
check_value_type(version_data, override_data, group, app, version, basic_file, override_file)
# 检查应用配置文件
def check_app_config(basic_data, override_data, basic_file, override_file):
version_err = []
for app, app_data in override_data.items():
if app in basic_data:
# 读取应用支持版本号区间
min_version = ''
max_version = ''
if os.path.exists(f'/etc/kylin-config/compatibility/{app}-compatibility-settings.yaml'):
with open(f'/etc/kylin-config/compatibility/{app}-compatibility-settings.yaml', 'r') as f:
version_range = yaml.safe_load(f)
min_version = version_range[app]['compatibility']['min_version']
max_version = version_range[app]['compatibility']['max_version']
versions = set(basic_data[app].keys()) | set(override_data[app].keys())
for version in versions:
if (version == '_default_version'):
continue
if min_version and max_version:
if -1 == _compare_versions(version, min_version) or 1 == _compare_versions(version, max_version):
version_list.append((basic_file, override_file, f'{app}/{version}'))
else:
# 定制文件版本是否比应用文件版本高 待定?
pass
if version in basic_data[app] and version in override_data[app]:
for group in override_data[app][version]:
if not isinstance(override_data[app][version][group], dict):
continue
check_value_type(basic_data[app][version], override_data[app][version], group, app, version, basic_file, override_file)
def check_one_app(basic_data, basic_file):
for dir in override_dirs:
for root, dirs, files in os.walk(dir):
for file in files:
override_file = f'{root}/{file}'
with open(override_file, 'r') as f:
override_data = yaml.safe_load(f)
for value in override_data.values():
is_group_file = True if '_default' in next(iter(value.values())) else False
if is_group_file:
check_group_config(basic_data, override_data, basic_file, override_file)
else:
check_app_config(basic_data, override_data, basic_file, override_file)
if __name__ == '__main__':
if len(sys.argv) < 2:
print("example: 111.py /home/xxx/output.txt")
sys.exit()
output_file = sys.argv[1]
for root, dirs, files in os.walk('/etc/kylin-config/basic'):
for file in files:
basic_file = f'{root}/{file}'
with open(basic_file, 'r') as f:
basic_data = yaml.safe_load(f)
check_one_app(basic_data, basic_file)
print_err()

View File

@ -9,6 +9,7 @@ import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as msgbox
import tkinter.filedialog as filedialog
import tkinter.simpledialog as simpledialog
import dbus
from gi.repository import GLib
@ -25,14 +26,16 @@ def close_menu(event):
download_menu.unpost()
def on_search():
pack_list = root.pack_slaves()
if view_frame in pack_list:
text = search_button.cget('text')
if text == 'search':
search_button.config(text='cancel')
view_frame.pack_forget()
search_frame.pack(side='bottom', fill='both', expand=True)
search_tree.delete(*search_tree.get_children())
search_entry.config(state='normal')
# search_entry.event_generate("<KeyRelease>")
else:
elif text == 'cancel':
search_button.config(text='search')
search_frame.pack_forget()
view_frame.pack(side='bottom', fill='both', expand=True)
items = tree.selection()
@ -55,21 +58,60 @@ def on_search_entry_change(event):
search_tree.insert('', 'end', text= key)
def on_download():
class MultiSelectDialog(tk.simpledialog.Dialog):
def body(self, master):
self.results = []
self.options = list(target_view.keys())
self.vars = []
for i, option in enumerate(self.options):
var = tk.IntVar()
checkbutton = tk.Checkbutton(master, text=option, variable=var)
checkbutton.grid(row=i, sticky='w')
self.vars.append(var)
select_all_button = tk.Button(master, text="全选", command=self.all_select)
select_all_button.grid(row=len(self.options), column=0, sticky='w')
select_none_button = tk.Button(master, text="全不选", command=self.none_select)
select_none_button.grid(row=len(self.options), column=1, sticky='w')
def apply(self):
self.results = [option for var, option in zip(self.vars, self.options) if var.get() == 1]
def all_select(self):
for var in self.vars:
var.set(1)
def none_select(self):
for var in self.vars:
var.set(0)
global target_view
path = filedialog.askdirectory(mustexist=True, title=' Choose a folder')
if path:
success = converter.editor_save(target_view, path)
if success:
msgbox.showinfo(message='Save successed')
else:
msgbox.showinfo(message='Save failed')
dialog = MultiSelectDialog(root, title="Multi-Select Dialog")
if dialog.results != []:
path = filedialog.askdirectory(mustexist=True, title=' Choose a folder')
if path:
try:
converter._value_override_default(target_view)
for app in dialog.results:
yaml_file_path = f'{path}/{app}.yaml'
if os.path.exists(yaml_file_path):
msgbox.askyesno(message=f'{yaml_file_path} is existed. Do you want to replace it')
else:
with open(yaml_file_path, 'w') as yaml_file:
yaml_file.write(yaml.safe_dump({app:target_view[app]}, allow_unicode = True))
msgbox.showinfo(message='Save successed')
except Exception as e:
msgbox.showinfo(message='Save failed')
def on_download_one():
global target_view
key = tree.item(right_select_item, 'text')
app = tree.item(right_select_item, 'text')
apps = []
apps.append(app)
path = filedialog.askdirectory(mustexist=True, title=' Choose a folder')
if path:
success = converter.editor_save({key:target_view[key]}, path)
success = converter.editor_save(apps, target_view, path)
if success:
msgbox.showinfo(message='Save successed')
else:
@ -85,40 +127,80 @@ def on_set():
user = destination_file.split('/')[2]
key = id = value = ''
key = id = value = permission = type = range = ''
for widget in inner_frame.winfo_children():
if isinstance(widget, tk.Text):
if 'key' in widget.winfo_name:
key = widget.get()
if 'id' in widget.winfo_name:
id = widget.get()
if 'custom' in widget.winfo_name:
value = widget.get()
if 'key' == widget.winfo_name():
key = widget.get(1.0, 'end')
key = key.strip()
if 'id' == widget.winfo_name():
id = widget.get(1.0, 'end')
id = id.strip()
if 'type' == widget.winfo_name():
type = widget.get(1.0, 'end')
type = type.strip()
if 'permission' == widget.winfo_name():
permission = widget.get(1.0, 'end')
permission = permission.strip()
if 'range' == widget.winfo_name():
range = widget.get(1.0, 'end')
range = range.strip()
if 'custom' == widget.winfo_name():
value = widget.get(1.0, 'end')
value = value.strip()
path = search_entry.get()
version = path.split('/')[1]
print(f'{user} {id} {version} {key} {value}')
# 类型检测
try:
if type != 'enum':
variant_type = GLib.VariantType(type)
variant = GLib.Variant.parse(variant_type, value)
except Exception as e:
msgbox.showinfo('unknown keyword')
return
# 取值范围检测
if type == 'enum' and value not in range:
msgbox.showinfo(message='Out of range')
return
elif type != 'enum' and range != '':
try:
min = GLib.Variant.parse(variant_type, range.split(',')[0].strip())
max = GLib.Variant.parse(variant_type, range.split(',')[1].strip())
if variant.compare(min) < 0 or variant.compare(max) > 0:
msgbox.showinfo(message='Out of range')
return
except Exception as e:
msgbox.showinfo(message=e)
return
bus = dbus.SystemBus()
obj = bus.get_object('com.kylin.kysdk.conf2', '/com/kylin/kysdk/conf2')
interface = dbus.Interface(obj, 'com.kylin.kysdk.conf2')
# success = interface.set(user, id, version, key, value)
# if success:
# global target_view
# target_view = converter._db2dict(f'{destination_file}/.config/kylin-config/user.db')
# msgbox.showinfo(message='Set successed')
# else:
# msgbox.showinfo(message='Set failed')
obj_interface = dbus.Interface(obj, dbus_interface='com.kylin.kysdk.conf2')
success = obj_interface.set(user, id, version, key, value)
if success:
global target_view
target_view = converter._db2dict(f'{destination_file}/.config/kylin-config/user.db')
msgbox.showinfo(message='Set successed')
else:
msgbox.showinfo(message='Set failed')
except Exception as e:
print(e)
def on_search_tree_select(event):
items = search_tree.selection()
text = search_tree.item(items[0], 'text')
text = search_tree.item(items, 'text')
if text == '':
return
tree.selection_set(search_list[text])
tree.see(search_list[text])
search_frame.pack_forget()
view_frame.pack(side='bottom', fill='both', expand=True)
search_button_text = search_button.cget('text')
if search_button_text == 'cancel':
search_button.config(text='search')
def on_tree_select(event):
selected_item = tree.selection()
@ -180,7 +262,7 @@ def on_tree_select(event):
summary_label = tk.Label(inner_frame, text=f'摘要', anchor='w')
summary_label.pack(side='top', fill='x')
summary_text = tk.Text(inner_frame, height=3, width=100, wrap='word')
summary_text = tk.Text(inner_frame, height=3, width=100, wrap='word', name='summary')
summary_text.insert('1.0', tmp.get('_summary'))
summary_text.config(state='disabled')
summary_text.pack(side='top', fill='x', expand=True)
@ -189,7 +271,7 @@ def on_tree_select(event):
decription_label = tk.Label(inner_frame, text=f'描述', anchor='w')
decription_label.pack(side='top', fill='x')
decription_text = tk.Text(inner_frame, height=3, width=100, wrap='word')
decription_text = tk.Text(inner_frame, height=3, width=100, wrap='word' ,name='description')
decription_text.insert('1.0', tmp.get('_description'))
decription_text.config(state='disabled')
decription_text.pack(side='top', fill='x', expand=True)
@ -198,11 +280,33 @@ def on_tree_select(event):
permission_label = tk.Label(inner_frame, text=f'权限', anchor='w')
permission_label.pack(side='top', fill='x')
permission_text = tk.Text(inner_frame, height=1, width=100, wrap='word')
permission_text = tk.Text(inner_frame, height=1, width=100, wrap='word', name='permission')
permission_text.insert('1.0', permission)
permission_text.config(state='disabled')
permission_text.pack(side='top', fill='x', expand=True)
if tmp.get('_range') is not None:
decription_label = tk.Label(inner_frame, text=f'取值范围', anchor='w')
decription_label.pack(side='top', fill='x')
range = tmp.get('_range')
if tmp.get('_type') == 'enum':
if range.startswith('@'):
path = search_entry.get()
version_data = target_view[path.split('/')[0]][path.split('/')[1]]
# _开头的应该是内部函数仅在类内部使用但我实在懒得搬代码了
element_list = converter._recursive_search(version_data, range[1:])
value_list = []
for element in element_list:
value_list.append(element['_nick'])
range = str(value_list)
else:
data = yaml.safe_load(range)
range = str(list(data.keys()))
decription_text = tk.Text(inner_frame, height=3, width=100, wrap='word' ,name='range')
decription_text.insert('1.0', range)
decription_text.config(state='disabled')
decription_text.pack(side='top', fill='x', expand=True)
if '_default' in tmp:
default_value = tmp['_default']
if isinstance(default_value, bool):
@ -216,16 +320,17 @@ def on_tree_select(event):
default_text.config(state='disabled')
default_text.pack(side='top', fill='x', expand=True)
custom_value = tmp.get('_value')
if custom_value is None or custom_value == default_value:
custom_value = '默认值'
custom_label = tk.Label(inner_frame, text=f'当前值', anchor='w')
custom_label.pack(side='top', fill='x')
if combobox.get() == 'custom':
custom_value = tmp.get('_value')
if custom_value is None:
custom_value = '默认值'
custom_label = tk.Label(inner_frame, text=f'当前值', anchor='w')
custom_label.pack(side='top', fill='x')
custom_text = tk.Text(inner_frame, height=5, width=100, wrap='word', name='custom')
custom_text.insert('1.0', custom_value)
custom_text.config(state='disabled')
custom_text.pack(side='top', fill='x', expand=True)
custom_text = tk.Text(inner_frame, height=5, width=100, wrap='word', name='custom')
custom_text.insert('1.0', custom_value)
custom_text.config(state='disabled')
custom_text.pack(side='top', fill='x', expand=True)
if type != 'group' and permission == 'public' and combobox.get() == 'custom':
custom_text.config(state='normal')
@ -275,7 +380,7 @@ root.bind("<Button-1>", close_menu)
download_menu = tk.Menu(root, tearoff=0)
download_menu.add_command(label="下载", command=on_download_one)
download_menu.add_command(label="导入到其他目录", command=on_import_file)
# download_menu.add_command(label="导入到其他目录", command=on_import_file)
search_list = {}
@ -302,19 +407,19 @@ search_entry = tk.Entry(button_frame, state='readonly')
search_entry.bind("<KeyRelease>", on_search_entry_change)
# 搜索按钮
# search_icon = tk.BitmapImage(data=search_icon_data)
search_button = tk.Button(button_frame, text= 's', command=on_search, width=20)
# search_icon = tk.PhotoImage('/etc/kylin-config/search.png')
search_button = tk.Button(button_frame, text='search', command=on_search, width=20)
# 下载按钮
# download_icon = tk.PhotoImage(file="download_icon.png")
download_button = tk.Button(button_frame, text= 'd', command=on_download, width=20)
# download_icon = tk.PhotoImage(file="/etc/kylin-config/download.png")
download_button = tk.Button(button_frame, text='export', command=on_download, width=20)
# 视图选择列表
with open('/etc/kylin-config/conf2.yaml', 'r') as file:
configures = yaml.safe_load(file)
options = configures['dirs']
if os.path.exists(f'{destination_file}/.config/kylin-config/configs'):
options.append('user')
options.append('mutable')
options.append('custom')
options.reverse()
@ -354,16 +459,33 @@ right_frame.pack(side='right', fill='both', expand=True)
# 创建一个Canvas
canvas = tk.Canvas(right_frame)
canvas.pack(side="left", fill="both", expand=True)
# 将Canvas的窗口设置为Frame
inner_frame = tk.Frame(canvas)
inner_frame.grid(row=0, column=0, sticky="nsew")
canvas_window = canvas.create_window((0, 0), window=inner_frame, anchor="nw")
canvas.config(scrollregion=canvas.bbox("all"))
right_scrollbar = ttk.Scrollbar(right_frame, orient="vertical", command=canvas.yview)
right_scrollbar.pack(side="right", fill="y")
canvas.configure(yscrollcommand=right_scrollbar.set)
# 将Canvas的窗口设置为Frame
inner_frame = tk.Frame(canvas)
canvas_window = canvas.create_window((0, 0), window=inner_frame, anchor="nw")
inner_frame.bind("<Configure>", lambda event: canvas.config(scrollregion=canvas.bbox("all")))
# 控制滚动条滚动 Button-4是向上滚动 Button-5是向下滚动 event.num的数值代表按钮id
def on_mouse_scroll(event):
inner_height = inner_frame.winfo_height()
canvas_height = canvas.winfo_height()
# 内容长度是否需要滚动
if inner_height > canvas_height:
# 仅响应在canvas空间区域的滚轮事件
if canvas.winfo_containing(event.x_root, event.y_root) == canvas:
if event.num == 4:
canvas.yview_scroll(-2, "units")
elif event.num == 5:
canvas.yview_scroll(2, "units")
canvas.bind_all("<Button-4>", on_mouse_scroll)
canvas.bind_all("<Button-5>", on_mouse_scroll)
# 创建Treeview显示搜索匹配的路径
search_tree = ttk.Treeview(search_frame, show='tree')
search_tree.bind("<<TreeviewSelect>>", on_search_tree_select)
@ -373,4 +495,4 @@ search_scrollbar = ttk.Scrollbar(search_frame, orient="vertical", command=search
search_scrollbar.pack(side="right", fill="y")
search_tree.configure(yscrollcommand=search_scrollbar.set)
root.mainloop()
root.mainloop()

View File

@ -18,6 +18,9 @@
*
*/
/*于2.5.1.0版本舍弃专用python实现可视化工具*/
#include "../api/libkysettings.h"
#include "../api/ksettingsschema.h"
@ -847,4 +850,4 @@ int main(int argc, char *argv[])
gtk_main();
return 0;
}
}

View File

@ -68,6 +68,7 @@ static void print_help()
" writable Check if a key is writable\n"
" monitor Watch for changes\n"
// " monitor-reload Watch for realod\n"
" reload Reload configuration file, retain user configuration"
" save Save User config in target folder"
"\n"
"Use kconf2 help \"COMMAND\" to get detailed help.\n");
@ -281,11 +282,11 @@ int main(int argc, char *argv[])
if (0 == strcmp(argv[1], "list-schemas"))
{
if (argc < 3)
{
print_command("list-schemas");
exit(0);
}
// if (argc < 3)
// {
// print_command("list-schemas");
// exit(0);
// }
gboolean limit_app = FALSE, limit_version = FALSE;
if (argc > 2)
limit_app = TRUE;
@ -643,4 +644,4 @@ int main(int argc, char *argv[])
print_help();
}
return 0;
}
}