hydrogen 1.2.6
PatternEditorPanel.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 <core/Hydrogen.h>
26#include <core/Basics/Pattern.h>
28#include <core/EventQueue.h>
29using namespace H2Core;
30
31
32#include "HydrogenApp.h"
33#include "PatternEditorPanel.h"
35#include "PatternEditorRuler.h"
36#include "NotePropertiesRuler.h"
37#include "DrumPatternEditor.h"
38#include "PianoRollEditor.h"
39
40#include "../UndoActions.h"
41#include "../MainForm.h"
42#include "../Widgets/Button.h"
44#include "../Widgets/Fader.h"
46#include "../Widgets/LCDCombo.h"
48#include "../WidgetScrollArea.h"
49
50#include "../CommonStrings.h"
52
53#include <cmath>
54
55
57{
59
60 QFont font( Preferences::get_instance()->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
61 font.setBold( true );
62 m_pSLlabel->setFont( font );
63 m_pSLlabel->setText( Hydrogen::get_instance()->getLastLoadedDrumkitName() );
64}
65
66
68 : QWidget( pParent )
69 , m_pPattern( nullptr )
72{
73 setAcceptDrops(true);
74
76
77 QFont boldFont( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
78 boldFont.setBold( true );
79
82
83 // Spacing between a label and the widget to its label.
84 const int nLabelSpacing = 6;
85// Editor TOP
86
87 m_pEditorTop1 = new QWidget( nullptr );
88 m_pEditorTop1->setFixedHeight(24);
89 m_pEditorTop1->setObjectName( "editor1" );
90
91 m_pEditorTop2 = new QWidget( nullptr );
92 m_pEditorTop2->setFixedHeight( 24 );
93 m_pEditorTop2->setObjectName( "editor2" );
94
95 QHBoxLayout *m_pEditorTop1_hbox = new QHBoxLayout( m_pEditorTop1 );
96 m_pEditorTop1_hbox->setSpacing( 0 );
97 m_pEditorTop1_hbox->setContentsMargins( 0, 0, 0, 0 );
98 m_pEditorTop1_hbox->setAlignment( Qt::AlignLeft );
99
100 QHBoxLayout *m_pEditorTop1_hbox_2 = new QHBoxLayout( m_pEditorTop2 );
101 m_pEditorTop1_hbox_2->setSpacing( 2 );
102 m_pEditorTop1_hbox_2->setContentsMargins( 0, 0, 0, 0 );
103 m_pEditorTop1_hbox_2->setAlignment( Qt::AlignLeft );
104
105
106 //soundlibrary name
107 m_pSLlabel = new QLabel( nullptr );
108 m_pSLlabel->setFont( boldFont );
109 m_pSLlabel->setText( Hydrogen::get_instance()->getLastLoadedDrumkitName() );
110 m_pSLlabel->setFixedSize( 170, 20 );
111 m_pSLlabel->move( 10, 3 );
112 m_pSLlabel->setToolTip( tr( "Loaded Soundlibrary" ) );
113 m_pEditorTop1_hbox->addWidget( m_pSLlabel );
114
115//wolke some background images back_size_res
116 m_pSizeResol = new QWidget( nullptr );
117 m_pSizeResol->setObjectName( "sizeResol" );
118 m_pSizeResol->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
119 m_pSizeResol->move( 0, 3 );
120 m_pEditorTop1_hbox_2->addWidget( m_pSizeResol );
121
122 QHBoxLayout* pSizeResolLayout = new QHBoxLayout( m_pSizeResol );
123 pSizeResolLayout->setContentsMargins( 2, 0, 2, 0 );
124 pSizeResolLayout->setSpacing( 2 );
125
126 // PATTERN size
127 m_pPatternSizeLbl = new ClickableLabel( m_pSizeResol, QSize( 0, 0 ), HydrogenApp::get_instance()->getCommonStrings()->getPatternSizeLabel(), ClickableLabel::Color::Dark );
128 m_pPatternSizeLbl->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
129 pSizeResolLayout->addWidget( m_pPatternSizeLbl );
130
131 m_pLCDSpinBoxNumerator = new LCDSpinBox( this, QSize( 62, 20 ), LCDSpinBox::Type::Double, 0.1, 16.0, true );
134 connect( m_pLCDSpinBoxNumerator, SIGNAL( valueChanged( double ) ), this, SLOT( patternSizeChanged( double ) ) );
135 m_pLCDSpinBoxNumerator->setKeyboardTracking( false );
136 m_pLCDSpinBoxNumerator->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
137 pSizeResolLayout->addWidget( m_pLCDSpinBoxNumerator );
138
139 QLabel* pLabel1 = new ClickableLabel( m_pSizeResol, QSize( 4, 13 ), "/", ClickableLabel::Color::Dark );
140 pLabel1->resize( QSize( 20, 17 ) );
141 pLabel1->setText( "/" );
142 pLabel1->setFont( boldFont );
143 pLabel1->setToolTip( tr( "You can use the '/' inside the pattern size spin boxes to switch back and forth." ) );
144 pLabel1->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
145 pSizeResolLayout->addWidget( pLabel1 );
146
147 m_pLCDSpinBoxDenominator = new LCDSpinBox( m_pSizeResol, QSize( 48, 20 ), LCDSpinBox::Type::Int, 1, 192, true );
150 connect( m_pLCDSpinBoxDenominator, SIGNAL( valueChanged( double ) ), this, SLOT( patternSizeChanged( double ) ) );
151 m_pLCDSpinBoxDenominator->setKeyboardTracking( false );
152 m_pLCDSpinBoxDenominator->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
153 pSizeResolLayout->addWidget( m_pLCDSpinBoxDenominator );
154 pSizeResolLayout->addSpacing( nLabelSpacing );
155
156 // GRID resolution
157 m_pResolutionLbl = new ClickableLabel( m_pSizeResol, QSize( 0, 0 ), HydrogenApp::get_instance()->getCommonStrings()->getResolutionLabel(), ClickableLabel::Color::Dark );
158 m_pResolutionLbl->setAlignment( Qt::AlignRight );
159 m_pResolutionLbl->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
160 pSizeResolLayout->addWidget( m_pResolutionLbl );
161
162 m_pResolutionCombo = new LCDCombo( m_pSizeResol, QSize( 0, 0 ), true );
163 // Large enough for "1/32T" to be fully visible at large font size.
164 // m_pResolutionCombo->setToolTip(tr( "Select grid resolution" ));
165 m_pResolutionCombo->insertItem( 0, QString( "1/4 - " )
166 .append( tr( "quarter" ) ) );
167 m_pResolutionCombo->insertItem( 1, QString( "1/8 - " )
168 .append( tr( "eighth" ) ) );
169 m_pResolutionCombo->insertItem( 2, QString( "1/16 - " )
170 .append( tr( "sixteenth" ) ) );
171 m_pResolutionCombo->insertItem( 3, QString( "1/32 - " )
172 .append( tr( "thirty-second" ) ) );
173 m_pResolutionCombo->insertItem( 4, QString( "1/64 - " )
174 .append( tr( "sixty-fourth" ) ) );
175 m_pResolutionCombo->insertSeparator( 5 );
176 m_pResolutionCombo->insertItem( 6, QString( "1/4T - " )
177 .append( tr( "quarter triplet" ) ) );
178 m_pResolutionCombo->insertItem( 7, QString( "1/8T - " )
179 .append( tr( "eighth triplet" ) ) );
180 m_pResolutionCombo->insertItem( 8, QString( "1/16T - " )
181 .append( tr( "sixteenth triplet" ) ) );
182 m_pResolutionCombo->insertItem( 9, QString( "1/32T - " )
183 .append( tr( "thirty-second triplet" ) ) );
184 m_pResolutionCombo->insertSeparator( 10 );
185 m_pResolutionCombo->insertItem( 11, tr( "off" ) );
186 m_pResolutionCombo->setMinimumSize( QSize( 24, 18 ) );
187 m_pResolutionCombo->setMaximumSize( QSize( 500, 18 ) );
188 m_pResolutionCombo->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
189 // is triggered from inside PatternEditorPanel()
190 connect( m_pResolutionCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( gridResolutionChanged( int ) ) );
191 pSizeResolLayout->addWidget( m_pResolutionCombo );
192
193 m_pRec = new QWidget( nullptr );
194 m_pRec->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
195 m_pRec->setObjectName( "pRec" );
196 m_pRec->move( 0, 3 );
197 m_pEditorTop1_hbox_2->addWidget( m_pRec );
198
199 QHBoxLayout* pRecLayout = new QHBoxLayout( m_pRec );
200 pRecLayout->setContentsMargins( 2, 0, 2, 0 );
201 pRecLayout->setSpacing( 2 );
202
203 // Hear notes btn
204 m_pHearNotesLbl = new ClickableLabel( m_pRec, QSize( 0, 0 ), HydrogenApp::get_instance()->getCommonStrings()->getHearNotesLabel(), ClickableLabel::Color::Dark );
205 m_pHearNotesLbl->setAlignment( Qt::AlignRight );
206 m_pHearNotesLbl->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
207 pRecLayout->addWidget( m_pHearNotesLbl );
208
209 m_pHearNotesBtn = new Button( m_pRec, QSize( 21, 18 ), Button::Type::Toggle,
210 "speaker.svg", "", false, QSize( 15, 13 ),
211 tr( "Hear new notes" ), false, true );
212 connect( m_pHearNotesBtn, SIGNAL( clicked() ), this, SLOT( hearNotesBtnClick() ) );
213 m_pHearNotesBtn->setChecked( pPref->getHearNewNotes() );
214 m_pHearNotesBtn->setObjectName( "HearNotesBtn" );
215 m_pHearNotesBtn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
216 pRecLayout->addWidget( m_pHearNotesBtn );
217 pRecLayout->addSpacing( nLabelSpacing );
218
219 // quantize
220 m_pQuantizeEventsLbl = new ClickableLabel( m_pRec, QSize( 0, 0 ), HydrogenApp::get_instance()->getCommonStrings()->getQuantizeEventsLabel(), ClickableLabel::Color::Dark );
221 m_pQuantizeEventsLbl->setAlignment( Qt::AlignRight );
222 m_pQuantizeEventsLbl->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
223 pRecLayout->addWidget( m_pQuantizeEventsLbl );
224
225 m_pQuantizeEventsBtn = new Button( m_pRec, QSize( 21, 18 ),
226 Button::Type::Toggle, "quantization.svg",
227 "", false, QSize( 15, 14 ),
228 tr( "Quantize keyboard/midi events to grid" ),
229 false, true );
230 m_pQuantizeEventsBtn->setChecked( pPref->getQuantizeEvents() );
231 m_pQuantizeEventsBtn->setObjectName( "QuantizeEventsBtn" );
232 connect( m_pQuantizeEventsBtn, SIGNAL( clicked() ), this, SLOT( quantizeEventsBtnClick() ) );
233 m_pQuantizeEventsBtn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
234 pRecLayout->addWidget( m_pQuantizeEventsBtn );
235 pRecLayout->addSpacing( nLabelSpacing );
236
237 // Editor mode
238 m_pShowPianoLbl = new ClickableLabel( m_pRec, QSize( 0, 0 ), HydrogenApp::get_instance()->getCommonStrings()->getShowPianoLabel(), ClickableLabel::Color::Dark );
239 m_pShowPianoLbl->setAlignment( Qt::AlignRight );
240 m_pShowPianoLbl->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
241 pRecLayout->addWidget( m_pShowPianoLbl );
242
243 __show_drum_btn = new Button( m_pRec, QSize( 25, 18 ), Button::Type::Push, "drum.svg", "", false, QSize( 17, 13 ), HydrogenApp::get_instance()->getCommonStrings()->getShowPianoRollEditorTooltip() );
244 __show_drum_btn->setObjectName( "ShowDrumBtn" );
245 connect( __show_drum_btn, SIGNAL( clicked() ), this, SLOT( showDrumEditorBtnClick() ) );
246 __show_drum_btn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
247 pRecLayout->addWidget( __show_drum_btn );
248
249 m_pEditorTop1_hbox_2->addStretch();
250
251 // Since the button to activate the piano roll is shown
252 // initially, both buttons get the same tooltip. Actually only the
253 // last one does need a tooltip since it will be shown regardless
254 // of whether it is hidden or not. But since this behavior might
255 // change in future versions of Qt the tooltip will be assigned to
256 // both of them.
257 __show_piano_btn = new Button( m_pRec, QSize( 25, 18 ), Button::Type::Push, "piano.svg", "", false, QSize( 19, 15 ), HydrogenApp::get_instance()->getCommonStrings()->getShowPianoRollEditorTooltip() );
258 __show_piano_btn->move( 178, 1 );
259 __show_piano_btn->setObjectName( "ShowPianoBtn" );
260 __show_piano_btn->hide();
261 connect( __show_piano_btn, SIGNAL( clicked() ), this, SLOT( showDrumEditorBtnClick() ) );
262 __show_piano_btn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
263 pRecLayout->addWidget( __show_piano_btn );
264
265 // zoom-in btn
266 Button *zoom_in_btn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Push, "plus.svg", "", false, QSize( 9, 9 ), tr( "Zoom in" ) );
267 connect( zoom_in_btn, SIGNAL( clicked() ), this, SLOT( zoomInBtnClicked() ) );
268
269
270 // zoom-out btn
271 Button *zoom_out_btn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Push, "minus.svg", "", false, QSize( 9, 9 ), tr( "Zoom out" ) );
272 connect( zoom_out_btn, SIGNAL( clicked() ), this, SLOT( zoomOutBtnClicked() ) );
273// End Editor TOP
274
275
276// RULER____________________________________
277
278 // Ruler ScrollView
279 m_pRulerScrollView = new WidgetScrollArea( nullptr );
280 m_pRulerScrollView->setFocusPolicy( Qt::NoFocus );
281 m_pRulerScrollView->setFrameShape( QFrame::NoFrame );
282 m_pRulerScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
283 m_pRulerScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
284 m_pRulerScrollView->setFixedHeight( 25 );
285 // Ruler
287 m_pPatternEditorRuler->setFocusPolicy( Qt::ClickFocus );
288
290 connect( m_pRulerScrollView->horizontalScrollBar(), SIGNAL( valueChanged( int ) ), this,
291 SLOT( on_patternEditorHScroll( int ) ) );
294
295
296// ~ RULER
297
298
299// EDITOR _____________________________________
300 // Editor scrollview
301 m_pEditorScrollView = new WidgetScrollArea( nullptr );
302 m_pEditorScrollView->setObjectName( "EditorScrollView" );
303 m_pEditorScrollView->setFocusPolicy( Qt::NoFocus );
304 m_pEditorScrollView->setFrameShape( QFrame::NoFrame );
305 m_pEditorScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
306 m_pEditorScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
307
308
309 // Editor
311
313 m_pEditorScrollView->setFocusPolicy( Qt::ClickFocus );
315
317
318 connect( m_pEditorScrollView->verticalScrollBar(), SIGNAL( valueChanged( int ) ), this,
319 SLOT( on_patternEditorVScroll( int ) ) );
320 connect( m_pEditorScrollView->horizontalScrollBar(), SIGNAL( valueChanged( int ) ), this,
321 SLOT( on_patternEditorHScroll( int ) ) );
324
325//PianoRollEditor
327 m_pPianoRollScrollView->setObjectName( "PianoRollScrollView" );
328 m_pPianoRollScrollView->setFocusPolicy( Qt::NoFocus );
329 m_pPianoRollScrollView->setFrameShape( QFrame::NoFrame );
330 m_pPianoRollScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
331 m_pPianoRollScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
334 connect( m_pPianoRollScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
335 this, SLOT( on_patternEditorHScroll(int) ) );
336 connect( m_pPianoRollScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
337 m_pPianoRollEditor, SLOT( scrolled( int ) ) );
338 connect( m_pPianoRollScrollView->verticalScrollBar(), SIGNAL( valueChanged( int ) ),
339 m_pPianoRollEditor, SLOT( scrolled( int ) ) );
342
345
346 m_pPianoRollEditor->mergeSelectionGroups( m_pDrumPatternEditor );
347
348// ~ EDITOR
349
350
351
352
353
354
355// INSTRUMENT LIST
356 // Instrument list scrollview
358 m_pInstrListScrollView->setObjectName( "InstrListScrollView" );
359 m_pInstrListScrollView->setFocusPolicy( Qt::ClickFocus );
360 m_pInstrListScrollView->setFrameShape( QFrame::NoFrame );
361 m_pInstrListScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
362 m_pInstrListScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
363
364 // Instrument list
367 m_pInstrListScrollView->setFixedWidth( m_pInstrumentList->width() );
368 m_pInstrumentList->setFocusPolicy( Qt::ClickFocus );
369 m_pInstrumentList->setFocusProxy( m_pEditorScrollView );
370
371 connect( m_pInstrListScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorVScroll(int) ) );
373
374// ~ INSTRUMENT LIST
375
376
377
378
379// NOTE_VELOCITY EDITOR
381 m_pNoteVelocityScrollView->setObjectName( "NoteVelocityScrollView" );
382 m_pNoteVelocityScrollView->setFocusPolicy( Qt::NoFocus );
383 m_pNoteVelocityScrollView->setFrameShape( QFrame::NoFrame );
384 m_pNoteVelocityScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
385 m_pNoteVelocityScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
389 m_pNoteVelocityScrollView->setFixedHeight( 100 );
390 connect( m_pNoteVelocityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
391 connect( m_pNoteVelocityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
392 m_pNoteVelocityEditor, SLOT( scrolled( int ) ) );
393
394 m_pNoteVelocityEditor->mergeSelectionGroups( m_pDrumPatternEditor );
395
396// ~ NOTE_VELOCITY EDITOR
397
398
399// NOTE_PAN EDITOR
400 m_pNotePanScrollView = new WidgetScrollArea( nullptr );
401 m_pNotePanScrollView->setObjectName( "NotePanScrollView" );
402 m_pNotePanScrollView->setFocusPolicy( Qt::NoFocus );
403 m_pNotePanScrollView->setFrameShape( QFrame::NoFrame );
404 m_pNotePanScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
405 m_pNotePanScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
409 m_pNotePanScrollView->setFixedHeight( 100 );
410
411 connect( m_pNotePanScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
412 this, SLOT( on_patternEditorHScroll(int) ) );
413 connect( m_pNotePanScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
414 m_pNotePanEditor, SLOT( scrolled( int ) ) );
415
416 m_pNotePanEditor->mergeSelectionGroups( m_pDrumPatternEditor );
417
418// ~ NOTE_PAN EDITOR
419
420
421// NOTE_LEADLAG EDITOR
423 m_pNoteLeadLagScrollView->setObjectName( "NoteLeadLagScrollView" );
424 m_pNoteLeadLagScrollView->setFocusPolicy( Qt::NoFocus );
425 m_pNoteLeadLagScrollView->setFrameShape( QFrame::NoFrame );
426 m_pNoteLeadLagScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
427 m_pNoteLeadLagScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
431 m_pNoteLeadLagScrollView->setFixedHeight( 100 );
432
433 connect( m_pNoteLeadLagScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
434 this, SLOT( on_patternEditorHScroll(int) ) );
435 connect( m_pNoteLeadLagScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
436 m_pNoteLeadLagEditor, SLOT( scrolled( int ) ) );
437
438 m_pNoteLeadLagEditor->mergeSelectionGroups( m_pDrumPatternEditor );
439
440// ~ NOTE_LEADLAG EDITOR
441
442
443// NOTE_NOTEKEY EDITOR
444
445
447 m_pNoteNoteKeyScrollView->setObjectName( "NoteNoteKeyScrollView" );
448 m_pNoteNoteKeyScrollView->setFocusPolicy( Qt::NoFocus );
449 m_pNoteNoteKeyScrollView->setFrameShape( QFrame::NoFrame );
450 m_pNoteNoteKeyScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
451 m_pNoteNoteKeyScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
455 m_pNoteNoteKeyScrollView->setFixedHeight( 210 );
456 connect( m_pNoteNoteKeyScrollView->horizontalScrollBar(), SIGNAL( valueChanged( int ) ),
457 this, SLOT( on_patternEditorHScroll( int ) ) );
458 connect( m_pNoteNoteKeyScrollView->horizontalScrollBar(), SIGNAL( valueChanged( int ) ),
459 m_pNoteNoteKeyEditor, SLOT( scrolled( int ) ) );
462
463 m_pNoteNoteKeyEditor->mergeSelectionGroups( m_pDrumPatternEditor );
464
465// ~ NOTE_NOTEKEY EDITOR
466
467// NOTE_PROBABILITY EDITOR
469 m_pNoteProbabilityScrollView->setObjectName( "NoteProbabilityScrollView" );
470 m_pNoteProbabilityScrollView->setFocusPolicy( Qt::NoFocus );
471 m_pNoteProbabilityScrollView->setFrameShape( QFrame::NoFrame );
472 m_pNoteProbabilityScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
473 m_pNoteProbabilityScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
477 m_pNoteProbabilityScrollView->setFixedHeight( 100 );
478 connect( m_pNoteProbabilityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
479 this, SLOT( on_patternEditorHScroll(int) ) );
480 connect( m_pNoteProbabilityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
481 m_pNoteProbabilityEditor, SLOT( scrolled( int ) ) );
482
483 m_pNoteProbabilityEditor->mergeSelectionGroups( m_pDrumPatternEditor );
484
485// ~ NOTE_PROBABILITY EDITOR
486
487
488
489 // external horizontal scrollbar
490 m_pPatternEditorHScrollBar = new QScrollBar( Qt::Horizontal , nullptr );
491 m_pPatternEditorHScrollBar->setObjectName( "PatternEditorHScrollBar" );
492 connect( m_pPatternEditorHScrollBar, SIGNAL( valueChanged( int ) ), this,
493 SLOT( syncToExternalHorizontalScrollbar( int ) ) );
494
495 // external vertical scrollbar
496 m_pPatternEditorVScrollBar = new QScrollBar( Qt::Vertical, nullptr );
497 m_pPatternEditorVScrollBar->setObjectName( "PatternEditorVScrollBar" );
498 connect( m_pPatternEditorVScrollBar, SIGNAL(valueChanged( int)), this,
500 connect( m_pPatternEditorVScrollBar, SIGNAL( valueChanged( int ) ),
501 m_pDrumPatternEditor, SLOT( scrolled( int ) ) );
502 connect( m_pPatternEditorHScrollBar, SIGNAL( valueChanged( int ) ),
503 m_pDrumPatternEditor, SLOT( scrolled( int ) ) );
504
505 QHBoxLayout *pPatternEditorHScrollBarLayout = new QHBoxLayout();
506 pPatternEditorHScrollBarLayout->setSpacing( 0 );
507 pPatternEditorHScrollBarLayout->setContentsMargins( 0, 0, 0, 0 );
508 pPatternEditorHScrollBarLayout->addWidget( m_pPatternEditorHScrollBar );
509 pPatternEditorHScrollBarLayout->addWidget( zoom_in_btn );
510 pPatternEditorHScrollBarLayout->addWidget( zoom_out_btn );
511
512 QWidget *pPatternEditorHScrollBarContainer = new QWidget();
513 pPatternEditorHScrollBarContainer->setLayout( pPatternEditorHScrollBarLayout );
514
515
516 QPalette label_palette;
517 label_palette.setColor( QPalette::WindowText, QColor( 230, 230, 230 ) );
518
519 m_pPatternNameLbl = new QLabel( nullptr );
520 m_pPatternNameLbl->setFont( boldFont );
521 m_pPatternNameLbl->setText( "pattern name label" );
522 m_pPatternNameLbl->setPalette(label_palette);
523
524
525
526
527
528
529// NOTE_PROPERTIES BUTTONS
530 PixmapWidget *pPropertiesPanel = new PixmapWidget( nullptr );
531 pPropertiesPanel->setObjectName( "PropertiesPanel" );
532 pPropertiesPanel->setColor( QColor( 58, 62, 72 ) );
533
534 pPropertiesPanel->setFixedSize( 181, 100 );
535
536 QVBoxLayout *pPropertiesVBox = new QVBoxLayout( pPropertiesPanel );
537 pPropertiesVBox->setSpacing( 0 );
538 pPropertiesVBox->setContentsMargins( 0, 0, 0, 0 );
539
540
542 new LCDCombo( nullptr, QSize( m_pInstrumentList->width(), 18 ), false );
543 m_pPropertiesCombo->setToolTip( tr( "Select note properties" ) );
544 m_pPropertiesCombo->addItem( tr("Velocity") );
545 m_pPropertiesCombo->addItem( tr("Pan") );
546 m_pPropertiesCombo->addItem( tr("Lead and Lag") );
547 m_pPropertiesCombo->addItem( tr("NoteKey") );
548 m_pPropertiesCombo->addItem( tr("Probability") );
549 /* m_pPropertiesCombo->addItem( tr("Cutoff") ); */
550 /* m_pPropertiesCombo->addItem( tr("Resonance") ); */
551 // is triggered here below
552 m_pPropertiesCombo->setObjectName( "PropertiesCombo" );
553 connect( m_pPropertiesCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( propertiesComboChanged( int ) ) );
554
555 pPropertiesVBox->addWidget( m_pPropertiesCombo );
556
557// ~ NOTE_PROPERTIES BUTTONS
558
559
560// LAYOUT
561 QWidget *pMainPanel = new QWidget();
562
563 QGridLayout *pGrid = new QGridLayout();
564 pGrid->setSpacing( 0 );
565 pGrid->setContentsMargins( 0, 0, 0, 0 );
566
567 pGrid->addWidget( m_pEditorTop1, 0, 0 );
568 pGrid->addWidget( m_pEditorTop2, 0, 1, 1, 2 );
569 pGrid->addWidget( m_pPatternNameLbl, 1, 0 );
570 pGrid->addWidget( m_pRulerScrollView, 1, 1 );
571
572 pGrid->addWidget( m_pInstrListScrollView, 2, 0 );
573
574 pGrid->addWidget( m_pEditorScrollView, 2, 1 );
575 pGrid->addWidget( m_pPianoRollScrollView, 2, 1 );
576
577 pGrid->addWidget( m_pPatternEditorVScrollBar, 2, 2 );
578 pGrid->addWidget( pPatternEditorHScrollBarContainer, 10, 1 );
579 pGrid->addWidget( m_pNoteVelocityScrollView, 4, 1 );
580 pGrid->addWidget( m_pNotePanScrollView, 4, 1 );
581 pGrid->addWidget( m_pNoteLeadLagScrollView, 4, 1 );
582 pGrid->addWidget( m_pNoteNoteKeyScrollView, 4, 1 );
583 pGrid->addWidget( m_pNoteProbabilityScrollView, 4, 1 );
584
585 pGrid->addWidget( pPropertiesPanel, 4, 0 );
586 pGrid->setRowStretch( 2, 100 );
587 pMainPanel->setLayout( pGrid );
588
589
590 // restore grid resolution
591 int nIndex;
592 int nRes = pPref->getPatternEditorGridResolution();
593 if ( nRes == MAX_NOTES ) {
594 nIndex = 11;
595 } else if ( pPref->isPatternEditorUsingTriplets() == false ) {
596 switch ( nRes ) {
597 case 4: nIndex = 0; break;
598 case 8: nIndex = 1; break;
599 case 16: nIndex = 2; break;
600 case 32: nIndex = 3; break;
601 case 64: nIndex = 4; break;
602 default:
603 nIndex = 0;
604 ERRORLOG( QString( "Wrong grid resolution: %1" ).arg( pPref->getPatternEditorGridResolution() ) );
605 }
606 } else {
607 switch ( nRes ) {
608 case 8: nIndex = 6; break;
609 case 16: nIndex = 7; break;
610 case 32: nIndex = 8; break;
611 case 64: nIndex = 9; break;
612 default:
613 nIndex = 6;
614 ERRORLOG( QString( "Wrong grid resolution: %1" ).arg( pPref->getPatternEditorGridResolution() ) );
615 }
616 }
617 m_pResolutionCombo->setCurrentIndex( nIndex );
618
619 // LAYOUT
620 QVBoxLayout *pVBox = new QVBoxLayout();
621 pVBox->setSpacing( 0 );
622 pVBox->setContentsMargins( 0, 0, 0, 0 );
623 this->setLayout( pVBox );
624
625 pVBox->addWidget( pMainPanel );
626
628
630
631 // update
632 m_pPropertiesCombo->setCurrentIndex( 0 );
636}
637
638
639
640
644
648
650{
651 //INFOLOG( "[syncToExternalHorizontalScrollbar]" );
652
653 // drum Editor
654 m_pEditorScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
655 m_pEditorScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
656
657 // piano roll Editor
658 m_pPianoRollScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
659
660 // Ruler
661 m_pRulerScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
662
663 // Instrument list
664 m_pInstrListScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
665
666 // Velocity ruler
667 m_pNoteVelocityScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
668
669 // pan ruler
670 m_pNotePanScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
671
672 // leadlag ruler
673 m_pNoteLeadLagScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
674
675 // notekey ruler
676 m_pNoteNoteKeyScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
677
678 // Probability ruler
679 m_pNoteProbabilityScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
680}
681
682
684{
685 //INFOLOG( "[on_patternEditorVScroll] " + QString::number(nValue) );
686 m_pPatternEditorVScrollBar->setValue( nValue );
687 resizeEvent( nullptr );
688}
689
691{
692 //INFOLOG( "[on_patternEditorHScroll] " + QString::number(nValue) );
693 m_pPatternEditorHScrollBar->setValue( nValue );
694 resizeEvent( nullptr );
695}
696
697
698
699
701{
702 int nResolution;
703 bool bUseTriplets = false;
704
705 switch( nSelected ) {
706 case 0:
707 // 1/4
708 nResolution = 4;
709 bUseTriplets = false;
710 break;
711 case 1:
712 // 1/8
713 nResolution = 8;
714 bUseTriplets = false;
715 break;
716 case 2:
717 // 1/16
718 nResolution = 16;
719 bUseTriplets = false;
720 break;
721 case 3:
722 // 1/32
723 nResolution = 32;
724 bUseTriplets = false;
725 break;
726 case 4:
727 // 1/64
728 nResolution = 64;
729 bUseTriplets = false;
730 break;
731 case 6:
732 // 1/4T
733 nResolution = 8;
734 bUseTriplets = true;
735 break;
736 case 7:
737 // 1/8T
738 nResolution = 16;
739 bUseTriplets = true;
740 break;
741 case 8:
742 // 1/16T
743 nResolution = 32;
744 bUseTriplets = true;
745 break;
746 case 9:
747 // 1/32T
748 nResolution = 64;
749 bUseTriplets = true;
750 break;
751 case 11:
752 // off
753 nResolution = MAX_NOTES;
754 bUseTriplets = false;
755 break;
756 default:
757 ERRORLOG( QString( "Invalid resolution selection [%1]" )
758 .arg( nSelected ) );
759 return;
760 }
761
762 m_pDrumPatternEditor->setResolution( nResolution, bUseTriplets );
763 m_pPianoRollEditor->setResolution( nResolution, bUseTriplets );
764 m_pNoteVelocityEditor->setResolution( nResolution, bUseTriplets );
765 m_pNoteLeadLagEditor->setResolution( nResolution, bUseTriplets );
766 m_pNoteNoteKeyEditor->setResolution( nResolution, bUseTriplets );
767 m_pNoteProbabilityEditor->setResolution( nResolution, bUseTriplets );
768 m_pNotePanEditor->setResolution( nResolution, bUseTriplets );
769
770 m_nCursorIncrement = ( bUseTriplets ? 4 : 3 ) * MAX_NOTES / ( nResolution * 3 );
772
775}
776
777
778
780{
781
782 PatternList *pPatternList = Hydrogen::get_instance()->getSong()->getPatternList();
784
785 if ( ( m_nSelectedPatternNumber != -1 ) &&
787 // update pattern name text
788 m_pPattern = pPatternList->get( m_nSelectedPatternNumber );
789 QString sCurrentPatternName = m_pPattern->get_name();
790 this->setWindowTitle( ( tr( "Pattern editor - %1" ).arg( sCurrentPatternName ) ) );
791 m_pPatternNameLbl->setText( sCurrentPatternName );
792
793 // update pattern size LCD
796
797 }
798 else {
799 m_pPattern = nullptr;
800
801 this->setWindowTitle( tr( "Pattern editor - No pattern selected" ) );
802 m_pPatternNameLbl->setText( tr( "No pattern selected" ) );
803 }
804
805 resizeEvent( nullptr ); // force an update of the scrollbars
806}
807
809{
811 pref->setHearNewNotes( m_pHearNotesBtn->isChecked() );
812
813 if ( m_pHearNotesBtn->isChecked() ) {
814 ( HydrogenApp::get_instance() )->showStatusBarMessage( tr( "Hear new notes = On" ) );
815 } else {
816 ( HydrogenApp::get_instance() )->showStatusBarMessage( tr( "Hear new notes = Off" ) );
817 }
818}
819
821{
823 pref->setQuantizeEvents( m_pQuantizeEventsBtn->isChecked() );
824
825 if ( m_pQuantizeEventsBtn->isChecked() ) {
826 ( HydrogenApp::get_instance() )->showStatusBarMessage( tr( "Quantize incoming keyboard/midi events = On" ) );
827 } else {
828 ( HydrogenApp::get_instance() )->showStatusBarMessage( tr( "Quantize incoming keyboard/midi events = Off" ) );
829 }
830}
831
832static void syncScrollBarSize( QScrollBar *pDest, QScrollBar *pSrc )
833{
834 pDest->setMinimum( pSrc->minimum() );
835 pDest->setMaximum( pSrc->maximum() );
836 pDest->setSingleStep( pSrc->singleStep() );
837 pDest->setPageStep( pSrc->pageStep() );
838}
839
840void PatternEditorPanel::resizeEvent( QResizeEvent *ev )
841{
842 UNUSED( ev );
843 QScrollArea *pScrollArea = m_pEditorScrollView;
844
845 syncScrollBarSize( m_pPatternEditorHScrollBar, pScrollArea->horizontalScrollBar() );
846 syncScrollBarSize( m_pPatternEditorVScrollBar, pScrollArea->verticalScrollBar() );
847
848 syncScrollBarSize( m_pRulerScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
849 syncScrollBarSize( m_pNoteVelocityScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
850 syncScrollBarSize( m_pNotePanScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
851 syncScrollBarSize( m_pNoteLeadLagScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() ) ;
852 syncScrollBarSize( m_pNoteNoteKeyScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
853 syncScrollBarSize( m_pNoteProbabilityScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
854}
855
856void PatternEditorPanel::showEvent ( QShowEvent *ev )
857{
858 UNUSED( ev );
859}
860
861
864{
865 UNUSED( dummy );
866 //INFOLOG( "contentsMoving" );
868}
869
870
871
873{
874 resizeEvent( nullptr ); // force a scrollbar update
875}
876
878{
879 if ( __show_drum_btn->isChecked() ) {
880 m_pPianoRollEditor->selectInstrumentNotes( nInstrument );
881 } else {
882 m_pDrumPatternEditor->selectInstrumentNotes( nInstrument );
883 }
884}
885
887{
888 __show_drum_btn->setToolTip( tr( "Show piano roll editor" ) );
889 __show_drum_btn->setChecked( false );
891 m_pEditorScrollView->show();
893
894 m_pEditorScrollView->setFocus();
896 m_pInstrumentList->setFocusProxy( m_pEditorScrollView );
897
898 m_pDrumPatternEditor->selectedInstrumentChangedEvent(); // force an update
899
900 m_pDrumPatternEditor->selectNone();
901 m_pPianoRollEditor->selectNone();
902
903 // force a re-sync of extern scrollbars
904 resizeEvent( nullptr );
905
906}
907
909{
910 __show_drum_btn->setToolTip( tr( "Show drum editor" ) );
911 __show_drum_btn->setChecked( true );
913 m_pPianoRollScrollView->verticalScrollBar()->setValue( 250 );
914 m_pEditorScrollView->hide();
916
917 m_pPianoRollScrollView->setFocus();
920
921 m_pDrumPatternEditor->selectNone();
922 m_pPianoRollEditor->selectNone();
923
924 m_pPianoRollEditor->selectedPatternChangedEvent();
925 m_pPianoRollEditor->updateEditor(); // force an update
926 // force a re-sync of extern scrollbars
927 resizeEvent( nullptr );
928}
929
931{
932 if ( __show_drum_btn->isVisible() ){
934 __show_drum_btn->hide();
935 __show_piano_btn->show();
936 __show_drum_btn->setBaseToolTip( HydrogenApp::get_instance()->getCommonStrings()->getShowDrumkitEditorTooltip() );
937 __show_piano_btn->setBaseToolTip( HydrogenApp::get_instance()->getCommonStrings()->getShowDrumkitEditorTooltip() );
938 } else {
940 __show_drum_btn->show();
941 __show_piano_btn->hide();
942 __show_drum_btn->setBaseToolTip( HydrogenApp::get_instance()->getCommonStrings()->getShowPianoRollEditorTooltip() );
943 __show_piano_btn->setBaseToolTip( HydrogenApp::get_instance()->getCommonStrings()->getShowPianoRollEditorTooltip() );
944 }
945}
946
947
949{
950 if( m_pPatternEditorRuler->getGridWidth() >= 24 ){
951 return;
952 }
953
954 m_pPatternEditorRuler->zoomIn();
955 m_pDrumPatternEditor->zoomIn();
956 m_pNoteVelocityEditor->zoomIn();
957 m_pNoteLeadLagEditor->zoomIn();
958 m_pNoteNoteKeyEditor->zoomIn();
959 m_pNoteProbabilityEditor->zoomIn();
960 m_pNotePanEditor->zoomIn();
961 m_pPianoRollEditor->zoomIn();
962
965
966 resizeEvent( nullptr );
967}
968
970{
971 m_pPatternEditorRuler->zoomOut();
972 m_pDrumPatternEditor->zoomOut();
973 m_pNoteVelocityEditor->zoomOut();
974 m_pNoteLeadLagEditor->zoomOut();
975 m_pNoteNoteKeyEditor->zoomOut();
976 m_pNoteProbabilityEditor->zoomOut();
977 m_pNotePanEditor->zoomOut();
978 m_pPianoRollEditor->zoomOut();
979
980 resizeEvent( nullptr );
981
984}
985
987 Hydrogen *pHydrogen = Hydrogen::get_instance();
988 std::shared_ptr<Song> pSong = pHydrogen->getSong();
989
990 m_pPattern = nullptr;
992
993 if ( pSong != nullptr ) {
994 PatternList *pPatternList = pSong->getPatternList();
996 m_pPattern = pPatternList->get( m_nSelectedPatternNumber );
997 }
998 }
999}
1000
1001void PatternEditorPanel::updateEditors( bool bPatternOnly ) {
1002
1004
1005 // Changes of pattern may leave the cursor out of bounds.
1007
1008 m_pPatternEditorRuler->updateEditor( true );
1009 m_pNoteVelocityEditor->updateEditor();
1010 m_pNotePanEditor->updateEditor();
1011 m_pNoteLeadLagEditor->updateEditor();
1012 m_pNoteNoteKeyEditor->updateEditor();
1013 m_pNoteProbabilityEditor->updateEditor();
1014 m_pPianoRollEditor->updateEditor( bPatternOnly );
1015 m_pDrumPatternEditor->updateEditor();
1016}
1017
1021
1027
1031
1035
1041
1045
1047 if ( H2Core::Hydrogen::get_instance()->isPatternEditorLocked() ) {
1048 updateEditors( true );
1049 }
1050}
1051
1053 if ( m_pPattern == nullptr ) {
1054 return;
1055 }
1056
1058
1059 double fNewDenominator = static_cast<double>( m_pPattern->get_denominator() );
1060 if ( fNewDenominator != m_pLCDSpinBoxDenominator->value() &&
1061 ! m_pLCDSpinBoxDenominator->hasFocus() ) {
1062 m_pLCDSpinBoxDenominator->setValue( fNewDenominator );
1063
1064 // Update numerator to allow only for a maximum pattern length of
1065 // four measures.
1066 m_pLCDSpinBoxNumerator->setMaximum( 4 * m_pLCDSpinBoxDenominator->value() );
1067 }
1068
1069 double fNewNumerator = static_cast<double>( m_pPattern->get_length() * m_pPattern->get_denominator() ) / static_cast<double>( MAX_NOTES );
1070 if ( fNewNumerator != m_pLCDSpinBoxNumerator->value() && ! m_pLCDSpinBoxNumerator->hasFocus() ) {
1071 m_pLCDSpinBoxNumerator->setValue( fNewNumerator );
1072 }
1073
1075}
1076
1078 if ( m_pPattern == nullptr ) {
1079 return;
1080 }
1081
1083 // Don't execute this function if the values of the spin boxes
1084 // have been set by Hydrogen instead of by the user.
1085 return;
1086 }
1087
1088 auto pHydrogen = Hydrogen::get_instance();
1089 auto pAudioEngine = pHydrogen->getAudioEngine();
1090 auto pInstrumentList = pHydrogen->getSong()->getInstrumentList();
1091
1092 // Update numerator to allow only for a maximum pattern length of
1093 // four measures.
1094 m_pLCDSpinBoxNumerator->setMaximum( 4 * m_pLCDSpinBoxDenominator->value() );
1095
1096 double fNewNumerator = m_pLCDSpinBoxNumerator->value();
1097 double fNewDenominator = m_pLCDSpinBoxDenominator->value();
1098
1099 /* Note: user can input a non integer numerator and this feature
1100 is very powerful because it allows to set really any possible
1101 pattern size (in ticks) using ANY arbitrary denominator.
1102 e.g. pattern size of 38 ticks will result from both inputs 1/5
1103 (quintuplet) and 0.79/4 of a whole note, since both are rounded
1104 and BOTH are UNSUPPORTED, but the first notation looks more
1105 meaningful */
1106
1107 int nNewLength =
1108 std::round( static_cast<double>( MAX_NOTES ) / fNewDenominator * fNewNumerator );
1109
1110 if ( nNewLength == m_pPattern->get_length() ) {
1111 return;
1112 }
1113
1114 QUndoStack* pUndoStack = HydrogenApp::get_instance()->m_pUndoStack;
1115 pUndoStack->beginMacro( QString( "Change pattern size to %1/%2" )
1116 .arg( fNewNumerator ).arg( fNewDenominator ) );
1117
1118 pUndoStack->push( new SE_patternSizeChangedAction( nNewLength,
1119 m_pPattern->get_length(),
1120 fNewDenominator,
1121 m_pPattern->get_denominator(),
1123 pUndoStack->endMacro();
1124}
1125
1126void PatternEditorPanel::patternSizeChangedAction( int nLength, double fDenominator,
1127 int nSelectedPatternNumber ) {
1128 auto pHydrogen = Hydrogen::get_instance();
1129 auto pAudioEngine = pHydrogen->getAudioEngine();
1130 auto pPatternList = pHydrogen->getSong()->getPatternList();
1131 H2Core::Pattern* pPattern = nullptr;
1132
1133 if ( ( nSelectedPatternNumber != -1 ) &&
1134 ( nSelectedPatternNumber < pPatternList->size() ) ) {
1135 pPattern = pPatternList->get( nSelectedPatternNumber );
1136 }
1137
1138 if ( pPattern == nullptr ) {
1139 ERRORLOG( QString( "Pattern corresponding to pattern number [%1] could not be retrieved" )
1140 .arg( nSelectedPatternNumber ) );
1141 return;
1142 }
1143
1144 pAudioEngine->lock( RIGHT_HERE );
1145 // set length and denominator
1146 pPattern->set_length( nLength );
1147 pPattern->set_denominator( static_cast<int>( fDenominator ) );
1148 pHydrogen->updateSongSize();
1149 pAudioEngine->unlock();
1150
1151 pHydrogen->setIsModified( true );
1152
1154}
1155
1156void PatternEditorPanel::dragEnterEvent( QDragEnterEvent *event )
1157{
1158 m_pInstrumentList->dragEnterEvent( event );
1159}
1160
1161
1162
1163void PatternEditorPanel::dropEvent( QDropEvent *event )
1164{
1165 m_pInstrumentList->dropEvent( event );
1166}
1167
1169 // A new song got loaded
1170 if ( nValue == 0 ) {
1171 // Performs an editor update with updateEditor() (and no argument).
1175 updateEditors( true );
1176 m_pPatternEditorRuler->updatePosition();
1177 }
1178}
1179
1181{
1182 if ( nSelected == 0 ) { // Velocity
1183 m_pNotePanScrollView->hide();
1188
1189 m_pNoteVelocityEditor->updateEditor();
1190 }
1191 else if ( nSelected == 1 ) { // Pan
1195 m_pNotePanScrollView->show();
1197
1198 m_pNotePanEditor->updateEditor();
1199 }
1200 else if ( nSelected == 2 ) { // Lead and Lag
1202 m_pNotePanScrollView->hide();
1206
1207 m_pNoteLeadLagEditor->updateEditor();
1208 }
1209 else if ( nSelected == 3 ) { // NoteKey
1211 m_pNotePanScrollView->hide();
1215
1216 m_pNoteNoteKeyEditor->updateEditor();
1217 }
1218 else if ( nSelected == 4 ) { // Probability
1219 m_pNotePanScrollView->hide();
1224
1225 m_pNoteProbabilityEditor->updateEditor();
1226 }
1227 /*
1228 else if ( nSelected == 5 ) { // Cutoff
1229 }
1230 else if ( nSelected == 6 ) { // Resonance
1231 }
1232 */
1233 else {
1234 ERRORLOG( QString( "unhandled value : %1" ).arg( nSelected ) );
1235 }
1236}
1237
1242
1244{
1245 int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
1246 uint y = nSelectedInstrument * Preferences::get_instance()->getPatternEditorGridHeight();
1247 m_pEditorScrollView->ensureVisible( m_nCursorPosition * m_pPatternEditorRuler->getGridWidth(), y );
1248}
1249
1251{
1252 if ( nCursorPosition < 0 ) {
1254 } else if ( m_pPattern != nullptr && nCursorPosition >= m_pPattern->get_length() ) {
1256 } else {
1257 m_nCursorPosition = nCursorPosition;
1258 }
1259}
1260
1262{
1264 0 );
1265
1267
1268 return m_nCursorPosition;
1269}
1270
1272{
1273 if ( m_pPattern == nullptr ) {
1274 return 0;
1275 }
1276
1278 m_pPattern->get_length() - m_nCursorIncrement );
1279
1281
1282 return m_nCursorPosition;
1283}
1284
1286 auto pPref = H2Core::Preferences::get_instance();
1287
1288 if ( changes & H2Core::Preferences::Changes::Font ) {
1289
1290 // It's sufficient to check the properties of just one label
1291 // because they will always carry the same.
1292 QFont boldFont( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
1293 boldFont.setBold( true );
1294 m_pSLlabel->setFont( boldFont );
1295 m_pPatternNameLbl->setFont( boldFont );
1296
1298 }
1299
1300 if ( changes & ( H2Core::Preferences::Changes::Colors ) ) {
1302 }
1303}
1304
1306
1307 auto pPref = H2Core::Preferences::get_instance();
1308 int nFactorTop = 112;
1309
1310 QColor topColorLight = pPref->getColorTheme()->m_midColor.lighter( nFactorTop );
1311 QColor topColorDark = pPref->getColorTheme()->m_midColor.darker( nFactorTop );
1312
1313 QString sEditorTopStyleSheet = QString( "\
1314QWidget#editor1 {\
1315 background-color: qlineargradient(x1: 0.5, y1: 0.1, x2: 0.5, y2: 0.9, \
1316 stop: 0 %1, stop: 1 %2); \
1317} \
1318QWidget#editor2 {\
1319 background-color: qlineargradient(x1: 0.5, y1: 0.1, x2: 0.5, y2: 0.9, \
1320 stop: 0 %1, stop: 1 %2); \
1321}")
1322 .arg( topColorLight.name() ).arg( topColorDark.name() );
1323 QString sWidgetTopStyleSheet = QString( "\
1324QWidget#sizeResol {\
1325 background-color: %1;\
1326} \
1327QWidget#pRec {\
1328 background-color: %1;\
1329}" )
1330 .arg( pPref->getColorTheme()->m_midLightColor.name() );
1331
1332 m_pEditorTop1->setStyleSheet( sEditorTopStyleSheet );
1333 m_pEditorTop2->setStyleSheet( sEditorTopStyleSheet );
1334
1335 m_pSizeResol->setStyleSheet( sWidgetTopStyleSheet );
1336 m_pRec->setStyleSheet( sWidgetTopStyleSheet );
1337
1338}
1339
1341 if ( ! m_pLCDSpinBoxDenominator->hasFocus() ) {
1342 m_pLCDSpinBoxDenominator->setFocus();
1343 } else {
1344 m_pLCDSpinBoxNumerator->setFocus();
1345 }
1346}
1347
1349{
1351
1352 switch ( m_pPropertiesCombo->currentIndex() ) {
1353 case 0:
1355 break;
1356 case 1:
1358 break;
1359 case 2:
1361 break;
1362 case 3:
1364 break;
1365 case 4:
1367 break;
1368 default:
1369 ERRORLOG( QString( "Unsupported m_pPropertiesCombo index [%1]" )
1370 .arg( m_pPropertiesCombo->currentIndex() ) );
1371 }
1372
1373 return mode;
1374}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:61
#define ERRORLOG(x)
Definition Object.h:242
static void syncScrollBarSize(QScrollBar *pDest, QScrollBar *pSrc)
Generic Button with SVG icons or text.
Definition Button.h:60
@ Push
Button is not set checkable.
Definition Button.h:68
@ Toggle
Button is set checkable.
Definition Button.h:70
Custom QLabel that emits a signal when clicked.
Drum pattern editor.
void onPreferencesChanged(H2Core::Preferences::Changes changes)
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
Hydrogen Audio Engine.
Definition Hydrogen.h:54
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:123
int getSelectedInstrumentNumber() const
Definition Hydrogen.h:678
int getSelectedPatternNumber() const
Definition Hydrogen.h:674
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
PatternList is a collection of patterns.
Definition PatternList.h:43
Pattern * get(int idx)
get a pattern from the list
Pattern class is a Note container.
Definition Pattern.h:46
void set_denominator(int denominator)
get the denominator of the pattern
Definition Pattern.h:345
void set_length(int length)
get the length of the pattern
Definition Pattern.h:335
Manager for User Preferences File (singleton)
Definition Preferences.h:79
void setPatternEditorGridHeight(unsigned value)
void setHearNewNotes(bool value)
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
const QString & getApplicationFontFamily() const
void setPatternEditorUsingTriplets(bool value)
int getPatternEditorGridResolution()
bool isPatternEditorUsingTriplets()
unsigned getPatternEditorGridHeight()
FontTheme::FontSize getFontSize() const
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 setPatternEditorGridResolution(int value)
void setQuantizeEvents(bool value)
void setPatternEditorGridWidth(unsigned value)
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
QUndoStack * m_pUndoStack
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
Custom spin box.
Definition LCDSpinBox.h:50
@ PatternSizeNumerator
The minimum value - a fractional one - can only be reached by entering it using the keyboard.
Definition LCDSpinBox.h:68
@ PatternSizeDenominator
Only a limited number of values is allowed.
Definition LCDSpinBox.h:70
void slashKeyPressed()
NotePropertiesEditor is (currently) a single class instantiated in different "modes" to select which ...
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void selectInstrumentNotes(int nInstrument)
ClickableLabel * m_pQuantizeEventsLbl
NotePropertiesRuler::Mode getNotePropertiesMode() const
void setCursorPosition(int nCursorPosition)
QScrollArea * m_pEditorScrollView
QScrollArea * m_pPianoRollScrollView
QScrollBar * m_pPatternEditorVScrollBar
NotePropertiesRuler * m_pNoteVelocityEditor
PianoRollEditor * m_pPianoRollEditor
QScrollArea * m_pNoteProbabilityScrollView
LCDSpinBox * m_pLCDSpinBoxNumerator
QScrollArea * m_pNoteNoteKeyScrollView
bool m_bArmPatternSizeSpinBoxes
Indicates whether the LCD spin boxes for the pattern size have been altered by Hydrogen or by the use...
NotePropertiesRuler * m_pNoteProbabilityEditor
ClickableLabel * m_pHearNotesLbl
void gridResolutionChanged(int nSelected)
virtual void resizeEvent(QResizeEvent *ev) override
virtual void patternModifiedEvent() override
void updatePatternSizeLCD()
Batch version for setting the values of the pattern size spin boxes.
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void updateEditors(bool bPatternOnly=false)
virtual void updateSongEvent(int nValue) override
virtual void stackedModeActivationEvent(int) override
virtual void songModeActivationEvent() override
QScrollArea * m_pRulerScrollView
QScrollBar * m_pPatternEditorHScrollBar
QScrollArea * m_pNoteLeadLagScrollView
virtual void drumkitLoadedEvent() override
void syncToExternalHorizontalScrollbar(int)
virtual void dragEnterEvent(QDragEnterEvent *event) override
virtual void showEvent(QShowEvent *ev) override
ClickableLabel * m_pResolutionLbl
void propertiesComboChanged(int nSelected)
NotePropertiesRuler * m_pNotePanEditor
virtual void selectedInstrumentChangedEvent() override
virtual void songSizeChangedEvent() override
virtual void playingPatternsChangedEvent() override
PatternEditorPanel(QWidget *parent)
PatternEditorRuler * m_pPatternEditorRuler
PatternEditorInstrumentList * m_pInstrumentList
DrumPatternEditor * m_pDrumPatternEditor
ClickableLabel * m_pShowPianoLbl
virtual void relocationEvent() override
QScrollArea * m_pNotePanScrollView
virtual void dropEvent(QDropEvent *event) override
ClickableLabel * m_pPatternSizeLbl
NotePropertiesRuler * m_pNoteLeadLagEditor
virtual void selectedPatternChangedEvent() override
QScrollArea * m_pNoteVelocityScrollView
H2Core::Pattern * m_pPattern
QScrollArea * m_pInstrListScrollView
virtual void patternEditorLockedEvent() override
NotePropertiesRuler * m_pNoteNoteKeyEditor
void patternSizeChangedAction(int nLength, double fDenominator, int nSelectedPatternNumber)
void contentsMoving(int dummy)
richiamato dall'uso dello scroll del mouse
LCDSpinBox * m_pLCDSpinBoxDenominator
void onPreferencesChanged(H2Core::Preferences::Changes changes)
static bool isUsingAdditionalPatterns(const H2Core::Pattern *pPattern)
Determines whether to pattern editor should show further patterns (determined by getPattersToShow()) ...
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void setColor(const QColor &color)
constexpr int getPointSize(H2Core::FontTheme::FontSize fontSize) const
#define MAX_NOTES
Maximum number of notes.
Definition config.dox:79
#define UNUSED(v)
Definition Globals.h:42
@ EVENT_PATTERN_MODIFIED
A pattern was added, deleted, or modified.
Definition EventQueue.h:68