qBittorrent
UIThemeManager Class Reference

#include <uithememanager.h>

Inheritance diagram for UIThemeManager:
Collaboration diagram for UIThemeManager:

Public Member Functions

QString getIconPath (const QString &iconId) const
 
QIcon getIcon (const QString &iconId, const QString &fallback={}) const
 
QIcon getFlagIcon (const QString &countryIsoCode) const
 
QColor getColor (const QString &id, const QColor &defaultColor) const
 
QIcon getSystrayIcon () const
 

Static Public Member Functions

static void initInstance ()
 
static void freeInstance ()
 
static UIThemeManagerinstance ()
 

Private Member Functions

 UIThemeManager ()
 
QString getIconPathFromResources (const QString &iconId, const QString &fallback={}) const
 
void loadColorsFromJSONConfig ()
 
void applyPalette () const
 
void applyStyleSheet () const
 

Private Attributes

const bool m_useCustomTheme
 
std::unique_ptr< UIThemeSourcem_themeSource
 
QHash< QString, QColor > m_colors
 
QHash< QString, QIcon > m_iconCache
 
QHash< QString, QIcon > m_flagCache
 

Static Private Attributes

static UIThemeManagerm_instance = nullptr
 

Detailed Description

Definition at line 49 of file uithememanager.h.

Constructor & Destructor Documentation

◆ UIThemeManager()

UIThemeManager::UIThemeManager ( )
private

Definition at line 169 of file uithememanager.cpp.

170  : m_useCustomTheme(Preferences::instance()->useCustomUITheme())
171 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
172  , m_useSystemTheme(Preferences::instance()->useSystemIconTheme())
173 #endif
174 {
175  if (m_useCustomTheme)
176  {
177  const QString themePath = Preferences::instance()->customUIThemePath();
178  m_themeSource = createUIThemeSource(themePath);
179  if (!m_themeSource)
180  {
181  LogMsg(tr("Failed to load UI theme from file: \"%1\"").arg(themePath), Log::WARNING);
182  }
183  else
184  {
186  applyPalette();
187  applyStyleSheet();
188  }
189  }
190 }
static Preferences * instance()
QString customUIThemePath() const
void applyPalette() const
std::unique_ptr< UIThemeSource > m_themeSource
void applyStyleSheet() const
const bool m_useCustomTheme
void loadColorsFromJSONConfig()
void LogMsg(const QString &message, const Log::MsgType &type)
Definition: logger.cpp:125
@ WARNING
Definition: logger.h:47
std::unique_ptr< UIThemeSource > createUIThemeSource(const QString &themePath)

References applyPalette(), applyStyleSheet(), anonymous_namespace{uithememanager.cpp}::createUIThemeSource(), Preferences::customUIThemePath(), Preferences::instance(), loadColorsFromJSONConfig(), LogMsg(), m_themeSource, m_useCustomTheme, and Log::WARNING.

Referenced by initInstance().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Function Documentation

◆ applyPalette()

void UIThemeManager::applyPalette ( ) const
private

Definition at line 346 of file uithememanager.cpp.

347 {
348  struct ColorDescriptor
349  {
350  QString id;
351  QPalette::ColorRole colorRole;
352  QPalette::ColorGroup colorGroup;
353  };
354 
355  const ColorDescriptor paletteColorDescriptors[] =
356  {
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}
382  };
383 
384  QPalette palette = qApp->palette();
385  for (const ColorDescriptor &colorDescriptor : paletteColorDescriptors)
386  {
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);
390  }
391  qApp->setPalette(palette);
392 }
QColor getColor(const QString &id, const QColor &defaultColor) const

References getColor().

Referenced by UIThemeManager().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ applyStyleSheet()

void UIThemeManager::applyStyleSheet ( ) const
private

Definition at line 197 of file uithememanager.cpp.

198 {
199  qApp->setStyleSheet(m_themeSource->readStyleSheet());
200 }

References m_themeSource.

Referenced by UIThemeManager().

Here is the caller graph for this function:

◆ freeInstance()

void UIThemeManager::freeInstance ( )
static

Definition at line 157 of file uithememanager.cpp.

158 {
159  delete m_instance;
160  m_instance = nullptr;
161 }
static UIThemeManager * m_instance

References m_instance.

Referenced by Application::cleanup().

Here is the caller graph for this function:

◆ getColor()

QColor UIThemeManager::getColor ( const QString &  id,
const QColor &  defaultColor 
) const

Definition at line 239 of file uithememanager.cpp.

240 {
241  return m_colors.value(id, defaultColor);
242 }
QHash< QString, QColor > m_colors

References m_colors.

Referenced by applyPalette(), ArticleListWidget::createItem(), ArticleListWidget::handleArticleRead(), LogMessageModel::LogMessageModel(), and anonymous_namespace{transferlistmodel.cpp}::torrentStateColorsFromUITheme().

Here is the caller graph for this function:

◆ getFlagIcon()

QIcon UIThemeManager::getFlagIcon ( const QString &  countryIsoCode) const

Definition at line 225 of file uithememanager.cpp.

226 {
227  if (countryIsoCode.isEmpty()) return {};
228 
229  const QString key = countryIsoCode.toLower();
230  const auto iter = m_flagCache.find(key);
231  if (iter != m_flagCache.end())
232  return *iter;
233 
234  const QIcon icon {QLatin1String(":/icons/flags/") + key + QLatin1String(".svg")};
235  m_flagCache[key] = icon;
236  return icon;
237 }
QHash< QString, QIcon > m_flagCache

References m_flagCache.

Referenced by PeerListWidget::updatePeer().

Here is the caller graph for this function:

◆ getIcon()

QIcon UIThemeManager::getIcon ( const QString &  iconId,
const QString &  fallback = {} 
) const

Definition at line 202 of file uithememanager.cpp.

203 {
204 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
205  if (m_useSystemTheme)
206  {
207  QIcon icon = QIcon::fromTheme(iconId);
208  if (icon.name() != iconId)
209  icon = QIcon::fromTheme(fallback, QIcon(getIconPathFromResources(iconId, fallback)));
210  return icon;
211  }
212 #endif
213 
214  // Cache to avoid rescaling svg icons
215  // And don't cache system icons because users might change them at run time
216  const auto iter = m_iconCache.find(iconId);
217  if (iter != m_iconCache.end())
218  return *iter;
219 
220  const QIcon icon {getIconPathFromResources(iconId, fallback)};
221  m_iconCache[iconId] = icon;
222  return icon;
223 }
QString getIconPathFromResources(const QString &iconId, const QString &fallback={}) const
QHash< QString, QIcon > m_iconCache

References getIconPathFromResources(), and m_iconCache.

Referenced by SearchJobWidget::contextMenuEvent(), FeedListWidget::createItem(), CategoryFilterModel::data(), TagFilterModel::data(), PropertiesWidget::displayFilesListMenu(), TransferListWidget::displayListMenu(), ExecutionLogWidget::ExecutionLogWidget(), getCheckingIcon(), getCompletedIcon(), getDownloadingIcon(), getErrorIcon(), getPausedIcon(), getQueuedIcon(), getStalledDownloadingIcon(), getStalledUploadingIcon(), getSystrayIcon(), getUploadingIcon(), anonymous_namespace{torrentcontentmodel.cpp}::UnifiedFileIconProvider::icon(), anonymous_namespace{feedlistwidget.cpp}::loadIcon(), anonymous_namespace{feedlistwidget.cpp}::rssFeedIcon(), and PeerListWidget::showPeerListMenu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getIconPath()

QString UIThemeManager::getIconPath ( const QString &  iconId) const

Definition at line 274 of file uithememanager.cpp.

275 {
276 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
277  if (m_useSystemTheme)
278  {
279  QString path = Utils::Fs::tempPath() + iconId + QLatin1String(".png");
280  if (!QFile::exists(path))
281  {
282  const QIcon icon = QIcon::fromTheme(iconId);
283  if (!icon.isNull())
284  icon.pixmap(32).save(path);
285  else
286  path = getIconPathFromResources(iconId);
287  }
288 
289  return path;
290  }
291 #endif
292  return getIconPathFromResources(iconId, {});
293 }
QString tempPath()
Definition: fs.cpp:314

References getIconPathFromResources(), and Utils::Fs::tempPath().

Here is the call graph for this function:

◆ getIconPathFromResources()

QString UIThemeManager::getIconPathFromResources ( const QString &  iconId,
const QString &  fallback = {} 
) const
private

Definition at line 295 of file uithememanager.cpp.

296 {
298  {
299  const QString customIcon = m_themeSource->iconPath(iconId);
300  if (!customIcon.isEmpty())
301  return customIcon;
302 
303  if (!fallback.isEmpty())
304  {
305  const QString fallbackIcon = m_themeSource->iconPath(fallback);
306  if (!fallbackIcon.isEmpty())
307  return fallbackIcon;
308  }
309  }
310 
311  return findIcon(iconId, DEFAULT_ICONS_DIR);
312 }
QString findIcon(const QString &iconId, const QString &dir)

References anonymous_namespace{uithememanager.cpp}::DEFAULT_ICONS_DIR, anonymous_namespace{uithememanager.cpp}::findIcon(), m_themeSource, and m_useCustomTheme.

Referenced by getIcon(), and getIconPath().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getSystrayIcon()

QIcon UIThemeManager::getSystrayIcon ( ) const

Definition at line 245 of file uithememanager.cpp.

246 {
248  switch (style)
249  {
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"));
257 #else
259  return getIcon(QLatin1String("qbittorrent-tray"));
261  return getIcon(QLatin1String("qbittorrent-tray-dark"));
263  return getIcon(QLatin1String("qbittorrent-tray-light"));
264 #endif
265  default:
266  break;
267  }
268 
269  // As a failsafe in case the enum is invalid
270  return getIcon(QLatin1String("qbittorrent-tray"));
271 }
TrayIcon::Style trayIconStyle() const
QIcon getIcon(const QString &iconId, const QString &fallback={}) const

References getIcon(), Preferences::instance(), TrayIcon::MonoDark, TrayIcon::MonoLight, TrayIcon::Normal, and Preferences::trayIconStyle().

Here is the call graph for this function:

◆ initInstance()

void UIThemeManager::initInstance ( )
static

Definition at line 163 of file uithememanager.cpp.

164 {
165  if (!m_instance)
167 }

References m_instance, and UIThemeManager().

Referenced by Application::exec().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ instance()

UIThemeManager * UIThemeManager::instance ( )
static

Definition at line 192 of file uithememanager.cpp.

193 {
194  return m_instance;
195 }

References m_instance.

Referenced by AboutDialog::AboutDialog(), AutomatedRssDownloader::addFeedArticlesToTree(), TrackerFiltersList::addItem(), AutomatedRssDownloader::AutomatedRssDownloader(), SearchJobWidget::contextMenuEvent(), CookiesDialog::CookiesDialog(), ArticleListWidget::createItem(), FeedListWidget::createItem(), MainWindow::createTrayIcon(), CategoryFilterModel::data(), TagFilterModel::data(), DeletionConfirmationDialog::DeletionConfirmationDialog(), AddNewTorrentDialog::displayContentTreeMenu(), ExecutionLogWidget::displayContextMenu(), PropertiesWidget::displayFilesListMenu(), TransferListWidget::displayListMenu(), MainWindow::displayRSSTab(), AutomatedRssDownloader::displayRulesListMenu(), MainWindow::displaySearchTab(), PropertiesWidget::displayWebSeedListMenu(), ExecutionLogWidget::ExecutionLogWidget(), FeedListWidget::FeedListWidget(), getCheckingIcon(), getCompletedIcon(), getDownloadingIcon(), getErrorIcon(), getPausedIcon(), getQueuedIcon(), getStalledDownloadingIcon(), getStalledUploadingIcon(), getUploadingIcon(), ArticleListWidget::handleArticleRead(), anonymous_namespace{torrentcontentmodel.cpp}::UnifiedFileIconProvider::icon(), LineEdit::LineEdit(), anonymous_namespace{feedlistwidget.cpp}::loadIcon(), MainWindow::loadPreferences(), LogMessageModel::LogMessageModel(), MainWindow::MainWindow(), MainWindow::on_actionExecutionLogs_triggered(), OptionsDialog::OptionsDialog(), PluginSelectDialog::PluginSelectDialog(), PropertiesWidget::PropertiesWidget(), PropTabBar::PropTabBar(), anonymous_namespace{feedlistwidget.cpp}::rssFeedIcon(), RSSWidget::RSSWidget(), SearchWidget::SearchWidget(), CategoryFilterWidget::showMenu(), TrackerFiltersList::showMenu(), TagFilterWidget::showMenu(), PeerListWidget::showPeerListMenu(), TrackerListWidget::showTrackerListMenu(), SpeedLimitDialog::SpeedLimitDialog(), StatusBar::StatusBar(), StatusFilterWidget::StatusFilterWidget(), SearchWidget::tabStatusChanged(), anonymous_namespace{transferlistmodel.cpp}::torrentStateColorsFromUITheme(), TrackerFiltersList::TrackerFiltersList(), TrackersAdditionDialog::TrackersAdditionDialog(), StatusBar::updateAltSpeedsBtn(), StatusBar::updateConnectionStatus(), AutomatedRssDownloader::updateEpisodeFilterValidity(), AutomatedRssDownloader::updateMustLineValidity(), AutomatedRssDownloader::updateMustNotLineValidity(), PeerListWidget::updatePeer(), OptionsDialog::webUIHttpsCertChanged(), and OptionsDialog::webUIHttpsKeyChanged().

◆ loadColorsFromJSONConfig()

void UIThemeManager::loadColorsFromJSONConfig ( )
private

Definition at line 314 of file uithememanager.cpp.

315 {
316  const QByteArray config = m_themeSource->readConfig();
317  if (config.isEmpty())
318  return;
319 
320  QJsonParseError jsonError;
321  const QJsonDocument configJsonDoc = QJsonDocument::fromJson(config, &jsonError);
322  if (jsonError.error != QJsonParseError::NoError)
323  {
324  LogMsg(tr("\"%1\" has invalid format. Reason: %2").arg(CONFIG_FILE_NAME, jsonError.errorString()), Log::WARNING);
325  return;
326  }
327  if (!configJsonDoc.isObject())
328  {
329  LogMsg(tr("\"%1\" has invalid format. Reason: %2").arg(CONFIG_FILE_NAME, tr("Root JSON value is not an object")), Log::WARNING);
330  return;
331  }
332 
333  const QJsonObject colors = configJsonDoc.object().value("colors").toObject();
334  for (auto color = colors.constBegin(); color != colors.constEnd(); ++color)
335  {
336  const QColor providedColor(color.value().toString());
337  if (!providedColor.isValid())
338  {
339  LogMsg(tr("Invalid color for ID \"%1\" is provided by theme").arg(color.key()), Log::WARNING);
340  continue;
341  }
342  m_colors.insert(color.key(), providedColor);
343  }
344 }

References anonymous_namespace{uithememanager.cpp}::CONFIG_FILE_NAME, LogMsg(), m_colors, m_themeSource, and Log::WARNING.

Referenced by UIThemeManager().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_colors

QHash<QString, QColor> UIThemeManager::m_colors
private

Definition at line 79 of file uithememanager.h.

Referenced by getColor(), and loadColorsFromJSONConfig().

◆ m_flagCache

QHash<QString, QIcon> UIThemeManager::m_flagCache
mutableprivate

Definition at line 81 of file uithememanager.h.

Referenced by getFlagIcon().

◆ m_iconCache

QHash<QString, QIcon> UIThemeManager::m_iconCache
mutableprivate

Definition at line 80 of file uithememanager.h.

Referenced by getIcon().

◆ m_instance

UIThemeManager * UIThemeManager::m_instance = nullptr
staticprivate

Definition at line 76 of file uithememanager.h.

Referenced by freeInstance(), initInstance(), and instance().

◆ m_themeSource

std::unique_ptr<UIThemeSource> UIThemeManager::m_themeSource
private

◆ m_useCustomTheme

const bool UIThemeManager::m_useCustomTheme
private

Definition at line 77 of file uithememanager.h.

Referenced by getIconPathFromResources(), and UIThemeManager().


The documentation for this class was generated from the following files: