diff --git a/kstyle/CMakeLists.txt b/kstyle/CMakeLists.txt --- a/kstyle/CMakeLists.txt +++ b/kstyle/CMakeLists.txt @@ -93,6 +93,7 @@ breezestyleplugin.cpp breezetileset.cpp breezewindowmanager.cpp + breezetoolsareamanager.cpp ) kconfig_add_kcfg_files(breeze_PART_SRCS breezestyleconfigdata.kcfgc) diff --git a/kstyle/breeze.h b/kstyle/breeze.h --- a/kstyle/breeze.h +++ b/kstyle/breeze.h @@ -187,7 +187,8 @@ AnimationHover = 0x1, AnimationFocus = 0x2, AnimationEnable = 0x4, - AnimationPressed = 0x8 + AnimationPressed = 0x8, + AnimationWindowFocused = 0x10, }; Q_DECLARE_FLAGS(AnimationModes, AnimationMode) diff --git a/kstyle/breezehelper.h b/kstyle/breezehelper.h --- a/kstyle/breezehelper.h +++ b/kstyle/breezehelper.h @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -245,6 +246,9 @@ //* generic shadow for ellipses void renderEllipseShadow( QPainter*, const QRectF&, const QColor& ) const; + + //* draw the tools area border + void renderToolsAreaBorder ( QPainter*, const QWidget* ) const; //@} @@ -263,6 +267,17 @@ //* returns true if a given widget supports alpha channel bool hasAlphaChannel( const QWidget* ) const; + //* returns true if widget is in the tools area + bool isInToolsArea( const QWidget* ) const; + + //* returns true if tools area has a toolbar + bool toolsAreaHasToolBar ( const QWidget* ) const; + + //* returns true if the tools area should be drawn + bool shouldDrawToolsArea ( const QWidget* ) const; + + QToolBar* grabToolBarForToolsArea ( const QWidget* ) const; + //@} //@name high dpi utility functions diff --git a/kstyle/breezehelper.cpp b/kstyle/breezehelper.cpp --- a/kstyle/breezehelper.cpp +++ b/kstyle/breezehelper.cpp @@ -27,6 +27,10 @@ #include #include +#include +#include +#include +#include #if BREEZE_HAVE_X11 #include @@ -1604,4 +1608,118 @@ return pixmap.devicePixelRatio(); } + bool Helper::isInToolsArea(const QWidget* widget) const + { + if (shouldDrawToolsArea(widget)) return false; + + auto castedWidget = const_cast(widget); + + auto grabMainWindow = [](QWidget *widget) { + auto window = qobject_cast(widget->window()); + return window; + }; + auto checkToolbarInToolsArea = [grabMainWindow](QWidget* widget) { + auto toolbar = qobject_cast(widget); + + if (toolbar == nullptr) { + return false; + } + + QMainWindow* window; + if (window = grabMainWindow(widget)) { + if (window->toolBarArea(toolbar) != Qt::TopToolBarArea) { + return false; + } + if (window->width() != toolbar->width()) { + return false; + } + } + + return true; + }; + auto checkMenubarInToolsArea = [grabMainWindow](QWidget *widget) { + QMainWindow* window; + if (window = grabMainWindow(widget)) { + if (window->menuWidget() == widget) { + return true; + } + } + + return false; + }; + + if (!widget->isVisible()) { + return false; + } + if (checkToolbarInToolsArea(castedWidget)) { + return true; + } else if (checkMenubarInToolsArea(castedWidget)) { + return true; + } else { + auto parent = castedWidget->parentWidget(); + while (parent != nullptr) { + if (checkToolbarInToolsArea(parent)) { + return true; + } + if (checkMenubarInToolsArea(parent)) { + return true; + } + parent = parent->parentWidget(); + } + } + + return false; + } + + bool Helper::toolsAreaHasToolBar (const QWidget* widget) const { + if (shouldDrawToolsArea(widget)) return false; + + auto mainWindow = qobject_cast(widget->window()); + if (mainWindow == nullptr) { + return false; + } + + QList widgets = mainWindow->findChildren(); + for (auto widget : widgets) { + return this->isInToolsArea(widget); + } + + return false; + } + + void Helper::renderToolsAreaBorder(QPainter* painter, const QWidget* widget) const { + if (shouldDrawToolsArea(widget)) return; + + QColor outline( KColorUtils::mix( widget->palette().color( QPalette::Window ), widget->palette().color( QPalette::WindowText ), 0.75 ) ); + + painter->setPen(QPen(outline, 1*widget->screen()->devicePixelRatio())); + painter->setBrush(Qt::NoBrush); + + painter->drawLine( + widget->rect().left() - 100, + widget->rect().bottom()+1, + widget->rect().right() + 100, + widget->rect().bottom()+1 + ); + } + + QToolBar* Helper::grabToolBarForToolsArea(const QWidget *widget) const { + auto mainWindow = qobject_cast(widget->window()); + if (mainWindow == nullptr) { + return nullptr; + } + + QList widgets = mainWindow->findChildren(); + for (auto widget : widgets) { + if (this->isInToolsArea(widget)) { + return widget; + } + } + + return nullptr; + } + + bool Helper::shouldDrawToolsArea(const QWidget* widget) const { + return widget->palette().color(QPalette::Window) == this->titleBarColor(true); + } } diff --git a/kstyle/breezestyle.h b/kstyle/breezestyle.h --- a/kstyle/breezestyle.h +++ b/kstyle/breezestyle.h @@ -60,6 +60,7 @@ class WidgetExplorer; class WindowManager; class BlurHelper; + class ToolsAreaManager; //* convenience typedef for base class #if !BREEZE_HAVE_KSTYLE @@ -306,6 +307,8 @@ bool drawToolBoxTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawToolBoxTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawDockWidgetTitleControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawToolBarControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawMenuBarEmptyAreaControl( const QStyleOption*, QPainter*, const QWidget* ) const; //*@} @@ -497,6 +500,9 @@ //* splitter Factory, to extend splitters hit area SplitterFactory* _splitterFactory = nullptr; + //* signal manager for the tools area + ToolsAreaManager* _toolsAreaManager; + //* widget explorer WidgetExplorer* _widgetExplorer = nullptr; diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp --- a/kstyle/breezestyle.cpp +++ b/kstyle/breezestyle.cpp @@ -31,6 +31,7 @@ #include "breezewidgetexplorer.h" #include "breezewindowmanager.h" #include "breezeblurhelper.h" +#include "breezetoolsareamanager.h" #include @@ -52,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -166,6 +168,7 @@ , _splitterFactory( new SplitterFactory( this ) ) , _widgetExplorer( new WidgetExplorer( this ) ) , _tabBarData( new BreezePrivate::TabBarData( this ) ) + , _toolsAreaManager ( new ToolsAreaManager(this) ) #if BREEZE_HAVE_KSTYLE , SH_ArgbDndWindow( newStyleHint( QStringLiteral( "SH_ArgbDndWindow" ) ) ) , CE_CapacityBar( newControlElement( QStringLiteral( "CE_CapacityBar" ) ) ) @@ -213,6 +216,7 @@ _mdiWindowShadowFactory->registerWidget( widget ); _shadowHelper->registerWidget( widget ); _splitterFactory->registerWidget( widget ); + _toolsAreaManager->registerWidget ( widget ); // enable mouse over effects for all necessary widgets if( @@ -882,10 +886,10 @@ case CE_RadioButtonLabel: fcn = &Style::drawCheckBoxLabelControl; break; case CE_ToolButtonLabel: fcn = &Style::drawToolButtonLabelControl; break; case CE_ComboBoxLabel: fcn = &Style::drawComboBoxLabelControl; break; - case CE_MenuBarEmptyArea: fcn = &Style::emptyControl; break; + case CE_MenuBarEmptyArea: fcn = &Style::drawMenuBarEmptyAreaControl; break; case CE_MenuBarItem: fcn = &Style::drawMenuBarItemControl; break; case CE_MenuItem: fcn = &Style::drawMenuItemControl; break; - case CE_ToolBar: fcn = &Style::emptyControl; break; + case CE_ToolBar: fcn = &Style::drawToolBarControl; break; case CE_ProgressBar: fcn = &Style::drawProgressBarControl; break; case CE_ProgressBarContents: fcn = &Style::drawProgressBarContentsControl; break; case CE_ProgressBarGroove: fcn = &Style::drawProgressBarGrooveControl; break; @@ -4225,7 +4229,12 @@ // copy rect and palette const auto& rect = option->rect; - const auto& palette = option->palette; + auto palette = option->palette; + + if (_helper->isInToolsArea(widget)) { + palette.setColor(QPalette::ButtonText, _helper->titleBarTextColor(widget->isActiveWindow())); + palette.setColor(QPalette::WindowText, _helper->titleBarTextColor(widget->isActiveWindow())); + } // state const State& state( option->state ); @@ -4509,15 +4518,28 @@ // copy rect and palette const auto& rect( option->rect ); - const auto& palette( option->palette ); + auto palette( option->palette ); + + palette.setColor(QPalette::WindowText, _helper->titleBarTextColor(widget->isActiveWindow())); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( enabled && (state & State_Selected) ); const bool sunken( enabled && (state & State_Sunken) ); const bool useStrongFocus( StyleConfigData::menuItemDrawStrongFocus() ); + painter->save(); + painter->setRenderHints( QPainter::Antialiasing ); + + painter->setPen(_helper->titleBarColor(widget->isActiveWindow())); + painter->setBrush(_helper->titleBarColor(widget->isActiveWindow())); + + QRectF copy(widget->geometry()); + copy.setTop(widget->childrenRect().top()); + + painter->drawRect(copy); + // render hover and focus if( useStrongFocus && ( selected || sunken ) ) { @@ -4596,8 +4618,13 @@ } - return true; + if (!_helper->toolsAreaHasToolBar(widget)) { + _helper->renderToolsAreaBorder(painter, widget); + } + painter->restore(); + + return true; } @@ -4817,6 +4844,63 @@ return true; } + bool Style::drawToolBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const + { + auto toolbar = const_cast(qobject_cast(widget)); + + if (!_helper->isInToolsArea(widget)) { + toolbar->setPalette(toolbar->parentWidget()->palette()); + return true; + } + + + auto palette = toolbar->palette(); + palette.setColor( QPalette::WindowText, _helper->titleBarTextColor( widget->isActiveWindow() ) ); + + toolbar->setPalette(palette); + + painter->save(); + painter->setRenderHints( QPainter::Antialiasing ); + + painter->setPen(_helper->titleBarColor(widget->isActiveWindow())); + painter->setBrush(_helper->titleBarColor(widget->isActiveWindow())); + + QRectF copy(widget->geometry()); + copy.setTop(widget->childrenRect().top() - 10); + + painter->drawRect(copy); + + _helper->renderToolsAreaBorder(painter, widget); + + painter->restore(); + return true; + } + + bool Style::drawMenuBarEmptyAreaControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const + { + if (!_helper->isInToolsArea(widget)) { + return true; + } + + painter->save(); + painter->setRenderHints( QPainter::Antialiasing ); + + painter->setPen(_helper->titleBarColor(widget->isActiveWindow())); + painter->setBrush(_helper->titleBarColor(widget->isActiveWindow())); + + QRectF copy(widget->geometry()); + copy.setTop(widget->childrenRect().top()); + + painter->drawRect(copy); + + if (!_helper->toolsAreaHasToolBar(widget)) { + _helper->renderToolsAreaBorder(painter, widget); + } + + painter->restore(); + return true; + } + //___________________________________________________________________________________ bool Style::drawProgressBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { diff --git a/kstyle/breezetoolsareamanager.h b/kstyle/breezetoolsareamanager.h new file mode 100644 --- /dev/null +++ b/kstyle/breezetoolsareamanager.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace Breeze { + class ToolsAreaManager: public QObject + { + Q_OBJECT + + public: + explicit ToolsAreaManager(QObject *parent = nullptr); + void registerWidget(QWidget *widget); + + Q_SIGNALS: + void toolbarUpdated(); + }; +} \ No newline at end of file diff --git a/kstyle/breezetoolsareamanager.cpp b/kstyle/breezetoolsareamanager.cpp new file mode 100644 --- /dev/null +++ b/kstyle/breezetoolsareamanager.cpp @@ -0,0 +1,31 @@ +#include "breezetoolsareamanager.h" +#include +#include +#include + +namespace Breeze { + ToolsAreaManager::ToolsAreaManager(QObject *parent) : QObject(parent) {} + + void ToolsAreaManager::registerWidget(QWidget *widget) + { + connect(this, &ToolsAreaManager::toolbarUpdated, + widget, [widget]() { + widget->update(); + }); + auto toolbar = qobject_cast(widget); + if (toolbar) { + connect(toolbar, &QToolBar::visibilityChanged, + this, [this]() { + emit this->toolbarUpdated(); + }); + connect(toolbar, &QToolBar::orientationChanged, + this, [this]() { + emit this->toolbarUpdated(); + }); + connect(toolbar, &QToolBar::topLevelChanged, + this, [this]() { + emit this->toolbarUpdated(); + }); + } + } +} \ No newline at end of file