+static GDBusConnection *
+get_connection (void)
+{
+ GDBusConnection *connection;
+ GError *error = NULL;
+ GVariant *reply;
+
+ /* Normally I hate sync calls with UIs, but we need to return NULL
+ * or a GtkSearchEngine as a result of this function.
+ */
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+
+ if (error)
+ {
+ g_debug ("Couldn't connect to D-Bus session bus, %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ /* If connection is set, we know it worked. */
+ g_debug ("Finding out if Tracker is available via D-Bus...");
+
+ /* We only wait 1 second max, we expect it to be very fast. If we
+ * don't get a response by then, clearly we're replaying a journal
+ * or cleaning up the DB internally. Either way, services is not
+ * available.
+ *
+ * We use the sync call here because we don't expect to be waiting
+ * long enough to block UI painting.
+ */
+ reply = g_dbus_connection_call_sync (connection,
+ DBUS_SERVICE_STATUS,
+ DBUS_PATH_STATUS,
+ DBUS_INTERFACE_STATUS,
+ "Wait",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ WAIT_TIMEOUT_SECONDS * 1000,
+ NULL,
+ &error);
+
+ if (error)
+ {
+ g_debug ("Tracker is not available, %s", error->message);
+ g_error_free (error);
+ g_object_unref (connection);
+ return NULL;
+ }
+
+ g_variant_unref (reply);
+
+ g_debug ("Tracker is ready");
+
+ return connection;
+}
+
+static void
+get_query_results (GtkSearchEngineTracker *engine,
+ const gchar *sparql,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_connection_call (engine->priv->connection,
+ DBUS_SERVICE_RESOURCES,
+ DBUS_PATH_RESOURCES,
+ DBUS_INTERFACE_RESOURCES,
+ "SparqlQuery",
+ g_variant_new ("(s)", sparql),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ QUERY_TIMEOUT_SECONDS * 1000,
+ engine->priv->cancellable,
+ callback,
+ user_data);
+}
+
+/* Stolen from libtracker-common */
+static GList *
+string_list_to_gslist (gchar **strv)
+{
+ GList *list;
+ gsize i;
+
+ list = NULL;
+
+ for (i = 0; strv[i]; i++)
+ list = g_list_prepend (list, g_strdup (strv[i]));
+
+ return g_list_reverse (list);
+}
+
+/* Stolen from libtracker-sparql */
+static gchar *
+sparql_escape_string (const gchar *literal)
+{
+ GString *str;
+ const gchar *p;
+
+ g_return_val_if_fail (literal != NULL, NULL);
+
+ str = g_string_new ("");
+ p = literal;
+
+ while (TRUE)
+ {
+ gsize len;
+
+ if (!((*p) != '\0'))
+ break;
+
+ len = strcspn ((const gchar *) p, "\t\n\r\b\f\"\\");
+ g_string_append_len (str, (const gchar *) p, (gssize) ((glong) len));
+ p = p + len;
+
+ switch (*p)
+ {
+ case '\t':
+ g_string_append (str, "\\t");
+ break;
+ case '\n':
+ g_string_append (str, "\\n");
+ break;
+ case '\r':
+ g_string_append (str, "\\r");
+ break;
+ case '\b':
+ g_string_append (str, "\\b");
+ break;
+ case '\f':
+ g_string_append (str, "\\f");
+ break;
+ case '"':
+ g_string_append (str, "\\\"");
+ break;
+ case '\\':
+ g_string_append (str, "\\\\");
+ break;
+ default:
+ continue;
+ }
+
+ p++;
+ }
+ return g_string_free (str, FALSE);
+ }
+
+static void
+sparql_append_string_literal (GString *sparql,
+ const gchar *str)
+{
+ gchar *s;
+
+ s = sparql_escape_string (str);
+
+ g_string_append_c (sparql, '"');
+ g_string_append (sparql, s);
+ g_string_append_c (sparql, '"');
+
+ g_free (s);
+}
+
+static void
+sparql_append_string_literal_lower_case (GString *sparql,
+ const gchar *str)
+{
+ gchar *s;
+
+ s = g_utf8_strdown (str, -1);
+ sparql_append_string_literal (sparql, s);
+ g_free (s);
+}