Allow to choose color scheme on Windows

PR #21615.
This commit is contained in:
Vladimir Golovnev 2024-10-19 13:37:51 +03:00 committed by GitHub
parent 4805afc1a2
commit a47e1cdb48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 163 additions and 4 deletions

View file

@ -95,7 +95,8 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v4 uses: jurplel/install-qt-action@v4
with: with:
version: "6.7.3" version: "6.8.0"
arch: win64_msvc2022_64
archives: qtbase qtsvg qttools archives: qtbase qtsvg qttools
cache: true cache: true

View file

@ -46,6 +46,7 @@ add_library(qbt_gui STATIC
autoexpandabledialog.h autoexpandabledialog.h
banlistoptionsdialog.h banlistoptionsdialog.h
color.h color.h
colorscheme.h
cookiesdialog.h cookiesdialog.h
cookiesmodel.h cookiesmodel.h
deletionconfirmationdialog.h deletionconfirmationdialog.h

45
src/gui/colorscheme.h Normal file
View file

@ -0,0 +1,45 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#pragma once
#include <QMetaEnum>
inline namespace ColorSchemeNS
{
Q_NAMESPACE
enum class ColorScheme
{
System ,
Light,
Dark
};
Q_ENUM_NS(ColorScheme)
}

View file

@ -243,6 +243,7 @@ void OptionsDialog::loadBehaviorTabOptions()
setLocale(pref->getLocale()); setLocale(pref->getLocale());
initializeStyleCombo(); initializeStyleCombo();
initializeColorSchemeOptions();
m_ui->checkUseCustomTheme->setChecked(Preferences::instance()->useCustomUITheme()); m_ui->checkUseCustomTheme->setChecked(Preferences::instance()->useCustomUITheme());
m_ui->customThemeFilePath->setSelectedPath(Preferences::instance()->customUIThemePath()); m_ui->customThemeFilePath->setSelectedPath(Preferences::instance()->customUIThemePath());
@ -359,6 +360,10 @@ void OptionsDialog::loadBehaviorTabOptions()
connect(m_ui->comboStyle, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboStyle, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
#endif #endif
#ifdef QBT_HAS_COLORSCHEME_OPTION
connect(m_ui->comboColorScheme, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
#endif
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
connect(m_ui->checkUseSystemIcon, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkUseSystemIcon, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
#endif #endif
@ -459,6 +464,10 @@ void OptionsDialog::saveBehaviorTabOptions() const
pref->setStyle(m_ui->comboStyle->currentText()); pref->setStyle(m_ui->comboStyle->currentText());
#endif #endif
#ifdef QBT_HAS_COLORSCHEME_OPTION
UIThemeManager::instance()->setColorScheme(m_ui->comboColorScheme->currentData().value<ColorScheme>());
#endif
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
pref->useSystemIcons(m_ui->checkUseSystemIcon->isChecked()); pref->useSystemIcons(m_ui->checkUseSystemIcon->isChecked());
#endif #endif
@ -1704,6 +1713,22 @@ void OptionsDialog::initializeStyleCombo()
#endif #endif
} }
void OptionsDialog::initializeColorSchemeOptions()
{
#ifdef QBT_HAS_COLORSCHEME_OPTION
m_ui->comboColorScheme->addItem(tr("Dark", "Dark color scheme"), QVariant::fromValue(ColorScheme::Dark));
m_ui->comboColorScheme->addItem(tr("Light", "Light color scheme"), QVariant::fromValue(ColorScheme::Light));
m_ui->comboColorScheme->addItem(tr("System", "System color scheme"), QVariant::fromValue(ColorScheme::System));
m_ui->comboColorScheme->setCurrentIndex(m_ui->comboColorScheme->findData(QVariant::fromValue(UIThemeManager::instance()->colorScheme())));
#else
m_ui->labelColorScheme->hide();
m_ui->comboColorScheme->hide();
m_ui->UISettingsBoxLayout->removeWidget(m_ui->labelColorScheme);
m_ui->UISettingsBoxLayout->removeWidget(m_ui->comboColorScheme);
m_ui->UISettingsBoxLayout->removeItem(m_ui->spacerColorScheme);
#endif
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
bool OptionsDialog::WinStartup() const bool OptionsDialog::WinStartup() const
{ {

View file

@ -144,6 +144,7 @@ private:
// General options // General options
void initializeLanguageCombo(); void initializeLanguageCombo();
void initializeStyleCombo(); void initializeStyleCombo();
void initializeColorSchemeOptions();
QString getLocale() const; QString getLocale() const;
bool isSplashScreenDisabled() const; bool isSplashScreenDisabled() const;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View file

@ -191,7 +191,30 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="3" column="0" colspan="3"> <item row="3" column="0">
<widget class="QLabel" name="labelColorScheme">
<property name="text">
<string>Color scheme:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboColorScheme"/>
</item>
<item row="3" column="2">
<spacer name="spacerColorScheme">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="3">
<widget class="QGroupBox" name="checkUseCustomTheme"> <widget class="QGroupBox" name="checkUseCustomTheme">
<property name="title"> <property name="title">
<string>Use custom UI Theme</string> <string>Use custom UI Theme</string>
@ -213,14 +236,14 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2"> <item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="checkUseSystemIcon"> <widget class="QCheckBox" name="checkUseSystemIcon">
<property name="text"> <property name="text">
<string>Use icons from system theme</string> <string>Use icons from system theme</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" colspan="2"> <item row="6" column="0" colspan="2">
<widget class="QPushButton" name="buttonCustomizeUITheme"> <widget class="QPushButton" name="buttonCustomizeUITheme">
<property name="text"> <property name="text">
<string>Customize UI Theme...</string> <string>Customize UI Theme...</string>
@ -3945,6 +3968,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
<tabstop>tabOption</tabstop> <tabstop>tabOption</tabstop>
<tabstop>tabSelection</tabstop> <tabstop>tabSelection</tabstop>
<tabstop>comboLanguage</tabstop> <tabstop>comboLanguage</tabstop>
<tabstop>comboStyle</tabstop>
<tabstop>comboColorScheme</tabstop>
<tabstop>checkUseCustomTheme</tabstop> <tabstop>checkUseCustomTheme</tabstop>
<tabstop>customThemeFilePath</tabstop> <tabstop>customThemeFilePath</tabstop>
<tabstop>checkUseSystemIcon</tabstop> <tabstop>checkUseSystemIcon</tabstop>

View file

@ -80,6 +80,9 @@ void UIThemeManager::initInstance()
UIThemeManager::UIThemeManager() UIThemeManager::UIThemeManager()
: m_useCustomTheme {Preferences::instance()->useCustomUITheme()} : m_useCustomTheme {Preferences::instance()->useCustomUITheme()}
#ifdef QBT_HAS_COLORSCHEME_OPTION
, m_colorSchemeSetting {u"Appearance/ColorScheme"_s}
#endif
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
, m_useSystemIcons {Preferences::instance()->useSystemIcons()} , m_useSystemIcons {Preferences::instance()->useSystemIcons()}
#endif #endif
@ -90,6 +93,10 @@ UIThemeManager::UIThemeManager()
LogMsg(tr("Set app style failed. Unknown style: \"%1\"").arg(styleName), Log::WARNING); LogMsg(tr("Set app style failed. Unknown style: \"%1\"").arg(styleName), Log::WARNING);
#endif #endif
#ifdef QBT_HAS_COLORSCHEME_OPTION
applyColorScheme();
#endif
// NOTE: Qt::QueuedConnection can be omitted as soon as support for Qt 6.5 is dropped // NOTE: Qt::QueuedConnection can be omitted as soon as support for Qt 6.5 is dropped
connect(QApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &UIThemeManager::onColorSchemeChanged, Qt::QueuedConnection); connect(QApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &UIThemeManager::onColorSchemeChanged, Qt::QueuedConnection);
@ -125,6 +132,38 @@ UIThemeManager *UIThemeManager::instance()
return m_instance; return m_instance;
} }
#ifdef QBT_HAS_COLORSCHEME_OPTION
ColorScheme UIThemeManager::colorScheme() const
{
return m_colorSchemeSetting.get(ColorScheme::System);
}
void UIThemeManager::setColorScheme(const ColorScheme value)
{
if (value == colorScheme())
return;
m_colorSchemeSetting = value;
}
void UIThemeManager::applyColorScheme() const
{
switch (colorScheme())
{
case ColorScheme::System:
default:
qApp->styleHints()->unsetColorScheme();
break;
case ColorScheme::Light:
qApp->styleHints()->setColorScheme(Qt::ColorScheme::Light);
break;
case ColorScheme::Dark:
qApp->styleHints()->setColorScheme(Qt::ColorScheme::Dark);
break;
}
}
#endif
void UIThemeManager::applyStyleSheet() const void UIThemeManager::applyStyleSheet() const
{ {
qApp->setStyleSheet(QString::fromUtf8(m_themeSource->readStyleSheet())); qApp->setStyleSheet(QString::fromUtf8(m_themeSource->readStyleSheet()));

View file

@ -31,6 +31,7 @@
#pragma once #pragma once
#include <QtSystemDetection> #include <QtSystemDetection>
#include <QtVersionChecks>
#include <QColor> #include <QColor>
#include <QHash> #include <QHash>
#include <QIcon> #include <QIcon>
@ -40,6 +41,15 @@
#include "uithemesource.h" #include "uithemesource.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)) && defined(Q_OS_WIN)
#define QBT_HAS_COLORSCHEME_OPTION
#endif
#ifdef QBT_HAS_COLORSCHEME_OPTION
#include "base/settingvalue.h"
#include "colorscheme.h"
#endif
class UIThemeManager final : public QObject class UIThemeManager final : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -50,6 +60,11 @@ public:
static void freeInstance(); static void freeInstance();
static UIThemeManager *instance(); static UIThemeManager *instance();
#ifdef QBT_HAS_COLORSCHEME_OPTION
ColorScheme colorScheme() const;
void setColorScheme(ColorScheme value);
#endif
QIcon getIcon(const QString &iconId, const QString &fallback = {}) const; QIcon getIcon(const QString &iconId, const QString &fallback = {}) const;
QIcon getFlagIcon(const QString &countryIsoCode) const; QIcon getFlagIcon(const QString &countryIsoCode) const;
QPixmap getScaledPixmap(const QString &iconId, int height) const; QPixmap getScaledPixmap(const QString &iconId, int height) const;
@ -66,8 +81,15 @@ private:
void applyStyleSheet() const; void applyStyleSheet() const;
void onColorSchemeChanged(); void onColorSchemeChanged();
#ifdef QBT_HAS_COLORSCHEME_OPTION
void applyColorScheme() const;
#endif
static UIThemeManager *m_instance; static UIThemeManager *m_instance;
const bool m_useCustomTheme; const bool m_useCustomTheme;
#ifdef QBT_HAS_COLORSCHEME_OPTION
SettingValue<ColorScheme> m_colorSchemeSetting;
#endif
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
const bool m_useSystemIcons; const bool m_useSystemIcons;
#endif #endif