diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index cf609066a..dceb426df 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -118,6 +118,11 @@ QMenu::indicator:selected { background-color: #747474; } +positionLine { + qproperty-tailGradient: false; + qproperty-lineColor: rgb(255, 255, 255); +} + PianoRoll { background-color: rgb(0, 0, 0); qproperty-backgroundShade: rgba( 255, 255, 255, 10 ); diff --git a/data/themes/default/style.css b/data/themes/default/style.css index feb85a612..4c698a9e2 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -150,6 +150,11 @@ QMenu::indicator:selected { background-color: #101213; } +positionLine { + qproperty-tailGradient: true; + qproperty-lineColor: rgb(255, 255, 255); +} + PianoRoll { background-color: #141616; qproperty-backgroundShade: rgba(255, 255, 255, 10); diff --git a/include/SongEditor.h b/include/SongEditor.h index 9621bcc23..c4c25d7d0 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -28,6 +28,7 @@ #define SONG_EDITOR_H #include +#include #include "ActionGroup.h" #include "Editor.h" @@ -47,13 +48,28 @@ class TimeLineWidget; class positionLine : public QWidget { + Q_OBJECT + Q_PROPERTY ( bool tailGradient READ hasTailGradient WRITE setHasTailGradient ) + Q_PROPERTY ( QColor lineColor READ lineColor WRITE setLineColor ) public: - positionLine( QWidget * parent ); + positionLine ( QWidget* parent ); + + // qproperty access functions + bool hasTailGradient () const; + void setHasTailGradient ( const bool g ); + QColor lineColor () const; + void setLineColor ( const QColor & c ); + +public slots: + void zoomChange (double zoom); private: - void paintEvent( QPaintEvent * pe ) override; + void paintEvent( QPaintEvent* pe ) override; + + bool m_hasTailGradient; + QColor m_lineColor; -} ; +}; class SongEditor : public TrackContainerView @@ -164,6 +180,9 @@ private: bool m_selectRegion; friend class SongEditorWindow; + +signals: + void zoomingValueChanged( double ); } ; diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index a86028805..a7f67c743 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -52,26 +52,89 @@ #include "PianoRoll.h" #include "Track.h" -positionLine::positionLine( QWidget * parent ) : - QWidget( parent ) +positionLine::positionLine( QWidget* parent ) : + QWidget( parent ), + m_hasTailGradient ( false ), + m_lineColor (0, 0, 0, 0) { - setFixedWidth( 1 ); + resize( 8, height() ); + setAttribute( Qt::WA_NoSystemBackground, true ); + setAttribute( Qt::WA_TransparentForMouseEvents ); } - - - -void positionLine::paintEvent( QPaintEvent * pe ) +void positionLine::paintEvent( QPaintEvent* pe ) { QPainter p( this ); - p.fillRect( rect(), QColor( 255, 255, 255, 153 ) ); + + // If width is 1, we don't need a gradient + if (width() == 1) + { + p.fillRect( rect(), + QColor( m_lineColor.red(), m_lineColor.green(), m_lineColor.blue(), 153) ); + } + + // If width > 1, we need the gradient + else + { + // Create the gradient trail behind the line + QLinearGradient gradient( rect().bottomLeft(), rect().bottomRight() ); + + // If gradient is enabled, we're in focus and we're playing, enable gradient + if (Engine::getSong()->isPlaying() && m_hasTailGradient && + Engine::getSong()->playMode() == Song::Mode_PlaySong) + { + gradient.setColorAt(( ( width() - 1.0 )/width() ), + QColor( m_lineColor.red(), m_lineColor.green(), m_lineColor.blue(), 60) ); + } + else + { + gradient.setColorAt(( ( width() - 1.0 )/width() ), + QColor( m_lineColor.red(), m_lineColor.green(), m_lineColor.blue(), 0) ); + } + + // Fill in the remaining parts + gradient.setColorAt(0, + QColor( m_lineColor.red(), m_lineColor.green(), m_lineColor.blue(), 0) ); + gradient.setColorAt(1, + QColor( m_lineColor.red(), m_lineColor.green(), m_lineColor.blue(), 153) ); + + // Fill line + p.fillRect( rect(), gradient ); + } } +// QProperty handles +bool positionLine::hasTailGradient() const +{ return m_hasTailGradient; } + +void positionLine::setHasTailGradient( const bool g ) +{ m_hasTailGradient = g; } + +QColor positionLine::lineColor() const +{ return m_lineColor; } + +void positionLine::setLineColor( const QColor & c ) +{ m_lineColor = c; } + +// NOTE: the move() implementation fixes a bug where the position line would appear +// in an unexpected location when positioned at the start of the track +void positionLine::zoomChange( double zoom ) +{ + int playHeadPos = x() + width() - 1; + + resize( 8.0 * zoom, height() ); + move( playHeadPos - width() + 1, y() ); + + update(); +} + + + + const QVector SongEditor::m_zoomLevels = { 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f }; - SongEditor::SongEditor( Song * song ) : TrackContainerView( song ), m_song( song ), @@ -111,6 +174,11 @@ SongEditor::SongEditor( Song * song ) : m_positionLine = new positionLine( this ); static_cast( layout() )->insertWidget( 1, m_timeLine ); + + connect( m_song, SIGNAL( playbackStateChanged() ), + m_positionLine, SLOT( update() ) ); + connect( this, SIGNAL( zoomingValueChanged( double ) ), + m_positionLine, SLOT( zoomChange( double ) ) ); // add some essential widgets to global tool-bar @@ -250,6 +318,8 @@ SongEditor::SongEditor( Song * song ) : m_zoomingModel->findText( "100%" ) ); connect( m_zoomingModel, SIGNAL( dataChanged() ), this, SLOT( zoomingChanged() ) ); + connect( m_zoomingModel, SIGNAL( dataChanged() ), + m_positionLine, SLOT( update() ) ); //Set up snapping model, 2^i for ( int i = 3; i >= -4; i-- ) @@ -808,7 +878,7 @@ void SongEditor::updatePosition( const MidiTime & t ) if( x >= trackOpWidth + widgetWidth -1 ) { m_positionLine->show(); - m_positionLine->move( x, m_timeLine->height() ); + m_positionLine->move( x-( m_positionLine->width() - 1 ), m_timeLine->height() ); } else { @@ -837,11 +907,11 @@ void SongEditor::zoomingChanged() setPixelsPerBar( pixelsPerBar() ); realignTracks(); updateRubberband(); + + emit zoomingValueChanged( m_zoomLevels[m_zoomingModel->value()] ); } - - void SongEditor::selectAllTcos( bool select ) { QVector so = select ? rubberBand()->selectableObjects() : rubberBand()->selectedObjects();