Ejemplo n.º 1
0
static gboolean
photos_search_provider_get_initial_result_set (PhotosSearchProvider *self,
                                               GDBusMethodInvocation *invocation,
                                               const gchar *const *terms)
{
  GApplication *app;
  PhotosFetchIdsJob *job;

  app = g_application_get_default ();
  g_application_hold (app);

  g_cancellable_cancel (self->cancellable);
  g_cancellable_reset (self->cancellable);

  job = photos_fetch_ids_job_new (terms);
  photos_fetch_ids_job_run (job,
                            self->state,
                            self->cancellable,
                            photos_search_provider_fetch_ids_executed,
                            g_object_ref (invocation));
  g_object_unref (job);

  return TRUE;
}
static void
photos_tracker_controller_perform_current_query (PhotosTrackerController *self)
{
  PhotosTrackerControllerPrivate *priv = self->priv;

  if (priv->current_query != NULL)
    photos_query_free (priv->current_query);

  priv->current_query = PHOTOS_TRACKER_CONTROLLER_GET_CLASS (self)->get_query (self);
  g_cancellable_reset (priv->cancellable);

  if (G_UNLIKELY (priv->queue == NULL))
    {
      photos_tracker_controller_query_error (self, priv->queue_error);
      return;
    }

  photos_tracker_queue_select (priv->queue,
                               priv->current_query->sparql,
                               priv->cancellable,
                               photos_tracker_controller_query_executed,
                               g_object_ref (self),
                               g_object_unref);
}
static gpointer
rejilla_async_task_manager_thread (RejillaAsyncTaskManager *self)
{
	gboolean result;
	GCancellable *cancel;
	RejillaAsyncTaskCtx *ctx;

	cancel = g_cancellable_new ();

	g_mutex_lock (self->priv->lock);

	while (1) {
		RejillaAsyncTaskResult res;

		/* say we are unused */
		self->priv->unused_threads ++;
	
		/* see if a task is waiting to be executed */
		while (!self->priv->waiting_tasks) {
			if (self->priv->cancelled)
				goto end;

			/* we always keep one thread ready */
			if (self->priv->num_threads - self->priv->unused_threads > 0) {
				GTimeVal timeout;

				/* wait to be woken up for 10 sec otherwise quit */
				g_get_current_time (&timeout);
				g_time_val_add (&timeout, 5000000);
				result = g_cond_timed_wait (self->priv->new_task,
							    self->priv->lock,
							    &timeout);

				if (!result)
					goto end;
			}
			else
				g_cond_wait (self->priv->new_task,
					     self->priv->lock);
		}
	
		/* say that we are active again */
		self->priv->unused_threads --;
	
		/* get the data from the list */
		ctx = self->priv->waiting_tasks->data;
		ctx->cancel = cancel;
		ctx->priority &= ~REJILLA_ASYNC_RESCHEDULE;

		self->priv->waiting_tasks = g_slist_remove (self->priv->waiting_tasks, ctx);
		self->priv->active_tasks = g_slist_prepend (self->priv->active_tasks, ctx);
	
		g_mutex_unlock (self->priv->lock);
		res = ctx->type->thread (self, cancel, ctx->data);
		g_mutex_lock (self->priv->lock);

		/* we remove the task from the list and signal it is finished */
		self->priv->active_tasks = g_slist_remove (self->priv->active_tasks, ctx);
		g_cond_signal (self->priv->task_finished);

		/* NOTE: when threads are cancelled then they are destroyed in
		 * the function that cancelled them to destroy callback_data in
		 * the active main loop */
		if (!g_cancellable_is_cancelled (cancel)) {
			if (res == REJILLA_ASYNC_TASK_RESCHEDULE) {
				if (self->priv->waiting_tasks) {
					RejillaAsyncTaskCtx *next;

					next = self->priv->waiting_tasks->data;
					if (next->priority > ctx->priority)
						rejilla_async_task_manager_insert_task (self, ctx);
					else
						self->priv->waiting_tasks = g_slist_prepend (self->priv->waiting_tasks, ctx);
				}
				else
					self->priv->waiting_tasks = g_slist_prepend (self->priv->waiting_tasks, ctx);
			}
			else {
				if (ctx->type->destroy)
					ctx->type->destroy (self, FALSE, ctx->data);
				g_free (ctx);
			}
		}
		else
			g_cancellable_reset (cancel);
	}

end:

	self->priv->unused_threads --;
	self->priv->num_threads --;

	/* maybe finalize is waiting for us to terminate */
	g_cond_signal (self->priv->thread_finished);
	g_mutex_unlock (self->priv->lock);

	g_object_unref (cancel);

	g_thread_exit (NULL);

	return NULL;
}
static void
backgrounds_changed_cb (GtkIconView       *icon_view,
                        CcBackgroundPanel *panel)
{
  GtkTreeIter iter;
  GtkTreeModel *model;
  CcBackgroundItem *item;
  CcBackgroundPanelPrivate *priv = panel->priv;
  char *pcolor, *scolor;
  gboolean draw_preview = TRUE;
  const char *uri;
  CcBackgroundItemFlags flags;
  char *filename;

  item = get_selected_item (panel);

  if (item == NULL)
    return;

  /* Update current source */
  model = gtk_combo_box_get_model (GTK_COMBO_BOX (WID ("sources-combobox")));
  gtk_combo_box_get_active_iter (GTK_COMBO_BOX (WID ("sources-combobox")),
                                 &iter);
  gtk_tree_model_get (model, &iter,
		      COL_SOURCE_TYPE, &priv->current_source, -1);

  uri = cc_background_item_get_uri (item);
  flags = cc_background_item_get_flags (item);

  if ((flags & CC_BACKGROUND_ITEM_HAS_URI) && uri == NULL)
    {
      g_settings_set_enum (priv->settings, WP_OPTIONS_KEY, G_DESKTOP_BACKGROUND_STYLE_NONE);
      g_settings_set_string (priv->settings, WP_URI_KEY, "");
    }
  else if (cc_background_item_get_source_url (item) != NULL &&
	   cc_background_item_get_needs_download (item))
    {
      GFile *source, *dest;
      gchar *cache_path, *basename, *dest_path, *display_name, *dest_uri;
      GdkPixbuf *pixbuf;

      cache_path = bg_pictures_source_get_cache_path ();
      if (g_mkdir_with_parents (cache_path, 0755) < 0)
        {
          g_warning ("Failed to create directory '%s'", cache_path);
          g_free (cache_path);
          return;
	}
      g_free (cache_path);

      dest_path = bg_pictures_source_get_unique_path (cc_background_item_get_source_url (item));
      dest = g_file_new_for_path (dest_path);
      g_free (dest_path);
      source = g_file_new_for_uri (cc_background_item_get_source_url (item));
      basename = g_file_get_basename (source);
      display_name = g_filename_display_name (basename);
      dest_path = g_file_get_path (dest);
      g_free (basename);

      /* create a blank image to use until the source image is ready */
      pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
      gdk_pixbuf_fill (pixbuf, 0x00000000);
      gdk_pixbuf_save (pixbuf, dest_path, "png", NULL, NULL);
      g_object_unref (pixbuf);
      g_free (dest_path);

      if (priv->copy_cancellable)
        {
          g_cancellable_cancel (priv->copy_cancellable);
          g_cancellable_reset (priv->copy_cancellable);
        }

      if (priv->spinner)
        {
          gtk_widget_destroy (GTK_WIDGET (priv->spinner));
          priv->spinner = NULL;
        }

      /* create a spinner while the file downloads */
      priv->spinner = gtk_spinner_new ();
      gtk_spinner_start (GTK_SPINNER (priv->spinner));
      gtk_box_pack_start (GTK_BOX (WID ("bottom-hbox")), priv->spinner, FALSE,
                          FALSE, 6);
      gtk_widget_show (priv->spinner);

      /* reference the panel in case it is removed before the copy is
       * finished */
      g_object_ref (panel);
      g_object_set_data_full (G_OBJECT (source), "item", g_object_ref (item), g_object_unref);
      g_file_copy_async (source, dest, G_FILE_COPY_OVERWRITE,
                         G_PRIORITY_DEFAULT, priv->copy_cancellable,
                         NULL, NULL,
                         copy_finished_cb, panel);
      g_object_unref (source);
      dest_uri = g_file_get_uri (dest);
      g_object_unref (dest);

      g_settings_set_string (priv->settings, WP_URI_KEY, dest_uri);
      g_object_set (G_OBJECT (item),
		    "uri", dest_uri,
		    "needs-download", FALSE,
		    "name", display_name,
		    NULL);
      g_free (display_name);
      g_free (dest_uri);

      /* delay the updated drawing of the preview until the copy finishes */
      draw_preview = FALSE;
    }
  else
    {
      g_settings_set_string (priv->settings, WP_URI_KEY, uri);
    }

  /* Also set the placement if we have a URI and the previous value was none */
  if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
    {
      g_settings_set_enum (priv->settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
    }
  else if (uri != NULL)
    {
      GDesktopBackgroundStyle style;
      style = g_settings_get_enum (priv->settings, WP_OPTIONS_KEY);
      if (style == G_DESKTOP_BACKGROUND_STYLE_NONE)
        g_settings_set_enum (priv->settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
    }

  if (flags & CC_BACKGROUND_ITEM_HAS_SHADING)
    g_settings_set_enum (priv->settings, WP_SHADING_KEY, cc_background_item_get_shading (item));

  /* When changing to a background with colours set,
   * don't overwrite what's in GSettings, but read
   * from it instead.
   * We have a hack for the colors source though */
  if (flags & CC_BACKGROUND_ITEM_HAS_PCOLOR &&
      priv->current_source != SOURCE_COLORS)
    {
      g_settings_set_string (priv->settings, WP_PCOLOR_KEY, cc_background_item_get_pcolor (item));
    }
  else
    {
      pcolor = g_settings_get_string (priv->settings, WP_PCOLOR_KEY);
      g_object_set (G_OBJECT (item), "primary-color", pcolor, NULL);
    }

  if (flags & CC_BACKGROUND_ITEM_HAS_SCOLOR &&
      priv->current_source != SOURCE_COLORS)
    {
      g_settings_set_string (priv->settings, WP_SCOLOR_KEY, cc_background_item_get_scolor (item));
    }
  else
    {
      scolor = g_settings_get_string (priv->settings, WP_SCOLOR_KEY);
      g_object_set (G_OBJECT (item), "secondary-color", scolor, NULL);
    }

  /* Apply all changes */
  g_settings_apply (priv->settings);

  update_remove_button (panel, item);

  /* update the preview information */
  if (draw_preview != FALSE)
    {
      update_preview (priv, item);

      /* Save the source XML if there is one */
      filename = get_save_path ();
      if (create_save_dir ())
        cc_background_xml_save (priv->current_background, filename);
    }
}
Ejemplo n.º 5
0
gboolean
checkcopy_file_list_write_checksum (CheckcopyFileList * list, GFile * dest)
{
  CheckcopyFileListPrivate *priv = GET_PRIVATE (list);

  GOutputStream * out;
  GCancellable * cancel;
  GError *error = NULL;
  gboolean aborted;

  cancel = checkcopy_get_cancellable ();

  if (priv->verify_only) {
    g_message ("Not writing checksum file because we are only verifying");
    return TRUE;
  }

  /* If we got cancelled, we still want to try this operation.
   * So remember the state of the cancellable, and continue
   */
  if ((aborted = g_cancellable_is_cancelled (cancel)) == TRUE)
    g_cancellable_reset (cancel);

  out = get_checksum_stream (list, dest);

  if (out) {
    /* Write the file */
    GList * file_list;
    GList * curr_file;

    file_list = checkcopy_file_list_get_sorted_list (list);

    for (curr_file = file_list; curr_file != NULL; curr_file = g_list_next (curr_file)) {
      CheckcopyFileInfo * info = (CheckcopyFileInfo *) curr_file->data;
      gchar * line;
      gint n;
      gsize n_written;
      gboolean r = FALSE;

      if (!(info->status==CHECKCOPY_STATUS_COPIED || info->status==CHECKCOPY_STATUS_VERIFICATION_FAILED)) {

        continue;
      }

      n = checkcopy_file_info_format_checksum (info, &line);

      if (!g_cancellable_set_error_if_cancelled (cancel, &error))
        r = g_output_stream_write_all (out, line, n, &n_written, cancel, &error);

      if (!r || n != n_written) {
        gchar * disp_name;

        disp_name = g_file_get_uri (priv->checksum_file);

        if (error) {
          g_critical ("While writing checksum file %s: %s", disp_name, error->message);

          g_error_free (error);
        } else {
          g_critical ("Only wrote %u of %d bytes of checksum file %s", n_written, n, disp_name);
        }
        g_free (disp_name);
      }

      if (error) {
        thread_show_gerror (dest, error);
        g_error_free (error);
        error = NULL;
        g_free (line);
        break;
      }

      g_free (line);
    } /* for */


    if (!g_cancellable_set_error_if_cancelled (cancel, &error))
      g_output_stream_close (out, cancel, &error);

    if (error) {
      thread_show_gerror (dest, error);
      g_error_free (error);
      error = NULL;
    }

    g_list_free (file_list);
  }

  if (aborted && !g_cancellable_is_cancelled (cancel)) {
    g_cancellable_cancel (cancel);
  }

  return out != NULL;
}
Ejemplo n.º 6
0
static gboolean
claim_op (GTlsConnectionBase    *tls,
	  GTlsConnectionBaseOp   op,
	  gboolean               blocking,
	  GCancellable          *cancellable,
	  GError               **error)
{
 try_again:
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  g_mutex_lock (&tls->op_mutex);

  if (((op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE ||
        op == G_TLS_CONNECTION_BASE_OP_READ) &&
       (tls->read_closing || tls->read_closed)) ||
      ((op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE ||
        op == G_TLS_CONNECTION_BASE_OP_WRITE) &&
       (tls->write_closing || tls->write_closed)))
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
			   _("Connection is closed"));
      g_mutex_unlock (&tls->op_mutex);
      return FALSE;
    }

  if (tls->handshake_error &&
      op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH &&
      op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ &&
      op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE)
    {
      if (error)
	*error = g_error_copy (tls->handshake_error);
      g_mutex_unlock (&tls->op_mutex);
      return FALSE;
    }

  if (op != G_TLS_CONNECTION_BASE_OP_HANDSHAKE)
    {
      if (op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH &&
          op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ &&
          op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE &&
          tls->need_handshake && !tls->handshaking)
	{
	  tls->handshaking = TRUE;
	  if (!do_implicit_handshake (tls, blocking, cancellable, error))
	    {
	      g_cancellable_reset (tls->waiting_for_op);
	      g_mutex_unlock (&tls->op_mutex);
	      return FALSE;
	    }
	}

      if (tls->need_finish_handshake &&
	  tls->implicit_handshake)
	{
	  GError *my_error = NULL;
	  gboolean success;

	  tls->need_finish_handshake = FALSE;

	  g_mutex_unlock (&tls->op_mutex);
	  success = finish_handshake (tls, tls->implicit_handshake, &my_error);
	  g_clear_object (&tls->implicit_handshake);
	  g_mutex_lock (&tls->op_mutex);

	  if (op != G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH &&
	      op != G_TLS_CONNECTION_BASE_OP_CLOSE_READ &&
	      op != G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE &&
	      (!success || g_cancellable_set_error_if_cancelled (cancellable, &my_error)))
	    {
	      g_propagate_error (error, my_error);
	      g_mutex_unlock (&tls->op_mutex);
	      return FALSE;
	    }

	  g_clear_error (&my_error);
	}
    }

  if ((op != G_TLS_CONNECTION_BASE_OP_WRITE && tls->reading) ||
      (op != G_TLS_CONNECTION_BASE_OP_READ && tls->writing) ||
      (op != G_TLS_CONNECTION_BASE_OP_HANDSHAKE && tls->handshaking))
    {
      GPollFD fds[2];
      int nfds;

      g_cancellable_reset (tls->waiting_for_op);

      g_mutex_unlock (&tls->op_mutex);

      if (!blocking)
	{
	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
			       _("Operation would block"));
	  return FALSE;
	}

      g_cancellable_make_pollfd (tls->waiting_for_op, &fds[0]);
      if (g_cancellable_make_pollfd (cancellable, &fds[1]))
	nfds = 2;
      else
	nfds = 1;

      g_poll (fds, nfds, -1);

      if (nfds > 1)
        g_cancellable_release_fd (cancellable);

      goto try_again;
    }

  if (op == G_TLS_CONNECTION_BASE_OP_HANDSHAKE)
    tls->handshaking = TRUE;
  if (op == G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH ||
      op == G_TLS_CONNECTION_BASE_OP_CLOSE_READ)
    tls->read_closing = TRUE;
  if (op == G_TLS_CONNECTION_BASE_OP_CLOSE_BOTH ||
      op == G_TLS_CONNECTION_BASE_OP_CLOSE_WRITE)
    tls->write_closing = TRUE;

  if (op != G_TLS_CONNECTION_BASE_OP_WRITE)
    tls->reading = TRUE;
  if (op != G_TLS_CONNECTION_BASE_OP_READ)
    tls->writing = TRUE;

  g_mutex_unlock (&tls->op_mutex);
  return TRUE;
}
static void
set_background (CcBackgroundPanel *panel,
                GSettings         *settings,
                CcBackgroundItem  *item)
{
  CcBackgroundPanelPrivate *priv = panel->priv;
  GDesktopBackgroundStyle style;
  gboolean save_settings = TRUE;
  const char *uri;
  CcBackgroundItemFlags flags;
  char *filename;

  if (item == NULL)
    return;

  uri = cc_background_item_get_uri (item);
  flags = cc_background_item_get_flags (item);

  if ((flags & CC_BACKGROUND_ITEM_HAS_URI) && uri == NULL)
    {
      g_settings_set_enum (settings, WP_OPTIONS_KEY, G_DESKTOP_BACKGROUND_STYLE_NONE);
      g_settings_set_string (settings, WP_URI_KEY, "");
    }
  else if (cc_background_item_get_source_url (item) != NULL &&
           cc_background_item_get_needs_download (item))
    {
      GFile *source, *dest;
      char *cache_path, *basename, *dest_path, *display_name, *dest_uri;
      GdkPixbuf *pixbuf;

      cache_path = bg_pictures_source_get_cache_path ();
      if (g_mkdir_with_parents (cache_path, USER_DIR_MODE) < 0)
        {
          g_warning ("Failed to create directory '%s'", cache_path);
          g_free (cache_path);
          return;
        }
      g_free (cache_path);

      dest_path = bg_pictures_source_get_unique_path (cc_background_item_get_source_url (item));
      dest = g_file_new_for_path (dest_path);
      g_free (dest_path);
      source = g_file_new_for_uri (cc_background_item_get_source_url (item));
      basename = g_file_get_basename (source);
      display_name = g_filename_display_name (basename);
      dest_path = g_file_get_path (dest);
      g_free (basename);

      /* create a blank image to use until the source image is ready */
      pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
      gdk_pixbuf_fill (pixbuf, 0x00000000);
      gdk_pixbuf_save (pixbuf, dest_path, "png", NULL, NULL);
      g_object_unref (pixbuf);
      g_free (dest_path);

      if (priv->copy_cancellable)
        {
          g_cancellable_cancel (priv->copy_cancellable);
          g_cancellable_reset (priv->copy_cancellable);
        }

      if (priv->spinner)
        {
          gtk_widget_destroy (GTK_WIDGET (priv->spinner));
          priv->spinner = NULL;
        }

      /* create a spinner while the file downloads */
      priv->spinner = gtk_spinner_new ();
      gtk_spinner_start (GTK_SPINNER (priv->spinner));
      gtk_box_pack_start (GTK_BOX (WID ("bottom-hbox")), priv->spinner, FALSE,
                          FALSE, 6);
      gtk_widget_show (priv->spinner);

      /* reference the panel in case it is removed before the copy is
       * finished */
      g_object_ref (panel);
      g_object_set_data_full (G_OBJECT (source), "item", g_object_ref (item), g_object_unref);
      g_object_set_data (G_OBJECT (source), "settings", settings);
      g_file_copy_async (source, dest, G_FILE_COPY_OVERWRITE,
                         G_PRIORITY_DEFAULT, priv->copy_cancellable,
                         NULL, NULL,
                         copy_finished_cb, panel);
      g_object_unref (source);
      dest_uri = g_file_get_uri (dest);
      g_object_unref (dest);

      g_settings_set_string (settings, WP_URI_KEY, dest_uri);
      g_object_set (G_OBJECT (item),
                    "uri", dest_uri,
                    "needs-download", FALSE,
                    "name", display_name,
                    NULL);
      g_free (display_name);
      g_free (dest_uri);

      /* delay the updated drawing of the preview until the copy finishes */
      save_settings = FALSE;
    }
  else
    {
      g_settings_set_string (settings, WP_URI_KEY, uri);
    }

  /* Also set the placement if we have a URI and the previous value was none */
  if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
    {
      g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
    }
  else if (uri != NULL)
    {
      style = g_settings_get_enum (settings, WP_OPTIONS_KEY);
      if (style == G_DESKTOP_BACKGROUND_STYLE_NONE)
        g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
    }

  if (flags & CC_BACKGROUND_ITEM_HAS_SHADING)
    g_settings_set_enum (settings, WP_SHADING_KEY, cc_background_item_get_shading (item));

  g_settings_set_string (settings, WP_PCOLOR_KEY, cc_background_item_get_pcolor (item));
  g_settings_set_string (settings, WP_SCOLOR_KEY, cc_background_item_get_scolor (item));

  /* update the preview information */
  if (save_settings != FALSE)
    {
      /* Apply all changes */
      g_settings_apply (settings);

      /* Save the source XML if there is one */
      filename = get_save_path (SAVE_PATH);
      if (create_save_dir ())
        cc_background_xml_save (CURRENT_BG, filename);
    }
}
Ejemplo n.º 8
0
static gboolean
pragha_scanner_worker_finished (gpointer data)
{
	GtkWidget *msg_dialog;
	gchar *last_scan_time = NULL;
	PraghaPreferences *preferences;
	PraghaDatabase *database;
	GSList *list;

	PraghaScanner *scanner = data;

	/* Stop updates */

	g_source_remove(scanner->update_timeout);

	/* Ensure that the other thread has finished */
	g_thread_join (scanner->no_files_thread);

	/* If not cancelled, update database and show a dialog */
	if(!g_cancellable_is_cancelled (scanner->cancellable)) {
		/* Hide the scanner and show the dialog */

		gtk_widget_hide(scanner->hbox);
		msg_dialog = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(scanner->hbox))),
		                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
		                                    GTK_MESSAGE_INFO,
		                                    GTK_BUTTONS_OK,
		                                    "%s",
		                                    _("Library scan complete"));

		g_signal_connect(G_OBJECT(msg_dialog), "response",
		                 G_CALLBACK(pragha_scanner_finished_dialog_response_cb),
		                 scanner);

		g_signal_connect(G_OBJECT(msg_dialog), "delete-event",
		                 G_CALLBACK(pragha_scanner_finished_dialog_delete),
		                 scanner);

		gtk_widget_show_all(msg_dialog);

		/* Save new database and update the library view */

		set_watch_cursor(msg_dialog);
		set_watch_cursor(scanner->hbox);

		database = pragha_database_get();

		pragha_database_begin_transaction (database);

		pragha_database_flush (database);
		g_hash_table_foreach (scanner->tracks_table,
		                      pragha_scanner_add_track_db,
		                      database);


		/* Import playlist detected. */

		for (list = scanner->playlists ; list != NULL; list = list->next)
			pragha_scanner_import_playlist(database, list->data);

		pragha_database_commit_transaction (database);

		pragha_database_change_tracks_done (database);
		g_object_unref(database);

		remove_watch_cursor(scanner->hbox);
		remove_watch_cursor(msg_dialog);

		/* Save finished time and folders scanned. */

		g_get_current_time(&scanner->last_update);
		last_scan_time = g_time_val_to_iso8601(&scanner->last_update);
		preferences = pragha_preferences_get();
		pragha_preferences_set_string(preferences,
			                     GROUP_LIBRARY,
			                     KEY_LIBRARY_LAST_SCANNED,
			                     last_scan_time);
		g_free(last_scan_time);

		pragha_preferences_set_filename_list(preferences,
			                             GROUP_LIBRARY,
			                             KEY_LIBRARY_SCANNED,
			                             scanner->folder_list);
		g_object_unref(G_OBJECT(preferences));
	}
	else {
		gtk_widget_hide(scanner->hbox);
	}

	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(scanner->progress_bar), NULL);
	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(scanner->progress_bar), 0.0);

	/* Clean memory */

	g_hash_table_remove_all(scanner->tracks_table);
	free_str_list(scanner->folder_list);
	scanner->folder_list = NULL;
	free_str_list(scanner->folder_scanned);
	scanner->folder_scanned = NULL;

	free_str_list(scanner->playlists);
	scanner->playlists = NULL;

	scanner->no_files = 0;
	scanner->files_scanned = 0;

	g_cancellable_reset (scanner->cancellable);
	scanner->update_timeout = 0;

	return FALSE;
}
static void
nemo_search_engine_tracker_start (NemoSearchEngine *engine)
{
	NemoSearchEngineTracker *tracker;
	gchar	*search_text, *location_uri;
	GString *sparql;
	GList *mimetypes, *l;
	gint mime_count;

	tracker = NEMO_SEARCH_ENGINE_TRACKER (engine);

	if (tracker->details->query_pending) {
		return;
	}

	if (tracker->details->query == NULL) {
		return;
	}

	g_cancellable_reset (tracker->details->cancellable);

	search_text = nemo_query_get_text (tracker->details->query);
	location_uri = nemo_query_get_location (tracker->details->query);
	mimetypes = nemo_query_get_mime_types (tracker->details->query);

	mime_count = g_list_length (mimetypes);

#ifdef FTS_MATCHING
	/* Using FTS: */
	sparql = g_string_new ("SELECT nie:url(?urn) "
			       "WHERE {"
			       "  ?urn a nfo:FileDataObject ;"
			       "  tracker:available true ; ");

	if (mime_count > 0) {
		g_string_append (sparql, "nie:mimeType ?mime ;");
	}

	g_string_append (sparql, "  fts:match ");
	sparql_append_string_literal (sparql, search_text);

	if (location_uri || mime_count > 0) {
		g_string_append (sparql, " . FILTER (");
	
		if (location_uri)  {
			g_string_append (sparql, " fn:starts-with(nie:url(?urn),");
			sparql_append_string_literal (sparql, location_uri);
			g_string_append (sparql, ")");
		}

		if (mime_count > 0) {
			if (location_uri) {
				g_string_append (sparql, " && ");
			}

			g_string_append (sparql, "(");
			for (l = mimetypes; l != NULL; l = l->next) {
				if (l != mimetypes) {
					g_string_append (sparql, " || ");
				}

				g_string_append (sparql, "?mime = ");
				sparql_append_string_literal (sparql, l->data);
			}
			g_string_append (sparql, ")");
		}

		g_string_append (sparql, ")");
	}

	g_string_append (sparql, " } ORDER BY DESC(fts:rank(?urn)) ASC(nie:url(?urn))");
#else  /* FTS_MATCHING */
	/* Using filename matching: */
	sparql = g_string_new ("SELECT nie:url(?urn) "
			       "WHERE {"
			       "  ?urn a nfo:FileDataObject ;");

	if (mime_count > 0) {
		g_string_append (sparql, "nie:mimeType ?mime ;");
	}

	g_string_append (sparql, "    tracker:available true ."
			 "  FILTER (fn:contains(nfo:fileName(?urn),");

	sparql_append_string_literal (sparql, search_text);

	g_string_append (sparql, ")");

	if (location_uri)  {
		g_string_append (sparql, " && fn:starts-with(nie:url(?urn),");
		sparql_append_string_literal (sparql, location_uri);
		g_string_append (sparql, ")");
	}

	if (mime_count > 0) {
		g_string_append (sparql, " && ");
		g_string_append (sparql, "(");
		for (l = mimetypes; l != NULL; l = l->next) {
			if (l != mimetypes) {
				g_string_append (sparql, " || ");
			}

			g_string_append (sparql, "?mime = ");
			sparql_append_string_literal (sparql, l->data);
		}
		g_string_append (sparql, ")");
	}

	g_string_append (sparql, ")");


	g_string_append (sparql, 
			 "} ORDER BY DESC(nie:url(?urn)) DESC(nfo:fileName(?urn))");
#endif /* FTS_MATCHING */

	tracker_sparql_connection_query_async (tracker->details->connection,
					       sparql->str,
					       tracker->details->cancellable,
					       query_callback,
					       tracker);
	g_string_free (sparql, TRUE);

	tracker->details->query_pending = TRUE;

	g_free (search_text);
	g_free (location_uri);

	if (mimetypes != NULL) {
		g_list_free_full (mimetypes, g_free);
	}
}