hydrogen 1.2.6
LayerPreview.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2025 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <QtGui>
24#include <QtWidgets>
25
26#include <core/Hydrogen.h>
27#include <core/Basics/Song.h>
32#include <core/Basics/Note.h>
36
37using namespace H2Core;
38
40#include "../Skin.h"
41#include "../HydrogenApp.h"
43#include "LayerPreview.h"
44
45LayerPreview::LayerPreview( QWidget* pParent )
46 : QWidget( pParent )
47 , m_pInstrument( nullptr )
49 , m_nSelectedLayer( 0 )
50 , m_bMouseGrab( false )
51 , m_bGrabLeft( false )
52{
53 setAttribute(Qt::WA_OpaquePaintEvent);
54
55 setMouseTracking( true );
56
57 int width = 276;
59 width = 261;
60 }
61
63 resize( width, height );
64
65 m_speakerPixmap.load( Skin::getSvgImagePath() + "/icons/white/speaker.svg" );
66
68
70
74 this->setStyleSheet("font-size: 9px; font-weight: bold;");
75}
76
77LayerPreview::~ LayerPreview()
78{
79 //INFOLOG( "DESTROY" );
80}
81
82void LayerPreview::set_selected_component( int SelectedComponent )
83{
84 m_nSelectedComponent = SelectedComponent;
85}
86
87void LayerPreview::paintEvent(QPaintEvent *ev)
88{
89 QPainter p( this );
90
92
93 QFont fontText( pPref->getLevel2FontFamily(), getPointSize( pPref->getFontSize() ) );
94 QFont fontButton( pPref->getLevel2FontFamily(), getPointSizeButton() );
95
96 p.fillRect( ev->rect(), pPref->getColorTheme()->m_windowColor );
97
98 int nLayers = 0;
99 for ( int i = 0; i < InstrumentComponent::getMaxLayers(); i++ ) {
100 if ( m_pInstrument ) {
101 auto pComponent = m_pInstrument->get_component( m_nSelectedComponent );
102 if(pComponent) {
103 auto pLayer = pComponent->get_layer( i );
104 if ( pLayer != nullptr ) {
105 nLayers++;
106 }
107 }
108 }
109 }
110
111 // How much the color of the labels for the individual layers
112 // are allowed to diverge from the general window color.
113 int nColorScalingWidth = 90;
114 int nColorScaling = 100;
115
116 QColor layerLabelColor, layerSegmentColor;
117
118 int nLayer = 0;
119 for ( int i = InstrumentComponent::getMaxLayers() - 1; i >= 0; i-- ) {
120 int y = 20 + m_nLayerHeight * i;
121 QString label = "< - >";
122
123 if ( m_pInstrument ) {
124 auto pComponent = m_pInstrument->get_component( m_nSelectedComponent );
125 if( pComponent ) {
126 auto pLayer = pComponent->get_layer( i );
127
128 if ( pLayer && nLayers > 0 ) {
129 auto pSample = pLayer->get_sample();
130 if( pSample != nullptr) {
131 label = pSample->get_filename();
132 layerSegmentColor =
133 pPref->getColorTheme()->m_accentColor.lighter( 130 );
134 } else {
135 layerSegmentColor =
136 pPref->getColorTheme()->m_buttonRedColor;
137 }
138
139
140 int x1 = (int)( pLayer->get_start_velocity() * width() );
141 int x2 = (int)( pLayer->get_end_velocity() * width() );
142
143 // Labels for layers to the left will have a
144 // lighter color as those to the right.
145 nColorScaling =
146 static_cast<int>(std::round( static_cast<float>(nLayer) /
147 static_cast<float>(nLayers) * 2 *
148 static_cast<float>(nColorScalingWidth) ) ) -
149 nColorScalingWidth + 100;
150 layerLabelColor =
151 pPref->getColorTheme()->m_windowColor.lighter( nColorScaling );
152
153 p.fillRect( x1, 0, x2 - x1, 19, layerLabelColor );
154 p.setPen( pPref->getColorTheme()->m_windowTextColor );
155 p.setFont( fontButton );
156 p.drawText( x1, 0, x2 - x1, 20, Qt::AlignCenter, QString("%1").arg( i + 1 ) );
157
158 if ( m_nSelectedLayer == i ) {
159 p.setPen( pPref->getColorTheme()->m_highlightColor );
160 } else {
161 p.setPen( pPref->getColorTheme()->m_windowTextColor.darker( 145 ) );
162 }
163 p.drawRect( x1, 1, x2 - x1 - 1, 18 ); // bordino in alto
164
165 // layer view
166 p.fillRect( 0, y, width(), m_nLayerHeight,
167 pPref->getColorTheme()->m_windowColor );
168 p.fillRect( x1, y, x2 - x1, m_nLayerHeight, layerSegmentColor );
169
170 nLayer++;
171 }
172 else {
173 // layer view
174 p.fillRect( 0, y, width(), m_nLayerHeight,
175 pPref->getColorTheme()->m_windowColor );
176 }
177 }
178 else {
179 // layer view
180 p.fillRect( 0, y, width(), m_nLayerHeight,
181 pPref->getColorTheme()->m_windowColor );
182 }
183 }
184 else {
185 // layer view
186 p.fillRect( 0, y, width(), m_nLayerHeight,
187 pPref->getColorTheme()->m_windowColor );
188 }
189 QColor layerTextColor = pPref->getColorTheme()->m_windowTextColor;
190 layerTextColor.setAlpha( 155 );
191 p.setPen( layerTextColor );
192 p.setFont( fontText );
193 p.drawText( 10, y, width() - 10, 20, Qt::AlignLeft, QString( "%1: %2" ).arg( i + 1 ).arg( label ) );
194 p.setPen( layerTextColor.darker( 145 ) );
195 p.drawRect( 0, y, width() - 1, m_nLayerHeight );
196 }
197
198 // selected layer
199 p.setPen( pPref->getColorTheme()->m_highlightColor );
200 int y = 20 + m_nLayerHeight * m_nSelectedLayer;
201 p.drawRect( 0, y, width() - 1, m_nLayerHeight );
202}
203
207
209 // A new song got loaded
210 if ( nValue == 0 ) {
212 }
213}
214
216{
218
219 bool bSelectedLayerChanged = false;
220
221 // select the last valid layer
222 if ( m_pInstrument != nullptr ) {
223 for (int i = InstrumentComponent::getMaxLayers() - 1; i >= 0; i-- ) {
224 auto p_compo = m_pInstrument->get_component( m_nSelectedComponent );
225 if ( p_compo ) {
226 if ( p_compo->get_layer( i ) ) {
228 bSelectedLayerChanged = true;
229 break;
230 }
231 }
232 else {
234 bSelectedLayerChanged = true;
235 }
236 }
237 }
238 else {
240 bSelectedLayerChanged = true;
241 }
242
243 if ( bSelectedLayerChanged ) {
245 }
246
247 update();
248}
249
251{
252 m_bMouseGrab = false;
253 setCursor( QCursor( Qt::ArrowCursor ) );
254
255 if ( m_pInstrument == nullptr ) {
256 return;
257 }
258
259 auto pEv = static_cast<MouseEvent*>( ev );
260
261 /*
262 * We want the tooltip to still show if mouse pointer
263 * is over an active layer's boundary
264 */
265 auto pCompo = m_pInstrument->get_component( m_nSelectedComponent );
266 if ( pCompo ) {
267 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
268
269 if ( pLayer ) {
270 int x1 = (int)( pLayer->get_start_velocity() * width() );
271 int x2 = (int)( pLayer->get_end_velocity() * width() );
272
273 if ( ( pEv->position().x() < x1 + 5 ) &&
274 ( pEv->position().x() > x1 - 5 ) ){
275 setCursor( QCursor( Qt::SizeHorCursor ) );
276 showLayerStartVelocity(pLayer, ev);
277 }
278 else if ( ( pEv->position().x() < x2 + 5 ) &&
279 ( pEv->position().x() > x2 - 5 ) ) {
280 setCursor( QCursor( Qt::SizeHorCursor ) );
281 showLayerEndVelocity(pLayer, ev);
282 }
283 }
284 }
285}
286
287void LayerPreview::mousePressEvent(QMouseEvent *ev)
288{
289 const int nPosition = 0;
290
291 auto pEv = static_cast<MouseEvent*>( ev );
292
293 if ( m_pInstrument == nullptr ) {
294 return;
295 }
296 if ( pEv->position().y() < 20 ) {
297 const float fVelocity = (float)pEv->position().x() / (float)width();
298
299 if ( m_pInstrument->hasSamples() ) {
300 Note * pNote = new Note( m_pInstrument, nPosition, fVelocity );
303 }
304
305 for ( int i = 0; i < InstrumentComponent::getMaxLayers(); i++ ) {
306 auto pCompo = m_pInstrument->get_component(m_nSelectedComponent);
307 if(pCompo){
308 auto pLayer = pCompo->get_layer( i );
309 if ( pLayer ) {
310 if ( ( fVelocity > pLayer->get_start_velocity()) && ( fVelocity < pLayer->get_end_velocity() ) ) {
311 if ( i != m_nSelectedLayer ) {
313 update();
315 }
316 break;
317 }
318 }
319 }
320 }
321 }
322 else {
323 m_nSelectedLayer = ( pEv->position().y() - 20 ) / m_nLayerHeight;
324
325 update();
327
328 auto pCompo = m_pInstrument->get_component(m_nSelectedComponent);
329 if( pCompo != nullptr ) {
330 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
331 if ( pLayer != nullptr ) {
332 const float fVelocity = pLayer->get_end_velocity() - 0.01;
333 Note *note = new Note( m_pInstrument, nPosition, fVelocity );
336
337 int x1 = (int)( pLayer->get_start_velocity() * width() );
338 int x2 = (int)( pLayer->get_end_velocity() * width() );
339
340 if ( ( pEv->position().x() < x1 + 5 ) && ( pEv->position().x() > x1 - 5 ) ){
341 setCursor( QCursor( Qt::SizeHorCursor ) );
342 m_bGrabLeft = true;
343 m_bMouseGrab = true;
344 showLayerStartVelocity(pLayer, ev);
345 }
346 else if ( ( pEv->position().x() < x2 + 5 ) && ( pEv->position().x() > x2 - 5 ) ){
347 setCursor( QCursor( Qt::SizeHorCursor ) );
348 m_bGrabLeft = false;
349 m_bMouseGrab = true;
350 showLayerEndVelocity(pLayer, ev);
351 }
352 else {
353 setCursor( QCursor( Qt::ArrowCursor ) );
354 }
355 }
356 }
357 }
358}
359
360void LayerPreview::mouseMoveEvent( QMouseEvent *ev )
361{
362 if ( !m_pInstrument ) {
363 return;
364 }
365
366 auto pEv = static_cast<MouseEvent*>( ev );
367
368 int x = pEv->position().x();
369 int y = pEv->position().y();
370
371 float fVel = (float)x / (float)width();
372 if (fVel < 0 ) {
373 fVel = 0;
374 }
375 else if (fVel > 1) {
376 fVel = 1;
377 }
378
379 if ( y < 20 ) {
380 setCursor( QCursor( m_speakerPixmap ) );
381 return;
382 }
383 if ( m_bMouseGrab ) {
384 auto pLayer = m_pInstrument->get_component( m_nSelectedComponent )->get_layer( m_nSelectedLayer );
385 if ( pLayer ) {
386 if ( m_bMouseGrab ) {
387 bool bChanged = false;
388 if ( m_bGrabLeft ) {
389 if ( fVel < pLayer->get_end_velocity()) {
390 pLayer->set_start_velocity( fVel );
391 bChanged = true;
392 showLayerStartVelocity( pLayer, ev );
393 }
394 }
395 else {
396 if ( fVel > pLayer->get_start_velocity()) {
397 pLayer->set_end_velocity( fVel );
398 bChanged = true;
399 showLayerEndVelocity( pLayer, ev );
400 }
401 }
402
403 if ( bChanged ) {
404 update();
406 }
407 }
408 }
409 }
410 else {
411 m_nSelectedLayer = ( pEv->position().y() - 20 ) / m_nLayerHeight;
413 auto pComponent = m_pInstrument->get_component(m_nSelectedComponent);
414 if( pComponent ){
415 auto pLayer = pComponent->get_layer( m_nSelectedLayer );
416 if ( pLayer ) {
417 int x1 = (int)( pLayer->get_start_velocity() * width() );
418 int x2 = (int)( pLayer->get_end_velocity() * width() );
419
420 if ( ( x < x1 + 5 ) && ( x > x1 - 5 ) ){
421 setCursor( QCursor( Qt::SizeHorCursor ) );
422 showLayerStartVelocity(pLayer, ev);
423 }
424 else if ( ( x < x2 + 5 ) && ( x > x2 - 5 ) ){
425 setCursor( QCursor( Qt::SizeHorCursor ) );
426 showLayerEndVelocity(pLayer, ev);
427 }
428 else {
429 setCursor( QCursor( Qt::ArrowCursor ) );
430 QToolTip::hideText();
431 }
432 }
433 else {
434 setCursor( QCursor( Qt::ArrowCursor ) );
435 QToolTip::hideText();
436 }
437 }
438 else {
439 setCursor( QCursor( Qt::ArrowCursor ) );
440 QToolTip::hideText();
441 }
442 }
443 }
444}
445
447{
448 update();
449}
450
452{
453 return static_cast<int> (raw * 127);
454}
455
456void LayerPreview::showLayerStartVelocity( const std::shared_ptr<InstrumentLayer> pLayer,
457 QMouseEvent* pEvent )
458{
459 const float fVelo = pLayer->get_start_velocity();
460
461 auto pEv = static_cast<MouseEvent*>( pEvent );
462
463 QToolTip::showText( pEv->globalPosition().toPoint(),
464 tr( "Dec. = %1\nMIDI = %2" )
465 .arg( QString::number( fVelo, 'f', 2) )
466 .arg( getMidiVelocityFromRaw( fVelo ) +1 ),
467 this);
468}
469
470void LayerPreview::showLayerEndVelocity( const std::shared_ptr<InstrumentLayer> pLayer,
471 QMouseEvent* pEvent )
472{
473 const float fVelo = pLayer->get_end_velocity();
474
475 auto pEv = static_cast<MouseEvent*>( pEvent );
476
477 QToolTip::showText( pEv->globalPosition().toPoint(),
478 tr( "Dec. = %1\nMIDI = %2" )
479 .arg( QString::number( fVelo, 'f', 2) )
480 .arg( getMidiVelocityFromRaw( fVelo ) +1 ),
481 this);
482}
483
485{
487
488 int nPointSize;
489
490 switch( pPref->getFontSize() ) {
492 nPointSize = 6;
493 break;
495 nPointSize = 8;
496 break;
498 nPointSize = 12;
499 break;
500 }
501
502 return nPointSize;
503}
504
Sampler * getSampler() const
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:663
std::shared_ptr< Instrument > getSelectedInstrument() const
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
A note plays an associated instrument with a velocity left and right pan.
Definition Note.h:101
void set_specific_compo_id(int value)
__specific_compo_id setter
Definition Note.h:519
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ Font
Either the font size or font family have changed.
@ Colors
At least one of the colors has changed.
void noteOn(Note *pNote)
Start playing a note.
Definition Sampler.cpp:185
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
static InstrumentEditorPanel * get_instance()
virtual void mouseMoveEvent(QMouseEvent *ev) override
LayerPreview(QWidget *pParent)
virtual void mousePressEvent(QMouseEvent *ev) override
QPixmap m_speakerPixmap
void showLayerEndVelocity(const std::shared_ptr< H2Core::InstrumentLayer > pLayer, QMouseEvent *pEvent)
display a layer's end velocity in a tooltip
static const int m_nLayerHeight
void onPreferencesChanged(H2Core::Preferences::Changes changes)
int m_nSelectedComponent
virtual void drumkitLoadedEvent() override
virtual void mouseReleaseEvent(QMouseEvent *ev) override
void showLayerStartVelocity(const std::shared_ptr< H2Core::InstrumentLayer > pLayer, QMouseEvent *pEvent)
display a layer's start velocity in a tooltip
virtual void selectedInstrumentChangedEvent() override
virtual void updateSongEvent(int) override
void paintEvent(QPaintEvent *ev) override
std::shared_ptr< H2Core::Instrument > m_pInstrument
void set_selected_component(int SelectedComponent)
int getMidiVelocityFromRaw(const float raw)
convert a raw velocity value (0.0 to 1.0) into a MIDI velocity value (0 to 127)
int getPointSizeButton() const
Used to detect changed in the font.
Compatibility class to support QMouseEvent more esily in Qt5 and Qt6.
Definition MouseEvent.h:35
QPointF position() const
static QString getSvgImagePath()
Definition Skin.h:40
constexpr int getPointSize(H2Core::FontTheme::FontSize fontSize) const