Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "appearancepreferencesmodel.h"
24 :
25 : #include "translation.h"
26 :
27 : #include "ui/internal/themeconverter.h"
28 :
29 : #include "log.h"
30 :
31 : using namespace mu::preferences;
32 : using namespace mu::notation;
33 : using namespace muse;
34 : using namespace muse::ui;
35 :
36 : static constexpr int INVALID_INDEX = -1;
37 :
38 0 : AppearancePreferencesModel::AppearancePreferencesModel(QObject* parent)
39 0 : : QObject(parent), muse::Contextable(muse::iocCtxForQmlObject(this))
40 : {
41 0 : }
42 :
43 0 : void AppearancePreferencesModel::init()
44 : {
45 0 : uiConfiguration()->isFollowSystemTheme().notification.onNotify(this, [this]() {
46 0 : emit isFollowSystemThemeChanged();
47 0 : });
48 :
49 0 : m_lastHighContrast = highContrastEnabled();
50 :
51 0 : uiConfiguration()->currentThemeChanged().onNotify(this, [this]() {
52 0 : emit themesChanged();
53 0 : emit foregroundColorChanged();
54 :
55 0 : bool hc = highContrastEnabled();
56 0 : if (hc != m_lastHighContrast) {
57 0 : m_lastHighContrast = hc;
58 0 : emit highContrastEnabledChanged();
59 : }
60 0 : });
61 :
62 0 : uiConfiguration()->fontChanged().onNotify(this, [this]() {
63 0 : emit currentFontIndexChanged();
64 0 : emit bodyTextSizeChanged();
65 0 : });
66 :
67 0 : notationConfiguration()->scoreInversionChanged().onNotify(this, [this]() {
68 0 : emit invertScoreColorChanged();
69 0 : });
70 :
71 0 : notationConfiguration()->isOnlyInvertInDarkThemeChanged().onNotify(this, [this]() {
72 0 : emit isOnlyInvertInDarkThemeChanged();
73 0 : });
74 :
75 0 : notationConfiguration()->backgroundChanged().onNotify(this, [this]() {
76 0 : emit backgroundColorChanged();
77 0 : emit backgroundUseColorChanged();
78 0 : emit backgroundWallpaperPathChanged();
79 0 : });
80 :
81 0 : notationConfiguration()->foregroundChanged().onNotify(this, [this]() {
82 0 : emit foregroundColorChanged();
83 0 : emit foregroundUseColorChanged();
84 0 : emit foregroundWallpaperPathChanged();
85 0 : });
86 :
87 0 : notationConfiguration()->notationColorChanged().onNotify(this, [this]() {
88 0 : emit engravingColorChanged();
89 0 : });
90 0 : }
91 :
92 0 : bool AppearancePreferencesModel::isFollowSystemThemeAvailable() const
93 : {
94 0 : return uiConfiguration()->isFollowSystemThemeAvailable();
95 : }
96 :
97 0 : bool AppearancePreferencesModel::isFollowSystemTheme() const
98 : {
99 0 : return uiConfiguration()->isFollowSystemTheme().val;
100 : }
101 :
102 0 : void AppearancePreferencesModel::setFollowSystemTheme(bool enabled)
103 : {
104 0 : if (enabled == isFollowSystemTheme()) {
105 0 : return;
106 : }
107 :
108 0 : uiConfiguration()->setFollowSystemTheme(enabled);
109 : }
110 :
111 0 : bool AppearancePreferencesModel::highContrastEnabled() const
112 : {
113 0 : return uiConfiguration()->isHighContrast();
114 : }
115 :
116 0 : QStringList AppearancePreferencesModel::generalThemeCodes() const
117 : {
118 : return {
119 : QString::fromStdString(LIGHT_THEME_CODE),
120 : QString::fromStdString(DARK_THEME_CODE)
121 0 : };
122 0 : }
123 :
124 0 : QStringList AppearancePreferencesModel::highContrastThemeCodes() const
125 : {
126 : return {
127 : QString::fromStdString(HIGH_CONTRAST_WHITE_THEME_CODE),
128 : QString::fromStdString(HIGH_CONTRAST_BLACK_THEME_CODE)
129 0 : };
130 0 : }
131 :
132 0 : QVariantList AppearancePreferencesModel::generalThemes() const
133 : {
134 0 : QVariantList result;
135 :
136 0 : for (const ThemeInfo& theme: allThemes()) {
137 0 : if (theme.codeKey == LIGHT_THEME_CODE || theme.codeKey == DARK_THEME_CODE) {
138 0 : result << ThemeConverter::toMap(theme);
139 : }
140 0 : }
141 :
142 0 : return result;
143 0 : }
144 :
145 0 : QVariantList AppearancePreferencesModel::highContrastThemes() const
146 : {
147 0 : QVariantList result;
148 :
149 0 : for (const ThemeInfo& theme : allThemes()) {
150 0 : if (theme.codeKey == HIGH_CONTRAST_WHITE_THEME_CODE || theme.codeKey == HIGH_CONTRAST_BLACK_THEME_CODE) {
151 0 : result << ThemeConverter::toMap(theme);
152 : }
153 0 : }
154 :
155 0 : return result;
156 0 : }
157 :
158 0 : QStringList AppearancePreferencesModel::accentColors() const
159 : {
160 0 : return uiConfiguration()->possibleAccentColors();
161 : }
162 :
163 0 : void AppearancePreferencesModel::resetAppearancePreferencesToDefault()
164 : {
165 0 : uiConfiguration()->resetThemes();
166 0 : uiConfiguration()->resetFonts();
167 0 : notationConfiguration()->resetBackground();
168 0 : notationConfiguration()->resetForeground();
169 0 : notationConfiguration()->resetNotationColor();
170 0 : }
171 :
172 0 : void AppearancePreferencesModel::setNewColor(const QColor& newColor, ColorType colorType)
173 : {
174 0 : switch (colorType) {
175 0 : case AccentColor:
176 0 : uiConfiguration()->setCurrentThemeStyleValue(ThemeStyleKey::ACCENT_COLOR, Val(newColor));
177 0 : break;
178 0 : case TextAndIconsColor:
179 0 : uiConfiguration()->setCurrentThemeStyleValue(ThemeStyleKey::FONT_PRIMARY_COLOR, Val(newColor));
180 0 : break;
181 0 : case DisabledColor:
182 0 : NOT_IMPLEMENTED;
183 0 : return;
184 0 : case BorderColor:
185 0 : uiConfiguration()->setCurrentThemeStyleValue(ThemeStyleKey::STROKE_COLOR, Val(newColor));
186 0 : break;
187 : }
188 :
189 0 : emit themesChanged();
190 : }
191 :
192 0 : QStringList AppearancePreferencesModel::allFonts() const
193 : {
194 0 : return uiConfiguration()->possibleFontFamilies();
195 : }
196 :
197 0 : QStringList AppearancePreferencesModel::wallpaperPathFilter() const
198 : {
199 0 : return { muse::qtrc("preferences", "Images") + " (*.jpg *.jpeg *.png *.bmp *.tif *.tiff)",
200 0 : muse::qtrc("preferences", "All") + " (*)" };
201 0 : }
202 :
203 0 : QString AppearancePreferencesModel::wallpapersDir() const
204 : {
205 0 : return notationConfiguration()->wallpapersDefaultDirPath().toQString();
206 : }
207 :
208 0 : void AppearancePreferencesModel::setHighContrastEnabled(bool enabled)
209 : {
210 0 : if (highContrastEnabled() == enabled) {
211 0 : return;
212 : }
213 :
214 0 : uiConfiguration()->setIsHighContrast(enabled);
215 : }
216 :
217 0 : QString AppearancePreferencesModel::currentThemeCode() const
218 : {
219 0 : return QString::fromStdString(currentTheme().codeKey);
220 : }
221 :
222 0 : int AppearancePreferencesModel::currentAccentColorIndex() const
223 : {
224 0 : QStringList allColors = accentColors();
225 0 : QString color = currentTheme().values[ACCENT_COLOR].toString().toLower();
226 :
227 0 : for (int i = 0; i < static_cast<int>(allColors.size()); ++i) {
228 0 : if (allColors[i].toLower() == color) {
229 0 : return i;
230 : }
231 : }
232 :
233 0 : return INVALID_INDEX;
234 0 : }
235 :
236 0 : ThemeInfo AppearancePreferencesModel::currentTheme() const
237 : {
238 0 : return uiConfiguration()->currentTheme();
239 : }
240 :
241 0 : ThemeList AppearancePreferencesModel::allThemes() const
242 : {
243 0 : return uiConfiguration()->themes();
244 : }
245 :
246 0 : int AppearancePreferencesModel::currentFontIndex() const
247 : {
248 0 : QString currentFont = QString::fromStdString(uiConfiguration()->fontFamily());
249 0 : return allFonts().indexOf(currentFont);
250 0 : }
251 :
252 0 : int AppearancePreferencesModel::bodyTextSize() const
253 : {
254 0 : return uiConfiguration()->fontSize(FontSizeType::BODY);
255 : }
256 :
257 0 : bool AppearancePreferencesModel::backgroundUseColor() const
258 : {
259 0 : return notationConfiguration()->backgroundUseColor();
260 : }
261 :
262 0 : QColor AppearancePreferencesModel::backgroundColor() const
263 : {
264 0 : return notationConfiguration()->backgroundColor();
265 : }
266 :
267 0 : QString AppearancePreferencesModel::backgroundWallpaperPath() const
268 : {
269 0 : return notationConfiguration()->backgroundWallpaperPath().toQString();
270 : }
271 :
272 0 : bool AppearancePreferencesModel::foregroundUseColor() const
273 : {
274 0 : return notationConfiguration()->foregroundUseColor();
275 : }
276 :
277 0 : QColor AppearancePreferencesModel::foregroundColor() const
278 : {
279 0 : return notationConfiguration()->foregroundColor();
280 : }
281 :
282 0 : QString AppearancePreferencesModel::foregroundWallpaperPath() const
283 : {
284 0 : return notationConfiguration()->foregroundWallpaperPath().toQString();
285 : }
286 :
287 0 : bool AppearancePreferencesModel::scoreInversionEnabled() const
288 : {
289 0 : return notationConfiguration()->scoreInversionEnabled();
290 : }
291 :
292 0 : bool AppearancePreferencesModel::isOnlyInvertInDarkTheme() const
293 : {
294 0 : return notationConfiguration()->isOnlyInvertInDarkTheme();
295 : }
296 :
297 0 : QColor AppearancePreferencesModel::engravingColor() const
298 : {
299 0 : return notationConfiguration()->notationColor();
300 : }
301 :
302 0 : void AppearancePreferencesModel::setCurrentThemeCode(const QString& themeCode)
303 : {
304 0 : if (themeCode == currentThemeCode() && !isFollowSystemTheme()) {
305 0 : return;
306 : }
307 :
308 0 : uiConfiguration()->setCurrentTheme(themeCodeFromString(themeCode));
309 : }
310 :
311 0 : void AppearancePreferencesModel::setCurrentAccentColorIndex(int index)
312 : {
313 0 : if (index < 0 || index >= accentColors().size()) {
314 0 : return;
315 : }
316 :
317 0 : if (index == currentAccentColorIndex()) {
318 0 : return;
319 : }
320 :
321 0 : QColor color = accentColors()[index];
322 0 : uiConfiguration()->setCurrentThemeStyleValue(ThemeStyleKey::ACCENT_COLOR, Val(color));
323 : }
324 :
325 0 : void AppearancePreferencesModel::setCurrentFontIndex(int index)
326 : {
327 0 : QStringList fonts = allFonts();
328 :
329 0 : if (index < 0 || index >= fonts.size()) {
330 0 : return;
331 : }
332 :
333 0 : uiConfiguration()->setFontFamily(fonts[index].toStdString());
334 0 : emit currentFontIndexChanged();
335 0 : }
336 :
337 0 : void AppearancePreferencesModel::setBodyTextSize(int size)
338 : {
339 0 : if (size == bodyTextSize() || size <= 0) {
340 0 : return;
341 : }
342 :
343 0 : uiConfiguration()->setBodyFontSize(size);
344 0 : emit bodyTextSizeChanged();
345 : }
346 :
347 0 : void AppearancePreferencesModel::setBackgroundUseColor(bool value)
348 : {
349 0 : if (value == backgroundUseColor()) {
350 0 : return;
351 : }
352 :
353 0 : notationConfiguration()->setBackgroundUseColor(value);
354 : }
355 :
356 0 : void AppearancePreferencesModel::setBackgroundColor(const QColor& color)
357 : {
358 0 : if (color == backgroundColor()) {
359 0 : return;
360 : }
361 :
362 0 : notationConfiguration()->setBackgroundColor(color);
363 : }
364 :
365 0 : void AppearancePreferencesModel::setBackgroundWallpaperPath(const QString& path)
366 : {
367 0 : if (path == backgroundWallpaperPath()) {
368 0 : return;
369 : }
370 :
371 0 : notationConfiguration()->setBackgroundWallpaperPath(path);
372 : }
373 :
374 0 : void AppearancePreferencesModel::setForegroundUseColor(bool value)
375 : {
376 0 : if (value == foregroundUseColor()) {
377 0 : return;
378 : }
379 :
380 0 : notationConfiguration()->setForegroundUseColor(value);
381 : }
382 :
383 0 : void AppearancePreferencesModel::setForegroundColor(const QColor& color)
384 : {
385 0 : if (color == foregroundColor()) {
386 0 : return;
387 : }
388 :
389 0 : notationConfiguration()->setForegroundColor(color);
390 : }
391 :
392 0 : void AppearancePreferencesModel::setForegroundWallpaperPath(const QString& path)
393 : {
394 0 : if (path == foregroundWallpaperPath()) {
395 0 : return;
396 : }
397 :
398 0 : notationConfiguration()->setForegroundWallpaperPath(path);
399 : }
400 :
401 0 : void AppearancePreferencesModel::setScoreInversionEnabled(bool value)
402 : {
403 0 : if (value == scoreInversionEnabled()) {
404 0 : return;
405 : }
406 :
407 0 : notationConfiguration()->setScoreInversionEnabled(value);
408 : }
409 :
410 0 : void AppearancePreferencesModel::setOnlyInvertInDarkTheme(bool value)
411 : {
412 0 : if (value == isOnlyInvertInDarkTheme()) {
413 0 : return;
414 : }
415 :
416 0 : notationConfiguration()->setOnlyInvertInDarkTheme(value);
417 : }
418 :
419 0 : void AppearancePreferencesModel::setEngravingColor(const QColor& color)
420 : {
421 0 : if (color == engravingColor()) {
422 0 : return;
423 : }
424 :
425 0 : notationConfiguration()->setNotationColor(color);
426 : }
|