hydrogen 1.2.3
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-2024 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
68
69 QFont font( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
70 setFont( font );
71 m_pPlaylistTree->setFont( font );
72
73 setWindowTitle ( tr ( "Playlist Browser" ) + QString(" - ") + Playlist::get_instance()->getFilename() );
74
75 installEventFilter( this );
76
77 // menubar
78 m_pMenubar = new QMenuBar( this );
79
80 // Playlist menu
81 m_pPlaylistMenu = m_pMenubar->addMenu( tr( "&Playlist" ) );
82
83 m_pPlaylistMenu->addAction( tr( "Add song to Play&list" ), this, SLOT( addSong() ), QKeySequence( "Ctrl+A" ) );
84 m_pPlaylistMenu->addAction( tr( "Add &current song to Playlist" ), this, SLOT( addCurrentSong() ), QKeySequence( "Ctrl+Alt+A" ) );
85 m_pPlaylistMenu->addSeparator(); // -----
86 m_pPlaylistMenu->addAction( tr( "&Remove selected song from Playlist" ), this, SLOT( removeFromList() ), QKeySequence::Delete );
87 m_pPlaylistMenu->addAction( tr( "&New Playlist" ), this, SLOT( clearPlaylist() ), QKeySequence( "Ctrl+N" ) );
88 m_pPlaylistMenu->addSeparator();
89 m_pPlaylistMenu->addAction( tr( "&Open Playlist" ), this, SLOT( loadList() ), QKeySequence( "Ctrl+O" ) );
90 m_pPlaylistMenu->addSeparator();
91 m_pPlaylistMenu->addAction( tr( "&Save Playlist" ), this, SLOT( saveList() ), QKeySequence( "Ctrl+S" ) );
92 m_pPlaylistMenu->addAction( tr( "Save Playlist &as" ), this, SLOT( saveListAs() ), QKeySequence( "Ctrl+Shift+S" ) );
93 m_pPlaylistMenu->setFont( font );
94
95#ifdef WIN32
96 //no scripts under windows
97#else
98 // Script menu
99 m_pScriptMenu = m_pMenubar->addMenu( tr( "&Scripts" ) );
100
101 m_pScriptMenu->addAction( tr( "&Add Script to selected song" ), this, SLOT( loadScript() ), QKeySequence( "" ) );
102 m_pScriptMenu->addAction( tr( "&Edit selected Script" ), this, SLOT( editScript() ), QKeySequence( "" ) );
103 m_pScriptMenu->addSeparator();
104 m_pScriptMenu->addAction( tr( "&Remove selected Script" ), this, SLOT( removeScript() ), QKeySequence( "" ) );
105 m_pScriptMenu->addSeparator();
106 m_pScriptMenu->addAction( tr( "&Create a new Script" ), this, SLOT( newScript() ), QKeySequence( "" ) );
107 m_pScriptMenu->setFont( font );
108#endif
109
110 QHBoxLayout* pMenuBarLayout = new QHBoxLayout( menuBarWidget );
111 pMenuBarLayout->setSpacing(0);
112 pMenuBarLayout->setContentsMargins( 0, 0, 0, 0 );
113 pMenuBarLayout->addWidget( m_pMenubar );
114
115 // CONTROLS
116 PixmapWidget *pControlsPanel = new PixmapWidget( controlWidget );
117 pControlsPanel->setFixedSize( 119, 32 );
118 pControlsPanel->setPixmap( "/playerControlPanel/playlist_background_Control.png" );
119
120 // Rewind button
121 m_pRwdBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push, "rewind.svg", "", false, QSize( 13, 13 ), tr("Rewind") );
122 m_pRwdBtn->move( 4, 4 );
123 connect(m_pRwdBtn, SIGNAL( clicked() ), this, SLOT( rewindBtnClicked() ));
124 std::shared_ptr<Action> pAction = std::make_shared<Action>("PLAYLIST_PREV_SONG");
125 m_pRwdBtn->setAction( pAction );
126
127 // Play button
128 m_pPlayBtn = new Button( pControlsPanel, QSize( 30, 21 ), Button::Type::Toggle, "play.svg", "", false, QSize( 13, 13 ), tr("Play/ Pause/ Load selected song") );
129 m_pPlayBtn->move( 31, 4 );
130 m_pPlayBtn->setChecked(false);
131 connect(m_pPlayBtn, SIGNAL( clicked() ), this, SLOT( nodePlayBTN() ));
132 pAction = std::make_shared<Action>("PLAY/PAUSE_TOGGLE");
133 m_pPlayBtn->setAction( pAction );
134
135 // Stop button
136 m_pStopBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push, "stop.svg", "", false, QSize( 11, 11 ), tr("Stop") );
137 m_pStopBtn->move( 63, 4 );
138 connect(m_pStopBtn, SIGNAL( clicked() ), this, SLOT( nodeStopBTN() ));
139 pAction = std::make_shared<Action>("STOP");
140 m_pStopBtn->setAction( pAction );
141
142 // Fast forward button
143 m_pFfwdBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push, "fast_forward.svg", "", false, QSize( 13, 13 ), tr("Fast Forward") );
144 m_pFfwdBtn->move( 90, 4 );
145 connect(m_pFfwdBtn, SIGNAL( clicked() ), this, SLOT( ffWDBtnClicked() ));
146 pAction = std::make_shared<Action>("PLAYLIST_NEXT_SONG");
147 m_pFfwdBtn->setAction( pAction );
148
149#ifdef WIN32
150 QStringList headers;
151 headers << tr ( "Song list" );
152 QTreeWidgetItem* header = new QTreeWidgetItem ( headers );
153 m_pPlaylistTree->setHeaderItem ( header );
154 m_pPlaylistTree->setAlternatingRowColors( true );
155 for ( int ii = 0; ii < m_pPlaylistTree->headerItem()->columnCount(); ii++ ) {
156 m_pPlaylistTree->headerItem()->setFont( ii, font );
157 }
158
159 /*addSongBTN->setEnabled ( true );
160 loadListBTN->setEnabled ( true );
161 removeFromListBTN->setEnabled ( false );
162 removeFromListBTN->setEnabled ( false );
163 saveListBTN->setEnabled ( false );
164 saveListAsBTN->setEnabled ( false );
165 loadScriptBTN->hide();
166 removeScriptBTN->hide();
167 editScriptBTN->hide();
168 newScriptBTN->hide();
169 clearPlBTN->setEnabled ( false );*/
170
171#else
172 QStringList headers;
173 headers << tr ( "Song list" ) << tr ( "Script" ) << tr ( "exec Script" );
174 QTreeWidgetItem* header = new QTreeWidgetItem ( headers );
175 m_pPlaylistTree->setHeaderItem ( header );
176
177 m_pPlaylistTree->setColumnWidth( 0, 405 );
178 m_pPlaylistTree->setColumnWidth( 1, 405 );
179 m_pPlaylistTree->setColumnWidth( 2, 105 );
180
181 m_pPlaylistTree->header()->setStretchLastSection( false );
182 m_pPlaylistTree->header()->setSectionResizeMode( 0, QHeaderView::Stretch );
183 m_pPlaylistTree->header()->setSectionResizeMode( 1, QHeaderView::Stretch );
184 m_pPlaylistTree->header()->setSectionResizeMode( 2, QHeaderView::Fixed );
185
186 m_pPlaylistTree->setAlternatingRowColors( true );
187 for ( int ii = 0; ii < m_pPlaylistTree->headerItem()->columnCount(); ii++ ) {
188 m_pPlaylistTree->headerItem()->setFont( ii, font );
189 }
190#endif
191
192 QVBoxLayout *pSideBarLayout = new QVBoxLayout(sideBarWidget);
193 pSideBarLayout->setSpacing(0);
194 pSideBarLayout->setMargin(0);
195
196 // zoom-in btn
197 Button *pUpBtn = new Button( nullptr, QSize( 16, 16 ), Button::Type::Push, "up.svg", "", false, QSize( 9, 9 ), tr( "sort" ) );
198 connect(pUpBtn, SIGNAL( clicked() ), this, SLOT(o_upBClicked()) );
199 pSideBarLayout->addWidget(pUpBtn);
200
201 // zoom-in btn
202 Button *pDownBtn = new Button( nullptr, QSize( 16, 16 ), Button::Type::Push, "down.svg", "", false, QSize( 9, 9 ), tr( "sort" ) );
203 connect(pDownBtn, SIGNAL( clicked() ), this, SLOT(o_downBClicked()));
204 pSideBarLayout->addWidget(pDownBtn);
205
206 //restore the playlist
207 Playlist* pPlaylist = Playlist::get_instance();
208 if( pPlaylist->size() > 0 ){
209 for ( uint i = 0; i < pPlaylist->size(); ++i ){
210 QTreeWidgetItem* pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
211
212 pPlaylistItem->setText( 0, pPlaylist->get( i )->filePath );
213 pPlaylistItem->setText( 1, pPlaylist->get( i )->scriptPath );
214
215 if ( pPlaylist->get( i )->scriptEnabled ) {
216 pPlaylistItem->setCheckState( 2, Qt::Checked );
217 } else {
218 pPlaylistItem->setCheckState( 2, Qt::Unchecked );
219 }
220 }
221
222 //restore the selected item
223 int activeSongNumber = Playlist::get_instance()->getActiveSongNumber();
224 int selectedSongNumber = Playlist::get_instance()->getSelectedSongNr();
225
226 if(! (activeSongNumber == -1 && selectedSongNumber == -1) )
227 {
228 int aselected = 0;
229 if( activeSongNumber == -1 ){
230 aselected = selectedSongNumber;
231 } else {
232 aselected = activeSongNumber ;
233 }
234
235 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->topLevelItem ( aselected );
236 m_pPlaylistItem->setBackground( 0, QColor( 50, 50, 50) );
237 m_pPlaylistItem->setBackground( 1, QColor( 50, 50, 50) );
238 m_pPlaylistItem->setBackground( 2, QColor( 50, 50, 50) );
239 }
240 }
241
242 m_pTimer = new QTimer( this );
243 connect(m_pTimer, SIGNAL(timeout() ), this, SLOT( updateActiveSongNumber() ) );
244 m_pTimer->start( 1000 ); // update player control at 1 fps
245
247}
248
250{
251 INFOLOG ( "DESTROY" );
252}
253
254void PlaylistDialog::keyPressEvent( QKeyEvent* ev )
255{
256 if(ev->key() == Qt::Key_Escape) {
258 }
259}
260
265
267{
269 if ( ! Filesystem::dir_readable( sPath, false ) ){
270 sPath = Filesystem::songs_dir();
271 }
272
273 FileDialog fd(this);
274 fd.setAcceptMode( QFileDialog::AcceptOpen );
275 fd.setWindowTitle( tr( "Add Song to PlayList" ) );
276 fd.setFileMode( QFileDialog::ExistingFiles );
277 fd.setNameFilter( Filesystem::songs_filter_name );
278 fd.setDirectory( sPath );
279
280 if ( fd.exec() != QDialog::Accepted ) {
281 return;
282 }
283
284 Preferences::get_instance()->setLastAddSongToPlaylistDirectory( fd.directory().absolutePath() );
285
286 foreach( QString filePath, fd.selectedFiles() ) {
287 updatePlayListNode( filePath );
288 }
289}
290
292{
293 std::shared_ptr<Song> pSong = Hydrogen::get_instance()->getSong();
294 QString filename = pSong->getFilename();
295
296 if (filename == "") {
297 // just in case!
298 QMessageBox::information ( this, "Hydrogen", tr ( "Please save your song first" ));
299 return;
300 }
301 updatePlayListNode ( filename );
302}
303
305{
306 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
307 int index = m_pPlaylistTree->indexOfTopLevelItem ( pPlaylistItem );
308 QTreeWidgetItem * pTmpItem = m_pPlaylistTree->topLevelItem ( 1 );
309
310 if (pPlaylistItem == nullptr){
311 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ));
312 } else {
313 if (pTmpItem == nullptr){
314 m_pPlaylistTree->clear();
319 setWindowTitle ( tr ( "Playlist Browser" ) );
320
321 return;
322 } else {
325 delete pPlaylistItem;
326
328 if ( Playlist::get_instance()->getActiveSongNumber() == index ){
330 } else if ( Playlist::get_instance()->getActiveSongNumber() > index ){
331 Playlist::get_instance()->setActiveSongNumber( Playlist::get_instance()->getActiveSongNumber() -1 );
332 }
333 }
334 }
335}
336
338{
339 bool DiscardChanges = false;
340 bool IsModified = Playlist::get_instance()->getIsModified();
341
342 if( IsModified ) {
343 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
344 switch(QMessageBox::information( this, "Hydrogen",
345 tr("\nThe current playlist contains unsaved changes.\n"
346 "Do you want to discard the changes?\n"),
347 pCommonStrings->getButtonDiscard(),
348 pCommonStrings->getButtonCancel(),
349 nullptr, // Enter == button 0
350 2 ) ) { // Escape == button 1
351 case 0: // Discard clicked or Alt+D pressed
352 // don't save but exit
353 DiscardChanges = true;
354 break;
355 case 1: // Cancel clicked or Alt+C pressed or Escape pressed
356 // don't exit
357 DiscardChanges = false;
358 break;
359 }
360 }
361
362 if(!IsModified || (IsModified && DiscardChanges))
363 {
364 m_pPlaylistTree->clear();
369 setWindowTitle ( tr ( "Playlist Browser" ) );
370
372 }
373 return;
374}
375
377{
378 QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
379 m_pPlaylistItem->setText ( 0, file );
380 m_pPlaylistItem->setText ( 1, tr("no Script") );
381 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
382
384
385 m_pPlaylistTree->setCurrentItem ( m_pPlaylistItem );
386}
387
389{
391 if ( ! Filesystem::dir_readable( sPath, false ) ){
393 }
394
395 FileDialog fd(this);
396 fd.setAcceptMode( QFileDialog::AcceptOpen );
397 fd.setWindowTitle( tr( "Load Playlist" ) );
398 fd.setFileMode( QFileDialog::ExistingFile );
399 fd.setDirectory( sPath );
400 fd.setNameFilter( Filesystem::playlists_filter_name );
401
402 if ( fd.exec() != QDialog::Accepted ) {
403 return;
404 }
405
406 QString filename = fd.selectedFiles().first();
407 Preferences::get_instance()->setLastPlaylistDirectory( fd.directory().absolutePath() );
408
410 Playlist* pPlaylist = Playlist::load( filename, relativePaths);
411 if ( ! pPlaylist ) {
412 _ERRORLOG( "Error loading the playlist" );
413 /* FIXME: get current instance (?) */
414 pPlaylist = Playlist::get_instance();
415 }
416
417 Playlist* playlist = Playlist::get_instance();
418 if( playlist->size() > 0 ) {
419 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
420 m_pPlaylist->clear();
421
422 for ( uint i = 0; i < playlist->size(); ++i ){
423 QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
424
425 if( playlist->get( i )->fileExists ){
426 m_pPlaylistItem->setText( 0, playlist->get( i )->filePath );
427 } else {
428 m_pPlaylistItem->setText( 0, tr("File not found: ") + playlist->get( i )->filePath );
429 }
430
431 m_pPlaylistItem->setText ( 1, playlist->get( i )->scriptPath );
432
433 if ( playlist->get( i )->scriptEnabled ) {
434 m_pPlaylistItem->setCheckState( 2, Qt::Checked );
435 } else {
436 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
437 }
438 }
439
440 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylist->topLevelItem ( 0 );
441 m_pPlaylist->setCurrentItem ( m_pPlaylistItem );
442 pPlaylist->setSelectedSongNr( 0 );
443 setWindowTitle ( tr ( "Playlist Browser" ) + QString(" - ") + pPlaylist->getFilename() );
444 }
445}
446
448{
450
452 if ( ! Filesystem::dir_writable( sPath, false ) ){
453 sPath = Filesystem::scripts_dir();
454 }
455
456 FileDialog fd(this);
457 fd.setFileMode ( QFileDialog::AnyFile );
458 fd.setNameFilter( Filesystem::scripts_filter_name );
459 fd.setAcceptMode ( QFileDialog::AcceptSave );
460 fd.setWindowTitle ( tr ( "New Script" ) );
461 fd.setDirectory( sPath );
462
463 QString defaultFilename;
464
465 defaultFilename += ".sh";
466
467 fd.selectFile ( defaultFilename );
468
469 QString filename;
470 if ( fd.exec() != QDialog::Accepted ) return;
471
472 filename = fd.selectedFiles().first();
473
474 if( filename.contains(" ", Qt::CaseInsensitive)){
475 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.") );
476 return;
477 }
478
479 QFile chngPerm ( filename );
480 if (!chngPerm.open(QIODevice::WriteOnly | QIODevice::Text)) {
481 return;
482 }
483
484 Preferences::get_instance()->setLastPlaylistScriptDirectory( fd.directory().absolutePath() );
485
486 QTextStream out(&chngPerm);
487 out << "#!/bin/sh\n\n#have phun";
488 chngPerm.close();
489
490 if (chngPerm.exists() ) {
491 chngPerm.setPermissions( QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner );
492 QMessageBox::information ( this, "Hydrogen", tr ( "WARNING, the new file is executable by the owner of the file!" ) );
493 }
494
495 if( pPref->getDefaultEditor().isEmpty() ){
496 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." ) );
497
498 static QString lastUsedDir = "/usr/bin/";
499
500 FileDialog fd(this);
501 fd.setAcceptMode( QFileDialog::AcceptOpen );
502 fd.setFileMode ( QFileDialog::ExistingFile );
503 fd.setDirectory ( lastUsedDir );
504
505 fd.setWindowTitle ( tr ( "Set your Default Editor" ) );
506
507 QString filename;
508 if ( fd.exec() == QDialog::Accepted ){
509 filename = fd.selectedFiles().first();
510
511 pPref->setDefaultEditor( filename );
512 }
513 }
514
515 QString openfile = pPref->getDefaultEditor() + " " + filename + "&";
516 std::system(openfile.toLatin1());
517
518 return;
519}
520
522{
524 if ( ! Filesystem::dir_writable( sPath, false ) ){
526 }
527
528 FileDialog fd(this);
529 fd.setWindowTitle( tr( "Save Playlist" ) );
530 fd.setFileMode( QFileDialog::AnyFile );
531 fd.setNameFilter( Filesystem::playlists_filter_name );
532 fd.setAcceptMode( QFileDialog::AcceptSave );
533 fd.setDirectory( sPath );
535 fd.setDefaultSuffix( Filesystem::playlist_ext );
536
537 if ( fd.exec() != QDialog::Accepted ) {
538 return;
539 }
540
541 QString filename = fd.selectedFiles().first();
542
543 Playlist* pPlaylist = Playlist::get_instance();
545 if ( Files::savePlaylistPath( filename, pPlaylist, relativePaths ) == nullptr ) {
546 return;
547 }
548
549 pPlaylist->setIsModified( false );
550 Preferences::get_instance()->setLastPlaylistDirectory( fd.directory().absolutePath() );
551
552 setWindowTitle( tr( "Playlist Browser" ) + QString(" - %1").arg( filename ) );
553}
554
556{
557 Playlist* pPlaylist = Playlist::get_instance();
558 if ( pPlaylist->getFilename().isEmpty() ) {
559 return saveListAs();
560 }
561
563 if ( Files::savePlaylistPath( pPlaylist->getFilename(), pPlaylist, relativePaths ) == nullptr ) {
564 return;
565 }
566
567 pPlaylist->setIsModified( false );
568}
569
571{
572
573 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
574 if ( pPlaylistItem == nullptr ){
575 QMessageBox::information ( this, "Hydrogen", tr ( "No Song in List or no Song selected!" ) );
576 return;
577 }
578
580 if ( ! Filesystem::dir_writable( sPath, false ) ){
581 sPath = Filesystem::scripts_dir();
582 }
583
584 FileDialog fd(this);
585 fd.setAcceptMode( QFileDialog::AcceptOpen );
586 fd.setFileMode ( QFileDialog::ExistingFile );
587 fd.setDirectory ( sPath );
588 fd.setNameFilter ( tr ( "Hydrogen Playlist (*.sh)" ) );
589 fd.setWindowTitle ( tr ( "Add Script to selected Song" ) );
590
591 QString filename;
592 if ( fd.exec() == QDialog::Accepted ){
593 filename = fd.selectedFiles().first();
594
595 if( filename.contains(" ", Qt::CaseInsensitive)){
596 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.") );
597 return;
598 }
599 Preferences::get_instance()->setLastPlaylistScriptDirectory( fd.directory().absolutePath() );
600
601 pPlaylistItem->setText ( 1, filename );
603
604 }
605}
606
608{
609 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
610
611
612 if (m_pPlaylistItem == nullptr){
613 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ));
614 return;
615 } else {
616 QString selected;
617 selected = m_pPlaylistItem->text ( 1 );
618 if( !QFile( selected ).exists() ){
619 QMessageBox::information ( this, "Hydrogen", tr ( "No Script in use!" ));
620 return;
621 } else {
622 m_pPlaylistItem->setText ( 1, tr("no Script") );
623
624 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
626 }
627 }
628
629}
630
632{
634 if( pPref->getDefaultEditor().isEmpty() ){
635 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." ) );
636
637 static QString lastUsedDir = "/usr/bin/";
638
639 FileDialog fd(this);
640 fd.setAcceptMode( QFileDialog::AcceptOpen );
641 fd.setFileMode ( QFileDialog::ExistingFile );
642 fd.setDirectory ( lastUsedDir );
643
644 fd.setWindowTitle ( tr ( "Set your Default Editor" ) );
645
646 QString filename;
647 if ( fd.exec() == QDialog::Accepted ){
648 filename = fd.selectedFiles().first();
649
650 pPref->setDefaultEditor( filename );
651 }
652 }
653
654 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
655
656 if ( pPlaylistItem == nullptr ){
657 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ) );
658 return;
659 }
660 QString selected;
661 selected = pPlaylistItem->text ( 1 );
662
663 QString filename = pPref->getDefaultEditor() + " " + selected + "&";
664
665 if( !QFile( selected ).exists() ){
666 QMessageBox::information ( this, "Hydrogen", tr ( "No Script selected!" ));
667 return;
668 }
669
670 std::system( filename.toLatin1() );
671
672 return;
673}
674
676{
677 m_pTimer->stop();
678
679 Playlist* pPlaylist = Playlist::get_instance();
680
681 QTreeWidget* pPlaylistTree = m_pPlaylistTree;
682 QTreeWidgetItem* pPlaylistTreeItem = m_pPlaylistTree->currentItem();
683 int index = pPlaylistTree->indexOfTopLevelItem ( pPlaylistTreeItem );
684
685 if (index == 0 ){
686 m_pTimer->start( 1000 );
687 return;
688 }
689
690 QTreeWidgetItem* tmpPlaylistItem = pPlaylistTree->takeTopLevelItem ( index );
691
692 pPlaylistTree->insertTopLevelItem ( index -1, tmpPlaylistItem );
693 pPlaylistTree->setCurrentItem ( tmpPlaylistItem );
694
695 if ( pPlaylist->getSelectedSongNr() >= 0 ){
696 pPlaylist->setSelectedSongNr( pPlaylist->getSelectedSongNr() -1 );
697 }
698
699 if ( pPlaylist->getActiveSongNumber() == index ){
700 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() -1 );
701 }else if ( pPlaylist->getActiveSongNumber() == index -1 ){
702 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() +1 );
703 }
704
706}
707
709{
710 m_pTimer->stop();
711 Playlist* pPlaylist = Playlist::get_instance();
712
713 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
714 int length = m_pPlaylist->topLevelItemCount();
715 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
716 int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
717
718 if ( index == length - 1){
719 m_pTimer->start( 1000 );
720 return;
721 }
722
723 QTreeWidgetItem* pTmpPlaylistItem = m_pPlaylist->takeTopLevelItem ( index );
724
725 m_pPlaylist->insertTopLevelItem ( index +1, pTmpPlaylistItem );
726 m_pPlaylist->setCurrentItem ( pTmpPlaylistItem );
727
728 if ( pPlaylist->getSelectedSongNr() >= 0 ) {
729 pPlaylist->setSelectedSongNr( pPlaylist->getSelectedSongNr() +1 );
730 }
731
732 if (pPlaylist ->getActiveSongNumber() == index ){
733 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() +1 );
734 }else if ( pPlaylist->getActiveSongNumber() == index +1 ){
735 pPlaylist->setActiveSongNumber( pPlaylist->getActiveSongNumber() -1 );
736 }
738
739}
740
741void PlaylistDialog::on_m_pPlaylistTree_itemClicked ( QTreeWidgetItem * item, int column )
742{
743 if ( column == 2 ){
744 QString selected;
745 selected = item->text ( 1 );
746
747 if( !QFile( selected ).exists() ){
748 QMessageBox::information ( this, "Hydrogen", tr ( "No Script!" ));
749 item->setCheckState( 2, Qt::Unchecked );
750 return;
751 }
753 }
754 return;
755}
756
758{
759 Hydrogen * pHydrogen = Hydrogen::get_instance();
761
762 if ( m_pPlayBtn->isChecked() ) {
763 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
764 if ( m_pPlaylistItem == nullptr ){
765 QMessageBox::information ( this, "Hydrogen", tr ( "No valid song selected!" ) );
766 m_pPlayBtn->setChecked(false);
767 return;
768 }
769 QString sFilename = "";
770 sFilename = m_pPlaylistItem->text ( 0 );
771
772 if( sFilename == pHydrogen->getSong()->getFilename()){
773 pHydrogen->sequencer_play();
774 return;
775 }
776
777 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
778 int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
780
781 if ( ! pH2App->openSong( sFilename ) ) {
782 m_pPlayBtn->setChecked(false);
783 }
784
785 pHydrogen->sequencer_play();
786 }
787 else {
788 pHydrogen->sequencer_stop();
789 pH2App->showStatusBarMessage( tr("Pause.") );
790 }
791}
792
799
801{
802 Hydrogen* pHydrogen = Hydrogen::get_instance();
803 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() + 1 );
804}
805
807{
808 Hydrogen* pHydrogen = Hydrogen::get_instance();
809 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() - 1 );
810}
811
813{
814 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->currentItem();
815 if ( pPlaylistItem == nullptr ){
816 QMessageBox::information ( this, "Hydrogen", tr ( "No Song selected!" ) );
817 return;
818 }
819
820 QString sFilename;
821 sFilename = pPlaylistItem->text( 0 );
822
823 int index = m_pPlaylistTree->indexOfTopLevelItem ( pPlaylistItem );
826
828
829 m_pPlayBtn->setChecked(false);
830
831 pH2App->openSong( sFilename );
832
833 pH2App->showStatusBarMessage( tr( "Playlist: set song no. %1" ).arg( index +1 ) );
834
837#ifdef WIN32
838 //I know nothing about windows scripts -wolke-
839 return;
840#else
841 QString execscript;
842 sFilename = pPlaylistItem->text ( 1 );
843 bool execcheckbox = pPlaylistItem->checkState ( 2 );
844
845 if( execcheckbox == false){
846 //QMessageBox::information ( this, "Hydrogen", tr ( "No Script selected!" ));
847 return;
848 }
849
850 if( execscript == "Script not used"){
851 //QMessageBox::information ( this, "Hydrogen", tr ( "Script not in use!" ));
852 return;
853 }
854
855 std::system( sFilename.toLatin1() );
856
857 return;
858#endif
859
860}
861
862
864{
865 int length = m_pPlaylistTree->topLevelItemCount();
866
868
869 for (int i = 0 ;i < length; i++){
870 QTreeWidgetItem * pPlaylistItem = m_pPlaylistTree->topLevelItem ( i );
871
872 Playlist::Entry* entry = new Playlist::Entry();
873 entry->filePath = pPlaylistItem->text( 0 );
874 entry->scriptPath = pPlaylistItem->text( 1 );
875 entry->scriptEnabled = pPlaylistItem->checkState( 2 );
876
877 Playlist::get_instance()->add( entry );
879 }
880 m_pTimer->start( 1000 );
881}
882
883
885{
886 for ( uint i = 0; i < Playlist::get_instance()->size(); ++i ){
887 if ( !m_pPlaylistTree->topLevelItem( i ) ) {
888 break;
889 }
890 ( m_pPlaylistTree->topLevelItem( i ) )->setBackground( 0, QBrush() );
891 ( m_pPlaylistTree->topLevelItem( i ) )->setBackground( 1, QBrush() );
892 ( m_pPlaylistTree->topLevelItem( i ) )->setBackground( 2, QBrush() );
893
894 }
895
897 if ( selected == -1 ) {
898 return;
899 }
900
901 QTreeWidgetItem* pPlaylistItem = m_pPlaylistTree->topLevelItem ( selected );
902 if ( pPlaylistItem != nullptr ){
903 pPlaylistItem->setBackground( 0, QColor( 50, 50, 50) );
904 pPlaylistItem->setBackground( 1, QColor( 50, 50, 50) );
905 pPlaylistItem->setBackground( 2, QColor( 50, 50, 50) );
906 }
907}
908
909
910bool PlaylistDialog::eventFilter ( QObject *o, QEvent *e )
911{
912 UNUSED ( o );
913 if ( e->type() == QEvent::KeyPress ) {
914 QKeyEvent *k = ( QKeyEvent * ) e;
915
916 switch ( k->key() ) {
917 case Qt::Key_F5 :
918 if( Playlist::get_instance()->size() == 0
920 break;
921 }
922
924 return true;
925 break;
926 case Qt::Key_F6 :
927 if( Playlist::get_instance()->size() == 0
928 || Playlist::get_instance()->getActiveSongNumber() >= Playlist::get_instance()->size() -1) {
929 break;
930 }
931
933 return true;
934 break;
935 }
936 } else {
937 return false; // standard event processing
938 }
939
940 return false;
941}
942
944{
945 bool bUseRelativeFilenames = Preferences::get_instance()->isPlaylistUsingRelativeFilenames();
946
947 Playlist* pPlaylist = Playlist::load ( filename, bUseRelativeFilenames );
948 if ( !pPlaylist ) {
949 _ERRORLOG( "Error loading the playlist" );
950 return false;
951 }
952
954
955 Playlist* playlist = Playlist::get_instance();
956 if ( playlist->size() > 0 ) {
957 QTreeWidget* m_pPlaylist = m_pPlaylistTree;
958 m_pPlaylist->clear();
959
960 for ( uint i = 0; i < playlist->size(); ++i ){
961 QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
962 m_pPlaylistItem->setText( 0, playlist->get( i )->filePath );
963 m_pPlaylistItem->setText( 1, playlist->get( i )->scriptPath );
964
965 if ( playlist->get( i )->scriptEnabled ) {
966 m_pPlaylistItem->setCheckState( 2, Qt::Checked );
967 } else {
968 m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
969 }
970 }
971
972 QTreeWidgetItem* m_pPlaylistItem = m_pPlaylist->topLevelItem ( 0 );
973 m_pPlaylist->setCurrentItem ( m_pPlaylistItem );
974 pPlaylist->setSelectedSongNr( 0 );
975 setWindowTitle ( tr ( "Playlist Browser" ) + QString(" - ") + pPlaylist->getFilename() );
976 }
977
978 return true;
979}
980
983
984 if ( changes & H2Core::Preferences::Changes::Font ) {
985
986 QFont font( pPref->getApplicationFontFamily(), getPointSize( pPref->getFontSize() ) );
987 QFont childFont( pPref->getLevel2FontFamily(), getPointSize( pPref->getFontSize() ) );
988 setFont( font );
989 m_pMenubar->setFont( font );
990 m_pPlaylistMenu->setFont( font );
991#ifndef WIN32
992 m_pScriptMenu->setFont( font );
993#endif
994
995 int ii;
996
997 for ( ii = 0; ii < m_pPlaylistTree->headerItem()->columnCount(); ii++ ) {
998 m_pPlaylistTree->headerItem()->setFont( ii, font );
999 }
1000
1001 QTreeWidgetItem* pNode = m_pPlaylistTree->topLevelItem( 0 );
1002
1003 while ( pNode != nullptr ) {
1004 for ( ii = 0; ii < pNode->columnCount(); ii++ ) {
1005 pNode->setFont( ii, childFont );
1006 }
1007 pNode = m_pPlaylistTree->itemBelow( pNode );
1008 }
1009
1010 }
1011}
#define INFOLOG(x)
Definition Object.h:237
#define _ERRORLOG(x)
Definition Object.h:245
Generic Button with SVG icons or text.
Definition Button.h:60
@ Push
Button is not set checkable.
@ Toggle
Button is set checkable.
Custom file dialog checking whether the user has write access to the selected folder before allowing ...
Definition FileDialog.h:33
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:95
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:97
static const QString playlist_ext
Definition Filesystem.h:90
static const QString songs_filter_name
Definition Filesystem.h:93
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:226
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:639
void sequencer_play()
Start the internal sequencer.
Definition Hydrogen.cpp:218
Drumkit info.
Definition Playlist.h:37
void add(Entry *entry)
Definition Playlist.h:134
void setNextSongByNumber(int SongNumber)
Definition Playlist.cpp:197
void setIsModified(bool IsModified)
Definition Playlist.h:174
int getActiveSongNumber()
Definition Playlist.h:149
int getSelectedSongNr()
Definition Playlist.h:139
void setFilename(const QString &filename)
Definition Playlist.h:164
void setSelectedSongNr(int songNumber)
Definition Playlist.h:144
Entry * get(int idx)
Definition Playlist.h:128
void setActiveSongNumber(int ActiveSongNumber)
Definition Playlist.h:154
const QString & getFilename()
Definition Playlist.h:159
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:156
int size() const
Definition Playlist.h:123
bool getIsModified()
Definition Playlist.h:169
Manager for User Preferences File (singleton)
Definition Preferences.h:78
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 setAction(std::shared_ptr< Action > pAction)
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