174
177
g_object_unref (file);
178
get_search_count (TrackerClient *client, const char *search)
180
GError *error = NULL;
183
dbus_g_proxy_call (client->proxy_search, "GetHitCount", &error, G_TYPE_STRING, "Videos",
184
G_TYPE_STRING, search,
185
G_TYPE_INVALID, G_TYPE_INT, &count, G_TYPE_INVALID);
180
static SearchResultsData *
181
search_results_new (TotemTrackerWidget *widget,
182
const gchar *search_text)
184
SearchResultsData *srd;
185
TrackerClient *client;
191
client = tracker_connect (TRUE, G_MAXINT);
196
srd = g_slice_new0 (SearchResultsData);
198
srd->widget = g_object_ref (widget);
199
srd->client = client;
200
srd->search_text = g_strdup (search_text);
206
search_results_free (SearchResultsData *srd)
213
g_object_unref (srd->widget);
217
tracker_disconnect (srd->client);
220
g_free (srd->search_text);
221
g_slice_free (SearchResultsData, srd);
225
search_results_cb (GPtrArray *results,
229
TotemTrackerWidgetPrivate *priv;
230
SearchResultsData *srd;
232
guint i, next_page, total_pages;
235
priv = srd->widget->priv;
237
gtk_widget_set_sensitive (priv->search_entry, TRUE);
188
g_warning ("%s", error->message);
189
g_error_free (error);
240
g_warning ("Error getting the search results for '%s': %s",
242
error->message ? error->message : "No reason");
244
gtk_label_set_text (GTK_LABEL (priv->status_label), _("Could not connect to Tracker"));
245
search_results_free (srd);
250
if (!results || results->len < 1) {
251
gtk_label_set_text (GTK_LABEL (priv->status_label), _("No results"));
252
search_results_free (srd);
257
for (i = 0; i < results->len; i++) {
260
details = g_ptr_array_index (results, i);
261
search_results_populate (srd->widget, details[0]);
264
next_page = (priv->current_result_page + 1) * TOTEM_TRACKER_MAX_RESULTS_SIZE;
265
total_pages = priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE + 1;
267
/* Set the new range on the page selector's adjustment and ensure the current page is correct */
268
gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->page_selector), 1, total_pages);
269
priv->current_result_page = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->page_selector)) - 1;
272
* This is used to show which items are listed in the list view, for example:
273
* Showing 10-20 of 128 matches
274
* This is similar to what web searches use, eg. Google on the top-right of their search results page show:
275
* Personalized Results 1 - 10 of about 4,130,000 for foobar */
276
str = g_strdup_printf (ngettext ("Showing %i - %i of %i match", "Showing %i - %i of %i matches", priv->total_result_count),
277
priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE,
278
next_page > priv->total_result_count ? priv->total_result_count : next_page,
279
priv->total_result_count);
280
gtk_label_set_text (GTK_LABEL (priv->status_label), str);
283
/* Enable or disable the pager buttons */
284
if (priv->current_result_page < priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE) {
285
gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
286
gtk_widget_set_sensitive (GTK_WIDGET (priv->next_button), TRUE);
289
if (priv->current_result_page > 0) {
290
gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
291
gtk_widget_set_sensitive (GTK_WIDGET (priv->previous_button), TRUE);
294
if (priv->current_result_page >= total_pages - 1) {
295
gtk_widget_set_sensitive (GTK_WIDGET (priv->next_button), FALSE);
298
g_signal_handlers_unblock_by_func (priv->page_selector, page_selector_value_changed_cb, srd->widget);
299
search_results_free (srd);
196
struct SearchResultsData {
197
TotemTrackerWidget *widget;
199
TrackerClient *client;
203
search_results_cb (char **result, GError *error, gpointer userdata)
303
get_fts_string (GStrv search_words,
304
gboolean use_or_operator)
205
struct SearchResultsData *data = (struct SearchResultsData*) userdata;
208
TotemTrackerWidgetPrivate *priv = data->widget->priv;
210
if (!error && result) {
211
for (i = 0; result [i] != NULL; i++)
212
populate_result (data->widget, result [i]);
214
next_page = (priv->current_result_page + 1) * TOTEM_TRACKER_MAX_RESULTS_SIZE;
216
/* Set the new range on the page selector's adjustment and ensure the current page is correct */
217
gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->page_selector), 1,
218
priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE + 1);
219
priv->current_result_page = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->page_selector)) - 1;
221
if (priv->total_result_count == 0) {
222
gtk_label_set_text (GTK_LABEL (priv->status_label), _("No results"));
225
* This is used to show which items are listed in the list view, for example:
226
* Showing 10-20 of 128 matches
227
* This is similar to what web searches use, eg. Google on the top-right of their search results page show:
228
* Personalized Results 1 - 10 of about 4,130,000 for foobar */
229
label = g_strdup_printf (ngettext ("Showing %i - %i of %i match", "Showing %i - %i of %i matches", priv->total_result_count),
230
priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE,
231
next_page > priv->total_result_count ? priv->total_result_count : next_page,
232
priv->total_result_count);
233
gtk_label_set_text (GTK_LABEL (priv->status_label), label);
237
/* Enable or disable the pager buttons */
238
if (priv->current_result_page < priv->total_result_count / TOTEM_TRACKER_MAX_RESULTS_SIZE) {
239
gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
240
gtk_widget_set_sensitive (GTK_WIDGET (priv->next_button), TRUE);
243
if (priv->current_result_page > 0) {
244
gtk_widget_set_sensitive (GTK_WIDGET (priv->page_selector), TRUE);
245
gtk_widget_set_sensitive (GTK_WIDGET (priv->previous_button), TRUE);
248
g_signal_handlers_unblock_by_func (priv->page_selector, page_selector_value_changed_cb, data->widget);
250
g_warning ("Error getting the search results for '%s': %s", data->search_text, error->message ? error->message : "No reason");
253
g_free (data->search_text);
254
tracker_disconnect (data->client);
313
fts = g_string_new ("");
314
len = g_strv_length (search_words);
316
for (i = 0; i < len; i++) {
317
g_string_append (fts, search_words[i]);
318
g_string_append_c (fts, '*');
321
if (use_or_operator) {
322
g_string_append (fts, " OR ");
324
g_string_append (fts, " ");
329
return g_string_free (fts, FALSE);
259
333
do_search (TotemTrackerWidget *widget)
261
TrackerClient *client;
262
struct SearchResultsData *data;
335
SearchResultsData *srd;
337
GError *error = NULL;
338
const gchar *search_text;
264
342
/* Clear the list store */
265
343
gtk_list_store_clear (GTK_LIST_STORE (widget->priv->result_store));
270
348
gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->next_button), FALSE);
272
350
/* Stop after clearing the list store if they're just emptying the search entry box */
273
if (strcmp (gtk_entry_get_text (GTK_ENTRY (widget->priv->search_entry)), "") == 0) {
274
gtk_label_set_text (GTK_LABEL (widget->priv->status_label), _("No results"));
351
search_text = gtk_entry_get_text (GTK_ENTRY (widget->priv->search_entry));
278
353
g_signal_handlers_block_by_func (widget->priv->page_selector, page_selector_value_changed_cb, widget);
280
355
/* Get the tracker client */
281
client = tracker_connect (TRUE);
283
g_warning ("Error trying to get the Tracker client.");
356
srd = search_results_new (widget, search_text);
358
gtk_label_set_text (GTK_LABEL (widget->priv->status_label), _("Could not connect to Tracker"));
287
data = g_new0 (struct SearchResultsData, 1);
288
data->widget = widget;
289
data->client = client;
292
data->search_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget->priv->search_entry)));
294
widget->priv->total_result_count = get_search_count (client, data->search_text);
296
tracker_search_text_async (data->client, -1, SERVICE_VIDEOS, data->search_text,
297
widget->priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE,
298
TOTEM_TRACKER_MAX_RESULTS_SIZE,
299
search_results_cb, data);
362
offset = widget->priv->current_result_page * TOTEM_TRACKER_MAX_RESULTS_SIZE;
364
if (search_text && search_text[0] != '\0') {
367
strv = g_strsplit (search_text, " ", -1);
368
fts = get_fts_string (strv, FALSE);
374
/* NOTE: We use FILTERS here for the type because we may want
375
* to show more items than just videos in the future - like
376
* music or some other specialised content.
379
query = g_strdup_printf ("SELECT COUNT(?urn) AS items "
382
" ?urn fts:match \"%s\" "
383
" FILTER (?type = nmm:Video) "
387
query = g_strdup_printf ("SELECT COUNT(?urn) AS items "
390
" FILTER (?type = nmm:Video) "
394
results = tracker_resources_sparql_query (srd->client, query, &error);
397
if (results && results->pdata && results->pdata[0]) {
400
count = g_ptr_array_index (results, 0);
401
widget->priv->total_result_count = atoi (count[0]);
403
widget->priv->total_result_count = 0;
405
g_warning ("Could not get count for videos available, %s",
406
error ? error->message : "no error given");
407
g_clear_error (&error);
411
query = g_strdup_printf ("SELECT ?urn "
414
" ?urn fts:match \"%s\" "
415
" FILTER (?type = nmm:Video) "
417
"ORDER BY ASC(?urn) "
422
TOTEM_TRACKER_MAX_RESULTS_SIZE);
424
query = g_strdup_printf ("SELECT ?urn "
427
" FILTER (?type = nmm:Video) "
429
"ORDER BY ASC(?urn) "
433
TOTEM_TRACKER_MAX_RESULTS_SIZE);
438
gtk_widget_set_sensitive (widget->priv->search_entry, FALSE);
440
/* Cookie is used for cancelling */
441
srd->cookie = tracker_resources_sparql_query_async (srd->client,
398
556
gtk_scrolled_window_add_with_viewport (scroll, GTK_WIDGET (widget->priv->result_list));
399
557
gtk_container_add (GTK_CONTAINER (v_box), GTK_WIDGET (scroll));
560
widget->priv->status_label = gtk_label_new ("");
561
gtk_misc_set_alignment (GTK_MISC (widget->priv->status_label), 0.0, 0.5);
562
gtk_box_pack_start (GTK_BOX (v_box), widget->priv->status_label, FALSE, TRUE, 2);
401
564
/* Initialise the pager box */
402
pager_box = gtk_hbox_new (FALSE, 2);
565
pager_box = gtk_hbox_new (FALSE, 6);
403
566
widget->priv->next_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
404
567
widget->priv->previous_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
405
568
adjust = GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 1, 1, 5, 0));
406
569
widget->priv->page_selector = gtk_spin_button_new (adjust, 1, 0);
407
gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->previous_button, FALSE, FALSE, 2);
408
gtk_box_pack_start (GTK_BOX (pager_box), gtk_label_new (_("Page")), FALSE, FALSE, 2);
409
gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->page_selector, TRUE, TRUE, 2);
410
gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->next_button, FALSE, FALSE, 2);
411
gtk_box_pack_start (GTK_BOX (v_box), pager_box, FALSE, FALSE, 2);
570
gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->previous_button, TRUE, TRUE, 0);
571
gtk_box_pack_start (GTK_BOX (pager_box), gtk_label_new (_("Page")), TRUE, TRUE, 0);
572
gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->page_selector, TRUE, TRUE, 0);
573
gtk_box_pack_start (GTK_BOX (pager_box), widget->priv->next_button, TRUE, TRUE, 0);
574
gtk_box_pack_start (GTK_BOX (v_box), pager_box, FALSE, TRUE, 0);
413
576
gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->previous_button), FALSE);
414
577
gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->page_selector), FALSE);
415
578
gtk_widget_set_sensitive (GTK_WIDGET (widget->priv->next_button), FALSE);
418
widget->priv->status_label = gtk_label_new ("");
419
gtk_box_pack_start (GTK_BOX (v_box), widget->priv->status_label, FALSE, FALSE, 2);
421
580
/* Add the main container to the widget */
422
581
gtk_container_add (GTK_CONTAINER (widget), v_box);
424
583
gtk_widget_show_all (GTK_WIDGET (widget));
426
585
/* Connect the search button clicked signal and the search entry */
586
g_signal_connect (widget->priv->search_entry, "changed",
587
G_CALLBACK (search_entry_changed_cb), widget);
427
588
g_signal_connect (widget->priv->search_button, "clicked",
428
589
G_CALLBACK (new_search), widget);
429
590
g_signal_connect (widget->priv->search_entry, "activate",