File indexing completed on 2024-04-21 14:55:48
0001 /** 0002 * KStyle for KDE4 0003 * Copyright (C) 2004-2005 Maksim Orlovich <maksim@kde.org> 0004 * Copyright (C) 2005,2006 Sandro Giessl <giessl@kde.org> 0005 * 0006 * Based in part on the following software: 0007 * KStyle for KDE3 0008 * Copyright (C) 2001-2002 Karol Szwed <gallium@kde.org> 0009 * Portions (C) 1998-2000 TrollTech AS 0010 * Keramik for KDE3, 0011 * Copyright (C) 2002 Malte Starostik <malte@kde.org> 0012 * (C) 2002-2003 Maksim Orlovich <maksim@kde.org> 0013 * Portions (C) 2001-2002 Karol Szwed <gallium@kde.org> 0014 * (C) 2001-2002 Fredrik Höglund <fredrik@kde.org> 0015 * (C) 2000 Daniel M. Duley <mosfet@kde.org> 0016 * (C) 2000 Dirk Mueller <mueller@kde.org> 0017 * (C) 2001 Martijn Klingens <klingens@kde.org> 0018 * (C) 2003 Sandro Giessl <sandro@giessl.com> 0019 * This library is free software; you can redistribute it and/or 0020 * modify it under the terms of the GNU Library General Public 0021 * License as published by the Free Software Foundation; either 0022 * version 2 of the License, or (at your option) any later version. 0023 * 0024 * This library is distributed in the hope that it will be useful, 0025 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0027 * Library General Public License for more details. 0028 * 0029 * Many thanks to Bradley T. Hughes for the 3 button scrollbar code. 0030 * 0031 * This library is free software; you can redistribute it and/or 0032 * modify it under the terms of the GNU Library General Public 0033 * License version 2 as published by the Free Software Foundation. 0034 * 0035 * This library is distributed in the hope that it will be useful, 0036 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0037 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0038 * Library General Public License for more details. 0039 * 0040 * You should have received a copy of the GNU Library General Public License 0041 * along with this library; see the file COPYING.LIB. If not, write to 0042 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0043 * Boston, MA 02110-1301, USA. 0044 */ 0045 0046 #include "k4style.h" 0047 0048 #include <qalgorithms.h> 0049 #include <QCache> 0050 #include <QEvent> 0051 #include <QVariant> 0052 #include <QAbstractItemView> 0053 #include <QApplication> 0054 #include <QDialogButtonBox> 0055 #include <QFormLayout> 0056 #include <QIcon> 0057 #include <QLabel> 0058 #include <QKeyEvent> 0059 #include <QPainter> 0060 #include <QScrollBar> 0061 #include <QStyleOption> 0062 #include <QPainterPath> 0063 0064 #include <kconfiggroup.h> 0065 #include <QDebug> 0066 #include <kiconloader.h> 0067 #include <kcolorscheme.h> 0068 0069 //### FIXME: Who to credit these to? 0070 static const qint32 u_arrow[] = { -1, -3, 0, -3, -2, -2, 1, -2, -3, -1, 2, -1, -4, 0, 3, 0, -4, 1, 3, 1}; 0071 static const qint32 d_arrow[] = { -4, -2, 3, -2, -4, -1, 3, -1, -3, 0, 2, 0, -2, 1, 1, 1, -1, 2, 0, 2}; 0072 static const qint32 l_arrow[] = { -3, -1, -3, 0, -2, -2, -2, 1, -1, -3, -1, 2, 0, -4, 0, 3, 1, -4, 1, 3}; 0073 static const qint32 r_arrow[] = { -2, -4, -2, 3, -1, -4, -1, 3, 0, -3, 0, 2, 1, -2, 1, 1, 2, -1, 2, 0}; 0074 #define QCOORDARRLEN(x) sizeof(x)/(sizeof(qint32)*2) 0075 0076 /** 0077 TODO: lots of missing widgets, SH_ settings, etc. 0078 0079 Minor stuff: 0080 ProgressBar::Precision handling 0081 */ 0082 0083 // ---------------------------------------------------------------------------- 0084 0085 // For item view selections 0086 struct SelectionTiles { 0087 QPixmap left, center, right; 0088 }; 0089 0090 // ---------------------------------------------------------------------------- 0091 0092 static const QStyle::StyleHint SH_KCustomStyleElement = (QStyle::StyleHint)0xff000001; 0093 static const int X_KdeBase = 0xff000000; 0094 0095 class K4StylePrivate 0096 { 0097 public: 0098 K4StylePrivate(); 0099 QCache<quint64, SelectionTiles> selectionCache; 0100 0101 QHash<QString, int> styleElements; 0102 int hintCounter, controlCounter, subElementCounter; 0103 }; 0104 0105 K4StylePrivate::K4StylePrivate() 0106 { 0107 selectionCache.setMaxCost(10); 0108 controlCounter = subElementCounter = X_KdeBase; 0109 hintCounter = X_KdeBase + 1; //sic! X_KdeBase is covered by SH_KCustomStyleElement 0110 } 0111 0112 // ---------------------------------------------------------------------------- 0113 0114 K4Style::K4Style() : clickedLabel(nullptr), d(new K4StylePrivate) 0115 { 0116 //Set up some default metrics... 0117 setWidgetLayoutProp(WT_Generic, Generic::DefaultFrameWidth, 2); 0118 setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutSpacing, 6); 0119 setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutMargin, 9); 0120 0121 setWidgetLayoutProp(WT_PushButton, PushButton::ContentsMargin, 5); 0122 setWidgetLayoutProp(WT_PushButton, PushButton::FocusMargin, 3); 0123 setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, 2); 0124 setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, 2); 0125 setWidgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, 8); 0126 setWidgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, 6); 0127 0128 setWidgetLayoutProp(WT_Splitter, Splitter::Width, 6); //As KStyle in KDE3 0129 0130 setWidgetLayoutProp(WT_CheckBox, CheckBox::Size, 16); 0131 setWidgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, 6); 0132 setWidgetLayoutProp(WT_CheckBox, CheckBox::NoLabelFocusMargin, 1); 0133 0134 setWidgetLayoutProp(WT_RadioButton, RadioButton::Size, 16); 0135 setWidgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, 6); 0136 0137 setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleTextColor, 0138 ColorMode(QPalette::HighlightedText)); 0139 setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleMargin, 2); 0140 setWidgetLayoutProp(WT_DockWidget, DockWidget::FrameWidth, 3); 0141 setWidgetLayoutProp(WT_DockWidget, DockWidget::SeparatorExtent, 6); 0142 0143 setWidgetLayoutProp(WT_ProgressBar, ProgressBar::GrooveMargin, 2); 0144 setWidgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace, 3); //(Matches QCommonStyle) 0145 setWidgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, 10000); 0146 setWidgetLayoutProp(WT_ProgressBar, ProgressBar::BusyIndicatorSize, 10); 0147 setWidgetLayoutProp(WT_ProgressBar, ProgressBar::Precision, 1); 0148 0149 setWidgetLayoutProp(WT_MenuBar, MenuBar::ItemSpacing, 14); 0150 setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin, 2); 0151 setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, 4); 0152 setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Right, 4); 0153 0154 setWidgetLayoutProp(WT_MenuBarItem, MenuBarItem::Margin, 1); 0155 0156 setWidgetLayoutProp(WT_Menu, Menu::FrameWidth, 1); 0157 setWidgetLayoutProp(WT_Menu, Menu::Margin, 3); 0158 setWidgetLayoutProp(WT_Menu, Menu::ScrollerHeight, 10); 0159 setWidgetLayoutProp(WT_Menu, Menu::TearOffHeight, 10); 0160 0161 setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, 12); 0162 setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, 3); 0163 setWidgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, 12); 0164 setWidgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, 3); 0165 setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, 11); 0166 setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, 3); 0167 setWidgetLayoutProp(WT_MenuItem, MenuItem::Margin, 2); 0168 setWidgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, 0); //the margins give enough rooms 0169 setWidgetLayoutProp(WT_MenuItem, MenuItem::MinHeight, 16); 0170 setWidgetLayoutProp(WT_MenuItem, MenuItem::TextColor, ColorMode(QPalette::Text)); 0171 setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveTextColor, ColorMode(QPalette::HighlightedText)); 0172 setWidgetLayoutProp(WT_MenuItem, MenuItem::DisabledTextColor, ColorMode(QPalette::Text)); 0173 setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveDisabledTextColor, ColorMode(QPalette::Text)); 0174 setWidgetLayoutProp(WT_MenuItem, MenuItem::AccelSpace, 16); 0175 0176 //KDE default is single top button, double bottom one 0177 setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, 0); 0178 setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, 1); 0179 setWidgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, 16); 0180 setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, 32); 0181 setWidgetLayoutProp(WT_ScrollBar, ScrollBar::BarWidth, 16); 0182 setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, 0183 ColorMode(ColorMode::BWAutoContrastMode, QPalette::Button)); 0184 setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, 0185 ColorMode(ColorMode::BWAutoContrastMode, QPalette::ButtonText)); 0186 0187 setWidgetLayoutProp(WT_TabBar, TabBar::TabContentsMargin, 6); 0188 setWidgetLayoutProp(WT_TabBar, TabBar::TabFocusMargin, 3); 0189 setWidgetLayoutProp(WT_TabBar, TabBar::TabOverlap, 0); 0190 setWidgetLayoutProp(WT_TabBar, TabBar::BaseHeight, 2); 0191 setWidgetLayoutProp(WT_TabBar, TabBar::BaseOverlap, 2); 0192 setWidgetLayoutProp(WT_TabBar, TabBar::ScrollButtonWidth, 10); 0193 setWidgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, 6); 0194 0195 setWidgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, 2); 0196 0197 setWidgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, 9); 0198 0199 setWidgetLayoutProp(WT_Slider, Slider::HandleThickness, 20); 0200 setWidgetLayoutProp(WT_Slider, Slider::HandleLength, 16); 0201 0202 setWidgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, 1); 0203 setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonWidth, 16); 0204 setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonSpacing, 1); 0205 setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Right, 1); 0206 setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Top, 1); 0207 setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Bot, 1); 0208 0209 setWidgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, 1); 0210 setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, 16); 0211 setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Right, 1); 0212 setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Top, 1); 0213 setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Bot, 1); 0214 setWidgetLayoutProp(WT_ComboBox, ComboBox::FocusMargin, 1); 0215 0216 setWidgetLayoutProp(WT_Header, Header::ContentsMargin, 3); 0217 setWidgetLayoutProp(WT_Header, Header::TextToIconSpace, 3); 0218 setWidgetLayoutProp(WT_Header, Header::MarkSize, 9); 0219 0220 setWidgetLayoutProp(WT_GroupBox, GroupBox::FrameWidth, 2); 0221 setWidgetLayoutProp(WT_GroupBox, GroupBox::TextAlignTop, false); 0222 setWidgetLayoutProp(WT_GroupBox, GroupBox::TitleTextColor, ColorMode(QPalette::Text)); 0223 0224 setWidgetLayoutProp(WT_ToolBar, ToolBar::HandleExtent, 6); 0225 setWidgetLayoutProp(WT_ToolBar, ToolBar::SeparatorExtent, 6); 0226 setWidgetLayoutProp(WT_ToolBar, ToolBar::ExtensionExtent, 10); 0227 setWidgetLayoutProp(WT_ToolBar, ToolBar::FrameWidth, 2); 0228 setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemSpacing, 3); 0229 setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemMargin, 1); 0230 0231 setWidgetLayoutProp(WT_ToolButton, ToolButton::ContentsMargin, 5); 0232 setWidgetLayoutProp(WT_ToolButton, ToolButton::FocusMargin, 3); 0233 setWidgetLayoutProp(WT_ToolButton, ToolButton::MenuIndicatorSize, 11); 0234 0235 setWidgetLayoutProp(WT_ToolBoxTab, ToolBoxTab::Margin, 0); 0236 0237 setWidgetLayoutProp(WT_Window, Window::TitleTextColor, ColorMode(QPalette::HighlightedText)); 0238 setWidgetLayoutProp(WT_Window, Window::TitleHeight, 20); 0239 setWidgetLayoutProp(WT_Window, Window::TitleMargin, 2); 0240 setWidgetLayoutProp(WT_Window, Window::NoTitleFrame, 0); 0241 setWidgetLayoutProp(WT_Window, Window::ButtonWidth, 16); 0242 setWidgetLayoutProp(WT_Window, Window::ButtonSpace, 2); 0243 setWidgetLayoutProp(WT_Window, Window::ButtonToTextSpace, 3); 0244 } 0245 0246 K4Style::~K4Style() 0247 { 0248 // this is just for stupid msvc compiler to force the creation of 0249 // DoubleButtonOption::defaultOption() inside kstyle lib 0250 // hope the optimizer won't throw it away 0251 const DoubleButtonOption *bOpt = extractOption<const DoubleButtonOption *>(nullptr); 0252 Q_UNUSED(bOpt) 0253 #ifdef __GNUC__ 0254 #warning "mem leak: need to delete bOpt" 0255 #endif 0256 delete d; 0257 } 0258 0259 /* 0260 Custom Style Element runtime extension: 0261 We reserve one StyleHint to let the effective style inform widgets whether it supports certain 0262 string based style elements. 0263 As this could lead to number conflicts (i.e. an app utilizing one of the hints itself for other 0264 purposes) there're various safety mechanisms to rule out such interference. 0265 0266 1) It's most unlikely that a widget in some 3rd party app will accidentally call a general 0267 QStyle/K4Style styleHint() or draw*() and (unconditionally) expect a valid return, however: 0268 a. The StyleHint is not directly above Qt's custom base, assuming most 3rd party apps would 0269 - in case - make use of such 0270 b. In order to be accepted, the StyleHint query must pass a widget with a perfectly matching 0271 name, containing the typical element prefix ("CE_", etc.) and being supported by the current style 0272 c. Instead using Qt's fragile qstyleoption_cast on the QStyleOption provided to the StyleHint 0273 query, try to dump out a string and hope for the best, we now manipulate the widgets objectName(). 0274 Plain Qt dependent widgets can do that themselves and if a widget uses K4Style's convenience access 0275 functions, it won't notice this at all 0276 0277 2) The key problem is that a common KDE widget will run into an apps custom style which will then 0278 falsely respond to the styleHint() call with an invalid value. 0279 To prevent this, supporting styles *must* set a Q_CLASSINFO "X-KDE-CustomElements". 0280 0281 3) If any of the above traps snaps, the returned id is 0 - the QStyle default, indicating 0282 that this element is not supported by the current style. 0283 0284 Obviously, this contains the "diminished clean" action to (temporarily) manipulate the 0285 objectName() of a const QWidget* - but this happens completely inside K4Style or the widget, if 0286 it does not make use of K4Styles static convenience functions. 0287 My biggest worry here would be, that in a multithreaded environment a thread (usually not being 0288 owner of the widget) does something crucially relying on the widgets name property... 0289 This however would also have to happen during the widget construction or stylechanges, when 0290 the functions in doubt will typically be called. 0291 So this is imho unlikely causing any trouble, ever. 0292 */ 0293 0294 /* 0295 The functions called by the real style implementation to add support for a certain element. 0296 Checks for well-formed string (containing the element prefix) and returns 0 otherwise. 0297 Checks whether the element is already supported or inserts it otherwise; Returns the proper id 0298 NOTICE: We could check for "X-KDE-CustomElements", but this would bloat style start up times 0299 (if they e.g. register 100 elements or so) 0300 */ 0301 0302 static inline int newStyleElement(const QString &element, const char *check, int &counter, QHash<QString, int> *elements) 0303 { 0304 if (!element.contains(check)) { 0305 return 0; 0306 } 0307 int id = elements->value(element, 0); 0308 if (!id) { 0309 ++counter; 0310 id = counter; 0311 elements->insert(element, id); 0312 } 0313 return id; 0314 } 0315 0316 QStyle::StyleHint K4Style::newStyleHint(const QString &element) 0317 { 0318 return (StyleHint)newStyleElement(element, "SH_", d->hintCounter, &d->styleElements); 0319 } 0320 0321 QStyle::ControlElement K4Style::newControlElement(const QString &element) 0322 { 0323 return (ControlElement)newStyleElement(element, "CE_", d->controlCounter, &d->styleElements); 0324 } 0325 0326 K4Style::SubElement K4Style::newSubElement(const QString &element) 0327 { 0328 return (SubElement)newStyleElement(element, "SE_", d->subElementCounter, &d->styleElements); 0329 } 0330 0331 QString K4Style::defaultStyle() 0332 { 0333 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) 0334 return QString("breeze"); 0335 #else 0336 return QString(); // native style 0337 #endif 0338 } 0339 0340 /* 0341 The functions called by widgets that request custom element support, passed to the effective style. 0342 Collected in a static inline function due to similarity. 0343 */ 0344 0345 static inline int customStyleElement(QStyle::StyleHint type, const QString &element, QWidget *widget) 0346 { 0347 if (!widget || widget->style()->metaObject()->indexOfClassInfo("X-KDE-CustomElements") < 0) { 0348 return 0; 0349 } 0350 0351 const QString originalName = widget->objectName(); 0352 widget->setObjectName(element); 0353 const int id = widget->style()->styleHint(type, nullptr, widget); 0354 widget->setObjectName(originalName); 0355 return id; 0356 } 0357 0358 QStyle::StyleHint K4Style::customStyleHint(const QString &element, const QWidget *widget) 0359 { 0360 return (StyleHint) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget)); 0361 } 0362 0363 QStyle::ControlElement K4Style::customControlElement(const QString &element, const QWidget *widget) 0364 { 0365 return (ControlElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget)); 0366 } 0367 0368 QStyle::SubElement K4Style::customSubElement(const QString &element, const QWidget *widget) 0369 { 0370 return (SubElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget)); 0371 } 0372 0373 void K4Style::polish(QWidget *w) 0374 { 0375 if (qobject_cast<QLabel *>(w)) { 0376 w->installEventFilter(this); 0377 } 0378 0379 // Enable hover effects in all itemviews 0380 if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(w)) { 0381 itemView->viewport()->setAttribute(Qt::WA_Hover); 0382 } 0383 0384 QCommonStyle::polish(w); 0385 } 0386 void K4Style::unpolish(QWidget *w) 0387 { 0388 if (qobject_cast<QLabel *>(w)) { 0389 w->removeEventFilter(this); 0390 } 0391 0392 QCommonStyle::unpolish(w); 0393 } 0394 void K4Style::polish(QApplication *a) 0395 { 0396 QCommonStyle::polish(a); 0397 } 0398 void K4Style::unpolish(QApplication *a) 0399 { 0400 QCommonStyle::unpolish(a); 0401 } 0402 void K4Style::polish(QPalette &pal) 0403 { 0404 QCommonStyle::polish(pal); 0405 } 0406 QRect K4Style::itemTextRect(const QFontMetrics &fm, const QRect &r, 0407 int flags, bool enabled, 0408 const QString &text) const 0409 { 0410 return QCommonStyle::itemTextRect(fm, r, flags, enabled, text); 0411 } 0412 QRect K4Style::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const 0413 { 0414 return QCommonStyle::itemPixmapRect(r, flags, pixmap); 0415 } 0416 void K4Style::drawItemText(QPainter *painter, const QRect &rect, 0417 int flags, const QPalette &pal, bool enabled, 0418 const QString &text, QPalette::ColorRole textRole) const 0419 { 0420 QCommonStyle::drawItemText(painter, rect, flags, pal, enabled, 0421 text, textRole); 0422 } 0423 void K4Style::drawItemPixmap(QPainter *painter, const QRect &rect, 0424 int alignment, const QPixmap &pixmap) const 0425 { 0426 QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap); 0427 } 0428 QPalette K4Style::standardPalette() const 0429 { 0430 return KColorScheme::createApplicationPalette(KSharedConfig::openConfig()); 0431 } 0432 0433 QIcon K4Style::standardIcon(StandardPixmap standardIcon, const QStyleOption */*option*/, 0434 const QWidget */*widget*/) const 0435 { 0436 switch (standardIcon) { 0437 case QStyle::SP_DesktopIcon: 0438 return QIcon::fromTheme("user-desktop"); 0439 case QStyle::SP_TrashIcon: 0440 return QIcon::fromTheme("user-trash"); 0441 case QStyle::SP_ComputerIcon: 0442 return QIcon::fromTheme("computer"); 0443 case QStyle::SP_DriveFDIcon: 0444 return QIcon::fromTheme("media-floppy"); 0445 case QStyle::SP_DriveHDIcon: 0446 return QIcon::fromTheme("drive-harddisk"); 0447 case QStyle::SP_DriveCDIcon: 0448 case QStyle::SP_DriveDVDIcon: 0449 return QIcon::fromTheme("drive-optical"); 0450 case QStyle::SP_DriveNetIcon: 0451 return QIcon::fromTheme("folder-remote"); 0452 case QStyle::SP_DirHomeIcon: 0453 return QIcon::fromTheme("user-home"); 0454 case QStyle::SP_DirOpenIcon: 0455 return QIcon::fromTheme("document-open-folder"); 0456 case QStyle::SP_DirClosedIcon: 0457 return QIcon::fromTheme("folder"); 0458 case QStyle::SP_DirIcon: 0459 return QIcon::fromTheme("folder"); 0460 case QStyle::SP_DirLinkIcon: 0461 return QIcon::fromTheme("folder"); //TODO: generate (!?) folder with link emblem 0462 case QStyle::SP_FileIcon: 0463 return QIcon::fromTheme("text-plain"); //TODO: look for a better icon 0464 case QStyle::SP_FileLinkIcon: 0465 return QIcon::fromTheme("text-plain"); //TODO: generate (!?) file with link emblem 0466 case QStyle::SP_FileDialogStart: 0467 return QIcon::fromTheme("media-playback-start"); //TODO: find correct icon 0468 case QStyle::SP_FileDialogEnd: 0469 return QIcon::fromTheme("media-playback-stop"); //TODO: find correct icon 0470 case QStyle::SP_FileDialogToParent: 0471 return QIcon::fromTheme("go-up"); 0472 case QStyle::SP_FileDialogNewFolder: 0473 return QIcon::fromTheme("folder-new"); 0474 case QStyle::SP_FileDialogDetailedView: 0475 return QIcon::fromTheme("view-list-details"); 0476 case QStyle::SP_FileDialogInfoView: 0477 return QIcon::fromTheme("document-properties"); 0478 case QStyle::SP_FileDialogContentsView: 0479 return QIcon::fromTheme("view-list-icons"); 0480 case QStyle::SP_FileDialogListView: 0481 return QIcon::fromTheme("view-list-text"); 0482 case QStyle::SP_FileDialogBack: 0483 return QIcon::fromTheme("go-previous"); 0484 case QStyle::SP_MessageBoxInformation: 0485 return QIcon::fromTheme("dialog-information"); 0486 case QStyle::SP_MessageBoxWarning: 0487 return QIcon::fromTheme("dialog-warning"); 0488 case QStyle::SP_MessageBoxCritical: 0489 return QIcon::fromTheme("dialog-error"); 0490 case QStyle::SP_MessageBoxQuestion: 0491 return QIcon::fromTheme("dialog-information"); 0492 case QStyle::SP_DialogOkButton: 0493 return QIcon::fromTheme("dialog-ok"); 0494 case QStyle::SP_DialogCancelButton: 0495 return QIcon::fromTheme("dialog-cancel"); 0496 case QStyle::SP_DialogHelpButton: 0497 return QIcon::fromTheme("help-contents"); 0498 case QStyle::SP_DialogOpenButton: 0499 return QIcon::fromTheme("document-open"); 0500 case QStyle::SP_DialogSaveButton: 0501 return QIcon::fromTheme("document-save"); 0502 case QStyle::SP_DialogCloseButton: 0503 return QIcon::fromTheme("dialog-close"); 0504 case QStyle::SP_DialogApplyButton: 0505 return QIcon::fromTheme("dialog-ok-apply"); 0506 case QStyle::SP_DialogResetButton: 0507 return QIcon::fromTheme("document-revert"); 0508 case QStyle::SP_DialogDiscardButton: 0509 return QIcon::fromTheme("dialog-cancel"); 0510 case QStyle::SP_DialogYesButton: 0511 return QIcon::fromTheme("dialog-ok-apply"); 0512 case QStyle::SP_DialogNoButton: 0513 return QIcon::fromTheme("dialog-cancel"); 0514 case QStyle::SP_ArrowUp: 0515 return QIcon::fromTheme("go-up"); 0516 case QStyle::SP_ArrowDown: 0517 return QIcon::fromTheme("go-down"); 0518 case QStyle::SP_ArrowLeft: 0519 return QIcon::fromTheme("go-previous-view"); 0520 case QStyle::SP_ArrowRight: 0521 return QIcon::fromTheme("go-next-view"); 0522 case QStyle::SP_ArrowBack: 0523 return QIcon::fromTheme("go-previous"); 0524 case QStyle::SP_ArrowForward: 0525 return QIcon::fromTheme("go-next"); 0526 case QStyle::SP_BrowserReload: 0527 return QIcon::fromTheme("view-refresh"); 0528 case QStyle::SP_BrowserStop: 0529 return QIcon::fromTheme("process-stop"); 0530 case QStyle::SP_MediaPlay: 0531 return QIcon::fromTheme("media-playback-start"); 0532 case QStyle::SP_MediaStop: 0533 return QIcon::fromTheme("media-playback-stop"); 0534 case QStyle::SP_MediaPause: 0535 return QIcon::fromTheme("media-playback-pause"); 0536 case QStyle::SP_MediaSkipForward: 0537 return QIcon::fromTheme("media-skip-forward"); 0538 case QStyle::SP_MediaSkipBackward: 0539 return QIcon::fromTheme("media-skip-backward"); 0540 case QStyle::SP_MediaSeekForward: 0541 return QIcon::fromTheme("media-seek-forward"); 0542 case QStyle::SP_MediaSeekBackward: 0543 return QIcon::fromTheme("media-seek-backward"); 0544 case QStyle::SP_MediaVolume: 0545 return QIcon::fromTheme("audio-volume-medium"); 0546 case QStyle::SP_MediaVolumeMuted: 0547 return QIcon::fromTheme("audio-volume-muted"); 0548 0549 default: 0550 return QIcon(); 0551 } 0552 } 0553 0554 QPixmap K4Style::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, 0555 const QWidget *widget) const 0556 { 0557 return QCommonStyle::standardPixmap(standardPixmap, opt, widget); 0558 } 0559 QPixmap K4Style::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, 0560 const QStyleOption *opt) const 0561 { 0562 return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt); 0563 } 0564 0565 void K4Style::drawInsideRect(QPainter *p, const QRect &r) const 0566 { 0567 p->drawRect(r.x(), r.y(), r.width() - 1, r.height() - 1); 0568 } 0569 0570 QRect K4Style::centerRect(const QRect &in, int w, int h) const 0571 { 0572 return QRect(in.x() + (in.width() - w) / 2, in.y() + (in.height() - h) / 2, w, h); 0573 } 0574 0575 QRect K4Style::centerRect(const QRect &in, const QSize &size) const 0576 { 0577 return centerRect(in, size.width(), size.height()); 0578 } 0579 0580 void K4Style::drawKStylePrimitive(WidgetType widgetType, int primitive, 0581 const QStyleOption *opt, 0582 const QRect &r, const QPalette &pal, 0583 State flags, QPainter *p, 0584 const QWidget *widget, 0585 K4Style::Option *kOpt) const 0586 { 0587 switch (widgetType) { 0588 case WT_Tree: { 0589 switch (primitive) { 0590 case Tree::VerticalBranch: 0591 case Tree::HorizontalBranch: 0592 //### FIXME: set sane color. 0593 p->fillRect(r, QBrush(Qt::Dense4Pattern)); 0594 return; 0595 case Tree::ExpanderOpen: 0596 case Tree::ExpanderClosed: { 0597 p->setPen(pal.text().color()); 0598 drawInsideRect(p, r); //the border. 0599 int signLineSize = r.width() / 4; 0600 p->drawLine(r.center().x() - signLineSize, r.center().y(), 0601 r.center().x() + signLineSize, r.center().y()); //- 0602 if (primitive == Tree::ExpanderClosed) //vertical line of + 0603 p->drawLine(r.center().x(), r.center().y() - signLineSize, 0604 r.center().x(), r.center().y() + signLineSize); 0605 return; 0606 } 0607 default: 0608 break; 0609 } 0610 0611 break; 0612 } 0613 0614 case WT_SpinBox: { 0615 switch (primitive) { 0616 case SpinBox::PlusSymbol: 0617 case SpinBox::MinusSymbol: { 0618 p->setPen(pal.buttonText().color()); 0619 0620 int l = qMin(r.width() - 2, r.height() - 2); 0621 QPoint c = r.center(); 0622 0623 p->drawLine(c.x() - l / 2, c.y(), c.x() + l / 2, c.y()); 0624 if (primitive == SpinBox::PlusSymbol) { 0625 p->drawLine(c.x(), c.y() - l / 2, c.x(), c.y() + l / 2); 0626 } 0627 0628 return; 0629 } 0630 default: 0631 break; 0632 } 0633 0634 break; 0635 } 0636 0637 case WT_GroupBox: { 0638 if (primitive == GroupBox::FlatFrame) { 0639 QPen oldPen = p->pen(); 0640 p->setPen(pal.color(QPalette::WindowText)); 0641 p->drawLine(r.topLeft(), r.topRight()); 0642 p->setPen(oldPen); 0643 } 0644 0645 break; 0646 } 0647 0648 case WT_ToolBoxTab: { 0649 if (primitive == ToolBoxTab::Panel) { 0650 drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, flags, p, widget); 0651 } 0652 0653 break; 0654 } 0655 0656 case WT_DockWidget: { 0657 switch (primitive) { 0658 case DockWidget::TitlePanel: 0659 p->fillRect(r, pal.color(QPalette::Highlight)); 0660 return; 0661 0662 case DockWidget::SeparatorHandle: 0663 return; 0664 0665 default: 0666 break; 0667 } 0668 0669 break; 0670 } 0671 0672 case WT_Window: { 0673 switch (primitive) { 0674 case Window::TitlePanel: 0675 p->fillRect(r, pal.color(QPalette::Highlight)); 0676 return; 0677 0678 case Window::ButtonMenu: { 0679 K4Style::TitleButtonOption *tbkOpts = 0680 extractOption<K4Style::TitleButtonOption *>(kOpt); 0681 if (!tbkOpts->icon.isNull()) { 0682 tbkOpts->icon.paint(p, r); 0683 } else { 0684 QStyleOption tool(0); 0685 tool.palette = pal; 0686 // TODO: give it a nice KDE logo. 0687 QPixmap pm = standardPixmap(SP_TitleBarMenuButton, &tool, widget); 0688 tool.rect = r; 0689 p->save(); 0690 drawItemPixmap(p, r, Qt::AlignCenter, pm); 0691 p->restore(); 0692 } 0693 return; 0694 } 0695 0696 case Window::ButtonMin: 0697 case Window::ButtonMax: 0698 case Window::ButtonRestore: 0699 case Window::ButtonClose: 0700 case Window::ButtonShade: 0701 case Window::ButtonUnshade: 0702 case Window::ButtonHelp: { 0703 K4Style::TitleButtonOption *tbkOpts = 0704 extractOption<K4Style::TitleButtonOption *>(kOpt); 0705 State bflags = flags; 0706 bflags &= ~State_Sunken; 0707 if (tbkOpts->active) { 0708 bflags |= State_Sunken; 0709 } 0710 drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, bflags, p, widget); 0711 return; 0712 } 0713 } 0714 0715 break; 0716 } 0717 0718 case WT_TabBar: { 0719 // For vertical text fallback, provide the generic text implementation 0720 // a transformed rotated painter, with rect swizzled appropriately 0721 if (primitive == TabBar::EastText || primitive == TabBar::WestText) { 0722 QTransform tr; 0723 0724 if (primitive == TabBar::WestText) { 0725 tr.translate(r.x(), r.height() + r.y()); 0726 tr.rotate(-90); 0727 } else { 0728 tr.translate(r.width() + r.x(), r.y()); 0729 tr.rotate(90); 0730 } 0731 0732 p->save(); 0733 p->setTransform(tr, true); 0734 drawKStylePrimitive(WT_TabBar, Generic::Text, opt, 0735 QRect(0, 0, r.height(), r.width()), pal, flags, p, widget, kOpt); 0736 p->restore(); 0737 } 0738 break; 0739 } 0740 0741 default: 0742 break; 0743 } 0744 0745 if (primitive == Generic::Text) { 0746 K4Style::TextOption *textOpts = extractOption<K4Style::TextOption *>(kOpt); 0747 0748 //### debug 0749 //p->setPen(Qt::green); 0750 //drawInsideRect(p, r); 0751 0752 QColor col = textOpts->color.color(pal); 0753 QPen old = p->pen(); 0754 p->setPen(col); 0755 drawItemText(p, r, Qt::AlignVCenter | Qt::TextShowMnemonic | textOpts->hAlign, pal, flags & State_Enabled, 0756 textOpts->text); 0757 p->setPen(old); 0758 } else if (primitive == Generic::Icon) { 0759 K4Style::IconOption *iconOpts = extractOption<K4Style::IconOption *>(kOpt); 0760 QIcon::Mode mode; 0761 QIcon::State iconState; 0762 0763 // Select the correct icon from the iconset 0764 if (flags & State_Enabled) 0765 if (iconOpts->active) { 0766 mode = QIcon::Active; 0767 } else { 0768 mode = QIcon::Normal; 0769 } 0770 else { 0771 mode = QIcon::Disabled; 0772 } 0773 0774 if ((flags & State_On) || (flags & State_Sunken)) { 0775 iconState = QIcon::On; 0776 } else { 0777 iconState = QIcon::Off; 0778 } 0779 0780 QSize size = iconOpts->size; 0781 if (!size.isValid()) { 0782 size = QSize(pixelMetric(PM_SmallIconSize), pixelMetric(PM_SmallIconSize)); 0783 } 0784 QPixmap icon = iconOpts->icon.pixmap(size, mode, iconState); 0785 p->drawPixmap(centerRect(r, icon.size()), icon); 0786 } else if (primitive == Generic::FocusIndicator) { 0787 QPen pen; 0788 pen.setWidth(0); 0789 pen.setStyle(Qt::DotLine); 0790 p->setPen(pen); 0791 drawInsideRect(p, r); 0792 } else if (primitive >= Generic::ArrowUp && primitive <= Generic::ArrowLeft) { 0793 //### FIXME: Helper for these sorts of things, as Keramik has virtually 0794 //identical code! 0795 K4Style::ColorOption *colorOpt = extractOption<K4Style::ColorOption *>(kOpt); 0796 QColor arrowColor = colorOpt->color.color(pal); 0797 0798 QPolygon poly; 0799 0800 switch (primitive) { 0801 case Generic::ArrowUp: 0802 poly.setPoints(QCOORDARRLEN(u_arrow), u_arrow); 0803 break; 0804 0805 case Generic::ArrowDown: 0806 poly.setPoints(QCOORDARRLEN(d_arrow), d_arrow); 0807 break; 0808 0809 case Generic::ArrowLeft: 0810 poly.setPoints(QCOORDARRLEN(l_arrow), l_arrow); 0811 break; 0812 0813 default: 0814 poly.setPoints(QCOORDARRLEN(r_arrow), r_arrow); 0815 } 0816 0817 if (flags & State_Enabled) { 0818 //CHECKME: Why is the -1 needed? 0819 poly.translate(r.x() + r.width() / 2 - 1, r.y() + r.height() / 2); 0820 0821 p->setPen(arrowColor); 0822 p->drawPolygon(poly); 0823 } else { 0824 //Disabled ones ignore color parameter 0825 poly.translate(r.x() + r.width() / 2, r.y() + r.height() / 2 + 1); 0826 p->setPen(pal.color(QPalette::Light)); 0827 p->drawPolygon(poly); 0828 poly.translate(-1, -1); 0829 p->setPen(pal.mid().color()); 0830 p->drawPolygon(poly); 0831 } 0832 0833 } 0834 #if 0 //Reenable if you need a debug aid 0835 else { 0836 p->setPen(Qt::red); 0837 drawInsideRect(p, r); 0838 } 0839 #endif 0840 } 0841 0842 void K4Style::setWidgetLayoutProp(WidgetType widget, int metric, int value) 0843 { 0844 if (metrics.size() <= widget) { 0845 metrics.resize(widget + 1); 0846 } 0847 0848 QVector<int> &widgetMetrics = metrics[widget]; 0849 if (widgetMetrics.size() <= metric) { 0850 widgetMetrics.resize(metric + 1); 0851 } 0852 0853 widgetMetrics[metric] = value; 0854 } 0855 0856 int K4Style::widgetLayoutProp(WidgetType widget, int metric, 0857 const QStyleOption *opt, 0858 const QWidget *w) const 0859 { 0860 Q_UNUSED(opt) 0861 Q_UNUSED(w) 0862 0863 if (metrics.size() <= widget) { 0864 return 0; 0865 } 0866 0867 const QVector<int> &widgetMetrics = metrics[widget]; 0868 if (widgetMetrics.size() <= metric) { 0869 return 0; 0870 } 0871 0872 return widgetMetrics[metric]; 0873 } 0874 0875 QSize K4Style::expandDim(const QSize &orig, WidgetType wt, int baseMarginMetric, 0876 const QStyleOption *opt, const QWidget *w, bool rotated) const 0877 { 0878 int addWidth = 2 * widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) + 0879 widgetLayoutProp(wt, baseMarginMetric + Left, opt, w) + 0880 widgetLayoutProp(wt, baseMarginMetric + Right, opt, w); 0881 0882 int addHeight = 2 * widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) + 0883 widgetLayoutProp(wt, baseMarginMetric + Top, opt, w) + 0884 widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w); 0885 0886 return QSize(orig.width() + (rotated ? addHeight : addWidth), 0887 orig.height() + (rotated ? addWidth : addHeight)); 0888 } 0889 0890 QRect K4Style::insideMargin(const QRect &orig, WidgetType wt, 0891 int baseMarginMetric, 0892 const QStyleOption *opt, const QWidget *w) const 0893 { 0894 int x1 = orig.topLeft().x(); 0895 int y1 = orig.topLeft().y(); 0896 int x2 = orig.bottomRight().x(); 0897 int y2 = orig.bottomRight().y(); 0898 0899 x1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w); 0900 x1 += widgetLayoutProp(wt, baseMarginMetric + Left, opt, w); 0901 0902 y1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w); 0903 y1 += widgetLayoutProp(wt, baseMarginMetric + Top, opt, w); 0904 0905 x2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w); 0906 x2 -= widgetLayoutProp(wt, baseMarginMetric + Right, opt, w); 0907 0908 y2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w); 0909 y2 -= widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w); 0910 0911 return QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); 0912 } 0913 0914 QRect K4Style::handleRTL(const QStyleOption *opt, const QRect &subRect) const 0915 { 0916 return visualRect(opt->direction, opt->rect, subRect); 0917 } 0918 0919 QPoint K4Style::handleRTL(const QStyleOption *opt, const QPoint &pos) const 0920 { 0921 return visualPos(opt->direction, opt->rect, pos); 0922 } 0923 0924 void K4Style::drawPrimitive(PrimitiveElement elem, const QStyleOption *option, QPainter *painter, const QWidget *widget) const 0925 { 0926 //Extract the stuff we need out of the option 0927 State flags = option->state; 0928 QRect r = option->rect; 0929 QPalette pal = option->palette; 0930 0931 switch (elem) { 0932 case PE_FrameFocusRect: 0933 drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, option, r, pal, flags, painter, widget); 0934 return; 0935 case PE_IndicatorArrowUp: 0936 drawKStylePrimitive(WT_Generic, Generic::ArrowUp, option, r, pal, flags, painter, widget); 0937 return; 0938 case PE_IndicatorArrowDown: 0939 drawKStylePrimitive(WT_Generic, Generic::ArrowDown, option, r, pal, flags, painter, widget); 0940 return; 0941 case PE_IndicatorArrowLeft: 0942 drawKStylePrimitive(WT_Generic, Generic::ArrowLeft, option, r, pal, flags, painter, widget); 0943 return; 0944 case PE_IndicatorArrowRight: 0945 drawKStylePrimitive(WT_Generic, Generic::ArrowRight, option, r, pal, flags, painter, widget); 0946 return; 0947 case PE_IndicatorMenuCheckMark: 0948 //### check flags 0949 drawKStylePrimitive(WT_MenuItem, MenuItem::CheckOn, option, r, pal, flags, painter, widget); 0950 return; 0951 case PE_IndicatorCheckBox: 0952 if (flags & State_NoChange) { 0953 drawKStylePrimitive(WT_CheckBox, CheckBox::CheckTriState, option, r, pal, flags, painter, widget); 0954 } else if (flags & State_On) { 0955 drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOn, option, r, pal, flags, painter, widget); 0956 } else { 0957 drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOff, option, r, pal, flags, painter, widget); 0958 } 0959 return; 0960 case PE_IndicatorRadioButton: 0961 if (flags & State_On) { 0962 drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOn, option, r, pal, flags, painter, widget); 0963 } else { 0964 drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOff, option, r, pal, flags, painter, widget); 0965 } 0966 return; 0967 case PE_IndicatorBranch: { 0968 int centerX = r.x() + r.width() / 2; 0969 int centerY = r.y() + r.height() / 2; 0970 0971 int expanderAdjust = 0; 0972 //First, determine whether we need to draw an expander. 0973 if (flags & State_Children) { 0974 //How large should we make it? 0975 int sizeLimit = qMin(qMin(r.width(), r.height()), 0976 widgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, option, widget)); 0977 if ((sizeLimit & 1) == 0) { 0978 --sizeLimit; 0979 } 0980 0981 expanderAdjust = sizeLimit / 2 + 1; 0982 0983 QRect expanderRect = QRect(centerX - sizeLimit / 2, centerY - sizeLimit / 2, 0984 sizeLimit, sizeLimit); 0985 0986 drawKStylePrimitive(WT_Tree, flags & State_Open ? Tree::ExpanderOpen : Tree::ExpanderClosed, 0987 option, expanderRect, pal, flags, painter, widget); 0988 } 0989 0990 //Now, draw the branches. The top line gets drawn unless we're completely 0991 //w/o any indication of a neightbor 0992 if (flags & (State_Item | State_Children | State_Sibling)) { 0993 QRect topLine = QRect(QPoint(centerX, r.y()), QPoint(centerX, centerY - expanderAdjust)); 0994 drawKStylePrimitive(WT_Tree, Tree::VerticalBranch, option, topLine, pal, flags, painter, widget); 0995 } 0996 0997 //The right/left (depending on dir) line gets drawn if we have an item 0998 if (flags & State_Item) { 0999 QRect horLine; 1000 if (option->direction == Qt::LeftToRight) 1001 horLine = QRect(QPoint(centerX + expanderAdjust, centerY), 1002 QPoint(r.right(), centerY)); 1003 else 1004 horLine = QRect(QPoint(r.left(), centerY), 1005 QPoint(centerX - expanderAdjust, centerY)); 1006 drawKStylePrimitive(WT_Tree, Tree::HorizontalBranch, option, horLine, pal, flags, painter, widget); 1007 } 1008 1009 //The bottom if we have a sibling 1010 if (flags & State_Sibling) { 1011 QRect botLine = QRect(QPoint(centerX, centerY + expanderAdjust), 1012 QPoint(centerX, r.bottom())); 1013 drawKStylePrimitive(WT_Tree, Tree::VerticalBranch, option, botLine, pal, flags, painter, widget); 1014 } 1015 return; 1016 } 1017 case PE_FrameMenu: 1018 drawKStylePrimitive(WT_Menu, Generic::Frame, option, r, pal, flags, painter, widget); 1019 return; 1020 case PE_IndicatorHeaderArrow: { 1021 const QStyleOptionHeader *hOpt = qstyleoption_cast<const QStyleOptionHeader *>(option); 1022 int primitive = 0; 1023 if (flags & State_UpArrow || (hOpt && hOpt->sortIndicator == QStyleOptionHeader::SortUp)) { 1024 primitive = Generic::ArrowUp; 1025 } else if (flags & State_DownArrow || (hOpt && hOpt->sortIndicator == QStyleOptionHeader::SortDown)) { 1026 primitive = Generic::ArrowDown; 1027 } 1028 if (primitive != 0) { 1029 drawKStylePrimitive(WT_Header, primitive, option, r, pal, flags, painter, widget); 1030 } 1031 return; 1032 } 1033 case PE_FrameTabBarBase: { 1034 drawKStylePrimitive(WT_TabBar, TabBar::BaseFrame, option, r, pal, flags, painter, widget); 1035 return; 1036 } 1037 case PE_IndicatorTabTear: { 1038 drawKStylePrimitive(WT_TabBar, TabBar::IndicatorTear, option, r, pal, flags, painter, widget); 1039 return; 1040 } 1041 case PE_FrameTabWidget: { 1042 drawKStylePrimitive(WT_TabWidget, Generic::Frame, option, r, pal, flags, painter, widget); 1043 return; 1044 } 1045 1046 case PE_PanelLineEdit: { 1047 drawKStylePrimitive(WT_LineEdit, LineEdit::Panel, option, r, pal, flags, painter, widget); 1048 return; 1049 } 1050 1051 case PE_FrameLineEdit: { 1052 drawKStylePrimitive(WT_LineEdit, Generic::Frame, option, r, pal, flags, painter, widget); 1053 return; 1054 } 1055 1056 case PE_FrameGroupBox: { 1057 if (const QStyleOptionFrame *fOpt = 1058 qstyleoption_cast<const QStyleOptionFrame *>(option)) { 1059 QStyleOptionFrame fOpt2(*fOpt); 1060 1061 if (fOpt2.features & QStyleOptionFrame::Flat) { 1062 drawKStylePrimitive(WT_GroupBox, GroupBox::FlatFrame, option, r, pal, flags, painter, widget); 1063 } else { 1064 drawKStylePrimitive(WT_GroupBox, Generic::Frame, option, r, pal, flags, painter, widget); 1065 } 1066 } 1067 return; 1068 } 1069 1070 case PE_FrameStatusBar: { 1071 drawKStylePrimitive(WT_StatusBar, Generic::Frame, option, r, pal, flags, painter, widget); 1072 return; 1073 } 1074 1075 case PE_FrameDockWidget: { 1076 drawKStylePrimitive(WT_DockWidget, Generic::Frame, option, r, pal, flags, painter, widget); 1077 return; 1078 } 1079 1080 case PE_IndicatorDockWidgetResizeHandle: { 1081 drawKStylePrimitive(WT_DockWidget, DockWidget::SeparatorHandle, option, r, pal, flags, 1082 painter, widget); 1083 return; 1084 } 1085 1086 case PE_FrameWindow: { 1087 drawKStylePrimitive(WT_Window, Generic::Frame, option, r, pal, flags, painter, widget); 1088 return; 1089 } 1090 1091 case PE_Frame: { 1092 drawKStylePrimitive(WT_Generic, Generic::Frame, option, r, pal, flags, painter, widget); 1093 return; 1094 } 1095 1096 case PE_IndicatorToolBarHandle: { 1097 if (flags & State_Horizontal) 1098 drawKStylePrimitive(WT_ToolBar, ToolBar::HandleHor, 1099 option, r, pal, flags, painter, widget); 1100 else 1101 drawKStylePrimitive(WT_ToolBar, ToolBar::HandleVert, 1102 option, r, pal, flags, painter, widget); 1103 return; 1104 } 1105 1106 case PE_IndicatorToolBarSeparator: 1107 drawKStylePrimitive(WT_ToolBar, ToolBar::Separator, option, r, pal, flags, painter, widget); 1108 return; 1109 1110 case PE_PanelButtonCommand: 1111 //case PE_PanelButtonBevel: // ### CHECKME 1112 drawKStylePrimitive(WT_PushButton, PushButton::Panel, option, r, pal, flags, painter, widget); 1113 return; 1114 case PE_FrameDefaultButton: 1115 drawKStylePrimitive(WT_PushButton, PushButton::DefaultButtonFrame, option, r, pal, flags, painter, widget); 1116 return; 1117 1118 case PE_PanelButtonTool: 1119 drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, option, r, pal, flags, painter, widget); 1120 return; 1121 1122 case PE_IndicatorButtonDropDown: 1123 drawKStylePrimitive(WT_ToolButton, Generic::ArrowDown, option, r, pal, flags, painter, widget); 1124 return; 1125 1126 case PE_PanelItemViewItem: { 1127 1128 const QStyleOptionViewItem *opt = qstyleoption_cast<const QStyleOptionViewItem *>(option); 1129 const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); 1130 bool hover = (option->state & State_MouseOver) && (!view || 1131 view->selectionMode() != QAbstractItemView::NoSelection); 1132 1133 bool hasCustomBackground = opt->backgroundBrush.style() != Qt::NoBrush && 1134 !(option->state & State_Selected); 1135 bool hasSolidBackground = !hasCustomBackground || opt->backgroundBrush.style() == Qt::SolidPattern; 1136 1137 const qreal rounding = 2.5; 1138 1139 if (!hover && !(option->state & State_Selected) && !hasCustomBackground && 1140 !(opt->features & QStyleOptionViewItem::Alternate)) { 1141 return; 1142 } 1143 1144 QPalette::ColorGroup cg; 1145 if (option->state & State_Enabled) { 1146 cg = (option->state & State_Active) ? QPalette::Normal : QPalette::Inactive; 1147 } else { 1148 cg = QPalette::Disabled; 1149 } 1150 1151 QColor color; 1152 1153 if (hasCustomBackground && hasSolidBackground) { 1154 color = opt->backgroundBrush.color(); 1155 } else { 1156 color = option->palette.color(cg, QPalette::Highlight); 1157 } 1158 1159 if (hover && !hasCustomBackground) { 1160 if (!(option->state & State_Selected)) { 1161 color.setAlphaF(.20); 1162 } else { 1163 color = color.lighter(110); 1164 } 1165 } 1166 1167 if (opt && (opt->features & QStyleOptionViewItem::Alternate)) { 1168 painter->fillRect(option->rect, option->palette.brush(cg, QPalette::AlternateBase)); 1169 } 1170 1171 if (!hover && !(option->state & State_Selected) && !hasCustomBackground) { 1172 return; 1173 } 1174 1175 quint64 key = quint64(option->rect.height()) << 32 | color.rgba(); 1176 SelectionTiles tiles; 1177 SelectionTiles *tilesPtr = d->selectionCache.object(key); 1178 if (tilesPtr) { 1179 // We can't use tilesPtr directly since obj lifetime is different 1180 // if we QCache::insert() vs. use ret value from QCache::object(). 1181 tiles = *tilesPtr; 1182 } 1183 if (!tilesPtr && hasSolidBackground) { 1184 QImage image(32 + 16, option->rect.height(), QImage::Format_ARGB32_Premultiplied); 1185 image.fill(0); 1186 1187 QRect r = image.rect().adjusted(0, 0, -1, -1); 1188 1189 QPainterPath path1, path2; 1190 path1.addRoundedRect(r, rounding, rounding); 1191 path2.addRoundedRect(r.adjusted(1, 1, -1, -1), rounding - 1, rounding - 1); 1192 1193 // items with custom background brushes always have their background drawn 1194 // regardless of whether they are hovered or selected or neither so 1195 // the gradient effect needs to be more subtle 1196 int lightenAmount = hasCustomBackground ? 110 : 130; 1197 QLinearGradient gradient(0, 0, 0, r.bottom()); 1198 gradient.setColorAt(0, color.lighter(lightenAmount)); 1199 gradient.setColorAt(1, color); 1200 1201 QPainter p(&image); 1202 p.setRenderHint(QPainter::Antialiasing); 1203 p.translate(.5, .5); 1204 p.setPen(QPen(color, 1)); 1205 p.setBrush(gradient); 1206 p.drawPath(path1); 1207 p.strokePath(path2, QPen(QColor(255, 255, 255, 64), 1)); 1208 p.end(); 1209 1210 QPixmap pixmap = QPixmap::fromImage(image); 1211 1212 tiles.left = pixmap.copy(0, 0, 8, image.height()); 1213 tiles.center = pixmap.copy(8, 0, 32, image.height()); 1214 tiles.right = pixmap.copy(40, 0, 8, image.height()); 1215 1216 d->selectionCache.insert(key, new SelectionTiles(tiles)); 1217 } else if (hasCustomBackground && !hasSolidBackground) { 1218 const QPointF oldBrushOrigin = painter->brushOrigin(); 1219 painter->setBrushOrigin(opt->rect.topLeft()); 1220 painter->setBrush(opt->backgroundBrush); 1221 painter->setPen(Qt::NoPen); 1222 painter->drawRect(opt->rect); 1223 painter->setBrushOrigin(oldBrushOrigin); 1224 return; 1225 } 1226 1227 bool roundedLeft = false; 1228 bool roundedRight = false; 1229 if (opt) { 1230 roundedLeft = (opt->viewItemPosition == QStyleOptionViewItem::Beginning); 1231 roundedRight = (opt->viewItemPosition == QStyleOptionViewItem::End); 1232 if (opt->viewItemPosition == QStyleOptionViewItem::OnlyOne || 1233 opt->viewItemPosition == QStyleOptionViewItem::Invalid || 1234 (view && view->selectionBehavior() != QAbstractItemView::SelectRows)) { 1235 roundedLeft = true; 1236 roundedRight = true; 1237 } 1238 } 1239 1240 QRect r = option->rect; 1241 bool reverseLayout = option->direction == Qt::RightToLeft; 1242 1243 if (!reverseLayout ? roundedLeft : roundedRight) { 1244 painter->drawPixmap(r.topLeft(), tiles.left); 1245 r.adjust(8, 0, 0, 0); 1246 } 1247 if (!reverseLayout ? roundedRight : roundedLeft) { 1248 painter->drawPixmap(r.right() - 8 + 1, r.top(), tiles.right); 1249 r.adjust(0, 0, -8, 0); 1250 } 1251 if (r.isValid()) { 1252 painter->drawTiledPixmap(r, tiles.center); 1253 } 1254 1255 return; 1256 } 1257 1258 default: 1259 break; 1260 } 1261 1262 QCommonStyle::drawPrimitive(elem, option, painter, widget); 1263 } 1264 1265 void K4Style::drawControl(ControlElement element, const QStyleOption *option, QPainter *p, const QWidget *widget) const 1266 { 1267 //Extract the stuff we need out of the option 1268 State flags = option->state; 1269 QRect r = option->rect; 1270 QPalette pal = option->palette; 1271 1272 switch (element) { 1273 case CE_PushButton: { 1274 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 1275 if (!bOpt) { 1276 return; 1277 } 1278 1279 //Draw the bevel outside 1280 drawControl(CE_PushButtonBevel, option, p, widget); 1281 1282 //Now, draw the label... 1283 QRect labelRect = r; 1284 1285 //Move inside of default indicator margin if need be 1286 if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) { 1287 labelRect = insideMargin(labelRect, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget); 1288 } 1289 1290 //now get the contents area 1291 labelRect = insideMargin(labelRect, WT_PushButton, PushButton::ContentsMargin, option, widget); 1292 1293 //### do we do anything for RTL here? 1294 1295 QStyleOptionButton bOptTmp = *bOpt; 1296 bOptTmp.rect = labelRect; 1297 drawControl(CE_PushButtonLabel, &bOptTmp, p, widget); 1298 1299 //Finally, renderer the focus indicator if need be 1300 if (flags & State_HasFocus) { 1301 QRect focusRect = insideMargin(r, WT_PushButton, PushButton::FocusMargin, option, widget); 1302 1303 QStyleOptionFocusRect foOpts; 1304 foOpts.palette = pal; 1305 foOpts.rect = focusRect; 1306 foOpts.state = flags; 1307 1308 drawKStylePrimitive(WT_PushButton, Generic::FocusIndicator, &foOpts, focusRect, pal, flags, p, widget); 1309 } 1310 1311 return; 1312 } 1313 1314 case CE_PushButtonBevel: { 1315 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 1316 if (!bOpt) { 1317 return; 1318 } 1319 1320 //Check whether we should draw default indicator. 1321 if (bOpt->features & QStyleOptionButton::DefaultButton) { 1322 drawPrimitive(PE_FrameDefaultButton, option, p, widget); 1323 } 1324 1325 QRect bevelRect = r; 1326 //Exclude the margin if default or auto-default 1327 if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) { 1328 bevelRect = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget); 1329 } 1330 1331 //Now draw the bevel itself. 1332 QStyleOptionButton bOptTmp = *bOpt; 1333 bOptTmp.rect = bevelRect; 1334 drawPrimitive(PE_PanelButtonCommand, &bOptTmp, p, widget); 1335 1336 return; 1337 } 1338 1339 case CE_PushButtonLabel: { 1340 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 1341 if (!bOpt) { 1342 return; 1343 } 1344 1345 //Extract out coordinates for easier manipulation 1346 //(OK, OK, for easier stealing of code from Keramik) 1347 int x, y, w, h; 1348 r.getRect(&x, &y, &w, &h); 1349 1350 //Are we active? If so, shift contents 1351 bool active = (flags & State_On) || (flags & State_Sunken); 1352 if (active) { 1353 x += widgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, option, widget); 1354 y += widgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, option, widget); 1355 } 1356 1357 //Layout the stuff. 1358 if (bOpt->features & QStyleOptionButton::HasMenu) { 1359 int indicatorWidth = widgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, option, widget); 1360 int indicatorSpacing = widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget); 1361 w -= indicatorWidth + indicatorSpacing; 1362 1363 //Draw the arrow... 1364 drawKStylePrimitive(WT_PushButton, Generic::ArrowDown, option, 1365 handleRTL(bOpt, QRect(x + w + indicatorSpacing, y, indicatorWidth, h)), 1366 pal, flags, p, widget); 1367 } 1368 1369 // Draw the icon if there is one 1370 if (!bOpt->icon.isNull()) { 1371 IconOption icoOpt; 1372 icoOpt.icon = bOpt->icon; 1373 icoOpt.size = bOpt->iconSize; 1374 icoOpt.active = flags & State_HasFocus; 1375 1376 if (!bOpt->text.isEmpty()) { 1377 int margin = widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget); 1378 //Center text + icon w/margin in between.. 1379 1380 //Calculate length of both. 1381 int length = bOpt->iconSize.width() + margin 1382 + p->fontMetrics().size(Qt::TextShowMnemonic, bOpt->text).width(); 1383 1384 //Calculate offset. 1385 int offset = (w - length) / 2; 1386 1387 //draw icon 1388 QRect rect = QRect(QPoint(x + offset, y + h / 2 - bOpt->iconSize.height() / 2), bOpt->iconSize); 1389 drawKStylePrimitive(WT_PushButton, Generic::Icon, option, 1390 handleRTL(bOpt, rect), 1391 pal, flags, p, widget, &icoOpt); 1392 1393 //new bounding rect for the text 1394 x += offset + bOpt->iconSize.width() + margin; 1395 w = length - bOpt->iconSize.width() - margin; 1396 } else { 1397 //Icon only. Center it. (Thankfully, they killed the icon + pixmap insanity in Qt4. Whee! 1398 //(no need to do anything for RTL here, it's symmetric) 1399 drawKStylePrimitive(WT_PushButton, Generic::Icon, option, 1400 QRect(x, y, w, h), 1401 pal, flags, p, widget, &icoOpt); 1402 } 1403 } else { 1404 //Center the text 1405 int textW = p->fontMetrics().size(Qt::TextShowMnemonic, bOpt->text).width(); 1406 x += (w - textW) / 2; 1407 w = textW; 1408 } 1409 1410 TextOption lbOpt(bOpt->text); 1411 drawKStylePrimitive(WT_PushButton, Generic::Text, option, handleRTL(bOpt, QRect(x, y, w, h)), 1412 pal, flags, p, widget, &lbOpt); 1413 1414 return; 1415 } 1416 1417 case CE_DockWidgetTitle: { 1418 const QStyleOptionDockWidget *dwOpt = ::qstyleoption_cast<const QStyleOptionDockWidget *>(option); 1419 if (!dwOpt) { 1420 return; 1421 } 1422 1423 QRect textRect = insideMargin(r, WT_DockWidget, DockWidget::TitleMargin, option, widget); 1424 drawKStylePrimitive(WT_DockWidget, DockWidget::TitlePanel, option, r, pal, flags, p, widget); 1425 1426 TextOption lbOpt(dwOpt->title); 1427 lbOpt.color = widgetLayoutProp(WT_DockWidget, DockWidget::TitleTextColor, 1428 option, widget); 1429 drawKStylePrimitive(WT_DockWidget, Generic::Text, option, textRect, pal, flags, p, widget, &lbOpt); 1430 return; 1431 } 1432 1433 case CE_ToolBoxTabShape: { 1434 drawKStylePrimitive(WT_ToolBoxTab, ToolBoxTab::Panel, option, r, pal, flags, p, widget); 1435 return; 1436 } 1437 /* 1438 case CE_ToolBoxTabLabel: 1439 { 1440 drawKStylePrimitive(WT_ToolBoxTab, Generic::Text, option, r, pal, flags, p, widget); 1441 return; 1442 } 1443 */ 1444 case CE_CheckBox: { 1445 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 1446 if (!bOpt) { 1447 return; 1448 } 1449 1450 //Draw the checkbox 1451 QRect checkBox = subElementRect(SE_CheckBoxIndicator, option, widget); 1452 QStyleOptionButton bOptTmp = *bOpt; 1453 bOptTmp.rect = checkBox; 1454 drawPrimitive(PE_IndicatorCheckBox, &bOptTmp, p, widget); 1455 1456 // pixmap and text label... 1457 bOptTmp.rect = subElementRect(SE_CheckBoxContents, option, widget); 1458 drawControl(CE_CheckBoxLabel, &bOptTmp, p, widget); 1459 1460 //Draw the focus rect... 1461 if (flags & State_HasFocus) { 1462 QRect focusRect = subElementRect(SE_CheckBoxFocusRect, option, widget); 1463 drawKStylePrimitive(WT_CheckBox, Generic::FocusIndicator, option, focusRect, 1464 pal, flags, p, widget); 1465 } 1466 return; 1467 } 1468 1469 case CE_CheckBoxLabel: { 1470 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 1471 if (!bOpt) { 1472 return; 1473 } 1474 1475 int textShift = 0; // shift text in case there is a label pixmap 1476 // draw the pixmap, if there is one 1477 if (!bOpt->icon.isNull()) { 1478 IconOption icoOpt; 1479 icoOpt.icon = bOpt->icon; 1480 icoOpt.size = bOpt->iconSize; 1481 icoOpt.active = flags & State_HasFocus; 1482 1483 QRect iconRect(r.x(), r.y() + (r.height() - bOpt->iconSize.height()) / 2, 1484 bOpt->iconSize.width(), bOpt->iconSize.height()); 1485 drawKStylePrimitive(WT_CheckBox, Generic::Icon, option, 1486 handleRTL(bOpt, iconRect), 1487 pal, flags, p, widget, &icoOpt); 1488 1489 textShift = bOpt->iconSize.width() + 1490 widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget); 1491 } 1492 1493 if (!bOpt->text.isEmpty()) { 1494 TextOption lbOpt(bOpt->text); 1495 drawKStylePrimitive(WT_CheckBox, Generic::Text, option, 1496 handleRTL(bOpt, r.adjusted(textShift, 0, 0, 0)), 1497 pal, flags, p, widget, &lbOpt); 1498 } 1499 1500 return; 1501 } 1502 1503 case CE_RadioButton: { 1504 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 1505 if (!bOpt) { 1506 return; 1507 } 1508 1509 //Draw the indicator 1510 QRect indicator = subElementRect(SE_RadioButtonIndicator, option, widget); 1511 QStyleOptionButton bOptTmp = *bOpt; 1512 bOptTmp.rect = indicator; 1513 drawPrimitive(PE_IndicatorRadioButton, &bOptTmp, p, widget); 1514 1515 // pixmap and text label... 1516 bOptTmp.rect = subElementRect(SE_RadioButtonContents, option, widget); 1517 drawControl(CE_RadioButtonLabel, &bOptTmp, p, widget); 1518 1519 //Draw the focus rect... 1520 if (flags & State_HasFocus) { 1521 QRect focusRect = subElementRect(SE_RadioButtonFocusRect, option, widget); 1522 drawKStylePrimitive(WT_RadioButton, Generic::FocusIndicator, option, focusRect, 1523 pal, flags, p, widget); 1524 } 1525 return; 1526 } 1527 1528 case CE_RadioButtonLabel: { 1529 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 1530 if (!bOpt) { 1531 return; 1532 } 1533 1534 int textShift = 0; // shift text in case there is a label pixmap 1535 // draw the pixmap, if there is one 1536 if (!bOpt->icon.isNull()) { 1537 IconOption icoOpt; 1538 icoOpt.icon = bOpt->icon; 1539 icoOpt.active = flags & State_HasFocus; 1540 icoOpt.size = bOpt->iconSize; 1541 1542 QRect iconRect(r.x(), r.y() + (r.height() - bOpt->iconSize.height()) / 2, 1543 bOpt->iconSize.width(), bOpt->iconSize.height()); 1544 drawKStylePrimitive(WT_RadioButton, Generic::Icon, option, 1545 handleRTL(bOpt, iconRect), 1546 pal, flags, p, widget, &icoOpt); 1547 1548 textShift = bOpt->iconSize.width() + 1549 widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget); 1550 } 1551 1552 TextOption lbOpt(bOpt->text); 1553 drawKStylePrimitive(WT_RadioButton, Generic::Text, option, 1554 handleRTL(bOpt, r.adjusted(textShift, 0, 0, 0)), 1555 pal, flags, p, widget, &lbOpt); 1556 return; 1557 } 1558 1559 //The CE_ProgressBar implementation inside QCommonStyle is acceptible. 1560 //We just implement the subElementRect's it uses 1561 1562 case CE_ProgressBarGroove: { 1563 drawKStylePrimitive(WT_ProgressBar, ProgressBar::Groove, option, r, 1564 pal, flags, p, widget); 1565 return; 1566 } 1567 1568 case CE_ProgressBarContents: { 1569 const QStyleOptionProgressBar *pbOpt = qstyleoption_cast<const QStyleOptionProgressBar *>(option); 1570 const QStyleOptionProgressBar *pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBar *>(option); 1571 if (!pbOpt) { 1572 return; 1573 } 1574 1575 //We layout as if LTR, relying on visualRect to fix it up 1576 double progress = pbOpt->progress - pbOpt->minimum; 1577 int steps = qMax(pbOpt->maximum - pbOpt->minimum, 1); 1578 bool busyIndicator = (pbOpt->minimum == 0 && pbOpt->maximum == 0); 1579 bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal; 1580 1581 //Do we have to draw anything? 1582 if (!progress && ! busyIndicator) { 1583 return; 1584 } 1585 1586 //Calculate width fraction 1587 double widthFrac; 1588 if (busyIndicator) { 1589 widthFrac = widgetLayoutProp(WT_ProgressBar, ProgressBar::BusyIndicatorSize, option, widget) / 100.0; 1590 } else { 1591 widthFrac = progress / steps; 1592 } 1593 1594 //And now the pixel width 1595 int width = qMin(r.width(), (int)(widthFrac * double(r.width()))); 1596 int height = qMin(r.height(), (int)(widthFrac * r.height())); 1597 1598 if (busyIndicator) { 1599 int size = width; 1600 if (!horizontal) { 1601 size = height; 1602 } 1603 //Clamp to upper width limit 1604 if (size > widgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, option, widget)) { 1605 size = widgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, option, widget); 1606 } 1607 1608 //A busy indicator with width 0 is kind of useless 1609 if (size < 1) { 1610 size = 1; 1611 } 1612 1613 int remSize = (horizontal ? r.width() : r.height()) - size; //The space around which we move around... 1614 if (remSize <= 0) { 1615 remSize = 1; //Do something non-crashy when too small... 1616 } 1617 1618 int pstep = int(progress) % (2 * remSize); 1619 1620 if (pstep > remSize) { 1621 //Bounce about.. We're remWidth + some delta, we want to be remWidth - delta... 1622 // - ( (remWidth + some delta) - 2* remWidth ) = - (some deleta - remWidth) = remWidth - some delta.. 1623 pstep = -(pstep - 2 * remSize); 1624 } 1625 1626 QRect indicatorRect; 1627 if (horizontal) { 1628 indicatorRect = QRect(r.x() + pstep, r.y(), size, r.height()); 1629 } else { 1630 indicatorRect = QRect(r.x(), r.y() + pstep, r.width(), size); 1631 } 1632 drawKStylePrimitive(WT_ProgressBar, ProgressBar::BusyIndicator, option, handleRTL(option, indicatorRect), 1633 pal, flags, p, widget); 1634 } else { 1635 QRect indicatorRect; 1636 if (horizontal) { 1637 indicatorRect = QRect(r.x(), r.y(), width, r.height()); 1638 } else { 1639 indicatorRect = QRect(r.x(), r.bottom() - height + 1, r.width(), height); 1640 } 1641 drawKStylePrimitive(WT_ProgressBar, ProgressBar::Indicator, option, handleRTL(option, indicatorRect), 1642 pal, flags, p, widget); 1643 } 1644 return; 1645 } 1646 1647 case CE_ProgressBarLabel: { 1648 const QStyleOptionProgressBar *pbOpt = qstyleoption_cast<const QStyleOptionProgressBar *>(option); 1649 const QStyleOptionProgressBar *pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBar *>(option); 1650 if (pbOpt) { 1651 TextOption lbOpt(pbOpt->text); 1652 bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal; 1653 bool reverseLayout = option->direction == Qt::RightToLeft; 1654 1655 p->save(); 1656 1657 // rotate label for vertical layout 1658 if (!horizontal && !reverseLayout) { 1659 p->translate(r.topRight()); 1660 p->rotate(90.0); 1661 } else if (!horizontal) { 1662 p->translate(r.bottomLeft()); 1663 p->rotate(-90.0); 1664 } 1665 1666 if (useSideText(pbOpt)) { 1667 lbOpt.color = QPalette::ButtonText; 1668 1669 //### or other way around? 1670 if (option->direction == Qt::LeftToRight) { 1671 lbOpt.hAlign = Qt::AlignRight; 1672 } else { 1673 lbOpt.hAlign = Qt::AlignLeft; 1674 } 1675 1676 //Handle side margin. 1677 int marWidth = widgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace, option, widget); 1678 1679 drawKStylePrimitive(WT_ProgressBar, Generic::Text, option, 1680 horizontal ? r.adjusted(0, marWidth, 0, -marWidth) : QRect(0, marWidth, r.height(), r.width() - marWidth), 1681 pal, flags, p, widget, &lbOpt); 1682 } else { 1683 if (pbOpt->textAlignment == Qt::AlignLeft) { //TODO: Check BIDI? 1684 lbOpt.hAlign = Qt::AlignHCenter; 1685 } else { 1686 lbOpt.hAlign = pbOpt->textAlignment; 1687 } 1688 1689 //Now, we need to figure out the geometry of the indicator. 1690 QRect progressRect; 1691 double progress = pbOpt->progress - pbOpt->minimum; 1692 int steps = qMax(pbOpt->maximum - pbOpt->minimum, 1); 1693 bool busyIndicator = (steps <= 1); 1694 1695 int width; 1696 int height; 1697 if (busyIndicator) { 1698 //how did this happen? handle as 0% 1699 width = 0; 1700 height = 0; 1701 } else { 1702 double widthFrac = progress / steps;; 1703 width = qMin(r.width(), (int)(widthFrac * r.width())); 1704 height = qMin(r.height(), (int)(widthFrac * r.height())); 1705 } 1706 1707 //If there is any indicator, we do two paths, with different 1708 //clipping rects, for the two colors. 1709 if (width || height) { 1710 if (horizontal) { 1711 p->setClipRect(handleRTL(option, QRect(r.x(), r.y(), width, r.height()))); 1712 } else if (!reverseLayout) { 1713 p->setClipRect(QRect(r.height() - height, 0, r.height(), r.width())); 1714 } else { 1715 p->setClipRect(QRect(0, 0, height, r.width())); 1716 } 1717 lbOpt.color = QPalette::HighlightedText; 1718 drawKStylePrimitive(WT_ProgressBar, Generic::Text, option, 1719 horizontal ? r : QRect(0, 0, r.height(), r.width()), 1720 pal, flags, p, widget, &lbOpt); 1721 1722 if (horizontal) { 1723 p->setClipRect(handleRTL(option, QRect(r.x() + width, r.y(), r.width() - width, r.height()))); 1724 } else if (!reverseLayout) { 1725 p->setClipRect(QRect(0, 0, r.height() - height, r.width())); 1726 } else { 1727 p->setClipRect(QRect(height, 0, r.height() - height, r.width())); 1728 } 1729 lbOpt.color = QPalette::ButtonText; 1730 drawKStylePrimitive(WT_ProgressBar, Generic::Text, option, 1731 horizontal ? r : QRect(0, 0, r.height(), r.width()), 1732 pal, flags, p, widget, &lbOpt); 1733 p->setClipping(false); 1734 } else { 1735 lbOpt.color = QPalette::ButtonText; 1736 drawKStylePrimitive(WT_ProgressBar, Generic::Text, option, 1737 horizontal ? r : QRect(0, 0, r.height(), r.width()), 1738 pal, flags, p, widget, &lbOpt); 1739 } 1740 } 1741 p->restore(); 1742 } 1743 return; 1744 } 1745 1746 case CE_MenuBarItem: { 1747 const QStyleOptionMenuItem *mOpt = ::qstyleoption_cast<const QStyleOptionMenuItem *>(option); 1748 if (!mOpt) { 1749 return; 1750 } 1751 1752 //Bevel... 1753 drawKStylePrimitive(WT_MenuBarItem, MenuBarItem::Panel, option, r, 1754 pal, flags, p, widget); 1755 1756 //Text... 1757 QRect textRect = insideMargin(r, WT_MenuBarItem, MenuBarItem::Margin, option, widget); 1758 1759 TextOption lbOpt(mOpt->text); 1760 drawKStylePrimitive(WT_MenuBarItem, Generic::Text, option, textRect, 1761 pal, flags, p, widget, &lbOpt); 1762 1763 return; 1764 } 1765 1766 case CE_MenuBarEmptyArea: { 1767 drawKStylePrimitive(WT_MenuBar, MenuBar::EmptyArea, option, r, 1768 pal, flags, p, widget); 1769 return; 1770 } 1771 1772 case CE_MenuEmptyArea: 1773 case CE_MenuVMargin: 1774 case CE_MenuHMargin: { 1775 drawKStylePrimitive(WT_Menu, Menu::Background, option, r, 1776 pal, flags, p, widget); 1777 return; 1778 } 1779 1780 case CE_MenuItem: { 1781 1782 //First of all,render the background. 1783 drawKStylePrimitive(WT_Menu, Menu::Background, option, r, 1784 pal, flags, p, widget); 1785 1786 const QStyleOptionMenuItem *miOpt = ::qstyleoption_cast<const QStyleOptionMenuItem *>(option); 1787 if (!miOpt || miOpt->menuItemType == QStyleOptionMenuItem::EmptyArea) { 1788 return; 1789 } 1790 1791 //Remove the margin (for everything but the column background) 1792 QRect ir = insideMargin(r, WT_MenuItem, MenuItem::Margin, option, widget); 1793 1794 //First, figure out the left column width. When CheckAlongsideIcon is disabled it's just 1795 // the icon column width. Otherwise it consists of CheckWidth+CheckSpace+icon column width. 1796 int iconColW = miOpt->maxIconWidth; 1797 iconColW = qMax(iconColW, widgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, option, widget)); 1798 int checkColW = widgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, option, widget); 1799 int checkSpace = widgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, option, widget); 1800 1801 int leftColW = iconColW; 1802 // only use the additional check row if the menu has checkable menuItems. 1803 bool checkAlongsideIcon = (miOpt->menuHasCheckableItems && 1804 widgetLayoutProp(WT_MenuItem, MenuItem::CheckAlongsideIcon, option, widget)); 1805 if (checkAlongsideIcon) { 1806 leftColW = checkColW + checkSpace + iconColW; 1807 } 1808 1809 //And the right arrow column... 1810 int rightColW = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, option, widget) + 1811 widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget); 1812 1813 //Render left column background. This is a bit tricky, since we don't use the V margin. 1814 QRect leftColRect(ir.x(), r.y(), leftColW, r.height()); 1815 drawKStylePrimitive(WT_MenuItem, MenuItem::CheckColumn, option, handleRTL(option, leftColRect), 1816 pal, flags, p, widget); 1817 1818 //Separators: done with the bg, can paint them and bail them out. 1819 if (miOpt->menuItemType == QStyleOptionMenuItem::Separator) { 1820 drawKStylePrimitive(WT_MenuItem, MenuItem::Separator, option, ir, pal, flags, p, widget); 1821 return; 1822 } 1823 1824 //Now paint the active indicator --- other stuff goes on top of it 1825 bool active = (flags & State_Selected); 1826 1827 //Active indicator... 1828 if (active) { 1829 drawKStylePrimitive(WT_MenuItem, MenuItem::ItemIndicator, option, handleRTL(option, r), pal, flags, p, widget); 1830 } 1831 1832 ColorMode textColor = (flags & State_Enabled) ? (widgetLayoutProp(WT_MenuItem, active ? 1833 MenuItem::ActiveTextColor : 1834 MenuItem::TextColor, option, widget)) 1835 : (widgetLayoutProp(WT_MenuItem, active ? 1836 MenuItem::ActiveDisabledTextColor : 1837 MenuItem::DisabledTextColor, option, widget)); 1838 1839 //Readjust the column rectangle back to proper height 1840 leftColRect = QRect(ir.x(), ir.y(), leftColW, ir.height()); 1841 // Paint checkbox, etc. 1842 if (!checkAlongsideIcon && !miOpt->icon.isNull()) { 1843 // there is an icon and the item is checked, so paint a CheckIcon 1844 if (miOpt->checked) { 1845 drawKStylePrimitive(WT_MenuItem, MenuItem::CheckIcon, 1846 option, handleRTL(option, leftColRect), pal, flags, 1847 p, widget); 1848 } 1849 } else { 1850 // paint a normal check- resp. radiomark. 1851 QRect checkColRect; 1852 if (checkAlongsideIcon) { 1853 checkColRect = QRect(leftColRect.x(), leftColRect.y(), 1854 checkColW, leftColRect.height()); 1855 } else { 1856 checkColRect = leftColRect; 1857 } 1858 1859 bool checked = miOpt->checked; 1860 if (miOpt->checkType == QStyleOptionMenuItem::NonExclusive) { 1861 drawKStylePrimitive(WT_MenuItem, checked ? MenuItem::CheckOn : MenuItem::CheckOff, 1862 option, handleRTL(option, checkColRect), pal, flags, 1863 p, widget); 1864 } else if (miOpt->checkType == QStyleOptionMenuItem::Exclusive) { 1865 drawKStylePrimitive(WT_MenuItem, checked ? MenuItem::RadioOn : MenuItem::RadioOff, 1866 option, handleRTL(option, checkColRect), pal, flags, 1867 p, widget); 1868 } 1869 } 1870 // Paint the menu icon. 1871 if (!miOpt->icon.isNull()) { 1872 int iconSize = pixelMetric(PM_SmallIconSize); 1873 1874 QRect iconColRect; 1875 if (checkAlongsideIcon) { 1876 iconColRect = QRect(leftColRect.x() + checkColW + checkSpace, leftColRect.y(), 1877 leftColRect.width() - (checkColW + checkSpace), leftColRect.height()); 1878 } else { 1879 iconColRect = leftColRect; 1880 } 1881 IconOption icoOpt; 1882 icoOpt.icon = miOpt->icon; 1883 icoOpt.active = flags & State_Selected; 1884 drawKStylePrimitive(WT_MenuItem, Generic::Icon, option, 1885 handleRTL(option, centerRect(iconColRect, iconSize, iconSize)), 1886 pal, flags, p, widget, &icoOpt); 1887 } 1888 1889 //Now include the spacing when calculating the next columns 1890 leftColW += widgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, option, widget); 1891 1892 //Render the text, including any accel. 1893 QString text = miOpt->text; 1894 QRect textRect = QRect(ir.x() + leftColW, ir.y(), ir.width() - leftColW - rightColW, ir.height()); 1895 QFont font = miOpt->font; 1896 const QFont oldFont = p->font(); 1897 1898 p->setFont(font); 1899 int tabPos = miOpt->text.indexOf(QLatin1Char('\t')); 1900 if (tabPos != -1) { 1901 text = miOpt->text.left(tabPos); 1902 QString accl = miOpt->text.mid(tabPos + 1); 1903 1904 //Draw the accel. 1905 TextOption lbOpt(accl); 1906 lbOpt.color = textColor; 1907 lbOpt.hAlign = Qt::AlignRight; 1908 drawKStylePrimitive(WT_MenuItem, Generic::Text, option, handleRTL(option, textRect), 1909 pal, flags, p, widget, &lbOpt); 1910 } 1911 1912 //Draw the text. 1913 TextOption lbOpt(text); 1914 lbOpt.color = textColor; 1915 drawKStylePrimitive(WT_MenuItem, Generic::Text, option, handleRTL(option, textRect), 1916 pal, flags, p, widget, &lbOpt); 1917 1918 p->setFont(oldFont); 1919 1920 //Render arrow, if need be. 1921 if (miOpt->menuItemType == QStyleOptionMenuItem::SubMenu) { 1922 ColorOption arrowColor; 1923 arrowColor.color = textColor; 1924 1925 int aw = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget); 1926 1927 QRect arrowRect(ir.x() + ir.width() - aw, ir.y(), aw, ir.height()); 1928 drawKStylePrimitive(WT_MenuItem, option->direction == Qt::LeftToRight ? 1929 Generic::ArrowRight : Generic::ArrowLeft, 1930 option, handleRTL(option, arrowRect), pal, flags, p, widget, &arrowColor); 1931 } 1932 1933 return; 1934 } 1935 1936 case CE_ScrollBarAddLine: 1937 case CE_ScrollBarSubLine: { 1938 const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option); 1939 if (!slOpt) { 1940 return; 1941 } 1942 1943 //Fix up the rectangle to be what we want 1944 r = internalSubControlRect(CC_ScrollBar, slOpt, 1945 element == CE_ScrollBarAddLine ? SC_ScrollBarAddLine : SC_ScrollBarSubLine, widget); 1946 const_cast<QStyleOption *>(option)->rect = r; 1947 1948 bool doubleButton = false; 1949 1950 //See whether we're a double-button... 1951 if (element == CE_ScrollBarAddLine && widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, option, widget)) { 1952 doubleButton = true; 1953 } 1954 if (element == CE_ScrollBarSubLine && widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, option, widget)) { 1955 doubleButton = true; 1956 } 1957 1958 if (doubleButton) { 1959 if (flags & State_Horizontal) { 1960 DoubleButtonOption::ActiveButton ab = DoubleButtonOption::None; 1961 1962 //Depending on RTL direction, the one on the left is either up or down. 1963 bool leftAdds, rightAdds; 1964 if (slOpt->direction == Qt::LeftToRight) { 1965 leftAdds = false; 1966 rightAdds = true; 1967 } else { 1968 leftAdds = true; 1969 rightAdds = false; 1970 } 1971 1972 //Determine whether any of the buttons is active 1973 if (flags & State_Sunken) { 1974 if (((slOpt->activeSubControls & SC_ScrollBarAddLine) && leftAdds) || 1975 ((slOpt->activeSubControls & SC_ScrollBarSubLine) && !leftAdds)) { 1976 ab = DoubleButtonOption::Left; 1977 } 1978 1979 if (((slOpt->activeSubControls & SC_ScrollBarAddLine) && rightAdds) || 1980 ((slOpt->activeSubControls & SC_ScrollBarSubLine) && !rightAdds)) { 1981 ab = DoubleButtonOption::Right; 1982 } 1983 } 1984 1985 DoubleButtonOption bOpt(ab); 1986 drawKStylePrimitive(WT_ScrollBar, ScrollBar::DoubleButtonHor, 1987 option, r, pal, flags, p, widget, &bOpt); 1988 1989 //Draw the left arrow.. 1990 QRect leftSubButton = QRect(r.x(), r.y(), r.width() / 2, r.height()); 1991 1992 ColorOption colOpt; 1993 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget); 1994 if (ab == DoubleButtonOption::Left) { 1995 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget); 1996 } 1997 1998 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowLeft, option, leftSubButton, pal, 1999 flags, p, widget, &colOpt); 2000 2001 //Right half.. 2002 QRect rightSubButton; 2003 rightSubButton.setBottomRight(r.bottomRight()); 2004 rightSubButton.setLeft(leftSubButton.right() + 1); 2005 rightSubButton.setTop(r.top()); 2006 2007 //Chose proper color 2008 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget); 2009 if (ab == DoubleButtonOption::Right) { 2010 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget); 2011 } 2012 2013 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowRight, option, rightSubButton, pal, 2014 flags, p, widget, &colOpt); 2015 } else { 2016 DoubleButtonOption::ActiveButton ab = DoubleButtonOption::None; 2017 2018 //Determine whether any of the buttons is active 2019 //Qt sets both sunken and activeSubControls for active, 2020 //just activeSubControls for hover. 2021 if (flags & State_Sunken) { 2022 if (slOpt->activeSubControls & SC_ScrollBarSubLine) { 2023 ab = DoubleButtonOption::Top; 2024 } 2025 2026 if (slOpt->activeSubControls & SC_ScrollBarAddLine) { 2027 ab = DoubleButtonOption::Bottom; 2028 } 2029 } 2030 2031 //Paint the bevel 2032 DoubleButtonOption bOpt(ab); 2033 drawKStylePrimitive(WT_ScrollBar, ScrollBar::DoubleButtonVert, 2034 option, r, pal, flags, p, widget, &bOpt); 2035 2036 //Paint top button. 2037 ColorOption colOpt; 2038 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget); 2039 2040 if (ab == DoubleButtonOption::Top) { 2041 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget); 2042 } 2043 2044 QRect topSubButton = QRect(r.x(), r.y(), r.width(), r.height() / 2); 2045 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowUp, option, topSubButton, pal, 2046 flags, p, widget, &colOpt); 2047 2048 //Paint bot button 2049 QRect botSubButton; 2050 botSubButton.setBottomRight(r.bottomRight()); 2051 botSubButton.setLeft(r.left()); 2052 botSubButton.setTop(topSubButton.bottom() + 1); 2053 2054 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget); 2055 2056 if (ab == DoubleButtonOption::Bottom) { 2057 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget); 2058 } 2059 2060 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowDown, option, botSubButton, pal, 2061 flags, p, widget, &colOpt); 2062 } 2063 } else { 2064 // Single button 2065 if (flags & State_Horizontal) { 2066 drawKStylePrimitive(WT_ScrollBar, ScrollBar::SingleButtonHor, 2067 option, r, pal, flags, p, widget); 2068 2069 int primitive; 2070 bool active = false; 2071 2072 if (element == CE_ScrollBarAddLine) { 2073 if (slOpt->direction == Qt::LeftToRight) { 2074 primitive = Generic::ArrowRight; 2075 } else { 2076 primitive = Generic::ArrowLeft; 2077 } 2078 2079 if ((slOpt->activeSubControls & SC_ScrollBarAddLine) && (flags & State_Sunken)) { 2080 active = true; 2081 } 2082 } else { 2083 if (slOpt->direction == Qt::LeftToRight) { 2084 primitive = Generic::ArrowLeft; 2085 } else { 2086 primitive = Generic::ArrowRight; 2087 } 2088 2089 if ((slOpt->activeSubControls & SC_ScrollBarSubLine) && (flags & State_Sunken)) { 2090 active = true; 2091 } 2092 } 2093 2094 ColorOption colOpt; 2095 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget); 2096 if (active) { 2097 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget); 2098 } 2099 2100 drawKStylePrimitive(WT_ScrollBar, primitive, option, r, pal, 2101 flags, p, widget, &colOpt); 2102 } else { 2103 drawKStylePrimitive(WT_ScrollBar, ScrollBar::SingleButtonVert, 2104 option, r, pal, flags, p, widget); 2105 2106 int primitive; 2107 bool active = false; 2108 2109 if (element == CE_ScrollBarAddLine) { 2110 primitive = Generic::ArrowDown; 2111 if ((slOpt->activeSubControls & SC_ScrollBarAddLine) && (flags & State_Sunken)) { 2112 active = true; 2113 } 2114 } else { 2115 primitive = Generic::ArrowUp; 2116 if ((slOpt->activeSubControls & SC_ScrollBarSubLine) && (flags & State_Sunken)) { 2117 active = true; 2118 } 2119 } 2120 2121 ColorOption colOpt; 2122 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget); 2123 if (active) { 2124 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget); 2125 } 2126 2127 drawKStylePrimitive(WT_ScrollBar, primitive, option, r, pal, 2128 flags, p, widget, &colOpt); 2129 } 2130 } 2131 return; 2132 } 2133 2134 // TODO: what about CE_ScrollBarFirst, CE_ScrollBarLast...? 2135 // case CE_ScrollBarFirst: 2136 // case CE_ScrollBarLast: 2137 2138 case CE_ScrollBarSlider: { 2139 drawKStylePrimitive(WT_ScrollBar, 2140 (flags & State_Horizontal) ? ScrollBar::SliderHor : 2141 ScrollBar::SliderVert, 2142 option, r, pal, flags, p, widget); 2143 return; 2144 } 2145 2146 case CE_ScrollBarAddPage: { 2147 const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option); 2148 if (!slOpt) { 2149 return; 2150 } 2151 2152 if (flags & State_Horizontal) 2153 drawKStylePrimitive(WT_ScrollBar, 2154 (slOpt->direction == Qt::LeftToRight) ? ScrollBar::GrooveAreaHorRight : 2155 ScrollBar::GrooveAreaHorLeft, 2156 option, r, pal, flags, p, widget); 2157 else 2158 drawKStylePrimitive(WT_ScrollBar, ScrollBar::GrooveAreaVertBottom, 2159 option, r, pal, flags, p, widget); 2160 return; 2161 } 2162 2163 case CE_ScrollBarSubPage: { 2164 const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option); 2165 if (!slOpt) { 2166 return; 2167 } 2168 2169 if (flags & State_Horizontal) 2170 drawKStylePrimitive(WT_ScrollBar, 2171 (slOpt->direction == Qt::LeftToRight) ? ScrollBar::GrooveAreaHorLeft : 2172 ScrollBar::GrooveAreaHorRight, 2173 option, r, pal, flags, p, widget); 2174 else 2175 drawKStylePrimitive(WT_ScrollBar, ScrollBar::GrooveAreaVertTop, 2176 option, r, pal, flags, p, widget); 2177 return; 2178 } 2179 2180 //QCS's CE_TabBarTab is perfectly fine, so we just handle the subbits 2181 2182 case CE_TabBarTabShape: { 2183 const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option); 2184 if (!tabOpt) { 2185 return; 2186 } 2187 2188 // TabOverlap handling 2189 int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget); 2190 bool beginning = tabOpt->position == QStyleOptionTab::Beginning; 2191 bool onlyOne = tabOpt->position == QStyleOptionTab::OnlyOneTab; 2192 if (!beginning && !onlyOne) { 2193 switch (tabSide(tabOpt)) { 2194 case North: 2195 case South: 2196 if (option->direction == Qt::LeftToRight) { 2197 r.adjust(-tabOverlap, 0, 0, 0); 2198 } else { 2199 r.adjust(0, 0, tabOverlap, 0); 2200 } 2201 break; 2202 case East: 2203 case West: 2204 r.adjust(0, -tabOverlap, 0, 0); 2205 default: 2206 break; 2207 } 2208 } 2209 2210 int prim; 2211 switch (tabSide(tabOpt)) { 2212 case North: 2213 prim = TabBar::NorthTab; break; 2214 case South: 2215 prim = TabBar::SouthTab; break; 2216 case East: 2217 prim = TabBar::EastTab; break; 2218 default: 2219 prim = TabBar::WestTab; break; 2220 } 2221 2222 drawKStylePrimitive(WT_TabBar, prim, option, r, pal, flags, p, widget); 2223 2224 return; 2225 } 2226 2227 case CE_TabBarTabLabel: { 2228 const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option); 2229 if (!tabOpt) { 2230 return; 2231 } 2232 2233 //First, we get our content region. 2234 QRect labelRect = subElementRect(SE_TabBarTabText, option, widget); 2235 2236 Side tabSd = tabSide(tabOpt); 2237 2238 //Now, what we do, depends on rotation, LTR vs. RTL, and text/icon combinations. 2239 //First, figure out if we have to deal with icons, and place them if need be. 2240 if (!tabOpt->icon.isNull()) { 2241 QStyleOptionTab tabV3(*tabOpt); 2242 QSize iconSize = tabV3.iconSize; 2243 if (!iconSize.isValid()) { 2244 int iconExtent = pixelMetric(PM_SmallIconSize); 2245 iconSize = QSize(iconExtent, iconExtent); 2246 } 2247 2248 IconOption icoOpt; 2249 icoOpt.icon = tabOpt->icon; 2250 icoOpt.active = flags & State_Selected; 2251 icoOpt.size = iconSize; 2252 2253 if (tabOpt->text.isNull()) { 2254 //Icon only. Easy. 2255 drawKStylePrimitive(WT_TabBar, Generic::Icon, option, labelRect, 2256 pal, flags, p, widget, &icoOpt); 2257 return; 2258 } 2259 2260 //OK, we have to stuff both icon and text. So we figure out where to stick the icon. 2261 QRect iconRect; 2262 2263 if (tabSd == North || tabSd == South) { 2264 //OK, this is simple affair, we just pick a side for the icon 2265 //based on layout direction. (Actually, I guess text 2266 //would be more accurate, but I am -so- not doing BIDI here) 2267 if (tabOpt->direction == Qt::LeftToRight) { 2268 //We place icon on the left. 2269 iconRect = QRect(labelRect.x(), labelRect.y() + (labelRect.height() - iconSize.height() + 1) / 2, 2270 iconSize.width(), iconSize.height()); 2271 2272 //Adjust the text rect. 2273 labelRect.setLeft(labelRect.x() + iconSize.width() + 2274 widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget)); 2275 } else { 2276 //We place icon on the right 2277 iconRect = QRect(labelRect.x() + labelRect.width() - iconSize.width(), 2278 labelRect.y() + (labelRect.height() - iconSize.height() + 1) / 2, iconSize.width(), iconSize.height()); 2279 //Adjust the text rect 2280 labelRect.setWidth(labelRect.width() - iconSize.width() - 2281 widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget)); 2282 } 2283 } else { 2284 bool aboveIcon = false; 2285 if (tabSd == West && tabOpt->direction == Qt::RightToLeft) { 2286 aboveIcon = true; 2287 } 2288 if (tabSd == East && tabOpt->direction == Qt::LeftToRight) { 2289 aboveIcon = true; 2290 } 2291 2292 if (aboveIcon) { 2293 iconRect = QRect(labelRect.x() + (labelRect.width() - iconSize.width() + 1) / 2, labelRect.y(), 2294 iconSize.width(), iconSize.height()); 2295 labelRect.setTop(labelRect.y() + iconSize.height() + 2296 widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget)); 2297 } else { 2298 iconRect = QRect(labelRect.x() + (labelRect.width() - iconSize.width() + 1) / 2, 2299 labelRect.y() + labelRect.height() - iconSize.height(), 2300 iconSize.width(), iconSize.height()); 2301 labelRect.setHeight(labelRect.height() - iconSize.height() - 2302 widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget)); 2303 } 2304 } 2305 2306 //Draw the thing 2307 drawKStylePrimitive(WT_TabBar, Generic::Icon, option, iconRect, 2308 pal, flags, p, widget, &icoOpt); 2309 } //if have icon. 2310 2311 //Draw text 2312 if (!tabOpt->text.isNull()) { 2313 TextOption lbOpt(tabOpt->text); 2314 if (widget) { 2315 lbOpt.color = widget->foregroundRole(); 2316 } 2317 2318 int primitive = Generic::Text; // For horizontal tabs 2319 2320 if (tabSd == East) { 2321 primitive = TabBar::EastText; 2322 } else if (tabSd == West) { 2323 primitive = TabBar::WestText; 2324 } 2325 2326 drawKStylePrimitive(WT_TabBar, primitive, option, labelRect, 2327 pal, flags, p, widget, &lbOpt); 2328 } 2329 2330 //If need be, draw focus rect 2331 if (tabOpt->state & State_HasFocus) { 2332 QRect focusRect = marginAdjustedTab(tabOpt, TabBar::TabFocusMargin); 2333 drawKStylePrimitive(WT_TabBar, Generic::FocusIndicator, option, focusRect, 2334 pal, flags, p, widget); 2335 } 2336 return; 2337 } 2338 2339 case CE_ToolBar: { 2340 if (flags & State_Horizontal) { 2341 drawKStylePrimitive(WT_ToolBar, ToolBar::PanelHor, option, r, pal, flags, p, widget); 2342 } else { 2343 drawKStylePrimitive(WT_ToolBar, ToolBar::PanelVert, option, r, pal, flags, p, widget); 2344 } 2345 2346 return; 2347 } 2348 2349 case CE_HeaderSection: { 2350 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { 2351 drawKStylePrimitive(WT_Header, (header->orientation == Qt::Horizontal) ? Header::SectionHor : Header::SectionVert, 2352 option, r, pal, flags, p, widget); 2353 return; 2354 } 2355 } 2356 2357 case CE_HeaderLabel: { 2358 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { 2359 QRect textRect = r; 2360 if (!header->icon.isNull()) { 2361 bool enabled = flags & State_Enabled; 2362 QPixmap pm = header->icon.pixmap(pixelMetric(PM_SmallIconSize), enabled ? QIcon::Normal : QIcon::Disabled); 2363 2364 // TODO: respect header->iconAlignment. 2365 bool reverseLayout = header->direction == Qt::RightToLeft; 2366 int iy = r.top() + (r.height() - pm.height()) / 2; 2367 int ix = reverseLayout ? r.right() - pm.width() : r.left(); 2368 QRect iconRect = QRect(ix, iy, pm.width(), pm.height()); 2369 2370 IconOption iconOpt; 2371 iconOpt.icon = pm; 2372 drawKStylePrimitive(WT_Header, Generic::Icon, option, iconRect, pal, flags, p, widget, &iconOpt); 2373 2374 // adjust the rect for the text... 2375 int spacing = widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget); 2376 if (reverseLayout) { 2377 textRect.setRight(r.right() - iconRect.width() - spacing); 2378 } else { 2379 textRect.setLeft(r.x() + iconRect.width() + spacing); 2380 } 2381 } 2382 2383 TextOption lbOpt(header->text); 2384 lbOpt.hAlign = header->textAlignment; 2385 drawKStylePrimitive(WT_Header, Generic::Text, option, textRect, pal, flags, p, widget, &lbOpt); 2386 } 2387 return; 2388 } 2389 2390 case CE_Splitter: { 2391 if (flags & State_Horizontal) { 2392 drawKStylePrimitive(WT_Splitter, Splitter::HandleHor, option, r, pal, flags, p, widget); 2393 } else { 2394 drawKStylePrimitive(WT_Splitter, Splitter::HandleVert, option, r, pal, flags, p, widget); 2395 } 2396 return; 2397 } 2398 2399 default: 2400 break; 2401 } 2402 2403 QCommonStyle::drawControl(element, option, p, widget); 2404 } 2405 2406 int K4Style::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const 2407 { 2408 switch (hint) { 2409 case SH_ComboBox_ListMouseTracking: 2410 return true; 2411 2412 case SH_MenuBar_MouseTracking: 2413 case SH_Menu_MouseTracking: 2414 return true; 2415 2416 case SH_Menu_SubMenuPopupDelay: 2417 return 96; // Motif-like delay... 2418 2419 case SH_TitleBar_NoBorder: 2420 return widgetLayoutProp(WT_Window, Window::NoTitleFrame, option, widget); 2421 2422 case SH_GroupBox_TextLabelVerticalAlignment: 2423 if (widgetLayoutProp(WT_GroupBox, GroupBox::TextAlignTop, option, widget)) { 2424 return Qt::AlignTop; 2425 } else { 2426 return Qt::AlignVCenter; 2427 } 2428 2429 case SH_GroupBox_TextLabelColor: { 2430 ColorMode cm(widgetLayoutProp(WT_GroupBox, GroupBox::TitleTextColor, 2431 option, widget)); 2432 return cm.color(option ? option->palette : qApp->palette()).rgba(); 2433 } 2434 2435 case SH_DialogButtonLayout: 2436 return QDialogButtonBox::KdeLayout; 2437 2438 case SH_ScrollBar_MiddleClickAbsolutePosition: 2439 return true; 2440 2441 // Don't draw the branch as selected in tree views 2442 case SH_ItemView_ShowDecorationSelected: 2443 return false; 2444 2445 case SH_ItemView_ActivateItemOnSingleClick: 2446 return KSharedConfig::openConfig()->group("KDE").readEntry("SingleClick", true); 2447 case SH_KCustomStyleElement: 2448 if (!widget) { 2449 return 0; 2450 } 2451 return d->styleElements.value(widget->objectName(), 0); 2452 2453 // per HIG, align the contents in a form layout to the left 2454 case SH_FormLayoutFormAlignment: 2455 return Qt::AlignLeft | Qt::AlignTop; 2456 2457 // per HIG, align the labels in a form layout to the right 2458 case SH_FormLayoutLabelAlignment: 2459 return Qt::AlignRight; 2460 2461 case SH_FormLayoutFieldGrowthPolicy: 2462 return QFormLayout::ExpandingFieldsGrow; 2463 2464 case SH_FormLayoutWrapPolicy: 2465 return QFormLayout::DontWrapRows; 2466 2467 case SH_MessageBox_TextInteractionFlags: 2468 return true; 2469 2470 case SH_DialogButtonBox_ButtonsHaveIcons: { 2471 // was KGlobalSettings::showIconsOnPushButtons() : 2472 KConfigGroup g(KSharedConfig::openConfig(), "KDE"); 2473 return g.readEntry("ShowIconsOnPushButtons", true); 2474 } 2475 case SH_ItemView_ArrowKeysNavigateIntoChildren: 2476 return true; 2477 case SH_Widget_Animate: { 2478 KConfigGroup g(KSharedConfig::openConfig(), "KDE-Global GUI Settings"); 2479 return g.readEntry("GraphicEffectsLevel", 0); 2480 } 2481 default: 2482 break; 2483 }; 2484 2485 return QCommonStyle::styleHint(hint, option, widget, returnData); 2486 } 2487 2488 int K4Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const 2489 { 2490 switch (metric) { 2491 case PM_SmallIconSize: 2492 case PM_ButtonIconSize: 2493 return KIconLoader::global()->currentSize(KIconLoader::Small); 2494 case PM_ToolBarIconSize: 2495 return KIconLoader::global()->currentSize(KIconLoader::Toolbar); 2496 case PM_LargeIconSize: 2497 return KIconLoader::global()->currentSize(KIconLoader::Dialog); 2498 case PM_MessageBoxIconSize: 2499 // TODO return KIconLoader::global()->currentSize(KIconLoader::MessageBox); 2500 return KIconLoader::SizeHuge; 2501 2502 case PM_DefaultFrameWidth: 2503 if (qstyleoption_cast<const QStyleOptionGroupBox *>(option)) { 2504 return widgetLayoutProp(WT_GroupBox, GroupBox::FrameWidth, option, widget); 2505 } else { 2506 return widgetLayoutProp(WT_Generic, Generic::DefaultFrameWidth, option, widget); 2507 } 2508 2509 case PM_DefaultChildMargin: 2510 case PM_DefaultTopLevelMargin: 2511 return widgetLayoutProp(WT_Generic, Generic::DefaultLayoutMargin, option, widget); 2512 2513 case PM_LayoutHorizontalSpacing: 2514 case PM_LayoutVerticalSpacing: 2515 // use layoutSpacingImplementation 2516 return -1; 2517 2518 case PM_DefaultLayoutSpacing: 2519 return widgetLayoutProp(WT_Generic, Generic::DefaultLayoutSpacing, option, widget); 2520 2521 case PM_LayoutLeftMargin: 2522 case PM_LayoutTopMargin: 2523 case PM_LayoutRightMargin: 2524 case PM_LayoutBottomMargin: { 2525 PixelMetric marginMetric; 2526 if ((option && (option->state & QStyle::State_Window)) 2527 || (widget && widget->isWindow())) { 2528 marginMetric = PM_DefaultTopLevelMargin; 2529 } else { 2530 marginMetric = PM_DefaultChildMargin; 2531 } 2532 return pixelMetric(marginMetric, option, widget); 2533 } 2534 2535 case PM_ButtonMargin: 2536 return 0; //Better not return anything here since we already 2537 //incorporated this into SE_PushButtonContents 2538 case PM_ButtonDefaultIndicator: 2539 // PushButton::DefaultIndicatorMargin is used throughout KStyle button 2540 // implementation code, so this probably is not necessary. 2541 // return it in case Apps rely on this metric, though. 2542 return widgetLayoutProp(WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget); 2543 case PM_ButtonShiftHorizontal: 2544 return widgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, option, widget); 2545 case PM_ButtonShiftVertical: 2546 return widgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, option, widget); 2547 case PM_MenuButtonIndicator: 2548 if (qstyleoption_cast<const QStyleOptionToolButton *>(option)) { 2549 return widgetLayoutProp(WT_ToolButton, ToolButton::MenuIndicatorSize, option, widget); 2550 } else { 2551 return widgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, option, widget); 2552 } 2553 2554 case PM_SplitterWidth: 2555 return widgetLayoutProp(WT_Splitter, Splitter::Width, option, widget); 2556 2557 case PM_IndicatorWidth: 2558 case PM_IndicatorHeight: 2559 return widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget); 2560 2561 case PM_ExclusiveIndicatorWidth: 2562 case PM_ExclusiveIndicatorHeight: 2563 return widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget); 2564 2565 case PM_DockWidgetFrameWidth: 2566 return widgetLayoutProp(WT_DockWidget, DockWidget::FrameWidth, option, widget); 2567 2568 case PM_DockWidgetSeparatorExtent: 2569 return widgetLayoutProp(WT_DockWidget, DockWidget::SeparatorExtent, option, widget); 2570 2571 // handle extent only used somewhere in Qt3support, don't care. 2572 // case PM_DockWidgetHandleExtent: 2573 2574 case PM_DockWidgetTitleMargin: 2575 return widgetLayoutProp(WT_DockWidget, DockWidget::TitleMargin, option, widget); 2576 2577 case PM_ProgressBarChunkWidth: 2578 return widgetLayoutProp(WT_ProgressBar, ProgressBar::Precision, option, widget); 2579 2580 case PM_MenuBarPanelWidth: 2581 return 0; //Simplification: just one primitive is used and it includes the border 2582 2583 case PM_MenuBarHMargin: { 2584 //Calculate how much extra space we need besides the frame size. We use the left margin 2585 //here, and adjust the total rect by the difference between it and the right margin 2586 int spaceL = widgetLayoutProp(WT_MenuBar, MenuBar::Margin, option, widget) + widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, option, widget); 2587 2588 return spaceL; 2589 } 2590 2591 case PM_MenuBarVMargin: { 2592 //As above, we return the top one, and fudge the total size for the bottom. 2593 int spaceT = widgetLayoutProp(WT_MenuBar, MenuBar::Margin, option, widget) + widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Top, option, widget); 2594 return spaceT; 2595 } 2596 2597 case PM_MenuBarItemSpacing: 2598 return widgetLayoutProp(WT_MenuBar, MenuBar::ItemSpacing, option, widget); 2599 2600 case PM_MenuDesktopFrameWidth: 2601 return 0; //### CHECKME 2602 2603 case PM_MenuPanelWidth: 2604 return widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget); 2605 2606 /* ### seems to trigger Qt bug. So we loose the margins for now 2607 case PM_MenuHMargin: 2608 { 2609 //Calculate how much extra space we need besides the frame size. We use the left margin 2610 //here, and adjust the total rect by the difference between it and the right margin 2611 int spaceL = widgetLayoutProp(WT_Menu, Menu::Margin, option, widget) + widgetLayoutProp(WT_Menu, Menu::Margin + Left, option, widget) - 2612 widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget); 2613 2614 return spaceL; 2615 } 2616 2617 case PM_MenuVMargin: 2618 { 2619 //As above, we return the top one, and fudge the total size for the bottom. 2620 int spaceT = widgetLayoutProp(WT_Menu, Menu::Margin, option, widget) + widgetLayoutProp(WT_Menu, Menu::Margin + Top, option, widget) - 2621 widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget); 2622 return spaceT; 2623 } */ 2624 2625 case PM_MenuScrollerHeight: 2626 return widgetLayoutProp(WT_Menu, Menu::ScrollerHeight, option, widget); 2627 2628 case PM_MenuTearoffHeight: 2629 return widgetLayoutProp(WT_Menu, Menu::TearOffHeight, option, widget); 2630 2631 case PM_TabBarTabHSpace: { 2632 const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option); 2633 if (tabOpt) { 2634 //Perhaps we can avoid the extra margin... 2635 if (tabOpt->text.isNull() && !tabOpt->icon.isNull()) { 2636 return 0; 2637 } 2638 if (tabOpt->icon.isNull() && !tabOpt->text.isNull()) { 2639 return 0; 2640 } 2641 } 2642 2643 return widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget); 2644 } 2645 2646 case PM_TabBarTabVSpace: 2647 return 0; 2648 2649 case PM_TabBarBaseHeight: 2650 return widgetLayoutProp(WT_TabBar, TabBar::BaseHeight, option, widget); 2651 2652 case PM_TabBarBaseOverlap: 2653 return widgetLayoutProp(WT_TabBar, TabBar::BaseOverlap, option, widget); 2654 2655 case PM_TabBarTabOverlap: 2656 return widgetLayoutProp(WT_TabBar, TabBar::TabOverlap, option, widget); 2657 2658 case PM_TabBarScrollButtonWidth: 2659 return widgetLayoutProp(WT_TabBar, TabBar::ScrollButtonWidth, option, widget); 2660 2661 case PM_TabBarTabShiftVertical: 2662 return 1; 2663 2664 case PM_TabBarTabShiftHorizontal: 2665 return 0; 2666 2667 case PM_SliderControlThickness: 2668 return widgetLayoutProp(WT_Slider, Slider::HandleThickness, option, widget); 2669 2670 case PM_SliderLength: 2671 return widgetLayoutProp(WT_Slider, Slider::HandleLength, option, widget); 2672 2673 case PM_SliderThickness: { 2674 // not sure what the difference to PM_SliderControlThickness actually is 2675 return widgetLayoutProp(WT_Slider, Slider::HandleThickness, option, widget); 2676 } 2677 2678 case PM_SpinBoxFrameWidth: 2679 return widgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, option, widget); 2680 2681 case PM_ComboBoxFrameWidth: 2682 return widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget); 2683 2684 case PM_HeaderMarkSize: 2685 return widgetLayoutProp(WT_Header, Header::MarkSize, option, widget); 2686 2687 case PM_HeaderMargin: 2688 return widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget); 2689 2690 case PM_ToolBarFrameWidth: 2691 return widgetLayoutProp(WT_ToolBar, ToolBar::FrameWidth, option, widget); 2692 2693 case PM_ToolBarHandleExtent: 2694 return widgetLayoutProp(WT_ToolBar, ToolBar::HandleExtent, option, widget); 2695 2696 case PM_ToolBarSeparatorExtent: 2697 return widgetLayoutProp(WT_ToolBar, ToolBar::SeparatorExtent, option, widget); 2698 2699 case PM_ToolBarExtensionExtent: 2700 return widgetLayoutProp(WT_ToolBar, ToolBar::ExtensionExtent, option, widget); 2701 2702 case PM_ToolBarItemMargin: 2703 return widgetLayoutProp(WT_ToolBar, ToolBar::ItemMargin, option, widget); 2704 2705 case PM_ToolBarItemSpacing: 2706 return widgetLayoutProp(WT_ToolBar, ToolBar::ItemSpacing, option, widget); 2707 2708 case PM_ScrollBarExtent: 2709 return widgetLayoutProp(WT_ScrollBar, ScrollBar::BarWidth, option, widget); 2710 2711 case PM_TitleBarHeight: 2712 return widgetLayoutProp(WT_Window, Window::TitleHeight, option, widget); 2713 2714 default: 2715 break; 2716 } 2717 2718 return QCommonStyle::pixelMetric(metric, option, widget); 2719 } 2720 2721 int K4Style::layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const 2722 { 2723 Q_UNUSED(control1); Q_UNUSED(control2); Q_UNUSED(orientation); 2724 2725 return pixelMetric(PM_DefaultLayoutSpacing, option, widget); 2726 } 2727 2728 bool K4Style::isVerticalTab(const QStyleOptionTab *tbOpt) const 2729 { 2730 switch (tbOpt->shape) { 2731 case QTabBar::RoundedWest: 2732 case QTabBar::RoundedEast: 2733 case QTabBar::TriangularWest: 2734 case QTabBar::TriangularEast: 2735 return true; 2736 default: 2737 return false; 2738 } 2739 } 2740 2741 bool K4Style::isReflectedTab(const QStyleOptionTab *tbOpt) const 2742 { 2743 switch (tbOpt->shape) { 2744 case QTabBar::RoundedEast: 2745 case QTabBar::TriangularEast: 2746 case QTabBar::RoundedSouth: 2747 case QTabBar::TriangularSouth: 2748 return true; 2749 default: 2750 return false; 2751 } 2752 } 2753 2754 K4Style::Side K4Style::tabSide(const QStyleOptionTab *tbOpt) const 2755 { 2756 switch (tbOpt->shape) { 2757 case QTabBar::RoundedEast: 2758 case QTabBar::TriangularEast: 2759 return East; 2760 case QTabBar::RoundedWest: 2761 case QTabBar::TriangularWest: 2762 return West; 2763 case QTabBar::RoundedNorth: 2764 case QTabBar::TriangularNorth: 2765 return North; 2766 default: 2767 return South; 2768 } 2769 } 2770 2771 QRect K4Style::marginAdjustedTab(const QStyleOptionTab *tabOpt, int property) const 2772 { 2773 QRect r = tabOpt->rect; 2774 2775 //For region, we first figure out the geometry if it was normal, and adjust. 2776 //this takes some rotating 2777 bool vertical = isVerticalTab(tabOpt); 2778 bool flip = isReflectedTab(tabOpt); 2779 2780 QRect idializedGeometry = vertical ? QRect(0, 0, r.height(), r.width()) 2781 : QRect(0, 0, r.width(), r.height()); 2782 2783 QRect contentArea = insideMargin(idializedGeometry, WT_TabBar, property, tabOpt, nullptr); 2784 2785 int leftMargin = contentArea.x(); 2786 int rightMargin = idializedGeometry.width() - 1 - contentArea.right(); 2787 int topMargin = contentArea.y(); 2788 int botMargin = idializedGeometry.height() - 1 - contentArea.bottom(); 2789 2790 if (vertical) { 2791 int t = rightMargin; 2792 rightMargin = topMargin; 2793 topMargin = leftMargin; 2794 leftMargin = botMargin; 2795 botMargin = t; 2796 2797 if (!flip) { 2798 qSwap(leftMargin, rightMargin); 2799 } 2800 } else if (flip) { 2801 qSwap(topMargin, botMargin); 2802 //For horizontal tabs, we also want to reverse stuff for RTL! 2803 if (tabOpt->direction == Qt::RightToLeft) { 2804 qSwap(leftMargin, rightMargin); 2805 } 2806 } 2807 2808 QRect geom = 2809 QRect(QPoint(leftMargin, topMargin), 2810 QPoint(r.width() - 1 - rightMargin, 2811 r.height() - 1 - botMargin)); 2812 geom.translate(r.topLeft()); 2813 return geom; 2814 } 2815 2816 bool K4Style::useSideText(const QStyleOptionProgressBar *pbOpt) const 2817 { 2818 if (widgetLayoutProp(WT_ProgressBar, ProgressBar::SideText) == 0) { 2819 return false; 2820 } 2821 2822 if (!pbOpt) { 2823 return false; //Paranoia 2824 } 2825 2826 if (!pbOpt->textVisible) { 2827 return false; //Don't allocate side margin if text display is off... 2828 } 2829 2830 if (pbOpt->textAlignment & Qt::AlignHCenter) { 2831 return false; //### do we want this? we don't 2832 } 2833 //force indicator to the side outside 2834 //the main otherwise. 2835 2836 if (pbOpt->minimum == pbOpt->maximum) { 2837 return false; 2838 } 2839 2840 int widthAlloc = pbOpt->fontMetrics.width(QLatin1String("100%")); 2841 2842 if (pbOpt->fontMetrics.width(pbOpt->text) > widthAlloc) { 2843 return false; //Doesn't fit! 2844 } 2845 2846 return true; 2847 } 2848 2849 int K4Style::sideTextWidth(const QStyleOptionProgressBar *pbOpt) const 2850 { 2851 return pbOpt->fontMetrics.width(QLatin1String("100%")) + 2852 2 * widgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace); 2853 } 2854 2855 QRect K4Style::subElementRect(SubElement sr, const QStyleOption *option, const QWidget *widget) const 2856 { 2857 QRect r = option->rect; 2858 2859 switch (sr) { 2860 case SE_PushButtonContents: { 2861 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 2862 if (!bOpt) { 2863 return r; 2864 } 2865 2866 if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) { 2867 r = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget); 2868 } 2869 2870 return insideMargin(r, WT_PushButton, PushButton::ContentsMargin, option, widget); 2871 } 2872 2873 case SE_PushButtonFocusRect: { 2874 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 2875 if (!bOpt) { 2876 return r; 2877 } 2878 2879 if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) { 2880 r = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget); 2881 } 2882 2883 return insideMargin(r, WT_PushButton, PushButton::FocusMargin, option, widget); 2884 } 2885 2886 case SE_ToolBoxTabContents: { 2887 return insideMargin(r, WT_ToolBoxTab, ToolBoxTab::Margin, option, widget); 2888 } 2889 2890 case SE_CheckBoxContents: { 2891 r.setX(r.x() + widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget) + 2892 widgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, option, widget)); 2893 return handleRTL(option, r); 2894 } 2895 2896 case SE_RadioButtonContents: { 2897 r.setX(r.x() + widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget) + 2898 widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget)); 2899 return handleRTL(option, r); 2900 } 2901 2902 case SE_CheckBoxFocusRect: { 2903 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 2904 if (!bOpt) { 2905 return r; 2906 } 2907 2908 QRect ret; 2909 2910 if (bOpt->text.isEmpty()) { 2911 // first convert, so we can deal with logical coords 2912 QRect checkRect = 2913 handleRTL(option, subElementRect(SE_CheckBoxIndicator, option, widget)); 2914 ret = insideMargin(checkRect, WT_CheckBox, CheckBox::NoLabelFocusMargin, option, widget); 2915 } else { 2916 // first convert, so we can deal with logical coords 2917 QRect contentsRect = 2918 handleRTL(option, subElementRect(SE_CheckBoxContents, option, widget)); 2919 ret = insideMargin(contentsRect, WT_CheckBox, CheckBox::FocusMargin, option, widget); 2920 } 2921 // convert back to screen coords 2922 return handleRTL(option, ret); 2923 } 2924 2925 case SE_RadioButtonFocusRect: { 2926 // first convert it back to logical coords 2927 QRect contentsRect = 2928 handleRTL(option, subElementRect(SE_RadioButtonContents, option, widget)); 2929 2930 // modify the rect and convert back to screen coords 2931 return handleRTL(option, 2932 insideMargin(contentsRect, WT_RadioButton, 2933 RadioButton::FocusMargin, option, widget)); 2934 } 2935 2936 case SE_ProgressBarGroove: { 2937 const QStyleOptionProgressBar *pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar *>(option); 2938 if (useSideText(pbOpt)) { 2939 r.setWidth(r.width() - sideTextWidth(pbOpt)); 2940 return r; 2941 } 2942 2943 //Centering mode --- could be forced or side... so the groove area is everything 2944 return r; 2945 } 2946 2947 case SE_ProgressBarContents: { 2948 QRect grooveRect = subElementRect(SE_ProgressBarGroove, option, widget); 2949 return insideMargin(grooveRect, WT_ProgressBar, ProgressBar::GrooveMargin, option, widget); 2950 } 2951 2952 case SE_ProgressBarLabel: { 2953 const QStyleOptionProgressBar *pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar *>(option); 2954 if (useSideText(pbOpt)) { 2955 int width = sideTextWidth(pbOpt); 2956 return QRect(r.x() + r.width() - width, r.y(), width, r.height()); 2957 } 2958 2959 //The same as the contents area.. 2960 return subElementRect(SE_PushButtonContents, option, widget); 2961 } 2962 2963 // SE_TabWidgetTabPane implementation in QCommonStyle is perfectly fine. 2964 case SE_TabWidgetTabContents: { 2965 const QStyleOptionTabWidgetFrame *tabOpt = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option); 2966 if (!tabOpt) { 2967 break; 2968 } 2969 2970 // Don't apply the custom margin when documentMode is enabled. 2971 if (tabOpt->lineWidth == 0) { 2972 break; 2973 } 2974 2975 // use QCommonStyle's SE_TabWidgetTabPane, and adjust the result 2976 // according to the custom frame width. 2977 QRect pane = QCommonStyle::subElementRect(SE_TabWidgetTabPane, option, widget); 2978 int m = widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, option, widget); 2979 int top = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Top, 2980 option, widget); 2981 int bot = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Bot, 2982 option, widget); 2983 int left = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Left, 2984 option, widget); 2985 int right = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Right, 2986 option, widget); 2987 2988 switch (tabOpt->shape) { 2989 case QTabBar::RoundedNorth: 2990 case QTabBar::TriangularNorth: 2991 return pane.adjusted(left, top, -right, -bot); 2992 case QTabBar::RoundedEast: 2993 case QTabBar::TriangularEast: 2994 return pane.adjusted(bot, left, -top, -right); 2995 case QTabBar::RoundedSouth: 2996 case QTabBar::TriangularSouth: 2997 return pane.adjusted(right, bot, -left, -top); 2998 case QTabBar::RoundedWest: 2999 case QTabBar::TriangularWest: 3000 return pane.adjusted(top, right, -bot, -left); 3001 } 3002 } 3003 3004 case SE_TabBarTabText: { 3005 const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option); 3006 if (!tabOpt) { 3007 return QRect(); 3008 } 3009 3010 QRect r = marginAdjustedTab(tabOpt, TabBar::TabContentsMargin); 3011 QStyleOptionTab tov3(*tabOpt); 3012 3013 switch (tov3.shape) { 3014 case QTabBar::RoundedNorth: 3015 case QTabBar::TriangularNorth: 3016 case QTabBar::RoundedSouth: 3017 case QTabBar::TriangularSouth: 3018 if (tov3.direction == Qt::LeftToRight) { 3019 r.adjust(tov3.leftButtonSize.width(), 0, -tov3.rightButtonSize.width(), 0); 3020 } else { 3021 r.adjust(tov3.rightButtonSize.width(), 0, -tov3.leftButtonSize.width(), 0); 3022 } 3023 break; 3024 case QTabBar::RoundedEast: 3025 case QTabBar::TriangularEast: 3026 r.adjust(0, tov3.leftButtonSize.width(), 0, -tov3.rightButtonSize.width()); 3027 break; 3028 case QTabBar::RoundedWest: 3029 case QTabBar::TriangularWest: 3030 r.adjust(0, tov3.rightButtonSize.width(), 0, -tov3.leftButtonSize.width()); 3031 break; 3032 } 3033 3034 return r; 3035 } 3036 3037 default: 3038 break; 3039 } 3040 3041 return QCommonStyle::subElementRect(sr, option, widget); 3042 } 3043 3044 void K4Style::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, 3045 QPainter *p, const QWidget *w) const 3046 { 3047 //Extract the stuff we need out of the option 3048 State flags = opt->state; 3049 QRect r = opt->rect; 3050 QPalette pal = opt->palette; 3051 3052 switch (cc) { 3053 case CC_ScrollBar: { 3054 QStyleOptionComplex *mutableOpt = const_cast<QStyleOptionComplex *>(opt); 3055 if ((mutableOpt->subControls & SC_ScrollBarSubLine) || (mutableOpt->subControls & SC_ScrollBarAddLine)) { 3056 //If we paint one of the buttons, must paint both! 3057 mutableOpt->subControls |= SC_ScrollBarSubPage | SC_ScrollBarAddLine; 3058 } 3059 //Note: we falldown to the base intentionally 3060 } 3061 break; 3062 3063 case CC_Slider: { 3064 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 3065 QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, w); 3066 QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, w); 3067 bool hor = slider->orientation == Qt::Horizontal; 3068 3069 if (slider->subControls & SC_SliderTickmarks) { 3070 // TODO: make tickmarks customizable with Slider::Tickmark-primitives? 3071 QStyleOptionSlider tmpSlider = *slider; 3072 tmpSlider.subControls = SC_SliderTickmarks; 3073 QCommonStyle::drawComplexControl(cc, &tmpSlider, p, w); 3074 } 3075 3076 if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { 3077 drawKStylePrimitive(WT_Slider, hor ? Slider::GrooveHor : Slider::GrooveVert, opt, groove, pal, flags, p, w); 3078 } 3079 3080 if (slider->subControls & SC_SliderHandle) { 3081 drawKStylePrimitive(WT_Slider, hor ? Slider::HandleHor : Slider::HandleVert, opt, handle, pal, flags, p, w); 3082 3083 if (slider->state & State_HasFocus) { 3084 QRect focus = subElementRect(SE_SliderFocusRect, slider, w); 3085 drawKStylePrimitive(WT_Slider, Generic::FocusIndicator, opt, focus, pal, flags, p, w, nullptr); 3086 } 3087 } 3088 } //option OK 3089 return; 3090 } //CC_Slider 3091 3092 case CC_SpinBox: { 3093 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { 3094 bool activeSbUp = sb->activeSubControls & SC_SpinBoxUp && (flags & State_Sunken); 3095 bool activeSbDown = sb->activeSubControls & SC_SpinBoxDown && (flags & State_Sunken); 3096 3097 if (sb->subControls & SC_SpinBoxFrame) { 3098 drawKStylePrimitive(WT_SpinBox, Generic::Frame, opt, r, pal, flags, p, w); 3099 } 3100 3101 if (sb->subControls & SC_SpinBoxEditField) { 3102 QRect editField = subControlRect(CC_SpinBox, opt, SC_SpinBoxEditField, w); 3103 drawKStylePrimitive(WT_SpinBox, SpinBox::EditField, opt, editField, pal, flags, p, w); 3104 } 3105 3106 QRect upRect, downRect; 3107 if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) { 3108 upRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w); 3109 downRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w); 3110 QRect buttonAreaRect = upRect | downRect; 3111 drawKStylePrimitive(WT_SpinBox, SpinBox::ButtonArea, opt, buttonAreaRect, pal, flags, p, w); 3112 } 3113 3114 if (sb->subControls & SC_SpinBoxUp) { 3115 // adjust the sunken state flag... 3116 State upFlags = flags; 3117 if (activeSbUp) { 3118 upFlags |= State_Sunken; 3119 } else { 3120 upFlags &= ~State_Sunken; 3121 } 3122 3123 drawKStylePrimitive(WT_SpinBox, SpinBox::UpButton, opt, upRect, pal, upFlags, p, w); 3124 3125 // draw symbol... 3126 int primitive; 3127 if (sb->buttonSymbols == QAbstractSpinBox::PlusMinus) { 3128 primitive = SpinBox::PlusSymbol; 3129 } else { 3130 primitive = Generic::ArrowUp; 3131 } 3132 drawKStylePrimitive(WT_SpinBox, primitive, opt, upRect, pal, upFlags, p, w); 3133 } 3134 3135 if (sb->subControls & SC_SpinBoxDown) { 3136 // adjust the sunken state flag... 3137 State downFlags = flags; 3138 if (activeSbDown) { 3139 downFlags |= State_Sunken; 3140 } else { 3141 downFlags &= ~State_Sunken; 3142 } 3143 3144 drawKStylePrimitive(WT_SpinBox, SpinBox::DownButton, opt, downRect, pal, downFlags, p, w); 3145 3146 // draw symbol... 3147 int primitive; 3148 if (sb->buttonSymbols == QAbstractSpinBox::PlusMinus) { 3149 primitive = SpinBox::MinusSymbol; 3150 } else { 3151 primitive = Generic::ArrowDown; 3152 } 3153 drawKStylePrimitive(WT_SpinBox, primitive, opt, downRect, pal, downFlags, p, w); 3154 } 3155 3156 return; 3157 } //option OK 3158 } //CC_SpinBox 3159 3160 case CC_ComboBox: { 3161 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { 3162 if (cb->subControls & SC_ComboBoxFrame) { 3163 drawKStylePrimitive(WT_ComboBox, Generic::Frame, opt, r, pal, flags, p, w); 3164 3165 // focus indicator 3166 if (cb->state & State_HasFocus) { 3167 QRect editField = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, w); 3168 QRect focusRect = insideMargin(editField, WT_ComboBox, ComboBox::FocusMargin, opt, w); 3169 drawKStylePrimitive(WT_ComboBox, Generic::FocusIndicator, opt, focusRect, pal, flags, p, w, nullptr); 3170 } 3171 } 3172 3173 if (cb->subControls & SC_ComboBoxEditField) { 3174 QRect editField = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, w); 3175 drawKStylePrimitive(WT_ComboBox, ComboBox::EditField, opt, editField, pal, flags, p, w); 3176 } 3177 3178 if (cb->subControls & SC_ComboBoxArrow) { 3179 QRect buttonRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w); 3180 drawKStylePrimitive(WT_ComboBox, ComboBox::Button, opt, buttonRect, pal, flags, p, w); 3181 3182 // draw symbol... 3183 drawKStylePrimitive(WT_ComboBox, Generic::ArrowDown, opt, buttonRect, pal, flags, p, w); 3184 } 3185 3186 return; 3187 } //option OK 3188 break; 3189 } //CC_Combo 3190 3191 case CC_ToolButton: { 3192 if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { 3193 QRect buttonRect = subControlRect(cc, tool, SC_ToolButton, w); 3194 QRect menuRect = subControlRect(cc, tool, SC_ToolButtonMenu, w); 3195 3196 // State_AutoRaise: only draw button when State_MouseOver 3197 State bflags = tool->state; 3198 if (bflags & State_AutoRaise) { 3199 if (!(bflags & State_MouseOver)) { 3200 bflags &= ~State_Raised; 3201 } 3202 } 3203 State mflags = bflags; 3204 3205 QStyleOption tOpt(0); 3206 tOpt.palette = pal; 3207 3208 if (tool->subControls & SC_ToolButton) { 3209 if (bflags & (State_Sunken | State_On | State_Raised)) { 3210 tOpt.rect = buttonRect; 3211 tOpt.state = bflags; 3212 drawPrimitive(PE_PanelButtonTool, &tOpt, p, w); 3213 } 3214 } 3215 3216 if (tool->subControls & SC_ToolButtonMenu) { 3217 tOpt.rect = menuRect; 3218 tOpt.state = mflags; 3219 drawPrimitive(PE_IndicatorButtonDropDown, &tOpt, p, w); 3220 } else if (tool->features & QStyleOptionToolButton::HasMenu) { 3221 // This is requesting KDE3-style arrow indicator, per Qt 4.4 behavior. Qt 4.3 prefers to hide 3222 // the fact of the menu's existence. Whee! Since we don't know how to paint this right, 3223 // though, we have to have some metrics set for it to look nice. 3224 int size = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorSize, opt, w); 3225 3226 if (size) { 3227 int xOff = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorXOff, opt, w); 3228 int yOff = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorYOff, opt, w); 3229 3230 QRect r = QRect(buttonRect.right() + xOff, buttonRect.bottom() + yOff, size, size); 3231 tOpt.rect = r; 3232 tOpt.state = bflags; 3233 drawPrimitive(PE_IndicatorButtonDropDown, &tOpt, p, w); 3234 } 3235 } 3236 3237 if (flags & State_HasFocus) { 3238 QRect focusRect = insideMargin(r, WT_ToolButton, ToolButton::FocusMargin, opt, w); 3239 tOpt.rect = focusRect; 3240 tOpt.state = bflags; 3241 drawKStylePrimitive(WT_ToolButton, Generic::FocusIndicator, &tOpt, focusRect, pal, bflags, p, w); 3242 } 3243 3244 // CE_ToolButtonLabel expects a readjusted rect, for the button area proper 3245 QStyleOptionToolButton labelOpt = *tool; 3246 labelOpt.rect = buttonRect; 3247 drawControl(CE_ToolButtonLabel, &labelOpt, p, w); 3248 3249 return; 3250 } 3251 break; 3252 } //CC_ToolButton 3253 3254 case CC_TitleBar: { 3255 const QStyleOptionTitleBar *tb = 3256 qstyleoption_cast<const QStyleOptionTitleBar *>(opt); 3257 if (!tb) { 3258 break; 3259 } 3260 3261 // title bar 3262 drawKStylePrimitive(WT_Window, Window::TitlePanel, opt, r, pal, flags, p, w); 3263 3264 // TODO: different color depending on Active/inactive state 3265 // draw title text 3266 QRect textRect = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, w); 3267 TextOption textOpt(tb->text); 3268 textOpt.color = widgetLayoutProp(WT_Window, Window::TitleTextColor, opt, w); 3269 drawKStylePrimitive(WT_Window, Generic::Text, opt, textRect, 3270 pal, flags, p, w, &textOpt); 3271 3272 TitleButtonOption buttonKOpt; 3273 buttonKOpt.icon = tb->icon; 3274 3275 if ((tb->subControls & SC_TitleBarSysMenu) && 3276 (tb->titleBarFlags & Qt::WindowSystemMenuHint)) { 3277 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarSysMenu) 3278 && (tb->state & State_Sunken); 3279 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, w); 3280 drawKStylePrimitive(WT_Window, Window::ButtonMenu, opt, br, pal, flags, p, w, 3281 &buttonKOpt); 3282 } 3283 3284 if ((tb->subControls & SC_TitleBarMinButton) && 3285 (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) { 3286 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarMinButton) 3287 && (tb->state & State_Sunken); 3288 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, w); 3289 drawKStylePrimitive(WT_Window, Window::ButtonMin, opt, br, pal, flags, p, w, 3290 &buttonKOpt); 3291 } 3292 3293 if ((tb->subControls & SC_TitleBarMaxButton) && 3294 (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) { 3295 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarMaxButton) 3296 && (tb->state & State_Sunken); 3297 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, w); 3298 drawKStylePrimitive(WT_Window, Window::ButtonMax, opt, br, pal, flags, p, w, 3299 &buttonKOpt); 3300 } 3301 3302 if ((tb->subControls & SC_TitleBarCloseButton) && 3303 (tb->titleBarFlags & Qt::WindowSystemMenuHint)) { 3304 // bool hover = (tb->activeSubControls & SC_TitleBarCloseButton) 3305 // && (tb->state & State_MouseOver); 3306 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarCloseButton) 3307 && (tb->state & State_Sunken); 3308 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, w); 3309 drawKStylePrimitive(WT_Window, Window::ButtonClose, opt, br, pal, flags, p, w, 3310 &buttonKOpt); 3311 } 3312 3313 if ((tb->subControls & SC_TitleBarNormalButton) && 3314 (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint) && 3315 (tb->titleBarState & Qt::WindowMinimized)) || 3316 ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) && 3317 (tb->titleBarState & Qt::WindowMaximized)))) { 3318 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarNormalButton) 3319 && (tb->state & State_Sunken); 3320 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, w); 3321 drawKStylePrimitive(WT_Window, Window::ButtonRestore, opt, br, pal, flags, p, w, 3322 &buttonKOpt); 3323 } 3324 3325 if (tb->subControls & SC_TitleBarShadeButton) { 3326 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarShadeButton) 3327 && (tb->state & State_Sunken); 3328 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, w); 3329 drawKStylePrimitive(WT_Window, Window::ButtonShade, opt, br, pal, flags, p, w, 3330 &buttonKOpt); 3331 } 3332 3333 if (tb->subControls & SC_TitleBarUnshadeButton) { 3334 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarUnshadeButton) 3335 && (tb->state & State_Sunken); 3336 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, w); 3337 drawKStylePrimitive(WT_Window, Window::ButtonUnshade, opt, br, pal, flags, p, w, 3338 &buttonKOpt); 3339 } 3340 3341 if ((tb->subControls & SC_TitleBarContextHelpButton) 3342 && (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)) { 3343 buttonKOpt.active = (tb->activeSubControls & SC_TitleBarContextHelpButton) 3344 && (tb->state & State_Sunken); 3345 QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, w); 3346 drawKStylePrimitive(WT_Window, Window::ButtonHelp, opt, br, pal, flags, p, w, 3347 &buttonKOpt); 3348 } 3349 3350 return; 3351 } // CC_TitleBar 3352 3353 default: 3354 break; 3355 } //switch 3356 3357 QCommonStyle::drawComplexControl(cc, opt, p, w); 3358 } 3359 3360 QRect K4Style::internalSubControlRect(ComplexControl control, const QStyleOptionComplex *option, 3361 SubControl subControl, const QWidget *widget) const 3362 { 3363 QRect r = option->rect; 3364 3365 if (control == CC_ScrollBar) { 3366 switch (subControl) { 3367 //The "top" arrow 3368 case SC_ScrollBarSubLine: { 3369 int majorSize; 3370 if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, option, widget)) { 3371 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, option, widget); 3372 } else { 3373 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, option, widget); 3374 } 3375 3376 if (option->state & State_Horizontal) { 3377 return handleRTL(option, QRect(r.x(), r.y(), majorSize, r.height())); 3378 } else { 3379 return handleRTL(option, QRect(r.x(), r.y(), r.width(), majorSize)); 3380 } 3381 3382 } 3383 3384 //The "bottom" arrow 3385 case SC_ScrollBarAddLine: { 3386 int majorSize; 3387 if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, option, widget)) { 3388 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, option, widget); 3389 } else { 3390 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, option, widget); 3391 } 3392 3393 if (option->state & State_Horizontal) { 3394 return handleRTL(option, QRect(r.right() - majorSize + 1, r.y(), majorSize, r.height())); 3395 } else { 3396 return handleRTL(option, QRect(r.x(), r.bottom() - majorSize + 1, r.width(), majorSize)); 3397 } 3398 } 3399 3400 default: 3401 break; 3402 } 3403 } 3404 3405 return QRect(); 3406 } 3407 3408 QRect K4Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option, 3409 SubControl subControl, const QWidget *widget) const 3410 { 3411 QRect r = option->rect; 3412 3413 switch (control) { 3414 case CC_ScrollBar: { 3415 switch (subControl) { 3416 //For both arrows, we return -everything-, 3417 //to get stuff to repaint right. See internalSubControlRect 3418 //for the real thing 3419 case SC_ScrollBarSubLine: 3420 case SC_ScrollBarAddLine: 3421 return r; 3422 3423 //The main groove area. This is used to compute the others... 3424 case SC_ScrollBarGroove: { 3425 QRect top = handleRTL(option, internalSubControlRect(control, option, SC_ScrollBarSubLine, widget)); 3426 QRect bot = handleRTL(option, internalSubControlRect(control, option, SC_ScrollBarAddLine, widget)); 3427 3428 QPoint topLeftCorner, botRightCorner; 3429 if (option->state & State_Horizontal) { 3430 topLeftCorner = QPoint(top.right() + 1, top.top()); 3431 botRightCorner = QPoint(bot.left() - 1, top.bottom()); 3432 } else { 3433 topLeftCorner = QPoint(top.left(), top.bottom() + 1); 3434 botRightCorner = QPoint(top.right(), bot.top() - 1); 3435 } 3436 3437 return handleRTL(option, QRect(topLeftCorner, botRightCorner)); 3438 } 3439 3440 case SC_ScrollBarFirst: 3441 case SC_ScrollBarLast: 3442 return QRect(); 3443 3444 case SC_ScrollBarSlider: { 3445 const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option); 3446 3447 //We do handleRTL here to unreflect things if need be 3448 QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget)); 3449 Q_ASSERT(slOpt); 3450 3451 if (slOpt->minimum == slOpt->maximum) { 3452 return groove; 3453 } 3454 3455 //Figure out how much room we have.. 3456 int space; 3457 if (option->state & State_Horizontal) { 3458 space = groove.width(); 3459 } else { 3460 space = groove.height(); 3461 } 3462 3463 //Calculate the portion of this space that the slider should take up. 3464 int sliderSize = int(space * float(slOpt->pageStep) / 3465 (slOpt->maximum - slOpt->minimum + slOpt->pageStep)); 3466 3467 if (sliderSize < widgetLayoutProp(WT_ScrollBar, ScrollBar::MinimumSliderHeight, option, widget)) { 3468 sliderSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::MinimumSliderHeight, option, widget); 3469 } 3470 3471 if (sliderSize > space) { 3472 sliderSize = space; 3473 } 3474 3475 //What do we have remaining? 3476 space = space - sliderSize; 3477 3478 //uhm, yeah, nothing much 3479 if (space <= 0) { 3480 return groove; 3481 } 3482 3483 int pos = qRound(float(slOpt->sliderPosition - slOpt->minimum) / 3484 (slOpt->maximum - slOpt->minimum) * space); 3485 if (option->state & State_Horizontal) { 3486 return handleRTL(option, QRect(groove.x() + pos, groove.y(), sliderSize, groove.height())); 3487 } else { 3488 return handleRTL(option, QRect(groove.x(), groove.y() + pos, groove.width(), sliderSize)); 3489 } 3490 } 3491 3492 case SC_ScrollBarSubPage: { 3493 //We do handleRTL here to unreflect things if need be 3494 QRect slider = handleRTL(option, subControlRect(control, option, SC_ScrollBarSlider, widget)); 3495 QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget)); 3496 3497 //We're above the slider in the groove. 3498 if (option->state & State_Horizontal) { 3499 return handleRTL(option, QRect(groove.x(), groove.y(), slider.x() - groove.x(), groove.height())); 3500 } else { 3501 return handleRTL(option, QRect(groove.x(), groove.y(), groove.width(), slider.y() - groove.y())); 3502 } 3503 } 3504 3505 case SC_ScrollBarAddPage: { 3506 //We do handleRTL here to unreflect things if need be 3507 QRect slider = handleRTL(option, subControlRect(control, option, SC_ScrollBarSlider, widget)); 3508 QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget)); 3509 3510 //We're below the slider in the groove. 3511 if (option->state & State_Horizontal) 3512 return handleRTL(option, 3513 QRect(slider.right() + 1, groove.y(), groove.right() - slider.right(), groove.height())); 3514 else 3515 return handleRTL(option, 3516 QRect(groove.x(), slider.bottom() + 1, groove.width(), groove.bottom() - slider.bottom())); 3517 } 3518 3519 default: 3520 break; 3521 } 3522 } //CC_ScrollBar 3523 3524 case CC_SpinBox: { 3525 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { 3526 3527 int fw = widgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, option, widget); 3528 int bw = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonWidth, option, widget); 3529 int bm = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin, option, widget); 3530 int bml = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Left, option, widget); 3531 int bmr = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Right, option, widget); 3532 int bmt = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Top, option, widget); 3533 int bmb = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Bot, option, widget); 3534 int bs = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonSpacing, option, widget); 3535 bool symmButtons = widgetLayoutProp(WT_SpinBox, SpinBox::SymmetricButtons, option, widget); 3536 bool supportFrameless = widgetLayoutProp(WT_SpinBox, SpinBox::SupportFrameless, option, widget); 3537 3538 // SpinBox without a frame, set the corresponding layout values to 0, reduce button width. 3539 if (supportFrameless && !sb->frame) { 3540 bw = bw - bmr; // reduce button with as the right button margin will be ignored. 3541 fw = 0; 3542 bmt = bmb = bmr = 0; 3543 } 3544 3545 const int buttonsWidth = bw - bml - bmr; 3546 const int buttonsLeft = r.right() - bw + bml + 1; 3547 3548 // compute the height of each button... 3549 int availableButtonHeight = r.height() - bmt - bmb - bs; 3550 if (symmButtons) { 3551 // make sure the availableButtonHeight is even by reducing the 3552 // button spacing by 1 if necessary. Results in both buttons 3553 // of the same height... 3554 if (availableButtonHeight % 2 != 0) { 3555 --bs; 3556 3557 // recalculate... 3558 availableButtonHeight = r.height() - bmt - bmb - bs; 3559 } 3560 } 3561 int heightUp = availableButtonHeight / 2; 3562 int heightDown = availableButtonHeight - heightUp; 3563 3564 switch (subControl) { 3565 case SC_SpinBoxUp: 3566 return handleRTL(option, 3567 QRect(buttonsLeft, r.top() + bmt, buttonsWidth, heightUp)); 3568 case SC_SpinBoxDown: 3569 return handleRTL(option, 3570 QRect(buttonsLeft, r.bottom() - bmb - heightDown + 1, buttonsWidth, heightDown)); 3571 case SC_SpinBoxEditField: { 3572 QRect labelRect(r.left() + fw, r.top() + fw, r.width() - fw - bw, r.height() - 2 * fw); 3573 labelRect = insideMargin(labelRect, WT_SpinBox, SpinBox::ContentsMargin, option, widget); 3574 return handleRTL(option, labelRect); 3575 } 3576 case SC_SpinBoxFrame: 3577 return (sb->frame || !supportFrameless) ? r : QRect(); 3578 default: 3579 break; 3580 } 3581 } //option ok 3582 } //CC_SpinBox 3583 3584 case CC_ComboBox: { 3585 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { 3586 3587 int fw = widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget); 3588 int bw = widgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, option, widget); 3589 int bm = widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin, option, widget); 3590 int bml = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Left, option, widget); 3591 int bmr = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Right, option, widget); 3592 int bmt = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Top, option, widget); 3593 int bmb = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Bot, option, widget); 3594 bool supportFrameless = widgetLayoutProp(WT_ComboBox, ComboBox::SupportFrameless, option, widget); 3595 3596 // ComboBox without a frame, set the corresponding layout values to 0, reduce button width. 3597 if (supportFrameless && !cb->frame) { 3598 bw = bw - bmr; // reduce button with as the right button margin will be ignored. 3599 fw = 0; 3600 bmt = bmb = bmr = 0; 3601 } 3602 3603 switch (subControl) { 3604 case SC_ComboBoxFrame: 3605 return (cb->frame || !supportFrameless) ? r : QRect(); 3606 case SC_ComboBoxArrow: 3607 return handleRTL(option, 3608 QRect(r.right() - bw + bml + 1, r.top() + bmt, bw - bml - bmr, r.height() - bmt - bmb)); 3609 case SC_ComboBoxEditField: { 3610 QRect labelRect(r.left() + fw, r.top() + fw, r.width() - fw - bw, r.height() - 2 * fw); 3611 labelRect = insideMargin(labelRect, WT_ComboBox, ComboBox::ContentsMargin, option, widget); 3612 return handleRTL(option, labelRect); 3613 } 3614 case SC_ComboBoxListBoxPopup: 3615 // TODO: need to add layoutProps to control the popup rect? 3616 // return cb->popupRect; 3617 // popupRect seems to be empty, so use QStyleOption::rect as Qt's styles do 3618 return r; 3619 default: 3620 break; 3621 } 3622 } //option ok 3623 } //CC_ComboBox 3624 3625 case CC_TitleBar: { 3626 const QStyleOptionTitleBar *tbOpt = 3627 qstyleoption_cast<const QStyleOptionTitleBar *>(option); 3628 if (!tbOpt) { 3629 break; 3630 } 3631 3632 QRect ret = insideMargin(r, WT_Window, Window::TitleMargin, option, widget); 3633 3634 const int btnHeight = ret.height(); 3635 const int btnWidth = widgetLayoutProp(WT_Window, Window::ButtonWidth, option, widget); 3636 const int btnSpace = widgetLayoutProp(WT_Window, Window::ButtonSpace, option, widget); 3637 const int titleSpace = widgetLayoutProp(WT_Window, Window::ButtonToTextSpace, option, widget); 3638 3639 bool isMinimized = tbOpt->titleBarState & Qt::WindowMinimized; 3640 bool isMaximized = tbOpt->titleBarState & Qt::WindowMaximized; 3641 3642 // button layout: menu -title- help,shade,min,max,close 3643 3644 bool menuCloseBtn = tbOpt->titleBarFlags & Qt::WindowSystemMenuHint; 3645 bool minBtn = !isMinimized && 3646 (tbOpt->titleBarFlags & Qt::WindowMinimizeButtonHint); 3647 bool maxBtn = !isMaximized && 3648 (tbOpt->titleBarFlags & Qt::WindowMaximizeButtonHint); 3649 bool restoreBtn = 3650 (isMinimized && (tbOpt->titleBarFlags & Qt::WindowMinimizeButtonHint)) || 3651 (isMaximized && (tbOpt->titleBarFlags & Qt::WindowMaximizeButtonHint)); 3652 bool shadeBtn = tbOpt->titleBarFlags & Qt::WindowShadeButtonHint; 3653 bool helpBtn = tbOpt->titleBarFlags & Qt::WindowContextHelpButtonHint; 3654 3655 int btnOffsetCount = 0; // for button rects; count the position in the button bar 3656 3657 switch (subControl) { 3658 case SC_TitleBarLabel: { 3659 if (tbOpt->titleBarFlags & Qt::WindowTitleHint) { 3660 int cLeft = 0; // count buttons in the button bar 3661 int cRight = 0; 3662 3663 if (menuCloseBtn) { 3664 // menu and close button 3665 ++cLeft; 3666 ++cRight; 3667 } 3668 if (minBtn) { 3669 ++cRight; 3670 } 3671 if (restoreBtn) { 3672 ++cRight; 3673 } 3674 if (maxBtn) { 3675 ++cRight; 3676 } 3677 if (shadeBtn) { 3678 ++cRight; 3679 } 3680 if (helpBtn) { 3681 ++cRight; 3682 } 3683 3684 ret.adjust(cLeft * btnWidth + (cLeft - 1)*btnSpace + titleSpace, 0, 3685 -(titleSpace + cRight * btnWidth + (cRight - 1)*btnSpace), 0); 3686 } 3687 break; 3688 } 3689 3690 case SC_TitleBarSysMenu: { 3691 if (tbOpt->titleBarFlags & Qt::WindowSystemMenuHint) { 3692 ret.setRect(ret.left(), ret.top(), btnWidth, btnHeight); 3693 } 3694 break; 3695 } 3696 3697 case SC_TitleBarContextHelpButton: 3698 if (helpBtn) { 3699 ++btnOffsetCount; 3700 } 3701 case SC_TitleBarMinButton: 3702 if (minBtn) { 3703 ++btnOffsetCount; 3704 } else if (subControl == SC_TitleBarMinButton) { 3705 return QRect(); 3706 } 3707 case SC_TitleBarNormalButton: 3708 if (restoreBtn) { 3709 ++btnOffsetCount; 3710 } else if (subControl == SC_TitleBarNormalButton) { 3711 return QRect(); 3712 } 3713 case SC_TitleBarMaxButton: 3714 if (maxBtn) { 3715 ++btnOffsetCount; 3716 } else if (subControl == SC_TitleBarMaxButton) { 3717 return QRect(); 3718 } 3719 case SC_TitleBarShadeButton: 3720 if (!isMinimized && shadeBtn) { 3721 ++btnOffsetCount; 3722 } else if (subControl == SC_TitleBarShadeButton) { 3723 return QRect(); 3724 } 3725 case SC_TitleBarUnshadeButton: 3726 if (isMinimized && shadeBtn) { 3727 ++btnOffsetCount; 3728 } else if (subControl == SC_TitleBarUnshadeButton) { 3729 return QRect(); 3730 } 3731 case SC_TitleBarCloseButton: { 3732 if (menuCloseBtn) { 3733 ++btnOffsetCount; 3734 } else if (subControl == SC_TitleBarCloseButton) { 3735 return QRect(); 3736 } 3737 // set the rect for all buttons that fell through: 3738 ret.setRect(ret.right() - btnOffsetCount * btnWidth - (btnOffsetCount - 1)*btnSpace, 3739 ret.top(), btnWidth, btnHeight); 3740 break; 3741 } 3742 3743 default: 3744 return QRect(); 3745 } 3746 3747 return visualRect(tbOpt->direction, tbOpt->rect, ret); 3748 3749 } // CC_TitleBar 3750 3751 default: 3752 break; 3753 } 3754 3755 return QCommonStyle::subControlRect(control, option, subControl, widget); 3756 } 3757 3758 /* 3759 Checks whether the point is before the bound rect for 3760 bound of given orientation 3761 */ 3762 static bool preceeds(const QPoint &pt, const QRect &bound, 3763 const QStyleOption *opt) 3764 { 3765 if (opt->state & QStyle::State_Horizontal) { 3766 //What's earlier depends on RTL or not 3767 if (opt->direction == Qt::LeftToRight) { 3768 return pt.x() < bound.right(); 3769 } else { 3770 return pt.x() > bound.x(); 3771 } 3772 } else { 3773 return pt.y() < bound.y(); 3774 } 3775 } 3776 3777 static QStyle::SubControl buttonPortion(const QRect &totalRect, 3778 const QPoint &pt, 3779 const QStyleOption *opt) 3780 { 3781 if (opt->state & QStyle::State_Horizontal) { 3782 //What's earlier depends on RTL or not 3783 if (opt->direction == Qt::LeftToRight) { 3784 return pt.x() < totalRect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; 3785 } else { 3786 return pt.x() > totalRect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; 3787 } 3788 } else { 3789 return pt.y() < totalRect.center().y() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; 3790 } 3791 } 3792 3793 QStyle::SubControl K4Style::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, 3794 const QPoint &pt, const QWidget *w) const 3795 { 3796 if (cc == CC_ScrollBar) { 3797 //First, check whether we're inside the groove or not... 3798 QRect groove = subControlRect(CC_ScrollBar, opt, SC_ScrollBarGroove, w); 3799 3800 if (groove.contains(pt)) { 3801 //Must be either page up/page down, or just click on the slider. 3802 //Grab the slider to compare 3803 QRect slider = subControlRect(CC_ScrollBar, opt, SC_ScrollBarSlider, w); 3804 3805 if (slider.contains(pt)) { 3806 return SC_ScrollBarSlider; 3807 } else if (preceeds(pt, slider, opt)) { 3808 return SC_ScrollBarSubPage; 3809 } else { 3810 return SC_ScrollBarAddPage; 3811 } 3812 } else { 3813 //This is one of the up/down buttons. First, decide which one it is. 3814 if (preceeds(pt, groove, opt)) { 3815 //"Upper" button 3816 if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, nullptr, w)) { 3817 QRect buttonRect = internalSubControlRect(CC_ScrollBar, opt, SC_ScrollBarSubLine, w); 3818 return buttonPortion(buttonRect, pt, opt); 3819 } else { 3820 return SC_ScrollBarSubLine; //Easy one! 3821 } 3822 } else { 3823 //"Bottom" button 3824 if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, nullptr, w)) { 3825 QRect buttonRect = internalSubControlRect(CC_ScrollBar, opt, SC_ScrollBarAddLine, w); 3826 return buttonPortion(buttonRect, pt, opt); 3827 } else { 3828 return SC_ScrollBarAddLine; //Easy one! 3829 } 3830 } 3831 } 3832 } 3833 3834 return QCommonStyle::hitTestComplexControl(cc, opt, pt, w); 3835 } 3836 3837 QSize K4Style::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const 3838 { 3839 switch (type) { 3840 case CT_PushButton: { 3841 const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option); 3842 if (!bOpt) { 3843 return contentsSize; 3844 } 3845 3846 QSize size = contentsSize; 3847 3848 if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) { 3849 size = expandDim(size, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget); 3850 } 3851 3852 //### TODO: Handle minimum size limits, extra spacing as in current styles ?? 3853 size = expandDim(size, WT_PushButton, PushButton::ContentsMargin, option, widget); 3854 3855 if (bOpt->features & QStyleOptionButton::HasMenu) { 3856 size.setWidth(size.width() + widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget)); 3857 } 3858 3859 if (!bOpt->text.isEmpty() && !bOpt->icon.isNull()) { 3860 // Incorporate the spacing between the icon and text. Qt sticks 4 there, 3861 // but we use PushButton::TextToIconSpace. 3862 size.setWidth(size.width() - 4 + widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget)); 3863 } 3864 return size; 3865 } 3866 3867 case CT_ToolButton: { 3868 // We want to avoid super-skiny buttons, for things like "up" when icons + text 3869 // For this, we would like to make width >= height. 3870 // However, once we get here, QToolButton may have already put in the menu area 3871 // (PM_MenuButtonIndicator) into the width. So we may have to take it out, fix things 3872 // up, and add it back in. So much for class-independent rendering... 3873 QSize size = contentsSize; 3874 int menuAreaWidth = 0; 3875 if (const QStyleOptionToolButton *tbOpt = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { 3876 if (tbOpt->features & QStyleOptionToolButton::MenuButtonPopup) { 3877 menuAreaWidth = pixelMetric(QStyle::PM_MenuButtonIndicator, option, widget); 3878 } else if (tbOpt->features & QStyleOptionToolButton::HasMenu) { 3879 size.setWidth(size.width() + widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorSize, tbOpt, widget)); 3880 } 3881 } 3882 3883 size.setWidth(size.width() - menuAreaWidth); 3884 if (size.width() < size.height()) { 3885 size.setWidth(size.height()); 3886 } 3887 size.setWidth(size.width() + menuAreaWidth); 3888 3889 return expandDim(size, WT_ToolButton, ToolButton::ContentsMargin, option, widget); 3890 } 3891 3892 case CT_CheckBox: { 3893 //Add size for indicator ### handle empty case differently? 3894 int indicator = widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget); 3895 int spacer = widgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, option, widget); 3896 3897 //Make sure we include space for the focus rect margin 3898 QSize size = expandDim(contentsSize, WT_CheckBox, CheckBox::FocusMargin, option, widget); 3899 3900 //Make sure we can fit the indicator (### an extra margin around that?) 3901 size.setHeight(qMax(size.height(), indicator)); 3902 3903 //Add space for the indicator and the icon 3904 size.setWidth(size.width() + indicator + spacer); 3905 3906 return size; 3907 } 3908 3909 case CT_RadioButton: { 3910 //Add size for indicator 3911 int indicator = widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget); 3912 int spacer = widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget); 3913 3914 //Make sure we include space for the focus rect margin 3915 QSize size = expandDim(contentsSize, WT_RadioButton, RadioButton::FocusMargin, option, widget); 3916 3917 //Make sure we can fit the indicator (### an extra margin around that?) 3918 size.setHeight(qMax(size.height(), indicator)); 3919 3920 //Add space for the indicator and the icon 3921 size.setWidth(size.width() + indicator + spacer); 3922 3923 return size; 3924 } 3925 3926 case CT_ProgressBar: { 3927 QSize size = contentsSize; 3928 3929 const QStyleOptionProgressBar *pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar *>(option); 3930 if (useSideText(pbOpt)) { 3931 //Allocate extra room for side text 3932 size.setWidth(size.width() + sideTextWidth(pbOpt)); 3933 } 3934 3935 return size; 3936 } 3937 3938 case CT_MenuBar: { 3939 int extraW = widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Right, option, widget) - 3940 widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, option, widget); 3941 3942 int extraH = widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Bot, option, widget) - 3943 widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Top, option, widget); 3944 3945 return QSize(contentsSize.width() + extraW, contentsSize.height() + extraH); 3946 } 3947 3948 case CT_Menu: { 3949 int extraW = widgetLayoutProp(WT_Menu, Menu::Margin + Right, option, widget) - 3950 widgetLayoutProp(WT_Menu, Menu::Margin + Left, option, widget); 3951 3952 int extraH = widgetLayoutProp(WT_Menu, Menu::Margin + Bot, option, widget) - 3953 widgetLayoutProp(WT_Menu, Menu::Margin + Top, option, widget); 3954 3955 return QSize(contentsSize.width() + extraW, contentsSize.height() + extraH); 3956 } 3957 3958 case CT_MenuItem: { 3959 const QStyleOptionMenuItem *miOpt = ::qstyleoption_cast<const QStyleOptionMenuItem *>(option); 3960 if (!miOpt) { 3961 return contentsSize; //Someone is asking for trouble.. 3962 } 3963 3964 //First, we calculate the intrinsic size of the item.. 3965 QSize insideSize; 3966 3967 switch (miOpt->menuItemType) { 3968 case QStyleOptionMenuItem::Normal: 3969 case QStyleOptionMenuItem::DefaultItem: //huh? 3970 case QStyleOptionMenuItem::SubMenu: { 3971 int iconColW = miOpt->maxIconWidth; 3972 iconColW = qMax(iconColW, widgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, option, widget)); 3973 3974 int leftColW = iconColW; 3975 if (miOpt->menuHasCheckableItems && 3976 widgetLayoutProp(WT_MenuItem, MenuItem::CheckAlongsideIcon, option, widget)) { 3977 leftColW = widgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, option, widget) + 3978 widgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, option, widget) + 3979 iconColW; 3980 } 3981 3982 leftColW += widgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, option, widget); 3983 3984 int rightColW = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, option, widget) + 3985 widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget); 3986 3987 QFontMetrics fm(miOpt->font); 3988 3989 int textW; 3990 int tabPos = miOpt->text.indexOf(QLatin1Char('\t')); 3991 if (tabPos == -1) { 3992 //No accel.. 3993 textW = contentsSize.width(); 3994 } else { 3995 // The width of the accelerator is not included here since 3996 // Qt will add that on separately after obtaining the 3997 // sizeFromContents() for each menu item in the menu to be shown 3998 // ( see QMenuPrivate::calcActionRects() ) 3999 textW = contentsSize.width() + 4000 widgetLayoutProp(WT_MenuItem, MenuItem::AccelSpace, option, widget); 4001 } 4002 4003 int h = qMax(contentsSize.height(), widgetLayoutProp(WT_MenuItem, MenuItem::MinHeight, option, widget)); 4004 insideSize = QSize(leftColW + textW + rightColW, h); 4005 break; 4006 } 4007 4008 case QStyleOptionMenuItem::Separator: { 4009 insideSize = QSize(10, widgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, option, widget)); 4010 } 4011 break; 4012 4013 //Double huh if we get those. 4014 case QStyleOptionMenuItem::Scroller: 4015 case QStyleOptionMenuItem::TearOff: 4016 case QStyleOptionMenuItem::Margin: 4017 case QStyleOptionMenuItem::EmptyArea: 4018 return contentsSize; 4019 } 4020 4021 //...now apply the outermost margin. 4022 return expandDim(insideSize, WT_MenuItem, MenuItem::Margin, option, widget); 4023 } 4024 4025 case CT_MenuBarItem: 4026 return expandDim(contentsSize, WT_MenuBarItem, MenuBarItem::Margin, option, widget); 4027 4028 case CT_TabBarTab: { 4029 //With our PM_TabBarTabHSpace/VSpace, Qt should give us what we want for 4030 //contentsSize, so we just expand that. Qt also takes care of 4031 //the vertical thing. 4032 4033 bool rotated = false; // indicates whether the tab is rotated by 90 degrees 4034 if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option)) { 4035 rotated = isVerticalTab(tabOpt); 4036 } 4037 4038 return expandDim(contentsSize, WT_TabBar, TabBar::TabContentsMargin, option, widget, rotated); 4039 } 4040 4041 case CT_TabWidget: { 4042 const QStyleOptionTabWidgetFrame *tabOpt = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option); 4043 if (!tabOpt) { 4044 break; 4045 } 4046 4047 int m = widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, option, widget); 4048 int vert = 2 * m + 4049 widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Top, option, widget) + 4050 widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Bot, option, widget); 4051 int hor = 2 * m + 4052 widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Left, option, widget) + 4053 widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Right, option, widget); 4054 4055 switch (tabOpt->shape) { 4056 case QTabBar::RoundedNorth: 4057 case QTabBar::TriangularNorth: 4058 case QTabBar::RoundedWest: 4059 case QTabBar::TriangularWest: 4060 return contentsSize + QSize(hor, vert); 4061 case QTabBar::RoundedSouth: 4062 case QTabBar::TriangularSouth: 4063 case QTabBar::RoundedEast: 4064 case QTabBar::TriangularEast: 4065 return contentsSize + QSize(vert, hor); 4066 } 4067 } 4068 4069 case CT_HeaderSection: { 4070 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { 4071 QSize iconSize = header->icon.isNull() ? QSize(0, 0) : QSize(22, 22); 4072 QSize textSize = header->fontMetrics.size(0, header->text); 4073 int iconSpacing = widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget); 4074 int w = iconSize.width() + iconSpacing + textSize.width(); 4075 int h = qMax(iconSize.height(), textSize.height()); 4076 4077 return expandDim(QSize(w, h), WT_Header, Header::ContentsMargin, option, widget); 4078 } 4079 } 4080 4081 case CT_ComboBox: { 4082 // TODO: Figure out what to do with the button margins 4083 QSize size = contentsSize; 4084 4085 // Add the contents margin 4086 size = expandDim(size, WT_ComboBox, ComboBox::ContentsMargin, option, widget); 4087 4088 // Add the button width 4089 size.rwidth() += widgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, option, widget); 4090 4091 // Add the frame width 4092 size.rwidth() += widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget) * 2; 4093 size.rheight() += widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget) * 2; 4094 4095 return size; 4096 } 4097 4098 default: 4099 break; 4100 } 4101 4102 return QCommonStyle::sizeFromContents(type, option, contentsSize, widget); 4103 } 4104 4105 bool K4Style::eventFilter(QObject *obj, QEvent *ev) 4106 { 4107 if (QCommonStyle::eventFilter(obj, ev)) { 4108 return true; 4109 } 4110 4111 if (QLabel *lbl = qobject_cast<QLabel *>(obj)) { 4112 QWidget *buddy = lbl->buddy(); 4113 if (buddy) { 4114 switch (ev->type()) { 4115 case QEvent::MouseButtonPress: { 4116 QMouseEvent *mev = dynamic_cast<QMouseEvent *>(ev); 4117 if (!mev) { 4118 break; 4119 } 4120 4121 if (lbl->rect().contains(mev->pos())) { 4122 clickedLabel = obj; 4123 lbl->repaint(); 4124 } 4125 break; 4126 } 4127 case QEvent::MouseButtonRelease: { 4128 QMouseEvent *mev = dynamic_cast<QMouseEvent *>(ev); 4129 if (!mev) { 4130 break; 4131 } 4132 4133 if (clickedLabel) { 4134 clickedLabel = nullptr; 4135 lbl->update(); 4136 } 4137 4138 // set focus to the buddy... 4139 if (lbl->rect().contains(mev->pos())) { 4140 buddy->setFocus(Qt::ShortcutFocusReason); 4141 } 4142 break; 4143 } 4144 case QEvent::Paint: 4145 if (obj == clickedLabel && buddy->isEnabled()) { 4146 // paint focus rect 4147 QPainter p(lbl); 4148 QStyleOptionFocusRect foOpts; 4149 QRect foRect(0, 0, lbl->width(), lbl->height()); 4150 foOpts.palette = lbl->palette(); 4151 foOpts.rect = foRect; 4152 drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, &foOpts, 4153 foRect, lbl->palette(), State(), &p, lbl); 4154 } 4155 break; 4156 4157 default: 4158 break; 4159 } 4160 } 4161 } 4162 4163 return false; 4164 } 4165 4166 K4Style::ColorMode::ColorMode(QPalette::ColorRole _role): 4167 mode(PaletteEntryMode), 4168 role(_role) 4169 {} 4170 4171 K4Style::ColorMode::ColorMode(Mode _mode, QPalette::ColorRole _role): 4172 mode(_mode), 4173 role(_role) 4174 {} 4175 4176 K4Style::ColorMode::operator int() const 4177 { 4178 return int(role) | int(mode); 4179 } 4180 4181 K4Style::ColorMode::ColorMode(int encoded) 4182 { 4183 mode = (encoded & BWAutoContrastMode) ? BWAutoContrastMode : PaletteEntryMode; 4184 role = QPalette::ColorRole(encoded & (~BWAutoContrastMode)); 4185 } 4186 4187 QColor K4Style::ColorMode::color(const QPalette &palette) 4188 { 4189 QColor palColor = palette.color(role); 4190 4191 if (mode == BWAutoContrastMode) { 4192 if (qGray(palColor.rgb()) > 128) { //### CHECKME 4193 palColor = Qt::black; 4194 } else { 4195 palColor = Qt::white; 4196 } 4197 } 4198 return palColor; 4199 } 4200 4201 K4Style::TextOption::TextOption() 4202 { 4203 init(); 4204 } 4205 4206 K4Style::TextOption::TextOption(const QString &_text): 4207 text(_text) 4208 { 4209 init(); 4210 } 4211 4212 void K4Style::TextOption::init() 4213 { 4214 hAlign = Qt::AlignLeft; //NOTE: Check BIDI? 4215 } 4216 4217 #include "moc_k4style.cpp"