diff --git a/include/SongEditor.h b/include/SongEditor.h index e03c632807e..de149e9a4a6 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -75,6 +75,9 @@ class SongEditor : public TrackContainerView public slots: void scrolled( int new_pos ); + void selectRegionFromPixels(int xStart, int xEnd); + void stopSelectRegion(); + void updateRubberband(); void setEditMode( EditMode mode ); void setEditModeDraw(); @@ -85,6 +88,9 @@ public slots: protected: virtual void closeEvent( QCloseEvent * ce ); + virtual void mousePressEvent(QMouseEvent * me); + virtual void mouseMoveEvent(QMouseEvent * me); + virtual void mouseReleaseEvent(QMouseEvent * me); private slots: void setHighQuality( bool ); @@ -109,6 +115,9 @@ private slots: virtual bool allowRubberband() const; + int trackIndexFromSelectionPoint(int yPos); + int indexOfTrackView(const TrackView* tv); + Song * m_song; @@ -135,6 +144,14 @@ private slots: bool m_smoothScroll; EditMode m_mode; + QPoint m_origin; + QPoint m_scrollPos; + QPoint m_mousePos; + int m_rubberBandStartTrackview; + MidiTime m_rubberbandStartMidipos; + int m_currentZoomingValue; + int m_trackHeadWidth; + bool m_selectRegion; friend class SongEditorWindow; diff --git a/include/Track.h b/include/Track.h index f548168b7a7..f3b6c5e4cdb 100644 --- a/include/Track.h +++ b/include/Track.h @@ -210,6 +210,12 @@ class TrackContentObjectView : public selectableObject, public ModelView { return m_tco; } + + inline TrackView * getTrackView() + { + return m_trackView; + } + // qproperty access func QColor mutedColor() const; QColor mutedBackgroundColor() const; @@ -229,7 +235,7 @@ class TrackContentObjectView : public selectableObject, public ModelView // access needsUpdate member variable bool needsUpdate(); void setNeedsUpdate( bool b ); - + public slots: virtual bool close(); void cut(); @@ -256,10 +262,6 @@ public slots: float pixelsPerTact(); - inline TrackView * getTrackView() - { - return m_trackView; - } DataFile createTCODataFiles(const QVector & tcos) const; diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index bf6ada40934..e0c9d11f7f1 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -133,27 +133,21 @@ public slots: virtual void dropEvent( QDropEvent * _de ); virtual void dragEnterEvent( QDragEnterEvent * _dee ); - /// - /// \brief selectRegionFromPixels - /// \param x - /// \param y - /// Use the rubber band to select TCO from all tracks using x, y pixels - void selectRegionFromPixels(int xStart, int xEnd); /// /// \brief stopRubberBand /// Removes the rubber band from display when finished with. void stopRubberBand(); + protected: static const int DEFAULT_PIXELS_PER_TACT = 16; - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); + virtual void resizeEvent( QResizeEvent * ); MidiTime m_currentPosition; + RubberBand *rubberBand() const; private: @@ -187,7 +181,7 @@ public slots: float m_ppt; RubberBand * m_rubberBand; - QPoint m_origin; + signals: diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 4c7498ab0e4..255fb1a021c 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -55,8 +55,7 @@ TrackContainerView::TrackContainerView( TrackContainer * _tc ) : m_trackViews(), m_scrollArea( new scrollArea( this ) ), m_ppt( DEFAULT_PIXELS_PER_TACT ), - m_rubberBand( new RubberBand( m_scrollArea ) ), - m_origin() + m_rubberBand( new RubberBand( m_scrollArea ) ) { m_tc->setHook( this ); //keeps the direction of the widget, undepended on the locale @@ -346,12 +345,8 @@ void TrackContainerView::dragEnterEvent( QDragEnterEvent * _dee ) arg( Track::SampleTrack ) ); } -void TrackContainerView::selectRegionFromPixels(int xStart, int xEnd) -{ - m_rubberBand->setEnabled( true ); - m_rubberBand->show(); - m_rubberBand->setGeometry( min( xStart, xEnd ), 0, max( xStart, xEnd ) - min( xStart, xEnd ), std::numeric_limits::max() ); -} + + void TrackContainerView::stopRubberBand() { @@ -427,50 +422,18 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) -void TrackContainerView::mousePressEvent( QMouseEvent * _me ) -{ - if( allowRubberband() == true ) - { - m_origin = m_scrollArea->mapFromParent( _me->pos() ); - m_rubberBand->setEnabled( true ); - m_rubberBand->setGeometry( QRect( m_origin, QSize() ) ); - m_rubberBand->show(); - } - QWidget::mousePressEvent( _me ); -} - - - - -void TrackContainerView::mouseMoveEvent( QMouseEvent * _me ) -{ - if( rubberBandActive() == true ) - { - m_rubberBand->setGeometry( QRect( m_origin, - m_scrollArea->mapFromParent( _me->pos() ) ). - normalized() ); - } - QWidget::mouseMoveEvent( _me ); -} - - - - -void TrackContainerView::mouseReleaseEvent( QMouseEvent * _me ) +void TrackContainerView::resizeEvent( QResizeEvent * _re ) { - m_rubberBand->hide(); - m_rubberBand->setEnabled( false ); - QWidget::mouseReleaseEvent( _me ); + realignTracks(); + QWidget::resizeEvent( _re ); } - -void TrackContainerView::resizeEvent( QResizeEvent * _re ) +RubberBand *TrackContainerView::rubberBand() const { - realignTracks(); - QWidget::resizeEvent( _re ); + return m_rubberBand; } diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 286b01f15c3..31cb142c074 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -51,8 +51,7 @@ #include "TimeDisplayWidget.h" #include "AudioDevice.h" #include "PianoRoll.h" - - +#include "Track.h" positionLine::positionLine( QWidget * parent ) : QWidget( parent ) @@ -80,15 +79,21 @@ SongEditor::SongEditor( Song * song ) : m_zoomingModel(new ComboBoxModel()), m_scrollBack( false ), m_smoothScroll( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() ), - m_mode(DrawMode) + m_mode(DrawMode), + m_origin(), + m_scrollPos(), + m_mousePos(), + m_rubberBandStartTrackview(0), + m_rubberbandStartMidipos(0), + m_currentZoomingValue(m_zoomingModel->value()), + m_trackHeadWidth(ConfigManager::inst()->value("ui", "compacttrackbuttons").toInt()==1 + ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT + : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH), + m_selectRegion(false) { m_zoomingModel->setParent(this); // create time-line - int widgetTotal = ConfigManager::inst()->value( "ui", - "compacttrackbuttons" ).toInt()==1 ? - DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT : - DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH; - m_timeLine = new TimeLineWidget( widgetTotal, 32, + m_timeLine = new TimeLineWidget( m_trackHeadWidth, 32, pixelsPerTact(), m_song->m_playPos[Song::Mode_PlaySong], m_currentPosition, this ); @@ -239,6 +244,10 @@ SongEditor::SongEditor( Song * song ) : this, SLOT( scrolled( int ) ) ); connect( m_song, SIGNAL( lengthChanged( int ) ), this, SLOT( updateScrollBar( int ) ) ); + connect(m_leftRightScroll, SIGNAL(valueChanged(int)),this, SLOT(updateRubberband())); + connect(contentWidget()->verticalScrollBar(), SIGNAL(valueChanged(int)),this, SLOT(updateRubberband())); + connect(m_timeLine, SIGNAL(selectionFinished()), this, SLOT(stopSelectRegion())); + // Set up zooming model for( float const & zoomLevel : m_zoomLevels ) @@ -293,6 +302,99 @@ void SongEditor::scrolled( int new_pos ) +void SongEditor::selectRegionFromPixels(int xStart, int xEnd) +{ + if (!m_selectRegion) + { + m_selectRegion = true; + + //deselect all tcos + for (auto &it : findChildren()) { it->setSelected(false); } + + rubberBand()->setEnabled(true); + rubberBand()->show(); + + //we save the position of scrollbars, mouse position and zooming level + m_origin = QPoint(xStart, 0); + m_scrollPos = QPoint(m_leftRightScroll->value(), contentWidget()->verticalScrollBar()->value()); + m_currentZoomingValue = zoomingModel()->value(); + + //calculate the song position where the mouse was clicked + m_rubberbandStartMidipos = MidiTime((xStart - m_trackHeadWidth) + / pixelsPerTact() * MidiTime::ticksPerTact()) + + m_currentPosition; + m_rubberBandStartTrackview = 0; + } + //the current mouse position within the borders of song editor + m_mousePos = QPoint(qMax(m_trackHeadWidth, qMin(xEnd, width())) + , std::numeric_limits::max()); + updateRubberband(); +} + + + + +void SongEditor::stopSelectRegion() +{ + m_selectRegion = false; +} + + + + +void SongEditor::updateRubberband() +{ + if (rubberBandActive()) + { + int originX = m_origin.x(); + + //take care of the zooming + if (m_currentZoomingValue != m_zoomingModel->value()) + { + originX = m_trackHeadWidth + (originX - m_trackHeadWidth) + * m_zoomLevels[m_zoomingModel->value()] / m_zoomLevels[m_currentZoomingValue]; + } + + //take care of the scrollbar position + int hs = (m_leftRightScroll->value() - m_scrollPos.x()) * pixelsPerTact(); + int vs = contentWidget()->verticalScrollBar()->value() - m_scrollPos.y(); + + //the adjusted origin point + QPoint origin = QPoint(qMax(originX - hs, m_trackHeadWidth), m_origin.y() - vs); + + //paint the rubber band rect + rubberBand()->setGeometry(QRect(origin, + contentWidget()->mapFromParent(QPoint(m_mousePos.x(), m_mousePos.y())) + ).normalized()); + + //the index of the TrackView the mouse is hover + int rubberBandTrackview = trackIndexFromSelectionPoint(m_mousePos.y()); + + //the miditime the mouse is hover + MidiTime rubberbandMidipos = MidiTime((qMin(m_mousePos.x(), width()) - m_trackHeadWidth) + / pixelsPerTact() * MidiTime::ticksPerTact()) + + m_currentPosition; + + //are tcos in the rect of selection? + for (auto &it : findChildren()) + { + TrackContentObjectView * tco = dynamic_cast(it); + if (tco) + { + auto indexOfTrackView = trackViews().indexOf(tco->getTrackView()); + bool isBeetweenRubberbandViews = indexOfTrackView >= qMin(m_rubberBandStartTrackview, rubberBandTrackview) + && indexOfTrackView <= qMax(m_rubberBandStartTrackview, rubberBandTrackview); + bool isBeetweenRubberbandMidiPos = tco->getTrackContentObject()->endPosition() >= qMin(m_rubberbandStartMidipos, rubberbandMidipos) + && tco->getTrackContentObject()->startPosition() <= qMax(m_rubberbandStartMidipos, rubberbandMidipos); + it->setSelected(isBeetweenRubberbandViews && isBeetweenRubberbandMidiPos); + } + } + } +} + + + + void SongEditor::setEditMode( EditMode mode ) { m_mode = mode; @@ -394,7 +496,7 @@ void SongEditor::wheelEvent( QWheelEvent * we ) void SongEditor::closeEvent( QCloseEvent * ce ) - { +{ if( parentWidget() ) { parentWidget()->hide(); @@ -404,7 +506,53 @@ void SongEditor::closeEvent( QCloseEvent * ce ) hide(); } ce->ignore(); - } +} + + + + +void SongEditor::mousePressEvent(QMouseEvent *me) +{ + if (allowRubberband()) + { + //we save the position of scrollbars, mouse position and zooming level + m_scrollPos = QPoint(m_leftRightScroll->value(), contentWidget()->verticalScrollBar()->value()); + m_origin = contentWidget()->mapFromParent(QPoint(me->pos().x(), me->pos().y())); + m_currentZoomingValue = zoomingModel()->value(); + + //paint the rubberband + rubberBand()->setEnabled(true); + rubberBand()->setGeometry(QRect(m_origin, QSize())); + rubberBand()->show(); + + //the trackView(index) and the miditime where the mouse was clicked + m_rubberBandStartTrackview = trackIndexFromSelectionPoint(me->y()); + m_rubberbandStartMidipos = MidiTime((me->x() - m_trackHeadWidth) + / pixelsPerTact() * MidiTime::ticksPerTact()) + + m_currentPosition; + } + QWidget::mousePressEvent(me); +} + + + + +void SongEditor::mouseMoveEvent(QMouseEvent *me) +{ + m_mousePos = me->pos(); + updateRubberband(); + QWidget::mouseMoveEvent(me); +} + + + + +void SongEditor::mouseReleaseEvent(QMouseEvent *me) +{ + rubberBand()->hide(); + rubberBand()->setEnabled(false); + QWidget::mouseReleaseEvent(me); +} @@ -602,6 +750,7 @@ void SongEditor::zoomingChanged() m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> setPixelsPerTact( pixelsPerTact() ); realignTracks(); + updateRubberband(); } @@ -615,6 +764,26 @@ bool SongEditor::allowRubberband() const +int SongEditor::trackIndexFromSelectionPoint(int yPos) +{ + const TrackView * tv = trackViewAt(yPos - m_timeLine->height()); + return tv ? indexOfTrackView(tv) + : yPos < m_timeLine->height() ? 0 + : trackViews().count(); +} + + + + +int SongEditor::indexOfTrackView(const TrackView *tv) +{ + return static_cast(std::distance(trackViews().begin(), + std::find(trackViews().begin(), trackViews().end(), tv))); +} + + + + ComboBoxModel *SongEditor::zoomingModel() const { return m_zoomingModel; diff --git a/src/gui/widgets/Rubberband.cpp b/src/gui/widgets/Rubberband.cpp index 6bf702edcb7..0a4e891b5a9 100644 --- a/src/gui/widgets/Rubberband.cpp +++ b/src/gui/widgets/Rubberband.cpp @@ -66,18 +66,6 @@ QVector RubberBand::selectedObjects() const void RubberBand::resizeEvent( QResizeEvent * _re ) { QRubberBand::resizeEvent( _re ); - if( isEnabled() ) - { - QVector so = selectableObjects(); - for( QVector::iterator it = so.begin(); - it != so.end(); ++it ) - { - ( *it )->setSelected( QRect( pos(), size() ).intersects( - QRect( ( *it )->mapTo( parentWidget(), - QPoint() ), - ( *it )->size() ) ) ); - } - } }