From e989bc16529ccb653f6ddea62bcf8ba055b0923f Mon Sep 17 00:00:00 2001 From: Stefan Derkits Date: Wed, 21 Dec 2011 14:30:24 +0100 Subject: [PATCH 01/11] Parse Grooveshark playlists on drag & drop not much error handling yet, but it works ;) --- src/libtomahawk/CMakeLists.txt | 2 + src/libtomahawk/dropjob.cpp | 30 +++ src/libtomahawk/dropjob.h | 1 + src/libtomahawk/utils/groovesharkparser.cpp | 258 ++++++++++++++++++++ src/libtomahawk/utils/groovesharkparser.h | 81 ++++++ 5 files changed, 372 insertions(+) create mode 100644 src/libtomahawk/utils/groovesharkparser.cpp create mode 100644 src/libtomahawk/utils/groovesharkparser.h diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 3c275a63b..121cfdfc9 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -101,6 +101,7 @@ set( libGuiSources utils/m3uloader.cpp utils/itunesparser.cpp utils/rdioparser.cpp + utils/groovesharkparser.cpp utils/shortenedlinkparser.cpp utils/stylehelper.cpp utils/dropjobnotifier.cpp @@ -218,6 +219,7 @@ set( libGuiHeaders utils/m3uloader.h utils/itunesparser.h utils/rdioparser.h + utils/groovesharkparser.h utils/shortenedlinkparser.h utils/dropjobnotifier.h utils/tomahawkutilsgui.h diff --git a/src/libtomahawk/dropjob.cpp b/src/libtomahawk/dropjob.cpp index 88e2b52fb..9a83f9c1a 100644 --- a/src/libtomahawk/dropjob.cpp +++ b/src/libtomahawk/dropjob.cpp @@ -26,6 +26,7 @@ #include "utils/spotifyparser.h" #include "utils/itunesparser.h" #include "utils/rdioparser.h" +#include "utils/groovesharkparser.h" #include "utils/m3uloader.h" #include "utils/shortenedlinkparser.h" #include "utils/logger.h" @@ -120,6 +121,9 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType // Not the most elegant if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists ) return true; + + if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) ) + return true; } if ( acceptedType.testFlag( Track ) ) @@ -188,6 +192,9 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data ) if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) ) return true; + + if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) ) + return true; if ( ShortenedLinkParser::handlesUrl( url ) ) return true; @@ -555,6 +562,27 @@ DropJob::handleRdioUrls( const QString& urlsRaw ) rdio->parse( urls ); } +void +DropJob::handleGroovesharkUrls ( const QString& urlsRaw ) +{ + QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts ); + tDebug() << "Got Grooveshark urls!" << urls; + + if ( dropAction() == Default ) + setDropAction( Create ); + + GroovesharkParser* groove = new GroovesharkParser( urls, dropAction() == Create, this ); + connect( groove, SIGNAL( tracks( QList ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) ); + + if ( dropAction() == Append ) + { + tDebug() << Q_FUNC_INFO << "Asking for grooveshark contents from" << urls; + connect( groove, SIGNAL( tracks( QList ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) ); + m_queryCount++; + } +} + + void DropJob::handleAllUrls( const QString& urls ) @@ -569,6 +597,8 @@ DropJob::handleAllUrls( const QString& urls ) handleSpotifyUrls( urls ); else if ( urls.contains( "rdio.com" ) ) handleRdioUrls( urls ); + else if ( urls.contains( "grooveshark.com" ) ) + handleGroovesharkUrls( urls ); else handleTrackUrls ( urls ); } diff --git a/src/libtomahawk/dropjob.h b/src/libtomahawk/dropjob.h index eda72504e..71ca32787 100644 --- a/src/libtomahawk/dropjob.h +++ b/src/libtomahawk/dropjob.h @@ -106,6 +106,7 @@ public: void handleM3u( const QString& urls ); void handleSpotifyUrls( const QString& urls ); void handleRdioUrls( const QString& urls ); + void handleGroovesharkUrls( const QString& urls ); static bool canParseSpotifyPlaylists() { return s_canParseSpotifyPlaylists; } static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; } diff --git a/src/libtomahawk/utils/groovesharkparser.cpp b/src/libtomahawk/utils/groovesharkparser.cpp new file mode 100644 index 000000000..8fc95ebca --- /dev/null +++ b/src/libtomahawk/utils/groovesharkparser.cpp @@ -0,0 +1,258 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Stefan Derkits + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#include "groovesharkparser.h" + +#include "utils/logger.h" +#include "utils/tomahawkutils.h" +#include "query.h" +#include "sourcelist.h" +#include "dropjob.h" +#include "jobview/JobStatusView.h" +#include "jobview/JobStatusModel.h" +#include "dropjobnotifier.h" +#include "viewmanager.h" + +#include + +#include + +#include +#include +#include + +using namespace Tomahawk; + +QPixmap* GroovesharkParser::s_pixmap = 0; + +const char* enApiSecret = "erCj5s0Vebyqtc9Aduyotc1CLListJ9HfO2os5hBeew="; + +GroovesharkParser::GroovesharkParser( const QStringList& trackUrls, bool createNewPlaylist, QObject* parent ) + : QObject ( parent ) + , m_limit ( 40 ) + , m_trackMode( true ) + , m_createNewPlaylist( createNewPlaylist ) + , m_browseJob( 0 ) +{ + foreach ( const QString& url, trackUrls ) + lookupUrl( url ); +} + +GroovesharkParser::~GroovesharkParser() +{ + +} + +void +GroovesharkParser::lookupUrl( const QString& link ) +{ + if( link.contains( "playlist" ) ) + { + if( !m_createNewPlaylist ) + m_trackMode = true; + else + m_trackMode = false; + + lookupGroovesharkPlaylist( link ); + } + else + return; + +} + + +void +GroovesharkParser::lookupGroovesharkPlaylist( const QString& linkRaw ) +{ + tLog() << "Parsing Grooveshark Playlist URI:" << linkRaw; + QString browseUri = linkRaw; + + QStringList urlParts = linkRaw.split("/"); + bool ok; + int playlistID = urlParts.last().toInt(&ok, 10); + if (!ok) + { + tDebug() << "incorrect grooveshark url"; + return; + } + + m_title = urlParts.at(urlParts.size()-2); + + tDebug() << "should get playlist " << playlistID; + + DropJob::DropType type; + + if ( browseUri.contains( "playlist" ) ) + type = DropJob::Playlist; + + QString base_url("http://api.grooveshark.com/ws3.php?sig="); + + QByteArray data = QString("{\"method\":\"getPlaylistSongs\",\"parameters\":{\"playlistID\":\"%1\"},\"header\":{\"wsKey\":\"tomahawkplayer\"}}").arg(playlistID).toLocal8Bit(); + + QByteArray magic = QByteArray::fromBase64( enApiSecret ); + + QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() ); + int length = magic.length(), n2 = wand.length(); + for ( int i=0; ipost( QNetworkRequest( url ), data ); + connect( reply, SIGNAL( finished() ), this, SLOT( groovesharkLookupFinished() ) ); + + //m_browseJob = new DropJobNotifier( pixmap(), "Grooveshark", type, reply ); + //JobStatusView::instance()->model()->addJob( m_browseJob ); + + m_queries.insert( reply ); +} + +void +GroovesharkParser::groovesharkLookupFinished() +{ + QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() ); + Q_ASSERT( r ); + + m_queries.remove( r ); + r->deleteLater(); + + if ( r->error() == QNetworkReply::NoError ) + { + QJson::Parser p; + bool ok; + QVariantMap res = p.parse( r, &ok ).toMap(); + + if ( !ok ) + { + tLog() << "Failed to parse json from Grooveshark browse item :" << p.errorString() << "On line" << p.errorLine(); + checkTrackFinished(); + return; + } + + //tDebug() << "parsed grooveshark result into a map " << res; + //tDebug() << "results " << res.value("result") << " which is of type " << res.value("result").type(); + QVariantList list = res.value("result").toMap().value("songs").toList(); + foreach (const QVariant& var, list) + { + QVariantMap trackResult = var.toMap(); + //tDebug() << map; + + QString title, artist, album; + + title = trackResult.value( "SongName", QString() ).toString(); + artist = trackResult.value( "ArtistName", QString() ).toString(); + album = trackResult.value( "AlbumName", QString() ).toString(); + + if ( title.isEmpty() && artist.isEmpty() ) // don't have enough... + { + tLog() << "Didn't get an artist and track name from spotify, not enough to build a query on. Aborting" << title << artist << album; + return; + } + + Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), m_trackMode ); + m_tracks << q; + } + + + } else + { + tLog() << "Error in network request to grooveshark for track decoding:" << r->errorString(); + } + + if ( m_trackMode ) + checkTrackFinished(); + else + checkBrowseFinished(); +} + +void +GroovesharkParser::checkBrowseFinished() +{ + tDebug() << "Checking for grooveshark batch playlist job finished" << m_queries.isEmpty() << m_createNewPlaylist; + if ( m_queries.isEmpty() ) // we're done + { + if ( m_browseJob ) + m_browseJob->setFinished(); + + if( m_createNewPlaylist && !m_tracks.isEmpty() ) + { + m_playlist = Playlist::create( SourceList::instance()->getLocal(), + uuid(), + m_title, + m_info, + m_creator, + false, + m_tracks ); + connect( m_playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistCreated() ) ); + return; + } + + + emit tracks( m_tracks ); + + deleteLater(); + } +} + +void +GroovesharkParser::checkTrackFinished() +{ + tDebug() << "Checking for grooveshark batch track job finished" << m_queries.isEmpty(); + if ( m_queries.isEmpty() ) // we're done + { + if ( m_browseJob ) + m_browseJob->setFinished(); + + emit tracks( m_tracks ); + + deleteLater(); + } + +} + +void +GroovesharkParser::playlistCreated() +{ + + ViewManager::instance()->show( m_playlist ); + + deleteLater(); +} + + +QPixmap +GroovesharkParser::pixmap() const +{ + if ( !s_pixmap ) + s_pixmap = new QPixmap( RESPATH "images/spotify-logo.png" ); + + return *s_pixmap; +} \ No newline at end of file diff --git a/src/libtomahawk/utils/groovesharkparser.h b/src/libtomahawk/utils/groovesharkparser.h new file mode 100644 index 000000000..7a62e87de --- /dev/null +++ b/src/libtomahawk/utils/groovesharkparser.h @@ -0,0 +1,81 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Stefan Derkits + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#ifndef GROOVESHARKPARSER_H +#define GROOVESHARKPARSER_H + +#include "dllmacro.h" +#include "typedefs.h" +#include "query.h" +#include "jobview/JobStatusItem.h" + +#include +#include +#include + +/** + * Small class to parse grooveshark links into query_ptrs + * + * Connect to the signals to get the results + */ + +class QNetworkReply; + +namespace Tomahawk +{ + +class DropJobNotifier; + +class DLLEXPORT GroovesharkParser : public QObject +{ + Q_OBJECT +public: + explicit GroovesharkParser( const QStringList& trackUrls, bool createNewPlaylist = false, QObject* parent = 0 ); + virtual ~GroovesharkParser(); +signals: + void track( const Tomahawk::query_ptr& track ); + void tracks( const QList< Tomahawk::query_ptr > tracks ); + void playlist( const Tomahawk::query_ptr& playlist ); + +private slots: + void groovesharkLookupFinished(); + + void playlistCreated(); +private: + QPixmap pixmap() const; + + void lookupUrl( const QString& url ); + void lookupGroovesharkPlaylist( const QString& playlist ); + void checkTrackFinished(); + void checkBrowseFinished(); + int m_limit; + bool m_trackMode; + bool m_createNewPlaylist; + QList< query_ptr > m_tracks; + QSet< QNetworkReply* > m_queries; + QString m_title, m_info, m_creator; + Tomahawk::playlist_ptr m_playlist; + DropJobNotifier* m_browseJob; + + static QPixmap* s_pixmap; + +}; + +} + +#endif // GROOVESHARKPARSER_H From 2e25337cc11bc8fec4ceef895d9d9421e8583f0c Mon Sep 17 00:00:00 2001 From: Stefan Derkits Date: Thu, 22 Dec 2011 23:59:16 +0100 Subject: [PATCH 02/11] Small changes in groovesharkparser --- src/libtomahawk/utils/groovesharkparser.cpp | 58 ++++++++++----------- src/libtomahawk/utils/groovesharkparser.h | 10 +++- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/libtomahawk/utils/groovesharkparser.cpp b/src/libtomahawk/utils/groovesharkparser.cpp index 8fc95ebca..6ee245c56 100644 --- a/src/libtomahawk/utils/groovesharkparser.cpp +++ b/src/libtomahawk/utils/groovesharkparser.cpp @@ -1,5 +1,7 @@ /* === This file is part of Tomahawk Player - === * + * Copyright 2010-2011, Leo Franchi + * Copyright 2010-2011, Hugo Lindström * Copyright 2010-2011, Stefan Derkits * * Tomahawk is free software: you can redistribute it and/or modify @@ -49,6 +51,14 @@ GroovesharkParser::GroovesharkParser( const QStringList& trackUrls, bool createN , m_createNewPlaylist( createNewPlaylist ) , m_browseJob( 0 ) { + QByteArray magic = QByteArray::fromBase64( enApiSecret ); + + QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() ); + int length = magic.length(), n2 = wand.length(); + for ( int i=0; ipost( QNetworkRequest( url ), data ); connect( reply, SIGNAL( finished() ), this, SLOT( groovesharkLookupFinished() ) ); - //m_browseJob = new DropJobNotifier( pixmap(), "Grooveshark", type, reply ); - //JobStatusView::instance()->model()->addJob( m_browseJob ); + m_browseJob = new DropJobNotifier( pixmap(), "Grooveshark", type, reply ); + JobStatusView::instance()->model()->addJob( m_browseJob ); m_queries.insert( reply ); } @@ -157,13 +158,10 @@ GroovesharkParser::groovesharkLookupFinished() return; } - //tDebug() << "parsed grooveshark result into a map " << res; - //tDebug() << "results " << res.value("result") << " which is of type " << res.value("result").type(); - QVariantList list = res.value("result").toMap().value("songs").toList(); + QVariantList list = res.value( "result" ).toMap().value( "songs" ).toList(); foreach (const QVariant& var, list) { QVariantMap trackResult = var.toMap(); - //tDebug() << map; QString title, artist, album; @@ -173,7 +171,7 @@ GroovesharkParser::groovesharkLookupFinished() if ( title.isEmpty() && artist.isEmpty() ) // don't have enough... { - tLog() << "Didn't get an artist and track name from spotify, not enough to build a query on. Aborting" << title << artist << album; + tLog() << "Didn't get an artist and track name from grooveshark, not enough to build a query on. Aborting" << title << artist << album; return; } @@ -190,11 +188,11 @@ GroovesharkParser::groovesharkLookupFinished() if ( m_trackMode ) checkTrackFinished(); else - checkBrowseFinished(); + checkPlaylistFinished(); } void -GroovesharkParser::checkBrowseFinished() +GroovesharkParser::checkPlaylistFinished() { tDebug() << "Checking for grooveshark batch playlist job finished" << m_queries.isEmpty() << m_createNewPlaylist; if ( m_queries.isEmpty() ) // we're done @@ -252,7 +250,7 @@ QPixmap GroovesharkParser::pixmap() const { if ( !s_pixmap ) - s_pixmap = new QPixmap( RESPATH "images/spotify-logo.png" ); + s_pixmap = new QPixmap( RESPATH "images/grooveshark.png" ); return *s_pixmap; -} \ No newline at end of file +} diff --git a/src/libtomahawk/utils/groovesharkparser.h b/src/libtomahawk/utils/groovesharkparser.h index 7a62e87de..a387ed928 100644 --- a/src/libtomahawk/utils/groovesharkparser.h +++ b/src/libtomahawk/utils/groovesharkparser.h @@ -1,6 +1,8 @@ /* === This file is part of Tomahawk Player - === * - * Copyright 2010-2011, Stefan Derkits + * Copyright 2010-2011, Leo Franchi + * Copyright 2010-2011, Hugo Lindström + * Copyright 2011, Stefan Derkits * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +26,8 @@ #include "query.h" #include "jobview/JobStatusItem.h" +#include + #include #include #include @@ -62,7 +66,7 @@ private: void lookupUrl( const QString& url ); void lookupGroovesharkPlaylist( const QString& playlist ); void checkTrackFinished(); - void checkBrowseFinished(); + void checkPlaylistFinished(); int m_limit; bool m_trackMode; bool m_createNewPlaylist; @@ -72,6 +76,8 @@ private: Tomahawk::playlist_ptr m_playlist; DropJobNotifier* m_browseJob; + QCA::SymmetricKey m_apiKey; + static QPixmap* s_pixmap; }; From c4c74d84dc4dacc63f1841ef27559149a56041de Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Thu, 22 Dec 2011 20:29:54 -0500 Subject: [PATCH 03/11] Show search widget on qt 4.8 --- src/libtomahawk/thirdparty/Qocoa/qocoa_mac.h | 1 + src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp | 2 +- src/libtomahawk/thirdparty/Qocoa/qsearchfield_mac.mm | 2 -- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libtomahawk/thirdparty/Qocoa/qocoa_mac.h b/src/libtomahawk/thirdparty/Qocoa/qocoa_mac.h index d86f9ad27..1b6963d11 100644 --- a/src/libtomahawk/thirdparty/Qocoa/qocoa_mac.h +++ b/src/libtomahawk/thirdparty/Qocoa/qocoa_mac.h @@ -45,6 +45,7 @@ static inline void zeroLayout(void *cocoaView, QWidget *parent) { QVBoxLayout *layout = new QVBoxLayout(parent); layout->setMargin(0); + parent->setAttribute(Qt::WA_NativeWindow); layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent)); } diff --git a/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp b/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp index a1da7af8c..7772755e8 100644 --- a/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp +++ b/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp @@ -27,7 +27,7 @@ THE SOFTWARE. #include #include "playlist/topbar/searchlineedit.h" -#include "utils/tomahawkutilsgui.h" +#include "utils/tomahawkutils.h" class DLLEXPORT QSearchFieldPrivate { diff --git a/src/libtomahawk/thirdparty/Qocoa/qsearchfield_mac.mm b/src/libtomahawk/thirdparty/Qocoa/qsearchfield_mac.mm index 5f60cf1e8..120a8c291 100644 --- a/src/libtomahawk/thirdparty/Qocoa/qsearchfield_mac.mm +++ b/src/libtomahawk/thirdparty/Qocoa/qsearchfield_mac.mm @@ -25,8 +25,6 @@ THE SOFTWARE. #include "qocoa_mac.h" -#include "qsearchfield.h" - #import "Foundation/NSAutoreleasePool.h" #import "Foundation/NSNotification.h" #import "AppKit/NSSearchField.h" From 3987ce7690939f1e3b903c7c39ebee5d2fcba06b Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Fri, 23 Dec 2011 08:00:25 -0600 Subject: [PATCH 04/11] Load chart data objects in a thread, as they call synchronous db methods --- src/libtomahawk/CMakeLists.txt | 2 + .../infoplugins/generic/chartsplugin.cpp | 8 +- src/libtomahawk/widgets/ChartDataLoader.cpp | 72 +++++++++++ src/libtomahawk/widgets/ChartDataLoader.h | 67 ++++++++++ src/libtomahawk/widgets/whatshotwidget.cpp | 114 +++++++++++++----- src/libtomahawk/widgets/whatshotwidget.h | 15 +++ src/mac/tomahawkapp_mac.mm | 1 + 7 files changed, 243 insertions(+), 36 deletions(-) create mode 100644 src/libtomahawk/widgets/ChartDataLoader.cpp create mode 100644 src/libtomahawk/widgets/ChartDataLoader.h diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 121cfdfc9..46ae46ab2 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -119,6 +119,7 @@ set( libGuiSources widgets/playlisttypeselectordlg.cpp widgets/welcomewidget.cpp widgets/whatshotwidget.cpp + widgets/ChartDataLoader.cpp widgets/RecentlyPlayedPlaylistsModel.cpp widgets/RecentPlaylistsModel.cpp widgets/OverlayButton.cpp @@ -237,6 +238,7 @@ set( libGuiHeaders widgets/welcomewidget.h widgets/whatshotwidget.h widgets/whatshotwidget_p.h + widgets/ChartDataLoader.h widgets/RecentlyPlayedPlaylistsModel.h widgets/RecentPlaylistsModel.h widgets/OverlayButton.h diff --git a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp index 02eff8d12..8c719f021 100644 --- a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp @@ -453,7 +453,7 @@ ChartsPlugin::chartReturned() QVariantList chartResponse = res.value( "list" ).toList(); QList< Tomahawk::InfoSystem::InfoStringHash > top_tracks; QList< Tomahawk::InfoSystem::InfoStringHash > top_albums; - QStringList top_artists; + QList< Tomahawk::InfoSystem::InfoStringHash > top_artists; /// Deside what type, we need to handle it differently /// @todo: We allready know the type, append it to breadcrumb hash @@ -528,7 +528,9 @@ ChartsPlugin::chartReturned() } else { - top_artists.append( artist ); + Tomahawk::InfoSystem::InfoStringHash artistHash; + artistHash["artist"] = artist; + top_artists.append( artistHash ); } } @@ -538,7 +540,7 @@ ChartsPlugin::chartReturned() if( chartType() == Artist ) { tDebug() << "ChartsPlugin:" << "\tgot " << top_artists.size() << " artists"; - returnedData[ "artists" ] = QVariant::fromValue< QStringList >( top_artists ); + returnedData[ "artists" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_artists ); returnedData[ "type" ] = "artists"; } diff --git a/src/libtomahawk/widgets/ChartDataLoader.cpp b/src/libtomahawk/widgets/ChartDataLoader.cpp new file mode 100644 index 000000000..363270fb6 --- /dev/null +++ b/src/libtomahawk/widgets/ChartDataLoader.cpp @@ -0,0 +1,72 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Leo Franchi + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ +#include "ChartDataLoader.h" + +using namespace Tomahawk; + + +ChartDataLoader::ChartDataLoader() + : QObject( 0 ) +{ +} + +void +ChartDataLoader::go() +{ + qDebug() << "CHART LOADING DATA!" << QThread::currentThreadId(); + switch ( m_type ) + { + case Track: + { + QList< query_ptr > track_ptrs; + foreach ( const Tomahawk::InfoSystem::InfoStringHash& track, m_data ) + { + track_ptrs << Query::get( track[ "artist" ], track[ "track" ], QString(), uuid(), false ); + } + + emit tracks( this, track_ptrs ); + break; + } + case Artist: + { + QList< artist_ptr > artist_ptrs; + + foreach ( const Tomahawk::InfoSystem::InfoStringHash& artistname, m_data ) { + artist_ptrs << Artist::get( artistname[ "artist" ], false ); + } + + emit artists( this, artist_ptrs ); + break; + } + case Album: + { + QList< album_ptr > album_ptrs; + + foreach ( const Tomahawk::InfoSystem::InfoStringHash& album, m_data ) + { + tDebug( LOGVERBOSE) << Q_FUNC_INFO << "Getting album" << album[ "album" ] << "By" << album[ "artist" ]; + artist_ptr artistPtr = Artist::get( album[ "artist" ], false ); + album_ptr albumPtr = Album::get( artistPtr, album[ "album" ], false ); + album_ptrs << albumPtr; + } + + emit albums( this, album_ptrs ); + break; + } + } +} diff --git a/src/libtomahawk/widgets/ChartDataLoader.h b/src/libtomahawk/widgets/ChartDataLoader.h new file mode 100644 index 000000000..001cacc52 --- /dev/null +++ b/src/libtomahawk/widgets/ChartDataLoader.h @@ -0,0 +1,67 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Leo Franchi + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ +#ifndef CHARTDATALOADER_H +#define CHARTDATALOADER_H + +#include "infosystem/infosystem.h" +#include "query.h" +#include "artist.h" +#include "album.h" + +#include + +namespace Tomahawk +{ + +/** + Synchronous loading of track, artist, album objects from the db + into their respective tomahawk types. Move this object to a thread + and listen to the result signals. +*/ +class ChartDataLoader : public QObject +{ + Q_OBJECT +public: + enum DataType { + Track, + Artist, + Album + }; + + ChartDataLoader(); + + void setType( DataType type ) { m_type = type; } + void setData( const QList< InfoSystem::InfoStringHash >& data ) { m_data = data; } + +public slots: + void go(); + +signals: + void tracks( Tomahawk::ChartDataLoader*, const QList< Tomahawk::query_ptr >& tracks ); + void artists( Tomahawk::ChartDataLoader*, const QList< Tomahawk::artist_ptr >& artists ); + void albums( Tomahawk::ChartDataLoader*, const QList< Tomahawk::album_ptr >& albums ); + + +private: + DataType m_type; + QList m_data; +}; + +} + +#endif // CHARTDATALOADER_H diff --git a/src/libtomahawk/widgets/whatshotwidget.cpp b/src/libtomahawk/widgets/whatshotwidget.cpp index cd4e5cec8..69cdab9ec 100644 --- a/src/libtomahawk/widgets/whatshotwidget.cpp +++ b/src/libtomahawk/widgets/whatshotwidget.cpp @@ -29,6 +29,7 @@ #include "sourcelist.h" #include "tomahawksettings.h" #include "RecentPlaylistsModel.h" +#include "ChartDataLoader.h" #include "audio/audioengine.h" #include "dynamic/GeneratorInterface.h" @@ -53,6 +54,7 @@ WhatsHotWidget::WhatsHotWidget( QWidget* parent ) , ui( new Ui::WhatsHotWidget ) , m_playlistInterface( 0 ) , m_sortedProxy( 0 ) + , m_workerThread( 0 ) { ui->setupUi( this ); @@ -94,6 +96,9 @@ WhatsHotWidget::WhatsHotWidget( QWidget* parent ) m_playlistInterface = new ChartsPlaylistInterface( this ); + m_workerThread = new QThread( this ); + m_workerThread->start(); + connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); @@ -106,6 +111,7 @@ WhatsHotWidget::WhatsHotWidget( QWidget* parent ) WhatsHotWidget::~WhatsHotWidget() { + m_workerThread->exit(0); delete m_playlistInterface; delete ui; } @@ -239,68 +245,61 @@ WhatsHotWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestDat const QString chartId = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >().value( "chart_id" ); m_queuedFetches.remove( chartId ); - if( type == "artists" ) + + ChartDataLoader* loader = new ChartDataLoader(); + loader->setProperty( "chartid", chartId ); + loader->moveToThread( m_workerThread ); + + qDebug() << "SCHEDULING LOADING FROM THREAD:" << QThread::currentThreadId(); + if ( type == "artists" ) { - const QStringList artists = returnedData["artists"].toStringList(); + loader->setType( ChartDataLoader::Artist ); + loader->setData( returnedData[ "artists" ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >() ); + + connect( loader, SIGNAL( artists( Tomahawk::ChartDataLoader*, QList< Tomahawk::artist_ptr > ) ), this, SLOT( chartArtistsLoaded( Tomahawk::ChartDataLoader*, QList< Tomahawk::artist_ptr > ) ) ); TreeModel* artistsModel = new TreeModel( ui->artistsViewLeft ); artistsModel->setColumnStyle( TreeModel::TrackOnly ); - foreach ( const QString& artist, artists ) - { - artist_ptr artistPtr = Artist::get( artist, false ); - artistsModel->addArtists( artistPtr ); - } m_artistModels[ chartId ] = artistsModel; if ( m_queueItemToShow == chartId ) setLeftViewArtists( artistsModel ); } - else if( type == "albums" ) + else if ( type == "albums" ) { - QList al; - const QList< Tomahawk::InfoSystem::InfoStringHash > albums = returnedData[ "albums" ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >(); + + loader->setType( ChartDataLoader::Album ); + loader->setData( returnedData[ "albums" ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >() ); + + connect( loader, SIGNAL( albums( Tomahawk::ChartDataLoader*, QList< Tomahawk::album_ptr > ) ), this, SLOT( chartAlbumsLoaded( Tomahawk::ChartDataLoader*, QList< Tomahawk::album_ptr > ) ) ); AlbumModel* albumModel = new AlbumModel( ui->additionsView ); - foreach ( const Tomahawk::InfoSystem::InfoStringHash& album, albums ) - { - tDebug( LOGVERBOSE) << Q_FUNC_INFO << "Getting album" << album[ "album" ] << "By" << album[ "artist" ]; - artist_ptr artistPtr = Artist::get( album[ "artist" ], false ); - album_ptr albumPtr = Album::get( artistPtr, album[ "album" ], false ); - al << albumPtr; - - } - albumModel->addAlbums( al ); m_albumModels[ chartId ] = albumModel; if ( m_queueItemToShow == chartId ) setLeftViewAlbums( albumModel ); } - else if( type == "tracks" ) + else if ( type == "tracks" ) { - const QList< Tomahawk::InfoSystem::InfoStringHash > tracks = returnedData[ "tracks" ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >(); + + loader->setType( ChartDataLoader::Track ); + loader->setData( returnedData[ "tracks" ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >() ); + + connect( loader, SIGNAL( tracks( Tomahawk::ChartDataLoader*, QList< Tomahawk::query_ptr > ) ), this, SLOT( chartTracksLoaded( Tomahawk::ChartDataLoader*, QList< Tomahawk::query_ptr > ) ) ); PlaylistModel* trackModel = new PlaylistModel( ui->tracksViewLeft ); trackModel->setStyle( TrackModel::Short ); - QList tracklist; - foreach ( const Tomahawk::InfoSystem::InfoStringHash& track, tracks ) - { - query_ptr query = Query::get( track[ "artist" ], track[ "track" ], QString(), uuid(), false ); - tracklist << query; - } - Pipeline::instance()->resolve( tracklist ); - trackModel->append( tracklist ); m_trackModels[ chartId ] = trackModel; if ( m_queueItemToShow == chartId ) setLeftViewTracks( trackModel ); } - else - { - tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "WhatsHot: got unknown chart type" << type; - } + + QMetaObject::invokeMethod( loader, "go", Qt::QueuedConnection ); + break; } @@ -473,3 +472,52 @@ WhatsHotWidget::setLeftViewTracks( PlaylistModel* model ) ui->tracksViewLeft->proxyModel()->sort( -1 ); ui->stackLeft->setCurrentIndex( 0 ); } + + +void +WhatsHotWidget::chartArtistsLoaded( ChartDataLoader* loader, const QList< artist_ptr >& artists ) +{ + qDebug() << "DOING CHART ARTIST DATA LOAD!"; + QString chartId = loader->property( "chartid" ).toString(); + Q_ASSERT( m_artistModels.contains( chartId ) ); + + if ( !m_artistModels.contains( chartId ) ) + { + foreach( const artist_ptr& artist, artists ) + m_artistModels[ chartId ]->addArtists( artist ); + } + + loader->deleteLater(); +} + + +void +WhatsHotWidget::chartTracksLoaded( ChartDataLoader* loader, const QList< query_ptr >& tracks ) +{ + + qDebug() << "DOING CHART TRACK DATA LOAD!"; + QString chartId = loader->property( "chartid" ).toString(); + Q_ASSERT( m_trackModels.contains( chartId ) ); + + if ( m_trackModels.contains( chartId ) ) + { + Pipeline::instance()->resolve( tracks ); + m_trackModels[ chartId ]->append( tracks ); + } + + loader->deleteLater(); +} + + +void +WhatsHotWidget::chartAlbumsLoaded( ChartDataLoader* loader, const QList< album_ptr >& albums ) +{ + qDebug() << "DOING CHART ALBUMS DATA LOAD!"; + QString chartId = loader->property( "chartid" ).toString(); + Q_ASSERT( m_albumModels.contains( chartId ) ); + + if ( m_albumModels.contains( chartId ) ) + m_albumModels[ chartId ]->addAlbums( albums ); + + loader->deleteLater(); +} diff --git a/src/libtomahawk/widgets/whatshotwidget.h b/src/libtomahawk/widgets/whatshotwidget.h index 392c39a32..5df378752 100644 --- a/src/libtomahawk/widgets/whatshotwidget.h +++ b/src/libtomahawk/widgets/whatshotwidget.h @@ -46,6 +46,11 @@ namespace Ui class WhatsHotWidget; } +namespace Tomahawk +{ + class ChartDataLoader; +} + /** * \class * \brief The tomahawk page that shows music charts. @@ -83,6 +88,11 @@ private slots: void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); void infoSystemFinished( QString target ); void leftCrumbIndexChanged( QModelIndex ); + + void chartArtistsLoaded( Tomahawk::ChartDataLoader*, const QList< Tomahawk::artist_ptr >& ); + void chartAlbumsLoaded( Tomahawk::ChartDataLoader*, const QList< Tomahawk::album_ptr >& ); + void chartTracksLoaded( Tomahawk::ChartDataLoader*, const QList< Tomahawk::query_ptr >& ); + private: void setLeftViewArtists( TreeModel* artistModel ); void setLeftViewAlbums( AlbumModel* albumModel ); @@ -96,6 +106,11 @@ private: QStandardItemModel* m_crumbModelLeft; QSortFilterProxyModel* m_sortedProxy; + // Load artist, album, and track objects in a thread + // {Artist,Album,Track}::get() calls are all synchronous db calls + // and we don't want to lock up out UI in case the db is busy (e.g. on startup) + QThread* m_workerThread; + // Cache our model data QHash< QString, AlbumModel* > m_albumModels; QHash< QString, TreeModel* > m_artistModels; diff --git a/src/mac/tomahawkapp_mac.mm b/src/mac/tomahawkapp_mac.mm index fae3e1d51..d5a0ca295 100644 --- a/src/mac/tomahawkapp_mac.mm +++ b/src/mac/tomahawkapp_mac.mm @@ -175,6 +175,7 @@ NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; OSStatus httpResult = LSSetDefaultHandlerForURLScheme((CFStringRef)@"tomahawk", (CFStringRef)bundleID); + Q_UNUSED(httpResult); //TODO: Check httpResult and httpsResult for errors } return self; From 06ac5cffb672f52f27fe510b66f18dd9ac28efb9 Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Fri, 23 Dec 2011 08:01:41 -0600 Subject: [PATCH 05/11] debug-- --- src/libtomahawk/widgets/ChartDataLoader.cpp | 1 - src/libtomahawk/widgets/whatshotwidget.cpp | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/libtomahawk/widgets/ChartDataLoader.cpp b/src/libtomahawk/widgets/ChartDataLoader.cpp index 363270fb6..9816b5f60 100644 --- a/src/libtomahawk/widgets/ChartDataLoader.cpp +++ b/src/libtomahawk/widgets/ChartDataLoader.cpp @@ -28,7 +28,6 @@ ChartDataLoader::ChartDataLoader() void ChartDataLoader::go() { - qDebug() << "CHART LOADING DATA!" << QThread::currentThreadId(); switch ( m_type ) { case Track: diff --git a/src/libtomahawk/widgets/whatshotwidget.cpp b/src/libtomahawk/widgets/whatshotwidget.cpp index 69cdab9ec..264b1187f 100644 --- a/src/libtomahawk/widgets/whatshotwidget.cpp +++ b/src/libtomahawk/widgets/whatshotwidget.cpp @@ -250,7 +250,6 @@ WhatsHotWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestDat loader->setProperty( "chartid", chartId ); loader->moveToThread( m_workerThread ); - qDebug() << "SCHEDULING LOADING FROM THREAD:" << QThread::currentThreadId(); if ( type == "artists" ) { loader->setType( ChartDataLoader::Artist ); @@ -477,7 +476,6 @@ WhatsHotWidget::setLeftViewTracks( PlaylistModel* model ) void WhatsHotWidget::chartArtistsLoaded( ChartDataLoader* loader, const QList< artist_ptr >& artists ) { - qDebug() << "DOING CHART ARTIST DATA LOAD!"; QString chartId = loader->property( "chartid" ).toString(); Q_ASSERT( m_artistModels.contains( chartId ) ); @@ -495,7 +493,6 @@ void WhatsHotWidget::chartTracksLoaded( ChartDataLoader* loader, const QList< query_ptr >& tracks ) { - qDebug() << "DOING CHART TRACK DATA LOAD!"; QString chartId = loader->property( "chartid" ).toString(); Q_ASSERT( m_trackModels.contains( chartId ) ); @@ -512,7 +509,6 @@ WhatsHotWidget::chartTracksLoaded( ChartDataLoader* loader, const QList< query_p void WhatsHotWidget::chartAlbumsLoaded( ChartDataLoader* loader, const QList< album_ptr >& albums ) { - qDebug() << "DOING CHART ALBUMS DATA LOAD!"; QString chartId = loader->property( "chartid" ).toString(); Q_ASSERT( m_albumModels.contains( chartId ) ); From cf4d0fe465a92022ed49214f586730cf2ba0e942 Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Fri, 23 Dec 2011 09:56:07 -0600 Subject: [PATCH 06/11] utils to utilsgui --- src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp b/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp index 7772755e8..a1da7af8c 100644 --- a/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp +++ b/src/libtomahawk/thirdparty/Qocoa/qsearchfield.cpp @@ -27,7 +27,7 @@ THE SOFTWARE. #include #include "playlist/topbar/searchlineedit.h" -#include "utils/tomahawkutils.h" +#include "utils/tomahawkutilsgui.h" class DLLEXPORT QSearchFieldPrivate { From 3875f0b6937f6eceffd5bd35bb92c0c68c56d12e Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Fri, 23 Dec 2011 05:45:52 +0100 Subject: [PATCH 07/11] * Auto expand group items. --- src/sourcetree/items/groupitem.cpp | 10 +++++++++- src/sourcetree/items/groupitem.h | 9 ++++++--- src/sourcetree/items/historyitem.h | 2 +- src/sourcetree/items/sourceitem.cpp | 1 - src/sourcetree/items/sourceitem.h | 4 +++- src/sourcetree/items/sourcetreeitem.h | 4 +++- src/sourcetree/sourcesmodel.cpp | 7 +++---- src/sourcetree/sourcetreeview.cpp | 18 ++++++++++-------- 8 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/sourcetree/items/groupitem.cpp b/src/sourcetree/items/groupitem.cpp index 57e8b56cd..01804c0ba 100644 --- a/src/sourcetree/items/groupitem.cpp +++ b/src/sourcetree/items/groupitem.cpp @@ -32,7 +32,8 @@ GroupItem::GroupItem( SourcesModel* model, SourceTreeItem* parent, const QString , m_text( text ) , m_peerSortValue( peerSortValue ) { - connect( this, SIGNAL( toggleExpandRequest( SourceTreeItem* ) ), model, SLOT( itemToggleExpandRequest( SourceTreeItem* ) ) ); + // expand by default + QTimer::singleShot( 0, this, SLOT( requestExpanding() ) ); } @@ -48,6 +49,13 @@ GroupItem::activate() } +void +GroupItem::requestExpanding() +{ + emit expandRequest( this ); +} + + QString GroupItem::text() const { diff --git a/src/sourcetree/items/groupitem.h b/src/sourcetree/items/groupitem.h index ae129b773..5f173ac0b 100644 --- a/src/sourcetree/items/groupitem.h +++ b/src/sourcetree/items/groupitem.h @@ -25,7 +25,6 @@ #include "boost/function.hpp" #include "boost/bind.hpp" -// generic item that has some name, some text, and calls a certain slot when activated. badabing! class GroupItem : public SourceTreeItem { Q_OBJECT @@ -35,15 +34,19 @@ public: virtual ~GroupItem(); virtual QString text() const; - virtual void activate(); virtual bool willAcceptDrag( const QMimeData* data ) const { Q_UNUSED( data ); return false; } virtual QIcon icon() const { return QIcon(); } virtual int peerSortValue() const { return m_peerSortValue; } virtual bool isBeingPlayed() const { return false; } +public slots: + virtual void activate(); + signals: void activated(); - void toggleExpandRequest( SourceTreeItem* ); + +private slots: + void requestExpanding(); private: QString m_text; diff --git a/src/sourcetree/items/historyitem.h b/src/sourcetree/items/historyitem.h index d3dd23449..7406d4e84 100644 --- a/src/sourcetree/items/historyitem.h +++ b/src/sourcetree/items/historyitem.h @@ -38,11 +38,11 @@ public: HistoryItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, int peerSortValue = 0 ); virtual ~HistoryItem(); +public slots: virtual void activate(); signals: void activated(); - void toggleExpandRequest( SourceTreeItem* ); private slots: void tempPageActivated( Tomahawk::ViewPage* ); diff --git a/src/sourcetree/items/sourceitem.cpp b/src/sourcetree/items/sourceitem.cpp index 5a78379ff..9eafeab36 100644 --- a/src/sourcetree/items/sourceitem.cpp +++ b/src/sourcetree/items/sourceitem.cpp @@ -158,7 +158,6 @@ SourceItem::activate() p = ViewManager::instance()->showSuperCollection(); else emit toggleExpandRequest( this ); -// p = ViewManager::instance()->show( source()->collection() ); model()->linkSourceItemToPage( this, p ); } diff --git a/src/sourcetree/items/sourceitem.h b/src/sourcetree/items/sourceitem.h index 7827721e3..0b9230a8e 100644 --- a/src/sourcetree/items/sourceitem.h +++ b/src/sourcetree/items/sourceitem.h @@ -37,7 +37,6 @@ public: SourceItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source ); virtual QString text() const; - virtual void activate(); virtual QIcon icon() const; virtual int peerSortValue() const; virtual int IDValue() const; @@ -51,6 +50,9 @@ public: void setStationsCategory( CategoryItem* item ) { m_stations = item; } void setPlaylistsCategory( CategoryItem* item ) { m_playlists = item; } +public slots: + virtual void activate(); + private slots: void onPlaylistsAdded( const QList& playlists ); void onPlaylistDeleted( const Tomahawk::playlist_ptr& playlists ); diff --git a/src/sourcetree/items/sourcetreeitem.h b/src/sourcetree/items/sourcetreeitem.h index 4e17f7e35..7e174b789 100644 --- a/src/sourcetree/items/sourcetreeitem.h +++ b/src/sourcetree/items/sourcetreeitem.h @@ -59,7 +59,6 @@ public: // varies depending on the type of the item virtual QString text() const { return QString(); } virtual Qt::ItemFlags flags() const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } - virtual void activate() {} virtual QIcon icon() const { return QIcon(); } virtual bool willAcceptDrag( const QMimeData* ) const { return false; } virtual bool dropMimeData( const QMimeData*, Qt::DropAction ) { return false; } @@ -77,6 +76,9 @@ public: void beginRowsRemoved( int from, int to ) { emit beginChildRowsRemoved( from, to ); } void endRowsRemoved() { emit childRowsRemoved(); } +public slots: + virtual void activate() {} + signals: void updated(); void selectRequest( SourceTreeItem* ); diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp index 4ddf6fa36..6e81995fc 100644 --- a/src/sourcetree/sourcesmodel.cpp +++ b/src/sourcetree/sourcesmodel.cpp @@ -256,8 +256,8 @@ SourcesModel::appendGroups() { beginInsertRows( QModelIndex(), rowCount(), rowCount() + 2 ); - SourceTreeItem* divider = new SourceTreeItem( this, m_rootItem, SourcesModel::Divider, 0 ); - HistoryItem* history = new HistoryItem( this, m_rootItem, tr( "History" ), 5 ); + new SourceTreeItem( this, m_rootItem, SourcesModel::Divider, 0 ); + new HistoryItem( this, m_rootItem, tr( "History" ), 5 ); GroupItem* browse = new GroupItem( this, m_rootItem, tr( "Browse" ), 10 ); // super collection @@ -611,7 +611,7 @@ SourcesModel::indexFromItem( SourceTreeItem* item ) const int SourcesModel::rowForItem( SourceTreeItem* item ) const { - if( !item || !item->parent() || !item->parent()->children().contains( item ) ) + if ( !item || !item->parent() || !item->parent()->children().contains( item ) ) return -1; return item->parent()->children().indexOf( item ); @@ -628,7 +628,6 @@ SourcesModel::itemSelectRequest( SourceTreeItem* item ) void SourcesModel::itemExpandRequest( SourceTreeItem *item ) { - qDebug() << "expanding source" << indexFromItem( item ) << item; emit expandRequest( QPersistentModelIndex( indexFromItem( item ) ) ); } diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index 01ecd8995..abacd799b 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -84,8 +84,8 @@ SourceTreeView::SourceTreeView( QWidget* parent ) // setAnimated( true ); m_delegate = new SourceDelegate( this ); - connect( m_delegate, SIGNAL( latchOn( Tomahawk::source_ptr ) ), this, SLOT( latchOnOrCatchUp( Tomahawk::source_ptr ) ), Qt::QueuedConnection ); - connect( m_delegate, SIGNAL( latchOff( Tomahawk::source_ptr ) ), this, SLOT( latchOff( Tomahawk::source_ptr ) ), Qt::QueuedConnection ); + connect( m_delegate, SIGNAL( latchOn( Tomahawk::source_ptr ) ), SLOT( latchOnOrCatchUp( Tomahawk::source_ptr ) ), Qt::QueuedConnection ); + connect( m_delegate, SIGNAL( latchOff( Tomahawk::source_ptr ) ), SLOT( latchOff( Tomahawk::source_ptr ) ), Qt::QueuedConnection ); setItemDelegate( m_delegate ); @@ -94,9 +94,9 @@ SourceTreeView::SourceTreeView( QWidget* parent ) m_model = new SourcesModel( this ); m_proxyModel = new SourcesProxyModel( m_model, this ); - connect( m_proxyModel, SIGNAL( selectRequest( QPersistentModelIndex ) ), this, SLOT( selectRequest( QPersistentModelIndex ) ) ); - connect( m_proxyModel, SIGNAL( expandRequest( QPersistentModelIndex ) ), this, SLOT( expandRequest( QPersistentModelIndex ) ) ); - connect( m_proxyModel, SIGNAL( toggleExpandRequest( QPersistentModelIndex ) ), this, SLOT( toggleExpandRequest( QPersistentModelIndex ) ) ); + connect( m_proxyModel, SIGNAL( selectRequest( QPersistentModelIndex ) ), SLOT( selectRequest( QPersistentModelIndex ) ) ); + connect( m_proxyModel, SIGNAL( expandRequest( QPersistentModelIndex ) ), SLOT( expandRequest( QPersistentModelIndex ) ) ); + connect( m_proxyModel, SIGNAL( toggleExpandRequest( QPersistentModelIndex ) ), SLOT( toggleExpandRequest( QPersistentModelIndex ) ) ); setModel( m_proxyModel ); @@ -104,7 +104,7 @@ SourceTreeView::SourceTreeView( QWidget* parent ) header()->setResizeMode( 0, QHeaderView::Stretch ); connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) ); - connect( this, SIGNAL( expanded( QModelIndex ) ), this, SLOT( onItemExpanded( QModelIndex ) ) ); + connect( this, SIGNAL( expanded( QModelIndex ) ), SLOT( onItemExpanded( QModelIndex ) ) ); // connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) ); showOfflineSources( TomahawkSettings::instance()->showOfflineSources() ); @@ -228,8 +228,10 @@ void SourceTreeView::onItemExpanded( const QModelIndex& idx ) { // make sure to expand children nodes for collections - if( idx.data( SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Collection ) { - for( int i = 0; i < model()->rowCount( idx ); i++ ) { + if( idx.data( SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Collection ) + { + for( int i = 0; i < model()->rowCount( idx ); i++ ) + { setExpanded( model()->index( i, 0, idx ), true ); } } From b3c144b4bfd63dfa78dd03742ade9b1a4f8b84f9 Mon Sep 17 00:00:00 2001 From: Stefan Derkits Date: Fri, 23 Dec 2011 22:17:31 +0100 Subject: [PATCH 08/11] put ifdefs around grooveshark parsing stuff --- src/libtomahawk/CMakeLists.txt | 11 ++++++++--- src/libtomahawk/dropjob.cpp | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 46ae46ab2..f463f62c1 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -101,7 +101,6 @@ set( libGuiSources utils/m3uloader.cpp utils/itunesparser.cpp utils/rdioparser.cpp - utils/groovesharkparser.cpp utils/shortenedlinkparser.cpp utils/stylehelper.cpp utils/dropjobnotifier.cpp @@ -136,6 +135,10 @@ set( libGuiSources widgets/BreadcrumbButton.cpp ) +IF(QCA2_FOUND) + set( libGuiSources ${libGuiSources} utils/groovesharkparser.cpp ) +ENDIF(QCA2_FOUND) + set( libGuiHeaders actioncollection.h @@ -220,7 +223,6 @@ set( libGuiHeaders utils/m3uloader.h utils/itunesparser.h utils/rdioparser.h - utils/groovesharkparser.h utils/shortenedlinkparser.h utils/dropjobnotifier.h utils/tomahawkutilsgui.h @@ -264,9 +266,12 @@ set( libGuiHeaders jobview/LatchedStatusItem.h thirdparty/Qocoa/qsearchfield.h - ) +IF(QCA2_FOUND) + set( libGuiHeaders ${libGuiHeaders} utils/groovesharkparser.h ) +ENDIF(QCA2_FOUND) + set( libSources tomahawksettings.cpp sourcelist.cpp diff --git a/src/libtomahawk/dropjob.cpp b/src/libtomahawk/dropjob.cpp index 9a83f9c1a..5e67b724e 100644 --- a/src/libtomahawk/dropjob.cpp +++ b/src/libtomahawk/dropjob.cpp @@ -26,7 +26,6 @@ #include "utils/spotifyparser.h" #include "utils/itunesparser.h" #include "utils/rdioparser.h" -#include "utils/groovesharkparser.h" #include "utils/m3uloader.h" #include "utils/shortenedlinkparser.h" #include "utils/logger.h" @@ -36,6 +35,10 @@ #include "utils/xspfloader.h" #include "jobview/JobStatusView.h" #include "jobview/JobStatusModel.h" +#ifdef QCA2_FOUND +#include "utils/groovesharkparser.h" +#endif //QCA2_FOUND + using namespace Tomahawk; @@ -192,10 +195,10 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data ) if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) ) return true; - +#ifdef QCA2_FOUND if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) ) return true; - +#endif //QCA2_FOUND if ( ShortenedLinkParser::handlesUrl( url ) ) return true; } @@ -565,6 +568,7 @@ DropJob::handleRdioUrls( const QString& urlsRaw ) void DropJob::handleGroovesharkUrls ( const QString& urlsRaw ) { +#ifdef QCA2_FOUND QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts ); tDebug() << "Got Grooveshark urls!" << urls; @@ -580,6 +584,9 @@ DropJob::handleGroovesharkUrls ( const QString& urlsRaw ) connect( groove, SIGNAL( tracks( QList ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) ); m_queryCount++; } +#else + tLog() << "Tomahawk compiled without QCA support, cannot use groovesharkparser"; +#endif } @@ -597,8 +604,10 @@ DropJob::handleAllUrls( const QString& urls ) handleSpotifyUrls( urls ); else if ( urls.contains( "rdio.com" ) ) handleRdioUrls( urls ); +#ifdef QCA2_FOUND else if ( urls.contains( "grooveshark.com" ) ) handleGroovesharkUrls( urls ); +#endif else handleTrackUrls ( urls ); } From 9634d3230f6ffff43b16bbaa77f5aef295bf8d46 Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Sat, 24 Dec 2011 11:10:23 -0600 Subject: [PATCH 09/11] Go back to old way of sending artists in charts, as old data type may be cached --- .../infosystem/infoplugins/generic/chartsplugin.cpp | 8 +++----- src/libtomahawk/widgets/ChartDataLoader.cpp | 5 +++-- src/libtomahawk/widgets/ChartDataLoader.h | 2 ++ src/libtomahawk/widgets/whatshotwidget.cpp | 6 ++++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp index 8c719f021..02eff8d12 100644 --- a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp @@ -453,7 +453,7 @@ ChartsPlugin::chartReturned() QVariantList chartResponse = res.value( "list" ).toList(); QList< Tomahawk::InfoSystem::InfoStringHash > top_tracks; QList< Tomahawk::InfoSystem::InfoStringHash > top_albums; - QList< Tomahawk::InfoSystem::InfoStringHash > top_artists; + QStringList top_artists; /// Deside what type, we need to handle it differently /// @todo: We allready know the type, append it to breadcrumb hash @@ -528,9 +528,7 @@ ChartsPlugin::chartReturned() } else { - Tomahawk::InfoSystem::InfoStringHash artistHash; - artistHash["artist"] = artist; - top_artists.append( artistHash ); + top_artists.append( artist ); } } @@ -540,7 +538,7 @@ ChartsPlugin::chartReturned() if( chartType() == Artist ) { tDebug() << "ChartsPlugin:" << "\tgot " << top_artists.size() << " artists"; - returnedData[ "artists" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_artists ); + returnedData[ "artists" ] = QVariant::fromValue< QStringList >( top_artists ); returnedData[ "type" ] = "artists"; } diff --git a/src/libtomahawk/widgets/ChartDataLoader.cpp b/src/libtomahawk/widgets/ChartDataLoader.cpp index 9816b5f60..a786aa199 100644 --- a/src/libtomahawk/widgets/ChartDataLoader.cpp +++ b/src/libtomahawk/widgets/ChartDataLoader.cpp @@ -45,8 +45,9 @@ ChartDataLoader::go() { QList< artist_ptr > artist_ptrs; - foreach ( const Tomahawk::InfoSystem::InfoStringHash& artistname, m_data ) { - artist_ptrs << Artist::get( artistname[ "artist" ], false ); + foreach ( const QString& artistname, m_artists ) + { + artist_ptrs << Artist::get( artistname, false ); } emit artists( this, artist_ptrs ); diff --git a/src/libtomahawk/widgets/ChartDataLoader.h b/src/libtomahawk/widgets/ChartDataLoader.h index 001cacc52..3fbb4cae7 100644 --- a/src/libtomahawk/widgets/ChartDataLoader.h +++ b/src/libtomahawk/widgets/ChartDataLoader.h @@ -47,6 +47,7 @@ public: void setType( DataType type ) { m_type = type; } void setData( const QList< InfoSystem::InfoStringHash >& data ) { m_data = data; } + void setData( const QStringList& artists ) { m_artists = artists; } public slots: void go(); @@ -60,6 +61,7 @@ signals: private: DataType m_type; QList m_data; + QStringList m_artists; }; } diff --git a/src/libtomahawk/widgets/whatshotwidget.cpp b/src/libtomahawk/widgets/whatshotwidget.cpp index 264b1187f..cb0d947f4 100644 --- a/src/libtomahawk/widgets/whatshotwidget.cpp +++ b/src/libtomahawk/widgets/whatshotwidget.cpp @@ -253,7 +253,7 @@ WhatsHotWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestDat if ( type == "artists" ) { loader->setType( ChartDataLoader::Artist ); - loader->setData( returnedData[ "artists" ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >() ); + loader->setData( returnedData[ "artists" ].value< QStringList >() ); connect( loader, SIGNAL( artists( Tomahawk::ChartDataLoader*, QList< Tomahawk::artist_ptr > ) ), this, SLOT( chartArtistsLoaded( Tomahawk::ChartDataLoader*, QList< Tomahawk::artist_ptr > ) ) ); @@ -479,10 +479,12 @@ WhatsHotWidget::chartArtistsLoaded( ChartDataLoader* loader, const QList< artist QString chartId = loader->property( "chartid" ).toString(); Q_ASSERT( m_artistModels.contains( chartId ) ); - if ( !m_artistModels.contains( chartId ) ) + if ( m_artistModels.contains( chartId ) ) { foreach( const artist_ptr& artist, artists ) + { m_artistModels[ chartId ]->addArtists( artist ); + } } loader->deleteLater(); From bd893995c3acf176cd4794fd0636dfef47c06dbf Mon Sep 17 00:00:00 2001 From: Stefan Derkits Date: Sat, 24 Dec 2011 22:43:25 +0100 Subject: [PATCH 10/11] Allow parsing of grooveshark tinysong.com links --- src/libtomahawk/utils/groovesharkparser.cpp | 4 +++- src/libtomahawk/utils/shortenedlinkparser.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libtomahawk/utils/groovesharkparser.cpp b/src/libtomahawk/utils/groovesharkparser.cpp index 6ee245c56..59c898822 100644 --- a/src/libtomahawk/utils/groovesharkparser.cpp +++ b/src/libtomahawk/utils/groovesharkparser.cpp @@ -93,7 +93,9 @@ GroovesharkParser::lookupGroovesharkPlaylist( const QString& linkRaw ) QStringList urlParts = linkRaw.split( "/" ); bool ok; - int playlistID = urlParts.last().toInt( &ok, 10 ); + QString playlistStr = urlParts.last(); + playlistStr.truncate(playlistStr.indexOf("?")); + int playlistID = playlistStr.toInt( &ok, 10 ); if (!ok) { tDebug() << "incorrect grooveshark url"; diff --git a/src/libtomahawk/utils/shortenedlinkparser.cpp b/src/libtomahawk/utils/shortenedlinkparser.cpp index 0e196449d..6c37f951e 100644 --- a/src/libtomahawk/utils/shortenedlinkparser.cpp +++ b/src/libtomahawk/utils/shortenedlinkparser.cpp @@ -56,6 +56,7 @@ ShortenedLinkParser::handlesUrl( const QString& url ) url.contains( "fb.me" ) || url.contains( "itun.es" ) || url.contains( "tinyurl.com" ) || + url.contains( "tinysong.com" ) || url.contains( "rd.io" ) ); } From 4c8fa37d0e1ae885cec455fa55d5e1272a73b393 Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Sun, 25 Dec 2011 19:56:09 -0600 Subject: [PATCH 11/11] Delete external resolvers when removing them from resolvers list --- src/libtomahawk/pipeline.cpp | 2 +- src/libtomahawk/resolvers/scriptresolver.cpp | 2 +- src/libtomahawk/resolvers/scriptresolver.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libtomahawk/pipeline.cpp b/src/libtomahawk/pipeline.cpp index af0b271e8..73d14fce4 100644 --- a/src/libtomahawk/pipeline.cpp +++ b/src/libtomahawk/pipeline.cpp @@ -169,7 +169,7 @@ Pipeline::removeScriptResolver( const QString& scriptPath ) if ( r ) { r->stop(); - connect( r, SIGNAL( stopped() ), r, SLOT( deleteLater() ) ); + r->deleteLater(); } } diff --git a/src/libtomahawk/resolvers/scriptresolver.cpp b/src/libtomahawk/resolvers/scriptresolver.cpp index 29a259906..56d027f65 100644 --- a/src/libtomahawk/resolvers/scriptresolver.cpp +++ b/src/libtomahawk/resolvers/scriptresolver.cpp @@ -300,7 +300,7 @@ ScriptResolver::cmdExited( int code, QProcess::ExitStatus status ) if ( m_stopped ) { tLog() << "*** Script resolver stopped "; - emit stopped(); + emit terminated(); return; } diff --git a/src/libtomahawk/resolvers/scriptresolver.h b/src/libtomahawk/resolvers/scriptresolver.h index 9191396be..c7cd9a9e4 100644 --- a/src/libtomahawk/resolvers/scriptresolver.h +++ b/src/libtomahawk/resolvers/scriptresolver.h @@ -55,7 +55,7 @@ public: virtual bool running() const; signals: - void stopped(); + void terminated(); public slots: virtual void stop();