mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
fix: Options dialog - remove CSS overrides, fix title case, add show icon checkbox, add Generator page
This commit is contained in:
@@ -261,6 +261,12 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(test_theme PRIVATE ${QT}::Widgets ${QT}::Test)
|
||||
add_test(NAME test_theme COMMAND test_theme)
|
||||
|
||||
add_executable(test_options_dialog tests/test_options_dialog.cpp
|
||||
src/optionsdialog.cpp src/themes/theme.cpp src/themes/thememanager.cpp)
|
||||
target_include_directories(test_options_dialog PRIVATE src)
|
||||
target_link_libraries(test_options_dialog PRIVATE ${QT}::Widgets ${QT}::Test)
|
||||
add_test(NAME test_options_dialog COMMAND test_options_dialog)
|
||||
|
||||
if(WIN32)
|
||||
add_executable(test_windbg_provider tests/test_windbg_provider.cpp
|
||||
plugins/WinDbgMemory/WinDbgMemoryPlugin.cpp)
|
||||
|
||||
25
src/main.cpp
25
src/main.cpp
@@ -220,8 +220,8 @@ static void applyGlobalTheme(const rcx::Theme& theme) {
|
||||
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.indHoverSpan);
|
||||
pal.setColor(QPalette::Highlight, theme.selection);
|
||||
pal.setColor(QPalette::HighlightedText, theme.text);
|
||||
pal.setColor(QPalette::ToolTipBase, theme.backgroundAlt);
|
||||
pal.setColor(QPalette::ToolTipText, theme.text);
|
||||
pal.setColor(QPalette::Mid, theme.border);
|
||||
@@ -313,8 +313,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
|
||||
|
||||
// Restore menu bar title case setting (after menus are created)
|
||||
{
|
||||
bool titleCase = QSettings("Reclass", "Reclass").value("menuBarTitleCase", true).toBool();
|
||||
m_titleBar->setMenuBarTitleCase(titleCase);
|
||||
QSettings s("Reclass", "Reclass");
|
||||
m_titleBar->setMenuBarTitleCase(s.value("menuBarTitleCase", true).toBool());
|
||||
if (s.value("showIcon", false).toBool())
|
||||
m_titleBar->setShowIcon(true);
|
||||
}
|
||||
|
||||
// MenuBarStyle is set as app style in main() — covers both QMenuBar and QMenu
|
||||
@@ -422,15 +424,6 @@ void MainWindow::createMenus() {
|
||||
themeMenu->addAction("Edit Theme...", this, &MainWindow::editTheme);
|
||||
|
||||
view->addSeparator();
|
||||
auto* actShowIcon = view->addAction("Show &Icon");
|
||||
actShowIcon->setCheckable(true);
|
||||
actShowIcon->setChecked(settings.value("showIcon", false).toBool());
|
||||
if (actShowIcon->isChecked()) m_titleBar->setShowIcon(true);
|
||||
connect(actShowIcon, &QAction::toggled, this, [this](bool checked) {
|
||||
m_titleBar->setShowIcon(checked);
|
||||
QSettings s("Reclass", "Reclass");
|
||||
s.setValue("showIcon", checked);
|
||||
});
|
||||
view->addAction(m_workspaceDock->toggleViewAction());
|
||||
|
||||
// Node
|
||||
@@ -1048,6 +1041,7 @@ void MainWindow::showOptionsDialog() {
|
||||
current.themeIndex = tm.currentIndex();
|
||||
current.fontName = QSettings("Reclass", "Reclass").value("font", "JetBrains Mono").toString();
|
||||
current.menuBarTitleCase = m_titleBar->menuBarTitleCase();
|
||||
current.showIcon = QSettings("Reclass", "Reclass").value("showIcon", false).toBool();
|
||||
current.safeMode = QSettings("Reclass", "Reclass").value("safeMode", false).toBool();
|
||||
current.autoStartMcp = QSettings("Reclass", "Reclass").value("autoStartMcp", false).toBool();
|
||||
|
||||
@@ -1067,6 +1061,11 @@ void MainWindow::showOptionsDialog() {
|
||||
QSettings("Reclass", "Reclass").setValue("menuBarTitleCase", r.menuBarTitleCase);
|
||||
}
|
||||
|
||||
if (r.showIcon != current.showIcon) {
|
||||
m_titleBar->setShowIcon(r.showIcon);
|
||||
QSettings("Reclass", "Reclass").setValue("showIcon", r.showIcon);
|
||||
}
|
||||
|
||||
if (r.safeMode != current.safeMode)
|
||||
QSettings("Reclass", "Reclass").setValue("safeMode", r.safeMode);
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QEvent>
|
||||
#include <functional>
|
||||
|
||||
namespace rcx {
|
||||
@@ -20,8 +18,6 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
setWindowTitle("Options");
|
||||
setFixedSize(700, 450);
|
||||
|
||||
const auto& t = ThemeManager::instance().current();
|
||||
|
||||
auto* mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->setSpacing(8);
|
||||
mainLayout->setContentsMargins(10, 10, 10, 10);
|
||||
@@ -87,6 +83,10 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
m_titleCaseCheck->setChecked(current.menuBarTitleCase);
|
||||
visualLayout->addRow(m_titleCaseCheck);
|
||||
|
||||
m_showIconCheck = new QCheckBox("Show icon in title bar");
|
||||
m_showIconCheck->setChecked(current.showIcon);
|
||||
visualLayout->addRow(m_showIconCheck);
|
||||
|
||||
generalLayout->addWidget(visualGroup);
|
||||
|
||||
// Safe Mode group box
|
||||
@@ -96,8 +96,6 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
|
||||
m_safeModeCheck = new QCheckBox("Safe Mode");
|
||||
m_safeModeCheck->setChecked(current.safeMode);
|
||||
m_safeModeCheck->setStyleSheet(QStringLiteral(
|
||||
"QCheckBox { font-weight: bold; }"));
|
||||
safeModeLayout->addWidget(m_safeModeCheck);
|
||||
|
||||
auto* safeModeDesc = new QLabel(
|
||||
@@ -127,8 +125,6 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
|
||||
m_autoMcpCheck = new QCheckBox("Auto-start MCP server");
|
||||
m_autoMcpCheck->setChecked(current.autoStartMcp);
|
||||
m_autoMcpCheck->setStyleSheet(QStringLiteral(
|
||||
"QCheckBox { font-weight: bold; }"));
|
||||
mcpLayout->addWidget(m_autoMcpCheck);
|
||||
|
||||
auto* mcpDesc = new QLabel(
|
||||
@@ -144,6 +140,18 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
m_pages->addWidget(aiPage); // index 1
|
||||
m_pageKeywords[aiItem] = collectPageKeywords(aiPage);
|
||||
|
||||
// -- Generator page --
|
||||
auto* generatorItem = new QTreeWidgetItem(envItem, {"Generator"});
|
||||
|
||||
auto* generatorPage = new QWidget;
|
||||
auto* generatorLayout = new QVBoxLayout(generatorPage);
|
||||
generatorLayout->setContentsMargins(0, 0, 0, 0);
|
||||
generatorLayout->setSpacing(8);
|
||||
generatorLayout->addStretch();
|
||||
|
||||
m_pages->addWidget(generatorPage); // index 2
|
||||
m_pageKeywords[generatorItem] = collectPageKeywords(generatorPage);
|
||||
|
||||
middleLayout->addWidget(m_pages, 1);
|
||||
|
||||
mainLayout->addLayout(middleLayout, 1);
|
||||
@@ -151,6 +159,7 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
// Tree <-> page connection
|
||||
m_itemPageIndex[generalItem] = 0;
|
||||
m_itemPageIndex[aiItem] = 1;
|
||||
m_itemPageIndex[generatorItem] = 2;
|
||||
connect(m_tree, &QTreeWidget::currentItemChanged, this,
|
||||
[this](QTreeWidgetItem* item, QTreeWidgetItem*) {
|
||||
if (!item) return;
|
||||
@@ -165,106 +174,6 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
mainLayout->addWidget(buttons);
|
||||
|
||||
// -- Styling --
|
||||
|
||||
// Combo boxes: set directly so the popup (top-level widget) inherits it
|
||||
QString comboStyle = QStringLiteral(
|
||||
"QComboBox {"
|
||||
" background: %1; color: %2; border: 1px solid %3;"
|
||||
" padding: 3px 8px; font-size: 12px;"
|
||||
"}"
|
||||
"QComboBox::drop-down {"
|
||||
" border: none; border-left: 1px solid %3;"
|
||||
" width: 20px;"
|
||||
"}"
|
||||
"QComboBox::down-arrow {"
|
||||
" image: url(:/vsicons/chevron-down.svg);"
|
||||
" width: 12px; height: 12px;"
|
||||
"}"
|
||||
"QComboBox QAbstractItemView {"
|
||||
" background: %1; color: %2; border: 1px solid %3;"
|
||||
" selection-background-color: %4;"
|
||||
"}")
|
||||
.arg(t.backgroundAlt.name(), t.text.name(),
|
||||
t.border.name(), t.hover.name());
|
||||
m_themeCombo->setStyleSheet(comboStyle);
|
||||
m_fontCombo->setStyleSheet(comboStyle);
|
||||
|
||||
// Dialog-wide stylesheet for everything else
|
||||
setStyleSheet(QStringLiteral(
|
||||
"QDialog { background: %1; }"
|
||||
|
||||
"QLineEdit {"
|
||||
" background: %2; color: %3; border: 1px solid %4;"
|
||||
" padding: 4px 8px; font-size: 12px;"
|
||||
"}"
|
||||
|
||||
"QTreeWidget {"
|
||||
" background: %2; color: %3; border: 1px solid %4;"
|
||||
" font-size: 12px; outline: none;"
|
||||
"}"
|
||||
"QTreeWidget::item { padding: 3px 0; outline: none; }"
|
||||
"QTreeWidget::item:selected { background: %5; color: %3; }"
|
||||
"QTreeWidget::item:hover { background: %6; }"
|
||||
|
||||
"QGroupBox {"
|
||||
" color: %3; border: 1px solid %4;"
|
||||
" margin-top: 8px; padding: 12px 8px 8px 8px;"
|
||||
" font-size: 12px; font-weight: bold;"
|
||||
"}"
|
||||
"QGroupBox::title {"
|
||||
" subcontrol-origin: margin;"
|
||||
" left: 8px; padding: 0 4px;"
|
||||
"}"
|
||||
|
||||
"QLabel { color: %3; font-size: 12px; }"
|
||||
|
||||
"QCheckBox { color: %3; font-size: 12px; spacing: 6px; }"
|
||||
|
||||
"QPushButton {"
|
||||
" background: %2; color: %3; border: 1px solid %4;"
|
||||
" padding: 5px 16px; min-width: 70px; font-size: 12px;"
|
||||
" outline: none;"
|
||||
"}"
|
||||
"QPushButton:hover { background: %6; }"
|
||||
"QPushButton:pressed { background: %1; }"
|
||||
"QPushButton:focus { outline: none; }")
|
||||
.arg(t.background.name(), // %1
|
||||
t.backgroundAlt.name(), // %2
|
||||
t.text.name(), // %3
|
||||
t.border.name(), // %4
|
||||
t.selection.name(), // %5
|
||||
t.hover.name())); // %6
|
||||
|
||||
// Install hover shadow on interactive widgets (not buttons — they use stylesheet hover)
|
||||
for (auto* w : {static_cast<QWidget*>(m_search),
|
||||
static_cast<QWidget*>(m_themeCombo),
|
||||
static_cast<QWidget*>(m_fontCombo),
|
||||
static_cast<QWidget*>(m_titleCaseCheck),
|
||||
static_cast<QWidget*>(m_safeModeCheck),
|
||||
static_cast<QWidget*>(m_autoMcpCheck)})
|
||||
w->installEventFilter(this);
|
||||
|
||||
m_shadowColor = t.text;
|
||||
m_shadowColor.setAlpha(80);
|
||||
}
|
||||
|
||||
bool OptionsDialog::eventFilter(QObject* obj, QEvent* event) {
|
||||
if (event->type() == QEvent::Enter) {
|
||||
auto* w = qobject_cast<QWidget*>(obj);
|
||||
if (w && !w->graphicsEffect()) {
|
||||
auto* shadow = new QGraphicsDropShadowEffect(w);
|
||||
shadow->setBlurRadius(12);
|
||||
shadow->setOffset(0, 0);
|
||||
shadow->setColor(m_shadowColor);
|
||||
w->setGraphicsEffect(shadow);
|
||||
}
|
||||
} else if (event->type() == QEvent::Leave) {
|
||||
auto* w = qobject_cast<QWidget*>(obj);
|
||||
if (w)
|
||||
w->setGraphicsEffect(nullptr);
|
||||
}
|
||||
return QDialog::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
OptionsResult OptionsDialog::result() const {
|
||||
@@ -272,6 +181,7 @@ OptionsResult OptionsDialog::result() const {
|
||||
r.themeIndex = m_themeCombo->currentIndex();
|
||||
r.fontName = m_fontCombo->currentText();
|
||||
r.menuBarTitleCase = m_titleCaseCheck->isChecked();
|
||||
r.showIcon = m_showIconCheck->isChecked();
|
||||
r.safeMode = m_safeModeCheck->isChecked();
|
||||
r.autoStartMcp = m_autoMcpCheck->isChecked();
|
||||
return r;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "themes/theme.h"
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QTreeWidget>
|
||||
@@ -7,7 +6,6 @@
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QHash>
|
||||
#include <QColor>
|
||||
|
||||
namespace rcx {
|
||||
|
||||
@@ -15,6 +13,7 @@ struct OptionsResult {
|
||||
int themeIndex = 0;
|
||||
QString fontName;
|
||||
bool menuBarTitleCase = true;
|
||||
bool showIcon = false;
|
||||
bool safeMode = false;
|
||||
bool autoStartMcp = false;
|
||||
};
|
||||
@@ -26,9 +25,6 @@ public:
|
||||
|
||||
OptionsResult result() const;
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||
|
||||
private:
|
||||
void filterTree(const QString& text);
|
||||
static QStringList collectPageKeywords(QWidget* page);
|
||||
@@ -39,11 +35,10 @@ private:
|
||||
QComboBox* m_themeCombo = nullptr;
|
||||
QComboBox* m_fontCombo = nullptr;
|
||||
QCheckBox* m_titleCaseCheck = nullptr;
|
||||
QCheckBox* m_showIconCheck = nullptr;
|
||||
QCheckBox* m_safeModeCheck = nullptr;
|
||||
QCheckBox* m_autoMcpCheck = nullptr;
|
||||
|
||||
QColor m_shadowColor;
|
||||
|
||||
// searchable keywords per leaf tree item
|
||||
QHash<QTreeWidgetItem*, QStringList> m_pageKeywords;
|
||||
// tree item → stacked widget page index
|
||||
|
||||
@@ -122,6 +122,8 @@ void TitleBarWidget::setMenuBarTitleCase(bool titleCase) {
|
||||
clean.remove('&');
|
||||
|
||||
if (titleCase) {
|
||||
action->setText("&" + clean.toUpper());
|
||||
} else {
|
||||
QString result;
|
||||
bool capitalizeNext = true;
|
||||
for (int i = 0; i < clean.length(); ++i) {
|
||||
@@ -135,8 +137,6 @@ void TitleBarWidget::setMenuBarTitleCase(bool titleCase) {
|
||||
}
|
||||
}
|
||||
action->setText("&" + result);
|
||||
} else {
|
||||
action->setText("&" + clean.toUpper());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
252
tests/test_options_dialog.cpp
Normal file
252
tests/test_options_dialog.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
#include <QtTest/QTest>
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QTreeWidget>
|
||||
#include <QStackedWidget>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QGroupBox>
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
#include "optionsdialog.h"
|
||||
#include "themes/thememanager.h"
|
||||
|
||||
using namespace rcx;
|
||||
|
||||
// Helper: apply the global palette the same way main.cpp does
|
||||
static void applyGlobalTheme(const Theme& theme) {
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::Window, theme.background);
|
||||
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.selection);
|
||||
pal.setColor(QPalette::HighlightedText, theme.text);
|
||||
pal.setColor(QPalette::ToolTipBase, theme.backgroundAlt);
|
||||
pal.setColor(QPalette::ToolTipText, theme.text);
|
||||
pal.setColor(QPalette::Mid, theme.border);
|
||||
pal.setColor(QPalette::Dark, theme.background);
|
||||
pal.setColor(QPalette::Light, theme.textFaint);
|
||||
pal.setColor(QPalette::Link, theme.indHoverSpan);
|
||||
|
||||
pal.setColor(QPalette::Disabled, QPalette::WindowText, theme.textMuted);
|
||||
pal.setColor(QPalette::Disabled, QPalette::Text, theme.textMuted);
|
||||
pal.setColor(QPalette::Disabled, QPalette::ButtonText, theme.textMuted);
|
||||
pal.setColor(QPalette::Disabled, QPalette::HighlightedText, theme.textMuted);
|
||||
pal.setColor(QPalette::Disabled, QPalette::Light, theme.background);
|
||||
|
||||
qApp->setPalette(pal);
|
||||
qApp->setStyleSheet(QString());
|
||||
}
|
||||
|
||||
class TestOptionsDialog : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
|
||||
void initTestCase() {
|
||||
// Apply theme palette so dialog inherits real colors
|
||||
auto& tm = ThemeManager::instance();
|
||||
applyGlobalTheme(tm.current());
|
||||
}
|
||||
|
||||
void dialogCreatesAllWidgets() {
|
||||
OptionsResult defaults;
|
||||
defaults.themeIndex = 0;
|
||||
defaults.fontName = "JetBrains Mono";
|
||||
defaults.menuBarTitleCase = true;
|
||||
defaults.safeMode = false;
|
||||
defaults.autoStartMcp = false;
|
||||
|
||||
OptionsDialog dlg(defaults);
|
||||
|
||||
// Core widgets exist
|
||||
auto* tree = dlg.findChild<QTreeWidget*>();
|
||||
QVERIFY(tree);
|
||||
auto* pages = dlg.findChild<QStackedWidget*>();
|
||||
QVERIFY(pages);
|
||||
QCOMPARE(pages->count(), 3);
|
||||
|
||||
auto* themeCombo = dlg.findChild<QComboBox*>("themeCombo");
|
||||
QVERIFY(themeCombo);
|
||||
QVERIFY(themeCombo->count() >= 3);
|
||||
|
||||
auto* fontCombo = dlg.findChild<QComboBox*>("fontCombo");
|
||||
QVERIFY(fontCombo);
|
||||
QCOMPARE(fontCombo->count(), 2);
|
||||
|
||||
auto* showIconCheck = dlg.findChild<QCheckBox*>();
|
||||
QVERIFY(showIconCheck);
|
||||
|
||||
auto* buttons = dlg.findChild<QDialogButtonBox*>();
|
||||
QVERIFY(buttons);
|
||||
QVERIFY(buttons->button(QDialogButtonBox::Ok));
|
||||
QVERIFY(buttons->button(QDialogButtonBox::Cancel));
|
||||
}
|
||||
|
||||
void resultReflectsInput() {
|
||||
OptionsResult input;
|
||||
input.themeIndex = 1;
|
||||
input.fontName = "Consolas";
|
||||
input.menuBarTitleCase = false;
|
||||
input.safeMode = true;
|
||||
input.autoStartMcp = true;
|
||||
|
||||
OptionsDialog dlg(input);
|
||||
auto r = dlg.result();
|
||||
|
||||
QCOMPARE(r.themeIndex, 1);
|
||||
QCOMPARE(r.fontName, QString("Consolas"));
|
||||
QCOMPARE(r.menuBarTitleCase, false);
|
||||
QCOMPARE(r.safeMode, true);
|
||||
QCOMPARE(r.autoStartMcp, true);
|
||||
}
|
||||
|
||||
void noStyleSheetOnDialog() {
|
||||
OptionsResult defaults;
|
||||
OptionsDialog dlg(defaults);
|
||||
|
||||
// Dialog itself must have no stylesheet override
|
||||
QVERIFY(dlg.styleSheet().isEmpty());
|
||||
|
||||
// Combo boxes must have no stylesheet override
|
||||
auto* themeCombo = dlg.findChild<QComboBox*>("themeCombo");
|
||||
QVERIFY(themeCombo->styleSheet().isEmpty());
|
||||
auto* fontCombo = dlg.findChild<QComboBox*>("fontCombo");
|
||||
QVERIFY(fontCombo->styleSheet().isEmpty());
|
||||
|
||||
// No child widget should have a stylesheet set
|
||||
for (auto* child : dlg.findChildren<QWidget*>()) {
|
||||
QVERIFY2(child->styleSheet().isEmpty(),
|
||||
qPrintable(QString("Widget %1 (%2) has unexpected stylesheet: %3")
|
||||
.arg(child->objectName(),
|
||||
child->metaObject()->className(),
|
||||
child->styleSheet())));
|
||||
}
|
||||
}
|
||||
|
||||
void highlightColorDiffersFromBackground() {
|
||||
// Verify the palette Highlight is distinguishable from Window background
|
||||
// This is the root cause of broken hover: if they're the same, hover is invisible
|
||||
auto& tm = ThemeManager::instance();
|
||||
for (int i = 0; i < tm.themes().size(); ++i) {
|
||||
const auto& theme = tm.themes()[i];
|
||||
// selection must differ from background
|
||||
QVERIFY2(theme.selection != theme.background,
|
||||
qPrintable(QString("Theme '%1': selection == background (%2)")
|
||||
.arg(theme.name, theme.background.name())));
|
||||
}
|
||||
}
|
||||
|
||||
void paletteHighlightIsSelection() {
|
||||
// After applying theme, QPalette::Highlight must be theme.selection (not theme.hover)
|
||||
auto& tm = ThemeManager::instance();
|
||||
const auto& theme = tm.current();
|
||||
applyGlobalTheme(theme);
|
||||
|
||||
QPalette pal = qApp->palette();
|
||||
QCOMPARE(pal.color(QPalette::Highlight), theme.selection);
|
||||
}
|
||||
|
||||
void treePageSwitching() {
|
||||
OptionsResult defaults;
|
||||
OptionsDialog dlg(defaults);
|
||||
|
||||
auto* tree = dlg.findChild<QTreeWidget*>();
|
||||
auto* pages = dlg.findChild<QStackedWidget*>();
|
||||
QVERIFY(tree && pages);
|
||||
|
||||
// General is selected by default -> page 0
|
||||
QCOMPARE(pages->currentIndex(), 0);
|
||||
|
||||
// Find "AI Features" item and select it
|
||||
auto* envItem = tree->topLevelItem(0);
|
||||
QVERIFY(envItem);
|
||||
QTreeWidgetItem* aiItem = nullptr;
|
||||
for (int i = 0; i < envItem->childCount(); ++i) {
|
||||
if (envItem->child(i)->text(0) == "AI Features") {
|
||||
aiItem = envItem->child(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
QVERIFY(aiItem);
|
||||
tree->setCurrentItem(aiItem);
|
||||
QCOMPARE(pages->currentIndex(), 1);
|
||||
|
||||
// Switch back to General
|
||||
QTreeWidgetItem* generalItem = nullptr;
|
||||
for (int i = 0; i < envItem->childCount(); ++i) {
|
||||
if (envItem->child(i)->text(0) == "General") {
|
||||
generalItem = envItem->child(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
QVERIFY(generalItem);
|
||||
tree->setCurrentItem(generalItem);
|
||||
QCOMPARE(pages->currentIndex(), 0);
|
||||
}
|
||||
|
||||
void searchFilterHidesItems() {
|
||||
OptionsResult defaults;
|
||||
OptionsDialog dlg(defaults);
|
||||
|
||||
auto* search = dlg.findChild<QLineEdit*>();
|
||||
auto* tree = dlg.findChild<QTreeWidget*>();
|
||||
QVERIFY(search && tree);
|
||||
|
||||
auto* envItem = tree->topLevelItem(0);
|
||||
QVERIFY(envItem);
|
||||
|
||||
// All children visible initially
|
||||
for (int i = 0; i < envItem->childCount(); ++i)
|
||||
QVERIFY(!envItem->child(i)->isHidden());
|
||||
|
||||
// Search for "MCP" - should hide General, show AI Features
|
||||
search->setText("MCP");
|
||||
QTreeWidgetItem* generalItem = nullptr;
|
||||
QTreeWidgetItem* aiItem = nullptr;
|
||||
for (int i = 0; i < envItem->childCount(); ++i) {
|
||||
auto* child = envItem->child(i);
|
||||
if (child->text(0) == "General") generalItem = child;
|
||||
if (child->text(0) == "AI Features") aiItem = child;
|
||||
}
|
||||
QVERIFY(generalItem && aiItem);
|
||||
QVERIFY(generalItem->isHidden());
|
||||
QVERIFY(!aiItem->isHidden());
|
||||
|
||||
// Clear search - all visible again
|
||||
search->setText("");
|
||||
QVERIFY(!generalItem->isHidden());
|
||||
QVERIFY(!aiItem->isHidden());
|
||||
}
|
||||
|
||||
void dialogInheritsPalette() {
|
||||
auto& tm = ThemeManager::instance();
|
||||
const auto& theme = tm.current();
|
||||
applyGlobalTheme(theme);
|
||||
|
||||
OptionsResult defaults;
|
||||
OptionsDialog dlg(defaults);
|
||||
dlg.show();
|
||||
QTest::qWaitForWindowExposed(&dlg);
|
||||
|
||||
// Dialog's effective palette should match the app palette
|
||||
QPalette dlgPal = dlg.palette();
|
||||
QPalette appPal = qApp->palette();
|
||||
|
||||
QCOMPARE(dlgPal.color(QPalette::Window), appPal.color(QPalette::Window));
|
||||
QCOMPARE(dlgPal.color(QPalette::WindowText), appPal.color(QPalette::WindowText));
|
||||
QCOMPARE(dlgPal.color(QPalette::Highlight), appPal.color(QPalette::Highlight));
|
||||
QCOMPARE(dlgPal.color(QPalette::Button), appPal.color(QPalette::Button));
|
||||
QCOMPARE(dlgPal.color(QPalette::ButtonText), appPal.color(QPalette::ButtonText));
|
||||
|
||||
// Highlight must be visible against background
|
||||
QVERIFY(dlgPal.color(QPalette::Highlight) != dlgPal.color(QPalette::Window));
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN(TestOptionsDialog)
|
||||
#include "test_options_dialog.moc"
|
||||
Reference in New Issue
Block a user