Skip to content

Commit 866caf5

Browse files
Merge pull request mixxxdj#16661 from xARSENICx/fix-macos-preferences-theme-switch
Preferences: Fix macOS system theme switch rendering and icons
2 parents 73d9cf4 + c802d16 commit 866caf5

2 files changed

Lines changed: 95 additions & 26 deletions

File tree

src/preferences/dialog/dlgpreferences.cpp

Lines changed: 89 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
#include "preferences/dialog/dlgpreferences.h"
22

3+
#include <QApplication>
34
#include <QDialog>
45
#include <QEvent>
56
#include <QMoveEvent>
7+
#include <QPalette>
68
#include <QResizeEvent>
79
#include <QScreen>
810
#include <QScrollArea>
11+
#include <QSlider>
12+
#include <QStyle>
913
#include <QtGlobal>
1014

1115
#include "controllers/dlgprefcontrollers.h"
@@ -293,7 +297,7 @@ void DlgPreferences::changePage(QTreeWidgetItem* pCurrent, QTreeWidgetItem* pPre
293297
return;
294298
}
295299

296-
for (PreferencesPage page : std::as_const(m_allPages)) {
300+
for (const PreferencesPage& page : std::as_const(m_allPages)) {
297301
if (pCurrent == page.pTreeItem) {
298302
switchToPage(pCurrent->text(0), page.pDlg);
299303
break;
@@ -320,6 +324,61 @@ bool DlgPreferences::eventFilter(QObject* o, QEvent* e) {
320324
return QWidget::eventFilter(o, e);
321325
}
322326

327+
void DlgPreferences::changeEvent(QEvent* pEvent) {
328+
static bool s_inPaletteUpdate = false;
329+
if (s_inPaletteUpdate) {
330+
QDialog::changeEvent(pEvent);
331+
return;
332+
}
333+
334+
if (pEvent->type() == QEvent::PaletteChange ||
335+
pEvent->type() == QEvent::ApplicationPaletteChange ||
336+
pEvent->type() == QEvent::ThemeChange) {
337+
struct ResetFlag {
338+
bool& flag;
339+
explicit ResetFlag(bool& f)
340+
: flag(f) {
341+
flag = true;
342+
}
343+
~ResetFlag() {
344+
flag = false;
345+
}
346+
} resetFlag(s_inPaletteUpdate);
347+
348+
// Re-apply macOS system slider styles based on the current theme mode
349+
fixSliderStyle();
350+
351+
const QPalette appPalette = QApplication::palette();
352+
if (palette() != appPalette) {
353+
setPalette(appPalette);
354+
}
355+
// Update m_iconsPath based on the new palette's text color
356+
if (!Color::isDimColor(appPalette.text().color())) {
357+
m_iconsPath.setPath(":/images/preferences/light/");
358+
} else {
359+
m_iconsPath.setPath(":/images/preferences/dark/");
360+
}
361+
362+
// Reload tree item icons for all pages
363+
for (const PreferencesPage& page : std::as_const(m_allPages)) {
364+
if (page.pTreeItem && !page.iconFile.isEmpty()) {
365+
page.pTreeItem->setIcon(0, QIcon(m_iconsPath.filePath(page.iconFile)));
366+
}
367+
}
368+
369+
const QList<QWidget*> children = findChildren<QWidget*>();
370+
for (QWidget* pChild : children) {
371+
pChild->setPalette(appPalette);
372+
if (pChild->style()) {
373+
pChild->style()->unpolish(pChild);
374+
pChild->style()->polish(pChild);
375+
}
376+
pChild->update();
377+
}
378+
}
379+
QDialog::changeEvent(pEvent);
380+
}
381+
323382
void DlgPreferences::onHide() {
324383
// Notify children that we are about to hide.
325384
emit closeDlg();
@@ -461,37 +520,43 @@ bool DlgPreferences::pendingConfigValidOnAllPages() {
461520
return true;
462521
}
463522

464-
void DlgPreferences::addPageWidget(PreferencesPage page,
523+
void DlgPreferences::addPageWidget(const PreferencesPage& page,
465524
const QString& pageTitle,
466525
const QString& iconFile) {
526+
PreferencesPage pageCopy = page;
527+
pageCopy.iconFile = iconFile;
467528
// Configure the tree button linked to the page
468-
page.pTreeItem->setIcon(0, QIcon(m_iconsPath.filePath(iconFile)));
469-
page.pTreeItem->setText(0, pageTitle);
470-
page.pTreeItem->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
471-
page.pTreeItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
529+
pageCopy.pTreeItem->setIcon(0, QIcon(m_iconsPath.filePath(iconFile)));
530+
pageCopy.pTreeItem->setText(0, pageTitle);
531+
pageCopy.pTreeItem->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
532+
pageCopy.pTreeItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
472533

473-
connect(this, &DlgPreferences::showDlg, page.pDlg, &DlgPreferencePage::slotShow);
474-
connect(this, &DlgPreferences::closeDlg, page.pDlg, &DlgPreferencePage::slotHide);
475-
connect(this, &DlgPreferences::showDlg, page.pDlg, &DlgPreferencePage::slotUpdate);
534+
connect(this, &DlgPreferences::showDlg, pageCopy.pDlg, &DlgPreferencePage::slotShow);
535+
connect(this, &DlgPreferences::closeDlg, pageCopy.pDlg, &DlgPreferencePage::slotHide);
536+
connect(this, &DlgPreferences::showDlg, pageCopy.pDlg, &DlgPreferencePage::slotUpdate);
476537

477-
connect(this, &DlgPreferences::applyPreferences, page.pDlg, &DlgPreferencePage::slotApply);
478-
connect(this, &DlgPreferences::cancelPreferences, page.pDlg, &DlgPreferencePage::slotCancel);
538+
connect(this, &DlgPreferences::applyPreferences, pageCopy.pDlg, &DlgPreferencePage::slotApply);
539+
connect(this,
540+
&DlgPreferences::cancelPreferences,
541+
pageCopy.pDlg,
542+
&DlgPreferencePage::slotCancel);
479543
connect(this,
480544
&DlgPreferences::resetToDefaults,
481-
page.pDlg,
545+
pageCopy.pDlg,
482546
&DlgPreferencePage::slotResetToDefaults);
483547

484548
// Add a new scroll area to the stacked pages widget containing the page
485549
QScrollArea* sa = new QScrollArea(pagesWidget);
486550
sa->setWidgetResizable(true);
487551

488-
sa->setWidget(page.pDlg);
552+
sa->setWidget(pageCopy.pDlg);
489553
pagesWidget->addWidget(sa);
490-
m_allPages.append(page);
554+
m_allPages.append(pageCopy);
491555

492556
int iframe = 2 * sa->frameWidth();
493557
m_pageSizeHint = m_pageSizeHint.expandedTo(
494-
page.pDlg->sizeHint() + QSize(iframe, iframe));
558+
pageCopy.pDlg->sizeHint() + QSize(iframe, iframe));
559+
fixSliderStyle();
495560
}
496561

497562
DlgPreferencePage* DlgPreferences::currentPage() {
@@ -597,8 +662,7 @@ void DlgPreferences::fixSliderStyle() {
597662
// - the groove is not correctly centered vertically
598663
// - the handle is cut off at the top
599664
// The style below is based on sliders in the macOS system settings dialogs.
600-
if (darkAppearance()) {
601-
setStyleSheet(R"--(
665+
const QString styleSheetStr = darkAppearance() ? R"--(
602666
QSlider::handle:horizontal {
603667
background-color: #8f8c8b;
604668
border-radius: 4px;
@@ -615,9 +679,8 @@ QSlider::groove:horizontal {
615679
margin-left: 8px;
616680
margin-right: 8px;
617681
}
618-
)--");
619-
} else {
620-
setStyleSheet(R"--(
682+
)--"
683+
: R"--(
621684
QSlider::handle:horizontal {
622685
background-color: #ffffff;
623686
border-radius: 4px;
@@ -635,7 +698,11 @@ QSlider::groove:horizontal {
635698
margin-left: 8px;
636699
margin-right: 8px;
637700
}
638-
)--");
701+
)--";
702+
703+
const QList<QSlider*> sliders = findChildren<QSlider*>();
704+
for (QSlider* pSlider : sliders) {
705+
pSlider->setStyleSheet(styleSheetStr);
639706
}
640-
#endif // __APPLE__
707+
#endif // Q_OS_MACOS
641708
}

src/preferences/dialog/dlgpreferences.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class DlgPreferences : public QDialog, public Ui::DlgPreferencesDlg {
4141

4242
DlgPreferencePage* pDlg;
4343
QTreeWidgetItem* pTreeItem;
44+
QString iconFile;
4445
};
4546

4647
DlgPreferences(
@@ -54,7 +55,7 @@ class DlgPreferences : public QDialog, public Ui::DlgPreferencesDlg {
5455
std::shared_ptr<Library> pLibrary);
5556
virtual ~DlgPreferences();
5657

57-
void addPageWidget(PreferencesPage page,
58+
void addPageWidget(const PreferencesPage& page,
5859
const QString& pageTitle,
5960
const QString& iconFile);
6061
void removePageWidget(DlgPreferencePage* pWidget);
@@ -81,9 +82,10 @@ class DlgPreferences : public QDialog, public Ui::DlgPreferencesDlg {
8182
void menuBarAutoHideChanged();
8283

8384
protected:
84-
bool eventFilter(QObject*, QEvent*);
85-
void moveEvent(QMoveEvent* e);
86-
void resizeEvent(QResizeEvent* e);
85+
bool eventFilter(QObject*, QEvent*) override;
86+
void changeEvent(QEvent* pEvent) override;
87+
void moveEvent(QMoveEvent* e) override;
88+
void resizeEvent(QResizeEvent* e) override;
8789

8890
private:
8991
DlgPreferencePage* currentPage();

0 commit comments

Comments
 (0)