Commit 604fb12f authored by Rouquier Philippe's avatar Rouquier Philippe Committed by ykw

Add tracker as a backend for search

parent c50dbba7
......@@ -344,6 +344,7 @@ dnl AM_CONDITIONAL(HAVE_LIBNOTIFY, test x"$build_libnotify" = "xyes")
dnl ****************check for search (optional)**************
BEAGLE_REQUIRED=0.3.0
TRACKER_REQUIRED=0.7.0
AC_ARG_ENABLE(search,
AS_HELP_STRING([--enable-search],[Build search pane (if a search backend is available) [[default=yes]]]),
......@@ -351,18 +352,36 @@ AC_ARG_ENABLE(search,
[enable_search="yes"])
if test x"$enable_search" = "xyes"; then
PKG_CHECK_MODULES(BRASERO_SEARCH, libbeagle-1.0 >= $BEAGLE_REQUIRED, build_search=yes, build_search=no)
PKG_CHECK_MODULES(BRASERO_SEARCH, tracker-client-0.7 >= $TRACKER_REQUIRED, build_search=yes, build_search=no)
if test x"$build_search" = "xyes"; then
AC_DEFINE(BUILD_SEARCH, 1, [define if you want to use search pane])
AC_DEFINE(BUILD_TRACKER, 1, [define if you want to use search pane])
AC_SUBST(BRASERO_SEARCH_CFLAGS)
AC_SUBST(BRASERO_SEARCH_LIBS)
build_beagle="no"
build_tracker="yes"
else
PKG_CHECK_MODULES(BRASERO_SEARCH, libbeagle-1.0 >= $BEAGLE_REQUIRED, build_search=yes, build_search=no)
if test x"$build_search" = "xyes"; then
AC_DEFINE(BUILD_SEARCH, 1, [define if you want to use search pane])
AC_DEFINE(BUILD_BEAGLE, 1, [define if you want to use search pane])
AC_SUBST(BRASERO_SEARCH_CFLAGS)
AC_SUBST(BRASERO_SEARCH_LIBS)
build_beagle="yes"
build_tracker="no"
fi
fi
else
build_search="no"
fi
AM_CONDITIONAL(BUILD_SEARCH, test x"$build_search" = "xyes")
AM_CONDITIONAL(BUILD_BEAGLE, test x"$build_beagle" = "xyes")
AM_CONDITIONAL(BUILD_TRACKER, test x"$build_tracker" = "xyes")
dnl ****************check for playlist (optional)**************
TOTEM_REQUIRED=2.22.0
......
......@@ -128,16 +128,27 @@ brasero_SOURCES += \
endif
if BUILD_TRACKER
brasero_SOURCES += \
brasero-search-tracker.h \
brasero-search-tracker.c
endif
if BUILD_BEAGLE
brasero_SOURCES += \
brasero-search-beagle.h \
brasero-search-beagle.c
endif
if BUILD_SEARCH
brasero_SOURCES += \
brasero-mime-filter.c \
brasero-mime-filter.h \
brasero-search-entry.c \
brasero-search-entry.h \
brasero-search.h \
brasero-search.c \
brasero-search-beagle.h \
brasero-search-beagle.c
brasero-search.c
endif
brasero_LDADD = \
......
......@@ -44,7 +44,7 @@ struct _BraseroSearchBeaglePrivate
BeagleClient *client;
BeagleQuery *query;
GSList * hits;
GSList *hits;
};
#define BRASERO_SEARCH_BEAGLE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_SEARCH_BEAGLE, BraseroSearchBeaglePrivate))
......@@ -86,31 +86,6 @@ brasero_search_beagle_uri_from_hit (BraseroSearchEngine *engine,
return beagle_hit_get_uri (BEAGLE_HIT (hit));
}
static gchar *
brasero_search_beagle_name_from_hit (BraseroSearchEngine *engine,
gpointer hit)
{
gchar *name;
const gchar *uri;
gchar *unescaped_uri;
uri = beagle_hit_get_uri (BEAGLE_HIT (hit));
/* beagle return badly formed uri not
* encoded in UTF-8 locale charset so we
* check them just in case */
unescaped_uri = g_uri_unescape_string (uri, NULL);
if (!g_utf8_validate (unescaped_uri, -1, NULL)) {
g_free (unescaped_uri);
return NULL;
}
name = g_path_get_basename (unescaped_uri);
g_free (unescaped_uri);
return name;
}
static const gchar *
brasero_search_beagle_mime_from_hit (BraseroSearchEngine *engine,
gpointer hit)
......@@ -118,19 +93,6 @@ brasero_search_beagle_mime_from_hit (BraseroSearchEngine *engine,
return beagle_hit_get_mime_type (BEAGLE_HIT (hit));
}
static const gchar *
brasero_search_beagle_description_from_hit (BraseroSearchEngine *engine,
gpointer hit)
{
const gchar *mime;
mime = beagle_hit_get_mime_type (BEAGLE_HIT (hit));
if (!mime)
return NULL;
return g_content_type_get_description (mime);
}
static int
brasero_search_beagle_score_from_hit (BraseroSearchEngine *engine,
gpointer hit)
......@@ -138,22 +100,6 @@ brasero_search_beagle_score_from_hit (BraseroSearchEngine *engine,
return (int) (beagle_hit_get_score (BEAGLE_HIT (hit)) * 100);
}
static GIcon *
brasero_search_beagle_icon_from_hit (BraseroSearchEngine *engine,
gpointer hit)
{
const gchar *mime;
mime = beagle_hit_get_mime_type (BEAGLE_HIT (hit));
if (!mime)
return NULL;
if (!strcmp (mime, "inode/directory"))
mime = "x-directory/normal";
return g_content_type_get_icon (mime);
}
static gboolean
brasero_search_beagle_add_hit_to_tree (BraseroSearchEngine *search,
GtkTreeModel *model,
......@@ -326,7 +272,7 @@ brasero_search_beagle_clean (BraseroSearchBeagle *beagle)
static gboolean
brasero_search_beagle_query_new (BraseroSearchEngine *search,
const gchar *keywords)
const gchar *keywords)
{
BraseroSearchBeaglePrivate *priv;
BeagleQueryPartHuman *text;
......@@ -459,11 +405,8 @@ brasero_search_beagle_init_engine (BraseroSearchEngineIface *iface)
{
iface->is_available = brasero_search_beagle_is_available;
iface->uri_from_hit = brasero_search_beagle_uri_from_hit;
iface->name_from_hit = brasero_search_beagle_name_from_hit;
iface->icon_from_hit = brasero_search_beagle_icon_from_hit;
iface->score_from_hit = brasero_search_beagle_score_from_hit;
iface->mime_from_hit = brasero_search_beagle_mime_from_hit;
iface->description_from_hit = brasero_search_beagle_description_from_hit;
iface->query_new = brasero_search_beagle_query_new;
iface->query_set_scope = brasero_search_beagle_query_set_scope;
iface->query_set_mime = brasero_search_beagle_set_query_mime;
......
......@@ -131,42 +131,6 @@ brasero_search_engine_add_hits (BraseroSearchEngine *search,
return iface->add_hits (search, model, range_start, range_end);
}
GIcon *
brasero_search_engine_icon_from_hit (BraseroSearchEngine *search,
gpointer hit)
{
BraseroSearchEngineIface *iface;
g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
if (!hit)
return NULL;
iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
if (!iface->icon_from_hit)
return FALSE;
return (* iface->icon_from_hit) (search, hit);
}
gchar *
brasero_search_engine_name_from_hit (BraseroSearchEngine *search,
gpointer hit)
{
BraseroSearchEngineIface *iface;
g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
if (!hit)
return NULL;
iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
if (!iface->name_from_hit)
return FALSE;
return (* iface->name_from_hit) (search, hit);
}
const gchar *
brasero_search_engine_uri_from_hit (BraseroSearchEngine *search,
gpointer hit)
......@@ -203,24 +167,6 @@ brasero_search_engine_mime_from_hit (BraseroSearchEngine *search,
return (* iface->mime_from_hit) (search, hit);
}
const gchar *
brasero_search_engine_description_from_hit (BraseroSearchEngine *search,
gpointer hit)
{
BraseroSearchEngineIface *iface;
g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
if (!hit)
return NULL;
iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
if (!iface->description_from_hit)
return FALSE;
return (* iface->description_from_hit) (search, hit);
}
gint
brasero_search_engine_score_from_hit (BraseroSearchEngine *search,
gpointer hit)
......@@ -335,9 +281,10 @@ brasero_search_engine_base_init (gpointer g_class)
G_STRUCT_OFFSET (BraseroSearchEngineIface, search_error),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
0);
1,
G_TYPE_POINTER);
brasero_search_engine_signals [SEARCH_FINISHED] =
g_signal_new ("search_finished",
BRASERO_TYPE_SEARCH_ENGINE,
......@@ -375,9 +322,21 @@ brasero_search_engine_base_init (gpointer g_class)
#ifdef BUILD_SEARCH
#include "brasero-search-beagle.h"
#ifdef BUILD_TRACKER
#include "brasero-search-tracker.h"
BraseroSearchEngine *
brasero_search_engine_new_default (void)
{
return g_object_new (BRASERO_TYPE_SEARCH_TRACKER, NULL);
}
#endif
BraseroSearchEngine *search_engine = NULL;
#ifdef BUILD_BEAGLE
#include "brasero-search-beagle.h"
BraseroSearchEngine *
brasero_search_engine_new_default (void)
......@@ -385,6 +344,8 @@ brasero_search_engine_new_default (void)
return g_object_new (BRASERO_TYPE_SEARCH_BEAGLE, NULL);
}
#endif
#else
BraseroSearchEngine *
......
......@@ -55,42 +55,37 @@ struct _BraseroSearchEngineIface {
GTypeInterface g_iface;
/* <Signals> */
void (*search_error) (BraseroSearchEngine *search);
void (*search_error) (BraseroSearchEngine *search,
GError *error);
void (*search_finished) (BraseroSearchEngine *search);
void (*hit_removed) (BraseroSearchEngine *search,
gpointer hit);
void (*hit_removed) (BraseroSearchEngine *search,
gpointer hit);
void (*hit_added) (BraseroSearchEngine *search,
gpointer hit);
gpointer hit);
/* <Virtual functions> */
gboolean (*is_available) (BraseroSearchEngine *search);
gboolean (*query_new) (BraseroSearchEngine *search,
const gchar *keywords);
gboolean (*query_set_scope) (BraseroSearchEngine *search,
BraseroSearchScope scope);
const gchar *keywords);
gboolean (*query_set_scope) (BraseroSearchEngine *search,
BraseroSearchScope scope);
gboolean (*query_set_mime) (BraseroSearchEngine *search,
const gchar **mimes);
gboolean (*query_start) (BraseroSearchEngine *search);
const gchar **mimes);
gboolean (*query_start) (BraseroSearchEngine *search);
gboolean (*add_hits) (BraseroSearchEngine *search,
GtkTreeModel *model,
gint range_start,
gint range_end);
GtkTreeModel *model,
gint range_start,
gint range_end);
gint (*num_hits) (BraseroSearchEngine *engine);
gint (*num_hits) (BraseroSearchEngine *engine);
const gchar* (*uri_from_hit) (BraseroSearchEngine *engine,
gpointer hit);
gchar* (*name_from_hit) (BraseroSearchEngine *engine,
gpointer hit);
GIcon* (*icon_from_hit) (BraseroSearchEngine *engine,
const gchar* (*uri_from_hit) (BraseroSearchEngine *engine,
gpointer hit);
gint (*score_from_hit) (BraseroSearchEngine *engine,
gpointer hit);
const gchar * (*mime_from_hit) (BraseroSearchEngine *engine,
gpointer hit);
const gchar * (*description_from_hit) (BraseroSearchEngine *engine,
gpointer hit);
gpointer hit);
gint (*score_from_hit) (BraseroSearchEngine *engine,
gpointer hit);
};
GType brasero_search_engine_get_type (void);
......@@ -133,21 +128,12 @@ void
brasero_search_engine_hit_added (BraseroSearchEngine *search,
gpointer hit);
GIcon *
brasero_search_engine_icon_from_hit (BraseroSearchEngine *search,
gpointer hit);
gchar *
brasero_search_engine_name_from_hit (BraseroSearchEngine *search,
gpointer hit);
const gchar *
brasero_search_engine_uri_from_hit (BraseroSearchEngine *search,
gpointer hit);
const gchar *
brasero_search_engine_mime_from_hit (BraseroSearchEngine *search,
gpointer hit);
const gchar *
brasero_search_engine_description_from_hit (BraseroSearchEngine *search,
gpointer hit);
gint
brasero_search_engine_score_from_hit (BraseroSearchEngine *search,
gpointer hit);
......
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
* brasero
* Copyright (C) Rouquier Philippe 2009 <bonfire-app@wanadoo.fr>
*
* brasero is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* brasero is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <libtracker-client/tracker.h>
#include "brasero-search-tracker.h"
#include "brasero-search-engine.h"
typedef struct _BraseroSearchTrackerPrivate BraseroSearchTrackerPrivate;
struct _BraseroSearchTrackerPrivate
{
TrackerClient *client;
GPtrArray *results;
BraseroSearchScope scope;
gchar **mimes;
gchar *keywords;
};
#define BRASERO_SEARCH_TRACKER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_SEARCH_TRACKER, BraseroSearchTrackerPrivate))
static void brasero_search_tracker_init_engine (BraseroSearchEngineIface *iface);
G_DEFINE_TYPE_WITH_CODE (BraseroSearchTracker,
brasero_search_tracker,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (BRASERO_TYPE_SEARCH_ENGINE,
brasero_search_tracker_init_engine));
static gboolean
brasero_search_tracker_is_available (BraseroSearchEngine *engine)
{
BraseroSearchTrackerPrivate *priv;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (engine);
if (priv->client)
return TRUE;
priv->client = tracker_connect (TRUE, 30000);
return (priv->client != NULL);
}
static gint
brasero_search_tracker_num_hits (BraseroSearchEngine *engine)
{
BraseroSearchTrackerPrivate *priv;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (engine);
if (!priv->results)
return 0;
return priv->results->len;
}
static gboolean
brasero_search_tracker_add_hit_to_tree (BraseroSearchEngine *search,
GtkTreeModel *model,
gint range_start,
gint range_end)
{
BraseroSearchTrackerPrivate *priv;
gint i;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (search);
if (!priv->results)
return FALSE;
for (i = range_start; g_ptr_array_index (priv->results, i) && i < range_end; i ++) {
gchar **hit;
GtkTreeIter row;
hit = g_ptr_array_index (priv->results, i);
gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &row, -1,
BRASERO_SEARCH_TREE_HIT_COL, hit,
-1);
}
return TRUE;
}
static const gchar *
brasero_search_tracker_uri_from_hit (BraseroSearchEngine *engine,
gpointer hit)
{
gchar **tracker_hit;
tracker_hit = hit;
if (!tracker_hit)
return NULL;
if (g_strv_length (tracker_hit) >= 1)
return tracker_hit [0];
return NULL;
}
static const gchar *
brasero_search_tracker_mime_from_hit (BraseroSearchEngine *engine,
gpointer hit)
{
gchar **tracker_hit;
tracker_hit = hit;
if (!tracker_hit)
return NULL;
if (g_strv_length (tracker_hit) >= 2)
return tracker_hit [1];
return NULL;
}
static int
brasero_search_tracker_score_from_hit (BraseroSearchEngine *engine,
gpointer hit)
{
gchar **tracker_hit;
tracker_hit = hit;
if (!tracker_hit)
return 0;
if (g_strv_length (tracker_hit) >= 3)
return (int) strtof (tracker_hit [2], NULL);
return 0;
}
static void
brasero_search_tracker_reply (GPtrArray *results,
GError *error,
gpointer user_data)
{
BraseroSearchEngine *search = BRASERO_SEARCH_ENGINE (user_data);
BraseroSearchTrackerPrivate *priv;
int i;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (search);
if (error) {
brasero_search_engine_query_error (search, error);
return;
}
if (!results) {
brasero_search_engine_query_finished (search);
return;
}
priv->results = results;
for (i = 0; i < results->len; i ++)
brasero_search_engine_hit_added (search, g_ptr_array_index (results, i));
brasero_search_engine_query_finished (search);
}
static gboolean
brasero_search_tracker_query_start (BraseroSearchEngine *search)
{
BraseroSearchTrackerPrivate *priv;
gboolean res = FALSE;
GString *query = NULL;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (search);
if (!priv->mimes && !priv->scope) {
if (!priv->keywords)
return FALSE;
query = g_string_new ("SELECT ?file ?mime " /* Which variables should be returned */
"WHERE {" /* Start defining the search and its scope */
" ?file a nfo:FileDataObject . "); /* File must be a file (not a stream, ...) */
g_string_append_printf(query,
" ?file fts:match \"%s\" . " /* File must match keywords */
"OPTIONAL { ?file nie:mimeType ?mime } " /* Get its mime */
"} "
"ORDER BY ASC(?file) "
"OFFSET 0 "
"LIMIT 10000",
priv->keywords);
}
else if (priv->mimes) {
int i;
query = g_string_new ("SELECT ?file ?mime " /* Which variables should be returned */
"WHERE {" /* Start defining the search and its scope */
" ?file a nfo:FileDataObject . "); /* File must be a file (not a stream, ...) */
if (priv->keywords)
g_string_append_printf (query,
" ?file fts:match \"%s\" . ", /* File must match possible keywords */
priv->keywords);
g_string_append (query,
" ?file nie:mimeType ?mime " /* Get its mime */
" FILTER ( ");
for (i = 0; priv->mimes [i]; i ++) { /* And filter files according to their mime type */
if (i > 0)
g_string_append (query, " || ");
g_string_append_printf (query,
"?mime = \"%s\"",
priv->mimes [i]);
}
g_string_append (query, /* Finish the query */
") } "
"ORDER BY ASC(?file) "
"OFFSET 0 "
"LIMIT 10000");
}
else if (priv->scope) {
gboolean param_added = FALSE;
query = g_string_new ("SELECT ?file ?mime fts:rank(?file) "
"WHERE { "
" ?file a nfo:FileDataObject . "
" ?file a ?type . "
" FILTER ( ");
if (priv->scope & BRASERO_SEARCH_SCOPE_MUSIC) {
query = g_string_append (query, "?type = nmm:MusicPiece");
param_added = TRUE;
}
if (priv->scope & BRASERO_SEARCH_SCOPE_VIDEO) {
if (param_added)
g_string_append (query, " || ");
query = g_string_append (query, "?type = nfo:Video");
param_added = TRUE;
}
if (priv->scope & BRASERO_SEARCH_SCOPE_PICTURES) {
if (param_added)
g_string_append (query, " || ");
query = g_string_append (query, "?type = nfo:Image");
param_added = TRUE;
}
if (priv->scope & BRASERO_SEARCH_SCOPE_DOCUMENTS) {
if (param_added)
g_string_append (query, " || ");
query = g_string_append (query, "?type = nfo:Document");
}
g_string_append (query,
" ) ");
if (priv->keywords)
g_string_append_printf (query,
" ?file fts:match \"%s\" ",
priv->keywords);
g_string_append (query,
"OPTIONAL { ?file nie:mimeType ?mime } "
"} "
"ORDER BY ASC(fts:rank(?file)) "
"OFFSET 0 "
"LIMIT 10000");
}
if (!query)
return FALSE;
res = tracker_resources_sparql_query_async (priv->client,
query->str,
brasero_search_tracker_reply,
search);
g_string_free (query, TRUE);
return res;
}
static gboolean
brasero_search_tracker_query_set_scope (BraseroSearchEngine *search,
BraseroSearchScope scope)
{
BraseroSearchTrackerPrivate *priv;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (search);
priv->scope = scope;
return TRUE;
}
static gboolean
brasero_search_tracker_set_query_mime (BraseroSearchEngine *search,
const gchar **mimes)
{
BraseroSearchTrackerPrivate *priv;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (search);
if (priv->mimes) {
g_strfreev (priv->mimes);
priv->mimes = NULL;
}
priv->mimes = g_strdupv ((gchar **) mimes);
return TRUE;
}
static void
brasero_search_tracker_clean (BraseroSearchTracker *search)
{
BraseroSearchTrackerPrivate *priv;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (search);
if (priv->results) {
g_ptr_array_foreach (priv->results, (GFunc) g_free, NULL);
g_ptr_array_free (priv->results, TRUE);
priv->results = NULL;
}
if (priv->keywords) {
g_free (priv->keywords);
priv->keywords = NULL;
}
if (priv->mimes) {
g_strfreev (priv->mimes);
priv->mimes = NULL;
}
}
static gboolean
brasero_search_tracker_query_new (BraseroSearchEngine *search,
const gchar *keywords)
{
BraseroSearchTrackerPrivate *priv;
priv = BRASERO_SEARCH_TRACKER_PRIVATE (search);
brasero_search_tracker_clean (BRASERO_SEARCH_TRACKER (search));
priv->keywords = g_strdup (keywords);
return TRUE;
}
static void
brasero_search_tracker_init_engine (BraseroSearchEngineIface *iface)
{
iface->is_available = brasero_search_tracker_is_available;
iface->query_new = brasero_search_tracker_query_new;
iface->query_set_mime = brasero_search_tracker_set_query_mime;
iface->query_set_scope = brasero_search_tracker_query_set_scope;
iface->query_start = brasero_search_tracker_query_start;