diff --git a/src/audiocontrols.cpp b/src/audiocontrols.cpp index bc255af3b..7a90319ec 100644 --- a/src/audiocontrols.cpp +++ b/src/audiocontrols.cpp @@ -124,8 +124,9 @@ AudioControls::AudioControls( QWidget* parent ) connect( ui->repeatButton, SIGNAL( clicked() ), SLOT( onRepeatClicked() ) ); connect( ui->shuffleButton, SIGNAL( clicked() ), SLOT( onShuffleClicked() ) ); - connect( ui->artistTrackLabel, SIGNAL( clicked() ), SLOT( onTrackClicked() ) ); - connect( ui->albumLabel, SIGNAL( clicked() ), SLOT( onAlbumClicked() ) ); + connect( ui->artistTrackLabel, SIGNAL( clickedArtist() ), SLOT( onArtistClicked() ) ); + connect( ui->artistTrackLabel, SIGNAL( clickedTrack() ), SLOT( onTrackClicked() ) ); + connect( ui->albumLabel, SIGNAL( clickedAlbum() ), SLOT( onAlbumClicked() ) ); // connect( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ), SLOT( onPlaybackLoading( Tomahawk::result_ptr ) ) ); @@ -413,9 +414,9 @@ AudioControls::onShuffleClicked() void -AudioControls::onTrackClicked() +AudioControls::onArtistClicked() { - PlaylistManager::instance()->showCurrentTrack(); + PlaylistManager::instance()->show( m_currentTrack->artist() ); } @@ -424,3 +425,10 @@ AudioControls::onAlbumClicked() { PlaylistManager::instance()->show( m_currentTrack->album() ); } + + +void +AudioControls::onTrackClicked() +{ + PlaylistManager::instance()->showCurrentTrack(); +} diff --git a/src/audiocontrols.h b/src/audiocontrols.h index 2ba63eeed..59ac80eef 100644 --- a/src/audiocontrols.h +++ b/src/audiocontrols.h @@ -38,8 +38,10 @@ private slots: void onRepeatClicked(); void onShuffleClicked(); - void onTrackClicked(); + + void onArtistClicked(); void onAlbumClicked(); + void onTrackClicked(); void onCoverArtDownloaded(); diff --git a/src/libtomahawk/database/database.cpp b/src/libtomahawk/database/database.cpp index 59a3f540c..797b5913c 100644 --- a/src/libtomahawk/database/database.cpp +++ b/src/libtomahawk/database/database.cpp @@ -1,5 +1,7 @@ #include "database.h" +#define WORKER_THREADS 5 + Database* Database::s_instance = 0; @@ -13,12 +15,18 @@ Database::instance() Database::Database( const QString& dbname, QObject* parent ) : QObject( parent ) , m_impl( new DatabaseImpl( dbname, this ) ) - , m_workerRO( new DatabaseWorker( m_impl, this, false ) ) , m_workerRW( new DatabaseWorker( m_impl, this, true ) ) { s_instance = this; - m_workerRO->start(); + for ( int i = 0; i < WORKER_THREADS; i++ ) + { + DatabaseWorker* worker = new DatabaseWorker( m_impl, this, false ); + worker->start(); + + m_workersRO << worker; + } + m_workerRW->start(); } @@ -27,8 +35,8 @@ Database::~Database() { qDebug() << Q_FUNC_INFO; + qDeleteAll( m_workersRO ); delete m_workerRW; - delete m_workerRO; delete m_impl; } @@ -46,12 +54,31 @@ Database::enqueue( QSharedPointer lc ) if( lc->doesMutates() ) { //qDebug() << Q_FUNC_INFO << "RW" << lc->commandname(); - emit newJobRO( lc ); + m_workerRW->enqueue( lc ); } else { - //qDebug() << Q_FUNC_INFO << "RO" << lc->commandname(); - emit newJobRW( lc ); +// qDebug() << Q_FUNC_INFO << "RO" << lc->commandname(); + + int busyThreads = 0; + DatabaseWorker* happyThread = 0; + for ( int i = 0; i < m_workersRO.count(); i++ ) + { + DatabaseWorker* worker = m_workersRO.at( i ); + + if ( !worker->busy() ) + { + happyThread = worker; + break; + } + busyThreads++; + + if ( !happyThread || worker->outstandingJobs() < happyThread->outstandingJobs() ) + happyThread = worker; + } + + qDebug() << "Enqueueing command to thread:" << happyThread << busyThreads << lc->commandname(); + happyThread->enqueue( lc ); } } diff --git a/src/libtomahawk/database/database.h b/src/libtomahawk/database/database.h index b62ebe050..156ba6743 100644 --- a/src/libtomahawk/database/database.h +++ b/src/libtomahawk/database/database.h @@ -45,7 +45,8 @@ public slots: private: DatabaseImpl* m_impl; - DatabaseWorker *m_workerRO, *m_workerRW; + DatabaseWorker* m_workerRW; + QList m_workersRO; bool m_indexReady; static Database* s_instance; diff --git a/src/libtomahawk/database/databaseworker.cpp b/src/libtomahawk/database/databaseworker.cpp index 63df84c92..ab7d41c78 100644 --- a/src/libtomahawk/database/databaseworker.cpp +++ b/src/libtomahawk/database/databaseworker.cpp @@ -15,18 +15,6 @@ DatabaseWorker::DatabaseWorker( DatabaseImpl* lib, Database* db, bool mutates ) , m_outstanding( 0 ) { moveToThread( this ); - if( mutates ) - { - connect( db, SIGNAL( newJobRW(QSharedPointer) ), - SLOT( doWork(QSharedPointer) ), - Qt::QueuedConnection ); - } - else - { - connect( db, SIGNAL( newJobRO(QSharedPointer) ), - SLOT( doWork(QSharedPointer) ), - Qt::QueuedConnection ); - } qDebug() << "CTOR DatabaseWorker" << this->thread(); } @@ -50,7 +38,19 @@ DatabaseWorker::run() void -DatabaseWorker::doWork( QSharedPointer cmd ) +DatabaseWorker::enqueue( const QSharedPointer& cmd ) +{ + QMutexLocker lock( &m_mut ); + m_commands << cmd; + m_outstanding++; + + if ( m_outstanding == 1 ) + QTimer::singleShot( 0, this, SLOT( doWork() ) ); +} + + +void +DatabaseWorker::doWork() { /* Run the dbcmd. Only inside a transaction if the cmd does mutates. @@ -59,8 +59,16 @@ DatabaseWorker::doWork( QSharedPointer cmd ) log to the database oplog for replication to peers. */ + QTime timer; timer.start(); + + QSharedPointer cmd; + { + QMutexLocker lock( &m_mut ); + cmd = m_commands.takeFirst(); + } + if( cmd->doesMutates() ) { bool transok = m_dbimpl->database().transaction(); @@ -154,6 +162,14 @@ DatabaseWorker::doWork( QSharedPointer cmd ) } cmd->emitFinished(); + + { + QMutexLocker lock( &m_mut ); + m_outstanding--; + } + + if ( m_outstanding > 0 ) + doWork(); } diff --git a/src/libtomahawk/database/databaseworker.h b/src/libtomahawk/database/databaseworker.h index 74c0eb22a..83ecd1562 100644 --- a/src/libtomahawk/database/databaseworker.h +++ b/src/libtomahawk/database/databaseworker.h @@ -24,13 +24,17 @@ Q_OBJECT public: DatabaseWorker( DatabaseImpl*, Database*, bool mutates ); ~DatabaseWorker(); - //void enqueue( QSharedPointer ); + + void enqueue( const QSharedPointer& ); + + bool busy() const { return m_outstanding > 0; } + unsigned int outstandingJobs() const { return m_outstanding; } protected: void run(); -public slots: - void doWork( QSharedPointer ); +private slots: + void doWork(); private: void logOp( DatabaseCommandLoggable* command ); @@ -38,8 +42,10 @@ private: QMutex m_mut; DatabaseImpl* m_dbimpl; QList< QSharedPointer > m_commands; + bool m_abort; int m_outstanding; + QJson::Serializer m_serializer; }; diff --git a/src/libtomahawk/utils/querylabel.cpp b/src/libtomahawk/utils/querylabel.cpp index 4a4ecdd54..4e566ccd9 100644 --- a/src/libtomahawk/utils/querylabel.cpp +++ b/src/libtomahawk/utils/querylabel.cpp @@ -57,6 +57,7 @@ QueryLabel::~QueryLabel() void QueryLabel::init() { + m_hoverType = None; setContentsMargins( 0, 0, 0, 0 ); setMouseTracking( true ); @@ -251,6 +252,7 @@ void QueryLabel::updateLabel() { m_hoverArea = QRect(); + m_hoverType = None; updateGeometry(); update(); @@ -302,6 +304,7 @@ QueryLabel::paintEvent( QPaintEvent* event ) { m_hoverArea.setLeft( 0 ); m_hoverArea.setRight( fontMetrics().width( elidedText ) + contentsMargins().left() * 2 ); + m_hoverType = Track; } p.setPen( palette().mid().color() ); @@ -311,8 +314,16 @@ QueryLabel::paintEvent( QPaintEvent* event ) if ( elidedText != s || ( m_result.isNull() && m_query.isNull() ) ) { - p.setBrush( palette().window() ); - p.setPen( palette().color( foregroundRole() ) ); + if ( m_hoverArea.width() ) + { + p.setPen( palette().highlightedText().color() ); + p.setBrush( palette().highlight() ); + } + else + { + p.setBrush( palette().window() ); + p.setPen( palette().color( foregroundRole() ) ); + } p.drawText( r, align, elidedText ); } else @@ -328,7 +339,7 @@ QueryLabel::paintEvent( QPaintEvent* event ) p.setBrush( palette().window() ); p.setPen( palette().color( foregroundRole() ) ); - if ( m_hoverArea.width() && m_hoverArea.left() + contentsMargins().left() == r.left() ) + if ( m_hoverType == Artist ) { p.setPen( palette().highlightedText().color() ); p.setBrush( palette().highlight() ); @@ -347,7 +358,7 @@ QueryLabel::paintEvent( QPaintEvent* event ) p.drawText( r, align, DASH ); r.adjust( dashX, 0, 0, 0 ); } - if ( m_hoverArea.width() && m_hoverArea.left() + contentsMargins().left() == r.left() ) + if ( m_hoverType == Album ) { p.setPen( palette().highlightedText().color() ); p.setBrush( palette().highlight() ); @@ -366,7 +377,7 @@ QueryLabel::paintEvent( QPaintEvent* event ) p.drawText( r, align, DASH ); r.adjust( dashX, 0, 0, 0 ); } - if ( m_hoverArea.width() && m_hoverArea.left() + contentsMargins().left() == r.left() ) + if ( m_hoverType == Track ) { p.setPen( palette().highlightedText().color() ); p.setBrush( palette().highlight() ); @@ -413,7 +424,23 @@ QueryLabel::mouseReleaseEvent( QMouseEvent* event ) m_dragPos = QPoint(); if ( time.elapsed() < qApp->doubleClickInterval() ) - emit clicked(); + { + switch( m_hoverType ) + { + case Artist: + emit clickedArtist(); + break; + case Album: + emit clickedAlbum(); + break; + case Track: + emit clickedTrack(); + break; + + default: + emit clicked(); + } + } } @@ -434,6 +461,7 @@ QueryLabel::mouseMoveEvent( QMouseEvent* event ) if ( m_query.isNull() && m_result.isNull() ) { m_hoverArea = QRect(); + m_hoverType = None; return; } @@ -460,19 +488,23 @@ QueryLabel::mouseMoveEvent( QMouseEvent* event ) } QRect hoverArea; + m_hoverType = None; if ( m_type & Artist && x < artistX ) { + m_hoverType = Artist; hoverArea.setLeft( 0 ); hoverArea.setRight( artistX + contentsMargins().left() ); } else if ( m_type & Album && x < albumX && x > artistX ) { + m_hoverType = Album; int spacing = ( m_type & Artist ) ? dashX : 0; hoverArea.setLeft( artistX + spacing ); hoverArea.setRight( albumX + spacing + contentsMargins().left() ); } else if ( m_type & Track && x < trackX && x > albumX ) { + m_hoverType = Track; int spacing = ( m_type & Album ) ? dashX : 0; hoverArea.setLeft( albumX + spacing ); hoverArea.setRight( trackX + contentsMargins().left() ); @@ -495,6 +527,7 @@ void QueryLabel::leaveEvent( QEvent* event ) { m_hoverArea = QRect(); + m_hoverType = None; repaint(); } diff --git a/src/libtomahawk/utils/querylabel.h b/src/libtomahawk/utils/querylabel.h index a815b4212..b584d255b 100644 --- a/src/libtomahawk/utils/querylabel.h +++ b/src/libtomahawk/utils/querylabel.h @@ -16,6 +16,7 @@ Q_OBJECT public: enum DisplayType { + None = 0, Artist = 1, Album = 2, Track = 4, @@ -61,6 +62,9 @@ public slots: signals: void clicked(); + void clickedArtist(); + void clickedAlbum(); + void clickedTrack(); void textChanged( const QString& text ); void resultChanged( const Tomahawk::result_ptr& result ); @@ -89,6 +93,7 @@ private: Qt::Alignment align; Qt::TextElideMode mode; + DisplayType m_hoverType; QRect m_hoverArea; QPoint m_dragPos; QMargins m_textMargins;