1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-01 20:00:13 +02:00

Merge branch 'master' into spotifyplaylists

This commit is contained in:
Leo Franchi
2012-03-18 13:34:01 -04:00
51 changed files with 2503 additions and 1118 deletions

View File

@@ -1,3 +1,5 @@
Version 0.4.1:
Version 0.4.0:
* Added visual notification for database indexing job.
* Fixed icons not appearing in resolvers list.

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -138,5 +138,6 @@
<file>data/images/spotifycore-logo.png</file>
<file>data/sql/dbmigrate-27_to_28.sql</file>
<file>data/images/process-stop.png</file>
<file>data/icons/tomahawk-icon-128x128-grayscale.png</file>
</qresource>
</RCC>

View File

@@ -19,7 +19,7 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Playlist Url</string>
<string>Playlist URL</string>
</property>
</widget>
</item>

View File

@@ -456,7 +456,7 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
imgurl.addEncodedQueryItem( "artist", QUrl::toPercentEncoding( artistName, "", "+" ) );
imgurl.addEncodedQueryItem( "album", QUrl::toPercentEncoding( albumName, "", "+" ) );
imgurl.addQueryItem( "autocorrect", QString::number( 1 ) );
imgurl.addQueryItem( "size", "large" );
imgurl.addQueryItem( "size", "largesquare" );
imgurl.addQueryItem( "api_key", "7a90f6672a04b809ee309af169f34b8b" );
QNetworkRequest req( imgurl );
@@ -475,7 +475,7 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
imgurl.addQueryItem( "method", "artist.imageredirect" );
imgurl.addEncodedQueryItem( "artist", QUrl::toPercentEncoding( artistName, "", "+" ) );
imgurl.addQueryItem( "autocorrect", QString::number( 1 ) );
imgurl.addQueryItem( "size", "large" );
imgurl.addQueryItem( "size", "largesquare" );
imgurl.addQueryItem( "api_key", "7a90f6672a04b809ee309af169f34b8b" );
QNetworkRequest req( imgurl );

View File

@@ -51,7 +51,7 @@ public:
SpotifyAccountFactory() {}
virtual Account* createAccount( const QString& accountId = QString() );
virtual QString description() const { return tr( "Play music from and sync your playlists with Spotify" ); }
virtual QString description() const { return tr( "Play music from and sync your playlists with Spotify Premium" ); }
virtual QString factoryId() const { return "spotifyaccount"; }
virtual QString prettyName() const { return "Spotify"; }

View File

@@ -38,7 +38,7 @@ public:
virtual QString prettyName() const { return "Google"; }
virtual QString factoryId() const { return "googleaccount"; }
QString description() const { return tr( "Connect to GChat to find your friends" ); }
QString description() const { return tr( "Connect to Google Talk to find your friends" ); }
virtual QPixmap icon() const;
virtual Account* createAccount( const QString& pluginId );
};

View File

@@ -252,7 +252,7 @@ void
AudioControls::onCoverUpdated()
{
Query* query = qobject_cast< Query* >( sender() );
if ( !query || query != m_currentTrack->toQuery().data() )
if ( !query || !m_currentTrack || query != m_currentTrack->toQuery().data() )
return;
setCover();
@@ -277,7 +277,7 @@ void
AudioControls::onSocialActionsLoaded()
{
Query* query = qobject_cast< Query* >( sender() );
if ( !query || query != m_currentTrack->toQuery().data() )
if ( !query || !m_currentTrack || query != m_currentTrack->toQuery().data() )
return;
setSocialActions();

View File

@@ -77,6 +77,10 @@ set( libGuiSources
playlist/artistview.cpp
playlist/customplaylistview.cpp
playlist/ViewHeader.cpp
playlist/RecentlyAddedModel.cpp
playlist/RecentlyPlayedModel.cpp
playlist/PlaylistLargeItemDelegate.cpp
playlist/PlaylistChartItemDelegate.cpp
playlist/dynamic/DynamicPlaylist.cpp
playlist/dynamic/DynamicView.cpp

View File

@@ -30,6 +30,7 @@ using namespace Tomahawk;
using namespace Accounts;
#define ACCOUNTMODEL_DEBUG 0
AccountModel::AccountModel( QObject* parent )
: QAbstractListModel( parent )
{

View File

@@ -26,6 +26,8 @@
#include <attica/content.h>
#define ACCOUNTMODELNODE_DEBUG 0
namespace Tomahawk {
namespace Accounts {
@@ -87,7 +89,9 @@ struct AccountModelNode {
{
if ( AccountManager::instance()->factoryForAccount( acct ) == fac )
{
// qDebug() << "Found account for factory:" << acct->accountFriendlyName();
#if ACCOUNTMODELNODE_DEBUG
qDebug() << "Found account for factory:" << acct->accountFriendlyName();
#endif
accounts.append( acct );
}
}
@@ -98,15 +102,24 @@ struct AccountModelNode {
init();
atticaContent = cnt;
// qDebug() << "Creating attica model node for resolver:" << cnt.id();
#if ACCOUNTMODELNODE_DEBUG
qDebug() << "Creating attica model node for resolver:" << cnt.id();
#endif
foreach ( Account* acct, AccountManager::instance()->accounts( Accounts::ResolverType ) )
{
#if ACCOUNTMODELNODE_DEBUG
qDebug() << "Checking account:" << acct->accountFriendlyName() << qobject_cast< AtticaResolverAccount* >( acct );
#endif
if ( AtticaResolverAccount* resolver = qobject_cast< AtticaResolverAccount* >( acct ) )
{
#if ACCOUNTMODELNODE_DEBUG
qDebug() << "With attica id:" << resolver->atticaId();
#endif
if ( resolver->atticaId() == atticaContent.id() )
{
// qDebug() << "found atticaaccount :" << resolver->accountFriendlyName();
#if ACCOUNTMODELNODE_DEBUG
qDebug() << "found atticaaccount :" << resolver->accountFriendlyName();
#endif
atticaAccount = resolver;
break;
}

View File

@@ -102,6 +102,8 @@ ResolverAccount::ResolverAccount( const QString& accountId, const QString& path
setAccountFriendlyName( m_resolver.data()->name() );
setTypes( AccountType( ResolverType ) );
sync();
}
@@ -225,6 +227,7 @@ AtticaResolverAccount::AtticaResolverAccount( const QString& accountId, const QS
TomahawkSettings::instance()->setValue( QString( "accounts/%1/atticaresolver" ).arg( accountId ), true );
loadIcon();
sync();
}

View File

@@ -31,7 +31,9 @@ using namespace Tomahawk;
Album::~Album()
{
#ifndef ENABLE_HEADLESS
delete m_cover;
#endif
}
@@ -74,8 +76,10 @@ Album::Album( unsigned int id, const QString& name, const Tomahawk::artist_ptr&
, m_id( id )
, m_name( name )
, m_artist( artist )
, m_cover( 0 )
, m_infoLoaded( false )
#ifndef ENABLE_HEADLESS
, m_cover( 0 )
#endif
{
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),

View File

@@ -73,11 +73,13 @@ private:
QString m_name;
artist_ptr m_artist;
QByteArray m_coverBuffer;
mutable QPixmap* m_cover;
bool m_infoLoaded;
mutable QString m_uuid;
#ifndef ENABLE_HEADLESS
mutable QPixmap* m_cover;
mutable QHash< int, QPixmap > m_coverCache;
#endif
Tomahawk::playlistinterface_ptr m_playlistInterface;
};

View File

@@ -31,7 +31,9 @@ using namespace Tomahawk;
Artist::~Artist()
{
#ifndef ENABLE_HEADLESS
delete m_cover;
#endif
}
@@ -73,8 +75,10 @@ Artist::Artist( unsigned int id, const QString& name )
: QObject()
, m_id( id )
, m_name( name )
, m_cover( 0 )
, m_infoLoaded( false )
#ifndef ENABLE_HEADLESS
, m_cover( 0 )
#endif
{
m_sortname = DatabaseImpl::sortname( name, true );

View File

@@ -72,11 +72,13 @@ private:
QString m_name;
QString m_sortname;
QByteArray m_coverBuffer;
mutable QPixmap* m_cover;
bool m_infoLoaded;
mutable QString m_uuid;
#ifndef ENABLE_HEADLESS
mutable QPixmap* m_cover;
mutable QHash< int, QPixmap > m_coverCache;
#endif
Tomahawk::playlistinterface_ptr m_playlistInterface;
};

View File

@@ -65,9 +65,10 @@ DatabaseCommand_LoadSocialActions::exec( DatabaseImpl* dbi )
action.action = query.value( 0 ); // action
action.value = query.value( 1 ); // comment
action.timestamp = query.value( 2 ); // timestamp
action.source = query.value( 3 ); // source
action.source = SourceList::instance()->get( query.value( 3 ).toInt() ); // source
allSocialActions.append( action );
if ( !action.source.isNull() )
allSocialActions.append( action );
}
m_query->setAllSocialActions( allSocialActions );

View File

@@ -55,9 +55,6 @@ DatabaseCommand_Resolve::exec( DatabaseImpl* lib )
qDebug() << "Using result-hint to speed up resolving:" << m_query->resultHint();
Tomahawk::result_ptr result = lib->resultFromHint( m_query );
/* qDebug() << "Result null:" << result.isNull();
* qDebug() << "Collection null:" << result->collection().isNull();
* qDebug() << "Source null:" << result->collection()->source().isNull();*/
if ( !result.isNull() && !result->collection().isNull() && result->collection()->source()->isOnline() )
{
QList<Tomahawk::result_ptr> res;
@@ -137,7 +134,7 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
else
{
s = SourceList::instance()->get( files_query.value( 16 ).toUInt() );
if( s.isNull() )
if ( s.isNull() )
{
qDebug() << "Could not find source" << files_query.value( 16 ).toUInt();
continue;
@@ -146,13 +143,18 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
url = QString( "servent://%1\t%2" ).arg( s->userName() ).arg( url );
}
bool cached = Tomahawk::Result::isCached( url );
Tomahawk::result_ptr result = Tomahawk::Result::get( url );
Tomahawk::artist_ptr artist =
Tomahawk::Artist::get( files_query.value( 18 ).toUInt(), files_query.value( 12 ).toString() );
Tomahawk::album_ptr album =
Tomahawk::Album::get( files_query.value( 19 ).toUInt(), files_query.value( 13 ).toString(), artist );
Tomahawk::artist_ptr composer =
Tomahawk::Artist::get( files_query.value( 20 ).toUInt(), files_query.value( 15 ).toString() );
if ( cached )
{
qDebug() << "Result already cached:" << result->toString();
res << result;
continue;
}
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( files_query.value( 18 ).toUInt(), files_query.value( 12 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( files_query.value( 19 ).toUInt(), files_query.value( 13 ).toString(), artist );
Tomahawk::artist_ptr composer = Tomahawk::Artist::get( files_query.value( 20 ).toUInt(), files_query.value( 15 ).toString() );
result->setModificationTime( files_query.value( 1 ).toUInt() );
result->setSize( files_query.value( 2 ).toUInt() );
@@ -181,6 +183,7 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
result->setAttributes( attr );
result->setCollection( s->collection() );
res << result;
}
@@ -270,7 +273,7 @@ DatabaseCommand_Resolve::fullTextResolve( DatabaseImpl* lib )
else
{
s = SourceList::instance()->get( files_query.value( 16 ).toUInt() );
if( s.isNull() )
if ( s.isNull() )
{
qDebug() << "Could not find source" << files_query.value( 16 ).toUInt();
continue;
@@ -279,13 +282,18 @@ DatabaseCommand_Resolve::fullTextResolve( DatabaseImpl* lib )
url = QString( "servent://%1\t%2" ).arg( s->userName() ).arg( url );
}
bool cached = Tomahawk::Result::isCached( url );
Tomahawk::result_ptr result = Tomahawk::Result::get( url );
Tomahawk::artist_ptr artist =
Tomahawk::Artist::get( files_query.value( 18 ).toUInt(), files_query.value( 12 ).toString() );
Tomahawk::album_ptr album =
Tomahawk::Album::get( files_query.value( 19 ).toUInt(), files_query.value( 13 ).toString(), artist );
Tomahawk::artist_ptr composer =
Tomahawk::Artist::get( files_query.value( 20 ).toUInt(), files_query.value( 15 ).toString() );
if ( cached )
{
qDebug() << "Result already cached:" << result->toString();
res << result;
continue;
}
Tomahawk::artist_ptr artist = Tomahawk::Artist::get( files_query.value( 18 ).toUInt(), files_query.value( 12 ).toString() );
Tomahawk::album_ptr album = Tomahawk::Album::get( files_query.value( 19 ).toUInt(), files_query.value( 13 ).toString(), artist );
Tomahawk::artist_ptr composer = Tomahawk::Artist::get( files_query.value( 20 ).toUInt(), files_query.value( 15 ).toString() );
result->setModificationTime( files_query.value( 1 ).toUInt() );
result->setSize( files_query.value( 2 ).toUInt() );
@@ -322,8 +330,8 @@ DatabaseCommand_Resolve::fullTextResolve( DatabaseImpl* lib )
}
result->setAttributes( attr );
result->setCollection( s->collection() );
res << result;
}

View File

@@ -482,7 +482,7 @@ DatabaseImpl::sortname( const QString& str, bool replaceArticle )
if ( replaceArticle && s.startsWith( "the " ) )
{
s = s.right( s.length() - 4 );
s = s.mid( 4 );
}
return s;

View File

@@ -0,0 +1,254 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 "PlaylistChartItemDelegate.h"
#include <QApplication>
#include <QPainter>
#include "query.h"
#include "result.h"
#include "artist.h"
#include "source.h"
#include "sourcelist.h"
#include "trackmodel.h"
#include "trackmodelitem.h"
#include "trackproxymodel.h"
#include "trackview.h"
#include "trackheader.h"
#include "utils/tomahawkutilsgui.h"
#include "utils/logger.h"
using namespace Tomahawk;
PlaylistChartItemDelegate::PlaylistChartItemDelegate( TrackView* parent, TrackProxyModel* proxy )
: QStyledItemDelegate( (QObject*)parent )
, m_view( parent )
, m_model( proxy )
{
m_topOption = QTextOption( Qt::AlignTop );
m_topOption.setWrapMode( QTextOption::NoWrap );
m_centerOption = QTextOption( Qt::AlignCenter );
m_centerOption.setWrapMode( QTextOption::NoWrap );
m_centerRightOption = QTextOption( Qt::AlignVCenter | Qt::AlignRight );
m_centerRightOption.setWrapMode( QTextOption::NoWrap );
m_bottomOption = QTextOption( Qt::AlignBottom );
m_bottomOption.setWrapMode( QTextOption::NoWrap );
}
QSize
PlaylistChartItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QSize size = QStyledItemDelegate::sizeHint( option, index );
int stretch = 0;
switch ( index.row() )
{
case 0:
stretch = 6;
break;
case 1:
stretch = 5;
break;
case 2:
stretch = 4;
break;
default:
if ( index.row() < 10 )
stretch = 3;
else
stretch = 2;
}
if ( index.isValid() )
{
int rowHeight = option.fontMetrics.height() + 8;
size.setHeight( rowHeight * stretch );
}
return size;
}
QWidget*
PlaylistChartItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
Q_UNUSED( parent );
Q_UNUSED( option );
Q_UNUSED( index );
return 0;
}
void
PlaylistChartItemDelegate::prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, TrackModelItem* item ) const
{
initStyleOption( option, index );
if ( item->isPlaying() )
{
option->palette.setColor( QPalette::Highlight, option->palette.color( QPalette::Mid ) );
option->state |= QStyle::State_Selected;
}
if ( option->state & QStyle::State_Selected )
{
option->palette.setColor( QPalette::Text, option->palette.color( QPalette::HighlightedText ) );
}
else
{
float opacity = 0.0;
if ( item->query()->results().count() )
opacity = item->query()->results().first()->score();
opacity = qMax( (float)0.3, opacity );
QColor textColor = TomahawkUtils::alphaBlend( option->palette.color( QPalette::Text ), option->palette.color( QPalette::BrightText ), opacity );
option->palette.setColor( QPalette::Text, textColor );
}
}
void
PlaylistChartItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
TrackModelItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
QStyleOptionViewItemV4 opt = option;
prepareStyleOption( &opt, index, item );
opt.text.clear();
qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );
if ( m_view->header()->visualIndex( index.column() ) > 0 )
return;
QPixmap pixmap, avatar;
QString artist, track, upperText, lowerText;
unsigned int duration = 0;
if ( item->query()->results().count() )
{
artist = item->query()->results().first()->artist()->name();
track = item->query()->results().first()->track();
duration = item->query()->results().first()->duration();
}
else
{
artist = item->query()->artist();
track = item->query()->track();
}
painter->save();
{
QRect r = opt.rect.adjusted( 3, 6, 0, -6 );
// Paint Now Playing Speaker Icon
if ( item->isPlaying() )
{
QPixmap nowPlayingIcon = TomahawkUtils::defaultPixmap( TomahawkUtils::NowPlayingSpeaker );
QRect npr = r.adjusted( 3, r.height() / 2 - nowPlayingIcon.height() / 2, 18 - r.width(), -r.height() / 2 + nowPlayingIcon.height() / 2 );
nowPlayingIcon = TomahawkUtils::defaultPixmap( TomahawkUtils::NowPlayingSpeaker, TomahawkUtils::Original, npr.size() );
painter->drawPixmap( npr, nowPlayingIcon );
r.adjust( 22, 0, 0, 0 );
}
QFont figureFont = opt.font;
figureFont.setPixelSize( 18 );
figureFont.setWeight( 99 );
QFont boldFont = opt.font;
boldFont.setPixelSize( 15 );
boldFont.setWeight( 99 );
QFont smallBoldFont = opt.font;
smallBoldFont.setPixelSize( 12 );
smallBoldFont.setWeight( 80 );
QFont durationFont = opt.font;
durationFont.setPixelSize( 12 );
durationFont.setWeight( 80 );
if ( index.row() == 0 )
{
figureFont.setPixelSize( 36 );
boldFont.setPixelSize( 26 );
smallBoldFont.setPixelSize( 22 );
}
else if ( index.row() == 1 )
{
figureFont.setPixelSize( 30 );
boldFont.setPixelSize( 22 );
smallBoldFont.setPixelSize( 18 );
}
else if ( index.row() == 2 )
{
figureFont.setPixelSize( 24 );
boldFont.setPixelSize( 18 );
smallBoldFont.setPixelSize( 14 );
}
else if ( index.row() >= 10 )
{
boldFont.setPixelSize( 12 );
smallBoldFont.setPixelSize( 11 );
}
QRect figureRect = r.adjusted( 0, 0, -option.rect.width() + 60 - 6 + r.left(), 0 );
painter->setFont( figureFont );
painter->setPen( option.palette.text().color().lighter( 450 ) );
painter->drawText( figureRect, QString::number( index.row() + 1 ), m_centerOption );
painter->setPen( opt.palette.text().color() );
QRect pixmapRect = r.adjusted( figureRect.width() + 6, 0, -option.rect.width() + figureRect.width() + option.rect.height() - 6 + r.left(), 0 );
pixmap = item->query()->cover( pixmapRect.size(), false );
if ( !pixmap )
{
pixmap = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultTrackImage, TomahawkUtils::ScaledCover, pixmapRect.size() );
}
painter->drawPixmap( pixmapRect, pixmap );
r.adjust( pixmapRect.width() + figureRect.width() + 18, 1, -28, 0 );
QRect leftRect = r.adjusted( 0, 0, -48, 0 );
QRect rightRect = r.adjusted( r.width() - 40, 0, 0, 0 );
painter->setFont( boldFont );
QString text = painter->fontMetrics().elidedText( artist, Qt::ElideRight, leftRect.width() );
painter->drawText( leftRect, text, m_topOption );
painter->setFont( smallBoldFont );
text = painter->fontMetrics().elidedText( track, Qt::ElideRight, leftRect.width() );
painter->drawText( index.row() >= 10 ? leftRect : leftRect.adjusted( 0, painter->fontMetrics().height() + 6, 0, 0 ), text, index.row() >= 10 ? m_bottomOption : m_topOption );
if ( duration > 0 )
{
painter->setFont( durationFont );
text = painter->fontMetrics().elidedText( TomahawkUtils::timeToString( duration ), Qt::ElideRight, rightRect.width() );
painter->drawText( rightRect, text, m_centerRightOption );
}
}
painter->restore();
}

View File

@@ -0,0 +1,56 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 PLAYLISTCHARTITEMDELEGATE_H
#define PLAYLISTCHARTITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QTextOption>
#include "dllmacro.h"
class TrackModel;
class TrackModelItem;
class TrackProxyModel;
class TrackView;
class DLLEXPORT PlaylistChartItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
PlaylistChartItemDelegate( TrackView* parent = 0, TrackProxyModel* proxy = 0 );
protected:
void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
private:
void prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, TrackModelItem* item ) const;
QTextOption m_topOption;
QTextOption m_centerOption;
QTextOption m_centerRightOption;
QTextOption m_bottomOption;
TrackView* m_view;
TrackProxyModel* m_model;
};
#endif // PLAYLISTCHARTITEMDELEGATE_H

View File

@@ -0,0 +1,263 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 "PlaylistLargeItemDelegate.h"
#include <QApplication>
#include <QPainter>
#include <QAbstractTextDocumentLayout>
#include "query.h"
#include "result.h"
#include "artist.h"
#include "source.h"
#include "sourcelist.h"
#include "trackmodel.h"
#include "trackmodelitem.h"
#include "trackproxymodel.h"
#include "trackview.h"
#include "trackheader.h"
#include "utils/tomahawkutilsgui.h"
#include "utils/logger.h"
using namespace Tomahawk;
PlaylistLargeItemDelegate::PlaylistLargeItemDelegate( TrackView* parent, TrackProxyModel* proxy )
: QStyledItemDelegate( (QObject*)parent )
, m_view( parent )
, m_model( proxy )
{
m_topOption = QTextOption( Qt::AlignTop );
m_topOption.setWrapMode( QTextOption::NoWrap );
m_centerRightOption = QTextOption( Qt::AlignVCenter | Qt::AlignRight );
m_centerRightOption.setWrapMode( QTextOption::NoWrap );
m_bottomOption = QTextOption( Qt::AlignBottom );
m_bottomOption.setWrapMode( QTextOption::NoWrap );
}
QSize
PlaylistLargeItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QSize size = QStyledItemDelegate::sizeHint( option, index );
if ( index.isValid() )
{
int rowHeight = option.fontMetrics.height() + 8;
size.setHeight( rowHeight * 3 );
}
return size;
}
QWidget*
PlaylistLargeItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
Q_UNUSED( parent );
Q_UNUSED( option );
Q_UNUSED( index );
return 0;
}
void
PlaylistLargeItemDelegate::prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, TrackModelItem* item ) const
{
initStyleOption( option, index );
if ( item->isPlaying() )
{
option->palette.setColor( QPalette::Highlight, option->palette.color( QPalette::Mid ) );
option->state |= QStyle::State_Selected;
}
if ( option->state & QStyle::State_Selected )
{
option->palette.setColor( QPalette::Text, option->palette.color( QPalette::HighlightedText ) );
}
else
{
float opacity = 0.0;
if ( item->query()->results().count() )
opacity = item->query()->results().first()->score();
opacity = qMax( (float)0.3, opacity );
QColor textColor = TomahawkUtils::alphaBlend( option->palette.color( QPalette::Text ), option->palette.color( QPalette::BrightText ), opacity );
option->palette.setColor( QPalette::Text, textColor );
}
}
void
PlaylistLargeItemDelegate::drawRichText( QPainter* painter, const QRect& rect, int flags, QTextDocument& text ) const
{
text.setPageSize( QSize( rect.width(), QWIDGETSIZE_MAX ) );
QAbstractTextDocumentLayout* layout = text.documentLayout();
const int height = qRound( layout->documentSize().height() );
int y = rect.y();
if ( flags & Qt::AlignBottom )
y += ( rect.height() - height );
else if ( flags & Qt::AlignVCenter )
y += ( rect.height() - height ) / 2;
QAbstractTextDocumentLayout::PaintContext context;
context.palette.setColor( QPalette::Text, painter->pen().color() );
painter->save();
painter->translate( rect.x(), y );
layout->draw( painter, context );
painter->restore();
}
void
PlaylistLargeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
TrackModelItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
QStyleOptionViewItemV4 opt = option;
prepareStyleOption( &opt, index, item );
opt.text.clear();
qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );
if ( m_view->header()->visualIndex( index.column() ) > 0 )
return;
QPixmap pixmap, avatar;
QString artist, track, upperText, lowerText;
source_ptr source = item->query()->playedBy().first;
unsigned int duration = 0;
if ( item->query()->results().count() )
{
artist = item->query()->results().first()->artist()->name();
track = item->query()->results().first()->track();
duration = item->query()->results().first()->duration();
}
else
{
artist = item->query()->artist();
track = item->query()->track();
}
lowerText = item->query()->socialActionDescription( "Love", Query::Detailed );
if ( source.isNull() )
{
}
else
{
upperText = QString( "%1 - %2" ).arg( artist ).arg( track );
QString playtime = TomahawkUtils::ageToString( QDateTime::fromTime_t( item->query()->playedBy().second ), true );
if ( source == SourceList::instance()->getLocal() )
lowerText = QString( tr( "played %1 by you" ) ).arg( playtime );
else
lowerText = QString( tr( "played %1 by %2" ) ).arg( playtime ).arg( source->friendlyName() );
}
painter->save();
{
QRect r = opt.rect.adjusted( 3, 6, 0, -6 );
// Paint Now Playing Speaker Icon
if ( item->isPlaying() )
{
QPixmap nowPlayingIcon = TomahawkUtils::defaultPixmap( TomahawkUtils::NowPlayingSpeaker );
QRect npr = r.adjusted( 3, r.height() / 2 - nowPlayingIcon.height() / 2, 18 - r.width(), -r.height() / 2 + nowPlayingIcon.height() / 2 );
nowPlayingIcon = TomahawkUtils::defaultPixmap( TomahawkUtils::NowPlayingSpeaker, TomahawkUtils::Original, npr.size() );
painter->drawPixmap( npr, nowPlayingIcon );
r.adjust( 22, 0, 0, 0 );
}
painter->setPen( opt.palette.text().color() );
QSize avatarSize( 32, 32 );
QRect pixmapRect = r.adjusted( 6, 0, -option.rect.width() + option.rect.height() - 6 + r.left(), 0 );
QRect avatarRect = r.adjusted( option.rect.width() - r.left() - 12 - avatarSize.width(), ( option.rect.height() - avatarSize.height() ) / 2 - 5, 0, 0 );
avatarRect.setSize( avatarSize );
if ( source )
avatar = source->avatar( Source::FancyStyle, avatarRect.size() );
pixmap = item->query()->cover( pixmapRect.size(), false );
if ( !pixmap )
{
pixmap = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultTrackImage, TomahawkUtils::ScaledCover, pixmapRect.size() );
}
painter->drawPixmap( pixmapRect, pixmap );
if ( !avatar.isNull() )
painter->drawPixmap( avatarRect, avatar );
QFont boldFont = opt.font;
boldFont.setPixelSize( 15 );
boldFont.setWeight( 99 );
QFont smallBoldFont = opt.font;
smallBoldFont.setPixelSize( 12 );
smallBoldFont.setBold( true );
smallBoldFont.setWeight( 80 );
QFont smallFont = opt.font;
smallFont.setPixelSize( 10 );
r.adjust( pixmapRect.width() + 12, 1, -28 - avatar.width(), 0 );
QRect leftRect = r.adjusted( 0, 0, -48, 0 );
QRect rightRect = r.adjusted( r.width() - 40, 0, 0, 0 );
painter->setFont( boldFont );
QString text = painter->fontMetrics().elidedText( artist, Qt::ElideRight, leftRect.width() );
painter->drawText( leftRect, text, m_topOption );
painter->setFont( smallBoldFont );
text = painter->fontMetrics().elidedText( track, Qt::ElideRight, leftRect.width() );
painter->drawText( leftRect.adjusted( 0, 19, 0, 0 ), text, m_topOption );
painter->setFont( smallFont );
QTextDocument textDoc;
textDoc.setHtml( lowerText );
textDoc.setDocumentMargin( 0 );
textDoc.setDefaultFont( painter->font() );
textDoc.setDefaultTextOption( m_bottomOption );
if ( textDoc.idealWidth() > leftRect.width() )
textDoc.setHtml( item->query()->socialActionDescription( "Love", Query::Short ) );
drawRichText( painter, leftRect, Qt::AlignBottom, textDoc );
if ( duration > 0 )
{
painter->setFont( smallBoldFont );
text = painter->fontMetrics().elidedText( TomahawkUtils::timeToString( duration ), Qt::ElideRight, rightRect.width() );
painter->drawText( rightRect, text, m_centerRightOption );
}
}
painter->restore();
}

View File

@@ -0,0 +1,57 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 PLAYLISTLARGEITEMDELEGATE_H
#define PLAYLISTLARGEITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QTextDocument>
#include <QTextOption>
#include "dllmacro.h"
class TrackModel;
class TrackModelItem;
class TrackProxyModel;
class TrackView;
class DLLEXPORT PlaylistLargeItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
PlaylistLargeItemDelegate( TrackView* parent = 0, TrackProxyModel* proxy = 0 );
protected:
void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
private:
void prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, TrackModelItem* item ) const;
void drawRichText( QPainter* painter, const QRect& rect, int flags, QTextDocument& text ) const;
QTextOption m_topOption;
QTextOption m_centerRightOption;
QTextOption m_bottomOption;
TrackView* m_view;
TrackProxyModel* m_model;
};
#endif // PLAYLISTLARGEITEMDELEGATE_H

View File

@@ -0,0 +1,102 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2012, Christian Muehlhaeuser <muesli@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 "RecentlyAddedModel.h"
#include <QMimeData>
#include <QTreeView>
#include "source.h"
#include "sourcelist.h"
#include "database/database.h"
#include "database/databasecommand_alltracks.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#define LATEST_TRACK_ITEMS 250
using namespace Tomahawk;
RecentlyAddedModel::RecentlyAddedModel( const source_ptr& source, QObject* parent )
: TrackModel( parent )
, m_source( source )
, m_limit( LATEST_TRACK_ITEMS )
{
if ( source.isNull() )
{
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
}
else
{
onSourceAdded( source );
loadHistory();
}
}
RecentlyAddedModel::~RecentlyAddedModel()
{
}
void
RecentlyAddedModel::loadHistory()
{
if ( rowCount( QModelIndex() ) )
{
clear();
}
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_source->collection() );
cmd->setLimit( m_limit );
cmd->setSortOrder( DatabaseCommand_AllTracks::ModificationTime );
cmd->setSortDescending( true );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( append( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
void
RecentlyAddedModel::onSourcesReady()
{
Q_ASSERT( m_source.isNull() );
loadHistory();
foreach ( const source_ptr& source, SourceList::instance()->sources() )
onSourceAdded( source );
}
void
RecentlyAddedModel::onSourceAdded( const Tomahawk::source_ptr& source )
{
connect( source->collection().data(), SIGNAL( changed() ), SLOT( loadHistory() ) );
}
bool
RecentlyAddedModel::isTemporary() const
{
return true;
}

View File

@@ -0,0 +1,54 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 RECENTLYADDEDMODEL_H
#define RECENTLYADDEDMODEL_H
#include <QList>
#include <QHash>
#include "typedefs.h"
#include "trackmodel.h"
#include "dllmacro.h"
class DLLEXPORT RecentlyAddedModel : public TrackModel
{
Q_OBJECT
public:
explicit RecentlyAddedModel( const Tomahawk::source_ptr& source, QObject* parent = 0 );
~RecentlyAddedModel();
unsigned int limit() const { return m_limit; }
void setLimit( unsigned int limit ) { m_limit = limit; }
bool isTemporary() const;
private slots:
void onSourcesReady();
void onSourceAdded( const Tomahawk::source_ptr& source );
void loadHistory();
private:
Tomahawk::source_ptr m_source;
unsigned int m_limit;
};
#endif // RECENTLYADDEDMODEL_H

View File

@@ -0,0 +1,140 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2012, Christian Muehlhaeuser <muesli@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 "RecentlyPlayedModel.h"
#include <QMimeData>
#include <QTreeView>
#include "source.h"
#include "sourcelist.h"
#include "database/database.h"
#include "database/databasecommand_playbackhistory.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#define HISTORY_TRACK_ITEMS 25
using namespace Tomahawk;
RecentlyPlayedModel::RecentlyPlayedModel( const source_ptr& source, QObject* parent )
: PlaylistModel( parent )
, m_source( source )
, m_limit( HISTORY_TRACK_ITEMS )
{
if ( source.isNull() )
{
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
}
else
{
onSourceAdded( source );
loadHistory();
}
}
RecentlyPlayedModel::~RecentlyPlayedModel()
{
}
void
RecentlyPlayedModel::loadHistory()
{
if ( rowCount( QModelIndex() ) )
{
clear();
}
DatabaseCommand_PlaybackHistory* cmd = new DatabaseCommand_PlaybackHistory( m_source );
cmd->setLimit( m_limit );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ),
SLOT( append( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
void
RecentlyPlayedModel::onSourcesReady()
{
Q_ASSERT( m_source.isNull() );
loadHistory();
foreach ( const source_ptr& source, SourceList::instance()->sources() )
onSourceAdded( source );
}
void
RecentlyPlayedModel::onSourceAdded( const Tomahawk::source_ptr& source )
{
connect( source.data(), SIGNAL( playbackFinished( Tomahawk::query_ptr ) ), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::UniqueConnection );
}
void
RecentlyPlayedModel::onPlaybackFinished( const Tomahawk::query_ptr& query )
{
int count = trackCount();
unsigned int playtime = query->playedBy().second;
if ( count )
{
TrackModelItem* oldestItem = itemFromIndex( index( count - 1, 0, QModelIndex() ) );
if ( oldestItem->query()->playedBy().second >= playtime )
return;
TrackModelItem* youngestItem = itemFromIndex( index( 0, 0, QModelIndex() ) );
if ( youngestItem->query()->playedBy().second <= playtime )
insert( query, 0 );
else
{
for ( int i = 0; i < count - 1; i++ )
{
TrackModelItem* item1 = itemFromIndex( index( i, 0, QModelIndex() ) );
TrackModelItem* item2 = itemFromIndex( index( i + 1, 0, QModelIndex() ) );
if ( item1->query()->playedBy().second >= playtime && item2->query()->playedBy().second <= playtime )
{
insert( query, i + 1 );
break;
}
}
}
}
else
insert( query, 0 );
if ( trackCount() > (int)m_limit )
remove( m_limit );
ensureResolved();
}
bool
RecentlyPlayedModel::isTemporary() const
{
return true;
}

View File

@@ -0,0 +1,55 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 RECENTLYPLAYEDMODEL_H
#define RECENTLYPLAYEDMODEL_H
#include <QList>
#include <QHash>
#include "typedefs.h"
#include "playlistmodel.h"
#include "dllmacro.h"
class DLLEXPORT RecentlyPlayedModel : public PlaylistModel
{
Q_OBJECT
public:
explicit RecentlyPlayedModel( const Tomahawk::source_ptr& source, QObject* parent = 0 );
~RecentlyPlayedModel();
unsigned int limit() const { return m_limit; }
void setLimit( unsigned int limit ) { m_limit = limit; }
bool isTemporary() const;
private slots:
void onSourcesReady();
void onSourceAdded( const Tomahawk::source_ptr& source );
void onPlaybackFinished( const Tomahawk::query_ptr& query );
void loadHistory();
private:
Tomahawk::source_ptr m_source;
unsigned int m_limit;
};
#endif // RECENTLYPLAYEDMODEL_H

View File

@@ -138,13 +138,3 @@ CollectionFlatModel::onTracksRemoved( const QList<Tomahawk::query_ptr>& tracks )
}
}
}
void
CollectionFlatModel::onDataChanged()
{
TrackModelItem* p = (TrackModelItem*)sender();
if ( p )
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount( QModelIndex() ) - 1 ) );
}

View File

@@ -58,8 +58,6 @@ signals:
void trackCountChanged( unsigned int tracks );
private slots:
void onDataChanged();
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks );
void onTracksRemoved( const QList<Tomahawk::query_ptr>& tracks );

View File

@@ -37,6 +37,7 @@ CustomPlaylistView::CustomPlaylistView( CustomPlaylistView::PlaylistType type, c
setFrameShape( QFrame::NoFrame );
setAttribute( Qt::WA_MacShowFocusRect, 0 );
m_model->setStyle( TrackModel::Large );
setPlaylistModel( m_model );
generateTracks();

View File

@@ -86,26 +86,6 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn
}
void
PlaylistModel::loadHistory( const Tomahawk::source_ptr& source, unsigned int amount )
{
if ( rowCount( QModelIndex() ) )
{
clear();
}
m_playlist.clear();
DatabaseCommand_PlaybackHistory* cmd = new DatabaseCommand_PlaybackHistory( source );
cmd->setLimit( amount );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ),
SLOT( append( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
void
PlaylistModel::clear()
{
@@ -277,15 +257,6 @@ PlaylistModel::trackResolved( bool )
}
void
PlaylistModel::onDataChanged()
{
TrackModelItem* p = (TrackModelItem*)sender();
if ( p && p->index.isValid() )
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) );
}
void
PlaylistModel::onRevisionLoaded( Tomahawk::PlaylistRevision revision )
{

View File

@@ -47,14 +47,12 @@ public:
explicit PlaylistModel( QObject* parent = 0 );
~PlaylistModel();
virtual QMimeData* mimeData ( const QModelIndexList& indexes ) const;
virtual QMimeData* mimeData( const QModelIndexList& indexes ) const;
virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent );
Tomahawk::playlist_ptr playlist() const { return m_playlist; }
virtual void loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEntries = true );
void loadHistory( const Tomahawk::source_ptr& source, unsigned int amount = 50 );
bool isTemporary() const;
public slots:
@@ -86,7 +84,6 @@ protected:
void removeFromWaitList( const QString& revisionguid ) { m_waitForRevision.removeAll( revisionguid ); }
private slots:
void onDataChanged();
void onRevisionLoaded( Tomahawk::PlaylistRevision revision );
void parsedDroppedTracks( QList<Tomahawk::query_ptr> );
void trackResolved( bool );

View File

@@ -88,6 +88,7 @@ TrackModel::columnCount( const QModelIndex& parent ) const
{
case Short:
case ShortWithAvatars:
case Large:
return 1;
break;
@@ -259,14 +260,24 @@ TrackModel::headerData( int section, Qt::Orientation orientation, int role ) con
void
TrackModel::getCover( const QModelIndex& index )
TrackModel::updateDetailedInfo( const QModelIndex& index )
{
if ( style() != TrackModel::Short )
if ( style() != TrackModel::Short && style() != TrackModel::Large )
return;
TrackModelItem* item = itemFromIndex( index );
if ( !item->query().isNull() )
if ( item->query().isNull() )
return;
if ( style() == TrackModel::Short || style() == TrackModel::Large )
{
item->query()->cover( QSize( 0, 0 ) );
}
if ( style() == TrackModel::Large )
{
item->query()->loadSocialActions();
}
}
@@ -584,3 +595,12 @@ TrackModel::columnAlignment( int column ) const
return Qt::AlignLeft;
}
}
void
TrackModel::onDataChanged()
{
TrackModelItem* p = (TrackModelItem*)sender();
if ( p && p->index.isValid() )
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) );
}

View File

@@ -36,7 +36,7 @@ Q_OBJECT
public:
enum TrackItemStyle
{ Detailed = 0, Short = 1, ShortWithAvatars = 2 };
{ Detailed = 0, Short = 1, ShortWithAvatars = 2, Large = 3 };
enum TrackModelRole
{ StyleRole = Qt::UserRole + 1 };
@@ -98,7 +98,7 @@ public:
/// Returns a flat list of all tracks in this model
QList< Tomahawk::query_ptr > queries() const;
void getCover( const QModelIndex& index );
void updateDetailedInfo( const QModelIndex& index );
signals:
void repeatModeChanged( Tomahawk::PlaylistInterface::RepeatMode mode );
@@ -134,6 +134,8 @@ protected:
TrackModelItem* rootItem() const { return m_rootItem; }
private slots:
void onDataChanged();
void onPlaybackStarted( const Tomahawk::result_ptr& result );
void onPlaybackStopped();

View File

@@ -1,3 +1,4 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
@@ -115,4 +116,5 @@ TrackModelItem::setupItem( const Tomahawk::query_ptr& query, TrackModelItem* par
connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ), SIGNAL( dataChanged() ) );
connect( query.data(), SIGNAL( resultsChanged() ), SIGNAL( dataChanged() ) );
connect( query.data(), SIGNAL( updated() ), SIGNAL( dataChanged() ) );
connect( query.data(), SIGNAL( socialActionsLoaded() ), SIGNAL( dataChanged() ) );
}

View File

@@ -147,15 +147,18 @@ TrackView::setTrackModel( TrackModel* model )
setAcceptDrops( true );
if ( model->style() == TrackModel::Short || model->style() == TrackModel::ShortWithAvatars )
switch( model->style() )
{
setHeaderHidden( true );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
}
else
{
setHeaderHidden( false );
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
case TrackModel::Short:
case TrackModel::ShortWithAvatars:
case TrackModel::Large:
setHeaderHidden( true );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
break;
default:
setHeaderHidden( false );
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
}
}
@@ -163,7 +166,7 @@ TrackView::setTrackModel( TrackModel* model )
void
TrackView::onViewChanged()
{
if ( m_model->style() != TrackModel::Short ) // eventual FIXME?
if ( m_model->style() != TrackModel::Short && m_model->style() != TrackModel::Large ) // eventual FIXME?
return;
if ( m_timer.isActive() )
@@ -196,7 +199,7 @@ TrackView::onScrollTimeout()
for ( int i = left.row(); i <= max; i++ )
{
m_model->getCover( m_proxyModel->mapToSource( m_proxyModel->index( i, 0 ) ) );
m_model->updateDetailedInfo( m_proxyModel->mapToSource( m_proxyModel->index( i, 0 ) ) );
}
}
@@ -519,7 +522,7 @@ TrackView::updateHoverIndex( const QPoint& pos )
repaint();
}
if ( !m_model || m_model->style() == TrackModel::Short || m_model->style() == TrackModel::ShortWithAvatars )
if ( !m_model || m_model->style() != TrackModel::Detailed )
return;
if ( idx.column() == TrackModel::Artist || idx.column() == TrackModel::Album )

View File

@@ -521,7 +521,7 @@ Query::setAllSocialActions( const QList< SocialAction >& socialActions )
QList< SocialAction >
Query::allSocialActions()
Query::allSocialActions() const
{
return m_allSocialActions;
}
@@ -537,7 +537,7 @@ Query::parseSocialActions()
{
Tomahawk::SocialAction socialAction;
socialAction = it.next();
if ( socialAction.timestamp.toUInt() > highestTimestamp && socialAction.source.toInt() == SourceList::instance()->getLocal()->id() )
if ( socialAction.timestamp.toUInt() > highestTimestamp && socialAction.source->id() == SourceList::instance()->getLocal()->id() )
{
m_currentSocialActions[ socialAction.action.toString() ] = socialAction.value.toBool();
}
@@ -584,6 +584,71 @@ Query::setLoved( bool loved )
}
QString
Query::socialActionDescription( const QString& action, DescriptionMode mode ) const
{
QString desc;
QList< Tomahawk::SocialAction > socialActions = allSocialActions();
QStringList actionSources;
int loveTotal = 0;
foreach ( const Tomahawk::SocialAction& sa, socialActions )
{
if ( sa.action == action )
{
if ( actionSources.contains( sa.source->friendlyName() ) )
continue;
actionSources << sa.source->friendlyName();
loveTotal++;
}
}
actionSources.clear();
int loveCounter = 0;
foreach ( const Tomahawk::SocialAction& sa, socialActions )
{
if ( sa.action == action )
{
if ( actionSources.contains( sa.source->friendlyName() ) )
continue;
actionSources << sa.source->friendlyName();
if ( ++loveCounter > 3 )
continue;
else if ( loveCounter > 1 )
{
if ( loveCounter == loveTotal )
desc += tr( " and " );
else
desc += ", ";
}
if ( sa.source->isLocal() )
{
if ( loveCounter == 1 )
desc += "<b>" + tr( "You" ) + "</b>";
else
desc += "<b>" + tr( "you" ) + "</b>";
}
else
desc += "<b>" + sa.source->friendlyName() + "</b>";
}
}
if ( loveCounter > 0 )
{
if ( loveCounter > 3 )
desc += " " + tr( "and" ) + " <b>" + tr( "%n other(s)", "", loveCounter - 3 ) + "</b>";
if ( mode == Short )
desc = "<b>" + tr( "%1 people" ).arg( loveCounter ) + "</b>";
desc += " " + tr( "loved this track" ); //FIXME: more action descs required
}
return desc;
}
#ifndef ENABLE_HEADLESS
QPixmap
Query::cover( const QSize& size, bool forceLoad ) const

View File

@@ -48,6 +48,9 @@ friend class ::DatabaseCommand_LoadPlaylistEntries;
friend class Pipeline;
public:
enum DescriptionMode
{ Detailed = 0, Short = 1 };
static query_ptr get( const QString& artist, const QString& track, const QString& album, const QID& qid = QString(), bool autoResolve = true );
static query_ptr get( const QString& query, const QID& qid );
@@ -114,8 +117,9 @@ public:
bool loved();
void loadSocialActions();
QList< Tomahawk::SocialAction > allSocialActions();
QList< Tomahawk::SocialAction > allSocialActions() const;
void setAllSocialActions( const QList< Tomahawk::SocialAction >& socialActions );
QString socialActionDescription( const QString& action, DescriptionMode mode ) const;
QWeakPointer< Tomahawk::Query > weakRef() { return m_ownRef; }
void setWeakRef( QWeakPointer< Tomahawk::Query > weakRef ) { m_ownRef = weakRef; }

View File

@@ -43,13 +43,21 @@ Result::get( const QString& url )
return s_results.value( url );
}
result_ptr r = result_ptr( new Result( url ), &QObject::deleteLater );
result_ptr r = result_ptr( new Result( url ), &Result::deleteLater );
s_results.insert( url, r );
return r;
}
bool
Result::isCached( const QString& url )
{
QMutexLocker lock( &s_mutex );
return ( s_results.contains( url ) );
}
Result::Result( const QString& url )
: QObject()
, m_url( url )
@@ -68,12 +76,21 @@ Result::Result( const QString& url )
Result::~Result()
{
}
void
Result::deleteLater()
{
QMutexLocker lock( &s_mutex );
if ( s_results.contains( m_url ) )
{
s_results.remove( m_url );
}
QObject::deleteLater();
}

View File

@@ -41,7 +41,7 @@ struct SocialAction
QVariant action;
QVariant value;
QVariant timestamp;
QVariant source;
Tomahawk::source_ptr source;
};
@@ -56,6 +56,7 @@ friend class ::DatabaseCommand_LoadFile;
public:
static Tomahawk::result_ptr get( const QString& url );
static bool isCached( const QString& url );
virtual ~Result();
QVariant toVariant() const;
@@ -108,6 +109,9 @@ public:
unsigned int trackId() const { return m_trackId; }
unsigned int fileId() const { return m_fileId; }
public slots:
void deleteLater();
signals:
// emitted when the collection this result comes from is going offline/online:
void statusChanged();

View File

@@ -52,14 +52,13 @@ QSearchField::QSearchField(QWidget *parent) : QWidget(parent)
setContentsMargins(0, 0, 0, 0);
lineEdit->setStyleSheet( "QLineEdit { border: 1px solid gray; border-radius: 6px; }" );
lineEdit->setMinimumHeight(27);
setFixedHeight(27);
#ifdef Q_WS_MAC
lineEdit->setContentsMargins(0, 0, 0, 0);
lineEdit->setMinimumHeight(27);
setFixedHeight(27);
#else
lineEdit->setContentsMargins(2, 2, 2, 2);
lineEdit->setMinimumHeight(27);
#endif
}

View File

@@ -41,6 +41,7 @@
#include "tomahawksettings.h"
#include "customplaylistview.h"
#include "PlaylistLargeItemDelegate.h"
#include "dynamic/widgets/DynamicWidget.h"
#include "widgets/welcomewidget.h"
@@ -437,7 +438,12 @@ Tomahawk::ViewPage*
ViewManager::showTopLovedPage()
{
if ( !m_topLovedWidget )
m_topLovedWidget = new CustomPlaylistView( CustomPlaylistView::TopLovedTracks, source_ptr(), m_widget );
{
CustomPlaylistView* view = new CustomPlaylistView( CustomPlaylistView::TopLovedTracks, source_ptr(), m_widget );
view->setItemDelegate( new PlaylistLargeItemDelegate( view, view->proxyModel() ) );
m_topLovedWidget = view;
}
return show( m_topLovedWidget );
}

View File

@@ -24,10 +24,10 @@
#include "playlist/albummodel.h"
#include "playlist/collectionflatmodel.h"
#include "playlist/playlistmodel.h"
#include "playlist/RecentlyAddedModel.h"
#include "playlist/RecentlyPlayedModel.h"
#include "database/database.h"
#include "database/databasecommand_alltracks.h"
#include "database/databasecommand_allalbums.h"
#include "utils/tomahawkutils.h"
@@ -61,24 +61,21 @@ SourceInfoWidget::SourceInfoWidget( const Tomahawk::source_ptr& source, QWidget*
ui->historyView->overlay()->setEnabled( false );
m_recentCollectionModel = new CollectionFlatModel( ui->recentCollectionView );
m_recentCollectionModel->setStyle( TrackModel::Short );
ui->recentCollectionView->setTrackModel( m_recentCollectionModel );
m_recentTracksModel = new RecentlyAddedModel( source, ui->recentCollectionView );
m_recentTracksModel->setStyle( TrackModel::Short );
ui->recentCollectionView->setTrackModel( m_recentTracksModel );
ui->recentCollectionView->sortByColumn( TrackModel::Age, Qt::DescendingOrder );
m_historyModel = new PlaylistModel( ui->historyView );
m_historyModel = new RecentlyPlayedModel( source, ui->historyView );
m_historyModel->setStyle( TrackModel::Short );
ui->historyView->setPlaylistModel( m_historyModel );
m_historyModel->loadHistory( source, 25 );
m_recentAlbumModel = new AlbumModel( ui->recentAlbumView );
ui->recentAlbumView->setAlbumModel( m_recentAlbumModel );
ui->recentAlbumView->proxyModel()->sort( -1 );
onCollectionChanged();
connect( source->collection().data(), SIGNAL( changed() ), SLOT( onCollectionChanged() ) );
connect( source.data(), SIGNAL( playbackFinished( Tomahawk::query_ptr ) ), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ) );
m_title = tr( "New Additions" );
if ( source->isLocal() )
@@ -103,7 +100,6 @@ SourceInfoWidget::~SourceInfoWidget()
void
SourceInfoWidget::onCollectionChanged()
{
loadTracks();
loadRecentAdditions();
}
@@ -115,36 +111,6 @@ SourceInfoWidget::loadRecentAdditions()
}
void
SourceInfoWidget::loadTracks()
{
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_source->collection() );
cmd->setLimit( 250 );
cmd->setSortOrder( DatabaseCommand_AllTracks::ModificationTime );
cmd->setSortDescending( true );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( onLoadedTrackHistory( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
void
SourceInfoWidget::onLoadedTrackHistory( const QList<Tomahawk::query_ptr>& queries )
{
m_recentCollectionModel->clear();
m_recentCollectionModel->append( queries );
}
void
SourceInfoWidget::onPlaybackFinished( const Tomahawk::query_ptr& query )
{
m_historyModel->insert( query, 0 );
}
void
SourceInfoWidget::changeEvent( QEvent* e )
{

View File

@@ -28,7 +28,8 @@
class AlbumModel;
class CollectionFlatModel;
class PlaylistModel;
class RecentlyAddedModel;
class RecentlyPlayedModel;
namespace Ui
{
@@ -58,18 +59,15 @@ protected:
void changeEvent( QEvent* e );
private slots:
void loadTracks();
void loadRecentAdditions();
void onCollectionChanged();
void onPlaybackFinished( const Tomahawk::query_ptr& query );
void onLoadedTrackHistory( const QList<Tomahawk::query_ptr>& queries );
private:
Ui::SourceInfoWidget *ui;
CollectionFlatModel* m_recentCollectionModel;
PlaylistModel* m_historyModel;
RecentlyAddedModel* m_recentTracksModel;
RecentlyPlayedModel* m_historyModel;
AlbumModel* m_recentAlbumModel;
Tomahawk::source_ptr m_source;

View File

@@ -29,16 +29,14 @@
#include "audio/audioengine.h"
#include "playlist/albummodel.h"
#include "playlist/playlistmodel.h"
#include "playlist/RecentlyPlayedModel.h"
#include "widgets/overlaywidget.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include "dynamic/GeneratorInterface.h"
#include "RecentlyPlayedPlaylistsModel.h"
#define HISTORY_TRACK_ITEMS 25
#define HISTORY_PLAYLIST_ITEMS 10
#define HISTORY_RESOLVING_TIMEOUT 2500
using namespace Tomahawk;
@@ -72,7 +70,7 @@ WelcomeWidget::WelcomeWidget( QWidget* parent )
ui->playlistWidget->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
updatePlaylists();
m_tracksModel = new PlaylistModel( ui->tracksView );
m_tracksModel = new RecentlyPlayedModel( source_ptr(), ui->tracksView );
m_tracksModel->setStyle( TrackModel::ShortWithAvatars );
ui->tracksView->overlay()->setEnabled( false );
ui->tracksView->setPlaylistModel( m_tracksModel );
@@ -81,9 +79,6 @@ WelcomeWidget::WelcomeWidget( QWidget* parent )
ui->additionsView->setAlbumModel( m_recentAlbumsModel );
ui->additionsView->proxyModel()->sort( -1 );
m_timer = new QTimer( this );
connect( m_timer, SIGNAL( timeout() ), SLOT( checkQueries() ) );
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
connect( ui->playlistWidget, SIGNAL( activated( QModelIndex ) ), SLOT( onPlaylistActivated( QModelIndex ) ) );
@@ -100,7 +95,6 @@ WelcomeWidget::~WelcomeWidget()
void
WelcomeWidget::loadData()
{
m_recentAlbumsModel->addFilteredCollection( collection_ptr(), 20, DatabaseCommand_AllAlbums::ModificationTime, true );
}
@@ -129,13 +123,18 @@ WelcomeWidget::isBeingPlayed() const
void
WelcomeWidget::onSourcesReady()
{
m_tracksModel->loadHistory( Tomahawk::source_ptr(), HISTORY_TRACK_ITEMS );
foreach ( const source_ptr& source, SourceList::instance()->sources() )
onSourceAdded( source );
}
void
WelcomeWidget::onSourceAdded( const Tomahawk::source_ptr& source )
{
connect( source->collection().data(), SIGNAL( changed() ), SLOT( updateRecentAdditions() ), Qt::UniqueConnection );
}
void
WelcomeWidget::updateRecentAdditions()
{
@@ -157,66 +156,6 @@ WelcomeWidget::updatePlaylists()
}
void
WelcomeWidget::onSourceAdded( const Tomahawk::source_ptr& source )
{
connect( source->collection().data(), SIGNAL( changed() ), SLOT( updateRecentAdditions() ), Qt::UniqueConnection );
connect( source.data(), SIGNAL( playbackFinished( Tomahawk::query_ptr ) ), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::UniqueConnection );
}
void
WelcomeWidget::checkQueries()
{
if ( m_timer->isActive() )
m_timer->stop();
m_tracksModel->ensureResolved();
}
void
WelcomeWidget::onPlaybackFinished( const Tomahawk::query_ptr& query )
{
int count = m_tracksModel->trackCount();
unsigned int playtime = query->playedBy().second;
if ( count )
{
TrackModelItem* oldestItem = m_tracksModel->itemFromIndex( m_tracksModel->index( count - 1, 0, QModelIndex() ) );
if ( oldestItem->query()->playedBy().second >= playtime )
return;
TrackModelItem* youngestItem = m_tracksModel->itemFromIndex( m_tracksModel->index( 0, 0, QModelIndex() ) );
if ( youngestItem->query()->playedBy().second <= playtime )
m_tracksModel->insert( query, 0 );
else
{
for ( int i = 0; i < count - 1; i++ )
{
TrackModelItem* item1 = m_tracksModel->itemFromIndex( m_tracksModel->index( i, 0, QModelIndex() ) );
TrackModelItem* item2 = m_tracksModel->itemFromIndex( m_tracksModel->index( i + 1, 0, QModelIndex() ) );
if ( item1->query()->playedBy().second >= playtime && item2->query()->playedBy().second <= playtime )
{
m_tracksModel->insert( query, i + 1 );
break;
}
}
}
}
else
m_tracksModel->insert( query, 0 );
if ( m_tracksModel->trackCount() > HISTORY_TRACK_ITEMS )
m_tracksModel->remove( HISTORY_TRACK_ITEMS );
if ( m_timer->isActive() )
m_timer->stop();
m_timer->start( HISTORY_RESOLVING_TIMEOUT );
}
void
WelcomeWidget::onPlaylistActivated( const QModelIndex& item )
{

View File

@@ -34,7 +34,7 @@
#include "dllmacro.h"
class AlbumModel;
class PlaylistModel;
class RecentlyPlayedModel;
class OverlayWidget;
namespace Ui
@@ -106,21 +106,17 @@ public slots:
void updateRecentAdditions();
void loadData();
private slots:
void onSourcesReady();
void onSourceAdded( const Tomahawk::source_ptr& source );
void onPlaylistActivated( const QModelIndex& );
void onPlaybackFinished( const Tomahawk::query_ptr& query );
void checkQueries();
private:
Ui::WelcomeWidget *ui;
PlaylistModel* m_tracksModel;
RecentlyPlayedModel* m_tracksModel;
AlbumModel* m_recentAlbumsModel;
QTimer* m_timer;
};
#endif // WELCOMEWIDGET_H

View File

@@ -35,6 +35,7 @@
#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"
@@ -81,6 +82,8 @@ WhatsHotWidget::WhatsHotWidget( QWidget* parent )
ui->tracksViewLeft->overlay()->setEnabled( false );
ui->tracksViewLeft->setHeaderHidden( true );
ui->tracksViewLeft->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
ui->tracksViewLeft->setItemDelegate( new PlaylistChartItemDelegate( ui->tracksViewLeft, ui->tracksViewLeft->proxyModel() ) );
ui->tracksViewLeft->setUniformRowHeights( false );
TreeProxyModel* artistsProxy = new TreeProxyModel( ui->artistsViewLeft );
artistsProxy->setFilterCaseSensitivity( Qt::CaseInsensitive );
@@ -289,7 +292,7 @@ WhatsHotWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestDat
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 );
trackModel->setStyle( TrackModel::Large );
m_trackModels[ chartId ] = trackModel;

View File

@@ -27,6 +27,11 @@
#include "utils/logger.h"
#include "widgets/SocialPlaylistWidget.h"
#include "playlist/customplaylistview.h"
#include "playlist/collectionview.h"
#include "playlist/playlistview.h"
#include "playlist/RecentlyAddedModel.h"
#include "playlist/RecentlyPlayedModel.h"
#include "playlist/PlaylistLargeItemDelegate.h"
#include "source.h"
#include "sourcelist.h"
@@ -40,12 +45,14 @@ SourceItem::SourceItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahaw
, m_playlists( 0 )
, m_stations( 0 )
, m_latchedOn( false )
, m_sourceInfoItem( 0 )
, m_sourceInfoItem( 0 )
, m_coolPlaylistsItem( 0 )
, m_collectionPage( 0 )
, m_sourceInfoPage( 0 )
, m_coolPlaylistsPage( 0 )
, m_lovedTracksPage( 0 )
, m_latestAdditionsPage( 0 )
, m_recentPlaysPage( 0 )
, m_whatsHotPage( 0 )
{
if ( m_source.isNull() )
@@ -54,20 +61,31 @@ SourceItem::SourceItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahaw
return;
}
m_lovedTracksItem = new GenericPageItem( model(), this, tr( "Loved Tracks" ), QIcon( RESPATH "images/loved_playlist.png" ),
boost::bind( &SourceItem::lovedTracksClicked, this ),
boost::bind( &SourceItem::getLovedTracksPage, this ) );
m_lovedTracksItem->setSortValue( -250 );
m_collectionItem = new GenericPageItem( model(), this, tr( "Collection" ), QIcon( RESPATH "images/drop-song.png" ), //FIXME different icon
boost::bind( &SourceItem::collectionClicked, this ),
boost::bind( &SourceItem::getCollectionPage, this ) );
m_collectionItem->setSortValue( -350 );
m_sourceInfoItem = new GenericPageItem( model(), this, tr( "New Additions" ), QIcon( RESPATH "images/new-additions.png" ),
/* m_sourceInfoItem = new GenericPageItem( model(), this, tr( "New Additions" ), QIcon( RESPATH "images/new-additions.png" ),
boost::bind( &SourceItem::sourceInfoClicked, this ),
boost::bind( &SourceItem::getSourceInfoPage, this ) );
m_sourceInfoItem->setSortValue( -300 );
boost::bind( &SourceItem::getSourceInfoPage, this ) );*/
m_latestAdditionsItem = new GenericPageItem( model(), this, tr( "Latest Additions" ), QIcon( RESPATH "images/new-additions.png" ),
boost::bind( &SourceItem::latestAdditionsClicked, this ),
boost::bind( &SourceItem::getLatestAdditionsPage, this ) );
m_recentPlaysItem = new GenericPageItem( model(), this, tr( "Recently Played" ), QIcon( RESPATH "images/new-additions.png" ),
boost::bind( &SourceItem::recentPlaysClicked, this ),
boost::bind( &SourceItem::getRecentPlaysPage, this ) );
m_lovedTracksItem = new GenericPageItem( model(), this, tr( "Loved Tracks" ), QIcon( RESPATH "images/loved_playlist.png" ),
boost::bind( &SourceItem::lovedTracksClicked, this ),
boost::bind( &SourceItem::getLovedTracksPage, this ) );
m_collectionItem->setSortValue( -350 );
// m_sourceInfoItem->setSortValue( -300 );
m_latestAdditionsItem->setSortValue( -250 );
m_recentPlaysItem->setSortValue( -200 );
m_lovedTracksItem->setSortValue( -150 );
// create category items if there are playlists to show, or stations to show
QList< playlist_ptr > playlists = source->collection()->playlists();
@@ -86,7 +104,7 @@ SourceItem::SourceItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahaw
onStationsAdded( stations );
}
if( ViewManager::instance()->pageForCollection( source->collection() ) )
if ( ViewManager::instance()->pageForCollection( source->collection() ) )
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForCollection( source->collection() ) );
m_defaultAvatar = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/user-avatar.png" ) );
@@ -284,7 +302,7 @@ SourceItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p )
for( int i = 0; i < curCount; i++ )
{
PlaylistItem* pl = qobject_cast< PlaylistItem* >( parent->children().at( i ) );
if( pl && pl->playlist() == p )
if ( pl && pl->playlist() == p )
{
parent->beginRowsRemoved( i, i );
parent->removeChild( pl );
@@ -295,20 +313,20 @@ SourceItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p )
}
}
if( ( parent == m_playlists || parent == m_stations ) &&
if ( ( parent == m_playlists || parent == m_stations ) &&
parent->children().isEmpty() && parent->parent() ) // Don't leave an empty Playlist or Station category
{
int idx = parent->parent()->children().indexOf( parent );
if( idx < 0 )
if ( idx < 0 )
return;
parent->parent()->beginRowsRemoved( idx, idx );
parent->parent()->removeChild( parent );
parent->parent()->endRowsRemoved();
if( parent == m_playlists )
if ( parent == m_playlists )
m_playlists = 0;
else if( parent == m_stations )
else if ( parent == m_stations )
m_stations = 0;
delete parent;
}
@@ -318,12 +336,10 @@ SourceItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p )
void
SourceItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
{
// qDebug() << Q_FUNC_INFO << m_source->friendlyName() << playlists.count();
if( playlists.isEmpty() )
if ( playlists.isEmpty() )
return;
if( !m_playlists )
if ( !m_playlists )
{
// add the category too
int cur = children().count();
@@ -337,19 +353,18 @@ SourceItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
int from = m_playlists->children().count() - addOffset;
m_playlists->beginRowsAdded( from, from + playlists.count() - 1 );
foreach( const playlist_ptr& p, playlists )
foreach ( const playlist_ptr& p, playlists )
{
PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p, m_playlists->children().count() - addOffset );
// qDebug() << "Playlist added:" << p->title() << p->creator() << p->info();
p->loadRevision();
items << plItem;
if( m_source->isLocal() )
if ( m_source->isLocal() )
connect( p.data(), SIGNAL( aboutToBeDeleted( Tomahawk::playlist_ptr ) ),
SLOT( onPlaylistDeleted( Tomahawk::playlist_ptr ) ), Qt::QueuedConnection );
SLOT( onPlaylistDeleted( Tomahawk::playlist_ptr ) ), Qt::QueuedConnection );
else
connect( p.data(), SIGNAL( deleted( Tomahawk::playlist_ptr ) ),
SLOT( onPlaylistDeleted( Tomahawk::playlist_ptr ) ), Qt::QueuedConnection );
SLOT( onPlaylistDeleted( Tomahawk::playlist_ptr ) ), Qt::QueuedConnection );
}
m_playlists->endRowsAdded();
@@ -357,7 +372,7 @@ SourceItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
void
SourceItem::onPlaylistDeleted( const playlist_ptr& playlist )
SourceItem::onPlaylistDeleted( const playlist_ptr& playlist )
{
playlistDeletedInternal( m_playlists, playlist );
}
@@ -366,10 +381,10 @@ SourceItem::onPlaylistDeleted( const playlist_ptr& playlist )
void
SourceItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
{
if( playlists.isEmpty() )
if ( playlists.isEmpty() )
return;
if( !m_playlists )
if ( !m_playlists )
{
// add the category too
int cur = children().count();
@@ -385,8 +400,8 @@ SourceItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
void
SourceItem::onAutoPlaylistDeleted( const dynplaylist_ptr& playlist )
{
if( !m_playlists )
qDebug() << "NO playlist category item for a deleting playlist..";
if ( !m_playlists )
qDebug() << "NO playlist category item for a deleting playlist...";
playlistDeletedInternal( m_playlists, playlist );
}
@@ -395,10 +410,10 @@ SourceItem::onAutoPlaylistDeleted( const dynplaylist_ptr& playlist )
void
SourceItem::onStationsAdded( const QList< dynplaylist_ptr >& stations )
{
if( stations.isEmpty() )
if ( stations.isEmpty() )
return;
if( !m_stations )
if ( !m_stations )
{
// add the category too
int cur = children().count();
@@ -428,7 +443,7 @@ SourceItem::requestExpanding()
ViewPage*
SourceItem::sourceInfoClicked()
{
if( m_source.isNull() )
if ( m_source.isNull() )
return 0;
m_sourceInfoPage = ViewManager::instance()->show( m_source );
@@ -446,7 +461,7 @@ SourceItem::getSourceInfoPage() const
ViewPage*
SourceItem::collectionClicked()
{
if( m_source.isNull() )
if ( m_source.isNull() )
return 0;
m_collectionPage = ViewManager::instance()->show( m_source->collection() );
@@ -486,7 +501,12 @@ ViewPage*
SourceItem::lovedTracksClicked()
{
if ( !m_lovedTracksPage )
m_lovedTracksPage = new CustomPlaylistView( m_source.isNull() ? CustomPlaylistView::TopLovedTracks : CustomPlaylistView::SourceLovedTracks, m_source, ViewManager::instance()->widget() );
{
CustomPlaylistView* view = new CustomPlaylistView( m_source.isNull() ? CustomPlaylistView::TopLovedTracks : CustomPlaylistView::SourceLovedTracks, m_source, ViewManager::instance()->widget() );
view->setItemDelegate( new PlaylistLargeItemDelegate( view, view->proxyModel() ) );
m_lovedTracksPage = view;
}
ViewManager::instance()->show( m_lovedTracksPage );
return m_lovedTracksPage;
@@ -498,3 +518,64 @@ SourceItem::getLovedTracksPage() const
{
return m_lovedTracksPage;
}
ViewPage*
SourceItem::latestAdditionsClicked()
{
if ( !m_latestAdditionsPage )
{
CollectionView* cv = new CollectionView( ViewManager::instance()->widget() );
cv->setFrameShape( QFrame::NoFrame );
cv->setAttribute( Qt::WA_MacShowFocusRect, 0 );
RecentlyAddedModel* raModel = new RecentlyAddedModel( m_source, cv );
raModel->setStyle( TrackModel::Large );
cv->setItemDelegate( new PlaylistLargeItemDelegate( cv, cv->proxyModel() ) );
cv->setTrackModel( raModel );
cv->sortByColumn( TrackModel::Age, Qt::DescendingOrder );
m_latestAdditionsPage = cv;
}
ViewManager::instance()->show( m_latestAdditionsPage );
return m_latestAdditionsPage;
}
ViewPage*
SourceItem::getLatestAdditionsPage() const
{
return m_latestAdditionsPage;
}
ViewPage*
SourceItem::recentPlaysClicked()
{
if ( !m_recentPlaysPage )
{
PlaylistView* pv = new PlaylistView( ViewManager::instance()->widget() );
pv->setFrameShape( QFrame::NoFrame );
pv->setAttribute( Qt::WA_MacShowFocusRect, 0 );
RecentlyPlayedModel* raModel = new RecentlyPlayedModel( m_source, pv );
raModel->setStyle( TrackModel::Large );
pv->setItemDelegate( new PlaylistLargeItemDelegate( pv, pv->proxyModel() ) );
pv->setPlaylistModel( raModel );
m_recentPlaysPage = pv;
}
ViewManager::instance()->show( m_recentPlaysPage );
return m_recentPlaysPage;
}
ViewPage*
SourceItem::getRecentPlaysPage() const
{
return m_recentPlaysPage;
}

View File

@@ -80,6 +80,12 @@ private slots:
Tomahawk::ViewPage* lovedTracksClicked();
Tomahawk::ViewPage* getLovedTracksPage() const;
Tomahawk::ViewPage* latestAdditionsClicked();
Tomahawk::ViewPage* getLatestAdditionsPage() const;
Tomahawk::ViewPage* recentPlaysClicked();
Tomahawk::ViewPage* getRecentPlaysPage() const;
private:
void playlistsAddedInternal( SourceTreeItem* parent, const QList< Tomahawk::dynplaylist_ptr >& playlists );
template< typename T >
@@ -97,11 +103,15 @@ private:
GenericPageItem* m_sourceInfoItem;
GenericPageItem* m_coolPlaylistsItem;
GenericPageItem* m_lovedTracksItem;
GenericPageItem* m_latestAdditionsItem;
GenericPageItem* m_recentPlaysItem;
Tomahawk::ViewPage* m_collectionPage;
Tomahawk::ViewPage* m_sourceInfoPage;
Tomahawk::ViewPage* m_coolPlaylistsPage;
Tomahawk::ViewPage* m_lovedTracksPage;
Tomahawk::ViewPage* m_latestAdditionsPage;
Tomahawk::ViewPage* m_recentPlaysPage;
Tomahawk::ViewPage* m_whatsHotPage;
};

View File

@@ -35,7 +35,7 @@ TomahawkTrayIcon::TomahawkTrayIcon( QObject* parent )
, m_currentAnimationFrame( 0 )
, m_showWindowAction( 0 )
{
QIcon icon( RESPATH "icons/tomahawk-icon-128x128.png" );
QIcon icon( RESPATH "icons/tomahawk-icon-128x128-grayscale.png" );
setIcon( icon );
refreshToolTip();