mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-19 15:29:42 +01:00
Merge branch 'master' into playlistinterface_ptr
Conflicts: src/libtomahawk/widgets/whatshotwidget.cpp
This commit is contained in:
commit
073cbbaad5
@ -120,6 +120,7 @@ set( libGuiSources
|
||||
widgets/playlisttypeselectordlg.cpp
|
||||
widgets/welcomewidget.cpp
|
||||
widgets/whatshotwidget.cpp
|
||||
widgets/ChartDataLoader.cpp
|
||||
widgets/RecentlyPlayedPlaylistsModel.cpp
|
||||
widgets/RecentPlaylistsModel.cpp
|
||||
widgets/OverlayButton.cpp
|
||||
@ -136,6 +137,10 @@ set( libGuiSources
|
||||
widgets/BreadcrumbButton.cpp
|
||||
)
|
||||
|
||||
IF(QCA2_FOUND)
|
||||
set( libGuiSources ${libGuiSources} utils/groovesharkparser.cpp )
|
||||
ENDIF(QCA2_FOUND)
|
||||
|
||||
set( libGuiHeaders
|
||||
actioncollection.h
|
||||
|
||||
@ -237,6 +242,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
|
||||
@ -262,9 +268,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
|
||||
|
@ -35,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;
|
||||
|
||||
@ -120,6 +124,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,7 +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;
|
||||
}
|
||||
@ -555,6 +565,31 @@ DropJob::handleRdioUrls( const QString& urlsRaw )
|
||||
rdio->parse( urls );
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::handleGroovesharkUrls ( const QString& urlsRaw )
|
||||
{
|
||||
#ifdef QCA2_FOUND
|
||||
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<Tomahawk::query_ptr> ) ), 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<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||
m_queryCount++;
|
||||
}
|
||||
#else
|
||||
tLog() << "Tomahawk compiled without QCA support, cannot use groovesharkparser";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DropJob::handleAllUrls( const QString& urls )
|
||||
@ -569,6 +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 );
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -169,7 +169,7 @@ Pipeline::removeScriptResolver( const QString& scriptPath )
|
||||
if ( r )
|
||||
{
|
||||
r->stop();
|
||||
connect( r, SIGNAL( stopped() ), r, SLOT( deleteLater() ) );
|
||||
r->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ ScriptResolver::cmdExited( int code, QProcess::ExitStatus status )
|
||||
if ( m_stopped )
|
||||
{
|
||||
tLog() << "*** Script resolver stopped ";
|
||||
emit stopped();
|
||||
emit terminated();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
virtual bool running() const;
|
||||
|
||||
signals:
|
||||
void stopped();
|
||||
void terminated();
|
||||
|
||||
public slots:
|
||||
virtual void stop();
|
||||
|
1
src/libtomahawk/thirdparty/Qocoa/qocoa_mac.h
vendored
1
src/libtomahawk/thirdparty/Qocoa/qocoa_mac.h
vendored
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
258
src/libtomahawk/utils/groovesharkparser.cpp
Normal file
258
src/libtomahawk/utils/groovesharkparser.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
|
||||
* Copyright 2010-2011, Stefan Derkits <stefan@derkits.at>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <qjson/parser.h>
|
||||
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
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 )
|
||||
{
|
||||
QByteArray magic = QByteArray::fromBase64( enApiSecret );
|
||||
|
||||
QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() );
|
||||
int length = magic.length(), n2 = wand.length();
|
||||
for ( int i=0; i<length; i++ ) magic[i] = magic[i] ^ wand[i%n2];
|
||||
|
||||
m_apiKey = QCA::SymmetricKey( magic );
|
||||
|
||||
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;
|
||||
|
||||
QStringList urlParts = linkRaw.split( "/" );
|
||||
bool ok;
|
||||
QString playlistStr = urlParts.last();
|
||||
playlistStr.truncate(playlistStr.indexOf("?"));
|
||||
int playlistID = playlistStr.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 ( linkRaw.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();
|
||||
|
||||
|
||||
|
||||
|
||||
QCA::MessageAuthenticationCode hmac( "hmac(md5)", m_apiKey );
|
||||
|
||||
QCA::SecureArray secdata( data );
|
||||
hmac.update(secdata);
|
||||
QCA::SecureArray resultArray = hmac.final();
|
||||
|
||||
QString hash = QCA::arrayToHex( resultArray.toByteArray() );
|
||||
QUrl url = QUrl( base_url + hash );
|
||||
|
||||
tDebug() << "Looking up URL..." << url.toString();
|
||||
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->post( 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;
|
||||
}
|
||||
|
||||
QVariantList list = res.value( "result" ).toMap().value( "songs" ).toList();
|
||||
foreach (const QVariant& var, list)
|
||||
{
|
||||
QVariantMap trackResult = var.toMap();
|
||||
|
||||
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 grooveshark, 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
|
||||
checkPlaylistFinished();
|
||||
}
|
||||
|
||||
void
|
||||
GroovesharkParser::checkPlaylistFinished()
|
||||
{
|
||||
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/grooveshark.png" );
|
||||
|
||||
return *s_pixmap;
|
||||
}
|
87
src/libtomahawk/utils/groovesharkparser.h
Normal file
87
src/libtomahawk/utils/groovesharkparser.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
|
||||
* Copyright 2011, Stefan Derkits <stefan@derkits.at>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GROOVESHARKPARSER_H
|
||||
#define GROOVESHARKPARSER_H
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "typedefs.h"
|
||||
#include "query.h"
|
||||
#include "jobview/JobStatusItem.h"
|
||||
|
||||
#include <qca_basic.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
/**
|
||||
* 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 checkPlaylistFinished();
|
||||
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;
|
||||
|
||||
QCA::SymmetricKey m_apiKey;
|
||||
|
||||
static QPixmap* s_pixmap;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GROOVESHARKPARSER_H
|
@ -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" ) );
|
||||
}
|
||||
|
||||
|
72
src/libtomahawk/widgets/ChartDataLoader.cpp
Normal file
72
src/libtomahawk/widgets/ChartDataLoader.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "ChartDataLoader.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
ChartDataLoader::ChartDataLoader()
|
||||
: QObject( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ChartDataLoader::go()
|
||||
{
|
||||
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 QString& artistname, m_artists )
|
||||
{
|
||||
artist_ptrs << Artist::get( artistname, 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;
|
||||
}
|
||||
}
|
||||
}
|
69
src/libtomahawk/widgets/ChartDataLoader.h
Normal file
69
src/libtomahawk/widgets/ChartDataLoader.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CHARTDATALOADER_H
|
||||
#define CHARTDATALOADER_H
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "query.h"
|
||||
#include "artist.h"
|
||||
#include "album.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
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; }
|
||||
void setData( const QStringList& artists ) { m_artists = artists; }
|
||||
|
||||
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<InfoSystem::InfoStringHash> m_data;
|
||||
QStringList m_artists;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CHARTDATALOADER_H
|
@ -29,6 +29,7 @@
|
||||
#include "sourcelist.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "RecentPlaylistsModel.h"
|
||||
#include "ChartDataLoader.h"
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
@ -52,6 +53,7 @@ WhatsHotWidget::WhatsHotWidget( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, ui( new Ui::WhatsHotWidget )
|
||||
, m_sortedProxy( 0 )
|
||||
, m_workerThread( 0 )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
@ -93,6 +95,9 @@ WhatsHotWidget::WhatsHotWidget( QWidget* parent )
|
||||
|
||||
m_playlistInterface = ( new ChartsPlaylistInterface( this ) )->getSharedPointer();
|
||||
|
||||
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 ) ) );
|
||||
@ -105,6 +110,8 @@ WhatsHotWidget::WhatsHotWidget( QWidget* parent )
|
||||
|
||||
WhatsHotWidget::~WhatsHotWidget()
|
||||
{
|
||||
m_workerThread->exit(0);
|
||||
delete m_playlistInterface;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -237,68 +244,60 @@ 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 );
|
||||
|
||||
if ( type == "artists" )
|
||||
{
|
||||
const QStringList artists = returnedData["artists"].toStringList();
|
||||
loader->setType( ChartDataLoader::Artist );
|
||||
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 > ) ) );
|
||||
|
||||
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<album_ptr> 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<query_ptr> 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;
|
||||
}
|
||||
|
||||
@ -471,3 +470,51 @@ WhatsHotWidget::setLeftViewTracks( PlaylistModel* model )
|
||||
ui->tracksViewLeft->proxyModel()->sort( -1 );
|
||||
ui->stackLeft->setCurrentIndex( 0 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WhatsHotWidget::chartArtistsLoaded( ChartDataLoader* loader, const QList< artist_ptr >& artists )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
|
||||
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 )
|
||||
{
|
||||
QString chartId = loader->property( "chartid" ).toString();
|
||||
Q_ASSERT( m_albumModels.contains( chartId ) );
|
||||
|
||||
if ( m_albumModels.contains( chartId ) )
|
||||
m_albumModels[ chartId ]->addAlbums( albums );
|
||||
|
||||
loader->deleteLater();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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* );
|
||||
|
@ -158,7 +158,6 @@ SourceItem::activate()
|
||||
p = ViewManager::instance()->showSuperCollection();
|
||||
else
|
||||
emit toggleExpandRequest( this );
|
||||
// p = ViewManager::instance()->show( source()->collection() );
|
||||
|
||||
model()->linkSourceItemToPage( this, p );
|
||||
}
|
||||
|
@ -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<Tomahawk::playlist_ptr>& playlists );
|
||||
void onPlaylistDeleted( const Tomahawk::playlist_ptr& playlists );
|
||||
|
@ -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* );
|
||||
|
@ -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 ) ) );
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user