mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-06-02 14:05:06 +02:00
* Added queue feature.
* Fixed a few playlist related bugs.
This commit is contained in:
parent
a42c317209
commit
597c52f96d
@ -116,6 +116,8 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
||||
playlist/playlistproxymodel.cpp
|
||||
playlist/playlistview.cpp
|
||||
playlist/playlistitemdelegate.cpp
|
||||
playlist/queueproxymodel.cpp
|
||||
playlist/queueview.cpp
|
||||
playlist/trackmodel.cpp
|
||||
playlist/trackproxymodel.cpp
|
||||
playlist/trackview.cpp
|
||||
@ -242,6 +244,8 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
playlist/playlistproxymodel.h
|
||||
playlist/playlistview.h
|
||||
playlist/playlistitemdelegate.h
|
||||
playlist/queueproxymodel.h
|
||||
playlist/queueview.h
|
||||
playlist/trackmodel.h
|
||||
playlist/trackproxymodel.h
|
||||
playlist/trackview.h
|
||||
|
@ -18,6 +18,8 @@
|
||||
AudioEngine::AudioEngine()
|
||||
: QThread()
|
||||
, m_playlist( 0 )
|
||||
, m_currentTrackPlaylist( 0 )
|
||||
, m_queue( 0 )
|
||||
, m_i( 0 )
|
||||
{
|
||||
qDebug() << "Init AudioEngine";
|
||||
@ -151,6 +153,9 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
else
|
||||
{
|
||||
m_lastTrack = m_currentTrack;
|
||||
if ( !m_lastTrack.isNull() )
|
||||
emit finished( m_lastTrack );
|
||||
|
||||
m_currentTrack = result;
|
||||
io = TomahawkApp::instance()->getIODeviceForUrl( m_currentTrack );
|
||||
|
||||
@ -256,13 +261,24 @@ AudioEngine::loadNextTrack()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( !m_playlist )
|
||||
Tomahawk::result_ptr result;
|
||||
|
||||
if ( m_queue && m_queue->trackCount() )
|
||||
{
|
||||
result = m_queue->nextItem();
|
||||
}
|
||||
|
||||
if ( m_playlist && result.isNull() )
|
||||
{
|
||||
result = m_playlist->nextItem();
|
||||
}
|
||||
|
||||
if ( result.isNull() )
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::result_ptr result = m_playlist->nextItem();
|
||||
if ( !result.isNull() )
|
||||
loadTrack( result );
|
||||
else
|
||||
@ -276,7 +292,7 @@ AudioEngine::playItem( PlaylistInterface* playlist, const Tomahawk::result_ptr&
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_playlist = playlist;
|
||||
m_currentPlaylist = playlist;
|
||||
m_currentTrackPlaylist = playlist;
|
||||
loadTrack( result );
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
bool isPaused() const { return m_audio->isPaused(); }
|
||||
|
||||
/* Returns the PlaylistInterface of the currently playing track. Note: This might be different to the current playlist! */
|
||||
PlaylistInterface* currentPlaylist() const { return m_currentPlaylist; }
|
||||
PlaylistInterface* currentTrackPlaylist() const { return m_currentTrackPlaylist; }
|
||||
|
||||
/* Returns the PlaylistInterface of the current playlist. Note: The currently playing track might still be from a different playlist! */
|
||||
PlaylistInterface* playlist() const { return m_playlist; }
|
||||
@ -50,12 +50,14 @@ public slots:
|
||||
|
||||
void playItem( PlaylistInterface* playlist, const Tomahawk::result_ptr& result );
|
||||
void setPlaylist( PlaylistInterface* playlist ) { m_playlist = playlist; }
|
||||
void setQueue( PlaylistInterface* queue ) { m_queue = queue; }
|
||||
|
||||
void onTrackAboutToClose();
|
||||
|
||||
signals:
|
||||
void loading( const Tomahawk::result_ptr& track );
|
||||
void started( const Tomahawk::result_ptr& track );
|
||||
void finished( const Tomahawk::result_ptr& track );
|
||||
void stopped();
|
||||
void paused();
|
||||
void resumed();
|
||||
@ -93,7 +95,8 @@ private:
|
||||
Tomahawk::result_ptr m_currentTrack;
|
||||
Tomahawk::result_ptr m_lastTrack;
|
||||
PlaylistInterface* m_playlist;
|
||||
PlaylistInterface* m_currentPlaylist;
|
||||
PlaylistInterface* m_currentTrackPlaylist;
|
||||
PlaylistInterface* m_queue;
|
||||
QMutex m_mutex;
|
||||
|
||||
int m_i;
|
||||
|
@ -36,6 +36,8 @@ public:
|
||||
|
||||
void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllTracks::SortOrder order );
|
||||
|
||||
virtual void appendTrack( const Tomahawk::query_ptr& query ) {}
|
||||
|
||||
signals:
|
||||
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
|
||||
void shuffleModeChanged( bool enabled );
|
||||
|
@ -18,6 +18,9 @@ CollectionView::CollectionView( QWidget* parent )
|
||||
|
||||
setDragDropMode( QAbstractItemView::DragOnly );
|
||||
setAcceptDrops( false );
|
||||
|
||||
setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
|
||||
}
|
||||
|
||||
|
||||
@ -34,3 +37,35 @@ CollectionView::dragEnterEvent( QDragEnterEvent* event )
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionView::setupMenus()
|
||||
{
|
||||
m_itemMenu.clear();
|
||||
|
||||
m_playItemAction = m_itemMenu.addAction( tr( "&Play" ) );
|
||||
m_addItemsToQueueAction = m_itemMenu.addAction( tr( "Add to &Queue" ) );
|
||||
m_itemMenu.addSeparator();
|
||||
m_addItemsToPlaylistAction = m_itemMenu.addAction( tr( "&Add to Playlist" ) );
|
||||
|
||||
connect( m_playItemAction, SIGNAL( triggered() ), SLOT( playItem() ) );
|
||||
connect( m_addItemsToQueueAction, SIGNAL( triggered() ), SLOT( addItemsToQueue() ) );
|
||||
connect( m_addItemsToPlaylistAction, SIGNAL( triggered() ), SLOT( addItemsToPlaylist() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionView::onCustomContextMenu( const QPoint& pos )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
setupMenus();
|
||||
|
||||
QModelIndex idx = indexAt( pos );
|
||||
idx = idx.sibling( idx.row(), 0 );
|
||||
setContextMenuIndex( idx );
|
||||
|
||||
if ( !idx.isValid() )
|
||||
return;
|
||||
|
||||
m_itemMenu.exec( mapToGlobal( pos ) );
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef COLLECTIONVIEW_H
|
||||
#define COLLECTIONVIEW_H
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "trackview.h"
|
||||
|
||||
@ -12,8 +14,20 @@ public:
|
||||
explicit CollectionView( QWidget* parent = 0 );
|
||||
~CollectionView();
|
||||
|
||||
private slots:
|
||||
void onCustomContextMenu( const QPoint& pos );
|
||||
|
||||
protected:
|
||||
virtual void dragEnterEvent( QDragEnterEvent* event );
|
||||
|
||||
private:
|
||||
void setupMenus();
|
||||
|
||||
QMenu m_itemMenu;
|
||||
|
||||
QAction* m_playItemAction;
|
||||
QAction* m_addItemsToQueueAction;
|
||||
QAction* m_addItemsToPlaylistAction;
|
||||
};
|
||||
|
||||
#endif // COLLECTIONVIEW_H
|
||||
|
@ -6,10 +6,13 @@
|
||||
|
||||
#include "tomahawk/query.h"
|
||||
#include "tomahawk/result.h"
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
|
||||
#include "playlist/plitem.h"
|
||||
#include "playlist/trackproxymodel.h"
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
|
||||
|
||||
PlaylistItemDelegate::PlaylistItemDelegate( QAbstractItemView* parent, TrackProxyModel* proxy )
|
||||
: QStyledItemDelegate( (QObject*)parent )
|
||||
@ -45,8 +48,10 @@ void
|
||||
PlaylistItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
PlItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
|
||||
if ( !item )
|
||||
if ( !item || item->query().isNull() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( item->query()->results().count() )
|
||||
painter->setOpacity( item->query()->results().at( 0 )->score() );
|
||||
|
@ -1,11 +1,14 @@
|
||||
#include "playlistmanager.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "audioengine.h"
|
||||
#include "collectionmodel.h"
|
||||
#include "collectionflatmodel.h"
|
||||
#include "collectionview.h"
|
||||
#include "playlistmodel.h"
|
||||
#include "playlistview.h"
|
||||
#include "queueview.h"
|
||||
#include "trackproxymodel.h"
|
||||
#include "trackmodel.h"
|
||||
|
||||
@ -13,22 +16,42 @@
|
||||
|
||||
#define FILTER_TIMEOUT 280
|
||||
|
||||
|
||||
PlaylistManager::PlaylistManager( QObject* parent )
|
||||
: QObject( parent )
|
||||
, m_widget( new QStackedWidget() )
|
||||
, m_widget( new QWidget() )
|
||||
, m_currentProxyModel( 0 )
|
||||
, m_currentModel( 0 )
|
||||
, m_currentView( 0 )
|
||||
, m_currentMode( 0 )
|
||||
, m_superCollectionVisible( true )
|
||||
{
|
||||
m_widget->setMinimumWidth( 690 );
|
||||
m_stack = new QStackedWidget();
|
||||
|
||||
m_queueView = new QueueView();
|
||||
m_queueModel = new PlaylistModel( m_queueView );
|
||||
m_queueView->queue()->setModel( m_queueModel );
|
||||
APP->audioEngine()->setQueue( m_queueView->queue()->proxyModel() );
|
||||
|
||||
m_widget->setLayout( new QVBoxLayout() );
|
||||
|
||||
m_splitter = new QSplitter();
|
||||
m_splitter->setOrientation( Qt::Vertical );
|
||||
m_splitter->setChildrenCollapsible( false );
|
||||
|
||||
m_splitter->addWidget( m_stack );
|
||||
m_splitter->addWidget( m_queueView );
|
||||
m_splitter->setStretchFactor( 0, 3 );
|
||||
m_splitter->setStretchFactor( 1, 1 );
|
||||
|
||||
m_widget->layout()->setMargin( 0 );
|
||||
m_widget->layout()->addWidget( m_splitter );
|
||||
|
||||
m_superCollectionView = new CollectionView();
|
||||
m_superCollectionFlatModel = new CollectionFlatModel( m_superCollectionView );
|
||||
m_superCollectionView->setModel( m_superCollectionFlatModel );
|
||||
|
||||
m_widget->addWidget( m_superCollectionView );
|
||||
m_stack->addWidget( m_superCollectionView );
|
||||
m_currentView = m_superCollectionView;
|
||||
|
||||
connect( &m_filterTimer, SIGNAL( timeout() ), SLOT( applyFilter() ) );
|
||||
@ -41,6 +64,13 @@ PlaylistManager::~PlaylistManager()
|
||||
}
|
||||
|
||||
|
||||
PlaylistView*
|
||||
PlaylistManager::queue() const
|
||||
{
|
||||
return m_queueView->queue();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
|
||||
{
|
||||
@ -61,14 +91,14 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
|
||||
m_playlistViews.insert( playlist, view );
|
||||
m_views.insert( (PlaylistInterface*)m_currentProxyModel, view );
|
||||
|
||||
m_widget->addWidget( view );
|
||||
m_widget->setCurrentWidget( view );
|
||||
m_stack->addWidget( view );
|
||||
m_stack->setCurrentWidget( view );
|
||||
m_currentView = view;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaylistView* view = m_playlistViews.value( playlist );
|
||||
m_widget->setCurrentWidget( view );
|
||||
m_stack->setCurrentWidget( view );
|
||||
m_currentProxyModel = view->proxyModel();
|
||||
m_currentModel = view->model();
|
||||
m_currentView = view;
|
||||
@ -102,14 +132,14 @@ PlaylistManager::show( const Tomahawk::album_ptr& album )
|
||||
m_albumViews.insert( album, view );
|
||||
m_views.insert( (PlaylistInterface*)m_currentProxyModel, view );
|
||||
|
||||
m_widget->addWidget( view );
|
||||
m_widget->setCurrentWidget( view );
|
||||
m_stack->addWidget( view );
|
||||
m_stack->setCurrentWidget( view );
|
||||
m_currentView = view;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaylistView* view = m_albumViews.value( album );
|
||||
m_widget->setCurrentWidget( view );
|
||||
m_stack->setCurrentWidget( view );
|
||||
m_currentProxyModel = view->proxyModel();
|
||||
m_currentModel = view->model();
|
||||
m_currentView = view;
|
||||
@ -142,14 +172,14 @@ PlaylistManager::show( const Tomahawk::collection_ptr& collection )
|
||||
m_collectionViews.insert( collection, view );
|
||||
m_views.insert( (PlaylistInterface*)m_currentProxyModel, view );
|
||||
|
||||
m_widget->addWidget( view );
|
||||
m_widget->setCurrentWidget( view );
|
||||
m_stack->addWidget( view );
|
||||
m_stack->setCurrentWidget( view );
|
||||
m_currentView = view;
|
||||
}
|
||||
else
|
||||
{
|
||||
CollectionView* view = m_collectionViews.value( collection );
|
||||
m_widget->setCurrentWidget( view );
|
||||
m_stack->setCurrentWidget( view );
|
||||
m_currentProxyModel = view->proxyModel();
|
||||
m_currentModel = view->model();
|
||||
m_currentView = view;
|
||||
@ -176,7 +206,7 @@ PlaylistManager::show( const Tomahawk::source_ptr& source )
|
||||
{
|
||||
SourceInfoWidget* swidget = new SourceInfoWidget( source );
|
||||
m_currentInfoWidget = swidget;
|
||||
m_widget->addWidget( m_currentInfoWidget );
|
||||
m_stack->addWidget( m_currentInfoWidget );
|
||||
m_sourceViews.insert( source, swidget );
|
||||
}
|
||||
else
|
||||
@ -184,7 +214,7 @@ PlaylistManager::show( const Tomahawk::source_ptr& source )
|
||||
m_currentInfoWidget = m_sourceViews.value( source );
|
||||
}
|
||||
|
||||
m_widget->setCurrentWidget( m_currentInfoWidget );
|
||||
m_stack->setCurrentWidget( m_currentInfoWidget );
|
||||
m_superCollectionVisible = false;
|
||||
|
||||
emit numSourcesChanged( 1 );
|
||||
@ -204,7 +234,7 @@ PlaylistManager::showSuperCollection()
|
||||
}
|
||||
}
|
||||
|
||||
m_widget->setCurrentWidget( m_superCollectionView );
|
||||
m_stack->setCurrentWidget( m_superCollectionView );
|
||||
m_currentProxyModel = m_superCollectionView->proxyModel();
|
||||
m_currentModel = m_superCollectionView->model();
|
||||
m_currentView = m_superCollectionView;
|
||||
@ -226,7 +256,7 @@ PlaylistManager::setTreeMode()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_currentMode = 1;
|
||||
m_widget->setCurrentWidget( m_superCollectionView );
|
||||
m_stack->setCurrentWidget( m_superCollectionView );
|
||||
}
|
||||
|
||||
|
||||
@ -236,7 +266,37 @@ PlaylistManager::setTableMode()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_currentMode = 0;
|
||||
m_widget->setCurrentWidget( m_superCollectionView );
|
||||
m_stack->setCurrentWidget( m_superCollectionView );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistManager::showQueue()
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
|
||||
QMetaObject::invokeMethod( this, "showQueue",
|
||||
Qt::QueuedConnection );
|
||||
return;
|
||||
}
|
||||
|
||||
m_queueView->showQueue();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistManager::hideQueue()
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
|
||||
QMetaObject::invokeMethod( this, "hideQueue",
|
||||
Qt::QueuedConnection );
|
||||
return;
|
||||
}
|
||||
|
||||
m_queueView->hideQueue();
|
||||
}
|
||||
|
||||
|
||||
@ -336,7 +396,7 @@ PlaylistManager::setShuffled( bool enabled )
|
||||
void
|
||||
PlaylistManager::showCurrentTrack()
|
||||
{
|
||||
PlaylistInterface* playlist = APP->audioEngine()->currentPlaylist();
|
||||
PlaylistInterface* playlist = APP->audioEngine()->currentTrackPlaylist();
|
||||
|
||||
if ( m_views.contains( playlist ) )
|
||||
{
|
||||
@ -346,7 +406,7 @@ PlaylistManager::showCurrentTrack()
|
||||
m_currentProxyModel = m_currentView->proxyModel();
|
||||
m_currentModel = m_currentView->model();
|
||||
|
||||
m_widget->setCurrentWidget( m_currentView );
|
||||
m_stack->setCurrentWidget( m_currentView );
|
||||
linkPlaylist();
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QStackedWidget>
|
||||
#include <QSplitter>
|
||||
|
||||
#include "tomahawk/collection.h"
|
||||
#include "tomahawk/playlistinterface.h"
|
||||
@ -11,7 +12,9 @@
|
||||
class CollectionModel;
|
||||
class CollectionFlatModel;
|
||||
class CollectionView;
|
||||
class PlaylistModel;
|
||||
class PlaylistView;
|
||||
class QueueView;
|
||||
class TrackProxyModel;
|
||||
class TrackModel;
|
||||
class TrackView;
|
||||
@ -26,11 +29,10 @@ public:
|
||||
~PlaylistManager();
|
||||
|
||||
QWidget* widget() const { return m_widget; }
|
||||
PlaylistView* queue() const;
|
||||
|
||||
bool isSuperCollectionVisible() const { return true; }
|
||||
|
||||
// QList<PlaylistView*> views( const Tomahawk::playlist_ptr& playlist ) { return m_views.value( playlist ); }
|
||||
|
||||
bool show( const Tomahawk::playlist_ptr& playlist );
|
||||
bool show( const Tomahawk::album_ptr& album );
|
||||
bool show( const Tomahawk::collection_ptr& collection );
|
||||
@ -52,6 +54,9 @@ public slots:
|
||||
void setTreeMode();
|
||||
void setTableMode();
|
||||
|
||||
void showQueue();
|
||||
void hideQueue();
|
||||
|
||||
void setFilter( const QString& filter );
|
||||
|
||||
void setRepeatMode( PlaylistInterface::RepeatMode mode );
|
||||
@ -65,7 +70,12 @@ private:
|
||||
void unlinkPlaylist();
|
||||
void linkPlaylist();
|
||||
|
||||
QStackedWidget* m_widget;
|
||||
QWidget* m_widget;
|
||||
QStackedWidget* m_stack;
|
||||
QSplitter* m_splitter;
|
||||
|
||||
PlaylistModel* m_queueModel;
|
||||
QueueView* m_queueView;
|
||||
|
||||
CollectionFlatModel* m_superCollectionFlatModel;
|
||||
CollectionView* m_superCollectionView;
|
||||
|
@ -14,6 +14,8 @@ PlaylistModel::PlaylistModel( QObject* parent )
|
||||
, m_waitForUpdate( false )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
setReadOnly( false );
|
||||
}
|
||||
|
||||
|
||||
@ -110,6 +112,19 @@ PlaylistModel::loadAlbum( const Tomahawk::album_ptr& album )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::appendTrack( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( query.isNull() )
|
||||
return;
|
||||
|
||||
QList< Tomahawk::query_ptr > ql;
|
||||
ql << query;
|
||||
|
||||
onTracksAdded( ql );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection )
|
||||
{
|
||||
@ -145,7 +160,8 @@ void
|
||||
PlaylistModel::onDataChanged()
|
||||
{
|
||||
PlItem* p = (PlItem*)sender();
|
||||
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) );
|
||||
if ( p && p->index.isValid() )
|
||||
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) );
|
||||
}
|
||||
|
||||
|
||||
@ -278,6 +294,9 @@ PlaylistModel::removeIndex( const QModelIndex& index )
|
||||
|
||||
TrackModel::removeIndex( index );
|
||||
|
||||
m_waitForUpdate = true;
|
||||
onPlaylistChanged();
|
||||
if ( !m_playlist.isNull() )
|
||||
{
|
||||
m_waitForUpdate = true;
|
||||
onPlaylistChanged();
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ public:
|
||||
void loadPlaylist( const Tomahawk::playlist_ptr& playlist );
|
||||
void loadAlbum( const Tomahawk::album_ptr& album );
|
||||
|
||||
void appendTrack( const Tomahawk::query_ptr& query );
|
||||
|
||||
virtual void removeIndex( const QModelIndex& index );
|
||||
|
||||
signals:
|
||||
@ -50,7 +52,7 @@ private slots:
|
||||
void onRevisionLoaded( Tomahawk::PlaylistRevision revision );
|
||||
void onPlaylistChanged();
|
||||
|
||||
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection );
|
||||
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection = Tomahawk::collection_ptr() );
|
||||
|
||||
private:
|
||||
QList<Tomahawk::plentry_ptr> playlistEntries() const;
|
||||
|
@ -39,6 +39,7 @@ PlaylistView::setupMenus()
|
||||
m_itemMenu.clear();
|
||||
|
||||
m_playItemAction = m_itemMenu.addAction( tr( "&Play" ) );
|
||||
m_addItemsToQueueAction = m_itemMenu.addAction( tr( "Add to &Queue" ) );
|
||||
m_itemMenu.addSeparator();
|
||||
m_addItemsToPlaylistAction = m_itemMenu.addAction( tr( "&Add to Playlist" ) );
|
||||
m_itemMenu.addSeparator();
|
||||
@ -48,6 +49,7 @@ PlaylistView::setupMenus()
|
||||
m_deleteItemAction->setEnabled( !model()->isReadOnly() );
|
||||
|
||||
connect( m_playItemAction, SIGNAL( triggered() ), SLOT( playItem() ) );
|
||||
connect( m_addItemsToQueueAction, SIGNAL( triggered() ), SLOT( addItemsToQueue() ) );
|
||||
connect( m_addItemsToPlaylistAction, SIGNAL( triggered() ), SLOT( addItemsToPlaylist() ) );
|
||||
connect( m_deleteItemAction, SIGNAL( triggered() ), SLOT( deleteItem() ) );
|
||||
}
|
||||
@ -61,7 +63,7 @@ PlaylistView::onCustomContextMenu( const QPoint& pos )
|
||||
|
||||
QModelIndex idx = indexAt( pos );
|
||||
idx = idx.sibling( idx.row(), 0 );
|
||||
m_contextMenuIndex = idx;
|
||||
setContextMenuIndex( idx );
|
||||
|
||||
if ( !idx.isValid() )
|
||||
return;
|
||||
@ -87,13 +89,6 @@ PlaylistView::keyPressEvent( QKeyEvent* event )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::playItem()
|
||||
{
|
||||
onItemActivated( m_contextMenuIndex );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::addItemsToPlaylist()
|
||||
{
|
||||
@ -103,5 +98,5 @@ PlaylistView::addItemsToPlaylist()
|
||||
void
|
||||
PlaylistView::deleteItem()
|
||||
{
|
||||
proxyModel()->removeIndex( m_contextMenuIndex );
|
||||
proxyModel()->removeIndex( contextMenuIndex() );
|
||||
}
|
||||
|
@ -22,17 +22,16 @@ protected:
|
||||
private slots:
|
||||
void onCustomContextMenu( const QPoint& pos );
|
||||
|
||||
void playItem();
|
||||
void addItemsToPlaylist();
|
||||
void deleteItem();
|
||||
|
||||
private:
|
||||
void setupMenus();
|
||||
|
||||
QModelIndex m_contextMenuIndex;
|
||||
|
||||
QMenu m_itemMenu;
|
||||
|
||||
QAction* m_playItemAction;
|
||||
QAction* m_addItemsToQueueAction;
|
||||
QAction* m_addItemsToPlaylistAction;
|
||||
QAction* m_deleteItemAction;
|
||||
};
|
||||
|
@ -12,13 +12,13 @@ PlItem::~PlItem()
|
||||
// Don't use qDeleteAll here! The children will remove themselves
|
||||
// from the list when they get deleted and the qDeleteAll iterator
|
||||
// will fail badly!
|
||||
for ( int i = children.count() - 1; i >= 0; i-- )
|
||||
delete children.at( i );
|
||||
|
||||
if ( parent && index.isValid() )
|
||||
{
|
||||
parent->children.removeAt( index.row() );
|
||||
}
|
||||
|
||||
for ( int i = children.count() - 1; i >= 0; i-- )
|
||||
delete children.at( i );
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
explicit PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent = 0, int row = -1 );
|
||||
|
||||
const Tomahawk::plentry_ptr& entry() const { return m_entry; };
|
||||
const Tomahawk::query_ptr& query() const { return m_query; };
|
||||
const Tomahawk::query_ptr& query() const { if ( !m_entry.isNull() ) return m_entry->query(); else return m_query; };
|
||||
|
||||
bool isPlaying() { return m_isPlaying; }
|
||||
void setIsPlaying( bool b ) { m_isPlaying = b; emit dataChanged(); }
|
||||
|
38
src/playlist/queueproxymodel.cpp
Normal file
38
src/playlist/queueproxymodel.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "queueproxymodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
QueueProxyModel::QueueProxyModel( QObject* parent )
|
||||
: PlaylistProxyModel( parent )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
QueueProxyModel::~QueueProxyModel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::result_ptr
|
||||
QueueProxyModel::siblingItem( int itemsAway )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << rowCount( QModelIndex() );
|
||||
|
||||
setCurrentItem( QModelIndex() );
|
||||
Tomahawk::result_ptr res = PlaylistProxyModel::siblingItem( itemsAway );
|
||||
|
||||
qDebug() << "new rowcount:" << rowCount( QModelIndex() );
|
||||
if ( rowCount( QModelIndex() ) == 1 )
|
||||
APP->playlistManager()->hideQueue();
|
||||
|
||||
removeIndex( currentItem() );
|
||||
|
||||
return res;
|
||||
}
|
19
src/playlist/queueproxymodel.h
Normal file
19
src/playlist/queueproxymodel.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef QUEUEPROXYMODEL_H
|
||||
#define QUEUEPROXYMODEL_H
|
||||
|
||||
#include "playlistproxymodel.h"
|
||||
|
||||
class QMetaData;
|
||||
|
||||
class QueueProxyModel : public PlaylistProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QueueProxyModel( QObject* parent = 0 );
|
||||
~QueueProxyModel();
|
||||
|
||||
virtual Tomahawk::result_ptr siblingItem( int itemsAway );
|
||||
};
|
||||
|
||||
#endif // QUEUEPROXYMODEL_H
|
115
src/playlist/queueview.cpp
Normal file
115
src/playlist/queueview.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include "queueview.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTimeLine>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "playlist/queueproxymodel.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
QueueView::QueueView( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, m_prevHeight( 175 )
|
||||
{
|
||||
setMinimumHeight( 25 );
|
||||
setMaximumHeight( 25 );
|
||||
setLayout( new QVBoxLayout() );
|
||||
|
||||
m_queue = new PlaylistView( this );
|
||||
m_queue->setProxyModel( new QueueProxyModel( this ) );
|
||||
|
||||
m_button = new QPushButton();
|
||||
m_button->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
|
||||
m_button->setText( tr( "Click to show queue" ) );
|
||||
connect( m_button, SIGNAL( clicked() ), SLOT( showQueue() ) );
|
||||
|
||||
layout()->setMargin( 0 );
|
||||
layout()->addWidget( m_button );
|
||||
layout()->addWidget( m_queue );
|
||||
|
||||
m_queue->hide();
|
||||
}
|
||||
|
||||
|
||||
QueueView::~QueueView()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueView::showQueue()
|
||||
{
|
||||
if ( !m_queue->isHidden() )
|
||||
return;
|
||||
|
||||
m_button->setText( tr( "Click to hide queue" ) );
|
||||
disconnect( m_button, SIGNAL( clicked() ), this, SLOT( showQueue() ) );
|
||||
connect( m_button, SIGNAL( clicked() ), SLOT( hideQueue() ) );
|
||||
|
||||
m_queue->setMaximumHeight( 0 );
|
||||
m_queue->show();
|
||||
|
||||
QTimeLine *timeLine = new QTimeLine( 300, this );
|
||||
timeLine->setFrameRange( 0, m_prevHeight );
|
||||
timeLine->setUpdateInterval( 20 );
|
||||
connect( timeLine, SIGNAL( frameChanged( int ) ), SLOT( onAnimationStep( int ) ) );
|
||||
connect( timeLine, SIGNAL( finished() ), SLOT( onAnimationFinished() ) );
|
||||
timeLine->start();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueView::hideQueue()
|
||||
{
|
||||
if ( m_queue->isHidden() )
|
||||
return;
|
||||
|
||||
m_button->setText( tr( "Click to show queue" ) );
|
||||
disconnect( m_button, SIGNAL( clicked() ), this, SLOT( hideQueue() ) );
|
||||
connect( m_button, SIGNAL( clicked() ), SLOT( showQueue() ) );
|
||||
|
||||
m_prevHeight = height() - 25;
|
||||
QTimeLine *timeLine = new QTimeLine( 300, this );
|
||||
timeLine->setFrameRange( 0, m_prevHeight );
|
||||
timeLine->setUpdateInterval( 20 );
|
||||
timeLine->setDirection( QTimeLine::Backward );
|
||||
connect( timeLine, SIGNAL( frameChanged( int ) ), SLOT( onAnimationStep( int ) ) );
|
||||
connect( timeLine, SIGNAL( finished() ), SLOT( onAnimationFinished() ) );
|
||||
timeLine->start();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueView::onAnimationStep( int frame )
|
||||
{
|
||||
setMinimumHeight( frame + 25 );
|
||||
setMaximumHeight( frame + 25 );
|
||||
m_queue->setMaximumHeight( frame );
|
||||
|
||||
m_queue->resize( m_queue->width(), frame );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueView::onAnimationFinished()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << maximumHeight();
|
||||
|
||||
if ( maximumHeight() < 32 )
|
||||
{
|
||||
setMinimumHeight( 25 );
|
||||
setMaximumHeight( 25 );
|
||||
m_queue->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
setMinimumHeight( 200 );
|
||||
m_queue->setMaximumHeight( QWIDGETSIZE_MAX );
|
||||
setMaximumHeight( QWIDGETSIZE_MAX );
|
||||
}
|
||||
|
||||
sender()->deleteLater();
|
||||
}
|
32
src/playlist/queueview.h
Normal file
32
src/playlist/queueview.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef QUEUEVIEW_H
|
||||
#define QUEUEVIEW_H
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "playlistview.h"
|
||||
|
||||
class QueueView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QueueView( QWidget* parent = 0 );
|
||||
~QueueView();
|
||||
|
||||
PlaylistView* queue() const { return m_queue; }
|
||||
|
||||
public slots:
|
||||
void showQueue();
|
||||
void hideQueue();
|
||||
|
||||
private slots:
|
||||
void onAnimationStep( int frame );
|
||||
void onAnimationFinished();
|
||||
|
||||
private:
|
||||
PlaylistView* m_queue;
|
||||
QPushButton* m_button;
|
||||
unsigned int m_prevHeight;
|
||||
};
|
||||
|
||||
#endif // QUEUEVIEW_H
|
@ -16,6 +16,9 @@ TrackModel::TrackModel( QObject* parent )
|
||||
, m_readOnly( true )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
connect( (QObject*)APP->audioEngine(), SIGNAL( finished( Tomahawk::result_ptr ) ), SLOT( onPlaybackFinished( Tomahawk::result_ptr ) ), Qt::DirectConnection );
|
||||
connect( (QObject*)APP->audioEngine(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection );
|
||||
}
|
||||
|
||||
|
||||
@ -272,6 +275,16 @@ TrackModel::mimeData( const QModelIndexList &indexes ) const
|
||||
void
|
||||
TrackModel::removeIndex( const QModelIndex& index )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
|
||||
QMetaObject::invokeMethod( this, "removeIndex",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const QModelIndex, index)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( index.column() > 0 )
|
||||
@ -309,3 +322,26 @@ TrackModel::itemFromIndex( const QModelIndex& index ) const
|
||||
return m_rootItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackModel::onPlaybackFinished( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
PlItem* oldEntry = itemFromIndex( m_currentIndex );
|
||||
qDebug() << oldEntry->query();
|
||||
if ( oldEntry && !oldEntry->query().isNull() && oldEntry->query()->results().contains( result ) )
|
||||
{
|
||||
oldEntry->setIsPlaying( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackModel::onPlaybackStopped()
|
||||
{
|
||||
PlItem* oldEntry = itemFromIndex( m_currentIndex );
|
||||
if ( oldEntry )
|
||||
{
|
||||
oldEntry->setIsPlaying( false );
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,6 @@ public:
|
||||
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
|
||||
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
|
||||
|
||||
virtual void removeIndex( const QModelIndex& index );
|
||||
virtual void removeIndexes( const QList<QModelIndex>& indexes );
|
||||
|
||||
virtual Tomahawk::result_ptr siblingItem( int direction ) { return Tomahawk::result_ptr(); }
|
||||
@ -54,6 +53,8 @@ public:
|
||||
virtual PlaylistInterface::RepeatMode repeatMode() const { return PlaylistInterface::NoRepeat; }
|
||||
virtual bool shuffled() const { return false; }
|
||||
|
||||
virtual void appendTrack( const Tomahawk::query_ptr& query ) = 0;
|
||||
|
||||
PlItem* itemFromIndex( const QModelIndex& index ) const;
|
||||
|
||||
PlItem* m_rootItem;
|
||||
@ -67,12 +68,18 @@ signals:
|
||||
public slots:
|
||||
virtual void setCurrentItem( const QModelIndex& index );
|
||||
|
||||
virtual void removeIndex( const QModelIndex& index );
|
||||
|
||||
virtual void setRepeatMode( PlaylistInterface::RepeatMode mode ) {}
|
||||
virtual void setShuffled( bool shuffled ) {}
|
||||
|
||||
protected:
|
||||
virtual void setReadOnly( bool b ) { m_readOnly = b; }
|
||||
|
||||
private slots:
|
||||
void onPlaybackFinished( const Tomahawk::result_ptr& result );
|
||||
void onPlaybackStopped();
|
||||
|
||||
private:
|
||||
QPersistentModelIndex m_currentIndex;
|
||||
bool m_readOnly;
|
||||
|
@ -163,7 +163,7 @@ TrackProxyModel::removeIndex( const QModelIndex& index )
|
||||
|
||||
if ( !sourceModel() )
|
||||
return;
|
||||
if ( index.column() > 0 )
|
||||
if ( !index.isValid() )
|
||||
return;
|
||||
|
||||
sourceModel()->removeIndex( mapToSource( index ) );
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/queueview.h"
|
||||
#include "audioengine.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "trackmodel.h"
|
||||
@ -31,6 +33,7 @@ TrackView::TrackView( QWidget* parent )
|
||||
setDragDropMode( QAbstractItemView::InternalMove );
|
||||
setDragDropOverwriteMode( false );
|
||||
setAllColumnsShowFocus( true );
|
||||
setMinimumWidth( 690 );
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
QFont f = font();
|
||||
@ -149,6 +152,31 @@ TrackView::onItemResized( const QModelIndex& index )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackView::playItem()
|
||||
{
|
||||
onItemActivated( m_contextMenuIndex );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackView::addItemsToQueue()
|
||||
{
|
||||
foreach( const QModelIndex& idx, selectedIndexes() )
|
||||
{
|
||||
if ( idx.column() )
|
||||
continue;
|
||||
|
||||
PlItem* item = model()->itemFromIndex( proxyModel()->mapToSource( idx ) );
|
||||
if ( item && item->query()->numResults() )
|
||||
{
|
||||
APP->playlistManager()->queue()->model()->appendTrack( item->query() );
|
||||
APP->playlistManager()->showQueue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackView::resizeEvent( QResizeEvent* event )
|
||||
{
|
||||
|
@ -26,9 +26,15 @@ public:
|
||||
|
||||
void setModel( TrackModel* model );
|
||||
|
||||
QModelIndex contextMenuIndex() const { return m_contextMenuIndex; }
|
||||
void setContextMenuIndex( const QModelIndex& idx ) { m_contextMenuIndex = idx; }
|
||||
|
||||
public slots:
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
|
||||
void playItem();
|
||||
void addItemsToQueue();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent( QResizeEvent* event );
|
||||
|
||||
@ -65,6 +71,8 @@ private:
|
||||
bool m_resizing;
|
||||
bool m_dragging;
|
||||
QRect m_dropRect;
|
||||
|
||||
QModelIndex m_contextMenuIndex;
|
||||
};
|
||||
|
||||
#endif // TRACKVIEW_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user