66 int h = pPref->getPatternEditorGridHeight();
69 QFont nameFont( pPref->getLevel2FontFamily(),
getPointSize( pPref->getFontSize() ) );
80 pCommonStrings->getSmallMuteButton(),
81 true, QSize(), tr(
"Mute instrument"),
85 m_pMuteBtn->setObjectName(
"InstrumentLineMuteButton" );
92 pCommonStrings->getSmallSoloButton(),
93 false, QSize(), tr(
"Solo"),
97 m_pSoloBtn->setObjectName(
"InstrumentLineSoloButton" );
101 "warning.svg",
"",
false, QSize(),
102 tr(
"Some samples for this instrument failed to load." ),
125 auto selectNotesAction =
m_pFunctionPopup->addAction( tr(
"Select notes" ) );
126 connect( selectNotesAction, &QAction::triggered,
this,
137 auto deleteAction =
m_pFunctionPopup->addAction( tr(
"Delete instrument" ) );
138 connect( deleteAction, &QAction::triggered,
this, [=](){
190 textColor = pPref->getColorTheme()->m_patternEditor_selectedRowTextColor;
192 textColor = pPref->getColorTheme()->m_patternEditor_textColor;
199 }" ).arg( textColor.name() ) );
202#ifdef H2CORE_HAVE_QT6
222 QPainter painter(
this);
224 QColor backgroundColor;
226 backgroundColor = pPref->getColorTheme()->m_patternEditor_selectedRowColor.darker( 114 );
230 backgroundColor = pPref->getColorTheme()->m_patternEditor_backgroundColor.darker( 120 );
232 backgroundColor = pPref->getColorTheme()->m_patternEditor_alternateRowColor.darker( 132 );
237 bool bHovered =
false;
243 backgroundColor, bHovered );
246 if ( (
m_bIsSelected && pHydrogenApp->getPatternEditorPanel() !=
nullptr &&
247 pHydrogenApp->getPatternEditorPanel()->getDrumPatternEditor()->hasFocus() &&
248 ! pHydrogenApp->hideKeyboardCursor() ) ||
255 pen.setColor( pPref->getColorTheme()->m_highlightColor);
257 pen.setColor( pPref->getColorTheme()->m_cursorColor );
261 painter.setPen( pen );
262 painter.setRenderHint( QPainter::Antialiasing );
264 height() - 2 ), 4, 4 );
299 if ( bSamplesMissing ) {
311 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
312 if ( pSong ==
nullptr ) {
317 auto pInstrList = pSong->getInstrumentList();
319 if ( pInstr ==
nullptr ) {
320 ERRORLOG( QString(
"Unable to retrieve instrument [%1]" )
336 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
337 if ( pSong ==
nullptr ) {
342 auto pInstrList = pSong->getInstrumentList();
344 if ( pInstr ==
nullptr ) {
345 ERRORLOG( QString(
"Unable to retrieve instrument [%1]" )
358 QMessageBox::information(
this,
"Hydrogen",
359 tr(
"One or more samples for this instrument failed to load. This may be because the"
360 " songfile uses an older default drumkit. This might be fixed by opening a new "
376 if ( ev->button() == Qt::LeftButton ) {
379 if ( pSong ==
nullptr ) {
384 if ( pInstr !=
nullptr && pInstr->hasSamples() ) {
387 const float fVelocity = std::min(
388 (
float)pEv->position().x()/(
float)nWidth, 1.0f);
389 Note *pNote =
new Note( pInstr, 0, fVelocity);
393 }
else if (ev->button() == Qt::RightButton ) {
399 ERRORLOG(
"A dialog is still opened. It needs to be closed first." );
406 QPoint( pEv->globalPosition().x(), pEv->globalPosition().y() ) );
410 PixmapWidget::mousePressEvent(ev);
421 assert( pPatternList !=
nullptr );
424 if ( nSelectedPatternNumber != -1 &&
425 nSelectedPatternNumber < pPatternList->size() ) {
426 Pattern* pCurrentPattern = pPatternList->
get( nSelectedPatternNumber );
427 return pCurrentPattern;
441 if ( pSelectedInstrument ==
nullptr ) {
442 ERRORLOG(
"No instrument selected" );
446 if ( nSelectedPatternNr == -1 ) {
451 std::list< Note* > noteList;
454 Note *pNote = it->second;
457 noteList.push_back( pNote );
460 if( noteList.size() > 0 ){
464 nSelectedPatternNr );
473 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
474 if ( pSong ==
nullptr ) {
482 if ( sSerialized.isEmpty() ) {
483 ERRORLOG( QString(
"Unable to serialize instrument line [%1]" )
488 QClipboard *clipboard = QApplication::clipboard();
489 clipboard->setText( sSerialized );
496 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
497 if ( pSong ==
nullptr ) {
504 std::list<Pattern*> patternList;
507 QClipboard *clipboard = QApplication::clipboard();
508 QString sSerialized = clipboard->text();
509 if ( ! pSong->pasteInstrumentLineFromString( sSerialized,
516 if (patternList.size() <= 0) {
528 PatternList *pPatternList = pSong->getPatternList();
530 if ( pSelectedInstrument ==
nullptr ) {
531 ERRORLOG(
"No instrument selected" );
536 pUndo->beginMacro( tr(
"Delete all notes on %1" ).arg( pSelectedInstrument->get_name() ) );
537 for (
int nPattern = 0; nPattern < pPatternList->
size(); nPattern++ ) {
538 std::list< Note* > noteList;
539 Pattern *pPattern = pPatternList->
get( nPattern );
542 if ( it->second->get_instrument() == pSelectedInstrument ) {
543 noteList.push_back( it->second );
546 if ( noteList.size() > 0 ) {
589 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
591 QStringList notePositions;
594 if (pCurrentPattern !=
nullptr) {
595 int nPatternSize = pCurrentPattern->
get_length();
597 if ( pSelectedInstrument ==
nullptr ) {
598 ERRORLOG(
"No instrument selected" );
603 for (
int i = 0; i < nPatternSize; i += nResolution) {
604 bool noteAlreadyPresent =
false;
607 Note *pNote = it->second;
610 noteAlreadyPresent =
true;
615 if ( noteAlreadyPresent ==
false ) {
616 notePositions << QString(
"%1").arg(i);
649 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
651 QStringList noteVeloValue;
652 QStringList oldNoteVeloValue;
655 if (pCurrentPattern !=
nullptr) {
656 int nPatternSize = pCurrentPattern->
get_length();
658 if ( pSelectedInstrument ==
nullptr ) {
659 ERRORLOG(
"No instrument selected" );
664 for (
int i = 0; i < nPatternSize; i += nResolution) {
667 Note *pNote = it->second;
669 float fVal = ( rand() % 100 ) / 100.0;
670 oldNoteVeloValue << QString(
"%1").arg( pNote->
get_velocity() );
678 noteVeloValue << QString(
"%1").arg(fVal);
696 if ( pSelectedInstrument ==
nullptr ) {
697 ERRORLOG(
"No instrument selected" );
701 QString sOldName = pSelectedInstrument->get_name();
703 QString sNewName = QInputDialog::getText(
this,
"Hydrogen", tr(
"New instrument name" ), QLineEdit::Normal, sOldName, &bIsOkPressed );
704 if ( bIsOkPressed ) {
705 pSelectedInstrument->set_name( sNewName );
759 setAcceptDrops(
true);
772 QScrollArea *pScrollArea =
dynamic_cast< QScrollArea *
>( parentWidget()->parentWidget() );
773 assert( pScrollArea );
801 if ( nEvent == 0 || nEvent == 1 ) {
812 auto pSong = pHydrogen->getSong();
813 auto pInstrList = pSong->getInstrumentList();
815 unsigned nInstruments = pInstrList->size();
817 if ( nInstr < nInstruments &&
827 auto pSong = pHydrogen->getSong();
828 auto pInstrList = pSong->getInstrumentList();
830 unsigned nSelectedInstr = pHydrogen->getSelectedInstrumentNumber();
832 unsigned nInstruments = pInstrList->size();
834 if ( nInstr < nInstruments &&
849 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
850 auto pInstrList = pSong->getInstrumentList();
854 unsigned nInstruments = pInstrList->size();
856 if ( nInstr >= nInstruments ) {
862 resize( width(), newHeight );
874 resize( width(), newHeight );
877 auto pInstr = pInstrList->get(nInstr);
881 pLine->
setName( pInstr->get_name() );
883 pLine->
setMuted( pInstr->is_muted() );
894 event->acceptProposedAction();
900 if ( ! event->mimeData()->hasFormat(
"text/plain") ) {
906 std::shared_ptr<Song> pSong = pHydrogen->getSong();
907 auto pInstrumentList = pSong->getInstrumentList();
908 int nInstruments = pInstrumentList->size();
911 QMessageBox::critical(
this,
"Hydrogen", tr(
"Unable to insert further instruments. Maximum possible number" ) +
916 auto pEv =
static_cast<DropEvent*
>( event );
918 QString sText =
event->mimeData()->text();
921 if ( sText.startsWith(
"Songs:") ||
922 sText.startsWith(
"Patterns:") ||
923 sText.startsWith(
"move pattern:") ||
924 sText.startsWith(
"drag pattern:") ) {
928 if (sText.startsWith(
"move instrument:")) {
930 int nSourceInstrument = pHydrogen->getSelectedInstrumentNumber();
936 pEv->position().y() - 50 : pEv->position().y();
940 if( nTargetInstrument >= pInstrumentList->size() ){
941 nTargetInstrument = pInstrumentList->size() - 1;
944 if ( nSourceInstrument == nTargetInstrument ) {
945 event->acceptProposedAction();
952 event->acceptProposedAction();
954 if( sText.startsWith(
"importInstrument:") ) {
957 sText = sText.remove(0,QString(
"importInstrument:").length());
959 QStringList tokens = sText.split(
"::" );
960 QString sDrumkitPath = tokens.at( 0 );
961 QString sInstrumentName = tokens.at( 1 );
969 if ( pEv->position().x() > 181 ) {
970 nTargetInstrument = ( pEv->position().y() - 90 ) /
m_nGridHeight ;
973 if( nTargetInstrument > pInstrumentList->size() ){
974 nTargetInstrument = pInstrumentList->size();
979 if ( sDrumkitPath.isEmpty() ) {
980 QMessageBox::critical(
this,
"Hydrogen", pCommonString->getInstrumentLoadError() );
987 event->acceptProposedAction();
997 if (event->button() == Qt::LeftButton) {
1007 auto pEv =
static_cast<MouseEvent*
>( event );
1009 if (!(event->buttons() & Qt::LeftButton)) {
1018 if ( pSelectedInstrument ==
nullptr ) {
1019 ERRORLOG(
"No instrument selected" );
1023 QString sText = QString(
"move instrument:%1").arg( pSelectedInstrument->get_name() );
1025 QDrag *pDrag =
new QDrag(
this);
1026 QMimeData *pMimeData =
new QMimeData;
1028 pMimeData->setText( sText );
1029 pDrag->setMimeData( pMimeData);
1032 pDrag->exec( Qt::CopyAction | Qt::MoveAction );
1036 QWidget::mouseMoveEvent(event);
1043 if ( nInstrumentNumber == -1 ) {
1047 if ( pInstrumentLine !=
nullptr ) {
1048 auto pInstrument = pInstrumentList->get( ii );
1049 if ( pInstrument ==
nullptr ) {
1050 ERRORLOG( QString(
"Instrument [%1] associated to InstrumentLine [%1] not found" )
1055 pInstrumentLine->setName( pInstrument->get_name() );
1056 pInstrumentLine->setMuted( pInstrument->is_muted() );
1057 pInstrumentLine->setSoloed( pInstrument->is_soloed() );
1063 auto pInstrument = pInstrumentList->get( nInstrumentNumber );
1064 if ( pInstrument ==
nullptr ) {
1065 ERRORLOG( QString(
"Instrument [%1] not found" )
1066 .arg( nInstrumentNumber ) );
1071 if ( pInstrumentLine ==
nullptr ) {
1072 ERRORLOG( QString(
"No InstrumentLine for instrument [%1] created yet" )
1073 .arg( nInstrumentNumber ) );
1077 pInstrumentLine->setName( pInstrument->get_name() );
1078 pInstrumentLine->setMuted( pInstrument->is_muted() );
1079 pInstrumentLine->setSoloed( pInstrument->is_soloed() );
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
#define FOREACH_NOTE_CST_IT_BOUND_LENGTH(_notes, _it, _bound, _pattern)
Iterate over all notes in column _bound in an immutable way if it is contained in _pattern.
#define FOREACH_NOTE_CST_IT_BEGIN_END(_notes, _it)
Iterate over all provided notes in an immutable way.
Compatibility class to support QDropEvent more esily in Qt5 and Qt6.
virtual void updateEditor(bool bPatternOnly=false) override
void unlock()
Mutex unlocking of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
Sampler * getSampler() const
bool setStripIsMuted(int nStrip, bool isMuted)
bool setStripIsSoloed(int nStrip, bool isSoloed)
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
bool hasJackAudioDriver() const
void renameJackPorts(std::shared_ptr< Song > pSong)
Calls audioEngine_renameJackPorts() if Preferences::m_bJackTrackOuts is set to true.
std::shared_ptr< Song > getSong() const
Get the current song.
int getSelectedInstrumentNumber() const
int getSelectedPatternNumber() const
void setSelectedInstrumentNumber(int nInstrument, bool bTriggerEvent=true)
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
AudioEngine * getAudioEngine() const
std::shared_ptr< Instrument > getSelectedInstrument() const
CoreActionController * getCoreActionController() const
A note plays an associated instrument with a velocity left and right pan.
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
float get_velocity() const
__velocity accessor
PatternList is a collection of patterns.
int size() const
returns the numbers of patterns
Pattern * get(int idx)
get a pattern from the list
Pattern class is a Note container.
int get_length() const
set the denominator of the pattern
const notes_t * get_notes() const
get the virtual pattern set
std::multimap< int, Note * > notes_t
< multimap note type
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
unsigned getPatternEditorGridHeight()
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.
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
QUndoStack * m_pUndoStack
PatternEditorPanel * getPatternEditorPanel()
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
QMenu * m_pFunctionPopupSub
void setRowSelection(RowSelection rowSelection)
void selectInstrumentNotes()
InstrumentLine(QWidget *pParent)
virtual void mousePressEvent(QMouseEvent *ev) override
virtual void mouseDoubleClickEvent(QMouseEvent *ev) override
virtual void leaveEvent(QEvent *ev)
void functionDeleteNotesAllPatterns()
void functionFillNotes(int every)
void setNumber(int nIndex)
void functionFillEveryTwelveNotes()
void functionRenameInstrument()
void functionCopyAllInstrumentPatterns()
void functionClearNotes()
void functionFillEverySixNotes()
void functionFillEveryThreeNotes()
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void setMuted(bool isMuted)
void setSelected(bool isSelected)
Button * m_pSampleWarning
void functionPasteAllInstrumentPatterns()
void setSamplesMissing(bool bSamplesMissing)
H2Core::Pattern * getCurrentPattern()
void functionFillAllNotes()
void setSoloed(bool soloed)
void setName(const QString &sName)
static constexpr int m_nButtonWidth
void sampleWarningClicked()
virtual void paintEvent(QPaintEvent *ev) override
void functionCutNotesAllPatterns()
void functionRandomizeVelocity()
int m_nInstrumentNumber
The related instrument number.
void functionFillEverySixteenNotes()
void functionFillEveryTwoNotes()
virtual void enterEvent(QEvent *ev) override
bool m_bEntered
Whether the cursor entered the boundary of the widget.
void functionFillEveryEightNotes()
void functionFillEveryFourNotes()
Compatibility class to support QMouseEvent more esily in Qt5 and Qt6.
~PatternEditorInstrumentList()
virtual void mouseMoveEvent(QMouseEvent *event) override
void updateInstrumentLines()
Update every InstrumentLine, create or destroy lines if necessary.
InstrumentLine * createInstrumentLine()
Create a new InstrumentLine.
PatternEditorPanel * m_pPatternEditorPanel
virtual void mousePressEvent(QMouseEvent *event) override
PatternEditorInstrumentList(QWidget *parent, PatternEditorPanel *pPatternEditorPanel)
virtual void drumkitLoadedEvent() override
virtual void instrumentParametersChangedEvent(int) override
DragScroller * m_pDragScroller
virtual void dragEnterEvent(QDragEnterEvent *event) override
virtual void selectedInstrumentChangedEvent() override
virtual void updateSongEvent(int nEvent) override
void repaintInstrumentLines()
QPoint __drag_start_position
virtual void dropEvent(QDropEvent *event) override
H2Core::Pattern * m_pPattern
InstrumentLine * m_pInstrumentLine[MAX_INSTRUMENTS]
void selectInstrumentNotes(int nInstrument)
DrumPatternEditor * getDrumPatternEditor()
bool isUsingTriplets() const
uint getResolution() const
static void drawListBackground(QPainter *p, QRect rect, QColor background, bool bHovered)
Draws the background of a row in both the pattern list of the SongEditor and the instrument list in t...
#define MAX_INSTRUMENTS
Maximum number of instruments allowed in Hydrogen.
#define MAX_NOTES
Maximum number of notes.
@ EVENT_SELECTED_INSTRUMENT_CHANGED