From a5ff1584d817682f8b37cf942de36ce309349c9c Mon Sep 17 00:00:00 2001 From: Sung-jae Park Date: Mon, 2 Dec 2013 10:54:33 +0900 Subject: [PATCH] Supporting the I18Nized icons for shortcut-list Change-Id: Ia33a1ad926f8f06f0a598325529019123ddf6eb4 --- lib/src/main.c | 52 +++++++--- packaging/libshortcut.spec | 4 +- pkgmgr_shortcut/src/service_register.c | 177 ++++++++++++++++++++++++++------- 3 files changed, 183 insertions(+), 50 deletions(-) diff --git a/lib/src/main.c b/lib/src/main.c index 60b91b1..d950889 100644 --- a/lib/src/main.c +++ b/lib/src/main.c @@ -644,43 +644,65 @@ static inline int open_db(void) /*! * \note this function will returns allocated(heap) string */ -static inline char *get_i18n_name(const char *lang, int id) +static inline int get_i18n_name(const char *lang, int id, char **name, char **icon) { sqlite3_stmt *stmt; - static const char *query = "SELECT name FROM shortcut_name WHERE id = ? AND lang = ? COLLATE NOCASE"; - const unsigned char *name; - char *ret; + static const char *query = "SELECT name, icon FROM shortcut_name WHERE id = ? AND lang = ? COLLATE NOCASE"; + const unsigned char *_name; + const unsigned char *_icon; + int ret; int status; status = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL); if (status != SQLITE_OK) { ErrPrint("Failed to prepare stmt: %s\n", sqlite3_errmsg(s_info.handle)); - return NULL; + return -EFAULT; } status = sqlite3_bind_int(stmt, 1, id); if (status != SQLITE_OK) { ErrPrint("Failed to bind id: %s\n", sqlite3_errmsg(s_info.handle)); - ret = NULL; + ret = -EFAULT; goto out; } status = sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_TRANSIENT); if (status != SQLITE_OK) { ErrPrint("Failed to bind lang: %s\n", sqlite3_errmsg(s_info.handle)); - ret = NULL; + ret = -EFAULT; goto out; } DbgPrint("id: %d, lang: %s\n", id, lang); if (SQLITE_ROW != sqlite3_step(stmt)) { ErrPrint("Failed to do step: %s\n", sqlite3_errmsg(s_info.handle)); - ret = NULL; + ret = -ENOENT; goto out; } - name = sqlite3_column_text(stmt, 0); - ret = name ? strdup((const char *)name) : NULL; + _name = sqlite3_column_text(stmt, 0); + if (name) { + if (_name && strlen((const char *)_name)) { + *name = strdup((const char *)_name); + if (!*name) { + ErrPrint("strdup: %s\n", strerror(errno)); + } + } else { + *name = NULL; + } + } + + _icon = sqlite3_column_text(stmt, 1); + if (icon) { + if (_icon && strlen((const char *)_icon)) { + *icon = strdup((const char *)_icon); + if (!*icon) { + ErrPrint("strdup: %s\n", strerror(errno)); + } + } else { + *icon = NULL; + } + } out: sqlite3_reset(stmt); @@ -731,7 +753,8 @@ EAPI int shortcut_get_list(const char *appid, int (*cb)(const char *appid, const sqlite3_stmt *stmt; const char *query; const unsigned char *name; - char *i18n_name; + char *i18n_name = NULL; + char *i18n_icon = NULL; const unsigned char *extra_data; const unsigned char *extra_key; const unsigned char *icon; @@ -819,15 +842,18 @@ EAPI int shortcut_get_list(const char *appid, int (*cb)(const char *appid, const * \todo * Implement the "GET LOCALE" code */ - i18n_name = get_i18n_name(language, id); + if (get_i18n_name(language, id, &i18n_name, &i18n_icon) < 0) { + /* Okay, we can't manage this. just use the fallback string */ + } cnt++; - if (cb(appid, (char *)icon, (i18n_name != NULL ? i18n_name : (char *)name), (char *)extra_key, (char *)extra_data, data) < 0) { + if (cb(appid, (i18n_icon != NULL ? i18n_icon : (char *)icon), (i18n_name != NULL ? i18n_name : (char *)name), (char *)extra_key, (char *)extra_data, data) < 0) { free(i18n_name); break; } free(i18n_name); + free(i18n_icon); } sqlite3_reset(stmt); diff --git a/packaging/libshortcut.spec b/packaging/libshortcut.spec index 1846f83..eea9709 100644 --- a/packaging/libshortcut.spec +++ b/packaging/libshortcut.spec @@ -1,9 +1,9 @@ Name: libshortcut Summary: Shortcut add feature supporting library -Version: 0.6.9 +Version: 0.6.10 Release: 0 Group: HomeTF/Framework -License: Apache License +License: Apache Source0: %{name}-%{version}.tar.gz Source1001: libshortcut.manifest diff --git a/pkgmgr_shortcut/src/service_register.c b/pkgmgr_shortcut/src/service_register.c index 56822d3..672e424 100644 --- a/pkgmgr_shortcut/src/service_register.c +++ b/pkgmgr_shortcut/src/service_register.c @@ -58,11 +58,11 @@ * | id | - | - | - | - | - | - | * +----+-------+-------+------+---------+-----------+------------+ * - * +----+-------+------+------+ - * | fk | pkgid | lang | name | - * +----+-------+------+------+ - * | id | - | - | | - * +----+-------+------+------+ + * +----+-------+------+------+------+ + * | fk | pkgid | lang | name | icon | + * +----+-------+------+------+------+ + * | id | - | - | | - | + * +----+-------+------+------+------+ */ #if !defined(LIBXML_TREE_ENABLED) @@ -71,6 +71,12 @@ int errno; +struct i18n_name { + xmlChar *icon; + xmlChar *name; + xmlChar *lang; +}; + static struct { const char *dbfile; sqlite3 *handle; @@ -271,7 +277,7 @@ static void db_create_table(void) ErrPrint("No changes to DB\n"); } - ddl = "CREATE TABLE shortcut_name (id INTEGER, pkgid TEXT, lang TEXT, name TEXT)"; + ddl = "CREATE TABLE shortcut_name (id INTEGER, pkgid TEXT, lang TEXT, name TEXT, icon TEXT)"; if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) { ErrPrint("Failed to execute the DDL (%s)\n", err); return; @@ -284,6 +290,21 @@ static void db_create_table(void) db_create_version(); } +static void alter_shortcut_icon(void) +{ + char *err; + static const char *ddl = "ALTER TABLE shortcut_name ADD icon TEXT"; + + if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) { + ErrPrint("Failed to execute the DDL (%s)\n", err); + return; + } + + if (sqlite3_changes(s_info.handle) == 0) { + ErrPrint("No changes to DB\n"); + } +} + static void alter_shortcut_name(void) { char *err; @@ -372,16 +393,23 @@ static void do_upgrade_db_schema(void) alter_shortcut_name(); alter_shortcut_service(); case 1: + alter_shortcut_icon(); + if (update_version(2) < 0) { + ErrPrint("Failed to update version\n"); + } + case 2: break; default: /* Need to update version */ DbgPrint("Old version: %d\n", version); - if (update_version(1) < 0) { + if (update_version(2) < 0) { ErrPrint("Failed to update version\n"); } alter_shortcut_name(); alter_shortcut_service(); + /* 2 */ + alter_shortcut_icon(); break; } } @@ -605,17 +633,25 @@ out: return ret; } -static int db_insert_name(int id, const char *pkgid, const char *lang, const char *name) +static int db_insert_name(int id, const char *pkgid, const char *lang, const char *name, const char *icon) { - static const char *dml = "INSERT INTO shortcut_name (id, pkgid, lang, name) VALUES (?, ?, ?, ?)"; + static const char *dml = "INSERT INTO shortcut_name (id, pkgid, lang, name, icon) VALUES (?, ?, ?, ?, ?)"; sqlite3_stmt *stmt; int ret; - if (id < 0 || !lang || !name) { + if (id < 0 || !lang) { ErrPrint("Invalid parameters\n"); return -EINVAL; } + if (!name) { + name = ""; + } + + if (!icon) { + icon = ""; + } + ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL); if (ret != SQLITE_OK) { ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle)); @@ -646,6 +682,12 @@ static int db_insert_name(int id, const char *pkgid, const char *lang, const cha goto out; } + if (sqlite3_bind_text(stmt, 5, icon, -1, SQLITE_TRANSIENT) != SQLITE_OK) { + ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle)); + ret = -EIO; + goto out; + } + ret = 0; if (sqlite3_step(stmt) != SQLITE_DONE) { ErrPrint("Failed to execute the DML for %d %s %s\n", id, lang, name); @@ -775,6 +817,45 @@ static int do_uninstall(const char *appid) return 0; } +static inline struct i18n_name *find_i18n_name(struct dlist *i18n_list, xmlChar *lang) +{ + struct dlist *l; + struct i18n_name *i18n; + + dlist_foreach(i18n_list, l, i18n) { + if (!xmlStrcasecmp(i18n->lang, lang)) { + return i18n; + } + } + + return NULL; +} + +static inline struct i18n_name *create_i18n_name(xmlChar *lang, xmlChar *name, xmlChar *icon) +{ + struct i18n_name *i18n; + + i18n = malloc(sizeof(*i18n)); + if (!i18n) { + ErrPrint("Heap: %s\n", strerror(errno)); + return NULL; + } + + i18n->lang = lang; + i18n->name = name; + i18n->icon = icon; + + return i18n; +} + +static inline void destroy_i18n_name(struct i18n_name *i18n) +{ + xmlFree(i18n->lang); + xmlFree(i18n->name); + xmlFree(i18n->icon); + free(i18n); +} + static int do_install(xmlDocPtr docPtr, const char *appid) { xmlNodePtr node = NULL; @@ -783,12 +864,10 @@ static int do_install(xmlDocPtr docPtr, const char *appid) xmlChar *data; xmlChar *name; xmlChar *icon; + xmlChar *lang; xmlChar *shortcut_appid; xmlNodePtr root; - struct i18n_name { - xmlChar *name; - xmlChar *lang; - } *i18n; + struct i18n_name *i18n; struct dlist *i18n_list = NULL; struct dlist *l; struct dlist *n; @@ -836,17 +915,41 @@ static int do_install(xmlDocPtr docPtr, const char *appid) name = NULL; for (child = node->children; child; child = child->next) { if (!xmlStrcasecmp(child->name, (const xmlChar *)"icon")) { - if (icon) { - DbgPrint("Icon is duplicated\n"); + lang = xmlNodeGetLang(child); + if (!lang) { + if (icon) { + DbgPrint("Default icon is duplicated\n"); + } else { + icon = xmlNodeGetContent(child); + DbgPrint("Default icon is %s\n", icon); + } + continue; } - icon = xmlNodeGetContent(child); + i18n = find_i18n_name(i18n_list, lang); + if (i18n) { + xmlFree(lang); + + if (i18n->icon) { + DbgPrint("%s is duplicated\n", i18n->icon); + continue; + } + + i18n->icon = xmlNodeGetContent(child); + } else { + i18n = create_i18n_name(lang, NULL, xmlNodeGetContent(child)); + if (!i18n) { + ErrPrint("Failed to create a new i18n_name\n"); + continue; + } + i18n_list = dlist_append(i18n_list, i18n); + } + continue; } if (!xmlStrcasecmp(child->name, (const xmlChar *)"label")) { - xmlChar *lang; lang = xmlNodeGetLang(child); if (!lang) { if (name) { @@ -859,15 +962,25 @@ static int do_install(xmlDocPtr docPtr, const char *appid) continue; } - i18n = malloc(sizeof(*i18n)); - if (!i18n) { - ErrPrint("Heap: %s\n", strerror(errno)); - break; + i18n = find_i18n_name(i18n_list, lang); + if (i18n) { + xmlFree(lang); + + if (i18n->name) { + DbgPrint("%s is duplicated\n", i18n->name); + continue; + } + + i18n->name = xmlNodeGetContent(child); + } else { + i18n = create_i18n_name(lang, xmlNodeGetContent(child), NULL); + if (!i18n) { + ErrPrint("Failed to create a new i18n_name\n"); + continue; + } + i18n_list = dlist_append(i18n_list, i18n); } - i18n->lang = lang; - i18n->name = xmlNodeGetContent(child); - i18n_list = dlist_append(i18n_list, i18n); continue; } } @@ -891,9 +1004,7 @@ static int do_install(xmlDocPtr docPtr, const char *appid) dlist_foreach_safe(i18n_list, l, n, i18n) { i18n_list = dlist_remove(i18n_list, l); - xmlFree(i18n->lang); - xmlFree(i18n->name); - free(i18n); + destroy_i18n_name(i18n); } } else { id = db_get_id((char *)appid, (char *)shortcut_appid, (char *)key, (char *)data); @@ -903,19 +1014,15 @@ static int do_install(xmlDocPtr docPtr, const char *appid) dlist_foreach_safe(i18n_list, l, n, i18n) { i18n_list = dlist_remove(i18n_list, l); - xmlFree(i18n->lang); - xmlFree(i18n->name); - free(i18n); + destroy_i18n_name(i18n); } } else { dlist_foreach_safe(i18n_list, l, n, i18n) { i18n_list = dlist_remove(i18n_list, l); - if (db_insert_name(id, appid, (char *)i18n->lang, (char *)i18n->name) < 0) { + if (db_insert_name(id, appid, (char *)i18n->lang, (char *)i18n->name, (char *)i18n->icon) < 0) { ErrPrint("Failed to add i18n name: %s(%s)\n", i18n->name, i18n->lang); } - xmlFree(i18n->lang); - xmlFree(i18n->name); - free(i18n); + destroy_i18n_name(i18n); } commit_transaction(); } -- 2.7.4