From 021546cb730dd3f6d6761788aedb024ccc3fdf70 Mon Sep 17 00:00:00 2001
From: Christopher Reichert <creichert07@gmail.com>
Date: Thu, 21 Jun 2012 12:52:49 -0500
Subject: [PATCH] Allow dragging tracks into loved tracks playlist.

Fix for TWK-932.
---
 src/CMakeLists.txt                       |   1 +
 src/sourcetree/SourceDelegate.cpp        |   1 +
 src/sourcetree/SourceTreeView.cpp        |   1 +
 src/sourcetree/SourcesModel.h            |   3 +-
 src/sourcetree/items/LovedTracksItem.cpp | 114 +++++++++++++++++++++++
 src/sourcetree/items/LovedTracksItem.h   |  52 +++++++++++
 src/sourcetree/items/SourceItem.cpp      |  33 +------
 src/sourcetree/items/SourceItem.h        |   5 -
 8 files changed, 173 insertions(+), 37 deletions(-)
 create mode 100644 src/sourcetree/items/LovedTracksItem.cpp
 create mode 100644 src/sourcetree/items/LovedTracksItem.h

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dd7e8dff5..04fd31da5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -62,6 +62,7 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
      sourcetree/items/PlaylistItems.cpp
      sourcetree/items/CategoryItems.cpp
      sourcetree/items/GenericPageItems.cpp
+     sourcetree/items/LovedTracksItem.cpp
      sourcetree/items/TemporaryPageItem.cpp
      sourcetree/items/GroupItem.cpp
      sourcetree/items/HistoryItem.cpp
diff --git a/src/sourcetree/SourceDelegate.cpp b/src/sourcetree/SourceDelegate.cpp
index 389329017..742699ec0 100644
--- a/src/sourcetree/SourceDelegate.cpp
+++ b/src/sourcetree/SourceDelegate.cpp
@@ -128,6 +128,7 @@ SourceDelegate::paintDecorations( QPainter* painter, const QStyleOptionViewItem&
         type == SourcesModel::AutomaticPlaylist ||
         type == SourcesModel::Station ||
         type == SourcesModel::TemporaryPage ||
+        type == SourcesModel::LovedTracksPage ||
         type == SourcesModel::GenericPage );
     const bool playing = ( AudioEngine::instance()->isPlaying() || AudioEngine::instance()->isPaused() );
 
diff --git a/src/sourcetree/SourceTreeView.cpp b/src/sourcetree/SourceTreeView.cpp
index b840bae33..64e94b357 100644
--- a/src/sourcetree/SourceTreeView.cpp
+++ b/src/sourcetree/SourceTreeView.cpp
@@ -702,6 +702,7 @@ SourceTreeView::dropEvent( QDropEvent* event )
     const QModelIndex index = indexAt( pos );
 
     if ( model()->data( index, SourcesModel::SourceTreeItemTypeRole ).toInt() == SourcesModel::StaticPlaylist
+         || model()->data( index, SourcesModel::SourceTreeItemTypeRole ).toInt() == SourcesModel::LovedTracksPage
          || model()->data( index, SourcesModel::SourceTreeItemTypeRole ).toInt() == SourcesModel::CategoryAdd )
     {
         SourceTreeItem* item = itemFromIndex< SourceTreeItem >( index );
diff --git a/src/sourcetree/SourcesModel.h b/src/sourcetree/SourcesModel.h
index b570cf8a0..eea811d14 100644
--- a/src/sourcetree/SourcesModel.h
+++ b/src/sourcetree/SourcesModel.h
@@ -61,7 +61,8 @@ public:
         Station = 5,
 
         GenericPage = 6,
-        TemporaryPage = 7
+        TemporaryPage = 7,
+        LovedTracksPage = 10
     };
 
     enum CategoryType {
diff --git a/src/sourcetree/items/LovedTracksItem.cpp b/src/sourcetree/items/LovedTracksItem.cpp
new file mode 100644
index 000000000..8b468b99c
--- /dev/null
+++ b/src/sourcetree/items/LovedTracksItem.cpp
@@ -0,0 +1,114 @@
+/*
+ *    Copyright 2012, Christopher Reichert <creichert07@gmail.com>
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "LovedTracksItem.h"
+
+#include "SourceTreeItem.h"
+#include "SourceItem.h"
+
+#include "DropJob.h"
+#include "ViewManager.h"
+
+#include "playlist/CustomPlaylistView.h"
+#include "playlist/PlaylistLargeItemDelegate.h"
+
+using namespace Tomahawk;
+
+
+LovedTracksItem::LovedTracksItem( SourcesModel* mdl, SourceTreeItem* parent )
+    : SourceTreeItem( mdl, parent, SourcesModel::LovedTracksPage )
+    , m_lovedTracksPage( 0 )
+{
+}
+
+
+LovedTracksItem::~LovedTracksItem()
+{
+}
+
+
+void
+LovedTracksItem::activate()
+{
+    if ( !m_lovedTracksPage )
+    {
+        SourceItem* par = dynamic_cast< SourceItem* >( parent() );
+        if ( !par )
+            return;
+
+        CustomPlaylistView* view = new CustomPlaylistView( par->source().isNull() ? CustomPlaylistView::TopLovedTracks :
+                                            CustomPlaylistView::SourceLovedTracks, par->source(), ViewManager::instance()->widget() );
+        PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate(PlaylistLargeItemDelegate::LovedTracks, view, view->proxyModel() );
+        connect( del, SIGNAL( updateIndex( QModelIndex ) ), view, SLOT( update( QModelIndex ) ) );
+        view->setItemDelegate( del );
+        view->setEmptyTip( tr( "Sorry, we could not find any loved tracks!" ) );
+
+        m_lovedTracksPage = view;
+    }
+
+    ViewManager::instance()->show( m_lovedTracksPage );
+    model()->linkSourceItemToPage( this, m_lovedTracksPage );
+}
+
+
+bool
+LovedTracksItem::willAcceptDrag( const QMimeData* data ) const
+{
+    return DropJob::acceptsMimeData( data, DropJob::Track );
+}
+
+
+SourceTreeItem::DropTypes
+LovedTracksItem::supportedDropTypes( const QMimeData* data ) const
+{
+    if ( data->hasFormat( "application/tomahawk.result.list" ) ||
+         data->hasFormat( "application/tomahawk.query.list" ) )
+        return DropTypeThisTrack;
+
+    return DropTypesNone;
+}
+
+
+bool
+LovedTracksItem::dropMimeData( const QMimeData* data, Qt::DropAction action )
+{
+    Q_UNUSED( action );
+
+    QList< Tomahawk::query_ptr > queries;
+    if ( !DropJob::acceptsMimeData( data, DropJob::Track ) )
+        return false;
+
+    DropJob *dj = new DropJob();
+    dj->setDropTypes( DropJob::Track );
+    dj->setDropAction( DropJob::Append );
+
+    connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ),
+             this, SLOT( loveDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
+
+    dj->tracksFromMimeData( data, false, false );
+    return true;
+}
+
+
+void
+LovedTracksItem::loveDroppedTracks( QList< Tomahawk::query_ptr > qrys )
+{
+    foreach( Tomahawk::query_ptr qry, qrys )
+        qry->setLoved( true );
+}
+
diff --git a/src/sourcetree/items/LovedTracksItem.h b/src/sourcetree/items/LovedTracksItem.h
new file mode 100644
index 000000000..e2bec4ce1
--- /dev/null
+++ b/src/sourcetree/items/LovedTracksItem.h
@@ -0,0 +1,52 @@
+/*
+ *    Copyright 2012, Christopher Reichert <creichert07@gmail.com>
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef LOVED_TRACKS_ITEM_H
+#define LOVED_TRACKS_ITEM_H
+
+#include "SourceTreeItem.h"
+
+#include <QtCore/QString>
+#include <QtGui/QIcon>
+
+
+class LovedTracksItem : public SourceTreeItem
+{
+    Q_OBJECT
+
+public:
+    LovedTracksItem( SourcesModel* model, SourceTreeItem* parent );
+    virtual ~LovedTracksItem();
+
+    virtual QString text() const { return QString( tr( "Loved Tracks" ) ); }
+    virtual QIcon icon() const { return QIcon( RESPATH "images/loved_playlist.png" ); }
+    virtual int peerSortValue() const { return -150; }
+    virtual void activate();
+
+    virtual bool willAcceptDrag( const QMimeData* data ) const;
+    virtual DropTypes supportedDropTypes( const QMimeData* data ) const;
+    virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action );
+
+private slots:
+    void loveDroppedTracks( QList< Tomahawk::query_ptr > qrys );
+
+private:
+    Tomahawk::ViewPage* m_lovedTracksPage;
+};
+
+#endif
diff --git a/src/sourcetree/items/SourceItem.cpp b/src/sourcetree/items/SourceItem.cpp
index 4847d8512..1911cebd4 100644
--- a/src/sourcetree/items/SourceItem.cpp
+++ b/src/sourcetree/items/SourceItem.cpp
@@ -24,6 +24,7 @@
 #include "ViewManager.h"
 #include "Playlist.h"
 #include "GenericPageItems.h"
+#include "LovedTracksItem.h"
 #include "utils/TomahawkUtilsGui.h"
 #include "utils/Logger.h"
 #include "widgets/SocialPlaylistWidget.h"
@@ -50,7 +51,6 @@ SourceItem::SourceItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahaw
     , m_collectionPage( 0 )
     , m_sourceInfoPage( 0 )
     , m_coolPlaylistsPage( 0 )
-    , m_lovedTracksPage( 0 )
     , m_latestAdditionsPage( 0 )
     , m_recentPlaysPage( 0 )
     , m_whatsHotPage( 0 )
@@ -77,15 +77,12 @@ SourceItem::SourceItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahaw
                                              boost::bind( &SourceItem::recentPlaysClicked, this ),
                                              boost::bind( &SourceItem::getRecentPlaysPage, this ) );
 
-    m_lovedTracksItem = new GenericPageItem( model(), this, tr( "Loved Tracks" ), QIcon( RESPATH "images/loved_playlist.png" ),
-                                             boost::bind( &SourceItem::lovedTracksClicked, this ),
-                                             boost::bind( &SourceItem::getLovedTracksPage, this ) );
+    new LovedTracksItem( model(), this );
 
     m_collectionItem->setSortValue( -350 );
 //    m_sourceInfoItem->setSortValue( -300 );
     m_latestAdditionsItem->setSortValue( -250 );
     m_recentPlaysItem->setSortValue( -200 );
-    m_lovedTracksItem->setSortValue( -150 );
 
     // create category items if there are playlists to show, or stations to show
     QList< playlist_ptr > playlists = source->collection()->playlists();
@@ -506,32 +503,6 @@ SourceItem::getCoolPlaylistsPage() const
 }
 
 
-ViewPage*
-SourceItem::lovedTracksClicked()
-{
-    if ( !m_lovedTracksPage )
-    {
-        CustomPlaylistView* view = new CustomPlaylistView( m_source.isNull() ? CustomPlaylistView::TopLovedTracks : CustomPlaylistView::SourceLovedTracks, m_source, ViewManager::instance()->widget() );
-        PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::LovedTracks, view, view->proxyModel() );
-        connect( del, SIGNAL( updateIndex( QModelIndex ) ), view, SLOT( update( QModelIndex ) ) );
-        view->setItemDelegate( del );
-        view->setEmptyTip( tr( "Sorry, we could not find any loved tracks!" ) );
-
-        m_lovedTracksPage = view;
-    }
-
-    ViewManager::instance()->show( m_lovedTracksPage );
-    return m_lovedTracksPage;
-}
-
-
-ViewPage*
-SourceItem::getLovedTracksPage() const
-{
-    return m_lovedTracksPage;
-}
-
-
 ViewPage*
 SourceItem::latestAdditionsClicked()
 {
diff --git a/src/sourcetree/items/SourceItem.h b/src/sourcetree/items/SourceItem.h
index cd6711735..891db69a9 100644
--- a/src/sourcetree/items/SourceItem.h
+++ b/src/sourcetree/items/SourceItem.h
@@ -79,9 +79,6 @@ private slots:
     Tomahawk::ViewPage* coolPlaylistsClicked();
     Tomahawk::ViewPage* getCoolPlaylistsPage() const;
 
-    Tomahawk::ViewPage* lovedTracksClicked();
-    Tomahawk::ViewPage* getLovedTracksPage() const;
-
     Tomahawk::ViewPage* latestAdditionsClicked();
     Tomahawk::ViewPage* getLatestAdditionsPage() const;
 
@@ -104,14 +101,12 @@ private:
     GenericPageItem* m_collectionItem;
     GenericPageItem* m_sourceInfoItem;
     GenericPageItem* m_coolPlaylistsItem;
-    GenericPageItem* m_lovedTracksItem;
     GenericPageItem* m_latestAdditionsItem;
     GenericPageItem* m_recentPlaysItem;
 
     Tomahawk::ViewPage* m_collectionPage;
     Tomahawk::ViewPage* m_sourceInfoPage;
     Tomahawk::ViewPage* m_coolPlaylistsPage;
-    Tomahawk::ViewPage* m_lovedTracksPage;
     Tomahawk::ViewPage* m_latestAdditionsPage;
     Tomahawk::ViewPage* m_recentPlaysPage;
     Tomahawk::ViewPage* m_whatsHotPage;