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

Add an intermediate LovedTracksModel

This commit is contained in:
Uwe L. Korn 2013-07-31 20:35:56 +02:00
parent c7e5fc62c2
commit 6fd7c83fad
13 changed files with 637 additions and 315 deletions

View File

@ -71,6 +71,7 @@ set( libGuiSources
playlist/ColumnView.cpp
playlist/TreeWidget.cpp
playlist/ViewHeader.cpp
playlist/LovedTracksModel.cpp
playlist/TopLovedTracksModel.cpp
playlist/RecentlyAddedModel.cpp
playlist/RecentlyPlayedModel.cpp

View File

@ -0,0 +1,122 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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 "LovedTracksModel_p.h"
#include "SourceList.h"
LovedTracksModel::LovedTracksModel( QObject *parent )
: PlaylistModel( parent, new LovedTracksModelPrivate( this ) )
{
Q_D( LovedTracksModel );
d->smoothingTimer.setInterval( 300 );
d->smoothingTimer.setSingleShot( true );
connect( &d->smoothingTimer, SIGNAL( timeout() ), this, SLOT( loadTracks() ) );
}
LovedTracksModel::~LovedTracksModel()
{
}
bool
LovedTracksModel::isTemporary() const
{
return true;
}
void
LovedTracksModel::loadTracks()
{
// Implement this in subclasses.
}
void
LovedTracksModel::onSourcesReady()
{
Q_D( LovedTracksModel );
Q_ASSERT( d->source.isNull() );
loadTracks();
foreach ( const Tomahawk::source_ptr& source, SourceList::instance()->sources() )
onSourceAdded( source );
}
void
LovedTracksModel::onSourceAdded( const Tomahawk::source_ptr& source )
{
connect( source.data(), SIGNAL( socialAttributesChanged( QString ) ), SLOT( onTrackLoved() ), Qt::UniqueConnection );
}
void
LovedTracksModel::onTrackLoved()
{
Q_D( LovedTracksModel );
d->smoothingTimer.start();
}
void
LovedTracksModel::tracksLoaded( QList< Tomahawk::query_ptr > newLoved )
{
finishLoading();
QList< Tomahawk::query_ptr > tracks;
foreach ( const Tomahawk::plentry_ptr ple, playlistEntries() )
tracks << ple->query();
bool changed = false;
QList< Tomahawk::query_ptr > mergedTracks = TomahawkUtils::mergePlaylistChanges( tracks, newLoved, changed );
if ( changed )
{
QList<Tomahawk::plentry_ptr> el = playlist()->entriesFromQueries( mergedTracks, true );
clear();
appendEntries( el );
}
}
void
LovedTracksModel::setSource( const Tomahawk::source_ptr& source )
{
Q_D( LovedTracksModel );
d->source = source;
if ( source.isNull() )
{
if ( SourceList::instance()->isReady() )
onSourcesReady();
else
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
}
else
{
onSourceAdded( source );
loadTracks();
}
}

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>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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/>.
*/
#pragma once
#ifndef LOVEDTRACKSMODEL_H
#define LOVEDTRACKSMODEL_H
#include "PlaylistModel.h"
class LovedTracksModelPrivate;
class DLLEXPORT LovedTracksModel : public PlaylistModel
{
Q_OBJECT
public:
explicit LovedTracksModel( QObject* parent = 0 );
virtual ~LovedTracksModel();
unsigned int limit() const;
void setLimit( unsigned int limit );
bool isTemporary() const;
public slots:
void setSource( const Tomahawk::source_ptr& source );
private slots:
virtual void loadTracks();
void onSourcesReady();
void onSourceAdded( const Tomahawk::source_ptr& source );
void onTrackLoved();
void tracksLoaded( QList<Tomahawk::query_ptr> );
private:
Q_DECLARE_PRIVATE( LovedTracksModel )
};
#endif // LOVEDTRACKSMODEL_H

View File

@ -0,0 +1,47 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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/>.
*/
#pragma once
#ifndef LOVEDTRACKSMODEL_P_H
#define LOVEDTRACKSMODEL_P_H
#include "LovedTracksModel.h"
#include "PlaylistModel_p.h"
#include <QTimer>
class LovedTracksModelPrivate : public PlaylistModelPrivate
{
public:
LovedTracksModelPrivate( LovedTracksModel* q )
: PlaylistModelPrivate( q )
, limit( defaultNumberOfLovedTracks )
{
}
Q_DECLARE_PUBLIC( LovedTracksModel )
static const uint defaultNumberOfLovedTracks = 25;
protected:
uint limit;
Tomahawk::source_ptr source;
QTimer smoothingTimer;
};
#endif // LOVEDTRACKSMODEL_P_H

View File

@ -18,7 +18,7 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PlayableModel.h"
#include "PlayableModel_p.h"
#include "audio/AudioEngine.h"
#include "utils/TomahawkUtils.h"
@ -40,24 +40,40 @@
using namespace Tomahawk;
PlayableModel::PlayableModel( QObject* parent, bool loading )
: QAbstractItemModel( parent )
, m_rootItem( new PlayableItem( 0 ) )
, m_readOnly( true )
, m_loading( loading )
void
PlayableModel::init()
{
Q_D( PlayableModel );
connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection );
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection );
m_header << tr( "Artist" ) << tr( "Title" ) << tr( "Composer" ) << tr( "Album" ) << tr( "Track" ) << tr( "Duration" )
<< tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Accuracy" ) << tr( "Name" );
d->header << tr( "Artist" ) << tr( "Title" ) << tr( "Composer" ) << tr( "Album" ) << tr( "Track" ) << tr( "Duration" )
<< tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Accuracy" ) << tr( "Name" );
}
PlayableModel::PlayableModel( QObject* parent, bool loading )
: QAbstractItemModel( parent )
, d_ptr( new PlayableModelPrivate( this, loading ) )
{
init();
}
PlayableModel::PlayableModel( QObject* parent, PlayableModelPrivate* d )
: QAbstractItemModel( parent )
, d_ptr( d )
{
init();
}
PlayableModel::~PlayableModel()
{
Q_D( PlayableModel );
tDebug() << Q_FUNC_INFO;
delete m_rootItem;
delete d->rootItem;
}
@ -71,7 +87,8 @@ PlayableModel::createIndex( int row, int column, PlayableItem* item ) const
QModelIndex
PlayableModel::index( int row, int column, const QModelIndex& parent ) const
{
if ( !m_rootItem || row < 0 || column < 0 )
Q_D( const PlayableModel );
if ( !d->rootItem || row < 0 || column < 0 )
return QModelIndex();
PlayableItem* parentItem = itemFromIndex( parent );
@ -109,11 +126,12 @@ PlayableModel::columnCount( const QModelIndex& parent ) const
bool
PlayableModel::hasChildren( const QModelIndex& parent ) const
{
Q_D( const PlayableModel );
PlayableItem* parentItem = itemFromIndex( parent );
if ( !parentItem )
return false;
if ( parentItem == m_rootItem )
if ( parentItem == d->rootItem )
return true;
return ( !parentItem->artist().isNull() || !parentItem->album().isNull() );
@ -143,28 +161,32 @@ PlayableModel::parent( const QModelIndex& child ) const
bool
PlayableModel::isReadOnly() const
{
return m_readOnly;
Q_D( const PlayableModel );
return d->readOnly;
}
void
PlayableModel::setReadOnly( bool b )
{
m_readOnly = b;
Q_D( PlayableModel );
d->readOnly = b;
}
bool
PlayableModel::isLoading() const
{
return m_loading;
Q_D( const PlayableModel );
return d->loading;
}
QString
PlayableModel::title() const
{
return m_title;
Q_D( const PlayableModel );
return d->title;
}
@ -364,12 +386,13 @@ PlayableModel::data( const QModelIndex& index, int role ) const
QVariant
PlayableModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
Q_D( const PlayableModel );
Q_UNUSED( orientation );
if ( role == Qt::DisplayRole && section >= 0 )
{
if ( section < m_header.count() )
return m_header.at( section );
if ( section < d->header.count() )
return d->header.at( section );
else
return tr( "Name" );
}
@ -386,7 +409,8 @@ PlayableModel::headerData( int section, Qt::Orientation orientation, int role )
void
PlayableModel::setCurrentIndex( const QModelIndex& index )
{
PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
Q_D( PlayableModel );
PlayableItem* oldEntry = itemFromIndex( d->currentIndex );
if ( oldEntry )
{
oldEntry->setIsPlaying( false );
@ -395,14 +419,14 @@ PlayableModel::setCurrentIndex( const QModelIndex& index )
PlayableItem* entry = itemFromIndex( index );
if ( index.isValid() && entry && !entry->query().isNull() )
{
m_currentIndex = index;
m_currentUuid = entry->query()->id();
d->currentIndex = index;
d->currentUuid = entry->query()->id();
entry->setIsPlaying( true );
}
else
{
m_currentIndex = QModelIndex();
m_currentUuid = QString();
d->currentIndex = QModelIndex();
d->currentUuid = QString();
}
emit currentIndexChanged();
@ -431,14 +455,16 @@ PlayableModel::flags( const QModelIndex& index ) const
QPersistentModelIndex
PlayableModel::currentItem()
{
return m_currentIndex;
Q_D( PlayableModel );
return d->currentIndex;
}
QID
PlayableModel::currentItemUuid()
{
return m_currentUuid;
Q_D( PlayableModel );
return d->currentUuid;
}
@ -597,14 +623,15 @@ PlayableModel::mimeData( const QModelIndexList &indexes ) const
void
PlayableModel::clear()
{
Q_D( PlayableModel );
if ( rowCount( QModelIndex() ) )
{
finishLoading();
emit beginResetModel();
delete m_rootItem;
m_rootItem = 0;
m_rootItem = new PlayableItem( 0 );
delete d->rootItem;
d->rootItem = 0;
d->rootItem = new PlayableItem( 0 );
emit endResetModel();
}
}
@ -613,10 +640,11 @@ PlayableModel::clear()
QList< query_ptr >
PlayableModel::queries() const
{
Q_ASSERT( m_rootItem );
Q_D( const PlayableModel );
Q_ASSERT( d->rootItem );
QList< query_ptr > tracks;
foreach ( PlayableItem* item, m_rootItem->children )
foreach ( PlayableItem* item, d->rootItem->children )
{
tracks << item->query();
}
@ -629,6 +657,7 @@ template <typename T>
void
PlayableModel::insertInternal( const QList< T >& items, int row, const QList< Tomahawk::PlaybackLog >& logs )
{
Q_D( PlayableModel );
if ( !items.count() )
{
emit itemCountChanged( rowCount( QModelIndex() ) );
@ -648,7 +677,7 @@ PlayableModel::insertInternal( const QList< T >& items, int row, const QList< To
PlayableItem* plitem;
foreach ( const T& item, items )
{
plitem = new PlayableItem( item, m_rootItem, row + i );
plitem = new PlayableItem( item, d->rootItem, row + i );
plitem->index = createIndex( row + i, 0, plitem );
if ( plitem->query() )
{
@ -683,6 +712,7 @@ PlayableModel::remove( int row, bool moreToCome )
void
PlayableModel::removeIndex( const QModelIndex& index, bool moreToCome )
{
Q_D( PlayableModel );
if ( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this, "remove",
@ -698,7 +728,7 @@ PlayableModel::removeIndex( const QModelIndex& index, bool moreToCome )
PlayableItem* item = itemFromIndex( index );
if ( item )
{
if ( index == m_currentIndex )
if ( index == d->currentIndex )
setCurrentIndex( QModelIndex() );
emit beginRemoveRows( index.parent(), index.row(), index.row() );
@ -741,18 +771,19 @@ PlayableModel::removeIndexes( const QList<QPersistentModelIndex>& indexes )
}
}
PlayableItem*
PlayableModel::rootItem() const
{
return m_rootItem;
Q_D( const PlayableModel );
return d->rootItem;
}
void
PlayableModel::onPlaybackStarted( const Tomahawk::result_ptr& result )
{
PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
Q_D( PlayableModel );
PlayableItem* oldEntry = itemFromIndex( d->currentIndex );
if ( oldEntry && ( oldEntry->query().isNull() || !oldEntry->query()->numResults() || oldEntry->query()->results().first().data() != result.data() ) )
{
oldEntry->setIsPlaying( false );
@ -763,7 +794,8 @@ PlayableModel::onPlaybackStarted( const Tomahawk::result_ptr& result )
void
PlayableModel::onPlaybackStopped()
{
PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
Q_D( PlayableModel );
PlayableItem* oldEntry = itemFromIndex( d->currentIndex );
if ( oldEntry )
{
oldEntry->setIsPlaying( false );
@ -855,7 +887,8 @@ PlayableModel::onDataChanged()
void
PlayableModel::startLoading()
{
m_loading = true;
Q_D( PlayableModel );
d->loading = true;
emit loadingStarted();
}
@ -863,7 +896,8 @@ PlayableModel::startLoading()
void
PlayableModel::finishLoading()
{
m_loading = false;
Q_D( PlayableModel );
d->loading = false;
emit loadingFinished();
}
@ -871,13 +905,14 @@ PlayableModel::finishLoading()
PlayableItem*
PlayableModel::itemFromIndex( const QModelIndex& index ) const
{
Q_D( const PlayableModel );
if ( index.isValid() )
{
return static_cast<PlayableItem*>( index.internalPointer() );
}
else
{
return m_rootItem;
return d->rootItem;
}
}
@ -1002,7 +1037,8 @@ PlayableModel::insertQueries( const QList< Tomahawk::query_ptr >& queries, int r
void
PlayableModel::setTitle( const QString& title )
{
m_title = title;
Q_D( PlayableModel );
d->title = title;
emit changed();
}
@ -1010,14 +1046,16 @@ PlayableModel::setTitle( const QString& title )
QString
PlayableModel::description() const
{
return m_description;
Q_D( const PlayableModel );
return d->description;
}
void
PlayableModel::setDescription( const QString& description )
{
m_description = description;
Q_D( PlayableModel );
d->description = description;
emit changed();
}
@ -1025,14 +1063,16 @@ PlayableModel::setDescription( const QString& description )
QPixmap
PlayableModel::icon() const
{
return m_icon;
Q_D( const PlayableModel );
return d->icon;
}
void
PlayableModel::setIcon( const QPixmap& pixmap )
{
m_icon = pixmap;
Q_D( PlayableModel );
d->icon = pixmap;
emit changed();
}

View File

@ -3,6 +3,7 @@
* Copyright 2010-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2011 Leo Franchi <lfranchi@kde.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,17 +23,16 @@
#ifndef PLAYABLEMODEL_H
#define PLAYABLEMODEL_H
#include <QAbstractItemModel>
#include <QPixmap>
#include "PlaylistInterface.h"
#include "DllMacro.h"
#include "PlaybackLog.h"
#include "Typedefs.h"
#include "DllMacro.h"
#include <QAbstractItemModel>
class QMetaData;
class PlayableItem;
class PlayableModelPrivate;
class DLLEXPORT PlayableModel : public QAbstractItemModel
{
@ -175,6 +175,9 @@ public slots:
virtual void setShuffled( bool /*shuffled*/ ) {}
protected:
QScopedPointer<PlayableModelPrivate> d_ptr;
PlayableModel( QObject* parent, PlayableModelPrivate* d );
PlayableItem* rootItem() const;
QModelIndex createIndex( int row, int column, PlayableItem* item = 0 ) const;
@ -188,25 +191,14 @@ private slots:
void onPlaybackStopped();
private:
void init();
template <typename T>
void insertInternal( const QList< T >& items, int row, const QList< Tomahawk::PlaybackLog >& logs = QList< Tomahawk::PlaybackLog >() );
QString scoreText( float score ) const;
Qt::Alignment columnAlignment( int column ) const;
PlayableItem* m_rootItem;
QPersistentModelIndex m_currentIndex;
Tomahawk::QID m_currentUuid;
bool m_readOnly;
QString m_title;
QString m_description;
QPixmap m_icon;
QStringList m_header;
bool m_loading;
Q_DECLARE_PRIVATE( PlayableModel )
};
#endif // PLAYABLEMODEL_H

View File

@ -0,0 +1,63 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2011 Leo Franchi <lfranchi@kde.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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/>.
*/
#pragma once
#ifndef PLAYABLEMODEL_P_H
#define PLAYABLEMODEL_P_H
#include "PlayableModel.h"
#include "PlayableItem.h"
#include <QPixmap>
#include <QStringList>
class PlayableModelPrivate
{
public:
PlayableModelPrivate( PlayableModel* q, bool _loading )
: q_ptr( q )
, rootItem( new PlayableItem( 0 ) )
, readOnly( true )
, loading( _loading )
{
}
PlayableModel* q_ptr;
Q_DECLARE_PUBLIC( PlayableModel )
private:
PlayableItem* rootItem;
QPersistentModelIndex currentIndex;
Tomahawk::QID currentUuid;
bool readOnly;
QString title;
QString description;
QPixmap icon;
QStringList header;
bool loading;
};
#endif // PLAYABLEMODEL_P_H

View File

@ -18,7 +18,7 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PlaylistModel.h"
#include "PlaylistModel_p.h"
#include <QMimeData>
#include <QTreeView>
@ -41,21 +41,31 @@
using namespace Tomahawk;
PlaylistModel::PlaylistModel( QObject* parent )
: PlayableModel( parent )
, m_isTemporary( false )
, m_changesOngoing( false )
, m_isLoading( false )
, m_acceptPlayableQueriesOnly( false )
, m_savedInsertPos( -1 )
void
PlaylistModel::init()
{
m_dropStorage.parent = QPersistentModelIndex();
m_dropStorage.row = -10;
Q_D( PlaylistModel );
d->dropStorage.parent = QPersistentModelIndex();
d->dropStorage.row = -10;
setReadOnly( true );
}
PlaylistModel::PlaylistModel( QObject* parent )
: PlayableModel( parent, new PlaylistModelPrivate( this ) )
{
init();
}
PlaylistModel::PlaylistModel( QObject* parent, PlaylistModelPrivate* d )
: PlayableModel( parent, d )
{
init();
}
PlaylistModel::~PlaylistModel()
{
}
@ -64,9 +74,10 @@ PlaylistModel::~PlaylistModel()
QString
PlaylistModel::guid() const
{
if ( !m_playlist.isNull() )
Q_D( const PlaylistModel );
if ( !d->playlist.isNull() )
{
return QString( "playlistmodel/%1" ).arg( m_playlist->guid() );
return QString( "playlistmodel/%1" ).arg( d->playlist->guid() );
}
else
return QString();
@ -76,31 +87,32 @@ PlaylistModel::guid() const
void
PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEntries )
{
if ( !m_playlist.isNull() )
Q_D( PlaylistModel );
if ( !d->playlist.isNull() )
{
disconnect( m_playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( onRevisionLoaded( Tomahawk::PlaylistRevision ) ) );
disconnect( m_playlist.data(), SIGNAL( deleted( Tomahawk::playlist_ptr ) ), this, SIGNAL( playlistDeleted() ) );
disconnect( m_playlist.data(), SIGNAL( changed() ), this, SLOT( onPlaylistChanged() ) );
disconnect( d->playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( onRevisionLoaded( Tomahawk::PlaylistRevision ) ) );
disconnect( d->playlist.data(), SIGNAL( deleted( Tomahawk::playlist_ptr ) ), this, SIGNAL( playlistDeleted() ) );
disconnect( d->playlist.data(), SIGNAL( changed() ), this, SLOT( onPlaylistChanged() ) );
}
m_isLoading = true;
d->isLoading = true;
if ( loadEntries )
clear();
m_playlist = playlist;
d->playlist = playlist;
connect( playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), SLOT( onRevisionLoaded( Tomahawk::PlaylistRevision ) ) );
connect( playlist.data(), SIGNAL( deleted( Tomahawk::playlist_ptr ) ), SIGNAL( playlistDeleted() ) );
connect( playlist.data(), SIGNAL( changed() ), SLOT( onPlaylistChanged() ) );
setReadOnly( !m_playlist->author()->isLocal() );
m_isTemporary = false;
setReadOnly( !d->playlist->author()->isLocal() );
d->isTemporary = false;
onPlaylistChanged();
if ( !loadEntries )
{
m_isLoading = false;
d->isLoading = false;
return;
}
@ -110,18 +122,19 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn
appendEntries( entries );
m_isLoading = false;
d->isLoading = false;
}
void
PlaylistModel::onPlaylistChanged()
{
QString age = TomahawkUtils::ageToString( QDateTime::fromTime_t( m_playlist->createdOn() ), true );
Q_D( PlaylistModel );
QString age = TomahawkUtils::ageToString( QDateTime::fromTime_t( d->playlist->createdOn() ), true );
QString desc;
if ( m_playlist->creator().isEmpty() )
if ( d->playlist->creator().isEmpty() )
{
if ( m_playlist->author()->isLocal() )
if ( d->playlist->author()->isLocal() )
{
desc = tr( "A playlist you created %1." )
.arg( age );
@ -129,18 +142,18 @@ PlaylistModel::onPlaylistChanged()
else
{
desc = tr( "A playlist by %1, created %2." )
.arg( m_playlist->author()->friendlyName() )
.arg( d->playlist->author()->friendlyName() )
.arg( age );
}
}
else
{
desc = tr( "A playlist by %1, created %2." )
.arg( m_playlist->creator() )
.arg( d->playlist->creator() )
.arg( age );
}
setTitle( m_playlist->title() );
setTitle( d->playlist->title() );
setDescription( desc );
emit playlistChanged();
@ -150,7 +163,8 @@ PlaylistModel::onPlaylistChanged()
void
PlaylistModel::clear()
{
m_waitingForResolved.clear();
Q_D( PlaylistModel );
d->waitingForResolved.clear();
PlayableModel::clear();
}
@ -165,6 +179,7 @@ PlaylistModel::appendEntries( const QList< plentry_ptr >& entries )
void
PlaylistModel::insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row )
{
Q_D( PlaylistModel );
// FIXME: This currently appends, not inserts!
Q_UNUSED( row );
@ -183,7 +198,7 @@ PlaylistModel::insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row
{
setTitle( albums.first()->name() );
setDescription( tr( "All tracks by %1 on album %2" ).arg( albums.first()->artist()->name() ).arg( albums.first()->name() ) );
m_isTemporary = true;
d->isTemporary = true;
}
}
@ -191,6 +206,7 @@ PlaylistModel::insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row
void
PlaylistModel::insertArtists( const QList< Tomahawk::artist_ptr >& artists, int row )
{
Q_D( PlaylistModel );
// FIXME: This currently appends, not inserts!
Q_UNUSED( row );
@ -209,7 +225,7 @@ PlaylistModel::insertArtists( const QList< Tomahawk::artist_ptr >& artists, int
{
setTitle( artists.first()->name() );
setDescription( tr( "All tracks by %1" ).arg( artists.first()->name() ) );
m_isTemporary = true;
d->isTemporary = true;
}
}
@ -217,10 +233,11 @@ PlaylistModel::insertArtists( const QList< Tomahawk::artist_ptr >& artists, int
void
PlaylistModel::insertQueries( const QList< Tomahawk::query_ptr >& queries, int row, const QList< Tomahawk::PlaybackLog >& logs )
{
Q_D( PlaylistModel );
QList< Tomahawk::plentry_ptr > entries;
foreach ( const query_ptr& query, queries )
{
if ( m_acceptPlayableQueriesOnly && query && query->resolvingFinished() && !query->playable() )
if ( d->acceptPlayableQueriesOnly && query && query->resolvingFinished() && !query->playable() )
continue;
plentry_ptr entry = plentry_ptr( new PlaylistEntry() );
@ -245,6 +262,7 @@ PlaylistModel::insertQueries( const QList< Tomahawk::query_ptr >& queries, int r
void
PlaylistModel::insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int row, const QList< Tomahawk::PlaybackLog >& logs )
{
Q_D( PlaylistModel );
if ( !entries.count() )
{
emit itemCountChanged( rowCount( QModelIndex() ) );
@ -257,10 +275,10 @@ PlaylistModel::insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int
crows.first = c;
crows.second = c + entries.count() - 1;
if ( !m_isLoading )
if ( !d->isLoading )
{
m_savedInsertPos = row;
m_savedInsertTracks = entries;
d->savedInsertPos = row;
d->savedInsertTracks = entries;
}
emit beginInsertRows( QModelIndex(), crows.first, crows.second );
@ -284,14 +302,14 @@ PlaylistModel::insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int
if ( !entry->query()->resolvingFinished() && !entry->query()->playable() )
{
queries << entry->query();
m_waitingForResolved.append( entry->query().data() );
d->waitingForResolved.append( entry->query().data() );
connect( entry->query().data(), SIGNAL( resolvingFinished( bool ) ), SLOT( trackResolved( bool ) ) );
}
connect( plitem, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) );
}
if ( !m_waitingForResolved.isEmpty() )
if ( !d->waitingForResolved.isEmpty() )
{
Pipeline::instance()->resolve( queries );
emit loadingStarted();
@ -307,6 +325,7 @@ PlaylistModel::insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int
void
PlaylistModel::trackResolved( bool )
{
Q_D( PlaylistModel );
Tomahawk::Query* q = qobject_cast< Query* >( sender() );
if ( !q )
{
@ -314,13 +333,13 @@ PlaylistModel::trackResolved( bool )
return;
}
if ( m_waitingForResolved.contains( q ) )
if ( d->waitingForResolved.contains( q ) )
{
m_waitingForResolved.removeAll( q );
d->waitingForResolved.removeAll( q );
disconnect( q, SIGNAL( resolvingFinished( bool ) ), this, SLOT( trackResolved( bool ) ) );
}
if ( m_waitingForResolved.isEmpty() )
if ( d->waitingForResolved.isEmpty() )
{
emit loadingFinished();
}
@ -330,28 +349,31 @@ PlaylistModel::trackResolved( bool )
void
PlaylistModel::onRevisionLoaded( Tomahawk::PlaylistRevision revision )
{
if ( !m_waitForRevision.contains( revision.revisionguid ) )
loadPlaylist( m_playlist );
Q_D( PlaylistModel );
if ( !d->waitForRevision.contains( revision.revisionguid ) )
loadPlaylist( d->playlist );
else
m_waitForRevision.removeAll( revision.revisionguid );
d->waitForRevision.removeAll( revision.revisionguid );
}
QMimeData*
PlaylistModel::mimeData( const QModelIndexList& indexes ) const
{
Q_D( const PlaylistModel );
// Add the playlist id to the mime data so that we can detect dropping on ourselves
QMimeData* d = PlayableModel::mimeData( indexes );
if ( !m_playlist.isNull() )
d->setData( "application/tomahawk.playlist.id", m_playlist->guid().toLatin1() );
QMimeData* data = PlayableModel::mimeData( indexes );
if ( !d->playlist.isNull() )
data->setData( "application/tomahawk.playlist.id", d->playlist->guid().toLatin1() );
return d;
return data;
}
bool
PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
{
Q_D( PlaylistModel );
Q_UNUSED( column );
if ( action == Qt::IgnoreAction || isReadOnly() )
@ -360,9 +382,9 @@ PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int r
if ( !DropJob::acceptsMimeData( data ) )
return false;
m_dropStorage.row = row;
m_dropStorage.parent = QPersistentModelIndex( parent );
m_dropStorage.action = action;
d->dropStorage.row = row;
d->dropStorage.parent = QPersistentModelIndex( parent );
d->dropStorage.action = action;
DropJob* dj = new DropJob();
@ -378,7 +400,7 @@ PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int r
// On mac, drags from outside the app are still Qt::MoveActions instead of Qt::CopyAction by default
// so check if the drag originated in this playlist to determine whether or not to copy
if ( !data->hasFormat( "application/tomahawk.playlist.id" ) ||
( !m_playlist.isNull() && data->data( "application/tomahawk.playlist.id" ) != m_playlist->guid() ) )
( !d->playlist.isNull() && data->data( "application/tomahawk.playlist.id" ) != d->playlist->guid() ) )
{
dj->setDropAction( DropJob::Append );
}
@ -394,66 +416,70 @@ PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int r
playlist_ptr
PlaylistModel::playlist() const
{
return m_playlist;
Q_D( const PlaylistModel );
return d->playlist;
}
void
PlaylistModel::parsedDroppedTracks( QList< query_ptr > tracks )
{
if ( m_dropStorage.row == -10 ) // nope
Q_D( PlaylistModel );
if ( d->dropStorage.row == -10 ) // nope
return;
int beginRow;
if ( m_dropStorage.row != -1 )
beginRow = m_dropStorage.row;
else if ( m_dropStorage.parent.isValid() )
beginRow = m_dropStorage.parent.row();
if ( d->dropStorage.row != -1 )
beginRow = d->dropStorage.row;
else if ( d->dropStorage.parent.isValid() )
beginRow = d->dropStorage.parent.row();
else
beginRow = rowCount( QModelIndex() );
if ( tracks.count() )
{
bool update = ( m_dropStorage.action & Qt::CopyAction || m_dropStorage.action & Qt::MoveAction );
bool update = ( d->dropStorage.action & Qt::CopyAction || d->dropStorage.action & Qt::MoveAction );
if ( update )
beginPlaylistChanges();
insertQueries( tracks, beginRow );
if ( update && m_dropStorage.action & Qt::CopyAction )
if ( update && d->dropStorage.action & Qt::CopyAction )
endPlaylistChanges();
}
m_dropStorage.parent = QPersistentModelIndex();
m_dropStorage.row = -10;
d->dropStorage.parent = QPersistentModelIndex();
d->dropStorage.row = -10;
}
void
PlaylistModel::beginPlaylistChanges()
{
if ( m_playlist.isNull() || !m_playlist->author()->isLocal() )
Q_D( PlaylistModel );
if ( d->playlist.isNull() || !d->playlist->author()->isLocal() )
return;
Q_ASSERT( !m_changesOngoing );
m_changesOngoing = true;
Q_ASSERT( !d->changesOngoing );
d->changesOngoing = true;
}
void
PlaylistModel::endPlaylistChanges()
{
if ( m_playlist.isNull() || !m_playlist->author()->isLocal() )
Q_D( PlaylistModel );
if ( d->playlist.isNull() || !d->playlist->author()->isLocal() )
{
m_savedInsertPos = -1;
m_savedInsertTracks.clear();
m_savedRemoveTracks.clear();
d->savedInsertPos = -1;
d->savedInsertTracks.clear();
d->savedRemoveTracks.clear();
return;
}
if ( m_changesOngoing )
if ( d->changesOngoing )
{
m_changesOngoing = false;
d->changesOngoing = false;
}
else
{
@ -463,9 +489,9 @@ PlaylistModel::endPlaylistChanges()
QList<plentry_ptr> l = playlistEntries();
QString newrev = uuid();
m_waitForRevision << newrev;
d->waitForRevision << newrev;
if ( dynplaylist_ptr dynplaylist = m_playlist.dynamicCast<Tomahawk::DynamicPlaylist>() )
if ( dynplaylist_ptr dynplaylist = d->playlist.dynamicCast<Tomahawk::DynamicPlaylist>() )
{
if ( dynplaylist->mode() == OnDemand )
{
@ -478,11 +504,11 @@ PlaylistModel::endPlaylistChanges()
}
else
{
m_playlist->createNewRevision( newrev, m_playlist->currentrevision(), l );
d->playlist->createNewRevision( newrev, d->playlist->currentrevision(), l );
}
if ( m_savedInsertPos >= 0 && !m_savedInsertTracks.isEmpty() &&
!m_savedRemoveTracks.isEmpty() )
if ( d->savedInsertPos >= 0 && !d->savedInsertTracks.isEmpty() &&
!d->savedRemoveTracks.isEmpty() )
{
// If we have *both* an insert and remove, then it's a move action
// However, since we got the insert before the remove (Qt...), the index we have as the saved
@ -498,27 +524,27 @@ PlaylistModel::endPlaylistChanges()
continue;
// qDebug() << "Checking for equality:" << (item->entry() == m_savedInsertTracks.first()) << m_savedInsertTracks.first()->query()->track() << m_savedInsertTracks.first()->query()->artist();
if ( item->entry() == m_savedInsertTracks.first() )
if ( item->entry() == d->savedInsertTracks.first() )
{
// Found our index
emit m_playlist->tracksMoved( m_savedInsertTracks, i );
emit d->playlist->tracksMoved( d->savedInsertTracks, i );
break;
}
}
m_savedInsertPos = -1;
m_savedInsertTracks.clear();
m_savedRemoveTracks.clear();
d->savedInsertPos = -1;
d->savedInsertTracks.clear();
d->savedRemoveTracks.clear();
}
else if ( m_savedInsertPos >= 0 )
else if ( d->savedInsertPos >= 0 )
{
emit m_playlist->tracksInserted( m_savedInsertTracks, m_savedInsertPos );
m_savedInsertPos = -1;
m_savedInsertTracks.clear();
emit d->playlist->tracksInserted( d->savedInsertTracks, d->savedInsertPos );
d->savedInsertPos = -1;
d->savedInsertTracks.clear();
}
else if ( !m_savedRemoveTracks.isEmpty() )
else if ( !d->savedRemoveTracks.isEmpty() )
{
emit m_playlist->tracksRemoved( m_savedRemoveTracks );
m_savedRemoveTracks.clear();
emit d->playlist->tracksRemoved( d->savedRemoveTracks );
d->savedRemoveTracks.clear();
}
}
@ -545,21 +571,22 @@ PlaylistModel::playlistEntries() const
void
PlaylistModel::removeIndex( const QModelIndex& index, bool moreToCome )
{
Q_D( PlaylistModel );
PlayableItem* item = itemFromIndex( index );
if ( item && m_waitingForResolved.contains( item->query().data() ) )
if ( item && d->waitingForResolved.contains( item->query().data() ) )
{
disconnect( item->query().data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( trackResolved( bool ) ) );
m_waitingForResolved.removeAll( item->query().data() );
if ( m_waitingForResolved.isEmpty() )
d->waitingForResolved.removeAll( item->query().data() );
if ( d->waitingForResolved.isEmpty() )
emit loadingFinished();
}
if ( !m_changesOngoing )
if ( !d->changesOngoing )
beginPlaylistChanges();
if ( item && !m_isLoading )
m_savedRemoveTracks << item->query();
if ( item && !d->isLoading )
d->savedRemoveTracks << item->query();
PlayableModel::removeIndex( index, moreToCome );
@ -571,33 +598,38 @@ PlaylistModel::removeIndex( const QModelIndex& index, bool moreToCome )
bool
PlaylistModel::waitForRevision( const QString& revisionguid ) const
{
return m_waitForRevision.contains( revisionguid );
Q_D( const PlaylistModel );
return d->waitForRevision.contains( revisionguid );
}
void
PlaylistModel::removeFromWaitList( const QString& revisionguid )
{
m_waitForRevision.removeAll( revisionguid );
Q_D( PlaylistModel );
d->waitForRevision.removeAll( revisionguid );
}
bool
PlaylistModel::isTemporary() const
{
return m_isTemporary;
Q_D( const PlaylistModel );
return d->isTemporary;
}
bool
PlaylistModel::acceptPlayableQueriesOnly() const
{
return m_acceptPlayableQueriesOnly;
Q_D( const PlaylistModel );
return d->acceptPlayableQueriesOnly;
}
void
PlaylistModel::setAcceptPlayableQueriesOnly( bool b )
{
m_acceptPlayableQueriesOnly = b;
Q_D( PlaylistModel );
d->acceptPlayableQueriesOnly = b;
}

View File

@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,23 +17,26 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef PLAYLISTMODEL_H
#define PLAYLISTMODEL_H
#include <QList>
#include <QHash>
#include "Typedefs.h"
#include "PlayableModel.h"
#include "Playlist.h"
#include "Query.h"
#include "PlaylistInterface.h"
#include "DllMacro.h"
#include "PlayableModel.h"
#include "Typedefs.h"
class QMimeData;
class QMetaData;
class PlaylistModelPrivate;
class DLLEXPORT PlaylistModel : public PlayableModel
{
Q_OBJECT
@ -79,6 +83,7 @@ signals:
void playlistChanged();
protected:
PlaylistModel( QObject* parent, PlaylistModelPrivate* d );
bool waitForRevision( const QString& revisionguid ) const;
void removeFromWaitList( const QString& revisionguid );
@ -93,20 +98,9 @@ private slots:
private:
void beginPlaylistChanges();
void endPlaylistChanges();
void init();
Tomahawk::playlist_ptr m_playlist;
bool m_isTemporary;
bool m_changesOngoing;
bool m_isLoading;
bool m_acceptPlayableQueriesOnly;
QList< Tomahawk::Query* > m_waitingForResolved;
QStringList m_waitForRevision;
int m_savedInsertPos;
QList< Tomahawk::plentry_ptr > m_savedInsertTracks;
QList< Tomahawk::query_ptr > m_savedRemoveTracks;
DropStorageData m_dropStorage;
Q_DECLARE_PRIVATE( PlaylistModel )
};
#endif // PLAYLISTMODEL_H

View File

@ -0,0 +1,58 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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/>.
*/
#pragma once
#ifndef PLAYLISTMODEL_P_H
#define PLAYLISTMODEL_P_H
#include "PlaylistModel.h"
#include "PlayableModel_p.h"
class PlaylistModelPrivate : public PlayableModelPrivate
{
public:
PlaylistModelPrivate( PlaylistModel* q )
: PlayableModelPrivate( q, false )
, isTemporary( false )
, changesOngoing( false )
, isLoading( false )
, acceptPlayableQueriesOnly( false )
, savedInsertPos( -1 )
{
}
Q_DECLARE_PUBLIC( PlaylistModel )
private:
Tomahawk::playlist_ptr playlist;
bool isTemporary;
bool changesOngoing;
bool isLoading;
bool acceptPlayableQueriesOnly;
QList< Tomahawk::Query* > waitingForResolved;
QStringList waitForRevision;
int savedInsertPos;
QList< Tomahawk::plentry_ptr > savedInsertTracks;
QList< Tomahawk::query_ptr > savedRemoveTracks;
PlaylistModel::DropStorageData dropStorage;
};
#endif // PLAYLISTMODEL_P_H

View File

@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,37 +17,18 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TopLovedTracksModel.h"
#include <QMimeData>
#include <QTreeView>
#include "TopLovedTracksModel_p.h"
#include "database/Database.h"
#include "database/DatabaseCommand_GenericSelect.h"
#include "utils/TomahawkUtils.h"
#include "utils/Logger.h"
#include "PlayableItem.h"
#include "PlaylistEntry.h"
#include "Source.h"
#include "SourceList.h"
#include <QTimer>
#define LOVED_TRACK_ITEMS 25
using namespace Tomahawk;
TopLovedTracksModel::TopLovedTracksModel( QObject* parent )
: PlaylistModel( parent )
, m_smoothingTimer( new QTimer )
, m_limit( LOVED_TRACK_ITEMS )
: LovedTracksModel( parent )
{
m_smoothingTimer->setInterval( 300 );
m_smoothingTimer->setSingleShot( true );
connect( m_smoothingTimer, SIGNAL( timeout() ), this, SLOT( loadTracks() ) );
}
@ -55,33 +37,21 @@ TopLovedTracksModel::~TopLovedTracksModel()
}
unsigned int
TopLovedTracksModel::limit() const
{
return m_limit;
}
void
TopLovedTracksModel::setLimit( unsigned int limit )
{
m_limit = limit;
}
void
TopLovedTracksModel::loadTracks()
{
Q_D( TopLovedTracksModel );
startLoading();
QString sql;
if ( m_source.isNull() )
if ( d->source.isNull() )
{
sql = QString( "SELECT track.name, artist.name, source, COUNT(*) as counter "
"FROM social_attributes, track, artist "
"WHERE social_attributes.id = track.id AND artist.id = track.artist AND social_attributes.k = 'Love' AND social_attributes.v = 'true' "
"GROUP BY track.id "
"ORDER BY counter DESC, social_attributes.timestamp DESC LIMIT 0, 50" );
"ORDER BY counter DESC, social_attributes.timestamp DESC LIMIT %1" )
.arg( d->limit );
}
else
{
@ -89,87 +59,12 @@ TopLovedTracksModel::loadTracks()
"FROM social_attributes, track, artist "
"WHERE social_attributes.id = track.id AND artist.id = track.artist AND social_attributes.k = 'Love' AND social_attributes.v = 'true' AND social_attributes.source %1 "
"GROUP BY track.id "
"ORDER BY counter DESC, social_attributes.timestamp DESC " ).arg( m_source->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_source->id() ) );
"ORDER BY counter DESC, social_attributes.timestamp DESC "
)
.arg( d->source->isLocal() ? "IS NULL" : QString( "= %1" ).arg( d->source->id() ) );
}
DatabaseCommand_GenericSelect* cmd = new DatabaseCommand_GenericSelect( sql, DatabaseCommand_GenericSelect::Track, -1, 0 );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( tracksLoaded( QList<Tomahawk::query_ptr> ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
void
TopLovedTracksModel::onSourcesReady()
{
Q_ASSERT( m_source.isNull() );
loadTracks();
foreach ( const source_ptr& source, SourceList::instance()->sources() )
onSourceAdded( source );
}
void
TopLovedTracksModel::setSource( const Tomahawk::source_ptr& source )
{
m_source = source;
if ( source.isNull() )
{
if ( SourceList::instance()->isReady() )
onSourcesReady();
else
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
}
else
{
onSourceAdded( source );
loadTracks();
}
}
void
TopLovedTracksModel::onSourceAdded( const Tomahawk::source_ptr& source )
{
connect( source.data(), SIGNAL( socialAttributesChanged( QString ) ), SLOT( onTrackLoved() ), Qt::UniqueConnection );
}
void
TopLovedTracksModel::onTrackLoved()
{
m_smoothingTimer->start();
}
bool
TopLovedTracksModel::isTemporary() const
{
return true;
}
void
TopLovedTracksModel::tracksLoaded( QList< query_ptr > newLoved )
{
finishLoading();
QList< query_ptr > tracks;
foreach ( const plentry_ptr ple, playlistEntries() )
tracks << ple->query();
bool changed = false;
QList< query_ptr > mergedTracks = TomahawkUtils::mergePlaylistChanges( tracks, newLoved, changed );
if ( changed )
{
QList<Tomahawk::plentry_ptr> el = playlist()->entriesFromQueries( mergedTracks, true );
clear();
appendEntries( el );
}
}

View File

@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,18 +17,15 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOVEDTRACKSMODEL_H
#define LOVEDTRACKSMODEL_H
#pragma once
#ifndef TOPLOVEDTRACKSMODEL_H
#define TOPLOVEDTRACKSMODEL_H
#include <QList>
#include <QHash>
#include "LovedTracksModel.h"
#include "Typedefs.h"
#include "PlaylistModel.h"
class TopLovedTracksModelPrivate;
#include "DllMacro.h"
class DLLEXPORT TopLovedTracksModel : public PlaylistModel
class DLLEXPORT TopLovedTracksModel : public LovedTracksModel
{
Q_OBJECT
@ -35,26 +33,11 @@ public:
explicit TopLovedTracksModel( QObject* parent = 0 );
virtual ~TopLovedTracksModel();
unsigned int limit() const;
void setLimit( unsigned int limit );
bool isTemporary() const;
public slots:
void setSource( const Tomahawk::source_ptr& source );
private slots:
void onSourcesReady();
void onSourceAdded( const Tomahawk::source_ptr& source );
void onTrackLoved();
void loadTracks();
void tracksLoaded( QList<Tomahawk::query_ptr> );
private:
Tomahawk::source_ptr m_source;
QTimer* m_smoothingTimer;
unsigned int m_limit;
Q_DECLARE_PRIVATE( TopLovedTracksModel )
};
#endif // LOVEDTRACKSMODEL_H
#endif // TOPLOVEDTRACKSMODEL_H

View File

@ -0,0 +1,38 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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/>.
*/
#pragma once
#ifndef TOPLOVEDTRACKSMODEL_P_H
#define TOPLOVEDTRACKSMODEL_P_H
#include "LovedTracksModel_p.h"
#include "TopLovedTracksModel.h"
class TopLovedTracksModelPrivate : public LovedTracksModelPrivate
{
public:
TopLovedTracksModelPrivate( TopLovedTracksModel* q )
: LovedTracksModelPrivate( q )
{
}
Q_DECLARE_PUBLIC( TopLovedTracksModel )
};
#endif // TOPLOVEDTRACKSMODEL_P_H