mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-06 22:26:32 +02:00
Merge branch 'master' into tweetsip
This commit is contained in:
@@ -110,6 +110,8 @@ DynamicModel::trackResolved()
|
|||||||
emit collapseFromTo( m_lastResolvedRow, m_currentAttempts );
|
emit collapseFromTo( m_lastResolvedRow, m_currentAttempts );
|
||||||
}
|
}
|
||||||
m_currentAttempts = 0;
|
m_currentAttempts = 0;
|
||||||
|
|
||||||
|
emit checkForOverflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -137,7 +139,7 @@ DynamicModel::newTrackLoading()
|
|||||||
} else if( m_onDemandRunning && m_currentAttempts == 0 ) { // if we're in dynamic mode and we're also currently idle
|
} else if( m_onDemandRunning && m_currentAttempts == 0 ) { // if we're in dynamic mode and we're also currently idle
|
||||||
m_lastResolvedRow = rowCount( QModelIndex() );
|
m_lastResolvedRow = rowCount( QModelIndex() );
|
||||||
m_playlist->generator()->fetchNext();
|
m_playlist->generator()->fetchNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -43,9 +43,12 @@ public:
|
|||||||
void loadPlaylist( const dynplaylist_ptr& playlist );
|
void loadPlaylist( const dynplaylist_ptr& playlist );
|
||||||
|
|
||||||
virtual void removeIndex( const QModelIndex& index, bool moreToCome = false );
|
virtual void removeIndex( const QModelIndex& index, bool moreToCome = false );
|
||||||
|
|
||||||
|
bool searchingForNext() const { return m_searchingForNext; }
|
||||||
signals:
|
signals:
|
||||||
void collapseFromTo( int startRow, int num );
|
void collapseFromTo( int startRow, int num );
|
||||||
|
void checkForOverflow();
|
||||||
|
|
||||||
void trackGenerationFailure( const QString& msg );
|
void trackGenerationFailure( const QString& msg );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@@ -60,6 +63,7 @@ private:
|
|||||||
bool m_startOnResolved;
|
bool m_startOnResolved;
|
||||||
bool m_onDemandRunning;
|
bool m_onDemandRunning;
|
||||||
bool m_changeOnNext;
|
bool m_changeOnNext;
|
||||||
|
bool m_searchingForNext;
|
||||||
int m_currentAttempts;
|
int m_currentAttempts;
|
||||||
int m_lastResolvedRow;
|
int m_lastResolvedRow;
|
||||||
};
|
};
|
||||||
|
@@ -37,6 +37,7 @@ using namespace Tomahawk;
|
|||||||
DynamicView::DynamicView( QWidget* parent )
|
DynamicView::DynamicView( QWidget* parent )
|
||||||
: PlaylistView( parent )
|
: PlaylistView( parent )
|
||||||
, m_onDemand( false )
|
, m_onDemand( false )
|
||||||
|
, m_checkOnCollapse( false )
|
||||||
{
|
{
|
||||||
m_fadeOutAnim.setDuration( FADE_LENGTH );
|
m_fadeOutAnim.setDuration( FADE_LENGTH );
|
||||||
m_fadeOutAnim.setCurveShape( QTimeLine::LinearCurve );
|
m_fadeOutAnim.setCurveShape( QTimeLine::LinearCurve );
|
||||||
@@ -51,6 +52,7 @@ DynamicView::DynamicView( QWidget* parent )
|
|||||||
|
|
||||||
|
|
||||||
connect( &m_fadeOutAnim, SIGNAL( frameChanged( int ) ), viewport(), SLOT( update() ) );
|
connect( &m_fadeOutAnim, SIGNAL( frameChanged( int ) ), viewport(), SLOT( update() ) );
|
||||||
|
connect( &m_fadeOutAnim, SIGNAL( finished() ), this, SLOT( animFinished() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicView::~DynamicView()
|
DynamicView::~DynamicView()
|
||||||
@@ -61,15 +63,22 @@ DynamicView::~DynamicView()
|
|||||||
void
|
void
|
||||||
DynamicView::setModel( DynamicModel* model)
|
DynamicView::setModel( DynamicModel* model)
|
||||||
{
|
{
|
||||||
|
m_model = model;
|
||||||
PlaylistView::setModel( model );
|
PlaylistView::setModel( model );
|
||||||
|
|
||||||
connect( model, SIGNAL( trackCountChanged( unsigned int ) ), SLOT( onTrackCountChanged( unsigned int ) ) );
|
connect( model, SIGNAL( trackCountChanged( unsigned int ) ), SLOT( onTrackCountChanged( unsigned int ) ) );
|
||||||
|
connect( model, SIGNAL( checkForOverflow() ), this, SLOT( checkForOverflow() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DynamicView::setOnDemand( bool onDemand )
|
DynamicView::setOnDemand( bool onDemand )
|
||||||
{
|
{
|
||||||
m_onDemand = onDemand;
|
m_onDemand = onDemand;
|
||||||
|
|
||||||
|
if( m_onDemand )
|
||||||
|
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||||
|
else
|
||||||
|
setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -116,54 +125,91 @@ DynamicView::onTrackCountChanged( unsigned int tracks )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
overlay()->hide();
|
overlay()->hide();
|
||||||
|
}
|
||||||
// make sure we can see all our tracks
|
|
||||||
scrollTo( proxyModel()->index( proxyModel()->rowCount() - 1, 0, QModelIndex() ), EnsureVisible );
|
void
|
||||||
|
DynamicView::checkForOverflow()
|
||||||
|
{
|
||||||
|
if( !m_onDemand || proxyModel()->rowCount( QModelIndex() ) == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( m_fadeOutAnim.state() == QTimeLine::Running )
|
||||||
|
m_checkOnCollapse = true;
|
||||||
|
|
||||||
|
/// We don't want stations to grow forever, because we don't want the view to have to scroll
|
||||||
|
/// So if there are too many tracks, we remove some that have already been played
|
||||||
|
/// Our threshold is 4 rows to the end. That's when we collapse.
|
||||||
|
QModelIndex last = proxyModel()->index( proxyModel()->rowCount( QModelIndex() ) - 1, 0, QModelIndex() );
|
||||||
|
QRect lastRect = visualRect( last );
|
||||||
|
qDebug() << "Checking viewport height of" << viewport()->height() << "and last track bottom:" << lastRect.bottomLeft().y() << "under threshold" << 4 * lastRect.height();
|
||||||
|
if( viewport()->height() - lastRect.bottomLeft().y() <= ( 4 * lastRect.height() ) ) {
|
||||||
|
qDebug() << "Deciding to remove some tracks from this station";
|
||||||
|
|
||||||
|
// figure out how many to remove. lets get rid of 1/3rd of the backlog, visually.
|
||||||
|
int toRemove = ( viewport()->height() / 3 ) / lastRect.height();
|
||||||
|
qDebug() << "Decided to remove" << toRemove << "rows!";
|
||||||
|
collapseEntries( 0, toRemove, proxyModel()->rowCount( QModelIndex() ) - toRemove );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DynamicView::collapseEntries( int startRow, int num )
|
DynamicView::collapseEntries( int startRow, int num, int numToKeep )
|
||||||
{
|
{
|
||||||
|
qDebug() << "BEGINNING TO COLLAPSE FROM" << startRow << num << numToKeep;
|
||||||
if( m_fadeOutAnim.state() == QTimeLine::Running )
|
if( m_fadeOutAnim.state() == QTimeLine::Running )
|
||||||
qDebug() << "COLLAPSING TWICE!";
|
qDebug() << "COLLAPSING TWICE!";
|
||||||
// TODO if we are scrolled, we can't animate this way.
|
|
||||||
// we have to animate the top coming down, which i haven't implemented yet..
|
/// Two options: Either we are overflowing our view, or we're not. If we are, it's because the search for a playable track
|
||||||
if( verticalScrollBar()->sliderPosition() == 0 ) {
|
/// went past the limit of the view. Just fade out from the beginning to the end in that case. otherwise, animate a slide
|
||||||
// we capture the image of the rows we're going to collapse
|
bool justFade = false;
|
||||||
// then we capture the image of the target row we're going to animate downwards
|
int realNum = num;
|
||||||
// then we fade the first image out while sliding the second image up.
|
QModelIndex last = indexAt( QPoint( 3, viewport()->height() - 3 ) );
|
||||||
QModelIndex topLeft = proxyModel()->index( startRow, 0, QModelIndex() );
|
if( last.isValid() && last.row() < startRow + num ) {
|
||||||
QModelIndex bottomRight = proxyModel()->index( startRow + num - 1, proxyModel()->columnCount( QModelIndex() ) - 1, QModelIndex() );
|
justFade = true;
|
||||||
QItemSelection sel( topLeft, bottomRight );
|
realNum = last.row();
|
||||||
QRect fadingRect = visualRegionForSelection( sel ).boundingRect();
|
}
|
||||||
QRect fadingRectViewport = fadingRect; // all values that we use in paintEvent() have to be in viewport coords
|
// we capture the image of the rows we're going to collapse
|
||||||
fadingRect.moveTo( viewport()->mapTo( this, fadingRect.topLeft() ) );
|
// then we capture the image of the target row we're going to animate downwards
|
||||||
|
// then we fade the first image out while sliding the second image up.
|
||||||
m_fadingIndexes = QPixmap::grabWidget( this, fadingRect ); // but all values we use to grab the widgetr have to be in scrollarea coords :(
|
QModelIndex topLeft = proxyModel()->index( startRow, 0, QModelIndex() );
|
||||||
m_fadingPointAnchor = QPoint( 0, fadingRectViewport.topLeft().y() );
|
QModelIndex bottomRight = proxyModel()->index( startRow + realNum - 1, proxyModel()->columnCount( QModelIndex() ) - 1, QModelIndex() );
|
||||||
|
QItemSelection sel( topLeft, bottomRight );
|
||||||
qDebug() << "Grabbed fading indexes from rect:" << fadingRect << m_fadingIndexes.size();
|
QRect fadingRect = visualRegionForSelection( sel ).boundingRect();
|
||||||
|
QRect fadingRectViewport = fadingRect; // all values that we use in paintEvent() have to be in viewport coords
|
||||||
topLeft = proxyModel()->index( startRow + num, 0, QModelIndex() );
|
fadingRect.moveTo( viewport()->mapTo( this, fadingRect.topLeft() ) );
|
||||||
bottomRight = proxyModel()->index( startRow + num, proxyModel()->columnCount( QModelIndex() ) - 1, QModelIndex() );
|
|
||||||
|
m_fadingIndexes = QPixmap::grabWidget( this, fadingRect ); // but all values we use to grab the widgetr have to be in scrollarea coords :(
|
||||||
|
m_fadingPointAnchor = QPoint( 0, fadingRectViewport.topLeft().y() );
|
||||||
|
|
||||||
|
m_fadeOutAnim.start();
|
||||||
|
|
||||||
|
qDebug() << "Grabbed fading indexes from rect:" << fadingRect << m_fadingIndexes.size();
|
||||||
|
|
||||||
|
if( !justFade ) {
|
||||||
|
/// sanity checks. make sure we have all the rows we need
|
||||||
|
int firstSlider = startRow + realNum;
|
||||||
|
Q_ASSERT( firstSlider + numToKeep - 1 <= proxyModel()->rowCount() );
|
||||||
|
|
||||||
|
topLeft = proxyModel()->index( startRow + realNum, 0, QModelIndex() );
|
||||||
|
bottomRight = proxyModel()->index( startRow + realNum + numToKeep - 1, proxyModel()->columnCount( QModelIndex() ) - 1, QModelIndex() );
|
||||||
QRect slidingRect = visualRegionForSelection( QItemSelection( topLeft, bottomRight ) ).boundingRect();
|
QRect slidingRect = visualRegionForSelection( QItemSelection( topLeft, bottomRight ) ).boundingRect();
|
||||||
QRect slidingRectViewport = slidingRect;
|
QRect slidingRectViewport = slidingRect;
|
||||||
// map internal view cord to external qscrollarea
|
// map internal view coord to external qscrollarea
|
||||||
slidingRect.moveTo( viewport()->mapTo( this, slidingRect.topLeft() ) );
|
slidingRect.moveTo( viewport()->mapTo( this, slidingRect.topLeft() ) );
|
||||||
|
|
||||||
m_slidingIndex = QPixmap::grabWidget( this, slidingRect );
|
m_slidingIndex = QPixmap::grabWidget( this, slidingRect );
|
||||||
m_bottomAnchor = QPoint( 0, slidingRectViewport.topLeft().y() );
|
m_bottomAnchor = QPoint( 0, slidingRectViewport.topLeft().y() );
|
||||||
m_bottomOfAnim = QPoint( 0, slidingRectViewport.bottomLeft().y() );
|
m_bottomOfAnim = QPoint( 0, slidingRectViewport.bottomLeft().y() );
|
||||||
qDebug() << "Grabbed sliding index from rect:" << slidingRect << m_slidingIndex.size();
|
qDebug() << "Grabbed sliding index from rect:" << slidingRect << m_slidingIndex.size();
|
||||||
|
|
||||||
// slide from the current position to the new one
|
// slide from the current position to the new one
|
||||||
int frameRange = fadingRect.topLeft().y() - slidingRect.topLeft().y();
|
int frameRange = fadingRect.topLeft().y() - slidingRect.topLeft().y();
|
||||||
m_slideAnim.setDuration( SLIDE_LENGTH + frameRange * LONG_MULT );
|
m_slideAnim.setDuration( SLIDE_LENGTH + frameRange * LONG_MULT );
|
||||||
m_slideAnim.setFrameRange( slidingRectViewport.topLeft().y(), fadingRectViewport.topLeft().y() );
|
m_slideAnim.setFrameRange( slidingRectViewport.topLeft().y(), fadingRectViewport.topLeft().y() );
|
||||||
|
|
||||||
m_fadeOutAnim.start();
|
|
||||||
QTimer::singleShot( SLIDE_OFFSET, &m_slideAnim, SLOT( start() ) );
|
QTimer::singleShot( SLIDE_OFFSET, &m_slideAnim, SLOT( start() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the actual indices
|
// delete the actual indices
|
||||||
QModelIndexList todel;
|
QModelIndexList todel;
|
||||||
for( int i = 0; i < num; i++ ) {
|
for( int i = 0; i < num; i++ ) {
|
||||||
@@ -174,6 +220,14 @@ DynamicView::collapseEntries( int startRow, int num )
|
|||||||
proxyModel()->removeIndexes( todel );
|
proxyModel()->removeIndexes( todel );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DynamicView::animFinished()
|
||||||
|
{
|
||||||
|
if( m_checkOnCollapse )
|
||||||
|
checkForOverflow();
|
||||||
|
m_checkOnCollapse = false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DynamicView::paintEvent( QPaintEvent* event )
|
DynamicView::paintEvent( QPaintEvent* event )
|
||||||
{
|
{
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QPropertyAnimation>
|
#include <QPropertyAnimation>
|
||||||
#include <QTimeLine>
|
#include <QTimeLine>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
class PlaylistModel;
|
class PlaylistModel;
|
||||||
class TrackModel;
|
class TrackModel;
|
||||||
@@ -51,18 +52,23 @@ public slots:
|
|||||||
// collapse and animate the transition
|
// collapse and animate the transition
|
||||||
// there MUST be a row *after* startRow + num. that is, you can't collapse
|
// there MUST be a row *after* startRow + num. that is, you can't collapse
|
||||||
// entries unless there is at least one entry after the last collapsed row
|
// entries unless there is at least one entry after the last collapsed row
|
||||||
void collapseEntries( int startRow, int num );
|
// optionally you can specify how many rows are past the block of collapsed rows
|
||||||
|
void collapseEntries( int startRow, int num, int numToKeep = 1 );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onTrackCountChanged( unsigned int );
|
void onTrackCountChanged( unsigned int );
|
||||||
|
void checkForOverflow();
|
||||||
|
void animFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
DynamicModel* m_model;
|
||||||
QString m_title;
|
QString m_title;
|
||||||
QString m_body;
|
QString m_body;
|
||||||
|
|
||||||
bool m_onDemand;
|
bool m_onDemand;
|
||||||
bool m_readOnly;
|
bool m_readOnly;
|
||||||
|
bool m_checkOnCollapse;
|
||||||
|
|
||||||
// for collapsing animation
|
// for collapsing animation
|
||||||
QPoint m_fadingPointAnchor;
|
QPoint m_fadingPointAnchor;
|
||||||
QPoint m_bottomAnchor;
|
QPoint m_bottomAnchor;
|
||||||
|
@@ -64,7 +64,7 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget
|
|||||||
m_view->setContentsMargins( 0, 0, 0, 0 );
|
m_view->setContentsMargins( 0, 0, 0, 0 );
|
||||||
m_layout->addWidget( m_view, 1 );
|
m_layout->addWidget( m_view, 1 );
|
||||||
|
|
||||||
connect( m_model, SIGNAL( collapseFromTo( int, int ) ), m_view, SLOT( collapseEntries( int, int ) ), Qt::QueuedConnection );
|
connect( m_model, SIGNAL( collapseFromTo( int, int ) ), m_view, SLOT( collapseEntries( int, int ) ) );
|
||||||
connect( m_model, SIGNAL( trackGenerationFailure( QString ) ), m_view, SLOT( showMessage( QString ) ) );
|
connect( m_model, SIGNAL( trackGenerationFailure( QString ) ), m_view, SLOT( showMessage( QString ) ) );
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user