From 97c48cacbfcb7a93f8c58d0f6f7f443b1beaf4ea Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 28 Mar 2024 21:39:58 +0100 Subject: [PATCH 1/6] Replace pngs with svgs Replace the pngs of the step buttons with the svgs from the previous branch. Adjust the code so they are rendered with the maximum available height. --- data/themes/default/step_btn_off.png | Bin 423 -> 0 bytes data/themes/default/step_btn_off.svg | 217 ++++++++++++++ data/themes/default/step_btn_off_light.png | Bin 410 -> 0 bytes data/themes/default/step_btn_off_light.svg | 182 ++++++++++++ data/themes/default/step_btn_on_0.png | Bin 487 -> 0 bytes data/themes/default/step_btn_on_0.svg | 325 +++++++++++++++++++++ data/themes/default/step_btn_on_200.png | Bin 407 -> 0 bytes data/themes/default/step_btn_on_200.svg | 272 +++++++++++++++++ src/gui/clips/MidiClipView.cpp | 14 +- 9 files changed, 1002 insertions(+), 8 deletions(-) delete mode 100644 data/themes/default/step_btn_off.png create mode 100644 data/themes/default/step_btn_off.svg delete mode 100644 data/themes/default/step_btn_off_light.png create mode 100644 data/themes/default/step_btn_off_light.svg delete mode 100644 data/themes/default/step_btn_on_0.png create mode 100644 data/themes/default/step_btn_on_0.svg delete mode 100644 data/themes/default/step_btn_on_200.png create mode 100644 data/themes/default/step_btn_on_200.svg diff --git a/data/themes/default/step_btn_off.png b/data/themes/default/step_btn_off.png deleted file mode 100644 index 646124a851ef17a6f86d14b331f17bb31d79d102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR46UDb6jb+O?zk|JAK`xlR8Sri_U%BTc;td zusMnKxy;`WY@wMoPdvAo6usSFGS%GFul|0i?B6BxA$(dF{v550zPS%bicJtKWC=%rVA>Vm{BzX${4BS@%mA6qGhU zxPH~5BkS0tUKY2s6PCh{RTt$vb8wv!;u6NRveUzILQe4pX?DZ40)cm3Ez|An_UkdZ zg$JjyF$l7XN;jV3xo}L$jZbSc$BS0es3)gN63Ta!gr*4^oZ2gxacx0o>dG5zXJyJK z{*m6WMeB0rR+G=Ou7ygP%g*U*KgzWAN!4t-{d;B|)E4%7u=?M&Ka9SU&K%gj>{<^n PP#HX3{an^LB{Ts5i{7W) diff --git a/data/themes/default/step_btn_off.svg b/data/themes/default/step_btn_off.svg new file mode 100644 index 00000000000..1ae4fbf1137 --- /dev/null +++ b/data/themes/default/step_btn_off.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/data/themes/default/step_btn_off_light.png b/data/themes/default/step_btn_off_light.png deleted file mode 100644 index 17a158eb49b31cab6356c1e954e9d9b99d1f4f56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4zvp1YsHEH{;(GA;_3s)Vo?cdFdQhA2caKr){=M}Kb6A_$6YBmun9jY+vd-U~ zZ+GtL9F`b{1+&gY=)7BTDof(d)i>YIS{bSy>-fIURwZarVZ?i-)ZKnQj0H0tdaO9= zEcL`s$hvIZxz(2aUMZ9FdYD zFl1F|;mZmwO5$p0yO0;*I%P($gIKqe>lBOU9dBe??l|6S3_ZD*uc + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/data/themes/default/step_btn_on_0.png b/data/themes/default/step_btn_on_0.png deleted file mode 100644 index 6b6a66b6920640f2983c86cd7ea86c68a9442644..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 487 zcmVf zMrSjYwW&)}e1~&Rcb5Q}4_w-H9hX0UeF*&Y>kI`5A##59tttHbkBh+pK!^c=gD*$8 zo!xhVmy0L<{e4_92LT@ea67vk9)8AIw;kLsna_v0Fg52)2w^NmEh%r;yQ*Eyg{c6( z6396<>A=?lwS%16ytV&12!0gUHl9}kev^Yn5v_ILM+c1}D$GH^*A5y9l!#JF+}z$) zCAW#FFcl!i)V$=vRDcv?^N0#_5U65FjUpkrNx|YAK}_W!M`p9rrgw7A dabv1Y*E9XP%UDnmA4C8E002ovPDHLkV1m;I&VT>_ diff --git a/data/themes/default/step_btn_on_0.svg b/data/themes/default/step_btn_on_0.svg new file mode 100644 index 00000000000..ccfa5616d03 --- /dev/null +++ b/data/themes/default/step_btn_on_0.svg @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/data/themes/default/step_btn_on_200.png b/data/themes/default/step_btn_on_200.png deleted file mode 100644 index b047afc185838c8da4c8d4f6d3eaf90c4087f299..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHh#SkeHa*1Myv(85kHU(9Tm&ku37p|N6mO#~MRC&rP3v z+T4?|!YzjDLFHB%*1FOXA*MMWWA5MYJTzZUj-B~6FT?Wf=02~o^b4+U(MkJ!#D|Sx z@~%frN2esI|6rdt{U4+9X7hrViyq59y#3v68I!@WWy0)E#vMMa4~(0gy(TjJk7rYD z*ygr}d7@<8L|L9K0S+lz3~SpP{O9yEo?{BjfB%SWqGVM;c)B*$NAF`SPv2yr;#ukj3_=D^S3j3^P6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index 0a6fece3168..0676a8d11e5 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -464,14 +464,12 @@ void MidiClipView::paintEvent( QPaintEvent * ) const int w = width() - 2 * BORDER_WIDTH; // scale step graphics to fit the beat clip length - stepon0 - = m_stepBtnOn0.scaled(w / steps, m_stepBtnOn0.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - stepon200 = m_stepBtnOn200.scaled( - w / steps, m_stepBtnOn200.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - stepoff - = m_stepBtnOff.scaled(w / steps, m_stepBtnOff.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - stepoffl = m_stepBtnOffLight.scaled( - w / steps, m_stepBtnOffLight.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + int const stepWidth = w / steps; + int const stepHeight = rect().height(); + stepon0 = embed::getIconPixmap("step_btn_on_0", stepWidth, stepHeight); + stepon200 = embed::getIconPixmap("step_btn_on_200", stepWidth, stepHeight); + stepoff = embed::getIconPixmap("step_btn_off", stepWidth, stepHeight); + stepoffl = embed::getIconPixmap("step_btn_off_light", stepWidth, stepHeight); for (int it = 0; it < steps; it++) // go through all the steps in the beat clip { From 26677a4d622ed8dee6fbb25abc1342476154a1a2 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 28 Mar 2024 22:50:01 +0100 Subject: [PATCH 2/6] Fix height of steps Ensure minimal height of 24 pixels like the pngs. Take border offsets into account. --- src/gui/clips/MidiClipView.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index 0676a8d11e5..e96321c8d7c 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -456,20 +456,16 @@ void MidiClipView::paintEvent( QPaintEvent * ) // Beat clip paint event (on BB Editor) if (beatClip && displayPattern) { - QPixmap stepon0; - QPixmap stepon200; - QPixmap stepoff; - QPixmap stepoffl; const int steps = std::max(1, m_clip->m_steps); const int w = width() - 2 * BORDER_WIDTH; // scale step graphics to fit the beat clip length int const stepWidth = w / steps; - int const stepHeight = rect().height(); - stepon0 = embed::getIconPixmap("step_btn_on_0", stepWidth, stepHeight); - stepon200 = embed::getIconPixmap("step_btn_on_200", stepWidth, stepHeight); - stepoff = embed::getIconPixmap("step_btn_off", stepWidth, stepHeight); - stepoffl = embed::getIconPixmap("step_btn_off_light", stepWidth, stepHeight); + int const stepHeight = std::max(24, rect().height() - 2 * BeatStepButtonOffset); + QPixmap const stepon0 = embed::getIconPixmap("step_btn_on_0", stepWidth, stepHeight); + QPixmap const stepon200 = embed::getIconPixmap("step_btn_on_200", stepWidth, stepHeight); + QPixmap const stepoff = embed::getIconPixmap("step_btn_off", stepWidth, stepHeight); + QPixmap const stepoffl = embed::getIconPixmap("step_btn_off_light", stepWidth, stepHeight); for (int it = 0; it < steps; it++) // go through all the steps in the beat clip { From 1b1df06f4679a7a4660926ebabde70e9ac1f2e7a Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 28 Mar 2024 23:18:39 +0100 Subject: [PATCH 3/6] Fix mouse clicks for larger step buttons Fix the method `mousePressEvent` so that it also works with the larger step buttons. The main change is the adjusted check for the y coordinate. All other changes are just refactoring and reformatting of the method's code. --- src/gui/clips/MidiClipView.cpp | 50 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index e96321c8d7c..1ad77b7a607 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -243,57 +243,59 @@ void MidiClipView::constructContextMenu( QMenu * _cm ) -void MidiClipView::mousePressEvent( QMouseEvent * _me ) +void MidiClipView::mousePressEvent(QMouseEvent * _me) { - bool displayPattern = fixedClips() || (pixelsPerBar() >= 96 && m_legacySEPattern); - if (_me->button() == Qt::LeftButton && m_clip->m_clipType == MidiClip::Type::BeatClip && displayPattern - && _me->y() > BeatStepButtonOffset && _me->y() < BeatStepButtonOffset + m_stepBtnOff.height()) + int const x = _me->x(); + int const y = _me->y(); - // when mouse button is pressed in pattern mode + bool const displayPattern = fixedClips() || (pixelsPerBar() >= 96 && m_legacySEPattern); + bool const isBeatClip = m_clip->m_clipType == MidiClip::Type::BeatClip; + bool const mouseClickedWithinHeight = BeatStepButtonOffset < y && y < rect().height() - BeatStepButtonOffset; + if (_me->button() == Qt::LeftButton && isBeatClip && displayPattern && mouseClickedWithinHeight) { -// get the step number that was clicked on and -// do calculations in floats to prevent rounding errors... - float tmp = ( ( float(_me->x()) - BORDER_WIDTH ) * - float( m_clip -> m_steps ) ) / float(width() - BORDER_WIDTH*2); + // Left mouse button pressed in pattern mode - int step = int( tmp ); + // Get the step number that was clicked on. Do calculations in floats to prevent rounding errors. + float const tmp = ((float(x) - BORDER_WIDTH) * float(m_clip->m_steps)) / float(width() - BORDER_WIDTH * 2); -// debugging to ensure we get the correct step... -// qDebug( "Step (%f) %d", tmp, step ); + int const step(tmp); - if( step >= m_clip->m_steps ) + // debugging to ensure we get the correct step... + // qDebug( "Step (%f) %d", tmp, step ); + + if (step >= m_clip->m_steps) { - qDebug( "Something went wrong in clip.cpp: step %d doesn't exist in clip!", step ); + qDebug("Something went wrong in clip.cpp: step %d doesn't exist in clip!", step); return; } - Note * n = m_clip->noteAtStep( step ); + Note* n = m_clip->noteAtStep(step); - if( n == nullptr ) + if (n == nullptr) { - m_clip->addStepNote( step ); + m_clip->addStepNote(step); } else // note at step found { m_clip->addJournalCheckPoint(); - m_clip->setStep( step, false ); + m_clip->setStep(step, false); } Engine::getSong()->setModified(); + update(); - if( getGUI()->pianoRoll()->currentMidiClip() == m_clip ) + auto * pianoRoll = getGUI()->pianoRoll(); + if (pianoRoll->currentMidiClip() == m_clip) { - getGUI()->pianoRoll()->update(); + pianoRoll->update(); } } else - - // if not in pattern mode, let parent class handle the event - { - ClipView::mousePressEvent( _me ); + // if not in pattern mode, let parent class handle the event + ClipView::mousePressEvent(_me); } } From 0959b6d2b1e0abd63086526baa58af7ccbf5098e Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 21 Apr 2024 11:04:50 +0200 Subject: [PATCH 4/6] Extract step computation in method Extract the computation of the selected step into a dedicated method in `MidiClipView`. The removes duplicated code in the mouse press and wheel event handling code. The method `getStep` returns an `std::optional` which contains the value of the step if the calculation was successful. It also contains the check for the height. The calculation with floats was removed in `getStep` as it should not be necessary. Adjust `MidiClipView::wheelEvent` so that it now computes the step in the same way as the mouse event handler. This reinstates the functionality to set the note velocities with the mouse wheel even if the beat pattern is enlarged. --- include/MidiClipView.h | 2 ++ src/gui/clips/MidiClipView.cpp | 55 ++++++++++++++++------------------ 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/include/MidiClipView.h b/include/MidiClipView.h index 4285bf9da0f..fba171cd2c3 100644 --- a/include/MidiClipView.h +++ b/include/MidiClipView.h @@ -85,6 +85,8 @@ protected slots: void paintEvent( QPaintEvent * pe ) override; void wheelEvent( QWheelEvent * _we ) override; +private: + std::optional getStep(const QPoint& point) const; private: QPixmap m_stepBtnOn0 = embed::getIconPixmap("step_btn_on_0"); diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index 1ad77b7a607..8861d11d300 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -245,30 +245,16 @@ void MidiClipView::constructContextMenu( QMenu * _cm ) void MidiClipView::mousePressEvent(QMouseEvent * _me) { - int const x = _me->x(); - int const y = _me->y(); + const auto optionalStep = getStep(_me->pos()); bool const displayPattern = fixedClips() || (pixelsPerBar() >= 96 && m_legacySEPattern); bool const isBeatClip = m_clip->m_clipType == MidiClip::Type::BeatClip; - bool const mouseClickedWithinHeight = BeatStepButtonOffset < y && y < rect().height() - BeatStepButtonOffset; - if (_me->button() == Qt::LeftButton && isBeatClip && displayPattern && mouseClickedWithinHeight) + if (_me->button() == Qt::LeftButton && isBeatClip && displayPattern && optionalStep.has_value()) { // Left mouse button pressed in pattern mode - // Get the step number that was clicked on. Do calculations in floats to prevent rounding errors. - float const tmp = ((float(x) - BORDER_WIDTH) * float(m_clip->m_steps)) / float(width() - BORDER_WIDTH * 2); - - int const step(tmp); - - // debugging to ensure we get the correct step... - // qDebug( "Step (%f) %d", tmp, step ); - - if (step >= m_clip->m_steps) - { - qDebug("Something went wrong in clip.cpp: step %d doesn't exist in clip!", step); - return; - } + const int step = optionalStep.value(); Note* n = m_clip->noteAtStep(step); @@ -317,21 +303,13 @@ void MidiClipView::mouseDoubleClickEvent(QMouseEvent *_me) void MidiClipView::wheelEvent(QWheelEvent * we) { + const auto optionalStep = getStep(we->pos()); + if(m_clip->m_clipType == MidiClip::Type::BeatClip && (fixedClips() || pixelsPerBar() >= 96) && - position(we).y() > height() - m_stepBtnOff.height()) + optionalStep.has_value()) { -// get the step number that was wheeled on and -// do calculations in floats to prevent rounding errors... - float tmp = ((float(position(we).x()) - BORDER_WIDTH) * - float(m_clip -> m_steps)) / float(width() - BORDER_WIDTH*2); - - int step = int( tmp ); - - if( step >= m_clip->m_steps ) - { - return; - } + const int step = optionalStep.value(); Note * n = m_clip->noteAtStep( step ); if(!n && we->angleDelta().y() > 0) @@ -670,5 +648,24 @@ void MidiClipView::paintEvent( QPaintEvent * ) painter.drawPixmap( 0, 0, m_paintPixmap ); } +std::optional MidiClipView::getStep(const QPoint& point) const +{ + const auto x = point.x(); + const auto y = point.y(); + + bool const mouseClickedWithinHeight = BeatStepButtonOffset < y && y < height() - BeatStepButtonOffset; + + int const step = (x - BORDER_WIDTH) * m_clip->m_steps / (width() - BORDER_WIDTH * 2); + + if (mouseClickedWithinHeight && step >= 0 && step < m_clip->m_steps) + { + return std::optional(step); + } + + qDebug("Something went wrong in clip.cpp: step %d doesn't exist in clip!", step); + + return std::optional(); +} + } // namespace lmms::gui From eb8017339e8559b8f95d9dde92161afe29d1d714 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 21 Apr 2024 11:47:18 +0200 Subject: [PATCH 5/6] Install SVGs in theme directories Adjust `data/themes/CMakeLists.txt` so that SVGs in the theme directories are also installed. --- data/themes/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/themes/CMakeLists.txt b/data/themes/CMakeLists.txt index 10d8df727e1..480f6f18bd6 100644 --- a/data/themes/CMakeLists.txt +++ b/data/themes/CMakeLists.txt @@ -1,4 +1,4 @@ INCLUDE(InstallHelpers) -INSTALL_DATA_SUBDIRS("themes" "*.png;*.css") +INSTALL_DATA_SUBDIRS("themes" "*.png;*.css;*.svg") From 679767820c22c1eeec0e18da7a72be4e5de0dd8c Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Mon, 22 Apr 2024 20:28:02 +0200 Subject: [PATCH 6/6] Fix rendering artifacts Fix artifacts that occur when Qt is requested to render SVGs into very small pixmaps. This is done by making sure that the SVG is always rendered into pixmaps that are at least 24x24 in size (the size of the original PNG pixmap). Adjust the pixmap drawing code so that a potentially larger source pixmap is drawn into a smaller target pixmap. --- src/gui/clips/MidiClipView.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index 8861d11d300..b70ea9165a2 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -441,11 +441,15 @@ void MidiClipView::paintEvent( QPaintEvent * ) // scale step graphics to fit the beat clip length int const stepWidth = w / steps; + // Make sure that the pixmaps will be at least 24 pixels wide. + // There are artifacts if SVGs are rendered into very small pixmaps. + int const sourcePixmapWidth = std::max(stepWidth, 24); int const stepHeight = std::max(24, rect().height() - 2 * BeatStepButtonOffset); - QPixmap const stepon0 = embed::getIconPixmap("step_btn_on_0", stepWidth, stepHeight); - QPixmap const stepon200 = embed::getIconPixmap("step_btn_on_200", stepWidth, stepHeight); - QPixmap const stepoff = embed::getIconPixmap("step_btn_off", stepWidth, stepHeight); - QPixmap const stepoffl = embed::getIconPixmap("step_btn_off_light", stepWidth, stepHeight); + + QPixmap const stepon0 = embed::getIconPixmap("step_btn_on_0", sourcePixmapWidth, stepHeight); + QPixmap const stepon200 = embed::getIconPixmap("step_btn_on_200", sourcePixmapWidth, stepHeight); + QPixmap const stepoff = embed::getIconPixmap("step_btn_off", sourcePixmapWidth, stepHeight); + QPixmap const stepoffl = embed::getIconPixmap("step_btn_off_light", sourcePixmapWidth, stepHeight); for (int it = 0; it < steps; it++) // go through all the steps in the beat clip { @@ -455,22 +459,25 @@ void MidiClipView::paintEvent( QPaintEvent * ) const int x = BORDER_WIDTH + static_cast(it * w / steps); const int y = BeatStepButtonOffset; + QRect target(x, y, stepWidth, stepHeight); + QRect source(0, 0, sourcePixmapWidth, stepHeight); + if (n) - { + { const int vol = n->getVolume(); - p.drawPixmap(x, y, stepoffl); - p.drawPixmap(x, y, stepon0); + p.drawPixmap(target, stepoffl, source); + p.drawPixmap(target, stepon0, source); p.setOpacity(std::sqrt(vol / 200.0)); - p.drawPixmap(x, y, stepon200); + p.drawPixmap(target, stepon200, source); p.setOpacity(1); } else if ((it / 4) % 2) { - p.drawPixmap(x, y, stepoffl); + p.drawPixmap(target, stepoffl, source); } else { - p.drawPixmap(x, y, stepoff); + p.drawPixmap(target, stepoff, source); } } // end for loop