hydrogen 1.2.6
PlaylistDialog.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
24#include "PlaylistDialog.h"
25#include "../HydrogenApp.h"
26#include "../CommonStrings.h"
27#include "../InstrumentRack.h"
31
32#include <core/Helpers/Files.h>
34#include <core/H2Exception.h>
36#include <core/Hydrogen.h>
39#include <core/Timeline.h>
40#include <core/EventQueue.h>
42
43#include "../Widgets/Button.h"
45
46#include <QTreeWidget>
47#include <QDomDocument>
48#include <QMessageBox>
49#include <QHeaderView>
50#include <vector>
51#include <cstdlib>
52#include <iostream>
53#include <fstream>
54#include <memory>
55
56using namespace H2Core;
57
58
60 : QDialog ( pParent )
61 , Object ()
62{
63
64 setupUi ( this );
65
66 // Show and enable maximize button. This is key when enlarging the
67 // application using a scaling factor and allows the OS to force its size
68 // beyond the minimum and make the scrollbars appear.
69 setWindowFlags( windowFlags() | Qt::CustomizeWindowHint |
70 Qt::WindowMinMaxButtonsHint );
71
73
74 QFont font( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
75 setFont( font );
76 m_pPlaylistTree->setFont( font );
77
78 setWindowTitle ( tr ( "Playlist Browser" ) + QString(" - ") + Playlist::get_instance()->getFilename() );
79
80 installEventFilter( this );
81
82 // menubar
83 m_pMenubar = new QMenuBar( this );
84
85 // Playlist menu
86 m_pPlaylistMenu = m_pMenubar->addMenu( tr( "&Playlist" ) );
87
88 auto pActionAddSong = m_pPlaylistMenu->addAction(
89 tr( "Add song to Play&list" ), this, SLOT( addSong() ) );
90 pActionAddSong->setShortcut( QKeySequence( "Ctrl+A" ) );
91 auto pActionAddCurrent = m_pPlaylistMenu->addAction(
92 tr( "Add &current song to Playlist" ), this, SLOT( addCurrentSong() ) );
93 pActionAddCurrent->setShortcut( QKeySequence( "Ctrl+Alt+A" ) );
94 m_pPlaylistMenu->addSeparator(); // -----
95 auto pActionRemoveSong = m_pPlaylistMenu->addAction(
96 tr( "&Remove selected song from Playlist" ), this, SLOT( removeFromList() ) );
97 pActionRemoveSong->setShortcut( QKeySequence::Delete );
98 auto pActionNew = m_pPlaylistMenu->addAction(
99 tr( "&New Playlist" ), this, SLOT( clearPlaylist() ) );
100 pActionNew->setShortcut( QKeySequence( "Ctrl+N" ) );
101 m_pPlaylistMenu->addSeparator();
102 auto pActionOpen = m_pPlaylistMenu->addAction(
103 tr( "&Open Playlist" ), this, SLOT( loadList() ) );
104 pActionOpen->setShortcut( QKeySequence( "Ctrl+O" ) );
105 m_pPlaylistMenu->addSeparator();
106 auto pActionSave = m_pPlaylistMenu->addAction(
107 tr( "&Save Playlist" ), this, SLOT( saveList() ) );
108 pActionSave->setShortcut( QKeySequence( "Ctrl+S" ) );
109 auto pActionSaveAs = m_pPlaylistMenu->addAction(
110 tr( "Save Playlist &as" ), this, SLOT( saveListAs() ) );
111 pActionSaveAs->setShortcut( QKeySequence( "Ctrl+Shift+S" ) );
112 m_pPlaylistMenu->setFont( font );
113
114#ifdef WIN32
115 //no scripts under windows
116#else
117 // Script menu
118 m_pScriptMenu = m_pMenubar->addMenu( tr( "&Scripts" ) );
119
120 m_pScriptMenu->addAction( tr( "&Add Script to selected song" ), this, SLOT( loadScript() ) );
121 m_pScriptMenu->addAction( tr( "&Edit selected Script" ), this, SLOT( editScript() ) );
122 m_pScriptMenu->addSeparator();
123 m_pScriptMenu->addAction( tr( "&Remove selected Script" ), this, SLOT( removeScript() ) );
124 m_pScriptMenu->addSeparator();
125 m_pScriptMenu->addAction( tr( "&Create a new Script" ), this, SLOT( newScript() ) );
126 m_pScriptMenu->setFont( font );
127#endif
128
129 QHBoxLayout* pMenuBarLayout = new QHBoxLayout( menuBarWidget );
130 pMenuBarLayout->setSpacing(0);
131 pMenuBarLayout->setContentsMargins( 0, 0, 0, 0 );
132 pMenuBarLayout->addWidget( m_pMenubar );
133
134 // CONTROLS
135 PixmapWidget *pControlsPanel = new PixmapWidget( controlWidget );
136 pControlsPanel->setFixedSize( 119, 32 );
137 pControlsPanel->setPixmap( "/playerControlPanel/playlist_background_Control.png" );
138
139 // Rewind button
140 m_pRwdBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push, "rewind.svg", "", false, QSize( 13, 13 ), tr("Rewind") );
141 m_pRwdBtn->move( 4, 4 );
142 connect(m_pRwdBtn, SIGNAL( clicked() ), this, SLOT( rewindBtnClicked() ));
143 std::shared_ptr<Action> pAction = std::make_shared<Action>("PLAYLIST_PREV_SONG");
144 m_pRwdBtn->setAction( pAction );
145
146 // Play button
147 m_pPlayBtn = new Button( pControlsPanel, QSize( 30, 21 ), Button::Type::Toggle, "play.svg", "", false, QSize( 13, 13 ), tr("Play/ Pause/ Load selected song") );
148 m_pPlayBtn->move( 31, 4 );
149 m_pPlayBtn->setChecked(false);
150 connect(m_pPlayBtn, SIGNAL( clicked() ), this, SLOT( nodePlayBTN() ));
151 pAction = std::make_shared<Action>("PLAY/PAUSE_TOGGLE");
152 m_pPlayBtn->setAction( pAction );
153
154 // Stop button
155 m_pStopBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push, "stop.svg", "", false, QSize( 11, 11 ), tr("Stop") );
156 m_pStopBtn->move( 63, 4 );
157 connect(m_pStopBtn, SIGNAL( clicked() ), this, SLOT( nodeStopBTN() ));
158 pAction = std::make_shared<Action>("STOP");
159 m_pStopBtn->setAction( pAction );
160
161 // Fast forward button
162 m_pFfwdBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push, "fast_forward.svg", "", false, QSize( 13, 13 ), tr("Fast Forward") );
163 m_pFfwdBtn->move( 90, 4 );
164 connect(m_pFfwdBtn, SIGNAL( clicked() ), this, SLOT( ffWDBtnClicked() ));
165 pAction = std::make_shared<Action>("PLAYLIST_NEXT_SONG");
166 m_pFfwdBtn->setAction( pAction );
167
168#ifdef WIN32
169 QStringList headers;
170 headers << tr ( "Song list" );
171 QTreeWidgetItem* header = new QTreeWidgetItem ( headers );
172 m_pPlaylistTree->setHeaderItem ( header );
173 m_pPlaylistTree->setAlternatingRowColors( true );
174 for ( int ii = 0; ii < m_pPlaylistTree->headerItem()->columnCount(); ii++ ) {
175 m_pPlaylistTree->headerItem()->setFont( ii, font );
176 }
177
178 /*addSongBTN->setEnabled ( true );
179 loadListBTN->setEnabled ( true );
180 removeFromListBTN->setEnabled ( false );
181 removeFromListBTN->setEnabled ( false );
182 saveListBTN->setEnabled ( false );
183 saveListAsBTN->setEnabled ( false );
184 loadScriptBTN->hide();
185 removeScriptBTN->hide();
186 editScriptBTN->hide();
187 newScriptBTN->hide();
188 clearPlBTN->setEnabled ( false );*/
189
190#else
191 QStringList headers;
192 headers << tr ( "Song list" ) << tr ( "Script" ) << tr ( "exec Script" );
193 QTreeWidgetItem* header = new QTreeWidgetItem ( headers );
194 m_pPlaylistTree->setHeaderItem ( header );
195
196 m_pPlaylistTree->setColumnWidth( 0, 405 );
197 m_pPlaylistTree->setColumnWidth( 1, 405 );
198 m_pPlaylistTree->setColumnWidth( 2, 105 );
199
200 m_pPlaylistTree->header()->setStretchLastSection( false );
201 m_pPlaylistTree->header()->setSectionResizeMode( 0, QHeaderView::Stretch );
202 m_pPlaylistTree->header()->setSectionResizeMode( 1, QHeaderView::Stretch );
203 m_pPlaylistTree->header()->setSectionResizeMode( 2, QHeaderView::Fixed );
204
205 m_pPlaylistTree->setAlternatingRowColors( true );
206 for ( int ii = 0; ii < m_pPlaylistTree->headerItem()->columnCount(); ii++ ) {
207 m_pPlaylistTree->headerItem()->setFont( ii, font );
208 }
209#endif
210
211 QVBoxLayout *pSideBarLayout = new QVBoxLayout(sideBarWidget);
212 pSideBarLayout->setSpacing(0);
213 pSideBarLayout->setContentsMargins( 0, 0, 0, 0 );
214
215 // zoom-in btn
216 Button *pUpBtn = new Button( nullptr, QSize( 16, 16 ), Button::Type::Push, "up.svg", "", false, QSize( 9, 9 ), tr( "sort" ) );
217 connect(pUpBtn, SIGNAL( clicked() ), this, SLOT(o_upBClicked()) );
218 pSideBarLayout->addWidget(pUpBtn);
219
220 // zoom-in btn
221 Button *pDownBtn = new Button( nullptr, QSize( 16, 16 ), Button::Type::Push, "down.svg", "", false, QSize( 9, 9 ), tr( "sort" ) );
222 connect(pDownBtn, SIGNAL( clicked() ), this, SLOT(o_downBClicked()));
223 pSideBarLayout->addWidget(pDownBtn);
224
225 //restore the playlist
226 Playlist* pPlaylist = Playlist::get_instance();
227 if( pPlaylist->size() > 0 ){
228 for ( uint i = 0; i < pPlaylist->size(); ++i ){
229 QTreeWidgetItem* pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
230
231 pPlaylistItem->setText( 0, pPlaylist->get( i )->filePath );
232 pPlaylistItem->setText( 1, pPlaylist->get( i )->scriptPath );
233
234 if ( pPlaylist->get( i )->scriptEnabled ) {
235 pPlaylistItem->setCheckState( 2, Qt::Checked );
236 } else {
237 pPlaylistItem->setCheckState( 2, Qt::Unchecked );
238 }
239 }
240
241 //restore the selected item
242 int activeSongNumber = Playlist::get_instance()->getActiveSongNumber();
243 int selectedSongNumber = Playlist::get_instance()->getSelectedSongNr();
244
245 if(! (activeSongNumber == -1 && selectedSongNumber == -1) )
246 {
247 int aselected = 0;
248 if( activeSongNumber == -1 ){
249 aselected = selectedSongNumber;
250 } else {
251 aselected = activeSongNumber ;
252 }
253
254 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->topLevelItem ( aselected );
255 m_pPlaylistItem->setBackground( 0, QColor( 50, 50, 50) );
256 m_pPlaylistItem->setBackground( 1, QColor( 50, 50, 50) );
257 m_pPlaylistItem->setBackground( 2, QColor( 50, 50, 50) );
258 }
259 }
260
261 m_pTimer = new QTimer( this );
262 connect(m_pTimer, SIGNAL(timeout() ), this, SLOT( updateActiveSongNumber() ) );
263 m_pTimer->start( 1000 ); // update player control at 1 fps
264
266}
267
269{
270 INFOLOG ( "DESTROY" );
271}
272
273void PlaylistDialog::keyPressEvent( QKeyEvent* ev )
274{
275 if(ev->key() == Qt::Key_Escape) {
277 }
278}
279
284
286{
288 if ( ! Filesystem::dir_readable( sPath, false ) ){
289 sPath = Filesystem::songs_dir();
290 }
291
292 FileDialog fd(this);
293 fd.setAcceptMode( QFileDialog::AcceptOpen );
294 fd.setWindowTitle( tr( "Add Song to PlayList" ) );
295 fd.setFileMode( QFileDialog::ExistingFiles );
296 fd.setNameFilter( Filesystem::songs_filter_name );
297 fd.setDirectory( sPath );
298
299 if ( fd.exec() != QDialog::Accepted ) {
300 return;
301 }
302
303 Preferences::get_instance()->setLastAddSongToPlaylistDirectory( fd.directory().absolutePath() );
304
305 foreach( QString filePath, fd.selectedFiles() ) {
306 updatePlayListNode( filePath );
307 }
308}
309
311{
312 std::shared_ptr<Song> pSong = Hydrogen::get_instance()->getSong();
313 QString filename = pSong->getFilename();
314
315 if (filename == "") {
316 // just in case!
317 QMessageBox::information ( this, "Hydrogen", tr ( "Please save your song first" ));
318 return;
319 }
320 updatePlayListNode ( filename );
321}
322
324{
325 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
326 int index = m_pPlaylistTree->indexOfTopLevelItem ( pPlaylistItem );
327 QTreeWidgetItem * pTmpItem = m_pPlaylistTree->topLevelItem ( 1 );
328
329 if (pPlaylistItem == nullptr){
330 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ));
331 } else {
332 if (pTmpItem == nullptr){
333 m_pPlaylistTree->clear();
338 setWindowTitle ( tr ( "Playlist Browser" ) );
339
340 return;
341 } else {
344 delete pPlaylistItem;
345
347 if ( Playlist::get_instance()->getActiveSongNumber() == index ){
349 } else if ( Playlist::get_instance()->getActiveSongNumber() > index ){
350 Playlist::get_instance()->setActiveSongNumber( Playlist::get_instance()->getActiveSongNumber() -1 );
351 }
352 }
353 }
354}
355
357{
358 bool DiscardChanges = false;
359 bool IsModified = Playlist::get_instance()->getIsModified();
360
361 if( IsModified ) {
362 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
363 switch(QMessageBox::information(
364 this, "Hydrogen",
365 tr("\nThe current playlist contains unsaved changes.\n"
366 "Do you want to discard the changes?\n"),
367 QMessageBox::Discard | QMessageBox::Cancel,
368 QMessageBox::Cancel ) ) {
369 case QMessageBox::Discard:
370 // don't save but exit
371 DiscardChanges = true;
372 break;
373 case QMessageBox::Cancel:
374 // don't exit
375 DiscardChanges = false;
376 break;
377 }
378 }
379
380 if(!IsModified || (IsModified && DiscardChanges))
381 {
382 m_pPlaylistTree->clear();
387 setWindowTitle ( tr ( "Playlist Browser" ) );
388
390 }
391 return;
392}
393
395{
396 QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
397 m_pPlaylistItem->setText ( 0, file );
398 m_pPlaylistItem->setText ( 1, tr("no Script") );
399 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
400
402
403 m_pPlaylistTree->setCurrentItem ( m_pPlaylistItem );
404}
405
407{
409 if ( ! Filesystem::dir_readable( sPath, false ) ){
411 }
412
413 FileDialog fd(this);
414 fd.setAcceptMode( QFileDialog::AcceptOpen );
415 fd.setWindowTitle( tr( "Load Playlist" ) );
416 fd.setFileMode( QFileDialog::ExistingFile );
417 fd.setDirectory( sPath );
418 fd.setNameFilter( Filesystem::playlists_filter_name );
419
420 if ( fd.exec() != QDialog::Accepted ) {
421 return;
422 }
423
424 QString filename = fd.selectedFiles().first();
425 Preferences::get_instance()->setLastPlaylistDirectory( fd.directory().absolutePath() );
426
428 Playlist* pPlaylist = Playlist::load( filename, relativePaths);
429 if ( ! pPlaylist ) {
430 _ERRORLOG( "Error loading the playlist" );
431 /* FIXME: get current instance (?) */
432 pPlaylist = Playlist::get_instance();
433 }
434
435 Playlist* playlist = Playlist::get_instance();
436 if( playlist->size() > 0 ) {
437 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
438 m_pPlaylist->clear();
439
440 for ( uint i = 0; i < playlist->size(); ++i ){
441 QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
442
443 if( playlist->get( i )->fileExists ){
444 m_pPlaylistItem->setText( 0, playlist->get( i )->filePath );
445 } else {
446 m_pPlaylistItem->setText( 0, tr("File not found: ") + playlist->get( i )->filePath );
447 }
448
449 m_pPlaylistItem->setText ( 1, playlist->get( i )->scriptPath );
450
451 if ( playlist->get( i )->scriptEnabled ) {
452 m_pPlaylistItem->setCheckState( 2, Qt::Checked );
453 } else {
454 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
455 }
456 }
457
458 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylist->topLevelItem ( 0 );
459 m_pPlaylist->setCurrentItem ( m_pPlaylistItem );
460 pPlaylist->setSelectedSongNr( 0 );
461 setWindowTitle ( tr ( "Playlist Browser" ) + QString(" - ") + pPlaylist->getFilename() );
462 }
463}
464
466{
468
470 if ( ! Filesystem::dir_writable( sPath, false ) ){
471 sPath = Filesystem::scripts_dir();
472 }
473
474 FileDialog fd(this);
475 fd.setFileMode ( QFileDialog::AnyFile );
476 fd.setNameFilter( Filesystem::scripts_filter_name );
477 fd.setAcceptMode ( QFileDialog::AcceptSave );
478 fd.setWindowTitle ( tr ( "New Script" ) );
479 fd.setDirectory( sPath );
480
481 QString defaultFilename;
482
483 defaultFilename += ".sh";
484
485 fd.selectFile ( defaultFilename );
486
487 QString filename;
488 if ( fd.exec() != QDialog::Accepted ) return;
489
490 filename = fd.selectedFiles().first();
491
492 if( filename.contains(" ", Qt::CaseInsensitive)){
493 QMessageBox::information ( this, "Hydrogen", tr ( "Script name or path to the script contains whitespaces.\nIMPORTANT\nThe path to the script and the scriptname must be without whitespaces.") );
494 return;
495 }
496
497 QFile chngPerm ( filename );
498 if (!chngPerm.open(QIODevice::WriteOnly | QIODevice::Text)) {
499 return;
500 }
501
502 Preferences::get_instance()->setLastPlaylistScriptDirectory( fd.directory().absolutePath() );
503
504 QTextStream out(&chngPerm);
505 out << "#!/bin/sh\n\n#have phun";
506 chngPerm.close();
507
508 if (chngPerm.exists() ) {
509 chngPerm.setPermissions( QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner );
510 QMessageBox::information ( this, "Hydrogen", tr ( "WARNING, the new file is executable by the owner of the file!" ) );
511 }
512
513 if( pPref->getDefaultEditor().isEmpty() ){
514 QMessageBox::information ( this, "Hydrogen", tr ( "No Default Editor Set. Please set your Default Editor\nDo not use a console based Editor\nSorry, but this will not work for the moment." ) );
515
516 static QString lastUsedDir = "/usr/bin/";
517
518 FileDialog fd(this);
519 fd.setAcceptMode( QFileDialog::AcceptOpen );
520 fd.setFileMode ( QFileDialog::ExistingFile );
521 fd.setDirectory ( lastUsedDir );
522
523 fd.setWindowTitle ( tr ( "Set your Default Editor" ) );
524
525 QString filename;
526 if ( fd.exec() == QDialog::Accepted ){
527 filename = fd.selectedFiles().first();
528
529 pPref->setDefaultEditor( filename );
530 }
531 }
532
533 QString openfile = pPref->getDefaultEditor() + " " + filename + "&";
534 std::system(openfile.toLatin1());
535
536 return;
537}
538
540{
542 if ( ! Filesystem::dir_writable( sPath, false ) ){
544 }
545
546 FileDialog fd(this);
547 fd.setWindowTitle( tr( "Save Playlist" ) );
548 fd.setFileMode( QFileDialog::AnyFile );
549 fd.setNameFilter( Filesystem::playlists_filter_name );
550 fd.setAcceptMode( QFileDialog::AcceptSave );
551 fd.setDirectory( sPath );
553 fd.setDefaultSuffix( Filesystem::playlist_ext );
554
555 if ( fd.exec() != QDialog::Accepted ) {
556 return;
557 }
558
559 QString filename = fd.selectedFiles().first();
560
561 Playlist* pPlaylist = Playlist::get_instance();
563 if ( Files::savePlaylistPath( filename, pPlaylist, relativePaths ) == nullptr ) {
564 return;
565 }
566
567 pPlaylist->setIsModified( false );
568 Preferences::get_instance()->setLastPlaylistDirectory( fd.directory().absolutePath() );
569
570 setWindowTitle( tr( "Playlist Browser" ) + QString(" - %1").arg( filename ) );
571}
572
574{
575 Playlist* pPlaylist = Playlist::get_instance();
576 if ( pPlaylist->getFilename().isEmpty() ) {
577 return saveListAs();
578 }
579
581 if ( Files::savePlaylistPath( pPlaylist->getFilename(), pPlaylist, relativePaths ) == nullptr ) {
582 return;
583 }
584
585 pPlaylist->setIsModified( false );
586}
587
589{
590
591 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
592 if ( pPlaylistItem == nullptr ){
593 QMessageBox::information ( this, "Hydrogen", tr ( "No Song in List or no Song selected!" ) );
594 return;
595 }
596
598 if ( ! Filesystem::dir_writable( sPath, false ) ){
599 sPath = Filesystem::scripts_dir();
600 }
601
602 FileDialog fd(this);
603 fd.setAcceptMode( QFileDialog::AcceptOpen );
604 fd.setFileMode ( QFileDialog::ExistingFile );
605 fd.setDirectory ( sPath );
606 fd.setNameFilter ( tr ( "Hydrogen Playlist (*.sh)" ) );
607 fd.setWindowTitle ( tr ( "Add Script to selected Song" ) );
608
609 QString filename;
610 if ( fd.exec() == QDialog::Accepted ){
611 filename = fd.selectedFiles().first();
612
613 if( filename.contains(" ", Qt::CaseInsensitive)){
614 QMessageBox::information ( this, "Hydrogen", tr ( "Script name or path to the script contains whitespaces.\nIMPORTANT\nThe path to the script and the scriptname must without whitespaces.") );
615 return;
616 }
617 Preferences::get_instance()->setLastPlaylistScriptDirectory( fd.directory().absolutePath() );
618
619 pPlaylistItem->setText ( 1, filename );
621
622 }
623}
624
626{
627 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
628
629
630 if (m_pPlaylistItem == nullptr){
631 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ));
632 return;
633 } else {
634 QString selected;
635 selected = m_pPlaylistItem->text ( 1 );
636 if( !QFile( selected ).exists() ){
637 QMessageBox::information ( this, "Hydrogen", tr ( "No Script in use!" ));
638 return;
639 } else {
640 m_pPlaylistItem->setText ( 1, tr("no Script") );
641
642 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
644 }
645 }
646
647}
648
650{
652 if( pPref->getDefaultEditor().isEmpty() ){
653 QMessageBox::information ( this, "Hydrogen", tr ( "No Default Editor Set. Please set your Default Editor\nDo not use a console based Editor\nSorry, but this will not work for the moment." ) );
654
655 static QString lastUsedDir = "/usr/bin/";
656
657 FileDialog fd(this);
658 fd.setAcceptMode( QFileDialog::AcceptOpen );
659 fd.setFileMode ( QFileDialog::ExistingFile );
660 fd.setDirectory ( lastUsedDir );
661
662 fd.setWindowTitle ( tr ( "Set your Default Editor" ) );
663
664 QString filename;
665 if ( fd.exec() == QDialog::Accepted ){
666 filename = fd.selectedFiles().first();
667
668 pPref->setDefaultEditor( filename );
669 }
670 }
671
672 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
673
674 if ( pPlaylistItem == nullptr ){
675 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ) );
676 return;
677 }
678 QString selected;
679 selected = pPlaylistItem->text ( 1 );
680
681 QString filename = pPref->getDefaultEditor() + " " + selected + "&";
682
683 if( !QFile( selected ).exists() ){
684 QMessageBox::information ( this, "Hydrogen", tr ( "No Script selected!" ));
685 return;
686 }
687
688 std::system( filename.toLatin1() );
689
690 return;
691}
692
694{
695 m_pTimer->stop();
696
697 Playlist* pPlaylist = Playlist::get_instance();
698
699 QTreeWidget* pPlaylistTree = m_pPlaylistTree;
700 QTreeWidgetItem* pPlaylistTreeItem = m_pPlaylistTree->currentItem();
701 int index = pPlaylistTree->indexOfTopLevelItem ( pPlaylistTreeItem );
702
703 if (index == 0 ){
704 m_pTimer->start( 1000 );
705 return;
706 }
707
708 QTreeWidgetItem* tmpPlaylistItem = pPlaylistTree->takeTopLevelItem ( index );
709
710 pPlaylistTree->insertTopLevelItem ( index -1, tmpPlaylistItem );
711 pPlaylistTree->setCurrentItem ( tmpPlaylistItem );
712
713 if ( pPlaylist->getSelectedSongNr() >= 0 ){
714 pPlaylist->setSelectedSongNr( pPlaylist->getSelectedSongNr() -1 );
715 }
716
717 if ( pPlaylist->getActiveSongNumber() == index ){
718 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() -1 );
719 }else if ( pPlaylist->getActiveSongNumber() == index -1 ){
720 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() +1 );
721 }
722
724}
725
727{
728 m_pTimer->stop();
729 Playlist* pPlaylist = Playlist::get_instance();
730
731 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
732 int length = m_pPlaylist->topLevelItemCount();
733 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
734 int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
735
736 if ( index == length - 1){
737 m_pTimer->start( 1000 );
738 return;
739 }
740
741 QTreeWidgetItem* pTmpPlaylistItem = m_pPlaylist->takeTopLevelItem ( index );
742
743 m_pPlaylist->insertTopLevelItem ( index +1, pTmpPlaylistItem );
744 m_pPlaylist->setCurrentItem ( pTmpPlaylistItem );
745
746 if ( pPlaylist->getSelectedSongNr() >= 0 ) {
747 pPlaylist->setSelectedSongNr( pPlaylist->getSelectedSongNr() +1 );
748 }
749
750 if (pPlaylist ->getActiveSongNumber() == index ){
751 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() +1 );
752 }else if ( pPlaylist->getActiveSongNumber() == index +1 ){
753 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() -1 );
754 }
756
757}
758
759void PlaylistDialog::on_m_pPlaylistTree_itemClicked ( QTreeWidgetItem * item, int column )
760{
761 if ( column == 2 ){
762 QString selected;
763 selected = item->text ( 1 );
764
765 if( !QFile( selected ).exists() ){
766 QMessageBox::information ( this, "Hydrogen", tr ( "No Script!" ));
767 item->setCheckState( 2, Qt::Unchecked );
768 return;
769 }
771 }
772 return;
773}
774
776{
777 Hydrogen * pHydrogen = Hydrogen::get_instance();
779
780 if ( m_pPlayBtn->isChecked() ) {
781 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
782 if ( m_pPlaylistItem == nullptr ){
783 QMessageBox::information ( this, "Hydrogen", tr ( "No valid song selected!" ) );
784 m_pPlayBtn->setChecked(false);
785 return;
786 }
787 QString sFilename = "";
788 sFilename = m_pPlaylistItem->text ( 0 );
789
790 if( sFilename == pHydrogen->getSong()->getFilename()){
791 pHydrogen->sequencer_play();
792 return;
793 }
794
795 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
796 int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
798
799 if ( ! pH2App->openSong( sFilename ) ) {
800 m_pPlayBtn->setChecked(false);
801 }
802
803 pHydrogen->sequencer_play();
804 }
805 else {
806 pHydrogen->sequencer_stop();
807 pH2App->showStatusBarMessage( tr("Pause.") );
808 }
809}
810
817
819{
820 Hydrogen* pHydrogen = Hydrogen::get_instance();
821 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() + 1 );
822}
823
825{
826 Hydrogen* pHydrogen = Hydrogen::get_instance();
827 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() - 1 );
828}
829
831{
832 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
833 if ( pPlaylistItem == nullptr ){
834 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ) );
835 return;
836 }
837
838 QString sFilename;
839 sFilename = pPlaylistItem->text( 0 );
840
841 int index = m_pPlaylistTree->indexOfTopLevelItem ( pPlaylistItem );
844
846
847 m_pPlayBtn->setChecked(false);
848
849 pH2App->openSong( sFilename );
850
851 pH2App->showStatusBarMessage( tr( "Playlist: set song no. %1" ).arg( index +1 ) );
852
855#ifdef WIN32
856 //I know nothing about windows scripts -wolke-
857 return;
858#else
859 QString execscript;
860 sFilename = pPlaylistItem->text ( 1 );
861 bool execcheckbox = pPlaylistItem->checkState ( 2 );
862
863 if( execcheckbox == false){
864 //QMessageBox::information ( this, "Hydrogen", tr ( "No Script selected!" ));
865 return;
866 }
867
868 if( execscript == "Script not used"){
869 //QMessageBox::information ( this, "Hydrogen", tr ( "Script not in use!" ));
870 return;
871 }
872
873 std::system( sFilename.toLatin1() );
874
875 return;
876#endif
877
878}
879
880
882{
883 int length = m_pPlaylistTree->topLevelItemCount();
884
886
887 for (int i = 0 ;i < length; i++){
888 QTreeWidgetItem * pPlaylistItem = m_pPlaylistTree->topLevelItem ( i );
889
890 Playlist::Entry* entry = new Playlist::Entry();
891 entry->filePath = pPlaylistItem->text( 0 );
892 entry->scriptPath = pPlaylistItem->text( 1 );
893 entry->scriptEnabled = pPlaylistItem->checkState( 2 );
894
895 Playlist::get_instance()->add( entry );
897 }
898 m_pTimer->start( 1000 );
899}
900
901
903{
904 for ( uint i = 0; i < Playlist::get_instance()->size(); ++i ){
905 if ( !m_pPlaylistTree->topLevelItem( i ) ) {
906 break;
907 }
908 ( m_pPlaylistTree->topLevelItem( i ) )->setBackground( 0, QBrush() );
909 ( m_pPlaylistTree->topLevelItem( i ) )->setBackground( 1, QBrush() );
910 ( m_pPlaylistTree->topLevelItem( i ) )->setBackground( 2, QBrush() );
911
912 }
913
915 if ( selected == -1 ) {
916 return;
917 }
918
919 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->topLevelItem ( selected );
920 if ( pPlaylistItem != nullptr ){
921 pPlaylistItem->setBackground( 0, QColor( 50, 50, 50) );
922 pPlaylistItem->setBackground( 1, QColor( 50, 50, 50) );
923 pPlaylistItem->setBackground( 2, QColor( 50, 50, 50) );
924 }
925}
926
927
928bool PlaylistDialog::eventFilter ( QObject *o, QEvent *e )
929{
930 UNUSED ( o );
931 if ( e->type() == QEvent::KeyPress ) {
932 QKeyEvent *k = ( QKeyEvent * ) e;
933
934 switch ( k->key() ) {
935 case Qt::Key_F5 :
936 if( Playlist::get_instance()->size() == 0
937 || Playlist::get_instance()->getActiveSongNumber() <=0) {
938 break;
939 }
940
942 return true;
943 break;
944 case Qt::Key_F6 :
945 if( Playlist::get_instance()->size() == 0
946 || Playlist::get_instance()->getActiveSongNumber() >= Playlist::get_instance()->size() -1) {
947 break;
948 }
949
951 return true;
952 break;
953 }
954 } else {
955 return false; // standard event processing
956 }
957
958 return false;
959}
960
962{
963 bool bUseRelativeFilenames = Preferences::get_instance()->isPlaylistUsingRelativeFilenames();
964
965 Playlist* pPlaylist = Playlist::load ( filename, bUseRelativeFilenames );
966 if ( !pPlaylist ) {
967 _ERRORLOG( "Error loading the playlist" );
968 return false;
969 }
970
972
973 Playlist* playlist = Playlist::get_instance();
974 if ( playlist->size() > 0 ) {
975 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
976 m_pPlaylist->clear();
977
978 for ( uint i = 0; i < playlist->size(); ++i ){
979 QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
980 m_pPlaylistItem->setText( 0, playlist->get( i )->filePath );
981 m_pPlaylistItem->setText( 1, playlist->get( i )->scriptPath );
982
983 if ( playlist->get( i )->scriptEnabled ) {
984 m_pPlaylistItem->setCheckState( 2, Qt::Checked );
985 } else {
986 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
987 }
988 }
989
990 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylist->topLevelItem ( 0 );
991 m_pPlaylist->setCurrentItem ( m_pPlaylistItem );
992 pPlaylist->setSelectedSongNr( 0 );
993 setWindowTitle ( tr ( "Playlist Browser" ) + QString(" - ") + pPlaylist->getFilename() );
994 }
995
996 return true;
997}
998
1000 auto pPref = H2Core::Preferences::get_instance();
1001
1002 if ( changes & H2Core::Preferences::Changes::Font ) {
1003
1004 QFont font( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
1005 QFont childFont( pPref->getLevel2FontFamily(), getPointSize( pPref->getFontSize() ) );
1006 setFont( font );
1007 m_pMenubar->setFont( font );
1008 m_pPlaylistMenu->setFont( font );
1009#ifndef WIN32
1010 m_pScriptMenu->setFont( font );
1011#endif
1012
1013 int ii;
1014
1015 for ( ii = 0; ii < m_pPlaylistTree->headerItem()->columnCount(); ii++ ) {
1016 m_pPlaylistTree->headerItem()->setFont( ii, font );
1017 }
1018
1019 QTreeWidgetItem* pNode = m_pPlaylistTree->topLevelItem( 0 );
1020
1021 while ( pNode != nullptr ) {
1022 for ( ii = 0; ii < pNode->columnCount(); ii++ ) {
1023 pNode->setFont( ii, childFont );
1024 }
1025 pNode = m_pPlaylistTree->itemBelow( pNode );
1026 }
1027
1028 }
1029}
#define INFOLOG(x)
Definition Object.h:240
#define _ERRORLOG(x)
Definition Object.h:248
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 file dialog checking whether the user has write access to the selected folder before allowing ...
Definition FileDialog.h:34
const std::shared_ptr< TransportPosition > getTransportPosition() const
bool locateToColumn(int nPatternGroup)
Relocates transport to the beginning of a particular column/Pattern group.
static QString savePlaylistPath(const QString &filePath, Playlist *playlist, bool relativePaths)
save the given playlist to filePath will overwrite an existing file
Definition Files.h:115
static QString scripts_dir()
returns user scripts path
static bool dir_readable(const QString &path, bool silent=false)
returns true if the given path is a readable regular directory
static const QString scripts_filter_name
Definition Filesystem.h:125
static QString songs_dir()
returns user songs path
static QString playlists_dir()
returns user playlist path
static bool dir_writable(const QString &path, bool silent=false)
returns true if the given path is a writable regular directory
static const QString playlists_filter_name
Definition Filesystem.h:127
static const QString playlist_ext
Definition Filesystem.h:120
static const QString songs_filter_name
Definition Filesystem.h:123
static QString untitled_playlist_file_name()
returns untitled playlist file name
Hydrogen Audio Engine.
Definition Hydrogen.h:54
void sequencer_stop()
Stop the internal sequencer.
Definition Hydrogen.cpp:231
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:123
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:663
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:653
void sequencer_play()
Start the internal sequencer.
Definition Hydrogen.cpp:221
Drumkit info.
Definition Playlist.h:37
void add(Entry *entry)
Definition Playlist.h:133
void setNextSongByNumber(int SongNumber)
Definition Playlist.cpp:207
void setIsModified(bool IsModified)
Definition Playlist.h:173
int getActiveSongNumber()
Definition Playlist.h:148
int getSelectedSongNr()
Definition Playlist.h:138
void setFilename(const QString &filename)
Definition Playlist.h:163
void setSelectedSongNr(int songNumber)
Definition Playlist.h:143
Entry * get(int idx)
Definition Playlist.h:127
void setActiveSongNumber(int ActiveSongNumber)
Definition Playlist.h:153
const QString & getFilename()
Definition Playlist.h:158
static Playlist * get_instance()
Returns a pointer to the current Playlist singleton stored in __instance.
Definition Playlist.h:60
static Playlist * load(const QString &filename, bool useRelativePaths)
Definition Playlist.cpp:166
int size() const
Definition Playlist.h:122
bool getIsModified()
Definition Playlist.h:168
Manager for User Preferences File (singleton)
Definition Preferences.h:79
bool isPlaylistUsingRelativeFilenames()
QString getLastPlaylistScriptDirectory() const
void setLastAddSongToPlaylistDirectory(QString sPath)
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setLastPlaylistDirectory(QString sPath)
QString getLastAddSongToPlaylistDirectory() const
void setDefaultEditor(QString editor)
void setLastPlaylistScriptDirectory(QString sPath)
const QString & getDefaultEditor()
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 setLastPlaylistFilename(const QString &filename)
QString getLastPlaylistDirectory() const
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
static bool openSong(QString sFilename)
void showStatusBarMessage(const QString &sMessage, const QString &sCaller="")
void showPlaylistDialog()
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
void setPixmap(QString sPixmapPath, bool expand_horiz=false)
virtual bool eventFilter(QObject *o, QEvent *e) override
void on_m_pPlaylistTree_itemDoubleClicked()
void on_m_pPlaylistTree_itemClicked(QTreeWidgetItem *item, int column)
QMenuBar * m_pMenubar
PlaylistDialog(QWidget *pParent)
void onPreferencesChanged(H2Core::Preferences::Changes changes)
virtual void closeEvent(QCloseEvent *ev) override
QMenu * m_pScriptMenu
virtual void keyPressEvent(QKeyEvent *ev) override
void updateActiveSongNumber()
QMenu * m_pPlaylistMenu
bool loadListByFileName(QString filename)
void updatePlayListNode(QString file)
constexpr int getPointSize(H2Core::FontTheme::FontSize fontSize) const
#define UNUSED(v)
Definition Globals.h:42