Example #1
0
/**
 * 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;
}