diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 62314247e..79120d6f7 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -146,6 +146,7 @@ set( libGuiSources widgets/ClickableLabel.cpp widgets/ComboBox.cpp widgets/DropDownButton.cpp + widgets/DownloadButton.cpp widgets/ElidedLabel.cpp widgets/FilterHeader.cpp widgets/CaptionLabel.cpp diff --git a/src/libtomahawk/DownloadManager.cpp b/src/libtomahawk/DownloadManager.cpp index a01297eab..79cd4da8f 100644 --- a/src/libtomahawk/DownloadManager.cpp +++ b/src/libtomahawk/DownloadManager.cpp @@ -24,6 +24,8 @@ #include "TomahawkSettings.h" #include "infosystem/InfoSystem.h" #include "utils/Logger.h" +#include "Result.h" +#include "Query.h" DownloadManager* DownloadManager::s_instance = 0; @@ -85,6 +87,36 @@ DownloadManager::localFileForDownload( const QString& url ) const } +QUrl +DownloadManager::localUrlForDownload( const Tomahawk::query_ptr& query ) const +{ + Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr(); + if ( result ) + { + return localUrlForDownload( result ); + } + + return QUrl(); +} + + +QUrl +DownloadManager::localUrlForDownload( const Tomahawk::result_ptr& result ) const +{ + if ( result && !result->downloadFormats().isEmpty() && + !localFileForDownload( result->downloadFormats().first().url.toString() ).isEmpty() ) + { + return QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( result->downloadFormats().first().url.toString() ) ).absolutePath() ); + } + else if ( result && result->downloadJob() && result->downloadJob()->state() == DownloadJob::Finished ) + { + return QUrl::fromLocalFile( QFileInfo( result->downloadJob()->localFile() ).absolutePath() ); + } + + return QUrl(); +} + + void DownloadManager::storeJobs( const QList& jobs ) { diff --git a/src/libtomahawk/DownloadManager.h b/src/libtomahawk/DownloadManager.h index f4a873581..62c84a884 100644 --- a/src/libtomahawk/DownloadManager.h +++ b/src/libtomahawk/DownloadManager.h @@ -45,6 +45,8 @@ public: void storeJobs( const QList& jobs ); QString localFileForDownload( const QString& url ) const; + QUrl localUrlForDownload( const Tomahawk::result_ptr& result ) const; + QUrl localUrlForDownload( const Tomahawk::query_ptr& query ) const; public slots: bool addJob( const downloadjob_ptr& job ); diff --git a/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp b/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp index e6b119ae2..2c4382865 100644 --- a/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp +++ b/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp @@ -28,6 +28,7 @@ #include "utils/TomahawkUtilsGui.h" #include "utils/DpiScaler.h" #include "ViewManager.h" +#include "widgets/DownloadButton.h" #include #include @@ -164,6 +165,10 @@ ColumnViewPreviewWidget::ColumnViewPreviewWidget( ColumnView* parent ) m_ageValue->setAlignment( Qt::AlignLeft | Qt::AlignVCenter ); gridLayout->addWidget( m_ageValue, 4, 1 ); + + m_downloadButton = new DownloadButton( this ); + mainLayout->addWidget( m_downloadButton ); + mainLayout->addStretch(); TomahawkUtils::unmarginLayout( mainLayout ); @@ -217,6 +222,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query ) m_bitrateValue->setText( tr( "%1 kbps" ).arg( query->results().first()->bitrate() ) ); m_durationValue->setText( TomahawkUtils::timeToString( query->track()->duration() ) ); m_ageValue->setText( TomahawkUtils::ageToString( QDateTime::fromTime_t( query->results().first()->modificationTime() ) ) ); + m_downloadButton->setQuery( query ); m_yearValue->setVisible( query->track()->year() > 0 ); m_yearLabel->setVisible( query->track()->year() > 0 ); @@ -226,6 +232,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query ) m_durationValue->setVisible( query->track()->duration() > 0 ); m_ageLabel->setVisible( query->results().first()->modificationTime() > 0 ); m_ageValue->setVisible( query->results().first()->modificationTime() > 0 ); + m_downloadButton->setVisible( true ); } else { @@ -237,6 +244,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query ) m_durationValue->setVisible( false ); m_ageLabel->setVisible( false ); m_ageValue->setVisible( false ); + m_downloadButton->setVisible( false ); } setMinimumHeight( sizeHint().height() ); diff --git a/src/libtomahawk/playlist/ColumnViewPreviewWidget.h b/src/libtomahawk/playlist/ColumnViewPreviewWidget.h index 523532968..4e771248e 100644 --- a/src/libtomahawk/playlist/ColumnViewPreviewWidget.h +++ b/src/libtomahawk/playlist/ColumnViewPreviewWidget.h @@ -30,6 +30,7 @@ class QueryLabel; class PlayableCover; class QLabel; class ScrollingLabel; +class DownloadButton; class DLLEXPORT ColumnViewPreviewWidget : public QWidget { @@ -71,6 +72,8 @@ private: ScrollingLabel* m_trackLabel; QueryLabel* m_artistLabel; + + DownloadButton* m_downloadButton; }; #endif // COLUMNVIEWPREVIEWWIDGET_H diff --git a/src/libtomahawk/playlist/GridItemDelegate.cpp b/src/libtomahawk/playlist/GridItemDelegate.cpp index fa6f30d43..68fbddc79 100644 --- a/src/libtomahawk/playlist/GridItemDelegate.cpp +++ b/src/libtomahawk/playlist/GridItemDelegate.cpp @@ -19,16 +19,6 @@ #include "GridItemDelegate.h" -#include -#include -#include -#include -#include -#include - -#include "DownloadManager.h" -#include "DownloadJob.h" - #include "Artist.h" #include "Query.h" #include "Result.h" @@ -39,17 +29,22 @@ #include "playlist/PlayableItem.h" #include "playlist/PlayableProxyModel.h" #include "widgets/HoverControls.h" -#include "widgets/DropDownButton.h" +#include "widgets/DownloadButton.h" #include "widgets/ImageButton.h" #include "utils/TomahawkStyle.h" #include "utils/TomahawkUtilsGui.h" #include "utils/PixmapDelegateFader.h" #include "utils/Closure.h" #include "utils/AnimatedSpinner.h" -#include "utils/WebPopup.h" #include "utils/DpiScaler.h" #include "utils/Logger.h" +#include +#include +#include +#include +#include + namespace { static const int FADE_DURATION = 400; }; @@ -325,43 +320,10 @@ GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, QRect r = textRect; r.setY( textRect.y() + textRect.height() + 8 ); r.setHeight( 32 ); - m_buyButtonRects[ index ] = r; - QString text; - bool itemsAvailable = false; - if ( item->result() && - ( ( !item->result()->downloadFormats().isEmpty() && !DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() ) || - ( item->result()->downloadJob() && item->result()->downloadJob()->state() == DownloadJob::Finished ) ) ) + if( DownloadButton::drawPrimitive(painter, r, item->query(), m_hoveringOverBuyButton == index ) ) { - text = tr( "View in Finder" ); - } - else if ( item->query() && item->query()->numResults( true ) && !item->query()->results().first()->downloadFormats().isEmpty() ) - { - text = tr( "Download %1" ).arg( item->query()->results().first()->downloadFormats().first().extension.toUpper() ); - itemsAvailable = true; - } - else if ( item->query()->numResults( true ) && !item->query()->results().first()->purchaseUrl().isEmpty() ) - { - text = tr( "Buy" ); - } - - if ( !item->result() || !item->result()->downloadJob() || item->result()->downloadJob()->state() == DownloadJob::Finished ) - { - if ( !text.isEmpty() ) - DropDownButton::drawPrimitive( painter, r, text, m_hoveringOverBuyButton == index, itemsAvailable ); - else - m_buyButtonRects.remove( index ); - } - else - { - painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() ); - painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND ); - painter->drawRect( r.adjusted( 2, 2, -2, -2 ) ); - painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); - painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); - QRect fillp = r.adjusted( 3, 3, -3, -3 ); - fillp.setWidth( float(fillp.width()) * ( float(item->result()->downloadJob()->progressPercentage()) / 100.0 ) ); - painter->drawRect( fillp ); + m_buyButtonRects[ index ] = r; } } } @@ -623,25 +585,7 @@ GridItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const Q if ( hoveringBuyButton ) { - if ( event->type() == QEvent::MouseButtonRelease ) - { - PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) ); - if ( !item ) - return false; - - if ( item->query() && item->query()->numResults( true ) && !item->query()->results().first()->downloadFormats().isEmpty() ) - { - m_model->sourceModel()->setAllColumnsEditable( true ); - m_view->edit( index ); - m_model->sourceModel()->setAllColumnsEditable( false ); - return true; - } - else - { - WebPopup* popup = new WebPopup( item->query()->results().first()->purchaseUrl(), QSize( 400, 800 ) ); - connect( item->query()->results().first().data(), SIGNAL( destroyed() ), popup, SLOT( close() ) ); - } - } + return DownloadButton::handleEditorEvent( event, m_view, m_model, index ); } return false; @@ -871,63 +815,7 @@ GridItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& opt PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) ); Q_ASSERT( item ); - if ( item->result() && !item->result()->downloadFormats().isEmpty() && - !DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() ) - { - QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ) ).absolutePath() ) ); - } - else if ( item->result() && item->result()->downloadJob() && item->result()->downloadJob()->state() == DownloadJob::Finished ) - { - QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( item->result()->downloadJob()->localFile() ).absolutePath() ) ); - } - else if ( item->result() && - !item->result()->downloadFormats().isEmpty() && !item->result()->downloadJob() ) - { - QStringList formats; - foreach ( const DownloadFormat& format, item->result()->downloadFormats() ) - { - formats << tr( "Download %1" ).arg( format.extension.toUpper() ); - } - - DropDownButton* editor = new DropDownButton( parent ); - editor->addItems( formats ); - - NewClosure( editor, SIGNAL( clicked() ), - const_cast(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor ); - - NewClosure( editor, SIGNAL( activated( int ) ), - const_cast(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor ); - return editor; - } - - return 0; -} - - -void -GridItemDelegate::addDownloadJob( const QModelIndex& index, QWidget* editor ) -{ - PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) ); - Q_ASSERT( item ); - - m_view->closePersistentEditor( index ); - - DropDownButton* cb = static_cast< DropDownButton* >(editor); - if ( !item->result()->downloadFormats().isEmpty() ) - DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().at( cb->currentIndex() ) ) ); -} - - -void -GridItemDelegate::closeEditor( const QModelIndex& index, QWidget* editor ) -{ - PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) ); - Q_ASSERT( item ); - - m_view->closePersistentEditor( index ); - - DropDownButton* cb = static_cast< DropDownButton* >(editor); - editor->deleteLater(); + return DownloadButton::handleCreateEditor( parent, item->query(), m_view, index ); } @@ -936,7 +824,7 @@ GridItemDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewI { QStyledItemDelegate::updateEditorGeometry( editor, option, index ); - DropDownButton* comboBox = static_cast(editor); + DownloadButton* comboBox = static_cast(editor); comboBox->resize( option.rect.size() - QSize( 8, 0 ) ); comboBox->move( option.rect.x() + 4, option.rect.y() ); diff --git a/src/libtomahawk/playlist/GridItemDelegate.h b/src/libtomahawk/playlist/GridItemDelegate.h index d79648846..2fa8c47f1 100644 --- a/src/libtomahawk/playlist/GridItemDelegate.h +++ b/src/libtomahawk/playlist/GridItemDelegate.h @@ -87,9 +87,6 @@ private slots: void fadingFrameChanged( const QPersistentModelIndex& ); void fadingFrameFinished( const QPersistentModelIndex& ); - void closeEditor( const QModelIndex& index, QWidget* editor ); - void addDownloadJob( const QModelIndex& index, QWidget* editor ); - private: QTimeLine* createTimeline( QTimeLine::Direction direction, int startFrame = 0 ); void clearButtons(); diff --git a/src/libtomahawk/playlist/PlaylistItemDelegate.cpp b/src/libtomahawk/playlist/PlaylistItemDelegate.cpp index d3d7998c4..3f8b22b7d 100644 --- a/src/libtomahawk/playlist/PlaylistItemDelegate.cpp +++ b/src/libtomahawk/playlist/PlaylistItemDelegate.cpp @@ -20,15 +20,6 @@ #include "PlaylistItemDelegate.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include "Query.h" #include "Result.h" #include "Artist.h" @@ -36,8 +27,6 @@ #include "Source.h" #include "SourceList.h" -#include "DownloadManager.h" -#include "DownloadJob.h" #include "PlayableModel.h" #include "PlayableItem.h" #include "PlayableProxyModel.h" @@ -45,16 +34,22 @@ #include "ViewHeader.h" #include "ViewManager.h" -#include "widgets/DropDownButton.h" +#include "widgets/DownloadButton.h" #include "audio/AudioEngine.h" #include "utils/ImageRegistry.h" #include "utils/PixmapDelegateFader.h" #include "utils/Closure.h" #include "utils/TomahawkStyle.h" #include "utils/TomahawkUtilsGui.h" -#include "utils/WebPopup.h" #include "utils/Logger.h" +#include +#include +#include +#include +#include +#include + using namespace Tomahawk; @@ -125,63 +120,7 @@ PlaylistItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) ); Q_ASSERT( item ); - if ( /*index.column() == PlayableModel::Download &&*/ item->result() && !item->result()->downloadFormats().isEmpty() && - !DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() ) - { - QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ) ).absolutePath() ) ); - } - else if ( /*index.column() == PlayableModel::Download &&*/ item->result() && item->result()->downloadJob() && item->result()->downloadJob()->state() == DownloadJob::Finished ) - { - QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( item->result()->downloadJob()->localFile() ).absolutePath() ) ); - } - else if ( /*index.column() == PlayableModel::Download &&*/ item->result() && - !item->result()->downloadFormats().isEmpty() && !item->result()->downloadJob() ) - { - QStringList formats; - foreach ( const DownloadFormat& format, item->result()->downloadFormats() ) - { - formats << tr( "Download %1" ).arg( format.extension ); - } - - DropDownButton* editor = new DropDownButton( parent ); - editor->addItems( formats ); - - NewClosure( editor, SIGNAL( clicked() ), - const_cast(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor ); - - NewClosure( editor, SIGNAL( activated( int ) ), - const_cast(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor ); - return editor; - } - - return 0; -} - - -void -PlaylistItemDelegate::addDownloadJob( const QModelIndex& index, QWidget* editor ) -{ - PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) ); - Q_ASSERT( item ); - - m_view->closePersistentEditor( index ); - - DropDownButton* cb = static_cast< DropDownButton* >(editor); - if ( !item->result()->downloadFormats().isEmpty() ) - DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().at( cb->currentIndex() ) ) ); -} - - -void -PlaylistItemDelegate::closeEditor( const QModelIndex& index, QWidget* editor ) -{ - PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) ); - Q_ASSERT( item ); - - m_view->closePersistentEditor( index ); - - DropDownButton* cb = static_cast< DropDownButton* >(editor); - editor->deleteLater(); + return DownloadButton::handleCreateEditor( parent, item->query(), m_view, index ); } @@ -190,7 +129,7 @@ PlaylistItemDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionV { QStyledItemDelegate::updateEditorGeometry( editor, option, index ); - DropDownButton* comboBox = static_cast(editor); + DownloadButton* comboBox = static_cast(editor); comboBox->resize( option.rect.size() - QSize( 8, 0 ) ); comboBox->move( option.rect.x() + 4, option.rect.y() ); @@ -277,69 +216,7 @@ PlaylistItemDelegate::paintDetailed( QPainter* painter, const QStyleOptionViewIt else */ if ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download ) { - if ( item->result() && !item->result()->downloadFormats().isEmpty() ) - { - QStyleOptionComboBox optc; - optc.rect = opt.rect.adjusted( 4, 0, -4, 0 ); - optc.editable = false; - optc.currentText = tr( "Download %1" ).arg( item->result()->downloadFormats().first().extension ); - optc.palette = m_view->palette(); - - if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active ) - optc.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled; - else - optc.state = QStyle::State_Active | QStyle::State_Enabled; - - if ( !DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() ) - { - painter->setPen( opt.palette.text().color() ); - const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, opt.rect.width() - 3 ); - painter->drawText( opt.rect, text, textOption ); - } - else if ( !item->result()->downloadJob() ) - { - DropDownButton::drawPrimitive( painter, optc.rect, optc.currentText, hoveringOver() == index, true ); - -/* QApplication::style()->drawComplexControl( QStyle::CC_ComboBox, &optc, painter, 0 ); - optc.rect.adjust( 4, 0, 0, 0 ); - QApplication::style()->drawControl( QStyle::CE_ComboBoxLabel, &optc, painter, 0 );*/ - } - else - { - if ( item->result()->downloadJob()->state() == DownloadJob::Finished ) - { - painter->setPen( opt.palette.text().color() ); - const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, opt.rect.width() - 3 ); - painter->drawText( opt.rect, text, textOption ); - } - else - { - painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() ); - painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND ); - painter->drawRect( optc.rect.adjusted( 2, 2, -2, -2 ) ); - painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); - painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); - QRect fillp = optc.rect.adjusted( 3, 3, -3, -3 ); - fillp.setWidth( float(fillp.width()) * ( float(item->result()->downloadJob()->progressPercentage()) / 100.0 ) ); - painter->drawRect( fillp ); - -/* QStyleOptionProgressBarV2 optp; - optp.rect = optc.rect; - optp.minimum = 0; - optp.maximum = 100; - optp.progress = item->result()->downloadJob()->progressPercentage(); - optp.palette = m_view->palette(); - optp.palette.setColor( QPalette::Highlight, QColor( "#E61878" ) ); - - if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active ) - optp.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled; - else - optp.state = QStyle::State_Active | QStyle::State_Enabled; - - QApplication::style()->drawControl( QStyle::CE_ProgressBar, &optp, painter, 0 );*/ - } - } - } + DownloadButton::drawPrimitive( painter, opt.rect.adjusted( 4, 0, -4, 0 ), item->query(), hoveringOver() == index ); } else if ( item->isPlaying() ) { @@ -657,67 +534,14 @@ PlaylistItemDelegate::drawTrack( QPainter* painter, const QStyleOptionViewItem& stateWidth += r.width() + 16; } - - if ( hasOnlineResults && !item->query()->results().first()->purchaseUrl().isEmpty() ) - { - QRect r = stateRect.adjusted( -stateWidth -144, 6, 0, -6 ); - r.setWidth( 144 ); - DropDownButton::drawPrimitive( painter, r, tr( "Buy" ), m_hoveringOverBuyButton == index, false ); - - m_buyButtonRects[ index ] = r; - - stateWidth += r.width() + 16; - } } - if ( hasOnlineResults && !item->query()->results().first()->downloadFormats().isEmpty() ) + QRect downloadButtonRect = stateRect.adjusted( -stateWidth -144, 6, 0, -6 ); + downloadButtonRect.setWidth( 144 ); + stateWidth += downloadButtonRect.width() + 16; + if ( DownloadButton::drawPrimitive( painter, downloadButtonRect, item->query(), m_hoveringOverDownloadButton == index ) ) { - painter->save(); - QStyleOptionComboBox optc; - optc.rect = stateRect.adjusted( -stateWidth -144, 6, 0, -6 ); - optc.rect.setWidth( 144 ); - m_downloadDropDownRects[ index ] = optc.rect; - stateWidth += optc.rect.width() + 16; - optc.editable = false; - optc.currentText = tr( "Download %1" ).arg( item->query()->results().first()->downloadFormats().first().extension.toUpper() ); - optc.palette = m_view->palette(); - - if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active ) - optc.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled; - else - optc.state = QStyle::State_Active | QStyle::State_Enabled; - - if ( !DownloadManager::instance()->localFileForDownload( item->query()->results().first()->downloadFormats().first().url.toString() ).isEmpty() ) - { - painter->setPen( optc.palette.text().color() ); - const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, optc.rect.width() - 3 ); - painter->drawText( optc.rect, text, QTextOption( Qt::AlignCenter ) ); - } - else if ( !item->query()->results().first()->downloadJob() ) - { - DropDownButton::drawPrimitive( painter, optc.rect, optc.currentText, hoveringOver() == index, true ); - } - else - { - if ( item->query()->results().first()->downloadJob()->state() == DownloadJob::Finished ) - { - painter->setPen( optc.palette.text().color() ); - const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, optc.rect.width() - 3 ); - painter->drawText( optc.rect, text, QTextOption( Qt::AlignCenter ) ); - } - else - { - painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() ); - painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND ); - painter->drawRect( optc.rect.adjusted( 2, 2, -2, -2 ) ); - painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); - painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); - QRect fillp = optc.rect.adjusted( 3, 3, -3, -3 ); - fillp.setWidth( float(fillp.width()) * ( float(item->query()->results().first()->downloadJob()->progressPercentage()) / 100.0 ) ); - painter->drawRect( fillp ); - } - } - painter->restore(); + m_downloadDropDownRects[ index ] = downloadButtonRect; } const int remWidth = r.width() - numberWidth - durationWidth; @@ -835,7 +659,6 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con bool hoveringArtist = false; bool hoveringInfo = false; bool hoveringLove = false; - bool hoveringBuy = false; bool hoveringDownloadDropDown = false; Tomahawk::source_ptr hoveredAvatar; QRect hoveredAvatarRect; @@ -858,12 +681,6 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con const QMouseEvent* ev = static_cast< QMouseEvent* >( event ); hoveringLove = loveRect.contains( ev->pos() ); } - if ( m_buyButtonRects.contains( index ) ) - { - const QRect buyRect = m_buyButtonRects[ index ]; - const QMouseEvent* ev = static_cast< QMouseEvent* >( event ); - hoveringBuy = buyRect.contains( ev->pos() ); - } if ( m_downloadDropDownRects.contains( index ) ) { const QRect downloadDropDownRect = m_downloadDropDownRects[ index ]; @@ -887,7 +704,7 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con if ( event->type() == QEvent::MouseMove ) { - if ( hoveringInfo || hoveringLove || hoveringArtist || hoveringBuy ) + if ( hoveringInfo || hoveringLove || hoveringArtist || hoveringDownloadDropDown ) m_view->setCursor( Qt::PointingHandCursor ); else m_view->setCursor( Qt::ArrowCursor ); @@ -911,19 +728,19 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con emit updateIndex( m_hoveringOverArtist ); m_hoveringOverArtist = QModelIndex(); } - if ( hoveringBuy && m_hoveringOverBuyButton != index ) + if ( hoveringDownloadDropDown && m_hoveringOverDownloadButton != index ) { - QPersistentModelIndex ti = m_hoveringOverBuyButton; - m_hoveringOverBuyButton = index; + QPersistentModelIndex ti = m_hoveringOverDownloadButton; + m_hoveringOverDownloadButton = index; PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( ti ) ); item->requestRepaint(); - emit updateIndex( m_hoveringOverBuyButton ); + emit updateIndex( m_hoveringOverDownloadButton ); } - if ( !hoveringBuy && m_hoveringOverBuyButton.isValid() ) + if ( !hoveringDownloadDropDown && m_hoveringOverDownloadButton.isValid() ) { - QPersistentModelIndex ti = m_hoveringOverBuyButton; - m_hoveringOverBuyButton = QModelIndex(); + QPersistentModelIndex ti = m_hoveringOverDownloadButton; + m_hoveringOverDownloadButton = QModelIndex(); PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( ti ) ); item->requestRepaint(); @@ -957,10 +774,10 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con { item->query()->queryTrack()->setLoved( !item->query()->queryTrack()->loved() ); } - else if ( hoveringBuy ) + else if ( hoveringDownloadDropDown || ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download ) ) { - WebPopup* popup = new WebPopup( item->query()->results().first()->purchaseUrl(), QSize( 400, 800 ) ); - connect( item->query()->results().first().data(), SIGNAL( destroyed() ), popup, SLOT( close() ) ); + if ( DownloadButton::handleEditorEvent( event , m_view, m_model, index ) ) + return true; } else if ( hoveringInfo ) { @@ -996,13 +813,6 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con } } } - else if ( ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download ) || hoveringDownloadDropDown ) - { - m_model->sourceModel()->setAllColumnsEditable( true ); - m_view->edit( index ); - m_model->sourceModel()->setAllColumnsEditable( false ); - return true; - } event->accept(); return true; @@ -1022,10 +832,9 @@ PlaylistItemDelegate::resetHoverIndex() m_hoveringOver = QModelIndex(); m_hoveringOverArtist = QModelIndex(); - m_hoveringOverBuyButton = QModelIndex(); + m_hoveringOverDownloadButton = QModelIndex(); m_infoButtonRects.clear(); m_loveButtonRects.clear(); - m_buyButtonRects.clear(); m_artistNameRects.clear(); QModelIndex itemIdx = m_model->mapToSource( idx ); diff --git a/src/libtomahawk/playlist/PlaylistItemDelegate.h b/src/libtomahawk/playlist/PlaylistItemDelegate.h index 4f3dad0ea..792731ede 100644 --- a/src/libtomahawk/playlist/PlaylistItemDelegate.h +++ b/src/libtomahawk/playlist/PlaylistItemDelegate.h @@ -57,8 +57,6 @@ signals: private slots: void doUpdateIndex( const QPersistentModelIndex& index ); - void closeEditor( const QModelIndex& index, QWidget* editor ); - void addDownloadJob( const QModelIndex& index, QWidget* editor ); protected: void prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, PlayableItem* item ) const; @@ -116,13 +114,12 @@ private: mutable QHash< QPersistentModelIndex, QSharedPointer< Tomahawk::PixmapDelegateFader > > m_pixmaps; mutable QHash< QPersistentModelIndex, QRect > m_infoButtonRects; mutable QHash< QPersistentModelIndex, QRect > m_loveButtonRects; - mutable QHash< QPersistentModelIndex, QRect > m_buyButtonRects; mutable QHash< QPersistentModelIndex, QRect > m_downloadDropDownRects; mutable QHash< QPersistentModelIndex, QRect > m_artistNameRects; mutable QHash< QPersistentModelIndex, QHash< Tomahawk::source_ptr, QRect > > m_avatarBoxRects; QPersistentModelIndex m_hoveringOver; QPersistentModelIndex m_hoveringOverArtist; - QPersistentModelIndex m_hoveringOverBuyButton; + QPersistentModelIndex m_hoveringOverDownloadButton; mutable QPersistentModelIndex m_nowPlaying; TrackView* m_view; diff --git a/src/libtomahawk/widgets/DownloadButton.cpp b/src/libtomahawk/widgets/DownloadButton.cpp new file mode 100644 index 000000000..a85b8100d --- /dev/null +++ b/src/libtomahawk/widgets/DownloadButton.cpp @@ -0,0 +1,282 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2015, Christian Muehlhaeuser + * Copyright 2016, Dominik Schmidt + * + * 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 . + */ + +#include "DownloadButton.h" + +#include "Artist.h" +#include "Album.h" +#include "Result.h" +#include "DownloadManager.h" +#include "utils/TomahawkStyle.h" +#include "utils/WebPopup.h" +#include "utils/Logger.h" + +#include +#include +#include +#include + +using namespace Tomahawk; + + +DownloadButton::DownloadButton( const Tomahawk::query_ptr& query, QWidget* parent, QAbstractItemView* view, const QModelIndex& index ) + : DropDownButton( parent ) + , m_view( view ) + , m_index( index ) +{ + init(); + + setQuery( query ); +} + + +DownloadButton::DownloadButton( QWidget* parent ) + : DropDownButton( parent ) +{ + init(); +} + + +void +DownloadButton::init() +{ + connect( this, SIGNAL( clicked() ), this, SLOT( addDownloadJob() ) ); + connect( this, SIGNAL( activated( int ) ), this, SLOT( addDownloadJob() ) ); +} + + +DownloadButton::~DownloadButton() +{ +} + + +void +DownloadButton::setQuery( const query_ptr& query ) +{ + if ( !m_query.isNull() ) + { + m_query->disconnect( this ); + } + if ( !m_result.isNull() ) + { + m_result->disconnect( this ); + } + + clear(); + m_result.clear(); + + m_query = query; + + if ( query.isNull() ) + return; + + Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr(); + if ( result.isNull() ) + return; + + QStringList formats; + foreach ( const DownloadFormat& format, result->downloadFormats() ) + { + formats << QObject::tr( "Download %1" ).arg( format.extension.toUpper() ); + } + + addItems( formats ); +} + +void +DownloadButton::addDownloadJob() +{ + if ( m_query.isNull() ) + return; + + Tomahawk::result_ptr result = m_query->numResults( true ) ? m_query->results().first() : Tomahawk::result_ptr(); + if ( result.isNull() ) + return; + + if ( handleClickPreDownload( m_query ) ) + return; + + if ( !result->downloadFormats().isEmpty() ) + { + if ( m_view && m_index.isValid() ) + { + m_view->closePersistentEditor( m_index ); + } + else + { + m_result = result; + connect( result.data(), SIGNAL( updated() ), SLOT( update() ) ); + connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( update() ) ); + } + + DownloadManager::instance()->addJob( result->toDownloadJob( result->downloadFormats().at( currentIndex() ) ) ); + } + else + { + handleClickPostDownload( m_query ); + } +} + + +void +DownloadButton::paintEvent( QPaintEvent* event ) +{ + QPainter p( this ); + setupPainter( &p ); + + if ( DownloadButton::drawPrimitive( &p, contentsRect(), m_query, m_hovering ) ) + setCursor( Qt::PointingHandCursor ); + else + setCursor( Qt::ArrowCursor ); +} + + +bool +DownloadButton::drawPrimitive( QPainter* painter, const QRect& rect, const Tomahawk::query_ptr& query, bool hovering ) +{ + if ( query.isNull() ) + return false; + + Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr(); + if ( result.isNull() ) + return false; + + if ( result->downloadJob() && result->downloadJob()->state() != DownloadJob::Finished ) + { + // if downloadJob exists and is not finished, paint a progress bar + painter->save(); + painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() ); + painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND ); + painter->drawRect( rect.adjusted( 2, 2, -2, -2 ) ); + painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); + painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND ); + QRect fillp = rect.adjusted( 3, 3, -3, -3 ); + fillp.setWidth( float(fillp.width()) * ( float( result->downloadJob()->progressPercentage() ) / 100.0 ) ); + painter->drawRect( fillp ); + painter->restore(); + } + else + { + QString text; + bool itemsAvailable = false; + if ( result && + ( ( !result->downloadFormats().isEmpty() && !DownloadManager::instance()->localFileForDownload( result->downloadFormats().first().url.toString() ).isEmpty() ) || + ( result->downloadJob() && result->downloadJob()->state() == DownloadJob::Finished ) ) ) + { + text = QObject::tr( "View in Finder" ); + } + else if ( !result->downloadFormats().isEmpty() ) + { + text = tr( "Download %1" ).arg( query->results().first()->downloadFormats().first().extension.toUpper() ); + itemsAvailable = true; + } + else if ( !result->purchaseUrl().isEmpty() ) + { + text = tr( "Buy" ); + } + + if ( !text.isEmpty() ) + DropDownButton::drawPrimitive( painter, rect, text, hovering, itemsAvailable ); + else + { + // this result can neither be bought nor downloaded + return false; + } + } + + return true; +} + +bool +DownloadButton::handleEditorEvent(QEvent* event , QAbstractItemView* view, PlayableProxyModel* model, const QModelIndex& index) +{ + if ( event->type() == QEvent::MouseButtonRelease ) + { + PlayableItem* item = model->sourceModel()->itemFromIndex( model->mapToSource( index ) ); + if ( !item && ! item->query() ) + return false; + + if ( handleClickPreDownload( item->query() ) ) + return true; + + if( item->query()->numResults( true ) && !item->query()->results().first()->downloadFormats().isEmpty() ) + { + model->sourceModel()->setAllColumnsEditable( true ); + view->edit( index ); + model->sourceModel()->setAllColumnsEditable( false ); + return true; + } + + return handleClickPostDownload( item->query() ); + } + + return false; +} + + +bool +DownloadButton::handleClickPreDownload( const Tomahawk::query_ptr& query ) +{ + // view in folder + if ( !DownloadManager::instance()->localUrlForDownload( query ).isEmpty() ) + { + QDesktopServices::openUrl( DownloadManager::instance()->localUrlForDownload( query ) ); + return true; + } + + // download in progress + Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr(); + if ( result && result->downloadJob() && result->downloadJob()->state() != DownloadJob::Finished ) + { + // do nothing, handled + return true; + } + + return false; +} + + +bool +DownloadButton::handleClickPostDownload( const Tomahawk::query_ptr& query ) +{ + // handle buy click + Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr(); + if ( result && !result->purchaseUrl().isEmpty() ) + { + WebPopup* popup = new WebPopup( result->purchaseUrl(), QSize( 400, 800 ) ); + connect( result.data(), SIGNAL( destroyed() ), popup, SLOT( close() ) ); + return true; + } + + return false; +} + + +QWidget* +DownloadButton::handleCreateEditor( QWidget* parent, const query_ptr& query, QAbstractItemView* view, const QModelIndex& index ) +{ + Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr(); + if ( result && !result->downloadFormats().isEmpty() && !result->downloadJob() ) + { + return new DownloadButton( query, parent, view, index ); + } + + return 0; +} + diff --git a/src/libtomahawk/widgets/DownloadButton.h b/src/libtomahawk/widgets/DownloadButton.h new file mode 100644 index 000000000..192578298 --- /dev/null +++ b/src/libtomahawk/widgets/DownloadButton.h @@ -0,0 +1,61 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2015, Christian Muehlhaeuser + * Copyright 2016, Dominik Schmidt + * + * 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 . + */ + +#ifndef DOWNLOADBUTTON_H +#define DOWNLOADBUTTON_H + +#include "DropDownButton.h" +#include "playlist/PlayableProxyModel.h" + +#include "Typedefs.h" +#include "DllMacro.h" + +class DLLEXPORT DownloadButton : public DropDownButton +{ +Q_OBJECT + +public: + explicit DownloadButton( const Tomahawk::query_ptr& query, QWidget* parent = nullptr, QAbstractItemView* view = nullptr, const QModelIndex& index = QModelIndex() ); + explicit DownloadButton( QWidget* parent = nullptr ); + virtual ~DownloadButton(); + + void setQuery( const Tomahawk::query_ptr& query ); + + static bool drawPrimitive( QPainter* p, const QRect& rect, const Tomahawk::query_ptr& query, bool hovering ); + static bool handleEditorEvent( QEvent* event, QAbstractItemView* view, PlayableProxyModel* model, const QModelIndex& index ); + static QWidget* handleCreateEditor( QWidget* parent, const Tomahawk::query_ptr& query , QAbstractItemView* view, const QModelIndex& index ); + +protected: + void paintEvent( QPaintEvent* event ); + +private slots: + void addDownloadJob(); + +private: + static bool handleClickPreDownload( const Tomahawk::query_ptr& query ); + static bool handleClickPostDownload( const Tomahawk::query_ptr& query ); + void init(); + + Tomahawk::query_ptr m_query; + Tomahawk::result_ptr m_result; + QAbstractItemView* m_view; + QModelIndex m_index; +}; + +#endif // DOWNLOADBUTTON_H diff --git a/src/libtomahawk/widgets/DropDownButton.h b/src/libtomahawk/widgets/DropDownButton.h index 48de535d4..aeb10ca6e 100644 --- a/src/libtomahawk/widgets/DropDownButton.h +++ b/src/libtomahawk/widgets/DropDownButton.h @@ -47,7 +47,7 @@ protected: private slots: -private: +protected: static void setupPainter( QPainter* p ); bool m_hovering;