Change zoom in SongEditor to a Slider Zoom (#6664)
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Co-authored-by: Alex <allejok96@gmail.com>
This commit is contained in:
BIN
data/themes/classic/horizontal_slider.png
Normal file
BIN
data/themes/classic/horizontal_slider.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -418,6 +418,25 @@ lmms--gui--AutomatableSlider::handle:vertical {
|
||||
margin: -4px -12px -2px;
|
||||
}
|
||||
|
||||
/* main horizontal sliders (zoom) */
|
||||
|
||||
lmms--gui--AutomatableSlider::groove:horizontal {
|
||||
background: rgba(0,0,0, 128);
|
||||
border: 1px inset rgba(100,100,100, 64);
|
||||
border-radius: 2px;
|
||||
height: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
lmms--gui--AutomatableSlider::handle:horizontal {
|
||||
background: none;
|
||||
border-image: url(resources:horizontal_slider.png);
|
||||
width: 10px;
|
||||
height: 26px;
|
||||
border-radius: 2px;
|
||||
margin: -12px -2px;
|
||||
}
|
||||
|
||||
/* about dialog */
|
||||
QTabWidget, QTabWidget QWidget {
|
||||
background: #5b6571;
|
||||
|
||||
BIN
data/themes/default/horizontal_slider.png
Normal file
BIN
data/themes/default/horizontal_slider.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -443,6 +443,25 @@ lmms--gui--AutomatableSlider::handle:vertical {
|
||||
margin: -4px -12px -2px;
|
||||
}
|
||||
|
||||
/* main horizontal sliders (zoom) */
|
||||
|
||||
lmms--gui--AutomatableSlider::groove:horizontal {
|
||||
background: #040506;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
height: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
lmms--gui--AutomatableSlider::handle:horizontal {
|
||||
background: none;
|
||||
border-image: url(resources:horizontal_slider.png);
|
||||
width: 10px;
|
||||
height: 26px;
|
||||
border-radius: 2px;
|
||||
margin: -12px -2px;
|
||||
}
|
||||
|
||||
/* window that shows up when you add effects */
|
||||
|
||||
lmms--gui--EffectSelectDialog QScrollArea {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef LMMS_GUI_SONG_EDITOR_H
|
||||
#define LMMS_GUI_SONG_EDITOR_H
|
||||
|
||||
#include "AutomatableModel.h"
|
||||
#include "Editor.h"
|
||||
#include "TrackContainerView.h"
|
||||
|
||||
@@ -69,7 +70,6 @@ public:
|
||||
void saveSettings( QDomDocument& doc, QDomElement& element ) override;
|
||||
void loadSettings( const QDomElement& element ) override;
|
||||
|
||||
ComboBoxModel *zoomingModel() const;
|
||||
ComboBoxModel *snappingModel() const;
|
||||
float getSnapSize() const;
|
||||
QString getSnapSizeString() const;
|
||||
@@ -120,10 +120,12 @@ private:
|
||||
bool allowRubberband() const override;
|
||||
bool knifeMode() const override;
|
||||
|
||||
int calculatePixelsPerBar() const;
|
||||
int calculateZoomSliderValue(int pixelsPerBar) const;
|
||||
|
||||
int trackIndexFromSelectionPoint(int yPos);
|
||||
int indexOfTrackView(const TrackView* tv);
|
||||
|
||||
|
||||
Song * m_song;
|
||||
|
||||
QScrollBar * m_leftRightScroll;
|
||||
@@ -141,12 +143,10 @@ private:
|
||||
|
||||
PositionLine * m_positionLine;
|
||||
|
||||
ComboBoxModel* m_zoomingModel;
|
||||
IntModel* m_zoomingModel;
|
||||
ComboBoxModel* m_snappingModel;
|
||||
bool m_proportionalSnap;
|
||||
|
||||
static const QVector<float> m_zoomLevels;
|
||||
|
||||
bool m_scrollBack;
|
||||
bool m_smoothScroll;
|
||||
|
||||
@@ -158,14 +158,14 @@ private:
|
||||
QPoint m_mousePos;
|
||||
int m_rubberBandStartTrackview;
|
||||
TimePos m_rubberbandStartTimePos;
|
||||
int m_currentZoomingValue;
|
||||
int m_rubberbandPixelsPerBar; //!< pixels per bar when selection starts
|
||||
int m_trackHeadWidth;
|
||||
bool m_selectRegion;
|
||||
|
||||
friend class SongEditorWindow;
|
||||
|
||||
signals:
|
||||
void zoomingValueChanged( float );
|
||||
void pixelsPerBarChanged(float);
|
||||
} ;
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ private:
|
||||
QAction* m_selectModeAction;
|
||||
QAction* m_crtlAction;
|
||||
|
||||
ComboBox * m_zoomingComboBox;
|
||||
AutomatableSlider * m_zoomingSlider;
|
||||
ComboBox * m_snappingComboBox;
|
||||
QLabel* m_snapSizeLabel;
|
||||
|
||||
@@ -221,7 +221,6 @@ private:
|
||||
QAction* m_removeBarAction;
|
||||
};
|
||||
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
@@ -125,7 +125,7 @@ ClipView::ClipView( Clip * clip,
|
||||
|
||||
connect( m_clip, SIGNAL(lengthChanged()),
|
||||
this, SLOT(updateLength()));
|
||||
connect( getGUI()->songEditor()->m_editor->zoomingModel(), SIGNAL(dataChanged()), this, SLOT(updateLength()));
|
||||
connect(getGUI()->songEditor()->m_editor, &SongEditor::pixelsPerBarChanged, this, &ClipView::updateLength);
|
||||
connect( m_clip, SIGNAL(positionChanged()),
|
||||
this, SLOT(updatePosition()));
|
||||
connect( m_clip, SIGNAL(destroyedClip()), this, SLOT(close()));
|
||||
@@ -314,10 +314,9 @@ void ClipView::updateLength()
|
||||
}
|
||||
else
|
||||
{
|
||||
setFixedWidth(
|
||||
static_cast<int>( m_clip->length() * pixelsPerBar() /
|
||||
TimePos::ticksPerBar() ) + 1 /*+
|
||||
BORDER_WIDTH * 2-1*/ );
|
||||
// this std::max function is needed for clips that do not start or end on the beat, otherwise, they "disappear" when zooming to min
|
||||
// 3 is the minimun width needed to make a clip visible
|
||||
setFixedWidth(std::max(static_cast<int>(m_clip->length() * pixelsPerBar() / TimePos::ticksPerBar() + 1), 3));
|
||||
}
|
||||
m_trackView->trackContainerView()->update();
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@
|
||||
|
||||
#include "SongEditor.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QAction>
|
||||
#include <QKeyEvent>
|
||||
#include <QLabel>
|
||||
#include <QMdiArea>
|
||||
#include <QScrollBar>
|
||||
#include <QSlider>
|
||||
#include <QTimeLine>
|
||||
|
||||
#include "ActionGroup.h"
|
||||
@@ -57,14 +60,24 @@
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr int MIN_PIXELS_PER_BAR = 2;
|
||||
constexpr int MAX_PIXELS_PER_BAR = 400;
|
||||
constexpr int ZOOM_STEPS = 200;
|
||||
|
||||
constexpr std::array SNAP_SIZES{8.f, 4.f, 2.f, 1.f, 1/2.f, 1/4.f, 1/8.f, 1/16.f};
|
||||
constexpr std::array PROPORTIONAL_SNAP_SIZES{64.f, 32.f, 16.f, 8.f, 4.f, 2.f, 1.f, 1/2.f, 1/4.f, 1/8.f, 1/16.f, 1/32.f, 1/64.f};
|
||||
|
||||
}
|
||||
|
||||
|
||||
const QVector<float> 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 ),
|
||||
m_zoomingModel(new ComboBoxModel()),
|
||||
m_zoomingModel(new IntModel(calculateZoomSliderValue(DEFAULT_PIXELS_PER_BAR), 0, ZOOM_STEPS, nullptr, tr("Zoom"))),
|
||||
m_snappingModel(new ComboBoxModel()),
|
||||
m_proportionalSnap( false ),
|
||||
m_scrollBack( false ),
|
||||
@@ -75,7 +88,7 @@ SongEditor::SongEditor( Song * song ) :
|
||||
m_mousePos(),
|
||||
m_rubberBandStartTrackview(0),
|
||||
m_rubberbandStartTimePos(0),
|
||||
m_currentZoomingValue(m_zoomingModel->value()),
|
||||
m_rubberbandPixelsPerBar(DEFAULT_PIXELS_PER_BAR),
|
||||
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),
|
||||
@@ -83,6 +96,7 @@ SongEditor::SongEditor( Song * song ) :
|
||||
{
|
||||
m_zoomingModel->setParent(this);
|
||||
m_snappingModel->setParent(this);
|
||||
|
||||
m_timeLine = new TimeLineWidget( m_trackHeadWidth, 32,
|
||||
pixelsPerBar(),
|
||||
m_song->m_playPos[Song::Mode_PlaySong],
|
||||
@@ -103,12 +117,15 @@ SongEditor::SongEditor( Song * song ) :
|
||||
|
||||
m_positionLine = new PositionLine(this);
|
||||
static_cast<QVBoxLayout *>( layout() )->insertWidget( 1, m_timeLine );
|
||||
|
||||
|
||||
connect( m_song, SIGNAL(playbackStateChanged()),
|
||||
m_positionLine, SLOT(update()));
|
||||
connect( this, SIGNAL(zoomingValueChanged(float)),
|
||||
m_positionLine, SLOT(zoomChange(float)));
|
||||
|
||||
|
||||
// When zoom changes, update position line
|
||||
// But we must convert pixels per bar to a zoom factor where 1.0 is 100%
|
||||
connect(this, &SongEditor::pixelsPerBarChanged, m_positionLine,
|
||||
[this]() { m_positionLine->zoomChange(pixelsPerBar() / float(DEFAULT_PIXELS_PER_BAR)); });
|
||||
|
||||
// Ensure loop markers snap to same increments as clips. Zoom & proportional
|
||||
// snap changes are handled in zoomingChanged() and toggleProportionalSnap()
|
||||
connect(m_snappingModel, &ComboBoxModel::dataChanged,
|
||||
@@ -171,8 +188,8 @@ SongEditor::SongEditor( Song * song ) :
|
||||
SLOT(hideMasterVolumeFloat()));
|
||||
|
||||
m_mvsStatus = new TextFloat;
|
||||
m_mvsStatus->setTitle( tr( "Master volume" ) );
|
||||
m_mvsStatus->setPixmap( embed::getIconPixmap( "master_volume" ) );
|
||||
m_mvsStatus->setTitle(tr("Master volume"));
|
||||
m_mvsStatus->setPixmap(embed::getIconPixmap("master_volume"));
|
||||
|
||||
getGUI()->mainWindow()->addWidgetToToolBar( master_vol_lbl );
|
||||
getGUI()->mainWindow()->addWidgetToToolBar( m_masterVolumeSlider );
|
||||
@@ -240,33 +257,23 @@ SongEditor::SongEditor( Song * song ) :
|
||||
connect(contentWidget()->verticalScrollBar(), SIGNAL(valueChanged(int)),this, SLOT(updateRubberband()));
|
||||
connect(m_timeLine, SIGNAL(selectionFinished()), this, SLOT(stopSelectRegion()));
|
||||
|
||||
//zoom connects
|
||||
connect(m_zoomingModel, SIGNAL(dataChanged()), this, SLOT(zoomingChanged()));
|
||||
|
||||
//Set up zooming model
|
||||
for( float const & zoomLevel : m_zoomLevels )
|
||||
// Set up snapping model
|
||||
for (float bars : SNAP_SIZES)
|
||||
{
|
||||
m_zoomingModel->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()));
|
||||
|
||||
//Set up snapping model, 2^i
|
||||
for ( int i = 3; i >= -4; i-- )
|
||||
{
|
||||
if ( i > 0 )
|
||||
if (bars > 1.0f)
|
||||
{
|
||||
m_snappingModel->addItem( QString( "%1 Bars").arg( 1 << i ) );
|
||||
m_snappingModel->addItem(QString("%1 Bars").arg(bars));
|
||||
}
|
||||
else if ( i == 0 )
|
||||
else if (bars == 1.0f)
|
||||
{
|
||||
m_snappingModel->addItem( "1 Bar" );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_snappingModel->addItem( QString( "1/%1 Bar" ).arg( 1 << (-i) ) );
|
||||
m_snappingModel->addItem(QString("1/%1 Bar").arg(1 / bars));
|
||||
}
|
||||
}
|
||||
m_snappingModel->setInitValue( m_snappingModel->findText( "1 Bar" ) );
|
||||
@@ -291,42 +298,40 @@ void SongEditor::loadSettings( const QDomElement& element )
|
||||
|
||||
|
||||
|
||||
/*! \brief Return grid size as number of bars */
|
||||
float SongEditor::getSnapSize() const
|
||||
{
|
||||
// 1 Bar is the third value in the snapping dropdown
|
||||
int val = -m_snappingModel->value() + 3;
|
||||
float snapSize = SNAP_SIZES[m_snappingModel->value()];
|
||||
|
||||
// If proportional snap is on, we snap to finer values when zoomed in
|
||||
if (m_proportionalSnap)
|
||||
{
|
||||
val = val - m_zoomingModel->value() + 3;
|
||||
// Finds the closest available snap size
|
||||
const float optimalSize = snapSize * DEFAULT_PIXELS_PER_BAR / pixelsPerBar();
|
||||
return *std::min_element(PROPORTIONAL_SNAP_SIZES.begin(), PROPORTIONAL_SNAP_SIZES.end(), [optimalSize](float a, float b)
|
||||
{
|
||||
return std::abs(a - optimalSize) < std::abs(b - optimalSize);
|
||||
});
|
||||
}
|
||||
val = std::max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing.
|
||||
|
||||
if ( val >= 0 ){
|
||||
return 1 << val;
|
||||
}
|
||||
else {
|
||||
return 1.0 / ( 1 << -val );
|
||||
}
|
||||
return snapSize;
|
||||
}
|
||||
|
||||
QString SongEditor::getSnapSizeString() const
|
||||
{
|
||||
int val = -m_snappingModel->value() + 3;
|
||||
val = val - m_zoomingModel->value() + 3;
|
||||
val = std::max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing.
|
||||
float bars = getSnapSize();
|
||||
|
||||
if ( val >= 0 ){
|
||||
int bars = 1 << val;
|
||||
if ( bars == 1 ) { return QString("1 Bar"); }
|
||||
else
|
||||
{
|
||||
return QString( "%1 Bars" ).arg(bars);
|
||||
}
|
||||
if (bars < 1)
|
||||
{
|
||||
return QString(tr("1/%1 Bar")).arg(round(1 / bars));
|
||||
}
|
||||
else {
|
||||
int div = ( 1 << -val );
|
||||
return QString( "1/%1 Bar" ).arg(div);
|
||||
else if (bars >= 2)
|
||||
{
|
||||
return QString(tr("%1 Bars")).arg(bars);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString("1 Bar");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +372,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_rubberbandPixelsPerBar = pixelsPerBar();
|
||||
|
||||
//calculate the song position where the mouse was clicked
|
||||
m_rubberbandStartTimePos = TimePos((xStart - m_trackHeadWidth)
|
||||
@@ -399,10 +404,9 @@ void SongEditor::updateRubberband()
|
||||
int originX = m_origin.x();
|
||||
|
||||
//take care of the zooming
|
||||
if (m_currentZoomingValue != m_zoomingModel->value())
|
||||
if (m_rubberbandPixelsPerBar != pixelsPerBar())
|
||||
{
|
||||
originX = m_trackHeadWidth + (originX - m_trackHeadWidth)
|
||||
* m_zoomLevels[m_zoomingModel->value()] / m_zoomLevels[m_currentZoomingValue];
|
||||
originX = m_trackHeadWidth + (originX - m_trackHeadWidth) * pixelsPerBar() / m_rubberbandPixelsPerBar;
|
||||
}
|
||||
|
||||
//take care of the scrollbar position
|
||||
@@ -524,9 +528,13 @@ void SongEditor::keyPressEvent( QKeyEvent * ke )
|
||||
{
|
||||
selectAllClips( false );
|
||||
}
|
||||
else if (ke->key() == Qt::Key_0 && ke->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
m_zoomingModel->reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
QWidget::keyPressEvent( ke );
|
||||
QWidget::keyPressEvent(ke);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,35 +543,24 @@ void SongEditor::keyPressEvent( QKeyEvent * ke )
|
||||
|
||||
void SongEditor::wheelEvent( QWheelEvent * we )
|
||||
{
|
||||
if( we->modifiers() & Qt::ControlModifier )
|
||||
if ((we->modifiers() & Qt::ControlModifier) && (position(we).x() > m_trackHeadWidth))
|
||||
{
|
||||
int z = m_zoomingModel->value();
|
||||
|
||||
if(we->angleDelta().y() > 0)
|
||||
{
|
||||
z++;
|
||||
}
|
||||
else if(we->angleDelta().y() < 0)
|
||||
{
|
||||
z--;
|
||||
}
|
||||
z = qBound( 0, z, m_zoomingModel->size() - 1 );
|
||||
|
||||
|
||||
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];
|
||||
// scroll so the bar "selected" by the mouse x doesn't move on the screen
|
||||
|
||||
// move zoom slider (pixelsPerBar will change automatically)
|
||||
int step = we->modifiers() & Qt::ShiftModifier ? 1 : 5;
|
||||
// when Alt is pressed, wheelEvent returns delta for x coordinate (mimics horizontal mouse wheel)
|
||||
int direction = (we->angleDelta().y() + we->angleDelta().x()) > 0 ? 1 : -1;
|
||||
m_zoomingModel->incValue(step * direction);
|
||||
|
||||
// scroll to zooming around cursor's bar
|
||||
int newBar = static_cast<int>(x / pixelsPerBar());
|
||||
m_leftRightScroll->setValue(m_leftRightScroll->value() + bar - newBar);
|
||||
|
||||
// update combobox with zooming-factor
|
||||
m_zoomingModel->setValue( z );
|
||||
|
||||
// update timeline
|
||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine->
|
||||
setPixelsPerBar( pixelsPerBar() );
|
||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine->setPixelsPerBar(pixelsPerBar());
|
||||
// and make sure, all Clip's are resized and relocated
|
||||
realignTracks();
|
||||
}
|
||||
@@ -612,7 +609,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_rubberbandPixelsPerBar = pixelsPerBar();
|
||||
|
||||
//paint the rubberband
|
||||
rubberBand()->setEnabled(true);
|
||||
@@ -655,12 +652,12 @@ void SongEditor::setMasterVolume( int new_val )
|
||||
{
|
||||
updateMasterVolumeFloat( new_val );
|
||||
|
||||
if( !m_mvsStatus->isVisible() && !m_song->m_loadingProject
|
||||
if (!m_mvsStatus->isVisible() && !m_song->m_loadingProject
|
||||
&& m_masterVolumeSlider->showStatus() )
|
||||
{
|
||||
m_mvsStatus->moveGlobal( m_masterVolumeSlider,
|
||||
m_mvsStatus->moveGlobal(m_masterVolumeSlider,
|
||||
QPoint( m_masterVolumeSlider->width() + 2, -2 ) );
|
||||
m_mvsStatus->setVisibilityTimeOut( 1000 );
|
||||
m_mvsStatus->setVisibilityTimeOut(1000);
|
||||
}
|
||||
Engine::audioEngine()->setMasterGain( new_val / 100.0f );
|
||||
}
|
||||
@@ -670,7 +667,7 @@ void SongEditor::setMasterVolume( int new_val )
|
||||
|
||||
void SongEditor::showMasterVolumeFloat( void )
|
||||
{
|
||||
m_mvsStatus->moveGlobal( m_masterVolumeSlider,
|
||||
m_mvsStatus->moveGlobal(m_masterVolumeSlider,
|
||||
QPoint( m_masterVolumeSlider->width() + 2, -2 ) );
|
||||
m_mvsStatus->show();
|
||||
updateMasterVolumeFloat( m_song->m_masterVolumeModel.value() );
|
||||
@@ -681,7 +678,7 @@ void SongEditor::showMasterVolumeFloat( void )
|
||||
|
||||
void SongEditor::updateMasterVolumeFloat( int new_val )
|
||||
{
|
||||
m_mvsStatus->setText( tr( "Value: %1%" ).arg( new_val ) );
|
||||
m_mvsStatus->setText(tr("Value: %1%").arg(new_val));
|
||||
}
|
||||
|
||||
|
||||
@@ -837,17 +834,50 @@ void SongEditor::updatePositionLine()
|
||||
|
||||
|
||||
|
||||
//! Convert zoom slider's value to bar width in pixels
|
||||
int SongEditor::calculatePixelsPerBar() const
|
||||
{
|
||||
// What we need to raise 2 by to get MIN_PIXELS_PER_BAR and MAX_PIXELS_PER_BAR
|
||||
static const double minExp = std::log2(MIN_PIXELS_PER_BAR);
|
||||
static const double maxExp = std::log2(MAX_PIXELS_PER_BAR);
|
||||
static const double stepsInv = 1 / static_cast<double>(ZOOM_STEPS) * (maxExp - minExp);
|
||||
double exponent = m_zoomingModel->value() * stepsInv + minExp;
|
||||
|
||||
double ppb = std::exp2(exponent);
|
||||
|
||||
return static_cast<int>(std::round(ppb));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Convert bar width in pixels to zoom slider value
|
||||
int SongEditor::calculateZoomSliderValue(int pixelsPerBar) const
|
||||
{
|
||||
// What we need to raise 2 by to get MIN_PIXELS_PER_BAR and MAX_PIXELS_PER_BAR
|
||||
static const double minExp = std::log2(MIN_PIXELS_PER_BAR);
|
||||
static const double maxExp = std::log2(MAX_PIXELS_PER_BAR);
|
||||
double exponent = std::log2(pixelsPerBar);
|
||||
|
||||
double sliderValue = (exponent - minExp) / (maxExp - minExp) * ZOOM_STEPS;
|
||||
|
||||
return static_cast<int>(std::round(sliderValue));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SongEditor::zoomingChanged()
|
||||
{
|
||||
setPixelsPerBar( m_zoomLevels[m_zoomingModel->value()] * DEFAULT_PIXELS_PER_BAR );
|
||||
int ppb = calculatePixelsPerBar();
|
||||
setPixelsPerBar(ppb);
|
||||
|
||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine->
|
||||
setPixelsPerBar( pixelsPerBar() );
|
||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine->setPixelsPerBar(ppb);
|
||||
realignTracks();
|
||||
updateRubberband();
|
||||
m_timeLine->setSnapSize(getSnapSize());
|
||||
|
||||
emit zoomingValueChanged( m_zoomLevels[m_zoomingModel->value()] );
|
||||
|
||||
emit pixelsPerBarChanged(ppb);
|
||||
}
|
||||
|
||||
|
||||
@@ -899,14 +929,6 @@ int SongEditor::indexOfTrackView(const TrackView *tv)
|
||||
|
||||
|
||||
|
||||
ComboBoxModel *SongEditor::zoomingModel() const
|
||||
{
|
||||
return m_zoomingModel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ComboBoxModel *SongEditor::snappingModel() const
|
||||
{
|
||||
return m_snappingModel;
|
||||
@@ -991,16 +1013,19 @@ SongEditorWindow::SongEditorWindow(Song* song) :
|
||||
auto zoom_lbl = new QLabel(m_toolBar);
|
||||
zoom_lbl->setPixmap( embed::getIconPixmap( "zoom" ) );
|
||||
|
||||
//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()));
|
||||
// Set slider zoom
|
||||
m_zoomingSlider = new AutomatableSlider(m_toolBar, tr("Zoom"));
|
||||
m_zoomingSlider->setModel(m_editor->m_zoomingModel);
|
||||
m_zoomingSlider->setOrientation(Qt::Horizontal);
|
||||
m_zoomingSlider->setPageStep(1);
|
||||
m_zoomingSlider->setFocusPolicy(Qt::NoFocus);
|
||||
m_zoomingSlider->setFixedSize(100, 26);
|
||||
m_zoomingSlider->setToolTip(tr("Zoom"));
|
||||
m_zoomingSlider->setContextMenuPolicy(Qt::NoContextMenu);
|
||||
connect(m_editor->m_zoomingModel, SIGNAL(dataChanged()), this, SLOT(updateSnapLabel()));
|
||||
|
||||
zoomToolBar->addWidget( zoom_lbl );
|
||||
zoomToolBar->addWidget( m_zoomingComboBox );
|
||||
zoomToolBar->addWidget(m_zoomingSlider);
|
||||
|
||||
DropToolBar *snapToolBar = addDropToolBarToTop(tr("Snap controls"));
|
||||
auto snap_lbl = new QLabel(m_toolBar);
|
||||
@@ -1034,7 +1059,7 @@ SongEditorWindow::SongEditorWindow(Song* song) :
|
||||
|
||||
QSize SongEditorWindow::sizeHint() const
|
||||
{
|
||||
return {720, 300};
|
||||
return {900, 300};
|
||||
}
|
||||
|
||||
void SongEditorWindow::updateSnapLabel(){
|
||||
@@ -1140,3 +1165,5 @@ void SongEditorWindow::adjustUiAfterProjectLoad()
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
|
||||
|
||||
@@ -22,23 +22,29 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TimeLineWidget.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QTimer>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
#include <QToolBar>
|
||||
|
||||
|
||||
#include "TimeLineWidget.h"
|
||||
#include "embed.h"
|
||||
#include "NStateButton.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "NStateButton.h"
|
||||
#include "TextFloat.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr int MIN_BAR_LABEL_DISTANCE = 35;
|
||||
}
|
||||
|
||||
|
||||
QPixmap * TimeLineWidget::s_posMarkerPixmap = nullptr;
|
||||
|
||||
@@ -270,12 +276,14 @@ void TimeLineWidget::paintEvent( QPaintEvent * )
|
||||
int const x = m_xOffset + s_posMarkerPixmap->width() / 2 -
|
||||
( ( static_cast<int>( m_begin * m_ppb ) / TimePos::ticksPerBar() ) % static_cast<int>( m_ppb ) );
|
||||
|
||||
// Double the interval between bar numbers until they are far enough appart
|
||||
int barLabelInterval = 1;
|
||||
while (barLabelInterval * m_ppb < MIN_BAR_LABEL_DISTANCE) { barLabelInterval *= 2; }
|
||||
|
||||
for( int i = 0; x + i * m_ppb < width(); ++i )
|
||||
{
|
||||
++barNumber;
|
||||
if( ( barNumber - 1 ) %
|
||||
qMax( 1, qRound( 1.0f / 3.0f *
|
||||
TimePos::ticksPerBar() / m_ppb ) ) == 0 )
|
||||
if ((barNumber - 1) % barLabelInterval == 0)
|
||||
{
|
||||
const int cx = x + qRound( i * m_ppb );
|
||||
p.setPen( barLineColor );
|
||||
|
||||
Reference in New Issue
Block a user