diff --git a/.gitignore b/.gitignore index 19b945fcb..f4683f379 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ thirdparty/qtweetlib/WARNING-twitter-api-keys clang/ win/ gcc/ +tags diff --git a/resources.qrc b/resources.qrc index 7a0bc3272..5a6337c21 100644 --- a/resources.qrc +++ b/resources.qrc @@ -85,6 +85,7 @@ data/images/automatic-playlist.png data/images/station.png data/images/new-additions.png + data/images/charts.png data/images/loved_playlist.png data/images/dashboard.png data/images/artist-icon.png diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index eeabc3471..bd09f66c0 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -175,16 +175,20 @@ set( libSources utils/spotifyparser.cpp utils/rdioparser.cpp utils/shortenedlinkparser.cpp + utils/stylehelper.cpp widgets/newplaylistwidget.cpp widgets/searchwidget.cpp widgets/SeekSlider.cpp widgets/playlisttypeselectordlg.cpp widgets/welcomewidget.cpp + widgets/whatshotwidget.cpp widgets/RecentlyPlayedPlaylistsModel.cpp widgets/RecentPlaylistsModel.cpp widgets/overlaywidget.cpp widgets/HeaderLabel.cpp + widgets/HeaderWidget.cpp + widgets/combobox.cpp widgets/SocialPlaylistWidget.cpp widgets/infowidgets/sourceinfowidget.cpp widgets/infowidgets/ArtistInfoWidget.cpp @@ -357,16 +361,20 @@ set( libHeaders utils/spotifyparser.h utils/rdioparser.h utils/shortenedlinkparser.h + utils/stylehelper.h widgets/newplaylistwidget.h widgets/searchwidget.h widgets/SeekSlider.h widgets/playlisttypeselectordlg.h widgets/welcomewidget.h + widgets/whatshotwidget.h widgets/RecentlyPlayedPlaylistsModel.h widgets/RecentPlaylistsModel.h widgets/overlaywidget.h widgets/HeaderLabel.h + widgets/HeaderWidget.h + widgets/combobox.h widgets/SocialPlaylistWidget.h widgets/infowidgets/sourceinfowidget.h widgets/infowidgets/ArtistInfoWidget.h @@ -391,6 +399,7 @@ set( libUI ${libUI} widgets/newplaylistwidget.ui widgets/searchwidget.ui widgets/welcomewidget.ui + widgets/whatshotwidget.ui widgets/SocialPlaylistWidget.ui widgets/infowidgets/sourceinfowidget.ui widgets/infowidgets/ArtistInfoWidget.ui diff --git a/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp index e1e832856..a752a5d1b 100644 --- a/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp @@ -47,7 +47,7 @@ LastFmPlugin::LastFmPlugin() : InfoPlugin() , m_scrobbler( 0 ) { - m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs; + m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChartArtists << InfoChartTracks; m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove; /* @@ -147,6 +147,14 @@ LastFmPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData req fetchTopTracks( requestId, requestData ); break; + case InfoChartArtists: + fetchChartArtists( requestId, requestData ); + break; + + case InfoChartTracks: + fetchChartTracks( requestId, requestData ); + break; + default: dataError( requestId, requestData ); } @@ -298,6 +306,43 @@ LastFmPlugin::fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestD emit getCachedInfo( requestId, criteria, 2419200000, requestData ); } +void +LastFmPlugin::fetchChartArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) +{ + if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() ) + { + dataError( requestId, requestData ); + return; + } + InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >(); + Tomahawk::InfoSystem::InfoCriteriaHash criteria; + if ( hash.contains( "country" ) ) + { + criteria["country"] = hash["country"]; + } + + emit getCachedInfo( requestId, criteria, 2419200000, requestData ); +} + + +void +LastFmPlugin::fetchChartTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) +{ + if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() ) + { + dataError( requestId, requestData ); + return; + } + InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >(); + Tomahawk::InfoSystem::InfoCriteriaHash criteria; + if ( hash.contains( "country" ) ) + { + criteria["country"] = hash["country"]; + } + + emit getCachedInfo( requestId, criteria, 2419200000, requestData ); +} + void LastFmPlugin::fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) @@ -356,6 +401,44 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash criteria, switch ( requestData.type ) { + case InfoChartArtists: + { + tDebug() << "LastfmPlugin: InfoChartArtists notin cache, fetching"; + QMap args; + if( criteria.contains( "country" ) ) { + args["method"] = "geo.getTopArtists"; + args["country"] = criteria["country"]; + } else { + args["method"] = "chart.getTopArtists"; + } + args["limit"] = "100"; + QNetworkReply* reply = lastfm::ws::get(args); + reply->setProperty( "requestId", requestId ); + reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); + + connect( reply, SIGNAL( finished() ), SLOT( chartTopArtistsReturned() ) ); + return; + } + + case InfoChartTracks: + { + tDebug() << "LastfmPlugin: InfoChartTracks not in cache, fetching"; + QMap args; + if( criteria.contains( "country" ) ) { + args["method"] = "geo.getTopTracks"; + args["country"] = criteria["country"]; + } else { + args["method"] = "chart.getTopTracks"; + } + args["limit"] = "100"; + QNetworkReply* reply = lastfm::ws::get(args); + reply->setProperty( "requestId", requestId ); + reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); + + connect( reply, SIGNAL( finished() ), SLOT( chartTopTracksReturned() ) ); + return; + } + case InfoArtistSimilars: { lastfm::Artist a( criteria["artist"] ); @@ -447,6 +530,72 @@ LastFmPlugin::similarArtistsReturned() emit updateCache( criteria, 2419200000, requestData.type, returnedData ); } +void +LastFmPlugin::chartTopArtistsReturned() +{ + tDebug() << "LastfmPlugin: InfoChartArtists data returned!"; + QNetworkReply* reply = qobject_cast( sender() ); + QList list = lastfm::Artist::list( reply ); + QStringList al; + + tDebug() << "\tgot " << list.size() << " artists"; + + foreach ( const lastfm::Artist& a, list ) + al << a.toString(); + + QVariantMap returnedData; + returnedData["artists"] = al; + + Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); + + emit info( + reply->property( "requestId" ).toUInt(), + requestData, + returnedData + ); + + Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>(); + Tomahawk::InfoSystem::InfoCriteriaHash criteria; + if( origData.contains("country") ) + criteria["country"] = origData["country"]; + emit updateCache( criteria, 2419200000, requestData.type, returnedData ); +} + +void +LastFmPlugin::chartTopTracksReturned() +{ + tDebug() << "LastfmPlugin: InfoChartTracks data returned!"; + QNetworkReply* reply = qobject_cast( sender() ); + QList tracks = parseTrackList( reply ); + + QList top_tracks; + + foreach( const lastfm::Track &t, tracks ) { + ArtistTrackPair pair; + pair.artist = t.artist().toString(); + pair.track = t.title(); + top_tracks << pair; + } + + tDebug() << "\tgot " << top_tracks.size() << " tracks"; + + QVariantMap returnedData; + returnedData["tracks"] = QVariant::fromValue( top_tracks ); + + Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); + + emit info( + reply->property( "requestId" ).toUInt(), + requestData, + returnedData + ); + + Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>(); + Tomahawk::InfoSystem::InfoCriteriaHash criteria; + if( origData.contains("country") ) + criteria["country"] = origData["country"]; + emit updateCache( criteria, 0, requestData.type, returnedData ); +} void LastFmPlugin::topTracksReturned() @@ -468,7 +617,7 @@ LastFmPlugin::topTracksReturned() Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>(); Tomahawk::InfoSystem::InfoCriteriaHash criteria; criteria["artist"] = origData["artist"]; - emit updateCache( criteria, 2419200000, requestData.type, returnedData ); + emit updateCache( criteria, 0, requestData.type, returnedData ); } @@ -675,3 +824,21 @@ LastFmPlugin::createScrobbler() } } + +QList +LastFmPlugin::parseTrackList( QNetworkReply * reply ) +{ + QList tracks; + try { + lastfm::XmlQuery lfm = lastfm::ws::parse(reply); + foreach (lastfm::XmlQuery xq, lfm.children( "track" )) { + tracks.append( lastfm::Track( xq ) ); + } + } + catch (lastfm::ws::ParseError& e) + { + qWarning() << e.what(); + } + return tracks; +} + diff --git a/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.h b/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.h index dcd6eae2c..c8da91a73 100644 --- a/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.h +++ b/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.h @@ -52,6 +52,8 @@ public slots: void artistImagesReturned(); void similarArtistsReturned(); void topTracksReturned(); + void chartTopArtistsReturned(); + void chartTopTracksReturned(); void namChangedSlot( QNetworkAccessManager *nam ); @@ -66,6 +68,8 @@ private: void fetchArtistImages( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); void fetchSimilarArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); void fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); + void fetchChartArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); + void fetchChartTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); void createScrobbler(); void nowPlaying( const QVariant &input ); @@ -74,6 +78,8 @@ private: void dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); + QList parseTrackList( QNetworkReply * reply ); + lastfm::MutableTrack m_track; lastfm::Audioscrobbler* m_scrobbler; QString m_pw; diff --git a/src/libtomahawk/infosystem/infosystem.h b/src/libtomahawk/infosystem/infosystem.h index 87366ec4a..b65c62a59 100644 --- a/src/libtomahawk/infosystem/infosystem.h +++ b/src/libtomahawk/infosystem/infosystem.h @@ -92,6 +92,10 @@ enum InfoType { // as items are saved in cache, mark them here to not change the InfoAlbumComposer = 48, InfoAlbumSongs = 49, + InfoChartArtists = 50, + InfoChartAlbums = 51, + InfoChartTracks = 52, + InfoMiscTopHotttness = 60, InfoMiscTopTerms = 61, @@ -118,6 +122,11 @@ struct InfoRequestData { QVariantMap customData; }; +struct ArtistTrackPair { + QString artist; + QString track; +}; + typedef QMap< InfoType, QVariant > InfoTypeMap; typedef QMap< InfoType, uint > InfoTimeoutMap; typedef QMap< QString, QMap< QString, QString > > InfoGenericMap; @@ -254,5 +263,7 @@ Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoGenericMap ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoCriteriaHash ); Q_DECLARE_METATYPE( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > ); +Q_DECLARE_METATYPE( Tomahawk::InfoSystem::ArtistTrackPair ); +Q_DECLARE_METATYPE( QList ); #endif // TOMAHAWK_INFOSYSTEM_H diff --git a/src/libtomahawk/utils/stylehelper.cpp b/src/libtomahawk/utils/stylehelper.cpp new file mode 100644 index 000000000..7583c5b76 --- /dev/null +++ b/src/libtomahawk/utils/stylehelper.cpp @@ -0,0 +1,151 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Casey Link + * + * 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 "stylehelper.h" + +#include +#include +#include + +QColor StyleHelper::headerUpperColor() +{ + return QColor( 80, 80, 80 ); +} + +QColor StyleHelper::headerLowerColor() +{ + return QColor( 72, 72, 72 ); +} + +QColor StyleHelper::headerHighlightColor() +{ + return QColor( "#333" ); +} + +void StyleHelper::horizontalHeader(QPainter *painter, const QRect &r) +{ + QRect upperHalf( 0, 0, r.width(), r.height() / 2 ); + QRect lowerHalf( 0, upperHalf.height(), r.width(), r.height() ); + painter->fillRect( upperHalf, StyleHelper::headerUpperColor() ); + painter->fillRect( lowerHalf, StyleHelper::headerLowerColor() ); + + { + QColor lineColor( 100, 100, 100 ); + QLine line( 0, 0, r.width(), 0 ); + painter->setPen( lineColor ); + painter->drawLine( line ); + } + { + QColor lineColor( 30, 30, 30 ); + QLine line( 0, r.height() - 1, r.width(), r.height() - 1 ); + painter->setPen( lineColor ); + painter->drawLine( line ); + } +} + +QColor StyleHelper::headerTextColor() +{ + return Qt::white; +} + + +/* + * This implementation is from QWindowsStyle (Qt 7.2) + * + * It is licensed under the GPL 3: + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * Contact: Nokia Corporation (qt-info@nokia.com) + */ +void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *p, const QStyleOption *opt) +{ + + if (opt->rect.width() <= 1 || opt->rect.height() <= 1) + return; + QRect r = opt->rect; + int size = qMin(r.height(), r.width()); + QPixmap pixmap; + QString pixmapName; + pixmapName.sprintf("arrow-%s-%d-%d-%d-%lld", + "$qt_ia", + uint(opt->state), element, + size, opt->palette.cacheKey()); + if (!QPixmapCache::find(pixmapName, pixmap)) { + int border = size/5; + int sqsize = 2*(size/2); + QImage image(sqsize, sqsize, QImage::Format_ARGB32); + image.fill(0); + QPainter imagePainter(&image); + imagePainter.setRenderHint(QPainter::Antialiasing, true); + QPolygon a; + switch (element) { + case QStyle::PE_IndicatorArrowUp: + a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize - border, sqsize/2); + break; + case QStyle::PE_IndicatorArrowDown: + a.setPoints(3, border, sqsize/2, sqsize/2, sqsize - border, sqsize - border, sqsize/2); + break; + case QStyle::PE_IndicatorArrowRight: + a.setPoints(3, sqsize - border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); + break; + case QStyle::PE_IndicatorArrowLeft: + a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); + break; + default: + break; + } + + int bsx = 0; + int bsy = 0; + + if (opt->state & QStyle::State_Sunken) { + bsx = qApp->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal); + bsy = qApp->style()->pixelMetric(QStyle::PM_ButtonShiftVertical); + } + + QRect bounds = a.boundingRect(); + int sx = sqsize / 2 - bounds.center().x() - 1; + int sy = sqsize / 2 - bounds.center().y() - 1; + imagePainter.translate(sx + bsx, sy + bsy); + imagePainter.setPen(opt->palette.buttonText().color()); + imagePainter.setBrush(opt->palette.buttonText()); + + if (!(opt->state & QStyle::State_Enabled)) { + QColor foreGround(150, 150, 150, 150); + imagePainter.setBrush(opt->palette.mid().color()); + imagePainter.setPen(opt->palette.mid().color()); + } else { + QColor shadow(0, 0, 0, 100); + imagePainter.translate(0, 1); + imagePainter.setPen(shadow); + imagePainter.setBrush(shadow); + QColor foreGround(255, 255, 255, 210); + imagePainter.drawPolygon(a); + imagePainter.translate(0, -1); + imagePainter.setPen(foreGround); + imagePainter.setBrush(foreGround); + } + + imagePainter.drawPolygon(a); + imagePainter.end(); + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(pixmapName, pixmap); + } + int xOffset = r.x() + (r.width() - size)/2; + int yOffset = r.y() + (r.height() - size)/2; + p->drawPixmap(xOffset, yOffset, pixmap); +} diff --git a/src/libtomahawk/utils/stylehelper.h b/src/libtomahawk/utils/stylehelper.h new file mode 100644 index 000000000..2fa371725 --- /dev/null +++ b/src/libtomahawk/utils/stylehelper.h @@ -0,0 +1,46 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Casey Link + * + * 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 STYLEHELPER_H +#define STYLEHELPER_H + + +#include +#include +#include + +class QPalette; +class QPainter; + +class StyleHelper +{ +public: + + static QColor headerUpperColor(); + static QColor headerLowerColor(); + static QColor headerTextColor(); + static QColor headerHighlightColor(); + + static void horizontalHeader(QPainter *painter, const QRect &rect); + static void drawArrow(QStyle::PrimitiveElement, QPainter *painter, const QStyleOption *opt); +private: + static QColor m_baseColor; + static QColor m_requestedBaseColor; +}; + +#endif // STYLEHELPER_H diff --git a/src/libtomahawk/viewmanager.cpp b/src/libtomahawk/viewmanager.cpp index 77a48dcd1..3a090e294 100644 --- a/src/libtomahawk/viewmanager.cpp +++ b/src/libtomahawk/viewmanager.cpp @@ -44,6 +44,7 @@ #include "dynamic/widgets/DynamicWidget.h" #include "widgets/welcomewidget.h" +#include "widgets/whatshotwidget.h" #include "widgets/infowidgets/sourceinfowidget.h" #include "widgets/infowidgets/ArtistInfoWidget.h" #include "widgets/infowidgets/AlbumInfoWidget.h" @@ -69,6 +70,7 @@ ViewManager::ViewManager( QObject* parent ) : QObject( parent ) , m_widget( new QWidget() ) , m_welcomeWidget( new WelcomeWidget() ) + , m_whatsHotWidget( new WhatsHotWidget() ) , m_currentMode( PlaylistInterface::Tree ) { s_instance = this; @@ -439,6 +441,13 @@ ViewManager::showWelcomePage() return show( m_welcomeWidget ); } +Tomahawk::ViewPage* +ViewManager::showWhatsHotPage() +{ + return show( m_whatsHotWidget ); +} + + void ViewManager::setTableMode() diff --git a/src/libtomahawk/viewmanager.h b/src/libtomahawk/viewmanager.h index 9fcbc5a26..bc3dd5c67 100644 --- a/src/libtomahawk/viewmanager.h +++ b/src/libtomahawk/viewmanager.h @@ -27,6 +27,7 @@ #include "playlistinterface.h" #include "viewpage.h" #include "widgets/welcomewidget.h" +#include "widgets/whatshotwidget.h" #include "dllmacro.h" @@ -51,6 +52,7 @@ class SourceInfoWidget; class InfoBar; class TopBar; class WelcomeWidget; +class WhatsHotWidget; class QPushButton; namespace Tomahawk @@ -82,6 +84,7 @@ public: Tomahawk::ViewPage* show( Tomahawk::ViewPage* page ); Tomahawk::ViewPage* welcomeWidget() const { return m_welcomeWidget; } + Tomahawk::ViewPage* whatsHotWidget() const { return m_whatsHotWidget; } ArtistView* superCollectionView() const { return m_superCollectionView; } /// Get the view page for the given item. Not pretty... @@ -120,6 +123,7 @@ signals: public slots: Tomahawk::ViewPage* showSuperCollection(); Tomahawk::ViewPage* showWelcomePage(); + Tomahawk::ViewPage* showWhatsHotPage(); void showCurrentTrack(); // Returns the shown viewpage @@ -181,6 +185,7 @@ private: TreeModel* m_superCollectionModel; ArtistView* m_superCollectionView; WelcomeWidget* m_welcomeWidget; + WhatsHotWidget* m_whatsHotWidget; QList< Tomahawk::collection_ptr > m_superCollections; diff --git a/src/libtomahawk/widgets/HeaderLabel.cpp b/src/libtomahawk/widgets/HeaderLabel.cpp index 055f2001f..6b86b04e5 100644 --- a/src/libtomahawk/widgets/HeaderLabel.cpp +++ b/src/libtomahawk/widgets/HeaderLabel.cpp @@ -21,6 +21,7 @@ #include #include "utils/logger.h" +#include "utils/stylehelper.h" #define FONT_SIZE 16 @@ -55,29 +56,10 @@ HeaderLabel::paintEvent( QPaintEvent* /* event */ ) { QPainter p( this ); QRect r = contentsRect(); - -// p.setRenderHint( QPainter::Antialiasing ); - - QRect upperHalf( 0, 0, r.width(), r.height() / 2 ); - QRect lowerHalf( 0, upperHalf.height(), r.width(), r.height() ); - p.fillRect( upperHalf, QColor( 80, 80, 80 ) ); - p.fillRect( lowerHalf, QColor( 72, 72, 72 ) ); - - { - QColor lineColor( 100, 100, 100 ); - QLine line( 0, 0, r.width(), 0 ); - p.setPen( lineColor ); - p.drawLine( line ); - } - { - QColor lineColor( 30, 30, 30 ); - QLine line( 0, r.height() - 1, r.width(), r.height() - 1 ); - p.setPen( lineColor ); - p.drawLine( line ); - } + StyleHelper::horizontalHeader(&p, r); QTextOption to( Qt::AlignVCenter ); r.adjust( 8, 0, -8, 0 ); - p.setPen( Qt::white ); + p.setPen( StyleHelper::headerTextColor() ); p.drawText( r, text(), to ); } diff --git a/src/libtomahawk/widgets/HeaderWidget.cpp b/src/libtomahawk/widgets/HeaderWidget.cpp new file mode 100644 index 000000000..94dd03ca4 --- /dev/null +++ b/src/libtomahawk/widgets/HeaderWidget.cpp @@ -0,0 +1,42 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Casey Link + * + * 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 "HeaderWidget.h" + + +#include "utils/stylehelper.h" + +#include +#include +#include + +HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) +{ +} + +HeaderWidget::~HeaderWidget() +{ +} + +void HeaderWidget::paintEvent(QPaintEvent *e) +{ + QStylePainter p(this); + QRect r = e->rect(); + + StyleHelper::horizontalHeader(&p, r); +} diff --git a/src/libtomahawk/widgets/HeaderWidget.h b/src/libtomahawk/widgets/HeaderWidget.h new file mode 100644 index 000000000..bdaef5060 --- /dev/null +++ b/src/libtomahawk/widgets/HeaderWidget.h @@ -0,0 +1,45 @@ + +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Casey Link + * + * 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 HEADERWIDGET_H +#define HEADERWIDGET_H + +#include +#include + +#include "dllmacro.h" + +class DLLEXPORT HeaderWidget : public QWidget +{ +Q_OBJECT + +public: + HeaderWidget(QWidget *parent = 0); + virtual ~HeaderWidget(); + + virtual void paintEvent(QPaintEvent *); + + +private: + + +}; + + +#endif diff --git a/src/libtomahawk/widgets/combobox.cpp b/src/libtomahawk/widgets/combobox.cpp new file mode 100644 index 000000000..6a53b8fb5 --- /dev/null +++ b/src/libtomahawk/widgets/combobox.cpp @@ -0,0 +1,79 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Casey Link + * + * 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 "combobox.h" + + +#include "utils/stylehelper.h" + +#include +#include +#include +#include + +ComboBox::ComboBox(QWidget *parent) : QComboBox(parent) +{ +} + +ComboBox::~ComboBox() +{ +} + +void ComboBox::paintEvent(QPaintEvent *) +{ + QStylePainter p(this); + p.setPen(palette().color(QPalette::Text)); + QStyleOptionComboBox cb; + initStyleOption(&cb); + QRect r = cb.rect; + + + StyleHelper::horizontalHeader(&p, r); + + if( cb.state & QStyle::State_MouseOver ) { + QRect highlightRect(r); + QSize shrink(3,4); + QSize hS(highlightRect.size()); + hS -= shrink; + highlightRect.setSize(hS); + highlightRect.translate(0,2); + p.save(); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush( StyleHelper::headerHighlightColor() ); + p.drawRoundedRect(highlightRect, 10.0, 10.0); + p.restore(); + } + + QTextOption to( Qt::AlignVCenter ); + r.adjust( 8, 0, -8, 0 ); + p.setPen( Qt::white ); + p.setBrush( StyleHelper::headerTextColor() ); + p.drawText( r, cb.currentText, to ); + + + bool reverse = cb.direction == Qt::RightToLeft; + int menuButtonWidth = 12; + int left = !reverse ? r.right() - menuButtonWidth : r.left(); + int right = !reverse ? r.right() : r.left() + menuButtonWidth; + QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), r.center().y() - 3, 9, 9); + + QStyleOption arrowOpt = cb; + arrowOpt.rect = arrowRect; + StyleHelper::drawArrow(QStyle::PE_IndicatorArrowDown, &p, &arrowOpt); + +} diff --git a/src/libtomahawk/widgets/combobox.h b/src/libtomahawk/widgets/combobox.h new file mode 100644 index 000000000..df701ab95 --- /dev/null +++ b/src/libtomahawk/widgets/combobox.h @@ -0,0 +1,44 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Casey Link + * + * 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 COMBOBOX_H +#define COMBOBOX_H + +#include +#include + +#include "dllmacro.h" + +class DLLEXPORT ComboBox : public QComboBox +{ +Q_OBJECT + +public: + ComboBox(QWidget *parent = 0); + virtual ~ComboBox(); + + virtual void paintEvent(QPaintEvent *); + + +private: + + +}; + + +#endif diff --git a/src/libtomahawk/widgets/whatshotwidget.cpp b/src/libtomahawk/widgets/whatshotwidget.cpp new file mode 100644 index 000000000..894e8246f --- /dev/null +++ b/src/libtomahawk/widgets/whatshotwidget.cpp @@ -0,0 +1,193 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * 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 "whatshotwidget.h" +#include "ui_whatshotwidget.h" + +#include + +#include "viewmanager.h" +#include "sourcelist.h" +#include "tomahawksettings.h" +#include "RecentPlaylistsModel.h" + +#include "audio/audioengine.h" +#include "playlist/playlistmodel.h" +#include "playlist/treeproxymodel.h" +#include "widgets/overlaywidget.h" +#include "utils/tomahawkutils.h" +#include "utils/logger.h" +#include + +#define HISTORY_TRACK_ITEMS 25 +#define HISTORY_PLAYLIST_ITEMS 10 +#define HISTORY_RESOLVING_TIMEOUT 2500 + +using namespace Tomahawk; + +static QString s_whatsHotIdentifier = QString( "WhatsHotWidget" ); + +WhatsHotWidget::WhatsHotWidget( QWidget* parent ) + : QWidget( parent ) + , ui( new Ui::WhatsHotWidget ) +{ + ui->setupUi( this ); + + TomahawkUtils::unmarginLayout( layout() ); + TomahawkUtils::unmarginLayout( ui->verticalLayout->layout() ); + TomahawkUtils::unmarginLayout( ui->verticalLayout_2->layout() ); + TomahawkUtils::unmarginLayout( ui->horizontalLayout->layout() ); + TomahawkUtils::unmarginLayout( ui->horizontalLayout_3->layout() ); + + + m_tracksModel = new PlaylistModel( ui->tracksView ); + m_tracksModel->setStyle( TrackModel::Short ); + + ui->tracksView->setFrameShape( QFrame::NoFrame ); + ui->tracksView->setAttribute( Qt::WA_MacShowFocusRect, 0 ); + ui->tracksView->overlay()->setEnabled( false ); + ui->tracksView->setTrackModel( m_tracksModel ); + ui->tracksView->setHeaderHidden( true ); + ui->tracksView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + + + m_artistsModel = new TreeModel( ui->artistsView ); + m_artistsModel->setColumnStyle( TreeModel::TrackOnly ); + + m_artistsProxy = new TreeProxyModel( ui->artistsView ); + m_artistsProxy->setFilterCaseSensitivity( Qt::CaseInsensitive ); + m_artistsProxy->setDynamicSortFilter( true ); + + ui->artistsView->setProxyModel( m_artistsProxy ); + ui->artistsView->setTreeModel( m_artistsModel ); + ui->artistsView->setFrameShape( QFrame::NoFrame ); + ui->artistsView->setAttribute( Qt::WA_MacShowFocusRect, 0 ); + + + m_artistsProxy->sort( -1 ); // disable sorting, must be called after artistsView->setTreeModel + + ui->artistsView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + ui->artistsView->header()->setVisible( false ); + + + m_timer = new QTimer( this ); + connect( m_timer, SIGNAL( timeout() ), SLOT( checkQueries() ) ); + + + connect( Tomahawk::InfoSystem::InfoSystem::instance(), + SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), + SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); + + connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) ); + + + Tomahawk::InfoSystem::InfoCriteriaHash artistInfo; + + Tomahawk::InfoSystem::InfoRequestData requestData; + requestData.caller = s_whatsHotIdentifier; + requestData.customData = QVariantMap(); + requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( artistInfo ); + + requestData.type = Tomahawk::InfoSystem::InfoChartArtists; + Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); + + requestData.type = Tomahawk::InfoSystem::InfoChartTracks; + Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); + + tDebug() << "WhatsHot: requested InfoChartArtists+Tracks"; +} + + +WhatsHotWidget::~WhatsHotWidget() +{ + delete ui; +} + + +void +WhatsHotWidget::checkQueries() +{ + m_timer->stop(); + m_tracksModel->ensureResolved(); +} + + +void +WhatsHotWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) +{ + if ( requestData.caller != s_whatsHotIdentifier ) + { +// tDebug() << "Info of wrong type or not with our identifier"; + return; + } + + tDebug() << "WhatsHot: got something..."; + QVariantMap returnedData = output.value< QVariantMap >(); + switch ( requestData.type ) + { + case InfoSystem::InfoChartArtists: + { + const QStringList artists = returnedData["artists"].toStringList(); + tDebug() << "WhatsHot: got artists! " << artists.size(); + tDebug() << artists; + foreach ( const QString& artist, artists ) + { + m_artistsModel->addArtists( Artist::get( artist ) ); + } + break; + } + case InfoSystem::InfoChartTracks: + { + const QList tracks = returnedData["tracks"].value >(); + tDebug() << "WhatsHot: got tracks! " << tracks.size(); + foreach ( const Tomahawk::InfoSystem::ArtistTrackPair& track, tracks ) + { + query_ptr query = Query::get( track.artist, track.track, QString(), uuid() ); + m_tracksModel->append( query ); + } + break; + } + default: + return; + } +} + + +void +WhatsHotWidget::infoSystemFinished( QString target ) +{ + Q_UNUSED( target ); +} + + +void +WhatsHotWidget::changeEvent( QEvent* e ) +{ + QWidget::changeEvent( e ); + switch ( e->type() ) + { + case QEvent::LanguageChange: + ui->retranslateUi( this ); + break; + + default: + break; + } +} + + diff --git a/src/libtomahawk/widgets/whatshotwidget.h b/src/libtomahawk/widgets/whatshotwidget.h new file mode 100644 index 000000000..2cfb79312 --- /dev/null +++ b/src/libtomahawk/widgets/whatshotwidget.h @@ -0,0 +1,88 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * 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 WHATSHOTWIDGET_H +#define WHATSHOTWIDGET_H + +#include +#include +#include + +#include "playlistinterface.h" +#include "infosystem/infosystem.h" +#include "playlist.h" +#include "result.h" +#include "viewpage.h" + +#include "utils/tomahawkutils.h" + +#include "dllmacro.h" + +class TreeModel; +class PlaylistModel; +class OverlayWidget; +class TreeProxyModel; + +namespace Ui +{ + class WhatsHotWidget; +} + +class DLLEXPORT WhatsHotWidget : public QWidget, public Tomahawk::ViewPage +{ +Q_OBJECT + +public: + WhatsHotWidget( QWidget* parent = 0 ); + ~WhatsHotWidget(); + + virtual QWidget* widget() { return this; } + virtual Tomahawk::PlaylistInterface* playlistInterface() const { return 0; } + + virtual QString title() const { return tr( "Charts" ); } + virtual QString description() const { return QString(); } + + virtual bool showStatsBar() const { return false; } + virtual bool showInfoBar() const { return false; } + + virtual bool jumpToCurrentTrack() { return false; } + +protected: + void changeEvent( QEvent* e ); + +signals: + void destroyed( QWidget* widget ); + +public slots: + +private slots: + void checkQueries(); + void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); + void infoSystemFinished( QString target ); + +private: + Ui::WhatsHotWidget *ui; + + PlaylistModel* m_tracksModel; + TreeModel* m_artistsModel; + TreeProxyModel* m_artistsProxy; + + QTimer* m_timer; +}; + +#endif // WHATSHOTWIDGET_H diff --git a/src/libtomahawk/widgets/whatshotwidget.ui b/src/libtomahawk/widgets/whatshotwidget.ui new file mode 100644 index 000000000..37c35bb7f --- /dev/null +++ b/src/libtomahawk/widgets/whatshotwidget.ui @@ -0,0 +1,196 @@ + + + WhatsHotWidget + + + + 0 + 0 + 875 + 513 + + + + + + + + + + + + QComboBox::AdjustToContentsOnFirstShow + + + + 0 + 0 + + + + + Billboard + + + + + Last.fm + + + + + iTunes + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 5 + + + + + + + + QComboBox::AdjustToContentsOnFirstShow + + + + Top 100 Tracks + + + + + + + + + + + + 320 + 0 + + + + + + + + + + + + + + + QComboBox::AdjustToContentsOnFirstShow + + + + 0 + 0 + + + + + Billboard + + + + + Last.fm + + + + + iTunes + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 5 + + + + + + + + QComboBox::AdjustToContentsOnFirstShow + + + + Top 100 Tracks + + + + + + + + + + + + 320 + 0 + + + + + + + + + + + PlaylistView + QTreeView +
playlist/playlistview.h
+
+ + ArtistView + QTreeView +
artistview.h
+
+ + ComboBox + QComboBox +
widgets/combobox.h
+
+ + HeaderWidget + QWidget +
widgets/HeaderWidget.h
+
+
+ + +
diff --git a/src/sourcetree/items/collectionitem.cpp b/src/sourcetree/items/collectionitem.cpp index 6f85111af..fd05c799f 100644 --- a/src/sourcetree/items/collectionitem.cpp +++ b/src/sourcetree/items/collectionitem.cpp @@ -44,6 +44,7 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons , m_sourceInfoPage( 0 ) , m_coolPlaylistsPage( 0 ) , m_lovedTracksPage( 0 ) + , m_whatsHotPage( 0 ) { m_lovedTracksItem = new GenericPageItem( model(), this, ( m_source.isNull() ? tr( "Top Loved Tracks" ) : tr( "Loved Tracks" ) ), QIcon( RESPATH "images/loved_playlist.png" ), boost::bind( &CollectionItem::lovedTracksClicked, this ), @@ -62,6 +63,13 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons ); recent->setSortValue( -300 ); + GenericPageItem* hot = new GenericPageItem( model(), this, tr( "Charts" ), QIcon( RESPATH "images/charts.png" ), + boost::bind( &ViewManager::showWhatsHotPage, ViewManager::instance() ), + boost::bind( &ViewManager::whatsHotWidget, ViewManager::instance() ) + ); + hot->setSortValue( -300 ); + + // TODO finish implementing and making pretty // m_coolPlaylistsItem = new GenericPageItem( model(), this, tr( "Cool Stuff" ), QIcon( RESPATH "images/new-additions.png" ), // boost::bind( &CollectionItem::coolPlaylistsClicked, this ), diff --git a/src/sourcetree/items/collectionitem.h b/src/sourcetree/items/collectionitem.h index 76c639355..838099d93 100644 --- a/src/sourcetree/items/collectionitem.h +++ b/src/sourcetree/items/collectionitem.h @@ -86,6 +86,7 @@ private: Tomahawk::ViewPage* m_sourceInfoPage; Tomahawk::ViewPage* m_coolPlaylistsPage; Tomahawk::ViewPage* m_lovedTracksPage; + Tomahawk::ViewPage* m_whatsHotPage; }; diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index de12e8f77..6f622261e 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -389,6 +389,8 @@ TomahawkApp::registerMetaTypes() qRegisterMetaType< QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > >( "QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache >" ); qRegisterMetaType< DirLister::Mode >("DirLister::Mode"); + qRegisterMetaType< Tomahawk::InfoSystem::ArtistTrackPair >("Tomahawk::InfoSystem::ArtistTrackPair"); + qRegisterMetaType< QList >("QList"); qRegisterMetaType< QPersistentModelIndex >( "QPersistentModelIndex" ); } diff --git a/thirdparty/liblastfm2/src/types/Track.cpp b/thirdparty/liblastfm2/src/types/Track.cpp index 64d8288d0..35e972b81 100644 --- a/thirdparty/liblastfm2/src/types/Track.cpp +++ b/thirdparty/liblastfm2/src/types/Track.cpp @@ -51,11 +51,32 @@ lastfm::Track::Track( const QDomElement& e ) d = new TrackData; if (e.isNull()) { d->null = true; return; } - - d->artist = e.namedItem( "artist" ).toElement().text(); + + //TODO: not sure of lastfm's xml changed, but nodes have + // Artist Name.. + // as children isntead of Artist Name + // we detect both here. + QDomNode artistName = e.namedItem( "artist" ).namedItem( "name" ); + if( artistName.isNull() ) { + d->artist = e.namedItem( "artist" ).toElement().text(); + } else { + d->artist = artistName.toElement().text(); + } + d->albumArtist = e.namedItem( "albumArtist" ).toElement().text(); d->album = e.namedItem( "album" ).toElement().text(); - d->title = e.namedItem( "track" ).toElement().text(); + + + //TODO: not sure if lastfm xml's changed, or if chart.getTopTracks uses + //a different format, but the title is stored at + //Title... + //we detect both here. + QDomNode trackTitle = e.namedItem( "name" ); + if( trackTitle.isNull() ) + d->title = e.namedItem( "track" ).toElement().text(); + else + d->title = trackTitle.toElement().text(); + d->correctedArtist = e.namedItem( "correctedArtist" ).toElement().text(); d->correctedAlbumArtist = e.namedItem( "correctedAlbumArtist" ).toElement().text(); d->correctedAlbum = e.namedItem( "correctedAlbum" ).toElement().text();