1 //=============================================================================
2 //  MuseScore
3 //  Linux Music Score Editor
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 "preferenceslistwidget.h"
21 #include <cfloat>
22 
23 namespace Ms {
24 
25 
PreferencesListWidget(QWidget * parent)26 PreferencesListWidget::PreferencesListWidget(QWidget* parent)
27       : QTreeWidget(parent)
28       {
29       setRootIsDecorated(false);
30       setHeaderLabels(QStringList() << tr("Preference") << tr("Value"));
31       header()->setStretchLastSection(false);
32       header()->setSectionResizeMode(0, QHeaderView::Stretch);
33       setAccessibleName(tr("Advanced preferences"));
34       setAccessibleDescription(tr("Access to more advanced preferences"));
35       setAlternatingRowColors(true);
36       setSortingEnabled(true);
37       sortByColumn(0, Qt::AscendingOrder);
38       setAllColumnsShowFocus(true);
39       }
40 
loadPreferences()41 void PreferencesListWidget::loadPreferences()
42       {
43       for (const QString &key : preferences.allPreferences().keys()) {
44             Preference* pref = preferences.allPreferences().value(key);
45 
46             if (pref->showInAdvancedList()) {
47                   // multiple dispatch using Visitor pattern, see overloaded visit() methods
48                   pref->accept(key, *this);
49                   }
50             }
51       }
52 
updatePreferences()53 void PreferencesListWidget::updatePreferences()
54       {
55       for (PreferenceItem* item : _preferenceItems.values())
56             item->update();
57       }
58 
addPreference(PreferenceItem * item)59 void PreferencesListWidget::addPreference(PreferenceItem* item)
60       {
61       addTopLevelItem(item);
62       setItemWidget(item, PREF_VALUE_COLUMN, item->editor());
63       _preferenceItems[item->name()] = item;
64       }
65 
visit(QString key,IntPreference *)66 void PreferencesListWidget::visit(QString key, IntPreference*)
67       {
68       IntPreferenceItem* item = new IntPreferenceItem(key);
69       addPreference(item);
70       }
71 
visit(QString key,DoublePreference *)72 void PreferencesListWidget::visit(QString key, DoublePreference*)
73       {
74       DoublePreferenceItem* item = new DoublePreferenceItem(key);
75       addPreference(item);
76       }
77 
visit(QString key,BoolPreference *)78 void PreferencesListWidget::visit(QString key, BoolPreference*)
79       {
80       BoolPreferenceItem* item = new BoolPreferenceItem(key);
81       addPreference(item);
82       }
83 
visit(QString key,StringPreference *)84 void PreferencesListWidget::visit(QString key, StringPreference*)
85       {
86       StringPreferenceItem* item = new StringPreferenceItem(key);
87       addPreference(item);
88       }
89 
visit(QString key,ColorPreference *)90 void PreferencesListWidget::visit(QString key, ColorPreference*)
91       {
92       ColorPreferenceItem* item = new ColorPreferenceItem(key);
93       addPreference(item);
94       }
95 
save()96 std::vector<QString> PreferencesListWidget::save()
97       {
98       std::vector<QString> changedPreferences;
99       for (int i = 0; i < topLevelItemCount(); ++i) {
100             PreferenceItem* item = static_cast<PreferenceItem*>(topLevelItem(i));
101             if (item->isModified()) {
102                   item->apply();
103                   changedPreferences.push_back(item->name());
104                   }
105             }
106 
107       return changedPreferences;
108       }
109 
110 //---------------------------------------------------------
111 //   PreferenceItem
112 //---------------------------------------------------------
113 
PreferenceItem(QString name)114 PreferenceItem::PreferenceItem(QString name)
115       : _name(name)
116       {
117       setText(0, name);
118       setSizeHint(0, QSize(0, 25));
119       }
120 
apply(QVariant value)121 void PreferenceItem::apply(QVariant value)
122       {
123       preferences.setPreference(name(), value);
124       }
125 
126 //---------------------------------------------------------
127 //   ColorPreferenceItem
128 //---------------------------------------------------------
129 
ColorPreferenceItem(QString name,std::function<void ()> applyFunc,std::function<void ()> updateFunc)130 ColorPreferenceItem::ColorPreferenceItem(QString name, std::function<void()> applyFunc, std::function<void()> updateFunc)
131       : PreferenceItem(name),
132         _initialValue(preferences.getColor(name)),
133         _editorColorLabel(new Awl::ColorLabel)
134       {
135       _editorColorLabel->setColor(_initialValue);
136       _editorColorLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
137       connect(_editorColorLabel, &Awl::ColorLabel::colorChanged, this, &PreferenceItem::editorValueModified);
138       _applyFunction = applyFunc;
139       _updateFunction = updateFunc;
140       }
141 
ColorPreferenceItem(QString name,Awl::ColorLabel * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)142 ColorPreferenceItem::ColorPreferenceItem(QString name, Awl::ColorLabel* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
143       : PreferenceItem(name),
144         _initialValue(preferences.getColor(name)),
145         _editorColorLabel(editor)
146       {
147       _editorColorLabel->setColor(_initialValue);
148       _editorColorLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
149       connect(_editorColorLabel, &Awl::ColorLabel::colorChanged, this, &PreferenceItem::editorValueModified);
150       _applyFunction = applyFunc;
151       _updateFunction = updateFunc;
152       }
153 
apply()154 void ColorPreferenceItem::apply()
155       {
156       if (_applyFunction) {
157             _applyFunction();
158             _initialValue = preferences.getColor(name());
159             }
160       else {
161             QColor newValue = _editorColorLabel->color();
162             _initialValue = newValue;
163             PreferenceItem::apply(newValue);
164             }
165       }
166 
update(bool setup)167 void ColorPreferenceItem::update(bool setup)
168       {
169       if (_updateFunction) {
170             _updateFunction();
171             }
172       else {
173             QColor newValue = preferences.getColor(name());
174             _editorColorLabel->setColor(newValue);
175             }
176       if (setup)
177             setInitialValueToEditor();
178       }
179 
setDefaultValue()180 void ColorPreferenceItem::setDefaultValue()
181       {
182       _editorColorLabel->setColor(preferences.defaultValue(name()).value<QColor>());
183       if (_applyFunction)
184             _applyFunction();
185       }
186 
editor() const187 QWidget* ColorPreferenceItem::editor() const
188       {
189       return _editorColorLabel;
190       }
191 
isModified() const192 bool ColorPreferenceItem::isModified() const
193       {
194       return _initialValue != _editorColorLabel->color();
195       }
196 
setInitialValueToEditor()197 void ColorPreferenceItem::setInitialValueToEditor()
198       {
199       _initialValue = _editorColorLabel->color();
200       }
201 
202 
203 //---------------------------------------------------------
204 //   IntPreferenceItem
205 //---------------------------------------------------------
206 
IntPreferenceItem(QString name,std::function<void ()> applyFunc,std::function<void ()> updateFunc)207 IntPreferenceItem::IntPreferenceItem(QString name, std::function<void()> applyFunc, std::function<void()> updateFunc)
208       : PreferenceItem(name),
209         _initialValue(preferences.getInt(name)),
210         _editorSpinBox(new QSpinBox)
211       {
212       _editorSpinBox->setMaximum(INT_MAX);
213       _editorSpinBox->setMinimum(INT_MIN);
214       _editorSpinBox->setValue(_initialValue);
215       connect(_editorSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreferenceItem::editorValueModified);
216       _applyFunction = applyFunc;
217       _updateFunction = updateFunc;
218       }
219 
IntPreferenceItem(QString name,QSpinBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)220 IntPreferenceItem::IntPreferenceItem(QString name, QSpinBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
221       : PreferenceItem(name),
222         _initialValue(preferences.getInt(name)),
223         _editorSpinBox(editor)
224       {
225       _editorSpinBox->setValue(_initialValue);
226       connect(_editorSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreferenceItem::editorValueModified);
227       _applyFunction = applyFunc;
228       _updateFunction = updateFunc;
229       }
230 
IntPreferenceItem(QString name,QComboBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)231 IntPreferenceItem::IntPreferenceItem(QString name, QComboBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
232       : PreferenceItem(name),
233         _editorComboBox(editor)
234       {
235       int index = _editorComboBox->findData(preferences.getInt(name));
236       _editorComboBox->setCurrentIndex(index);
237       _initialEditorIndex = index;
238       connect(_editorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PreferenceItem::editorValueModified);
239       _applyFunction = applyFunc;
240       _updateFunction = updateFunc;
241       }
242 
apply()243 void IntPreferenceItem::apply()
244       {
245       if (_applyFunction) {
246             _applyFunction();
247             _initialValue = preferences.getInt(name());
248             }
249       else {
250             if (_editorSpinBox) {
251                   int newValue = _editorSpinBox->value();
252                   _initialValue = newValue;
253                   PreferenceItem::apply(newValue);
254                   }
255             else if (_editorComboBox) {
256                   int newValue = _editorComboBox->currentData().toInt();
257                   PreferenceItem::apply(newValue);
258                   _initialEditorIndex = _editorComboBox->currentIndex();
259                   }
260             }
261       }
262 
update(bool setup)263 void IntPreferenceItem::update(bool setup)
264       {
265       if (_updateFunction) {
266             _updateFunction();
267             }
268       else {
269             if (_editorSpinBox) {
270                   int newValue = preferences.getInt(name());
271                   _editorSpinBox->setValue(newValue);
272                   }
273             else if (_editorComboBox) {
274                   int index = _editorComboBox->findData(preferences.getInt(name()));
275                   if (index == -1)
276                         setDefaultValue();
277                   else
278                         _editorComboBox->setCurrentIndex(index);
279                   }
280             }
281       if (setup)
282             setInitialValueToEditor();
283       }
284 
setDefaultValue()285 void IntPreferenceItem::setDefaultValue()
286       {
287       if (_editorSpinBox) {
288             _editorSpinBox->setValue(preferences.defaultValue(name()).toInt());
289             }
290       else if (_editorComboBox) {
291             int index = _editorComboBox->findData(preferences.defaultValue(name()).toInt());
292             qDebug() << "Preference: " << name() << ":" << index << " != " << "-1";
293             _editorComboBox->setCurrentIndex(index);
294             }
295       if (_applyFunction)
296             _applyFunction();
297       }
298 
editor() const299 QWidget* IntPreferenceItem::editor() const
300       {
301       if (_editorSpinBox)
302             return _editorSpinBox;
303       else if (_editorComboBox)
304             return _editorComboBox;
305       else
306             Q_ASSERT(false);
307       return nullptr;
308       }
309 
310 
isModified() const311 bool IntPreferenceItem::isModified() const
312       {
313       if (_editorSpinBox)
314             return _initialValue != _editorSpinBox->value();
315       else if (_editorComboBox)
316             return _initialEditorIndex != _editorComboBox->currentIndex();
317       else
318             Q_ASSERT(false);
319       return false;
320       }
321 
setInitialValueToEditor()322 void IntPreferenceItem::setInitialValueToEditor()
323       {
324       if (_editorSpinBox)
325             _initialValue = _editorSpinBox->value();
326       else if (_editorComboBox)
327             _initialEditorIndex = _editorComboBox->currentIndex();
328       }
329 
330 //---------------------------------------------------------
331 //   DoublePreferenceItem
332 //---------------------------------------------------------
333 
DoublePreferenceItem(QString name,std::function<void ()> applyFunc,std::function<void ()> updateFunc)334 DoublePreferenceItem::DoublePreferenceItem(QString name, std::function<void()> applyFunc, std::function<void()> updateFunc)
335       : PreferenceItem(name),
336         _initialValue(preferences.getDouble(name)),
337         _editorDoubleSpinBox(new QDoubleSpinBox)
338       {
339       _editorDoubleSpinBox->setMaximum(DBL_MAX);
340       _editorDoubleSpinBox->setMinimum(DBL_MIN);
341       _editorDoubleSpinBox->setValue(_initialValue);
342       if (qAbs(_initialValue) < 2.0)
343             _editorDoubleSpinBox->setSingleStep(0.1);
344       connect(_editorDoubleSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &PreferenceItem::editorValueModified);
345       _applyFunction = applyFunc;
346       _updateFunction = updateFunc;
347       }
348 
DoublePreferenceItem(QString name,QDoubleSpinBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)349 DoublePreferenceItem::DoublePreferenceItem(QString name, QDoubleSpinBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
350       : PreferenceItem(name),
351         _initialValue(preferences.getDouble(name)),
352         _editorDoubleSpinBox(editor)
353       {
354       _editorDoubleSpinBox->setValue(_initialValue);
355       if (qAbs(_initialValue) < 2.0)
356             _editorDoubleSpinBox->setSingleStep(0.1);
357       connect(_editorDoubleSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &PreferenceItem::editorValueModified);
358       _applyFunction = applyFunc;
359       _updateFunction = updateFunc;
360       }
361 
DoublePreferenceItem(QString name,QComboBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)362 DoublePreferenceItem::DoublePreferenceItem(QString name, QComboBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
363       : PreferenceItem(name),
364         _editorComboBox(editor)
365       {
366       int index = _editorComboBox->findData(preferences.getDouble(name));
367       _editorComboBox->setCurrentIndex(index);
368       _initialEditorIndex = index;
369       connect(_editorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PreferenceItem::editorValueModified);
370       _applyFunction = applyFunc;
371       _updateFunction = updateFunc;
372       }
373 
DoublePreferenceItem(QString name,QSpinBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)374 DoublePreferenceItem::DoublePreferenceItem(QString name, QSpinBox* editor, std::function<void ()> applyFunc, std::function<void ()> updateFunc)
375       : PreferenceItem(name),
376         _initialValue(preferences.getDouble(name)),
377         _editorSpinBox(editor)
378       {
379       _editorSpinBox->setValue(_initialValue);
380       if (qAbs(_initialValue) < 2.0)
381             _editorDoubleSpinBox->setSingleStep(0.1);
382       connect(_editorSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreferenceItem::editorValueModified);
383       _applyFunction = applyFunc;
384       _updateFunction = updateFunc;
385       }
386 
apply()387 void DoublePreferenceItem::apply()
388       {
389       if (_applyFunction) {
390             _applyFunction();
391             _initialValue = preferences.getDouble(name());
392             }
393       else {
394             if (_editorDoubleSpinBox) {
395                   double newValue = _editorDoubleSpinBox->value();
396                   _initialValue = newValue;
397                   PreferenceItem::apply(newValue);
398                   }
399             else if (_editorComboBox) {
400                   double newValue = _editorComboBox->currentData().toDouble();
401                   PreferenceItem::apply(newValue);
402                   _initialEditorIndex = _editorComboBox->currentIndex();
403                   }
404             else if (_editorSpinBox) {
405                   double newValue = _editorSpinBox->value();
406                   _initialValue = newValue;
407                   PreferenceItem::apply(newValue);
408                   }
409             }
410       }
411 
update(bool setup)412 void DoublePreferenceItem::update(bool setup)
413       {
414       if (_updateFunction) {
415             _updateFunction();
416             }
417       else {
418             if (_editorDoubleSpinBox) {
419                   double newValue = preferences.getDouble(name());
420                   _editorDoubleSpinBox->setValue(newValue);
421                   }
422             else if (_editorComboBox) {
423                   int index = _editorComboBox->findData(preferences.getDouble(name()));
424                   if (index == -1)
425                         setDefaultValue();
426                   else
427                         _editorComboBox->setCurrentIndex(index);
428                   }
429             else if (_editorSpinBox) {
430                   double newValue = preferences.getDouble(name());
431                   _editorSpinBox->setValue(newValue);
432                   }
433             }
434       if (setup)
435             setInitialValueToEditor();
436       }
437 
setDefaultValue()438 void DoublePreferenceItem::setDefaultValue()
439       {
440       if (_editorDoubleSpinBox){
441             _editorDoubleSpinBox->setValue(preferences.defaultValue(name()).toDouble());
442             }
443       else if (_editorComboBox) {
444             int index = _editorComboBox->findData(preferences.defaultValue(name()).toDouble());
445             _editorComboBox->setCurrentIndex(index);
446             }
447       else if (_editorSpinBox){
448             _editorSpinBox->setValue(preferences.defaultValue(name()).toDouble());
449             }
450       if (_applyFunction)
451             _applyFunction();
452       }
453 
editor() const454 QWidget* DoublePreferenceItem::editor() const
455       {
456       if (_editorDoubleSpinBox)
457             return _editorDoubleSpinBox;
458       else if (_editorComboBox)
459             return _editorComboBox;
460       else if (_editorSpinBox)
461             return _editorSpinBox;
462       else
463             Q_ASSERT(false);
464       return nullptr;
465       }
466 
isModified() const467 bool DoublePreferenceItem::isModified() const
468       {
469       if (_editorDoubleSpinBox)
470             return _initialValue != _editorDoubleSpinBox->value();
471       else if (_editorComboBox)
472             return _initialEditorIndex != _editorComboBox->currentIndex();
473       else if (_editorSpinBox)
474             return _initialValue != _editorSpinBox->value();
475       else
476             Q_ASSERT(false);
477       return false;
478       }
479 
setInitialValueToEditor()480 void DoublePreferenceItem::setInitialValueToEditor()
481       {
482       if (_editorDoubleSpinBox)
483             _initialValue = _editorDoubleSpinBox->value();
484       else if (_editorComboBox)
485             _initialEditorIndex = _editorComboBox->currentIndex();
486       else if (_editorSpinBox)
487             _initialValue = _editorSpinBox->value();
488       else
489             Q_ASSERT(false);
490       }
491 
492 
493 //---------------------------------------------------------
494 //   BoolPreferenceItem
495 //---------------------------------------------------------
496 
BoolPreferenceItem(QString name,std::function<void ()> applyFunc,std::function<void ()> updateFunc)497 BoolPreferenceItem::BoolPreferenceItem(QString name, std::function<void()> applyFunc, std::function<void()> updateFunc)
498       : PreferenceItem(name),
499         _initialValue(preferences.getBool(name)),
500         _editorCheckBox(new QCheckBox)
501       {
502       _editorCheckBox->setChecked(_initialValue);
503       connect(_editorCheckBox, &QCheckBox::toggled, this, &PreferenceItem::editorValueModified);
504       _applyFunction = applyFunc;
505       _updateFunction = updateFunc;
506       }
507 
BoolPreferenceItem(QString name,QCheckBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)508 BoolPreferenceItem::BoolPreferenceItem(QString name, QCheckBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
509       : PreferenceItem(name),
510         _initialValue(preferences.getBool(name)),
511         _editorCheckBox(editor)
512       {
513       _editorCheckBox->setChecked(_initialValue);
514       connect(_editorCheckBox, &QCheckBox::toggled, this, &PreferenceItem::editorValueModified);
515       _applyFunction = applyFunc;
516       _updateFunction = updateFunc;
517       }
518 
BoolPreferenceItem(QString name,QGroupBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)519 BoolPreferenceItem::BoolPreferenceItem(QString name, QGroupBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
520       : PreferenceItem(name),
521         _initialValue(preferences.getBool(name)),
522         _editorGroupBox(editor)
523       {
524       _editorGroupBox->setChecked(_initialValue);
525       connect(_editorGroupBox, &QGroupBox::toggled, this, &PreferenceItem::editorValueModified);
526       _applyFunction = applyFunc;
527       _updateFunction = updateFunc;
528       }
529 
BoolPreferenceItem(QString name,QRadioButton * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)530 BoolPreferenceItem::BoolPreferenceItem(QString name, QRadioButton* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
531       : PreferenceItem(name),
532         _initialValue(preferences.getBool(name)),
533         _editorRadioButton(editor)
534       {
535       _editorRadioButton->setChecked(_initialValue);
536       connect(_editorRadioButton, &QRadioButton::toggled, this, &PreferenceItem::editorValueModified);
537       _applyFunction = applyFunc;
538       _updateFunction = updateFunc;
539       }
540 
apply()541 void BoolPreferenceItem::apply()
542       {
543       if (_applyFunction) {
544             _applyFunction();
545             _initialValue = preferences.getBool(name());
546             }
547       else {
548             if (_editorCheckBox) {
549                   bool newValue = _editorCheckBox->isChecked();
550                   _initialValue = newValue;
551                   PreferenceItem::apply(newValue);
552                   }
553             else if (_editorGroupBox) {
554                   bool newValue = _editorGroupBox->isChecked();
555                   _initialValue = newValue;
556                   PreferenceItem::apply(newValue);
557                   }
558             else if (_editorRadioButton) {
559                   bool newValue = _editorRadioButton->isChecked();
560                   _initialValue = newValue;
561                   PreferenceItem::apply(newValue);
562                   }
563             }
564       }
565 
update(bool setup)566 void BoolPreferenceItem::update(bool setup)
567       {
568       if (_updateFunction) {
569             _updateFunction();
570             }
571       else {
572             if (_editorCheckBox) {
573                   bool newValue = preferences.getBool(name());
574                   _editorCheckBox->setChecked(newValue);
575                   }
576             else if (_editorGroupBox) {
577                   bool newValue = preferences.getBool(name());
578                   _editorGroupBox->setChecked(newValue);
579                   }
580             else if (_editorRadioButton) {
581                   bool newValue = preferences.getBool(name());
582                   _editorRadioButton->setChecked(newValue);
583                   }
584             }
585       if (setup)
586             setInitialValueToEditor();
587       }
588 
setDefaultValue()589 void BoolPreferenceItem::setDefaultValue()
590       {
591       if (_editorCheckBox)
592             _editorCheckBox->setChecked(preferences.defaultValue(name()).toBool());
593       else if (_editorGroupBox)
594             _editorGroupBox->setChecked(preferences.defaultValue(name()).toBool());
595       else if (_editorRadioButton)
596             _editorRadioButton->setChecked(preferences.defaultValue(name()).toBool());
597       if (_applyFunction)
598             _applyFunction();
599       }
600 
editor() const601 QWidget* BoolPreferenceItem::editor() const
602       {
603       if (_editorCheckBox)
604             return _editorCheckBox;
605       else if (_editorGroupBox)
606             return _editorGroupBox;
607       else if (_editorRadioButton)
608             return _editorRadioButton;
609       else
610             Q_ASSERT(false);
611       return nullptr;
612       }
613 
isModified() const614 bool BoolPreferenceItem::isModified() const
615       {
616       if (_editorCheckBox)
617             return _initialValue != _editorCheckBox->isChecked();
618       else if (_editorGroupBox)
619             return _initialValue != _editorGroupBox->isChecked();
620       else if (_editorRadioButton)
621             return _initialValue != _editorRadioButton->isChecked();
622       else
623             Q_ASSERT(false);
624       return false;
625       }
626 
setInitialValueToEditor()627 void BoolPreferenceItem::setInitialValueToEditor()
628       {
629       if (_editorCheckBox)
630             _initialValue = _editorCheckBox->isChecked();
631       else if (_editorGroupBox)
632             _initialValue = _editorGroupBox->isChecked();
633       else if (_editorRadioButton)
634             _initialValue = _editorRadioButton->isChecked();
635       else
636             Q_ASSERT(false);
637       }
638 
639 //---------------------------------------------------------
640 //   StringPreferenceItem
641 //---------------------------------------------------------
642 
StringPreferenceItem(QString name,std::function<void ()> applyFunc,std::function<void ()> updateFunc)643 StringPreferenceItem::StringPreferenceItem(QString name, std::function<void()> applyFunc, std::function<void()> updateFunc)
644       : PreferenceItem(name),
645         _initialValue(preferences.getString(name)),
646         _editorLineEdit(new QLineEdit)
647       {
648       _editorLineEdit->setText(_initialValue);
649       connect(_editorLineEdit, &QLineEdit::textChanged, this, &PreferenceItem::editorValueModified);
650       _applyFunction = applyFunc;
651       _updateFunction = updateFunc;
652       }
653 
StringPreferenceItem(QString name,QLineEdit * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)654 StringPreferenceItem::StringPreferenceItem(QString name, QLineEdit* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
655       : PreferenceItem(name),
656         _initialValue(preferences.getString(name)),
657         _editorLineEdit(editor)
658       {
659       _editorLineEdit->setText(_initialValue);
660       connect(_editorLineEdit, &QLineEdit::textChanged, this, &PreferenceItem::editorValueModified);
661       _applyFunction = applyFunc;
662       _updateFunction = updateFunc;
663       }
664 
StringPreferenceItem(QString name,QFontComboBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)665 StringPreferenceItem::StringPreferenceItem(QString name, QFontComboBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
666       : PreferenceItem(name),
667         _initialValue(preferences.getString(name)),
668         _editorFontComboBox(editor)
669       {
670       _editorFontComboBox->setCurrentFont(QFont(_initialValue));
671       connect(_editorFontComboBox, &QFontComboBox::currentFontChanged, this, &PreferenceItem::editorValueModified);
672       _applyFunction = applyFunc;
673       _updateFunction = updateFunc;
674       }
675 
StringPreferenceItem(QString name,QComboBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)676 StringPreferenceItem::StringPreferenceItem(QString name, QComboBox* editor, std::function<void()> applyFunc, std::function<void()> updateFunc)
677       : PreferenceItem(name),
678         _editorComboBox(editor)
679       {
680       int index = _editorComboBox->findData(preferences.getString(name));
681       _editorComboBox->setCurrentIndex(index);
682       _initialEditorIndex = index;
683       connect(_editorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PreferenceItem::editorValueModified);
684       _applyFunction = applyFunc;
685       _updateFunction = updateFunc;
686       }
687 
StringPreferenceItem(QString name,QRadioButton * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)688 StringPreferenceItem::StringPreferenceItem(QString name, QRadioButton* editor, std::function<void ()> applyFunc, std::function<void ()> updateFunc)
689       : PreferenceItem(name),
690         _initialValue(""),
691         _editorRadioButton(editor)
692       {
693       connect(_editorRadioButton, &QRadioButton::toggled, this, &PreferenceItem::editorValueModified);
694       Q_ASSERT(applyFunc); // if an apply and an update function are not provided this cannot work
695       _applyFunction = applyFunc;
696       Q_ASSERT(updateFunc);
697       _updateFunction = updateFunc;
698       update(true);
699       }
700 
701 
apply()702 void StringPreferenceItem::apply()
703       {
704       if (_applyFunction) {
705             _applyFunction();
706             _initialValue = preferences.getString(name());
707             }
708       else {
709             if (_editorLineEdit) {
710                   QString newValue = _editorLineEdit->text();
711                   _initialValue = newValue;
712                   PreferenceItem::apply(newValue);
713                   }
714             else if (_editorFontComboBox) {
715                   QString newValue = _editorFontComboBox->currentFont().family();
716                   _initialValue = newValue;
717                   PreferenceItem::apply(newValue);
718                   }
719             else if (_editorComboBox) {
720                   QString newValue = _editorComboBox->currentText();
721                   PreferenceItem::apply(newValue);
722                   _initialEditorIndex = _editorComboBox->currentIndex();;
723                   }
724             else if (_editorRadioButton) {
725                   // there must always be a _applyFunction
726                   Q_ASSERT(false);
727                   }
728             }
729       }
730 
update(bool setup)731 void StringPreferenceItem::update( bool setup)
732       {
733       if (_updateFunction) {
734             _updateFunction();
735             }
736       else {
737             if (_editorLineEdit) {
738                   QString newValue = preferences.getString(name());
739                   _editorLineEdit->setText(newValue);
740                   }
741             else if (_editorFontComboBox) {
742                   QString newValue = preferences.getString(name());
743                   _editorFontComboBox->setCurrentFont(QFont(newValue));
744                   }
745             else if (_editorComboBox) {
746                   int index = _editorComboBox->findData(preferences.getString(name()));
747                   if (index == -1)
748                         setDefaultValue();
749                   else
750                         _editorComboBox->setCurrentIndex(index);
751                   }
752             else if (_editorRadioButton) {
753                   // there must always be a _updateFunction
754                   Q_ASSERT(false);
755                   }
756             }
757       if (setup)
758             setInitialValueToEditor();
759       }
760 
setDefaultValue()761 void StringPreferenceItem::setDefaultValue()
762       {
763       if (_editorLineEdit) {
764             _editorLineEdit->setText(preferences.defaultValue(name()).toString());
765             }
766       else if (_editorFontComboBox) {
767             _editorFontComboBox->setCurrentFont(QFont(preferences.defaultValue(name()).toString()));
768             }
769       else if (_editorComboBox) {
770             int index = _editorComboBox->findData(preferences.defaultValue(name()).toString());
771             _editorComboBox->setCurrentIndex(index);
772             }
773       else if (_editorRadioButton) {
774             ;
775             }
776       if (_applyFunction)
777             _applyFunction();
778       }
779 
editor() const780 QWidget* StringPreferenceItem::editor() const
781       {
782       if (_editorLineEdit)
783             return _editorLineEdit;
784       else if (_editorFontComboBox)
785             return _editorFontComboBox;
786       else if (_editorComboBox)
787             return _editorComboBox;
788       else if (_editorRadioButton)
789             return _editorRadioButton;
790       else
791             Q_ASSERT(false);
792       return nullptr;
793       }
794 
isModified() const795 bool StringPreferenceItem::isModified() const
796       {
797       if (_editorLineEdit)
798             return _initialValue != _editorLineEdit->text();
799       else if (_editorFontComboBox)
800             return _initialValue != _editorFontComboBox->currentFont().family();
801       else if (_editorComboBox)
802             return _initialEditorIndex != _editorComboBox->currentIndex();
803       else if (_editorRadioButton)
804             return _initialIsChecked != _editorRadioButton->isChecked();
805       else
806             Q_ASSERT(false);
807       return false;
808       }
809 
setInitialValueToEditor()810 void StringPreferenceItem::setInitialValueToEditor()
811       {
812       if (_editorLineEdit)
813             _initialValue = _editorLineEdit->text();
814       else if (_editorFontComboBox)
815             _initialValue = _editorFontComboBox->currentFont().family();
816       else if (_editorComboBox)
817             _initialEditorIndex = _editorComboBox->currentIndex();
818       else if (_editorRadioButton)
819              _initialIsChecked = _editorRadioButton->isChecked();
820       else
821             Q_ASSERT(false);
822       }
823 
824 //---------------------------------------------------------
825 //   CustomPreferenceItem
826 //---------------------------------------------------------
827 
CustomPreferenceItem(QString name,QRadioButton * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)828 CustomPreferenceItem::CustomPreferenceItem(QString name, QRadioButton* editor, std::function<void ()> applyFunc, std::function<void ()> updateFunc)
829       : PreferenceItem(name),
830         _editorRadioButton(editor)
831       {
832       Q_ASSERT(applyFunc); // if an apply and an update function are not provided this cannot work
833       _applyFunction = applyFunc;
834       Q_ASSERT(updateFunc);
835       _updateFunction = updateFunc;
836       update(true); // update on creation is the same as assigning an initival value
837       connect(_editorRadioButton, &QRadioButton::toggled, this, &PreferenceItem::editorValueModified);
838       }
839 
CustomPreferenceItem(QString name,QComboBox * editor,std::function<void ()> applyFunc,std::function<void ()> updateFunc)840 CustomPreferenceItem::CustomPreferenceItem(QString name, QComboBox* editor, std::function<void ()> applyFunc, std::function<void ()> updateFunc)
841       : PreferenceItem(name),
842         _editorComboBox(editor)
843       {
844       Q_ASSERT(applyFunc); // if an apply and an update function are not provided this cannot work
845       _applyFunction = applyFunc;
846       Q_ASSERT(updateFunc);
847       _updateFunction = updateFunc;
848       update(true); // update on creation is the same as assigning an initival value
849       connect(_editorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PreferenceItem::editorValueModified);
850       }
851 
apply()852 void CustomPreferenceItem::apply()
853       {
854       _applyFunction();
855       }
856 
update(bool setup)857 void CustomPreferenceItem::update(bool setup)
858       {
859       _updateFunction();
860       if (setup)
861             setInitialValueToEditor();
862       }
863 
setDefaultValue()864 void CustomPreferenceItem::setDefaultValue()
865       {
866       Q_ASSERT(false);
867       }
868 
editor() const869 QWidget* CustomPreferenceItem::editor() const
870       {
871       if (_editorRadioButton)
872             return _editorRadioButton;
873       else if (_editorComboBox)
874             return _editorComboBox;
875       else
876             Q_ASSERT(false);
877       return nullptr;
878       }
879 
isModified() const880 bool CustomPreferenceItem::isModified() const
881       {
882       if (_editorRadioButton)
883             return _initialIsChecked != _editorRadioButton->isChecked();
884       else if (_editorComboBox)
885             return _initialEditorIndex != _editorComboBox->currentIndex();
886       else
887             Q_ASSERT(false);
888       return false;
889       }
890 
setInitialValueToEditor()891 void CustomPreferenceItem::setInitialValueToEditor()
892       {
893       if (_editorRadioButton)
894             _initialIsChecked = _editorRadioButton->isChecked();
895       else if (_editorComboBox)
896             _initialEditorIndex = _editorComboBox->currentIndex();
897       else
898             Q_ASSERT(false);
899       }
900 
901 } // namespace Ms
902