2
Loads application info for initial app usage and verification
4
Copyright 2011 Canonical Ltd.
7
Ted Gould <ted@canonical.com>
9
This program is free software: you can redistribute it and/or modify it
10
under the terms of the GNU General Public License version 3, as published
11
by the Free Software Foundation.
13
This program is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranties of
15
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
16
PURPOSE. See the GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License along
19
with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include <glib/gi18n.h>
25
#include "load-app-info.h"
26
#include "shared-values.h"
28
static void new_element (GMarkupParseContext *context, const gchar * name, const gchar ** attribute_names, const gchar ** attribute_values, gpointer user_data, GError **error);
29
static void end_element (GMarkupParseContext *context, const gchar * name, gpointer user_data, GError ** error);
31
static GMarkupParser app_info_parser = {
32
start_element: new_element,
33
end_element: end_element,
39
typedef struct _menu_data_t menu_data_t;
50
typedef enum _menu_errors_t menu_errors_t;
53
DUPLICATE_DESKTOPFILE,
62
load_app_info (const gchar * filename, sqlite3 * db)
65
g_return_val_if_fail(filename != NULL, FALSE);
66
g_return_val_if_fail(db != NULL, FALSE);
68
if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
73
GFile * file = g_file_new_for_path(filename);
76
GError * error = NULL;
78
gboolean load = g_file_load_contents(file,
79
NULL, /* cancelable */
86
g_warning("Unable to load file '%s': %s", filename, error->message);
93
g_warning("Unable to load file '%s'", filename);
99
menu_data_t menu_data = {
109
menu_data.statement = g_string_new("");
111
GMarkupParseContext * context = g_markup_parse_context_new(&app_info_parser,
114
NULL /* destroy func */);
116
gboolean parsed = g_markup_parse_context_parse(context, data, len, &error);
119
g_warning("Unable to parse file '%s': %s", filename, error->message);
125
g_warning("Unable to parse file '%s'", filename);
128
if (!menu_data.seen_header) {
129
g_warning("Never found a header in '%s'", filename);
133
if (!menu_data.seen_menus) {
134
g_warning("Never found menus in '%s'", filename);
138
g_markup_parse_context_free(context);
140
/* Execute SQL Statement */
142
if (parsed && menu_data.statement->str[0] != '\0') {
143
int exec_status = SQLITE_OK;
144
gchar * failstring = NULL;
145
exec_status = sqlite3_exec(db,
146
menu_data.statement->str,
147
NULL, NULL, &failstring);
148
if (exec_status != SQLITE_OK) {
149
g_warning("Unable to execute SQL statement to load DB: %s", failstring);
153
g_free(menu_data.desktopfile);
154
g_free(menu_data.domain);
155
g_string_free(menu_data.statement, TRUE);
159
g_object_unref(file);
167
static GQuark domain = 0;
169
domain = g_quark_from_static_string("hud-app-info-parser");
174
#define COLLECT(first, ...) \
175
g_markup_collect_attributes (name, \
176
attribute_names, attribute_values, error, \
177
first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID)
178
#define OPTIONAL G_MARKUP_COLLECT_OPTIONAL
179
#define STRDUP G_MARKUP_COLLECT_STRDUP
180
#define STRING G_MARKUP_COLLECT_STRING
181
#define NO_ATTRS() COLLECT (G_MARKUP_COLLECT_INVALID, NULL)
184
new_element (GMarkupParseContext *context, const gchar * name, const gchar ** attribute_names, const gchar ** attribute_values, gpointer user_data, GError **error)
186
menu_data_t * menu_data = (menu_data_t *)user_data;
188
if (g_strcmp0(name, "hudappinfo") == 0) {
189
if (menu_data->seen_header) {
190
g_set_error(error, error_domain(), DUPLICATE_HEADERS, "Recieved second header");
193
menu_data->seen_header = TRUE;
197
if (!menu_data->seen_header) {
198
g_set_error(error, error_domain(), MISSING_HEADER, "Missing the header when we got to element '%s'", name);
202
if (g_strcmp0(name, "desktopfile") == 0) {
203
const gchar * desktopfile;
205
if (!COLLECT(STRING, "path", &desktopfile)) {
209
if (menu_data->desktopfile != NULL) {
210
g_set_error(error, error_domain(), DUPLICATE_DESKTOPFILE, "Two desktop file definitions. First as '%s' then as '%s'.", menu_data->desktopfile, desktopfile);
214
menu_data->desktopfile = g_strdup(desktopfile);
218
if (g_strcmp0(name, "menus") == 0) {
219
if (menu_data->desktopfile == NULL) {
220
g_set_error(error, error_domain(), MISSING_DESKTOP, "No desktop file is defined");
223
if (menu_data->seen_menus) {
224
g_set_error(error, error_domain(), DUPLICATE_MENUS, "Second set of menus found");
227
menu_data->seen_menus = TRUE;
232
if (g_strcmp0(name, "menu") == 0) {
233
if (!menu_data->seen_menus) {
234
g_set_error(error, error_domain(), MISSING_MENUS, "Menu tag found without enclosing menus");
240
if (!COLLECT(STRING, "name", &mname)) {
244
const gchar * translated = NULL;
245
if (menu_data->domain != NULL) {
246
translated = g_dgettext(menu_data->domain, mname);
248
translated = _(mname);
251
if (g_queue_is_empty(&menu_data->queue)) {
252
g_queue_push_head(&menu_data->queue, g_strdup(translated));
254
g_queue_push_head(&menu_data->queue, g_strconcat((gchar *)g_queue_peek_head(&menu_data->queue), DB_SEPARATOR, translated, NULL));
260
if (g_strcmp0(name, "item") == 0) {
261
if (!menu_data->seen_menus) {
262
g_set_error(error, error_domain(), MISSING_MENUS, "Item tag found without enclosing menus");
267
const gchar * scount;
269
if (!COLLECT(STRING, "name", &iname,
270
STRING, "count", &scount)) {
274
const gchar * translated = NULL;
275
if (menu_data->domain != NULL) {
276
translated = g_dgettext(menu_data->domain, iname);
278
translated = _(iname);
281
gchar * finalitem = g_strconcat((gchar *)g_queue_peek_head(&menu_data->queue), DB_SEPARATOR, translated, NULL);
282
gint64 count = g_ascii_strtoll(scount, NULL, 10);
285
for (i = 0; i < count; i++) {
287
g_string_append_printf(menu_data->statement, "insert into usage (application, entry, timestamp) values ('%s', '%s', date('now', 'utc'));", menu_data->desktopfile, finalitem);
289
g_string_append_printf(menu_data->statement, "insert into usage (application, entry, timestamp) values ('%s', '%s', date('now', 'utc', '-%d days'));", menu_data->desktopfile, finalitem, i);
301
end_element (GMarkupParseContext *context, const gchar * name, gpointer user_data, GError ** error)
303
menu_data_t * menu_data = (menu_data_t *)user_data;
305
if (g_strcmp0(name, "menu") == 0) {
306
if (g_queue_is_empty(&menu_data->queue)) {
307
g_warning("Menu stack is empty!");
309
g_free(g_queue_pop_head(&menu_data->queue));