LCOV - code coverage report
Current view: top level - muse/framework/ui/api - themeapi.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 199 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 "themeapi.h"
      24              : 
      25              : #include <QFontMetrics>
      26              : 
      27              : using namespace muse::ui;
      28              : using namespace muse::api;
      29              : 
      30              : struct FontConfig
      31              : {
      32              :     QFont::Weight weight = QFont::Normal;
      33              :     FontSizeType sizeType = FontSizeType::BODY;
      34              : };
      35              : 
      36            0 : ThemeApi::ThemeApi(IApiEngine* e)
      37            0 :     : api::ApiObject(e)
      38              : {
      39            0 :     setObjectName("UiTheme");
      40            0 : }
      41              : 
      42            0 : void ThemeApi::init()
      43              : {
      44            0 :     configuration()->currentThemeChanged().onNotify(this, [this]() {
      45            0 :         update();
      46            0 :     });
      47              : 
      48            0 :     initThemeValues();
      49              : 
      50            0 :     initUiFonts();
      51            0 :     initIconsFont();
      52            0 :     initMusicalFont();
      53            0 :     initMusicalTextFont();
      54            0 :     calculateDefaultButtonSize();
      55            0 : }
      56              : 
      57            0 : void ThemeApi::initThemeValues()
      58              : {
      59            0 :     QMap<ThemeStyleKey, QVariant> themeValues = configuration()->currentTheme().values;
      60              : 
      61            0 :     m_backgroundPrimaryColor = themeValues[BACKGROUND_PRIMARY_COLOR].toString();
      62            0 :     m_backgroundSecondaryColor = themeValues[BACKGROUND_SECONDARY_COLOR].toString();
      63            0 :     m_backgroundTertiaryColor = themeValues[BACKGROUND_TERTIARY_COLOR].toString();
      64            0 :     m_backgroundQuarternaryColor = themeValues[BACKGROUND_QUARTERNARY_COLOR].toString();
      65            0 :     m_popupBackgroundColor = themeValues[POPUP_BACKGROUND_COLOR].toString();
      66            0 :     m_textFieldColor = themeValues[TEXT_FIELD_COLOR].toString();
      67            0 :     m_accentColor = themeValues[ACCENT_COLOR].toString();
      68            0 :     m_strokeColor = themeValues[STROKE_COLOR].toString();
      69            0 :     m_buttonColor = themeValues[BUTTON_COLOR].toString();
      70            0 :     m_fontPrimaryColor = themeValues[FONT_PRIMARY_COLOR].toString();
      71            0 :     m_fontSecondaryColor = themeValues[FONT_SECONDARY_COLOR].toString();
      72            0 :     m_linkColor = themeValues[LINK_COLOR].toString();
      73            0 :     m_focusColor = themeValues[FOCUS_COLOR].toString();
      74              : 
      75            0 :     m_borderWidth = themeValues[BORDER_WIDTH].toReal();
      76            0 :     m_navCtrlBorderWidth = themeValues[NAVIGATION_CONTROL_BORDER_WIDTH].toReal();
      77            0 :     m_accentOpacityNormal = themeValues[ACCENT_OPACITY_NORMAL].toReal();
      78            0 :     m_accentOpacityHover = themeValues[ACCENT_OPACITY_HOVER].toReal();
      79            0 :     m_accentOpacityHit = themeValues[ACCENT_OPACITY_HIT].toReal();
      80            0 :     m_buttonOpacityNormal = themeValues[BUTTON_OPACITY_NORMAL].toReal();
      81            0 :     m_buttonOpacityHover = themeValues[BUTTON_OPACITY_HOVER].toReal();
      82            0 :     m_buttonOpacityHit = themeValues[BUTTON_OPACITY_HIT].toReal();
      83            0 :     m_itemOpacityDisabled = themeValues[ITEM_OPACITY_DISABLED].toReal();
      84              : 
      85            0 :     m_extra = configuration()->currentTheme().extra;
      86            0 : }
      87              : 
      88            0 : void ThemeApi::update()
      89              : {
      90            0 :     calculateDefaultButtonSize();
      91            0 :     initThemeValues();
      92            0 :     notifyAboutThemeChanged();
      93            0 : }
      94              : 
      95            0 : bool ThemeApi::isDark() const
      96              : {
      97            0 :     return configuration()->isDarkMode();
      98              : }
      99              : 
     100            0 : QColor ThemeApi::backgroundPrimaryColor() const
     101              : {
     102            0 :     return m_backgroundPrimaryColor;
     103              : }
     104              : 
     105            0 : QColor ThemeApi::backgroundSecondaryColor() const
     106              : {
     107            0 :     return m_backgroundSecondaryColor;
     108              : }
     109              : 
     110            0 : QColor ThemeApi::backgroundTertiaryColor() const
     111              : {
     112            0 :     return m_backgroundTertiaryColor;
     113              : }
     114              : 
     115            0 : QColor ThemeApi::backgroundQuarternaryColor() const
     116              : {
     117            0 :     return m_backgroundQuarternaryColor;
     118              : }
     119              : 
     120            0 : QColor ThemeApi::popupBackgroundColor() const
     121              : {
     122            0 :     return m_popupBackgroundColor;
     123              : }
     124              : 
     125            0 : QColor ThemeApi::textFieldColor() const
     126              : {
     127            0 :     return m_textFieldColor;
     128              : }
     129              : 
     130            0 : QColor ThemeApi::accentColor() const
     131              : {
     132            0 :     return m_accentColor;
     133              : }
     134              : 
     135            0 : QColor ThemeApi::strokeColor() const
     136              : {
     137            0 :     return m_strokeColor;
     138              : }
     139              : 
     140            0 : QColor ThemeApi::buttonColor() const
     141              : {
     142            0 :     return m_buttonColor;
     143              : }
     144              : 
     145            0 : QColor ThemeApi::fontPrimaryColor() const
     146              : {
     147            0 :     return m_fontPrimaryColor;
     148              : }
     149              : 
     150            0 : QColor ThemeApi::fontSecondaryColor() const
     151              : {
     152            0 :     return m_fontSecondaryColor;
     153              : }
     154              : 
     155            0 : QColor ThemeApi::linkColor() const
     156              : {
     157            0 :     return m_linkColor;
     158              : }
     159              : 
     160            0 : QColor ThemeApi::focusColor() const
     161              : {
     162            0 :     return m_focusColor;
     163              : }
     164              : 
     165            0 : QFont ThemeApi::bodyFont() const
     166              : {
     167            0 :     return m_bodyFont;
     168              : }
     169              : 
     170            0 : QFont ThemeApi::bodyBoldFont() const
     171              : {
     172            0 :     return m_bodyBoldFont;
     173              : }
     174              : 
     175            0 : QFont ThemeApi::largeBodyFont() const
     176              : {
     177            0 :     return m_largeBodyFont;
     178              : }
     179              : 
     180            0 : QFont ThemeApi::largeBodyBoldFont() const
     181              : {
     182            0 :     return m_largeBodyBoldFont;
     183              : }
     184              : 
     185            0 : QFont ThemeApi::tabFont() const
     186              : {
     187            0 :     return m_tabFont;
     188              : }
     189              : 
     190            0 : QFont ThemeApi::tabBoldFont() const
     191              : {
     192            0 :     return m_tabBoldFont;
     193              : }
     194              : 
     195            0 : QFont ThemeApi::headerFont() const
     196              : {
     197            0 :     return m_headerFont;
     198              : }
     199              : 
     200            0 : QFont ThemeApi::headerBoldFont() const
     201              : {
     202            0 :     return m_headerBoldFont;
     203              : }
     204              : 
     205            0 : QFont ThemeApi::titleBoldFont() const
     206              : {
     207            0 :     return m_titleBoldFont;
     208              : }
     209              : 
     210            0 : QFont ThemeApi::iconsFont() const
     211              : {
     212            0 :     return m_iconsFont;
     213              : }
     214              : 
     215            0 : QFont ThemeApi::toolbarIconsFont() const
     216              : {
     217            0 :     return m_toolbarIconsFont;
     218              : }
     219              : 
     220            0 : QFont ThemeApi::musicalFont() const
     221              : {
     222            0 :     return m_musicalFont;
     223              : }
     224              : 
     225            0 : QFont ThemeApi::musicalTextFont() const
     226              : {
     227            0 :     return m_musicalTextFont;
     228              : }
     229              : 
     230            0 : qreal ThemeApi::defaultButtonSize() const
     231              : {
     232            0 :     return m_defaultButtonSize;
     233              : }
     234              : 
     235            0 : qreal ThemeApi::borderWidth() const
     236              : {
     237            0 :     return m_borderWidth;
     238              : }
     239              : 
     240            0 : qreal ThemeApi::navCtrlBorderWidth() const
     241              : {
     242            0 :     return m_navCtrlBorderWidth;
     243              : }
     244              : 
     245            0 : qreal ThemeApi::accentOpacityNormal() const
     246              : {
     247            0 :     return m_accentOpacityNormal;
     248              : }
     249              : 
     250            0 : qreal ThemeApi::accentOpacityHover() const
     251              : {
     252            0 :     return m_accentOpacityHover;
     253              : }
     254              : 
     255            0 : qreal ThemeApi::accentOpacityHit() const
     256              : {
     257            0 :     return m_accentOpacityHit;
     258              : }
     259              : 
     260            0 : qreal ThemeApi::buttonOpacityNormal() const
     261              : {
     262            0 :     return m_buttonOpacityNormal;
     263              : }
     264              : 
     265            0 : qreal ThemeApi::buttonOpacityHover() const
     266              : {
     267            0 :     return m_buttonOpacityHover;
     268              : }
     269              : 
     270            0 : qreal ThemeApi::buttonOpacityHit() const
     271              : {
     272            0 :     return m_buttonOpacityHit;
     273              : }
     274              : 
     275            0 : qreal ThemeApi::itemOpacityDisabled() const
     276              : {
     277            0 :     return m_itemOpacityDisabled;
     278              : }
     279              : 
     280            0 : int ThemeApi::flickableMaxVelocity() const
     281              : {
     282            0 :     return configuration()->flickableMaxVelocity();
     283              : }
     284              : 
     285            0 : int ThemeApi::tooltipDelay() const
     286              : {
     287            0 :     return configuration()->tooltipDelay();
     288              : }
     289              : 
     290            0 : void ThemeApi::initUiFonts()
     291              : {
     292            0 :     setupUiFonts();
     293              : 
     294            0 :     configuration()->fontChanged().onNotify(this, [this]() {
     295            0 :         setupUiFonts();
     296            0 :         update();
     297            0 :     });
     298            0 : }
     299              : 
     300            0 : void ThemeApi::initIconsFont()
     301              : {
     302            0 :     setupIconsFont();
     303              : 
     304            0 :     configuration()->iconsFontChanged().onNotify(this, [this]() {
     305            0 :         setupIconsFont();
     306            0 :         update();
     307            0 :     });
     308            0 : }
     309              : 
     310            0 : void ThemeApi::initMusicalFont()
     311              : {
     312            0 :     setupMusicFont();
     313              : 
     314            0 :     configuration()->musicalFontChanged().onNotify(this, [this]() {
     315            0 :         setupMusicFont();
     316            0 :         update();
     317            0 :     });
     318            0 : }
     319              : 
     320            0 : void ThemeApi::initMusicalTextFont()
     321              : {
     322            0 :     setupMusicTextFont();
     323              : 
     324            0 :     configuration()->musicalTextFontChanged().onNotify(this, [this]() {
     325            0 :         setupMusicTextFont();
     326            0 :         update();
     327            0 :     });
     328            0 : }
     329              : 
     330            0 : void ThemeApi::setupUiFonts()
     331              : {
     332              :     const std::vector<std::pair<QFont*, FontConfig> > fonts {
     333            0 :         { &m_bodyFont, { QFont::Normal, FontSizeType::BODY } },
     334            0 :         { &m_bodyBoldFont, { QFont::DemiBold, FontSizeType::BODY } },
     335            0 :         { &m_largeBodyFont, { QFont::Normal, FontSizeType::BODY_LARGE } },
     336            0 :         { &m_largeBodyBoldFont, { QFont::DemiBold, FontSizeType::BODY_LARGE } },
     337            0 :         { &m_tabFont, { QFont::Normal, FontSizeType::TAB } },
     338            0 :         { &m_tabBoldFont, { QFont::DemiBold, FontSizeType::TAB } },
     339            0 :         { &m_headerFont, { QFont::Normal, FontSizeType::HEADER } },
     340            0 :         { &m_headerBoldFont, { QFont::DemiBold, FontSizeType::HEADER } },
     341            0 :         { &m_titleBoldFont, { QFont::DemiBold, FontSizeType::TITLE } },
     342            0 :     };
     343              : 
     344            0 :     for (const auto& [font, fontConfig] : fonts) {
     345            0 :         std::string family = configuration()->fontFamily();
     346            0 :         int size = configuration()->fontSize(fontConfig.sizeType);
     347              : 
     348            0 :         font->setPixelSize(size);
     349            0 :         font->setFamily(QString::fromStdString(family));
     350            0 :         font->setWeight(fontConfig.weight);
     351            0 :     }
     352            0 : }
     353              : 
     354            0 : void ThemeApi::setupIconsFont()
     355              : {
     356            0 :     QString family = QString::fromStdString(configuration()->iconsFontFamily());
     357              : 
     358            0 :     m_iconsFont.setFamily(family);
     359            0 :     m_iconsFont.setPixelSize(configuration()->iconsFontSize(IconSizeType::Regular));
     360              : 
     361            0 :     m_toolbarIconsFont.setFamily(family);
     362            0 :     m_toolbarIconsFont.setPixelSize(configuration()->iconsFontSize(IconSizeType::Toolbar));
     363            0 : }
     364              : 
     365            0 : void ThemeApi::setupMusicFont()
     366              : {
     367            0 :     m_musicalFont.setFamily(QString::fromStdString(configuration()->musicalFontFamily()));
     368            0 :     m_musicalFont.setPixelSize(configuration()->musicalFontSize());
     369            0 : }
     370              : 
     371            0 : void ThemeApi::setupMusicTextFont()
     372              : {
     373            0 :     m_musicalTextFont.setFamily(QString::fromStdString(configuration()->musicalTextFontFamily()));
     374            0 :     m_musicalTextFont.setPixelSize(configuration()->musicalTextFontSize());
     375            0 : }
     376              : 
     377            0 : void ThemeApi::calculateDefaultButtonSize()
     378              : {
     379            0 :     constexpr qreal MINIMUM_BUTTON_SIZE = 30.0;
     380            0 :     constexpr qreal BUTTON_PADDING = 8.0;
     381              : 
     382            0 :     QFontMetricsF bodyFontMetrics(m_bodyFont);
     383            0 :     QFontMetricsF iconFontMetrics(m_iconsFont);
     384              : 
     385            0 :     qreal requiredSize = std::max(bodyFontMetrics.height(), iconFontMetrics.height()) + BUTTON_PADDING;
     386            0 :     m_defaultButtonSize = std::max(requiredSize, MINIMUM_BUTTON_SIZE);
     387            0 : }
     388              : 
     389            0 : void ThemeApi::notifyAboutThemeChanged()
     390              : {
     391            0 :     emit themeChanged();
     392            0 : }
     393              : 
     394            0 : QVariantMap ThemeApi::extra() const
     395              : {
     396            0 :     return m_extra;
     397              : }
        

Generated by: LCOV version 2.0-1