#include "breezetoolsareamanager.h" #include "breezepropertynames.h" #include #include #include #include #include #include #include #include const char *colorProperty = "KDE_COLOR_SCHEME_PATH"; namespace Breeze { ToolsAreaManager::ToolsAreaManager() : QObject() { QString path; if (qApp && qApp->property(colorProperty).isValid()) { path = qApp->property(colorProperty).toString(); } recreateConfigWatcher(path); configUpdated(); } ToolsAreaManager::~ToolsAreaManager() { } void ToolsAreaManager::recreateConfigWatcher(const QString &path) { const auto openFlags = path.isEmpty() ? KConfig::OpenFlag::FullConfig : KConfig::OpenFlag::NoGlobals; _config = KSharedConfig::openConfig(path, openFlags); if (!path.startsWith(QLatin1Char('/'))) { _watcher = KConfigWatcher::create(_config); connect(_watcher.data(), &KConfigWatcher::configChanged, this, &ToolsAreaManager::configUpdated); } else { _watcher.reset(); } } void ToolsAreaManager::appendIfNotAlreadyExists(const QMainWindow *window, const QPointer &toolBar) { const auto windowIt = std::find_if(_windows.begin(), _windows.end(), [window](const WindowToolBars &windowToolBars) { return window == windowToolBars.window; }); if (windowIt != _windows.end()) { if (!windowIt->toolBars.contains(toolBar)) { windowIt->toolBars.append(toolBar); } } else { _windows.emplace_back(WindowToolBars{window, {toolBar}}); connect(window, &QObject::destroyed, this, [this, window] { removeWindow(window); }); } } void ToolsAreaManager::removeWindowToolBar(const QMainWindow *window, const QPointer &toolBar) { const auto windowIt = std::find_if(_windows.begin(), _windows.end(), [window](const WindowToolBars &windowToolBars) { return window == windowToolBars.window; }); if (windowIt != _windows.end()) { windowIt->toolBars.removeAll(toolBar); } } void ToolsAreaManager::removeWindow(const QMainWindow *window) { std::erase_if(_windows, [window](const WindowToolBars &windowToolBars) { return window == windowToolBars.window; }); } void ToolsAreaManager::registerApplication(QApplication *application) { _listener = new AppListener(this); _listener->manager = this; if (application->property(colorProperty).isValid()) { auto path = application->property(colorProperty).toString(); recreateConfigWatcher(path); } application->installEventFilter(_listener); configUpdated(); } QRect ToolsAreaManager::toolsAreaRect(const QMainWindow &window) const { int itemHeight = window.menuWidget() ? window.menuWidget()->height() : 0; const auto windowIt = std::find_if(_windows.begin(), _windows.end(), [&window](const WindowToolBars &windowToolBars) { return &window == windowToolBars.window; }); if (windowIt != _windows.end()) { for (auto item : windowIt->toolBars) { if (!item.isNull() && item->isVisible() && window.toolBarArea(item) == Qt::TopToolBarArea) { itemHeight = qMax(item->mapTo(&window, item->rect().bottomLeft()).y(), itemHeight); } } } if (itemHeight > 0) { itemHeight += 1; } return QRect(0, 0, window.width(), itemHeight); } bool ToolsAreaManager::tryRegisterToolBar(QPointer window, QPointer widget) { Q_ASSERT(!widget.isNull()); QPointer toolbar; if (!(toolbar = qobject_cast(widget))) { return false; } if (window->toolBarArea(toolbar) == Qt::TopToolBarArea) { widget->setPalette(palette()); appendIfNotAlreadyExists(window, toolbar); return true; } return false; } void ToolsAreaManager::tryUnregisterToolBar(QPointer window, QPointer widget) { Q_ASSERT(!widget.isNull()); QPointer toolbar; if (!(toolbar = qobject_cast(widget))) { return; } if (window->toolBarArea(toolbar) != Qt::TopToolBarArea) { widget->setPalette(window->palette()); removeWindowToolBar(window, toolbar); } } void ToolsAreaManager::configUpdated() { auto active = KColorScheme(QPalette::Active, KColorScheme::Header, _config); auto inactive = KColorScheme(QPalette::Inactive, KColorScheme::Header, _config); auto disabled = KColorScheme(QPalette::Disabled, KColorScheme::Header, _config); _palette = KColorScheme::createApplicationPalette(_config); _palette.setBrush(QPalette::Active, QPalette::Window, active.background()); _palette.setBrush(QPalette::Active, QPalette::WindowText, active.foreground()); _palette.setBrush(QPalette::Disabled, QPalette::Window, disabled.background()); _palette.setBrush(QPalette::Disabled, QPalette::WindowText, disabled.foreground()); _palette.setBrush(QPalette::Inactive, QPalette::Window, inactive.background()); _palette.setBrush(QPalette::Inactive, QPalette::WindowText, inactive.foreground()); for (const WindowToolBars &windowToolBars : _windows) { for (const auto &toolbar : windowToolBars.toolBars) { if (!toolbar.isNull()) { toolbar->setPalette(_palette); } } if (QMenuBar *menuBar = windowToolBars.window->menuBar()) { menuBar->setPalette(_palette); } } _colorSchemeHasHeaderColor = KColorScheme::isColorSetSupported(_config, KColorScheme::Header); } bool AppListener::eventFilter(QObject *watched, QEvent *event) { Q_ASSERT(watched); Q_ASSERT(event); if (watched != qApp) { return false; } if (event->type() == QEvent::DynamicPropertyChange) { if (watched != qApp) { return false; } auto ev = static_cast(event); if (ev->propertyName() == colorProperty) { QString path; if (qApp && qApp->property(colorProperty).isValid()) { path = qApp->property(colorProperty).toString(); } manager->recreateConfigWatcher(path); manager->configUpdated(); } } return false; } bool ToolsAreaManager::eventFilter(QObject *watched, QEvent *event) { Q_ASSERT(watched); Q_ASSERT(event); QPointer parent = watched; QPointer mainWindow = nullptr; while (parent != nullptr) { if (qobject_cast(parent)) { mainWindow = qobject_cast(parent); break; } parent = parent->parent(); } if (const QMainWindow *mw = qobject_cast(watched)) { QChildEvent *ev = nullptr; if (event->type() == QEvent::ChildAdded || event->type() == QEvent::ChildRemoved) { ev = static_cast(event); if (event->type() == QEvent::ChildAdded) { QChildEvent *childEvent = static_cast(event); if (QMenuBar *menuBar = qobject_cast(childEvent->child())) { menuBar->setPalette(_palette); } } } else { return false; } QPointer tb = qobject_cast(ev->child()); if (tb.isNull()) { return false; } if (ev->added()) { if (mw->toolBarArea(tb) == Qt::TopToolBarArea) { appendIfNotAlreadyExists(mw, tb); } } else if (ev->removed()) { removeWindowToolBar(mw, tb); } } else if (qobject_cast(watched)) { if (!mainWindow.isNull()) { tryUnregisterToolBar(mainWindow, qobject_cast(watched)); } } return false; } void ToolsAreaManager::registerWidget(QWidget *widget) { Q_ASSERT(widget); auto ptr = QPointer(widget); QPointer mainWindow = qobject_cast(ptr); if (mainWindow && mainWindow.data() == mainWindow->window()) { const auto toolBars = mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly); for (auto *toolBar : toolBars) { tryRegisterToolBar(mainWindow, toolBar); } if (QMenuBar *menuBar = mainWindow->menuBar()) { menuBar->setPalette(_palette); } return; } auto parent = ptr; while (parent != nullptr) { if (qobject_cast(parent) || qobject_cast(parent)) { break; } if (auto window = qobject_cast(parent)) { mainWindow = window; } parent = parent->parentWidget(); } if (mainWindow == nullptr) { return; } if (mainWindow.data() != mainWindow->window()) { return; } tryRegisterToolBar(mainWindow, widget); } void ToolsAreaManager::unregisterWidget(QWidget *widget) { Q_ASSERT(widget); auto ptr = QPointer(widget); if (QPointer window = qobject_cast(ptr)) { removeWindow(window); return; } else if (QPointer toolbar = qobject_cast(ptr)) { auto parent = ptr; QPointer mainWindow = nullptr; while (parent != nullptr) { if (qobject_cast(parent)) { mainWindow = qobject_cast(parent); break; } parent = parent->parentWidget(); } if (mainWindow == nullptr) { return; } removeWindowToolBar(mainWindow, toolbar); } } bool Breeze::ToolsAreaManager::hasHeaderColors() { return _colorSchemeHasHeaderColor; } }