-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add vertical zoom controls to SongEditor #6776
base: master
Are you sure you want to change the base?
Changes from all commits
c53f3d9
10d9512
9002145
94361c6
fb4f762
8d6d042
ee05592
cdf0ac4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -98,6 +98,7 @@ class TrackContainerView : public QWidget, public ModelView, | |||||
} | ||||||
|
||||||
void setPixelsPerBar( int ppb ); | ||||||
void setVerticalScale(double h); | ||||||
|
||||||
const TrackView * trackViewAt( const int _y ) const; | ||||||
|
||||||
|
@@ -167,6 +168,7 @@ public slots: | |||||
|
||||||
protected: | ||||||
static const int DEFAULT_PIXELS_PER_BAR = 16; | ||||||
static const int DEFAULT_TRACK_HEIGHT = 32; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would remove this constant entirely - there are already |
||||||
|
||||||
void resizeEvent( QResizeEvent * ) override; | ||||||
|
||||||
|
@@ -203,6 +205,7 @@ public slots: | |||||
QVBoxLayout * m_scrollLayout; | ||||||
|
||||||
float m_ppb; | ||||||
double m_trackHeightScale; | ||||||
|
||||||
RubberBand * m_rubberBand; | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -58,13 +58,17 @@ namespace lmms::gui | |||||
{ | ||||||
|
||||||
|
||||||
const QVector<float> SongEditor::m_zoomLevels = | ||||||
const QVector<float> SongEditor::m_zoomXLevels = | ||||||
{ 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f }; | ||||||
|
||||||
const QVector<float> SongEditor::m_zoomYLevels = | ||||||
{ 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.5f, 3.0f, 4.0f, 8.0f, 16.0f }; | ||||||
Comment on lines
+64
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any particular reason for these specific values? You may also want to look at #6664, which is changing the horizontal zoom control to a continuous slider. |
||||||
|
||||||
Comment on lines
+61
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These can be removed after making them constexpr. |
||||||
SongEditor::SongEditor( Song * song ) : | ||||||
TrackContainerView( song ), | ||||||
m_song( song ), | ||||||
m_zoomingModel(new ComboBoxModel()), | ||||||
m_zoomingXModel(new ComboBoxModel()), | ||||||
m_zoomingYModel(new ComboBoxModel()), | ||||||
m_snappingModel(new ComboBoxModel()), | ||||||
m_proportionalSnap( false ), | ||||||
m_scrollBack( false ), | ||||||
|
@@ -75,13 +79,14 @@ SongEditor::SongEditor( Song * song ) : | |||||
m_mousePos(), | ||||||
m_rubberBandStartTrackview(0), | ||||||
m_rubberbandStartTimePos(0), | ||||||
m_currentZoomingValue(m_zoomingModel->value()), | ||||||
m_currentZoomingValue(m_zoomingXModel->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); | ||||||
m_zoomingXModel->setParent(this); | ||||||
m_zoomingYModel->setParent(this); | ||||||
m_snappingModel->setParent(this); | ||||||
m_timeLine = new TimeLineWidget( m_trackHeadWidth, 32, | ||||||
pixelsPerBar(), | ||||||
|
@@ -242,16 +247,22 @@ SongEditor::SongEditor( Song * song ) : | |||||
|
||||||
|
||||||
//Set up zooming model | ||||||
for( float const & zoomLevel : m_zoomLevels ) | ||||||
for(const auto& zoomLevel : m_zoomXLevels) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
style |
||||||
{ | ||||||
m_zoomingXModel->addItem(QString("%1\%").arg(zoomLevel * 100)); | ||||||
} | ||||||
m_zoomingXModel->setInitValue(m_zoomingXModel->findText("100%")); | ||||||
connect(m_zoomingXModel, SIGNAL(dataChanged()), this, SLOT(zoomingChanged())); | ||||||
connect(m_zoomingXModel, SIGNAL(dataChanged()), m_positionLine, SLOT(update())); | ||||||
Comment on lines
+255
to
+256
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'd be better to avoid the SIGNAL and SLOT macros and use the newer way of calling connect. |
||||||
|
||||||
// Set up Y-axis zooming model | ||||||
for(const auto& zoomLevel : m_zoomYLevels) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
style |
||||||
{ | ||||||
m_zoomingModel->addItem( QString( "%1\%" ).arg( zoomLevel * 100 ) ); | ||||||
m_zoomingYModel->addItem(QString("%1\%").arg(zoomLevel * 100)); | ||||||
} | ||||||
m_zoomingModel->setInitValue( | ||||||
m_zoomingModel->findText( "100%" ) ); | ||||||
connect( m_zoomingModel, SIGNAL(dataChanged()), | ||||||
this, SLOT(zoomingChanged())); | ||||||
connect( m_zoomingModel, SIGNAL(dataChanged()), | ||||||
m_positionLine, SLOT(update())); | ||||||
m_zoomingYModel->setInitValue(m_zoomingYModel->findText("100%")); | ||||||
connect(m_zoomingYModel, SIGNAL(dataChanged()), this, SLOT(zoomingYChanged())); | ||||||
|
||||||
|
||||||
//Set up snapping model, 2^i | ||||||
for ( int i = 3; i >= -4; i-- ) | ||||||
|
@@ -298,7 +309,7 @@ float SongEditor::getSnapSize() const | |||||
// If proportional snap is on, we snap to finer values when zoomed in | ||||||
if (m_proportionalSnap) | ||||||
{ | ||||||
val = val - m_zoomingModel->value() + 3; | ||||||
val = val - m_zoomingXModel->value() + 3; | ||||||
} | ||||||
val = std::max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing. | ||||||
|
||||||
|
@@ -313,7 +324,7 @@ float SongEditor::getSnapSize() const | |||||
QString SongEditor::getSnapSizeString() const | ||||||
{ | ||||||
int val = -m_snappingModel->value() + 3; | ||||||
val = val - m_zoomingModel->value() + 3; | ||||||
val = val - m_zoomingXModel->value() + 3; | ||||||
val = std::max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing. | ||||||
|
||||||
if ( val >= 0 ){ | ||||||
|
@@ -367,7 +378,7 @@ void SongEditor::selectRegionFromPixels(int xStart, int xEnd) | |||||
//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(); | ||||||
m_currentZoomingValue = zoomingXModel()->value(); | ||||||
|
||||||
//calculate the song position where the mouse was clicked | ||||||
m_rubberbandStartTimePos = TimePos((xStart - m_trackHeadWidth) | ||||||
|
@@ -399,10 +410,10 @@ void SongEditor::updateRubberband() | |||||
int originX = m_origin.x(); | ||||||
|
||||||
//take care of the zooming | ||||||
if (m_currentZoomingValue != m_zoomingModel->value()) | ||||||
if (m_currentZoomingValue != m_zoomingXModel->value()) | ||||||
{ | ||||||
originX = m_trackHeadWidth + (originX - m_trackHeadWidth) | ||||||
* m_zoomLevels[m_zoomingModel->value()] / m_zoomLevels[m_currentZoomingValue]; | ||||||
* m_zoomXLevels[m_zoomingXModel->value()] / m_zoomXLevels[m_currentZoomingValue]; | ||||||
} | ||||||
|
||||||
//take care of the scrollbar position | ||||||
|
@@ -537,7 +548,7 @@ void SongEditor::wheelEvent( QWheelEvent * we ) | |||||
{ | ||||||
if( we->modifiers() & Qt::ControlModifier ) | ||||||
{ | ||||||
int z = m_zoomingModel->value(); | ||||||
int z = m_zoomingXModel->value(); | ||||||
|
||||||
if(we->angleDelta().y() > 0) | ||||||
{ | ||||||
|
@@ -547,19 +558,19 @@ void SongEditor::wheelEvent( QWheelEvent * we ) | |||||
{ | ||||||
z--; | ||||||
} | ||||||
z = qBound( 0, z, m_zoomingModel->size() - 1 ); | ||||||
z = qBound(0, z, m_zoomingXModel->size() - 1); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
We're trying to get away from Qt-specific functions where we can. You may need to include <algorithm> for this. |
||||||
|
||||||
|
||||||
int x = position(we).x() - m_trackHeadWidth; | ||||||
// bar based on the mouse x-position where the scroll wheel was used | ||||||
int bar = x / pixelsPerBar(); | ||||||
// what would be the bar in the new zoom level on the very same mouse x | ||||||
int newBar = x / DEFAULT_PIXELS_PER_BAR / m_zoomLevels[z]; | ||||||
int newBar = x / DEFAULT_PIXELS_PER_BAR / m_zoomXLevels[z]; | ||||||
// scroll so the bar "selected" by the mouse x doesn't move on the screen | ||||||
m_leftRightScroll->setValue(m_leftRightScroll->value() + bar - newBar); | ||||||
|
||||||
// update combobox with zooming-factor | ||||||
m_zoomingModel->setValue( z ); | ||||||
m_zoomingXModel->setValue(z); | ||||||
|
||||||
// update timeline | ||||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> | ||||||
|
@@ -612,7 +623,7 @@ void SongEditor::mousePressEvent(QMouseEvent *me) | |||||
//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(); | ||||||
m_currentZoomingValue = zoomingXModel()->value(); | ||||||
|
||||||
//paint the rubberband | ||||||
rubberBand()->setEnabled(true); | ||||||
|
@@ -839,17 +850,21 @@ void SongEditor::updatePositionLine() | |||||
|
||||||
void SongEditor::zoomingChanged() | ||||||
{ | ||||||
setPixelsPerBar( m_zoomLevels[m_zoomingModel->value()] * DEFAULT_PIXELS_PER_BAR ); | ||||||
|
||||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> | ||||||
setPixelsPerBar( pixelsPerBar() ); | ||||||
setPixelsPerBar(m_zoomXLevels[m_zoomingXModel->value()] * DEFAULT_PIXELS_PER_BAR); | ||||||
|
||||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine->setPixelsPerBar(pixelsPerBar()); | ||||||
realignTracks(); | ||||||
updateRubberband(); | ||||||
m_timeLine->setSnapSize(getSnapSize()); | ||||||
|
||||||
emit zoomingValueChanged( m_zoomLevels[m_zoomingModel->value()] ); | ||||||
emit zoomingValueChanged(m_zoomXLevels[m_zoomingXModel->value()]); | ||||||
} | ||||||
|
||||||
void SongEditor::zoomingYChanged() | ||||||
{ | ||||||
setVerticalScale(m_zoomYLevels[m_zoomingYModel->value()]); | ||||||
updatePositionLine(); | ||||||
} | ||||||
|
||||||
void SongEditor::selectAllClips( bool select ) | ||||||
{ | ||||||
|
@@ -899,12 +914,15 @@ int SongEditor::indexOfTrackView(const TrackView *tv) | |||||
|
||||||
|
||||||
|
||||||
ComboBoxModel *SongEditor::zoomingModel() const | ||||||
ComboBoxModel* SongEditor::zoomingXModel() const | ||||||
{ | ||||||
return m_zoomingModel; | ||||||
return m_zoomingXModel; | ||||||
} | ||||||
|
||||||
|
||||||
ComboBoxModel* SongEditor::zoomingYModel() const | ||||||
{ | ||||||
return m_zoomingYModel; | ||||||
} | ||||||
|
||||||
|
||||||
ComboBoxModel *SongEditor::snappingModel() const | ||||||
|
@@ -988,19 +1006,29 @@ SongEditorWindow::SongEditorWindow(Song* song) : | |||||
|
||||||
DropToolBar *zoomToolBar = addDropToolBarToTop(tr("Zoom controls")); | ||||||
|
||||||
auto zoom_lbl = new QLabel(m_toolBar); | ||||||
zoom_lbl->setPixmap( embed::getIconPixmap( "zoom" ) ); | ||||||
auto zoomx_lbl = new QLabel(m_toolBar); | ||||||
zoomx_lbl->setPixmap(embed::getIconPixmap("zoom_x")); | ||||||
auto zoomy_lbl = new QLabel(m_toolBar); | ||||||
Comment on lines
+1009
to
+1011
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
zoomy_lbl->setPixmap(embed::getIconPixmap("zoom_y")); | ||||||
|
||||||
//Set up zooming-stuff | ||||||
m_zoomingComboBox = new ComboBox( m_toolBar ); | ||||||
m_zoomingComboBox->setFixedSize( 80, ComboBox::DEFAULT_HEIGHT ); | ||||||
m_zoomingComboBox->move( 580, 4 ); | ||||||
m_zoomingComboBox->setModel(m_editor->m_zoomingModel); | ||||||
m_zoomingComboBox->setToolTip(tr("Horizontal zooming")); | ||||||
connect(m_editor->zoomingModel(), SIGNAL(dataChanged()), this, SLOT(updateSnapLabel())); | ||||||
|
||||||
zoomToolBar->addWidget( zoom_lbl ); | ||||||
zoomToolBar->addWidget( m_zoomingComboBox ); | ||||||
m_zoomingXComboBox = new ComboBox(m_toolBar); | ||||||
m_zoomingXComboBox->setFixedSize(80, ComboBox::DEFAULT_HEIGHT); | ||||||
m_zoomingXComboBox->move(580, 4); | ||||||
m_zoomingXComboBox->setModel(m_editor->m_zoomingXModel); | ||||||
m_zoomingXComboBox->setToolTip(tr("Horizontal zooming")); | ||||||
connect(m_editor->zoomingXModel(), SIGNAL(dataChanged()), this, SLOT(updateSnapLabel())); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The SIGNAL and SLOT macros can be removed here too |
||||||
|
||||||
m_zoomingYComboBox = new ComboBox(m_toolBar); | ||||||
m_zoomingYComboBox->setFixedSize(80, ComboBox::DEFAULT_HEIGHT); | ||||||
m_zoomingYComboBox->move(580, 4); | ||||||
m_zoomingYComboBox->setModel(m_editor->m_zoomingYModel); | ||||||
m_zoomingYComboBox->setToolTip(tr("Vertical zooming")); | ||||||
|
||||||
zoomToolBar->addWidget(zoomx_lbl); | ||||||
zoomToolBar->addWidget(m_zoomingXComboBox); | ||||||
zoomToolBar->addWidget(zoomy_lbl); | ||||||
zoomToolBar->addWidget(m_zoomingYComboBox); | ||||||
|
||||||
DropToolBar *snapToolBar = addDropToolBarToTop(tr("Snap controls")); | ||||||
auto snap_lbl = new QLabel(m_toolBar); | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,6 +84,7 @@ TrackContainerView::TrackContainerView( TrackContainer * _tc ) : | |
m_trackViews(), | ||
m_scrollArea( new scrollArea( this ) ), | ||
m_ppb( DEFAULT_PIXELS_PER_BAR ), | ||
m_trackHeightScale(1), | ||
m_rubberBand( new RubberBand( m_scrollArea ) ) | ||
{ | ||
m_tc->setHook( this ); | ||
|
@@ -280,7 +281,13 @@ TrackView * TrackContainerView::createTrackView( Track * _t ) | |
if (trackView->getTrack() == _t) { return trackView; } | ||
} | ||
|
||
return _t->createView( this ); | ||
auto trackView = _t->createView(this); | ||
|
||
int height = lround(m_trackHeightScale * DEFAULT_TRACK_HEIGHT); | ||
trackView->setFixedHeight(height); | ||
trackView->getTrack()->setHeight(height); | ||
Comment on lines
+286
to
+288
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will overwrite any custom height when creating the view for a track, which will affect loading tracks from files and cloning tracks. |
||
|
||
return trackView; | ||
} | ||
|
||
|
||
|
@@ -349,6 +356,32 @@ void TrackContainerView::setPixelsPerBar( int ppb ) | |
} | ||
} | ||
|
||
void TrackContainerView::setVerticalScale(double h) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Surely there's a better name than |
||
{ | ||
for (const auto& trackView : m_trackViews) | ||
{ | ||
int new_height = lround(h * DEFAULT_TRACK_HEIGHT); | ||
int cur_height = trackView->getTrack()->getHeight(); | ||
|
||
// If a track has been manually resized, calculate the new height by scaling the old height rather than just setting it. | ||
if(cur_height != lround((m_trackHeightScale * DEFAULT_TRACK_HEIGHT))) | ||
{ | ||
new_height = lround(cur_height * (h / m_trackHeightScale)); | ||
} | ||
|
||
// clamp the value to prevent it from becoming smaller than the zoom level. | ||
if(new_height < lround(h * DEFAULT_TRACK_HEIGHT)) | ||
{ | ||
new_height = lround(h * DEFAULT_TRACK_HEIGHT); | ||
} | ||
Comment on lines
+372
to
+376
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use |
||
|
||
trackView->setFixedHeight(new_height); | ||
trackView->getTrack()->setHeight(new_height); | ||
} | ||
|
||
m_trackHeightScale = h; | ||
} | ||
|
||
|
||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use constexpr arrays instead.