diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac75818a9..fd60a7a7d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -105,6 +105,7 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui} utils/progresstreeview.cpp utils/proxystyle.cpp utils/widgetdragfilter.cpp + utils/animatedsplitter.cpp playlist/collectionmodel.cpp playlist/collectionproxymodel.cpp @@ -233,6 +234,7 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui} utils/imagebutton.h utils/progresstreeview.h utils/widgetdragfilter.h + utils/animatedsplitter.h playlist/collectionmodel.h playlist/collectionproxymodel.h diff --git a/src/playlist/playlistmanager.cpp b/src/playlist/playlistmanager.cpp index eb579f35f..0f9c7ff1e 100644 --- a/src/playlist/playlistmanager.cpp +++ b/src/playlist/playlistmanager.cpp @@ -2,7 +2,9 @@ #include -#include "audioengine.h" +#include "audio/audioengine.h" +#include "utils/animatedsplitter.h" + #include "collectionmodel.h" #include "collectionflatmodel.h" #include "collectionview.h" @@ -35,9 +37,10 @@ PlaylistManager::PlaylistManager( QObject* parent ) m_widget->setLayout( new QVBoxLayout() ); - m_splitter = new QSplitter(); + m_splitter = new AnimatedSplitter(); m_splitter->setOrientation( Qt::Vertical ); m_splitter->setChildrenCollapsible( false ); + m_splitter->setGreedyWidget( 0 ); m_splitter->addWidget( m_stack ); m_splitter->addWidget( m_queueView ); @@ -281,7 +284,7 @@ PlaylistManager::showQueue() return; } - m_queueView->showQueue(); + m_splitter->show( 1 ); } @@ -296,7 +299,7 @@ PlaylistManager::hideQueue() return; } - m_queueView->hideQueue(); + m_splitter->hide( 1 ); } diff --git a/src/playlist/playlistmanager.h b/src/playlist/playlistmanager.h index 93a5e736e..dd161c87a 100644 --- a/src/playlist/playlistmanager.h +++ b/src/playlist/playlistmanager.h @@ -4,11 +4,11 @@ #include #include #include -#include #include "tomahawk/collection.h" #include "tomahawk/playlistinterface.h" +class AnimatedSplitter; class CollectionModel; class CollectionFlatModel; class CollectionView; @@ -72,7 +72,7 @@ private: QWidget* m_widget; QStackedWidget* m_stack; - QSplitter* m_splitter; + AnimatedSplitter* m_splitter; PlaylistModel* m_queueModel; QueueView* m_queueView; diff --git a/src/playlist/queueview.cpp b/src/playlist/queueview.cpp index 51f7ea568..0574f0a1a 100644 --- a/src/playlist/queueview.cpp +++ b/src/playlist/queueview.cpp @@ -1,7 +1,6 @@ #include "queueview.h" #include -#include #include #include "playlist/queueproxymodel.h" @@ -11,26 +10,22 @@ 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_queue->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored ); 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() ) ); + connect( m_button, SIGNAL( clicked() ), SIGNAL( showWidget() ) ); layout()->setMargin( 0 ); layout()->addWidget( m_button ); layout()->addWidget( m_queue ); - layout()->setAlignment( Qt::AlignTop ); - - m_queue->hide(); } @@ -41,82 +36,26 @@ QueueView::~QueueView() void -QueueView::showQueue() +QueueView::onShown( QWidget* widget ) { - if ( !m_queue->isHidden() ) + qDebug() << Q_FUNC_INFO << widget; + if ( widget != this ) 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( m_prevHeight ); - m_queue->resize( m_queue->width(), m_prevHeight ); - m_queue->show(); - - QTimeLine *timeLine = new QTimeLine( 300, this ); - timeLine->setFrameRange( 0, m_prevHeight ); - timeLine->setUpdateInterval( 20 ); - timeLine->setCurveShape( QTimeLine::EaseOutCurve ); - - connect( timeLine, SIGNAL( frameChanged( int ) ), SLOT( onAnimationStep( int ) ) ); - connect( timeLine, SIGNAL( finished() ), SLOT( onAnimationFinished() ) ); - timeLine->start(); + disconnect( m_button, SIGNAL( clicked() ), this, SIGNAL( showWidget() ) ); + connect( m_button, SIGNAL( clicked() ), SIGNAL( hideWidget() ) ); } void -QueueView::hideQueue() +QueueView::onHidden( QWidget* widget ) { - if ( m_queue->isHidden() ) + qDebug() << Q_FUNC_INFO << widget; + if ( widget != this ) 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 ); - timeLine->setCurveShape( QTimeLine::EaseOutCurve ); - - connect( timeLine, SIGNAL( frameChanged( int ) ), SLOT( onAnimationStep( int ) ) ); - connect( timeLine, SIGNAL( finished() ), SLOT( onAnimationFinished() ) ); - timeLine->start(); -} - - -void -QueueView::onAnimationStep( int frame ) -{ - setUpdatesEnabled( false ); - - setMinimumHeight( frame + 25 ); - setMaximumHeight( frame + 25 ); - - setUpdatesEnabled( true ); -} - - -void -QueueView::onAnimationFinished() -{ - qDebug() << Q_FUNC_INFO << maximumHeight(); - - if ( maximumHeight() < 32 ) - { - setMinimumHeight( 25 ); - setMaximumHeight( 25 ); - m_queue->hide(); - } - else - { - setMinimumHeight( 200 ); - setMaximumHeight( QWIDGETSIZE_MAX ); - m_queue->setMaximumHeight( QWIDGETSIZE_MAX ); - } - - sender()->deleteLater(); + disconnect( m_button, SIGNAL( clicked() ), this, SIGNAL( hideWidget() ) ); + connect( m_button, SIGNAL( clicked() ), SIGNAL( showWidget() ) ); } diff --git a/src/playlist/queueview.h b/src/playlist/queueview.h index a7bd00284..084460761 100644 --- a/src/playlist/queueview.h +++ b/src/playlist/queueview.h @@ -15,18 +15,19 @@ public: PlaylistView* queue() const { return m_queue; } -public slots: - void showQueue(); - void hideQueue(); + QSize sizeHint() const { return QSize( 0, 200 ); } -private slots: - void onAnimationStep( int frame ); - void onAnimationFinished(); +public slots: + void onShown( QWidget* ); + void onHidden( QWidget* ); + +signals: + void showWidget(); + void hideWidget(); private: PlaylistView* m_queue; QPushButton* m_button; - unsigned int m_prevHeight; }; #endif // QUEUEVIEW_H diff --git a/src/utils/animatedsplitter.cpp b/src/utils/animatedsplitter.cpp new file mode 100644 index 000000000..bc9701704 --- /dev/null +++ b/src/utils/animatedsplitter.cpp @@ -0,0 +1,160 @@ +#include "animatedsplitter.h" + +#include +#include + + +AnimatedSplitter::AnimatedSplitter( QWidget* parent ) + : QSplitter( parent ) + , m_animateIndex( -1 ) + , m_greedyIndex( -1 ) + , m_greedyHeight( -1 ) +{ +} + + +void +AnimatedSplitter::show( int index ) +{ + if ( m_greedyIndex < 0 ) + return; + + m_animateIndex = index; + + QWidget* w = widget( index ); + QSize size = w->sizeHint(); + qDebug() << "SizeHint:" << index << w->height() << size; + + m_greedyHeight = widget( m_greedyIndex )->height(); + + QTimeLine *timeLine = new QTimeLine( 300, this ); + timeLine->setFrameRange( w->height(), size.height() ); + timeLine->setUpdateInterval( 20 ); + timeLine->setCurveShape( QTimeLine::EaseOutCurve ); + + connect( timeLine, SIGNAL( frameChanged( int ) ), SLOT( onAnimationStep( int ) ) ); + connect( timeLine, SIGNAL( finished() ), SLOT( onAnimationFinished() ) ); + timeLine->start(); + + emit shown( w ); +} + + +void +AnimatedSplitter::hide( int index ) +{ + if ( m_greedyIndex < 0 ) + return; + + m_animateIndex = index; + + QWidget* w = widget( index ); + qDebug() << "SizeHint:" << index << w->height(); + + m_greedyHeight = widget( m_greedyIndex )->height(); + + QTimeLine *timeLine = new QTimeLine( 300, this ); + timeLine->setFrameRange( 25, w->height() ); + timeLine->setUpdateInterval( 20 ); + timeLine->setDirection( QTimeLine::Backward ); + timeLine->setCurveShape( QTimeLine::EaseOutCurve ); + + connect( timeLine, SIGNAL( frameChanged( int ) ), SLOT( onAnimationStep( int ) ) ); + connect( timeLine, SIGNAL( finished() ), SLOT( onAnimationFinished() ) ); + timeLine->start(); + + emit hidden( w ); +} + + +void +AnimatedSplitter::addWidget( QWidget* widget ) +{ + QSplitter::addWidget( widget ); + + connect( widget, SIGNAL( showWidget() ), SLOT( onShowRequest() ) ); + connect( widget, SIGNAL( hideWidget() ), SLOT( onHideRequest() ) ); + connect( this, SIGNAL( shown( QWidget* ) ), widget, SLOT( onShown( QWidget* ) ) ); + connect( this, SIGNAL( hidden( QWidget* ) ), widget, SLOT( onHidden( QWidget* ) ) ); +} + + +void +AnimatedSplitter::onShowRequest() +{ + qDebug() << Q_FUNC_INFO; + + int j = -1; + for ( int i = 0; i < count(); i ++ ) + { + if ( widget( i ) == sender() ) + { + j = i; + break; + } + } + + if ( j > 0 ) + show( j ); +} + + +void +AnimatedSplitter::onHideRequest() +{ + qDebug() << Q_FUNC_INFO; + + int j = -1; + for ( int i = 0; i < count(); i ++ ) + { + if ( widget( i ) == sender() ) + { + j = i; + break; + } + } + + if ( j > 0 ) + hide( j ); +} + + +void +AnimatedSplitter::onAnimationStep( int frame ) +{ + qDebug() << Q_FUNC_INFO << frame; + + QList< int > sizes; + + for ( int i = 0; i < count(); i ++ ) + { + int j = 0; + + if ( i == m_greedyIndex ) + { + j = height() - frame; // FIXME + } + else if ( i == m_animateIndex ) + { + j = frame; + } + else + { + j = widget( i )->height(); + } + + sizes << j; + } + + qDebug() << sizes; + setSizes( sizes ); +} + + +void +AnimatedSplitter::onAnimationFinished() +{ + qDebug() << Q_FUNC_INFO; + + sender()->deleteLater(); +} diff --git a/src/utils/animatedsplitter.h b/src/utils/animatedsplitter.h new file mode 100644 index 000000000..54176cc37 --- /dev/null +++ b/src/utils/animatedsplitter.h @@ -0,0 +1,38 @@ +#ifndef ANIMATEDSPLITTER_H +#define ANIMATEDSPLITTER_H + +#include + +class AnimatedSplitter : public QSplitter +{ +Q_OBJECT + +public: + explicit AnimatedSplitter( QWidget* parent = 0 ); + + void show( int index ); + void hide( int index ); + + void setGreedyWidget( int index ) { m_greedyIndex = index; } + + void addWidget( QWidget* widget ); + +signals: + void shown( QWidget* ); + void hidden( QWidget* ); + +private slots: + void onShowRequest(); + void onHideRequest(); + + void onAnimationStep( int frame ); + void onAnimationFinished(); + +private: + int m_animateIndex; + + int m_greedyIndex; + int m_greedyHeight; +}; + +#endif //ANIMATEDSPLITTER_H