1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2017 Werner Schweer and others
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "musescore.h"
21 #include "timeline.h"
22 #include "preferences.h"
23 #include "prefsdialog.h"
24 #include "seq.h"
25 #include "shortcutcapturedialog.h"
26 #include "scoreview.h"
27 #include "shortcut.h"
28 #include "workspace.h"
29
30 #include "audio/drivers/pa.h"
31 #ifdef USE_PORTMIDI
32 #include "audio/drivers/pm.h"
33 #endif
34
35 #include "pathlistdialog.h"
36 #include "resourceManager.h"
37 #include "audio/midi/msynthesizer.h"
38
39 #ifdef AVSOMR
40 #include "avsomr/avsomrlocal.h"
41 #endif
42
43 #ifdef Q_OS_MAC
44 #include "macos/cocoabridge.h"
45 #endif
46
47 namespace Ms {
48
49 //---------------------------------------------------------
50 // startPreferenceDialog
51 //---------------------------------------------------------
52
startPreferenceDialog()53 void MuseScore::startPreferenceDialog()
54 {
55 if (!preferenceDialog) {
56 preferenceDialog = new PreferenceDialog(this);
57 connect(preferenceDialog, &PreferenceDialog::preferencesChanged, this,
58 &MuseScore::preferencesChanged);
59 connect(preferenceDialog, &PreferenceDialog::mixerPreferencesChanged, this,
60 &MuseScore::mixerPreferencesChanged);
61 }
62 preferenceDialog->start();
63 }
64
65 //---------------------------------------------------------
66 // PreferenceDialog
67 //---------------------------------------------------------
68
PreferenceDialog(QWidget * parent)69 PreferenceDialog::PreferenceDialog(QWidget* parent)
70 : AbstractDialog(parent)
71 {
72 setObjectName("PreferenceDialog");
73 setupUi(this);
74 setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
75 setModal(true);
76 shortcutsChanged = false;
77
78 styleName->clear();
79 styleName->addItem(tr("Light"));
80 styleName->addItem(tr("Dark"));
81 #ifdef Q_OS_MAC // On Mac, we have a theme option to follow the system's Dark Mode
82 if (CocoaBridge::isSystemDarkModeSupported())
83 styleName->addItem(tr("System"));
84 #endif
85
86 #ifndef USE_JACK
87 jackDriver->setVisible(false);
88 #endif
89 #ifndef USE_ALSA
90 alsaDriver->setVisible(false);
91 alsaDriver->setChecked(false);
92 #else
93 alsaSampleRate->clear();
94 alsaSampleRate->addItem(tr("192000"), 192000);
95 alsaSampleRate->addItem( tr("96000"), 96000);
96 alsaSampleRate->addItem( tr("88200"), 88200);
97 alsaSampleRate->addItem( tr("48000"), 48000); // default
98 alsaSampleRate->addItem( tr("44100"), 44100);
99 alsaSampleRate->addItem( tr("32000"), 32000);
100 alsaSampleRate->addItem( tr("22050"), 22050);
101
102 alsaPeriodSize->clear();
103 alsaPeriodSize->addItem(tr("4096"), 4096);
104 alsaPeriodSize->addItem(tr("2048"), 2048);
105 alsaPeriodSize->addItem(tr("1024"), 1024); // default
106 alsaPeriodSize->addItem( tr("512"), 512);
107 alsaPeriodSize->addItem( tr("256"), 256);
108 alsaPeriodSize->addItem( tr("128"), 128);
109 alsaPeriodSize->addItem( tr("64"), 64);
110 #endif
111
112 exportAudioSampleRate->clear();
113 exportAudioSampleRate->addItem(tr("32000"), 32000);
114 exportAudioSampleRate->addItem(tr("44100"), 44100); // default
115 exportAudioSampleRate->addItem(tr("48000"), 48000);
116
117 #ifndef USE_LAME
118 exportMp3BitRateLabel->setVisible(false);
119 exportMp3BitRate->setVisible(false);
120 exportMp3BitRateUnit->setVisible(false);
121 #else
122 exportMp3BitRate->clear();
123 exportMp3BitRate->addItem( tr("32"), 32);
124 exportMp3BitRate->addItem( tr("40"), 40);
125 exportMp3BitRate->addItem( tr("48"), 48);
126 exportMp3BitRate->addItem( tr("56"), 56);
127 exportMp3BitRate->addItem( tr("64"), 64);
128 exportMp3BitRate->addItem( tr("80"), 80);
129 exportMp3BitRate->addItem( tr("96"), 96);
130 exportMp3BitRate->addItem(tr("112"), 112);
131 exportMp3BitRate->addItem(tr("128"), 128); // default
132 exportMp3BitRate->addItem(tr("160"), 160);
133 exportMp3BitRate->addItem(tr("192"), 192);
134 exportMp3BitRate->addItem(tr("224"), 224);
135 exportMp3BitRate->addItem(tr("256"), 256);
136 exportMp3BitRate->addItem(tr("320"), 320);
137 #endif
138
139 #ifndef USE_PORTAUDIO
140 portaudioDriver->setVisible(false);
141 #endif
142 #ifndef USE_PORTMIDI
143 portMidiInput->setVisible(false);
144 portMidiInputLabel->setVisible(false);
145 #endif
146 #ifndef USE_PULSEAUDIO
147 pulseaudioDriver->setVisible(false);
148 #endif
149
150 tabIO->setEnabled(!noSeq);
151
152 QButtonGroup* fgButtons = new QButtonGroup(this);
153 fgButtons->setExclusive(true);
154 fgButtons->addButton(fgColorButton);
155 fgButtons->addButton(fgWallpaperButton);
156 connect(fgColorButton, &QRadioButton::toggled, this, &PreferenceDialog::updateFgView);
157
158 QButtonGroup* bgButtons = new QButtonGroup(this);
159 bgButtons->setExclusive(true);
160 bgButtons->addButton(bgColorButton);
161 bgButtons->addButton(bgWallpaperButton);
162 connect(bgColorButton, &QRadioButton::toggled, this, &PreferenceDialog::updateBgView);
163
164 zoomDefaultType->clear();
165 zoomDefaultType->addItem(tr("Percentage"), 0);
166 zoomDefaultType->addItem(tr("Page Width"), 1);
167 zoomDefaultType->addItem(tr("Whole Page"), 2);
168 zoomDefaultType->addItem(tr("Two Pages"), 3);
169
170 zoomPrecisionKeyboard->setRange(ZOOM_PRECISION_MIN, ZOOM_PRECISION_MAX);
171 zoomPrecisionMouse->setRange(ZOOM_PRECISION_MIN, ZOOM_PRECISION_MAX);
172
173 connect(buttonBox, &QDialogButtonBox::clicked, this, &PreferenceDialog::buttonBoxClicked);
174 connect(fgWallpaperSelect, &QToolButton::clicked, this, &PreferenceDialog::selectFgWallpaper);
175 connect(bgWallpaperSelect, &QToolButton::clicked, this, &PreferenceDialog::selectBgWallpaper);
176
177 bgWallpaperSelect->setIcon(*icons[int(Icons::fileOpen_ICON)]);
178 fgWallpaperSelect->setIcon(*icons[int(Icons::fileOpen_ICON)]);
179
180 connect(myScoresButton, &QToolButton::clicked, this, &PreferenceDialog::selectScoresDirectory);
181 connect(myStylesButton, &QToolButton::clicked, this, &PreferenceDialog::selectStylesDirectory);
182 connect(myTemplatesButton, &QToolButton::clicked, this, &PreferenceDialog::selectTemplatesDirectory);
183 connect(myPluginsButton, &QToolButton::clicked, this, &PreferenceDialog::selectPluginsDirectory);
184 connect(mySoundfontsButton, &QToolButton::clicked, this, &PreferenceDialog::changeSoundfontPaths);
185 connect(myImagesButton, &QToolButton::clicked, this, &PreferenceDialog::selectImagesDirectory);
186 connect(myExtensionsButton, &QToolButton::clicked, this, &PreferenceDialog::selectExtensionsDirectory);
187
188 myScoresButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
189 myStylesButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
190 myTemplatesButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
191 myPluginsButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
192 mySoundfontsButton->setIcon(*icons[int(Icons::edit_ICON)]);
193 myImagesButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
194 myExtensionsButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
195
196 connect(updateTranslation, &QToolButton::clicked, this, &PreferenceDialog::updateTranslationClicked);
197
198 connect(defaultStyleButton, &QToolButton::clicked, this, &PreferenceDialog::selectDefaultStyle);
199 connect(partStyleButton, &QToolButton::clicked, this, &PreferenceDialog::selectPartStyle);
200 connect(styleFileButton, &QToolButton::clicked, this, &PreferenceDialog::styleFileButtonClicked);
201 connect(instrumentList1Button, &QToolButton::clicked, this, &PreferenceDialog::selectInstrumentList1);
202 connect(instrumentList2Button, &QToolButton::clicked, this, &PreferenceDialog::selectInstrumentList2);
203 connect(scoreOrderList1Button, &QToolButton::clicked, this, &PreferenceDialog::selectScoreOrderList1);
204 connect(scoreOrderList2Button, &QToolButton::clicked, this, &PreferenceDialog::selectScoreOrderList2);
205 connect(startWithButton, &QToolButton::clicked, this, &PreferenceDialog::selectStartWith);
206
207 defaultStyleButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
208 partStyleButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
209 styleFileButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
210 instrumentList1Button->setIcon(*icons[int(Icons::fileOpen_ICON)]);
211 instrumentList2Button->setIcon(*icons[int(Icons::fileOpen_ICON)]);
212 scoreOrderList1Button->setIcon(*icons[int(Icons::fileOpen_ICON)]);
213 scoreOrderList2Button->setIcon(*icons[int(Icons::fileOpen_ICON)]);
214 startWithButton->setIcon(*icons[int(Icons::fileOpen_ICON)]);
215
216 connect(shortcutList, &QTreeWidget::itemActivated, this, &PreferenceDialog::defineShortcutClicked);
217 connect(resetShortcut, &QToolButton::clicked, this, &PreferenceDialog::resetShortcutClicked);
218 connect(saveShortcutList, &QToolButton::clicked, this, &PreferenceDialog::saveShortcutListClicked);
219 connect(loadShortcutList, &QToolButton::clicked, this, &PreferenceDialog::loadShortcutListClicked);
220 connect(clearShortcut, &QToolButton::clicked, this, &PreferenceDialog::clearShortcutClicked);
221 connect(defineShortcut, &QToolButton::clicked, this, &PreferenceDialog::defineShortcutClicked);
222 connect(resetToDefault, &QToolButton::clicked, this, &PreferenceDialog::resetAllValues);
223 connect(filterShortcuts, &QLineEdit::textChanged, this, &PreferenceDialog::filterShortcutsTextChanged);
224 connect(printShortcuts, &QToolButton::clicked, this, &PreferenceDialog::printShortcutsClicked);
225 connect(zoomDefaultType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PreferenceDialog::zoomDefaultTypeChanged);
226
227 recordButtons = new QButtonGroup(this);
228 recordButtons->setExclusive(false);
229 recordButtons->addButton(recordRewind, RMIDI_REWIND);
230 recordButtons->addButton(recordTogglePlay, RMIDI_TOGGLE_PLAY);
231 recordButtons->addButton(recordPlay, RMIDI_PLAY);
232 recordButtons->addButton(recordStop, RMIDI_STOP);
233 recordButtons->addButton(rcr2, RMIDI_NOTE1);
234 recordButtons->addButton(rcr3, RMIDI_NOTE2);
235 recordButtons->addButton(rcr4, RMIDI_NOTE4);
236 recordButtons->addButton(rcr5, RMIDI_NOTE8);
237 recordButtons->addButton(rcr6, RMIDI_NOTE16);
238 recordButtons->addButton(rcr7, RMIDI_NOTE32);
239 recordButtons->addButton(rcr8, RMIDI_NOTE64);
240 recordButtons->addButton(rcr9, RMIDI_REST);
241 recordButtons->addButton(rcr10, RMIDI_DOT);
242 recordButtons->addButton(rcr11, RMIDI_DOTDOT);
243 recordButtons->addButton(rcr12, RMIDI_TIE);
244 recordButtons->addButton(recordUndo, RMIDI_UNDO);
245 recordButtons->addButton(recordEditMode, RMIDI_NOTE_EDIT_MODE);
246 recordButtons->addButton(recordRealtimeAdvance, RMIDI_REALTIME_ADVANCE);
247
248 connect(recordButtons, QOverload<int>::of(&QButtonGroup::buttonClicked), this, &PreferenceDialog::recordButtonClicked);
249 connect(midiRemoteControlClear, &QToolButton::clicked, this, &PreferenceDialog::midiRemoteControlClearClicked);
250 connect(portaudioDriver, &QGroupBox::toggled, this, &PreferenceDialog::exclusiveAudioDriver);
251 connect(pulseaudioDriver, &QGroupBox::toggled, this, &PreferenceDialog::exclusiveAudioDriver);
252 connect(alsaDriver, &QGroupBox::toggled, this, &PreferenceDialog::exclusiveAudioDriver);
253 connect(jackDriver, &QGroupBox::toggled, this, &PreferenceDialog::exclusiveAudioDriver);
254 connect(useJackAudio, &QRadioButton::toggled, this, &PreferenceDialog::nonExclusiveJackDriver);
255 connect(useJackMidi, &QRadioButton::toggled, this, &PreferenceDialog::nonExclusiveJackDriver);
256 connect(rescanDrivers, &QToolButton::clicked, this, &PreferenceDialog::restartAudioEngine);
257 updateRemote();
258
259 advancedWidget = new PreferencesListWidget();
260 QVBoxLayout* l = static_cast<QVBoxLayout*> (tabAdvanced->layout());
261 l->insertWidget(0, advancedWidget);
262 advancedWidget->loadPreferences();
263 connect(advancedSearch, &QLineEdit::textChanged, this, &PreferenceDialog::filterAdvancedPreferences);
264 connect(resetPreference, &QPushButton::clicked, this, &PreferenceDialog::resetAdvancedPreferenceToDefault);
265 connect(this, &PreferenceDialog::preferencesChanged, mscore->timeline(), &Timeline::updateTimelineTheme); // this should probably be moved to updateUiStyleAndTheme
266 MuseScore::restoreGeometry(this);
267 #if !defined(Q_OS_MAC) && (!defined(Q_OS_WIN) || defined(FOR_WINSTORE))
268 General->removeTab(General->indexOf(tabUpdate)); // updateTab not needed on Linux and not wanted in Windows Store
269 #endif
270 }
271
272 //---------------------------------------------------------
273 // start
274 //---------------------------------------------------------
275
start()276 void PreferenceDialog::start()
277 {
278
279 // Each entry to one of the vectors controls one widget (and usually one preference).
280 // Each entry is a *PreferenceItem(preference_key, widget, optional applyFunction, optional updateFunction).
281 // A *PreferenceItem with only the first 2 parameters saves its value on apply and loads it when the dialog starts or when reset is pressed.
282 //
283 // The default apply/update(load) behavior can be overriden by providing an applyFunction and/or updateFunction (the default value is nullptr).
284 // The apply function (either the default or the provided one) is called in PreferenceDialog::Apply.
285 // The update function (either the default or the provided one) is called in PreferenceDialog::Update.
286 //
287 // If the logic is too complicated to be implemented like this (for example for multiple interconnected preferences),
288 // doNothing can be used in place of a function to disable the call to that function.
289 // Then the related functionality must be called directly from PrefsDialog::Apply (or PrefsDialog::Update).
290
291 const auto doNothing = []() { }; // used to disable the default apply/update functions (in contrast to nullptr which instructs the use of the defaults)
292
293 // Most widgets go here.
294 normalWidgets = std::vector<PreferenceItem*>{
295 new IntPreferenceItem(PREF_APP_AUTOSAVE_AUTOSAVETIME, autoSaveTime),
296 new BoolPreferenceItem(PREF_APP_AUTOSAVE_USEAUTOSAVE, autoSave),
297 new StringPreferenceItem(PREF_APP_PATHS_INSTRUMENTLIST1, instrumentList1),
298 new StringPreferenceItem(PREF_APP_PATHS_INSTRUMENTLIST2, instrumentList2),
299 new StringPreferenceItem(PREF_APP_PATHS_SCOREORDERLIST1, scoreOrderList1),
300 new StringPreferenceItem(PREF_APP_PATHS_SCOREORDERLIST2, scoreOrderList2),
301 new StringPreferenceItem(PREF_APP_PATHS_MYIMAGES, myImages),
302 new StringPreferenceItem(PREF_APP_PATHS_MYPLUGINS, myPlugins),
303 new StringPreferenceItem(PREF_APP_PATHS_MYSCORES, myScores),
304 new StringPreferenceItem(PREF_APP_PATHS_MYSOUNDFONTS, mySoundfonts),
305 new StringPreferenceItem(PREF_APP_PATHS_MYSTYLES, myStyles),
306 new StringPreferenceItem(PREF_APP_PATHS_MYTEMPLATES, myTemplates),
307 new StringPreferenceItem(PREF_APP_PATHS_MYEXTENSIONS, myExtensions),
308 new StringPreferenceItem(PREF_APP_STARTUP_STARTSCORE, sessionScore),
309 new IntPreferenceItem(PREF_EXPORT_PDF_DPI, exportPdfDpi),
310 new DoublePreferenceItem(PREF_EXPORT_PNG_RESOLUTION, pngResolution),
311 new BoolPreferenceItem(PREF_EXPORT_PNG_USETRANSPARENCY, pngTransparent),
312 new BoolPreferenceItem(PREF_IMPORT_MUSICXML_IMPORTBREAKS, importBreaks),
313 new BoolPreferenceItem(PREF_IMPORT_MUSICXML_IMPORTLAYOUT, importLayout),
314 new BoolPreferenceItem(PREF_MIGRATION_APPLY_EDWIN_FOR_XML_FILES, applyDefaultTypeFaceToImportedScores,
315 [this]() { preferences.setPreference(PREF_MIGRATION_APPLY_EDWIN_FOR_XML_FILES, applyDefaultTypeFaceToImportedScores->isChecked()); }, // apply function
316 [this]() {
317 bool value = preferences.getBool(PREF_MIGRATION_DO_NOT_ASK_ME_AGAIN_XML) && preferences.getBool(PREF_MIGRATION_APPLY_EDWIN_FOR_XML_FILES);
318 applyDefaultTypeFaceToImportedScores->setChecked(value);
319 }), // update function
320 #ifdef AVSOMR
321 new BoolPreferenceItem(PREF_IMPORT_AVSOMR_USELOCAL, useLocalAvsOmr, [&](){ updateUseLocalAvsOmr(); }),
322 #endif
323 new BoolPreferenceItem(PREF_IO_MIDI_ADVANCEONRELEASE, advanceOnRelease),
324 new BoolPreferenceItem(PREF_IO_MIDI_ENABLEINPUT, enableMidiInput),
325 new BoolPreferenceItem(PREF_IO_MIDI_EXPANDREPEATS, expandRepeats),
326 new BoolPreferenceItem(PREF_EXPORT_AUDIO_NORMALIZE, normalize),
327 new BoolPreferenceItem(PREF_IO_MIDI_EXPORTRPNS, exportRPNs),
328 new IntPreferenceItem(PREF_IO_MIDI_REALTIMEDELAY, realtimeDelay),
329 new BoolPreferenceItem(PREF_IO_MIDI_USEREMOTECONTROL, rcGroup),
330 new IntPreferenceItem(PREF_IO_OSC_PORTNUMBER, oscPort),
331 new BoolPreferenceItem(PREF_IO_OSC_USEREMOTECONTROL, oscServer),
332 new BoolPreferenceItem(PREF_SCORE_CHORD_PLAYONADDNOTE, playChordOnAddNote),
333 new BoolPreferenceItem(PREF_SCORE_HARMONY_PLAY_ONEDIT, playHarmonyOnEdit),
334 new IntPreferenceItem(PREF_SCORE_NOTE_DEFAULTPLAYDURATION, defaultPlayDuration),
335 new BoolPreferenceItem(PREF_SCORE_NOTE_PLAYONCLICK, playNotes),
336 new BoolPreferenceItem(PREF_UI_APP_STARTUP_CHECKUPDATE, checkUpdateStartup),
337 new BoolPreferenceItem(PREF_UI_APP_STARTUP_SHOWNAVIGATOR, navigatorShow),
338 new BoolPreferenceItem(PREF_UI_APP_STARTUP_SHOWPLAYPANEL, playPanelShow),
339 new BoolPreferenceItem(PREF_UI_APP_STARTUP_SHOWSPLASHSCREEN, showSplashScreen),
340 new BoolPreferenceItem(PREF_UI_APP_STARTUP_SHOWSTARTCENTER, showStartcenter),
341 new BoolPreferenceItem(PREF_UI_APP_STARTUP_SHOWTOURS, showTours),
342 new BoolPreferenceItem(PREF_APP_TELEMETRY_ALLOWED, collectTelemetry),
343 new BoolPreferenceItem(PREF_IO_JACK_TIMEBASEMASTER, becomeTimebaseMaster),
344 new BoolPreferenceItem(PREF_IO_JACK_REMEMBERLASTCONNECTIONS, rememberLastMidiConnections),
345 new BoolPreferenceItem(PREF_SCORE_NOTE_WARNPITCHRANGE, warnPitchRange),
346 new StringPreferenceItem(PREF_IMPORT_OVERTURE_CHARSET, importCharsetListOve, nullptr, [&](){ updateCharsetListOve(); }), // keep the default apply
347 new StringPreferenceItem(PREF_IMPORT_GUITARPRO_CHARSET, importCharsetListGP, nullptr, [&](){ updateCharsetListGP(); }), // keep the default apply
348 new IntPreferenceItem(PREF_EXPORT_AUDIO_SAMPLERATE, exportAudioSampleRate),
349 new IntPreferenceItem(PREF_EXPORT_MP3_BITRATE, exportMp3BitRate),
350 new StringPreferenceItem(PREF_SCORE_STYLE_DEFAULTSTYLEFILE, defaultStyle,
351 [this]() { // apply function
352 preferences.setPreference(PREF_SCORE_STYLE_DEFAULTSTYLEFILE, defaultStyle->text());
353 MScore::readDefaultStyle(preferences.getString(PREF_SCORE_STYLE_DEFAULTSTYLEFILE));
354 }),
355 new StringPreferenceItem(PREF_SCORE_STYLE_PARTSTYLEFILE, partStyle,
356 [this]() { // apply function
357 preferences.setPreference(PREF_SCORE_STYLE_PARTSTYLEFILE, partStyle->text());
358 MScore::defaultStyleForPartsHasChanged();
359 }),
360 new StringPreferenceItem(PREF_IMPORT_STYLE_STYLEFILE, importStyleFile,
361 [this]() { // apply function
362 preferences.setPreference(PREF_IMPORT_STYLE_STYLEFILE, useImportStyleFile->isChecked() ? importStyleFile->text() : "");
363 },
364 [this]() { // update function
365 QString styleFile = preferences.getString(PREF_IMPORT_STYLE_STYLEFILE);
366 importStyleFile->setText(styleFile);
367 useImportBuiltinStyle->setChecked(styleFile.isEmpty());
368 useImportStyleFile->setChecked(!styleFile.isEmpty());
369 }),
370 new BoolPreferenceItem(PREF_IO_MIDI_SHOWCONTROLSINMIXER, showMidiControls,
371 [this]() { // apply function
372 preferences.setPreference(PREF_IO_MIDI_SHOWCONTROLSINMIXER, showMidiControls->isChecked());
373 emit mixerPreferencesChanged(preferences.getBool(PREF_IO_MIDI_SHOWCONTROLSINMIXER));
374 }),
375 new BoolPreferenceItem(PREF_UI_CANVAS_SCROLL_VERTICALORIENTATION, pageVertical,
376 [this]() { applyPageVertical(); }, // apply function
377 [this]() { pageVertical->setChecked(MScore::verticalOrientation()); }), // update function
378 new IntPreferenceItem(PREF_IO_MIDI_SHORTESTNOTE, shortestNote,
379 [this]() { applyShortestNote(); }, // apply function
380 [this]() { updateShortestNote(); }), // update function
381 new BoolPreferenceItem(PREF_MIGRATION_DO_NOT_ASK_ME_AGAIN, scoreMigrationEnabled,
382 [this]() { preferences.setPreference(PREF_MIGRATION_DO_NOT_ASK_ME_AGAIN, !scoreMigrationEnabled->isChecked()); }, // apply function
383 [this]() { scoreMigrationEnabled->setChecked(!preferences.getBool(PREF_MIGRATION_DO_NOT_ASK_ME_AGAIN)); }), // update function
384 new BoolPreferenceItem(PREF_MIGRATION_DO_NOT_ASK_ME_AGAIN_XML),
385 new StringPreferenceItem(PREF_UI_APP_LANGUAGE, language, [&](){ languageApply(); }, [&](){ languageUpdate(); }),
386 new CustomPreferenceItem(PREF_APP_STARTUP_SESSIONSTART, lastSession,
387 [this]() { // apply function
388 if (lastSession->isChecked())
389 preferences.setCustomPreference<SessionStart>(PREF_APP_STARTUP_SESSIONSTART, SessionStart::LAST);
390 },
391 [this]() { // update function
392 lastSession->setChecked(preferences.sessionStart() == SessionStart::LAST);
393 }),
394 new CustomPreferenceItem(PREF_APP_STARTUP_SESSIONSTART, newSession,
395 [this]() { // apply function
396 if (newSession->isChecked())
397 preferences.setCustomPreference<SessionStart>(PREF_APP_STARTUP_SESSIONSTART, SessionStart::NEW);
398 },
399 [this]() { // update function
400 newSession->setChecked(preferences.sessionStart() == SessionStart::NEW);
401 }),
402 new CustomPreferenceItem(PREF_APP_STARTUP_SESSIONSTART, scoreSession,
403 [this]() { // apply function
404 if (scoreSession->isChecked())
405 preferences.setCustomPreference<SessionStart>(PREF_APP_STARTUP_SESSIONSTART, SessionStart::SCORE);
406 },
407 [this]() { // update function
408 scoreSession->setChecked(preferences.sessionStart() == SessionStart::SCORE);
409 }),
410 new CustomPreferenceItem(PREF_APP_STARTUP_SESSIONSTART, emptySession,
411 [this]() { // apply function
412 if (emptySession->isChecked())
413 preferences.setCustomPreference<SessionStart>(PREF_APP_STARTUP_SESSIONSTART, SessionStart::EMPTY);
414 },
415 [this]() { // update function
416 emptySession->setChecked(preferences.sessionStart() == SessionStart::EMPTY);
417 }),
418 new BoolPreferenceItem(PREF_EXPORT_MUSICXML_EXPORTLAYOUT, exportAllLayouts),
419 new CustomPreferenceItem(PREF_EXPORT_MUSICXML_EXPORTBREAKS, exportAllLayouts,
420 [this]() { // apply function
421 if (exportAllLayouts->isChecked())
422 preferences.setCustomPreference<MusicxmlExportBreaks>(PREF_EXPORT_MUSICXML_EXPORTBREAKS, MusicxmlExportBreaks::ALL);
423 },
424 []() { // update function
425 ;
426 }),
427 new CustomPreferenceItem(PREF_EXPORT_MUSICXML_EXPORTBREAKS, exportAllBreaks,
428 [this]() { // apply function
429 if (exportAllBreaks->isChecked())
430 preferences.setCustomPreference<MusicxmlExportBreaks>(PREF_EXPORT_MUSICXML_EXPORTBREAKS, MusicxmlExportBreaks::ALL);
431 },
432 [this]() { // update function
433 if (!preferences.getBool(PREF_EXPORT_MUSICXML_EXPORTLAYOUT))
434 exportAllBreaks->setChecked(preferences.musicxmlExportBreaks() == MusicxmlExportBreaks::ALL);
435 }),
436 new CustomPreferenceItem(PREF_EXPORT_MUSICXML_EXPORTBREAKS, exportManualBreaks,
437 [this]() { // apply function
438 if (exportManualBreaks->isChecked())
439 preferences.setCustomPreference<MusicxmlExportBreaks>(PREF_EXPORT_MUSICXML_EXPORTBREAKS, MusicxmlExportBreaks::MANUAL);
440 },
441 [this]() { // update function
442 if (!preferences.getBool(PREF_EXPORT_MUSICXML_EXPORTLAYOUT))
443 exportManualBreaks->setChecked(preferences.musicxmlExportBreaks() == MusicxmlExportBreaks::MANUAL);
444 }),
445 new CustomPreferenceItem(PREF_EXPORT_MUSICXML_EXPORTBREAKS, exportNoBreaks,
446 [this]() { // apply function
447 if (exportNoBreaks->isChecked())
448 preferences.setCustomPreference<MusicxmlExportBreaks>(PREF_EXPORT_MUSICXML_EXPORTBREAKS, MusicxmlExportBreaks::NO);
449 },
450 [this]() { // update function
451 if (!preferences.getBool(PREF_EXPORT_MUSICXML_EXPORTLAYOUT))
452 exportNoBreaks->setChecked(preferences.musicxmlExportBreaks() == MusicxmlExportBreaks::NO);
453 }),
454
455 };
456
457 // Contains widgets that change the appearance of MuseScore (style/theme) and/or are saved in Workspaces.
458 uiRelatedWidgets = std::vector<PreferenceItem*>{
459 new BoolPreferenceItem(PREF_UI_CANVAS_BG_USECOLOR, bgColorButton, nullptr, [&](){ updateBgView(preferences.getBool(PREF_UI_CANVAS_BG_USECOLOR)); }),
460 new ColorPreferenceItem(PREF_UI_CANVAS_BG_COLOR, bgColorLabel, nullptr, doNothing),
461 new BoolPreferenceItem(PREF_UI_CANVAS_FG_USECOLOR, fgColorButton, nullptr, [&](){ updateFgView(preferences.getBool(PREF_UI_CANVAS_FG_USECOLOR)); }),
462 new BoolPreferenceItem(PREF_UI_CANVAS_FG_USECOLOR_IN_PALETTES, fgUseColorInPalettes, nullptr, doNothing),
463 new ColorPreferenceItem(PREF_UI_CANVAS_FG_COLOR, fgColorLabel, nullptr, doNothing),
464 new StringPreferenceItem(PREF_UI_CANVAS_BG_WALLPAPER, bgWallpaper, nullptr, doNothing),
465 new StringPreferenceItem(PREF_UI_CANVAS_FG_WALLPAPER, fgWallpaper, nullptr, doNothing),
466 new IntPreferenceItem(PREF_UI_CANVAS_ZOOM_DEFAULT_TYPE, zoomDefaultType, nullptr,
467 [this]() { // update function
468 zoomDefaultType->setCurrentIndex(preferences.getInt(PREF_UI_CANVAS_ZOOM_DEFAULT_TYPE));
469 zoomDefaultTypeChanged(preferences.getInt(PREF_UI_CANVAS_ZOOM_DEFAULT_TYPE));
470 }),
471 new IntPreferenceItem(PREF_UI_CANVAS_ZOOM_DEFAULT_LEVEL, zoomDefaultLevel,
472 [this]() { preferences.setPreference(PREF_UI_CANVAS_ZOOM_DEFAULT_LEVEL, zoomDefaultLevel->value()); }, // apply function
473 [this]() { zoomDefaultLevel->setValue(preferences.getInt(PREF_UI_CANVAS_ZOOM_DEFAULT_LEVEL)); } // update function
474 ),
475 new IntPreferenceItem(PREF_UI_CANVAS_ZOOM_PRECISION_KEYBOARD, zoomPrecisionKeyboard),
476 new IntPreferenceItem(PREF_UI_CANVAS_ZOOM_PRECISION_MOUSE, zoomPrecisionMouse),
477 new BoolPreferenceItem(PREF_UI_CANVAS_MISC_ANTIALIASEDDRAWING, drawAntialiased),
478 new BoolPreferenceItem(PREF_UI_CANVAS_SCROLL_LIMITSCROLLAREA, limitScrollArea),
479 new IntPreferenceItem(PREF_UI_CANVAS_MISC_SELECTIONPROXIMITY, proximity),
480 new IntPreferenceItem(PREF_UI_THEME_ICONWIDTH, iconWidth),
481 new IntPreferenceItem(PREF_UI_THEME_ICONHEIGHT, iconHeight),
482 new StringPreferenceItem(PREF_UI_THEME_FONTFAMILY, fontFamily, nullptr,
483 [&]() { // update function
484 auto currFontFamily = preferences.getString(PREF_UI_THEME_FONTFAMILY);
485 if (-1 == fontFamily->findText(currFontFamily))
486 fontFamily->addItem(currFontFamily);
487 fontFamily->setCurrentIndex(fontFamily->findText(currFontFamily));
488 }),
489 new DoublePreferenceItem(PREF_UI_THEME_FONTSIZE, fontSize),
490 new CustomPreferenceItem(PREF_UI_APP_GLOBALSTYLE, styleName,
491 [&]() { // apply function
492 preferences.setCustomPreference<MuseScorePreferredStyleType>(PREF_UI_APP_GLOBALSTYLE, MuseScorePreferredStyleType(styleName->currentIndex()));
493 },
494 [&]() { // update function
495 styleName->setCurrentIndex(int(preferences.preferredGlobalStyle()));
496 }),
497 };
498
499 // All these widgets are interconnected and are used together to set their preferences. Don't add unrelated, or not immediately related widgets.
500 audioRelatedWidgets = std::vector<PreferenceItem*>{
501 new BoolPreferenceItem(PREF_IO_ALSA_USEALSAAUDIO, alsaDriver, doNothing),
502 new BoolPreferenceItem(PREF_IO_JACK_USEJACKAUDIO, useJackAudio, doNothing),
503 new BoolPreferenceItem(PREF_IO_PORTAUDIO_USEPORTAUDIO, portaudioDriver, doNothing),
504 new BoolPreferenceItem(PREF_IO_PULSEAUDIO_USEPULSEAUDIO, pulseaudioDriver, doNothing),
505 new BoolPreferenceItem(PREF_IO_JACK_USEJACKMIDI, useJackMidi, doNothing),
506 new BoolPreferenceItem(PREF_IO_JACK_USEJACKTRANSPORT, useJackTransport, doNothing),
507 new StringPreferenceItem(PREF_IO_ALSA_DEVICE, alsaDevice, doNothing),
508 new IntPreferenceItem(PREF_IO_ALSA_SAMPLERATE, alsaSampleRate, doNothing),
509 new IntPreferenceItem(PREF_IO_ALSA_PERIODSIZE, alsaPeriodSize, doNothing),
510 new IntPreferenceItem(PREF_IO_ALSA_FRAGMENTS, alsaFragments, doNothing),
511 new IntPreferenceItem(PREF_IO_PORTAUDIO_DEVICE, portaudioApi, doNothing, doNothing),
512 new IntPreferenceItem(PREF_IO_PORTAUDIO_DEVICE, portaudioDevice, doNothing, doNothing),
513 #ifdef USE_PORTMIDI
514 new StringPreferenceItem(PREF_IO_PORTMIDI_INPUTDEVICE, portMidiInput, doNothing, doNothing),
515 new StringPreferenceItem(PREF_IO_PORTMIDI_OUTPUTDEVICE, portMidiOutput, doNothing, doNothing),
516 new IntPreferenceItem(PREF_IO_PORTMIDI_OUTPUTLATENCYMILLISECONDS, portMidiOutputLatencyMilliseconds),
517 #endif
518 };
519
520 // These connections are used to enable the Apply button and to save only the changed preferences.
521
522 for (auto& x : normalWidgets)
523 connect(x, &PreferenceItem::editorValueModified, this, &PreferenceDialog::widgetModified);
524
525 for (auto& x : uiRelatedWidgets)
526 connect(x, &PreferenceItem::editorValueModified, this, &PreferenceDialog::uiWidgetModified);
527
528 for (auto& x : audioRelatedWidgets)
529 connect(x, &PreferenceItem::editorValueModified, this, &PreferenceDialog::audioWidgetModified);
530
531 for (auto& x : advancedWidget->preferenceItems())
532 connect(x, &PreferenceItem::editorValueModified, this, &PreferenceDialog::applyActivate);
533
534 updateValues(false, true);
535 modifiedWidgets.clear();
536 modifiedUiWidgets.clear();
537 modifiedAudioWidgets.clear();
538 applySetActive(false);
539 show();
540 }
541
542 //---------------------------------------------------------
543 // ~PreferenceDialog
544 //---------------------------------------------------------
545
~PreferenceDialog()546 PreferenceDialog::~PreferenceDialog()
547 {
548 for (size_t i = 0; i < normalWidgets.size(); i++)
549 delete normalWidgets.at(i);
550 normalWidgets.clear();
551
552 for (size_t i = 0; i < uiRelatedWidgets.size(); i++)
553 delete uiRelatedWidgets.at(i);
554 uiRelatedWidgets.clear();
555
556 for (size_t i = 0; i < audioRelatedWidgets.size(); i++)
557 delete audioRelatedWidgets.at(i);
558 audioRelatedWidgets.clear();
559
560 qDeleteAll(localShortcuts);
561 }
562
563 //---------------------------------------------------------
564 // retranslate
565 //---------------------------------------------------------
566
retranslate()567 void PreferenceDialog::retranslate()
568 {
569 retranslateUi(this);
570 updateValues();
571 }
572
573 //---------------------------------------------------------
574 // hideEvent
575 //---------------------------------------------------------
576
hideEvent(QHideEvent * ev)577 void PreferenceDialog::hideEvent(QHideEvent* ev)
578 {
579 MuseScore::saveGeometry(this);
580 QWidget::hideEvent(ev);
581 }
582
583 //---------------------------------------------------------
584 // recordButtonClicked
585 //---------------------------------------------------------
586
recordButtonClicked(int val)587 void PreferenceDialog::recordButtonClicked(int val)
588 {
589 for (QAbstractButton* b : recordButtons->buttons()) {
590 b->setChecked(recordButtons->id(b) == val);
591 }
592 mscore->setMidiRecordId(val);
593 }
594
595 //---------------------------------------------------------
596 // updateRemote
597 //---------------------------------------------------------
598
updateRemote()599 void PreferenceDialog::updateRemote()
600 {
601 rewindActive->setChecked(preferences.midiRemote(RMIDI_REWIND).type != -1);
602 togglePlayActive->setChecked(preferences.midiRemote(RMIDI_TOGGLE_PLAY).type != -1);
603 playActive->setChecked(preferences.midiRemote(RMIDI_PLAY).type != -1);
604 stopActive->setChecked(preferences.midiRemote(RMIDI_STOP).type != -1);
605 rca2->setChecked(preferences.midiRemote(RMIDI_NOTE1).type != -1);
606 rca3->setChecked(preferences.midiRemote(RMIDI_NOTE2).type != -1);
607 rca4->setChecked(preferences.midiRemote(RMIDI_NOTE4).type != -1);
608 rca5->setChecked(preferences.midiRemote(RMIDI_NOTE8).type != -1);
609 rca6->setChecked(preferences.midiRemote(RMIDI_NOTE16).type != -1);
610 rca7->setChecked(preferences.midiRemote(RMIDI_NOTE32).type != -1);
611 rca8->setChecked(preferences.midiRemote(RMIDI_NOTE64).type != -1);
612 rca9->setChecked(preferences.midiRemote(RMIDI_REST).type != -1);
613 rca10->setChecked(preferences.midiRemote(RMIDI_DOT).type != -1);
614 rca11->setChecked(preferences.midiRemote(RMIDI_DOTDOT).type != -1);
615 rca12->setChecked(preferences.midiRemote(RMIDI_TIE).type != -1);
616 recordUndoActive->setChecked(preferences.midiRemote(RMIDI_UNDO).type != -1);
617 editModeActive->setChecked(preferences.midiRemote(RMIDI_NOTE_EDIT_MODE).type != -1);
618 realtimeAdvanceActive->setChecked(preferences.midiRemote(RMIDI_REALTIME_ADVANCE).type != -1);
619
620 int id = mscore->midiRecordId();
621 recordRewind->setChecked(id == RMIDI_REWIND);
622 recordTogglePlay->setChecked(id == RMIDI_TOGGLE_PLAY);
623 recordPlay->setChecked(id == RMIDI_PLAY);
624 recordStop->setChecked(id == RMIDI_STOP);
625 rcr2->setChecked(id == RMIDI_NOTE1);
626 rcr3->setChecked(id == RMIDI_NOTE2);
627 rcr4->setChecked(id == RMIDI_NOTE4);
628 rcr5->setChecked(id == RMIDI_NOTE8);
629 rcr6->setChecked(id == RMIDI_NOTE16);
630 rcr7->setChecked(id == RMIDI_NOTE32);
631 rcr8->setChecked(id == RMIDI_NOTE64);
632 rcr9->setChecked(id == RMIDI_REST);
633 rcr10->setChecked(id == RMIDI_DOT);
634 rcr11->setChecked(id == RMIDI_DOTDOT);
635 rcr12->setChecked(id == RMIDI_TIE);
636 recordUndo->setChecked(id == RMIDI_UNDO);
637 recordEditMode->setChecked(id == RMIDI_NOTE_EDIT_MODE);
638 recordRealtimeAdvance->setChecked(id == RMIDI_REALTIME_ADVANCE);
639 }
640
641 //---------------------------------------------------------
642 // updateValues
643 //---------------------------------------------------------
644
updateValues(bool useDefaultValues,bool setup)645 void PreferenceDialog::updateValues(bool useDefaultValues, bool setup)
646 {
647 if (useDefaultValues)
648 preferences.setReturnDefaultValuesMode(true);
649
650 styleName->clear();
651 styleName->addItem(tr("Light"));
652 styleName->addItem(tr("Dark"));
653 #ifdef Q_OS_MAC // On Mac, we have a theme option to follow the system's Dark Mode
654 if (CocoaBridge::isSystemDarkModeSupported())
655 styleName->addItem(tr("System"));
656 #endif
657
658 advancedWidget->updatePreferences();
659
660 //macOS default fonts are not in QFontCombobox because they are "private":
661 //https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qfontcombobox.cpp.html#329
662
663 jackDriver->setChecked(preferences.getBool(PREF_IO_JACK_USEJACKAUDIO) || preferences.getBool(PREF_IO_JACK_USEJACKMIDI));
664
665 #ifndef AVSOMR
666 groupBox_omr->setVisible(false);
667 #endif
668
669 //
670 // initialize local shortcut table
671 // we need a deep copy to be able to rewind all
672 // changes on "Abort"
673 //
674 qDeleteAll(localShortcuts);
675 localShortcuts.clear();
676 for(const Shortcut* s : Shortcut::shortcuts())
677 localShortcuts[s->key()] = new Shortcut(*s);
678 updateSCListView();
679
680 //Generate the filtered Shortcut List
681 filterShortcutsTextChanged(filterShortcuts->text());
682
683 //
684 // initialize portaudio
685 //
686 #ifdef USE_PORTAUDIO
687 if (portAudioIsUsed) {
688 Portaudio* audio = static_cast<Portaudio*>(seq->driver());
689 if (audio) {
690 QStringList apis = audio->apiList();
691 portaudioApi->clear();
692 portaudioApi->addItems(apis);
693 portaudioApi->setCurrentIndex(audio->currentApi());
694
695 QStringList devices = audio->deviceList(audio->currentApi());
696 portaudioDevice->clear();
697 portaudioDevice->addItems(devices);
698 portaudioDevice->setCurrentIndex(audio->currentDevice());
699
700 connect(portaudioApi, QOverload<int>::of(&QComboBox::activated), this, &PreferenceDialog::portaudioApiActivated);
701 #ifdef USE_PORTMIDI
702 PortMidiDriver* midiDriver = static_cast<PortMidiDriver*>(audio->mididriver());
703 if (midiDriver) {
704 QStringList midiInputs = midiDriver->deviceInList();
705 int curMidiInIdx = 0;
706 portMidiInput->clear();
707 for(int i = 0; i < midiInputs.size(); ++i) {
708 portMidiInput->addItem(midiInputs.at(i), i);
709 if (midiInputs.at(i) == preferences.getString(PREF_IO_PORTMIDI_INPUTDEVICE))
710 curMidiInIdx = i;
711 }
712 portMidiInput->setCurrentIndex(curMidiInIdx);
713
714 QStringList midiOutputs = midiDriver->deviceOutList();
715 int curMidiOutIdx = -1; // do not set a midi out device if user never selected one
716 portMidiOutput->clear();
717 portMidiOutput->addItem("", -1);
718 for(int i = 0; i < midiOutputs.size(); ++i) {
719 portMidiOutput->addItem(midiOutputs.at(i), i);
720 if (midiOutputs.at(i) == preferences.getString(PREF_IO_PORTMIDI_OUTPUTDEVICE))
721 curMidiOutIdx = i + 1;
722 }
723 portMidiOutput->setCurrentIndex(curMidiOutIdx);
724 }
725 #endif
726 }
727 }
728 #endif
729
730 #ifndef HAS_MIDI
731 enableMidiInput->setEnabled(false);
732 rcGroup->setEnabled(false);
733 #endif
734
735 for (auto& x : normalWidgets)
736 x->update(setup);
737
738 for (auto& x : uiRelatedWidgets)
739 x->update(setup);
740
741 for (auto& x : audioRelatedWidgets)
742 x->update(setup);
743
744 if (useDefaultValues)
745 preferences.setReturnDefaultValuesMode(false);
746 }
747
748 //---------------------------------------------------------
749 // portaudioApiActivated
750 //---------------------------------------------------------
751
752 #ifdef USE_PORTAUDIO
portaudioApiActivated(int idx)753 void PreferenceDialog::portaudioApiActivated(int idx)
754 {
755 Portaudio* audio = static_cast<Portaudio*>(seq->driver());
756 QStringList devices = audio->deviceList(idx);
757 portaudioDevice->clear();
758 portaudioDevice->addItems(devices);
759 }
760 #else
portaudioApiActivated(int)761 void PreferenceDialog::portaudioApiActivated(int) {}
762 #endif
763
764 //---------------------------------------------------------
765 // ShortcutItem
766 //---------------------------------------------------------
767
operator <(const QTreeWidgetItem & item) const768 bool ShortcutItem::operator<(const QTreeWidgetItem& item) const
769 {
770
771 const QTreeWidget * pTree =treeWidget ();
772 int column = pTree ? pTree->sortColumn() : 0;
773 return QString::localeAwareCompare(text(column).toLower(), item.text(column).toLower()) > 0;
774 }
775
776 //---------------------------------------------------------
777 // updateSCListView
778 //---------------------------------------------------------
779
updateSCListView()780 void PreferenceDialog::updateSCListView()
781 {
782 shortcutList->clear();
783 for (Shortcut* s : localShortcuts) {
784 if (!s)
785 continue;
786 ShortcutItem* newItem = new ShortcutItem;
787 newItem->setText(0, s->descr());
788 if (s->icon() != Icons::Invalid_ICON)
789 newItem->setIcon(0, *icons[int(s->icon())]);
790 newItem->setText(1, s->keysToString());
791 newItem->setData(0, Qt::UserRole, s->key());
792 QString accessibleInfo = tr("Action: %1; Shortcut: %2")
793 .arg(newItem->text(0)).arg(newItem->text(1).isEmpty()
794 ? tr("No shortcut defined") : newItem->text(1));
795 newItem->setData(0, Qt::AccessibleTextRole, accessibleInfo);
796 newItem->setData(1, Qt::AccessibleTextRole, accessibleInfo);
797 if (enableExperimental
798 || (!s->key().startsWith("media")
799 && !s->key().startsWith("layer")
800 #ifdef NDEBUG
801 && !s->key().startsWith("debugger")
802 #endif
803 && !s->key().startsWith("edit_harmony")
804 && !s->key().startsWith("insert-fretframe"))) {
805 shortcutList->addTopLevelItem(newItem);
806 }
807 }
808 shortcutList->resizeColumnToContents(0);
809 }
810
811 //---------------------------------------------------------
812 // resetShortcutClicked
813 // reset selected shortcut to buildin default
814 //---------------------------------------------------------
815
resetShortcutClicked()816 void PreferenceDialog::resetShortcutClicked()
817 {
818 QTreeWidgetItem* active = shortcutList->currentItem();
819 if (!active)
820 return;
821 QString str = active->data(0, Qt::UserRole).toString();
822 if (str.isEmpty())
823 return;
824 Shortcut* shortcut = localShortcuts[str.toLatin1().data()];
825
826 shortcut->reset();
827
828 active->setText(1, shortcut->keysToString());
829 shortcutsChanged = true;
830 applySetActive(true);
831 }
832
833 //---------------------------------------------------------
834 // saveShortcutListClicked
835 //---------------------------------------------------------
836
saveShortcutListClicked()837 void PreferenceDialog::saveShortcutListClicked()
838 {
839 QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save Shortcuts"), preferences.getString(PREF_APP_PATHS_MYSHORTCUTS) + "/shortcuts.xml", tr("MuseScore Shortcuts File") + " (*.xml)", 0, preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog);
840 preferences.setPreference(PREF_APP_PATHS_MYSHORTCUTS, saveFileName);
841 Shortcut::saveToNewFile(saveFileName);
842 }
843
844 //---------------------------------------------------------
845 // loadShortcutListClicked
846 //---------------------------------------------------------
847
loadShortcutListClicked()848 void PreferenceDialog::loadShortcutListClicked()
849 {
850 QString loadFileName = QFileDialog::getOpenFileName(this, tr("Load Shortcuts"), preferences.getString(PREF_APP_PATHS_MYSHORTCUTS), tr("MuseScore Shortcuts File") + " (*.xml)", 0, preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog);
851 if (!loadFileName.isNull()) {
852 preferences.setPreference(PREF_APP_PATHS_MYSHORTCUTS, loadFileName);
853 Shortcut::loadFromNewFile(loadFileName);
854 }
855 }
856
857 //---------------------------------------------------------
858 // clearShortcutClicked
859 //---------------------------------------------------------
860
clearShortcutClicked()861 void PreferenceDialog::clearShortcutClicked()
862 {
863 QTreeWidgetItem* active = shortcutList->currentItem();
864 if (!active)
865 return;
866 QString str = active->data(0, Qt::UserRole).toString();
867 if (str.isEmpty())
868 return;
869 Shortcut* s = localShortcuts[str.toLatin1().data()];
870 s->clear();
871 active->setText(1, "");
872 shortcutsChanged = true;
873 applySetActive(true);
874 }
875
876 //--------------------------------------------------------
877 // filterShortcutsTextChanged
878 //--------------------------------------------------------
879
filterShortcutsTextChanged(const QString & query)880 void PreferenceDialog::filterShortcutsTextChanged(const QString &query )
881 {
882 QTreeWidgetItem *item;
883 for(int i = 0; i < shortcutList->topLevelItemCount(); i++) {
884 item = shortcutList->topLevelItem(i);
885 item->setHidden(!(item->text(0).contains(query, Qt::CaseInsensitive) || item->text(1).contains(query, Qt::CaseInsensitive)));
886 }
887 }
888
889 //--------------------------------------------------------
890 // filterAdvancedPreferences
891 //--------------------------------------------------------
892
filterAdvancedPreferences(const QString & query)893 void PreferenceDialog::filterAdvancedPreferences(const QString& query)
894 {
895 QTreeWidgetItem *item;
896 for(int i = 0; i < advancedWidget->topLevelItemCount(); i++) {
897 item = advancedWidget->topLevelItem(i);
898
899 if(item->text(0).toLower().contains(query.toLower()))
900 item->setHidden(false);
901 else
902 item->setHidden(true);
903 }
904 }
905
906 //--------------------------------------------------------
907 // resetAdvancedPreferenceToDefault
908 //--------------------------------------------------------
909
resetAdvancedPreferenceToDefault()910 void PreferenceDialog::resetAdvancedPreferenceToDefault()
911 {
912 preferences.setReturnDefaultValuesMode(true);
913 for (QTreeWidgetItem* item : advancedWidget->selectedItems()) {
914 PreferenceItem* pref = static_cast<PreferenceItem*>(item);
915 pref->setDefaultValue();
916 }
917 preferences.setReturnDefaultValuesMode(false);
918 }
919
920 //---------------------------------------------------------
921 // selectFgWallpaper
922 //---------------------------------------------------------
923
selectFgWallpaper()924 void PreferenceDialog::selectFgWallpaper()
925 {
926 QString s = mscore->getWallpaper(tr("Choose Notepaper"));
927 if (!s.isNull()) {
928 fgWallpaper->setText(s);
929 updateFgView(false);
930 }
931 }
932
933 //---------------------------------------------------------
934 // selectBgWallpaper
935 //---------------------------------------------------------
936
selectBgWallpaper()937 void PreferenceDialog::selectBgWallpaper()
938 {
939 QString s = mscore->getWallpaper(tr("Choose Background Wallpaper"));
940 if (!s.isNull()) {
941 bgWallpaper->setText(s);
942 updateBgView(false);
943 }
944 }
945
946 //---------------------------------------------------------
947 // selectDefaultStyle
948 //---------------------------------------------------------
949
selectDefaultStyle()950 void PreferenceDialog::selectDefaultStyle()
951 {
952 QString s = mscore->getStyleFilename(true, tr("Choose Default Style"));
953 if (!s.isNull())
954 defaultStyle->setText(s);
955 }
956
957 //---------------------------------------------------------
958 // selectPartStyle
959 //---------------------------------------------------------
960
selectPartStyle()961 void PreferenceDialog::selectPartStyle()
962 {
963 QString s = mscore->getStyleFilename(true, tr("Choose Default Style for Parts"));
964 if (!s.isNull())
965 partStyle->setText(s);
966 }
967
968 //---------------------------------------------------------
969 // selectInstrumentList1
970 //---------------------------------------------------------
971
selectInstrumentList1()972 void PreferenceDialog::selectInstrumentList1()
973 {
974 QString s = QFileDialog::getOpenFileName(
975 this,
976 tr("Choose Instrument List"),
977 instrumentList1->text(),
978 tr("Instrument List") + " (*.xml)",
979 0,
980 preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog
981 );
982 if (!s.isNull())
983 instrumentList1->setText(s);
984 }
985
986 //---------------------------------------------------------
987 // selectInstrumentList2
988 //---------------------------------------------------------
989
selectInstrumentList2()990 void PreferenceDialog::selectInstrumentList2()
991 {
992 QString s = QFileDialog::getOpenFileName(
993 this,
994 tr("Choose Instrument List"),
995 instrumentList2->text(),
996 tr("Instrument List") + " (*.xml)",
997 0,
998 preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog
999 );
1000 if (!s.isNull())
1001 instrumentList2->setText(s);
1002 }
1003
1004 //---------------------------------------------------------
1005 // selectScoreOrderList1
1006 //---------------------------------------------------------
1007
selectScoreOrderList1()1008 void PreferenceDialog::selectScoreOrderList1()
1009 {
1010 QString s = QFileDialog::getOpenFileName(
1011 this,
1012 tr("Choose Score Order List"),
1013 scoreOrderList1->text(),
1014 tr("Score Order List") + " (*.xml)",
1015 0,
1016 preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog
1017 );
1018 if (!s.isNull())
1019 scoreOrderList1->setText(s);
1020 }
1021
1022 //---------------------------------------------------------
1023 // selectScoreOrderList2
1024 //---------------------------------------------------------
1025
selectScoreOrderList2()1026 void PreferenceDialog::selectScoreOrderList2()
1027 {
1028 QString s = QFileDialog::getOpenFileName(
1029 this,
1030 tr("Choose Score Order List"),
1031 scoreOrderList2->text(),
1032 tr("Score Order List") + " (*.xml)",
1033 0,
1034 preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog
1035 );
1036 if (!s.isNull())
1037 scoreOrderList2->setText(s);
1038 }
1039
1040 //---------------------------------------------------------
1041 // zoomDefaultTypeChanged
1042 //---------------------------------------------------------
1043
zoomDefaultTypeChanged(const int index)1044 void PreferenceDialog::zoomDefaultTypeChanged(const int index)
1045 {
1046 // Only enable editing of [zoom-percentage spinner widget] if [Percentage] is selected
1047 zoomDefaultLevel->setEnabled(static_cast<ZoomType>(index) == ZoomType::PERCENTAGE);
1048 }
1049
1050 //---------------------------------------------------------
1051 // selectStartWith
1052 //---------------------------------------------------------
1053
selectStartWith()1054 void PreferenceDialog::selectStartWith()
1055 {
1056 QString s = QFileDialog::getOpenFileName(
1057 this,
1058 tr("Choose Starting Score"),
1059 sessionScore->text(),
1060 tr("MuseScore Files") + " (*.mscz *.mscx);;" + tr("All") + " (*)",
1061 0,
1062 preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog
1063 );
1064 if (!s.isNull())
1065 sessionScore->setText(s);
1066 }
1067
1068 //---------------------------------------------------------
1069 // fgClicked
1070 //---------------------------------------------------------
1071
updateFgView(bool useColor)1072 void PreferenceDialog::updateFgView(bool useColor)
1073 {
1074 fgColorButton->setChecked(useColor);
1075 fgWallpaperButton->setChecked(!useColor);
1076 fgUseColorInPalettes->setChecked(preferences.getBool(PREF_UI_CANVAS_FG_USECOLOR_IN_PALETTES));
1077 fgWallpaper->setEnabled(!useColor);
1078 fgWallpaperSelect->setEnabled(!useColor);
1079 fgUseColorInPalettes->setEnabled(useColor);
1080
1081 if (useColor) {
1082 fgColorLabel->setColor(preferences.getColor(PREF_UI_CANVAS_FG_COLOR));
1083 fgColorLabel->setPixmap(0);
1084 }
1085 else {
1086 fgColorLabel->setPixmap(new QPixmap(fgWallpaper->text()));
1087 }
1088 }
1089
1090 //---------------------------------------------------------
1091 // bgClicked
1092 //---------------------------------------------------------
1093
updateBgView(bool useColor)1094 void PreferenceDialog::updateBgView(bool useColor)
1095 {
1096 bgColorButton->setChecked(useColor);
1097 bgWallpaperButton->setChecked(!useColor);
1098 bgWallpaper->setEnabled(!useColor);
1099 bgWallpaperSelect->setEnabled(!useColor);
1100
1101 if (useColor) {
1102 bgColorLabel->setColor(preferences.getColor(PREF_UI_CANVAS_BG_COLOR));
1103 bgColorLabel->setPixmap(0);
1104 }
1105 else {
1106 bgColorLabel->setPixmap(new QPixmap(bgWallpaper->text()));
1107 }
1108 }
1109
1110
1111 //---------------------------------------------------------
1112 // languageUpdate
1113 //---------------------------------------------------------
1114
languageUpdate()1115 void PreferenceDialog::languageUpdate()
1116 {
1117 language->blockSignals(true);
1118 language->clear();
1119 QString lang = preferences.getString(PREF_UI_APP_LANGUAGE);
1120 int curIdx = 0;
1121 for(int i = 0; i < mscore->languages().size(); ++i) {
1122 language->addItem(mscore->languages().at(i).name, i);
1123 if (mscore->languages().at(i).key == lang)
1124 curIdx = i;
1125 }
1126 language->blockSignals(false);
1127 language->setCurrentIndex(curIdx);
1128 }
1129
1130 //---------------------------------------------------------
1131 // languageApply
1132 //---------------------------------------------------------
1133
languageApply()1134 void PreferenceDialog::languageApply()
1135 {
1136 int lang = language->itemData(language->currentIndex()).toInt();
1137 QString l = lang == 0 ? "system" : mscore->languages().at(lang).key;
1138 bool languageChanged = l != preferences.getString(PREF_UI_APP_LANGUAGE);
1139
1140 if (languageChanged) {
1141 preferences.setPreference(PREF_UI_APP_LANGUAGE, l);
1142 setMscoreLocale(preferences.getString(PREF_UI_APP_LANGUAGE));
1143 mscore->update();
1144 }
1145 }
1146
1147
1148 //---------------------------------------------------------
1149 // updateCharsetListGP
1150 //---------------------------------------------------------
1151
updateCharsetListGP()1152 void PreferenceDialog::updateCharsetListGP()
1153 {
1154 QList<QByteArray> charsets = QTextCodec::availableCodecs();
1155 std::sort(charsets.begin(), charsets.end());
1156 int idx = 0;
1157 importCharsetListGP->clear();
1158 for (QByteArray charset : charsets) {
1159 importCharsetListGP->addItem(charset);
1160 if (charset == preferences.getString(PREF_IMPORT_GUITARPRO_CHARSET))
1161 importCharsetListGP->setCurrentIndex(idx);
1162 idx++;
1163 }
1164 }
1165
1166 //---------------------------------------------------------
1167 // updateCharsetListOve
1168 //---------------------------------------------------------
1169
updateCharsetListOve()1170 void PreferenceDialog::updateCharsetListOve()
1171 {
1172 QList<QByteArray> charsets = QTextCodec::availableCodecs();
1173 std::sort(charsets.begin(), charsets.end());
1174 int idx = 0;
1175 importCharsetListOve->clear();
1176 for (QByteArray charset : charsets) {
1177 importCharsetListOve->addItem(charset);
1178 if (charset == preferences.getString(PREF_IMPORT_OVERTURE_CHARSET))
1179 importCharsetListOve->setCurrentIndex(idx);
1180 idx++;
1181 }
1182 }
1183
1184 #ifdef AVSOMR
1185 //---------------------------------------------------------
1186 // updateUseLocalAvsOmr
1187 //---------------------------------------------------------
1188
updateUseLocalAvsOmr()1189 void PreferenceDialog::updateUseLocalAvsOmr()
1190 {
1191 useLocalAvsOmr->setChecked(preferences.getBool(PREF_IMPORT_AVSOMR_USELOCAL));
1192 Avs::AvsOmrLocal::instance()->isInstalledAsync([this](bool isInstalled) {
1193 QString text = QObject::tr("Use local OMR engine");
1194 if (isInstalled)
1195 text += " (" + QObject::tr("Installed") + ")";
1196 else
1197 text += " (" + QObject::tr("Not installed, needs internet connection for installing") + ")";
1198
1199 useLocalAvsOmr->setText(text);
1200 });
1201 }
1202 #else
updateUseLocalAvsOmr()1203 void PreferenceDialog::updateUseLocalAvsOmr()
1204 {
1205 ;
1206 }
1207 #endif
1208
1209 //---------------------------------------------------------
1210 // applyPageVertical
1211 //---------------------------------------------------------
1212
applyPageVertical()1213 void PreferenceDialog::applyPageVertical()
1214 {
1215 const auto cv = mscore->currentScoreView();
1216 preferences.setPreference(PREF_UI_CANVAS_SCROLL_VERTICALORIENTATION, pageVertical->isChecked());
1217 MScore::setVerticalOrientation(pageVertical->isChecked());
1218 for (Score* s : mscore->scores()) {
1219 s->doLayout();
1220 for (Score* ss : s->scoreList())
1221 ss->doLayout();
1222 }
1223 if (cv)
1224 cv->pageTop();
1225 mscore->scorePageLayoutChanged();
1226 mscore->update();
1227 }
1228
1229 //---------------------------------------------------------
1230 // buttonBoxClicked
1231 //---------------------------------------------------------
1232
buttonBoxClicked(QAbstractButton * button)1233 void PreferenceDialog::buttonBoxClicked(QAbstractButton* button)
1234 {
1235 switch(buttonBox->standardButton(button)) {
1236 case QDialogButtonBox::Apply:
1237 apply();
1238 break;
1239 case QDialogButtonBox::Ok:
1240 apply();
1241 // intentional ??
1242 // fall through
1243 case QDialogButtonBox::Cancel:
1244 default:
1245 hide();
1246 break;
1247 }
1248 }
1249
1250 //---------------------------------------------------------
1251 // applySetActive
1252 //---------------------------------------------------------
1253
applySetActive(bool active)1254 void PreferenceDialog::applySetActive(bool active)
1255 {
1256 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(active);
1257 }
1258
1259
1260 //---------------------------------------------------------
1261 // applyActivate
1262 //---------------------------------------------------------
1263
applyActivate()1264 void PreferenceDialog::applyActivate()
1265 {
1266 applySetActive(true);
1267 }
1268
1269 //---------------------------------------------------------
1270 // applyActivate
1271 //---------------------------------------------------------
1272
checkApplyActivation()1273 void PreferenceDialog::checkApplyActivation()
1274 {
1275 qDebug() << modifiedWidgets.size() << " " << modifiedUiWidgets.size() << " " << modifiedAudioWidgets.size();
1276 if (modifiedWidgets.size() == 0 && modifiedUiWidgets.size() == 0 && modifiedAudioWidgets.size() == 0)
1277 applySetActive(false);
1278 }
1279
1280 //---------------------------------------------------------
1281 // widgetModified
1282 //---------------------------------------------------------
1283
widgetModified()1284 void PreferenceDialog::widgetModified()
1285 {
1286 PreferenceItem* item = static_cast<PreferenceItem*>(sender());
1287 const auto itemIter = std::find(modifiedWidgets.begin(), modifiedWidgets.end(), item);
1288 if (itemIter == modifiedWidgets.end()) {
1289 modifiedWidgets.push_back(item);
1290 applySetActive(true);
1291 }
1292 else {
1293 if (!item->isModified()) {
1294 modifiedWidgets.erase(itemIter);
1295 checkApplyActivation();
1296 }
1297 }
1298 }
1299
1300 //---------------------------------------------------------
1301 // uiWidgetModified
1302 //---------------------------------------------------------
1303
uiWidgetModified()1304 void PreferenceDialog::uiWidgetModified()
1305 {
1306 PreferenceItem* item = static_cast<PreferenceItem*>(sender());
1307 const auto itemIter = std::find(modifiedUiWidgets.begin(), modifiedUiWidgets.end(), item);
1308 if (itemIter == modifiedUiWidgets.end()) {
1309 modifiedUiWidgets.push_back(item);
1310 applySetActive(true);
1311 }
1312 else {
1313 if (!item->isModified()) {
1314 modifiedUiWidgets.erase(itemIter);
1315 checkApplyActivation();
1316 }
1317 }
1318 }
1319
1320
1321 //---------------------------------------------------------
1322 // audioWidgetModified
1323 //---------------------------------------------------------
1324
audioWidgetModified()1325 void PreferenceDialog::audioWidgetModified()
1326 {
1327 PreferenceItem* item = static_cast<PreferenceItem*>(sender());
1328 const auto itemIter = std::find(modifiedAudioWidgets.begin(), modifiedAudioWidgets.end(), item);
1329 if (itemIter == modifiedAudioWidgets.end()) {
1330 modifiedAudioWidgets.push_back(item);
1331 applySetActive(true);
1332 }
1333 else {
1334 if (!item->isModified()) {
1335 modifiedAudioWidgets.erase(itemIter);
1336 checkApplyActivation();
1337 }
1338 }
1339 }
1340
1341 //---------------------------------------------------------
1342 // apply
1343 //---------------------------------------------------------
1344
apply()1345 void PreferenceDialog::apply()
1346 {
1347 const auto cv = mscore->currentScoreView();
1348
1349 QElapsedTimer timer;
1350 timer.start();
1351
1352 if(buttonBox->button(QDialogButtonBox::Apply)->isEnabled() == false)
1353 return;
1354
1355 bool uiStyleThemeChanged = false;
1356 bool audioModified = false;
1357
1358 applySetActive(false);
1359 buttonBox->button(QDialogButtonBox::Apply)->setText(tr("Applying…"));
1360 buttonBox->repaint();
1361
1362 std::vector<QString> changedAdvancedProperties = advancedWidget->save();
1363 for (auto x : changedAdvancedProperties)
1364 if (x.startsWith("ui"))
1365 uiStyleThemeChanged = true;
1366
1367 for (auto& x : modifiedWidgets)
1368 x->apply();
1369
1370 for (auto& x : modifiedUiWidgets) {
1371 x->apply();
1372 uiStyleThemeChanged = true;
1373 }
1374
1375 if (modifiedAudioWidgets.size() > 0)
1376 audioModified = true;
1377
1378 #ifdef AVSOMR
1379 preferences.setPreference(PREF_IMPORT_AVSOMR_USELOCAL, useLocalAvsOmr->isChecked());
1380 #endif
1381
1382 if (audioModified) {
1383 bool wasJack = (preferences.getBool(PREF_IO_JACK_USEJACKMIDI) || preferences.getBool(PREF_IO_JACK_USEJACKAUDIO));
1384 bool wasJackAudio = preferences.getBool(PREF_IO_JACK_USEJACKAUDIO);
1385 bool wasJackMidi = preferences.getBool(PREF_IO_JACK_USEJACKMIDI);
1386 preferences.setPreference(PREF_IO_JACK_USEJACKAUDIO, jackDriver->isChecked() && useJackAudio->isChecked());
1387 preferences.setPreference(PREF_IO_JACK_USEJACKMIDI, jackDriver->isChecked() && useJackMidi->isChecked());
1388 bool nowJack = (preferences.getBool(PREF_IO_JACK_USEJACKMIDI) || preferences.getBool(PREF_IO_JACK_USEJACKAUDIO));
1389 bool jackParametersChanged = (preferences.getBool(PREF_IO_JACK_USEJACKAUDIO) != wasJackAudio
1390 || preferences.getBool(PREF_IO_JACK_USEJACKMIDI) != wasJackMidi
1391 || preferences.getBool(PREF_IO_JACK_REMEMBERLASTCONNECTIONS) != rememberLastMidiConnections->isChecked()
1392 || preferences.getBool(PREF_IO_JACK_TIMEBASEMASTER) != becomeTimebaseMaster->isChecked())
1393 && (wasJack && nowJack);
1394 //till this
1395
1396 preferences.setPreference(PREF_IO_JACK_USEJACKTRANSPORT, jackDriver->isChecked() && useJackTransport->isChecked()); //this
1397
1398 if (jackParametersChanged) {
1399 // Change parameters of JACK driver without unload
1400 if (seq) {
1401 if (seq->driver() == nullptr) {
1402 qDebug("sequencer driver is null");
1403 restartAudioEngine();
1404 }
1405 seq->driver()->init(true);
1406 if (!seq->init(true))
1407 qDebug("sequencer init failed");
1408 }
1409 }
1410 else if (
1411 (wasJack != nowJack)
1412 || (preferences.getBool(PREF_IO_PORTAUDIO_USEPORTAUDIO) != portaudioDriver->isChecked())
1413 || (preferences.getBool(PREF_IO_PULSEAUDIO_USEPULSEAUDIO) != pulseaudioDriver->isChecked())
1414 #ifdef USE_ALSA
1415 || (preferences.getString(PREF_IO_ALSA_DEVICE) != alsaDevice->text())
1416 || (preferences.getInt(PREF_IO_ALSA_SAMPLERATE) != alsaSampleRate->currentData().toInt())
1417 || (preferences.getInt(PREF_IO_ALSA_PERIODSIZE) != alsaPeriodSize->currentData().toInt())
1418 || (preferences.getInt(PREF_IO_ALSA_FRAGMENTS) != alsaFragments->value())
1419 #endif
1420 ) {
1421 preferences.setPreference(PREF_IO_ALSA_USEALSAAUDIO, alsaDriver->isChecked());
1422 preferences.setPreference(PREF_IO_PORTAUDIO_USEPORTAUDIO, portaudioDriver->isChecked());
1423 preferences.setPreference(PREF_IO_PULSEAUDIO_USEPULSEAUDIO, pulseaudioDriver->isChecked());
1424 preferences.setPreference(PREF_IO_ALSA_DEVICE, alsaDevice->text());
1425 preferences.setPreference(PREF_IO_ALSA_SAMPLERATE, alsaSampleRate->currentData().toInt());
1426 preferences.setPreference(PREF_IO_ALSA_PERIODSIZE, alsaPeriodSize->currentData().toInt());
1427 preferences.setPreference(PREF_IO_ALSA_FRAGMENTS, alsaFragments->value());
1428
1429 restartAudioEngine();
1430 }
1431 #ifdef USE_PORTAUDIO
1432 if (portAudioIsUsed && !noSeq) {
1433 Portaudio* audio = static_cast<Portaudio*>(seq->driver());
1434 preferences.setPreference(PREF_IO_PORTAUDIO_DEVICE, audio->deviceIndex(portaudioApi->currentIndex(), portaudioDevice->currentIndex()));
1435 }
1436 #endif
1437
1438 #ifdef USE_PORTMIDI
1439 preferences.setPreference(PREF_IO_PORTMIDI_INPUTDEVICE, portMidiInput->currentText());
1440 preferences.setPreference(PREF_IO_PORTMIDI_OUTPUTDEVICE, portMidiOutput->currentText());
1441 if (seq->driver() && static_cast<PortMidiDriver*>(static_cast<Portaudio*>(seq->driver())->mididriver())->isSameCoreMidiIacBus(preferences.getString(PREF_IO_PORTMIDI_INPUTDEVICE), preferences.getString(PREF_IO_PORTMIDI_OUTPUTDEVICE))) {
1442 QMessageBox msgBox;
1443 msgBox.setWindowTitle(tr("Possible MIDI Loopback"));
1444 msgBox.setIcon(QMessageBox::Warning);
1445 msgBox.setText(tr("Warning: You used the same CoreMIDI IAC bus for input and output. This will cause problematic loopback, whereby MuseScore's output MIDI messages will be sent back to MuseScore as input, causing confusion. To avoid this problem, access Audio MIDI Setup via Spotlight to create a dedicated virtual port for MuseScore's MIDI output, restart MuseScore, return to Preferences, and select your new virtual port for MuseScore's MIDI output. Other programs may then use that dedicated virtual port to receive MuseScore's MIDI output."));
1446 msgBox.exec();
1447 }
1448 #endif
1449 }
1450
1451 if (shortcutsChanged) {
1452 shortcutsChanged = false;
1453 for(const Shortcut* s : localShortcuts) {
1454 Shortcut* os = Shortcut::getShortcut(s->key());
1455 if (os) {
1456 if (!os->compareKeys(*s))
1457 os->setKeys(*s);
1458 }
1459 }
1460 Shortcut::dirty = true;
1461 }
1462
1463 if(uiStyleThemeChanged) {
1464 WorkspacesManager::retranslateAll();
1465 preferences.setPreference(PREF_APP_WORKSPACE, WorkspacesManager::currentWorkspace()->id());
1466 WorkspacesManager::currentWorkspace()->save();
1467 emit mscore->workspacesChanged();
1468 }
1469
1470 emit preferencesChanged(false, uiStyleThemeChanged);
1471 uiStyleThemeChanged = false;
1472 preferences.save();
1473 mscore->startAutoSave();
1474
1475 // Smooth panning
1476 if (cv) {
1477 cv->panSettings().loadFromPreferences();
1478 cv->setControlCursorVisible(preferences.getBool(PREF_PAN_CURSOR_VISIBLE));
1479 }
1480
1481 modifiedWidgets.clear();
1482 modifiedUiWidgets.clear();
1483 modifiedAudioWidgets.clear();
1484
1485 buttonBox->button(QDialogButtonBox::Apply)->setText(tr("Apply"));
1486 qDebug() << "Final: " << timer.elapsed();
1487 }
1488
1489 //---------------------------------------------------------
1490 // resetAllValues
1491 //---------------------------------------------------------
1492
resetAllValues()1493 void PreferenceDialog::resetAllValues()
1494 {
1495 updateValues(true);
1496
1497 shortcutsChanged = true;
1498 applySetActive(true);
1499 qDeleteAll(localShortcuts);
1500 localShortcuts.clear();
1501 Shortcut::resetToDefault();
1502 for (const Shortcut* s : Shortcut::shortcuts())
1503 localShortcuts[s->key()] = new Shortcut(*s);
1504 updateSCListView();
1505 }
1506
1507 //---------------------------------------------------------
1508 // styleFileButtonClicked
1509 //---------------------------------------------------------
1510
styleFileButtonClicked()1511 void PreferenceDialog::styleFileButtonClicked()
1512 {
1513 QString fn = mscore->getStyleFilename(true, tr("Choose Default Style for Imports"));
1514 if (fn.isEmpty())
1515 return;
1516 importStyleFile->setText(fn);
1517 }
1518
1519 //---------------------------------------------------------
1520 // midiRemoteControlClearClicked
1521 //---------------------------------------------------------
1522
midiRemoteControlClearClicked()1523 void PreferenceDialog::midiRemoteControlClearClicked()
1524 {
1525 for (int i = 0; i < MIDI_REMOTES; ++i)
1526 preferences.clearMidiRemote(i);
1527 updateRemote();
1528 }
1529
1530 //---------------------------------------------------------
1531 // exclusiveAudioDriver
1532 // Allow user to select only one audio driver, restrict
1533 // to uncheck all drivers.
1534 //---------------------------------------------------------
1535
exclusiveAudioDriver(bool on)1536 void PreferenceDialog::exclusiveAudioDriver(bool on)
1537 {
1538 if (on) {
1539 if (portaudioDriver != QObject::sender())
1540 portaudioDriver->setChecked(false);
1541 if (pulseaudioDriver != QObject::sender())
1542 pulseaudioDriver->setChecked(false);
1543 if (alsaDriver != QObject::sender())
1544 alsaDriver->setChecked(false);
1545 if (jackDriver != QObject::sender())
1546 jackDriver->setChecked(false);
1547 if (jackDriver == QObject::sender() && !useJackMidi->isChecked() && !useJackAudio->isChecked()) {
1548 useJackMidi->setChecked(true);
1549 useJackAudio->setChecked(true);
1550 }
1551 }
1552 else {
1553 // True if QGroupBox is checked now or was checked before clicking on it
1554 bool portAudioChecked = portaudioDriver->isVisible() && ((QObject::sender() != portaudioDriver && portaudioDriver->isChecked()) || QObject::sender() == portaudioDriver);
1555 bool pulseaudioChecked = pulseaudioDriver->isVisible() && ((QObject::sender() != pulseaudioDriver && pulseaudioDriver->isChecked()) || QObject::sender() == pulseaudioDriver);
1556 bool alsaChecked = alsaDriver->isVisible() && ((QObject::sender() != alsaDriver && alsaDriver->isChecked()) || QObject::sender() == alsaDriver);
1557 bool jackChecked = jackDriver->isVisible() && ((QObject::sender() != jackDriver && jackDriver->isChecked()) || QObject::sender() == jackDriver);
1558 // If nothing is checked, prevent looping (run with -s, sequencer disabled)
1559 if (!(portAudioChecked || pulseaudioChecked || alsaChecked || jackChecked))
1560 return;
1561 // Don't allow to uncheck all drivers
1562 if (portaudioDriver == QObject::sender())
1563 portaudioDriver->setChecked(!(pulseaudioChecked || alsaChecked || jackChecked));
1564 if (pulseaudioDriver == QObject::sender())
1565 pulseaudioDriver->setChecked(!(portAudioChecked || alsaChecked || jackChecked));
1566 if (alsaDriver == QObject::sender())
1567 alsaDriver->setChecked(!(portAudioChecked || pulseaudioChecked || jackChecked));
1568 if (jackDriver == QObject::sender())
1569 jackDriver->setChecked(!(portAudioChecked || pulseaudioChecked || alsaChecked));
1570 }
1571 }
1572
1573 //---------------------------------------------------------
1574 // exclusiveJackDriver
1575 // Allow user to select "use Jack Audio", "use Jack MIDI"
1576 // or both, but forbid unchecking both.
1577 // There is no need to select "JACK audio server" without
1578 // checking any of them.
1579 //---------------------------------------------------------
1580
nonExclusiveJackDriver(bool on)1581 void PreferenceDialog::nonExclusiveJackDriver(bool on)
1582 {
1583 if (!on) {
1584 if (QObject::sender() == useJackAudio)
1585 useJackAudio->setChecked(!useJackMidi->isChecked());
1586 else if (QObject::sender() == useJackMidi)
1587 useJackMidi->setChecked(!useJackAudio->isChecked());
1588 }
1589 }
1590
1591 //---------------------------------------------------------
1592 // selectScoresDirectory
1593 //---------------------------------------------------------
1594
selectScoresDirectory()1595 void PreferenceDialog::selectScoresDirectory()
1596 {
1597 QString s = QFileDialog::getExistingDirectory(
1598 this,
1599 tr("Choose Score Folder"),
1600 myScores->text(),
1601 QFileDialog::ShowDirsOnly | (preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog)
1602 );
1603 if (!s.isNull())
1604 myScores->setText(s);
1605 }
1606
1607 //---------------------------------------------------------
1608 // selectStylesDirectory
1609 //---------------------------------------------------------
1610
selectStylesDirectory()1611 void PreferenceDialog::selectStylesDirectory()
1612 {
1613 QString s = QFileDialog::getExistingDirectory(
1614 this,
1615 tr("Choose Style Folder"),
1616 myStyles->text(),
1617 QFileDialog::ShowDirsOnly | (preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog)
1618 );
1619 if (!s.isNull())
1620 myStyles->setText(s);
1621 }
1622
1623 //---------------------------------------------------------
1624 // selectTemplatesDirectory
1625 //---------------------------------------------------------
1626
selectTemplatesDirectory()1627 void PreferenceDialog::selectTemplatesDirectory()
1628 {
1629 QString s = QFileDialog::getExistingDirectory(
1630 this,
1631 tr("Choose Template Folder"),
1632 myTemplates->text(),
1633 QFileDialog::ShowDirsOnly | (preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog)
1634 );
1635 if (!s.isNull())
1636 myTemplates->setText(s);
1637 }
1638
1639 //---------------------------------------------------------
1640 // selectPluginsDirectory
1641 //---------------------------------------------------------
1642
selectPluginsDirectory()1643 void PreferenceDialog::selectPluginsDirectory()
1644 {
1645 QString s = QFileDialog::getExistingDirectory(
1646 this,
1647 tr("Choose Plugin Folder"),
1648 myPlugins->text(),
1649 QFileDialog::ShowDirsOnly | (preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog)
1650 );
1651 if (!s.isNull())
1652 myPlugins->setText(s);
1653 }
1654
1655 //---------------------------------------------------------
1656 // selectImagesDirectory
1657 //---------------------------------------------------------
1658
selectImagesDirectory()1659 void PreferenceDialog::selectImagesDirectory()
1660 {
1661 QString s = QFileDialog::getExistingDirectory(
1662 this,
1663 tr("Choose Image Folder"),
1664 myImages->text(),
1665 QFileDialog::ShowDirsOnly | (preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog)
1666 );
1667 if (!s.isNull())
1668 myImages->setText(s);
1669 }
1670
1671 //---------------------------------------------------------
1672 // changeSoundfontPaths
1673 //---------------------------------------------------------
1674
changeSoundfontPaths()1675 void PreferenceDialog::changeSoundfontPaths()
1676 {
1677 PathListDialog pld(this);
1678 pld.setWindowTitle(tr("SoundFont Folders"));
1679 pld.setPath(mySoundfonts->text());
1680 if(pld.exec())
1681 mySoundfonts->setText(pld.path());
1682 }
1683
1684 //---------------------------------------------------------
1685 // selectExtensionsDirectory
1686 //---------------------------------------------------------
1687
selectExtensionsDirectory()1688 void PreferenceDialog::selectExtensionsDirectory()
1689 {
1690 QString s = QFileDialog::getExistingDirectory(
1691 this,
1692 tr("Choose Extensions Folder"),
1693 myExtensions->text(),
1694 QFileDialog::ShowDirsOnly | (preferences.getBool(PREF_UI_APP_USENATIVEDIALOGS) ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog)
1695 );
1696 if (!s.isNull())
1697 myExtensions->setText(s);
1698 }
1699
1700 //---------------------------------------------------------
1701 // updateLanguagesClicked
1702 //---------------------------------------------------------
1703
updateTranslationClicked()1704 void PreferenceDialog::updateTranslationClicked()
1705 {
1706 ResourceManager r(this);
1707 r.selectLanguagesTab();
1708 r.exec();
1709 }
1710
1711 //---------------------------------------------------------
1712 // defineShortcutClicked
1713 //---------------------------------------------------------
1714
defineShortcutClicked()1715 void PreferenceDialog::defineShortcutClicked()
1716 {
1717 QTreeWidgetItem* active = shortcutList->currentItem();
1718 if (!active)
1719 return;
1720 QString str = active->data(0, Qt::UserRole).toString();
1721 if (str.isEmpty())
1722 return;
1723 Shortcut* s = localShortcuts[str.toLatin1().data()];
1724 ShortcutCaptureDialog sc(s, localShortcuts, this);
1725 int rv = sc.exec();
1726 if (rv == 0)
1727 return;
1728 if (rv == 2)
1729 s->clear();
1730 s->addShortcut(sc.getKey());
1731 active->setText(1, s->keysToString());
1732 shortcutsChanged = true;
1733 applySetActive(true);
1734 }
1735
1736
1737 //---------------------------------------------------------
1738 // printShortcutsClicked
1739 //---------------------------------------------------------
1740
printShortcutsClicked()1741 void PreferenceDialog::printShortcutsClicked()
1742 {
1743 #ifndef QT_NO_PRINTER
1744 QPrinter printer(QPrinter::HighResolution);
1745 const MStyle& s = MScore::defaultStyle();
1746 qreal pageW = s.value(Sid::pageWidth).toReal();
1747 qreal pageH = s.value(Sid::pageHeight).toReal();
1748 printer.setPaperSize(QSizeF(pageW, pageH), QPrinter::Inch);
1749
1750 printer.setCreator("MuseScore Version: " VERSION);
1751 printer.setFullPage(true);
1752 printer.setColorMode(QPrinter::Color);
1753 printer.setDocName(tr("MuseScore Shortcuts"));
1754 printer.setOutputFormat(QPrinter::NativeFormat);
1755
1756 QPrintDialog pd(&printer, 0);
1757 pd.setWindowTitle(tr("Print Shortcuts"));
1758 if (!pd.exec())
1759 return;
1760 qreal dpmm = printer.logicalDpiY() / 25.4;
1761 qreal ph = printer.height();
1762 qreal tm = dpmm * 15;
1763 qreal bm = dpmm * 15;
1764 qreal lm = dpmm * 20;
1765
1766 QPainter p;
1767 p.begin(&printer);
1768 qreal y = 0.0;
1769 qreal lh = QFontMetricsF(p.font()).lineSpacing();
1770
1771 // get max width for description
1772 QMapIterator<QString, Shortcut*> isc(localShortcuts);
1773 qreal col1Width = 0.0;
1774 while (isc.hasNext()) {
1775 isc.next();
1776 Shortcut* sc = isc.value();
1777 col1Width = qMax(col1Width, QFontMetricsF(p.font()).width(sc->descr()));
1778 }
1779
1780 int idx = 0;
1781 QTreeWidgetItem* item = shortcutList->topLevelItem(0);
1782 while (item) {
1783 if (idx == 0 || y >= (ph - bm)) {
1784 y = tm;
1785 if (idx)
1786 printer.newPage();
1787 else {
1788 p.save();
1789 QFont font(p.font());
1790 font.setPointSizeF(14.0);
1791 font.setBold(true);
1792 p.setFont(font);
1793 p.drawText(lm, y, tr("MuseScore Shortcuts"));
1794 p.restore();
1795 y += QFontMetricsF(font).lineSpacing();
1796 y += 5 * dpmm;
1797 }
1798 }
1799 p.drawText(lm, y, item->text(0));
1800 p.drawText(col1Width + lm + 5 * dpmm, y, item->text(1));
1801 y += lh;
1802 ++idx;
1803 item = shortcutList->itemBelow(item);
1804 }
1805 p.end();
1806 #endif
1807 }
1808
1809 //---------------------------------------------------------
1810 // rebuildAudioDrivers
1811 //---------------------------------------------------------
1812
restartAudioEngine()1813 void PreferenceDialog::restartAudioEngine()
1814 {
1815 mscore->restartAudioEngine();
1816 }
1817
1818 //---------------------------------------------------------
1819 // updateShortestNote
1820 //---------------------------------------------------------
1821
updateShortestNote()1822 void PreferenceDialog::updateShortestNote()
1823 {
1824 int shortestNoteIndex;
1825 int nn = preferences.getInt(PREF_IO_MIDI_SHORTESTNOTE);
1826 if (nn == MScore::division)
1827 shortestNoteIndex = 0; // Quarter
1828 else if (nn == MScore::division / 2)
1829 shortestNoteIndex = 1; // Eighth
1830 else if (nn == MScore::division / 4)
1831 shortestNoteIndex = 2; // etc.
1832 else if (nn == MScore::division / 8)
1833 shortestNoteIndex = 3;
1834 else if (nn == MScore::division / 16)
1835 shortestNoteIndex = 4;
1836 else if (nn == MScore::division / 32)
1837 shortestNoteIndex = 5;
1838 else if (nn == MScore::division / 64)
1839 shortestNoteIndex = 6;
1840 else if (nn == MScore::division / 128)
1841 shortestNoteIndex = 7;
1842 else if (nn == MScore::division / 256)
1843 shortestNoteIndex = 8;
1844 else {
1845 qDebug("Unknown shortestNote value of %d, defaulting to 16th", nn);
1846 shortestNoteIndex = 2;
1847 }
1848 shortestNote->setCurrentIndex(shortestNoteIndex);
1849 }
1850
1851 //---------------------------------------------------------
1852 // applyShortestNote
1853 //---------------------------------------------------------
1854
applyShortestNote()1855 void PreferenceDialog::applyShortestNote()
1856 {
1857 int ticks = MScore::division / 4;
1858 switch (shortestNote->currentIndex()) {
1859 case 0: ticks = MScore::division; break;
1860 case 1: ticks = MScore::division / 2; break;
1861 case 2: ticks = MScore::division / 4; break;
1862 case 3: ticks = MScore::division / 8; break;
1863 case 4: ticks = MScore::division / 16; break;
1864 case 5: ticks = MScore::division / 32; break;
1865 case 6: ticks = MScore::division / 64; break;
1866 case 7: ticks = MScore::division / 128; break;
1867 case 8: ticks = MScore::division / 256; break;
1868 default: {
1869 qDebug("Unknown index for shortestNote: %d, defaulting to 16th",
1870 shortestNote->currentIndex());
1871 ticks = MScore::division / 4;
1872 }
1873 }
1874 preferences.setPreference(PREF_IO_MIDI_SHORTESTNOTE, ticks);
1875 }
1876
1877 } // namespace Ms
1878