1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-04-20 07:52:30 +02:00

First pass at new releases widget

This commit is contained in:
Casey Link 2012-04-11 15:58:38 -05:00
parent 69d1450b5c
commit 548aa1a194
8 changed files with 579 additions and 1 deletions

View File

@ -87,6 +87,7 @@
<file>data/images/station.png</file>
<file>data/images/new-additions.png</file>
<file>data/images/charts.png</file>
<file>data/images/new-releases.png</file>
<file>data/images/loved_playlist.png</file>
<file>data/images/dashboard.png</file>
<file>data/images/artist-icon.png</file>

View File

@ -134,6 +134,7 @@ set( libGuiSources
widgets/playlisttypeselectordlg.cpp
widgets/welcomewidget.cpp
widgets/whatshotwidget.cpp
widgets/newreleaseswidget.cpp
widgets/ChartDataLoader.cpp
widgets/RecentlyPlayedPlaylistsModel.cpp
widgets/RecentPlaylistsModel.cpp
@ -303,6 +304,7 @@ set( libUI ${libUI}
widgets/searchwidget.ui
widgets/welcomewidget.ui
widgets/whatshotwidget.ui
widgets/newreleaseswidget.ui
widgets/SocialPlaylistWidget.ui
widgets/infowidgets/sourceinfowidget.ui
widgets/infowidgets/ArtistInfoWidget.ui

View File

@ -75,6 +75,7 @@ ViewManager::ViewManager( QObject* parent )
, m_widget( new QWidget() )
, m_welcomeWidget( new WelcomeWidget() )
, m_whatsHotWidget( new WhatsHotWidget() )
, m_newReleasesWidget( new NewReleasesWidget() )
, m_topLovedWidget( 0 )
, m_recentPlaysWidget( 0 )
, m_currentMode( PlaylistInterface::Tree )
@ -119,6 +120,7 @@ ViewManager::ViewManager( QObject* parent )
connect( m_infobar, SIGNAL( autoUpdateChanged( bool ) ), SLOT( autoUpdateChanged( bool ) ) );
connect( this, SIGNAL( tomahawkLoaded() ), m_whatsHotWidget, SLOT( fetchData() ) );
connect( this, SIGNAL( tomahawkLoaded() ), m_newReleasesWidget, SLOT( fetchData() ) );
connect( this, SIGNAL( tomahawkLoaded() ), m_welcomeWidget, SLOT( loadData() ) );
/* connect( m_infobar, SIGNAL( flatMode() ), SLOT( setTableMode() ) );
@ -131,6 +133,7 @@ ViewManager::~ViewManager()
{
saveCurrentPlaylistSettings();
delete m_whatsHotWidget;
delete m_newReleasesWidget;
delete m_welcomeWidget;
delete m_topLovedWidget;
delete m_recentPlaysWidget;
@ -438,6 +441,13 @@ ViewManager::showWhatsHotPage()
}
Tomahawk::ViewPage*
ViewManager::showNewReleasesPage()
{
return show( m_newReleasesWidget );
}
Tomahawk::ViewPage*
ViewManager::showTopLovedPage()
{

View File

@ -31,6 +31,7 @@
#include "viewpage.h"
#include "widgets/welcomewidget.h"
#include "widgets/whatshotwidget.h"
#include "widgets/newreleaseswidget.h"
#include "dllmacro.h"
@ -91,6 +92,7 @@ public:
Tomahawk::ViewPage* welcomeWidget() const { return m_welcomeWidget; }
Tomahawk::ViewPage* whatsHotWidget() const { return m_whatsHotWidget; }
Tomahawk::ViewPage* newReleasesWidget() const { return m_newReleasesWidget; }
Tomahawk::ViewPage* topLovedWidget() const { return m_topLovedWidget; }
Tomahawk::ViewPage* recentPlaysWidget() const { return m_recentPlaysWidget; }
ArtistView* superCollectionView() const { return m_superCollectionView; }
@ -140,6 +142,7 @@ public slots:
Tomahawk::ViewPage* showSuperCollection();
Tomahawk::ViewPage* showWelcomePage();
Tomahawk::ViewPage* showWhatsHotPage();
Tomahawk::ViewPage* showNewReleasesPage();
Tomahawk::ViewPage* showTopLovedPage();
Tomahawk::ViewPage* showRecentPlaysPage();
void showCurrentTrack();
@ -205,6 +208,7 @@ private:
QueueView* m_queue;
WelcomeWidget* m_welcomeWidget;
WhatsHotWidget* m_whatsHotWidget;
NewReleasesWidget* m_newReleasesWidget;
Tomahawk::ViewPage* m_topLovedWidget;
Tomahawk::ViewPage* m_recentPlaysWidget;

View File

@ -0,0 +1,372 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2012, Casey Link <unnamedrambler@gmail.com>
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.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 "newreleaseswidget.h"
#include "whatshotwidget_p.h"
#include "ui_newreleaseswidget.h"
#include <QPainter>
#include <QStandardItemModel>
#include <QStandardItem>
#include "viewmanager.h"
#include "sourcelist.h"
#include "tomahawksettings.h"
#include "RecentPlaylistsModel.h"
#include "ChartDataLoader.h"
#include "audio/audioengine.h"
#include "dynamic/GeneratorInterface.h"
#include "playlist/playlistmodel.h"
#include "playlist/treeproxymodel.h"
#include "playlist/PlaylistChartItemDelegate.h"
#include "widgets/overlaywidget.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include "pipeline.h"
#define HISTORY_TRACK_ITEMS 25
#define HISTORY_PLAYLIST_ITEMS 10
#define HISTORY_RESOLVING_TIMEOUT 2500
using namespace Tomahawk;
static QString s_newReleasesIdentifier = QString( "NewReleasesWidget" );
NewReleasesWidget::NewReleasesWidget( QWidget* parent )
: QWidget( parent )
, ui( new Ui::NewReleasesWidget )
, m_sortedProxy( 0 )
, m_workerThread( 0 )
{
ui->setupUi( this );
ui->albumsView->setFrameShape( QFrame::NoFrame );
ui->albumsView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
TomahawkUtils::unmarginLayout( layout() );
TomahawkUtils::unmarginLayout( ui->stackLeft->layout() );
TomahawkUtils::unmarginLayout( ui->horizontalLayout->layout() );
TomahawkUtils::unmarginLayout( ui->horizontalLayout_2->layout() );
TomahawkUtils::unmarginLayout( ui->breadCrumbLeft->layout() );
TomahawkUtils::unmarginLayout( ui->verticalLayout->layout() );
m_crumbModelLeft = new QStandardItemModel( this );
m_sortedProxy = new QSortFilterProxyModel( this );
m_sortedProxy->setDynamicSortFilter( true );
m_sortedProxy->setFilterCaseSensitivity( Qt::CaseInsensitive );
ui->breadCrumbLeft->setRootIcon( QPixmap( RESPATH "images/new-releases.png" ) );
connect( ui->breadCrumbLeft, SIGNAL( activateIndex( QModelIndex ) ), SLOT( leftCrumbIndexChanged(QModelIndex) ) );
//m_playlistInterface = Tomahawk::playlistinterface_ptr( 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 ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
}
NewReleasesWidget::~NewReleasesWidget()
{
qDeleteAll( m_workers );
m_workers.clear();
m_workerThread->exit(0);
m_playlistInterface.clear();
delete ui;
}
Tomahawk::playlistinterface_ptr
NewReleasesWidget::playlistInterface() const
{
return m_playlistInterface;
}
bool
NewReleasesWidget::isBeingPlayed() const
{
return false;
}
bool
NewReleasesWidget::jumpToCurrentTrack()
{
return false;
}
void
NewReleasesWidget::fetchData()
{
Tomahawk::InfoSystem::InfoStringHash artistInfo;
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = s_newReleasesIdentifier;
requestData.customData = QVariantMap();
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( artistInfo );
requestData.type = Tomahawk::InfoSystem::InfoNewReleaseCapabilities;
requestData.timeoutMillis = 20000;
requestData.allSources = true;
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
tDebug( LOGVERBOSE ) << "NewReleases: requested InfoNewReleaseCapabilities";
}
void
NewReleasesWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
if ( requestData.caller != s_newReleasesIdentifier )
return;
if ( !output.canConvert< QVariantMap >() )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "NewReleases: Could not parse output";
return;
}
QVariantMap returnedData = output.toMap();
switch ( requestData.type )
{
case InfoSystem::InfoNewReleaseCapabilities:
{
tLog() << "NewReleases: got InfoNewReleaseCapabilities";
QStandardItem *rootItem= m_crumbModelLeft->invisibleRootItem();
foreach ( const QString label, returnedData.keys() )
{
QStandardItem *childItem = parseNode( rootItem, label, returnedData[label] );
rootItem->appendRow(childItem);
tLog() << "NewReleases: " << label;
}
m_sortedProxy->setSourceModel( m_crumbModelLeft );
m_sortedProxy->sort( 0, Qt::AscendingOrder );
ui->breadCrumbLeft->setModel( m_sortedProxy );
break;
}
case InfoSystem::InfoNewRelease:
{
if( !returnedData.contains("type") )
break;
const QString type = returnedData["type"].toString();
if( !returnedData.contains(type) )
break;
const QString side = requestData.customData["whatshot_side"].toString();
const QString chartId = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >().value( "nr_id" );
m_queuedFetches.remove( chartId );
ChartDataLoader* loader = new ChartDataLoader();
loader->setProperty( "nrid", chartId );
loader->moveToThread( m_workerThread );
if ( type == "albums" )
{
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( newReleasesLoaded( Tomahawk::ChartDataLoader*, QList<Tomahawk::album_ptr> ) ) );
AlbumModel* albumModel = new AlbumModel( ui->albumsView );
m_albumModels[ chartId ] = albumModel;
if ( m_queueItemToShow == chartId )
setLeftViewAlbums( albumModel );
}
else
{
// intentionally unhandled
}
QMetaObject::invokeMethod( loader, "go", Qt::QueuedConnection );
break;
}
default:
return;
}
}
void
NewReleasesWidget::infoSystemFinished( QString target )
{
Q_UNUSED( target );
}
void
NewReleasesWidget::leftCrumbIndexChanged( QModelIndex index )
{
tDebug( LOGVERBOSE ) << "NewReleases:: left crumb changed" << index.data();
QStandardItem* item = m_crumbModelLeft->itemFromIndex( m_sortedProxy->mapToSource( index ) );
if( !item )
return;
if( !item->data( Breadcrumb::ChartIdRole ).isValid() )
return;
QList<QModelIndex> indexes;
while ( index.parent().isValid() )
{
indexes.prepend(index);
index = index.parent();
}
const QString nrId = item->data( Breadcrumb::ChartIdRole ).toString();
if ( m_albumModels.contains( nrId ) )
{
setLeftViewAlbums( m_albumModels[ nrId ] );
return;
}
if ( m_queuedFetches.contains( nrId ) )
{
return;
}
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria.insert( "nr_id", nrId );
/// Remember to lower the source!
criteria.insert( "nr_source", index.data().toString().toLower() );
Tomahawk::InfoSystem::InfoRequestData requestData;
QVariantMap customData;
customData.insert( "newrelease_side", "left" );
requestData.caller = s_newReleasesIdentifier;
requestData.customData = customData;
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( criteria );
requestData.type = Tomahawk::InfoSystem::InfoNewRelease;
requestData.timeoutMillis = 20000;
requestData.allSources = true;
qDebug() << "Making infosystem request for chart of type:" <<nrId;
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
m_queuedFetches.insert( nrId );
m_queueItemToShow = nrId;
}
void
NewReleasesWidget::changeEvent( QEvent* e )
{
QWidget::changeEvent( e );
switch ( e->type() )
{
case QEvent::LanguageChange:
ui->retranslateUi( this );
break;
default:
break;
}
}
QStandardItem*
NewReleasesWidget::parseNode( QStandardItem* parentItem, const QString &label, const QVariant &data )
{
Q_UNUSED( parentItem );
// tDebug( LOGVERBOSE ) << "NewReleases:: parsing " << label;
QStandardItem *sourceItem = new QStandardItem(label);
if ( data.canConvert< QList< Tomahawk::InfoSystem::InfoStringHash > >() )
{
QList< Tomahawk::InfoSystem::InfoStringHash > charts = data.value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
foreach ( Tomahawk::InfoSystem::InfoStringHash chart, charts )
{
QStandardItem *childItem= new QStandardItem( chart[ "label" ] );
childItem->setData( chart[ "id" ], Breadcrumb::ChartIdRole );
if ( chart.value( "default", "" ) == "true")
{
childItem->setData( true, Breadcrumb::DefaultRole );
}
sourceItem->appendRow( childItem );
}
}
else if ( data.canConvert<QVariantMap>() )
{
QVariantMap dataMap = data.toMap();
foreach ( const QString childLabel,dataMap.keys() )
{
QStandardItem *childItem = parseNode( sourceItem, childLabel, dataMap[childLabel] );
sourceItem->appendRow( childItem );
}
}
else if ( data.canConvert<QVariantList>() )
{
QVariantList dataList = data.toList();
foreach ( const QVariant value, dataList )
{
QStandardItem *childItem= new QStandardItem(value.toString());
sourceItem->appendRow(childItem);
}
}
else
{
QStandardItem *childItem= new QStandardItem( data.toString() );
sourceItem->appendRow( childItem );
}
return sourceItem;
}
void
NewReleasesWidget::setLeftViewAlbums( AlbumModel* model )
{
ui->albumsView->setAlbumModel( model );
ui->albumsView->proxyModel()->sort( -1 ); // disable sorting, must be called after artistsViewLeft->setTreeModel
ui->stackLeft->setCurrentIndex( 2 );
}
void
NewReleasesWidget::newReleasesLoaded( ChartDataLoader* loader, const QList< album_ptr >& albums )
{
QString chartId = loader->property( "nrid" ).toString();
Q_ASSERT( m_albumModels.contains( chartId ) );
if ( m_albumModels.contains( chartId ) )
m_albumModels[ chartId ]->addAlbums( albums );
m_workers.remove( loader );
loader->deleteLater();
}

View File

@ -0,0 +1,126 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2012, Casey Link <unnamedrambler@gmail.com>
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.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 NEWRELEASESWIDGET_H
#define NEWRELEASESWIDGET_H
#include <QtGui/QWidget>
#include <QtGui/QListWidgetItem>
#include <QtGui/QStyledItemDelegate>
#include "playlistinterface.h"
#include "infosystem/infosystem.h"
#include "viewpage.h"
#include "utils/tomahawkutils.h"
#include "dllmacro.h"
class QSortFilterProxyModel;
class QStandardItemModel;
class QStandardItem;
class TreeModel;
class PlaylistModel;
class OverlayWidget;
class TreeProxyModel;
class AlbumModel;
namespace Ui
{
class NewReleasesWidget;
}
namespace Tomahawk
{
class ChartDataLoader;
class ChartsPlaylistInterface;
class ChartDataLoader;
}
/**
* \class
* \brief The tomahawk page that shows music charts.
*/
class DLLEXPORT NewReleasesWidget : public QWidget, public Tomahawk::ViewPage
{
Q_OBJECT
public:
NewReleasesWidget( QWidget* parent = 0 );
~NewReleasesWidget();
virtual QWidget* widget() { return this; }
virtual Tomahawk::playlistinterface_ptr playlistInterface() const;
virtual QString title() const { return tr( "New Releases" ); }
virtual QString description() const { return QString(); }
virtual bool showStatsBar() const { return false; }
virtual bool showInfoBar() const { return false; }
virtual bool jumpToCurrentTrack();
virtual bool isBeingPlayed() const;
protected:
void changeEvent( QEvent* e );
signals:
void destroyed( QWidget* widget );
public slots:
void fetchData();
private slots:
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( QString target );
void leftCrumbIndexChanged( QModelIndex );
void newReleasesLoaded( Tomahawk::ChartDataLoader*, const QList< Tomahawk::album_ptr >& );
private:
void setLeftViewArtists( TreeModel* artistModel );
void setLeftViewAlbums( AlbumModel* albumModel );
void setLeftViewTracks( PlaylistModel* trackModel );
QStandardItem* parseNode( QStandardItem* parentItem, const QString &label, const QVariant &data );
Ui::NewReleasesWidget *ui;
Tomahawk::playlistinterface_ptr m_playlistInterface;
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;
QSet< Tomahawk::ChartDataLoader* > m_workers;
// Cache our model data
QHash< QString, AlbumModel* > m_albumModels;
QString m_queueItemToShow;
QSet< QString > m_queuedFetches;
QTimer* m_timer;
friend class Tomahawk::ChartsPlaylistInterface;
};
#endif // NEWRELEASESWIDGET_H

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewReleasesWidget</class>
<widget class="QWidget" name="NewReleasesWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>875</width>
<height>513</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="Tomahawk::Breadcrumb" name="breadCrumbLeft" native="true"/>
</item>
<item>
<widget class="QStackedWidget" name="stackLeft">
<widget class="QWidget" name="page">
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
</widget>
<widget class="QWidget" name="page1">
<layout class="QHBoxLayout" name="horizontalLayout"/>
</widget>
<widget class="QWidget" name="page2">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="AlbumView" name="albumsView">
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AlbumView</class>
<extends>QListView</extends>
<header location="global">playlist/albumview.h</header>
</customwidget>
<customwidget>
<class>Tomahawk::Breadcrumb</class>
<extends>QWidget</extends>
<header>widgets/Breadcrumb.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -297,6 +297,11 @@ SourcesModel::appendGroups()
boost::bind( &ViewManager::whatsHotWidget, ViewManager::instance() ) );
hot->setSortValue( 4 );
GenericPageItem* newReleases = new GenericPageItem( this, browse, tr( "New Releases" ), QIcon( RESPATH "images/new-releases.png" ),
boost::bind( &ViewManager::showNewReleasesPage, ViewManager::instance() ),
boost::bind( &ViewManager::newReleasesWidget, ViewManager::instance() ) );
newReleases->setSortValue( 5 );
m_collectionsGroup = new GroupItem( this, m_rootItem, tr( "Friends" ), 4 );
endInsertRows();
@ -320,7 +325,7 @@ SourcesModel::appendItem( const Tomahawk::source_ptr& source )
beginInsertRows( idx, rowCount( idx ), rowCount( idx ) );
new SourceItem( this, parent, source );
endInsertRows();
parent->checkExpandedState();
}