1 //============================================================================= 2 // MusE Score 3 // Linux Music Score Editor 4 // 5 // Copyright (C) 2002-2016 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 #ifndef __PREFERENCES_H__ 21 #define __PREFERENCES_H__ 22 23 /* 24 * HOW TO ADD A NEW PREFERENCE 25 * - Add a new define to the list of defines below 26 * - Add the preference to the _allPreferences map in the init() function in preferences.cpp 27 * and specify the default value for this preference 28 * - That's it. The preference is stored and retrieved automatically and can be read 29 * using getString(), getInt(), etc., and changed using setPreference() 30 */ 31 32 #include <functional> 33 #include "globals.h" 34 #include "global/settings/types/preferencekeys.h" 35 36 namespace Ms { 37 38 extern QString mscoreGlobalShare; 39 40 enum class SessionStart : char { 41 EMPTY, LAST, NEW, SCORE 42 }; 43 44 // midi remote control values: 45 enum { 46 RMIDI_REWIND, 47 RMIDI_TOGGLE_PLAY, 48 RMIDI_PLAY, 49 RMIDI_STOP, 50 RMIDI_NOTE1, 51 RMIDI_NOTE2, 52 RMIDI_NOTE4, 53 RMIDI_NOTE8, 54 RMIDI_NOTE16, 55 RMIDI_NOTE32, 56 RMIDI_NOTE64, 57 RMIDI_REST, 58 RMIDI_DOT, 59 RMIDI_DOTDOT, 60 RMIDI_TIE, 61 RMIDI_UNDO, 62 RMIDI_NOTE_EDIT_MODE, 63 RMIDI_REALTIME_ADVANCE, 64 MIDI_REMOTES 65 }; 66 67 // The "theme" the user chooses in Preferences 68 enum class MuseScorePreferredStyleType : char { 69 LIGHT_FUSION = 0, 70 DARK_FUSION, 71 #ifdef Q_OS_MAC 72 FOLLOW_SYSTEM, 73 #endif 74 }; 75 76 // The actual "theme", resulting from the user's choice 77 enum class MuseScoreEffectiveStyleType : char { 78 LIGHT_FUSION = 0, 79 DARK_FUSION 80 }; 81 82 // MusicXML export break values 83 enum class MusicxmlExportBreaks : char { 84 ALL, MANUAL, NO 85 }; 86 87 // Default-zoom-type options 88 enum class ZoomType : int { 89 PERCENTAGE = 0, PAGE_WIDTH, WHOLE_PAGE, TWO_PAGES, 90 }; 91 92 class PreferenceVisitor; 93 94 //--------------------------------------------------------- 95 // Preference 96 //--------------------------------------------------------- 97 class Preference { 98 private: 99 QVariant _defaultValue = 0; 100 bool _showInAdvancedList = true; 101 102 protected: 103 QMetaType::Type _type = QMetaType::UnknownType; Preference(QVariant defaultValue)104 Preference(QVariant defaultValue) : _defaultValue(defaultValue) {} 105 106 public: 107 Preference(QVariant defaultValue, QMetaType::Type type, bool showInAdvancedList = true); ~Preference()108 virtual ~Preference() {} 109 defaultValue()110 QVariant defaultValue() const {return _defaultValue;} showInAdvancedList()111 bool showInAdvancedList() const {return _showInAdvancedList;} type()112 QMetaType::Type type() {return _type;} 113 virtual void accept(QString key, PreferenceVisitor&) = 0; 114 }; 115 116 class IntPreference : public Preference { 117 public: 118 IntPreference(int defaultValue, bool showInAdvancedList = true); 119 virtual void accept(QString key, PreferenceVisitor&); 120 }; 121 122 class DoublePreference : public Preference { 123 public: 124 DoublePreference(double defaultValue, bool showInAdvancedList = true); 125 virtual void accept(QString key, PreferenceVisitor&); 126 }; 127 128 class BoolPreference : public Preference { 129 public: 130 BoolPreference(bool defaultValue, bool showInAdvancedList = true); 131 virtual void accept(QString key, PreferenceVisitor&); 132 }; 133 134 class StringPreference: public Preference { 135 public: 136 StringPreference(QString defaultValue, bool showInAdvancedList = true); 137 virtual void accept(QString key, PreferenceVisitor&); 138 }; 139 140 class ColorPreference: public Preference { 141 public: 142 ColorPreference(QColor defaultValue, bool showInAdvancedList = true); 143 virtual void accept(QString key, PreferenceVisitor&); 144 }; 145 146 // Support for EnumPreference is currently not fully implemented 147 class EnumPreference: public Preference { 148 public: 149 EnumPreference(QVariant defaultValue, bool showInAdvancedList = true); 150 virtual void accept(QString, PreferenceVisitor&); 151 }; 152 153 //--------------------------------------------------------- 154 // Preferences 155 //--------------------------------------------------------- 156 157 class Preferences { 158 public: 159 typedef QHash<QString, Preference*> prefs_map_t; 160 using OnSetListener = std::function<void(const QString& key, const QVariant& value)>; 161 using ListenerID = uint32_t; 162 163 private: 164 165 // Map of all preferences and their default values 166 // A preference can not be read or set if it is not present in this map 167 // This map is not used for storing a preference it is only for default values 168 prefs_map_t _allPreferences; 169 // used for storing preferences in memory when _storeInMemoryOnly is true 170 // and for storing temporary preferences 171 QHash<QString, QVariant> _inMemorySettings; 172 bool _storeInMemoryOnly = false; 173 bool _returnDefaultValues = false; 174 bool _initialized = false; 175 QSettings* _settings; // should not be used directly but through settings() accessor 176 177 QSettings* settings() const; 178 // the following functions must be used to access and change a preference 179 // instead of using QSettings directly 180 QVariant get(const QString key) const; 181 bool has(const QString key) const; 182 void set(const QString key, QVariant value, bool temporary = false); 183 void remove(const QString key); 184 185 QVariant preference(const QString key) const; 186 QMetaType::Type type(const QString key) const; 187 bool checkIfKeyExists(const QString key) const; 188 bool checkType(const QString key, QMetaType::Type t) const; 189 190 // Used with workspace 191 QMap<QString, QVariant> localPreferences; 192 QMap<QString, QVariant> getDefaultLocalPreferences(); 193 bool useLocalPrefs = false; 194 195 QMap<ListenerID, OnSetListener> _onSetListeners; 196 197 public: 198 Preferences(); 199 ~Preferences(); 200 void init(bool storeInMemoryOnly = false); 201 void save(); 202 // set to true to let getters return default values instead of values from QSettings setReturnDefaultValuesMode(bool returnDefaultValues)203 void setReturnDefaultValuesMode(bool returnDefaultValues) {_returnDefaultValues = returnDefaultValues;} 204 allPreferences()205 const prefs_map_t& allPreferences() const {return _allPreferences;} 206 207 // general getters 208 QVariant defaultValue(const QString key) const; 209 bool getBool(const QString key) const; 210 QColor getColor(const QString key) const; 211 QString getString(const QString key) const; 212 int getInt(const QString key) const; 213 double getDouble(const QString key) const; 214 215 // general setters 216 void setToDefaultValue(const QString key); 217 void setPreference(const QString key, QVariant value); 218 219 // set listeners 220 ListenerID addOnSetListener(const OnSetListener& l); 221 void removeOnSetListener(const ListenerID& id); 222 223 // A temporary preference is stored "in memory" only and not written to file. 224 // If there is both a "normal" preference and a temporary preference with the same 225 // key the temporary preference is used 226 void setTemporaryPreference(const QString key, QVariant value); 227 228 /* 229 * Some preferences like enums and structs/classes are not easily read using the general set/get methods 230 * and therefore require specific getters and/or setters 231 */ 232 SessionStart sessionStart() const; 233 MusicxmlExportBreaks musicxmlExportBreaks() const; 234 MuseScorePreferredStyleType preferredGlobalStyle() const; 235 MuseScoreEffectiveStyleType effectiveGlobalStyle() const; 236 bool isThemeDark() const; 237 238 template<typename T> setCustomPreference(const QString key,T t)239 void setCustomPreference(const QString key, T t) 240 { 241 set(key, QVariant::fromValue<T>(t)); 242 } 243 244 // The midiRemote preference requires special handling due to its complexity 245 MidiRemote midiRemote(int recordId) const; 246 void updateMidiRemote(int recordId, MidiRemoteType type, int data); 247 void clearMidiRemote(int recordId); 248 getLocalPreferences()249 QMap<QString, QVariant> getLocalPreferences() { return localPreferences; } 250 void setLocalPreference(QString key, QVariant value); setUseLocalPreferences(bool value)251 void setUseLocalPreferences(bool value) { useLocalPrefs = value; } getUseLocalPreferences()252 bool getUseLocalPreferences() { return useLocalPrefs; } updateLocalPreferences()253 void updateLocalPreferences() { localPreferences = getDefaultLocalPreferences(); } 254 }; 255 256 // singleton 257 extern Preferences preferences; 258 259 // Stream operators for enum classes 260 // enum classes don't play well with QSettings without custom serialization 261 inline QDataStream& 262 operator<<(QDataStream &out, const Ms::MuseScorePreferredStyleType &val) 263 { 264 return out << static_cast<int>(val); 265 } 266 267 inline QDataStream& 268 operator>>(QDataStream &in, Ms::MuseScorePreferredStyleType &val) 269 { 270 int tmp; 271 in >> tmp; 272 val = static_cast<Ms::MuseScorePreferredStyleType>(tmp); 273 return in; 274 } 275 276 inline QDataStream& 277 operator<<(QDataStream &out, const Ms::MuseScoreEffectiveStyleType &val) 278 { 279 return out << static_cast<int>(val); 280 } 281 282 inline QDataStream& 283 operator>>(QDataStream &in, Ms::MuseScoreEffectiveStyleType &val) 284 { 285 int tmp; 286 in >> tmp; 287 val = static_cast<Ms::MuseScoreEffectiveStyleType>(tmp); 288 return in; 289 } 290 291 inline QDataStream& 292 operator<<(QDataStream &out, const Ms::SessionStart &val) 293 { 294 return out << static_cast<int>(val); 295 } 296 297 inline QDataStream& 298 operator>>(QDataStream &in, Ms::SessionStart &val) 299 { 300 int tmp; 301 in >> tmp; 302 val = static_cast<Ms::SessionStart>(tmp); 303 return in; 304 } 305 306 inline QDataStream& 307 operator<<(QDataStream &out, const Ms::MusicxmlExportBreaks &val) 308 { 309 return out << static_cast<int>(val); 310 } 311 312 inline QDataStream& 313 operator>>(QDataStream &in, Ms::MusicxmlExportBreaks &val) 314 { 315 int tmp; 316 in >> tmp; 317 val = static_cast<Ms::MusicxmlExportBreaks>(tmp); 318 return in; 319 } 320 321 322 class PreferenceVisitor { 323 public: 324 virtual void visit(QString key, IntPreference*) = 0; 325 virtual void visit(QString key, DoublePreference*) = 0; 326 virtual void visit(QString key, BoolPreference*) = 0; 327 virtual void visit(QString key, StringPreference*) = 0; 328 virtual void visit(QString key, ColorPreference*) = 0; 329 }; 330 331 332 } // namespace Ms 333 334 Q_DECLARE_METATYPE(Ms::SessionStart); 335 Q_DECLARE_METATYPE(Ms::MusicxmlExportBreaks); 336 Q_DECLARE_METATYPE(Ms::MuseScorePreferredStyleType); 337 Q_DECLARE_METATYPE(Ms::MuseScoreEffectiveStyleType); 338 339 #endif 340