diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index f8e9012cc..b4afa595b 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -159,6 +159,7 @@ set( libGuiSources widgets/RecentPlaylistsModel.cpp widgets/RecentlyPlayedPlaylistsModel.cpp widgets/ScriptCollectionHeader.cpp + widgets/ScrollingLabel.cpp widgets/SearchWidget.cpp widgets/SeekSlider.cpp widgets/SourceTreePopupDialog.cpp diff --git a/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp b/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp index 222f324d5..0a8f4bc89 100644 --- a/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp +++ b/src/libtomahawk/playlist/ColumnViewPreviewWidget.cpp @@ -21,6 +21,7 @@ #include "ColumnView.h" #include "widgets/PlayableCover.h" #include "widgets/QueryLabel.h" +#include "widgets/ScrollingLabel.h" #include "utils/Logger.h" #include "Source.h" #include "utils/TomahawkUtilsGui.h" @@ -66,12 +67,13 @@ ColumnViewPreviewWidget::ColumnViewPreviewWidget( ColumnView* parent ) mainLayout->addSpacing( 16 ); #endif - m_trackLabel = new QLabel( this ); - m_trackLabel->setAlignment( Qt::AlignCenter ); + m_trackLabel = new ScrollingLabel( this ); + //m_trackLabel->setAlignment( Qt::AlignCenter ); QFont font; font.setPointSize( TomahawkUtils::defaultFontSize() + 9 ); font.setBold( true ); m_trackLabel->setFont( font ); + m_trackLabel->setFixedHeight( QFontMetrics( font ).height() + 6 ); mainLayout->addWidget( m_trackLabel ); m_artistLabel = new QueryLabel( this ); diff --git a/src/libtomahawk/playlist/ColumnViewPreviewWidget.h b/src/libtomahawk/playlist/ColumnViewPreviewWidget.h index 859328c66..3935fedcc 100644 --- a/src/libtomahawk/playlist/ColumnViewPreviewWidget.h +++ b/src/libtomahawk/playlist/ColumnViewPreviewWidget.h @@ -28,6 +28,7 @@ class ColumnView; class QueryLabel; class PlayableCover; class QLabel; +class ScrollingLabel; class DLLEXPORT ColumnViewPreviewWidget : public QWidget { @@ -66,7 +67,7 @@ private: QLabel* m_yearLabel; QLabel* m_yearValue; - QLabel* m_trackLabel; + ScrollingLabel* m_trackLabel; QueryLabel* m_artistLabel; }; diff --git a/src/libtomahawk/widgets/ScrollingLabel.cpp b/src/libtomahawk/widgets/ScrollingLabel.cpp new file mode 100644 index 000000000..86881da05 --- /dev/null +++ b/src/libtomahawk/widgets/ScrollingLabel.cpp @@ -0,0 +1,191 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2014, Teo Mrnjavac + * + * 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 "ScrollingLabel.h" + +#include "utils/DpiScaler.h" + +#include + + +ScrollingLabel::ScrollingLabel( QWidget* parent) + : QWidget( parent ) + , m_scrollPos( 0 ) + , m_isMouseOver( false ) +{ + m_staticText.setTextFormat( Qt::PlainText ); + + setFixedHeight( fontMetrics().height() ); + m_leftMargin = height() / 3; + + m_separator = QString::fromUtf8( " \u26AB " ); + + connect( &m_timer, SIGNAL( timeout() ), this, SLOT( onTimerTimeout() ) ); + m_timer.setInterval( 10 ); +} + + +QString +ScrollingLabel::text() const +{ + return m_text; +} + + +void +ScrollingLabel::setText( QString text ) +{ + m_text = text; + updateText(); + update(); +} + + +void +ScrollingLabel::updateText() +{ + m_timer.stop(); + + m_singleTextWidth = fontMetrics().width( m_text ); + m_scrollEnabled = ( m_singleTextWidth > width() - m_leftMargin ); + + m_scrollPos = -64; + + if ( m_scrollEnabled && m_isMouseOver ) + { + m_staticText.setText( m_text + m_separator ); + m_timer.start(); + } + else + m_staticText.setText( m_text ); + + m_staticText.prepare( QTransform(), font() ); + m_wholeTextSize = QSize( fontMetrics().width( m_staticText.text() ), + fontMetrics().height() ); +} + + +void +ScrollingLabel::paintEvent( QPaintEvent* ) +{ + QPainter p( this ); + + if ( m_scrollEnabled ) + { + m_buffer.fill( qRgba(0, 0, 0, 0) ); + QPainter pb( &m_buffer ); + pb.setPen( p.pen() ); + pb.setFont( p.font() ); + + int x = qMin( -m_scrollPos, 0 ) + m_leftMargin; + while ( x < width() ) + { + pb.drawStaticText( QPointF( x, ( height() - m_wholeTextSize.height() ) / 2 ) + QPoint( 2, 2 ), m_staticText ); + x += m_wholeTextSize.width(); + } + + TomahawkUtils::DpiScaler s( this ); + //Apply Alpha Channel + pb.setCompositionMode( QPainter::CompositionMode_DestinationIn ); + pb.setClipRect( width() - s.scaledX( 15 ), + 0, + s.scaledX( 15 ), + height() ); + pb.drawImage( 0, 0, m_alphaChannel ); + pb.setClipRect( 0, 0, s.scaledX( 15 ), height() ); + //initial situation: don't apply alpha channel in the left half of the image at all; apply it more and more until scrollPos gets positive + if ( m_scrollPos < 0 ) + pb.setOpacity( (qreal)( qMax( -s.scaledX( 8 ), m_scrollPos ) + s.scaledX( 8 ) ) / s.scaledX( 8 ) ); + pb.drawImage( 0, 0, m_alphaChannel ); + + //pb.end(); + p.drawImage( 0, 0, m_buffer ); + } + else + { + if ( m_wholeTextSize.width() > width() - 2*m_leftMargin ) + { + p.drawStaticText( QPointF( m_leftMargin, ( height() - m_wholeTextSize.height() ) / 2 ), + m_staticText ); + } + else + { + p.drawStaticText( QPointF( ( width() - m_wholeTextSize.width() ) / 2., + ( height() - m_wholeTextSize.height() ) / 2. ), + m_staticText ); + } + } +} + + +void +ScrollingLabel::resizeEvent( QResizeEvent* ) +{ + //From limmes@StackOverflow + //When the widget is resized, we need to update the alpha channel. + m_alphaChannel = QImage( size(), QImage::Format_ARGB32_Premultiplied ); + m_buffer = QImage( size(), QImage::Format_ARGB32_Premultiplied ); + + //Create Alpha Channel: + if ( width() > 64 ) + { + //create first scanline + QRgb* scanline1 = (QRgb*)m_alphaChannel.scanLine( 0 ); + for ( int x = 1; x < 16; ++x ) + scanline1[ x - 1 ] = scanline1[ width() - x ] = qRgba( 0, 0, 0, x << 4 ); + for ( int x = 15; x < width() - 15; ++x ) + scanline1[ x ] = qRgb( 0, 0, 0 ); + //copy scanline to the other ones + for ( int y = 1; y < height(); ++y ) + memcpy( m_alphaChannel.scanLine( y ), (uchar*)scanline1, width() * 4 ); + } + else + m_alphaChannel.fill( qRgb( 0, 0, 0 ) ); + + + //Update scrolling state + bool newScrollEnabled = ( m_singleTextWidth > width() - m_leftMargin ); + if( newScrollEnabled != m_scrollEnabled ) + updateText(); +} + + +void +ScrollingLabel::enterEvent( QEvent* ) +{ + m_isMouseOver = true; + updateText(); + update(); +} + + +void +ScrollingLabel::leaveEvent( QEvent* ) +{ + m_isMouseOver = false; + updateText(); + update(); +} + + +void +ScrollingLabel::onTimerTimeout() +{ + m_scrollPos = ( m_scrollPos + 1 ) % m_wholeTextSize.width(); + update(); +} diff --git a/src/libtomahawk/widgets/ScrollingLabel.h b/src/libtomahawk/widgets/ScrollingLabel.h new file mode 100644 index 000000000..513b1e2f9 --- /dev/null +++ b/src/libtomahawk/widgets/ScrollingLabel.h @@ -0,0 +1,64 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2014, Teo Mrnjavac + * + * 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 SCROLLINGLABEL_H +#define SCROLLINGLABEL_H + +#include +#include +#include + + +class ScrollingLabel : public QWidget +{ + Q_OBJECT + Q_PROPERTY( QString text READ text WRITE setText ) + +public: + explicit ScrollingLabel( QWidget* parent = 0 ); + +public slots: + QString text() const; + void setText( QString text ); + +protected: + virtual void paintEvent( QPaintEvent* ); + virtual void resizeEvent( QResizeEvent* ); + virtual void enterEvent( QEvent* ); + virtual void leaveEvent( QEvent* ); + +private: + bool m_isMouseOver; + void updateText(); + QString m_text; + QString m_separator; + QStaticText m_staticText; + int m_singleTextWidth; + QSize m_wholeTextSize; + int m_leftMargin; + bool m_scrollEnabled; + int m_scrollPos; + QImage m_alphaChannel; + QImage m_buffer; + QTimer m_timer; + +private slots: + virtual void onTimerTimeout(); +}; + +#endif // SCROLLINGLABEL_H