/** * as_app_builder_search_translations: * @app: an #AsApp * @prefix: a prefix to search, e.g. "/usr" * @min_percentage: minimum percentage to add language * @flags: #AsAppBuilderFlags, e.g. %AS_APP_BUILDER_FLAG_USE_FALLBACKS * @cancellable: a #GCancellable or %NULL * @error: a #GError or %NULL * * Searches a prefix for languages, and using a heuristic adds <language> * tags to the specified application. * * If there are no #AsTranslation objects set on the #AsApp then all domains * are matched, which may include more languages than you intended to. * * @min_percentage sets the minimum percentage to add a language tag. * The usual value would be 25% and any language less complete than * this will not be added. * * The purpose of this functionality is to avoid blowing up the size * of the AppStream metadata with a lot of extra data detailing * languages with very few translated strings. * * Returns: %TRUE for success * * Since: 0.5.8 **/ gboolean as_app_builder_search_translations (AsApp *app, const gchar *prefix, guint min_percentage, AsAppBuilderFlags flags, GCancellable *cancellable, GError **error) { AsAppBuilderEntry *e; GList *l; g_autoptr(AsAppBuilderContext) ctx = NULL; ctx = as_app_builder_ctx_new (); ctx->translations = as_app_get_translations (app); /* search for QT .qm files */ if (!as_app_builder_search_translations_qt (ctx, prefix, flags, error)) return FALSE; /* search for gettext .mo files */ if (!as_app_builder_search_translations_gettext (ctx, prefix, flags, error)) return FALSE; /* search for Google .pak files */ if (!as_app_builder_search_translations_pak (ctx, prefix, flags, error)) return FALSE; /* calculate percentages */ for (l = ctx->data; l != NULL; l = l->next) { e = l->data; e->percentage = MIN (e->nstrings * 100 / ctx->max_nstrings, 100); } /* sort */ ctx->data = g_list_sort (ctx->data, as_app_builder_entry_sort_cb); /* add results */ for (l = ctx->data; l != NULL; l = l->next) { e = l->data; if (e->percentage < min_percentage) continue; as_app_add_language (app, (gint) e->percentage, e->locale); } return TRUE; }
/** * asb_plugin_process_filename: */ static gboolean asb_plugin_process_filename (AsbPlugin *plugin, AsbPackage *pkg, const gchar *filename, GList **apps, const gchar *tmpdir, GError **error) { gboolean ret = TRUE; gchar *error_msg = 0; gchar *filename_tmp; gint rc; guint i; sqlite3 *db = NULL; _cleanup_free_ gchar *basename = NULL; _cleanup_free_ gchar *description = NULL; _cleanup_free_ gchar *language_string = NULL; _cleanup_free_ gchar *name = NULL; _cleanup_free_ gchar *symbol = NULL; _cleanup_object_unref_ AsbApp *app = NULL; _cleanup_object_unref_ AsIcon *icon = NULL; _cleanup_strv_free_ gchar **languages = NULL; /* open IME database */ filename_tmp = g_build_filename (tmpdir, filename, NULL); rc = sqlite3_open (filename_tmp, &db); if (rc) { ret = FALSE; g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "Can't open database: %s", sqlite3_errmsg (db)); goto out; } /* get name */ rc = sqlite3_exec(db, "SELECT * FROM ime WHERE attr = 'name' LIMIT 1;", asb_plugin_sqlite_callback_cb, &name, &error_msg); if (rc != SQLITE_OK) { ret = FALSE; g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "Can't get IME name from %s: %s", filename, error_msg); sqlite3_free(error_msg); goto out; } /* get symbol */ rc = sqlite3_exec(db, "SELECT * FROM ime WHERE attr = 'symbol' LIMIT 1;", asb_plugin_sqlite_callback_cb, &symbol, &error_msg); if (rc != SQLITE_OK) { ret = FALSE; g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "Can't get IME symbol from %s: %s", filename, error_msg); sqlite3_free(error_msg); goto out; } /* get languages */ rc = sqlite3_exec(db, "SELECT * FROM ime WHERE attr = 'languages' LIMIT 1;", asb_plugin_sqlite_callback_cb, &language_string, &error_msg); if (rc != SQLITE_OK) { ret = FALSE; g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "Can't get IME languages from %s: %s", filename, error_msg); sqlite3_free(error_msg); goto out; } /* get description */ rc = sqlite3_exec(db, "SELECT * FROM ime WHERE attr = 'description' LIMIT 1;", asb_plugin_sqlite_callback_cb, &description, &error_msg); if (rc != SQLITE_OK) { ret = FALSE; g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "Can't get IME name from %s: %s", filename, error_msg); sqlite3_free(error_msg); goto out; } /* this is _required_ */ if (name == NULL || description == NULL) { ret = FALSE; g_set_error (error, ASB_PLUGIN_ERROR, ASB_PLUGIN_ERROR_FAILED, "No 'name' and 'description' in %s", filename); goto out; } /* create new app */ basename = g_path_get_basename (filename); app = asb_app_new (pkg, basename); as_app_set_id_kind (AS_APP (app), AS_ID_KIND_INPUT_METHOD); as_app_add_category (AS_APP (app), "Addons"); as_app_add_category (AS_APP (app), "InputSources"); as_app_set_name (AS_APP (app), "C", name); as_app_set_comment (AS_APP (app), "C", description); if (symbol != NULL && symbol[0] != '\0') as_app_add_metadata (AS_APP (app), "X-IBus-Symbol", symbol); if (language_string != NULL) { languages = g_strsplit (language_string, ",", -1); for (i = 0; languages[i] != NULL; i++) { if (g_strcmp0 (languages[i], "other") == 0) continue; as_app_add_language (AS_APP (app), 100, languages[i]); } } asb_app_set_requires_appdata (app, TRUE); asb_app_set_hidpi_enabled (app, asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_HIDPI_ICONS)); /* add icon */ icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "system-run-symbolic"); as_app_add_icon (AS_APP (app), icon); asb_plugin_add_app (apps, AS_APP (app)); out: if (db != NULL) sqlite3_close (db); return ret; }
/** * cra_plugin_process_filename: */ static gboolean cra_plugin_process_filename (CraPlugin *plugin, CraPackage *pkg, const gchar *filename, GList **apps, const gchar *tmpdir, GError **error) { GNode *root = NULL; GString *valid_xml; const gchar *tmp; const GNode *n; gboolean found_header = FALSE; gboolean ret; guint i; _cleanup_free_ gchar *basename = NULL; _cleanup_free_ gchar *data = NULL; _cleanup_free_ gchar *filename_tmp; _cleanup_object_unref_ CraApp *app = NULL; _cleanup_strv_free_ gchar **languages = NULL; _cleanup_strv_free_ gchar **lines = NULL; /* open file */ filename_tmp = g_build_filename (tmpdir, filename, NULL); ret = g_file_get_contents (filename_tmp, &data, NULL, error); if (!ret) goto out; /* some components start with a comment (invalid XML) and some * don't even have '<?xml' -- try to fix up best we can */ valid_xml = g_string_new (""); lines = g_strsplit (data, "\n", -1); for (i = 0; lines[i] != NULL; i++) { if (g_str_has_prefix (lines[i], "<?xml") || g_str_has_prefix (lines[i], "<component>")) found_header = TRUE; if (found_header) g_string_append_printf (valid_xml, "%s\n", lines[i]); } /* parse contents */ root = as_node_from_xml (valid_xml->str, -1, AS_NODE_FROM_XML_FLAG_NONE, error); if (!ret) goto out; /* create new app */ basename = g_path_get_basename (filename); app = cra_app_new (pkg, basename); as_app_set_id_kind (AS_APP (app), AS_ID_KIND_INPUT_METHOD); as_app_add_category (AS_APP (app), "Addons", -1); as_app_add_category (AS_APP (app), "InputSources", -1); as_app_set_icon (AS_APP (app), "system-run-symbolic", -1); as_app_set_icon_kind (AS_APP (app), AS_ICON_KIND_STOCK); cra_app_set_requires_appdata (app, TRUE); /* read the component header which all input methods have */ n = as_node_find (root, "component/description"); if (n != NULL) { as_app_set_name (AS_APP (app), "C", as_node_get_data (n), -1); as_app_set_comment (AS_APP (app), "C", as_node_get_data (n), -1); } n = as_node_find (root, "component/homepage"); if (n != NULL) { as_app_add_url (AS_APP (app), AS_URL_KIND_HOMEPAGE, as_node_get_data (n), -1); } /* do we have a engine section we can use? */ n = as_node_find (root, "component/engines/engine/longname"); if (n != NULL) as_app_set_name (AS_APP (app), "C", as_node_get_data (n), -1); n = as_node_find (root, "component/engines/engine/description"); if (n != NULL) as_app_set_comment (AS_APP (app), "C", as_node_get_data (n), -1); n = as_node_find (root, "component/engines/engine/symbol"); if (n != NULL) { tmp = as_node_get_data (n); if (tmp != NULL && tmp[0] != '\0') { as_app_add_metadata (AS_APP (app), "X-IBus-Symbol", tmp, -1); } } n = as_node_find (root, "component/engines/engine/language"); if (n != NULL) { tmp = as_node_get_data (n); if (tmp != NULL) { languages = g_strsplit (tmp, ",", -1); for (i = 0; languages[i] != NULL; i++) { if (g_strcmp0 (languages[i], "other") == 0) continue; as_app_add_language (AS_APP (app), 100, languages[i], -1); } } } /* add */ cra_plugin_add_app (apps, app); out: if (root != NULL) as_node_unref (root); return ret; }