File indexing completed on 2024-05-05 04:46:52

0001 #include "style.h"
0002 #include <QCoreApplication>
0003 #include <QGuiApplication>
0004 #include <QIcon>
0005 #include <QStyle>
0006 #include <QApplication>
0007 #include <QFontDatabase>
0008 
0009 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0010 #include <MauiMan3/thememanager.h>
0011 #include <MauiMan3/backgroundmanager.h>
0012 #include <MauiMan3/accessibilitymanager.h>
0013 #else
0014 #include <MauiMan4/thememanager.h>
0015 #include <MauiMan4/backgroundmanager.h>
0016 #include <MauiMan4/accessibilitymanager.h>
0017 
0018 #include <QStyleHints>
0019 #endif
0020 
0021 #ifdef Q_OS_ANDROID
0022 #include "mauiandroid.h"
0023 #endif
0024 
0025 Style *Style::m_instance = nullptr;
0026 
0027 void Style::styleChanged()
0028 {
0029     // It should be safe to use qApp->style() unguarded here, because the signal
0030     // will only have been connected if qApp is a QApplication.
0031     Q_ASSERT(qobject_cast<QApplication *>(QCoreApplication::instance()));
0032     auto *style = qApp->style();
0033     if (!style || QCoreApplication::closingDown()) {
0034         return;
0035     }
0036 
0037     Q_ASSERT(style != sender());
0038 
0039     connect(style, &QObject::destroyed, this, &Style::styleChanged);
0040 
0041     m_currentIconTheme = QIcon::themeName();
0042     Q_EMIT currentIconThemeChanged(m_currentIconTheme);
0043     
0044     m_monospacedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
0045     Q_EMIT monospacedFontChanged();
0046 }
0047 
0048 
0049 Style::Style(QObject *parent) : QObject(parent)
0050   ,m_iconSizes (new GroupSizes(8,16, 22, 32, 48, 64, 128, this))
0051   ,m_space( new GroupSizes(4, 6, 8, 16, 24, 32, 40, this))
0052   ,m_fontSizes(new GroupSizes(this))
0053   ,m_units(new Units(this))
0054   ,m_accentColor(QColor("#26c6da"))
0055   ,m_themeSettings( new MauiMan::ThemeManager(this))
0056   ,m_backgroundSettings( new MauiMan::BackgroundManager(this))
0057   ,m_accessibilitySettings( new MauiMan::AccessibilityManager(this))
0058   {
0059     connect(qApp, &QCoreApplication::aboutToQuit, []()
0060     {
0061         delete m_instance;
0062         m_instance = nullptr;
0063     });
0064 
0065     connect(qGuiApp, &QGuiApplication::fontChanged, [this](const QFont &font)
0066     {
0067         m_defaultFont = font;
0068         setFontSizes();
0069         Q_EMIT defaultFontChanged();
0070         // Q_EMIT m_fontSizes->sizesChanged();
0071         Q_EMIT fontSizesChanged();
0072         Q_EMIT h1FontChanged();
0073         Q_EMIT h2FontChanged();
0074         Q_EMIT 
0075     });
0076 
0077 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0078     connect(m_themeSettings, &MauiMan::ThemeManager::styleTypeChanged, [this](int type)
0079     {
0080         if(m_styleType_blocked)
0081             return;
0082 
0083         m_styleType = static_cast<Style::StyleType>(type);
0084         Q_EMIT styleTypeChanged(m_styleType);
0085     });
0086 #else     
0087     
0088     connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, [this](Qt::ColorScheme type)
0089     {
0090         qDebug() << "Color schem style type changed<<"<< type;
0091         if(m_styleType_blocked)
0092             return;
0093         
0094          switch(type)
0095     {
0096         case Qt::ColorScheme::Unknown:  
0097             m_styleType = static_cast<Style::StyleType>(m_themeSettings->styleType()); 
0098             break;
0099         case Qt::ColorScheme::Light: 
0100              m_styleType = Style::StyleType::Light; 
0101         break;
0102         case Qt::ColorScheme::Dark:
0103              m_styleType = Style::StyleType::Dark;
0104              break;
0105     }
0106     
0107      Q_EMIT styleTypeChanged(m_styleType);
0108     });
0109     
0110      connect(m_themeSettings, &MauiMan::ThemeManager::styleTypeChanged, [this](int type)
0111     {
0112         if(m_styleType_blocked)
0113             return;
0114 
0115         m_styleType = static_cast<Style::StyleType>(type);
0116         Q_EMIT styleTypeChanged(m_styleType);
0117     });  
0118     
0119 #endif
0120 
0121     connect(m_themeSettings, &MauiMan::ThemeManager::accentColorChanged, [this](QString color)
0122     {
0123         m_accentColor = color;
0124         Q_EMIT this->accentColorChanged(m_accentColor);
0125     });
0126 
0127     connect(m_themeSettings, &MauiMan::ThemeManager::borderRadiusChanged, [this](uint radius)
0128     {
0129         m_radiusV = radius;
0130         Q_EMIT this->radiusVChanged(m_radiusV);
0131     });
0132 
0133     connect(m_themeSettings, &MauiMan::ThemeManager::iconSizeChanged, [this](uint size)
0134     {
0135         m_iconSize = size;
0136         Q_EMIT this->iconSizeChanged(m_iconSize);
0137     });
0138 
0139     connect(m_themeSettings, &MauiMan::ThemeManager::paddingSizeChanged, [this](uint size)
0140     {
0141         m_defaultPadding = size;
0142         Q_EMIT this->defaultPaddingChanged();
0143     });
0144 
0145     connect(m_themeSettings, &MauiMan::ThemeManager::marginSizeChanged, [this](uint size)
0146     {
0147         qDebug() << "ContentMARGINS CHANGED" << size;
0148         m_contentMargins = size;
0149         Q_EMIT this->contentMarginsChanged();
0150     });
0151 
0152     connect(m_themeSettings, &MauiMan::ThemeManager::spacingSizeChanged, [this](uint size)
0153     {
0154         m_defaultSpacing = size;
0155         Q_EMIT this->defaultSpacingChanged();
0156     });
0157 
0158     connect(m_themeSettings, &MauiMan::ThemeManager::enableEffectsChanged, [this](bool value)
0159     {
0160         m_enableEffects = value;
0161         Q_EMIT this->enableEffectsChanged(m_enableEffects);
0162     });
0163     
0164     connect(m_backgroundSettings, &MauiMan::BackgroundManager::wallpaperSourceChanged, [this](QString source)
0165     {
0166         m_adaptiveColorSchemeSource = QUrl::fromUserInput(source).toLocalFile();
0167         Q_EMIT this->adaptiveColorSchemeSourceChanged(m_adaptiveColorSchemeSource);
0168     });
0169     
0170     connect(m_themeSettings, &MauiMan::ThemeManager::enableEffectsChanged, [this](bool value)
0171     {
0172         m_enableEffects = value;
0173         Q_EMIT this->enableEffectsChanged(m_enableEffects);
0174     });
0175     
0176     connect(m_accessibilitySettings, &MauiMan::AccessibilityManager::scrollBarPolicyChanged, [this](uint state)
0177     {
0178      qDebug() << "SCROLBAR POLICY CHANGED" << state;
0179     Q_EMIT scrollBarPolicyChanged(state);
0180     });
0181 
0182    if(MauiManUtils::isMauiSession())
0183    {
0184         connect(m_themeSettings, &MauiMan::ThemeManager::iconThemeChanged, [this](QString name)
0185         {
0186             qDebug() << "Ask to change the icon theme";
0187             m_currentIconTheme = name;
0188             Q_EMIT currentIconThemeChanged(m_currentIconTheme);
0189         });
0190    }else
0191    {
0192 //        //to be able to check and icon theme change rely on the style being reset, this not even works on Plasma, so do we need it?
0193 //       QStyle *style = qApp->style();
0194 //       if (style)
0195 //       {
0196 //           connect(style, &QObject::destroyed, this, &Style::styleChanged);
0197 //       }
0198 }
0199 
0200     m_defaultFont = qGuiApp->font();
0201     m_monospacedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
0202     setFontSizes();
0203 
0204     m_radiusV = m_themeSettings->borderRadius();
0205     m_iconSize = m_themeSettings->iconSize();
0206     m_accentColor = m_themeSettings->accentColor();
0207 
0208     m_contentMargins = m_themeSettings->marginSize();
0209     m_defaultPadding = m_themeSettings->paddingSize();
0210     m_defaultSpacing = m_themeSettings->spacingSize();
0211 
0212     m_currentIconTheme = QIcon::themeName();
0213 
0214     //TODO Use new Qt6 StyelHint properties for this
0215     
0216     
0217     
0218  
0219 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0220     
0221 #ifdef Q_OS_ANDROID
0222     MAUIAndroid android;
0223     m_styleType = android.darkModeEnabled() ? StyleType::Dark : StyleType::Light;
0224 #else   
0225     m_styleType = static_cast<Style::StyleType>(m_themeSettings->styleType());
0226 #endif
0227     
0228 #else    
0229     //For Maui Session we want to use MauiMan
0230     if(!MauiManUtils::isMauiSession())
0231     {
0232      switch(QGuiApplication::styleHints()->colorScheme())
0233     {
0234         case Qt::ColorScheme::Unknown:  
0235             m_styleType = static_cast<Style::StyleType>(m_themeSettings->styleType()); 
0236             break;
0237         case Qt::ColorScheme::Light: 
0238              m_styleType = Style::StyleType::Light; 
0239         break;
0240         case Qt::ColorScheme::Dark:
0241              m_styleType = Style::StyleType::Dark;
0242              break;
0243     }
0244   }
0245     else
0246     {
0247          m_styleType = static_cast<Style::StyleType>(m_themeSettings->styleType());
0248     }   
0249 #endif
0250 
0251     m_adaptiveColorSchemeSource = QUrl::fromUserInput(m_backgroundSettings->wallpaperSource()).toLocalFile();
0252     m_enableEffects = m_themeSettings->enableEffects();
0253 }
0254 
0255 void Style::setFontSizes()
0256 {
0257     qDebug() << m_defaultFont << m_defaultFont.pointSize();
0258 
0259     m_defaultFontSize = m_defaultFont.pointSize ();
0260 
0261     m_fontSizes->m_tiny = m_defaultFont.pointSize ()-2;
0262     m_fontSizes->m_small = m_defaultFont.pointSize ()-1;
0263     m_fontSizes->m_medium = m_defaultFont.pointSize ();
0264     m_fontSizes->m_big = m_defaultFont.pointSize ()+1;
0265     m_fontSizes->m_large = m_defaultFont.pointSize ()+2;
0266     m_fontSizes->m_huge = m_defaultFont.pointSize ()+3;
0267     m_fontSizes->m_enormous = m_defaultFont.pointSize ()+4;
0268 
0269     m_h1Font.setPointSize(m_fontSizes->m_enormous);
0270     m_h1Font.setWeight(QFont::Black);
0271     m_h1Font.setBold(true);
0272 
0273     m_h2Font.setPointSize(m_fontSizes->m_big);
0274     m_h2Font.setWeight(QFont::DemiBold);
0275     // m_h2Font.setBold(false);
0276 }
0277 
0278 void Style::setRadiusV(const uint& radius)
0279 {
0280     if(m_radiusV == radius)
0281     {
0282         return;
0283     }
0284 
0285     m_radiusV = radius;
0286     Q_EMIT radiusVChanged(m_radiusV);
0287 }
0288 
0289 bool Style::enableEffects() const
0290 {
0291     return m_enableEffects;
0292 }
0293 
0294 bool Style::translucencyAvailable() const
0295 {
0296     return m_translucencyAvailable;
0297 }
0298 
0299 void Style::setTranslucencyAvailable(const bool &value)
0300 {
0301     if(value == m_translucencyAvailable)
0302     {
0303         return;
0304     }
0305 
0306     m_translucencyAvailable = value;
0307     Q_EMIT this->translucencyAvailableChanged(m_translucencyAvailable);
0308 }
0309 
0310 
0311 Style *Style::qmlAttachedProperties(QObject *object)
0312 {
0313     Q_UNUSED(object)
0314     return Style::instance();
0315 }
0316 
0317 int getClosest(int, int, int);
0318 
0319 // Returns element closest to target in arr[]
0320 int findClosest(int arr[], int n, int target)
0321 {
0322     // Corner cases
0323     if (target <= arr[0])
0324         return arr[0];
0325     if (target >= arr[n - 1])
0326         return arr[n - 1];
0327 
0328     // Doing binary search
0329     int i = 0, j = n, mid = 0;
0330     while (i < j) {
0331         mid = (i + j) / 2;
0332 
0333         if (arr[mid] == target)
0334             return arr[mid];
0335 
0336         /* If target is less than array element,
0337          *        then search in left */
0338         if (target < arr[mid]) {
0339 
0340             // If target is greater than previous
0341             // to mid, return closest of two
0342             if (mid > 0 && target > arr[mid - 1])
0343                 return getClosest(arr[mid - 1],
0344                         arr[mid], target);
0345 
0346             /* Repeat for left half */
0347             j = mid;
0348         }
0349 
0350         // If target is greater than mid
0351         else {
0352             if (mid < n - 1 && target < arr[mid + 1])
0353                 return getClosest(arr[mid],
0354                                   arr[mid + 1], target);
0355             // update i
0356             i = mid + 1;
0357         }
0358     }
0359 
0360     // Only single element left after search
0361     return arr[mid];
0362 }
0363 
0364 // Method to compare which one is the more close.
0365 // We find the closest by taking the difference
0366 // between the target and both values. It assumes
0367 // that val2 is greater than val1 and target lies
0368 // between these two.
0369 int getClosest(int val1, int val2,
0370                int target)
0371 {
0372     if (target - val1 >= val2 - target)
0373         return val2;
0374     else
0375         return val1;
0376 }
0377 
0378 
0379 int Style::mapToIconSizes(const int &size)
0380 {
0381     int values[] = {8, 16, 22, 32, 48, 64, 128};
0382     int n = sizeof(values) / sizeof(values[0]);
0383     return findClosest (values, n, size);
0384 }
0385 
0386 GroupSizes::GroupSizes(const uint tiny, const uint small, const uint medium, const uint big, const uint large, const uint huge, const uint enormous, QObject *parent) : QObject(parent)
0387   ,m_tiny(tiny)
0388   ,m_small(small)
0389   ,m_medium(medium)
0390   ,m_big(big)
0391   ,m_large(large)
0392   ,m_huge(huge)
0393   ,m_enormous(enormous)
0394 
0395 {
0396 
0397 }
0398 
0399 GroupSizes::GroupSizes(QObject* parent) : QObject(parent)
0400 {
0401 }
0402 
0403 
0404 QVariant Style::adaptiveColorSchemeSource() const
0405 {
0406     return m_adaptiveColorSchemeSource;
0407 }
0408 
0409 void Style::setAdaptiveColorSchemeSource(const QVariant& source)
0410 {
0411     m_adaptiveColorSchemeSource_blocked = true;
0412     if(source == m_adaptiveColorSchemeSource)
0413     {
0414         return;
0415     }
0416 
0417     m_adaptiveColorSchemeSource = source;
0418     Q_EMIT adaptiveColorSchemeSourceChanged(m_adaptiveColorSchemeSource);
0419 }
0420 
0421 void Style::unsetAdaptiveColorSchemeSource()
0422 {
0423     m_adaptiveColorSchemeSource_blocked = false;
0424     m_adaptiveColorSchemeSource = QUrl::fromUserInput(m_backgroundSettings->wallpaperSource()).toLocalFile();
0425     Q_EMIT adaptiveColorSchemeSourceChanged(m_adaptiveColorSchemeSource);
0426 }
0427 
0428 QColor Style::accentColor() const
0429 {
0430     return m_accentColor;
0431 }
0432 
0433 void Style::setAccentColor(const QColor& color)
0434 {
0435     m_accentColor_blocked = true;
0436 
0437     if(m_accentColor == color)
0438     {
0439         return;
0440     }
0441 
0442     m_accentColor = color;
0443     Q_EMIT accentColorChanged(m_accentColor);
0444 }
0445 
0446 void Style::unsetAccentColor()
0447 {
0448     m_accentColor_blocked = false;
0449     m_accentColor = m_themeSettings->accentColor();
0450     Q_EMIT accentColorChanged(m_accentColor);
0451 }
0452 
0453 Style::StyleType Style::styleType() const
0454 {
0455     return m_styleType;
0456 }
0457 
0458 void Style::setStyleType(const Style::StyleType &type)
0459 {
0460     m_styleType_blocked = true;
0461 
0462     if (m_styleType == type)
0463         return;
0464 
0465     m_styleType = type;
0466     Q_EMIT styleTypeChanged(m_styleType);
0467 }
0468 
0469 void Style::unsetStyeType()
0470 {
0471     m_styleType_blocked = false;
0472     m_styleType = static_cast<Style::StyleType>(m_themeSettings->styleType());
0473     Q_EMIT styleTypeChanged(m_styleType);
0474 }
0475 
0476 Units::Units(QObject *parent) : QObject(parent)
0477   , m_fontMetrics(QFontMetricsF(QGuiApplication::font()))
0478   , m_gridUnit(m_fontMetrics.height())
0479   , m_veryLongDuration(400)
0480   , m_longDuration(200)
0481   , m_shortDuration(100)
0482   , m_veryShortDuration(50)
0483   , m_humanMoment(2000)
0484   , m_toolTipDelay(700)
0485 {
0486 
0487 }
0488 
0489 uint Style::iconSize() const
0490 {
0491     return m_iconSize;
0492 }
0493 
0494 QString Style::currentIconTheme() const
0495 {
0496     return m_currentIconTheme;
0497 }
0498 
0499 bool Style::menusHaveIcons() const
0500 {
0501     return !qApp->testAttribute(Qt::AA_DontShowIconsInMenus);
0502 }
0503 
0504 uint Style::scrollBarPolicy() const
0505 {
0506     return m_accessibilitySettings->scrollBarPolicy();
0507 }
0508 
0509 bool Style::playSounds() const
0510 {
0511     return m_accessibilitySettings->playSounds();    
0512 }
0513 
0514 
0515 
0516