hydrogen 1.2.6
SoundLibraryPanel.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 "SoundLibraryPanel.h"
24
25#include <QtGui>
26#include <QtWidgets>
27
28#include "SoundLibraryTree.h"
29#include "FileBrowser.h"
30
33
34#include "../HydrogenApp.h"
35#include "../CommonStrings.h"
36#include "../Widgets/Button.h"
42#include "../InstrumentRack.h"
44
45#include <core/Basics/Adsr.h>
47#include <core/H2Exception.h>
48#include <core/Hydrogen.h>
49#include <core/Basics/Drumkit.h>
52#include <core/Basics/Pattern.h>
54#include <core/Basics/Sample.h>
55#include <core/Basics/Song.h>
58
59using namespace H2Core;
60
61#include <cassert>
62
63SoundLibraryPanel::SoundLibraryPanel( QWidget *pParent, bool bInItsOwnDialog )
64 : QWidget( pParent )
65 , __sound_library_tree( nullptr )
66 , __drumkit_menu( nullptr )
67 , __song_menu( nullptr )
68 , __pattern_menu( nullptr )
69 , __pattern_menu_list( nullptr )
70 , m_pTreeSystemDrumkitsItem( nullptr )
71 , m_pTreeUserDrumkitsItem( nullptr )
73 , __song_item( nullptr )
74 , __pattern_item( nullptr )
75 , __pattern_item_list( nullptr )
76 , m_bInItsOwnDialog( bInItsOwnDialog )
77{
78
79 __drumkit_menu = new QMenu( this );
80 __drumkit_menu->addAction( tr( "Load" ), this, SLOT( on_drumkitLoadAction() ) );
81 __drumkit_menu->addAction( tr( "Export" ), this, SLOT( on_drumkitExportAction() ) );
82 __drumkit_menu->addAction( tr( "Properties" ), this, SLOT( on_drumkitPropertiesAction() ) );
83 __drumkit_menu->addSeparator();
84 __drumkit_menu->addAction( tr( "Delete" ), this, SLOT( on_drumkitDeleteAction() ) );
85
86 // A version with reduced functionality for read-only drumkits
87 __drumkit_menu_system = new QMenu( this );
88 __drumkit_menu_system->addAction( tr( "Load" ), this, SLOT( on_drumkitLoadAction() ) );
89 __drumkit_menu_system->addAction( tr( "Export" ), this, SLOT( on_drumkitExportAction() ) );
90 __drumkit_menu_system->addAction( tr( "Properties" ), this, SLOT( on_drumkitPropertiesAction() ) );
91
92 __song_menu = new QMenu( this );
93 __song_menu->addSeparator();
94 __song_menu->addAction( tr( "Load" ), this, SLOT( on_songLoadAction() ) );
95
96 __pattern_menu = new QMenu( this );
97 __pattern_menu->addSeparator();
98 __pattern_menu->addAction( tr( "Load" ), this, SLOT( on_patternLoadAction() ) );
99 __pattern_menu->addAction( tr( "Delete" ), this, SLOT( on_patternDeleteAction() ) );
100
101 __pattern_menu_list = new QMenu( this );
102 __pattern_menu_list->addSeparator();
103 __pattern_menu_list->addAction( tr( "Load" ), this, SLOT( on_patternLoadAction() ) );
104
105// DRUMKIT LIST
106 __sound_library_tree = new SoundLibraryTree( nullptr );
107 connect( __sound_library_tree, SIGNAL( currentItemChanged ( QTreeWidgetItem*, QTreeWidgetItem* ) ), this, SLOT( on_DrumkitList_ItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ) );
108 connect( __sound_library_tree, SIGNAL( itemActivated ( QTreeWidgetItem*, int ) ), this, SLOT( on_DrumkitList_itemActivated( QTreeWidgetItem*, int ) ) );
109 connect( __sound_library_tree, SIGNAL( leftClicked(QPoint) ), this, SLOT( on_DrumkitList_leftClicked(QPoint)) );
110 if( ! m_bInItsOwnDialog ) {
111 connect( __sound_library_tree, SIGNAL( rightClicked(QPoint) ), this, SLOT( on_DrumkitList_rightClicked(QPoint)) );
112 connect( __sound_library_tree, SIGNAL( onMouseMove( QMouseEvent* ) ), this, SLOT( on_DrumkitList_mouseMove( QMouseEvent* ) ) );
113 }
114
115
116 // LAYOUT
117 QVBoxLayout *pVBox = new QVBoxLayout();
118 pVBox->setSpacing( 0 );
119 pVBox->setContentsMargins( 0, 0, 0, 0 );
120
121 pVBox->addWidget( __sound_library_tree );
122
123
124 this->setLayout( pVBox );
125
128
130
131 updateTree();
132
134}
135
136
137
139{
140 if ( auto pH2App = HydrogenApp::get_instance() ) {
141 pH2App->removeEventListener( this );
142 }
143}
144
145
146
148{
150 auto pHydrogen = H2Core::Hydrogen::get_instance();
151 auto pSoundLibraryDatabase = pHydrogen->getSoundLibraryDatabase();
152 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
153
154 __sound_library_tree->clear();
155
156 QFont boldFont( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
157 boldFont.setBold( true );
158
159 QFont childFont( pPref->getLevel2FontFamily(), getPointSize( pPref->getFontSize() ) );
160 setFont( childFont );
161
163 m_pTreeUserDrumkitsItem = nullptr;
165
166 // top-level drumkit items found
167 QList<QTreeWidgetItem*> drumkitItems;
168
169 // drumkit list
170 m_drumkitRegister.clear();
171 m_drumkitLabels.clear();
172 for ( const auto& pDrumkitEntry : pSoundLibraryDatabase->getDrumkitDatabase() ) {
173 auto pDrumkit = pDrumkitEntry.second;
174 if ( pDrumkit != nullptr ) {
175 QString sItemLabel = pDrumkit->get_name();
176 auto drumkitType =
177 Filesystem::determineDrumkitType( pDrumkitEntry.first );
178
179 QTreeWidgetItem* pDrumkitItem;
180 if ( drumkitType == Filesystem::DrumkitType::System ) {
181 if ( m_pTreeSystemDrumkitsItem == nullptr ) {
182 m_pTreeSystemDrumkitsItem = new QTreeWidgetItem();
183 m_pTreeSystemDrumkitsItem->setText( 0, tr( "System drumkits" ) );
184 m_pTreeSystemDrumkitsItem->setFont( 0, boldFont );
185 }
186
187 pDrumkitItem = new QTreeWidgetItem( m_pTreeSystemDrumkitsItem );
188 sItemLabel.append( QString( " (%1)" )
189 .arg( pCommonStrings->getSoundLibrarySystemSuffix() ) );
190 }
191 else if ( drumkitType == Filesystem::DrumkitType::User ) {
192 if ( m_pTreeUserDrumkitsItem == nullptr ) {
193 m_pTreeUserDrumkitsItem = new QTreeWidgetItem();
194 m_pTreeUserDrumkitsItem->setText( 0, tr( "User drumkits" ) );
195 m_pTreeUserDrumkitsItem->setFont( 0, boldFont );
196 }
197
198 pDrumkitItem = new QTreeWidgetItem( m_pTreeUserDrumkitsItem );
199 } else {
200 if ( m_pTreeSessionDrumkitsItem == nullptr ) {
201 m_pTreeSessionDrumkitsItem = new QTreeWidgetItem();
202 m_pTreeSessionDrumkitsItem->setText( 0, tr( "Session drumkits" ) );
203 m_pTreeSessionDrumkitsItem->setFont( 0, boldFont );
204 }
205 pDrumkitItem = new QTreeWidgetItem( m_pTreeSessionDrumkitsItem );
206 sItemLabel.append( QString( " (%1)" )
207 .arg( pCommonStrings->getSoundLibrarySessionSuffix() ) );
208 }
209
210
211 // Ensure uniqueness of the label.
212 int nCount = 1;
213 while ( m_drumkitLabels.contains( sItemLabel ) ) {
214 sItemLabel = QString( "%1 (%2)" )
215 .arg( pDrumkit->get_name() ).arg( nCount );
216 nCount++;
217 }
218
219 m_drumkitLabels << sItemLabel;
220 m_drumkitRegister[ sItemLabel ] = pDrumkitEntry.first;
221
222 pDrumkitItem->setText( 0, sItemLabel );
223 pDrumkitItem->setToolTip( 0, pDrumkitEntry.first );
224 if ( ! m_bInItsOwnDialog ) {
225 auto pInstrList = pDrumkit->get_instruments();
226 for ( const auto& pInstrument : *pDrumkit->get_instruments() ) {
227 if ( pInstrument != nullptr ) {
228 QTreeWidgetItem* pInstrumentItem = new QTreeWidgetItem( pDrumkitItem );
229 pInstrumentItem->setText( 0, QString( "[%1] %2" )
230 .arg( pInstrument->get_id() )
231 .arg( pInstrument->get_name() ) );
232 pInstrumentItem->setToolTip( 0, pInstrument->get_name() );
233 }
234 }
235 }
236 }
237 }
238
239 // Ensure the ordering of the top-level nodes is always
240 // system > user > session
241 if ( m_pTreeSystemDrumkitsItem != nullptr ) {
242 drumkitItems << m_pTreeSystemDrumkitsItem;
243 }
244 if ( m_pTreeUserDrumkitsItem != nullptr ) {
245 drumkitItems << m_pTreeUserDrumkitsItem;
246 }
247 if ( m_pTreeSessionDrumkitsItem != nullptr ) {
248 drumkitItems << m_pTreeSessionDrumkitsItem;
249 }
250 __sound_library_tree->addTopLevelItems( drumkitItems );
251
252 // Ensure drumkit nodes are expanded (necessary when added as
253 // above.)
254 if ( m_pTreeSystemDrumkitsItem != nullptr ) {
255 m_pTreeSystemDrumkitsItem->setExpanded( true );
256 }
257 if ( m_pTreeUserDrumkitsItem != nullptr ) {
258 m_pTreeUserDrumkitsItem->setExpanded( true );
259 }
260 if ( m_pTreeSessionDrumkitsItem != nullptr ) {
261 m_pTreeSessionDrumkitsItem->setExpanded( true );
262 }
263
264 if ( ! m_bInItsOwnDialog ) {
265 //Songlist
266 QStringList songs = Filesystem::song_list_cleared();
267 if ( songs.size() > 0 ) {
268 __song_item = new QTreeWidgetItem( __sound_library_tree );
269 __song_item->setText( 0, tr( "Songs" ) );
270 __song_item->setToolTip( 0, tr("Double click to expand the list") );
271 __song_item->setExpanded( __expand_songs_list );
272 __song_item->setFont( 0, boldFont );
273 for (uint i = 0; i < songs.size(); i++) {
274 QTreeWidgetItem* pSongItem = new QTreeWidgetItem( __song_item );
275 QString song = songs[i];
276 pSongItem->setText( 0 , song.left( song.indexOf(".")) );
277 pSongItem->setToolTip( 0, song );
278 }
279 }
280
281
282 //Pattern list
283 QStringList patternDirList = Filesystem::pattern_drumkits();
284 if ( patternDirList.size() > 0 ) {
285
286 __pattern_item = new QTreeWidgetItem( __sound_library_tree );
287 __pattern_item->setText( 0, tr( "Patterns" ) );
288 __pattern_item->setToolTip( 0, tr("Double click to expand the list") );
290 __pattern_item->setFont( 0, boldFont );
291
292 auto patternInfoVector = pSoundLibraryDatabase->getPatternInfoVector();
293 QStringList patternCategories =
294 pSoundLibraryDatabase->getPatternCategories();
295
296 //now sorting via category
297
298 /*: Base tooltip displayed when hovering over a pattern in
299 the Sound Library. It indicates which drumkit the
300 pattern was created with*/
301 QString sPatternTooltip = tr( "Created for drumkit" );
302 for ( const auto& categoryName : patternCategories ) {
303
304 QTreeWidgetItem* pCategoryItem = new QTreeWidgetItem( __pattern_item );
305 pCategoryItem->setText( 0, categoryName );
306
307 for ( const auto& pInfo : patternInfoVector ) {
308 QString patternCategory = pInfo->getCategory();
309 if ( ( patternCategory == categoryName ) ||
310 ( patternCategory.isEmpty() && categoryName == "No category" ) ){
311 QTreeWidgetItem* pPatternItem = new QTreeWidgetItem( pCategoryItem );
312 pPatternItem->setText( 0, pInfo->getName());
313 pPatternItem->setText( 1, pInfo->getPath() );
314 pPatternItem->setToolTip( 0, QString( "%1 [%2]" )
315 .arg( sPatternTooltip )
316 .arg( pInfo->getDrumkitName() ) );
317 }
318 }
319 }
320 }
321 }
322
324}
325
326
327
328void SoundLibraryPanel::on_DrumkitList_ItemChanged( QTreeWidgetItem * current, QTreeWidgetItem * previous )
329{
330 UNUSED( previous );
331
332 if( current == nullptr ){
333 return;
334 }
335
336 if ( current->parent() == m_pTreeSystemDrumkitsItem ||
337 current->parent() == m_pTreeUserDrumkitsItem ||
338 current->parent() == m_pTreeSessionDrumkitsItem ){
339 emit item_changed( true );
340 } else {
341 emit item_changed( false );
342 }
343
345}
346
347
348
349void SoundLibraryPanel::on_DrumkitList_itemActivated( QTreeWidgetItem * item, int column )
350{
351 UNUSED( column );
352
353// INFOLOG( "[on_DrumkitList_itemActivated]" );
354 if ( item == m_pTreeSystemDrumkitsItem ||
355 item == m_pTreeUserDrumkitsItem ||
357 ( ( m_pTreeSystemDrumkitsItem != nullptr &&
358 item == m_pTreeSystemDrumkitsItem->parent() ) ||
359 ( m_pTreeUserDrumkitsItem != nullptr &&
360 item == m_pTreeUserDrumkitsItem->parent() ) ||
361 ( m_pTreeSessionDrumkitsItem != nullptr &&
362 item == m_pTreeSessionDrumkitsItem->parent() ) )||
363 item->parent() == __song_item ||
364 item == __song_item ||
365 item == __pattern_item ||
366 item->parent() == __pattern_item ||
367 item->parent()->parent() == __pattern_item ||
368 item == __pattern_item_list ||
369 item->parent() == __pattern_item_list ||
370 item->parent()->parent() == __pattern_item_list ) {
371 return;
372 }
373
374 if ( item->parent() == m_pTreeSystemDrumkitsItem ||
375 item->parent() == m_pTreeUserDrumkitsItem ||
376 item->parent() == m_pTreeSessionDrumkitsItem ) {
377 // Double clicking a drumkit
378 }
379 else {
380 // Double clicking an instrument
381 QString sSelectedName = item->text(0);
382
383 QString sInstrName = sSelectedName.remove( 0, sSelectedName.indexOf( "] " ) + 2 );
384 QString sDrumkitName = item->parent()->text(0);
385 QString sDrumkitPath = m_drumkitRegister[ sDrumkitName ];
386 INFOLOG( QString( "Loading instrument [%1] from drumkit [%2] located in [%3]" )
387 .arg( sInstrName ).arg( sDrumkitName ).arg( sDrumkitPath ) );
388
389 auto pInstrument = Instrument::load_instrument( sDrumkitPath, sInstrName );
390
391 if ( pInstrument == nullptr ) {
392 ERRORLOG( "Unable to load instrument. Abort" );
393 return;
394 }
395
396 pInstrument->set_muted( false );
397
399 }
400}
401
402
403
404
405
406
407
409{
410 if( __sound_library_tree->currentItem() == nullptr ) {
411 return;
412 }
413
414 if (
415 __sound_library_tree->currentItem()->parent() == nullptr ||
419 return;
420 }
421
422 if ( __sound_library_tree->currentItem()->parent() == __song_item ) {
423 __song_menu->popup( pos );
424 }
425
426 if ( __sound_library_tree->currentItem()->parent()->parent() == __pattern_item && __pattern_item != nullptr ) {
427 __pattern_menu->popup( pos );
428 }
429
430 if ( __sound_library_tree->currentItem()->parent() == m_pTreeUserDrumkitsItem ) {
431 __drumkit_menu->popup( pos );
432 }
433
434 if ( __sound_library_tree->currentItem()->parent() == m_pTreeSystemDrumkitsItem ) {
435 __drumkit_menu_system->popup( pos );
436 }
437
438 // We do not provide distinct parent items for read-only and
439 // writable session drumkits as it would make the GUI unnecessary
440 // complex. Instead, the level of access for the current user is
441 // checked during runtime (which should be a very rare thing to do).
442 if ( __sound_library_tree->currentItem()->parent() == m_pTreeSessionDrumkitsItem ) {
443 const QString sDrumkitName = __sound_library_tree->currentItem()->text( 0 );
444 const QString sDrumkitPath = m_drumkitRegister[ sDrumkitName ];
445 const auto drumkitType = Filesystem::determineDrumkitType( sDrumkitPath );
446
447 if ( drumkitType == Filesystem::DrumkitType::SessionReadOnly ) {
448 __drumkit_menu_system->popup( pos );
449 } else {
450 __drumkit_menu->popup( pos );
451 }
452 }
453
454}
455
456
457
462
463
464
466{
467 if (! ( event->buttons() & Qt::LeftButton ) ) {
468 return;
469 }
470
471 if ( ( event->pos() - __start_drag_position ).manhattanLength() < QApplication::startDragDistance() ) {
472 return;
473 }
474
475 if ( !__sound_library_tree->currentItem() ) {
476 return;
477 }
478
479 if ( __sound_library_tree->currentItem()->parent() == m_pTreeSystemDrumkitsItem ||
480 __sound_library_tree->currentItem()->parent() == m_pTreeUserDrumkitsItem ||
481 __sound_library_tree->currentItem()->parent() == m_pTreeSessionDrumkitsItem ) {
482 // drumkit selection
483 //INFOLOG( "ho selezionato un drumkit (system)" );
484 return;
485 }
486 else {
487 //INFOLOG( "ho selezionato uno strumento" );
488 // instrument selection
489 if ( __sound_library_tree->currentItem() == nullptr )
490 {
491 return;
492 }
493
494 if ( __sound_library_tree->currentItem()->parent() == nullptr )
495 {
496 return;
497 }
498
499 if ( __sound_library_tree->currentItem()->parent() == __song_item )
500 {
501 return;
502 }
503
504 if ( __sound_library_tree->currentItem()->parent()->text(0) == nullptr )
505 {
506 return;
507 }
508
509 if ( __sound_library_tree->currentItem()->parent() == __pattern_item ) {
510 return;
511 }
512
513 if ( __sound_library_tree->currentItem()->parent()->parent() == __pattern_item ) {
514
515 QString sPatternPath = __sound_library_tree->currentItem()->text( 1 );
516 QString dragtype = "drag pattern";
517 QString sText = dragtype + "::" + sPatternPath;
518
519 QDrag *pDrag = new QDrag(this);
520 QMimeData *pMimeData = new QMimeData;
521
522 pMimeData->setText( sText );
523 pDrag->setMimeData( pMimeData);
524 pDrag->exec( Qt::CopyAction | Qt::MoveAction );
525 return;
526 }
527
528 const QString sDrumkitName = __sound_library_tree->currentItem()->parent()->text(0);
529 const QString sDrumkitPath = m_drumkitRegister[ sDrumkitName ];
530 const QString sInstrumentName = ( __sound_library_tree->currentItem()->text(0) )
531 .remove( 0, __sound_library_tree->currentItem()->text(0).indexOf( "] " ) + 2 );
532
533 const QString sText = "importInstrument:" + sDrumkitPath + "::" + sInstrumentName;
534
535 QDrag *pDrag = new QDrag(this);
536 QMimeData *pMimeData = new QMimeData;
537
538 pMimeData->setText( sText );
539 pDrag->setMimeData( pMimeData);
540
541 pDrag->exec( Qt::CopyAction | Qt::MoveAction );
542 }
543}
544
545
546
548{
549 auto pHydrogen = H2Core::Hydrogen::get_instance();
550
551 QString sDrumkitName = __sound_library_tree->currentItem()->text(0);
552 QString sDrumkitPath = m_drumkitRegister[ sDrumkitName ];
553 auto pDrumkit =
554 pHydrogen->getSoundLibraryDatabase()->getDrumkit( sDrumkitPath );
555
556 if ( pDrumkit == nullptr ) {
557 ERRORLOG( QString( "Unable to find drumkit [%1] (mapped to path [%2]" )
558 .arg( sDrumkitName ).arg( sDrumkitPath ) );
559 return;
560 }
561
562 auto pSongInstrList = pHydrogen->getSong()->getInstrumentList();
563 auto pDrumkitInstrList = pDrumkit->get_instruments();
564
565 int oldCount = pSongInstrList->size();
566 int newCount = pDrumkitInstrList->size();
567
568 bool conditionalLoad = false;
569 bool hasNotes = false;
570
571 INFOLOG("Old kit has " + QString::number( oldCount ) + " instruments, new one has " + QString::number( newCount ) );
572
573 if ( newCount < oldCount )
574 {
575 // Check if any of the instruments that will be removed have notes
576 for ( int i = 0; i < pSongInstrList->size(); i++)
577 {
578 if ( i >= newCount )
579 {
580 INFOLOG("Checking if Instrument " + QString::number( i ) + " has notes..." );
581
582 if ( pHydrogen->instrumentHasNotes( pSongInstrList->get( i ) ) )
583 {
584 hasNotes = true;
585 INFOLOG("Instrument " + QString::number( i ) + " has notes" );
586 }
587 }
588
589 }
590
591 if ( hasNotes ) {
592 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
593 QMessageBox msgBox;
594 msgBox.setWindowTitle("Hydrogen");
595 msgBox.setIcon( QMessageBox::Warning );
596 msgBox.setText( tr( "The existing kit has %1 instruments but the new one only has %2.\nThe first %2 instruments will be replaced with the new instruments and will keep their notes, but some of the remaining instruments have notes.\nWould you like to keep or discard the remaining instruments and notes?\n").arg( QString::number( oldCount ),QString::number( newCount ) ) );
597
598 msgBox.setStandardButtons( QMessageBox::Save | QMessageBox::Discard |
599 QMessageBox::Cancel );
600 msgBox.setDefaultButton(QMessageBox::Cancel);
601
602 switch ( msgBox.exec() )
603 {
604 case QMessageBox::Save:
605 // Save old instruments with notes
606 conditionalLoad = true;
607 break;
608
609 case QMessageBox::Discard:
610 // discard extra instruments
611 conditionalLoad = false;
612 break;
613
614 case QMessageBox::Cancel:
615 // Cancel
616 return;
617 }
618 }
619 }
620
621 assert( pDrumkit );
622
623 QApplication::setOverrideCursor(Qt::WaitCursor);
624
625 pHydrogen->getCoreActionController()->setDrumkit( pDrumkit, conditionalLoad );
626
627 QApplication::restoreOverrideCursor();
628}
629
633
637
643
644
645
647{
648 if ( m_pTreeSystemDrumkitsItem != nullptr ) {
649 for (int i = 0; i < m_pTreeSystemDrumkitsItem->childCount() ; i++){
650 ( m_pTreeSystemDrumkitsItem->child( i ) )->setBackground( 0, QBrush() );
651 }
652 }
653
654 if ( m_pTreeUserDrumkitsItem != nullptr ) {
655 for (int i = 0; i < m_pTreeUserDrumkitsItem->childCount() ; i++){
656 ( m_pTreeUserDrumkitsItem->child( i ) )->setBackground(0, QBrush() );
657 }
658 }
659
660 if ( m_pTreeSessionDrumkitsItem != nullptr ) {
661 for (int i = 0; i < m_pTreeSessionDrumkitsItem->childCount() ; i++){
662 ( m_pTreeSessionDrumkitsItem->child( i ) )->setBackground( 0, QBrush() );
663 }
664 }
665
666}
667
668QString SoundLibraryPanel::getDrumkitLabel( const QString& sDrumkitPath ) const {
669 for ( const auto& entry : m_drumkitRegister ) {
670 if ( entry.second == sDrumkitPath ) {
671 return entry.first;
672 }
673 }
674
675 return "";
676}
677QString SoundLibraryPanel::getDrumkitPath( const QString& sDrumkitLabel ) const {
678 return m_drumkitRegister.at( sDrumkitLabel );
679}
680
682{
683 auto pSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrument();
684 if ( pSelectedInstrument == nullptr ) {
685 DEBUGLOG( "No instrument selected" );
686 return;
687 }
688 QString sDrumkitPath = pSelectedInstrument->get_drumkit_path();
689 QString sDrumkitLabel = getDrumkitLabel( sDrumkitPath );
690
691 if ( sDrumkitLabel.isEmpty() ) {
692 ERRORLOG( QString( "Unable to find label corresponding to drumkit [%1]. No highlighting applied" )
693 .arg( sDrumkitPath ) );
694 return;
695 }
696
697 if ( m_pTreeSystemDrumkitsItem != nullptr ) {
698 for ( int i = 0; i < m_pTreeSystemDrumkitsItem->childCount() ; i++){
699 if ( ( m_pTreeSystemDrumkitsItem->child( i ) )->text( 0 ) == sDrumkitLabel ){
700 ( m_pTreeSystemDrumkitsItem->child( i ) )->setBackground( 0, QColor( 50, 50, 50) );
701 return;
702 }
703 }
704 }
705
706 if ( m_pTreeUserDrumkitsItem != nullptr ) {
707 for (int i = 0; i < m_pTreeUserDrumkitsItem->childCount() ; i++){
708 if ( ( m_pTreeUserDrumkitsItem->child( i ))->text( 0 ) == sDrumkitLabel ){
709 ( m_pTreeUserDrumkitsItem->child( i ) )->setBackground( 0, QColor( 50, 50, 50) );
710 break;
711 }
712 }
713 }
714
715 if ( m_pTreeSessionDrumkitsItem != nullptr ) {
716 for ( int i = 0; i < m_pTreeSessionDrumkitsItem->childCount() ; i++){
717 if ( ( m_pTreeSessionDrumkitsItem->child( i ) )->text( 0 ) == sDrumkitLabel ){
718 ( m_pTreeSessionDrumkitsItem->child( i ) )->setBackground( 0, QColor( 50, 50, 50) );
719 return;
720 }
721 }
722 }
723
724}
725
726
728{
729 QTreeWidgetItem* pItem = __sound_library_tree->currentItem();
730 const QString sDrumkitName = pItem->text(0);
731 const QString sDrumkitPath = m_drumkitRegister[ sDrumkitName ];
732 const auto drumkitType = Filesystem::determineDrumkitType( sDrumkitPath );
733
734 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
735
736 if ( pItem->parent() == m_pTreeSystemDrumkitsItem ||
737 ( pItem->parent() == m_pTreeSessionDrumkitsItem &&
739 QMessageBox::warning( this, "Hydrogen", QString( "\"%1\" " )
740 .arg(sDrumkitName)
741 .append( tr( "is a read-only drumkit and can't be deleted.") ) );
742 return;
743 }
744
745 // If we delete the current loaded drumkit we can get trouble with some empty pointers
746 if ( pItem->text(0) == Hydrogen::get_instance()->getLastLoadedDrumkitName() ){
747 QMessageBox::warning( this, "Hydrogen", tr( "It is not possible to delete the currently loaded drumkit: \n \"%1\".\nTo delete this drumkit first load another drumkit.").arg(sDrumkitName) );
748 return;
749 }
750
751 if ( QMessageBox::warning(
752 this, "Hydrogen",
753 tr( "Warning, the \"%1\" drumkit will be deleted from disk.\nAre you sure?").arg(sDrumkitName),
754 QMessageBox::Ok | QMessageBox::Cancel,
755 QMessageBox::Cancel ) == QMessageBox::Cancel ) {
756 return;
757 }
758
759 QApplication::setOverrideCursor(Qt::WaitCursor);
760 bool bSuccess = Drumkit::remove( m_drumkitRegister[ pItem->text(0) ] );
761 QApplication::restoreOverrideCursor();
762 if ( ! bSuccess ) {
763 QMessageBox::warning( this, "Hydrogen", tr( "Drumkit deletion failed.") );
764 }
765}
766
767
768
770{
771 auto pSoundLibraryDatabase =
773
774 QString sDrumkitName = __sound_library_tree->currentItem()->text(0);
775 QString sDrumkitPath = m_drumkitRegister[ sDrumkitName ];
776 auto pDrumkit = pSoundLibraryDatabase->getDrumkit( sDrumkitPath );
777
778 SoundLibraryExportDialog exportDialog( this, pDrumkit );
779 exportDialog.exec();
780}
781
782
783
785{
786 auto pHydrogen = H2Core::Hydrogen::get_instance();
787 auto pSoundLibraryDatabase = pHydrogen->getSoundLibraryDatabase();
788
789 QString sDrumkitName = __sound_library_tree->currentItem()->text(0);
790 QString sDrumkitPath = m_drumkitRegister[ sDrumkitName ];
791 auto pDrumkit = pSoundLibraryDatabase->getDrumkit( sDrumkitPath );
792
793 if ( pDrumkit == nullptr ) {
794 ERRORLOG( QString( "Unable to find drumkit [%1] (mapped to path [%2]" )
795 .arg( sDrumkitName ).arg( sDrumkitPath ) );
796 return;
797 }
798
799 // We provide a copy of the recent drumkit to ensure the drumkit
800 // is not getting dirty upon saving (in case new properties are
801 // stored in the kit but writing it to disk fails).
802 auto pNewDrumkit = std::make_shared<Drumkit>( pDrumkit );
803 SoundLibraryPropertiesDialog dialog( this, pNewDrumkit, true );
804 dialog.exec();
805}
806
808{
809 QString sFilename = Filesystem::song_path( __sound_library_tree->currentItem()->text( 0 ) );
810
811 HydrogenApp::get_instance()->openSong( sFilename );
812}
813
814
815
817
818 QString sPatternName = __sound_library_tree->currentItem()->text( 0 );
819 QString sDrumkitName = __sound_library_tree->currentItem()->toolTip ( 0 );
821 ->openPattern( Filesystem::pattern_path( sDrumkitName,
822 sPatternName ) );
823}
824
825
827{
828 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
829 QString patternPath = __sound_library_tree->currentItem()->text( 1 );
830
831 if ( QMessageBox::information(
832 this, "Hydrogen",
833 tr( "Warning, the selected pattern will be deleted from disk.\nAre you sure?"),
834 QMessageBox::Ok | QMessageBox::Cancel,
835 QMessageBox::Cancel ) == QMessageBox::Cancel ) {
836 return;
837 }
838
839 QFile rmfile( patternPath );
840 bool err = rmfile.remove();
841 if ( err == false ) {
842 ERRORLOG( "Error removing the pattern" );
843 }
844
846}
847
852
854{
855 assert( __sound_library_tree );
856 if ( __song_item == nullptr) {
857 __expand_songs_list = false;
858 } else {
859 __expand_songs_list = __song_item->isExpanded();
860 }
861 if ( __pattern_item == nullptr) {
862 __expand_pattern_list = false;
863 } else {
865 }
868 //ERRORLOG( QString("songs %1 patterns %2").arg(__expand_songs_list).arg(__expand_pattern_list) );
869}
870
873
874 if ( changes & H2Core::Preferences::Changes::Font ) {
875
876 QFont font( pPref->getLevel2FontFamily(), getPointSize( pPref->getFontSize() ) );
877 QFont boldFont( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
878 boldFont.setBold( true );
879
880 int ii, jj;
881 QTreeWidgetItem* childNode;
882 if ( m_pTreeSystemDrumkitsItem != nullptr ) {
883 m_pTreeSystemDrumkitsItem->setFont( 0, boldFont );
884 for ( ii = 0; ii < m_pTreeSystemDrumkitsItem->childCount(); ii++ ){
885 childNode = m_pTreeSystemDrumkitsItem->child( ii );
886 childNode->setFont( 0, font );
887 for ( jj = 0; jj < childNode->childCount(); jj++ ) {
888 childNode->child( jj )->setFont( 0, font );
889 }
890 }
891 }
892
893 if ( m_pTreeUserDrumkitsItem != nullptr ) {
894 m_pTreeUserDrumkitsItem->setFont( 0, boldFont );
895 for ( ii = 0; ii < m_pTreeUserDrumkitsItem->childCount(); ii++ ){
896 childNode = m_pTreeUserDrumkitsItem->child( ii );
897 childNode->setFont( 0, font );
898 for ( jj = 0; jj < childNode->childCount(); jj++ ) {
899 childNode->child( jj )->setFont( 0, font );
900 }
901 }
902 }
903
904 if ( m_pTreeSessionDrumkitsItem != nullptr ) {
905 m_pTreeSessionDrumkitsItem->setFont( 0, boldFont );
906 for ( ii = 0; ii < m_pTreeSessionDrumkitsItem->childCount(); ii++ ){
907 childNode = m_pTreeSessionDrumkitsItem->child( ii );
908 childNode->setFont( 0, font );
909 for ( jj = 0; jj < childNode->childCount(); jj++ ) {
910 childNode->child( jj )->setFont( 0, font );
911 }
912 }
913 }
914
915 if ( __song_item != nullptr ) {
916 __song_item->setFont( 0, boldFont );
917 for ( ii = 0; ii < __song_item->childCount(); ii++ ){
918 __song_item->child( ii )->setFont( 0, font );
919 __song_item->setFont( ii, font );
920 }
921 }
922
923 if ( __pattern_item != nullptr ) {
924 __pattern_item->setFont( 0, boldFont );
925 for ( ii = 0; ii < __pattern_item->childCount(); ii++ ){
926 childNode = __pattern_item->child( ii );
927 childNode->setFont( 0, font );
928 for ( jj = 0; jj < childNode->childCount(); jj++ ) {
929 childNode->child( jj )->setFont( 0, font );
930 }
931 }
932 }
933 }
934}
935
937 // A new song got loaded
938 if ( nValue == 0 ) {
940 }
941}
#define INFOLOG(x)
Definition Object.h:240
#define ERRORLOG(x)
Definition Object.h:242
#define DEBUGLOG(x)
Definition Object.h:239
Sampler * getSampler() const
bool openPattern(const QString &sPath, int nPatternNumber=-1)
Opens a pattern from disk and adds it to the pattern list.
static bool remove(const QString &sDrumkitDir)
remove a drumkit from the disk
Definition Drumkit.cpp:704
static QString song_path(const QString &sg_name)
returns user song path, add file extension
static DrumkitType determineDrumkitType(const QString &sPath)
static QStringList song_list_cleared()
returns a list of existing songs, excluding the autosaved one
static QStringList pattern_drumkits()
returns a list of existing drumkit sub dir into the patterns directory
static QString pattern_path(const QString &dk_name, const QString &p_name)
returns user patterns path, add file extension
@ User
Kit was installed by the user, is automatically loaded, and most probably writable.
Definition Filesystem.h:78
@ System
Kit was installed with Hydrogen, is automatically loaded, and most probably readonly.
Definition Filesystem.h:75
@ SessionReadOnly
Kit was loaded via a NSM session, OSC command, or CLI option, only persist for the current Hydrogen s...
Definition Filesystem.h:82
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
SoundLibraryDatabase * getSoundLibraryDatabase() const
Definition Hydrogen.h:95
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:653
static std::shared_ptr< Instrument > load_instrument(const QString &drumkit_path, const QString &instrument_name)
creates a new Instrument, loads samples from a given instrument within a given drumkit
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.
void preview_instrument(std::shared_ptr< Instrument > pInstr)
Definition Sampler.cpp:1392
void updatePatterns(bool bTriggerEvent=true)
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
static bool openSong(QString sFilename)
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
std::map< QString, QString > m_drumkitRegister
Used to uniquely identify the drumkit corresponding to an item in the tree.
QString getDrumkitLabel(const QString &sDrumkitPath) const
QTreeWidgetItem * m_pTreeSessionDrumkitsItem
void on_DrumkitList_ItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
SoundLibraryPanel(QWidget *parent, bool bInItsOwnDialog)
void on_DrumkitList_leftClicked(QPoint pos)
QTreeWidgetItem * __pattern_item
void onPreferencesChanged(H2Core::Preferences::Changes changes)
virtual void updateSongEvent(int nValue) override
virtual void soundLibraryChangedEvent() override
virtual void drumkitLoadedEvent() override
QTreeWidgetItem * __pattern_item_list
bool m_bInItsOwnDialog
Whether the dialog was constructed via a click in the MainForm or as part of the GUI.
QStringList m_drumkitLabels
List of all labels used for drumkits in the tree.
void item_changed(bool bDrumkitSelected)
QString getDrumkitPath(const QString &sDrumkitLabel) const
SoundLibraryTree * __sound_library_tree
virtual void selectedInstrumentChangedEvent() override
QTreeWidgetItem * m_pTreeSystemDrumkitsItem
QTreeWidgetItem * __song_item
void on_DrumkitList_mouseMove(QMouseEvent *event)
void on_DrumkitList_itemActivated(QTreeWidgetItem *item, int column)
QTreeWidgetItem * m_pTreeUserDrumkitsItem
void on_DrumkitList_rightClicked(QPoint pos)
constexpr int getPointSize(H2Core::FontTheme::FontSize fontSize) const
#define UNUSED(v)
Definition Globals.h:42