hydrogen 1.2.6
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-2025 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <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{
63}
64
66{
67 clear();
68 QApplication::setOverrideCursor( Qt::WaitCursor );
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 }
78#ifdef H2CORE_HAVE_COREAUDIO
79 for ( QString s : CoreAudioDriver::getDevices() ) {
80 addItem( s );
81 }
82#endif
83 }
85#ifdef H2CORE_HAVE_ALSA
86 for ( QString s : AlsaAudioDriver::getDevices() ) {
87 addItem( s );
88 }
89#endif
90 }
91 QApplication::restoreOverrideCursor();
93}
94
95
97 : LCDCombo( pParent )
98{
99}
100
101void HostAPIComboBox::setValue( QString sHostAPI ) {
102 // The ComboBox doesn't have any item strings until it's actually opened,
103 // so we must add the item to it temporarily
104 clear();
105 addItem( sHostAPI );
106 setCurrentText( sHostAPI );
107}
108
110{
111 clear();
112#ifdef H2CORE_HAVE_PORTAUDIO
113 QApplication::setOverrideCursor( Qt::WaitCursor );
114 addItems( PortAudioDriver::getHostAPIs() );
115 QApplication::restoreOverrideCursor();
116#endif
117
119}
120
121
122ColorTreeItem::ColorTreeItem( int nId, QTreeWidgetItem* pParent, QString sLabel )
123 : QTreeWidgetItem( pParent, QStringList( sLabel ) ) {
124 m_nId = nId;
125}
126ColorTreeItem::ColorTreeItem( int nId, QTreeWidget* pParent, QString sLabel )
127 : QTreeWidgetItem( pParent, QStringList( sLabel ) ) {
128 m_nId = nId;
129}
131 return m_nId;
132}
133
134QString PreferencesDialog::m_sColorRed = "#ca0003";
135
136
138 : QDialog( parent )
139 , m_pCurrentColor( nullptr )
140 , m_nCurrentId( 0 )
141 , m_changes( H2Core::Preferences::Changes::None )
142 , m_bMidiTableChanged( false ) {
143
144 m_pCurrentTheme = std::make_shared<H2Core::Theme>( H2Core::Preferences::get_instance()->getTheme() );
145 m_pPreviousTheme = std::make_shared<H2Core::Theme>( H2Core::Preferences::get_instance()->getTheme() );
146 setupUi( this );
147
148 setWindowTitle( tr( "Preferences" ) );
149 // Show and enable maximize button. This is key when enlarging the
150 // application using a scaling factor and allows the OS to force its size
151 // beyond the minimum and make the scrollbars appear.
152 setWindowFlags( windowFlags() | Qt::CustomizeWindowHint |
153 Qt::WindowMinMaxButtonsHint );
154
155 connect( this, &PreferencesDialog::rejected, this, &PreferencesDialog::onRejected );
156
158
159 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
160 auto pHydrogen = Hydrogen::get_instance();
161
163 // General tab
164 QSize generalTabWidgetSize( 60, 24 );
165
166 restoreLastUsedSongCheckbox->setChecked( pPref->isRestoreLastSongEnabled() );
167 restoreLastUsedPlaylistCheckbox->setChecked( pPref->isRestoreLastPlaylistEnabled() );
168 useRelativePlaylistPathsCheckbox->setChecked( pPref->isPlaylistUsingRelativeFilenames() );
169 hideKeyboardCursor->setChecked( pPref->hideKeyboardCursor() );
170
171 // General tab - restore the right m_bsetlash value
172 if ( pPref->m_brestartLash == true ){
173 if (pPref->m_bsetLash == false ){
174 pPref->m_bsetLash = true ;
175 pPref->m_brestartLash = false;
176 }
177
178 }
179 useLashCheckbox->setChecked( pPref->m_bsetLash );
180
181 sBcountOffset->setSize( generalTabWidgetSize );
182 sBcountOffset->setValue( pPref->m_countOffset );
183 sBstartOffset->setSize( generalTabWidgetSize );
184 sBstartOffset->setValue( pPref->m_startOffset );
185
186 sBmaxBars->setSize( generalTabWidgetSize );
187 sBmaxBars->setValue( pPref->getMaxBars() );
188 sBmaxLayers->setSize( generalTabWidgetSize );
189 sBmaxLayers->setValue( pPref->getMaxLayers() );
190 autosaveSpinBox->setSize( generalTabWidgetSize );
191 autosaveSpinBox->setValue( pPref->m_nAutosavesPerHour );
192
193 QString pathtoRubberband = pPref->m_rubberBandCLIexecutable;
194 rubberbandLineEdit->setText( pathtoRubberband );
195
196#ifdef H2CORE_HAVE_RUBBERBAND
197 pathToRubberbandExLable->hide();
198 rubberbandLineEdit->hide();
199#endif
200
201 // General tab - Language selection menu
202 languageComboBox->setSize( QSize( 310, 24 ) );
203 for ( QString sLang : Translations::availableTranslations( "hydrogen" ) ) {
204 QLocale loc( sLang );
205 QString sLabel = loc.nativeLanguageName() + " (" + loc.nativeCountryName() + ')';
206 languageComboBox->addItem( sLabel, QVariant( sLang ) );
207 }
208 // General tab - Find preferred language and select that in menu
209 QStringList languages;
210 QString sPreferredLanguage = pPref->getPreferredLanguage();
211 if ( !sPreferredLanguage.isNull() ) {
212 languages << sPreferredLanguage;
213 }
214 languages << QLocale::system().uiLanguages();
215 QString sLanguage = Translations::findTranslation( languages, "hydrogen" );
216 m_sInitialLanguage = sLanguage;
217 int nLanguage = languageComboBox->findData( QVariant( sLanguage ) );
218 if ( nLanguage != -1 ) {
219 languageComboBox->setCurrentIndex( nLanguage );
220 }
221
223 // Audio tab
224
225 // For everything above the restart button
226 QSize audioTabWidgetSizeTop( 240, 24 );
227 // and everything below
228 QSize audioTabWidgetSizeBottom( 184, 24 );
229
230 driverComboBox->setSize( audioTabWidgetSizeTop );
231 driverComboBox->clear();
232 driverComboBox->addItem(
234 for ( const auto& ddriver : Preferences::getSupportedAudioDrivers() ) {
235 driverComboBox->addItem(
237 }
238
239 const auto sAudioDriver =
241 const auto nAudioDriverIndex = driverComboBox->findText( sAudioDriver );
242 if ( nAudioDriverIndex > -1 ) {
243 driverComboBox->setCurrentIndex( nAudioDriverIndex );
244 }
245 else {
246 driverInfoLbl->setText( tr("Select your Audio Driver" ));
247 ERRORLOG( QString( "Unknown audio driver from preferences [%1]" )
248 .arg( sAudioDriver ) );
249 }
250 connect( driverComboBox, SIGNAL(activated(int)), this,
251 SLOT(driverComboBoxActivated(int)));
252
253 // Audio tab - Set the PortAudio HostAPI combo box to the current
254 // selected value.
255 portaudioHostAPIComboBox->setSize( audioTabWidgetSizeTop );
256 portaudioHostAPIComboBox->setValue( pPref->m_sPortAudioHostAPI );
257 connect( portaudioHostAPIComboBox, SIGNAL(activated(int)), this,
259
260 m_pAudioDeviceTxt->setSize( audioTabWidgetSizeTop );
261 m_pAudioDeviceTxt->setHostAPI( pPref->m_sPortAudioHostAPI );
262 connect( m_pAudioDeviceTxt, SIGNAL(currentTextChanged(const QString&)),
263 this, SLOT( audioDeviceTxtChanged(const QString&)));
264
265 latencyTargetSpinBox->setSize( QSize( 55, 23 ) );
266 latencyTargetSpinBox->setValue( pPref->m_nLatencyTarget );
267 connect( latencyTargetSpinBox, SIGNAL(valueChanged(int)), this,
269
270 bufferSizeSpinBox->setSize( audioTabWidgetSizeTop );
271 bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
272 connect( bufferSizeSpinBox, SIGNAL(valueChanged(int)), this,
274
275 sampleRateComboBox->setSize( audioTabWidgetSizeTop );
276 switch ( pPref->m_nSampleRate ) {
277 case 44100:
278 sampleRateComboBox->setCurrentIndex( 0 );
279 break;
280 case 48000:
281 sampleRateComboBox->setCurrentIndex( 1 );
282 break;
283 case 88200:
284 sampleRateComboBox->setCurrentIndex( 2 );
285 break;
286 case 96000:
287 sampleRateComboBox->setCurrentIndex( 3 );
288 break;
289 default:
290 ERRORLOG( QString("Wrong samplerate: %1").arg( pPref->m_nSampleRate ) );
291 }
292 connect( sampleRateComboBox, SIGNAL(editTextChanged(const QString&)), this,
293 SLOT(sampleRateComboBoxEditTextChanged(const QString&)));
294
295 // Audio tab - JACK
296 trackOutsCheckBox->setChecked( pPref->m_bJackTrackOuts );
297 connect(trackOutsCheckBox, SIGNAL(toggled(bool)), this, SLOT(toggleTrackOutsCheckBox( bool )));
298
299 connectDefaultsCheckBox->setChecked( pPref->m_bJackConnectDefaults );
300 enableTimebaseCheckBox->setChecked( pPref->m_bJackTimebaseEnabled );
301
302 trackOutputComboBox->setSize( audioTabWidgetSizeTop );
303 switch ( pPref->m_JackTrackOutputMode ) {
305 trackOutputComboBox->setCurrentIndex( 0 );
306 break;
308 trackOutputComboBox->setCurrentIndex( 1 );
309 break;
310 default:
311 ERRORLOG( QString( "Unknown JACK track output mode [%1]" )
312 .arg( static_cast<int>( pPref->m_JackTrackOutputMode ) ) );
313 }
314 // Audio tab - ~JACK
315
316 // Audio tab - metronome volume
317 metronomeVolumeSpinBox->setSize( audioTabWidgetSizeBottom );
318 uint metronomeVol = (uint)( pPref->m_fMetronomeVolume * 100.0 );
319 metronomeVolumeSpinBox->setValue(metronomeVol);
320
321 // Audio tab - max voices
322 maxVoicesTxt->setSize( audioTabWidgetSizeBottom );
323 maxVoicesTxt->setValue( pPref->m_nMaxNotes );
324
325 resampleComboBox->setSize( audioTabWidgetSizeBottom );
326 resampleComboBox->setCurrentIndex( static_cast<int>(pHydrogen->getAudioEngine()->getSampler()->getInterpolateMode() ) );
327
329
331 // MIDI tab
333 QSize midiTabWidgetSize = QSize( 309, 24 );
334 m_pMidiDriverComboBox->setSize( midiTabWidgetSize );
335 m_pMidiDriverComboBox->clear();
336#ifdef H2CORE_HAVE_ALSA
337 m_pMidiDriverComboBox->addItem( "ALSA" );
338#endif
339#ifdef H2CORE_HAVE_PORTMIDI
340 m_pMidiDriverComboBox->addItem( "PortMidi" );
341#endif
342#ifdef H2CORE_HAVE_COREMIDI
343 m_pMidiDriverComboBox->addItem( "CoreMIDI" );
344#endif
345#ifdef H2CORE_HAVE_JACK
346 m_pMidiDriverComboBox->addItem( "JACK-MIDI" );
347#endif
348
349 if ( m_pMidiDriverComboBox->findText(pPref->m_sMidiDriver) > -1 ) {
350 m_pMidiDriverComboBox->setCurrentIndex(m_pMidiDriverComboBox->findText(pPref->m_sMidiDriver));
351 } else {
352 driverInfoLbl->setText( tr("Select your MIDI Driver" ) );
353 ERRORLOG( "Unknown MIDI input from preferences [" + pPref->m_sMidiDriver + "]" );
354 }
355 connect(m_pMidiDriverComboBox, SIGNAL(currentIndexChanged(int)),
356 this, SLOT( onMidiDriverComboBoxIndexChanged(int) ));
357
358 midiPortChannelComboBox->setSize( midiTabWidgetSize );
359 midiPortChannelComboBox->setEnabled( false );
360 midiPortComboBox->setSize( midiTabWidgetSize );
361 midiPortComboBox->setEnabled( false );
362 connect( midiPortComboBox, SIGNAL(activated(int)), this,
363 SLOT(midiPortComboBoxActivated(int)));
364
365 // MIDI tab - list midi input ports
366 midiPortComboBox->clear();
367 midiPortComboBox->addItem( pCommonStrings->getPreferencesNone() );
368 if ( pHydrogen->getMidiInput() != nullptr ) {
369 std::vector<QString> midiOutList = pHydrogen->getMidiInput()->getOutputPortList();
370
371 if ( midiOutList.size() != 0 ) {
372 midiPortComboBox->setEnabled( true );
373 midiPortChannelComboBox->setEnabled( true );
374 }
375 for (uint i = 0; i < midiOutList.size(); i++) {
376 QString sPortName = midiOutList[i];
377 midiPortComboBox->addItem( sPortName );
378
379 if ( sPortName == pPref->m_sMidiPortName ) {
380 midiPortComboBox->setCurrentIndex( i + 1 );
381 }
382 }
383 }
384
385 // MIDI tab - list midi output ports
386 midiOutportComboBox->setSize( midiTabWidgetSize );
387 midiOutportComboBox->clear();
388 midiOutportComboBox->addItem( pCommonStrings->getPreferencesNone() );
389 if ( pHydrogen->getMidiOutput() != nullptr ) {
390 std::vector<QString> midiOutList = pHydrogen->getMidiOutput()->getInputPortList();
391
392 if ( midiOutList.size() != 0 ) {
393 midiOutportComboBox->setEnabled( true );
394 midiPortChannelComboBox->setEnabled( true );
395 }
396 for (uint i = 0; i < midiOutList.size(); i++) {
397 QString sPortName = midiOutList[i];
398 midiOutportComboBox->addItem( sPortName );
399
400 if ( sPortName == pPref->m_sMidiOutputPortName ) {
401 midiOutportComboBox->setCurrentIndex( i + 1 );
402 }
403 }
404 }
405 connect( midiOutportComboBox, SIGNAL(activated(int)), this,
407
408 if ( pPref->m_nMidiChannelFilter == -1 ) {
409 midiPortChannelComboBox->setCurrentIndex( 0 );
410 }
411 else {
412 midiPortChannelComboBox->setCurrentIndex( pPref->m_nMidiChannelFilter + 1 );
413 }
414
415 m_pIgnoreNoteOffCheckBox->setChecked( pPref->m_bMidiNoteOffIgnore );
416 m_pEnableMidiFeedbackCheckBox->setChecked( pPref->m_bEnableMidiFeedback );
417 m_pDiscardMidiMsgCheckbox->setChecked( pPref->m_bMidiDiscardNoteAfterAction );
418 m_pFixedMapping->setChecked( pPref->m_bMidiFixedMapping );
419
420 connect( midiTable, &MidiTable::changed,
421 [=]() {
422 m_changes =
423 static_cast<H2Core::Preferences::Changes>(
425 m_bMidiTableChanged = true;
426 });
427
429 // OSC tab
430 enableOscCheckbox->setChecked( pPref->getOscServerEnabled() );
431 enableOscFeedbackCheckbox->setChecked( pPref->getOscFeedbackEnabled() );
432 connect(enableOscCheckbox, SIGNAL(toggled(bool)), this, SLOT(toggleOscCheckBox( bool )));
433 incomingOscPortSpinBox->setSize( QSize( 66, 24 ) );
434 incomingOscPortSpinBox->setValue( pPref->getOscServerPort() );
435
436 if ( pPref->m_nOscTemporaryPort != -1 ) {
437 oscTemporaryPortLabel->show();
438 oscTemporaryPortLabel->setText( QString( "<b><i><font color=" )
439 .append( m_sColorRed )
440 .append( ">" )
441 .append( tr( "The select port is unavailable. This instance uses the following temporary port instead:" ) )
442 .append( "</font></i></b>" ) );
443 oscTemporaryPort->show();
444 oscTemporaryPort->setEnabled( false );
445 oscTemporaryPort->setText( QString::number( pPref->m_nOscTemporaryPort ) );
446 } else {
447 oscTemporaryPortLabel->hide();
448 oscTemporaryPort->hide();
449 }
450
451 if ( ! pPref->getOscServerEnabled() ) {
452 enableOscFeedbackCheckbox->hide();
453 incomingOscPortSpinBox->hide();
454 incomingOscPortLabel->hide();
455 oscTemporaryPortLabel->hide();
456 oscTemporaryPort->hide();
457 }
458
460 // Appearance tab
461 QSize appearanceTabWidgetSize = QSize( 277, 24 );
462 connect( importThemeButton, SIGNAL(clicked(bool)), SLOT(importTheme()));
463 connect( exportThemeButton, SIGNAL(clicked(bool)), SLOT(exportTheme()));
464 connect( resetThemeButton, SIGNAL(clicked(bool)), this, SLOT(resetTheme()));
465
466 // Appearance tab - Fonts
467 fontSizeComboBox->setSize( appearanceTabWidgetSize );
468 connect( applicationFontComboBox, &QFontComboBox::currentFontChanged, this, &PreferencesDialog::onApplicationFontChanged );
469 connect( level2FontComboBox, &QFontComboBox::currentFontChanged, this, &PreferencesDialog::onLevel2FontChanged );
470 connect( level3FontComboBox, &QFontComboBox::currentFontChanged, this, &PreferencesDialog::onLevel3FontChanged );
471 connect( fontSizeComboBox, SIGNAL( currentIndexChanged(int) ),
472 this, SLOT( onFontSizeChanged(int) ) );
473
474 // Appearance tab - Interface
475 UIChangeWarningLabel->hide();
476 UIChangeWarningLabel->setText( QString( "<b><i><font color=" )
477 .append( m_sColorRed )
478 .append( ">" )
479 .append( tr( "For changes of the interface layout to take effect Hydrogen must be restarted." ) )
480 .append( "</font></i></b>" ) );
481
482 styleComboBox->setSize( appearanceTabWidgetSize );
483 mixerFalloffComboBox->setSize( appearanceTabWidgetSize );
484 uiLayoutComboBox->setSize( appearanceTabWidgetSize );
485 uiScalingPolicyComboBox->setSize( appearanceTabWidgetSize );
486 iconColorComboBox->setSize( appearanceTabWidgetSize );
487 coloringMethodAuxSpinBox->setSize( appearanceTabWidgetSize );
488
489 connect( styleComboBox, SIGNAL( activated(int) ), this,
490 SLOT( styleComboBoxActivated(int) ) );
491 connect( uiLayoutComboBox, SIGNAL( currentIndexChanged(int) ), this,
492 SLOT( onUILayoutChanged(int) ) );
493 connect( uiScalingPolicyComboBox, SIGNAL( currentIndexChanged(int) ), this,
495 connect( mixerFalloffComboBox, SIGNAL( currentIndexChanged(int) ), this,
497 connect( iconColorComboBox, SIGNAL(currentIndexChanged(int)), this,
498 SLOT( onIconColorChanged(int)) );
499 connect( coloringMethodAuxSpinBox, SIGNAL( valueChanged(int)), this, SLOT( onColorNumberChanged( int ) ) );
500
501 m_colorSelectionButtons = std::vector<ColorSelectionButton*>( m_pCurrentTheme->getInterfaceTheme()->m_nMaxPatternColors );
502 int nButtonSize = fontSizeComboBox->height();
503 // float fLineWidth = static_cast<float>(fontSizeComboBox->width());
504 // Using a fixed one size resizing of the widget seems to happen
505 // after the constructor is called.
506 float fLineWidth = 308;
507 int nButtonsPerLine = std::floor( fLineWidth / static_cast<float>(nButtonSize + 6) );
508
509 colorSelectionGrid->setHorizontalSpacing( 4 );
510 for ( int ii = 0; ii < m_pCurrentTheme->getInterfaceTheme()->m_nMaxPatternColors; ii++ ) {
511 ColorSelectionButton* bbutton =
512 new ColorSelectionButton( this, m_pCurrentTheme->getInterfaceTheme()->m_patternColors[ ii ],
513 nButtonSize );
514 bbutton->hide();
515 connect( bbutton, &ColorSelectionButton::colorChanged, this,
517 colorSelectionGrid->addWidget( bbutton,
518 std::floor( static_cast<float>( ii ) /
519 static_cast<float>( nButtonsPerLine ) ),
520 (ii % nButtonsPerLine) + 1); //+1 to take the hspace into account.
521 m_colorSelectionButtons[ ii ] = bbutton;
522 }
523
524 coloringMethodCombo->setSize( appearanceTabWidgetSize );
525 coloringMethodCombo->clear();
526 coloringMethodCombo->addItem(tr("Automatic"));
527 coloringMethodCombo->addItem(tr("Custom"));
528 connect( coloringMethodCombo, SIGNAL( currentIndexChanged(int) ), this, SLOT( onColoringMethodChanged(int) ) );
529
530 // Appearance tab - Colors
531 colorButton->setAutoFillBackground(true);
532 m_pColorSliderTimer = new QTimer( this );
533 m_pColorSliderTimer->setSingleShot( true );
534 connect( m_pColorSliderTimer, SIGNAL(timeout()), this, SLOT(updateColors()) );
535
536 ColorTreeItem* pTopLevelItem;
537 colorTree->clear();
538 pTopLevelItem = new ColorTreeItem( 0x000, colorTree, tr( "General" ) );
539 new ColorTreeItem( 0x100, pTopLevelItem, tr( "Window" ) );
540 new ColorTreeItem( 0x101, pTopLevelItem, tr( "Window Text" ) );
541 new ColorTreeItem( 0x102, pTopLevelItem, tr( "Base" ) );
542 new ColorTreeItem( 0x103, pTopLevelItem, tr( "Alternate Base" ) );
543 new ColorTreeItem( 0x104, pTopLevelItem, tr( "Text" ) );
544 new ColorTreeItem( 0x105, pTopLevelItem, tr( "Button" ) );
545 new ColorTreeItem( 0x106, pTopLevelItem, tr( "Button Text" ) );
546 new ColorTreeItem( 0x107, pTopLevelItem, tr( "Light" ) );
547 new ColorTreeItem( 0x108, pTopLevelItem, tr( "Mid Light" ) );
548 new ColorTreeItem( 0x109, pTopLevelItem, tr( "Mid" ) );
549 new ColorTreeItem( 0x10a, pTopLevelItem, tr( "Dark" ) );
550 new ColorTreeItem( 0x10b, pTopLevelItem, tr( "Shadow Text" ) );
551 new ColorTreeItem( 0x10c, pTopLevelItem, tr( "Highlight" ) );
552 new ColorTreeItem( 0x10d, pTopLevelItem, tr( "Highlight Text" ) );
553 new ColorTreeItem( 0x10e, pTopLevelItem, tr( "Selection Highlight" ) );
554 new ColorTreeItem( 0x10f, pTopLevelItem, tr( "Selection Inactive" ) );
555 new ColorTreeItem( 0x110, pTopLevelItem, tr( "Tool Tip Base" ) );
556 new ColorTreeItem( 0x111, pTopLevelItem, tr( "Tool Tip Text" ) );
557
558 auto pWidgetItem = new ColorTreeItem( 0x000, colorTree, tr( "Widgets" ) );
559 auto pDefaultItem = new ColorTreeItem( 0x200, pWidgetItem, tr( "Widget" ) );
560 new ColorTreeItem( 0x201, pWidgetItem, tr( "Widget Text" ) );
561 new ColorTreeItem( 0x202, pWidgetItem, tr( "Accent" ) );
562 new ColorTreeItem( 0x203, pWidgetItem, tr( "Accent Text" ) );
563 new ColorTreeItem( 0x204, pWidgetItem, tr( "Button Red" ) );
564 new ColorTreeItem( 0x205, pWidgetItem, tr( "Button Red Text" ) );
565 new ColorTreeItem( 0x206, pWidgetItem, tr( "Spin Box" ) );
566 new ColorTreeItem( 0x207, pWidgetItem, tr( "Spin Box Text" ) );
567 new ColorTreeItem( 0x208, pWidgetItem, tr( "Playhead" ) );
568 new ColorTreeItem( 0x209, pWidgetItem, tr( "Cursor" ) );
569
570 pTopLevelItem = new ColorTreeItem( 0x000, colorTree, tr( "Song Editor" ) );
571 new ColorTreeItem( 0x300, pTopLevelItem, tr( "Background" ) );
572 new ColorTreeItem( 0x301, pTopLevelItem, tr( "Alternate Row" ) );
573 new ColorTreeItem( 0x302, pTopLevelItem, tr( "Virtual Row" ) );
574 new ColorTreeItem( 0x303, pTopLevelItem, tr( "Selected Row" ) );
575 new ColorTreeItem( 0x304, pTopLevelItem, tr( "Selected Row Text" ) );
576 new ColorTreeItem( 0x305, pTopLevelItem, tr( "Line" ) );
577 new ColorTreeItem( 0x306, pTopLevelItem, tr( "Text" ) );
578 new ColorTreeItem( 0x307, pTopLevelItem, tr( "Automation Background" ) );
579 new ColorTreeItem( 0x308, pTopLevelItem, tr( "Automation Line" ) );
580 new ColorTreeItem( 0x309, pTopLevelItem, tr( "Automation Node" ) );
581 new ColorTreeItem( 0x30a, pTopLevelItem, tr( "Stacked Mode On" ) );
582 new ColorTreeItem( 0x30b, pTopLevelItem, tr( "Stacked Mode On Next" ) );
583 new ColorTreeItem( 0x30c, pTopLevelItem, tr( "Stacked Mode Off Next" ) );
584
585 pTopLevelItem = new ColorTreeItem( 0x000, colorTree, tr( "Pattern Editor" ) );
586 new ColorTreeItem( 0x400, pTopLevelItem, tr( "Background" ) );
587 new ColorTreeItem( 0x401, pTopLevelItem, tr( "Alternate Row" ) );
588 new ColorTreeItem( 0x402, pTopLevelItem, tr( "Selected Row" ) );
589 new ColorTreeItem( 0x403, pTopLevelItem, tr( "Selected Row Text" ) );
590 new ColorTreeItem( 0x404, pTopLevelItem, tr( "Octave Row" ) );
591 new ColorTreeItem( 0x405, pTopLevelItem, tr( "Text" ) );
592 new ColorTreeItem( 0x406, pTopLevelItem, tr( "Note (Full Velocity)" ) );
593 new ColorTreeItem( 0x407, pTopLevelItem, tr( "Note (Default Velocity)" ) );
594 new ColorTreeItem( 0x408, pTopLevelItem, tr( "Note (Half Velocity)" ) );
595 new ColorTreeItem( 0x409, pTopLevelItem, tr( "Note (Zero Velocity)" ) );
596 new ColorTreeItem( 0x40a, pTopLevelItem, tr( "Note Off" ) );
597 new ColorTreeItem( 0x40b, pTopLevelItem, tr( "Grid Line 1" ) );
598 new ColorTreeItem( 0x40c, pTopLevelItem, tr( "Grid Line 2" ) );
599 new ColorTreeItem( 0x40d, pTopLevelItem, tr( "Grid Line 3" ) );
600 new ColorTreeItem( 0x40e, pTopLevelItem, tr( "Grid Line 4" ) );
601 new ColorTreeItem( 0x40f, pTopLevelItem, tr( "Grid Line 5" ) );
602 new ColorTreeItem( 0x410, pTopLevelItem, tr( "Grid Line 6" ) );
603
604 colorButton->setEnabled( false );
605
606 connect( colorTree, SIGNAL(itemSelectionChanged()),
607 this, SLOT(colorTreeSelectionChanged()) );
608 connect( colorButton, SIGNAL(colorChanged()),
609 this, SLOT(colorButtonChanged()) );
610 connect(rslider, SIGNAL(valueChanged(int)), SLOT(rsliderChanged(int)));
611 connect(gslider, SIGNAL(valueChanged(int)), SLOT(gsliderChanged(int)));
612 connect(bslider, SIGNAL(valueChanged(int)), SLOT(bsliderChanged(int)));
613 connect(hslider, SIGNAL(valueChanged(int)), SLOT(hsliderChanged(int)));
614 connect(sslider, SIGNAL(valueChanged(int)), SLOT(ssliderChanged(int)));
615 connect(vslider, SIGNAL(valueChanged(int)), SLOT(vsliderChanged(int)));
616
617 connect(rval, SIGNAL(valueChanged(int)), SLOT(rsliderChanged(int)));
618 connect(gval, SIGNAL(valueChanged(int)), SLOT(gsliderChanged(int)));
619 connect(bval, SIGNAL(valueChanged(int)), SLOT(bsliderChanged(int)));
620 connect(hval, SIGNAL(valueChanged(int)), SLOT(hsliderChanged(int)));
621 connect(sval, SIGNAL(valueChanged(int)), SLOT(ssliderChanged(int)));
622 connect(vval, SIGNAL(valueChanged(int)), SLOT(vsliderChanged(int)));
623
624 // We initialize the tree by expanding the "Widget" node and
625 // selecting the first color. This looks more nice than with no
626 // color selected at all and works better with the Shotlist.
627 colorTree->expandItem( pWidgetItem );
628 colorTree->setCurrentItem( pDefaultItem );
629
631
633
634 m_bNeedDriverRestart = false;
635}
636
638{
639 INFOLOG("~PREFERENCES_DIALOG");
640}
641
643{
644 Preferences *preferencesMng = Preferences::get_instance();
645 preferencesMng->loadPreferences( false ); // reload old user's preferences
646
647 //restore the right m_bsetlash value
648 if ( preferencesMng->m_brestartLash == true ){
649 if (preferencesMng->m_bsetLash == false ){
650 preferencesMng->m_bsetLash = true ;
651 preferencesMng->m_brestartLash = false;
652 }
653
654 }
655
658
659 reject();
660}
661
663{
665}
666
669 auto pAudioDriver = Hydrogen::get_instance()->getAudioOutput();
670
671 bool bAudioOptionAltered = false;
672 const auto prevAudioDriver = pPref->m_audioDriver;
673 const auto selectedDriver = Preferences::parseAudioDriver(
674 driverComboBox->currentText() );
675
676 if ( prevAudioDriver != selectedDriver ) {
677 if ( selectedDriver != Preferences::AudioDriver::None ) {
678 pPref->m_audioDriver = selectedDriver;
679 bAudioOptionAltered = true;
680 }
681 else {
682 ERRORLOG( QString( "Invalid audio driver: [%1]" )
683 .arg( driverComboBox->currentText() ) );
684 }
685 }
686
687 // Driver-specific settings
688 if ( selectedDriver == Preferences::AudioDriver::Alsa ||
689 ( selectedDriver == Preferences::AudioDriver::Auto &&
690 dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver) != nullptr ) ) {
691 if ( pPref->m_sAlsaAudioDevice != m_pAudioDeviceTxt->lineEdit()->text() ) {
692 pPref->m_sAlsaAudioDevice = m_pAudioDeviceTxt->lineEdit()->text();
693 bAudioOptionAltered = true;
694 }
695 }
696 else if ( selectedDriver == Preferences::AudioDriver::Oss ||
697 ( selectedDriver == Preferences::AudioDriver::Auto &&
698 dynamic_cast<H2Core::OssDriver*>(pAudioDriver) != nullptr ) ) {
699 if ( pPref->m_sOSSDevice != m_pAudioDeviceTxt->lineEdit()->text() ) {
700 pPref->m_sOSSDevice = m_pAudioDeviceTxt->lineEdit()->text();
701 bAudioOptionAltered = true;
702 }
703 }
704 else if ( selectedDriver == Preferences::AudioDriver::PortAudio ||
705 ( selectedDriver == Preferences::AudioDriver::Auto &&
706 dynamic_cast<H2Core::PortAudioDriver*>(pAudioDriver) != nullptr ) ) {
707 if ( pPref->m_sPortAudioDevice != m_pAudioDeviceTxt->lineEdit()->text() ) {
708 pPref->m_sPortAudioDevice = m_pAudioDeviceTxt->lineEdit()->text();
709 bAudioOptionAltered = true;
710 }
711 if ( pPref->m_sPortAudioHostAPI != portaudioHostAPIComboBox->currentText() ) {
712 pPref->m_sPortAudioHostAPI = portaudioHostAPIComboBox->currentText();
713 bAudioOptionAltered = true;
714 }
715 if ( pPref->m_nLatencyTarget != latencyTargetSpinBox->value() ) {
716 pPref->m_nLatencyTarget = latencyTargetSpinBox->value();
717 bAudioOptionAltered = true;
718 }
719 }
720 else if (selectedDriver == Preferences::AudioDriver::CoreAudio ||
721 ( selectedDriver == Preferences::AudioDriver::Auto &&
722 dynamic_cast<H2Core::CoreAudioDriver*>(pAudioDriver) != nullptr ) ) {
723 if ( pPref->m_sCoreAudioDevice != m_pAudioDeviceTxt->lineEdit()->text() ) {
724 pPref->m_sCoreAudioDevice = m_pAudioDeviceTxt->lineEdit()->text();
725 bAudioOptionAltered = true;
726 }
727 }
728
729 // JACK
730 if ( pPref->m_bJackConnectDefaults != connectDefaultsCheckBox->isChecked() ) {
731 pPref->m_bJackConnectDefaults = connectDefaultsCheckBox->isChecked();
732 bAudioOptionAltered = true;
733 }
734
735 if ( pPref->m_bJackTrackOuts != trackOutsCheckBox->isChecked() ) {
736 pPref->m_bJackTrackOuts = trackOutsCheckBox->isChecked();
737 bAudioOptionAltered = true;
738 }
739
740 if ( pPref->m_bJackTimebaseEnabled != enableTimebaseCheckBox->isChecked() ) {
741 pPref->m_bJackTimebaseEnabled = enableTimebaseCheckBox->isChecked();
742 bAudioOptionAltered = true;
743 }
744
745 switch ( trackOutputComboBox->currentIndex() ) {
746 case 0:
747 if ( pPref->m_JackTrackOutputMode !=
749 pPref->m_JackTrackOutputMode =
751 bAudioOptionAltered = true;
752 }
753 break;
754 case 1:
755 if ( pPref->m_JackTrackOutputMode !=
757 pPref->m_JackTrackOutputMode =
759 bAudioOptionAltered = true;
760 }
761 break;
762 default:
763 ERRORLOG( QString( "Unexpected track output value" ) );
764 }
765 // ~ JACK
766
767 if ( pPref->m_nBufferSize != bufferSizeSpinBox->value() ) {
768 pPref->m_nBufferSize = bufferSizeSpinBox->value();
769 bAudioOptionAltered = true;
770 }
771
772 if ( sampleRateComboBox->currentText() == "44100" &&
773 pPref->m_nSampleRate != 44100 ) {
774 pPref->m_nSampleRate = 44100;
775 bAudioOptionAltered = true;
776 }
777 else if ( sampleRateComboBox->currentText() == "48000" &&
778 pPref->m_nSampleRate != 48000 ) {
779 pPref->m_nSampleRate = 48000;
780 bAudioOptionAltered = true;
781 }
782 else if ( sampleRateComboBox->currentText() == "88200" &&
783 pPref->m_nSampleRate != 88200 ) {
784 pPref->m_nSampleRate = 88200;
785 bAudioOptionAltered = true;
786 }
787 else if ( sampleRateComboBox->currentText() == "96000" &&
788 pPref->m_nSampleRate != 96000 ) {
789 pPref->m_nSampleRate = 96000;
790 bAudioOptionAltered = true;
791 }
792
793 if ( bAudioOptionAltered ) {
794 m_changes =
795 static_cast<H2Core::Preferences::Changes>(
797 }
798}
799
800
802{
803 auto pH2App = HydrogenApp::get_instance();
804 auto pCommonStrings = pH2App->getCommonStrings();
805 auto pPref = Preferences::get_instance();
806 auto pHydrogen = Hydrogen::get_instance();
807
809 // Audio tab
811 bool bAudioOptionAltered = false;
812
814
815 if ( m_bNeedDriverRestart ) {
816 if ( QMessageBox::information(
817 this, "Hydrogen",
818 tr( "Driver restart required.\n Restart driver?"),
819 QMessageBox::Ok | QMessageBox::Cancel,
820 QMessageBox::Cancel ) == QMessageBox::Cancel ) {
821 // Don't save the Preferences and don't close the PreferencesDialog
822 return;
823 }
824 }
825
826 // Check whether the current audio driver is valid
827 if ( pHydrogen->getAudioOutput() == nullptr ||
828 dynamic_cast<NullDriver*>(pHydrogen->getAudioOutput()) != nullptr ) {
829 if ( QMessageBox::warning(
830 this, "Hydrogen", QString( "%1\n" )
831 .arg( pCommonStrings->getAudioDriverNotPresent() )
832 .append( tr( "Are you sure you want to proceed?" ) ),
833 QMessageBox::Ok | QMessageBox::Cancel,
834 QMessageBox::Cancel ) == QMessageBox::Cancel ) {
835 return;
836 }
837 }
838
839 if ( pPref->m_fMetronomeVolume != metronomeVolumeSpinBox->value() / 100.0 ) {
840 pPref->m_fMetronomeVolume = metronomeVolumeSpinBox->value() / 100.0;
841 bAudioOptionAltered = true;
842 }
843
844 // Polyphony
845 if ( pPref->m_nMaxNotes != maxVoicesTxt->value() ) {
846 pPref->m_nMaxNotes = maxVoicesTxt->value();
847 bAudioOptionAltered = true;
848 }
849
850 // Interpolation
851 if ( static_cast<int>( pHydrogen->getAudioEngine()->getSampler()->getInterpolateMode() ) !=
852 resampleComboBox->currentIndex() ) {
853 switch ( resampleComboBox->currentIndex() ){
854 case 0:
855 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Linear );
856 break;
857 case 1:
858 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Cosine );
859 break;
860 case 2:
861 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Third );
862 break;
863 case 3:
864 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Cubic );
865 break;
866 case 4:
867 Hydrogen::get_instance()->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Hermite );
868 break;
869 }
870 bAudioOptionAltered = true;
871 }
872
873 if ( bAudioOptionAltered ) {
874 m_changes =
875 static_cast<H2Core::Preferences::Changes>(
877 }
878
880 // MIDI tab
882 bool bMidiOptionAltered = false;
883
885 mM->reset_instance();
886
887 midiTable->saveMidiTable();
888 if ( m_bMidiTableChanged ) {
890 }
891
892 if ( m_pMidiDriverComboBox->currentText() == "ALSA" &&
893 pPref->m_sMidiDriver != "ALSA" ) {
894 pPref->m_sMidiDriver = "ALSA";
895 bMidiOptionAltered = true;
896 }
897 else if ( m_pMidiDriverComboBox->currentText() == "PortMidi" &&
898 pPref->m_sMidiDriver != "PortMidi" ) {
899 pPref->m_sMidiDriver = "PortMidi";
900 bMidiOptionAltered = true;
901 }
902 else if ( m_pMidiDriverComboBox->currentText() == "CoreMIDI" &&
903 pPref->m_sMidiDriver != "CoreMIDI" ) {
904 pPref->m_sMidiDriver = "CoreMIDI";
905 bMidiOptionAltered = true;
906 }
907 else if ( m_pMidiDriverComboBox->currentText() == "JACK-MIDI" &&
908 pPref->m_sMidiDriver != "JACK-MIDI" ) {
909 pPref->m_sMidiDriver = "JACK-MIDI";
910 bMidiOptionAltered = true;
911 }
912
913 if ( pPref->m_bMidiNoteOffIgnore != m_pIgnoreNoteOffCheckBox->isChecked() ) {
914 pPref->m_bMidiNoteOffIgnore = m_pIgnoreNoteOffCheckBox->isChecked();
915 bMidiOptionAltered = true;
916 }
917
918 if ( pPref->m_bMidiFixedMapping != m_pFixedMapping->isChecked() ) {
919 pPref->m_bMidiFixedMapping = m_pFixedMapping->isChecked();
920 bMidiOptionAltered = true;
921 }
922
923 if ( pPref->m_bMidiDiscardNoteAfterAction !=
924 m_pDiscardMidiMsgCheckbox->isChecked() ) {
925 pPref->m_bMidiDiscardNoteAfterAction = m_pDiscardMidiMsgCheckbox->isChecked();
926 bMidiOptionAltered = true;
927 }
928
929 if ( pPref->m_bEnableMidiFeedback !=
930 m_pEnableMidiFeedbackCheckBox->isChecked() ) {
931 pPref->m_bEnableMidiFeedback = m_pEnableMidiFeedbackCheckBox->isChecked();
932 bMidiOptionAltered = true;
933 }
934
935 QString sNewMidiPortName = midiPortComboBox->currentText();
936 if ( midiPortComboBox->currentIndex() == 0 ) {
937 sNewMidiPortName = Preferences::getNullMidiPort();
938 }
939 if ( pPref->m_sMidiPortName != sNewMidiPortName ) {
940 pPref->m_sMidiPortName = sNewMidiPortName;
941 bMidiOptionAltered = true;
943 }
944
945 QString sNewMidiOutputPortName = midiOutportComboBox->currentText();
946 if ( midiOutportComboBox->currentIndex() == 0 ) {
947 sNewMidiOutputPortName = Preferences::getNullMidiPort();
948 }
949 if ( pPref->m_sMidiOutputPortName != sNewMidiOutputPortName ) {
950 pPref->m_sMidiOutputPortName = sNewMidiOutputPortName;
951 bMidiOptionAltered = true;
953 }
954
955 if ( pPref->m_nMidiChannelFilter !=
956 midiPortChannelComboBox->currentIndex() - 1 ) {
957 pPref->m_nMidiChannelFilter = midiPortChannelComboBox->currentIndex() - 1;
958 bMidiOptionAltered = true;
959 }
960
961 if ( bMidiOptionAltered ) {
962 m_changes =
963 static_cast<H2Core::Preferences::Changes>(
965 }
966
968 // OSC tab
970 bool bOscOptionAltered = false;
971
972 if ( enableOscCheckbox->isChecked() != pPref->getOscServerEnabled() ) {
973 pPref->setOscServerEnabled( enableOscCheckbox->isChecked() );
974 pHydrogen->toggleOscServer( enableOscCheckbox->isChecked() );
975 bOscOptionAltered = true;
976 }
977
978 if ( pPref->getOscFeedbackEnabled() !=
979 enableOscFeedbackCheckbox->isChecked() ) {
980 pPref->setOscFeedbackEnabled( enableOscFeedbackCheckbox->isChecked() );
981 bOscOptionAltered = true;
982 }
983
984 if ( incomingOscPortSpinBox->value() != pPref->getOscServerPort() ) {
985 pPref->setOscServerPort( incomingOscPortSpinBox->value() );
986 pHydrogen->recreateOscServer();
987 bOscOptionAltered = true;
988 }
989
990 if ( bOscOptionAltered ) {
991 m_changes =
992 static_cast<H2Core::Preferences::Changes>(
994 }
995
997 // General tab
999 bool bGeneralOptionAltered = false;
1000
1001 if ( pPref->isRestoreLastSongEnabled() !=
1002 restoreLastUsedSongCheckbox->isChecked() ) {
1003 pPref->setRestoreLastSongEnabled( restoreLastUsedSongCheckbox->isChecked() );
1004 bGeneralOptionAltered = true;
1005 }
1006
1007 if ( pPref->isRestoreLastPlaylistEnabled() !=
1008 restoreLastUsedPlaylistCheckbox->isChecked() ) {
1009 pPref->setRestoreLastPlaylistEnabled( restoreLastUsedPlaylistCheckbox->isChecked() );
1010 bGeneralOptionAltered = true;
1011 }
1012
1013 if ( pPref->isPlaylistUsingRelativeFilenames() !=
1014 useRelativePlaylistPathsCheckbox->isChecked() ) {
1015 pPref->setUseRelativeFilenamesForPlaylists( useRelativePlaylistPathsCheckbox->isChecked() );
1016 bGeneralOptionAltered = true;
1017 }
1018
1019 if ( pPref->m_bsetLash != useLashCheckbox->isChecked() ) {
1020 pPref->m_bsetLash = useLashCheckbox->isChecked(); //restore m_bsetLash after saving pref
1021 bGeneralOptionAltered = true;
1022 }
1023
1024 if ( pPref->hideKeyboardCursor() != hideKeyboardCursor->isChecked() ) {
1025 pPref->setHideKeyboardCursor( hideKeyboardCursor->isChecked() );
1026 bGeneralOptionAltered = true;
1027 }
1028
1029 //path to rubberband
1030 if ( pPref->m_rubberBandCLIexecutable != rubberbandLineEdit->text() ) {
1031 pPref->m_rubberBandCLIexecutable = rubberbandLineEdit->text();
1032 bGeneralOptionAltered = true;
1033 }
1034
1035 //check preferences
1036 if ( pPref->m_brestartLash == true ){
1037 pPref->m_bsetLash = true ;
1038 }
1039
1040 if ( pPref->m_countOffset != sBcountOffset->value() ) {
1041 pPref->m_countOffset = sBcountOffset->value();
1042 pHydrogen->setBcOffsetAdjust();
1043 bGeneralOptionAltered = true;
1044 }
1045
1046 if ( pPref->m_startOffset != sBstartOffset->value() ) {
1047 pPref->m_startOffset = sBstartOffset->value();
1048 pHydrogen->setBcOffsetAdjust();
1049 bGeneralOptionAltered = true;
1050 }
1051
1052 if ( pPref->getMaxBars() != sBmaxBars->value() ) {
1053 pPref->setMaxBars( sBmaxBars->value() );
1054 bGeneralOptionAltered = true;
1055 }
1056
1057 if ( pPref->getMaxLayers() != sBmaxLayers->value() ) {
1058 pPref->setMaxLayers( sBmaxLayers->value() );
1059 bGeneralOptionAltered = true;
1060 }
1061
1062 if ( pPref->m_nAutosavesPerHour != autosaveSpinBox->value() ) {
1063 pPref->m_nAutosavesPerHour = autosaveSpinBox->value();
1064 m_changes =
1067 }
1068
1069 QString sPreferredLanguage = languageComboBox->currentData().toString();
1070 if ( sPreferredLanguage != m_sInitialLanguage ) {
1071 QMessageBox::information( this, "Hydrogen", tr( "Hydrogen must be restarted for language change to take effect" ));
1072 pPref->setPreferredLanguage( sPreferredLanguage );
1073 bGeneralOptionAltered = true;
1074 }
1075
1076 if ( bGeneralOptionAltered ) {
1077 m_changes =
1078 static_cast<H2Core::Preferences::Changes>(
1080 }
1081
1083
1084 pPref->setTheme( m_pCurrentTheme );
1085
1086 if ( m_bNeedDriverRestart ) {
1087 // Restart audio and MIDI drivers now that we updated all
1088 // values in Preferences.
1089 QApplication::setOverrideCursor( Qt::WaitCursor );
1090 pHydrogen->restartDrivers();
1091 QApplication::restoreOverrideCursor();
1092 }
1093
1094 pH2App->changePreferences( m_changes );
1095
1096 pPref->savePreferences();
1097 accept();
1098}
1099
1100
1102{
1103 UNUSED( index );
1105 m_bNeedDriverRestart = true;
1106}
1107
1109{
1110 m_pAudioDeviceTxt->setHostAPI( portaudioHostAPIComboBox->currentText() );
1112 m_bNeedDriverRestart = true;
1113}
1114
1116{
1118 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1119 auto pAudioDriver = Hydrogen::get_instance()->getAudioOutput();
1120
1121 // Reset info text
1123
1124 bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
1125 switch ( pPref->m_nSampleRate ) {
1126 case 44100:
1127 sampleRateComboBox->setCurrentIndex( 0 );
1128 break;
1129 case 48000:
1130 sampleRateComboBox->setCurrentIndex( 1 );
1131 break;
1132 case 88200:
1133 sampleRateComboBox->setCurrentIndex( 2 );
1134 break;
1135 case 96000:
1136 sampleRateComboBox->setCurrentIndex( 3 );
1137 break;
1138 default:
1139 ERRORLOG( QString("Wrong samplerate: %1").arg( pPref->m_nSampleRate ) );
1140 }
1141
1142 const auto selectedAudioDriver = Preferences::parseAudioDriver(
1143 driverComboBox->currentText() );
1144
1145 if ( selectedAudioDriver == Preferences::AudioDriver::Auto ) {
1146
1147 if ( dynamic_cast<H2Core::JackAudioDriver*>(pAudioDriver) != nullptr ) {
1149 }
1150 else if ( dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver) != nullptr ) {
1152 }
1153 else if ( dynamic_cast<H2Core::PortAudioDriver*>(pAudioDriver) != nullptr ) {
1155 }
1156 else if ( dynamic_cast<H2Core::CoreAudioDriver*>(pAudioDriver) != nullptr ) {
1158 }
1159 else if ( dynamic_cast<H2Core::PulseAudioDriver*>(pAudioDriver) != nullptr ) {
1161 }
1162 else if ( dynamic_cast<H2Core::OssDriver*>(pAudioDriver) != nullptr ) {
1164 }
1165 else {
1166
1167 m_pAudioDeviceTxt->setDriver( Preferences::AudioDriver::Null );
1168 m_pAudioDeviceTxt->setIsActive( false );
1169 m_pAudioDeviceTxt->lineEdit()->setText( "" );
1170 bufferSizeSpinBox->setIsActive( false );
1171 sampleRateComboBox->setIsActive( false );
1172 bufferSizeSpinBox->setToolTip( "" );
1173 sampleRateComboBox->setToolTip( "" );
1174 trackOutputComboBox->setIsActive( false );
1175 trackOutputComboBox->hide();
1176 trackOutputLbl->hide();
1177 trackOutsCheckBox->setEnabled( false );
1178 trackOutsCheckBox->hide();
1179 connectDefaultsCheckBox->setEnabled( false );
1180 connectDefaultsCheckBox->hide();
1181 enableTimebaseCheckBox->setEnabled( false );
1182 enableTimebaseCheckBox->hide();
1183 portaudioHostAPIComboBox->hide();
1184 portaudioHostAPILabel->hide();
1185 latencyTargetLabel->hide();
1186 latencyTargetSpinBox->hide();
1187 latencyValueLabel->hide();
1188 }
1189 }
1190 else if ( selectedAudioDriver == Preferences::AudioDriver::Oss ) {
1192 }
1193 else if ( selectedAudioDriver == Preferences::AudioDriver::Jack ) {
1195 }
1196 else if ( selectedAudioDriver == Preferences::AudioDriver::Alsa ) {
1198 }
1199 else if ( selectedAudioDriver == Preferences::AudioDriver::PortAudio ) {
1201 }
1202 else if ( selectedAudioDriver == Preferences::AudioDriver::CoreAudio ) {
1204 }
1205 else if ( selectedAudioDriver == Preferences::AudioDriver::PulseAudio ) {
1207 }
1208 else {
1209 ERRORLOG( QString( "Unknown driver [%1]" )
1210 .arg( Preferences::audioDriverToQString( selectedAudioDriver ) ) );
1211 }
1212
1213 metronomeVolumeSpinBox->setEnabled(true);
1214 bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
1215}
1216
1218
1219 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1220 auto pAudioDriver = Hydrogen::get_instance()->getAudioOutput();
1221 QString sInfo;
1222
1223 if ( driverComboBox->currentText() ==
1225 sInfo.append( tr("Automatic driver selection") )
1226 .append( "<br><br>" );
1227 }
1228
1229 if ( dynamic_cast<H2Core::JackAudioDriver*>(pAudioDriver) != nullptr ) {
1230 sInfo.append( "<b>" )
1231 .append( tr( "JACK Audio Connection Kit Driver" ) )
1232 .append( "</b><br>" )
1233 .append( tr( "Low latency audio driver" ) );
1234#ifndef H2CORE_HAVE_JACK
1235 sInfo.append( "<br><b><font color=" )
1236 .append( m_sColorRed ).append( ">")
1237 .append( pCommonStrings->getPreferencesNotCompiled() )
1238 .append( "</font></b>" );
1239#endif
1240 }
1241 else if ( dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver) != nullptr ) {
1242 sInfo.append( "<b>" ).append( tr( "ALSA Driver" ) )
1243 .append( "</b><br>" );
1244#ifndef H2CORE_HAVE_ALSA
1245 sInfo.append( "<br><b><font color=" )
1246 .append( m_sColorRed ).append( ">")
1247 .append( pCommonStrings->getPreferencesNotCompiled() )
1248 .append( "</font></b>" );
1249#else
1250 auto pAlsaDriver =
1251 dynamic_cast<H2Core::AlsaAudioDriver*>(pAudioDriver);
1252 if ( pAlsaDriver != nullptr ) {
1253 sInfo.append( "<br>" ).append( tr( "Currently connected to device: " ) )
1254 .append( "<b>" ).append( pAlsaDriver->m_sAlsaAudioDevice )
1255 .append( "</b>" );
1256 } else {
1257 ERRORLOG( "ALSA driver selected in PreferencesDialog but no ALSA driver running?" );
1258 }
1259#endif
1260 }
1261 else if ( dynamic_cast<H2Core::PortAudioDriver*>(pAudioDriver) != nullptr ) {
1262 sInfo.append( "<b>" ).append( tr( "PortAudio Driver" ) )
1263 .append( "</b><br>" );
1264#ifndef H2CORE_HAVE_PORTAUDIO
1265 sInfo.append( "<br><b><font color=" )
1266 .append( m_sColorRed ).append( ">")
1267 .append( pCommonStrings->getPreferencesNotCompiled() )
1268 .append( "</font></b>" );
1269#endif
1270 }
1271 else if ( dynamic_cast<H2Core::CoreAudioDriver*>(pAudioDriver) != nullptr ) {
1272 sInfo.append( "<b>" ).append( tr( "CoreAudio Driver" ) )
1273 .append( "</b><br>" );
1274#ifndef H2CORE_HAVE_COREAUDIO
1275 sInfo.append( "<br><b><font color=" )
1276 .append( m_sColorRed ).append( ">")
1277 .append( pCommonStrings->getPreferencesNotCompiled() )
1278 .append( "</font></b>" );
1279#endif
1280 }
1281 else if ( dynamic_cast<H2Core::PulseAudioDriver*>(pAudioDriver) != nullptr ) {
1282 sInfo.append( "<b>" ).append( tr( "PulseAudio Driver" ) )
1283 .append( "</b><br>" );
1284#ifndef H2CORE_HAVE_PULSEAUDIO
1285 sInfo.append( "<br><b><font color=" )
1286 .append( m_sColorRed ).append( ">")
1287 .append( pCommonStrings->getPreferencesNotCompiled() )
1288 .append( "</font></b>" );
1289#endif
1290 }
1291 else if ( dynamic_cast<H2Core::OssDriver*>(pAudioDriver) != nullptr ) {
1292 sInfo.append( "<b>" ).append( tr( "Open Sound System" ) )
1293 .append( "</b><br>" )
1294 .append( tr( "Simple audio driver [/dev/dsp]" ) );
1295#ifndef H2CORE_HAVE_OSS
1296 sInfo.append( "<br><b><font color=" )
1297 .append( m_sColorRed ).append( ">")
1298 .append( pCommonStrings->getPreferencesNotCompiled() )
1299 .append( "</font></b>" );
1300#endif
1301 }
1302 else {
1303
1304 if ( driverComboBox->currentText() ==
1306
1307 // Display the selected driver as well.
1308 sInfo.append( "<b>" )
1309 .append( tr( "Error starting audio driver" ) )
1310 .append( "</b><br><br>" );
1311 }
1312
1313 // Display the selected driver as well.
1314 sInfo.append( "NullDriver" )
1315 .append( "<br><br><b><font color=" )
1316 .append( m_sColorRed ).append( ">")
1317 .append( pCommonStrings->getAudioDriverNotPresent() )
1318 .append( "</font></b>" );
1319 }
1320
1321 driverInfoLbl->setText( sInfo );
1322}
1323
1325 auto pPref = H2Core::Preferences::get_instance();
1326
1327 m_pAudioDeviceTxt->setDriver( Preferences::AudioDriver::Oss );
1328 m_pAudioDeviceTxt->setIsActive(true);
1329 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sOSSDevice );
1330 bufferSizeSpinBox->setIsActive(true);
1331 sampleRateComboBox->setIsActive(true);
1332 trackOutputComboBox->hide();
1333 trackOutputLbl->hide();
1334 connectDefaultsCheckBox->hide();
1335 enableTimebaseCheckBox->hide();
1336 trackOutsCheckBox->hide();
1337 portaudioHostAPIComboBox->hide();
1338 portaudioHostAPILabel->hide();
1339 latencyTargetLabel->hide();
1340 latencyTargetSpinBox->hide();
1341 latencyValueLabel->hide();
1342
1343 bufferSizeSpinBox->setToolTip( "" );
1344 sampleRateComboBox->setToolTip( "" );
1345}
1346
1348 auto pPref = H2Core::Preferences::get_instance();
1349
1350 m_pAudioDeviceTxt->setDriver( Preferences::AudioDriver::Alsa );
1351 m_pAudioDeviceTxt->setIsActive(true);
1352 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sAlsaAudioDevice );
1353 bufferSizeSpinBox->setIsActive(true);
1354 sampleRateComboBox->setIsActive(true);
1355 trackOutputComboBox->hide();
1356 trackOutputLbl->hide();
1357 connectDefaultsCheckBox->hide();
1358 enableTimebaseCheckBox->hide();
1359 trackOutsCheckBox->hide();
1360 portaudioHostAPIComboBox->hide();
1361 portaudioHostAPILabel->hide();
1362 latencyTargetLabel->hide();
1363 latencyTargetSpinBox->hide();
1364 latencyValueLabel->hide();
1365
1366 bufferSizeSpinBox->setToolTip( "" );
1367 sampleRateComboBox->setToolTip( "" );
1368}
1369
1371 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1372
1373 m_pAudioDeviceTxt->setDriver( Preferences::AudioDriver::Jack );
1374 m_pAudioDeviceTxt->setIsActive(false);
1375 m_pAudioDeviceTxt->lineEdit()->setText( "" );
1376 bufferSizeSpinBox->setIsActive(false);
1377 sampleRateComboBox->setIsActive(false);
1378 trackOutputComboBox->setIsActive( true );
1379 connectDefaultsCheckBox->setEnabled( true );
1380 enableTimebaseCheckBox->setEnabled( true );
1381 trackOutsCheckBox->setEnabled( true );
1382 trackOutputComboBox->show();
1383 trackOutputLbl->show();
1384 connectDefaultsCheckBox->show();
1385 enableTimebaseCheckBox->show();
1386 trackOutsCheckBox->show();
1387 portaudioHostAPIComboBox->hide();
1388 portaudioHostAPILabel->hide();
1389 latencyTargetLabel->hide();
1390 latencyTargetSpinBox->hide();
1391 latencyValueLabel->hide();
1392
1393 bufferSizeSpinBox->setToolTip( pCommonStrings->getPreferencesJackTooltip() );
1394 sampleRateComboBox->setToolTip( pCommonStrings->getPreferencesJackTooltip() );
1395}
1396
1398 auto pPref = H2Core::Preferences::get_instance();
1399
1400 m_pAudioDeviceTxt->setDriver( Preferences::AudioDriver::CoreAudio );
1401 m_pAudioDeviceTxt->setIsActive( true );
1402 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sCoreAudioDevice );
1403 bufferSizeSpinBox->setIsActive( true );
1404 sampleRateComboBox->setIsActive(true);
1405 trackOutputComboBox->hide();
1406 trackOutputLbl->hide();
1407 connectDefaultsCheckBox->hide();
1408 enableTimebaseCheckBox->hide();
1409 trackOutsCheckBox->hide();
1410 portaudioHostAPIComboBox->hide();
1411 portaudioHostAPILabel->hide();
1412 latencyTargetLabel->hide();
1413 latencyTargetSpinBox->hide();
1414 latencyValueLabel->hide();
1415
1416 bufferSizeSpinBox->setToolTip( "" );
1417 sampleRateComboBox->setToolTip( "" );
1418}
1419
1421 auto pPref = H2Core::Preferences::get_instance();
1422
1423 m_pAudioDeviceTxt->setDriver( Preferences::AudioDriver::PortAudio );
1424 m_pAudioDeviceTxt->setIsActive( true );
1425 m_pAudioDeviceTxt->lineEdit()->setText( pPref->m_sPortAudioDevice );
1426 bufferSizeSpinBox->setIsActive(false);
1427 sampleRateComboBox->setIsActive(true);
1428 trackOutputComboBox->hide();
1429 trackOutputLbl->hide();
1430 connectDefaultsCheckBox->hide();
1431 enableTimebaseCheckBox->hide();
1432 trackOutsCheckBox->hide();
1433 portaudioHostAPIComboBox->show();
1434 portaudioHostAPILabel->show();
1435 latencyTargetLabel->show();
1436 latencyTargetSpinBox->show();
1437 latencyValueLabel->show();
1438
1439 const auto pAudioDriver = H2Core::Hydrogen::get_instance()->getAudioOutput();
1440 int nLatency;
1441 if ( pAudioDriver == nullptr ) {
1442 ERRORLOG( "AudioDriver is not ready!" );
1443 return;
1444 }
1445 else {
1446 nLatency = pAudioDriver->getLatency();
1447 }
1448 latencyValueLabel->setText( QString("Current: %1 frames").arg( nLatency ) );
1449
1450 bufferSizeSpinBox->setToolTip( "" );
1451 sampleRateComboBox->setToolTip( "" );
1452}
1453
1455
1456 m_pAudioDeviceTxt->setDriver( Preferences::AudioDriver::PulseAudio );
1457 m_pAudioDeviceTxt->setIsActive(false);
1458 m_pAudioDeviceTxt->lineEdit()->setText("");
1459 bufferSizeSpinBox->setIsActive(true);
1460 sampleRateComboBox->setIsActive(true);
1461 trackOutputComboBox->hide();
1462 trackOutputLbl->hide();
1463 connectDefaultsCheckBox->hide();
1464 enableTimebaseCheckBox->hide();
1465 trackOutsCheckBox->hide();
1466 portaudioHostAPIComboBox->hide();
1467 portaudioHostAPILabel->hide();
1468 latencyTargetLabel->hide();
1469 latencyTargetSpinBox->hide();
1470 latencyValueLabel->hide();
1471
1472 bufferSizeSpinBox->setToolTip( "" );
1473 sampleRateComboBox->setToolTip( "" );
1474}
1475
1477 auto pPref = Preferences::get_instance();
1478
1479 m_pCurrentTheme->getFontTheme()->m_sApplicationFontFamily = font.family();
1480 pPref->setApplicationFontFamily( font.family() );
1481
1482 m_changes =
1483 static_cast<H2Core::Preferences::Changes>(
1485
1487}
1488
1490 auto pPref = Preferences::get_instance();
1491
1492 m_pCurrentTheme->getFontTheme()->m_sLevel2FontFamily = font.family();
1493 pPref->setLevel2FontFamily( font.family() );
1494
1495 m_changes =
1496 static_cast<H2Core::Preferences::Changes>(
1498
1500}
1501
1503 auto pPref = Preferences::get_instance();
1504
1505 m_pCurrentTheme->getFontTheme()->m_sLevel3FontFamily = font.family();
1506 pPref->setLevel3FontFamily( font.family() );
1507
1508 m_changes =
1509 static_cast<H2Core::Preferences::Changes>(
1511
1513}
1514
1521
1523 auto pPref = Preferences::get_instance();
1524
1525 switch ( nIndex ) {
1526 case 0:
1527 pPref->setFontSize( FontTheme::FontSize::Small );
1528 m_pCurrentTheme->getFontTheme()->m_fontSize = FontTheme::FontSize::Small;
1529 break;
1530 case 1:
1531 pPref->setFontSize( FontTheme::FontSize::Medium );
1532 m_pCurrentTheme->getFontTheme()->m_fontSize = FontTheme::FontSize::Medium;
1533 break;
1534 case 2:
1535 pPref->setFontSize( FontTheme::FontSize::Large );
1536 m_pCurrentTheme->getFontTheme()->m_fontSize = FontTheme::FontSize::Large;
1537 break;
1538 default:
1539 ERRORLOG( QString( "Unknown font size: %1" ).arg( nIndex ) );
1540 }
1541
1542 m_changes =
1543 static_cast<H2Core::Preferences::Changes>(
1545
1547}
1548
1550 if ( static_cast<InterfaceTheme::Layout>(nIndex) !=
1551 m_pPreviousTheme->getInterfaceTheme()->m_layout ||
1552 m_pCurrentTheme->getInterfaceTheme()->m_scalingPolicy !=
1553 m_pPreviousTheme->getInterfaceTheme()->m_scalingPolicy ) {
1554 UIChangeWarningLabel->show();
1555 } else {
1556 UIChangeWarningLabel->hide();
1557 }
1558 m_pCurrentTheme->getInterfaceTheme()->m_layout = static_cast<InterfaceTheme::Layout>(nIndex);
1560
1561 m_changes =
1562 static_cast<H2Core::Preferences::Changes>(
1564
1566}
1567
1569 if ( static_cast<InterfaceTheme::ScalingPolicy>(nIndex) !=
1570 m_pPreviousTheme->getInterfaceTheme()->m_scalingPolicy ||
1571 m_pCurrentTheme->getInterfaceTheme()->m_layout !=
1572 m_pPreviousTheme->getInterfaceTheme()->m_layout ) {
1573 UIChangeWarningLabel->show();
1574 } else {
1575 UIChangeWarningLabel->hide();
1576 }
1577 m_pCurrentTheme->getInterfaceTheme()->m_scalingPolicy = static_cast<InterfaceTheme::ScalingPolicy>(nIndex);
1579
1580 m_changes =
1581 static_cast<H2Core::Preferences::Changes>(
1583
1585}
1586
1597
1600 m_pCurrentTheme->getInterfaceTheme()->m_nVisiblePatternColors = nIndex;
1601 for ( int ii = 0; ii < Preferences::get_instance()->getMaxPatternColors(); ii++ ) {
1602 if ( ii < nIndex ) {
1603 m_colorSelectionButtons[ ii ]->show();
1604 } else {
1605 m_colorSelectionButtons[ ii ]->hide();
1606 }
1607 }
1608
1609 m_changes =
1610 static_cast<H2Core::Preferences::Changes>(
1612
1614}
1615
1617 int nMaxPatternColors = Preferences::get_instance()->getMaxPatternColors();
1618 std::vector<QColor> colors( nMaxPatternColors );
1619 for ( int ii = 0; ii < nMaxPatternColors; ii++ ) {
1620 colors[ ii ] = m_colorSelectionButtons[ ii ]->getColor();
1621 }
1622 m_pCurrentTheme->getInterfaceTheme()->m_patternColors = colors;
1624
1625 m_changes =
1626 static_cast<H2Core::Preferences::Changes>(
1628
1630}
1631
1633 m_pCurrentTheme->getInterfaceTheme()->m_coloringMethod = static_cast<H2Core::InterfaceTheme::ColoringMethod>(nIndex);
1635
1636 if ( nIndex == 0 ) {
1637 coloringMethodAuxSpinBox->hide();
1638 coloringMethodAuxLabel->hide();
1639 colorSelectionLabel->hide();
1640 for ( int ii = 0; ii < m_pCurrentTheme->getInterfaceTheme()->m_nMaxPatternColors; ii++ ) {
1641 m_colorSelectionButtons[ ii ]->hide();
1642 }
1643 } else {
1644 coloringMethodAuxSpinBox->show();
1645 coloringMethodAuxLabel->show();
1646 colorSelectionLabel->show();
1647 for ( int ii = 0; ii < m_pCurrentTheme->getInterfaceTheme()->m_nVisiblePatternColors; ii++ ) {
1648 m_colorSelectionButtons[ ii ]->show();
1649 }
1650 }
1651
1652 m_changes =
1653 static_cast<H2Core::Preferences::Changes>(
1655
1657}
1658
1661
1662 if ( nIndex == 0 ) {
1663 m_pCurrentTheme->getInterfaceTheme()->m_fMixerFalloffSpeed = InterfaceTheme::FALLOFF_SLOW;
1665 } else if ( nIndex == 1 ) {
1666 m_pCurrentTheme->getInterfaceTheme()->m_fMixerFalloffSpeed = InterfaceTheme::FALLOFF_NORMAL;
1668 } else if ( nIndex == 2 ) {
1669 m_pCurrentTheme->getInterfaceTheme()->m_fMixerFalloffSpeed = InterfaceTheme::FALLOFF_FAST;
1671 } else {
1672 ERRORLOG( QString("Wrong mixerFalloff value = %1").arg( nIndex ) );
1673 }
1674
1675 m_changes =
1676 static_cast<H2Core::Preferences::Changes>(
1678
1680}
1681
1687
1689{
1690 UNUSED( i );
1691 m_bNeedDriverRestart = true;
1692}
1693
1694
1695
1696
1701
1702
1703
1705{
1706 QApplication::setOverrideCursor( Qt::WaitCursor );
1707
1710 auto pHydrogen = Hydrogen::get_instance();
1711 pHydrogen->restartDrivers();
1712
1713 QApplication::restoreOverrideCursor();
1714
1715 if ( pHydrogen->getAudioOutput() == nullptr ||
1716 dynamic_cast<NullDriver*>(pHydrogen->getAudioOutput()) != nullptr ) {
1717 QMessageBox::critical( this, "Hydrogen",
1718 tr( "Unable to start audio driver" ) );
1719 }
1720
1721 pPref->savePreferences();
1722 m_bNeedDriverRestart = false;
1724}
1725
1727{
1728 UNUSED( index );
1729 m_bNeedDriverRestart = true;
1730}
1731
1733{
1734 UNUSED( index );
1735 m_bNeedDriverRestart = true;
1736}
1737
1739{
1740 UNUSED( index );
1741
1742 QString sStyle = styleComboBox->currentText();
1743 if ( sStyle != m_pCurrentTheme->getInterfaceTheme()->m_sQTStyle ) {
1744
1745 // Instant visual feedback.
1746 QApplication *pQApp = (HydrogenApp::get_instance())->getMainForm()->m_pQApp;
1747 pQApp->setStyle( sStyle );
1749 pPref->setQTStyle( sStyle );
1750
1751 m_pCurrentTheme->getInterfaceTheme()->m_sQTStyle = sStyle;
1752
1753 m_changes =
1754 static_cast<H2Core::Preferences::Changes>(
1756
1758 }
1759}
1760
1761
1762
1764{
1765 if ( useLashCheckbox->isChecked() ){
1767 }
1768 else
1769 {
1771 }
1772 QMessageBox::information ( this, "Hydrogen", tr ( "Please restart hydrogen to enable/disable LASH support" ) );
1773}
1774
1779
1784
1786{
1787 if ( toggled ) {
1788 enableOscFeedbackCheckbox->show();
1789 incomingOscPortSpinBox->show();
1790 incomingOscPortLabel->show();
1791 if ( Preferences::get_instance()->m_nOscTemporaryPort != -1 ) {
1792 oscTemporaryPortLabel->show();
1793 oscTemporaryPort->show();
1794 }
1795 } else {
1796 enableOscFeedbackCheckbox->hide();
1797 incomingOscPortSpinBox->hide();
1798 incomingOscPortLabel->hide();
1799 oscTemporaryPortLabel->hide();
1800 oscTemporaryPort->hide();
1801 }
1802}
1803
1804QColor* PreferencesDialog::getColorById( int nId, std::shared_ptr<H2Core::ColorTheme> pColorTheme ) const {
1805 switch( nId ) {
1806 case 0x100: return &pColorTheme->m_windowColor;
1807 case 0x101: return &pColorTheme->m_windowTextColor;
1808 case 0x102: return &pColorTheme->m_baseColor;
1809 case 0x103: return &pColorTheme->m_alternateBaseColor;
1810 case 0x104: return &pColorTheme->m_textColor;
1811 case 0x105: return &pColorTheme->m_buttonColor;
1812 case 0x106: return &pColorTheme->m_buttonTextColor;
1813 case 0x107: return &pColorTheme->m_lightColor;
1814 case 0x108: return &pColorTheme->m_midLightColor;
1815 case 0x109: return &pColorTheme->m_midColor;
1816 case 0x10a: return &pColorTheme->m_darkColor;
1817 case 0x10b: return &pColorTheme->m_shadowTextColor;
1818 case 0x10c: return &pColorTheme->m_highlightColor;
1819 case 0x10d: return &pColorTheme->m_highlightedTextColor;
1820 case 0x10e: return &pColorTheme->m_selectionHighlightColor;
1821 case 0x10f: return &pColorTheme->m_selectionInactiveColor;
1822 case 0x110: return &pColorTheme->m_toolTipBaseColor;
1823 case 0x111: return &pColorTheme->m_toolTipTextColor;
1824 case 0x200: return &pColorTheme->m_widgetColor;
1825 case 0x201: return &pColorTheme->m_widgetTextColor;
1826 case 0x202: return &pColorTheme->m_accentColor;
1827 case 0x203: return &pColorTheme->m_accentTextColor;
1828 case 0x204: return &pColorTheme->m_buttonRedColor;
1829 case 0x205: return &pColorTheme->m_buttonRedTextColor;
1830 case 0x206: return &pColorTheme->m_spinBoxColor;
1831 case 0x207: return &pColorTheme->m_spinBoxTextColor;
1832 case 0x208: return &pColorTheme->m_playheadColor;
1833 case 0x209: return &pColorTheme->m_cursorColor;
1834 case 0x300: return &pColorTheme->m_songEditor_backgroundColor;
1835 case 0x301: return &pColorTheme->m_songEditor_alternateRowColor;
1836 case 0x302: return &pColorTheme->m_songEditor_virtualRowColor;
1837 case 0x303: return &pColorTheme->m_songEditor_selectedRowColor;
1838 case 0x304: return &pColorTheme->m_songEditor_selectedRowTextColor;
1839 case 0x305: return &pColorTheme->m_songEditor_lineColor;
1840 case 0x306: return &pColorTheme->m_songEditor_textColor;
1841 case 0x307: return &pColorTheme->m_songEditor_automationBackgroundColor;
1842 case 0x308: return &pColorTheme->m_songEditor_automationLineColor;
1843 case 0x309: return &pColorTheme->m_songEditor_automationNodeColor;
1844 case 0x30a: return &pColorTheme->m_songEditor_stackedModeOnColor;
1845 case 0x30b: return &pColorTheme->m_songEditor_stackedModeOnNextColor;
1846 case 0x30c: return &pColorTheme->m_songEditor_stackedModeOffNextColor;
1847 case 0x400: return &pColorTheme->m_patternEditor_backgroundColor;
1848 case 0x401: return &pColorTheme->m_patternEditor_alternateRowColor;
1849 case 0x402: return &pColorTheme->m_patternEditor_selectedRowColor;
1850 case 0x403: return &pColorTheme->m_patternEditor_selectedRowTextColor;
1851 case 0x404: return &pColorTheme->m_patternEditor_octaveRowColor;
1852 case 0x405: return &pColorTheme->m_patternEditor_textColor;
1853 case 0x406: return &pColorTheme->m_patternEditor_noteVelocityFullColor;
1854 case 0x407: return &pColorTheme->m_patternEditor_noteVelocityDefaultColor;
1855 case 0x408: return &pColorTheme->m_patternEditor_noteVelocityHalfColor;
1856 case 0x409: return &pColorTheme->m_patternEditor_noteVelocityZeroColor;
1857 case 0x40a: return &pColorTheme->m_patternEditor_noteOffColor;
1858 case 0x40b: return &pColorTheme->m_patternEditor_lineColor;
1859 case 0x40c: return &pColorTheme->m_patternEditor_line1Color;
1860 case 0x40d: return &pColorTheme->m_patternEditor_line2Color;
1861 case 0x40e: return &pColorTheme->m_patternEditor_line3Color;
1862 case 0x40f: return &pColorTheme->m_patternEditor_line4Color;
1863 case 0x410: return &pColorTheme->m_patternEditor_line5Color;
1864 default: return nullptr;
1865 }
1866
1867 return nullptr;
1868}
1869
1870void PreferencesDialog::setColorById( int nId, const QColor& color,
1871 std::shared_ptr<H2Core::ColorTheme> pColorTheme ) {
1872 switch( nId ) {
1873 case 0x100: pColorTheme->m_windowColor = color;
1874 break;
1875 case 0x101: pColorTheme->m_windowTextColor = color;
1876 break;
1877 case 0x102: pColorTheme->m_baseColor = color;
1878 break;
1879 case 0x103: pColorTheme->m_alternateBaseColor = color;
1880 break;
1881 case 0x104: pColorTheme->m_textColor = color;
1882 break;
1883 case 0x105: pColorTheme->m_buttonColor = color;
1884 break;
1885 case 0x106: pColorTheme->m_buttonTextColor = color;
1886 break;
1887 case 0x107: pColorTheme->m_lightColor = color;
1888 break;
1889 case 0x108: pColorTheme->m_midLightColor = color;
1890 break;
1891 case 0x109: pColorTheme->m_midColor = color;
1892 break;
1893 case 0x10a: pColorTheme->m_darkColor = color;
1894 break;
1895 case 0x10b: pColorTheme->m_shadowTextColor = color;
1896 break;
1897 case 0x10c: pColorTheme->m_highlightColor = color;
1898 break;
1899 case 0x10d: pColorTheme->m_highlightedTextColor = color;
1900 break;
1901 case 0x10e: pColorTheme->m_selectionHighlightColor = color;
1902 break;
1903 case 0x10f: pColorTheme->m_selectionInactiveColor = color;
1904 break;
1905 case 0x110: pColorTheme->m_toolTipBaseColor = color;
1906 break;
1907 case 0x111: pColorTheme->m_toolTipTextColor = color;
1908 break;
1909 case 0x200: pColorTheme->m_widgetColor = color;
1910 break;
1911 case 0x201: pColorTheme->m_widgetTextColor = color;
1912 break;
1913 case 0x202: pColorTheme->m_accentColor = color;
1914 break;
1915 case 0x203: pColorTheme->m_accentTextColor = color;
1916 break;
1917 case 0x204: pColorTheme->m_buttonRedColor = color;
1918 break;
1919 case 0x205: pColorTheme->m_buttonRedTextColor = color;
1920 break;
1921 case 0x206: pColorTheme->m_spinBoxColor = color;
1922 break;
1923 case 0x207: pColorTheme->m_spinBoxTextColor = color;
1924 break;
1925 case 0x208: pColorTheme->m_playheadColor = color;
1926 break;
1927 case 0x209: pColorTheme->m_cursorColor = color;
1928 break;
1929 case 0x300: pColorTheme->m_songEditor_backgroundColor = color;
1930 break;
1931 case 0x301: pColorTheme->m_songEditor_alternateRowColor = color;
1932 break;
1933 case 0x302: pColorTheme->m_songEditor_virtualRowColor = color;
1934 break;
1935 case 0x303: pColorTheme->m_songEditor_selectedRowColor = color;
1936 break;
1937 case 0x304: pColorTheme->m_songEditor_selectedRowTextColor = color;
1938 break;
1939 case 0x305: pColorTheme->m_songEditor_lineColor = color;
1940 break;
1941 case 0x306: pColorTheme->m_songEditor_textColor = color;
1942 break;
1943 case 0x307: pColorTheme->m_songEditor_automationBackgroundColor = color;
1944 break;
1945 case 0x308: pColorTheme->m_songEditor_automationLineColor = color;
1946 break;
1947 case 0x309: pColorTheme->m_songEditor_automationNodeColor = color;
1948 break;
1949 case 0x30a: pColorTheme->m_songEditor_stackedModeOnColor = color;
1950 break;
1951 case 0x30b: pColorTheme->m_songEditor_stackedModeOnNextColor = color;
1952 break;
1953 case 0x30c: pColorTheme->m_songEditor_stackedModeOffNextColor = color;
1954 break;
1955 case 0x400: pColorTheme->m_patternEditor_backgroundColor = color;
1956 break;
1957 case 0x401: pColorTheme->m_patternEditor_alternateRowColor = color;
1958 break;
1959 case 0x402: pColorTheme->m_patternEditor_selectedRowColor = color;
1960 break;
1961 case 0x403: pColorTheme->m_patternEditor_selectedRowTextColor = color;
1962 break;
1963 case 0x404: pColorTheme->m_patternEditor_octaveRowColor = color;
1964 break;
1965 case 0x405: pColorTheme->m_patternEditor_textColor = color;
1966 break;
1967 case 0x406: pColorTheme->m_patternEditor_noteVelocityFullColor = color;
1968 break;
1969 case 0x407: pColorTheme->m_patternEditor_noteVelocityDefaultColor = color;
1970 break;
1971 case 0x408: pColorTheme->m_patternEditor_noteVelocityHalfColor = color;
1972 break;
1973 case 0x409: pColorTheme->m_patternEditor_noteVelocityZeroColor = color;
1974 break;
1975 case 0x40a: pColorTheme->m_patternEditor_noteOffColor = color;
1976 break;
1977 case 0x40b: pColorTheme->m_patternEditor_lineColor = color;
1978 break;
1979 case 0x40c: pColorTheme->m_patternEditor_line1Color = color;
1980 break;
1981 case 0x40d: pColorTheme->m_patternEditor_line2Color = color;
1982 break;
1983 case 0x40e: pColorTheme->m_patternEditor_line3Color = color;
1984 break;
1985 case 0x40f: pColorTheme->m_patternEditor_line4Color = color;
1986 break;
1987 case 0x410: pColorTheme->m_patternEditor_line5Color = color;
1988 break;
1989 default: DEBUGLOG( "Unknown ID" );
1990 }
1991}
1992
1994 if( pItem == nullptr) {
1995 ERRORLOG( "NULL item" );
1996 return;
1997 }
1998
1999 int nId = pItem->getId();
2000 if( nId == 0 ) {
2001 // Node without a color used as a heading.
2002 return;
2003 }
2004
2005 QColor* pCurrentColor = getColorById( nId, m_pCurrentTheme->getColorTheme() );
2006 if ( pCurrentColor == nullptr ) {
2007 ERRORLOG( QString( "Unable to get current color for id [%1]" ).arg( nId ) );
2008 return;
2009 }
2010 QColor* pPreviousColor = getColorById( nId, m_pPreviousTheme->getColorTheme() );
2011 if ( pPreviousColor == nullptr ) {
2012 ERRORLOG( QString( "Unable to get previous color for id [%1]" ).arg( nId ) );
2013 return;
2014 }
2015
2016 const QColor& currentColor = *pCurrentColor;
2017 const QColor& previousColor = *pPreviousColor;
2018
2019 QFont font = pItem->font( 0 );
2020 font.setWeight( currentColor != previousColor ? QFont::Black : QFont::Normal );
2021 font.setItalic( currentColor != previousColor );
2022 pItem->setFont( 0, font );
2023 pItem->setData( 0, Qt::DecorationRole, currentColor );
2024}
2025
2027 QTreeWidgetItemIterator it( colorTree );
2028 while ( *it ) {
2029 setColorTreeItemDirty( static_cast<ColorTreeItem*>( *it ) );
2030 ++it;
2031 }
2032}
2033
2035 ColorTreeItem* pItem = static_cast<ColorTreeItem*>(colorTree->selectedItems()[0]);
2036
2037 if( pItem == nullptr ) {
2038 // Unset title
2039 m_pCurrentColor = nullptr;
2040 updateColors();
2041 return;
2042 }
2043
2044 int nId = static_cast<ColorTreeItem*>(pItem)->getId();
2045 m_nCurrentId = nId;
2046
2047 if ( nId == 0x000 ) {
2048 // A text node without color was clicked.
2049 m_pCurrentColor = nullptr;
2050 } else {
2051 m_pCurrentColor = getColorById( nId, m_pCurrentTheme->getColorTheme() );
2052 }
2053 updateColors();
2054}
2055
2057 setColorById( m_nCurrentId, colorButton->getColor(), m_pCurrentTheme->getColorTheme() );
2059 updateColors();
2060}
2061
2063 int r, g, b, h, s, v;
2064
2065 // If m_pCurrentColor is nullptr, it will be converted to false.
2066 rslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2067 gslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2068 bslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2069 hslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2070 sslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2071 vslider->setEnabled( static_cast<bool>(m_pCurrentColor) );
2072 rval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2073 gval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2074 bval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2075 hval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2076 sval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2077 vval->setEnabled( static_cast<bool>(m_pCurrentColor) );
2078 colorButton->setEnabled( static_cast<bool>(m_pCurrentColor) );
2079 if ( m_pCurrentColor == nullptr ) {
2080 DEBUGLOG( "No current color yet" );
2081 return;
2082 }
2083
2084 QColor currentColor(*m_pCurrentColor);
2085
2086 colorButton->setColor( currentColor );
2087
2088 m_pCurrentColor->getRgb(&r, &g, &b);
2089 m_pCurrentColor->getHsv(&h, &s, &v);
2090
2091 rslider->blockSignals(true);
2092 gslider->blockSignals(true);
2093 bslider->blockSignals(true);
2094 hslider->blockSignals(true);
2095 sslider->blockSignals(true);
2096 vslider->blockSignals(true);
2097 rval->blockSignals(true);
2098 gval->blockSignals(true);
2099 bval->blockSignals(true);
2100 hval->blockSignals(true);
2101 sval->blockSignals(true);
2102 vval->blockSignals(true);
2103
2104 rslider->setValue(r);
2105 gslider->setValue(g);
2106 bslider->setValue(b);
2107 hslider->setValue(h);
2108 sslider->setValue(s);
2109 vslider->setValue(v);
2110 rval->setValue(r);
2111 gval->setValue(g);
2112 bval->setValue(b);
2113 hval->setValue(h);
2114 sval->setValue(s);
2115 vval->setValue(v);
2116
2117 rslider->blockSignals(false);
2118 gslider->blockSignals(false);
2119 bslider->blockSignals(false);
2120 hslider->blockSignals(false);
2121 sslider->blockSignals(false);
2122 vslider->blockSignals(false);
2123 rval->blockSignals(false);
2124 gval->blockSignals(false);
2125 bval->blockSignals(false);
2126 hval->blockSignals(false);
2127 sval->blockSignals(false);
2128 vval->blockSignals(false);
2129
2132
2133 m_changes =
2134 static_cast<H2Core::Preferences::Changes>(
2136
2138}
2139
2141 if ( m_pColorSliderTimer->isActive() ) {
2142 m_pColorSliderTimer->stop();
2143 }
2144 m_pColorSliderTimer->start( 25 );
2145}
2146
2148 int r, g, b;
2149 if ( m_pCurrentColor != nullptr ) {
2150 m_pCurrentColor->getRgb( &r, &g, &b );
2151 m_pCurrentColor->setRgb( nValue, g, b );
2152 }
2154}
2155
2157 int r, g, b;
2158 if ( m_pCurrentColor != nullptr ) {
2159 m_pCurrentColor->getRgb( &r, &g, &b );
2160 m_pCurrentColor->setRgb( r, nValue, b );
2161 }
2163}
2164
2166 int r, g, b;
2167 if ( m_pCurrentColor != nullptr ) {
2168 m_pCurrentColor->getRgb( &r, &g, &b );
2169 m_pCurrentColor->setRgb( r, g, nValue );
2170 }
2172}
2173
2175 int h, s, v;
2176 if ( m_pCurrentColor != nullptr ) {
2177 m_pCurrentColor->getHsv( &h, &s, &v );
2178 m_pCurrentColor->setHsv( nValue, s, v );
2179 }
2181}
2182
2184 int h, s, v;
2185 if ( m_pCurrentColor != nullptr ) {
2186 m_pCurrentColor->getHsv( &h, &s, &v );
2187 m_pCurrentColor->setHsv( h, nValue, v );
2188 }
2190}
2191
2193 int h, s, v;
2194 if ( m_pCurrentColor != nullptr ) {
2195 m_pCurrentColor->getHsv( &h, &s, &v );
2196 m_pCurrentColor->setHsv( h, s, nValue );
2197 }
2199}
2200
2203 if ( ! H2Core::Filesystem::dir_readable( sPath, false ) ){
2204 sPath = Filesystem::sys_theme_dir();
2205 }
2206
2207 QString sTitle = tr( "Import Theme" );
2208 FileDialog fd( this );
2209 fd.setWindowTitle( sTitle );
2210 fd.setDirectory( sPath );
2211 fd.setFileMode( QFileDialog::ExistingFile );
2212 fd.setNameFilter( Filesystem::themes_filter_name );
2213 fd.setAcceptMode( QFileDialog::AcceptOpen );
2214 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::sys_theme_dir() ) );
2215 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::usr_theme_dir() ) );
2216 fd.setDefaultSuffix( Filesystem::themes_ext );
2217
2218 if ( fd.exec() != QDialog::Accepted ) {
2219 return;
2220 }
2221
2222 QFileInfo fileInfo( fd.selectedFiles().first() );
2223 QString sSelectedPath = fileInfo.absoluteFilePath();
2224 H2Core::Preferences::get_instance()->setLastImportThemeDirectory( fd.directory().absolutePath() );
2225
2226 if ( sSelectedPath.isEmpty() ) {
2227 QMessageBox::warning( this, "Hydrogen", tr("Theme couldn't be found.") );
2228 return;
2229 }
2230
2231 auto pTheme = Theme::importTheme( sSelectedPath );
2232 m_pCurrentTheme = std::make_shared<Theme>( pTheme );
2234 if ( m_nCurrentId == 0 ) {
2235 m_pCurrentColor = nullptr;
2238
2239 m_changes =
2240 static_cast<H2Core::Preferences::Changes>(
2242
2244 }
2246
2247 HydrogenApp::get_instance()->showStatusBarMessage( tr( "Theme imported from " ) + sSelectedPath );
2248
2249 m_changes =
2250 static_cast<H2Core::Preferences::Changes>(
2252
2254
2255}
2256
2259 if ( ! H2Core::Filesystem::dir_writable( sPath, false ) ){
2260 sPath = Filesystem::usr_theme_dir();
2261 }
2262 QString sTitle = tr( "Export Theme" );
2263 FileDialog fd( this );
2264 fd.setWindowTitle( sTitle );
2265 fd.setDirectory( sPath );
2266 fd.setFileMode( QFileDialog::AnyFile );
2267 fd.setNameFilter( Filesystem::themes_filter_name );
2268 fd.setAcceptMode( QFileDialog::AcceptSave );
2269 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::sys_theme_dir() ) );
2270 fd.setSidebarUrls( fd.sidebarUrls() << QUrl::fromLocalFile( Filesystem::usr_theme_dir() ) );
2271 fd.setDefaultSuffix( Filesystem::themes_ext );
2272
2273 if ( fd.exec() != QDialog::Accepted ) {
2274 return;
2275 }
2276
2277 QFileInfo fileInfo( fd.selectedFiles().first() );
2278 QString sSelectedPath = fileInfo.absoluteFilePath();
2279
2280 if ( sSelectedPath.isEmpty() ||
2281 ! Theme::exportTheme( sSelectedPath, m_pCurrentTheme ) ) {
2282 QMessageBox::warning( this, "Hydrogen", tr("Theme can not be exported.") );
2283 return;
2284 }
2285
2286 H2Core::Preferences::get_instance()->setLastExportThemeDirectory( fd.directory().absolutePath() );
2287
2288 HydrogenApp::get_instance()->showStatusBarMessage( tr( "Theme exported to " ) +
2289 sSelectedPath );
2290
2291}
2292
2302
2303
2304void PreferencesDialog::updateAppearanceTab( const std::shared_ptr<H2Core::Theme> pTheme ) {
2305
2306 // Colors
2307 m_pCurrentColor = getColorById( m_nCurrentId, pTheme->getColorTheme() );
2308 updateColors();
2309
2310 // Interface
2311 float fFalloffSpeed = pTheme->getInterfaceTheme()->m_fMixerFalloffSpeed;
2312 if ( fFalloffSpeed == InterfaceTheme::FALLOFF_SLOW ) {
2313 mixerFalloffComboBox->setCurrentIndex( 0 );
2314 }
2315 else if ( fFalloffSpeed == InterfaceTheme::FALLOFF_NORMAL ) {
2316 mixerFalloffComboBox->setCurrentIndex( 1 );
2317 }
2318 else if ( fFalloffSpeed == InterfaceTheme::FALLOFF_FAST ) {
2319 mixerFalloffComboBox->setCurrentIndex( 2 );
2320 }
2321 else {
2322 ERRORLOG( QString("PreferencesDialog: wrong mixerFalloff value = %1").arg( fFalloffSpeed ) );
2323 }
2324 uiLayoutComboBox->setCurrentIndex( static_cast<int>( pTheme->getInterfaceTheme()->m_layout ) );
2325
2326#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
2327 uiScalingPolicyComboBox->setCurrentIndex( static_cast<int>( pTheme->getInterfaceTheme()->m_scalingPolicy ) );
2328#else
2329 uiScalingPolicyComboBox->setEnabled( false );
2330 uiScalingPolicyLabel->setEnabled( false );
2331#endif
2332
2333 iconColorComboBox->setCurrentIndex( static_cast<int>( pTheme->getInterfaceTheme()->m_iconColor ) );
2334
2335 // Style
2336 QStringList list = QStyleFactory::keys();
2337 uint i = 0;
2338 styleComboBox->clear();
2339 for ( QStringList::Iterator it = list.begin(); it != list.end(); it++) {
2340 styleComboBox->addItem( *it );
2341 QString sStyle = (*it);
2342 if (sStyle == pTheme->getInterfaceTheme()->m_sQTStyle ) {
2343 styleComboBox->setCurrentIndex( i );
2344 HydrogenApp::get_instance()->getMainForm()->m_pQApp->setStyle( sStyle );
2345 }
2346 i++;
2347 }
2348
2349 //SongEditor coloring
2350 int nColoringMethod = static_cast<int>(pTheme->getInterfaceTheme()->m_coloringMethod);
2351 if ( nColoringMethod == 0 ) {
2352 // "Automatic" selected
2353 coloringMethodAuxSpinBox->hide();
2354 colorSelectionLabel->hide();
2355 } else {
2356 coloringMethodAuxSpinBox->show();
2357 colorSelectionLabel->show();
2358 }
2359
2360 coloringMethodCombo->setCurrentIndex( nColoringMethod );
2361 coloringMethodAuxSpinBox->setValue( pTheme->getInterfaceTheme()->m_nVisiblePatternColors );
2362 QSize size( uiScalingPolicyComboBox->width(), coloringMethodAuxSpinBox->height() );
2363
2364 // Ensure the number of color buttons match.
2365 if ( m_colorSelectionButtons.size() !=
2366 pTheme->getInterfaceTheme()->m_nMaxPatternColors ) {
2367
2368 m_colorSelectionButtons.resize( pTheme->getInterfaceTheme()->m_nMaxPatternColors );
2370 int nButtonSize = fontSizeComboBox->height();
2371 // float fLineWidth = static_cast<float>(fontSizeComboBox->width());
2372 // Using a fixed one size resizing of the widget seems to happen
2373 // after the constructor is called.
2374 float fLineWidth = 308;
2375 int nButtonsPerLine = std::floor( fLineWidth / static_cast<float>(nButtonSize + 6) );
2376
2377 colorSelectionGrid->setHorizontalSpacing( 4 );
2378 for ( int ii = 0; ii < pTheme->getInterfaceTheme()->m_nMaxPatternColors; ii++ ) {
2379 ColorSelectionButton* bbutton =
2380 new ColorSelectionButton( this, pTheme->getInterfaceTheme()->m_patternColors[ ii ],
2381 nButtonSize );
2382 bbutton->hide();
2383 connect( bbutton, &ColorSelectionButton::colorChanged, this,
2385 colorSelectionGrid->addWidget( bbutton,
2386 std::floor( static_cast<float>( ii ) /
2387 static_cast<float>( nButtonsPerLine ) ),
2388 (ii % nButtonsPerLine) + 1); //+1 to take the hspace into account.
2389 m_colorSelectionButtons[ ii ] = bbutton;
2390 }
2391 }
2392
2393 // Update their colors.
2394 for ( int ii = 0; ii < m_colorSelectionButtons.size(); ++ii ) {
2395 m_colorSelectionButtons[ ii ]->setColor( pTheme->getInterfaceTheme()->
2396 m_patternColors[ ii ] );
2397 }
2398
2399 // Display only the required number.
2400 if ( nColoringMethod != 0 ) {
2401 for ( int ii = 0; ii < pTheme->getInterfaceTheme()->m_nVisiblePatternColors; ii++ ) {
2402 m_colorSelectionButtons[ ii ]->show();
2403 }
2404 }
2405
2406 // Fonts
2407 applicationFontComboBox->setCurrentFont( QFont( pTheme->getFontTheme()->m_sApplicationFontFamily ) );
2408 level2FontComboBox->setCurrentFont( QFont( pTheme->getFontTheme()->m_sLevel2FontFamily ) );
2409 level3FontComboBox->setCurrentFont( QFont( pTheme->getFontTheme()->m_sLevel3FontFamily ) );
2410 switch( pTheme->getFontTheme()->m_fontSize ) {
2412 fontSizeComboBox->setCurrentIndex( 0 );
2413 break;
2415 fontSizeComboBox->setCurrentIndex( 1 );
2416 break;
2418 fontSizeComboBox->setCurrentIndex( 2 );
2419 break;
2420 default:
2421 ERRORLOG( QString( "Unknown font size: %1" )
2422 .arg( static_cast<int>( pTheme->getFontTheme()->m_fontSize ) ) );
2423 }
2424}
#define INFOLOG(x)
Definition Object.h:240
#define ERRORLOG(x)
Definition Object.h:242
#define DEBUGLOG(x)
Definition Object.h:239
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()
H2Core::Preferences::AudioDriver m_driver
Custom file dialog checking whether the user has write access to the selected folder before allowing ...
Definition FileDialog.h:34
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:122
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:124
static QString sys_theme_dir()
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:663
AudioOutput * getAudioOutput() const
Used to display audio driver info.
Definition Hydrogen.cpp:741
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:79
bool isPlaylistUsingRelativeFilenames()
static AudioDriver parseAudioDriver(const QString &sDriver)
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)
unsigned m_nSampleRate
Sample rate of the audio.
void setTheme(const std::shared_ptr< Theme > pTheme)
QString m_sPortAudioHostAPI
static std::vector< AudioDriver > getSupportedAudioDrivers()
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
static QString audioDriverToQString(const AudioDriver &driver)
QString m_sMidiDriver
MIDI driver.
bool isRestoreLastSongEnabled()
bool isRestoreLastPlaylistEnabled()
@ postFader
Applies layer, component, and instrument gain, note and instrument pan, note velocity,...
@ preFader
Only layer gain and note velocity will be applied to the samples.
bool loadPreferences(bool bGlobal)
Load the preferences file.
AudioDriver m_audioDriver
Audio driver.
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.
void setLastExportThemeDirectory(QString sPath)
bool m_bJackTimebaseEnabled
External applications with a faulty JACK Timebase implementation can mess up the transport within Hyd...
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:199
static bool exportTheme(const QString &sPath, const std::shared_ptr< Theme > pTheme)
Definition Theme.cpp:725
static std::shared_ptr< Theme > importTheme(const QString &sPath)
Definition Theme.cpp:616
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
LCDCombo(QWidget *pParent, QSize size=QSize(0, 0), bool bModifyOnChange=false)
Definition LCDCombo.cpp:31
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