LCOV - code coverage report
Current view: top level - muse/framework/ui/internal - uiconfiguration.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 371 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-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 <QFontDatabase>
      24              : #include <QJsonArray>
      25              : #include <QJsonDocument>
      26              : #include <QJsonObject>
      27              : #include <QScreen>
      28              : #include <QSettings>
      29              : #include <QApplication>
      30              : 
      31              : #include "uiconfiguration.h"
      32              : #include "global/configreader.h"
      33              : 
      34              : #include "internal/baseapplication.h"
      35              : #include "io/path.h"
      36              : #include "io/fileinfo.h"
      37              : #include "settings.h"
      38              : #include "themeconverter.h"
      39              : 
      40              : #include "imainwindow.h"
      41              : 
      42              : #ifdef Q_OS_WIN
      43              : #include <QOperatingSystemVersion>
      44              : #endif
      45              : 
      46              : #include "muse_framework_config.h"
      47              : 
      48              : #include "log.h"
      49              : 
      50              : using namespace Qt::Literals;
      51              : using namespace muse;
      52              : using namespace muse::ui;
      53              : using namespace muse::async;
      54              : 
      55              : static const Settings::Key UI_THEMES_KEY("ui", "ui/application/themes");
      56              : static const Settings::Key UI_CURRENT_THEME_CODE_KEY("ui", "ui/application/currentThemeCode");
      57              : static const Settings::Key UI_CUSTOM_COLORS_KEY("ui", "ui/application/customColors");
      58              : static const Settings::Key UI_FOLLOW_SYSTEM_THEME_KEY("ui", "ui/application/followSystemTheme");
      59              : static const Settings::Key UI_FONT_FAMILY_KEY("ui", "ui/theme/fontFamily");
      60              : static const Settings::Key UI_FONT_SIZE_KEY("ui", "ui/theme/fontSize");
      61              : static const Settings::Key UI_ICONS_FONT_FAMILY_KEY("ui", "ui/theme/iconsFontFamily");
      62              : static const Settings::Key UI_MUSICAL_FONT_FAMILY_KEY("ui", "ui/theme/musicalFontFamily");
      63              : static const Settings::Key UI_MUSICAL_FONT_SIZE_KEY("ui", "ui/theme/musicalFontSize");
      64              : static const Settings::Key UI_MUSICAL_TEXT_FONT_FAMILY_KEY("ui", "ui/theme/musicalTextFontFamily");
      65              : static const Settings::Key UI_MUSICAL_TEXT_FONT_SIZE_KEY("ui", "ui/theme/musicalTextFontSize");
      66              : 
      67              : static const int FLICKABLE_MAX_VELOCITY = 4000;
      68              : 
      69              : static const int TOOLTIP_DELAY = 500;
      70              : 
      71              : // read custom colors saved by Qt < 6.9
      72              : // see: https://github.com/qt/qtbase/blob/v6.2.4/src/gui/kernel/qplatformdialoghelper.cpp#L292-L302
      73            0 : static std::vector<Val> readLegacyCustomColors()
      74              : {
      75            0 :     constexpr size_t customColorCount = 16;
      76              : 
      77            0 :     QSettings settings(QSettings::UserScope, u"QtProject"_s);
      78            0 :     std::vector<Val> legacyValues(customColorCount, Val(QColorConstants::White));
      79            0 :     for (size_t i = 0; i < customColorCount; ++i) {
      80            0 :         const QVariant value = settings.value(u"Qt/customColors/"_s + QString::number(i));
      81            0 :         if (value.isValid()) {
      82            0 :             legacyValues[i] = Val(QColor::fromRgb(value.toUInt()));
      83              :         }
      84            0 :     }
      85              : 
      86            0 :     return legacyValues;
      87            0 : }
      88              : 
      89            0 : void UiConfiguration::init()
      90              : {
      91            0 :     m_config = ConfigReader::read(":/configs/ui.cfg");
      92              : 
      93            0 :     settings()->setDefaultValue(UI_CURRENT_THEME_CODE_KEY, Val(LIGHT_THEME_CODE));
      94            0 :     settings()->setDefaultValue(UI_CUSTOM_COLORS_KEY, Val(readLegacyCustomColors()));
      95            0 :     settings()->setDefaultValue(UI_FOLLOW_SYSTEM_THEME_KEY, Val(false));
      96            0 :     settings()->setDefaultValue(UI_FONT_FAMILY_KEY, Val(defaultFontFamily()));
      97            0 :     settings()->setDefaultValue(UI_FONT_SIZE_KEY, Val(defaultFontSize()));
      98            0 :     settings()->setDefaultValue(UI_ICONS_FONT_FAMILY_KEY, Val("MusescoreIcon"));
      99            0 :     settings()->setDefaultValue(UI_MUSICAL_FONT_FAMILY_KEY, Val("Leland"));
     100            0 :     settings()->setDefaultValue(UI_MUSICAL_FONT_SIZE_KEY, Val(24));
     101            0 :     settings()->setDefaultValue(UI_MUSICAL_TEXT_FONT_FAMILY_KEY, Val("Leland Text"));
     102            0 :     settings()->setDefaultValue(UI_MUSICAL_TEXT_FONT_SIZE_KEY, Val(defaultFontSize()));
     103            0 :     settings()->setDefaultValue(UI_THEMES_KEY, Val(""));
     104              : 
     105            0 :     settings()->valueChanged(UI_THEMES_KEY).onReceive(this, [this](const Val&) {
     106            0 :         updateThemes();
     107            0 :         notifyAboutCurrentThemeChanged();
     108            0 :     });
     109              : 
     110            0 :     settings()->valueChanged(UI_CURRENT_THEME_CODE_KEY).onReceive(this, [this](const Val&) {
     111            0 :         notifyAboutCurrentThemeChanged();
     112            0 :     });
     113              : 
     114            0 :     settings()->valueChanged(UI_FOLLOW_SYSTEM_THEME_KEY).onReceive(this, [this](const Val& val) {
     115            0 :         m_isFollowSystemTheme.set(val.toBool());
     116            0 :         updateSystemThemeListeningStatus();
     117            0 :     });
     118              : 
     119            0 :     settings()->valueChanged(UI_FONT_FAMILY_KEY).onReceive(this, [this](const Val&) {
     120            0 :         m_fontChanged.notify();
     121            0 :     });
     122              : 
     123            0 :     settings()->valueChanged(UI_FONT_SIZE_KEY).onReceive(this, [this](const Val&) {
     124            0 :         m_fontChanged.notify();
     125            0 :         m_iconsFontChanged.notify();
     126            0 :     });
     127              : 
     128            0 :     settings()->valueChanged(UI_ICONS_FONT_FAMILY_KEY).onReceive(this, [this](const Val&) {
     129            0 :         m_iconsFontChanged.notify();
     130            0 :     });
     131              : 
     132            0 :     settings()->valueChanged(UI_MUSICAL_FONT_FAMILY_KEY).onReceive(this, [this](const Val&) {
     133            0 :         m_musicalFontChanged.notify();
     134            0 :     });
     135              : 
     136            0 :     settings()->valueChanged(UI_MUSICAL_FONT_SIZE_KEY).onReceive(this, [this](const Val&) {
     137            0 :         m_musicalFontChanged.notify();
     138            0 :     });
     139              : 
     140            0 :     platformTheme()->platformThemeChanged().onNotify(this, [this]() {
     141            0 :         synchThemeWithSystemIfNecessary();
     142            0 :     });
     143              : 
     144            0 :     m_themeWatcher.fileChanged().onReceive(this, [this](const std::string&){
     145            0 :         initThemes();
     146            0 :         notifyAboutCurrentThemeChanged();
     147            0 :     });
     148              : 
     149            0 :     correctUserFontIfNeeded();
     150              : 
     151            0 :     initThemes();
     152            0 : }
     153              : 
     154            0 : void UiConfiguration::deinit()
     155              : {
     156            0 :     platformTheme()->stopListening();
     157            0 :     m_themeWatcher.stopWatching();
     158            0 : }
     159              : 
     160            0 : void UiConfiguration::initThemes()
     161              : {
     162            0 :     m_isFollowSystemTheme.val = settings()->value(UI_FOLLOW_SYSTEM_THEME_KEY).toBool();
     163              : 
     164            0 :     updateSystemThemeListeningStatus();
     165              : 
     166            0 :     for (const ThemeCode& codeKey : allStandardThemeCodes()) {
     167            0 :         m_themes.push_back(makeStandardTheme(codeKey));
     168            0 :     }
     169              : 
     170            0 :     updateThemes();
     171            0 :     updateCurrentTheme();
     172            0 : }
     173              : 
     174            0 : void UiConfiguration::correctUserFontIfNeeded()
     175              : {
     176            0 :     QString userFontFamily = QString::fromStdString(fontFamily());
     177            0 :     if (!QFontDatabase::hasFamily(userFontFamily)) {
     178            0 :         std::string fallbackFontFamily = defaultFontFamily();
     179            0 :         LOGI() << "The user font " << userFontFamily << " is missing, we will use the fallback font " << fallbackFontFamily;
     180              : 
     181            0 :         setFontFamily(fallbackFontFamily);
     182            0 :     }
     183            0 : }
     184              : 
     185            0 : void UiConfiguration::updateCurrentTheme()
     186              : {
     187            0 :     ThemeCode currentCodeKey = currentThemeCodeKey();
     188              : 
     189            0 :     for (size_t i = 0; i < m_themes.size(); ++i) {
     190            0 :         if (m_themes[i].codeKey == currentCodeKey) {
     191            0 :             m_currentThemeIndex = i;
     192            0 :             break;
     193              :         }
     194              :     }
     195              : 
     196            0 :     platformTheme()->applyPlatformStyleOnAppForTheme(currentCodeKey);
     197            0 : }
     198              : 
     199            0 : void UiConfiguration::updateThemes()
     200              : {
     201            0 :     ThemeList modifiedThemes = readThemes();
     202              : 
     203            0 :     if (modifiedThemes.empty()) {
     204            0 :         m_themes.clear();
     205            0 :         for (const ThemeCode& codeKey : allStandardThemeCodes()) {
     206            0 :             m_themes.push_back(makeStandardTheme(codeKey));
     207            0 :         }
     208              : 
     209            0 :         return;
     210              :     }
     211              : 
     212            0 :     for (ThemeInfo& theme: m_themes) {
     213            0 :         auto it = std::find_if(modifiedThemes.begin(), modifiedThemes.end(), [theme](const ThemeInfo& modifiedTheme) {
     214            0 :             return modifiedTheme.codeKey == theme.codeKey;
     215              :         });
     216              : 
     217            0 :         bool isModified = it != modifiedThemes.end();
     218            0 :         if (isModified) {
     219            0 :             for (auto key : it->values.keys()) {
     220            0 :                 if (key != UNKNOWN) {
     221            0 :                     theme.values[key] = it->values[key];
     222              :                 }
     223            0 :             }
     224              :         }
     225              :     }
     226            0 : }
     227              : 
     228            0 : bool UiConfiguration::isFollowSystemThemeAvailable() const
     229              : {
     230            0 :     return platformTheme()->isFollowSystemThemeAvailable();
     231              : }
     232              : 
     233            0 : ValNt<bool> UiConfiguration::isFollowSystemTheme() const
     234              : {
     235            0 :     return m_isFollowSystemTheme;
     236              : }
     237              : 
     238            0 : void UiConfiguration::setFollowSystemTheme(bool follow)
     239              : {
     240            0 :     settings()->setSharedValue(UI_FOLLOW_SYSTEM_THEME_KEY, Val(follow));
     241            0 : }
     242              : 
     243            0 : void UiConfiguration::updateSystemThemeListeningStatus()
     244              : {
     245            0 :     if (isFollowSystemTheme().val) {
     246            0 :         platformTheme()->startListening();
     247            0 :         synchThemeWithSystemIfNecessary();
     248              :     } else {
     249            0 :         platformTheme()->stopListening();
     250              :     }
     251            0 : }
     252              : 
     253            0 : void UiConfiguration::synchThemeWithSystemIfNecessary()
     254              : {
     255            0 :     if (!m_isFollowSystemTheme.val) {
     256            0 :         return;
     257              :     }
     258              : 
     259            0 :     doSetIsDarkMode(platformTheme()->isSystemThemeDark());
     260              : }
     261              : 
     262            0 : void UiConfiguration::notifyAboutCurrentThemeChanged()
     263              : {
     264            0 :     updateCurrentTheme();
     265            0 :     m_currentThemeChanged.notify();
     266            0 : }
     267              : 
     268            0 : static QColor colorFromHex(const QString& hex)
     269              : {
     270            0 :     if (!hex.startsWith('#')) {
     271            0 :         return QColor();
     272              :     }
     273              : 
     274            0 :     QString str = hex;
     275            0 :     if (str.length() == 9) { // #RRGGBBAA
     276              :         // Convert to Qt notation: #AARRGGBB
     277            0 :         QString alpha = str.mid(7, 2);
     278            0 :         str.chop(2);
     279            0 :         str.insert(1, alpha);
     280            0 :     }
     281              : 
     282            0 :     return QColor::fromString(str);
     283            0 : }
     284              : 
     285            0 : ThemeInfo UiConfiguration::makeStandardTheme(const ThemeCode& codeKey) const
     286              : {
     287            0 :     ThemeInfo theme;
     288            0 :     theme.codeKey = codeKey;
     289              : 
     290            0 :     io::path_t themeFilePath = globalConfiguration()->appDataPath() + codeKey + ".cfg";
     291              : 
     292              :     // Hot reload is disabled in stable builds
     293            0 :     if (muse::BaseApplication::appUnstable() && io::FileInfo::exists(themeFilePath)) {
     294            0 :         m_themeWatcher.startWatching(themeFilePath.toStdString());
     295              :     } else {
     296            0 :         themeFilePath = ":/configs/" + codeKey + ".cfg";
     297              :     }
     298              : 
     299            0 :     Config config = ConfigReader::read(themeFilePath);
     300              : 
     301              :     theme.values = {
     302            0 :         { BACKGROUND_PRIMARY_COLOR, colorFromHex(config.value("background_primary_color").toQString()) },
     303            0 :         { BACKGROUND_SECONDARY_COLOR, colorFromHex(config.value("background_secondary_color").toQString()) },
     304            0 :         { BACKGROUND_TERTIARY_COLOR, colorFromHex(config.value("background_tertiary_color").toQString()) },
     305            0 :         { BACKGROUND_QUARTERNARY_COLOR, colorFromHex(config.value("background_quarternary_color").toQString()) },
     306            0 :         { POPUP_BACKGROUND_COLOR, colorFromHex(config.value("popup_background_color").toQString()) },
     307            0 :         { PROJECT_TAB_COLOR, colorFromHex(config.value("project_tab_color").toQString()) },
     308            0 :         { TEXT_FIELD_COLOR, colorFromHex(config.value("text_field_color").toQString()) },
     309            0 :         { ACCENT_COLOR, colorFromHex(config.value("accent_color").toQString()) },
     310            0 :         { STROKE_COLOR, colorFromHex(config.value("stroke_color").toQString()) },
     311            0 :         { STROKE_SECONDARY_COLOR, colorFromHex(config.value("stroke_secondary_color").toQString()) },
     312            0 :         { BUTTON_COLOR, colorFromHex(config.value("button_color").toQString()) },
     313            0 :         { FONT_PRIMARY_COLOR, colorFromHex(config.value("font_primary_color").toQString()) },
     314            0 :         { FONT_SECONDARY_COLOR, colorFromHex(config.value("font_secondary_color").toQString()) },
     315            0 :         { LINK_COLOR, colorFromHex(config.value("link_color").toQString()) },
     316            0 :         { FOCUS_COLOR, colorFromHex(config.value("focus_color").toQString()) },
     317            0 :         { WHITE_COLOR, colorFromHex(config.value("white_color").toQString()) },
     318            0 :         { BLACK_COLOR, colorFromHex(config.value("black_color").toQString()) },
     319            0 :         { PLAY_COLOR, colorFromHex(config.value("play_color").toQString()) },
     320            0 :         { RECORD_COLOR, colorFromHex(config.value("record_color").toQString()) },
     321              : 
     322            0 :         { BORDER_WIDTH, config.value("border_width").toDouble() },
     323            0 :         { NAVIGATION_CONTROL_BORDER_WIDTH, config.value("navigation_control_border_width").toDouble() },
     324              : 
     325            0 :         { ACCENT_OPACITY_NORMAL, config.value("accent_opacity_normal").toDouble() },
     326            0 :         { ACCENT_OPACITY_HOVER, config.value("accent_opacity_hover").toDouble() },
     327            0 :         { ACCENT_OPACITY_HIT, config.value("accent_opacity_hit").toDouble() },
     328              : 
     329            0 :         { BUTTON_OPACITY_NORMAL, config.value("button_opacity_normal").toDouble() },
     330            0 :         { BUTTON_OPACITY_HOVER, config.value("button_opacity_hover").toDouble() },
     331            0 :         { BUTTON_OPACITY_HIT, config.value("button_opacity_hit").toDouble() },
     332              : 
     333            0 :         { ITEM_OPACITY_DISABLED, config.value("item_opacity_disabled").toDouble() }
     334            0 :     };
     335              : 
     336            0 :     for (const auto& [key, val] : config) {
     337            0 :         if (val.type() == Val::Type::String) {
     338            0 :             QColor color = colorFromHex(val.toQString());
     339            0 :             if (color.isValid()) {
     340            0 :                 theme.extra.insert(QString::fromStdString(key), color);
     341              :             } else {
     342            0 :                 theme.extra.insert(QString::fromStdString(key), val.toQString());
     343              :             }
     344              :         } else {
     345            0 :             theme.extra.insert(QString::fromStdString(key), val.toDouble());
     346              :         }
     347              :     }
     348              : 
     349            0 :     return theme;
     350            0 : }
     351              : 
     352            0 : ThemeList UiConfiguration::readThemes() const
     353              : {
     354            0 :     TRACEFUNC;
     355              : 
     356            0 :     ThemeList result;
     357              : 
     358            0 :     QByteArray json = QByteArray::fromStdString(settings()->value(UI_THEMES_KEY).toString());
     359            0 :     if (json.isEmpty()) {
     360            0 :         return result;
     361              :     }
     362              : 
     363            0 :     QJsonParseError err;
     364            0 :     QJsonDocument jsodDoc = QJsonDocument::fromJson(json, &err);
     365            0 :     if (err.error != QJsonParseError::NoError) {
     366            0 :         LOGE() << "Couldn't read themes: " << err.errorString();
     367            0 :         return result;
     368              :     }
     369              : 
     370            0 :     if (!jsodDoc.isArray()) {
     371            0 :         return result;
     372              :     }
     373              : 
     374            0 :     QVariantList objList = jsodDoc.array().toVariantList();
     375              : 
     376            0 :     for (const QVariant& themeObj: objList) {
     377            0 :         result.push_back(ThemeConverter::fromMap(themeObj.toMap()));
     378              :     }
     379              : 
     380            0 :     return result;
     381            0 : }
     382              : 
     383            0 : void UiConfiguration::writeThemes(const ThemeList& themes)
     384              : {
     385            0 :     TRACEFUNC;
     386              : 
     387            0 :     QJsonArray jsonArray;
     388            0 :     for (const ThemeInfo& theme : themes) {
     389            0 :         QVariantMap map = ThemeConverter::toMap(theme);
     390            0 :         jsonArray << QJsonObject::fromVariantMap(map);
     391            0 :     }
     392              : 
     393            0 :     QJsonDocument jsonDoc(jsonArray);
     394              : 
     395            0 :     Val value(jsonDoc.toJson(QJsonDocument::Compact).constData());
     396            0 :     settings()->setSharedValue(UI_THEMES_KEY, value);
     397            0 : }
     398              : 
     399            0 : ThemeList UiConfiguration::themes() const
     400              : {
     401            0 :     return m_themes;
     402              : }
     403              : 
     404            0 : QStringList UiConfiguration::possibleAccentColors() const
     405              : {
     406              :     static const QStringList lightAccentColors {
     407              :         "#F28585",
     408              :         "#F9906F",
     409              :         "#F0A663",
     410              :         "#EDBE6E",
     411              :         "#DAD153",
     412              :         "#C0D84A",
     413              :         "#9DDA60",
     414              :         "#79D88E",
     415              :         "#67D2A4",
     416              :         "#51CAC2",
     417              :         "#46BCD3",
     418              :         "#70B8FA",
     419              :         "#8999FF",
     420              :         "#B69BFF",
     421              :         "#D093FB",
     422              :         "#E39CEB",
     423              :         "#F298D3",
     424              :         "#FF92B6"
     425            0 :     };
     426              : 
     427              :     static const QStringList darkAccentColors {
     428              :         "#D73838",
     429              :         "#DA5931",
     430              :         "#CA6100",
     431              :         "#AD720C",
     432              :         "#898006",
     433              :         "#728707",
     434              :         "#4B8C09",
     435              :         "#1D9337",
     436              :         "#0E935B",
     437              :         "#019086",
     438              :         "#018DA9",
     439              :         "#2082DD",
     440              :         "#5B6FF3",
     441              :         "#8D64FF",
     442              :         "#B252F7",
     443              :         "#D830EA",
     444              :         "#E03DAA",
     445              :         "#E9447B"
     446            0 :     };
     447              : 
     448            0 :     if (isDarkMode()) {
     449            0 :         return darkAccentColors;
     450              :     }
     451              : 
     452            0 :     return lightAccentColors;
     453              : }
     454              : 
     455            0 : QStringList UiConfiguration::possibleFontFamilies() const
     456              : {
     457            0 :     QStringList allFonts = QFontDatabase::families();
     458            0 :     for (const QString& fontFamily : m_nonTextFonts) {
     459            0 :         allFonts.removeAll(fontFamily);
     460              :     }
     461            0 :     return allFonts;
     462            0 : }
     463              : 
     464            0 : QStringList UiConfiguration::nonTextFonts() const
     465              : {
     466            0 :     return m_nonTextFonts;
     467              : }
     468              : 
     469            0 : void UiConfiguration::setNonTextFonts(const QStringList& fontFamilies)
     470              : {
     471            0 :     m_nonTextFonts = fontFamilies;
     472            0 : }
     473              : 
     474            0 : void UiConfiguration::resetThemes()
     475              : {
     476            0 :     m_themes.clear();
     477            0 :     for (const ThemeCode& codeKey : allStandardThemeCodes()) {
     478            0 :         m_themes.push_back(makeStandardTheme(codeKey));
     479            0 :     }
     480              : 
     481            0 :     writeThemes(m_themes);
     482              : 
     483            0 :     notifyAboutCurrentThemeChanged();
     484            0 : }
     485              : 
     486            0 : const ThemeInfo& UiConfiguration::currentTheme() const
     487              : {
     488            0 :     return m_themes[m_currentThemeIndex];
     489              : }
     490              : 
     491            0 : ThemeCode UiConfiguration::currentThemeCodeKey() const
     492              : {
     493            0 :     ThemeCode preferredThemeCode = settings()->value(UI_CURRENT_THEME_CODE_KEY).toString();
     494            0 :     return preferredThemeCode.empty() ? LIGHT_THEME_CODE : preferredThemeCode;
     495            0 : }
     496              : 
     497            0 : bool UiConfiguration::isDarkMode() const
     498              : {
     499            0 :     return isDarkTheme(currentThemeCodeKey());
     500              : }
     501              : 
     502            0 : void UiConfiguration::setIsDarkMode(bool dark)
     503              : {
     504            0 :     setFollowSystemTheme(false);
     505              : 
     506            0 :     doSetIsDarkMode(dark);
     507            0 : }
     508              : 
     509            0 : void UiConfiguration::doSetIsDarkMode(bool dark)
     510              : {
     511            0 :     if (isHighContrast()) {
     512            0 :         doSetCurrentTheme(dark ? HIGH_CONTRAST_BLACK_THEME_CODE : HIGH_CONTRAST_WHITE_THEME_CODE);
     513              :     } else {
     514            0 :         doSetCurrentTheme(dark ? DARK_THEME_CODE : LIGHT_THEME_CODE);
     515              :     }
     516            0 : }
     517              : 
     518            0 : bool UiConfiguration::isHighContrast() const
     519              : {
     520            0 :     return isHighContrastTheme(currentThemeCodeKey());
     521              : }
     522              : 
     523            0 : void UiConfiguration::setIsHighContrast(bool highContrast)
     524              : {
     525            0 :     if (isDarkMode()) {
     526            0 :         doSetCurrentTheme(highContrast ? HIGH_CONTRAST_BLACK_THEME_CODE : DARK_THEME_CODE);
     527              :     } else {
     528            0 :         doSetCurrentTheme(highContrast ? HIGH_CONTRAST_WHITE_THEME_CODE : LIGHT_THEME_CODE);
     529              :     }
     530            0 : }
     531              : 
     532            0 : void UiConfiguration::setCurrentTheme(const ThemeCode& themeCode)
     533              : {
     534            0 :     setFollowSystemTheme(false);
     535              : 
     536            0 :     doSetCurrentTheme(themeCode);
     537            0 : }
     538              : 
     539            0 : void UiConfiguration::doSetCurrentTheme(const ThemeCode& themeCode)
     540              : {
     541            0 :     settings()->setSharedValue(UI_CURRENT_THEME_CODE_KEY, Val(themeCode));
     542            0 : }
     543              : 
     544            0 : void UiConfiguration::setCurrentThemeStyleValue(ThemeStyleKey key, const Val& val)
     545              : {
     546            0 :     ThemeInfo& currentTheme = m_themes[m_currentThemeIndex];
     547            0 :     currentTheme.values[key] = val.toQVariant();
     548              : 
     549            0 :     ThemeList modifiedThemes = readThemes();
     550              : 
     551            0 :     auto it = std::find_if(modifiedThemes.begin(), modifiedThemes.end(), [currentTheme](const ThemeInfo& theme) {
     552            0 :         return theme.codeKey == currentTheme.codeKey;
     553              :     });
     554              : 
     555            0 :     if (it != modifiedThemes.end()) {
     556            0 :         modifiedThemes.erase(it);
     557              :     }
     558              : 
     559            0 :     modifiedThemes.push_back(currentTheme);
     560            0 :     writeThemes(modifiedThemes);
     561            0 : }
     562              : 
     563            0 : muse::async::Notification UiConfiguration::currentThemeChanged() const
     564              : {
     565            0 :     return m_currentThemeChanged;
     566              : }
     567              : 
     568            0 : std::string UiConfiguration::fontFamily() const
     569              : {
     570            0 :     return settings()->value(UI_FONT_FAMILY_KEY).toString();
     571              : }
     572              : 
     573            0 : void UiConfiguration::setFontFamily(const std::string& family)
     574              : {
     575            0 :     settings()->setSharedValue(UI_FONT_FAMILY_KEY, Val(family));
     576            0 : }
     577              : 
     578            0 : int UiConfiguration::fontSize(FontSizeType type) const
     579              : {
     580            0 :     int bodyFontSize = settings()->value(UI_FONT_SIZE_KEY).toInt();
     581              : 
     582              :     /*
     583              :      * DEFAULT SIZE:
     584              :      * body: 12
     585              :      * body large: 14
     586              :      * tab: 16
     587              :      * header: 22
     588              :      * title: 32
     589              :      */
     590            0 :     switch (type) {
     591            0 :     case FontSizeType::BODY: return bodyFontSize;
     592            0 :     case FontSizeType::BODY_LARGE: return bodyFontSize + bodyFontSize / 6;
     593            0 :     case FontSizeType::TAB: return bodyFontSize + bodyFontSize / 3;
     594            0 :     case FontSizeType::HEADER: return bodyFontSize + bodyFontSize / 1.2;
     595            0 :     case FontSizeType::TITLE: return bodyFontSize + bodyFontSize / 0.6;
     596              :     }
     597              : 
     598            0 :     return bodyFontSize;
     599              : }
     600              : 
     601            0 : void UiConfiguration::setBodyFontSize(int size)
     602              : {
     603            0 :     settings()->setSharedValue(UI_FONT_SIZE_KEY, Val(size));
     604            0 : }
     605              : 
     606            0 : muse::async::Notification UiConfiguration::fontChanged() const
     607              : {
     608            0 :     return m_fontChanged;
     609              : }
     610              : 
     611            0 : std::string UiConfiguration::iconsFontFamily() const
     612              : {
     613            0 :     return settings()->value(UI_ICONS_FONT_FAMILY_KEY).toString();
     614              : }
     615              : 
     616            0 : int UiConfiguration::iconsFontSize(IconSizeType type) const
     617              : {
     618            0 :     int bodyFontSize = fontSize(FontSizeType::BODY) + 4;
     619              : 
     620            0 :     switch (type) {
     621            0 :     case IconSizeType::Regular: return bodyFontSize;
     622            0 :     case IconSizeType::Toolbar: return bodyFontSize + 2;
     623              :     }
     624              : 
     625            0 :     return bodyFontSize;
     626              : }
     627              : 
     628            0 : muse::async::Notification UiConfiguration::iconsFontChanged() const
     629              : {
     630            0 :     return m_iconsFontChanged;
     631              : }
     632              : 
     633            0 : io::path_t UiConfiguration::appIconPath() const
     634              : {
     635            0 :     return m_config.value("appIconPath").toPath();
     636              : }
     637              : 
     638            0 : std::string UiConfiguration::musicalFontFamily() const
     639              : {
     640            0 :     return settings()->value(UI_MUSICAL_FONT_FAMILY_KEY).toString();
     641              : }
     642              : 
     643            0 : int UiConfiguration::musicalFontSize() const
     644              : {
     645            0 :     return settings()->value(UI_MUSICAL_FONT_SIZE_KEY).toInt();
     646              : }
     647              : 
     648            0 : muse::async::Notification UiConfiguration::musicalFontChanged() const
     649              : {
     650            0 :     return m_musicalFontChanged;
     651              : }
     652              : 
     653            0 : std::string UiConfiguration::musicalTextFontFamily() const
     654              : {
     655            0 :     return settings()->value(UI_MUSICAL_TEXT_FONT_FAMILY_KEY).toString();
     656              : }
     657              : 
     658            0 : int UiConfiguration::musicalTextFontSize() const
     659              : {
     660            0 :     return settings()->value(UI_MUSICAL_TEXT_FONT_SIZE_KEY).toInt();
     661              : }
     662              : 
     663            0 : Notification UiConfiguration::musicalTextFontChanged() const
     664              : {
     665            0 :     return m_musicalTextFontChanged;
     666              : }
     667              : 
     668            0 : std::string UiConfiguration::defaultFontFamily() const
     669              : {
     670            0 :     return QFontDatabase::systemFont(QFontDatabase::GeneralFont).family().toStdString();
     671              : }
     672              : 
     673            0 : int UiConfiguration::defaultFontSize() const
     674              : {
     675            0 :     return 12;
     676              : }
     677              : 
     678            0 : void UiConfiguration::resetFonts()
     679              : {
     680            0 :     settings()->setSharedValue(UI_FONT_FAMILY_KEY, settings()->defaultValue(UI_FONT_FAMILY_KEY));
     681            0 :     settings()->setSharedValue(UI_FONT_SIZE_KEY, settings()->defaultValue(UI_FONT_SIZE_KEY));
     682            0 :     settings()->setSharedValue(UI_ICONS_FONT_FAMILY_KEY, settings()->defaultValue(UI_ICONS_FONT_FAMILY_KEY));
     683            0 :     settings()->setSharedValue(UI_MUSICAL_FONT_FAMILY_KEY, settings()->defaultValue(UI_MUSICAL_FONT_FAMILY_KEY));
     684            0 :     settings()->setSharedValue(UI_MUSICAL_FONT_SIZE_KEY, settings()->defaultValue(UI_MUSICAL_FONT_SIZE_KEY));
     685            0 : }
     686              : 
     687            0 : void UiConfiguration::setCustomPhysicalDotsPerInch(std::optional<double> dpi)
     688              : {
     689            0 :     m_customDPI = dpi;
     690            0 : }
     691              : 
     692            0 : std::optional<double> UiConfiguration::customPhysicalDotsPerInch() const
     693              : {
     694            0 :     return m_customDPI;
     695              : }
     696              : 
     697            0 : bool UiConfiguration::isGlobalMenuAvailable() const
     698              : {
     699            0 :     return platformTheme()->isGlobalMenuAvailable();
     700              : }
     701              : 
     702            0 : bool UiConfiguration::isSystemDragSupported() const
     703              : {
     704              : #ifdef MUSE_MODULE_UI_SYSTEMDRAG_SUPPORTED
     705            0 :     return true;
     706              : #else
     707              :     return false;
     708              : #endif
     709              : }
     710              : 
     711            0 : void UiConfiguration::applyPlatformStyle(QWindow* window)
     712              : {
     713            0 :     platformTheme()->applyPlatformStyleOnWindowForTheme(window, currentThemeCodeKey());
     714            0 : }
     715              : 
     716            0 : int UiConfiguration::flickableMaxVelocity() const
     717              : {
     718            0 :     return FLICKABLE_MAX_VELOCITY;
     719              : }
     720              : 
     721            0 : int UiConfiguration::tooltipDelay() const
     722              : {
     723            0 :     return TOOLTIP_DELAY;
     724              : }
     725              : 
     726            0 : std::vector<QColor> UiConfiguration::colorDialogCustomColors() const
     727              : {
     728            0 :     const ValList colorVals = settings()->value(UI_CUSTOM_COLORS_KEY).toList();
     729              : 
     730            0 :     std::vector<QColor> customColors;
     731            0 :     customColors.reserve(colorVals.size());
     732            0 :     for (const auto& colorVal : colorVals) {
     733            0 :         customColors.push_back(colorVal.toQColor());
     734              :     }
     735              : 
     736            0 :     return customColors;
     737            0 : }
     738              : 
     739            0 : void UiConfiguration::setColorDialogCustomColors(const std::vector<QColor>& customColors)
     740              : {
     741            0 :     ValList colorVals;
     742            0 :     colorVals.reserve(customColors.size());
     743            0 :     for (const auto& color: customColors) {
     744            0 :         colorVals.emplace_back(color);
     745              :     }
     746              : 
     747            0 :     settings()->setLocalValue(UI_CUSTOM_COLORS_KEY, Val(colorVals));
     748            0 : }
        

Generated by: LCOV version 2.0-1