commit a8ce17de0f28f80d5ea2bf0f4acd7f8bf707f072 Author: phantomjinx <p.g.richard...@phantomjinx.co.uk> Date: Sun Sep 11 00:44:09 2011 +0100
Implement drag n drop cover support for clarity * In the same way as the coverart display, using fetchcover, a jpg can be dragged from the browser and replace the main cover in the index. * The dnd sends a track update signal and the tracks are all updated accordingly. plugins/clarity/Makefile.am | 1 + plugins/clarity/clarity_dnd_support.c | 246 +++++++++++++++++++++++++++++++++ plugins/clarity/clarity_dnd_support.h | 77 ++++++++++ plugins/clarity/clarity_widget.c | 25 +++- 4 files changed, 341 insertions(+), 8 deletions(-) --- diff --git a/plugins/clarity/Makefile.am b/plugins/clarity/Makefile.am index c623eda..441b33d 100644 --- a/plugins/clarity/Makefile.am +++ b/plugins/clarity/Makefile.am @@ -37,6 +37,7 @@ libclarity_la_SOURCES = plugin.c plugin.h \ clarity_utils.c clarity_utils.h \ clarity_preferences.c clarity_preferences.h \ clarity_context_menu.c clarity_context_menu.h \ + clarity_dnd_support.c clarity_dnd_support.h \ fetchcover.c fetchcover.h libclarity_la_CFLAGS = $(CLUTTER_GTK_CFLAGS) libclarity_la_LDFLAGS = $(GTKPOD_PLUGIN_LDFLAGS) diff --git a/plugins/clarity/clarity_dnd_support.c b/plugins/clarity/clarity_dnd_support.c new file mode 100644 index 0000000..d2cf79b --- /dev/null +++ b/plugins/clarity/clarity_dnd_support.c @@ -0,0 +1,246 @@ +/* + | Copyright (C) 2002-2011 Jorg Schuler <jcsjcs at users sourceforge net> + | Paul Richardson <phantom_sf at users.sourceforge.net> + | Part of the gtkpod project. + | + | URL: http://www.gtkpod.org/ + | URL: http://gtkpod.sourceforge.net/ + | + | This program 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 2 of the License, or + | (at your option) any later version. + | + | This program 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, write to the Free Software + | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + | + | iTunes and iPod are trademarks of Apple + | + | This product is not supported/written/published by Apple! + | + */ + +#ifndef CLARITY_DND_SUPPORT_C_ +#define CLARITY_DND_SUPPORT_C_ + +#include "libgtkpod/gtkpod_app_iface.h" +#include "clarity_dnd_support.h" +#include "fetchcover.h" +#include "clarity_canvas.h" +#include "clarity_utils.h" + +/** + * dnd_clarity_drag_drop: + * + * Used by the drag and drop of a jpg. When a drop is + * made, this determines whether the drop is valid + * then requests the data from the source widget. + * + */ +gboolean dnd_clarity_drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data) { + GdkAtom target; + target = gtk_drag_dest_find_target(widget, drag_context, NULL); + + if (target != GDK_NONE) { + gtk_drag_get_data(widget, drag_context, target, time); + return TRUE; + } + + return FALSE; +} + +/** + * dnd_clarity_drag_motion: + * + * Used by the drag and drop of a jpg. While the jpg is being + * dragged, this reports to the source widget whether it is an + * acceptable location to allow a drop. + * + */ +gboolean dnd_clarity_drag_motion(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, guint time, gpointer user_data) { + GdkAtom target; + iTunesDB *itdb; + ExtraiTunesDBData *eitdb; + + itdb = gp_get_selected_itdb(); + /* no drop is possible if no playlist/repository is selected */ + if (itdb == NULL) { + gdk_drag_status(dc, 0, time); + return FALSE; + } + + eitdb = itdb->userdata; + g_return_val_if_fail (eitdb, FALSE); + /* no drop is possible if no repository is loaded */ + if (!eitdb->itdb_imported) { + gdk_drag_status(dc, 0, time); + return FALSE; + } + + target = gtk_drag_dest_find_target(widget, dc, NULL); + /* no drop possible if no valid target can be found */ + if (target == GDK_NONE) { + gdk_drag_status(dc, 0, time); + return FALSE; + } + + gdk_drag_status(dc, gdk_drag_context_get_suggested_action(dc), time); + + return TRUE; +} + +/** + * dnd_clarity_drag_data_received: + * + * Used by the drag and drop of a jpg. When the drop is performed, this + * acts on the receipt of the data from the source widget and applies + * the jpg to the track. + * + */ +void dnd_clarity_drag_data_received(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data) { + g_return_if_fail(CLARITY_IS_CANVAS(widget)); + g_return_if_fail (dc); + g_return_if_fail (data); + g_return_if_fail (gtk_selection_data_get_data(data)); + g_return_if_fail (gtk_selection_data_get_length(data) > 0); + + /* mozilla bug 402394 */ + +#if DEBUG + printf ("data length = %d\n", gtk_selection_data_get_length(data->length)); + printf ("data->data = %s\n", gtk_selection_data_get_data(data)); +#endif + + AlbumItem *item; + GList *tracks; + gchar *url = NULL; + Fetch_Cover *fcover; + gchar *filename = NULL; + gboolean image_status = FALSE; + gchar *image_error = NULL; + /* For use with DND_IMAGE_JPEG */ + GdkPixbuf *pixbuf; + GError *error = NULL; + + ClarityCanvas *ccanvas = CLARITY_CANVAS(widget); + + /* Find the display cover item in the cover display */ + item = clarity_canvas_get_current_album_item(ccanvas); + if (!item) { + /* looks like there are no covers yet something got dragged into it */ + gtk_drag_finish(dc, FALSE, FALSE, time); + return; + } + + tracks = item->tracks; + + switch (info) { + case DND_IMAGE_JPEG: +#if DEBUG + printf ("Using DND_IMAGE_JPEG\n"); +#endif + pixbuf = gtk_selection_data_get_pixbuf(data); + if (pixbuf != NULL) { + /* initialise the url string with a safe value as not used if already have image */ + url = "local image"; + /* Initialise a fetchcover object */ + fcover = fetchcover_new(url, tracks); + clarity_canvas_block_change(ccanvas, TRUE); + + /* find the filename with which to save the pixbuf to */ + if (fetchcover_select_filename(fcover)) { + filename = g_build_filename(fcover->dir, fcover->filename, NULL); + if (!gdk_pixbuf_save(pixbuf, filename, "jpeg", &error, NULL)) { + /* Save failed for some reason */ + if (error->message) + fcover->err_msg = g_strdup(error->message); + else + fcover->err_msg = "Saving image to file failed. No internal error message was returned."; + + g_error_free(error); + } + else { + /* Image successfully saved */ + image_status = TRUE; + } + } + /* record any errors and free the fetchcover */ + if (fcover->err_msg != NULL) + image_error = g_strdup(fcover->err_msg); + + free_fetchcover(fcover); + g_object_unref(pixbuf); + clarity_canvas_block_change(ccanvas, FALSE); + } + else { + /* despite the data being of type image/jpeg, the pixbuf is NULL */ + image_error = "jpeg data flavour was used but the data did not contain a GdkPixbuf object"; + } + break; + case DND_TEXT_PLAIN: +#if DEBUG + printf ("Defaulting to using DND_TEXT_PLAIN\n"); +#endif + +#ifdef HAVE_CURL + /* initialise the url string with the data from the dnd */ + url = g_strdup ((gchar *) gtk_selection_data_get_data(data)); + /* Initialise a fetchcover object */ + fcover = fetchcover_new (url, tracks); + clarity_canvas_block_change(ccanvas, TRUE); + + if (fetchcover_net_retrieve_image (fcover)) + { +#if DEBUG + printf ("Successfully retrieved\n"); + printf ("Url of fetch cover: %s\n", fcover->url->str); + printf ("filename of fetch cover: %s\n", fcover->filename); +#endif + + filename = g_build_filename(fcover->dir, fcover->filename, NULL); + image_status = TRUE; + } + + /* record any errors and free the fetchcover */ + if (fcover->err_msg != NULL) + image_error = g_strdup(fcover->err_msg); + + free_fetchcover (fcover); + clarity_canvas_block_change(ccanvas, FALSE); +#else + image_error = g_strdup(_("Item had to be downloaded but gtkpod was not compiled with curl.")); + image_status = FALSE; +#endif + } + + if (!image_status || filename == NULL) { + gtkpod_warning(_("Error occurred dropping an image onto the clarity display: %s\n"), image_error); + + if (image_error) + g_free(image_error); + if (filename) + g_free(filename); + + gtk_drag_finish(dc, FALSE, FALSE, time); + return; + } + + clarity_util_update_coverart(tracks, filename); + + if (image_error) + g_free(image_error); + + g_free(filename); + + gtkpod_statusbar_message(_("Successfully set new cover art for selected tracks")); + gtk_drag_finish(dc, FALSE, FALSE, time); + return; +} + +#endif /* CLARITY_DND_SUPPORT_C_ */ diff --git a/plugins/clarity/clarity_dnd_support.h b/plugins/clarity/clarity_dnd_support.h new file mode 100644 index 0000000..42572b7 --- /dev/null +++ b/plugins/clarity/clarity_dnd_support.h @@ -0,0 +1,77 @@ +/* + | Copyright (C) 2002-2011 Jorg Schuler <jcsjcs at users sourceforge net> + | Paul Richardson <phantom_sf at users.sourceforge.net> + | Part of the gtkpod project. + | + | URL: http://www.gtkpod.org/ + | URL: http://gtkpod.sourceforge.net/ + | + | This program 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 2 of the License, or + | (at your option) any later version. + | + | This program 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, write to the Free Software + | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + | + | iTunes and iPod are trademarks of Apple + | + | This product is not supported/written/published by Apple! + | + */ + +#ifndef CLARITY_DND_SUPPORT_H_ +#define CLARITY_DND_SUPPORT_H_ + +#include <gtk/gtk.h> +#include <libgtkpod/gp_itdb.h> +#include <libgtkpod/gp_private.h> +#include "plugin.h" + +static GtkTargetEntry clarity_drop_types[] = + { + /* Konqueror supported flavours */ + { "image/jpeg", 0, DND_IMAGE_JPEG }, + + /* Fallback flavours */ + { "text/plain", 0, DND_TEXT_PLAIN }, + { "STRING", 0, DND_TEXT_PLAIN } + }; + +/** + * dnd_clarity_drag_drop: + * + * Used by the drag and drop of a jpg. When a drop is + * made, this determines whether the drop is valid + * then requests the data from the source widget. + * + */ +gboolean dnd_clarity_drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data); + +/** + * dnd_clarity_drag_motion: + * + * Used by the drag and drop of a jpg. While the jpg is being + * dragged, this reports to the source widget whether it is an + * acceptable location to allow a drop. + * + */ +gboolean dnd_clarity_drag_motion(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, guint time, gpointer user_data); + +/** + * dnd_clarity_drag_data_received: + * + * Used by the drag and drop of a jpg. When the drop is performed, this + * acts on the receipt of the data from the source widget and applies + * the jpg to the track. + * + */ +void dnd_clarity_drag_data_received(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data); + +#endif /* CLARITY_DND_SUPPORT_H_ */ diff --git a/plugins/clarity/clarity_widget.c b/plugins/clarity/clarity_widget.c index c044d40..df3fa29 100644 --- a/plugins/clarity/clarity_widget.c +++ b/plugins/clarity/clarity_widget.c @@ -31,6 +31,7 @@ #include "clarity_canvas.h" #include "clarity_widget.h" #include "album_model.h" +#include "clarity_dnd_support.h" G_DEFINE_TYPE( ClarityWidget, clarity_widget, GTK_TYPE_BOX); @@ -62,14 +63,6 @@ enum { PROP_0 }; -/* - * TODO - * - * popup menu - * drag n drop - * set cover from file - */ - static void clarity_widget_dispose(GObject *gobject) { ClarityWidget *cw = CLARITY_WIDGET(gobject); cw->current_playlist = NULL; @@ -289,6 +282,22 @@ static void clarity_widget_init (ClarityWidget *self) { g_signal_connect (G_OBJECT(priv->rightbutton), "clicked", G_CALLBACK(_on_clarity_button_clicked), priv); + /* Dnd destinaton for foreign image files */ + gtk_drag_dest_set(priv->draw_area, 0, clarity_drop_types, TGNR(clarity_drop_types), GDK_ACTION_COPY + | GDK_ACTION_MOVE); + + g_signal_connect ((gpointer) priv->draw_area, "drag-drop", + G_CALLBACK (dnd_clarity_drag_drop), + NULL); + + g_signal_connect ((gpointer) priv->draw_area, "drag-data-received", + G_CALLBACK (dnd_clarity_drag_data_received), + NULL); + + g_signal_connect ((gpointer) priv->draw_area, "drag-motion", + G_CALLBACK (dnd_clarity_drag_motion), + NULL); + _init_slider_range(priv); priv->controlbox = gtk_hbox_new(FALSE, 2); ------------------------------------------------------------------------------ Malware Security Report: Protecting Your Business, Customers, and the Bottom Line. Protect your business and customers by understanding the threat from malware and how it can impact your online business. http://www.accelacomm.com/jaw/sfnl/114/51427462/ _______________________________________________ gtkpod-cvs2 mailing list gtkpod-cvs2@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2