QWidget*
PlaylistItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    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<PlaylistItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );

        NewClosure( editor, SIGNAL( activated( int ) ),
                    const_cast<PlaylistItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );
        return editor;
    }
Tomahawk::result_ptr
PlayableProxyModelPlaylistInterface::resultAt( qint64 index ) const
{
    if ( m_proxyModel.isNull() )
        return result_ptr();

    PlayableItem* item = reinterpret_cast<PlayableItem*>( (void*)index );
    if ( item && item->result() )
        return item->result();

    return result_ptr();
}
Example #3
0
void
CollectionViewPage::onDownloadAll()
{
    for ( int i = 0; i < m_flatModel->rowCount( QModelIndex() ); i++ )
    {
        PlayableItem* item = m_flatModel->itemFromIndex( m_flatModel->index( i, 0, QModelIndex() ) );
        if ( !item )
            continue;

        if ( !item->result()->downloadFormats().isEmpty() )
            DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().first() ) );
    }
}
Example #4
0
QSize
TreeItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    QSize size = QStyledItemDelegate::sizeHint( option, index );

    if ( index.isValid() )
    {
        PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
        if ( item )
        {
            if ( item->album() )
            {
                size.setHeight( option.fontMetrics.height() * 3 );
                return size;
            }
            else if ( item->query() || item->result() )
            {
                size.setHeight( option.fontMetrics.height() * 1.6 );
                return size;
            }
        }
    }
    
    // artist per default
    size.setHeight( option.fontMetrics.height() * 4 );
    return size;
}
Example #5
0
void
ColumnView::onCustomContextMenu( const QPoint& pos )
{
    m_contextMenu->clear();

    QModelIndex idx = indexAt( pos );
    idx = idx.sibling( idx.row(), 0 );
    m_contextMenuIndex = idx;

    if ( !idx.isValid() )
        return;

    QList<query_ptr> queries;
    QList<artist_ptr> artists;
    QList<album_ptr> albums;

    QModelIndexList indexes = selectedIndexes();
    if ( !indexes.contains( idx ) )
    {
        indexes.clear();
        indexes << idx;
    }

    foreach ( const QModelIndex& index, indexes )
    {
        if ( index.column() || indexes.contains( index.parent() ) )
            continue;

        PlayableItem* item = m_proxyModel->itemFromIndex( m_proxyModel->mapToSource( index ) );

        if ( item && !item->result().isNull() )
            queries << item->result()->toQuery();
        else if ( item && !item->query().isNull() )
            queries << item->query();
        if ( item && !item->artist().isNull() )
            artists << item->artist();
        if ( item && !item->album().isNull() )
            albums << item->album();
    }

    m_contextMenu->setQueries( queries );
    m_contextMenu->setArtists( artists );
    m_contextMenu->setAlbums( albums );
    m_contextMenu->setPlaylistInterface( proxyModel()->playlistInterface() );

    m_contextMenu->exec( viewport()->mapToGlobal( pos ) );
}
Example #6
0
void
ArtistView::onItemActivated( const QModelIndex& index )
{
    PlayableItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( index ) );
    if ( item )
    {
        if ( !item->artist().isNull() )
            ViewManager::instance()->show( item->artist() );
        else if ( !item->album().isNull() )
            ViewManager::instance()->show( item->album() );
        else if ( !item->result().isNull() && item->result()->isOnline() )
        {
            m_model->setCurrentItem( item->index );
            AudioEngine::instance()->playItem( m_proxyModel->playlistInterface(), item->result() );
        }
    }
}
Example #7
0
void
ContextView::onDownloadAll()
{
    for ( int i = 0; i < m_trackView->proxyModel()->rowCount( QModelIndex() ); i++ )
    {
        PlayableItem* item = m_trackView->proxyModel()->itemFromIndex( m_trackView->proxyModel()->mapToSource( m_trackView->proxyModel()->index( i, 0, QModelIndex() ) ) );
        if ( !item || !item->query() || !item->query()->results().count() )
            continue;
        if ( !item->query()->results().first()->downloadFormats().count() )
            continue;

        if ( !DownloadManager::instance()->localFileForDownload( item->query()->results().first()->downloadFormats().first().url.toString() ).isEmpty() )
            continue;
        if ( !item->result()->downloadFormats().isEmpty() )
            DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().first() ) );
    }
}
Example #8
0
void
TreeView::currentChanged( const QModelIndex& current, const QModelIndex& previous )
{
    QTreeView::currentChanged( current, previous );

    if ( !m_updateContextView )
        return;

    PlayableItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( current ) );
    if ( item )
    {
        if ( !item->result().isNull() )
            ViewManager::instance()->context()->setQuery( item->result()->toQuery() );
        else if ( !item->artist().isNull() )
            ViewManager::instance()->context()->setArtist( item->artist() );
        else if ( !item->album().isNull() )
            ViewManager::instance()->context()->setAlbum( item->album() );
        else if ( !item->query().isNull() )
            ViewManager::instance()->context()->setQuery( item->query() );
    }
}
Example #9
0
void
CollectionViewPage::onDownloadAll()
{
    if ( DownloadManager::instance()->state() == DownloadManager::Running )
    {
        DownloadManager::instance()->cancelAll();
    }
    else
    {
        for ( int i = 0; i < m_trackView->proxyModel()->rowCount( QModelIndex() ); i++ )
        {
            PlayableItem* item = m_trackView->proxyModel()->itemFromIndex( m_trackView->proxyModel()->mapToSource( m_trackView->proxyModel()->index( i, 0, QModelIndex() ) ) );
            if ( !item )
                continue;

            QList< DownloadFormat > formats = item->query()->results().first()->downloadFormats();
            if ( formats.isEmpty() || !DownloadManager::instance()->localFileForDownload( formats.first().url.toString() ).isEmpty() )
                continue;

            if ( !item->result()->downloadFormats().isEmpty() )
                DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().first() ) );
        }
    }
}
bool
TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
{
    PlayableItem* item = sourceModel()->itemFromIndex( sourceModel()->index( sourceRow, 0, sourceParent ) );
    Q_ASSERT( item );

    //FIXME: m_cache lookup is broken
    if ( /*m_model->mode() == Tomahawk::DatabaseMode &&*/ !item->query().isNull() )
    {
/*        QList< Tomahawk::query_ptr > rl = m_cache.values( sourceParent );
        foreach ( const Tomahawk::query_ptr& cachedQuery, rl )
        {
            if ( cachedQuery.isNull() )
                continue;

            if ( cachedQuery->track()->track() == item->query()->track()->track() &&
               ( cachedQuery->track()->albumpos() == item->query()->track()->albumpos() || cachedQuery->track()->albumpos() == 0 ) )
            {
                return ( cachedQuery.data() == item->query().data() );
            }
        }*/

        for ( int i = 0; i < sourceModel()->rowCount( sourceParent ); i++ )
        {
            if ( i == sourceRow )
                continue;

            PlayableItem* ti = sourceModel()->itemFromIndex( sourceModel()->index( i, 0, sourceParent ) );
            if ( ti && ti->name() == item->name() && !ti->query().isNull() )
            {
                if ( ti->query()->track()->albumpos() == item->query()->track()->albumpos() || ti->query()->track()->albumpos() == 0 || item->query()->track()->albumpos() == 0 )
                {
                    if ( item->result().isNull() )
                        return false;

                    if ( !ti->result().isNull() )
                    {
                        if ( !item->result()->isOnline() && ti->result()->isOnline() )
                            return false;

                        if ( ( item->result()->resolvedByCollection().isNull() || !item->result()->resolvedByCollection()->isLocal() ) &&
                             !ti->result()->resolvedByCollection().isNull() && ti->result()->resolvedByCollection()->isLocal() )
                        {
                            return false;
                        }
                    }
                }
            }
        }
    }

    bool accepted = false;
    if ( m_filter.isEmpty() )
        accepted = true;
    else if ( !item->artist().isNull() )
        accepted = m_artistsFilter.contains( item->artist() );
    else if ( !item->album().isNull() )
        accepted = m_albumsFilter.contains( item->album() );

    if ( !accepted )
    {
        QStringList sl = m_filter.split( " ", QString::SkipEmptyParts );
        foreach( const QString& s, sl )
        {
            if ( !item->name().contains( s, Qt::CaseInsensitive ) &&
                 !item->albumName().contains( s, Qt::CaseInsensitive ) &&
                 !item->artistName().contains( s, Qt::CaseInsensitive ) )
            {
                return false;
            }
        }
    }
Example #11
0
void
TreeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
    if ( !item )
        return;

    QString text;
    if ( !item->artist().isNull() )
    {
        text = item->artist()->name();
    }
    else if ( !item->album().isNull() )
    {
        text = item->album()->name();
    }
    else if ( !item->result().isNull() || !item->query().isNull() )
    {
        float opacity = item->result().isNull() ? 0.0 : item->result()->score();
        opacity = qMax( (float)0.3, opacity );
        QColor textColor = TomahawkUtils::alphaBlend( option.palette.color( QPalette::Foreground ), option.palette.color( QPalette::Background ), opacity );

        {
            QStyleOptionViewItemV4 o = option;
            initStyleOption( &o, QModelIndex() );

            painter->save();
            o.palette.setColor( QPalette::Text, textColor );

            if ( o.state & QStyle::State_Selected && o.state & QStyle::State_Active )
            {
                o.palette.setColor( QPalette::Text, o.palette.color( QPalette::HighlightedText ) );
            }

            if ( item->isPlaying() )
            {
                o.palette.setColor( QPalette::Highlight, o.palette.color( QPalette::Mid ) );
                if ( o.state & QStyle::State_Selected )
                    o.palette.setColor( QPalette::Text, textColor );
                o.state |= QStyle::State_Selected;
            }

            int oldX = 0;
            if ( m_view->header()->visualIndex( index.column() ) == 0 )
            {
                oldX = o.rect.x();
                o.rect.setX( 0 );
            }
            qApp->style()->drawControl( QStyle::CE_ItemViewItem, &o, painter );
            if ( oldX > 0 )
                o.rect.setX( oldX );

            {
                QRect r = o.rect.adjusted( 3, 0, 0, 0 );

                // Paint Now Playing Speaker Icon
                if ( item->isPlaying() && m_view->header()->visualIndex( index.column() ) == 0 )
                {
                    r.adjust( 0, 0, 0, -3 );
                    QRect npr = r.adjusted( 3, 1, 18 - r.width(), 1 );
                    painter->drawPixmap( npr, TomahawkUtils::defaultPixmap( TomahawkUtils::NowPlayingSpeaker, TomahawkUtils::Original, npr.size() ) );
                    r.adjust( 25, 0, 0, 3 );
                }

                painter->setPen( o.palette.text().color() );

                QTextOption to( Qt::AlignVCenter );
                QString text = painter->fontMetrics().elidedText( index.data().toString(), Qt::ElideRight, r.width() - 3 );
                painter->drawText( r.adjusted( 0, 1, 0, 0 ), text, to );
            }
            painter->restore();
        }

        return;
    }
    else
        return;

    if ( text.trimmed().isEmpty() )
        text = tr( "Unknown" );

    QStyleOptionViewItemV4 opt = option;
    initStyleOption( &opt, QModelIndex() );
    qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );

    if ( option.state & QStyle::State_Selected )
    {
        opt.palette.setColor( QPalette::Text, opt.palette.color( QPalette::HighlightedText ) );
    }

    if ( index.column() > 0 )
        return;

    painter->save();
    painter->setRenderHint( QPainter::Antialiasing );
    painter->setPen( opt.palette.color( QPalette::Text ) );

    QRect r = option.rect.adjusted( 4, 4, -option.rect.width() + option.rect.height() - 4, -4 );
//    painter->drawPixmap( r, QPixmap( RESPATH "images/cover-shadow.png" ) );

    if ( !m_pixmaps.contains( index ) )
    {
        if ( !item->album().isNull() )
        {
            m_pixmaps.insert( index, QSharedPointer< Tomahawk::PixmapDelegateFader >( new Tomahawk::PixmapDelegateFader( item->album(), r.size(), TomahawkUtils::ScaledCover, false ) ) );
            _detail::Closure* closure = NewClosure( m_pixmaps[ index ], SIGNAL( repaintRequest() ), const_cast<TreeItemDelegate*>(this), SLOT( doUpdateIndex( const QPersistentModelIndex& ) ), QPersistentModelIndex( index ) );
            closure->setAutoDelete( false );
        }
        else if ( !item->artist().isNull() )
Example #12
0
void
GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
    if ( !item || !index.isValid() )
        return;

    QStyleOptionViewItemV4 opt = option;
    initStyleOption( &opt, QModelIndex() );
//    qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );

    QRect r = option.rect;
    r.setHeight( r.width() );

    QString top, bottom;
    if ( !item->album().isNull() )
    {
        top = item->album()->name();

        if ( !item->album()->artist().isNull() )
            bottom = item->album()->artist()->name();
    }
    else if ( !item->artist().isNull() )
    {
        top = item->artist()->name();
    }
    else if ( !item->query().isNull() )
    {
        top = item->query()->track()->track();
        bottom = item->query()->track()->artist();
    }
    else
    {
        return;
    }

    painter->save();
    painter->setRenderHint( QPainter::TextAntialiasing );

    if ( !m_covers.contains( index ) )
    {
        if ( !item->album().isNull() )
        {
            m_covers.insert( index, QSharedPointer< Tomahawk::PixmapDelegateFader >( new Tomahawk::PixmapDelegateFader( item->album(), r.size(), TomahawkUtils::Original, false ) ) );
        }
        else if ( !item->artist().isNull() )
        {
            m_covers.insert( index, QSharedPointer< Tomahawk::PixmapDelegateFader >( new Tomahawk::PixmapDelegateFader( item->artist(), r.size(), TomahawkUtils::Original, false ) ) );
        }
        else
        {
            m_covers.insert( index, QSharedPointer< Tomahawk::PixmapDelegateFader >( new Tomahawk::PixmapDelegateFader( item->query(), r.size(), TomahawkUtils::Original, false ) ) );
        }

        NewClosure( m_covers[ index ], SIGNAL( repaintRequest() ),
                    const_cast<GridItemDelegate*>(this), SLOT( doUpdateIndex( QPersistentModelIndex ) ), QPersistentModelIndex( index ) )->setAutoDelete( false );
    }

    QSharedPointer< Tomahawk::PixmapDelegateFader > fader = m_covers[ index ];
    if ( fader->size() != r.size() )
        fader->setSize( r.size() );
    const QPixmap cover = fader->currentPixmap();

    qreal opacity = -1.0;
    qreal pct = -1.0;
    if ( m_hoverFaders.contains( index ) )
    {
        pct = ( m_hoverFaders[ index ]->currentFrame() / 100.0 );
        opacity = 1.0 - pct * 0.70;
    }
    else if ( m_hoverIndex == index )
    {
        opacity = 0.3;
        pct = 1.0;
    }
    if ( opacity > -1.0 )
    {
        painter->save();

        const int cropIn = pct * ( (qreal)cover.width() * 0.10 );
        const QRect crop = cover.rect().adjusted( cropIn, cropIn, -cropIn, -cropIn );

        painter->drawPixmap( r, cover.copy( crop ).scaled( r.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );

        painter->setOpacity( 1.0 - opacity );
        painter->setPen( Qt::transparent );
        painter->setBrush( Qt::black );
        painter->drawRect( r );

        painter->restore();
    }
    else
    {
        painter->drawPixmap( r, cover );
    }

    QTextOption to;
    to.setWrapMode( QTextOption::NoWrap );

    QString text;
    QRect textRect = option.rect.adjusted( 0, r.height() + m_margin / 4, 0, -m_margin / 2 + m_margin / 8 );
    bool oneLiner = false;
    if ( bottom.isEmpty() )
        oneLiner = true;

    painter->setPen( TomahawkStyle::SELECTION_FOREGROUND );
    painter->setFont( m_font );
    painter->setPen( Qt::black );
    painter->setOpacity( 0.8 );

    if ( m_showPosition )
    {
        painter->save();

        if ( !oneLiner )
        {
            QFont figFont = m_font;
            figFont.setPixelSize( textRect.height() - m_margin / 8 );
            painter->setFont( figFont );
        }

        const QString fig = QString::number( index.row() + 1 );
        painter->drawText( textRect, fig, QTextOption( Qt::AlignLeft | Qt::AlignVCenter ) );

        textRect.adjust( painter->fontMetrics().boundingRect( textRect, Qt::AlignLeft | Qt::AlignVCenter, fig ).width() + m_margin / 4, 0, 0, 0 );
        painter->restore();
    }

    if ( oneLiner )
    {
        // If the user is hovering over an artist rect, draw a background so they knows it's clickable
        if ( m_hoveringOverArtist == index )
        {
            QFont f = painter->font();
            f.setUnderline( true );
            painter->setFont( f );
        }

        to.setAlignment( Qt::AlignLeft | Qt::AlignTop );
        text = painter->fontMetrics().elidedText( top, Qt::ElideRight, textRect.width() - m_margin / 4 );
        painter->drawText( textRect, text, to );

        // Calculate rect of artist on-hover button click area
        m_artistNameRects[ index ] = painter->fontMetrics().boundingRect( textRect, Qt::AlignLeft | Qt::AlignTop, text );
    }
    else
    {
        painter->save();
        // If the user is hovering over an album rect, underline the album name
        if ( m_hoveringOverAlbum == index )
        {
            QFont f = painter->font();
            f.setUnderline( true );
            painter->setFont( f );
        }

        if ( m_showBuyButtons && !item->query().isNull() )
        {
            textRect.adjust( 0, 0, 0, -40 );
        }

        to.setAlignment( Qt::AlignLeft | Qt::AlignTop );
        text = painter->fontMetrics().elidedText( top, Qt::ElideRight, textRect.width() - m_margin / 4 );
        painter->drawText( textRect, text, to );

        if ( item->album() )
        {
            // Calculate rect of album on-hover button click area
            m_albumNameRects[ index ] = painter->fontMetrics().boundingRect( textRect, Qt::AlignLeft | Qt::AlignTop, text );
        }
        painter->restore();

        painter->save();
        painter->setOpacity( 0.6 );
        painter->setFont( m_smallFont );

        // If the user is hovering over an artist rect, underline the artist name
        if ( m_hoveringOverArtist == index )
        {
            QFont f = painter->font();
            f.setUnderline( true );
            painter->setFont( f );
        }

        textRect.adjust( 0, painter->fontMetrics().height() + m_margin / 16, 0, 0 );
        to.setAlignment( Qt::AlignLeft | Qt::AlignBottom );
        text = painter->fontMetrics().elidedText( bottom, Qt::ElideRight, textRect.width() - m_margin / 4 );
        painter->drawText( textRect, text, to );

        // Calculate rect of artist on-hover button click area
        m_artistNameRects[ index ] = painter->fontMetrics().boundingRect( textRect, Qt::AlignLeft | Qt::AlignBottom, text );
        painter->restore();

        if ( m_showBuyButtons && !item->query().isNull() )
        {
            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 ) ) )
            {
                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 );
            }
        }
    }

    painter->restore();
}
Example #13
0
void
ColumnItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
    if ( !item )
        return;

    QTextOption textOption( Qt::AlignVCenter | (Qt::Alignment)index.data( Qt::TextAlignmentRole ).toUInt() );
    textOption.setWrapMode( QTextOption::NoWrap );

    QString text;
    if ( !item->artist().isNull() )
    {
        text = item->artist()->name();
    }
    else if ( !item->album().isNull() )
    {
        text = item->album()->name();
    }
    else if ( !item->result().isNull() || !item->query().isNull() )
    {
        float opacity = item->result() && item->result()->isOnline() ? 1.0 : 0.0;
        opacity = qMax( (float)0.3, opacity );
        QColor textColor = TomahawkUtils::alphaBlend( option.palette.color( QPalette::Foreground ), option.palette.color( QPalette::Background ), opacity );

        {
            QStyleOptionViewItemV4 o = option;
            initStyleOption( &o, QModelIndex() );

            painter->save();
            o.palette.setColor( QPalette::Text, textColor );

            if ( m_view->currentIndex() == index )
                o.state |= QStyle::State_Selected;
            else
                o.state &= ~QStyle::State_Selected;

            if ( o.state & QStyle::State_Selected && o.state & QStyle::State_Active )
            {
                o.palette.setColor( QPalette::Text, o.palette.color( QPalette::HighlightedText ) );
            }

            if ( item->isPlaying() )
            {
                textColor = TomahawkStyle::NOW_PLAYING_ITEM_TEXT;
                o.palette.setColor( QPalette::Highlight, TomahawkStyle::NOW_PLAYING_ITEM );
                o.palette.setColor( QPalette::Text, TomahawkStyle::NOW_PLAYING_ITEM_TEXT );
                o.state |= QStyle::State_Selected;
            }

            int oldX = 0;
//            if ( m_view->header()->visualIndex( index.column() ) == 0 )
            {
                oldX = o.rect.x();
                o.rect.setX( 0 );
            }
            qApp->style()->drawControl( QStyle::CE_ItemViewItem, &o, painter );
            if ( oldX > 0 )
                o.rect.setX( oldX );

/*            if ( m_hoveringOver == index && !index.data().toString().isEmpty() && index.column() == 0 )
            {
                o.rect.setWidth( o.rect.width() - o.rect.height() );
                QRect arrowRect( o.rect.x() + o.rect.width(), o.rect.y() + 1, o.rect.height() - 2, o.rect.height() - 2 );

                QPixmap infoIcon = TomahawkUtils::defaultPixmap( TomahawkUtils::InfoIcon, TomahawkUtils::Original, arrowRect.size() );
                painter->drawPixmap( arrowRect, infoIcon );

                m_infoButtonRects[ index ] = arrowRect;
            }*/

            {
                QRect r = o.rect.adjusted( 3, 0, 0, 0 );

                // Paint Now Playing Speaker Icon
                if ( item->isPlaying() )
                {
                    const int pixMargin = 1;
                    const int pixHeight = r.height() - pixMargin * 2;
                    QRect npr = r.adjusted( pixMargin, pixMargin, pixHeight - r.width() + pixMargin, -pixMargin );
                    painter->drawPixmap( npr, TomahawkUtils::defaultPixmap( TomahawkUtils::NowPlayingSpeaker, TomahawkUtils::Original, npr.size() ) );
                    r.adjust( pixHeight + 6, 0, 0, 0 );
                }

                painter->setPen( o.palette.text().color() );

                QString text = index.data().toString();
                if ( item->query()->track()->albumpos() > 0 )
                {
                    text = QString( "%1. %2" )
                              .arg( index.data( PlayableModel::AlbumPosRole ).toString() )
                              .arg( index.data().toString() );
                }

                text = painter->fontMetrics().elidedText( text, Qt::ElideRight, r.width() - 3 );
                painter->drawText( r.adjusted( 0, 1, 0, 0 ), text, textOption );
            }
            painter->restore();
        }

        return;
    }
    else
        return;

    if ( text.trimmed().isEmpty() )
        text = tr( "Unknown" );

    QStyleOptionViewItemV4 opt = option;
    initStyleOption( &opt, QModelIndex() );

    const QModelIndex curIndex = m_view->currentIndex();
    if ( curIndex == index || curIndex.parent() == index || curIndex.parent().parent() == index )
        opt.state |= QStyle::State_Selected;
    else
        opt.state &= ~QStyle::State_Selected;

    qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );

    if ( opt.state & QStyle::State_Selected )
    {
        opt.palette.setColor( QPalette::Text, opt.palette.color( QPalette::HighlightedText ) );
    }

    QRect arrowRect( m_view->viewport()->width() - option.rect.height(), option.rect.y() + 1, option.rect.height() - 2, option.rect.height() - 2 );
    if ( m_hoveringOver.row() == index.row() && m_hoveringOver.parent() == index.parent() )
    {
        QPixmap infoIcon = TomahawkUtils::defaultPixmap( TomahawkUtils::InfoIcon, TomahawkUtils::Original, arrowRect.size() );
        painter->drawPixmap( arrowRect, infoIcon );

        m_infoButtonRects[ index ] = arrowRect;
    }

    if ( index.column() > 0 )
        return;

    painter->save();
    painter->setRenderHint( QPainter::TextAntialiasing );
    painter->setPen( opt.palette.color( QPalette::Text ) );

    QRect r = option.rect.adjusted( 8, 2, -option.rect.width() + option.rect.height() + 4, -2 );
//    painter->drawPixmap( r, QPixmap( RESPATH "images/cover-shadow.png" ) );

    if ( !m_pixmaps.contains( index ) )
    {
        if ( !item->album().isNull() )
        {
            m_pixmaps.insert( index, QSharedPointer< Tomahawk::PixmapDelegateFader >( new Tomahawk::PixmapDelegateFader( item->album(), r.size(), TomahawkUtils::Original, false ) ) );
            _detail::Closure* closure = NewClosure( m_pixmaps[ index ], SIGNAL( repaintRequest() ), const_cast<ColumnItemDelegate*>(this), SLOT( doUpdateIndex( const QPersistentModelIndex& ) ), QPersistentModelIndex( index ) );
            closure->setAutoDelete( false );
        }
        else if ( !item->artist().isNull() )