hydrogen 1.2.3
PreferencesDialog.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#include <cstring>
24
25#include "PreferencesDialog.h"
26#include "../HydrogenApp.h"
27#include "../MainForm.h"
28#include "../CommonStrings.h"
29
30#include "qmessagebox.h"
31#include "qstylefactory.h"
32
33#include <QPixmap>
34#include <QFontDatabase>
35#include <QTreeWidgetItemIterator>
37
38#include <core/EventQueue.h>
39#include <core/MidiMap.h>
40#include <core/Hydrogen.h>
41#include <core/IO/MidiInput.h>
50
54
55
56using namespace H2Core;
57
58
60 : LCDCombo( pParent)
61{
62 m_sDriver = "";
63}
64
66{
67 clear();
68 QApplication::setOverrideCursor( Qt::WaitCursor );
69 if ( m_sDriver == "PortAudio" ) {
70#ifdef H2CORE_HAVE_PORTAUDIO
71 // Get device list for PortAudio based on current value of the API combo box
72 for ( QString s : PortAudioDriver::getDevices( m_sHostAPI ) ) {
73 addItem( s );
74 }
75#endif
76 } else if ( m_sDriver == "CoreAudio" ) {
77#ifdef H2CORE_HAVE_COREAUDIO
78 for ( QString s : CoreAudioDriver::getDevices() ) {
79 addItem( s );
80 }
81#endif
82 } else if ( m_sDriver == "ALSA" ) {
83#ifdef H2CORE_HAVE_ALSA
84 for ( QString s : AlsaAudioDriver::getDevices() ) {
85 addItem( s );
86 }
87#endif
88 }
89 QApplication::restoreOverrideCursor();
91}
92
93
95 : LCDCombo( pParent )
96{
97}
98
99void HostAPIComboBox::setValue( QString sHostAPI ) {
100 // The ComboBox doesn't have any item strings until it's actually opened,
101 // so we must add the item to it temporarily
102 clear();
103 addItem( sHostAPI );
104 setCurrentText( sHostAPI );
105}
106
108{
109 clear();
110#ifdef H2CORE_HAVE_PORTAUDIO
111 QApplication::setOverrideCursor( Qt::WaitCursor );
112 addItems( PortAudioDriver::getHostAPIs() );
113 QApplication::restoreOverrideCursor();
114#endif
115
117}
118
119
120ColorTreeItem::ColorTreeItem( int nId, QTreeWidgetItem* pParent, QString sLabel )
121 : QTreeWidgetItem( pParent, QStringList( sLabel ) ) {
122 m_nId = nId;
123}
124ColorTreeItem::ColorTreeItem( int nId, QTreeWidget* pParent, QString sLabel )
125 : QTreeWidgetItem( pParent, QStringList( sLabel ) ) {
126 m_nId = nId;
127}
129 return m_nId;
130}
131
132QString PreferencesDialog::m_sColorRed = "#ca0003";
133
134
136 : QDialog( parent )
137 , m_pCurrentColor( nullptr )
138 , m_nCurrentId( 0 )
139 , m_changes( H2Core::Preferences::Changes::None )
140 , m_bMidiTableChanged( false ) {
141
142 m_pCurrentTheme = std::make_shared<H2Core::Theme>( H2Core::Preferences::get_instance()->getTheme() );
143 m_pPreviousTheme = std::make_shared<H2Core::Theme>( H2Core::Preferences::get_instance()->getTheme() );
144 setupUi( this );
145
146 setWindowTitle( tr( "Preferences" ) );
147
148 setMinimumSize( width(), height() );
149
150 connect( this, &PreferencesDialog::rejected, this, &PreferencesDialog::onRejected );
151
153
154 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
155 auto pHydrogen = Hydrogen::get_instance();
156
158 // General tab
159 QSize generalTabWidgetSize( 60, 24 );
160
161 restoreLastUsedSongCheckbox->setChecked( pPref->isRestoreLastSongEnabled() );
162 restoreLastUsedPlaylistCheckbox->setChecked( pPref->isRestoreLastPlaylistEnabled() );
163 useRelativePlaylistPathsCheckbox->setChecked( pPref->isPlaylistUsingRelativeFilenames() );
164 hideKeyboardCursor->setChecked( pPref->hideKeyboardCursor() );
165
166 // General tab - restore the right m_bsetlash value
167 if ( pPref->m_brestartLash == true ){
168 if (pPref->m_bsetLash == false ){
169 pPref->m_bsetLash = true ;
170 pPref->m_brestartLash = false;
171 }
172
173 }
174 useLashCheckbox->setChecked( pPref->m_bsetLash );
175
176 sBcountOffset->setSize( generalTabWidgetSize );
177 sBcountOffset->setValue( pPref->m_countOffset );
178 sBstartOffset->setSize( generalTabWidgetSize );
179 sBstartOffset->setValue( pPref->m_startOffset );
180
181 sBmaxBars->setSize( generalTabWidgetSize );
182 sBmaxBars->setValue( pPref->getMaxBars() );
183 sBmaxLayers->setSize( generalTabWidgetSize );
184 sBmaxLayers->setValue( pPref->getMaxLayers() );
185 autosaveSpinBox->setSize( generalTabWidgetSize );
186 autosaveSpinBox->setValue( pPref->m_nAutosavesPerHour );
187
188 QString pathtoRubberband = pPref->m_rubberBandCLIexecutable;
189 rubberbandLineEdit->setText( pathtoRubberband );
190
191#ifdef H2CORE_HAVE_RUBBERBAND
192 pathToRubberbandExLable->hide();
193 rubberbandLineEdit->hide();
194#endif
195
196 // General tab - Language selection menu
197 languageComboBox->setSize( QSize( 310, 24 ) );
198 for ( QString sLang : Translations::availableTranslations( "hydrogen" ) ) {
199 QLocale loc( sLang );
200 QString sLabel = loc.nativeLanguageName() + " (" + loc.nativeCountryName() + ')';
201 languageComboBox->addItem( sLabel, QVariant( sLang ) );
202 }
203 // General tab - Find preferred language and select that in menu
204 QStringList languages;
205 QString sPreferredLanguage = pPref->getPreferredLanguage();
206 if ( !sPreferredLanguage.isNull() ) {
207 languages << sPreferredLanguage;
208 }
209 languages << QLocale::system().uiLanguages();
210 QString sLanguage = Translations::findTranslation( languages, "hydrogen" );
211 m_sInitialLanguage = sLanguage;
212 int nLanguage = languageComboBox->findData( QVariant( sLanguage ) );
213 if ( nLanguage != -1 ) {
214 languageComboBox->setCurrentIndex( nLanguage );
215 }
216
218 // Audio tab
219
220 // For everything above the restart button
221 QSize audioTabWidgetSizeTop( 240, 24 );
222 // and everything below
223 QSize audioTabWidgetSizeBottom( 184, 24 );
224
225 driverComboBox->setSize( audioTabWidgetSizeTop );
226 driverComboBox->clear();
227 driverComboBox->addItem( "Auto" );
228 for ( const QString& ssDriver : pHydrogen->getAudioEngine()->getSupportedAudioDrivers() ) {
229 driverComboBox->addItem( ssDriver );
230 }
231
232 if( driverComboBox->findText(pPref->m_sAudioDriver) > -1){
233 driverComboBox->setCurrentIndex(driverComboBox->findText(pPref->m_sAudioDriver));
234 }
235 else
236 {
237 driverInfoLbl->setText( tr("Select your Audio Driver" ));
238 ERRORLOG( "Unknown audio driver from preferences [" + pPref->m_sAudioDriver + "]" );
239 }
240 connect( driverComboBox, SIGNAL(activated(int)), this,
241 SLOT(driverComboBoxActivated(int)));
242
243 // Audio tab - Set the PortAudio HostAPI combo box to the current
244 // selected value.
245 portaudioHostAPIComboBox->setSize( audioTabWidgetSizeTop );
246 portaudioHostAPIComboBox->setValue( pPref->m_sPortAudioHostAPI );
247 connect( portaudioHostAPIComboBox, SIGNAL(activated(int)), this,
249
250 m_pAudioDeviceTxt->setSize( audioTabWidgetSizeTop );
251 m_pAudioDeviceTxt->setHostAPI( pPref->m_sPortAudioHostAPI );
252 connect( m_pAudioDeviceTxt, SIGNAL(currentTextChanged(const QString&)),
253 this, SLOT( audioDeviceTxtChanged(const QString&)));
254
255 latencyTargetSpinBox->setSize( QSize( 55, 23 ) );
256 latencyTargetSpinBox->setValue( pPref->m_nLatencyTarget );
257 connect( latencyTargetSpinBox, SIGNAL(valueChanged(int)), this,
259
260 bufferSizeSpinBox->setSize( audioTabWidgetSizeTop );
261 bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
262 connect( bufferSizeSpinBox, SIGNAL(valueChanged(int)), this,
264
265 sampleRateComboBox->setSize( audioTabWidgetSizeTop );
266 switch ( pPref->m_nSampleRate ) {
267 case 44100:
268 sampleRateComboBox->setCurrentIndex( 0 );
269 break;
270 case 48000:
271 sampleRateComboBox->setCurrentIndex( 1 );
272 break;
273 case 88200:
274 sampleRateComboBox->setCurrentIndex( 2 );
275 break;
276 case 96000:
277 sampleRateComboBox->setCurrentIndex( 3 );
278 break;
279 default:
280 ERRORLOG( QString("Wrong samplerate: %1").arg( pPref->m_nSampleRate ) );
281 }
282 connect( sampleRateComboBox, SIGNAL(editTextChanged(const QString&)), this,
283 SLOT(sampleRateComboBoxEditTextChanged(const QString&)));
284
285 // Audio tab - JACK
286 trackOutsCheckBox->setChecked( pPref->m_bJackTrackOuts );
287 connect(trackOutsCheckBox, SIGNAL(toggled(bool)), this, SLOT(toggleTrackOutsCheckBox( bool )));
288
289 connectDefaultsCheckBox->setChecked( pPref->m_bJackConnectDefaults );
290 enableTimebaseCheckBox->setChecked( pPref->m_bJackTimebaseEnabled );
291
292 trackOutputComboBox->setSize( audioTabWidgetSizeTop );
293 switch ( pPref->m_JackTrackOutputMode ) {
294 case Preferences::JackTrackOutputMode::postFader:
295 trackOutputComboBox->setCurrentIndex( 0 );
296 break;
297 case Preferences::JackTrackOutputMode::preFader:
298 trackOutputComboBox->setCurrentIndex( 1 );
299 break;
300 default:
301 ERRORLOG( QString( "Unknown JACK track output mode [%1]" )
302 .arg( static_cast<int>( pPref->m_JackTrackOutputMode ) ) );
303 }
304
305 jackBBTSyncComboBox->setSize( audioTabWidgetSizeTop );
306 switch ( pPref->m_JackBBTSync ) {
307 case Preferences::JackBBTSyncMethod::constMeasure:
308 jackBBTSyncComboBox->setCurrentIndex( 0 );
309 break;
310 case Preferences::JackBBTSyncMethod::identicalBars:
311 jackBBTSyncComboBox->setCurrentIndex( 1 );
312 break;
313 default:
314 ERRORLOG( QString( "Unknown JACK BBT synchronization method [%1]" )
315 .arg( static_cast<int>(pPref->m_JackBBTSync) ) );
316 }
317 // Audio tab - ~JACK
318
319 // Audio tab - metronome volume
320 metronomeVolumeSpinBox->setSize( audioTabWidgetSizeBottom );
321 uint metronomeVol = (uint)( pPref->m_fMetronomeVolume * 100.0 );
322 metronomeVolumeSpinBox->setValue(metronomeVol);
323
324 // Audio tab - max voices
325 maxVoicesTxt->setSize( audioTabWidgetSizeBottom );
326 maxVoicesTxt->setValue( pPref->m_nMaxNotes );
327
328 resampleComboBox->setSize( audioTabWidgetSizeBottom );
329 resampleComboBox->setCurrentIndex( static_cast<int>(pHydrogen->getAudioEngine()->getSampler()->getInterpolateMode() ) );
330
332
334 // MIDI tab
336 QSize midiTabWidgetSize = QSize( 309, 24 );
337 m_pMidiDriverComboBox->setSize( midiTabWidgetSize );
338 m_pMidiDriverComboBox->clear();
339#ifdef H2CORE_HAVE_ALSA
340 m_pMidiDriverComboBox->addItem( "ALSA" );
341#endif
342#ifdef H2CORE_HAVE_PORTMIDI
343 m_pMidiDriverComboBox->addItem( "PortMidi" );
344#endif
345#ifdef H2CORE_HAVE_COREMIDI
346 m_pMidiDriverComboBox->addItem( "CoreMIDI" );
347#endif
348#ifdef H2CORE_HAVE_JACK
349 m_pMidiDriverComboBox->addItem( "JACK-MIDI" );
350#endif
351
352 if ( m_pMidiDriverComboBox->findText(pPref->m_sMidiDriver) > -1 ) {
353 m_pMidiDriverComboBox->setCurrentIndex(m_pMidiDriverComboBox->findText(pPref->m_sMidiDriver));
354 } else {
355 driverInfoLbl->setText( tr("Select your MIDI Driver" ) );
356 ERRORLOG( "Unknown MIDI input from preferences [" + pPref->m_sMidiDriver + "]" );
357 }
358 connect(m_pMidiDriverComboBox, SIGNAL(currentIndexChanged(int)),
359 this, SLOT( onMidiDriverComboBoxIndexChanged(int) ));
360
361 midiPortChannelComboBox->setSize( midiTabWidgetSize );
362 midiPortChannelComboBox->setEnabled( false );
363 midiPortComboBox->setSize( midiTabWidgetSize );
364 midiPortComboBox->setEnabled( false );
365 connect( midiPortComboBox, SIGNAL(activated(int)), this,
366 SLOT(midiPortComboBoxActivated(int)));
367
368 // MIDI tab - list midi input ports
369 midiPortComboBox->clear();
370 midiPortComboBox->addItem( pCommonStrings->getPreferencesNone() );
371 if ( pHydrogen->getMidiInput() != nullptr ) {
372 std::vector<QString> midiOutList = pHydrogen->getMidiInput()->getOutputPortList();
373
374 if ( midiOutList.size() != 0 ) {
375 midiPortComboBox->setEnabled( true );
376 midiPortChannelComboBox->setEnabled( true );
377 }
378 for (uint i = 0; i < midiOutList.size(); i++) {
379 QString sPortName = midiOutList[i];
380 midiPortComboBox->addItem( sPortName );
381
382 if ( sPortName == pPref->m_sMidiPortName ) {
383 midiPortComboBox->setCurrentIndex( i + 1 );
384 }
385 }
386 }
387
388 // MIDI tab - list midi output ports
389 midiOutportComboBox->setSize( midiTabWidgetSize );
390 midiOutportComboBox->clear();
391 midiOutportComboBox->addItem( pCommonStrings->getPreferencesNone() );
392 if ( pHydrogen->getMidiOutput() != nullptr ) {
393 std::vector<QString> midiOutList = pHydrogen->getMidiOutput()->getInputPortList();
394
395 if ( midiOutList.size() != 0 ) {
396 midiOutportComboBox->setEnabled( true );
397 midiPortChannelComboBox->setEnabled( true );
398 }
399 for (uint i = 0; i < midiOutList.size(); i++) {
400 QString sPortName = midiOutList[i];
401 midiOutportComboBox->addItem( sPortName );
402
403 if ( sPortName == pPref->m_sMidiOutputPortName ) {
404 midiOutportComboBox->setCurrentIndex( i + 1 );
405 }
406 }
407 }
408 connect( midiOutportComboBox, SIGNAL(activated(int)), this,
410
411 if ( pPref->m_nMidiChannelFilter == -1 ) {
412 midiPortChannelComboBox->setCurrentIndex( 0 );
413 }
414 else {
415 midiPortChannelComboBox->setCurrentIndex( pPref->m_nMidiChannelFilter + 1 );
416 }
417
418 m_pIgnoreNoteOffCheckBox->setChecked( pPref->m_bMidiNoteOffIgnore );
419 m_pEnableMidiFeedbackCheckBox->setChecked( pPref->m_bEnableMidiFeedback );
420 m_pDiscardMidiMsgCheckbox->setChecked( pPref->m_bMidiDiscardNoteAfterAction );
421 m_pFixedMapping->setChecked( pPref->m_bMidiFixedMapping );
422
423 connect( midiTable, &MidiTable::changed,
424 [=]() {
425 m_changes =
426 static_cast<H2Core::Preferences::Changes>(
428 m_bMidiTableChanged = true;
429 });
430
432 // OSC tab
433 enableOscCheckbox->setChecked( pPref->getOscServerEnabled() );
434 enableOscFeedbackCheckbox->setChecked( pPref->getOscFeedbackEnabled() );
435 connect(enableOscCheckbox, SIGNAL(toggled(bool)), this, SLOT(toggleOscCheckBox( bool )));
436 incomingOscPortSpinBox->setSize( QSize( 66, 24 ) );
437 incomingOscPortSpinBox->setValue( pPref->getOscServerPort() );
438
439 if ( pPref->m_nOscTemporaryPort != -1 ) {
440 oscTemporaryPortLabel->show();
441 oscTemporaryPortLabel->setText( QString( "<b><i><font color=" )
442 .append( m_sColorRed )
443 .append( ">" )
444 .append( tr( "The select port is unavailable. This instance uses the following temporary port instead:" ) )
445 .append( "</font></i></b>" ) );
446 oscTemporaryPort->show();
447 oscTemporaryPort->setEnabled( false );
448 oscTemporaryPort->setText( QString::number( pPref->m_nOscTemporaryPort ) );
449 } else {
450 oscTemporaryPortLabel->hide();
451 oscTemporaryPort->hide();
452 }
453
454 if ( ! pPref->getOscServerEnabled() ) {
455 enableOscFeedbackCheckbox->hide();
456 incomingOscPortSpinBox->hide();
457 incomingOscPortLabel->hide();
458 oscTemporaryPortLabel->hide();
459 oscTemporaryPort->hide();
460 }
461
463 // Appearance tab
464 QSize appearanceTabWidgetSize = QSize( 277, 24 );
465 connect( importThemeButton, SIGNAL(clicked(bool)), SLOT(importTheme()));
466 connect( exportThemeButton, SIGNAL(clicked(bool)), SLOT(exportTheme()));
467 connect( resetThemeButton, SIGNAL(clicked(bool)), this, SLOT(resetTheme()));
468
469 // Appearance tab - Fonts
470 fontSizeComboBox->setSize( appearanceTabWidgetSize );
471 connect( applicationFontComboBox, &QFontComboBox::currentFontChanged, this, &PreferencesDialog::onApplicationFontChanged );
472 connect( level2FontComboBox, &QFontComboBox::currentFontChanged, this, &PreferencesDialog::onLevel2FontChanged );
473 connect( level3FontComboBox, &QFontComboBox::currentFontChanged, this, &PreferencesDialog::onLevel3FontChanged );
474 connect( fontSizeComboBox, SIGNAL( currentIndexChanged(int) ),
475 this, SLOT( onFontSizeChanged(int) ) );
476
477 // Appearance tab - Interface
478 UIChangeWarningLabel->hide();
479 UIChangeWarningLabel->setText( QString( "<b><i><font color=" )
480 .append( m_sColorRed )
481 .append( ">" )
482 .append( tr( "For changes of the interface layout to take effect Hydrogen must be restarted." ) )
483 .append( "</font></i></b>" ) );
484
485 styleComboBox->setSize( appearanceTabWidgetSize );
486 mixerFalloffComboBox->setSize( appearanceTabWidgetSize );
487 uiLayoutComboBox->setSize( appearanceTabWidgetSize );
488 uiScalingPolicyComboBox->setSize( appearanceTabWidgetSize );
489 iconColorComboBox->setSize( appearanceTabWidgetSize );
490 coloringMethodAuxSpinBox->setSize( appearanceTabWidgetSize );
491
492 connect( styleComboBox, SIGNAL( activated(int) ), this,
493 SLOT( styleComboBoxActivated(int) ) );
494 connect( uiLayoutComboBox, SIGNAL( currentIndexChanged(int) ), this,
495 SLOT( onUILayoutChanged(int) ) );
496 connect( uiScalingPolicyComboBox, SIGNAL( currentIndexChanged(int) ), this,
498 connect( mixerFalloffComboBox, SIGNAL( currentIndexChanged(int) ), this,
500 connect( iconColorComboBox, SIGNAL(currentIndexChanged(int)), this,
501 SLOT( onIconColorChanged(int)) );
502 connect( coloringMethodAuxSpinBox, SIGNAL( valueChanged(int)), this, SLOT( onColorNumberChanged( int ) ) );
503
504 m_colorSelectionButtons = std::vector<ColorSelectionButton*>( m_pCurrentTheme->getInterfaceTheme()->m_nMaxPatternColors );
505 int nButtonSize = fontSizeComboBox->height();
506 // float fLineWidth = static_cast<float>(fontSizeComboBox->width());
507 // Using a fixed one size resizing of the widget seems to happen
508 // after the constructor is called.
509 float fLineWidth = 308;
510 int nButtonsPerLine = std::floor( fLineWidth / static_cast<float>(nButtonSize + 6) );
511
512 colorSelectionGrid->setHorizontalSpacing( 4 );
513 for ( int ii = 0; ii < m_pCurrentTheme->getInterfaceTheme()->m_nMaxPatternColors; ii++ ) {
514 ColorSelectionButton* bbutton =
515 new ColorSelectionButton( this, m_pCurrentTheme->getInterfaceTheme()->m_patternColors[ ii ],
516 nButtonSize );
517 bbutton->hide();
518 connect( bbutton, &ColorSelectionButton::colorChanged, this,
520 colorSelectionGrid->addWidget( bbutton,
521 std::floor( static_cast<float>( ii ) /
522 static_cast<float>( nButtonsPerLine ) ),
523 (ii % nButtonsPerLine) + 1); //+1 to take the hspace into account.
524 m_colorSelectionButtons[ ii ] = bbutton;
525 }
526
527 coloringMethodCombo->setSize( appearanceTabWidgetSize );
528 coloringMethodCombo->clear();
529 coloringMethodCombo->addItem(tr("Automatic"));
530 coloringMethodCombo->addItem(tr("Custom"));
531 connect( coloringMethodCombo, SIGNAL( currentIndexChanged(int) ), this, SLOT( onColoringMethodChanged(int) ) );
532
533 // Appearance tab - Colors
534 colorButton->setAutoFillBackground(true);
535 m_pColorSliderTimer = new QTimer( this );
536 m_pColorSliderTimer->setSingleShot( true );
537 connect( m_pColorSliderTimer, SIGNAL(timeout()), this, SLOT(updateColors()) );
538
539 ColorTreeItem* pTopLevelItem;
540 colorTree->clear();
541 pTopLevelItem = new ColorTreeItem( 0x000, colorTree, tr( "General" ) );
542 new ColorTreeItem( 0x100, pTopLevelItem, tr( "Window" ) );
543 new ColorTreeItem( 0x101, pTopLevelItem, tr( "Window Text" ) );
544 new ColorTreeItem( 0x102, pTopLevelItem, tr( "Base" ) );
545 new ColorTreeItem( 0x103, pTopLevelItem, tr( "Alternate Base" ) );
546 new ColorTreeItem( 0x104, pTopLevelItem, tr( "Text" ) );
547 new ColorTreeItem( 0x105, pTopLevelItem, tr( "Button" ) );
548 new ColorTreeItem( 0x106, pTopLevelItem, tr( "Button Text" ) );
549 new ColorTreeItem( 0x107, pTopLevelItem, tr( "Light" ) );
550 new ColorTreeItem( 0x108, pTopLevelItem, tr( "Mid Light" ) );
551 new ColorTreeItem( 0x109, pTopLevelItem, tr( "Mid" ) );
552 new ColorTreeItem( 0x10a, pTopLevelItem, tr( "Dark" ) );
553 new ColorTreeItem( 0x10b, pTopLevelItem, tr( "Shadow Text" ) );
554 new ColorTreeItem( 0x10c, pTopLevelItem, tr( "Highlight" ) );
555 new ColorTreeItem( 0x10d, pTopLevelItem, tr( "Highlight Text" ) );
556 new ColorTreeItem( 0x10e, pTopLevelItem, tr( "Selection Highlight" ) );
557 new ColorTreeItem( 0x10f, pTopLevelItem, tr( "Selection Inactive" ) );
558 new ColorTreeItem( 0x110, pTopLevelItem, tr( "Tool Tip Base" ) );
559 new ColorTreeItem( 0x111, pTopLevelItem, tr( "Tool Tip Text" ) );
560
561 auto pWidgetItem = new ColorTreeItem( 0x000, colorTree, tr( "Widgets" ) );
562 auto pDefaultItem = new ColorTreeItem( 0x200, pWidgetItem, tr( "Widget" ) );
563 new ColorTreeItem( 0x201, pWidgetItem, tr( "Widget Text" ) );
564 new ColorTreeItem( 0x202, pWidgetItem, tr( "Accent" ) );
565 new ColorTreeItem( 0x203, pWidgetItem, tr( "Accent Text" ) );
566 new ColorTreeItem( 0x204, pWidgetItem, tr( "Button Red" ) );
567 new ColorTreeItem( 0x205, pWidgetItem, tr( "Button Red Text" ) );
568 new ColorTreeItem( 0x206, pWidgetItem, tr( "Spin Box" ) );
569 new ColorTreeItem( 0x207, pWidgetItem, tr( "Spin Box Text" ) );
570 new ColorTreeItem( 0x208, pWidgetItem, tr( "Playhead" ) );
571 new ColorTreeItem( 0x209, pWidgetItem, tr( "Cursor" ) );
572
573 pTopLevelItem = new ColorTreeItem( 0x000, colorTree, tr( "Song Editor" ) );
574 new ColorTreeItem( 0x300, pTopLevelItem, tr( "Background" ) );
575 new ColorTreeItem( 0x301, pTopLevelItem, tr( "Alternate Row" ) );
576 new ColorTreeItem( 0x302, pTopLevelItem, tr( "Virtual Row" ) );
577 new ColorTreeItem( 0x303, pTopLevelItem, tr( "Selected Row" ) );
578 new ColorTreeItem( 0x304, pTopLevelItem, tr( "Selected Row Text" ) );
579 new ColorTreeItem( 0x305, pTopLevelItem, tr( "Line" ) );
580 new ColorTreeItem( 0x306, pTopLevelItem, tr( "Text" ) );
581 new ColorTreeItem( 0x307, pTopLevelItem, tr( "Automation Background" ) );
582 new ColorTreeItem( 0x308, pTopLevelItem, tr( "Automation Line" ) );
583 new ColorTreeItem( 0x309, pTopLevelItem, tr( "Automation Node" ) );
584 new ColorTreeItem( 0x30a, pTopLevelItem, tr( "Stacked Mode On" ) );
585 new ColorTreeItem( 0x30b, pTopLevelItem, tr( "Stacked Mode On Next" ) );
586 new ColorTreeItem( 0x30c, pTopLevelItem, tr( "Stacked Mode Off Next" ) );
587
588 pTopLevelItem = new ColorTreeItem( 0x000, colorTree, tr( "Pattern Editor" ) );
589 new ColorTreeItem( 0x400, pTopLevelItem, tr( "Background" ) );
590 new ColorTreeItem( 0x401, pTopLevelItem, tr( "Alternate Row" ) );
591 new ColorTreeItem( 0x402, pTopLevelItem, tr( "Selected Row" ) );
592 new ColorTreeItem( 0x403, pTopLevelItem, tr( "Selected Row Text" ) );
593 new ColorTreeItem( 0x404, pTopLevelItem, tr( "Octave Row" ) );
594 new ColorTreeItem( 0x405, pTopLevelItem, tr( "Text" ) );
595 new ColorTreeItem( 0x406, pTopLevelItem, tr( "Note (Full Velocity)" ) );
596 new ColorTreeItem( 0x407, pTopLevelItem, tr( "Note (Default Velocity)" ) );
597 new ColorTreeItem( 0x408, pTopLevelItem, tr( "Note (Half Velocity)" ) );
598 new ColorTreeItem( 0x409, pTopLevelItem, tr( "Note (Zero Velocity)" ) );
599 new ColorTreeItem( 0x40a, pTopLevelItem, tr( "Note Off" ) );
600 new ColorTreeItem( 0x40b, pTopLevelItem, tr( "Grid Line 1" ) );
601 new ColorTreeItem( 0x40c, pTopLevelItem, tr( "Grid Line 2" ) );
602 new ColorTreeItem( 0x40d, pTopLevelItem, tr( "Grid Line 3" ) );
603 new ColorTreeItem( 0x40e, pTopLevelItem, tr( "Grid Line 4" ) );
604 new ColorTreeItem( 0x40f, pTopLevelItem, tr( "Grid Line 5" ) );
605 new ColorTreeItem( 0x410, pTopLevelItem, tr( "Grid Line 6" ) );
606
607 colorButton->setEnabled( false );
608
609 connect( colorTree, SIGNAL(itemSelectionChanged()),
610 this, SLOT(colorTreeSelectionChanged()) );
611 connect( colorButton, SIGNAL(colorChanged()),
612 this, SLOT(colorButtonChanged()) );
613 connect(rslider, SIGNAL(valueChanged(int)), SLOT(rsliderChanged(int)));
614 connect(gslider, SIGNAL(valueChanged(int)), SLOT(gsliderChanged(int)));
615 connect(bslider, SIGNAL(valueChanged(int)), SLOT(bsliderChanged(int)));
616 connect(hslider, SIGNAL(valueChanged(int)), SLOT(hsliderChanged(int)));
617 connect(sslider, SIGNAL(valueChanged(int)), SLOT(ssliderChanged(int)));
618 connect(vslider, SIGNAL(valueChanged(int)), SLOT(vsliderChanged(int)));
619
620 connect(rval, SIGNAL(valueChanged(int)), SLOT(rsliderChanged(int)));
621 connect(gval, SIGNAL(valueChanged(int)), SLOT(gsliderChanged(int)));
622 connect(bval, SIGNAL(valueChanged(int)), SLOT(bsliderChanged(int)));
623 connect(hval, SIGNAL(valueChanged(int)), SLOT(hsliderChanged(int)));
624 connect(sval, SIGNAL(valueChanged(int)), SLOT(ssliderChanged(int)));
625 connect(vval, SIGNAL(valueChanged(int)), SLOT(vsliderChanged(int)));
626
627 // We initialize the tree by expanding the "Widget" node and
628 // selecting the first color. This looks more nice than with no
629 // color selected at all and works better with the Shotlist.
630 colorTree->expandItem( pWidgetItem );
631 colorTree->setCurrentItem( pDefaultItem );
632
634
636
637 m_bNeedDriverRestart = false;
638}
639
641{
642 INFOLOG("~PREFERENCES_DIALOG");
643}
644
646{
647 Preferences *preferencesMng = Preferences::get_instance();
648 preferencesMng->loadPreferences( false ); // reload old user's preferences
649
650 //restore the right m_bsetlash value
651 if ( preferencesMng->m_brestartLash == true ){
652 if (preferencesMng->m_bsetLash == false ){
653 preferencesMng->m_bsetLash = true ;
654 preferencesMng->m_brestartLash = false;
655 }
656
657 }
658
661
662 reject();
663}
664
666{
668}
669
672 auto pAudioDriver = Hydrogen::get_instance()->getAudioOutput();
673
674 bool bAudioOptionAltered = false;
675 QString sPrevAudioDriver = pPref->m_sAudioDriver;
676
677 // Selected audio driver
678 if (driverComboBox->currentText() == "JACK" ) {
679 pPref->m_sAudioDriver = "JACK";
680 }
681 else if ( driverComboBox->currentText() == "ALSA" ||
682 ( driverComboBox->currentText() == "Auto" &&
683 dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver) != nullptr ) ) {
684 pPref->m_sAudioDriver = "ALSA";
685 pPref->m_sAlsaAudioDevice = m_pAudioDeviceTxt->lineEdit()->text();
686 }
687 else if ( driverComboBox->currentText() == "OSS" ||
688 ( driverComboBox->currentText() == "Auto" &&
689 dynamic_cast<H2Core::OssDriver*>(pAudioDriver) != nullptr ) ) {
690 pPref->m_sAudioDriver = "OSS";
691 pPref->m_sOSSDevice = m_pAudioDeviceTxt->lineEdit()->text();
692 }
693 else if (driverComboBox->currentText() == "PortAudio" ||
694 ( driverComboBox->currentText() == "Auto" &&
695 dynamic_cast<H2Core::PortAudioDriver*>(pAudioDriver) != nullptr ) ) {
696 pPref->m_sAudioDriver = "PortAudio";
697 pPref->m_sPortAudioDevice = m_pAudioDeviceTxt->lineEdit()->text();
698 pPref->m_sPortAudioHostAPI = portaudioHostAPIComboBox->currentText();
699 pPref->m_nLatencyTarget = latencyTargetSpinBox->value();
700 }
701 else if (driverComboBox->currentText() == "CoreAudio" ||
702 ( driverComboBox->currentText() == "Auto" &&
703 dynamic_cast<H2Core::CoreAudioDriver*>(pAudioDriver) != nullptr ) ) {
704 pPref->m_sAudioDriver = "CoreAudio";
705 pPref->m_sCoreAudioDevice = m_pAudioDeviceTxt->lineEdit()->text();
706 }
707 else if (driverComboBox->currentText() == "PulseAudio" ) {
708 pPref->m_sAudioDriver = "PulseAudio";
709 }
710 else if (driverComboBox->currentText() == "Auto" ) {
711 pPref->m_sAudioDriver = "Auto";
712 }
713 else {
714 ERRORLOG( "[okBtnClicked] Invalid audio driver: " + driverComboBox->currentText() );
715 }
716
717 if ( pPref->m_sAudioDriver != sPrevAudioDriver ) {
718 bAudioOptionAltered = true;
719 }
720
721 // JACK
722 if ( pPref->m_bJackConnectDefaults != connectDefaultsCheckBox->isChecked() ) {
723 pPref->m_bJackConnectDefaults = connectDefaultsCheckBox->isChecked();
724 bAudioOptionAltered = true;
725 }
726
727 if ( pPref->m_bJackTrackOuts != trackOutsCheckBox->isChecked() ) {
728 pPref->m_bJackTrackOuts = trackOutsCheckBox->isChecked();
729 bAudioOptionAltered = true;
730 }
731
732 if ( pPref->m_bJackTimebaseEnabled != enableTimebaseCheckBox->isChecked() ) {
733 pPref->m_bJackTimebaseEnabled = enableTimebaseCheckBox->isChecked();
734 bAudioOptionAltered = true;
735 }
736
737 switch ( trackOutputComboBox->currentIndex() ) {
738 case 0:
739 if ( pPref->m_JackTrackOutputMode !=
740 Preferences::JackTrackOutputMode::postFader ) {
741 pPref->m_JackTrackOutputMode =
742 Preferences::JackTrackOutputMode::postFader;
743 bAudioOptionAltered = true;
744 }
745 break;
746 case 1:
747 if ( pPref->m_JackTrackOutputMode !=
748 Preferences::JackTrackOutputMode::preFader ) {
749 pPref->m_JackTrackOutputMode =
750 Preferences::JackTrackOutputMode::preFader;
751 bAudioOptionAltered = true;
752 }
753 break;
754 default:
755 ERRORLOG( QString( "Unexpected track output value" ) );
756 }
757
758 switch ( jackBBTSyncComboBox->currentIndex() ) {
759 case 0:
760 if ( pPref->m_JackBBTSync != Preferences::JackBBTSyncMethod::constMeasure ) {
761 pPref->m_JackBBTSync = Preferences::JackBBTSyncMethod::constMeasure;
762 bAudioOptionAltered = true;
763 }
764 break;
765 case 1:
766 if ( pPref->m_JackBBTSync != Preferences::JackBBTSyncMethod::identicalBars ) {
767 pPref->m_JackBBTSync = Preferences::JackBBTSyncMethod::identicalBars;
768 bAudioOptionAltered = true;
769 }
770 break;
771 default:
772 ERRORLOG( QString( "Unexpected JACK BBT synchronization value" ) );
773 }
774 // ~ JACK
775
776 if ( pPref->m_nBufferSize != bufferSizeSpinBox->value() ) {
777 pPref->m_nBufferSize = bufferSizeSpinBox->value();
778 bAudioOptionAltered = true;
779 }
780
781 if ( sampleRateComboBox->currentText() == "44100" &&
782 pPref->m_nSampleRate != 44100 ) {
783 pPref->m_nSampleRate = 44100;
784 bAudioOptionAltered = true;
785 }
786 else if ( sampleRateComboBox->currentText() == "48000" &&
787 pPref->m_nSampleRate != 48000 ) {
788 pPref->m_nSampleRate = 48000;
789 bAudioOptionAltered = true;
790 }
791 else if ( sampleRateComboBox->currentText() == "88200" &&
792 pPref->m_nSampleRate != 88200 ) {
793 pPref->m_nSampleRate = 88200;
794 bAudioOptionAltered = true;
795 }
796 else if ( sampleRateComboBox->currentText() == "96000" &&
797 pPref->m_nSampleRate != 96000 ) {
798 pPref->m_nSampleRate = 96000;
799 bAudioOptionAltered = true;
800 }
801
802 if ( bAudioOptionAltered ) {
803 m_changes =
804 static_cast<H2Core::Preferences::Changes>(
806 }
807}
808
809
811{
812 auto pH2App = HydrogenApp::get_instance();
813 auto pCommonStrings = pH2App->getCommonStrings();
814 auto pPref = Preferences::get_instance();
815 auto pHydrogen = Hydrogen::get_instance();
816
818 // Audio tab
820 bool bAudioOptionAltered = false;
821
823
824 if ( m_bNeedDriverRestart ) {
825 int res = QMessageBox::information( this, "Hydrogen",
826 tr( "Driver restart required.\n Restart driver?"),
827 pCommonStrings->getButtonOk(),
828 pCommonStrings->getButtonCancel(),
829 nullptr, 1 );
830 if ( res != 0 ) {
831 // Don't save the Preferences and don't close the PreferencesDialog
832 return;
833 }
834 }
835
836 // Check whether the current audio driver is valid
837 if ( pHydrogen->getAudioOutput() == nullptr ||
838 dynamic_cast<NullDriver*>(pHydrogen->getAudioOutput()) != nullptr ) {
839 int nRes = QMessageBox::warning( this, "Hydrogen",
840 QString( "%1\n" )
841 .arg( pCommonStrings->getAudioDriverNotPresent() )
842 .append( tr( "Are you sure you want to proceed?" ) ),
843 pCommonStrings->getButtonOk(),
844 pCommonStrings->getButtonCancel(),
845 nullptr, 1 );
846 if ( nRes != 0 ) {
847 return;
848 }
849 }
850
851 if ( pPref->m_fMetronomeVolume != metronomeVolumeSpinBox->value() / 100.0 ) {
852 pPref->m_fMetronomeVolume = metronomeVolumeSpinBox->value() / 100.0;
853 bAudioOptionAltered = true;
854 }
855
856 // Polyphony
857 if ( pPref->m_nMaxNotes != maxVoicesTxt->value() ) {
858 pPref->m_nMaxNotes = maxVoicesTxt->value();
859 bAudioOptionAltered = true;
860 }
861
862 // Interpolation
863 if ( static_cast<int>( pHydrogen->getAudioEngine()->getSampler()->getInterpolateMode() ) !=
864 resampleComboBox->currentIndex() ) {
865 switch ( resampleComboBox->currentIndex() ){
866 case 0:
867 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Linear );
868 break;
869 case 1:
870 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Cosine );
871 break;
872 case 2:
873 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Third );
874 break;
875 case 3:
876 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Cubic );
877 break;
878 case 4:
879 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Hermite );
880 break;
881 }
882 bAudioOptionAltered = true;
883 }
884
885 if ( bAudioOptionAltered ) {
886 m_changes =
887 static_cast<H2Core::Preferences::Changes>(
889 }
890
892 // MIDI tab
894 bool bMidiOptionAltered = false;
895
897 mM->reset_instance();
898
899 midiTable->saveMidiTable();
900 if ( m_bMidiTableChanged ) {
902 }
903
904 if ( m_pMidiDriverComboBox->currentText() == "ALSA" &&
905 pPref->m_sMidiDriver != "ALSA" ) {
906 pPref->m_sMidiDriver = "ALSA";
907 bMidiOptionAltered = true;
908 }
909 else if ( m_pMidiDriverComboBox->currentText() == "PortMidi" &&
910 pPref->m_sMidiDriver != "PortMidi" ) {
911 pPref->m_sMidiDriver = "PortMidi";
912 bMidiOptionAltered = true;
913 }
914 else if ( m_pMidiDriverComboBox->currentText() == "CoreMIDI" &&
915 pPref->m_sMidiDriver != "CoreMIDI" ) {
916 pPref->m_sMidiDriver = "CoreMIDI";
917 bMidiOptionAltered = true;
918 }
919 else if ( m_pMidiDriverComboBox->currentText() == "JACK-MIDI" &&
920 pPref->m_sMidiDriver != "JACK-MIDI" ) {
921 pPref->m_sMidiDriver = "JACK-MIDI";
922 bMidiOptionAltered = true;
923 }
924
925 if ( pPref->m_bMidiNoteOffIgnore != m_pIgnoreNoteOffCheckBox->isChecked() ) {
926 pPref->m_bMidiNoteOffIgnore = m_pIgnoreNoteOffCheckBox->isChecked();
927 bMidiOptionAltered = true;
928 }
929
930 if ( pPref->m_bMidiFixedMapping != m_pFixedMapping->isChecked() ) {
931 pPref->m_bMidiFixedMapping = m_pFixedMapping->isChecked();
932 bMidiOptionAltered = true;
933 }
934
935 if ( pPref->m_bMidiDiscardNoteAfterAction !=
936 m_pDiscardMidiMsgCheckbox->isChecked() ) {
937 pPref->m_bMidiDiscardNoteAfterAction = m_pDiscardMidiMsgCheckbox->isChecked();
938 bMidiOptionAltered = true;
939 }
940
941 if ( pPref->m_bEnableMidiFeedback !=
942 m_pEnableMidiFeedbackCheckBox->isChecked() ) {
943 pPref->m_bEnableMidiFeedback = m_pEnableMidiFeedbackCheckBox->isChecked();
944 bMidiOptionAltered = true;
945 }
946
947 QString sNewMidiPortName = midiPortComboBox->currentText();
948 if ( midiPortComboBox->currentIndex() == 0 ) {
949 sNewMidiPortName = Preferences::getNullMidiPort();
950 }
951 if ( pPref->m_sMidiPortName != sNewMidiPortName ) {
952 pPref->m_sMidiPortName = sNewMidiPortName;
953 bMidiOptionAltered = true;
955 }
956
957 QString sNewMidiOutputPortName = midiOutportComboBox->currentText();
958 if ( midiOutportComboBox->currentIndex() == 0 ) {
959 sNewMidiOutputPortName = Preferences::getNullMidiPort();
960 }
961 if ( pPref->m_sMidiOutputPortName != sNewMidiOutputPortName ) {
962 pPref->m_sMidiOutputPortName = sNewMidiOutputPortName;
963 bMidiOptionAltered = true;
965 }
966
967 if ( pPref->m_nMidiChannelFilter !=
968 midiPortChannelComboBox->currentIndex() - 1 ) {
969 pPref->m_nMidiChannelFilter = midiPortChannelComboBox->currentIndex() - 1;
970 bMidiOptionAltered = true;
971 }
972
973 if ( bMidiOptionAltered ) {
974 m_changes =
975 static_cast<H2Core::Preferences::Changes>(
977 }
978
980 // OSC tab
982 bool bOscOptionAltered = false;
983
984 if ( enableOscCheckbox->isChecked() != pPref->getOscServerEnabled() ) {
985 pPref->setOscServerEnabled( enableOscCheckbox->isChecked() );
986 pHydrogen->toggleOscServer( enableOscCheckbox->isChecked() );
987 bOscOptionAltered = true;
988 }
989
990 if ( pPref->getOscFeedbackEnabled() !=
991 enableOscFeedbackCheckbox->isChecked() ) {
992 pPref->setOscFeedbackEnabled( enableOscFeedbackCheckbox->isChecked() );
993 bOscOptionAltered = true;
994 }
995
996 if ( incomingOscPortSpinBox->value() != pPref->getOscServerPort() ) {
997 pPref->setOscServerPort( incomingOscPortSpinBox->value() );
998 pHydrogen->recreateOscServer();
999 bOscOptionAltered = true;
1000 }
1001
1002 if ( bOscOptionAltered ) {
1003 m_changes =
1004 static_cast<H2Core::Preferences::Changes>(
1006 }
1007
1009 // General tab
1011 bool bGeneralOptionAltered = false;
1012
1013 if ( pPref->isRestoreLastSongEnabled() !=
1014 restoreLastUsedSongCheckbox->isChecked() ) {
1015 pPref->setRestoreLastSongEnabled( restoreLastUsedSongCheckbox->isChecked() );
1016 bGeneralOptionAltered = true;
1017 }
1018
1019 if ( pPref->isRestoreLastPlaylistEnabled() !=
1020 restoreLastUsedPlaylistCheckbox->isChecked() ) {
1021 pPref->setRestoreLastPlaylistEnabled( restoreLastUsedPlaylistCheckbox->isChecked() );
1022 bGeneralOptionAltered = true;
1023 }
1024
1025 if ( pPref->isPlaylistUsingRelativeFilenames() !=
1026 useRelativePlaylistPathsCheckbox->isChecked() ) {
1027 pPref->setUseRelativeFilenamesForPlaylists( useRelativePlaylistPathsCheckbox->isChecked() );
1028 bGeneralOptionAltered = true;
1029 }
1030
1031 if ( pPref->m_bsetLash != useLashCheckbox->isChecked() ) {
1032 pPref->m_bsetLash = useLashCheckbox->isChecked(); //restore m_bsetLash after saving pref
1033 bGeneralOptionAltered = true;
1034 }
1035
1036 if ( pPref->hideKeyboardCursor() != hideKeyboardCursor->isChecked() ) {
1037 pPref->setHideKeyboardCursor( hideKeyboardCursor->isChecked() );
1038 bGeneralOptionAltered = true;
1039 }
1040
1041 //path to rubberband
1042 if ( pPref->m_rubberBandCLIexecutable != rubberbandLineEdit->text() ) {
1043 pPref->m_rubberBandCLIexecutable = rubberbandLineEdit->text();
1044 bGeneralOptionAltered = true;
1045 }
1046
1047 //check preferences
1048 if ( pPref->m_brestartLash == true ){
1049 pPref->m_bsetLash = true ;
1050 }
1051
1052 if ( pPref->m_countOffset != sBcountOffset->value() ) {
1053 pPref->m_countOffset = sBcountOffset->value();
1054 pHydrogen->setBcOffsetAdjust();
1055 bGeneralOptionAltered = true;
1056 }
1057
1058 if ( pPref->m_startOffset != sBstartOffset->value() ) {
1059 pPref->m_startOffset = sBstartOffset->value();
1060 pHydrogen->setBcOffsetAdjust();
1061 bGeneralOptionAltered = true;
1062 }
1063
1064 if ( pPref->getMaxBars() != sBmaxBars->value() ) {
1065 pPref->setMaxBars( sBmaxBars->value() );
1066 bGeneralOptionAltered = true;
1067 }
1068
1069 if ( pPref->getMaxLayers() != sBmaxLayers->value() ) {
1070 pPref->setMaxLayers( sBmaxLayers->value() );
1071 bGeneralOptionAltered = true;
1072 }
1073
1074 if ( pPref->m_nAutosavesPerHour != autosaveSpinBox->value() ) {
1075 pPref->m_nAutosavesPerHour = autosaveSpinBox->value();
1076 m_changes =
1079 }
1080
1081 QString sPreferredLanguage = languageComboBox->currentData().toString();
1082 if ( sPreferredLanguage != m_sInitialLanguage ) {
1083 QMessageBox::information( this, "Hydrogen", tr( "Hydrogen must be restarted for language change to take effect" ));
1084 pPref->setPreferredLanguage( sPreferredLanguage );
1085 bGeneralOptionAltered = true;
1086 }
1087
1088 if ( bGeneralOptionAltered ) {
1089 m_changes =
1090 static_cast<H2Core::Preferences::Changes>(
1092 }
1093
1095
1096 pPref->setTheme( m_pCurrentTheme );
1097
1098 if ( m_bNeedDriverRestart ) {
1099 // Restart audio and MIDI drivers now that we updated all
1100 // values in Preferences.
1101 QApplication::setOverrideCursor( Qt::WaitCursor );
1102 pHydrogen->restartDrivers();
1103 QApplication::restoreOverrideCursor();
1104 }
1105
1106 pH2App->changePreferences( m_changes );
1107
1108 pPref->savePreferences();
1109 accept();
1110}
1111
1112
1114{
1115 UNUSED( index );
1117 m_bNeedDriverRestart = true;
1118}
1119
1121{
1122 m_pAudioDeviceTxt->setHostAPI( portaudioHostAPIComboBox->currentText() );
1124 m_bNeedDriverRestart = true;
1125}
1126
1128{
1130 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1131 auto pAudioDriver = Hydrogen::get_instance()->getAudioOutput();
1132
1133 // Reset info text
1135
1136 bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
1137 switch ( pPref->m_nSampleRate ) {
1138 case 44100:
1139 sampleRateComboBox->setCurrentIndex( 0 );
1140 break;
1141 case 48000:
1142 sampleRateComboBox->setCurrentIndex( 1 );
1143 break;
1144 case 88200:
1145 sampleRateComboBox->setCurrentIndex( 2 );
1146 break;
1147 case 96000:
1148 sampleRateComboBox->setCurrentIndex( 3 );
1149 break;
1150 default:
1151 ERRORLOG( QString("Wrong samplerate: %1").arg( pPref->m_nSampleRate ) );
1152 }
1153
1154
1155 if ( driverComboBox->currentText() == "Auto" ) {
1156
1157 if ( dynamic_cast<H2Core::JackAudioDriver*>(pAudioDriver) != nullptr ) {
1159 }
1160 else if ( dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver) != nullptr ) {
1162 }
1163 else if ( dynamic_cast<H2Core::PortAudioDriver*>(pAudioDriver) != nullptr ) {
1165 }
1166 else if ( dynamic_cast<H2Core::CoreAudioDriver*>(pAudioDriver) != nullptr ) {
1168 }
1169 else if ( dynamic_cast<H2Core::PulseAudioDriver*>(pAudioDriver) != nullptr ) {
1171 }
1172 else if ( dynamic_cast<H2Core::OssDriver*>(pAudioDriver) != nullptr ) {
1174 }
1175 else {
1176
1177 m_pAudioDeviceTxt->setDriver( "Null" );
1178 m_pAudioDeviceTxt->setIsActive( false );
1179 m_pAudioDeviceTxt->lineEdit()->setText( "" );
1180 bufferSizeSpinBox->setIsActive( false );
1181 sampleRateComboBox->setIsActive( false );
1182 bufferSizeSpinBox->setToolTip( "" );
1183 sampleRateComboBox->setToolTip( "" );
1184 trackOutputComboBox->setIsActive( false );
1185 trackOutputComboBox->hide();
1186 trackOutputLbl->hide();
1187 trackOutsCheckBox->setEnabled( false );
1188 trackOutsCheckBox->hide();
1189 connectDefaultsCheckBox->setEnabled( false );
1190 connectDefaultsCheckBox->hide();
1191 enableTimebaseCheckBox->setEnabled( false );
1192 enableTimebaseCheckBox->hide();
1193 jackBBTSyncComboBox->setIsActive( false );
1194 jackBBTSyncLbl->setEnabled( false );
1195 jackBBTSyncComboBox->hide();
1196 jackBBTSyncLbl->hide();
1197 portaudioHostAPIComboBox->hide();
1198 portaudioHostAPILabel->hide();
1199 latencyTargetLabel->hide();
1200 latencyTargetSpinBox->hide();
1201 latencyValueLabel->hide();
1202 }
1203 }
1204 else if ( driverComboBox->currentText() == "OSS" ) {
1206 }
1207 else if ( driverComboBox->currentText() == "JACK" ) {
1209 }
1210 else if ( driverComboBox->currentText() == "ALSA" ) {
1212 }
1213 else if ( driverComboBox->currentText() == "PortAudio" ) {
1215 }
1216 else if ( driverComboBox->currentText() == "CoreAudio" ) {
1218 }
1219 else if ( driverComboBox->currentText() == "PulseAudio" ) {
1221 }
1222 else {
1223 QString selectedDriver = driverComboBox->currentText();
1224 ERRORLOG( "Unknown driver = " + selectedDriver );
1225 }
1226
1227 metronomeVolumeSpinBox->setEnabled(true);
1228 bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
1229}
1230
1232
1233 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1234 auto pAudioDriver = Hydrogen::get_instance()->getAudioOutput();
1235 QString sInfo;
1236
1237 if ( driverComboBox->currentText() == "Auto" ) {
1238 sInfo.append( tr("Automatic driver selection") )
1239 .append( "<br><br>" );
1240 }
1241
1242 if ( dynamic_cast<H2Core::JackAudioDriver*>(pAudioDriver) != nullptr ) {
1243 sInfo.append( "<b>" )
1244 .append( tr( "JACK Audio Connection Kit Driver" ) )
1245 .append( "</b><br>" )
1246 .append( tr( "Low latency audio driver" ) );
1247#ifndef H2CORE_HAVE_JACK
1248 sInfo.append( "<br><b><font color=" )
1249 .append( m_sColorRed ).append( ">")
1250 .append( pCommonStrings->getPreferencesNotCompiled() )
1251 .append( "</font></b>" );
1252#endif
1253 }
1254 else if ( dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver) != nullptr ) {
1255 sInfo.append( "<b>" ).append( tr( "ALSA Driver" ) )
1256 .append( "</b><br>" );
1257#ifndef H2CORE_HAVE_ALSA
1258 sInfo.append( "<br><b><font color=" )
1259 .append( m_sColorRed ).append( ">")
1260 .append( pCommonStrings->getPreferencesNotCompiled() )
1261 .append( "</font></b>" );
1262#else
1263 auto pAlsaDriver =
1264 dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver);
1265 if ( pAlsaDriver != nullptr ) {
1266 sInfo.append( "<br>" ).append( tr( "Currently connected to device: " ) )
1267 .append( "<b>" ).append( pAlsaDriver->m_sAlsaAudioDevice )
1268 .append( "</b>" );
1269 } else {
1270 ERRORLOG( "ALSA driver selected in PreferencesDialog but no ALSA driver running?" );
1271 }
1272#endif
1273 }
1274 else if ( dynamic_cast<H2Core::PortAudioDriver*>(pAudioDriver) != nullptr ) {
1275 sInfo.append( "<b>" ).append( tr( "PortAudio Driver" ) )
1276 .append( "</b><br>" );
1277#ifndef H2CORE_HAVE_PORTAUDIO
1278 sInfo.append( "<br><b><font color=" )
1279 .append( m_sColorRed ).append( ">")
1280 .append( pCommonStrings->getPreferencesNotCompiled() )
1281 .append( "</font></b>" );
1282#endif
1283 }
1284 else if ( dynamic_cast<H2Core::CoreAudioDriver*>(pAudioDriver) != nullptr ) {
1285 sInfo.append( "<b>" ).append( tr( "CoreAudio Driver" ) )
1286 .append( "</b><br>" );
1287#ifndef H2CORE_HAVE_COREAUDIO
1288 sInfo.append( "<br><b><font color=" )
1289 .append( m_sColorRed ).append( ">")
1290 .append( pCommonStrings->getPreferencesNotCompiled() )
1291 .append( "</font></b>" );
1292#endif
1293 }
1294 else if ( dynamic_cast<H2Core::PulseAudioDriver*>(pAudioDriver) != nullptr ) {
1295 sInfo.append( "<b>" ).append( tr( "PulseAudio Driver" ) )
1296 .append( "</b><br>" );
1297#ifndef H2CORE_HAVE_PULSEAUDIO
1298 sInfo.append( "<br><b><font color=" )
1299 .append( m_sColorRed ).append( ">")
1300 .append( pCommonStrings->getPreferencesNotCompiled() )
1301 .append( "</font></b>" );
1302#endif
1303 }
1304 else if ( dynamic_cast<H2Core::OssDriver*>(pAudioDriver) != nullptr ) {
1305 sInfo.append( "<b>" ).append( tr( "Open Sound System" ) )
1306 .append( "</b><br>" )
1307 .append( tr( "Simple audio driver [/dev/dsp]" ) );
1308#ifndef H2CORE_HAVE_OSS
1309 sInfo.append( "<br><b><font color=" )
1310 .append( m_sColorRed ).append( ">")
1311 .append( pCommonStrings->getPreferencesNotCompiled() )
1312 .append( "</font></b>" );
1313#endif
1314 }
1315 else {
1316
1317 if ( driverComboBox->currentText() == "Auto" ) {
1318
1319 // Display the selected driver as well.
1320 sInfo.append( "<b>" )
1321 .append( tr( "Error starting audio driver" ) )
1322 .append( "</b><br><br>" );
1323 }
1324
1325 // Display the selected driver as well.
1326 sInfo.append( "NullDriver" )
1327 .append( "<br><br><b><font color=" )
1328 .append( m_sColorRed ).append( ">")
1329 .append( pCommonStrings->getAudioDriverNotPresent() )
1330 .append( "</font></b>" );
1331 }
1332
1333 driverInfoLbl->setText( sInfo );
1334}
1335
1337 auto pPref = H2Core::Preferences::get_instance();
1338
1339 m_pAudioDeviceTxt->setDriver( "OSS" );
1340 m_pAudioDeviceTxt->setIsActive(true);
1341 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sOSSDevice );
1342 bufferSizeSpinBox->setIsActive(true);
1343 sampleRateComboBox->setIsActive(true);
1344 trackOutputComboBox->hide();
1345 trackOutputLbl->hide();
1346 connectDefaultsCheckBox->hide();
1347 enableTimebaseCheckBox->hide();
1348 trackOutsCheckBox->hide();
1349 jackBBTSyncComboBox->hide();
1350 jackBBTSyncLbl->hide();
1351 portaudioHostAPIComboBox->hide();
1352 portaudioHostAPILabel->hide();
1353 latencyTargetLabel->hide();
1354 latencyTargetSpinBox->hide();
1355 latencyValueLabel->hide();
1356
1357 bufferSizeSpinBox->setToolTip( "" );
1358 sampleRateComboBox->setToolTip( "" );
1359}
1360
1362 auto pPref = H2Core::Preferences::get_instance();
1363
1364 m_pAudioDeviceTxt->setDriver( "ALSA" );
1365 m_pAudioDeviceTxt->setIsActive(true);
1366 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sAlsaAudioDevice );
1367 bufferSizeSpinBox->setIsActive(true);
1368 sampleRateComboBox->setIsActive(true);
1369 trackOutputComboBox->hide();
1370 trackOutputLbl->hide();
1371 connectDefaultsCheckBox->hide();
1372 enableTimebaseCheckBox->hide();
1373 trackOutsCheckBox->hide();
1374 jackBBTSyncComboBox->hide();
1375 jackBBTSyncLbl->hide();
1376 portaudioHostAPIComboBox->hide();
1377 portaudioHostAPILabel->hide();
1378 latencyTargetLabel->hide();
1379 latencyTargetSpinBox->hide();
1380 latencyValueLabel->hide();
1381
1382 bufferSizeSpinBox->setToolTip( "" );
1383 sampleRateComboBox->setToolTip( "" );
1384}
1385
1387 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1388
1389 m_pAudioDeviceTxt->setDriver( "JACK" );
1390 m_pAudioDeviceTxt->setIsActive(false);
1391 m_pAudioDeviceTxt->lineEdit()->setText( "" );
1392 bufferSizeSpinBox->setIsActive(false);
1393 sampleRateComboBox->setIsActive(false);
1394 trackOutputComboBox->setIsActive( true );
1395 connectDefaultsCheckBox->setEnabled( true );
1396 enableTimebaseCheckBox->setEnabled( true );
1397 trackOutsCheckBox->setEnabled( true );
1398 jackBBTSyncComboBox->setIsActive( true );
1399 jackBBTSyncLbl->setEnabled( true );
1400 trackOutputComboBox->show();
1401 trackOutputLbl->show();
1402 connectDefaultsCheckBox->show();
1403 enableTimebaseCheckBox->show();
1404 trackOutsCheckBox->show();
1405 jackBBTSyncComboBox->show();
1406 jackBBTSyncLbl->show();
1407 portaudioHostAPIComboBox->hide();
1408 portaudioHostAPILabel->hide();
1409 latencyTargetLabel->hide();
1410 latencyTargetSpinBox->hide();
1411 latencyValueLabel->hide();
1412
1413 bufferSizeSpinBox->setToolTip( pCommonStrings->getPreferencesJackTooltip() );
1414 sampleRateComboBox->setToolTip( pCommonStrings->getPreferencesJackTooltip() );
1415}
1416
1418 auto pPref = H2Core::Preferences::get_instance();
1419
1420 m_pAudioDeviceTxt->setDriver( "CoreAudio" );
1421 m_pAudioDeviceTxt->setIsActive( true );
1422 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sCoreAudioDevice );
1423 bufferSizeSpinBox->setIsActive( true );
1424 sampleRateComboBox->setIsActive(true);
1425 trackOutputComboBox->hide();
1426 trackOutputLbl->hide();
1427 connectDefaultsCheckBox->hide();
1428 enableTimebaseCheckBox->hide();
1429 trackOutsCheckBox->hide();
1430 jackBBTSyncComboBox->hide();
1431 jackBBTSyncLbl->hide();
1432 portaudioHostAPIComboBox->hide();
1433 portaudioHostAPILabel->hide();
1434 latencyTargetLabel->hide();
1435 latencyTargetSpinBox->hide();
1436 latencyValueLabel->hide();
1437
1438 bufferSizeSpinBox->setToolTip( "" );
1439 sampleRateComboBox->setToolTip( "" );
1440}
1441
1443 auto pPref = H2Core::Preferences::get_instance();
1444
1445 m_pAudioDeviceTxt->setDriver( "PortAudio" );
1446 m_pAudioDeviceTxt->setIsActive( true );
1447 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sPortAudioDevice );
1448 bufferSizeSpinBox->setIsActive(false);
1449 sampleRateComboBox->setIsActive(true);
1450 trackOutputComboBox->hide();
1451 trackOutputLbl->hide();
1452 connectDefaultsCheckBox->hide();
1453 enableTimebaseCheckBox->hide();
1454 trackOutsCheckBox->hide();
1455 jackBBTSyncComboBox->hide();
1456 jackBBTSyncLbl->hide();
1457 portaudioHostAPIComboBox->show();
1458 portaudioHostAPILabel->show();
1459 latencyTargetLabel->show();
1460 latencyTargetSpinBox->show();
1461 latencyValueLabel->show();
1462
1463 const auto pAudioDriver = H2Core::Hydrogen::get_instance()->getAudioOutput();
1464 int nLatency;
1465 if ( pAudioDriver == nullptr ) {
1466 ERRORLOG( "AudioDriver is not ready!" );
1467 return;
1468 }
1469 else {
1470 nLatency = pAudioDriver->getLatency();
1471 }
1472 latencyValueLabel->setText( QString("Current: %1 frames").arg( nLatency ) );
1473
1474 bufferSizeSpinBox->setToolTip( "" );
1475 sampleRateComboBox->setToolTip( "" );
1476}
1477
1479
1480 m_pAudioDeviceTxt->setDriver( "PulseAudio" );
1481 m_pAudioDeviceTxt->setIsActive(false);
1482 m_pAudioDeviceTxt->lineEdit()->setText("");
1483 bufferSizeSpinBox->setIsActive(true);
1484 sampleRateComboBox->setIsActive(true);
1485 trackOutputComboBox->hide();
1486 trackOutputLbl->hide();
1487 connectDefaultsCheckBox->hide();
1488 enableTimebaseCheckBox->hide();
1489 trackOutsCheckBox->hide();
1490 jackBBTSyncComboBox->hide();
1491 jackBBTSyncLbl->hide();
1492 portaudioHostAPIComboBox->hide();
1493 portaudioHostAPILabel->hide();
1494 latencyTargetLabel->hide();
1495 latencyTargetSpinBox->hide();
1496 latencyValueLabel->hide();
1497
1498 bufferSizeSpinBox->setToolTip( "" );
1499 sampleRateComboBox->setToolTip( "" );
1500}
1501
1503 auto pPref = Preferences::get_instance();
1504
1505 m_pCurrentTheme->getFontTheme()->m_sApplicationFontFamily = font.family();
1506 pPref->setApplicationFontFamily( font.family() );
1507
1508 m_changes =
1509 static_cast<H2Core::Preferences::Changes>(
1511
1513}
1514
1516 auto pPref = Preferences::get_instance();
1517
1518 m_pCurrentTheme->getFontTheme()->m_sLevel2FontFamily = font.family();
1519 pPref->setLevel2FontFamily( font.family() );
1520
1521 m_changes =
1522 static_cast<H2Core::Preferences::Changes>(
1524
1526}
1527
1529 auto pPref = Preferences::get_instance();
1530
1531 m_pCurrentTheme->getFontTheme()->m_sLevel3FontFamily = font.family();
1532 pPref->setLevel3FontFamily( font.family() );
1533
1534 m_changes =
1535 static_cast<H2Core::Preferences::Changes>(
1537
1539}
1540
1547
1549 auto pPref = Preferences::get_instance();
1550
1551 switch ( nIndex ) {
1552 case 0:
1553 pPref->setFontSize( FontTheme::FontSize::Small );
1554 m_pCurrentTheme->getFontTheme()->m_fontSize = FontTheme::FontSize::Small;
1555 break;
1556 case 1:
1557 pPref->setFontSize( FontTheme::FontSize::Medium );
1558 m_pCurrentTheme->getFontTheme()->m_fontSize = FontTheme::FontSize::Medium;
1559 break;
1560 case 2:
1561 pPref->setFontSize( FontTheme::FontSize::Large );
1562 m_pCurrentTheme->getFontTheme()->m_fontSize = FontTheme::FontSize::Large;
1563 break;
1564 default:
1565 ERRORLOG( QString( "Unknown font size: %1" ).arg( nIndex ) );
1566 }
1567
1568 m_changes =
1569 static_cast<H2Core::Preferences::Changes>(
1571
1573}
1574
1576 if ( static_cast<InterfaceTheme::Layout>(nIndex) !=
1577 m_pPreviousTheme->getInterfaceTheme()->m_layout ||
1578 m_pCurrentTheme->getInterfaceTheme()->m_scalingPolicy !=
1579 m_pPreviousTheme->getInterfaceTheme()->m_scalingPolicy ) {
1580 UIChangeWarningLabel->show();
1581 INFOLOG( "hosw" );
1582 } else {
1583 INFOLOG( "hide" );
1584 UIChangeWarningLabel->hide();
1585 }
1586 m_pCurrentTheme->getInterfaceTheme()->m_layout = static_cast<InterfaceTheme::Layout>(nIndex);
1588
1589 m_changes =
1590 static_cast<H2Core::Preferences::Changes>(
1592
1594}
1595
1597 if ( static_cast<InterfaceTheme::ScalingPolicy>(nIndex) !=
1598 m_pPreviousTheme->getInterfaceTheme()->m_scalingPolicy ||
1599 m_pCurrentTheme->getInterfaceTheme()->m_layout !=
1600 m_pPreviousTheme->getInterfaceTheme()->m_layout ) {
1601 UIChangeWarningLabel->show();
1602 INFOLOG( "hosw" );
1603 } else {
1604 INFOLOG( "hide" );
1605 UIChangeWarningLabel->hide();
1606 }
1607 m_pCurrentTheme->getInterfaceTheme()->m_scalingPolicy = static_cast<InterfaceTheme::ScalingPolicy>(nIndex);
1609
1610 m_changes =
1611 static_cast<H2Core::Preferences::Changes>(
1613
1615}
1616
1627
1630 m_pCurrentTheme->getInterfaceTheme()->m_nVisiblePatternColors = nIndex;
1631 for ( int ii = 0; ii < Preferences::get_instance()->getMaxPatternColors(); ii++ ) {
1632 if ( ii < nIndex ) {
1633 m_colorSelectionButtons[ ii ]->show();
1634 } else {
1635 m_colorSelectionButtons[ ii ]->hide();
1636 }
1637 }
1638
1639 m_changes =
1640 static_cast<H2Core::Preferences::Changes>(
1642
1644}
1645
1647 int nMaxPatternColors = Preferences::get_instance()->getMaxPatternColors();
1648 std::vector<QColor> colors( nMaxPatternColors );
1649 for ( int ii = 0; ii < nMaxPatternColors; ii++ ) {
1650 colors[ ii ] = m_colorSelectionButtons[ ii ]->getColor();
1651 }
1652 m_pCurrentTheme->getInterfaceTheme()->m_patternColors = colors;
1654
1655 m_changes =
1656 static_cast<H2Core::Preferences::Changes>(
1658
1660}
1661
1663 m_pCurrentTheme->getInterfaceTheme()->m_coloringMethod = static_cast<H2Core::InterfaceTheme::ColoringMethod>(nIndex);
1665
1666 if ( nIndex == 0 ) {
1667 coloringMethodAuxSpinBox->hide();
1668 coloringMethodAuxLabel->hide();
1669 colorSelectionLabel->hide();
1670 for ( int ii = 0; ii < m_pCurrentTheme->getInterfaceTheme()->m_nMaxPatternColors; ii++ ) {
1671 m_colorSelectionButtons[ ii ]->hide();
1672 }
1673 } else {
1674 coloringMethodAuxSpinBox->show();
1675 coloringMethodAuxLabel->show();
1676 colorSelectionLabel->show();
1677 for ( int ii = 0; ii < m_pCurrentTheme->getInterfaceTheme()->m_nVisiblePatternColors; ii++ ) {
1678 m_colorSelectionButtons[ ii ]->show();
1679 }
1680 }
1681
1682 m_changes =
1683 static_cast<H2Core::Preferences::Changes>(
1685
1687}
1688
1691
1692 if ( nIndex == 0 ) {
1695 } else if ( nIndex == 1 ) {
1698 } else if ( nIndex == 2 ) {
1701 } else {
1702 ERRORLOG( QString("Wrong mixerFalloff value = %1").arg( nIndex ) );
1703 }
1704
1705 m_changes =
1706 static_cast<H2Core::Preferences::Changes>(
1708
1710}
1711
1717
1719{
1720 UNUSED( i );
1721 m_bNeedDriverRestart = true;
1722}
1723
1724
1725
1726
1731
1732
1733
1735{
1736 QApplication::setOverrideCursor( Qt::WaitCursor );
1737
1740 auto pHydrogen = Hydrogen::get_instance();
1741 pHydrogen->restartDrivers();
1742
1743 QApplication::restoreOverrideCursor();
1744
1745 if ( pHydrogen->getAudioOutput() == nullptr ||
1746 dynamic_cast<NullDriver*>(pHydrogen->getAudioOutput()) != nullptr ) {
1747 QMessageBox::critical( this, "Hydrogen",
1748 tr( "Unable to start audio driver" ) );
1749 }
1750
1751 pPref->savePreferences();
1752 m_bNeedDriverRestart = false;
1754}
1755
1757{
1758 UNUSED( index );
1759 m_bNeedDriverRestart = true;
1760}
1761
1763{
1764 UNUSED( index );
1765 m_bNeedDriverRestart = true;
1766}
1767
1769{
1770 UNUSED( index );
1771
1772 QString sStyle = styleComboBox->currentText();
1773 if ( sStyle != m_pCurrentTheme->getInterfaceTheme()->m_sQTStyle ) {
1774
1775 // Instant visual feedback.
1776 QApplication *pQApp = (HydrogenApp::get_instance())->getMainForm()->m_pQApp;
1777 pQApp->setStyle( sStyle );
1779 pPref->setQTStyle( sStyle );
1780
1781 m_pCurrentTheme->getInterfaceTheme()->m_sQTStyle = sStyle;
1782
1783 m_changes =
1784 static_cast<H2Core::Preferences::Changes>(
1786
1788 }
1789}
1790
1791
1792
1794{
1795 if ( useLashCheckbox->isChecked() ){
1797 }
1798 else
1799 {
1801 }
1802 QMessageBox::information ( this, "Hydrogen", tr ( "Please restart hydrogen to enable/disable LASH support" ) );
1803}
1804
1809
1814
1816{
1817 if ( toggled ) {
1818 enableOscFeedbackCheckbox->show();
1819 incomingOscPortSpinBox->show();
1820 incomingOscPortLabel->show();
1821 if ( Preferences::get_instance()->m_nOscTemporaryPort != -1 ) {
1822 oscTemporaryPortLabel->show();
1823 oscTemporaryPort->show();
1824 }
1825 } else {
1826 enableOscFeedbackCheckbox->hide();
1827 incomingOscPortSpinBox->hide();
1828 incomingOscPortLabel->hide();
1829 oscTemporaryPortLabel->hide();
1830 oscTemporaryPort->hide();
1831 }
1832}
1833
1834QColor* PreferencesDialog::getColorById( int nId, std::shared_ptr<H2Core::ColorTheme> pColorTheme ) const {
1835 switch( nId ) {
1836 case 0x100: return &pColorTheme->m_windowColor;
1837 case 0x101: return &pColorTheme->m_windowTextColor;
1838 case 0x102: return &pColorTheme->m_baseColor;
1839 case 0x103: return &pColorTheme->m_alternateBaseColor;
1840 case 0x104: return &pColorTheme->m_textColor;
1841 case 0x105: return &pColorTheme->m_buttonColor;
1842 case 0x106: return &pColorTheme->m_buttonTextColor;
1843 case 0x107: return &pColorTheme->m_lightColor;
1844 case 0x108: return &pColorTheme->m_midLightColor;
1845 case 0x109: return &pColorTheme->m_midColor;
1846 case 0x10a: return &pColorTheme->m_darkColor;
1847 case 0x10b: return &pColorTheme->m_shadowTextColor;
1848 case 0x10c: return &pColorTheme->m_highlightColor;
1849 case 0x10d: return &pColorTheme->m_highlightedTextColor;
1850 case 0x10e: return &pColorTheme->m_selectionHighlightColor;
1851 case 0x10f: return &pColorTheme->m_selectionInactiveColor;
1852 case 0x110: return &pColorTheme->m_toolTipBaseColor;
1853 case 0x111: return &pColorTheme->m_toolTipTextColor;
1854 case 0x200: return &pColorTheme->m_widgetColor;
1855 case 0x201: return &pColorTheme->m_widgetTextColor;
1856 case 0x202: return &pColorTheme->m_accentColor;
1857 case 0x203: return &pColorTheme->m_accentTextColor;
1858 case 0x204: return &pColorTheme->m_buttonRedColor;
1859 case 0x205: return &pColorTheme->m_buttonRedTextColor;
1860 case 0x206: return &pColorTheme->m_spinBoxColor;
1861 case 0x207: return &pColorTheme->m_spinBoxTextColor;
1862 case 0x208: return &pColorTheme->m_playheadColor;
1863 case 0x209: return &pColorTheme->m_cursorColor;
1864 case 0x300: return &pColorTheme->m_songEditor_backgroundColor;
1865 case 0x301: return &pColorTheme->m_songEditor_alternateRowColor;
1866 case 0x302: return &pColorTheme->m_songEditor_virtualRowColor;
1867 case 0x303: return &pColorTheme->m_songEditor_selectedRowColor;
1868 case 0x304: return &pColorTheme->m_songEditor_selectedRowTextColor;
1869 case 0x305: return &pColorTheme->m_songEditor_lineColor;
1870 case 0x306: return &pColorTheme->m_songEditor_textColor;
1871 case 0x307: return &pColorTheme->m_songEditor_automationBackgroundColor;
1872 case 0x308: return &pColorTheme->m_songEditor_automationLineColor;
1873 case 0x309: return &pColorTheme->m_songEditor_automationNodeColor;
1874 case 0x30a: return &pColorTheme->m_songEditor_stackedModeOnColor;
1875 case 0x30b: return &pColorTheme->m_songEditor_stackedModeOnNextColor;
1876 case 0x30c: return &pColorTheme->m_songEditor_stackedModeOffNextColor;
1877 case 0x400: return &pColorTheme->m_patternEditor_backgroundColor;
1878 case 0x401: return &pColorTheme->m_patternEditor_alternateRowColor;
1879 case 0x402: return &pColorTheme->m_patternEditor_selectedRowColor;
1880 case 0x403: return &pColorTheme->m_patternEditor_selectedRowTextColor;
1881 case 0x404: return &pColorTheme->m_patternEditor_octaveRowColor;
1882 case 0x405: return &pColorTheme->m_patternEditor_textColor;
1883 case 0x406: return &pColorTheme->m_patternEditor_noteVelocityFullColor;
1884 case 0x407: return &pColorTheme->m_patternEditor_noteVelocityDefaultColor;
1885 case 0x408: return &pColorTheme->m_patternEditor_noteVelocityHalfColor;
1886 case 0x409: return &pColorTheme->m_patternEditor_noteVelocityZeroColor;
1887 case 0x40a: return &pColorTheme->m_patternEditor_noteOffColor;
1888 case 0x40b: return &pColorTheme->m_patternEditor_lineColor;
1889 case 0x40c: return &pColorTheme->m_patternEditor_line1Color;
1890 case 0x40d: return &pColorTheme->m_patternEditor_line2Color;
1891 case 0x40e: return &pColorTheme->m_patternEditor_line3Color;
1892 case 0x40f: return &pColorTheme->m_patternEditor_line4Color;
1893 case 0x410: return &pColorTheme->m_patternEditor_line5Color;
1894 default: return nullptr;
1895 }
1896
1897 return nullptr;
1898}
1899
1900void PreferencesDialog::setColorById( int nId, const QColor& color,
1901 std::shared_ptr<H2Core::ColorTheme> pColorTheme ) {
1902 switch( nId ) {
1903 case 0x100: pColorTheme->m_windowColor = color;
1904 break;
1905 case 0x101: pColorTheme->m_windowTextColor = color;
1906 break;
1907 case 0x102: pColorTheme->m_baseColor = color;
1908 break;
1909 case 0x103: pColorTheme->m_alternateBaseColor = color;
1910 break;
1911 case 0x104: pColorTheme->m_textColor = color;
1912 break;
1913 case 0x105: pColorTheme->m_buttonColor = color;
1914 break;
1915 case 0x106: pColorTheme->m_buttonTextColor = color;
1916 break;
1917 case 0x107: pColorTheme->m_lightColor = color;
1918 break;
1919 case 0x108: pColorTheme->m_midLightColor = color;
1920 break;
1921 case 0x109: pColorTheme->m_midColor = color;
1922 break;
1923 case 0x10a: pColorTheme->m_darkColor = color;
1924 break;
1925 case 0x10b: pColorTheme->m_shadowTextColor = color;
1926 break;
1927 case 0x10c: pColorTheme->m_highlightColor = color;
1928 break;
1929 case 0x10d: pColorTheme->m_highlightedTextColor = color;
1930 break;
1931 case 0x10e: pColorTheme->m_selectionHighlightColor = color;
1932 break;
1933 case 0x10f: pColorTheme->m_selectionInactiveColor = color;
1934 break;
1935 case 0x110: pColorTheme->m_toolTipBaseColor = color;
1936 break;
1937 case 0x111: pColorTheme->m_toolTipTextColor = color;
1938 break;
1939 case 0x200: pColorTheme->m_widgetColor = color;
1940 break;
1941 case 0x201: pColorTheme->m_widgetTextColor = color;
1942 break;
1943 case 0x202: pColorTheme->m_accentColor = color;
1944 break;
1945 case 0x203: pColorTheme->m_accentTextColor = color;
1946 break;
1947 case 0x204: pColorTheme->m_buttonRedColor = color;
1948 break;
1949 case 0x205: pColorTheme->m_buttonRedTextColor = color;
1950 break;
1951 case 0x206: pColorTheme->m_spinBoxColor = color;
1952 break;
1953 case 0x207: pColorTheme->m_spinBoxTextColor = color;
1954 break;
1955 case 0x208: pColorTheme->m_playheadColor = color;
1956 break;
1957 case 0x209: pColorTheme->m_cursorColor = color;
1958 break;
1959 case 0x300: pColorTheme->m_songEditor_backgroundColor = color;
1960 break;
1961 case 0x301: pColorTheme->m_songEditor_alternateRowColor = color;
1962 break;
1963 case 0x302: pColorTheme->m_songEditor_virtualRowColor = color;
1964 break;
1965 case 0x303: pColorTheme->m_songEditor_selectedRowColor = color;
1966 break;
1967 case 0x304: pColorTheme->m_songEditor_selectedRowTextColor = color;
1968 break;
1969 case 0x305: pColorTheme->m_songEditor_lineColor = color;
1970 break;
1971 case 0x306: pColorTheme->m_songEditor_textColor = color;
1972 break;
1973 case 0x307: pColorTheme->m_songEditor_automationBackgroundColor = color;
1974 break;
1975 case 0x308: pColorTheme->m_songEditor_automationLineColor = color;
1976 break;
1977 case 0x309: pColorTheme->m_songEditor_automationNodeColor = color;
1978 break;
1979 case 0x30a: pColorTheme->m_songEditor_stackedModeOnColor = color;
1980 break;
1981 case 0x30b: pColorTheme->m_songEditor_stackedModeOnNextColor = color;
1982 break;
1983 case 0x30c: pColorTheme->m_songEditor_stackedModeOffNextColor = color;
1984 break;
1985 case 0x400: pColorTheme->m_patternEditor_backgroundColor = color;
1986 break;
1987 case 0x401: pColorTheme->m_patternEditor_alternateRowColor = color;
1988 break;
1989 case 0x402: pColorTheme->m_patternEditor_selectedRowColor = color;
1990 break;
1991 case 0x403: pColorTheme->m_patternEditor_selectedRowTextColor = color;
1992 break;
1993 case 0x404: pColorTheme->m_patternEditor_octaveRowColor = color;
1994 break;
1995 case 0x405: pColorTheme->m_patternEditor_textColor = color;
1996 break;
1997 case 0x406: pColorTheme->m_patternEditor_noteVelocityFullColor = color;
1998 break;
1999 case 0x407: pColorTheme->m_patternEditor_noteVelocityDefaultColor = color;
2000 break;
2001 case 0x408: pColorTheme->m_patternEditor_noteVelocityHalfColor = color;
2002 break;
2003 case 0x409: pColorTheme->m_patternEditor_noteVelocityZeroColor = color;
2004 break;
2005 case 0x40a: pColorTheme->m_patternEditor_noteOffColor = color;
2006 break;
2007 case 0x40b: pColorTheme->m_patternEditor_lineColor = color;
2008 break;
2009 case 0x40c: pColorTheme->m_patternEditor_line1Color = color;
2010 break;
2011 case 0x40d: pColorTheme->m_patternEditor_line2Color = color;
2012 break;
2013 case 0x40e: pColorTheme->m_patternEditor_line3Color = color;
2014 break;
2015 case 0x40f: pColorTheme->m_patternEditor_line4Color = color;
2016 break;
2017 case 0x410: pColorTheme->m_patternEditor_line5Color = color;
2018 break;
2019 default: DEBUGLOG( "Unknown ID" );
2020 }
2021}
2022
2024 if( pItem == nullptr) {
2025 ERRORLOG( "NULL item" );
2026 return;
2027 }
2028
2029 int nId = pItem->getId();
2030 if( nId == 0 ) {
2031 // Node without a color used as a heading.
2032 return;
2033 }
2034
2035 QColor* pCurrentColor = getColorById( nId, m_pCurrentTheme->getColorTheme() );
2036 if ( pCurrentColor == nullptr ) {
2037 ERRORLOG( QString( "Unable to get current color for id [%1]" ).arg( nId ) );
2038 return;
2039 }
2040 QColor* pPreviousColor = getColorById( nId, m_pPreviousTheme->getColorTheme() );
2041 if ( pPreviousColor == nullptr ) {
2042 ERRORLOG( QString( "Unable to get previous color for id [%1]" ).arg( nId ) );
2043 return;
2044 }
2045
2046 const QColor& currentColor = *pCurrentColor;
2047 const QColor& previousColor = *pPreviousColor;
2048
2049 QFont font = pItem->font( 0 );
2050 font.setWeight( currentColor != previousColor ? QFont::Black : QFont::Normal );
2051 font.setItalic( currentColor != previousColor );
2052 pItem->setFont( 0, font );
2053 pItem->setData( 0, Qt::DecorationRole, currentColor );
2054}
2055
2057 QTreeWidgetItemIterator it( colorTree );
2058 while ( *it ) {
2059 setColorTreeItemDirty( static_cast<ColorTreeItem*>( *it ) );
2060 ++it;
2061 }
2062}
2063
2065 ColorTreeItem* pItem = static_cast<ColorTreeItem*>(colorTree->selectedItems()[0]);
2066
2067 if( pItem == nullptr ) {
2068 // Unset title
2069 m_pCurrentColor = nullptr;
2070 updateColors();
2071 return;
2072 }
2073
2074 int nId = static_cast<ColorTreeItem*>(pItem)->getId();
2075 m_nCurrentId = nId;
2076
2077 if ( nId == 0x000 ) {
2078 // A text node without color was clicked.
2079 m_pCurrentColor = nullptr;
2080 } else {
2082 }
2083 updateColors();
2084}
2085
2091
2093 int r, g, b, h, s, v;
2094
2095 // If m_pCurrentColor is nullptr, it will be converted to false.
2096 rslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2097 gslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2098 bslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2099 hslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2100 sslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2101 vslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2102 rval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2103 gval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2104 bval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2105 hval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2106 sval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2107 vval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2108 colorButton->setEnabled( static_cast<bool>(m_pCurrentColor) );
2109 if ( m_pCurrentColor == nullptr ) {
2110 DEBUGLOG( "No current color yet" );
2111 return;
2112 }
2113
2114 QColor currentColor(*m_pCurrentColor);
2115
2116 colorButton->setColor( currentColor );
2117
2118 m_pCurrentColor->getRgb(&r, &g, &b);
2119 m_pCurrentColor->getHsv(&h, &s, &v);
2120
2121 rslider->blockSignals(true);
2122 gslider->blockSignals(true);
2123 bslider->blockSignals(true);
2124 hslider->blockSignals(true);
2125 sslider->blockSignals(true);
2126 vslider->blockSignals(true);
2127 rval->blockSignals(true);
2128 gval->blockSignals(true);
2129 bval->blockSignals(true);
2130 hval->blockSignals(true);
2131 sval->blockSignals(true);
2132 vval->blockSignals(true);
2133
2134 rslider->setValue(r);
2135 gslider->setValue(g);
2136 bslider->setValue(b);
2137 hslider->setValue(h);
2138 sslider->setValue(s);
2139 vslider->setValue(v);
2140 rval->setValue(r);
2141 gval->setValue(g);
2142 bval->setValue(b);
2143 hval->setValue(h);
2144 sval->setValue(s);
2145 vval->setValue(v);
2146
2147 rslider->blockSignals(false);
2148 gslider->blockSignals(false);
2149 bslider->blockSignals(false);
2150 hslider->blockSignals(false);
2151 sslider->blockSignals(false);
2152 vslider->blockSignals(false);
2153 rval->blockSignals(false);
2154 gval->blockSignals(false);
2155 bval->blockSignals(false);
2156 hval->blockSignals(false);
2157 sval->blockSignals(false);
2158 vval->blockSignals(false);
2159
2162
2163 m_changes =
2164 static_cast<H2Core::Preferences::Changes>(
2166
2168}
2169
2171 if ( m_pColorSliderTimer->isActive() ) {
2172 m_pColorSliderTimer->stop();
2173 }
2174 m_pColorSliderTimer->start( 25 );
2175}
2176
2178 int r, g, b;
2179 if ( m_pCurrentColor != nullptr ) {
2180 m_pCurrentColor->getRgb( &r, &g, &b );
2181 m_pCurrentColor->setRgb( nValue, g, b );
2182 }
2184}
2185
2187 int r, g, b;
2188 if ( m_pCurrentColor != nullptr ) {
2189 m_pCurrentColor->getRgb( &r, &g, &b );
2190 m_pCurrentColor->setRgb( r, nValue, b );
2191 }
2193}
2194
2196 int r, g, b;
2197 if ( m_pCurrentColor != nullptr ) {
2198 m_pCurrentColor->getRgb( &r, &g, &b );
2199 m_pCurrentColor->setRgb( r, g, nValue );
2200 }
2202}
2203
2205 int h, s, v;
2206 if ( m_pCurrentColor != nullptr ) {
2207 m_pCurrentColor->getHsv( &h, &s, &v );
2208 m_pCurrentColor->setHsv( nValue, s, v );
2209 }
2211}
2212
2214 int h, s, v;
2215 if ( m_pCurrentColor != nullptr ) {
2216 m_pCurrentColor->getHsv( &h, &s, &v );
2217 m_pCurrentColor->setHsv( h, nValue, v );
2218 }
2220}
2221
2223 int h, s, v;
2224 if ( m_pCurrentColor != nullptr ) {
2225 m_pCurrentColor->getHsv( &h, &s, &v );
2226 m_pCurrentColor->setHsv( h, s, nValue );
2227 }
2229}
2230
2233 if ( ! H2Core::Filesystem::dir_readable( sPath, false ) ){
2234 sPath = Filesystem::sys_theme_dir();
2235 }
2236
2237 QString sTitle = tr( "Import Theme" );
2238 FileDialog fd( this );
2239 fd.setWindowTitle( sTitle );
2240 fd.setDirectory( sPath );
2241 fd.setFileMode( QFileDialog::ExistingFile );
2242 fd.setNameFilter( Filesystem::themes_filter_name );
2243 fd.setAcceptMode( QFileDialog::AcceptOpen );
2244 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::sys_theme_dir() ) );
2245 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::usr_theme_dir() ) );
2246 fd.setDefaultSuffix( Filesystem::themes_ext );
2247
2248 if ( fd.exec() != QDialog::Accepted ) {
2249 return;
2250 }
2251
2252 QFileInfo fileInfo = fd.selectedFiles().first();
2253 QString sSelectedPath = fileInfo.absoluteFilePath();
2254 H2Core::Preferences::get_instance()->setLastImportThemeDirectory( fd.directory().absolutePath() );
2255
2256 if ( sSelectedPath.isEmpty() ) {
2257 QMessageBox::warning( this, "Hydrogen", tr("Theme couldn't be found.") );
2258 return;
2259 }
2260
2261 auto pTheme = Theme::importTheme( sSelectedPath );
2262 m_pCurrentTheme = std::make_shared<Theme>( pTheme );
2264 if ( m_nCurrentId == 0 ) {
2265 m_pCurrentColor = nullptr;
2268
2269 m_changes =
2270 static_cast<H2Core::Preferences::Changes>(
2272
2274 }
2276
2277 HydrogenApp::get_instance()->showStatusBarMessage( tr( "Theme imported from " ) + sSelectedPath );
2278
2279 m_changes =
2280 static_cast<H2Core::Preferences::Changes>(
2282
2284
2285}
2286
2289 if ( ! H2Core::Filesystem::dir_writable( sPath, false ) ){
2290 sPath = Filesystem::usr_theme_dir();
2291 }
2292 QString sTitle = tr( "Export Theme" );
2293 FileDialog fd( this );
2294 fd.setWindowTitle( sTitle );
2295 fd.setDirectory( sPath );
2296 fd.setFileMode( QFileDialog::AnyFile );
2297 fd.setNameFilter( Filesystem::themes_filter_name );
2298 fd.setAcceptMode( QFileDialog::AcceptSave );
2299 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::sys_theme_dir() ) );
2300 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::usr_theme_dir() ) );
2301 fd.setDefaultSuffix( Filesystem::themes_ext );
2302
2303 if ( fd.exec() != QDialog::Accepted ) {
2304 return;
2305 }
2306
2307 QFileInfo fileInfo = fd.selectedFiles().first();
2308 QString sSelectedPath = fileInfo.absoluteFilePath();
2309
2310 if ( sSelectedPath.isEmpty() ||
2311 ! Theme::exportTheme( sSelectedPath, m_pCurrentTheme ) ) {
2312 QMessageBox::warning( this, "Hydrogen", tr("Theme can not be exported.") );
2313 return;
2314 }
2315
2316 H2Core::Preferences::get_instance()->setLastExportThemeDirectory( fd.directory().absolutePath() );
2317
2318 HydrogenApp::get_instance()->showStatusBarMessage( tr( "Theme exported to " ) +
2319 sSelectedPath );
2320
2321}
2322
2332
2333
2334void PreferencesDialog::updateAppearanceTab( const std::shared_ptr<H2Core::Theme> pTheme ) {
2335
2336 // Colors
2337 m_pCurrentColor = getColorById( m_nCurrentId, pTheme->getColorTheme() );
2338 updateColors();
2339
2340 // Interface
2341 float fFalloffSpeed = pTheme->getInterfaceTheme()->m_fMixerFalloffSpeed;
2342 if ( fFalloffSpeed == InterfaceTheme::FALLOFF_SLOW ) {
2343 mixerFalloffComboBox->setCurrentIndex( 0 );
2344 }
2345 else if ( fFalloffSpeed == InterfaceTheme::FALLOFF_NORMAL ) {
2346 mixerFalloffComboBox->setCurrentIndex( 1 );
2347 }
2348 else if ( fFalloffSpeed == InterfaceTheme::FALLOFF_FAST ) {
2349 mixerFalloffComboBox->setCurrentIndex( 2 );
2350 }
2351 else {
2352 ERRORLOG( QString("PreferencesDialog: wrong mixerFalloff value = %1").arg( fFalloffSpeed ) );
2353 }
2354 uiLayoutComboBox->setCurrentIndex( static_cast<int>( pTheme->getInterfaceTheme()->m_layout ) );
2355
2356#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
2357 uiScalingPolicyComboBox->setCurrentIndex( static_cast<int>( pTheme->getInterfaceTheme()->m_scalingPolicy ) );
2358#else
2359 uiScalingPolicyComboBox->setEnabled( false );
2360 uiScalingPolicyLabel->setEnabled( false );
2361#endif
2362
2363 iconColorComboBox->setCurrentIndex( static_cast<int>( pTheme->getInterfaceTheme()->m_iconColor ) );
2364
2365 // Style
2366 QStringList list = QStyleFactory::keys();
2367 uint i = 0;
2368 styleComboBox->clear();
2369 for ( QStringList::Iterator it = list.begin(); it != list.end(); it++) {
2370 styleComboBox->addItem( *it );
2371 QString sStyle = (*it);
2372 if (sStyle == pTheme->getInterfaceTheme()->m_sQTStyle ) {
2373 styleComboBox->setCurrentIndex( i );
2374 HydrogenApp::get_instance()->getMainForm()->m_pQApp->setStyle( sStyle );
2375 }
2376 i++;
2377 }
2378
2379 //SongEditor coloring
2380 int nColoringMethod = static_cast<int>(pTheme->getInterfaceTheme()->m_coloringMethod);
2381 if ( nColoringMethod == 0 ) {
2382 // "Automatic" selected
2383 coloringMethodAuxSpinBox->hide();
2384 colorSelectionLabel->hide();
2385 } else {
2386 coloringMethodAuxSpinBox->show();
2387 colorSelectionLabel->show();
2388 }
2389
2390 coloringMethodCombo->setCurrentIndex( nColoringMethod );
2391 coloringMethodAuxSpinBox->setValue( pTheme->getInterfaceTheme()->m_nVisiblePatternColors );
2392 QSize size( uiScalingPolicyComboBox->width(), coloringMethodAuxSpinBox->height() );
2393
2394 // Ensure the number of color buttons match.
2395 if ( m_colorSelectionButtons.size() !=
2396 pTheme->getInterfaceTheme()->m_nMaxPatternColors ) {
2397
2398 m_colorSelectionButtons.resize( pTheme->getInterfaceTheme()->m_nMaxPatternColors );
2400 int nButtonSize = fontSizeComboBox->height();
2401 // float fLineWidth = static_cast<float>(fontSizeComboBox->width());
2402 // Using a fixed one size resizing of the widget seems to happen
2403 // after the constructor is called.
2404 float fLineWidth = 308;
2405 int nButtonsPerLine = std::floor( fLineWidth / static_cast<float>(nButtonSize + 6) );
2406
2407 colorSelectionGrid->setHorizontalSpacing( 4 );
2408 for ( int ii = 0; ii < pTheme->getInterfaceTheme()->m_nMaxPatternColors; ii++ ) {
2409 ColorSelectionButton* bbutton =
2410 new ColorSelectionButton( this, pTheme->getInterfaceTheme()->m_patternColors[ ii ],
2411 nButtonSize );
2412 bbutton->hide();
2413 connect( bbutton, &ColorSelectionButton::colorChanged, this,
2415 colorSelectionGrid->addWidget( bbutton,
2416 std::floor( static_cast<float>( ii ) /
2417 static_cast<float>( nButtonsPerLine ) ),
2418 (ii % nButtonsPerLine) + 1); //+1 to take the hspace into account.
2419 m_colorSelectionButtons[ ii ] = bbutton;
2420 }
2421 }
2422
2423 // Update their colors.
2424 for ( int ii = 0; ii < m_colorSelectionButtons.size(); ++ii ) {
2425 m_colorSelectionButtons[ ii ]->setColor( pTheme->getInterfaceTheme()->
2426 m_patternColors[ ii ] );
2427 }
2428
2429 // Display only the required number.
2430 if ( nColoringMethod != 0 ) {
2431 for ( int ii = 0; ii < pTheme->getInterfaceTheme()->m_nVisiblePatternColors; ii++ ) {
2432 m_colorSelectionButtons[ ii ]->show();
2433 }
2434 }
2435
2436 // Fonts
2437 applicationFontComboBox->setCurrentFont( QFont( pTheme->getFontTheme()->m_sApplicationFontFamily ) );
2438 level2FontComboBox->setCurrentFont( QFont( pTheme->getFontTheme()->m_sLevel2FontFamily ) );
2439 level3FontComboBox->setCurrentFont( QFont( pTheme->getFontTheme()->m_sLevel3FontFamily ) );
2440 switch( pTheme->getFontTheme()->m_fontSize ) {
2441 case FontTheme::FontSize::Small:
2442 fontSizeComboBox->setCurrentIndex( 0 );
2443 break;
2444 case FontTheme::FontSize::Medium:
2445 fontSizeComboBox->setCurrentIndex( 1 );
2446 break;
2447 case FontTheme::FontSize::Large:
2448 fontSizeComboBox->setCurrentIndex( 2 );
2449 break;
2450 default:
2451 ERRORLOG( QString( "Unknown font size: %1" )
2452 .arg( static_cast<int>( pTheme->getFontTheme()->m_fontSize ) ) );
2453 }
2454}
#define INFOLOG(x)
Definition Object.h:237
#define ERRORLOG(x)
Definition Object.h:239
#define DEBUGLOG(x)
Definition Object.h:236
QPushButton opening a QColorDialog when clicked and displaying the selected color as background - wit...
Node in the Color tree of the appearance tab.
ColorTreeItem(int nId, QTreeWidgetItem *pParent, QString sLabel)
DeviceComboBox(QWidget *pParent)
virtual void showPopup()
Custom file dialog checking whether the user has write access to the selected folder before allowing ...
Definition FileDialog.h:33
static QStringList getDevices()
Use the name hints to build a list of potential device names.
Sampler * getSampler() const
static QStringList getDevices()
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
static bool dir_readable(const QString &path, bool silent=false)
returns true if the given path is a readable regular directory
static const QString themes_ext
Definition Filesystem.h:92
static QString usr_theme_dir()
static bool dir_writable(const QString &path, bool silent=false)
returns true if the given path is a writable regular directory
static const QString themes_filter_name
Definition Filesystem.h:94
static QString sys_theme_dir()
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
AudioOutput * getAudioOutput() const
Used to display audio driver info.
Definition Hydrogen.cpp:719
static float FALLOFF_SLOW
Definition Theme.h:138
static float FALLOFF_NORMAL
Definition Theme.h:139
static float FALLOFF_FAST
Definition Theme.h:140
JACK (Jack Audio Connection Kit) server driver.
OSS Audio Driver.
Definition OssDriver.h:65
static QStringList getDevices()
static QStringList getHostAPIs()
Manager for User Preferences File (singleton)
Definition Preferences.h:78
bool isPlaylistUsingRelativeFilenames()
void setPatternColors(std::vector< QColor > patternColors)
JackTrackOutputMode m_JackTrackOutputMode
Specifies which audio settings will be applied to the sample supplied in the JACK per track output po...
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setQTStyle(const QString &sStyle)
QString m_sAudioDriver
Audio driver.
unsigned m_nSampleRate
Sample rate of the audio.
void setTheme(const std::shared_ptr< Theme > pTheme)
QString m_sPortAudioHostAPI
void setLastImportThemeDirectory(QString sPath)
bool savePreferences()
Save the preferences file.
void setVisiblePatternColors(int nValue)
void setColoringMethod(InterfaceTheme::ColoringMethod coloringMethod)
void setIconColor(InterfaceTheme::IconColor iconColor)
QString m_sMidiOutputPortName
int getMaxPatternColors() const
QString m_sMidiDriver
MIDI driver.
bool isRestoreLastSongEnabled()
bool isRestoreLastPlaylistEnabled()
bool loadPreferences(bool bGlobal)
Load the preferences file.
void setColorTheme(const std::shared_ptr< ColorTheme > pNewColorTheme)
QString getLastImportThemeDirectory() const
const QString & getPreferredLanguage()
bool m_bJackConnectDefaults
Toggles auto-connecting of the main stereo output ports to the system's default ports when starting t...
unsigned m_nMaxNotes
max notes
int getMaxBars() const
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ GeneralTab
Any option in the General tab appeared.
@ AppearanceTab
Any option in the Appearance tab excluding colors, font size, or font family.
@ Font
Either the font size or font family have changed.
@ Colors
At least one of the colors has changed.
@ OscTab
Any option in the OSC tab appeared.
@ MidiTab
Any option in the MIDI tab appeared.
@ AudioTab
Any option in the Audio tab appeared.
bool m_bMidiDiscardNoteAfterAction
QString m_sOSSDevice
Device used for output.
QString getLastExportThemeDirectory() const
int getMaxLayers() const
QString m_rubberBandCLIexecutable
Rubberband CLI.
JackBBTSyncMethod m_JackBBTSync
Since Hydrogen uses both fixed pattern lengths and recalculates the tick size each time it encounters...
void setLastExportThemeDirectory(QString sPath)
bool m_bJackTimebaseEnabled
External applications with a faulty JACK timebase master implementation can mess up the transport wit...
void setDefaultUILayout(InterfaceTheme::Layout layout)
float m_fMetronomeVolume
Metronome volume FIXME: remove this volume!!
void setMixerFalloffSpeed(float value)
int m_nOscTemporaryPort
In case m_nOscServerPort is already occupied by another client, the alternative - random - port numbe...
static QString getNullMidiPort()
Choice of m_sMidiPortName and m_sMidiOutputPortName in case no port/device was selected.
bool m_bJackTrackOuts
If set to true, JackAudioDriver::makeTrackOutputs() will create two individual left and right output ...
unsigned m_nBufferSize
Buffer size of the audio.
void setUIScalingPolicy(InterfaceTheme::ScalingPolicy policy)
void setInterpolateMode(Interpolation::InterpolateMode mode)
Definition Sampler.h:200
static bool exportTheme(const QString &sPath, const std::shared_ptr< Theme > pTheme)
Definition Theme.cpp:725
const std::shared_ptr< FontTheme > getFontTheme() const
Definition Theme.h:235
const std::shared_ptr< ColorTheme > getColorTheme() const
Definition Theme.h:223
static std::shared_ptr< Theme > importTheme(const QString &sPath)
Definition Theme.cpp:616
const std::shared_ptr< InterfaceTheme > getInterfaceTheme() const
Definition Theme.h:229
static QStringList availableTranslations(QString sFileName, QString sDirectory=H2Core::Filesystem::i18n_dir())
static QString findTranslation(QStringList languages, QString sFileName, QString sDirectory=H2Core::Filesystem::i18n_dir())
The standard QTranslation::load will prefer an exact match of a languae-REGION pair,...
HostAPIComboBox(QWidget *pParent)
virtual void showPopup()
void setValue(QString sHostAPI)
MainForm * getMainForm()
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
void showStatusBarMessage(const QString &sMessage, const QString &sCaller="")
void changePreferences(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
virtual void showPopup() override
Definition LCDCombo.cpp:84
void addItem(const QString &text, const QVariant &userData=QVariant())
Definition LCDCombo.cpp:63
QApplication * m_pQApp
Definition MainForm.h:52
The MidiMap maps MidiActions to MidiEvents.
Definition MidiMap.h:38
static MidiMap * get_instance()
Returns a pointer to the current MidiMap singleton stored in __instance.
Definition MidiMap.h:65
static void reset_instance()
Convenience function calling reset() on the current MidiMap __instance.
Definition MidiMap.cpp:71
void changed()
Identicates a user action changing the content of the table.
static QString m_sColorRed
void portaudioHostAPIComboBoxActivated(int index)
void midiPortComboBoxActivated(int index)
void setColorTreeItemDirty(ColorTreeItem *pItem)
void triggerColorSliderTimer()
Introduce a temporal smoothing.
void onUILayoutChanged(int nIndex)
void toggleTrackOutsCheckBox(bool toggled)
void toggleOscCheckBox(bool toggled)
void latencyTargetSpinBoxValueChanged(int i)
void audioDeviceTxtChanged(const QString &)
void mixerFalloffComboBoxCurrentIndexChanged(int)
void onColoringMethodChanged(int nIndex)
void onLevel3FontChanged(const QFont &font)
void bufferSizeSpinBoxValueChanged(int i)
void onLevel2FontChanged(const QFont &font)
void onApplicationFontChanged(const QFont &font)
PreferencesDialog(QWidget *parent)
void onMidiDriverComboBoxIndexChanged(int index)
std::shared_ptr< H2Core::Theme > m_pCurrentTheme
void setColorById(int nId, const QColor &color, std::shared_ptr< H2Core::ColorTheme > uiStyle)
void onFontSizeChanged(int nIndex)
void updateAppearanceTab(const std::shared_ptr< H2Core::Theme > pTheme)
void driverComboBoxActivated(int index)
void uiScalingPolicyComboBoxCurrentIndexChanged(int)
std::vector< ColorSelectionButton * > m_colorSelectionButtons
H2Core::Preferences::Changes m_changes
Stores which part of the dialog was altered.
void styleComboBoxActivated(int index)
void onColorNumberChanged(int nIndex)
void midiOutportComboBoxActivated(int index)
std::shared_ptr< H2Core::Theme > m_pPreviousTheme
void sampleRateComboBoxEditTextChanged(const QString &text)
QColor * getColorById(int nId, std::shared_ptr< H2Core::ColorTheme > uiStyle) const
#define UNUSED(v)
Definition Globals.h:42
@ EVENT_MIDI_MAP_CHANGED
Definition EventQueue.h:178