Refresh custom colors once color scheme is changed

PR #20588.
This commit is contained in:
Vladimir Golovnev 2024-03-23 11:32:07 +03:00 committed by GitHub
parent 25b7972f88
commit ce013f132f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 195 additions and 126 deletions

View file

@ -1,5 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2020 Prince Gupta <jagannatharjun11@gmail.com> * Copyright (C) 2020 Prince Gupta <jagannatharjun11@gmail.com>
* Copyright (C) 2019 sledgehammer999 <hammered999@gmail.com> * Copyright (C) 2019 sledgehammer999 <hammered999@gmail.com>
* *
@ -36,65 +37,26 @@
#include "base/global.h" #include "base/global.h"
#include "gui/uithememanager.h" #include "gui/uithememanager.h"
namespace const int MAX_VISIBLE_MESSAGES = 20000;
{
const int MAX_VISIBLE_MESSAGES = 20000;
QColor getTimestampColor() BaseLogModel::Message::Message(const QString &time, const QString &message, const Log::MsgType type)
{ : m_time {time}
return UIThemeManager::instance()->getColor(u"Log.TimeStamp"_s); , m_message {message}
} , m_type {type}
QColor getLogNormalColor()
{
return UIThemeManager::instance()->getColor(u"Log.Normal"_s);
}
QColor getLogInfoColor()
{
return UIThemeManager::instance()->getColor(u"Log.Info"_s);
}
QColor getLogWarningColor()
{
return UIThemeManager::instance()->getColor(u"Log.Warning"_s);
}
QColor getLogCriticalColor()
{
return UIThemeManager::instance()->getColor(u"Log.Critical"_s);
}
QColor getPeerBannedColor()
{
return UIThemeManager::instance()->getColor(u"Log.BannedPeer"_s);
}
}
BaseLogModel::Message::Message(const QString &time, const QString &message, const QColor &foreground, const Log::MsgType type)
: m_time(time)
, m_message(message)
, m_foreground(foreground)
, m_type(type)
{ {
} }
QVariant BaseLogModel::Message::time() const QString BaseLogModel::Message::time() const
{ {
return m_time; return m_time;
} }
QVariant BaseLogModel::Message::message() const QString BaseLogModel::Message::message() const
{ {
return m_message; return m_message;
} }
QVariant BaseLogModel::Message::foreground() const Log::MsgType BaseLogModel::Message::type() const
{
return m_foreground;
}
QVariant BaseLogModel::Message::type() const
{ {
return m_type; return m_type;
} }
@ -102,8 +64,9 @@ QVariant BaseLogModel::Message::type() const
BaseLogModel::BaseLogModel(QObject *parent) BaseLogModel::BaseLogModel(QObject *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
, m_messages(MAX_VISIBLE_MESSAGES) , m_messages(MAX_VISIBLE_MESSAGES)
, m_timeForeground(getTimestampColor())
{ {
loadColors();
connect(UIThemeManager::instance(), &UIThemeManager::themeChanged, this, &BaseLogModel::onUIThemeChanged);
} }
int BaseLogModel::rowCount(const QModelIndex &) const int BaseLogModel::rowCount(const QModelIndex &) const
@ -135,7 +98,7 @@ QVariant BaseLogModel::data(const QModelIndex &index, const int role) const
case TimeForegroundRole: case TimeForegroundRole:
return m_timeForeground; return m_timeForeground;
case MessageForegroundRole: case MessageForegroundRole:
return message.foreground(); return messageForeground(message);
case TypeRole: case TypeRole:
return message.type(); return message.type();
default: default:
@ -160,6 +123,17 @@ void BaseLogModel::addNewMessage(const BaseLogModel::Message &message)
endInsertRows(); endInsertRows();
} }
void BaseLogModel::onUIThemeChanged()
{
loadColors();
emit dataChanged(index(0, 0), index((rowCount() - 1), (columnCount() - 1)), {TimeForegroundRole, MessageForegroundRole});
}
void BaseLogModel::loadColors()
{
m_timeForeground = UIThemeManager::instance()->getColor(u"Log.TimeStamp"_s);
}
void BaseLogModel::reset() void BaseLogModel::reset()
{ {
beginResetModel(); beginResetModel();
@ -169,14 +143,9 @@ void BaseLogModel::reset()
LogMessageModel::LogMessageModel(QObject *parent) LogMessageModel::LogMessageModel(QObject *parent)
: BaseLogModel(parent) : BaseLogModel(parent)
, m_foregroundForMessageTypes
{
{Log::NORMAL, getLogNormalColor()},
{Log::INFO, getLogInfoColor()},
{Log::WARNING, getLogWarningColor()},
{Log::CRITICAL, getLogCriticalColor()}
}
{ {
loadColors();
for (const Log::Msg &msg : asConst(Logger::instance()->getMessages())) for (const Log::Msg &msg : asConst(Logger::instance()->getMessages()))
handleNewMessage(msg); handleNewMessage(msg);
connect(Logger::instance(), &Logger::newLogMessage, this, &LogMessageModel::handleNewMessage); connect(Logger::instance(), &Logger::newLogMessage, this, &LogMessageModel::handleNewMessage);
@ -185,16 +154,38 @@ LogMessageModel::LogMessageModel(QObject *parent)
void LogMessageModel::handleNewMessage(const Log::Msg &message) void LogMessageModel::handleNewMessage(const Log::Msg &message)
{ {
const QString time = QLocale::system().toString(QDateTime::fromSecsSinceEpoch(message.timestamp), QLocale::ShortFormat); const QString time = QLocale::system().toString(QDateTime::fromSecsSinceEpoch(message.timestamp), QLocale::ShortFormat);
const QString messageText = message.message; addNewMessage({time, message.message, message.type});
const QColor foreground = m_foregroundForMessageTypes[message.type]; }
addNewMessage({time, messageText, foreground, message.type}); QColor LogMessageModel::messageForeground(const Message &message) const
{
return m_foregroundForMessageTypes.value(message.type());
}
void LogMessageModel::onUIThemeChanged()
{
loadColors();
BaseLogModel::onUIThemeChanged();
}
void LogMessageModel::loadColors()
{
const auto *themeManager = UIThemeManager::instance();
const QColor normalColor = themeManager->getColor(u"Log.Normal"_s);
m_foregroundForMessageTypes =
{
{Log::NORMAL, normalColor.isValid() ? normalColor : QApplication::palette().color(QPalette::Active, QPalette::WindowText)},
{Log::INFO, themeManager->getColor(u"Log.Info"_s)},
{Log::WARNING, themeManager->getColor(u"Log.Warning"_s)},
{Log::CRITICAL, themeManager->getColor(u"Log.Critical"_s)}
};
} }
LogPeerModel::LogPeerModel(QObject *parent) LogPeerModel::LogPeerModel(QObject *parent)
: BaseLogModel(parent) : BaseLogModel(parent)
, m_bannedPeerForeground(getPeerBannedColor())
{ {
loadColors();
for (const Log::Peer &peer : asConst(Logger::instance()->getPeers())) for (const Log::Peer &peer : asConst(Logger::instance()->getPeers()))
handleNewMessage(peer); handleNewMessage(peer);
connect(Logger::instance(), &Logger::newLogPeer, this, &LogPeerModel::handleNewMessage); connect(Logger::instance(), &Logger::newLogPeer, this, &LogPeerModel::handleNewMessage);
@ -207,5 +198,21 @@ void LogPeerModel::handleNewMessage(const Log::Peer &peer)
? tr("%1 was blocked. Reason: %2.", "0.0.0.0 was blocked. Reason: reason for blocking.").arg(peer.ip, peer.reason) ? tr("%1 was blocked. Reason: %2.", "0.0.0.0 was blocked. Reason: reason for blocking.").arg(peer.ip, peer.reason)
: tr("%1 was banned", "0.0.0.0 was banned").arg(peer.ip); : tr("%1 was banned", "0.0.0.0 was banned").arg(peer.ip);
addNewMessage({time, message, m_bannedPeerForeground, Log::NORMAL}); addNewMessage({time, message, Log::NORMAL});
}
QColor LogPeerModel::messageForeground([[maybe_unused]] const Message &message) const
{
return m_bannedPeerForeground;
}
void LogPeerModel::onUIThemeChanged()
{
loadColors();
BaseLogModel::onUIThemeChanged();
}
void LogPeerModel::loadColors()
{
m_bannedPeerForeground = UIThemeManager::instance()->getColor(u"Log.BannedPeer"_s);
} }

View file

@ -1,5 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2020 Prince Gupta <jagannatharjun11@gmail.com> * Copyright (C) 2020 Prince Gupta <jagannatharjun11@gmail.com>
* Copyright (C) 2019 sledgehammer999 <hammered999@gmail.com> * Copyright (C) 2019 sledgehammer999 <hammered999@gmail.com>
* *
@ -62,25 +63,27 @@ protected:
class Message class Message
{ {
public: public:
Message(const QString &time, const QString &message, const QColor &foreground, Log::MsgType type); Message(const QString &time, const QString &message, Log::MsgType type);
QVariant time() const; QString time() const;
QVariant message() const; QString message() const;
QVariant foreground() const; Log::MsgType type() const;
QVariant type() const;
private: private:
QVariant m_time; QString m_time;
QVariant m_message; QString m_message;
QVariant m_foreground; Log::MsgType m_type;
QVariant m_type;
}; };
void addNewMessage(const Message &message); void addNewMessage(const Message &message);
virtual QColor messageForeground(const Message &message) const = 0;
virtual void onUIThemeChanged();
private: private:
void loadColors();
boost::circular_buffer_space_optimized<Message> m_messages; boost::circular_buffer_space_optimized<Message> m_messages;
const QColor m_timeForeground; QColor m_timeForeground;
}; };
class LogMessageModel : public BaseLogModel class LogMessageModel : public BaseLogModel
@ -95,7 +98,11 @@ private slots:
void handleNewMessage(const Log::Msg &message); void handleNewMessage(const Log::Msg &message);
private: private:
const QHash<int, QColor> m_foregroundForMessageTypes; QColor messageForeground(const Message &message) const override;
void onUIThemeChanged() override;
void loadColors();
QHash<int, QColor> m_foregroundForMessageTypes;
}; };
class LogPeerModel : public BaseLogModel class LogPeerModel : public BaseLogModel
@ -110,5 +117,9 @@ private slots:
void handleNewMessage(const Log::Peer &peer); void handleNewMessage(const Log::Peer &peer);
private: private:
const QColor m_bannedPeerForeground; QColor messageForeground(const Message &message) const override;
void onUIThemeChanged() override;
void loadColors();
QColor m_bannedPeerForeground;
}; };

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2017-2024 Vladimir Golovnev <glassez@yandex.ru>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -28,6 +28,7 @@
#include "articlelistwidget.h" #include "articlelistwidget.h"
#include <QApplication>
#include <QListWidgetItem> #include <QListWidgetItem>
#include "base/global.h" #include "base/global.h"
@ -42,6 +43,12 @@ ArticleListWidget::ArticleListWidget(QWidget *parent)
setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionMode(QAbstractItemView::ExtendedSelection);
checkInvariant(); checkInvariant();
connect(UIThemeManager::instance(), &UIThemeManager::themeChanged, this, [this]
{
for (int row = 0; row < count(); ++row)
applyUITheme(item(row));
});
} }
RSS::Article *ArticleListWidget::getRSSArticle(QListWidgetItem *item) const RSS::Article *ArticleListWidget::getRSSArticle(QListWidgetItem *item) const
@ -100,11 +107,10 @@ void ArticleListWidget::handleArticleAdded(RSS::Article *rssArticle)
void ArticleListWidget::handleArticleRead(RSS::Article *rssArticle) void ArticleListWidget::handleArticleRead(RSS::Article *rssArticle)
{ {
auto *item = mapRSSArticle(rssArticle); auto *item = mapRSSArticle(rssArticle);
if (!item) return; if (!item)
return;
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.ReadArticle"_s)}; applyUITheme(item);
item->setData(Qt::ForegroundRole, foregroundBrush);
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"rss_read_article"_s, u"sphere"_s));
checkInvariant(); checkInvariant();
} }
@ -127,18 +133,25 @@ QListWidgetItem *ArticleListWidget::createItem(RSS::Article *article) const
item->setData(Qt::DisplayRole, article->title()); item->setData(Qt::DisplayRole, article->title());
item->setData(Qt::UserRole, QVariant::fromValue(article)); item->setData(Qt::UserRole, QVariant::fromValue(article));
if (article->isRead()) applyUITheme(item);
{
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.ReadArticle"_s)};
item->setData(Qt::ForegroundRole, foregroundBrush);
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"rss_read_article"_s, u"sphere"_s));
}
else
{
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.UnreadArticle"_s)};
item->setData(Qt::ForegroundRole, foregroundBrush);
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"rss_unread_article"_s, u"sphere"_s));
}
return item; return item;
} }
void ArticleListWidget::applyUITheme(QListWidgetItem *item) const
{
const bool isRead = getRSSArticle(item)->isRead();
const auto *themeManager = UIThemeManager::instance();
if (isRead)
{
const QColor color = themeManager->getColor(u"RSS.ReadArticle"_s);
item->setData(Qt::ForegroundRole, (color.isValid() ? color : QApplication::palette().color(QPalette::Inactive, QPalette::WindowText)));
item->setData(Qt::DecorationRole, themeManager->getIcon(u"rss_read_article"_s, u"sphere"_s));
}
else
{
const QColor color = themeManager->getColor(u"RSS.UnreadArticle"_s);
item->setData(Qt::ForegroundRole, (color.isValid() ? color : QApplication::palette().color(QPalette::Active, QPalette::Link)));
item->setData(Qt::DecorationRole, themeManager->getIcon(u"rss_unread_article"_s, u"sphere"_s));
}
}

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2017-2024 Vladimir Golovnev <glassez@yandex.ru>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -58,6 +58,7 @@ private slots:
private: private:
void checkInvariant() const; void checkInvariant() const;
QListWidgetItem *createItem(RSS::Article *article) const; QListWidgetItem *createItem(RSS::Article *article) const;
void applyUITheme(QListWidgetItem *item) const;
RSS::Item *m_rssItem = nullptr; RSS::Item *m_rssItem = nullptr;
bool m_unreadOnly = false; bool m_unreadOnly = false;

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2010 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
@ -112,21 +112,17 @@ TransferListModel::TransferListModel(QObject *parent)
{BitTorrent::TorrentState::MissingFiles, tr("Missing Files")}, {BitTorrent::TorrentState::MissingFiles, tr("Missing Files")},
{BitTorrent::TorrentState::Error, tr("Errored", "Torrent status, the torrent has an error")} {BitTorrent::TorrentState::Error, tr("Errored", "Torrent status, the torrent has an error")}
} }
, m_stateThemeColors {torrentStateColorsFromUITheme()}
, m_checkingIcon {UIThemeManager::instance()->getIcon(u"force-recheck"_s, u"checking"_s)}
, m_completedIcon {UIThemeManager::instance()->getIcon(u"checked-completed"_s, u"completed"_s)}
, m_downloadingIcon {UIThemeManager::instance()->getIcon(u"downloading"_s)}
, m_errorIcon {UIThemeManager::instance()->getIcon(u"error"_s)}
, m_movingIcon {UIThemeManager::instance()->getIcon(u"set-location"_s)}
, m_pausedIcon {UIThemeManager::instance()->getIcon(u"stopped"_s, u"media-playback-pause"_s)}
, m_queuedIcon {UIThemeManager::instance()->getIcon(u"queued"_s)}
, m_stalledDLIcon {UIThemeManager::instance()->getIcon(u"stalledDL"_s)}
, m_stalledUPIcon {UIThemeManager::instance()->getIcon(u"stalledUP"_s)}
, m_uploadingIcon {UIThemeManager::instance()->getIcon(u"upload"_s, u"uploading"_s)}
{ {
configure(); configure();
connect(Preferences::instance(), &Preferences::changed, this, &TransferListModel::configure); connect(Preferences::instance(), &Preferences::changed, this, &TransferListModel::configure);
loadUIThemeResources();
connect(UIThemeManager::instance(), &UIThemeManager::themeChanged, this, [this]
{
loadUIThemeResources();
emit dataChanged(index(0, 0), index((rowCount() - 1), (columnCount() - 1)), {Qt::DecorationRole, Qt::ForegroundRole});
});
// Load the torrents // Load the torrents
using namespace BitTorrent; using namespace BitTorrent;
addTorrents(Session::instance()->torrents()); addTorrents(Session::instance()->torrents());
@ -699,6 +695,23 @@ void TransferListModel::configure()
} }
} }
void TransferListModel::loadUIThemeResources()
{
m_stateThemeColors = torrentStateColorsFromUITheme();
const auto *themeManager = UIThemeManager::instance();
m_checkingIcon = themeManager->getIcon(u"force-recheck"_s, u"checking"_s);
m_completedIcon = themeManager->getIcon(u"checked-completed"_s, u"completed"_s);
m_downloadingIcon = themeManager->getIcon(u"downloading"_s);
m_errorIcon = themeManager->getIcon(u"error"_s);
m_movingIcon = themeManager->getIcon(u"set-location"_s);
m_pausedIcon = themeManager->getIcon(u"stopped"_s, u"media-playback-pause"_s);
m_queuedIcon = themeManager->getIcon(u"queued"_s);
m_stalledDLIcon = themeManager->getIcon(u"stalledDL"_s);
m_stalledUPIcon = themeManager->getIcon(u"stalledUP"_s);
m_uploadingIcon = themeManager->getIcon(u"upload"_s, u"uploading"_s);
}
QIcon TransferListModel::getIconByState(const BitTorrent::TorrentState state) const QIcon TransferListModel::getIconByState(const BitTorrent::TorrentState state) const
{ {
switch (state) switch (state)

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2010 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
@ -114,6 +114,7 @@ private slots:
private: private:
void configure(); void configure();
void loadUIThemeResources();
QString displayValue(const BitTorrent::Torrent *torrent, int column) const; QString displayValue(const BitTorrent::Torrent *torrent, int column) const;
QVariant internalValue(const BitTorrent::Torrent *torrent, int column, bool alt) const; QVariant internalValue(const BitTorrent::Torrent *torrent, int column, bool alt) const;
QIcon getIconByState(BitTorrent::TorrentState state) const; QIcon getIconByState(BitTorrent::TorrentState state) const;
@ -122,7 +123,7 @@ private:
QHash<BitTorrent::Torrent *, int> m_torrentMap; // maps torrent handle to row number QHash<BitTorrent::Torrent *, int> m_torrentMap; // maps torrent handle to row number
const QHash<BitTorrent::TorrentState, QString> m_statusStrings; const QHash<BitTorrent::TorrentState, QString> m_statusStrings;
// row text colors // row text colors
const QHash<BitTorrent::TorrentState, QColor> m_stateThemeColors; QHash<BitTorrent::TorrentState, QColor> m_stateThemeColors;
enum class HideZeroValuesMode enum class HideZeroValuesMode
{ {

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>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -29,7 +29,6 @@
#pragma once #pragma once
#include <QApplication>
#include <QColor> #include <QColor>
#include <QHash> #include <QHash>
#include <QPalette> #include <QPalette>
@ -53,17 +52,16 @@ struct UIThemeColor
inline QHash<QString, UIThemeColor> defaultUIThemeColors() inline QHash<QString, UIThemeColor> defaultUIThemeColors()
{ {
const QPalette palette = QApplication::palette();
return { return {
{u"Log.TimeStamp"_s, {Color::Primer::Light::fgSubtle, Color::Primer::Dark::fgSubtle}}, {u"Log.TimeStamp"_s, {Color::Primer::Light::fgSubtle, Color::Primer::Dark::fgSubtle}},
{u"Log.Normal"_s, {palette.color(QPalette::Active, QPalette::WindowText), palette.color(QPalette::Active, QPalette::WindowText)}}, {u"Log.Normal"_s, {{}, {}}},
{u"Log.Info"_s, {Color::Primer::Light::accentFg, Color::Primer::Dark::accentFg}}, {u"Log.Info"_s, {Color::Primer::Light::accentFg, Color::Primer::Dark::accentFg}},
{u"Log.Warning"_s, {Color::Primer::Light::severeFg, Color::Primer::Dark::severeFg}}, {u"Log.Warning"_s, {Color::Primer::Light::severeFg, Color::Primer::Dark::severeFg}},
{u"Log.Critical"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}}, {u"Log.Critical"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}},
{u"Log.BannedPeer"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}}, {u"Log.BannedPeer"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}},
{u"RSS.ReadArticle"_s, {palette.color(QPalette::Inactive, QPalette::WindowText), palette.color(QPalette::Inactive, QPalette::WindowText)}}, {u"RSS.ReadArticle"_s, {{}, {}}},
{u"RSS.UnreadArticle"_s, {palette.color(QPalette::Active, QPalette::Link), palette.color(QPalette::Active, QPalette::Link)}}, {u"RSS.UnreadArticle"_s, {{}, {}}},
{u"TransferList.Downloading"_s, {Color::Primer::Light::successFg, Color::Primer::Dark::successFg}}, {u"TransferList.Downloading"_s, {Color::Primer::Light::successFg, Color::Primer::Dark::successFg}},
{u"TransferList.StalledDownloading"_s, {Color::Primer::Light::successEmphasis, Color::Primer::Dark::successEmphasis}}, {u"TransferList.StalledDownloading"_s, {Color::Primer::Light::successEmphasis, Color::Primer::Dark::successEmphasis}},

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>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -64,21 +64,23 @@ namespace
} }
} }
class ColorWidget final : public QFrame class ColorWidget final : public QLabel
{ {
Q_DISABLE_COPY_MOVE(ColorWidget) Q_DISABLE_COPY_MOVE(ColorWidget)
Q_DECLARE_TR_FUNCTIONS(ColorWidget) Q_DECLARE_TR_FUNCTIONS(ColorWidget)
public: public:
explicit ColorWidget(const QColor &currentColor, const QColor &defaultColor, QWidget *parent = nullptr) explicit ColorWidget(const QColor &currentColor, const QColor &defaultColor, QWidget *parent = nullptr)
: QFrame(parent) : QLabel(parent)
, m_defaultColor {defaultColor} , m_defaultColor {defaultColor}
, m_currentColor {currentColor}
{ {
setObjectName(u"colorWidget"_s); setObjectName(u"colorWidget"_s);
setFrameShape(QFrame::Box); setFrameShape(QFrame::Box);
setFrameShadow(QFrame::Plain); setFrameShadow(QFrame::Plain);
setAlignment(Qt::AlignCenter);
setCurrentColor(currentColor); applyColor(currentColor);
} }
QColor currentColor() const QColor currentColor() const
@ -118,8 +120,17 @@ private:
} }
void applyColor(const QColor &color) void applyColor(const QColor &color)
{
if (color.isValid())
{ {
setStyleSheet(u"#colorWidget { background-color: %1; }"_s.arg(color.name())); setStyleSheet(u"#colorWidget { background-color: %1; }"_s.arg(color.name()));
setText({});
}
else
{
setStyleSheet({});
setText(tr("System"));
}
} }
void showColorDialog() void showColorDialog()
@ -262,6 +273,8 @@ void UIThemeDialog::loadColors()
int row = 2; int row = 2;
for (const QString &id : colorIDs) for (const QString &id : colorIDs)
{ {
if (id == u"Log.Normal")
qDebug() << "!!!!!!!";
m_ui->colorsLayout->addWidget(new QLabel(id), row, 0); m_ui->colorsLayout->addWidget(new QLabel(id), row, 0);
const UIThemeColor &defaultColor = defaultColors.value(id); const UIThemeColor &defaultColor = defaultColors.value(id);

View file

@ -30,6 +30,7 @@
#include "uithememanager.h" #include "uithememanager.h"
#include <QApplication>
#include <QPalette> #include <QPalette>
#include <QPixmapCache> #include <QPixmapCache>
#include <QResource> #include <QResource>
@ -79,11 +80,8 @@ UIThemeManager::UIThemeManager()
, m_useSystemIcons {Preferences::instance()->useSystemIcons()} , m_useSystemIcons {Preferences::instance()->useSystemIcons()}
#endif #endif
{ {
connect(QApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, [] // 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);
// workaround to refresh styled controls once color scheme is changed
QApplication::setStyle(QApplication::style()->name());
});
if (m_useCustomTheme) if (m_useCustomTheme)
{ {
@ -122,6 +120,14 @@ void UIThemeManager::applyStyleSheet() const
qApp->setStyleSheet(QString::fromUtf8(m_themeSource->readStyleSheet())); qApp->setStyleSheet(QString::fromUtf8(m_themeSource->readStyleSheet()));
} }
void UIThemeManager::onColorSchemeChanged()
{
emit themeChanged();
// workaround to refresh styled controls once color scheme is changed
QApplication::setStyle(QApplication::style()->name());
}
QIcon UIThemeManager::getIcon(const QString &iconId, [[maybe_unused]] const QString &fallback) const QIcon UIThemeManager::getIcon(const QString &iconId, [[maybe_unused]] const QString &fallback) const
{ {
const auto colorMode = isDarkTheme() ? ColorMode::Dark : ColorMode::Light; const auto colorMode = isDarkTheme() ? ColorMode::Dark : ColorMode::Light;
@ -184,8 +190,6 @@ QPixmap UIThemeManager::getScaledPixmap(const QString &iconId, const int height)
QColor UIThemeManager::getColor(const QString &id) const QColor UIThemeManager::getColor(const QString &id) const
{ {
const QColor color = m_themeSource->getColor(id, (isDarkTheme() ? ColorMode::Dark : ColorMode::Light)); const QColor color = m_themeSource->getColor(id, (isDarkTheme() ? ColorMode::Dark : ColorMode::Light));
Q_ASSERT(color.isValid());
return color; return color;
} }

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) 2019 Prince Gupta <jagannatharjun11@gmail.com> * Copyright (C) 2019 Prince Gupta <jagannatharjun11@gmail.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -38,7 +38,6 @@
#include <QPixmap> #include <QPixmap>
#include <QString> #include <QString>
#include "base/pathfwd.h"
#include "uithemesource.h" #include "uithemesource.h"
class UIThemeManager final : public QObject class UIThemeManager final : public QObject
@ -57,11 +56,15 @@ public:
QColor getColor(const QString &id) const; QColor getColor(const QString &id) const;
signals:
void themeChanged();
private: private:
UIThemeManager(); // singleton class UIThemeManager(); // singleton class
void applyPalette() const; void applyPalette() const;
void applyStyleSheet() const; void applyStyleSheet() const;
void onColorSchemeChanged();
static UIThemeManager *m_instance; static UIThemeManager *m_instance;
const bool m_useCustomTheme; const bool m_useCustomTheme;

View file

@ -114,8 +114,13 @@ QByteArray DefaultThemeSource::readStyleSheet()
QColor DefaultThemeSource::getColor(const QString &colorId, const ColorMode colorMode) const QColor DefaultThemeSource::getColor(const QString &colorId, const ColorMode colorMode) const
{ {
const auto iter = m_colors.constFind(colorId);
Q_ASSERT(iter != m_colors.constEnd());
if (iter == m_colors.constEnd()) [[unlikely]]
return {};
return (colorMode == ColorMode::Light) return (colorMode == ColorMode::Light)
? m_colors.value(colorId).light : m_colors.value(colorId).dark; ? iter.value().light : iter.value().dark;
} }
Path DefaultThemeSource::getIconPath(const QString &iconId, const ColorMode colorMode) const Path DefaultThemeSource::getIconPath(const QString &iconId, const ColorMode colorMode) const