Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: c936dbaa7f
Fetching contributors…

Cannot retrieve contributors at this time

8728 lines (6803 sloc) 426.25 kB
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id:$
//
// Copyright (C) 2010 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include <math.h>
#include "mstyle.h"
#include "colorutils.h"
#include "frameshadow.h"
#include "animations.h"
#include "menubarengine.h"
#include "widgetstateengine.h"
#include "transitions.h"
#include "windowmanager.h"
#include "mconfig.h"
#define MgStyleConfigData_toolTipTransparent true
#define MgStyleConfigData_toolBarDrawItemSeparator true
#define MgStyleConfigData_viewDrawTriangularExpander true
#define MgStyleConfigData_viewTriangularExpanderSize ArrowNormal
#define MgStyleConfigData_viewDrawTreeBranchLines true
#define MgStyleConfigData_checkBoxStyle_CS_CHECK false
#define MgStyleConfigData_scrollBarColored true
#define MgStyleConfigData_scrollBarBevel true
//---------------------------------------------------------
// MgStyle
//---------------------------------------------------------
MgStyle::MgStyle()
: QCommonStyle()
{
_addLineButtons = DoubleButton;
_subLineButtons = SingleButton;
_singleButtonHeight = 14;
_doubleButtonHeight = 28;
_mnemonic = Qt::TextShowMnemonic;
// _widgetExplorer = new WidgetExplorer(this);
_tabBarData = new TabBarData(this);
_frameFocusPrimitive = 0;
_tabBarTabShapeControl = 0;
_hintCounter = QStyle::SH_CustomBase;
_controlCounter = QStyle::CE_CustomBase;
_subElementCounter = QStyle::SE_CustomBase;
CE_CapacityBar = newControlElement("CE_CapacityBar");
_animations = new Animations(this);
_transitions = new Transitions(this);
// _windowManager = new WindowManager(this);
_frameShadowFactory = new FrameShadowFactory(this);
configurationChanged();
}
//---------------------------------------------------------
// drawMenuBarItem
//---------------------------------------------------------
bool MgStyle::drawMenuBarItem(const QStyleOption* option, QPainter* painter,
const QWidget* widget) const
{
const QStyleOptionMenuItem* menuOpt = ::qstyleoption_cast<const QStyleOptionMenuItem*>(option);
if (!menuOpt)
return true;
const State& flags(option->state);
const bool enabled(flags & State_Enabled);
const QRect& r(option->rect);
const QPalette& palette(option->palette);
if (enabled) {
const bool active(flags & State_Selected);
const bool animated(animations().menuBarEngine().isAnimated(widget, r.topLeft()));
const qreal opacity(animations().menuBarEngine().opacity(widget, r.topLeft()));
const QRect currentRect(animations().menuBarEngine().currentRect(widget, r.topLeft()));
const QRect animatedRect(animations().menuBarEngine().animatedRect(widget));
const bool intersected(animatedRect.intersects(r));
const bool current(currentRect.contains(r.topLeft()));
const bool timerIsActive(animations().menuBarEngine().isTimerActive(widget));
// do nothing in case of empty intersection between animated rect and current
if ((intersected || !animated || animatedRect.isNull()) && (active || animated || timerIsActive)) {
QColor color(palette.color(QPalette::Window));
if (MgStyleConfigData::menuHighlightMode != MgStyleConfigData::MM_DARK) {
if (flags & State_Sunken) {
if (MgStyleConfigData::menuHighlightMode == MgStyleConfigData::MM_STRONG)
color = palette.color(QPalette::Highlight);
else
color = ColorUtils::mix(color, ColorUtils::tint(color, palette.color(QPalette::Highlight), 0.6));
}
else {
if (MgStyleConfigData::menuHighlightMode == MgStyleConfigData::MM_STRONG)
color = ColorUtils::tint(color, _helper.viewHoverBrush().brush(palette).color());
else
color = ColorUtils::mix(color, ColorUtils::tint(color, _helper.viewHoverBrush().brush(palette).color()));
}
}
else
color = _helper.calcMidColor(_helper.backgroundColor(color, widget, r.center()));
// drawing
if (animated && intersected)
_helper.holeFlat(color, 0.0)->render(animatedRect.adjusted(1,1,-1,-1), painter, TileSet::Full);
else if (timerIsActive && current)
_helper.holeFlat(color, 0.0)->render(r.adjusted(1,1,-1,-1), painter, TileSet::Full);
else if (animated && current) {
color.setAlphaF(opacity);
_helper.holeFlat(color, 0.0)->render(r.adjusted(1,1,-1,-1), painter, TileSet::Full);
}
else if (active )
_helper.holeFlat(color, 0.0)->render(r.adjusted(1,1,-1,-1), painter, TileSet::Full);
}
}
// text
QPalette::ColorRole role(QPalette::WindowText);
if (MgStyleConfigData::menuHighlightMode == MgStyleConfigData::MM_STRONG && (flags & State_Sunken) && enabled)
role = QPalette::HighlightedText;
drawItemText(painter, r, Qt::AlignCenter | Qt::TextShowMnemonic, palette, enabled, menuOpt->text, role);
return true;
}
//---------------------------------------------------------
// pixelMetric
//---------------------------------------------------------
int MgStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget ) const
{
switch (metric) {
// rely on QCommonStyle here
case PM_SmallIconSize:
case PM_ButtonIconSize:
return 16;
case PM_ToolBarIconSize:
return 22;
case PM_LargeIconSize:
return 32; //??
case PM_MessageBoxIconSize:
return 22; //??
case PM_DefaultFrameWidth:
{
if( qobject_cast<const QLineEdit*>(widget) )
return LineEdit_FrameWidth;
else if( qobject_cast<const QComboBox*>(widget))
return ComboBox_FrameWidth;
else if( qobject_cast<const QFrame*>(widget) )
return Frame_FrameWidth;
else if( qstyleoption_cast<const QStyleOptionGroupBox *>(option) )
return GroupBox_FrameWidth;
else
return 1;
}
case PM_LayoutLeftMargin:
case PM_LayoutTopMargin:
case PM_LayoutRightMargin:
case PM_LayoutBottomMargin:
{
// use either Child margin or TopLevel margin, depending on
// widget type
if ((option && (option->state & QStyle::State_Window)) || (widget && widget->isWindow())) {
return pixelMetric( PM_DefaultTopLevelMargin, option, widget );
}
else {
return pixelMetric( PM_DefaultChildMargin, option, widget );
}
}
// push buttons
case PM_ButtonMargin:
return 5;
case PM_MenuButtonIndicator:
if (qstyleoption_cast<const QStyleOptionToolButton*>(option))
return ToolButton_MenuIndicatorSize;
else
return PushButton_MenuIndicatorSize;
case PM_ScrollBarExtent:
return MgStyleConfigData::scrollBarWidth + 2;
// tooltip label
case PM_ToolTipLabelFrameWidth:
if (MgStyleConfigData::toolTipDrawStyledFrames)
return 3;
else
break;
case PM_DefaultChildMargin: return 4;
case PM_DefaultTopLevelMargin: return 11;
case PM_DefaultLayoutSpacing: return 4;
// case PM_LayoutHorizontalSpacing: return -1; // this crashes qt4.8
// case PM_LayoutVerticalSpacing: return -1;
case PM_LayoutHorizontalSpacing: return 0;
case PM_LayoutVerticalSpacing: return 0;
// buttons
case PM_ButtonDefaultIndicator: return 0;
case PM_ButtonShiftHorizontal: return 0;
case PM_ButtonShiftVertical: return 0;
// checkboxes: return radiobutton sizes
case PM_IndicatorWidth: return CheckBox_Size;
case PM_IndicatorHeight: return CheckBox_Size;
case PM_ExclusiveIndicatorWidth: return CheckBox_Size;
case PM_ExclusiveIndicatorHeight: return CheckBox_Size;
// case PM_CheckListControllerSize: return CheckBox_Size;
// case PM_CheckListButtonSize: return CheckBox_Size;
// splitters and dock widgets
case PM_SplitterWidth: return Splitter_Width;
case PM_DockWidgetFrameWidth: return DockWidget_FrameWidth;
case PM_DockWidgetSeparatorExtent: return DockWidget_SeparatorExtend;
case PM_DockWidgetTitleMargin: return DockWidget_TitleMargin;
// progress bar
case PM_ProgressBarChunkWidth: return 1;
// menu bars
case PM_MenuBarPanelWidth: return 0;
case PM_MenuBarHMargin: return 0;
case PM_MenuBarVMargin: return 0;
case PM_MenuBarItemSpacing: return 0;
case PM_MenuDesktopFrameWidth: return 0;
case PM_MenuPanelWidth: return 5;
case PM_MenuScrollerHeight: return 10;
case PM_MenuTearoffHeight: return 10;
//! tabbar
case PM_TabBarTabHSpace: return 0;
case PM_TabBarTabVSpace: return 0;
case PM_TabBarBaseHeight: return TabBar_BaseHeight;
case PM_TabBarBaseOverlap: return TabBar_BaseOverlap;
case PM_TabBarTabOverlap: return 0;
case PM_TabBarScrollButtonWidth: return TabBar_ScrollButtonWidth;
/*
disable shifts: return because last time I checked it did not work well
for South and East tabs. Instead the shifts are added directly in
drawTabBarTabLabel. (Hugo)
*/
case PM_TabBarTabShiftVertical: return 0;
case PM_TabBarTabShiftHorizontal: return 0;
// sliders
case PM_SliderThickness: return 23;
case PM_SliderControlThickness: return 23;
case PM_SliderLength: return 13;
// spinboxes
case PM_SpinBoxFrameWidth: return SpinBox_FrameWidth;
// comboboxes
case PM_ComboBoxFrameWidth: return ComboBox_FrameWidth;
// tree view header
case PM_HeaderMarkSize: return 9;
case PM_HeaderMargin: return 3;
// toolbars
case PM_ToolBarFrameWidth: return 0;
case PM_ToolBarHandleExtent: return 6;
case PM_ToolBarSeparatorExtent: return 6;
case PM_ToolBarExtensionExtent: return 16;
case PM_ToolBarItemMargin: return 1;
case PM_ToolBarItemSpacing: return 1;
// MDI windows titlebars
case PM_TitleBarHeight: return 20;
// spacing between widget and scrollbars
case PM_ScrollView_ScrollBarSpacing:
if (const QFrame* frame = qobject_cast<const QFrame*>(widget)) {
const bool framed(frame->frameShape() != QFrame::NoFrame);
return framed ? -2 : 0;
}
else
return -2;
default:
break;
}
return QCommonStyle::pixelMetric(metric, option, widget);
}
//---------------------------------------------------------
// expandSize
// expand size based on margins
//---------------------------------------------------------
QSize MgStyle::expandSize(const QSize& size, int main, int left, int top, int right, int bottom) const
{
return size + QSize(2*main+left+right, 2*main+top+bottom);
}
//---------------------------------------------------------
// sizeFromContents
//---------------------------------------------------------
QSize MgStyle::sizeFromContents(ContentsType element, const QStyleOption* option, const QSize& size, const QWidget* widget) const
{
switch(element) {
case CT_CheckBox: return checkBoxSizeFromContents(option, size, widget);
case CT_ComboBox: return comboBoxSizeFromContents(option, size, widget);
case CT_HeaderSection: return headerSectionSizeFromContents(option, size, widget);
case CT_PushButton: return pushButtonSizeFromContents(option, size, widget);
case CT_MenuBar: return size;
case CT_MenuBarItem:
return expandSize(size, MenuBarItem_Margin, MenuBarItem_Margin_Left, 0, MenuBarItem_Margin_Right, 0);
case CT_MenuItem: return menuItemSizeFromContents(option, size, widget);
case CT_RadioButton: return checkBoxSizeFromContents(option, size, widget);
case CT_TabBarTab: return tabBarTabSizeFromContents(option, size, widget);
case CT_TabWidget: return expandSize(size, TabWidget_ContentsMargin);
case CT_ToolButton: return toolButtonSizeFromContents(option, size, widget);
default: return QCommonStyle::sizeFromContents(element, option, size, widget);
}
}
//---------------------------------------------------------
// checkBoxSizeFromContents
//---------------------------------------------------------
QSize MgStyle::checkBoxSizeFromContents(const QStyleOption*, const QSize& contentsSize, const QWidget*) const
{
//Add size for indicator
const int indicator( CheckBox_Size );
//Make sure we can fit the indicator
QSize size( contentsSize );
size.setHeight(qMax(size.height(), indicator));
//Add space for the indicator and the icon
const int spacer = CheckBox_BoxTextSpace;
size.rwidth() += indicator + spacer;
return size;
}
//---------------------------------------------------------
// comboBoxSizeFromContents
//---------------------------------------------------------
QSize MgStyle::comboBoxSizeFromContents( const QStyleOption* option, const QSize& contentsSize, const QWidget*) const
{
QSize size = expandSize( contentsSize,
ComboBox_ContentsMargin,
ComboBox_ContentsMargin_Left,
ComboBox_ContentsMargin_Top,
ComboBox_ContentsMargin_Right,
ComboBox_ContentsMargin_Bottom );
// add frame width
size = expandSize(size, ComboBox_FrameWidth);
// Add the button width
size.rwidth() += ComboBox_ButtonWidth;
// TODO: For some reason the size is not right in the following configurations
// this is still to be understood and might reveal some deeper issue.
// notably, should compare to zhqt is done for PushButtons
const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option);
if (cb && !cb->editable && (!cb->currentIcon.isNull() || cb->fontMetrics.height() > 13))
size.rheight() += 1;
// also expand to account for scrollbar
size.rwidth() += MgStyleConfigData::scrollBarWidth - 6;
return size;
}
//---------------------------------------------------------
// headerSectionSizeFromContents
//---------------------------------------------------------
QSize MgStyle::headerSectionSizeFromContents(const QStyleOption* option, const QSize& contentsSize, const QWidget*) const
{
const QStyleOptionHeader* headerOpt( qstyleoption_cast<const QStyleOptionHeader *>( option ));
if( !headerOpt )
return contentsSize;
//TODO: check if hardcoded icon size is the right thing to do
QSize iconSize = headerOpt->icon.isNull() ? QSize(0,0) : QSize(22,22);
QSize textSize = headerOpt->fontMetrics.size(0, headerOpt->text);
int iconSpacing = Header_TextToIconSpace;
int w = iconSize.width() + iconSpacing + textSize.width();
int h = qMax(iconSize.height(), textSize.height() );
return expandSize( QSize(w, h), Header_ContentsMargin );
}
//---------------------------------------------------------
// menuItemSizeFromContents
//---------------------------------------------------------
QSize MgStyle::menuItemSizeFromContents(const QStyleOption* option, const QSize& contentsSize, const QWidget* widget) const
{
const QStyleOptionMenuItem* menuItemOption = qstyleoption_cast<const QStyleOptionMenuItem*>(option);
if( !menuItemOption)
return contentsSize;
// First, we calculate the intrinsic size of the item.
// this must be kept consistent with what's in drawMenuItemContol
QSize insideSize;
switch (menuItemOption->menuItemType) {
case QStyleOptionMenuItem::Normal:
case QStyleOptionMenuItem::DefaultItem:
case QStyleOptionMenuItem::SubMenu:
{
int iconColW = qMax( menuItemOption->maxIconWidth, (int) MenuItem_IconWidth );
int leftColW = iconColW;
if( menuItemOption->menuHasCheckableItems ) {
leftColW += MenuItem_CheckWidth + MenuItem_CheckSpace; }
leftColW += MenuItem_IconSpace;
int rightColW = MenuItem_ArrowSpace + MenuItem_ArrowWidth;
QFontMetrics fm(menuItemOption->font);
int textW;
int tabPos = menuItemOption->text.indexOf(QLatin1Char('\t'));
if( tabPos == -1)
textW = contentsSize.width();
else {
// The width of the accelerator is not included here since
// Qt will add that on separately after obtaining the
// sizeFromContents() for each menu item in the menu to be shown
// ( see QMenuPrivate::calcActionRects() )
textW = contentsSize.width() + MenuItem_AccelSpace;
}
int h = qMax(contentsSize.height(), (int) MenuItem_MinHeight );
insideSize = QSize(leftColW + textW + rightColW, h);
break;
}
case QStyleOptionMenuItem::Separator:
{
// separator can have a title and an icon
// in that case they are rendered as menubar 'title', which
// corresponds to checked toolbuttons.
// a rectangle identical to the one of normal items is returned.
if( !( menuItemOption->text.isEmpty() && menuItemOption->icon.isNull() ) ) {
QStyleOptionMenuItem local( *menuItemOption );
local.menuItemType = QStyleOptionMenuItem::Normal;
return menuItemSizeFromContents( &local, contentsSize, widget );
}
else {
insideSize = QSize(10, 0);
break;
}
}
case QStyleOptionMenuItem::Scroller:
case QStyleOptionMenuItem::TearOff:
case QStyleOptionMenuItem::Margin:
case QStyleOptionMenuItem::EmptyArea:
return contentsSize;
}
// apply the outermost margin.
return expandSize(insideSize, MenuItem_Margin );
}
//---------------------------------------------------------
// pushButtonSizeFromContents
//---------------------------------------------------------
QSize MgStyle::pushButtonSizeFromContents(const QStyleOption* option, const QSize& contentsSize, const QWidget*) const
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt)
return contentsSize;
// adjust to handle button margins
QSize size = expandSize(contentsSize,
PushButton_ContentsMargin,
PushButton_ContentsMargin_Left,
PushButton_ContentsMargin_Top,
PushButton_ContentsMargin_Right,
PushButton_ContentsMargin_Bottom);
if( bOpt->features & QStyleOptionButton::HasMenu)
size.rwidth() += PushButton_TextToIconSpace;
if( !bOpt->text.isEmpty() && !bOpt->icon.isNull()) {
// Incorporate the spacing between the icon and text. Qt sticks 4 there,
// but we use PushButton::TextToIconSpace.
size.rwidth() += PushButton_TextToIconSpace - 4;
}
return size;
}
//---------------------------------------------------------
// tabBarTabSizeFromContents
//---------------------------------------------------------
QSize MgStyle::tabBarTabSizeFromContents(const QStyleOption* option, const QSize& contentsSize, const QWidget* widget) const
{
const QStyleOptionTab *tabOpt( qstyleoption_cast<const QStyleOptionTab*>(option) );
QSize size;
const bool verticalTabs(tabOpt && isVerticalTab(tabOpt));
if( verticalTabs ) {
size = expandSize( contentsSize,
TabBar_TabContentsMargin,
TabBar_TabContentsMargin_Top,
TabBar_TabContentsMargin_Right,
TabBar_TabContentsMargin_Bottom,
TabBar_TabContentsMargin_Left );
}
else {
size = expandSize( contentsSize,
TabBar_TabContentsMargin,
TabBar_TabContentsMargin_Left,
TabBar_TabContentsMargin_Top,
TabBar_TabContentsMargin_Right,
TabBar_TabContentsMargin_Bottom );
}
// need to add extra size to match corner buttons
// try cast parent for tabWidget
const QTabWidget* tabWidget( widget ? qobject_cast<const QTabWidget*>( widget->parent() ):0 );
if( !tabWidget )
return size;
// try get corner widgets
const QWidget* leftWidget( tabWidget->cornerWidget( Qt::TopLeftCorner ) );
const QWidget* rightWidget( tabWidget->cornerWidget( Qt::TopRightCorner ) );
QSize cornerSize;
if( leftWidget && leftWidget->isVisible() )
cornerSize = leftWidget->minimumSizeHint();
if( rightWidget && rightWidget->isVisible() )
cornerSize = cornerSize.expandedTo( rightWidget->minimumSizeHint() );
if( !cornerSize.isValid() )
return size;
// expand size
// note: the extra pixels added to the relevant dimension are fine-tuned.
if( verticalTabs )
size.setWidth( qMax( size.width(), cornerSize.width() + 6 ) );
else
size.setHeight( qMax( size.height(), cornerSize.height() + 4 ) );
return size;
}
//---------------------------------------------------------
// toolButtonSizeFromContents
//---------------------------------------------------------
QSize MgStyle::toolButtonSizeFromContents(const QStyleOption* option, const QSize& contentsSize, const QWidget* widget) const
{
QSize size = contentsSize;
const QStyleOptionToolButton* tbOpt = qstyleoption_cast<const QStyleOptionToolButton*>(option);
if( tbOpt && !tbOpt->icon.isNull() && !tbOpt->text.isEmpty() && tbOpt->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
size.rheight() -= 5;
}
// We want to avoid super-skiny buttons, for things like "up" when icons + text
// For this, we would like to make width >= height.
// However, once we get here, QToolButton may have already put in the menu area
// (PM_MenuButtonIndicator) into the width. So we may have to take it out, fix things
// up, and add it back in. So much for class-independent rendering...
int menuAreaWidth = 0;
if( tbOpt ) {
if( tbOpt->features & QStyleOptionToolButton::MenuButtonPopup) {
menuAreaWidth = pixelMetric(QStyle::PM_MenuButtonIndicator, option, widget);
}
else if( tbOpt->features & QStyleOptionToolButton::HasMenu) {
// TODO: something wrong here: The size is not properly accounted for
// when drawing the slab.
size.rwidth() += ToolButton_InlineMenuIndicatorSize;
}
}
size.rwidth() -= menuAreaWidth;
if( size.width() < size.height())
size.setWidth(size.height());
size.rwidth() += menuAreaWidth;
const QToolButton* t( qobject_cast<const QToolButton*>(widget) );
if( t && t->autoRaise() )
return expandSize( size, ToolButton_ContentsMargin ); // these are toolbutton margins
else
return expandSize( size, PushButton_ContentsMargin, 0, PushButton_ContentsMargin_Top, 0,
PushButton_ContentsMargin_Bottom );
}
//---------------------------------------------------------
// isVerticalTab
//---------------------------------------------------------
bool MgStyle::isVerticalTab( const QTabBar::Shape& shape ) const
{
return shape == QTabBar::RoundedEast
|| shape == QTabBar::RoundedWest
|| shape == QTabBar::TriangularEast
|| shape == QTabBar::TriangularWest;
}
//---------------------------------------------------------
// polish
//---------------------------------------------------------
void MgStyle::polish(QWidget* widget)
{
if (!widget)
return;
// register widget to animations
animations().registerWidget(widget);
transitions().registerWidget(widget);
// windowManager().registerWidget(widget);
frameShadowFactory().registerWidget(widget, _helper);
// scroll areas
if (QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(widget))
polishScrollArea(scrollArea );
// several widgets set autofill background to false, which effectively breaks the background
// gradient rendering. Instead of patching all concerned applications,
// we change the background here
if (widget->inherits( "MessageList::Core::Widget")) {
widget->setAutoFillBackground(false);
}
// adjust flags for windows and dialogs
switch(widget->windowFlags() & Qt::WindowType_Mask) {
case Qt::Window:
case Qt::Dialog:
widget->setAttribute(Qt::WA_StyledBackground);
break;
case Qt::ToolTip:
if(!widget->autoFillBackground() ) {
#ifndef Q_WS_MAC
widget->setAttribute(Qt::WA_TranslucentBackground);
#endif
#ifdef Q_WS_WIN
//FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly
widget->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint);
#endif
}
break;
default:
break;
}
if (qobject_cast<QAbstractItemView*>(widget)
|| qobject_cast<QAbstractSpinBox*>(widget)
|| qobject_cast<QCheckBox*>(widget)
|| qobject_cast<QComboBox*>(widget)
|| qobject_cast<QDial*>(widget)
|| qobject_cast<QLineEdit*>(widget)
|| qobject_cast<QPushButton*>(widget)
|| qobject_cast<QRadioButton*>(widget)
|| qobject_cast<QScrollBar*>(widget)
|| qobject_cast<QSlider*>(widget)
|| qobject_cast<QSplitterHandle*>(widget)
|| qobject_cast<QTabBar*>(widget)
|| qobject_cast<QTextEdit*>(widget)
|| qobject_cast<QToolButton*>(widget)
) {
widget->setAttribute(Qt::WA_Hover);
}
// also enable hover effects in itemviews' viewport
if( QAbstractItemView *itemView = qobject_cast<QAbstractItemView*>(widget)) {
itemView->viewport()->setAttribute(Qt::WA_Hover);
}
// checkable group boxes
if( QGroupBox* groupBox = qobject_cast<QGroupBox*>(widget)) {
if (groupBox->isCheckable())
groupBox->setAttribute(Qt::WA_Hover);
}
else if( qobject_cast<QAbstractButton*>(widget) && qobject_cast<QDockWidget*>( widget->parent() ) ) {
widget->setAttribute(Qt::WA_Hover);
}
else if( qobject_cast<QAbstractButton*>(widget) && qobject_cast<QToolBox*>( widget->parent() ) ) {
widget->setAttribute(Qt::WA_Hover);
}
/*
add extra margins for widgets in toolbars
this allows to preserve alignment with respect to actions
*/
if (qobject_cast<QToolBar*>(widget->parent()))
widget->setContentsMargins(0,0,0,1);
if (qobject_cast<QToolButton*>(widget)) {
if (qobject_cast<QToolBar*>( widget->parent() ) ) {
// this hack is needed to have correct text color
// rendered in toolbars. This does not really update nicely when changing styles
// but is the best I can do for now since setting the palette color at painting
// time is not doable
QPalette palette( widget->palette() );
palette.setColor( QPalette::Disabled, QPalette::ButtonText, palette.color( QPalette::Disabled, QPalette::WindowText ) );
palette.setColor( QPalette::Active, QPalette::ButtonText, palette.color( QPalette::Active, QPalette::WindowText ) );
palette.setColor( QPalette::Inactive, QPalette::ButtonText, palette.color( QPalette::Inactive, QPalette::WindowText ) );
widget->setPalette( palette );
}
widget->setBackgroundRole(QPalette::NoRole);
}
else if (qobject_cast<QMenuBar*>(widget)) {
widget->setBackgroundRole(QPalette::NoRole);
}
else if (qobject_cast<QToolBar*>(widget)) {
widget->setBackgroundRole(QPalette::NoRole);
#ifndef Q_WS_MAC
widget->setAttribute(Qt::WA_TranslucentBackground);
#endif
widget->installEventFilter(this);
#ifdef Q_WS_WIN
//FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly
widget->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint);
#endif
}
else if( qobject_cast<QTabBar*>(widget) ) {
widget->installEventFilter( this );
}
else if( widget->inherits( "QTipLabel" ) ) {
widget->setBackgroundRole(QPalette::NoRole);
#ifndef Q_WS_MAC
widget->setAttribute(Qt::WA_TranslucentBackground);
#endif
#ifdef Q_WS_WIN
//FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly
widget->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint);
#endif
}
else if( qobject_cast<QScrollBar*>(widget) ) {
widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
// when painted in konsole, one needs to paint the window background below
// the scrollarea, otherwise an ugly flat background is used
if( widget->parent() && widget->parent()->inherits( "Konsole::TerminalDisplay" ) ) {
widget->installEventFilter( this );
}
}
else if( qobject_cast<QDockWidget*>(widget)) {
widget->setBackgroundRole(QPalette::NoRole);
#ifndef Q_WS_MAC
widget->setAttribute(Qt::WA_TranslucentBackground);
#endif
widget->setContentsMargins(3,3,3,3);
widget->installEventFilter(this);
}
else if( qobject_cast<QMdiSubWindow*>(widget) ) {
widget->setAutoFillBackground( false );
widget->installEventFilter( this );
}
else if( qobject_cast<QToolBox*>(widget)) {
widget->setBackgroundRole(QPalette::NoRole);
widget->setAutoFillBackground(false);
widget->setContentsMargins(5,5,5,5);
widget->installEventFilter(this);
}
else if( widget->parentWidget() && widget->parentWidget()->parentWidget() && qobject_cast<QToolBox*>(widget->parentWidget()->parentWidget()->parentWidget())) {
widget->setBackgroundRole(QPalette::NoRole);
widget->setAutoFillBackground(false);
widget->parentWidget()->setAutoFillBackground(false);
}
else if( qobject_cast<QMenu*>(widget) ) {
#ifndef Q_WS_MAC
// does not work on MAC
widget->setAttribute(Qt::WA_TranslucentBackground);
#endif
#ifdef Q_WS_WIN
//FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly
widget->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint);
#endif
}
else if( widget->inherits("QComboBoxPrivateContainer")) {
widget->installEventFilter(this);
#ifndef Q_WS_MAC
widget->setAttribute(Qt::WA_TranslucentBackground);
#endif
#ifdef Q_WS_WIN
//FramelessWindowHint is needed on windows to make WA_TranslucentBackground work properly
widget->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint);
#endif
}
#if 0
else if( widget->inherits( "KWin::GeometryTip" ) ) {
// special handling of kwin geometry tip widget
widget->installEventFilter(this);
widget->setAttribute(Qt::WA_NoSystemBackground);
widget->setAttribute(Qt::WA_TranslucentBackground);
if( QLabel* label = qobject_cast<QLabel*>( widget ) ) {
label->setFrameStyle( QFrame::NoFrame );
label->setMargin(5);
}
#ifdef Q_WS_WIN
widget->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint);
#endif
}
#endif
else if( qobject_cast<QFrame*>( widget ) && widget->parent() && widget->parent()->inherits( "KTitleWidget" ) ) {
widget->setAutoFillBackground( false );
widget->setBackgroundRole( QPalette::Window );
}
// base class polishing
QCommonStyle::polish(widget);
}
//---------------------------------------------------------
// unpolish
//---------------------------------------------------------
void MgStyle::unpolish(QWidget* widget)
{
// register widget to animations
animations().unregisterWidget(widget);
transitions().unregisterWidget(widget);
// windowManager().unregisterWidget( widget );
frameShadowFactory().unregisterWidget( widget );
// event filters
switch (widget->windowFlags() & Qt::WindowType_Mask) {
case Qt::Window:
case Qt::Dialog:
widget->removeEventFilter(this);
widget->setAttribute(Qt::WA_StyledBackground, false);
break;
default:
break;
}
// checkable group boxes
if (QGroupBox* groupBox = qobject_cast<QGroupBox*>(widget)) {
if (groupBox->isCheckable())
groupBox->setAttribute(Qt::WA_Hover, false);
}
// hover flags
if(
qobject_cast<QAbstractItemView*>(widget)
|| qobject_cast<QAbstractSpinBox*>(widget)
|| qobject_cast<QCheckBox*>(widget)
|| qobject_cast<QComboBox*>(widget)
|| qobject_cast<QDial*>(widget)
|| qobject_cast<QLineEdit*>(widget)
|| qobject_cast<QPushButton*>(widget)
|| qobject_cast<QRadioButton*>(widget)
|| qobject_cast<QScrollBar*>(widget)
|| qobject_cast<QSlider*>(widget)
|| qobject_cast<QSplitterHandle*>(widget)
|| qobject_cast<QTabBar*>(widget)
|| qobject_cast<QTextEdit*>(widget)
|| qobject_cast<QToolButton*>(widget)
) {
widget->setAttribute(Qt::WA_Hover, false);
}
// checkable group boxes
if (QGroupBox* groupBox = qobject_cast<QGroupBox*>(widget)) {
if (groupBox->isCheckable())
groupBox->setAttribute(Qt::WA_Hover, false);
}
if( qobject_cast<QMenuBar*>(widget)
|| (widget && widget->inherits("Q3ToolBar"))
|| qobject_cast<QToolBar*>(widget)
|| (widget && qobject_cast<QToolBar *>(widget->parent()))
|| qobject_cast<QToolBox*>(widget)) {
widget->setBackgroundRole(QPalette::Button);
widget->removeEventFilter(this);
widget->clearMask();
}
if( qobject_cast<QTabBar*>(widget) ) {
widget->removeEventFilter( this );
}
else if( widget->inherits( "QTipLabel" ) ) {
widget->setAttribute(Qt::WA_PaintOnScreen, false);
widget->setAttribute(Qt::WA_NoSystemBackground, false);
widget->clearMask();
}
else if( qobject_cast<QScrollBar*>(widget) ) {
widget->setAttribute(Qt::WA_OpaquePaintEvent);
}
else if( qobject_cast<QDockWidget*>(widget) ) {
widget->setContentsMargins(0,0,0,0);
widget->clearMask();
}
else if( qobject_cast<QToolBox*>(widget) ) {
widget->setBackgroundRole(QPalette::Button);
widget->setContentsMargins(0,0,0,0);
widget->removeEventFilter(this);
}
else if( qobject_cast<QMenu*>(widget) ) {
widget->setAttribute(Qt::WA_PaintOnScreen, false);
widget->setAttribute(Qt::WA_NoSystemBackground, false);
widget->clearMask();
}
else if( widget->inherits("QComboBoxPrivateContainer") )
widget->removeEventFilter(this);
QCommonStyle::unpolish(widget);
}
//---------------------------------------------------------
// polishScrollArea
//---------------------------------------------------------
void MgStyle::polishScrollArea( QAbstractScrollArea* scrollArea ) const
{
if (!scrollArea)
return;
// check frame style and background role
if( scrollArea->frameShape() != QFrame::NoFrame )
return;
if( scrollArea->backgroundRole() != QPalette::Window )
return;
// get viewport and check background role
QWidget* viewport( scrollArea->viewport() );
if( !( viewport && viewport->backgroundRole() == QPalette::Window ) )
return;
// change viewport autoFill background.
// do the same for children if the background role is QPalette::Window
viewport->setAutoFillBackground( false );
QList<QWidget*> children( viewport->findChildren<QWidget*>() );
foreach( QWidget* child, children ) {
if( child->parent() == viewport && child->backgroundRole() == QPalette::Window ) {
child->setAutoFillBackground( false );
}
}
}
//---------------------------------------------------------
// drawPrimitive
//---------------------------------------------------------
void MgStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option,
QPainter* painter, const QWidget* widget) const
{
painter->save();
StylePrimitive fcn(0);
switch(element) {
case PE_FrameStatusBar: fcn = &MgStyle::emptyPrimitive; break;
case PE_Frame: fcn = &MgStyle::drawFramePrimitive; break;
case PE_FrameFocusRect: fcn = _frameFocusPrimitive; break;
case PE_FrameGroupBox: fcn = &MgStyle::drawFrameGroupBoxPrimitive; break;
case PE_FrameLineEdit: fcn = &MgStyle::drawFramePrimitive; break;
case PE_FrameMenu: fcn = &MgStyle::drawFrameMenuPrimitive; break;
case PE_FrameTabBarBase: fcn = &MgStyle::drawFrameTabBarBasePrimitive; break;
case PE_FrameTabWidget: fcn = &MgStyle::drawFrameTabWidgetPrimitive; break;
case PE_FrameWindow: fcn = &MgStyle::drawFrameWindowPrimitive; break;
case PE_IndicatorArrowUp: fcn = &MgStyle::drawIndicatorArrowUpPrimitive; break;
case PE_IndicatorArrowDown: fcn = &MgStyle::drawIndicatorArrowDownPrimitive; break;
case PE_IndicatorArrowLeft: fcn = &MgStyle::drawIndicatorArrowLeftPrimitive; break;
case PE_IndicatorArrowRight: fcn = &MgStyle::drawIndicatorArrowRightPrimitive; break;
case PE_IndicatorDockWidgetResizeHandle: fcn = &MgStyle::drawIndicatorDockWidgetResizeHandlePrimitive; break;
case PE_IndicatorHeaderArrow: fcn = &MgStyle::drawIndicatorHeaderArrowPrimitive; break;
case PE_PanelButtonCommand: fcn = &MgStyle::drawPanelButtonCommandPrimitive; break;
case PE_PanelButtonTool: fcn = &MgStyle::drawPanelButtonToolPrimitive; break;
case PE_PanelItemViewItem: fcn = &MgStyle::drawPanelItemViewItemPrimitive; break;
case PE_PanelLineEdit: fcn = &MgStyle::drawPanelLineEditPrimitive; break;
case PE_PanelMenu: fcn = &MgStyle::drawPanelMenuPrimitive; break;
case PE_PanelScrollAreaCorner: fcn = &MgStyle::drawPanelScrollAreaCornerPrimitive; break;
case PE_PanelTipLabel: fcn = &MgStyle::drawPanelTipLabelPrimitive; break;
case PE_IndicatorBranch: fcn = &MgStyle::drawIndicatorBranchPrimitive; break;
case PE_IndicatorButtonDropDown: fcn = &MgStyle::drawIndicatorButtonDropDownPrimitive; break;
case PE_IndicatorCheckBox: fcn = &MgStyle::drawIndicatorCheckBoxPrimitive; break;
case PE_IndicatorRadioButton: fcn = &MgStyle::drawIndicatorRadioButtonPrimitive; break;
case PE_IndicatorTabTear: fcn = &MgStyle::drawIndicatorTabTearPrimitive; break;
case PE_IndicatorToolBarHandle: fcn = &MgStyle::drawIndicatorToolBarHandlePrimitive; break;
case PE_IndicatorToolBarSeparator: fcn = &MgStyle::drawIndicatorToolBarSeparatorPrimitive; break;
case PE_Widget: fcn = &MgStyle::drawWidgetPrimitive; break;
default:
break;
}
// try find primitive in map, and run.
// exit if result is true, otherwise fallback to generic case
if (!(fcn && (this->*fcn)(option, painter, widget)))
QCommonStyle::drawPrimitive( element, option, painter, widget );
painter->restore();
}
//---------------------------------------------------------
// drawPanelTipLabelPrimitive
//---------------------------------------------------------
bool MgStyle::drawPanelTipLabelPrimitive(const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
// parent style painting if frames should not be styled
if (!MgStyleConfigData::toolTipDrawStyledFrames)
return false;
const QRect& r( option->rect );
const QColor color( option->palette.brush(QPalette::ToolTipBase).color() );
QColor topColor(_helper.backgroundTopColor(color));
QColor bottomColor(_helper.backgroundBottomColor(color));
// make tooltip semi transparents when possible
// alpha is copied from "kdebase/apps/dolphin/tooltips/filemetadatatooltip.cpp"
const bool hasAlpha = _helper.hasAlphaChannel(widget);
if (hasAlpha && MgStyleConfigData_toolTipTransparent) {
topColor.setAlpha(220);
bottomColor.setAlpha(220);
}
QLinearGradient gr(0, r.top(), 0, r.bottom());
gr.setColorAt(0, topColor);
gr.setColorAt(1, bottomColor);
// contrast pixmap
QLinearGradient gr2(0, r.top(), 0, r.bottom());
gr2.setColorAt(0.5, _helper.calcLightColor(bottomColor));
gr2.setColorAt(0.9, bottomColor);
painter->save();
if (hasAlpha) {
painter->setRenderHint(QPainter::Antialiasing);
QRectF local( r );
local.adjust( 0.5, 0.5, -0.5, -0.5 );
painter->setPen( Qt::NoPen );
painter->setBrush( gr );
painter->drawRoundedRect( local, 4, 4 );
painter->setBrush( Qt::NoBrush );
painter->setPen(QPen( gr2, 1.1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawRoundedRect( local, 4, 4 );
}
else {
painter->setPen(Qt::NoPen);
painter->setBrush(gr);
painter->drawRect(r);
painter->setBrush(Qt::NoBrush);
painter->setPen(QPen(gr2, 1.1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawRect(r);
}
painter->restore();
return true;
}
bool MgStyle::drawFramePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
{
const State& flags( option->state );
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const bool enabled( flags & State_Enabled );
const bool isInputWidget( widget && widget->testAttribute( Qt::WA_Hover ) );
const bool hoverHighlight( enabled && isInputWidget && (flags&State_MouseOver) );
//const bool focusHighlight( enabled && isInputWidget && (flags&State_HasFocus) );
bool focusHighlight(false);
if( enabled && isInputWidget && (flags&State_HasFocus) )
focusHighlight = true;
// assume focus takes precedence over hover
animations().lineEditEngine().updateState( widget, AnimationFocus, focusHighlight );
animations().lineEditEngine().updateState( widget, AnimationHover, hoverHighlight && !focusHighlight );
if( flags & State_Sunken) {
const QRect local( r.adjusted( 1, 1, -1, -1 ) );
qreal opacity( -1 );
AnimationMode mode = AnimationNone;
if( enabled && animations().lineEditEngine().isAnimated( widget, AnimationFocus ) )
{
opacity = animations().lineEditEngine().opacity( widget, AnimationFocus );
mode = AnimationFocus;
} else if( enabled && animations().lineEditEngine().isAnimated( widget, AnimationHover ) ) {
opacity = animations().lineEditEngine().opacity( widget, AnimationHover );
mode = AnimationHover;
}
if( frameShadowFactory().isRegistered( widget ) )
{
frameShadowFactory().updateState( widget, focusHighlight, hoverHighlight, opacity, mode );
} else {
_helper.renderHole(
painter, palette.color(QPalette::Window), local, focusHighlight, hoverHighlight,
opacity, mode, TileSet::Ring );
}
} else if( flags & State_Raised ) {
const QRect local( r.adjusted(-1, -1, 1, 1) );
renderSlab( painter, local, palette.color(QPalette::Background), NoFill);
}
return true;
}
bool MgStyle::drawFrameFocusRectPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
{
if( !widget ) return true;
// focus indicators are painted only in Q3ListView and QAbstractItemView
if( !( qobject_cast<const QAbstractItemView*>( widget ) || widget->inherits( "Q3ListView" ) ) ) return true;
const State& flags( option->state );
const QRect r( option->rect.adjusted( 0, 0, 0, -2 ) );
const QPalette& palette( option->palette );
QLinearGradient lg(r.bottomLeft(), r.bottomRight() );
lg.setColorAt(0.0, Qt::transparent);
lg.setColorAt(1.0, Qt::transparent);
if( flags & State_Selected)
{
lg.setColorAt(0.2, palette.color(QPalette::BrightText));
lg.setColorAt(0.8, palette.color(QPalette::BrightText));
} else {
lg.setColorAt(0.2, palette.color(QPalette::Text));
lg.setColorAt(0.8, palette.color(QPalette::Text));
}
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setPen(QPen(lg, 1));
painter->drawLine(r.bottomLeft(), r.bottomRight() );
return true;
}
//---------------------------------------------------------
// drawFrameGroupBoxPrimitive
//---------------------------------------------------------
bool MgStyle::drawFrameGroupBoxPrimitive(const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
// cast option and check
const QStyleOptionFrame *fOpt = qstyleoption_cast<const QStyleOptionFrame *>(option);
if (!fOpt)
return true;
// no frame for flat groupboxes
QStyleOptionFrameV2 fOpt2(*fOpt);
if (fOpt2.features & QStyleOptionFrameV2::Flat)
return true;
// normal frame
const QPalette& palette( option->palette );
const QRect& r( option->rect );
const QColor base( _helper.backgroundColor( palette.color( QPalette::Window ), widget, r.center() ) );
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
QLinearGradient innerGradient(0, r.top()-r.height()+12, 0, r.bottom()+r.height()-19);
QColor light(_helper.calcLightColor(base));
light.setAlphaF(0.4);
innerGradient.setColorAt(0.0, light);
light.setAlphaF(0.0);
innerGradient.setColorAt(1.0, light);
painter->setBrush(innerGradient);
painter->setClipRect(r.adjusted(0, 0, 0, -19));
_helper.fillSlab(*painter, r);
TileSet* slopeTileSet = _helper.slope(base, 0.0);
painter->setClipping(false);
slopeTileSet->render(r, painter);
painter->restore();
return true;
}
bool MgStyle::drawFrameMenuPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
// only draw frame for (expanded) toolbars
// do nothing for other cases
if( qobject_cast<const QToolBar*>(widget) ) {
_helper.renderWindowBackground( painter, option->rect, widget, option->palette );
_helper.drawFloatFrame( painter, option->rect, option->palette.window().color(), true );
}
return true;
}
bool MgStyle::drawFrameTabBarBasePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
{
// cast option and check
const QStyleOptionTabBarBase* tabOpt( qstyleoption_cast<const QStyleOptionTabBarBase*>( option ) );
if( !tabOpt ) return true;
if( tabOpt->tabBarRect.isValid() )
{
// if tabBar rect is valid, all the frame is handled in tabBarTabShapeControl
// nothing to be done here.
// on the other hand, invalid tabBarRect corresponds to buttons in tabbars (e.g. corner buttons),
// and the appropriate piece of frame needs to be drawn
return true;
}
// store palette and rect
const QPalette& palette( option->palette );
const QRect& r( option->rect );
QRect frameRect( r );
SlabRect slab;
switch( tabOpt->shape )
{
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
{
frameRect.adjust( -7, -GlowWidth, 7, GlowWidth );
frameRect.translate( 0, 4 );
slab = SlabRect( frameRect, TileSet::Top );
break;
}
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
{
frameRect.adjust( -7, -GlowWidth, 7, GlowWidth );
frameRect.translate( 0, -4 );
slab = SlabRect( frameRect, TileSet::Bottom );
break;
}
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
{
frameRect.adjust( -GlowWidth, -7, GlowWidth, 7 + 1 );
frameRect.translate( 5, 0 );
slab = SlabRect( frameRect, TileSet::Left );
break;
}
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
{
frameRect.adjust( -GlowWidth, -7, GlowWidth, 7 + 1 );
frameRect.translate( -5, 0 );
slab = SlabRect( frameRect, TileSet::Right );
break;
}
default: return true;
}
// render registered slabs
renderSlab( painter, slab, palette.color(QPalette::Window), NoFill );
return true;
}
bool MgStyle::drawFrameTabWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
{
// cast option and check
const QStyleOptionTabWidgetFrame* tabOpt( qstyleoption_cast<const QStyleOptionTabWidgetFrame*>( option ) );
if( !tabOpt )
return true;
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const bool reverseLayout( option->direction == Qt::RightToLeft );
/*
no frame is drawn when tabbar is empty.
this is consistent with the tabWidgetTabContents subelementRect
*/
if( tabOpt->tabBarSize.isEmpty() ) return true;
// get tabbar dimentions
const int w( tabOpt->tabBarSize.width() );
const int h( tabOpt->tabBarSize.height() );
// left corner widget
const int lw( tabOpt->leftCornerWidgetSize.width() );
const int lh( tabOpt->leftCornerWidgetSize.height() );
// right corner
const int rw( tabOpt->rightCornerWidgetSize.width() );
const int rh( tabOpt->rightCornerWidgetSize.height() );
// list of slabs to be drawn
SlabRectList slabs;
// expand rect by glow width.
QRect baseSlabRect( insideMargin( r, -GlowWidth ) );
// render the three free sides
switch( tabOpt->shape )
{
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
{
// main slab
slabs << SlabRect( baseSlabRect, (TileSet::Ring & ~TileSet::Top) );
// top
if( reverseLayout )
{
// left side
QRect slabRect( baseSlabRect );
slabRect.setRight( qMax( slabRect.right() - w - lw, slabRect.left() + rw ) + 7 );
slabRect.setHeight( 7 );
slabs << SlabRect( slabRect, TileSet::TopLeft );
// right side
if( rw > 0 )
{
QRect slabRect( baseSlabRect );
slabRect.setLeft( slabRect.right() - rw - 7 );
slabRect.setHeight( 7 );
slabs << SlabRect( slabRect, TileSet::TopRight );
}
} else {
// left side
if( lw > 0 )
{
QRect slabRect( baseSlabRect );
slabRect.setRight( baseSlabRect.left() + lw + 7 );
slabRect.setHeight( 7 );
slabs << SlabRect( slabRect, TileSet::TopLeft );
}
// right side
QRect slabRect( baseSlabRect );
slabRect.setLeft( qMin( slabRect.left() + w + lw + 1, slabRect.right() - rw ) -7 );
slabRect.setHeight( 7 );
slabs << SlabRect( slabRect, TileSet::TopRight );
}
break;
}
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
{
slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Bottom );
if( reverseLayout )
{
// left side
QRect slabRect( baseSlabRect );
slabRect.setRight( qMax( slabRect.right() - w - lw, slabRect.left() + rw ) + 7 );
slabRect.setTop( slabRect.bottom() - 7 );
slabs << SlabRect( slabRect, TileSet::BottomLeft );
// right side
if( rw > 0 )
{
QRect slabRect( baseSlabRect );
slabRect.setLeft( slabRect.right() - rw - 7 );
slabRect.setTop( slabRect.bottom() - 7 );
slabs << SlabRect( slabRect, TileSet::BottomRight );
}
} else {
// left side
if( lw > 0 )
{
QRect slabRect( baseSlabRect );
slabRect.setRight( baseSlabRect.left() + lw + 7 );
slabRect.setTop( slabRect.bottom() - 7 );
slabs << SlabRect( slabRect, TileSet::BottomLeft );
}
// right side
QRect slabRect( baseSlabRect );
slabRect.setLeft( qMin( slabRect.left() + w + lw + 1, slabRect.right() - rw ) -7 );
slabRect.setTop( slabRect.bottom() - 7 );
slabs << SlabRect( slabRect, TileSet::BottomRight );
}
break;
}
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
{
slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Left );
// top side
if( lh > 0 )
{
QRect slabRect( baseSlabRect );
slabRect.setBottom( baseSlabRect.top() + lh + 7 + 1 );
slabRect.setWidth( 7 );
slabs << SlabRect( slabRect, TileSet::TopLeft );
}
// bottom side
QRect slabRect( baseSlabRect );
slabRect.setTop( qMin( slabRect.top() + h + lh, slabRect.bottom() - rh ) -7 + 1 );
slabRect.setWidth( 7 );
slabs << SlabRect( slabRect, TileSet::BottomLeft );
break;
}
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
{
slabs << SlabRect( baseSlabRect, TileSet::Ring & ~TileSet::Right );
// top side
if( lh > 0 )
{
QRect slabRect( baseSlabRect );
slabRect.setBottom( baseSlabRect.top() + lh + 7 + 1 );
slabRect.setLeft( slabRect.right()-7 );
slabs << SlabRect( slabRect, TileSet::TopRight );
}
// bottom side
QRect slabRect( baseSlabRect );
slabRect.setTop( qMin( slabRect.top() + h + lh, slabRect.bottom() - rh ) -7 + 1 );
slabRect.setLeft( slabRect.right()-7 );
slabs << SlabRect( slabRect, TileSet::BottomRight );
break;
}
break;
default: break;
}
// render registered slabs
foreach( const SlabRect& slab, slabs )
{ renderSlab( painter, slab, palette.color(QPalette::Window), NoFill ); }
return true;
}
bool MgStyle::drawFrameWindowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
{
const QRect& r( option->rect );
const QPalette& palette( option->palette );
_helper.drawFloatFrame( painter, r, palette.window().color(), false );
return true;
}
bool MgStyle::drawIndicatorArrowPrimitive( ArrowOrientation orientation, const QStyleOption* option, QPainter* painter, const QWidget* ) const
{
const QRect& r(option->rect);
const QPalette& palette(option->palette);
const State& flags(option->state);
const bool enabled(flags & State_Enabled);
const bool mouseOver(enabled && (flags & State_MouseOver));
// define gradient and polygon for drawing arrow
const QPolygonF a = genericArrow(orientation, ArrowNormal);
QColor color = palette.color(QPalette::WindowText);
const QColor background = palette.color(QPalette::Window);
const QColor highlight( _helper.viewHoverBrush().brush(palette).color());
const qreal penThickness = 1.6;
const qreal offset(qMin( penThickness, qreal(1.0)));
if (mouseOver)
color = highlight;
painter->translate(r.center());
painter->setRenderHint(QPainter::Antialiasing);
painter->translate(0,offset);
painter->setPen(QPen(_helper.calcLightColor(background), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
painter->translate(0,-offset);
painter->setPen(QPen(_helper.decoColor(background, color), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
return true;
}
bool MgStyle::drawIndicatorHeaderArrowPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
{
const QStyleOptionHeader *headerOpt = qstyleoption_cast<const QStyleOptionHeader *>(option);
const State& flags( option->state );
// arrow orientation
ArrowOrientation orientation( ArrowNone );
if( flags&State_UpArrow || ( headerOpt && headerOpt->sortIndicator==QStyleOptionHeader::SortUp ) ) orientation = ArrowUp;
else if( flags&State_DownArrow || ( headerOpt && headerOpt->sortIndicator==QStyleOptionHeader::SortDown ) ) orientation = ArrowDown;
if( orientation == ArrowNone ) return true;
// flags, rect and palette
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const bool enabled( flags & State_Enabled );
const bool mouseOver( enabled && (flags & State_MouseOver ) );
animations().headerViewEngine().updateState( widget, r.topLeft(), mouseOver );
const bool animated( enabled && animations().headerViewEngine().isAnimated( widget, r.topLeft() ) );
// define gradient and polygon for drawing arrow
const QPolygonF a = genericArrow( orientation, ArrowNormal );
QColor color = palette.color( QPalette::WindowText );
const QColor background = palette.color(QPalette::Window);
const QColor highlight( _helper.viewHoverBrush().brush(palette).color() );
const qreal penThickness = 1.6;
const qreal offset( qMin( penThickness, qreal(1.0)) );
if( animated )
{
const qreal opacity( animations().headerViewEngine().opacity( widget, r.topLeft() ) );
color = ColorUtils::mix( color, highlight, opacity );
} else if( mouseOver ) color = highlight;
painter->translate( r.center() );
painter->translate( 0, 1 );
painter->setRenderHint(QPainter::Antialiasing);
painter->translate(0,offset);
painter->setPen(QPen(_helper.calcLightColor(background), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
painter->translate(0,-offset);
painter->setPen(QPen( _helper.decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
return true;
}
bool MgStyle::drawPanelButtonCommandPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
{
const State& flags( option->state );
const bool enabled( flags & State_Enabled );
const bool mouseOver( enabled && (flags & State_MouseOver) );
const bool hasFocus( enabled && (flags & State_HasFocus) );
const QPalette& palette( option->palette );
StyleOptions opts = 0;
if( flags & (State_On|State_Sunken) ) opts |= Sunken;
if( flags & State_HasFocus) opts |= Focus;
if( enabled && (flags & State_MouseOver)) opts |= Hover;
// update animation state
animations().widgetStateEngine().updateState( widget, AnimationHover, mouseOver );
animations().widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver );
// store animation state
const bool hoverAnimated( animations().widgetStateEngine().isAnimated( widget, AnimationHover ) );
const bool focusAnimated( animations().widgetStateEngine().isAnimated( widget, AnimationFocus ) );
const qreal hoverOpacity( animations().widgetStateEngine().opacity( widget, AnimationHover ) );
const qreal focusOpacity( animations().widgetStateEngine().opacity( widget, AnimationFocus ) );
// decide if widget must be rendered flat.
/*
The decision is made depending on
- whether the "flat" flag is set in the option
- whether the widget is hight enough to render both icons and normal margins
Note: in principle one should also check for the button text height
*/
const QRect& r( option->rect );
const QStyleOptionButton* bOpt( qstyleoption_cast< const QStyleOptionButton* >( option ) );
bool flat = ( bOpt && (
bOpt->features.testFlag( QStyleOptionButton::Flat ) ||
( (!bOpt->icon.isNull()) && sizeFromContents( CT_PushButton, option, bOpt->iconSize, widget ).height() > r.height() ) ) );
if( flat )
{
QRect slitRect(r);
if( !( opts & Sunken) )
{
// hover rect
if( enabled && hoverAnimated )
{
QColor glow( _helper.alphaColor( _helper.viewFocusBrush().brush(QPalette::Active).color(), hoverOpacity ) );
_helper.slitFocused( glow )->render(slitRect, painter );
} else if( mouseOver) {
_helper.slitFocused(_helper.viewFocusBrush().brush(QPalette::Active).color())->render(slitRect, painter );
}
} else {
slitRect.adjust( 0, 0, 0, -1 );
// flat pressed-down buttons do not get focus effect,
// consistently with tool buttons
if( enabled && hoverAnimated )
{
_helper.renderHole( painter, palette.color(QPalette::Window), slitRect, false, mouseOver, hoverOpacity, AnimationHover, TileSet::Ring );
} else {
_helper.renderHole( painter, palette.color(QPalette::Window), slitRect, false, mouseOver);
}
}
} else {
const QRect slabRect(r.adjusted( -1, 0, 1, 0 ) );
// match color to the window background
const QColor buttonColor( _helper.backgroundColor( palette.color(QPalette::Button), widget, r.center() ) );
if( enabled && hoverAnimated && !(opts & Sunken ) )
{
renderButtonSlab( painter, slabRect, buttonColor, opts, hoverOpacity, AnimationHover, TileSet::Ring );
} else if( enabled && !mouseOver && focusAnimated && !(opts & Sunken ) ) {
renderButtonSlab( painter, slabRect, buttonColor, opts, focusOpacity, AnimationFocus, TileSet::Ring );
} else {
renderButtonSlab( painter, slabRect, buttonColor, opts);
}
}
return true;
}
//---------------------------------------------------------
// drawPanelButtonToolPrimitive
//---------------------------------------------------------
bool MgStyle::drawPanelButtonToolPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
/*
For toolbutton in TabBars, corresponding to expanding arrows, no frame is drawn
However one needs to draw the window background, because the button rect might
overlap with some tab below. (this is a Qt bug)
*/
const bool isInTabBar( widget && qobject_cast<const QTabBar*>( widget->parent() ) );
if( isInTabBar )
{
const QPalette& palette( option->palette );
QRect r( option->rect );
// adjust rect depending on shape
const QTabBar* tabBar( static_cast<const QTabBar*>( widget->parent() ) );
switch( tabBar->shape() )
{
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
r.setBottom( r.bottom()-6 );
break;
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
r.setTop( r.top() + 6 );
break;
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
r.setRight( r.right() - 6 );
break;
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
r.setLeft( r.left() + 6 );
break;
default: break;
}
const QPalette local(widget->parentWidget() ? widget->parentWidget()->palette() : palette);
// check whether parent has autofill background flag
if (const QWidget* parent = _helper.checkAutoFillBackground(widget))
painter->fillRect(r, parent->palette().color(parent->backgroundRole()));
else
_helper.renderWindowBackground(painter, r, widget, local);
return true;
}
const QRect& r( option->rect );
const State& flags( option->state );
const QPalette& palette( option->palette );
const bool enabled( flags & State_Enabled );
const bool mouseOver(enabled && (flags & State_MouseOver));
const bool hasFocus(enabled && (flags & State_HasFocus));
const bool reverseLayout( option->direction == Qt::RightToLeft );
const bool autoRaised( flags & State_AutoRaise );
// check whether toolbutton is in toolbar
const bool isInToolBar( widget && qobject_cast<const QToolBar*>( widget->parent() ) );
// toolbar engine
const bool toolBarAnimated( isInToolBar && widget && ( animations().toolBarEngine().isAnimated( widget->parentWidget() ) || animations().toolBarEngine().isFollowMouseAnimated( widget->parentWidget() ) ) );
const QRect animatedRect( (isInToolBar && widget) ? animations().toolBarEngine().animatedRect( widget->parentWidget() ):QRect() );
const QRect childRect( (widget && widget->parentWidget()) ? r.translated( widget->mapToParent( QPoint(0,0) ) ):QRect() );
const QRect currentRect( widget ? animations().toolBarEngine().currentRect( widget->parentWidget() ):QRect() );
const bool current( isInToolBar && widget && widget->parentWidget() && currentRect.intersects( r.translated( widget->mapToParent( QPoint(0,0) ) ) ) );
const bool toolBarTimerActive( isInToolBar && widget && animations().toolBarEngine().isTimerActive( widget->parentWidget() ) );
const qreal toolBarOpacity( ( isInToolBar && widget ) ? animations().toolBarEngine().opacity( widget->parentWidget() ):0 );
// toolbutton engine
if( isInToolBar && !toolBarAnimated )
{
animations().widgetStateEngine().updateState( widget, AnimationHover, mouseOver );
} else {
// mouseOver has precedence over focus
animations().widgetStateEngine().updateState( widget, AnimationHover, mouseOver );
animations().widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver );
}
bool hoverAnimated( animations().widgetStateEngine().isAnimated( widget, AnimationHover ) );
bool focusAnimated( animations().widgetStateEngine().isAnimated( widget, AnimationFocus ) );
qreal hoverOpacity( animations().widgetStateEngine().opacity( widget, AnimationHover ) );
qreal focusOpacity( animations().widgetStateEngine().opacity( widget, AnimationFocus ) );
// slit rect
QRect slitRect( r );
// non autoraised tool buttons get same slab as regular buttons
if( widget && !autoRaised )
{
StyleOptions opts = 0;
slitRect.adjust( -1, 0, 1, 0 );
// "normal" parent, and non "autoraised" (that is: always raised) buttons
if( flags & (State_On|State_Sunken) ) opts |= Sunken;
if( flags & State_HasFocus) opts |= Focus;
if( enabled && (flags & State_MouseOver)) opts |= Hover;
TileSet::Tiles tiles( TileSet::Ring );
// adjust tiles and rect in case of menubutton
const QToolButton* t = qobject_cast<const QToolButton*>( widget );
if( t && t->popupMode()==QToolButton::MenuButtonPopup )
{
if( reverseLayout )
{
tiles = TileSet::Bottom | TileSet::Top | TileSet::Right;
slitRect.adjust( -4, 0, 0, 0 );
} else {
tiles = TileSet::Bottom | TileSet::Top | TileSet::Left;
slitRect.adjust( 0, 0, 4, 0 );
}
}
// adjust opacity and animation mode
qreal opacity( -1 );
AnimationMode mode( AnimationNone );
if( enabled && hoverAnimated )
{
opacity = hoverOpacity;
mode = AnimationHover;
} else if( enabled && !hasFocus && focusAnimated ) {
opacity = focusOpacity;
mode = AnimationFocus;
}
// match button color to window background
const QColor buttonColor( _helper.backgroundColor( palette.color(QPalette::Button), widget, r.center() ) );
// render slab
renderButtonSlab( painter, slitRect, buttonColor, opts, opacity, mode, tiles );
return true;
}
//! fine tuning of slitRect geometry
if( widget && widget->inherits( "QDockWidgetTitleButton" ) )
slitRect.adjust( 1, 0, 0, 0 );
else if( widget && widget->inherits( "QToolBarExtension" ) )
slitRect.adjust( 1, 1, -1, -1 );
else if( widget && widget->objectName() == "qt_menubar_ext_button" )
slitRect.adjust( -1, -1, 0, 0 );
// normal (auto-raised) toolbuttons
if( flags & (State_Sunken|State_On) )
{
if( enabled && hoverAnimated )
{
_helper.renderHole( painter, palette.color(QPalette::Window), slitRect, hasFocus, mouseOver, hoverOpacity, AnimationHover, TileSet::Ring );
} else if( toolBarAnimated ) {
if( enabled && animatedRect.isNull() && current )
{
_helper.renderHole( painter, palette.color(QPalette::Window), slitRect, hasFocus, mouseOver, toolBarOpacity, AnimationHover, TileSet::Ring );
} else {
_helper.renderHole( painter, palette.color(QPalette::Window), slitRect, false, false);
}
} else if( toolBarTimerActive && current ) {
_helper.renderHole( painter, palette.color(QPalette::Window), slitRect, hasFocus, true );
} else {
_helper.renderHole( painter, palette.color(QPalette::Window), slitRect, hasFocus, mouseOver);
}
} else {
if( enabled && hoverAnimated )
{
QColor glow( _helper.alphaColor( _helper.viewFocusBrush().brush(QPalette::Active).color(), hoverOpacity ) );
_helper.slitFocused( glow )->render( slitRect, painter );
} else if( toolBarAnimated ) {
if( enabled && animatedRect.isNull() && current )
{
QColor glow( _helper.alphaColor( _helper.viewFocusBrush().brush(QPalette::Active).color(), toolBarOpacity ) );
_helper.slitFocused( glow )->render( slitRect, painter );
}
} else if( hasFocus || mouseOver || (toolBarTimerActive && current ) ) {
_helper.slitFocused(_helper.viewFocusBrush().brush(QPalette::Active).color())->render( slitRect, painter );
}
}
return true;
}
bool MgStyle::drawPanelItemViewItemPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
const QStyleOptionViewItemV4 *opt = qstyleoption_cast<const QStyleOptionViewItemV4*>(option);
const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
const bool hover = (option->state & State_MouseOver) && (!view || view->selectionMode() != QAbstractItemView::NoSelection);
const bool hasCustomBackground = opt->backgroundBrush.style() != Qt::NoBrush && !(option->state & State_Selected);
const bool hasSolidBackground = !hasCustomBackground || opt->backgroundBrush.style() == Qt::SolidPattern;
if( !hover && !(option->state & State_Selected) && !hasCustomBackground && !(opt->features & QStyleOptionViewItemV2::Alternate) )
{ return true; }
QPalette::ColorGroup cg;
if( option->state & State_Enabled) cg = (option->state & State_Active) ? QPalette::Normal : QPalette::Inactive;
else cg = QPalette::Disabled;
QColor color;
if( hasCustomBackground && hasSolidBackground) color = opt->backgroundBrush.color();
else color = option->palette.color(cg, QPalette::Highlight);
if( hover && !hasCustomBackground)
{
if( !(option->state & State_Selected)) color.setAlphaF(0.2);
else color = color.lighter(110);
}
if( opt && (opt->features & QStyleOptionViewItemV2::Alternate))
{ painter->fillRect(option->rect, option->palette.brush(cg, QPalette::AlternateBase)); }
if( !hover && !(option->state & State_Selected) && !hasCustomBackground)
{ return true; }
if( hasCustomBackground && !hasSolidBackground)
{
const QPointF oldBrushOrigin = painter->brushOrigin();
painter->setBrushOrigin(opt->rect.topLeft());
painter->setBrush(opt->backgroundBrush);
painter->setPen(Qt::NoPen);
painter->drawRect(opt->rect);
painter->setBrushOrigin(oldBrushOrigin);
} else {
// get selection tileset
QRect r = option->rect;
TileSet *tileSet( _helper.selection( color, r.height(), hasCustomBackground ) );
bool roundedLeft = false;
bool roundedRight = false;
if( opt )
{
roundedLeft = (opt->viewItemPosition == QStyleOptionViewItemV4::Beginning);
roundedRight = (opt->viewItemPosition == QStyleOptionViewItemV4::End);
if( opt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne ||
opt->viewItemPosition == QStyleOptionViewItemV4::Invalid ||
(view && view->selectionBehavior() != QAbstractItemView::SelectRows))
{
roundedLeft = true;
roundedRight = true;
}
}
const bool reverseLayout( option->direction == Qt::RightToLeft );
TileSet::Tiles tiles( TileSet::Center );
if( !reverseLayout ? roundedLeft : roundedRight) tiles |= TileSet::Left;
else r.adjust( -8, 0, 0, 0 );
if( !reverseLayout ? roundedRight : roundedLeft) tiles |= TileSet::Right;
else r.adjust( 0, 0, 8, 0 );
if( r.isValid()) tileSet->render( r, painter, tiles );
}
return true;
}
bool MgStyle::drawPanelLineEditPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
const State& flags( option->state );
const bool enabled( flags & State_Enabled );
const QRect& r( option->rect );
const QPalette& palette( option->palette );
// cast option and check
const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame*>(option);
if( !panel ) return true;
const QBrush inputBrush( enabled ? palette.base() : palette.window() );
const int lineWidth(panel->lineWidth);
if( lineWidth > 0)
{
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
painter->setBrush(inputBrush);
_helper.fillHole(*painter, r.adjusted( 0, -1, 0, 0 ) );
drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
painter->restore();
} else {
painter->fillRect(r.adjusted(2,2,-2,-2), inputBrush);
}
return true;
}
//---------------------------------------------------------
// drawPanelMenuPrimitive
//---------------------------------------------------------
bool MgStyle::drawPanelMenuPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
// do nothing if menu is embedded in another widget
// this corresponds to having a transparent background
if (widget && !widget->isWindow())
return true;
const QStyleOptionMenuItem* mOpt( qstyleoption_cast<const QStyleOptionMenuItem*>(option) );
if( !( mOpt && widget ) )
return true;
const QRect& r = mOpt->rect;
const QColor color = mOpt->palette.color( widget->window()->backgroundRole() );
const bool hasAlpha( _helper.hasAlphaChannel( widget ) );
if( hasAlpha ) {
painter->setCompositionMode(QPainter::CompositionMode_Source );
TileSet *tileSet( _helper.roundCorner(color) );
tileSet->render( r, painter );
painter->setCompositionMode(QPainter::CompositionMode_SourceOver );
painter->setClipRegion( _helper.roundedMask( r.adjusted( 1, 1, -1, -1 ) ), Qt::IntersectClip );
}
_helper.renderMenuBackground( painter, r, widget, mOpt->palette );
if( hasAlpha )
painter->setClipping( false );
_helper.drawFloatFrame( painter, r, color, !hasAlpha );
return true;
}
bool MgStyle::drawPanelScrollAreaCornerPrimitive( const QStyleOption*, QPainter*, const QWidget* widget) const
{
// disable painting of PE_PanelScrollAreaCorner
// the default implementation fills the rect with the window background color
// which does not work for windows that have gradients.
// unfortunately, this does not work when scrollbars are children of QWebView,
// in which case, false is returned, in order to fall back to the parent style implementation
return !( widget && widget->inherits( "QWebView" ) );
}
bool MgStyle::drawIndicatorBranchPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
{
const State& flags( option->state );
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const QPoint center( r.center() );
const bool reverseLayout( option->direction == Qt::RightToLeft );
const int centerX = center.x();
const int centerY = center.y();
int expanderAdjust = 0;
//draw expander
if (flags & State_Children)
{
int sizeLimit = qMin( qMin(r.width(), r.height() ), (int) Tree_MaxExpanderSize );
const bool expanderOpen( flags & State_Open );
// make sure size limit is odd
if( !(sizeLimit&1) ) --sizeLimit;
expanderAdjust = sizeLimit/2 + 1;
QRect expanderRect = centerRect( r, sizeLimit, sizeLimit );
const int radius( (expanderRect.width() - 4) / 2 );
// flags
const bool enabled( flags & State_Enabled );
const bool mouseOver(enabled && (flags & State_MouseOver));
// color
const QColor expanderColor( mouseOver ? _helper.viewHoverBrush().brush(palette).color():palette.color( QPalette::Text ) );
if(!MgStyleConfigData_viewDrawTriangularExpander)
{
// plus or minus sign used for expanders
painter->save();
painter->setPen( expanderColor );
painter->drawLine( center - QPoint( radius, 0 ), center + QPoint( radius, 0 ) );
if( !expanderOpen )
{ painter->drawLine( center - QPoint( 0, radius ), center + QPoint( 0, radius ) ); }
painter->restore();
} else {
// arrows
painter->save();
painter->translate( center );
// get size from option
QPolygonF a;
ArrowSize size = ArrowSmall;
size = MgStyleConfigData_viewTriangularExpanderSize;
if( expanderOpen )
{
painter->translate( 0, 0.5 );
a = genericArrow( ArrowDown, size );
} else {
painter->translate( 0.5, 0 );
a = genericArrow( reverseLayout ? ArrowLeft:ArrowRight, size );
}
const qreal penThickness( 1.2 );
painter->setPen( QPen( expanderColor, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
painter->setRenderHint(QPainter::Antialiasing);
painter->drawPolyline( a );
painter->restore();
}
}
// tree branches
if( !MgStyleConfigData_viewDrawTreeBranchLines) return true;
painter->setPen( ColorUtils::mix( palette.color( QPalette::Text ), palette.color( QPalette::Background ), 0.8 ) );
if (flags & (State_Item | State_Children | State_Sibling))
{
const QLine line( QPoint( centerX, r.top() ), QPoint( centerX, centerY - expanderAdjust ) );
painter->drawLine( line );
}
//The right/left (depending on dir) line gets drawn if we have an item
if (flags & State_Item)
{
const QLine line = reverseLayout ?
QLine( QPoint( r.left(), centerY ), QPoint( centerX - expanderAdjust, centerY ) ):
QLine( QPoint( centerX + expanderAdjust, centerY ), QPoint( r.right(), centerY ) );
painter->drawLine( line );
}
//The bottom if we have a sibling
if (flags & State_Sibling)
{
const QLine line( QPoint( centerX, centerY + expanderAdjust ), QPoint( centerX, r.bottom()) );
painter->drawLine( line );
}
return true;
}
bool MgStyle::drawIndicatorButtonDropDownPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
const QPalette& palette( option->palette );
const QRect& r( option->rect );
const State& flags( option->state );
const bool enabled( flags & State_Enabled );
const bool mouseOver(enabled && (flags & State_MouseOver));
const bool reverseLayout( option->direction == Qt::RightToLeft );
const bool autoRaise( flags & State_AutoRaise );
const bool sunken(enabled && (flags & State_Sunken));
// match button color to window background
const QToolButton *tool( qobject_cast<const QToolButton *>(widget) );
const QColor highlight( _helper.viewHoverBrush().brush( palette ).color() );
QColor color = palette.color( autoRaise ? QPalette::WindowText:QPalette::ButtonText );
QColor background = palette.color( QPalette::Window );
StyleOptions opts = 0;
// define gradient and polygon for drawing arrow
QPolygonF a = genericArrow( ArrowDown, ArrowNormal );
qreal penThickness = 1.6;
bool drawContrast = true;
// toolbuttons
if( tool->popupMode()==QToolButton::MenuButtonPopup )
{
if(!autoRaise)
{
const bool hasFocus(enabled && (flags & State_HasFocus));
// handle animations
// mouseOver has precedence over focus
animations().widgetStateEngine().updateState( widget, AnimationHover, mouseOver );
animations().widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver );
const bool hoverAnimated( animations().widgetStateEngine().isAnimated( widget, AnimationHover ) );
const bool focusAnimated( animations().widgetStateEngine().isAnimated( widget, AnimationFocus ) );
const qreal hoverOpacity( animations().widgetStateEngine().opacity( widget, AnimationHover ) );
const qreal focusOpacity( animations().widgetStateEngine().opacity( widget, AnimationFocus ) );
color = palette.color( QPalette::ButtonText );
background = _helper.backgroundColor( palette.color( QPalette::Button ), widget, r.center() );
if( hasFocus ) opts |= Focus;
if( mouseOver ) opts |= Hover;
// adjust opacity and animation mode
qreal opacity( -1 );
AnimationMode mode( AnimationNone );
if( enabled && hoverAnimated )
{
opacity = hoverOpacity;
mode = AnimationHover;
} else if( enabled && !hasFocus && focusAnimated ) {
opacity = focusOpacity;
mode = AnimationFocus;
}
// paint frame
painter->save();
if( reverseLayout )
{
QRect frameRect( r.adjusted( 0, 0, 10, 0 ) );
if( flags & (State_On|State_Sunken) )
{
frameRect.adjust( 0, 0, -1, -1 );
opts |= Sunken;
}
painter->setClipRect( frameRect.adjusted( 0, 0, -8, 0 ), Qt::IntersectClip );
renderButtonSlab( painter, frameRect, background, opts, opacity, mode, TileSet::Bottom | TileSet::Top | TileSet::Left );
} else {
QRect frameRect( r.adjusted(-10,0,0,0) );
if( flags & (State_On|State_Sunken) )
{
frameRect.adjust( 1, 0, 0, -1 );
opts |= Sunken;
}
painter->setClipRect( frameRect.adjusted( 8, 0, 0, 0 ), Qt::IntersectClip );
renderButtonSlab( painter, frameRect, background, opts, opacity, mode, TileSet::Bottom | TileSet::Top | TileSet::Right );
}
painter->restore();
// draw separating vertical line
const QColor color( palette.color(QPalette::Window) );
QColor light =_helper.alphaColor( _helper.calcLightColor(color), 0.6 );
QColor dark = _helper.calcDarkColor(color);
dark.setAlpha(200);
int yTop( r.top()+2 );
if( sunken ) yTop += 1;
const int yBottom( r.bottom()-4 );
painter->setPen(QPen(light,1));
if( reverseLayout )
{
painter->drawLine(r.right()+5, yTop+1, r.right()+5, yBottom);
painter->drawLine(r.right()+3, yTop+2, r.right()+3, yBottom);
painter->setPen(QPen(dark,1));
painter->drawLine(r.right()+4, yTop, r.right()+4, yBottom);
a.translate( 3, 1 );
} else {
painter->drawLine(r.x()-5, yTop+1, r.x()-5, yBottom-1);
painter->drawLine(r.x()-3, yTop+1, r.x()-3, yBottom-1);
painter->setPen(QPen(dark,1));
painter->drawLine(r.x()-4, yTop, r.x()-4, yBottom);
a.translate(-3,1);
}
}
// handle arrow over animation
if( const QStyleOptionToolButton *tbOption = qstyleoption_cast<const QStyleOptionToolButton *>(option) )
{
const bool arrowHover( enabled && mouseOver && (tbOption->activeSubControls & SC_ToolButtonMenu));
animations().toolButtonEngine().updateState( widget, AnimationHover, arrowHover );
const bool animated( enabled && animations().toolButtonEngine().isAnimated( widget, AnimationHover ) );
const qreal opacity( animations().toolButtonEngine().opacity( widget, AnimationHover) );
if( animated ) color = ColorUtils::mix( color, highlight, opacity );
else if( arrowHover ) color = highlight;
else color = palette.color( autoRaise ? QPalette::WindowText:QPalette::ButtonText );
}
} else {
// toolbutton animation
// when the arrow is painted directly on the icon, button hover and arrow hover
// are identical. The generic widget engine is used.
animations().widgetStateEngine().updateState( widget, AnimationHover, mouseOver );
const bool animated( animations().widgetStateEngine().isAnimated( widget, AnimationHover ) );
const qreal opacity( animations().widgetStateEngine().opacity( widget, AnimationHover ) );
if( animated ) color = ColorUtils::mix( color, highlight, opacity );
else if( mouseOver ) color = highlight;
else color = palette.color( autoRaise ? QPalette::WindowText:QPalette::ButtonText );
// smaller down arrow for menu indication on toolbuttons
penThickness = 1.4;
a = genericArrow( ArrowDown, ArrowSmall );
}
painter->translate( r.center() );
painter->setRenderHint(QPainter::Antialiasing);
// white reflection
if( drawContrast )
{
const qreal offset( qMin( penThickness, qreal(1.0)) );
painter->translate(0,offset);
painter->setPen(QPen(_helper.calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
painter->translate(0,-offset);
}
painter->setPen(QPen( _helper.decoColor( background, color ) , penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
return true;
}
bool MgStyle::drawIndicatorCheckBoxPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
const QRect& r( option->rect );
const State& flags( option->state );
const bool enabled( flags & State_Enabled );
const bool mouseOver(enabled && (flags & State_MouseOver));
const bool hasFocus( flags & State_HasFocus );
StyleOptions opts(0);
if( !enabled ) opts |= Disabled;
if( mouseOver ) opts |= Hover;
if( hasFocus ) opts |= Focus;
// get checkbox state
CheckBoxState state;
if( flags & State_NoChange ) state = CheckTriState;
else if( flags & State_On ) state = CheckOn;
else state = CheckOff;
// match button color to window background
QPalette palette( option->palette );
palette.setColor(
QPalette::Button,
_helper.backgroundColor(
palette.color( QPalette::Button ), widget, r.center() ) );
// mouseOver has precedence over focus
animations().widgetStateEngine().updateState( widget, AnimationHover, mouseOver );
animations().widgetStateEngine().updateState( widget, AnimationFocus, hasFocus&&!mouseOver );
if( enabled && animations().widgetStateEngine().isAnimated( widget, AnimationHover ) )
{
const qreal opacity( animations().widgetStateEngine().opacity( widget, AnimationHover ) );
renderCheckBox( painter, r, palette, opts, state, opacity, AnimationHover );
} else if( enabled && !hasFocus && animations().widgetStateEngine().isAnimated( widget, AnimationFocus ) ) {
const qreal opacity( animations().widgetStateEngine().opacity( widget, AnimationFocus ) );
renderCheckBox( painter, r, palette, opts, state, opacity, AnimationFocus );
} else renderCheckBox( painter, r, palette, opts, state);
return true;
}
//---------------------------------------------------------
// drawIndicatorRadioButtonPrimitive
//---------------------------------------------------------
bool MgStyle::drawIndicatorRadioButtonPrimitive(const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
const QRect& r( option->rect );
const State& flags( option->state );
const bool enabled( flags & State_Enabled );
const bool mouseOver(enabled && (flags & State_MouseOver));
const bool hasFocus( flags & State_HasFocus );
StyleOptions opts(0);
if( !enabled ) opts |= Disabled;
if( mouseOver ) opts |= Hover;
if( hasFocus ) opts |= Focus;
// match button color to window background
QPalette palette( option->palette );
palette.setColor( QPalette::Button, _helper.backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) );
// mouseOver has precedence over focus
animations().widgetStateEngine().updateState( widget, AnimationHover, mouseOver );
animations().widgetStateEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver );
const CheckBoxState state( ( flags & State_On ) ? CheckOn:CheckOff );
if( enabled && animations().widgetStateEngine().isAnimated( widget, AnimationHover ) )
{
const qreal opacity( animations().widgetStateEngine().opacity( widget, AnimationHover ) );
renderRadioButton( painter, r, palette, opts, state, opacity, AnimationHover );
} else if( enabled && animations().widgetStateEngine().isAnimated( widget, AnimationFocus ) ) {
const qreal opacity( animations().widgetStateEngine().opacity( widget, AnimationFocus ) );
renderRadioButton( painter, r, palette, opts, state, opacity, AnimationFocus );
} else renderRadioButton( painter, r, palette, opts, state );
return true;
}
bool MgStyle::drawIndicatorTabTearPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const
{
const QStyleOptionTab* tabOpt( qstyleoption_cast<const QStyleOptionTab*>(option) );
if(!tabOpt)
return true;
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const bool reverseLayout( option->direction == Qt::RightToLeft );
// in fact with current version of Qt (4.6.0) the cast fails and document mode is always false
// this will hopefully be fixed in later versions
const QStyleOptionTabV3* tabOptV3( qstyleoption_cast<const QStyleOptionTabV3*>(option) );
bool documentMode( tabOptV3 ? tabOptV3->documentMode : false );
const QTabWidget *tabWidget = (widget && widget->parentWidget()) ? qobject_cast<const QTabWidget *>(widget->parentWidget()) : NULL;
documentMode |= (tabWidget ? tabWidget->documentMode() : true );
QRect gradientRect(r);
switch( tabOpt->shape )
{
case QTabBar::TriangularNorth:
case QTabBar::RoundedNorth:
gradientRect.adjust( 0, 0, 0, -5 );
if( !reverseLayout ) gradientRect.translate(-GlowWidth,0);
break;
case QTabBar::TriangularSouth:
case QTabBar::RoundedSouth:
gradientRect.adjust( 0, 5, 0, 0 );
if( !reverseLayout ) gradientRect.translate(-GlowWidth,0);
break;
case QTabBar::TriangularWest:
case QTabBar::RoundedWest:
gradientRect.adjust( 0, 0, -5, 0 );
gradientRect.translate(0,-GlowWidth);
break;
case QTabBar::TriangularEast:
case QTabBar::RoundedEast:
gradientRect.adjust( 5, 0, 0, 0 );
gradientRect.translate(0,-GlowWidth);
break;
default: return true;
}
// fade tabbar
QPixmap pm(gradientRect.size());
pm.fill(Qt::transparent);
QPainter pp(&pm);
const bool verticalTabs( isVerticalTab( tabOpt ) );
int w = 0, h = 0;
if( verticalTabs ) h = gradientRect.height();
else w = gradientRect.width();
QLinearGradient grad;
if( reverseLayout && !verticalTabs ) grad = QLinearGradient( 0, 0, w, h );
else grad = QLinearGradient(w, h, 0, 0);
grad.setColorAt(0, Qt::transparent );
grad.setColorAt(0.6, Qt::black);
_helper.renderWindowBackground( &pp, pm.rect(), widget, palette );
pp.setCompositionMode(QPainter::CompositionMode_DestinationAtop);
pp.fillRect(pm.rect(), QBrush(grad));
pp.end();
// draw pixmap
painter->drawPixmap(gradientRect.topLeft()+QPoint(0,-1),pm);
return true;
}
bool MgStyle::drawIndicatorToolBarHandlePrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
{
const State& flags( option->state );
const bool horizontal( flags & State_Horizontal );
const QRect& r( option->rect );
const QPalette& palette( option->palette );
int counter(1);
if( horizontal )
{
const int center( r.left()+r.width()/2 );
for( int j = r.top()+2; j <= r.bottom()-3; j+=3, ++counter )
{
if(counter%2 == 0) _helper.renderDot( painter, QPoint(center+1, j), palette.color(QPalette::Background));
else _helper.renderDot( painter, QPoint(center-2, j), palette.color(QPalette::Background));
}
} else {
const int center( r.top()+r.height()/2 );
for( int j = r.left()+2; j <= r.right()-3; j+=3, ++counter )
{
if(counter%2 == 0) _helper.renderDot( painter, QPoint(j, center+1), palette.color(QPalette::Background));
else _helper.renderDot( painter, QPoint(j, center-2), palette.color(QPalette::Background));
}
}
return true;
}
bool MgStyle::drawIndicatorToolBarSeparatorPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* ) const
{
const State& flags( option->state );
const QRect& r( option->rect );
const QPalette& palette( option->palette );
if( MgStyleConfigData_toolBarDrawItemSeparator )
{
const QColor color( palette.color(QPalette::Window) );
if(flags & State_Horizontal) _helper.drawSeparator( painter, r, color, Qt::Vertical );
else _helper.drawSeparator( painter, r, color, Qt::Horizontal );
}
return true;
}
//---------------------------------------------------------
// drawWidgetPrimitive
//---------------------------------------------------------
bool MgStyle::drawWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
// check widget and attributes
if (!widget || !widget->testAttribute(Qt::WA_StyledBackground) || widget->testAttribute(Qt::WA_NoSystemBackground))
return false;
if (!((widget->windowFlags() & Qt::WindowType_Mask) & (Qt::Window | Qt::Dialog)))
return false;
if (!widget->isWindow())
return false;
// normal "window" background
_helper.renderWindowBackground(painter, option->rect, widget, option->palette);
return true;
}
void MgStyle::renderSplitter( const QStyleOption* option, QPainter* painter, const QWidget* widget, bool horizontal ) const
{
const QPalette& palette( option->palette );
const QRect& r( option->rect );
const State& flags( option->state );
const bool enabled( flags & State_Enabled );
const bool mouseOver(enabled && (flags & (State_MouseOver|State_Sunken) ));
// get orientation
const Qt::Orientation orientation( horizontal ? Qt::Horizontal : Qt::Vertical );
bool animated( false );
qreal opacity( AnimationData::OpacityInvalid );
if( enabled )
{
if( qobject_cast<const QMainWindow*>( widget ) )
{
animations().dockSeparatorEngine().updateRect( widget, r, orientation, mouseOver );
animated = animations().dockSeparatorEngine().isAnimated( widget, r, orientation );
opacity = animated ? animations().dockSeparatorEngine().opacity( widget, orientation ) : AnimationData::OpacityInvalid;
} else if( QPaintDevice* device = painter->device() ) {
/*
try update QSplitterHandle using painter device, because Qt passes
QSplitter as the widget to the QStyle primitive.
*/
animations().splitterEngine().updateState( device, mouseOver );
animated = animations().splitterEngine().isAnimated( device );
opacity = animations().splitterEngine().opacity( device );
}
}
// get base color
const QColor color = palette.color(QPalette::Background);
if( horizontal )
{
const int h = r.height();
if( animated || mouseOver )
{
QColor highlight = _helper.alphaColor(_helper.calcLightColor(color),0.5*( animated ? opacity:1.0 ) );
qreal a( r.height() > 30 ? 10.0/r.height():0.1 );
QLinearGradient lg( 0, r.top(), 0, r.bottom() );
lg.setColorAt(0, Qt::transparent );
lg.setColorAt(a, highlight );
lg.setColorAt(1.0-a, highlight );
lg.setColorAt(1, Qt::transparent );
painter->fillRect( r, lg );
}
const int ngroups( qMax(1,h / 250) );
int center( (h - (ngroups-1) * 250) /2 + r.top() );
for(int k = 0; k < ngroups; k++, center += 250)
{
_helper.renderDot( painter, QPoint(r.left()+1, center-3), color);
_helper.renderDot( painter, QPoint(r.left()+1, center), color);
_helper.renderDot( painter, QPoint(r.left()+1, center+3), color);
}
} else {
const int w( r.width() );
if( animated || mouseOver )
{
const QColor highlight( _helper.alphaColor(_helper.calcLightColor(color),0.5*( animated ? opacity:1.0 ) ) );
const qreal a( r.width() > 30 ? 10.0/r.width():0.1 );
QLinearGradient lg( r.left(), 0, r.right(), 0 );
lg.setColorAt(0, Qt::transparent );
lg.setColorAt(a, highlight );
lg.setColorAt(1.0-a, highlight );
lg.setColorAt(1, Qt::transparent );
painter->fillRect( r, lg );
}
int ngroups = qMax(1, w / 250);
int center = (w - (ngroups-1) * 250) /2 + r.left();
for(int k = 0; k < ngroups; k++, center += 250)
{
_helper.renderDot( painter, QPoint(center-3, r.top()+1), color);
_helper.renderDot( painter, QPoint(center, r.top()+1), color);
_helper.renderDot( painter, QPoint(center+3, r.top()+1), color);
}
}
}
//---------------------------------------------------------
// renderRadioButton
//---------------------------------------------------------
void MgStyle::renderRadioButton(QPainter* painter, const QRect& rect,
const QPalette& palette, StyleOptions options, CheckBoxState state,
qreal opacity, AnimationMode mode) const
{
const int s( CheckBox_Size );
const QRect r( centerRect(rect, s, s) );
const int x = r.x();
const int y = r.y();
const QColor color( palette.color(QPalette::Button) );
const QColor glow( slabShadowColor( color, options, opacity, mode ) );
QPixmap slabPixmap = glow.isValid() ? _helper.roundSlabFocused( color, glow, 0.0 ):_helper.roundSlab( color, 0.0 );
painter->drawPixmap(x, y, slabPixmap);
// draw the radio mark
if (state == CheckOn) {
const qreal radius( 2.6 );
const qreal dx( 0.5*r.width() - radius );
const qreal dy( 0.5*r.height() - radius );
painter->save();
painter->setRenderHints(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
const QColor background( palette.color( QPalette::Button ) );
const QColor color( palette.color(QPalette::ButtonText) );
painter->setBrush( _helper.calcLightColor( background ) );
painter->translate( 0, radius/2 );
painter->drawEllipse( QRectF(r).adjusted(dx, dy, -dx, -dy) );
painter->setBrush( _helper.decoColor( background, color ) );
painter->translate( 0, -radius/2 );
painter->drawEllipse( QRectF(r).adjusted(dx, dy, -dx, -dy ) );
painter->restore();
}
}
//---------------------------------------------------------
// slabShadowColor
//---------------------------------------------------------
QColor MgStyle::slabShadowColor(QColor color, StyleOptions options, qreal opacity, AnimationMode mode) const
{
QColor glow;
if( mode == AnimationNone || opacity < 0 ) {
if( options & Hover )
glow = _helper.viewHoverBrush().brush(QPalette::Active).color();
else if( options & Focus )
glow = _helper.viewFocusBrush().brush(QPalette::Active).color();
else if( (options & SubtleShadow) && color.isValid() )
glow = _helper.alphaColor(_helper.calcShadowColor(color), 0.15 );
}
else if( mode == AnimationHover ) {
// animated color, hover
if( options & Focus )
glow = _helper.viewFocusBrush().brush(QPalette::Active).color();
else if( (options & SubtleShadow) && color.isValid() )
glow = _helper.alphaColor(_helper.calcShadowColor(color), 0.15 );
if( glow.isValid() )
glow = ColorUtils::mix( glow, _helper.viewHoverBrush().brush(QPalette::Active).color(), opacity );
else
glow = _helper.alphaColor( _helper.viewHoverBrush().brush(QPalette::Active).color(), opacity );
}
else if( mode == AnimationFocus ) {
if( options & Hover )
glow = _helper.viewHoverBrush().brush(QPalette::Active).color();
else if( (options & SubtleShadow) && color.isValid() )
glow = _helper.alphaColor(_helper.calcShadowColor(color), 0.15 );
if( glow.isValid() )
glow = ColorUtils::mix( glow, _helper.viewFocusBrush().brush(QPalette::Active).color(), opacity );
else
glow = _helper.alphaColor( _helper.viewFocusBrush().brush(QPalette::Active).color(), opacity );
}
return glow;
}
void MgStyle::renderCheckBox(
QPainter *painter, const QRect &rect, const QPalette &palette,
StyleOptions options, CheckBoxState state,
qreal opacity,
AnimationMode mode ) const
{
const int s( qMin(rect.width(), rect.height()) );
//const int s( CheckBox_Size );
const QRect r( centerRect(rect, s, s) );
if( options & Sunken ) _helper.holeFlat( palette.color(QPalette::Window), 0.0 )->render( r, painter, TileSet::Full );
else renderSlab( painter, r, palette.color(QPalette::Button), options, opacity, mode, TileSet::Ring );
// check mark
const qreal x( r.center().x() - 3.5 );
const qreal y( r.center().y() - 2.5 );
if( state != CheckOff)
{
qreal penThickness( 2.0 );
const QColor color( (options&Sunken) ? palette.color(QPalette::WindowText): palette.color(QPalette::ButtonText) );
const QColor background( (options&Sunken) ? palette.color(QPalette::Window): palette.color(QPalette::Button) );
QPen pen( _helper.decoColor( background, color ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
QPen contrastPen( _helper.calcLightColor( background ), penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
pen.setCapStyle(Qt::RoundCap);
if( state == CheckTriState)
{
QVector<qreal> dashes;
if( MgStyleConfigData_checkBoxStyle_CS_CHECK)
{
dashes << 1.0 << 2.0;
penThickness = 1.3;
pen.setWidthF(penThickness);
contrastPen.setWidthF(penThickness);
} else {
dashes << 0.4 << 2.0;
}
pen.setDashPattern(dashes);
contrastPen.setDashPattern(dashes);
}
painter->save();
if( !(options&Sunken) ) painter->translate(0, -1);
painter->setRenderHint(QPainter::Antialiasing);
const qreal offset( qMin( penThickness, qreal(1.0) ) );
if( MgStyleConfigData_checkBoxStyle_CS_CHECK)
{
painter->setPen(contrastPen);
painter->translate( 0, offset );
painter->drawLine(QPointF(x+9, y), QPointF(x+3,y+7));
painter->drawLine(QPointF(x, y+4), QPointF(x+3,y+7));
painter->setPen(pen);
painter->translate( 0, -offset );
painter->drawLine(QPointF(x+9, y), QPointF(x+3,y+7));
painter->drawLine(QPointF(x, y+4), QPointF(x+3,y+7));
} else {
if( options&Sunken )
{
painter->setPen(contrastPen);
painter->translate( 0, offset );
painter->drawLine(QPointF(x+8, y), QPointF(x+1,y+7));
painter->drawLine(QPointF(x+8, y+7), QPointF(x+1,y));
painter->setPen(pen);
painter->translate( 0, -offset );
painter->drawLine(QPointF(x+8, y), QPointF(x+1,y+7));
painter->drawLine(QPointF(x+8, y+7), QPointF(x+1,y));
} else {
painter->setPen(contrastPen);
painter->translate( 0, offset );
painter->drawLine(QPointF(x+8, y-1), QPointF(x,y+7));
painter->drawLine(QPointF(x+8, y+7), QPointF(x,y-1));
painter->setPen(pen);
painter->translate( 0, -offset );
painter->drawLine(QPointF(x+8, y-1), QPointF(x,y+7));
painter->drawLine(QPointF(x+8, y+7), QPointF(x,y-1));
}
}
painter->restore();
}
return;
}
void MgStyle::renderScrollBarHole(
QPainter *painter, const QRect &r, const QColor &color,
const Qt::Orientation& orientation, const TileSet::Tiles& tiles) const
{
if( !r.isValid() ) return;
// one need to make smaller shadow
// (notably on the size when rect height is too high)
const bool smallShadow( r.height() < 10 );
_helper.scrollHole( color, orientation, smallShadow )->render( r, painter, tiles );
}
//---------------------------------------------------------
// renderScrollBarHandle
//---------------------------------------------------------
void MgStyle::renderScrollBarHandle(
QPainter* painter, const QRect& r, const QPalette& palette,
const Qt::Orientation& orientation, const bool& hover, const qreal& opacity ) const
{
if( !r.isValid()) return;
painter->save();
painter->setRenderHints(QPainter::Antialiasing);
const QColor color( palette.color(QPalette::Button) );
const QColor light( _helper.calcLightColor(color) );
const QColor mid( _helper.calcMidColor(color) );
const QColor dark( _helper.calcDarkColor(color) );
const QColor shadow( _helper.calcShadowColor(color) );
const bool horizontal( orientation == Qt::Horizontal );
// draw the hole as background
const QRect holeRect( horizontal ? r.adjusted(-4,0,4,0) : r.adjusted(0,-3,0,4) );
renderScrollBarHole( painter, holeRect, palette.color(QPalette::Window), orientation, horizontal ? TileSet::Vertical : TileSet::Horizontal );
// draw the slider itself
QRectF rect( horizontal ? r.adjusted(3, 2, -3, -3):r.adjusted(3, 4, -3, -3) );
if( !rect.isValid())
{
// e.g. not enough height
painter->restore();
return;
}
// draw the slider
QColor glowColor;
if( !MgStyleConfigData_scrollBarColored)
{
QColor base = ColorUtils::mix(dark, shadow, 0.5);
QColor hovered = _helper.viewHoverBrush().brush(QPalette::Active).color();
if( opacity >= 0 ) glowColor = ColorUtils::mix( base, hovered, opacity );
else if( hover ) glowColor = hovered;
else glowColor = base;
} else {
glowColor = ColorUtils::mix(dark, shadow, 0.5);
}
// glow / shadow
painter->setPen(Qt::NoPen);
painter->setBrush(_helper.alphaColor(glowColor, 0.6));
painter->drawRoundedRect(rect.adjusted(-0.8,-0.8,0.8,0.8), 3, 3);
painter->setPen(QPen( _helper.alphaColor(glowColor, 0.3), 1.5));
if( horizontal) painter->drawRoundedRect(rect.adjusted(-1.2,-0.8,1.2,0.8), 3, 3);
else painter->drawRoundedRect(rect.adjusted(-0.8,-1.2,0.8,1.2), 3, 3);
// colored background
painter->setPen(Qt::NoPen);
if( MgStyleConfigData_scrollBarColored)
{
if( opacity >= 0 ) painter->setBrush( ColorUtils::mix( color, palette.color(QPalette::Highlight), opacity ) );
else if( hover ) painter->setBrush( palette.color(QPalette::Highlight) );
else painter->setBrush( color );
painter->drawRoundedRect(rect, 2, 2);
}
// slider gradient
{
QLinearGradient sliderGradient( rect.topLeft(), horizontal ? rect.bottomLeft() : rect.topRight());
if( !MgStyleConfigData_scrollBarColored)
{
sliderGradient.setColorAt(0.0, color);
sliderGradient.setColorAt(1.0, mid);
} else {
sliderGradient.setColorAt(0.0, _helper.alphaColor( light, 0.6 ));
sliderGradient.setColorAt(0.3, _helper.alphaColor( dark, 0.3 ));
sliderGradient.setColorAt(1.0, _helper.alphaColor( light, 0.8 ));
}
painter->setBrush(sliderGradient);
painter->drawRoundedRect(rect, 2, 2);
}
// pattern
if( MgStyleConfigData_scrollBarBevel )
{
// don't let the pattern move
QPoint offset = horizontal ? QPoint(-rect.left(), 0) : QPoint(0, -rect.top());
QPoint periodEnd = offset + (horizontal ? QPoint(30, 0) : QPoint(0, 30));
QLinearGradient patternGradient(rect.topLeft()+offset, rect.topLeft()+periodEnd);
if( !MgStyleConfigData_scrollBarColored)
{
patternGradient.setColorAt(0.0, _helper.alphaColor(shadow, 0.1));
patternGradient.setColorAt(1.0, _helper.alphaColor(light, 0.1));
} else {
patternGradient.setColorAt(0.0, _helper.alphaColor(shadow, 0.15));
patternGradient.setColorAt(1.0, _helper.alphaColor(light, 0.15));
}
patternGradient.setSpread(QGradient::ReflectSpread);
painter->setBrush(patternGradient);
painter->drawRoundedRect(rect, 2, 2);
}
if( MgStyleConfigData_scrollBarColored) {
painter->restore();
return;
}
// bevel
{
QLinearGradient bevelGradient( rect.topLeft(), horizontal ? rect.topRight() : rect.bottomLeft());
bevelGradient.setColorAt(0.0, Qt::transparent);
bevelGradient.setColorAt(0.5, light);
bevelGradient.setColorAt(1.0, Qt::transparent);
rect.adjust(0.5, 0.5, -0.5, -0.5); // for sharper lines
painter->setPen(QPen(bevelGradient, 1.0));
painter->drawLine(rect.topLeft(), horizontal ? rect.topRight() : rect.bottomLeft());
painter->drawLine(rect.bottomRight(), horizontal ? rect.bottomLeft() : rect.topRight());
}
painter->restore();
}
//---------------------------------------------------------
// renderScrollBarArrow
//---------------------------------------------------------
void MgStyle::renderScrollBarArrow(QPainter* painter, const QRect& r, const QColor& color,
const QColor& background, ArrowOrientation orientation) const
{
const qreal penThickness = 1.6;
QPolygonF a(genericArrow(orientation, ArrowNormal));
const QColor contrast(_helper.calcLightColor(background));
const QColor base(_helper.decoColor(background, color));
painter->save();
painter->translate( r.center() );
painter->setRenderHint(QPainter::Antialiasing);
const qreal offset( qMin( penThickness, qreal(1.0)) );
painter->translate(0,offset);
painter->setPen( QPen( contrast, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
painter->translate(0,-offset);
painter->setPen(QPen( base, penThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPolyline(a);
painter->restore();
}
//______________________________________________________________________________
QColor MgStyle::scrollBarArrowColor( const QStyleOption* option, const SubControl& control, const QWidget* widget ) const
{
const QRect& r( option->rect );
const QPalette& palette( option->palette );
QColor color( palette.color( QPalette::WindowText ) );
const bool enabled( option->state & State_Enabled );
if( !enabled ) return color;
const bool hover( animations().scrollBarEngine().isHovered( widget, control ) );
const bool animated( animations().scrollBarEngine().isAnimated( widget, control ) );
const qreal opacity( animations().scrollBarEngine().opacity( widget, control ) );
QPoint position( hover ? widget->mapFromGlobal( QCursor::pos() ) : QPoint( -1, -1 ) );
if( hover && r.contains( position ) )
{
// we need to update the arrow controlRect on fly because there is no
// way to get it from the styles directly, outside of repaint events
animations().scrollBarEngine().setSubControlRect( widget, control, r );
}
if( r.intersects( animations().scrollBarEngine().subControlRect( widget, control ) ) )
{
QColor highlight = _helper.viewHoverBrush().brush(palette).color();
if( animated )
{
color = ColorUtils::mix( color, highlight, opacity );
} else if( hover ) {
color = highlight;
}
}
return color;
}
//______________________________________________________________________________
void MgStyle::renderSliderTickmarks( QPainter* painter, const QStyleOptionSlider* option, const QWidget* widget ) const
{
const int& ticks( option->tickPosition );
const int available( pixelMetric(PM_SliderSpaceAvailable, option, widget) );
int interval = option->tickInterval;
if( interval < 1 ) interval = option->pageStep;
if( interval < 1 ) return;
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const int fudge( pixelMetric(PM_SliderLength, option, widget) / 2 );
int current( option->minimum );
// Since there is no subrect for tickmarks do a translation here.
painter->save();
painter->translate(r.x(), r.y());
if( option->orientation == Qt::Horizontal )
{
QColor base( _helper.backgroundColor( palette.color( QPalette::Window ), widget, r.center() ) );
painter->setPen( _helper.calcDarkColor( base ) );
}
int tickSize( option->orientation == Qt::Horizontal ? r.height()/3:r.width()/3 );
while( current <= option->maximum )
{
const int position( sliderPositionFromValue(option->minimum, option->maximum, current, available) + fudge );
// calculate positions
if( option->orientation == Qt::Horizontal )
{
if( ticks == QSlider::TicksAbove ) painter->drawLine( position, 0, position, tickSize );
else if( ticks == QSlider::TicksBelow ) painter->drawLine( position, r.height()-tickSize, position, r.height() );
else {
painter->drawLine( position, 0, position, tickSize );
painter->drawLine( position, r.height()-tickSize, position, r.height() );
}
} else {
QColor base( _helper.backgroundColor( palette.color( QPalette::Window ), widget, QPoint( r.center().x(), position ) ) );
painter->setPen( _helper.calcDarkColor( base ) );
if( ticks == QSlider::TicksAbove ) painter->drawLine( 0, position, tickSize, position );
else if( ticks == QSlider::TicksBelow ) painter->drawLine( r.width()-tickSize, position, r.width(), position );
else {
painter->drawLine( 0, position, tickSize, position );
painter->drawLine( r.width()-tickSize, position, r.width(), position );
}
}
// go to next position
current += interval;
}
painter->restore();
}
//---------------------------------------------------------
// genericArrow
//---------------------------------------------------------
QPolygonF MgStyle::genericArrow(MgStyle::ArrowOrientation orientation, MgStyle::ArrowSize size) const
{
QPolygonF a(3);
switch (orientation) {
case ArrowUp: {
if (size == ArrowTiny)
a << QPointF(-1.75, 1.125) << QPointF(0.5, -1.125) << QPointF(2.75, 1.125);
else if( size == ArrowSmall )
a << QPointF( -2,1.5) << QPointF(0.5, -1.5) << QPointF(3,1.5);
else
a << QPointF( -3,2.5) << QPointF(0.5, -1.5) << QPointF(4,2.5);
break;
}
case ArrowDown: {
if( size == ArrowTiny )
a << QPointF( -1.75, -1.125 ) << QPointF( 0.5, 1.125 ) << QPointF( 2.75, -1.125 );
else if( size == ArrowSmall )
a << QPointF( -2,-1.5) << QPointF(0.5, 1.5) << QPointF(3,-1.5);
else
a << QPointF( -3,-1.5) << QPointF(0.5, 2.5) << QPointF(4,-1.5);
break;
}
case ArrowLeft: {
if( size == ArrowTiny )
a << QPointF( 1.125, -1.75 ) << QPointF( -1.125, 0.5 ) << QPointF( 1.125, 2.75 );
else if( size == ArrowSmall )
a << QPointF(1.5,-2) << QPointF(-1.5, 0.5) << QPointF(1.5,3);
else
a << QPointF(2.5,-3) << QPointF(-1.5, 0.5) << QPointF(2.5,4);
break;
}
case ArrowRight: {
if( size == ArrowTiny )
a << QPointF( -1.125, -1.75 ) << QPointF( 1.125, 0.5 ) << QPointF( -1.125, 2.75 );
else if( size == ArrowSmall )
a << QPointF(-1.5,-2) << QPointF(1.5, 0.5) << QPointF(-1.5,3);
else
a << QPointF(-1.5,-3) << QPointF(2.5, 0.5) << QPointF(-1.5,4);
break;
}
default:
break;
}
return a;
}
//---------------------------------------------------------
// renderDialSlab
//---------------------------------------------------------
void MgStyle::renderDialSlab( QPainter *painter, const QRect& r, const QColor &color, const QStyleOption *option, StyleOptions opts, qreal opacity, AnimationMode mode) const
{
// cast option
const QStyleOptionSlider* sliderOption( qstyleoption_cast<const QStyleOptionSlider*>( option ) );
if( !sliderOption ) return;
// adjust rect to be square, and centered
const int dimension( qMin( r.width(), r.height() ) );
const QRect rect( centerRect( r, dimension, dimension ) );
// calculate glow color
const QColor glow( slabShadowColor( color, opts, opacity, mode ) );
// get main slab
QPixmap pix( glow.isValid() ? _helper.dialSlabFocused( color, glow, 0.0, dimension ) : _helper.dialSlab( color, 0.0, dimension ));
const qreal baseOffset( 3.5 );
const QColor light( _helper.calcLightColor(color) );
const QColor shadow( _helper.calcShadowColor(color) );
QPainter p( &pix );
p.setPen( Qt::NoPen );
p.setRenderHints(QPainter::Antialiasing);
// indicator
qreal angle(0);
if( sliderOption->maximum == sliderOption->minimum ) angle = M_PI / 2;
else {
const qreal fraction( qreal(sliderOption->sliderValue - sliderOption->minimum)/qreal(sliderOption->maximum - sliderOption->minimum));
if( sliderOption->dialWrapping ) angle = 1.5*M_PI - fraction*2*M_PI;
else angle = (M_PI*8 - fraction*10*M_PI)/6;
}
QPointF center( pix.rect().center() );
const int sliderWidth( dimension/6 );
const qreal radius( 0.5*( dimension - 2*sliderWidth ) );
center += QPointF( radius*cos(angle), -radius*sin(angle));
QRectF sliderRect( 0, 0, sliderWidth, sliderWidth );
sliderRect.moveCenter( center );
// outline circle
const qreal offset( 0.3 );
QLinearGradient lg( 0, baseOffset, 0, baseOffset + 2*sliderRect.height() );
p.setBrush( light );
p.setPen( Qt::NoPen );
p.drawEllipse( sliderRect.translated(0, offset) );
// mask
p.setPen( Qt::NoPen );
p.save();
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
p.setBrush(QBrush(Qt::black));
p.drawEllipse( sliderRect );
p.restore();
// shadow
p.translate( sliderRect.topLeft() );
_helper.drawInverseShadow( p, shadow.darker(200), 0.0, sliderRect.width(), 0.0 );
// glow
if( glow.isValid() ) _helper.drawInverseGlow( p, glow, 0.0, sliderRect.width(), sliderRect.width() );
p.end();
painter->drawPixmap( rect.topLeft(), pix );
return;
}
void MgStyle::renderButtonSlab(QPainter *painter, QRect r, const QColor &color, StyleOptions options, qreal opacity,
AnimationMode mode,
TileSet::Tiles tiles) const
{
if( (r.width() <= 0) || (r.height() <= 0)) return;
r.translate(0,-1);
if( !painter->clipRegion().isEmpty() ) painter->setClipRegion( painter->clipRegion().translated(0,-1) );
if( options & Sunken) r.adjust( -1, 0, 1, 1 );
// fill
if( !(options & NoFill))
{
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
if( _helper.calcShadowColor(color).value() > color.value() && (options & Sunken) )
{
QLinearGradient innerGradient(0, r.top(), 0, r.bottom() + r.height());
innerGradient.setColorAt(0.0, color);
innerGradient.setColorAt(1.0, _helper.calcLightColor(color));
painter->setBrush(innerGradient);
} else if(options & Sunken) {
QLinearGradient innerGradient(0, r.top() - r.height(), 0, r.bottom());
innerGradient.setColorAt(0.0, _helper.calcLightColor(color));
innerGradient.setColorAt(1.0, color);
painter->setBrush(innerGradient);
} else {
QLinearGradient innerGradient(0, r.top()-0.2*r.height(), 0, r.bottom()+ 0.4*r.height() );
innerGradient.setColorAt(0.0, _helper.calcLightColor(color));
innerGradient.setColorAt(0.6, color );
painter->setBrush(innerGradient);
}
_helper.fillSlab(*painter, r);
painter->restore();
}
// edges
// for slabs, hover takes precedence over focus (other way around for holes)
// but in any case if the button is sunken we don't show focus nor hover
TileSet *tile;
if( options & Sunken)
{
tile = _helper.slabSunken(color, 0.0);
} else {
QColor glow = slabShadowColor( color, options, opacity, mode );
tile = glow.isValid() ? _helper.slabFocused(color, glow, 0.0) : _helper.slab(color, 0.0);
}
tile->render(r, painter, tiles);
}
//---------------------------------------------------------
// renderSlab
//---------------------------------------------------------
void MgStyle::renderSlab(QPainter *painter, QRect r, const QColor &color, StyleOptions options, qreal opacity,
AnimationMode mode, TileSet::Tiles tiles) const
{
// check rect
if( !r.isValid() )
return;
// this is needed for button vertical alignment
r.translate(0,-1);
if (!painter->clipRegion().isEmpty())
painter->setClipRegion( painter->clipRegion().translated(0,-1));
// additional adjustment for sunken frames
if (options & Sunken)
r.adjust(-1,0,1,2);
// fill
if (!(options & NoFill)) {
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
if (_helper.calcShadowColor(color).value() > color.value() && (options & Sunken)) {
QLinearGradient innerGradient(0, r.top(), 0, r.bottom() + r.height());
innerGradient.setColorAt(0.0, color);
innerGradient.setColorAt(1.0, _helper.calcLightColor(color));
painter->setBrush(innerGradient);
}
else {
QLinearGradient innerGradient(0, r.top() - r.height(), 0, r.bottom());
innerGradient.setColorAt(0.0, _helper.calcLightColor(color));
innerGradient.setColorAt(1.0, color);
painter->setBrush(innerGradient);
}
_helper.fillSlab(*painter, r);
painter->restore();
}
// edges
// for slabs, hover takes precedence over focus (other way around for holes)
// but in any case if the button is sunken we don't show focus nor hover
TileSet* tile = 0;
if ((options & Sunken) && color.isValid())
tile = _helper.slabSunken(color, 0.0);
else {
// calculate proper glow color based on current settings and opacity
QColor glow(slabShadowColor(color, options, opacity, mode));
if (glow.isValid())
tile = _helper.slabFocused(color, glow , 0.0);
else if (color.isValid())
tile = _helper.slab(color, 0.0);
else
return;
}
// render tileset
if (tile)
tile->render(r, painter, tiles);
}
void MgStyle::fillTabBackground( QPainter* painter, const QRect &r, const QColor &color, QTabBar::Shape shape, const QWidget* widget ) const
{
// filling
QRect fillRect(r);
switch( shape )
{
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
fillRect.adjust( 4, 4, -4, -6 );
break;
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
fillRect.adjust( 4, 4, -4, -4 );
break;
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
fillRect.adjust( 4, 3, -5, -5 );
break;
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
fillRect.adjust( 5, 3, -4, -5 );
break;
default: return;
}
if( widget ) _helper.renderWindowBackground( painter, fillRect, widget, color );
else painter->fillRect( fillRect, color );
}
void MgStyle::fillTab( QPainter* painter, const QRect &r, const QColor &color, QTabBar::Shape shape, bool active ) const
{
const QColor dark( _helper.calcDarkColor(color) );
const QColor shadow( _helper.calcShadowColor(color) );
const QColor light( _helper.calcLightColor(color) );
const QColor hl( _helper.viewFocusBrush().brush(QPalette::Active).color() );
const QRect fillRect( r.adjusted(4, 3,-4,-5) );
QLinearGradient highlight;
switch( shape )
{
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
highlight = QLinearGradient(fillRect.topLeft(), fillRect.bottomLeft());
break;
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
highlight = QLinearGradient(fillRect.bottomLeft(), fillRect.topLeft());
break;
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
highlight = QLinearGradient(fillRect.topRight(), fillRect.topLeft());
break;
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
highlight = QLinearGradient(fillRect.topLeft(), fillRect.topRight());
break;
default: return;
}
if( active) {
highlight.setColorAt(0.0, _helper.alphaColor(light, 0.5));
highlight.setColorAt(0.1, _helper.alphaColor(light, 0.5));
highlight.setColorAt(0.25, _helper.alphaColor(light, 0.3));
highlight.setColorAt(0.5, _helper.alphaColor(light, 0.2));
highlight.setColorAt(0.75, _helper.alphaColor(light, 0.1));
highlight.setColorAt(0.9, Qt::transparent);
} else {
// inactive
highlight.setColorAt(0.0, _helper.alphaColor(light, 0.1));
highlight.setColorAt(0.4, _helper.alphaColor(dark, 0.5));
highlight.setColorAt(0.8, _helper.alphaColor(dark, 0.4));
highlight.setColorAt(0.9, Qt::transparent);
}
painter->setRenderHints(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
painter->setBrush(highlight);
painter->drawRoundedRect( fillRect, 2, 2 );
}
//---------------------------------------------------------
// drawControl
//---------------------------------------------------------
void MgStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
painter->save();
StyleControl fcn(0);
if (element == CE_CapacityBar)
fcn = &MgStyle::drawCapacityBarControl;
else {
switch (element) {
case CE_ComboBoxLabel: fcn = &MgStyle::drawComboBoxLabelControl; break;
case CE_DockWidgetTitle: fcn = &MgStyle::drawDockWidgetTitleControl; break;
case CE_HeaderEmptyArea: fcn = &MgStyle::drawHeaderEmptyAreaControl; break;
case CE_HeaderLabel: fcn = &MgStyle::drawHeaderLabelControl; break;
case CE_HeaderSection: fcn = &MgStyle::drawHeaderSectionControl; break;
case CE_MenuBarEmptyArea: fcn = &MgStyle::emptyControl; break;
case CE_MenuBarItem: fcn = &MgStyle::drawMenuBarItemControl; break;
case CE_MenuItem: fcn = &MgStyle::drawMenuItemControl; break;
case CE_ProgressBar: fcn = &MgStyle::drawProgressBarControl; break;
case CE_ProgressBarContents: fcn = &MgStyle::drawProgressBarContentsControl; break;
case CE_ProgressBarGroove: fcn = &MgStyle::drawProgressBarGrooveControl; break;
case CE_ProgressBarLabel: fcn = &MgStyle::drawProgressBarLabelControl; break;
/*
for CE_PushButtonBevel the only thing that is done is draw the PanelButtonCommand primitive
since the prototypes are identical we register the second directly in the control map: fcn = without
using an intermediate function
*/
case CE_PushButtonBevel: fcn = &MgStyle::drawPanelButtonCommandPrimitive; break;
case CE_PushButtonLabel: fcn = &MgStyle::drawPushButtonLabelControl; break;
case CE_RubberBand: fcn = &MgStyle::drawRubberBandControl; break;
case CE_ScrollBarSlider: fcn = &MgStyle::drawScrollBarSliderControl; break;
case CE_ScrollBarAddLine: fcn = &MgStyle::drawScrollBarAddLineControl; break;
case CE_ScrollBarAddPage: fcn = &MgStyle::drawScrollBarAddPageControl; break;
case CE_ScrollBarSubLine: fcn = &MgStyle::drawScrollBarSubLineControl; break;
case CE_ScrollBarSubPage: fcn = &MgStyle::drawScrollBarSubPageControl; break;
case CE_ShapedFrame: fcn = &MgStyle::drawShapedFrameControl; break;
case CE_Splitter: fcn = &MgStyle::drawSplitterControl; break;
case CE_TabBarTabLabel: fcn = &MgStyle::drawTabBarTabLabelControl; break;
case CE_TabBarTabShape: fcn = &MgStyle::drawTabBarTabShapeControl_Single; break;
case CE_ToolBar: fcn = &MgStyle::drawToolBarControl; break;
case CE_ToolBoxTabLabel: fcn = &MgStyle::drawToolBoxTabLabelControl; break;
case CE_ToolBoxTabShape: fcn = &MgStyle::drawToolBoxTabShapeControl; break;
case CE_ToolButtonLabel: fcn = &MgStyle::drawToolButtonLabelControl; break;
default: break;
}
}
if (!(fcn && (this->*fcn)(option, painter, widget))) {
QCommonStyle::drawControl(element, option, painter, widget);
}
painter->restore();
}
//---------------------------------------------------------
// drawComplexControl
//---------------------------------------------------------
void MgStyle::drawComplexControl(ComplexControl element, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
{
painter->save();
StyleComplexControl fcn(0);
switch(element) {
case CC_ComboBox: fcn = &MgStyle::drawComboBoxComplexControl; break;
case CC_Dial: fcn = &MgStyle::drawDialComplexControl; break;
case CC_GroupBox: fcn = &MgStyle::drawGroupBoxComplexControl; break;
case CC_Slider: fcn = &MgStyle::drawSliderComplexControl; break;
case CC_SpinBox: fcn = &MgStyle::drawSpinBoxComplexControl; break;
case CC_TitleBar: fcn = &MgStyle::drawTitleBarComplexControl; break;
case CC_ToolButton: fcn = &MgStyle::drawToolButtonComplexControl; break;
default: break;
}
if (!(fcn && (this->*fcn)(option, painter, widget)))
QCommonStyle::drawComplexControl( element, option, painter, widget);
painter->restore();
}
//---------------------------------------------------------
// drawItemText
//---------------------------------------------------------
void MgStyle::drawItemText(QPainter* painter, const QRect& r, int flags, const QPalette& palette,
bool enabled, const QString &text, QPalette::ColorRole textRole ) const
{
if( (flags & Qt::TextShowMnemonic) || !(flags&Qt::TextHideMnemonic) ) {
flags &= ~Qt::TextShowMnemonic;
flags |= _mnemonic;
}
if( animations().widgetEnabilityEngine().enabled() ) {
/*
check if painter engine is registered to WidgetEnabilityEngine, and animated
if yes, merge the palettes. Note: a static_cast is safe here, since only the address
of the pointer is used, not the actual content.
*/
const QWidget* widget( static_cast<const QWidget*>( painter->device() ) );
if (animations().widgetEnabilityEngine().isAnimated( widget, AnimationEnable)) {
const QPalette pal = _helper.mergePalettes(palette, animations().widgetEnabilityEngine().opacity(widget, AnimationEnable));
return QCommonStyle::drawItemText(painter, r, flags, pal, enabled, text, textRole);
}
}
return QCommonStyle::drawItemText(painter, r, flags, palette, enabled, text, textRole);
}
//---------------------------------------------------------
// eventFilter
//---------------------------------------------------------
bool MgStyle::eventFilter(QObject *object, QEvent *event)
{
if (QTabBar* tabBar = qobject_cast<QTabBar*>(object))
return eventFilterTabBar( tabBar, event );
if (QToolBar* toolBar = qobject_cast<QToolBar*>(object))
return eventFilterToolBar( toolBar, event );
if (QDockWidget* dockWidget = qobject_cast<QDockWidget*>(object))
return eventFilterDockWidget(dockWidget, event);
if (QToolBox* toolBox = qobject_cast<QToolBox*>(object))
return eventFilterToolBox(toolBox, event);
if (QMdiSubWindow* subWindow = qobject_cast<QMdiSubWindow*>(object))
return eventFilterMdiSubWindow(subWindow, event);
if (QScrollBar* scrollBar = qobject_cast<QScrollBar*>(object))
return eventFilterScrollBar(scrollBar, event);
// cast to QWidget
QWidget *widget = static_cast<QWidget*>(object);
if (widget->inherits("QComboBoxPrivateContainer"))
return eventFilterComboBoxContainer(widget, event);
return QCommonStyle::eventFilter(object, event);
}
bool MgStyle::drawComboBoxComplexControl( const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget ) const
{
// cast option and check
const QStyleOptionComboBox* cb( qstyleoption_cast<const QStyleOptionComboBox *>(option) );
if( !cb ) return true;
const State& flags( option->state );
const QRect& r( option->rect );
const QPalette& palette( option->palette );
const bool enabled( flags & State_Enabled );
const bool mouseOver(enabled && (flags & State_MouseOver));
const bool hasFocus( flags & State_HasFocus );
const bool& editable( cb->editable );
const bool& hasFrame( cb->frame );
// frame
if( cb->subControls & SC_ComboBoxFrame)
{
// style options
StyleOptions opts = 0;
if( mouseOver ) opts |= Hover;
if( hasFocus ) opts |= Focus;
if( (flags & (State_Sunken|State_On)) && !editable ) opts |= Sunken;
const QColor inputColor( enabled ? palette.color(QPalette::Base) : palette.color(QPalette::Window) );
const QRect editField( subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget) );
if(editable)
{
// editable combobox. Make it look like a LineEdit
// focus takes precedence over hover
animations().lineEditEngine().updateState( widget, AnimationFocus, hasFocus );
animations().lineEditEngine().updateState( widget, AnimationHover, mouseOver && !hasFocus );
const QRect fr( r.adjusted(1,1,-1,-1) );
// input area
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
painter->setBrush(inputColor);
if( !hasFrame )
{
// adjust rect to match frameLess editors
painter->fillRect(r, inputColor);
painter->restore();
} else {
_helper.fillHole( *painter, r.adjusted( 0, -1, 0, 0 ) );
painter->restore();
const QColor color( palette.color(QPalette::Window) );
if( enabled && animations().lineEditEngine().isAnimated( widget, AnimationFocus ) )
{
_helper.renderHole( painter, color, fr, hasFocus, mouseOver, animations().lineEditEngine().opacity( widget, AnimationFocus ), AnimationFocus, TileSet::Ring);
} else if( enabled && animations().lineEditEngine().isAnimated( widget, AnimationHover ) ) {
_helper.renderHole( painter, color, fr, hasFocus, mouseOver, animations().lineEditEngine().opacity( widget, AnimationHover ), AnimationHover, TileSet::Ring);
} else {
_helper.renderHole( painter, color, fr, hasFocus && enabled, mouseOver);
}
}
} else {
// non editable combobox. Make it look like a PushButton
// hover takes precedence over focus
animations().lineEditEngine().updateState( widget, AnimationHover, mouseOver );
animations().lineEditEngine().updateState( widget, AnimationFocus, hasFocus && !mouseOver );
// blend button color to the background
const QColor buttonColor( _helper.backgroundColor( palette.color( QPalette::Button ), widget, r.center() ) );
const QRect slabRect( r.adjusted(-1, 0, 1, 0 ) );
if( !hasFrame )
{
// do nothing.
} else if( enabled && animations().lineEditEngine().isAnimated( widget, AnimationHover ) ) {
const qreal opacity( animations().lineEditEngine().opacity( widget, AnimationHover ) );
renderButtonSlab( painter, slabRect, buttonColor, opts, opacity, AnimationHover, TileSet::Ring );
} else if( enabled && animations().lineEditEngine().isAnimated( widget, AnimationFocus ) ) {
const qreal opacity( animations().lineEditEngine().opacity( widget, AnimationFocus ) );
renderButtonSlab( painter, slabRect, buttonColor, opts, opacity, AnimationFocus, TileSet::Ring );
} else {
renderButtonSlab( painter, slabRect, buttonColor, opts);
}
}
}
if( cb->subControls & SC_ComboBoxArrow)
{
const QComboBox* comboBox = qobject_cast<const QComboBox*>( widget );
const bool empty( comboBox && !comboBox->count() );
QColor color;
QColor background;
bool drawContrast( true );
if( cb->editable )
{
if( enabled && empty ) color = palette.color( QPalette::Disabled, QPalette::Text );
else {
// check animation state
const bool subControlHover( enabled && mouseOver && cb->activeSubControls&SC_ComboBoxArrow );
animations().comboBoxEngine().updateState( widget, AnimationHover, subControlHover );
const bool animated( enabled && animations().comboBoxEngine().isAnimated( widget, AnimationHover ) );
const qreal opacity( animations().comboBoxEngine().opacity( widget, AnimationHover ) );
if( animated )
{
QColor highlight = _helper.viewHoverBrush().brush(palette).color();
color = ColorUtils::mix( palette.color( QPalette::Text ), highlight, opacity );
} else if( subControlHover ) {
color = _helper.viewHoverBrush().brush(palette).color();