/**************************************************************************** ** Copyright (c) 2025 Evgeny Teterin (nayk) ** All right reserved. ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the ** "Software"), to deal in the Software without restriction, including ** without limitation the rights to use, copy, modify, merge, publish, ** distribute, sublicense, and/or sell copies of the Software, and to ** permit persons to whom the Software is furnished to do so, subject to ** the following conditions: ** ** The above copyright notice and this permission notice shall be ** included in all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** ****************************************************************************/ #include "application_config.h" #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) # include #endif //============================================================================== bool systemUseDarkTheme() { QApplication *application = qobject_cast( QApplication::instance() ); if (!application) return false; QPalette appPalette = application->palette(); bool darkTheme {false}; int n = -1; #if QT_VERSION > QT_VERSION_CHECK(6, 5, 0) if (application->styleHints()->colorScheme() == Qt::ColorScheme::Light) n = 1; else if (application->styleHints()->colorScheme() == Qt::ColorScheme::Dark) n = 0; #endif #ifdef Q_OS_WIN if (n < 0) { QSettings registry(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)", QSettings::NativeFormat); //n = registry.value("SystemUsesLightTheme",-1).toInt(); n = registry.value("AppsUseLightTheme", -1).toInt(); } #endif if (n < 0) { QRgb c1 = appPalette.color(QPalette::Window).rgb(); QRgb c2 = appPalette.color(QPalette::WindowText).rgb(); darkTheme = ((qRed(c1) * 11 + qGreen(c1) * 16 + qBlue(c1) * 5) / 32) < ((qRed(c2) * 11 + qGreen(c2) * 16 + qBlue(c2) * 5) / 32); } else { darkTheme = (n == 0); } return darkTheme; } //============================================================================== void Application::initialize() { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); #endif #if defined (PROG_NAME) QApplication::setApplicationName( QString(PROG_NAME) ); #endif #if defined (SOFT_DEVELOPER) QApplication::setOrganizationName( QString(SOFT_DEVELOPER) ); #endif #if defined (DEVELOPER_DOMAIN) QApplication::setOrganizationDomain( QString(DEVELOPER_DOMAIN) ); #endif #if defined (PROG_VERSION) QApplication::setApplicationVersion( QString(PROG_VERSION) ); #endif #if defined (BUILD_DATE) qApp->setProperty( "buildDate", QString(BUILD_DATE) ); #endif } //============================================================================== QString Application::applicationRootPath() { QString path { QApplication::applicationDirPath() }; if ( path.right(1) != "/" ) { path += "/"; } if (path.right(5) == "/bin/") { path.remove( path.length() - 4, 4 ); } return path; } //============================================================================== void Application::installTranslations(const QString &lng) { const QString dirName { applicationRootPath() + "translations/" }; QDir translationsDir { dirName }; QStringList filesList = translationsDir.entryList( QStringList() << QString("*_%1.qm").arg(lng), QDir::Files ); for (const QString &fileName: std::as_const(filesList)) { QTranslator *translator = new QTranslator(QApplication::instance()); if (translator->load( dirName + fileName )) { QApplication::instance()->installTranslator( translator ); } else { delete translator; } } } //============================================================================== bool Application::updateApplicationStyle(AppTheme appTheme) { QApplication *application = qobject_cast( QApplication::instance() ); if (!application) return false; application->setStyleSheet(""); if (QStyleFactory::keys().contains("Fusion")) { application->setStyle( QStyleFactory::create("Fusion") ); } bool darkTheme = (appTheme == SystemTheme) ? systemUseDarkTheme() : appTheme == DarkTheme; QPalette appPalette = application->palette(); appPalette.setColor( QPalette::Highlight, QColor(55, 174, 254)); appPalette.setColor( QPalette::HighlightedText, QColor(245, 250, 255)); appPalette.setColor( QPalette::Link, QColor(55, 174, 254)); appPalette.setColor( QPalette::LinkVisited, QColor(52, 103, 146)); appPalette.setColor( QPalette::Disabled, QPalette::Link, QColor(52, 103, 146)); appPalette.setColor( QPalette::Disabled, QPalette::LinkVisited, QColor(40, 90, 130)); if (darkTheme) { appPalette.setColor( QPalette::Window, QColor(30, 35, 40)); appPalette.setColor( QPalette::WindowText, QColor(245, 250, 255)); appPalette.setColor( QPalette::Base, QColor(45, 50, 55)); appPalette.setColor( QPalette::AlternateBase, QColor(48, 53, 58)); appPalette.setColor( QPalette::ToolTipBase, QColor(60, 65, 70)); appPalette.setColor( QPalette::ToolTipText, QColor(200, 205, 210)); appPalette.setColor( QPalette::Text, QColor(245, 250, 255)); appPalette.setColor( QPalette::Button, QColor(55, 60, 65)); appPalette.setColor( QPalette::ButtonText, QColor(245, 250, 255)); appPalette.setColor( QPalette::BrightText, QColor(194, 232, 255)); appPalette.setColor( QPalette::PlaceholderText, QColor(200, 205, 210)); appPalette.setColor( QPalette::Disabled, QPalette::WindowText, QColor(157, 157, 157)); appPalette.setColor( QPalette::Disabled, QPalette::Base, QColor(30, 35, 40)); appPalette.setColor( QPalette::Disabled, QPalette::AlternateBase, QColor(33, 38, 43)); appPalette.setColor( QPalette::Disabled, QPalette::ToolTipBase, QColor(200, 205, 210)); appPalette.setColor( QPalette::Disabled, QPalette::ToolTipText, QColor(5, 10, 15)); appPalette.setColor( QPalette::Disabled, QPalette::Text, QColor(150, 155, 160)); appPalette.setColor( QPalette::Disabled, QPalette::ButtonText, QColor(150, 155, 160)); appPalette.setColor( QPalette::Disabled, QPalette::BrightText, QColor(150, 193, 218)); } else { // light theme appPalette.setColor( QPalette::Window, QColor(230, 235, 240)); appPalette.setColor( QPalette::WindowText, QColor(0, 3, 5)); appPalette.setColor( QPalette::Base, QColor(245, 250, 255)); appPalette.setColor( QPalette::AlternateBase, QColor(242, 247, 252)); appPalette.setColor( QPalette::ToolTipBase, QColor(255, 255, 220)); appPalette.setColor( QPalette::ToolTipText, QColor(0, 0, 0)); appPalette.setColor( QPalette::Text, QColor(0, 3, 5)); appPalette.setColor( QPalette::Button, QColor(225, 230, 235)); appPalette.setColor( QPalette::ButtonText, QColor(0, 3, 5)); appPalette.setColor( QPalette::BrightText, QColor(255, 255, 255)); appPalette.setColor( QPalette::PlaceholderText, QColor(5, 10, 15)); appPalette.setColor( QPalette::Disabled, QPalette::WindowText, QColor(120, 120, 120)); appPalette.setColor( QPalette::Disabled, QPalette::Base, QColor(240, 240, 240)); appPalette.setColor( QPalette::Disabled, QPalette::AlternateBase, QColor(247, 247, 247)); appPalette.setColor( QPalette::Disabled, QPalette::ToolTipBase, QColor(255, 255, 220)); appPalette.setColor( QPalette::Disabled, QPalette::ToolTipText, QColor(0, 0, 0)); appPalette.setColor( QPalette::Disabled, QPalette::Text, QColor(120, 120, 120)); appPalette.setColor( QPalette::Disabled, QPalette::ButtonText, QColor(120, 120, 120)); appPalette.setColor( QPalette::Disabled, QPalette::BrightText, QColor(255, 255, 255)); } application->setPalette(appPalette); QString qssFile {":/qss/style.qss"}; QString qss; if (QFile::exists(qssFile)) { QFile file(qssFile); if (!file.open(QFile::ReadOnly)) return false; QByteArray buf; while (!file.atEnd()) { buf.append( file.read(1024) ); } file.close(); qss = QString(buf); QRgb rgb = appPalette.color(QPalette::Highlight).rgb(); QString clStr = QString("rgb(%1, %2, %3)").arg(qRed(rgb)).arg(qGreen(rgb)).arg(qBlue(rgb)); qss.replace("$MENU_ITEM_SELECT_COLOR", clStr); rgb = appPalette.color(QPalette::LinkVisited).rgb(); clStr = QString("rgb(%1, %2, %3)").arg(qRed(rgb)).arg(qGreen(rgb)).arg(qBlue(rgb)); qss.replace("$MENU_ITEM_SELECT_BORDER", clStr); double checkBoxMetric = QApplication::primaryScreen()->logicalDotsPerInch() / 4.3; double toggleMetric = checkBoxMetric * 1.2; clStr = QString("%1px").arg(qRound( checkBoxMetric )); qss.replace("$CHECKBOX_SIZE", clStr); clStr = QString("%1px").arg(qRound( toggleMetric )); qss.replace("$TOGGLE_HEIGHT", clStr); clStr = QString("%1px").arg(qRound( toggleMetric * 1.5 )); qss.replace("$TOGGLE_WIDTH", clStr); clStr = darkTheme ? "dark" : "light"; qss.replace("$THEME", clStr); if (toggleMetric > 32) { qss.replace("toggle_checked.png", "toggle_checked@2x.png"); qss.replace("toggle_unchecked.png", "toggle_unchecked@2x.png"); qss.replace("toggle_checked_disabled.png", "toggle_checked_disabled@2x.png"); qss.replace("toggle_unchecked_disabled.png", "toggle_unchecked_disabled@2x.png"); qss.replace("toggle_checked_focus.png", "toggle_checked_focus@2x.png"); qss.replace("toggle_unchecked_focus.png", "toggle_unchecked_focus@2x.png"); qss.replace("toggle_pressed.png", "toggle_pressed@2x.png"); } if (checkBoxMetric > 32) { qss.replace("_checked.png", "_checked@2x.png"); qss.replace("_unchecked.png", "_unchecked@2x.png"); qss.replace("_indeterminate.png", "_indeterminate@2x.png"); qss.replace("_disabled.png", "_disabled@2x.png"); qss.replace("_focus.png", "_focus@2x.png"); qss.replace("_pressed.png", "_pressed@2x.png"); } } qssFile = applicationRootPath() + "style.qss"; if (QFile::exists(qssFile)) { QFile file(qssFile); if (!file.open(QFile::ReadOnly)) return false; QByteArray buf; while (!file.atEnd()) { buf.append( file.read(1024) ); } file.close(); qss += "\n" + QString(buf); } application->setStyleSheet(qss); application->setProperty("AppsUseDarkTheme", darkTheme); return true; } //============================================================================== bool Application::applicationUseDarkTheme() { QApplication *application = qobject_cast( QApplication::instance() ); if (!application) return false; if (!application->property("AppsUseDarkTheme").isNull()) { return application->property("AppsUseDarkTheme").toBool(); } bool darkTheme = systemUseDarkTheme(); application->setProperty("AppsUseDarkTheme", darkTheme); return darkTheme; } //==============================================================================