fix: type chooser updates colors when theme changes

Add applyTheme() to TypeSelectorPopup that refreshes palette and
stylesheets for all child widgets. Controller connects it to
ThemeManager::themeChanged on popup creation.
This commit is contained in:
IChooseYou
2026-02-18 09:59:50 -07:00
parent b1d3e52204
commit fa0d9a377b
4 changed files with 141 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
#include "controller.h" #include "controller.h"
#include "typeselectorpopup.h" #include "typeselectorpopup.h"
#include "providerregistry.h" #include "providerregistry.h"
#include "themes/thememanager.h"
#include <Qsci/qsciscintilla.h> #include <Qsci/qsciscintilla.h>
#include <QSplitter> #include <QSplitter>
#include <QFile> #include <QFile>
@@ -1726,6 +1727,9 @@ void RcxController::updateCommandRow() {
TypeSelectorPopup* RcxController::ensurePopup(RcxEditor* editor) { TypeSelectorPopup* RcxController::ensurePopup(RcxEditor* editor) {
if (!m_cachedPopup) { if (!m_cachedPopup) {
m_cachedPopup = new TypeSelectorPopup(editor); m_cachedPopup = new TypeSelectorPopup(editor);
// Keep popup colors in sync when theme changes
connect(&ThemeManager::instance(), &ThemeManager::themeChanged,
m_cachedPopup, &TypeSelectorPopup::applyTheme);
// Pre-warm: force native window creation so first visible show is fast // Pre-warm: force native window creation so first visible show is fast
m_cachedPopup->warmUp(); m_cachedPopup->warmUp();
} }

View File

@@ -279,14 +279,14 @@ TypeSelectorPopup::TypeSelectorPopup(QWidget* parent)
// Separator // Separator
{ {
auto* sep = new QFrame; m_separator = new QFrame;
sep->setFrameShape(QFrame::HLine); m_separator->setFrameShape(QFrame::HLine);
sep->setFrameShadow(QFrame::Plain); m_separator->setFrameShadow(QFrame::Plain);
QPalette sepPal = pal; QPalette sepPal = pal;
sepPal.setColor(QPalette::WindowText, theme.border); sepPal.setColor(QPalette::WindowText, theme.border);
sep->setPalette(sepPal); m_separator->setPalette(sepPal);
sep->setFixedHeight(1); m_separator->setFixedHeight(1);
layout->addWidget(sep); layout->addWidget(m_separator);
} }
// Row 3: Modifier toggles [ plain ] [ * ] [ ** ] [ [n] ] // Row 3: Modifier toggles [ plain ] [ * ] [ ** ] [ [n] ]
@@ -456,6 +456,60 @@ void TypeSelectorPopup::setFont(const QFont& font) {
delegate->setFont(font); delegate->setFont(font);
} }
void TypeSelectorPopup::applyTheme(const Theme& theme) {
QPalette pal;
pal.setColor(QPalette::Window, theme.backgroundAlt);
pal.setColor(QPalette::WindowText, theme.text);
pal.setColor(QPalette::Base, theme.background);
pal.setColor(QPalette::AlternateBase, theme.surface);
pal.setColor(QPalette::Text, theme.text);
pal.setColor(QPalette::Button, theme.button);
pal.setColor(QPalette::ButtonText, theme.text);
pal.setColor(QPalette::Highlight, theme.hover);
pal.setColor(QPalette::HighlightedText, theme.text);
setPalette(pal);
m_titleLabel->setPalette(pal);
m_filterEdit->setPalette(pal);
m_listView->setPalette(pal);
m_previewLabel->setPalette(pal);
m_arrayCountEdit->setPalette(pal);
// Separator
QPalette sepPal = pal;
sepPal.setColor(QPalette::WindowText, theme.border);
m_separator->setPalette(sepPal);
// Esc button
m_escLabel->setStyleSheet(QStringLiteral(
"QToolButton { color: %1; border: none; padding: 2px 6px; }"
"QToolButton:hover { color: %2; }")
.arg(theme.textDim.name(), theme.indHoverSpan.name()));
// Create button
m_createBtn->setStyleSheet(QStringLiteral(
"QToolButton { color: %1; border: none; padding: 3px 6px; }"
"QToolButton:hover { color: %2; background: %3; }")
.arg(theme.textMuted.name(), theme.text.name(), theme.hover.name()));
// Modifier toggle buttons
QString btnStyle = QStringLiteral(
"QToolButton { color: %1; background: %2; border: 1px solid %3;"
" padding: 2px 8px; border-radius: 3px; }"
"QToolButton:checked { color: %4; background: %5; border-color: %5; }"
"QToolButton:hover:!checked { background: %6; }")
.arg(theme.textDim.name(), theme.background.name(), theme.border.name(),
theme.text.name(), theme.selected.name(), theme.hover.name());
m_btnPlain->setStyleSheet(btnStyle);
m_btnPtr->setStyleSheet(btnStyle);
m_btnDblPtr->setStyleSheet(btnStyle);
m_btnArray->setStyleSheet(btnStyle);
// Preview label
m_previewLabel->setStyleSheet(QStringLiteral(
"QLabel { color: %1; padding: 1px 6px; }").arg(theme.syntaxType.name()));
}
void TypeSelectorPopup::setTitle(const QString& title) { void TypeSelectorPopup::setTitle(const QString& title) {
m_titleLabel->setText(title); m_titleLabel->setText(title);
} }

View File

@@ -16,6 +16,8 @@ class QWidget;
namespace rcx { namespace rcx {
struct Theme;
// ── Popup mode ── // ── Popup mode ──
enum class TypePopupMode { Root, FieldType, ArrayElement, PointerTarget }; enum class TypePopupMode { Root, FieldType, ArrayElement, PointerTarget };
@@ -53,6 +55,7 @@ public:
void setFont(const QFont& font); void setFont(const QFont& font);
void setTitle(const QString& title); void setTitle(const QString& title);
void setMode(TypePopupMode mode); void setMode(TypePopupMode mode);
void applyTheme(const Theme& theme);
void setCurrentNodeSize(int bytes); void setCurrentNodeSize(int bytes);
void setTypes(const QVector<TypeEntry>& types, const TypeEntry* current = nullptr); void setTypes(const QVector<TypeEntry>& types, const TypeEntry* current = nullptr);
void popup(const QPoint& globalPos); void popup(const QPoint& globalPos);
@@ -77,6 +80,7 @@ private:
QLabel* m_previewLabel = nullptr; QLabel* m_previewLabel = nullptr;
QListView* m_listView = nullptr; QListView* m_listView = nullptr;
QStringListModel* m_model = nullptr; QStringListModel* m_model = nullptr;
QFrame* m_separator = nullptr;
// Modifier toggles // Modifier toggles
QWidget* m_modRow = nullptr; QWidget* m_modRow = nullptr;

View File

@@ -887,6 +887,79 @@ private slots:
qPrintable(QString("Large popup width %1 should be > small %2") qPrintable(QString("Large popup width %1 should be > small %2")
.arg(largeW).arg(smallW))); .arg(largeW).arg(smallW)));
} }
// ── Test: popup updates colors when theme changes ──
void testPopupUpdatesOnThemeChange() {
auto& tm = ThemeManager::instance();
int origIdx = tm.currentIndex();
// Ensure at least two themes exist
QVERIFY2(tm.themes().size() >= 2,
"Need at least 2 themes to test theme switching");
// Create popup with current theme
TypeSelectorPopup popup;
TypeEntry prim;
prim.entryKind = TypeEntry::Primitive;
prim.primitiveKind = NodeKind::Int32;
prim.displayName = QStringLiteral("int32_t");
popup.setTypes({prim});
QColor bgBefore = popup.palette().color(QPalette::Window);
// Switch to a different theme
int otherIdx = (origIdx == 0) ? 1 : 0;
tm.setCurrent(otherIdx);
QApplication::processEvents();
// The popup should have applyTheme connected to themeChanged
popup.applyTheme(tm.current());
QColor bgAfter = popup.palette().color(QPalette::Window);
// If the two themes have different background colors, verify the change
// (some themes may coincidentally share colors, so we just verify the
// method doesn't crash and the palette is set to the new theme's color)
QCOMPARE(bgAfter, tm.current().backgroundAlt);
// Also verify child widgets got updated
auto* filterEdit = popup.findChild<QLineEdit*>();
QVERIFY(filterEdit);
QCOMPARE(filterEdit->palette().color(QPalette::Base),
tm.current().background);
auto* listView = popup.findChild<QListView*>();
QVERIFY(listView);
QCOMPARE(listView->palette().color(QPalette::Base),
tm.current().background);
// Restore original theme
tm.setCurrent(origIdx);
}
void testPopupAutoConnectsThemeChange() {
auto& tm = ThemeManager::instance();
int origIdx = tm.currentIndex();
QVERIFY2(tm.themes().size() >= 2, "Need >= 2 themes");
TypeSelectorPopup popup;
// applyTheme is a public slot — verify it can be connected
connect(&tm, &ThemeManager::themeChanged,
&popup, &TypeSelectorPopup::applyTheme);
QColor bgBefore = popup.palette().color(QPalette::Window);
int otherIdx = (origIdx == 0) ? 1 : 0;
tm.setCurrent(otherIdx);
QApplication::processEvents();
// After theme change + signal, popup palette should match new theme
QCOMPARE(popup.palette().color(QPalette::Window),
tm.current().backgroundAlt);
// Restore
tm.setCurrent(origIdx);
}
}; };
QTEST_MAIN(TestTypeSelector) QTEST_MAIN(TestTypeSelector)