1
0
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:
Christian Muehlhaeuser 2010-11-27 02:00:42 +01:00
parent a42c317209
commit 597c52f96d
24 changed files with 497 additions and 50 deletions

View File

@ -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

View File

@ -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 );
}

View File

@ -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;

View File

@ -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 );

View File

@ -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 ) );
}

View File

@ -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

View File

@ -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() );

View File

@ -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();
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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() );
}

View File

@ -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;
};

View File

@ -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 );
}

View File

@ -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(); }

View 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;
}

View 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
View 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
View 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

View File

@ -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 );
}
}

View File

@ -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;

View File

@ -163,7 +163,7 @@ TrackProxyModel::removeIndex( const QModelIndex& index )
if ( !sourceModel() )
return;
if ( index.column() > 0 )
if ( !index.isValid() )
return;
sourceModel()->removeIndex( mapToSource( index ) );

View File

@ -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 )
{

View File

@ -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