32 #include <QApplication>
35 #include <QJsonDocument>
36 #include <QJsonObject>
57 QString
findIcon(
const QString &iconId,
const QString &dir)
59 const QString pathSvg = dir + iconId + QLatin1String(
".svg");
60 if (QFile::exists(pathSvg))
63 const QString pathPng = dir + iconId + QLatin1String(
".png");
64 if (QFile::exists(pathPng))
73 if (!
file.open(QIODevice::ReadOnly | QIODevice::Text))
75 LogMsg(UIThemeManager::tr(
"UITheme - Failed to open \"%1\". Reason: %2")
81 return file.readAll();
97 QString
iconPath(
const QString &iconId)
const override
99 return findIcon(iconId, m_qrcIconsDir);
103 const QString m_qrcThemeDir {
":/uitheme/"};
127 QString
iconPath(
const QString &iconId)
const override
129 return findIcon(iconId, m_iconsDir);
140 const QFileInfo themeInfo {themePath};
143 return std::make_unique<FolderThemeSource>(themeInfo.dir());
145 if ((themeInfo.suffix() == QLatin1String {
"qbtheme"})
146 && QResource::registerResource(themePath, QLatin1String {
"/uitheme"}))
148 return std::make_unique<QRCThemeSource>();
170 : m_useCustomTheme(
Preferences::instance()->useCustomUITheme())
171 #
if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
172 , m_useSystemTheme(
Preferences::instance()->useSystemIconTheme())
204 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
205 if (m_useSystemTheme)
207 QIcon icon = QIcon::fromTheme(iconId);
208 if (icon.name() != iconId)
227 if (countryIsoCode.isEmpty())
return {};
229 const QString key = countryIsoCode.toLower();
234 const QIcon icon {QLatin1String(
":/icons/flags/") + key + QLatin1String(
".svg")};
241 return m_colors.value(
id, defaultColor);
250 #if defined(Q_OS_UNIX)
252 return QIcon::fromTheme(QLatin1String(
"qbittorrent-tray"));
254 return QIcon::fromTheme(QLatin1String(
"qbittorrent-tray-dark"));
256 return QIcon::fromTheme(QLatin1String(
"qbittorrent-tray-light"));
259 return getIcon(QLatin1String(
"qbittorrent-tray"));
261 return getIcon(QLatin1String(
"qbittorrent-tray-dark"));
263 return getIcon(QLatin1String(
"qbittorrent-tray-light"));
270 return getIcon(QLatin1String(
"qbittorrent-tray"));
276 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
277 if (m_useSystemTheme)
280 if (!QFile::exists(path))
282 const QIcon icon = QIcon::fromTheme(iconId);
284 icon.pixmap(32).save(path);
300 if (!customIcon.isEmpty())
303 if (!fallback.isEmpty())
305 const QString fallbackIcon =
m_themeSource->iconPath(fallback);
306 if (!fallbackIcon.isEmpty())
317 if (config.isEmpty())
320 QJsonParseError jsonError;
321 const QJsonDocument configJsonDoc = QJsonDocument::fromJson(config, &jsonError);
322 if (jsonError.error != QJsonParseError::NoError)
327 if (!configJsonDoc.isObject())
333 const QJsonObject colors = configJsonDoc.object().value(
"colors").toObject();
334 for (
auto color = colors.constBegin(); color != colors.constEnd(); ++color)
336 const QColor providedColor(color.value().toString());
337 if (!providedColor.isValid())
339 LogMsg(tr(
"Invalid color for ID \"%1\" is provided by theme").arg(color.key()),
Log::WARNING);
342 m_colors.insert(color.key(), providedColor);
348 struct ColorDescriptor
351 QPalette::ColorRole colorRole;
352 QPalette::ColorGroup colorGroup;
355 const ColorDescriptor paletteColorDescriptors[] =
357 {QLatin1String(
"Palette.Window"), QPalette::Window, QPalette::Normal},
358 {QLatin1String(
"Palette.WindowText"), QPalette::WindowText, QPalette::Normal},
359 {QLatin1String(
"Palette.Base"), QPalette::Base, QPalette::Normal},
360 {QLatin1String(
"Palette.AlternateBase"), QPalette::AlternateBase, QPalette::Normal},
361 {QLatin1String(
"Palette.Text"), QPalette::Text, QPalette::Normal},
362 {QLatin1String(
"Palette.ToolTipBase"), QPalette::ToolTipBase, QPalette::Normal},
363 {QLatin1String(
"Palette.ToolTipText"), QPalette::ToolTipText, QPalette::Normal},
364 {QLatin1String(
"Palette.BrightText"), QPalette::BrightText, QPalette::Normal},
365 {QLatin1String(
"Palette.Highlight"), QPalette::Highlight, QPalette::Normal},
366 {QLatin1String(
"Palette.HighlightedText"), QPalette::HighlightedText, QPalette::Normal},
367 {QLatin1String(
"Palette.Button"), QPalette::Button, QPalette::Normal},
368 {QLatin1String(
"Palette.ButtonText"), QPalette::ButtonText, QPalette::Normal},
369 {QLatin1String(
"Palette.Link"), QPalette::Link, QPalette::Normal},
370 {QLatin1String(
"Palette.LinkVisited"), QPalette::LinkVisited, QPalette::Normal},
371 {QLatin1String(
"Palette.Light"), QPalette::Light, QPalette::Normal},
372 {QLatin1String(
"Palette.Midlight"), QPalette::Midlight, QPalette::Normal},
373 {QLatin1String(
"Palette.Mid"), QPalette::Mid, QPalette::Normal},
374 {QLatin1String(
"Palette.Dark"), QPalette::Dark, QPalette::Normal},
375 {QLatin1String(
"Palette.Shadow"), QPalette::Shadow, QPalette::Normal},
376 {QLatin1String(
"Palette.WindowTextDisabled"), QPalette::WindowText, QPalette::Disabled},
377 {QLatin1String(
"Palette.TextDisabled"), QPalette::Text, QPalette::Disabled},
378 {QLatin1String(
"Palette.ToolTipTextDisabled"), QPalette::ToolTipText, QPalette::Disabled},
379 {QLatin1String(
"Palette.BrightTextDisabled"), QPalette::BrightText, QPalette::Disabled},
380 {QLatin1String(
"Palette.HighlightedTextDisabled"), QPalette::HighlightedText, QPalette::Disabled},
381 {QLatin1String(
"Palette.ButtonTextDisabled"), QPalette::ButtonText, QPalette::Disabled}
384 QPalette palette = qApp->palette();
385 for (
const ColorDescriptor &colorDescriptor : paletteColorDescriptors)
387 const QColor defaultColor = palette.color(colorDescriptor.colorGroup, colorDescriptor.colorRole);
388 const QColor newColor =
getColor(colorDescriptor.id, defaultColor);
389 palette.setColor(colorDescriptor.colorGroup, colorDescriptor.colorRole, newColor);
391 qApp->setPalette(palette);
QBITTORRENT_HAS_EXECINFO_H if(NOT QBITTORRENT_HAS_EXECINFO_H) message(FATAL_ERROR "execinfo.h header file not found.\n" "Please either disable the STACKTRACE feature or use a libc that has this header file
static Preferences * instance()
QString customUIThemePath() const
TrayIcon::Style trayIconStyle() const
void applyPalette() const
QHash< QString, QIcon > m_flagCache
QString getIconPath(const QString &iconId) const
std::unique_ptr< UIThemeSource > m_themeSource
QString getIconPathFromResources(const QString &iconId, const QString &fallback={}) const
QIcon getSystrayIcon() const
static UIThemeManager * m_instance
static UIThemeManager * instance()
static void freeInstance()
QColor getColor(const QString &id, const QColor &defaultColor) const
QHash< QString, QColor > m_colors
void applyStyleSheet() const
static void initInstance()
QIcon getFlagIcon(const QString &countryIsoCode) const
QIcon getIcon(const QString &iconId, const QString &fallback={}) const
const bool m_useCustomTheme
void loadColorsFromJSONConfig()
QHash< QString, QIcon > m_iconCache
QByteArray readConfig() override
QString iconPath(const QString &iconId) const override
QByteArray readStyleSheet() override
FolderThemeSource(const QDir &dir)
QByteArray readConfig() override
QByteArray readStyleSheet() override
QString iconPath(const QString &iconId) const override
void LogMsg(const QString &message, const Log::MsgType &type)
QString fileName(const QString &filePath)
const QString STYLESHEET_FILE_NAME
const QString CONFIG_FILE_NAME
const QString DEFAULT_ICONS_DIR
const QString STYLESHEET_RESOURCES_DIR
QString findIcon(const QString &iconId, const QString &dir)
std::unique_ptr< UIThemeSource > createUIThemeSource(const QString &themePath)
QByteArray readFile(const QString &fileName)
const QString THEME_ICONS_DIR
file(GLOB QBT_TS_FILES "${qBittorrent_SOURCE_DIR}/src/lang/*.ts") set_source_files_properties($