50
60
GObject parent_instance;
62
HudWatchdog * watchdog;
63
HudSource *all_sources;
64
HudApplicationList *app_list;
65
HudSource *current_source;
66
HudSource *last_used_source;
53
67
gchar *search_string;
54
68
HudTokenList *token_list;
72
guint querynumber; /* Incrementing count, which one were we? */
73
HudQueryIfaceComCanonicalHudQuery * skel;
76
DeeModel * results_model;
78
DeeModelTag * results_tag;
80
DeeModel * appstack_model;
81
gchar * appstack_name;
83
GSequence * results_list; /* Should almost always be NULL except when refreshing the query */
84
guint max_usage; /* Used to make the GList search easier */
61
89
typedef GObjectClass HudQueryClass;
63
91
G_DEFINE_TYPE (HudQuery, hud_query, G_TYPE_OBJECT)
64
93
static guint hud_query_changed_signal;
66
static HudQuery *last_created_query;
69
hud_query_find_max_usage (gpointer data,
72
guint *max_usage = user_data;
73
HudResult *result = data;
77
item = hud_result_get_item (result);
78
usage = hud_item_get_usage (item);
80
*max_usage = MAX (*max_usage, usage);
84
hud_query_compare_results (gconstpointer a,
88
HudResult *result_a = *(HudResult * const *) a;
89
HudResult *result_b = *(HudResult * const *) b;
90
gint max_usage = GPOINTER_TO_INT (user_data);
94
distance_a = hud_result_get_distance (result_a, max_usage);
95
distance_b = hud_result_get_distance (result_b, max_usage);
97
return distance_a - distance_b;
95
/* Schema that is used in the DeeModel representing
97
static const gchar * results_model_schema[HUD_QUERY_RESULTS_COUNT] = {
99
"s", /* Command Name */
100
"a(ii)", /* Highlights in command name */
101
"s", /* Description */
102
"a(ii)", /* Highlights in description */
105
"b", /* Parameterized */
108
/* Schema that is used in the DeeModel representing
110
static const gchar * appstack_model_schema[HUD_QUERY_APPSTACK_COUNT] = {
111
"s", /* Application ID */
117
compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
119
gint max_usage = ((HudQuery *) user_data)->max_usage;
120
return hud_result_get_distance ((HudResult *) a, max_usage)
121
- hud_result_get_distance ((HudResult *) b, max_usage);
124
/* Add a HudResult to the list of results. This is inserted at the
125
end for the moment, until action sort priorities are implemented.
126
We can't sort until we have the max usage, then we can sort
127
everything depending on distance and usage. */
129
results_list_populate (HudResult * result, gpointer user_data)
131
HudQuery * query = (HudQuery *)user_data;
132
// TODO: Change back to prepend after we have action sort priorities
133
// g_sequence_insert_before(g_sequence_get_begin_iter(query->results_list), result);
134
g_sequence_append(query->results_list, result);
138
/* A structure to track the items in the appstack */
139
typedef struct _appstack_item_t appstack_item_t;
140
struct _appstack_item_t {
143
HudSourceItemType type;
146
/* Free all of them items */
148
appstack_item_free (gpointer user_data)
150
appstack_item_t * item = (appstack_item_t *)user_data;
152
g_free(item->app_id);
153
g_free(item->app_icon);
159
/* Sort function for the appstack */
161
appstack_sort (GVariant ** row1, GVariant ** row2, gpointer user_data)
163
gint32 type1 = g_variant_get_int32(row1[HUD_QUERY_APPSTACK_ITEM_TYPE]);
164
gint32 type2 = g_variant_get_int32(row2[HUD_QUERY_APPSTACK_ITEM_TYPE]);
166
/* If the types are the same, we'll alphabetize by ID */
167
if (type1 == type2) {
168
const gchar * app_id1 = g_variant_get_string(row1[HUD_QUERY_APPSTACK_APPLICATION_ID], NULL);
169
const gchar * app_id2 = g_variant_get_string(row2[HUD_QUERY_APPSTACK_APPLICATION_ID], NULL);
171
return g_strcmp0(app_id1, app_id2);
174
return type1 - type2;
177
/* Takes the hash and puts it into the Dee Model */
179
appstack_hash_to_model (GHashTable * hash, DeeModel * model)
181
GList * values = g_hash_table_get_values(hash);
184
for (value = values; value != NULL; value = g_list_next(value)) {
185
appstack_item_t * item = (appstack_item_t *)value->data;
187
GVariant * columns[HUD_QUERY_APPSTACK_COUNT + 1];
188
columns[HUD_QUERY_APPSTACK_APPLICATION_ID] = g_variant_new_string(item->app_id ? item->app_id : "");
189
columns[HUD_QUERY_APPSTACK_ICON_NAME] = g_variant_new_string(item->app_icon ? item->app_icon : "");
190
columns[HUD_QUERY_APPSTACK_ITEM_TYPE] = g_variant_new_int32(item->type);
191
columns[HUD_QUERY_APPSTACK_COUNT] = NULL;
193
dee_model_insert_row_sorted(model, columns, appstack_sort, NULL);
199
/* Add an item to the hash table */
201
appstack_hash_add_source (GHashTable * table, HudSource * source, HudSourceItemType in_type)
203
if (source == NULL) {
207
const gchar * id = hud_source_get_app_id(source);;
208
g_return_if_fail(id != NULL);
210
const gchar * icon = hud_source_get_app_icon(source);;
211
HudSourceItemType type = in_type;
213
if (HUD_IS_MENU_MODEL_COLLECTOR(source) || HUD_IS_DBUSMENU_COLLECTOR(source)) {
214
type = HUD_SOURCE_ITEM_TYPE_INDICATOR;
217
appstack_item_t * item = g_new0(appstack_item_t, 1);
218
item->app_id = g_strdup(id);
219
item->app_icon = g_strdup(icon);
222
g_hash_table_insert(table, g_strdup(id), item);
227
/* Add a HudItem to the list of app results */
229
app_results_list_populate (const gchar *application_id, const gchar *application_icon, HudSourceItemType type, gpointer user_data)
231
g_return_if_fail(application_id != NULL);
233
GHashTable * table = (GHashTable *)user_data;
235
appstack_item_t * item = g_new0(appstack_item_t, 1);
236
item->app_id = g_strdup(application_id);
237
item->app_icon = g_strdup(application_icon);
240
g_hash_table_insert(table, g_strdup(application_id), item);
245
/* Go through the list and find the item with the highest usage
246
that the others will be compared against */
248
results_list_max_usage (gpointer data, gpointer user_data)
250
HudResult * result = (HudResult *)data;
251
HudItem * item = hud_result_get_item(result);
252
guint * max_usage = (guint *)user_data;
254
*max_usage = MAX(*max_usage, hud_item_get_usage(item));
258
/* Turn the results list into a DeeModel. It assumes the results are already sorted. */
260
results_list_to_model (gpointer data, gpointer user_data)
262
HudResult * result = (HudResult *)data;
263
HudQuery * query = (HudQuery *)user_data;
264
HudItem * item = hud_result_get_item(result);
266
GVariant * columns[HUD_QUERY_RESULTS_COUNT + 1];
267
columns[HUD_QUERY_RESULTS_COMMAND_ID] = g_variant_new_variant(g_variant_new_uint64(hud_item_get_id(item)));
268
columns[HUD_QUERY_RESULTS_COMMAND_NAME] = g_variant_new_string(hud_item_get_command(item));
269
columns[HUD_QUERY_RESULTS_COMMAND_HIGHLIGHTS] = g_variant_new_array(G_VARIANT_TYPE("(ii)"), NULL, 0);
270
columns[HUD_QUERY_RESULTS_DESCRIPTION] = g_variant_new_string(hud_item_get_description(item));
271
columns[HUD_QUERY_RESULTS_DESCRIPTION_HIGHLIGHTS] = g_variant_new_array(G_VARIANT_TYPE("(ii)"), NULL, 0);
272
columns[HUD_QUERY_RESULTS_SHORTCUT] = g_variant_new_string(hud_item_get_shortcut(item));
273
columns[HUD_QUERY_RESULTS_DISTANCE] = g_variant_new_uint32(hud_result_get_distance(result, query->max_usage));
274
columns[HUD_QUERY_RESULTS_PARAMETERIZED] = g_variant_new_boolean(HUD_IS_MODEL_ITEM(item) ? hud_model_item_is_parameterized(HUD_MODEL_ITEM(item)) : FALSE);
275
columns[HUD_QUERY_RESULTS_COUNT] = NULL;
277
DeeModelIter * iter = dee_model_append_row(query->results_model,
278
columns /* variants */);
280
dee_model_set_tag(query->results_model, iter, query->results_tag, result);
101
286
hud_query_refresh (HudQuery *query)
104
288
guint64 start_time;
290
hud_watchdog_ping(query->watchdog);
106
291
start_time = g_get_monotonic_time ();
108
g_ptr_array_set_size (query->results, 0);
110
if (hud_token_list_get_length (query->token_list) != 0)
111
hud_source_search (query->source, query->results, query->token_list);
113
g_ptr_array_foreach (query->results, hud_query_find_max_usage, &max_usage);
114
g_ptr_array_sort_with_data (query->results, hud_query_compare_results, GINT_TO_POINTER (max_usage));
115
if (query->results->len > query->num_results)
116
g_ptr_array_set_size (query->results, query->num_results);
293
dee_model_clear(query->results_model);
294
query->results_list = g_sequence_new(NULL);
295
query->max_usage = 0;
297
/* Note that the results are kept sorted as they are collected using a GSequence */
298
HudSource * search_source = query->current_source;
299
if (search_source == NULL) {
300
search_source = hud_application_list_get_focused_app(query->app_list);
303
/* Make sure we've used it before searching it */
304
if (search_source != NULL && search_source != query->last_used_source) {
305
if (query->last_used_source != NULL)
307
hud_source_unuse(query->last_used_source);
308
g_clear_object(&query->last_used_source);
310
hud_source_use(search_source);
311
query->last_used_source = g_object_ref(search_source);
314
if (search_source != NULL) {
315
hud_source_search (search_source, query->token_list, results_list_populate, query);
317
g_debug("Current source was null. This should usually not happen outside tests in regular user use");
319
g_debug("Num results: %d", g_sequence_get_length(query->results_list));
321
g_sequence_foreach(query->results_list, results_list_max_usage, &query->max_usage);
322
g_debug("Max Usage: %d", query->max_usage);
324
/* Now that we have the max usage we can sort */
325
g_sequence_sort(query->results_list, compare_func, query);
326
g_sequence_foreach(query->results_list, results_list_to_model, query);
328
/* NOTE: Not freeing the items as the references are picked up by the DeeModel */
329
g_sequence_free(query->results_list);
330
query->results_list = NULL;
332
/* Reset for new data */
333
dee_model_clear(query->appstack_model);
335
/* Get the list of all applications that have data that is relevant
336
to the current query, but just the app info. */
337
GHashTable * appstack_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, appstack_item_free);
338
hud_source_list_applications (query->all_sources, query->token_list, app_results_list_populate, appstack_hash);
340
/* If we've selected a source, make sure it's in the list */
341
appstack_hash_add_source(appstack_hash, query->current_source, HUD_SOURCE_ITEM_TYPE_BACKGROUND_APP);
343
/* Always have the focused app in there too */
344
HudSource * focused = hud_application_list_get_focused_app(query->app_list);
345
appstack_hash_add_source(appstack_hash, focused, HUD_SOURCE_ITEM_TYPE_FOCUSED_APP);
347
/* Always have the side stage app in there too */
348
HudSource * side_stage = hud_application_list_get_side_stage_focused_app(query->app_list);
349
appstack_hash_add_source(appstack_hash, side_stage, HUD_SOURCE_ITEM_TYPE_SIDESTAGE_APP);
351
/* Now take the hash, having already deduplicated for us, and turn
352
it into a shorted DeeModel */
353
appstack_hash_to_model(appstack_hash, query->appstack_model);
355
/* Thanks hash ol' friend */
356
g_hash_table_unref(appstack_hash);
118
358
g_debug ("query took %dus\n", (int) (g_get_monotonic_time () - start_time));
360
g_object_set(G_OBJECT(query->skel), "current-query", query->search_string, NULL);
149
391
g_debug ("Destroyed query '%s'", query->search_string);
393
/* TODO: move to destroy */
394
if (query->last_used_source != NULL)
396
hud_source_unuse(query->last_used_source);
397
g_clear_object(&query->last_used_source);
400
g_clear_object(&query->skel);
401
g_clear_object(&query->results_model);
402
/* NOTE: ^^ Kills results_tag as well */
403
g_clear_object(&query->appstack_model);
151
405
if (query->refresh_id)
152
406
g_source_remove (query->refresh_id);
154
hud_source_unuse (query->source);
156
g_object_unref (query->source);
157
hud_token_list_free (query->token_list);
158
g_free (query->search_string);
159
g_ptr_array_unref (query->results);
408
g_object_unref (query->all_sources);
409
g_object_unref (query->app_list);
410
g_clear_object (&query->current_source);
411
if (query->token_list != NULL) {
412
hud_token_list_free (query->token_list);
413
query->token_list = NULL;
415
g_clear_pointer(&query->search_string, g_free);
417
g_clear_pointer(&query->object_path, g_free);
418
g_clear_pointer(&query->results_name, g_free);
419
g_clear_pointer(&query->appstack_name, g_free);
421
g_clear_object(&query->voice);
422
g_clear_object(&query->watchdog);
161
424
G_OBJECT_CLASS (hud_query_parent_class)
162
425
->finalize (object);
428
/* Handle the DBus function UpdateQuery */
430
handle_voice_query (HudQueryIfaceComCanonicalHudQuery * skel, GDBusMethodInvocation * invocation, gpointer user_data)
432
g_return_val_if_fail(HUD_IS_QUERY(user_data), FALSE);
433
HudQuery * query = HUD_QUERY(user_data);
434
hud_watchdog_ping(query->watchdog);
436
g_debug("Voice query is loading");
437
hud_query_iface_com_canonical_hud_query_emit_voice_query_loading (
438
HUD_QUERY_IFACE_COM_CANONICAL_HUD_QUERY (skel));
440
GError *error = NULL;
442
HudSource * search_source = query->current_source;
443
if (search_source == NULL) {
444
search_source = hud_application_list_get_focused_app(query->app_list);
447
if (!hud_voice_query (query->voice, search_source, &voice_result, &error))
449
g_dbus_method_invocation_return_error_literal(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, error->message);
454
g_debug("Voice query is finished");
456
if (voice_result == NULL)
457
voice_result = g_strdup("");
459
gchar *search_string = g_utf8_strdown(voice_result, -1);
460
g_free(voice_result);
462
g_debug("Updating Query to: '%s'", search_string);
464
/* Clear the last query */
465
g_clear_pointer(&query->search_string, g_free);
466
if (query->token_list != NULL) {
467
hud_token_list_free (query->token_list);
468
query->token_list = NULL;
471
query->search_string = search_string;
473
if (query->search_string[0] != '\0') {
474
query->token_list = hud_token_list_new_from_string (query->search_string);
478
hud_query_refresh (query);
480
/* Tell DBus everything is going to be A-OK */
481
hud_query_iface_com_canonical_hud_query_complete_voice_query(skel, invocation, 0, search_string);
486
/* Handle the DBus function UpdateQuery */
488
handle_update_query (HudQueryIfaceComCanonicalHudQuery * skel, GDBusMethodInvocation * invocation, const gchar * search_string, gpointer user_data)
490
g_return_val_if_fail(HUD_IS_QUERY(user_data), FALSE);
491
HudQuery * query = HUD_QUERY(user_data);
492
hud_watchdog_ping(query->watchdog);
494
g_debug("Updating Query to: '%s'", search_string);
496
/* Clear the last query */
497
g_clear_pointer(&query->search_string, g_free);
498
if (query->token_list != NULL) {
499
hud_token_list_free (query->token_list);
500
query->token_list = NULL;
503
/* Grab the data from this one */
504
query->search_string = g_strdup (search_string);
505
query->search_string = g_strstrip(query->search_string);
507
if (query->search_string[0] != '\0') {
508
query->token_list = hud_token_list_new_from_string (query->search_string);
512
hud_query_refresh (query);
514
/* Tell DBus everything is going to be A-OK */
515
hud_query_iface_com_canonical_hud_query_complete_update_query(skel, invocation, 0);
520
/* Handle the DBus function UpdateApp */
522
handle_update_app (HudQueryIfaceComCanonicalHudQuery * skel, GDBusMethodInvocation * invocation, const gchar * app_id, gpointer user_data)
524
g_return_val_if_fail(HUD_IS_QUERY(user_data), FALSE);
525
HudQuery * query = HUD_QUERY(user_data);
526
hud_watchdog_ping(query->watchdog);
528
g_debug("Updating App to: '%s'", app_id);
530
g_clear_object (&query->current_source);
531
query->current_source = hud_source_get(query->all_sources, app_id);
532
if (query->current_source != NULL) {
533
g_object_ref (query->current_source);
537
hud_query_refresh (query);
539
/* Tell DBus everything is going to be A-OK */
540
hud_query_iface_com_canonical_hud_query_complete_update_app(skel, invocation, 0);
545
/* Handle getting execute from DBus */
547
handle_execute (HudQueryIfaceComCanonicalHudQuery * skel, GDBusMethodInvocation * invocation, GVariant * command_id, guint timestamp, gpointer user_data)
549
g_return_val_if_fail(HUD_IS_QUERY(user_data), FALSE);
550
HudQuery * query = HUD_QUERY(user_data);
551
hud_watchdog_ping(query->watchdog);
554
GVariant * inner = g_variant_get_variant(command_id);
555
guint64 id = g_variant_get_uint64(inner);
556
g_variant_unref(inner);
558
HudItem * item = hud_item_lookup(id);
561
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Item specified by command key does not exist");
565
GVariantBuilder platform;
566
g_variant_builder_init(&platform, G_VARIANT_TYPE_DICTIONARY);
568
GVariantBuilder entry;
569
g_variant_builder_init(&entry, G_VARIANT_TYPE_DICT_ENTRY);
570
g_variant_builder_add_value(&entry, g_variant_new_string("desktop-startup-id"));
571
gchar * timestr = g_strdup_printf("_TIME%d", timestamp);
572
g_variant_builder_add_value(&entry, g_variant_new_variant(g_variant_new_string(timestr)));
575
g_variant_builder_add_value(&platform, g_variant_builder_end(&entry));
577
hud_item_activate(item, g_variant_builder_end(&platform));
579
hud_query_iface_com_canonical_hud_query_complete_execute_command(skel, invocation);
584
/* Handle getting parameterized from DBus */
586
handle_parameterized (HudQueryIfaceComCanonicalHudQuery * skel, GDBusMethodInvocation * invocation, GVariant * command_id, guint timestamp, gpointer user_data)
588
g_return_val_if_fail(HUD_IS_QUERY(user_data), FALSE);
589
HudQuery * query = HUD_QUERY(user_data);
590
hud_watchdog_ping(query->watchdog);
592
GVariant * inner = g_variant_get_variant(command_id);
593
guint64 id = g_variant_get_uint64(inner);
594
g_variant_unref(inner);
596
HudItem * item = hud_item_lookup(id);
599
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Item specified by command key does not exist");
603
if (!HUD_IS_MODEL_ITEM(item)) {
604
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Item specified by command is not a menu model item");
608
if (!hud_model_item_is_parameterized(HUD_MODEL_ITEM(item))) {
609
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Item specified by command does not have parameterized actions");
613
const gchar * base_action = NULL;
614
const gchar * action_path = NULL;
615
const gchar * model_path = NULL;
616
gint model_section = 0;
618
hud_model_item_activate_parameterized(HUD_MODEL_ITEM(item), timestamp, &base_action, &action_path, &model_path, &model_section);
620
if (base_action == NULL) {
621
/* This value can be NULL, but variants require an empty string */
625
if (base_action == NULL ||
626
action_path == NULL || !g_variant_is_object_path(action_path) ||
627
model_path == NULL || !g_variant_is_object_path(model_path)) {
628
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Values returned by the model item are invalid");
632
hud_query_iface_com_canonical_hud_query_complete_execute_parameterized (skel,
633
invocation, base_action, action_path, model_path, model_section);
638
handle_execute_toolbar (HudQueryIfaceComCanonicalHudQuery *object, GDBusMethodInvocation *invocation, const gchar *arg_item, guint arg_timestamp, gpointer user_data)
640
g_return_val_if_fail(HUD_IS_QUERY(user_data), FALSE);
641
HudQuery * query = HUD_QUERY(user_data);
642
hud_watchdog_ping(query->watchdog);
644
HudClientQueryToolbarItems item = hud_client_query_toolbar_items_get_value_from_nick(arg_item);
646
if (item != HUD_CLIENT_QUERY_TOOLBAR_QUIT) {
647
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "TODO");
651
HudSource * search_source = query->current_source;
652
if (search_source == NULL) {
653
search_source = hud_application_list_get_focused_app(query->app_list);
656
if (search_source == NULL) {
657
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No source currently in use");
661
GVariantBuilder platform;
662
g_variant_builder_init(&platform, G_VARIANT_TYPE_DICTIONARY);
664
GVariantBuilder entry;
665
g_variant_builder_init(&entry, G_VARIANT_TYPE_DICT_ENTRY);
666
g_variant_builder_add_value(&entry, g_variant_new_string("desktop-startup-id"));
667
gchar * timestr = g_strdup_printf("_TIME%d", arg_timestamp);
668
g_variant_builder_add_value(&entry, g_variant_new_variant(g_variant_new_string(timestr)));
671
g_variant_builder_add_value(&platform, g_variant_builder_end(&entry));
673
hud_source_activate_toolbar(search_source, item, g_variant_builder_end(&platform));
674
g_dbus_method_invocation_return_value(invocation, NULL);
678
/* Really this is just an unref, but let's put it in a nice function
679
so that it's easier to change later if we need to. */
681
hud_query_close (HudQuery * query)
683
g_return_if_fail(HUD_IS_QUERY(query));
684
g_object_unref(query);
688
/* Handle the DBus function CloseQuery */
690
handle_close_query (HudQueryIfaceComCanonicalHudQuery * skel, GDBusMethodInvocation * invocation, gpointer user_data)
692
g_return_val_if_fail(HUD_IS_QUERY(user_data), FALSE);
693
HudQuery * query = HUD_QUERY(user_data);
694
hud_watchdog_ping(query->watchdog);
696
/* Close the query */
697
hud_query_close(query);
699
/* NOTE: Don't use the query after this, it may not exist */
702
/* Tell DBus we're dying */
703
hud_query_iface_com_canonical_hud_query_complete_close_query(skel, invocation);
709
hud_query_init_real (HudQuery *query, GDBusConnection *connection, const guint querynumber)
711
GError *error = NULL;
713
query->querynumber = querynumber;
715
query->skel = hud_query_iface_com_canonical_hud_query_skeleton_new();
717
/* NOTE: Connect to the functions before putting on the bus. */
718
g_signal_connect(G_OBJECT(query->skel), "handle-update-query", G_CALLBACK(handle_update_query), query);
719
g_signal_connect(G_OBJECT(query->skel), "handle-update-app", G_CALLBACK(handle_update_app), query);
720
g_signal_connect(G_OBJECT(query->skel), "handle-voice-query", G_CALLBACK(handle_voice_query), query);
721
g_signal_connect(G_OBJECT(query->skel), "handle-close-query", G_CALLBACK(handle_close_query), query);
722
g_signal_connect(G_OBJECT(query->skel), "handle-execute-command", G_CALLBACK(handle_execute), query);
723
g_signal_connect(G_OBJECT(query->skel), "handle-execute-parameterized", G_CALLBACK(handle_parameterized), query);
724
g_signal_connect(G_OBJECT(query->skel), "handle-execute-toolbar", G_CALLBACK(handle_execute_toolbar), query);
726
query->object_path = g_strdup_printf("/com/canonical/hud/query%d", query->querynumber);
727
if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(query->skel),
732
g_warning ("%s %s\n", "g_dbus_interface_skeleton_export failed:", error->message);
736
GDBusInterfaceInfo* info = g_dbus_interface_skeleton_get_info (
737
G_DBUS_INTERFACE_SKELETON(query->skel) );
738
g_debug("Created interface skeleton: [%s] on [%s]", info->name, g_dbus_interface_skeleton_get_object_path(G_DBUS_INTERFACE_SKELETON(query->skel)));
740
query->results_name = g_strdup_printf("com.canonical.hud.query%d.results", query->querynumber);
741
query->results_model = dee_shared_model_new(query->results_name);
742
dee_model_set_schema_full(query->results_model, results_model_schema, G_N_ELEMENTS(results_model_schema));
743
query->results_tag = dee_model_register_tag(query->results_model, g_object_unref);
745
query->appstack_name = g_strdup_printf("com.canonical.hud.query%d.appstack", query->querynumber);
746
query->appstack_model = dee_shared_model_new(query->appstack_name);
747
dee_model_set_schema_full(query->appstack_model, appstack_model_schema, G_N_ELEMENTS(appstack_model_schema));
749
g_object_set(G_OBJECT(query->skel),
750
"appstack-model", query->appstack_name,
751
"results-model", query->results_name,
754
g_dbus_interface_skeleton_flush(G_DBUS_INTERFACE_SKELETON(query->skel));
757
query->voice = hud_voice_new(query->skel, NULL, &error);
760
g_warning ("%s %s\n", "Voice engine failed to initialize:", error->message);
166
766
hud_query_init (HudQuery *query)
201
801
* Returns: the new #HudQuery
204
hud_query_new (HudSource *source,
804
hud_query_new (HudSource *all_sources,
805
HudWatchdog *watchdog,
806
HudApplicationList *application_list,
205
807
const gchar *search_string,
809
GDBusConnection *connection,
810
const guint query_count)
210
814
g_debug ("Created query '%s'", search_string);
212
816
query = g_object_new (HUD_TYPE_QUERY, NULL);
213
query->source = g_object_ref (source);
214
query->results = g_ptr_array_new_with_free_func (g_object_unref);
817
hud_query_init_real(query, connection, query_count);
818
query->all_sources = g_object_ref (all_sources);
819
query->app_list = g_object_ref (application_list);
215
820
query->search_string = g_strdup (search_string);
216
query->token_list = hud_token_list_new_from_string (query->search_string);
821
query->token_list = NULL;
823
if (watchdog != NULL) {
824
query->watchdog = g_object_ref(watchdog);
827
if (query->search_string[0] != '\0') {
828
query->token_list = hud_token_list_new_from_string (query->search_string);
217
831
query->num_results = num_results;
219
hud_source_use (query->source);
221
833
hud_query_refresh (query);
223
g_signal_connect_object (source, "changed", G_CALLBACK (hud_query_source_changed), query, 0);
225
g_clear_object (&last_created_query);
226
last_created_query = g_object_ref (query);
835
g_signal_connect_object (all_sources, "changed", G_CALLBACK (hud_query_source_changed), query, 0);
232
* hud_query_get_query_key:
233
* @query: a #HudQuery
235
* Returns the query key for @HudQuery.
237
* Each #HudQuery has a unique identifying key that is assigned when the
240
* FIXME: This is a lie.
242
* Returns: (transfer none): the query key for @query
245
hud_query_get_query_key (HudQuery *query)
247
static GVariant *query_key;
249
if (query_key == NULL)
250
query_key = g_variant_ref_sink (g_variant_new_string ("query key"));
257
* @query_key: a query key
259
* Finds the query that has the given @query_key.
261
* Returns: (transfer none): the query, or %NULL if no such query exists
264
hud_query_lookup (GVariant *query_key)
266
return last_created_query;
271
* @query: a #HudQuery
273
* Closes a #HudQuery.
275
* This drops the query from the internal list of queries. Future use
276
* of hud_query_lookup() to find this query will fail.
278
* You must still release your own reference on @query, if you have one.
279
* This only drops the internal reference.
282
hud_query_close (HudQuery *query)
284
if (query == last_created_query)
285
g_clear_object (&last_created_query);
289
* hud_query_get_n_results:
290
* @query: a #HudQuery
292
* Gets the number of results in @query.
294
* Returns: the number of results
841
* hud_query_get_path:
842
* @query: a #HudQuery
844
* Gets the path that the query object is exported to DBus on.
846
* Return value: A dbus object path
849
hud_query_get_path (HudQuery *query)
851
g_return_val_if_fail(HUD_IS_QUERY(query), NULL);
853
return query->object_path;
857
* hud_query_get_results_name:
858
* @query: a #HudQuery
860
* Gets the DBus name that the shared results model is using
862
* Return value: A dbus name
865
hud_query_get_results_name (HudQuery *query)
867
g_return_val_if_fail(HUD_IS_QUERY(query), NULL);
869
return query->results_name;
873
* hud_query_get_appstack_name:
874
* @query: a #HudQuery
876
* Gets the DBus name that the appstack model is using
878
* Return value: A dbus name
881
hud_query_get_appstack_name (HudQuery * query)
883
g_return_val_if_fail(HUD_IS_QUERY(query), NULL);
885
return query->appstack_name;
889
hud_query_get_results_model(HudQuery *self)
891
g_return_val_if_fail(HUD_IS_QUERY(self), NULL);
893
return self->results_model;
898
hud_query_get_appstack_model(HudQuery *self)
900
g_return_val_if_fail(HUD_IS_QUERY(self), NULL);
902
return self->appstack_model;
907
hud_query_get_query (HudQuery * query)
909
g_return_val_if_fail(HUD_IS_QUERY(query), NULL);
911
return query->search_string;
297
hud_query_get_n_results (HudQuery *query)
915
hud_query_get_number (HudQuery * query)
299
return query->results->len;
917
g_return_val_if_fail(HUD_IS_QUERY(query), 0);
303
* hud_query_get_result_by_index:
304
* @query: a #HudQuery
305
* @i: the index of the result
307
* Gets the @i<!-- -->th result from @query.
309
* @i must be less than the number of results in the query. See
310
* hud_query_get_n_results().
312
* Returns: (transfer none): the #HudResult at position @i
315
hud_query_get_result_by_index (HudQuery *query,
318
return query->results->pdata[i];
919
return query->querynumber;