Allow to choose Qt style

PR #21553.
This commit is contained in:
Vladimir Golovnev 2024-10-11 16:04:57 +03:00 committed by GitHub
parent 2d857b6200
commit 2d185dc1c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 106 additions and 28 deletions

View file

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

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2014-2023 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2014-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -58,10 +58,6 @@
#include <QSplashScreen> #include <QSplashScreen>
#include <QTimer> #include <QTimer>
#ifdef Q_OS_WIN
#include <QOperatingSystemVersion>
#endif
#ifdef QBT_STATIC_QT #ifdef QBT_STATIC_QT
#include <QtPlugin> #include <QtPlugin>
Q_IMPORT_PLUGIN(QICOPlugin) Q_IMPORT_PLUGIN(QICOPlugin)
@ -189,11 +185,6 @@ int main(int argc, char *argv[])
// We must save it here because QApplication constructor may change it // We must save it here because QApplication constructor may change it
const bool isOneArg = (argc == 2); const bool isOneArg = (argc == 2);
#if !defined(DISABLE_GUI) && defined(Q_OS_WIN)
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
QApplication::setStyle(u"Fusion"_s);
#endif
// `app` must be declared out of try block to allow display message box in case of exception // `app` must be declared out of try block to allow display message box in case of exception
std::unique_ptr<Application> app; std::unique_ptr<Application> app;
try try

View file

@ -429,6 +429,19 @@ void Preferences::setWinStartup(const bool b)
settings.remove(profileID); settings.remove(profileID);
} }
} }
QString Preferences::getStyle() const
{
return value<QString>(u"Appearance/Style"_s);
}
void Preferences::setStyle(const QString &styleName)
{
if (styleName == getStyle())
return;
setValue(u"Appearance/Style"_s, styleName);
}
#endif // Q_OS_WIN #endif // Q_OS_WIN
// Downloads // Downloads

View file

@ -130,6 +130,8 @@ public:
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
bool WinStartup() const; bool WinStartup() const;
void setWinStartup(bool b); void setWinStartup(bool b);
QString getStyle() const;
void setStyle(const QString &styleName);
#endif #endif
// Downloads // Downloads

View file

@ -44,6 +44,10 @@
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QTranslator> #include <QTranslator>
#ifdef Q_OS_WIN
#include <QStyleFactory>
#endif
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/sharelimitaction.h" #include "base/bittorrent/sharelimitaction.h"
#include "base/exceptions.h" #include "base/exceptions.h"
@ -236,6 +240,8 @@ void OptionsDialog::loadBehaviorTabOptions()
initializeLanguageCombo(); initializeLanguageCombo();
setLocale(pref->getLocale()); setLocale(pref->getLocale());
initializeStyleCombo();
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());
m_ui->customThemeFilePath->setMode(FileSystemPathEdit::Mode::FileOpen); m_ui->customThemeFilePath->setMode(FileSystemPathEdit::Mode::FileOpen);
@ -345,7 +351,11 @@ void OptionsDialog::loadBehaviorTabOptions()
m_ui->checkBoxPerformanceWarning->setChecked(session->isPerformanceWarningEnabled()); m_ui->checkBoxPerformanceWarning->setChecked(session->isPerformanceWarningEnabled());
connect(m_ui->comboI18n, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboLanguage, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
#ifdef Q_OS_WIN
connect(m_ui->comboStyle, 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);
@ -443,6 +453,10 @@ void OptionsDialog::saveBehaviorTabOptions() const
} }
pref->setLocale(locale); pref->setLocale(locale);
#ifdef Q_OS_WIN
pref->setStyle(m_ui->comboStyle->currentText());
#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
@ -1385,7 +1399,7 @@ void OptionsDialog::initializeLanguageCombo()
for (const QString &langFile : langFiles) for (const QString &langFile : langFiles)
{ {
const QString langCode = QStringView(langFile).sliced(12).chopped(3).toString(); // remove "qbittorrent_" and ".qm" const QString langCode = QStringView(langFile).sliced(12).chopped(3).toString(); // remove "qbittorrent_" and ".qm"
m_ui->comboI18n->addItem(Utils::Misc::languageToLocalizedString(langCode), langCode); m_ui->comboLanguage->addItem(Utils::Misc::languageToLocalizedString(langCode), langCode);
} }
} }
@ -1670,6 +1684,30 @@ bool OptionsDialog::isSplashScreenDisabled() const
return !m_ui->checkShowSplash->isChecked(); return !m_ui->checkShowSplash->isChecked();
} }
void OptionsDialog::initializeStyleCombo()
{
#ifdef Q_OS_WIN
const QString prefStyleName = Preferences::instance()->getStyle();
const QString selectedStyleName = prefStyleName.isEmpty() ? QApplication::style()->name() : prefStyleName;
QStringList styleNames = QStyleFactory::keys();
for (qsizetype i = 1, stylesCount = styleNames.size(); i < stylesCount; ++i)
{
if (selectedStyleName.compare(styleNames.at(i), Qt::CaseInsensitive) == 0)
{
styleNames.swapItemsAt(0, i);
break;
}
}
m_ui->comboStyle->addItems(styleNames);
#else
m_ui->labelStyle->hide();
m_ui->comboStyle->hide();
m_ui->UISettingsBoxLayout->removeWidget(m_ui->labelStyle);
m_ui->UISettingsBoxLayout->removeWidget(m_ui->comboStyle);
m_ui->UISettingsBoxLayout->removeItem(m_ui->spacerStyle);
#endif
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
bool OptionsDialog::WinStartup() const bool OptionsDialog::WinStartup() const
{ {
@ -1719,7 +1757,7 @@ QString OptionsDialog::getProxyPassword() const
// Locale Settings // Locale Settings
QString OptionsDialog::getLocale() const QString OptionsDialog::getLocale() const
{ {
return m_ui->comboI18n->itemData(m_ui->comboI18n->currentIndex(), Qt::UserRole).toString(); return m_ui->comboLanguage->itemData(m_ui->comboLanguage->currentIndex(), Qt::UserRole).toString();
} }
void OptionsDialog::setLocale(const QString &localeStr) void OptionsDialog::setLocale(const QString &localeStr)
@ -1744,7 +1782,7 @@ void OptionsDialog::setLocale(const QString &localeStr)
name = locale.name(); name = locale.name();
} }
// Attempt to find exact match // Attempt to find exact match
int index = m_ui->comboI18n->findData(name, Qt::UserRole); int index = m_ui->comboLanguage->findData(name, Qt::UserRole);
if (index < 0) if (index < 0)
{ {
//Attempt to find a language match without a country //Attempt to find a language match without a country
@ -1752,16 +1790,16 @@ void OptionsDialog::setLocale(const QString &localeStr)
if (pos > -1) if (pos > -1)
{ {
QString lang = name.left(pos); QString lang = name.left(pos);
index = m_ui->comboI18n->findData(lang, Qt::UserRole); index = m_ui->comboLanguage->findData(lang, Qt::UserRole);
} }
} }
if (index < 0) if (index < 0)
{ {
// Unrecognized, use US English // Unrecognized, use US English
index = m_ui->comboI18n->findData(u"en"_s, Qt::UserRole); index = m_ui->comboLanguage->findData(u"en"_s, Qt::UserRole);
Q_ASSERT(index >= 0); Q_ASSERT(index >= 0);
} }
m_ui->comboI18n->setCurrentIndex(index); m_ui->comboLanguage->setCurrentIndex(index);
} }
Path OptionsDialog::getTorrentExportDir() const Path OptionsDialog::getTorrentExportDir() const

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2023-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -143,6 +143,7 @@ private:
// General options // General options
void initializeLanguageCombo(); void initializeLanguageCombo();
void initializeStyleCombo();
QString getLocale() const; QString getLocale() const;
bool isSplashScreenDisabled() const; bool isSplashScreenDisabled() const;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View file

@ -132,9 +132,9 @@
<property name="title"> <property name="title">
<string>Interface</string> <string>Interface</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_81"> <layout class="QGridLayout" name="UISettingsBoxLayout">
<item row="0" column="0" colspan="3"> <item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_15"> <widget class="QLabel" name="labelRestartRequired">
<property name="font"> <property name="font">
<font> <font>
<italic>true</italic> <italic>true</italic>
@ -146,17 +146,17 @@
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="labelLanguage">
<property name="text"> <property name="text">
<string>Language:</string> <string>Language:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QComboBox" name="comboI18n"/> <widget class="QComboBox" name="comboLanguage"/>
</item> </item>
<item row="1" column="2"> <item row="1" column="2">
<spacer name="horizontalSpacer_111"> <spacer name="spacerLanguage">
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Horizontal</enum> <enum>Qt::Orientation::Horizontal</enum>
</property> </property>
@ -168,7 +168,30 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="2" column="0" colspan="3"> <item row="2" column="0">
<widget class="QLabel" name="labelStyle">
<property name="text">
<string>Style:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboStyle"/>
</item>
<item row="2" column="2">
<spacer name="spacerStyle">
<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="3" 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>
@ -190,14 +213,14 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="4" 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="4" column="0" colspan="2"> <item row="5" 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>
@ -3921,7 +3944,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
<tabstops> <tabstops>
<tabstop>tabOption</tabstop> <tabstop>tabOption</tabstop>
<tabstop>tabSelection</tabstop> <tabstop>tabSelection</tabstop>
<tabstop>comboI18n</tabstop> <tabstop>comboLanguage</tabstop>
<tabstop>checkUseCustomTheme</tabstop> <tabstop>checkUseCustomTheme</tabstop>
<tabstop>customThemeFilePath</tabstop> <tabstop>customThemeFilePath</tabstop>
<tabstop>checkUseSystemIcon</tabstop> <tabstop>checkUseSystemIcon</tabstop>

View file

@ -37,6 +37,10 @@
#include <QStyle> #include <QStyle>
#include <QStyleHints> #include <QStyleHints>
#ifdef Q_OS_WIN
#include <QOperatingSystemVersion>
#endif
#include "base/global.h" #include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/path.h" #include "base/path.h"
@ -80,6 +84,12 @@ UIThemeManager::UIThemeManager()
, m_useSystemIcons {Preferences::instance()->useSystemIcons()} , m_useSystemIcons {Preferences::instance()->useSystemIcons()}
#endif #endif
{ {
#ifdef Q_OS_WIN
const QString defaultStyle = (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) ? u"Fusion"_s : QString();
if (const QString styleName = Preferences::instance()->getStyle(); !QApplication::setStyle(styleName.isEmpty() ? defaultStyle : styleName))
LogMsg(tr("Set app style failed. Unknown style: \"%1\"").arg(styleName), Log::WARNING);
#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);