/**
 * rb_async_copy_start:
 * @copy: a #RBAsyncCopy
 * @src: source URI
 * @dest: destination URI
 * @callback: completion callback
 * @user_data: data for completion callback
 * @destroy_data: destroy function for user_data
 *
 * Starts copying @src to @dest, calling @callback on completion or error.
 */
void
rb_async_copy_start (RBAsyncCopy *copy,
		     const char *src,
		     const char *dest,
		     RBAsyncCopyCallback callback,
		     gpointer user_data,
		     GDestroyNotify destroy_data)
{
	g_assert (copy->priv->src == NULL);

	copy->priv->cancel = g_cancellable_new ();

	copy->priv->callback = callback;
	copy->priv->callback_data = user_data;
	copy->priv->destroy_data = destroy_data;

	copy->priv->src = g_file_new_for_commandline_arg (src);
	copy->priv->dest = g_file_new_for_commandline_arg (dest);

	g_file_copy_async (copy->priv->src,
			   copy->priv->dest,
			   G_FILE_COPY_NONE,
			   G_PRIORITY_DEFAULT,
			   copy->priv->cancel,
			   progress_cb,
			   copy,
			   copy_cb,
			   copy);
}
/* Try to copy the theme file to the user's screensaver directory.
 * If a file with the given name already exists, the error will be
 * caught later and the copy re-attempted with a random value
 * appended to the filename.
**/
static void
copy_theme_dialog_copy_next (CopyThemeDialog *dialog)
{
	GFile *file, *destination;
	gchar *basename, *full_basename;

	if (copy_finished (dialog))
	{
		g_signal_emit (G_OBJECT (dialog), signals[COMPLETE],
		               0, NULL);
		return;
	}

	file = G_FILE (dialog->priv->file->data);
	basename = (gchar *) (dialog->priv->basename->data);

	g_return_if_fail (file != NULL);
	g_return_if_fail (basename != NULL);

	full_basename = g_strdup_printf ("%s.desktop", basename);
	destination = g_file_get_child (dialog->priv->theme_dir, full_basename);
	g_free (full_basename);

	g_file_copy_async (file, destination, G_FILE_COPY_NONE,
	                   G_PRIORITY_DEFAULT, dialog->priv->cancellable,
	                   NULL, NULL, single_copy_complete, dialog);
}
static void
pdf_load_job_remote_refresh_cache (PdfLoadJob *job)
{
  GFile *remote_file;

  remote_file = g_file_new_for_uri (job->uri);
  g_file_copy_async (remote_file,
                     job->download_file,
                     G_FILE_COPY_OVERWRITE,
                     G_PRIORITY_DEFAULT,
                     job->cancellable,
                     NULL,
                     NULL,
                     remote_file_copy_cb,
                     job);

  g_object_unref (remote_file);
}
示例#4
0
static void
install_button_clicked_cb (GtkButton   *button,
                           const gchar *font_file)
{
    GFile *src, *dest;
    gchar *dest_path, *dest_filename;

    GError *err = NULL;

    /* first check if ~/.fonts exists */
    dest_path = g_build_filename (g_get_home_dir (), ".fonts", NULL);
    if (!g_file_test (dest_path, G_FILE_TEST_EXISTS)) {
        GFile *f = g_file_new_for_path (dest_path);
        g_file_make_directory_with_parents (f, NULL, &err);
        g_object_unref (f);
        if (err) {
            /* TODO: show error dialog */
            g_warning ("Could not create fonts directory: %s", err->message);
            g_error_free (err);
            g_free (dest_path);
            return;
        }
    }
    g_free (dest_path);

    /* create destination filename */
    src = g_file_new_for_uri (font_file);

    dest_filename = g_file_get_basename (src);
    dest_path = g_build_filename (g_get_home_dir (), ".fonts", dest_filename, NULL);
    g_free (dest_filename);

    dest = g_file_new_for_path (dest_path);

    /* TODO: show error dialog if file exists */
    g_file_copy_async (src, dest, G_FILE_COPY_NONE, 0, NULL, NULL, NULL,
                       font_install_finished_cb, button);

    g_object_unref (src);
    g_object_unref (dest);
    g_free (dest_path);
}
示例#5
0
static gboolean copy_uris_process_queue(Tcopyfile *cf) {
  if (cf->sourcelist) {
    GFile *uri, *dest;
    gchar *tmp;

    uri = cf->sourcelist->data;
    cf->sourcelist = g_slist_remove(cf->sourcelist, uri);
    tmp = g_file_get_basename(uri);
    dest = g_file_get_child(cf->destdir,tmp);
    g_free(tmp);

    cf->curfile = uri;
    cf->curdest = dest;
    g_file_copy_async(uri,dest,G_FILE_COPY_NONE,
          G_PRIORITY_LOW,NULL,
          NULL,NULL,
          copy_async_lcb,cf);
    return TRUE;
  }
  return FALSE;
}
示例#6
0
 void copy_async_lcb(GObject *source_object,GAsyncResult *res,gpointer user_data) {
 Tcopyfile *cf = user_data;
 gboolean done;
 GError *error=NULL;
 /* fill in the blanks */
 done = g_file_copy_finish(cf->curfile,res,&error);
 if (!done) {
    if (error->code == G_IO_ERROR_EXISTS) {
      gint retval;
      gchar *tmpstr, *dispname;
      GFileInfo *info =g_file_query_info (cf->curfile,"standard::display-name", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL);
      dispname = (gchar *)g_file_info_get_display_name (info);
      tmpstr = g_strdup_printf(_("%s cannot be copied, it already exists, overwrite?"),dispname);
      retval = yes_no_dialog (_("Overwrite file?"), tmpstr);
      g_free(tmpstr);
      g_free(dispname);
      if (retval != -8) {
        g_file_copy_async(cf->curfile,cf->curdest,G_FILE_COPY_OVERWRITE,
            G_PRIORITY_LOW,NULL,
            NULL,NULL,
            copy_async_lcb,cf);
        return;
      }
    }else {
      g_print("ERROR copying file::%s\n",error->message);
      g_error_free (error);
    }
  }
  g_object_unref(cf->curfile);
  g_object_unref(cf->curdest);
  if (!copy_uris_process_queue(cf)) {
    filebrowser_backend_refresh_folder (cf->fbback);
    g_object_unref(cf->destdir);
    g_slice_free(Tcopyfile,cf);
  }
}
示例#7
0
static void  _copy_files_async_true(GFile *src,gpointer data)
{
    g_debug("_copy_files_async_true start");
    TDData* _data = (TDData*) data;
    dest_pb = _data->dest_file;
    _copy_cancellable = _data->cancellable;

    GtkWidget *parent = NULL;
    GtkWidget *progress_bar = NULL;
    const char* basename = g_file_get_basename(src);

    parent = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_deletable(GTK_WINDOW(parent),FALSE);
    gtk_window_set_position(GTK_WINDOW(parent),GTK_WIN_POS_CENTER);
    gtk_widget_set_size_request(parent, 400, 30);
    gtk_window_set_title(GTK_WINDOW(parent),basename);
    gtk_window_set_resizable(GTK_WINDOW(parent),FALSE);
    g_signal_connect (G_OBJECT (parent), "delete_event", G_CALLBACK (progress_bar_delete_event), NULL);
    gtk_widget_show(parent);

    progress_bar = gtk_progress_bar_new();
    gtk_container_add(GTK_CONTAINER(parent),progress_bar);
    gtk_widget_show(progress_bar);


#if DEBUG
    char* src_uri = g_file_get_uri (src);
    char* dest_uri = g_file_get_uri (dest_pb);
    g_debug ("_copy_files_async: copy %s to %s", src_uri, dest_uri);
    g_free (src_uri);
    g_free (dest_uri);
#endif
    g_file_copy_async(src, dest_pb, G_FILE_COPY_NOFOLLOW_SYMLINKS,
                G_PRIORITY_DEFAULT, _copy_cancellable, g_file_copy_progress_handler,
                progress_bar, g_file_copy_async_finish_handler, progress_bar);
}
示例#8
0
文件: actions.c 项目: JosephMcc/pix
void
gth_browser_activate_action_tool_desktop_background (GtkAction  *action,
					             GthBrowser *browser)
{
	WallpaperData *wdata;
	gboolean       saving_wallpaper = FALSE;
	GList         *items;
	GList         *file_list;
	GthFileData   *file_data;
	const char    *mime_type;

	wdata = wallpaper_data_new (browser);

	items = gth_file_selection_get_selected (GTH_FILE_SELECTION (gth_browser_get_file_list_view (browser)));
	file_list = gth_file_list_get_files (GTH_FILE_LIST (gth_browser_get_file_list (browser)), items);
	file_data = (file_list != NULL) ? file_list->data : NULL;
	mime_type = (file_data != NULL) ? gth_file_data_get_mime_type (file_data) : NULL;

	if (gth_main_extension_is_active ("image_viewer")
	    && (gth_browser_get_file_modified (browser) || ! _gdk_pixbuf_mime_type_is_readable (mime_type)))
	{
		GtkWidget *viewer_page;

		viewer_page = gth_browser_get_viewer_page (browser);
		if (viewer_page != NULL) {
			GthImage *image;
			GthTask  *task;

			image = gth_image_new_for_surface (gth_image_viewer_page_get_image (GTH_IMAGE_VIEWER_PAGE (viewer_page)));
			file_data = gth_file_data_new (wdata->new_style.file, NULL);
			task = gth_save_image_task_new (image,
							"image/jpeg",
							file_data,
							GTH_OVERWRITE_RESPONSE_YES);
			g_signal_connect (task,
					  "completed",
					  G_CALLBACK (save_wallpaper_task_completed_cb),
					  wdata);
			gth_browser_exec_task (GTH_BROWSER (browser), task, FALSE);

			saving_wallpaper = TRUE;

			_g_object_unref (task);
			g_object_unref (image);
		}
	}

	if (saving_wallpaper)
		return;

	if (file_data == NULL)
		return;

	if (g_file_is_native (file_data->file)) {
		_g_object_unref (wdata->new_style.file);
		wdata->new_style.file = g_file_dup (file_data->file);
		wallpaper_data_set (wdata);
	}
	else
		g_file_copy_async (file_data->file,
				   wdata->new_style.file,
				   G_FILE_COPY_OVERWRITE,
				   G_PRIORITY_DEFAULT,
				   NULL,
				   NULL,
				   NULL,
				   copy_wallpaper_ready_cb,
				   wdata);

	_g_object_list_unref (file_list);
	_gtk_tree_path_list_free (items);
}
static void
single_copy_complete (GObject *source_object, GAsyncResult *res,
                      gpointer user_data)
{
	GError *error = NULL;
	gboolean should_continue = FALSE;
	CopyThemeDialog *dialog = COPY_THEME_DIALOG (user_data);

	if (g_file_copy_finish (G_FILE (source_object), res, &error))
	{
		should_continue = TRUE;
	}

	else
	{
		/* If the file already exists, generate a new random name
		 * and try again.
		**/
		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
		{
			GFile *file, *destination;
			gchar *basename, *full_basename;
			g_error_free (error);

			file = G_FILE (dialog->priv->file->data);
			basename = (gchar *) (dialog->priv->basename->data);

			g_return_if_fail (file != NULL);
			g_return_if_fail (basename != NULL);

			full_basename = g_strdup_printf ("%s-%u.desktop",
			                                 basename,
			                                 g_random_int ());
			destination = g_file_get_child (dialog->priv->theme_dir,
			                                full_basename);
			g_free (full_basename);

			g_file_copy_async (file, destination, G_FILE_COPY_NONE,
			                   G_PRIORITY_DEFAULT,
			                   dialog->priv->cancellable,
			                   NULL, NULL,
			                   single_copy_complete, dialog);
		}

		else
		{
			if (g_error_matches (error, G_IO_ERROR,
			                     G_IO_ERROR_CANCELLED))
			{
				/* User has cancelled the theme copy */
				g_signal_emit (G_OBJECT (dialog),
				               signals[CANCELLED],
				               0, NULL);
			}

			else
			{
				/* Some other error occurred, ignore and
				 * try to copy remaining files
				**/
				should_continue = TRUE;
			}

			g_error_free (error);
		}
	}

	/* Update informational widgets and, if needed, signal
	 * copy completion.
	**/
	if (should_continue)
	{
		dialog->priv->index++;
		dialog->priv->file = dialog->priv->file->next;
		dialog->priv->basename = dialog->priv->basename->next;
		copy_theme_dialog_update_num_files (dialog);
		copy_theme_dialog_copy_next (dialog);
	}
}
static gboolean
add_single_file (BgPicturesSource     *bg_source,
                 GFile                *file,
                 const gchar          *content_type,
                 guint64               mtime,
                 GtkTreeRowReference **ret_row_ref)
{
  CcBackgroundItem *item = NULL;
  CcBackgroundItemFlags flags = 0;
  GtkListStore *store;
  GtkTreeIter iter;
  GtkTreePath *path = NULL;
  GtkTreeRowReference *row_ref = NULL;
  cairo_surface_t *surface = NULL;
  char *source_uri = NULL;
  char *uri = NULL;
  gboolean needs_download;
  gboolean retval = FALSE;
  GFile *pictures_dir, *cache_dir;
  GrlMedia *media;

  /* find png and jpeg files */
  if (!content_type)
    goto out;
  if (!in_content_types (content_type))
    goto out;

  /* create a new CcBackgroundItem */
  uri = g_file_get_uri (file);

  pictures_dir = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
  cache_dir = bg_pictures_source_get_cache_file ();
  needs_download = !g_file_has_parent (file, pictures_dir) &&
          !g_file_has_parent (file, cache_dir);
  g_object_unref (pictures_dir);
  g_object_unref (cache_dir);

  if (!needs_download)
    {
      source_uri = g_strdup (uri);
      flags |= CC_BACKGROUND_ITEM_HAS_URI;
    }
  else
    {
      source_uri = uri;
      uri = NULL;
    }

  item = cc_background_item_new (uri);
  flags |= CC_BACKGROUND_ITEM_HAS_SHADING | CC_BACKGROUND_ITEM_HAS_PLACEMENT;
  g_object_set (G_OBJECT (item),
		"flags", flags,
		"shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
		"placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
                "modified", mtime,
                "needs-download", needs_download,
                "source-url", source_uri,
		NULL);

  if (!ret_row_ref && in_screenshot_types (content_type))
    goto read_file;

  surface = get_content_loading_icon (BG_SOURCE (bg_source));
  store = bg_source_get_liststore (BG_SOURCE (bg_source));

  /* insert the item into the liststore */
  gtk_list_store_insert_with_values (store, &iter, -1,
                                     0, surface,
                                     1, item,
                                     -1);

  path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
  row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
  g_object_set_data_full (G_OBJECT (item), "row-ref", row_ref, (GDestroyNotify) gtk_tree_row_reference_free);


 read_file:

  media = g_object_get_data (G_OBJECT (file), "grl-media");
  if (media == NULL)
    {
      g_object_set_data_full (G_OBJECT (file), "item", g_object_ref (item), g_object_unref);
      g_file_read_async (file, G_PRIORITY_DEFAULT,
                         bg_source->priv->cancellable,
                         picture_opened_for_read, bg_source);
    }
  else
    {
      GFile *native_file;
      GFile *thumbnail_file = NULL;
      gchar *native_dir;
      gchar *native_path;
      const gchar *title;
      const gchar *thumbnail_uri;

      title = grl_media_get_title (media);
      g_object_set (G_OBJECT (item), "name", title, NULL);

      thumbnail_uri = grl_media_get_thumbnail (media);
      thumbnail_file = g_file_new_for_uri (thumbnail_uri);

      native_path = gnome_desktop_thumbnail_path_for_uri (source_uri, GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
      native_file = g_file_new_for_path (native_path);

      native_dir = g_path_get_dirname (native_path);
      g_mkdir_with_parents (native_dir, USER_DIR_MODE);

      g_object_set_data_full (G_OBJECT (thumbnail_file), "item", g_object_ref (item), g_object_unref);
      g_object_set_data_full (G_OBJECT (thumbnail_file),
                              "native-file",
                              g_object_ref (native_file),
                              g_object_unref);
      g_file_copy_async (thumbnail_file,
                         native_file,
                         G_FILE_COPY_ALL_METADATA,
                         G_PRIORITY_DEFAULT,
                         bg_source->priv->cancellable,
                         NULL,
                         NULL,
                         picture_copied_for_read,
                         bg_source);

      g_clear_object (&thumbnail_file);
      g_object_unref (native_file);
      g_free (native_dir);
      g_free (native_path);
    }

  retval = TRUE;

 out:
  if (ret_row_ref)
    {
      if (row_ref && retval != FALSE)
        *ret_row_ref = gtk_tree_row_reference_copy (row_ref);
      else
        *ret_row_ref = NULL;
    }
  gtk_tree_path_free (path);
  g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
  g_clear_object (&item);
  g_object_unref (file);
  g_free (source_uri);
  g_free (uri);
  return retval;
}
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);
    }
}
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);
    }
}