KDELibs4Support

k4style.cpp
1 
46 #include "k4style.h"
47 
48 #include <qalgorithms.h>
49 #include <QCache>
50 #include <QEvent>
51 #include <QVariant>
52 #include <QAbstractItemView>
53 #include <QApplication>
54 #include <QDialogButtonBox>
55 #include <QFormLayout>
56 #include <QIcon>
57 #include <QLabel>
58 #include <QKeyEvent>
59 #include <QPainter>
60 #include <QScrollBar>
61 #include <QStyleOption>
62 #include <QPainterPath>
63 
64 #include <kconfiggroup.h>
65 #include <QDebug>
66 #include <kiconloader.h>
67 #include <kcolorscheme.h>
68 
69 //### FIXME: Who to credit these to?
70 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};
71 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};
72 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};
73 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};
74 #define QCOORDARRLEN(x) sizeof(x)/(sizeof(qint32)*2)
75 
83 // ----------------------------------------------------------------------------
84 
85 // For item view selections
86 struct SelectionTiles {
88 };
89 
90 // ----------------------------------------------------------------------------
91 
92 static const QStyle::StyleHint SH_KCustomStyleElement = (QStyle::StyleHint)0xff000001;
93 static const int X_KdeBase = 0xff000000;
94 
95 class K4StylePrivate
96 {
97 public:
98  K4StylePrivate();
99  QCache<quint64, SelectionTiles> selectionCache;
100 
101  QHash<QString, int> styleElements;
102  int hintCounter, controlCounter, subElementCounter;
103 };
104 
105 K4StylePrivate::K4StylePrivate()
106 {
107  selectionCache.setMaxCost(10);
108  controlCounter = subElementCounter = X_KdeBase;
109  hintCounter = X_KdeBase + 1; //sic! X_KdeBase is covered by SH_KCustomStyleElement
110 }
111 
112 // ----------------------------------------------------------------------------
113 
114 K4Style::K4Style() : clickedLabel(nullptr), d(new K4StylePrivate)
115 {
116  //Set up some default metrics...
117  setWidgetLayoutProp(WT_Generic, Generic::DefaultFrameWidth, 2);
118  setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutSpacing, 6);
119  setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutMargin, 9);
120 
121  setWidgetLayoutProp(WT_PushButton, PushButton::ContentsMargin, 5);
122  setWidgetLayoutProp(WT_PushButton, PushButton::FocusMargin, 3);
123  setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, 2);
124  setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, 2);
125  setWidgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, 8);
126  setWidgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, 6);
127 
128  setWidgetLayoutProp(WT_Splitter, Splitter::Width, 6); //As KStyle in KDE3
129 
130  setWidgetLayoutProp(WT_CheckBox, CheckBox::Size, 16);
131  setWidgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, 6);
132  setWidgetLayoutProp(WT_CheckBox, CheckBox::NoLabelFocusMargin, 1);
133 
134  setWidgetLayoutProp(WT_RadioButton, RadioButton::Size, 16);
135  setWidgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, 6);
136 
137  setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleTextColor,
138  ColorMode(QPalette::HighlightedText));
139  setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleMargin, 2);
140  setWidgetLayoutProp(WT_DockWidget, DockWidget::FrameWidth, 3);
141  setWidgetLayoutProp(WT_DockWidget, DockWidget::SeparatorExtent, 6);
142 
143  setWidgetLayoutProp(WT_ProgressBar, ProgressBar::GrooveMargin, 2);
144  setWidgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace, 3); //(Matches QCommonStyle)
145  setWidgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, 10000);
146  setWidgetLayoutProp(WT_ProgressBar, ProgressBar::BusyIndicatorSize, 10);
147  setWidgetLayoutProp(WT_ProgressBar, ProgressBar::Precision, 1);
148 
149  setWidgetLayoutProp(WT_MenuBar, MenuBar::ItemSpacing, 14);
150  setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin, 2);
151  setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, 4);
152  setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Right, 4);
153 
154  setWidgetLayoutProp(WT_MenuBarItem, MenuBarItem::Margin, 1);
155 
156  setWidgetLayoutProp(WT_Menu, Menu::FrameWidth, 1);
157  setWidgetLayoutProp(WT_Menu, Menu::Margin, 3);
158  setWidgetLayoutProp(WT_Menu, Menu::ScrollerHeight, 10);
159  setWidgetLayoutProp(WT_Menu, Menu::TearOffHeight, 10);
160 
161  setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, 12);
162  setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, 3);
163  setWidgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, 12);
164  setWidgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, 3);
165  setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, 11);
166  setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, 3);
167  setWidgetLayoutProp(WT_MenuItem, MenuItem::Margin, 2);
168  setWidgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, 0); //the margins give enough rooms
169  setWidgetLayoutProp(WT_MenuItem, MenuItem::MinHeight, 16);
170  setWidgetLayoutProp(WT_MenuItem, MenuItem::TextColor, ColorMode(QPalette::Text));
171  setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveTextColor, ColorMode(QPalette::HighlightedText));
172  setWidgetLayoutProp(WT_MenuItem, MenuItem::DisabledTextColor, ColorMode(QPalette::Text));
173  setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveDisabledTextColor, ColorMode(QPalette::Text));
174  setWidgetLayoutProp(WT_MenuItem, MenuItem::AccelSpace, 16);
175 
176  //KDE default is single top button, double bottom one
177  setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, 0);
178  setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, 1);
179  setWidgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, 16);
180  setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, 32);
181  setWidgetLayoutProp(WT_ScrollBar, ScrollBar::BarWidth, 16);
182  setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor,
183  ColorMode(ColorMode::BWAutoContrastMode, QPalette::Button));
184  setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor,
185  ColorMode(ColorMode::BWAutoContrastMode, QPalette::ButtonText));
186 
187  setWidgetLayoutProp(WT_TabBar, TabBar::TabContentsMargin, 6);
188  setWidgetLayoutProp(WT_TabBar, TabBar::TabFocusMargin, 3);
189  setWidgetLayoutProp(WT_TabBar, TabBar::TabOverlap, 0);
190  setWidgetLayoutProp(WT_TabBar, TabBar::BaseHeight, 2);
191  setWidgetLayoutProp(WT_TabBar, TabBar::BaseOverlap, 2);
192  setWidgetLayoutProp(WT_TabBar, TabBar::ScrollButtonWidth, 10);
193  setWidgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, 6);
194 
195  setWidgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, 2);
196 
197  setWidgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, 9);
198 
199  setWidgetLayoutProp(WT_Slider, Slider::HandleThickness, 20);
200  setWidgetLayoutProp(WT_Slider, Slider::HandleLength, 16);
201 
202  setWidgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, 1);
203  setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonWidth, 16);
204  setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonSpacing, 1);
205  setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Right, 1);
206  setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Top, 1);
207  setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Bot, 1);
208 
209  setWidgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, 1);
210  setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, 16);
211  setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Right, 1);
212  setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Top, 1);
213  setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Bot, 1);
214  setWidgetLayoutProp(WT_ComboBox, ComboBox::FocusMargin, 1);
215 
216  setWidgetLayoutProp(WT_Header, Header::ContentsMargin, 3);
217  setWidgetLayoutProp(WT_Header, Header::TextToIconSpace, 3);
218  setWidgetLayoutProp(WT_Header, Header::MarkSize, 9);
219 
220  setWidgetLayoutProp(WT_GroupBox, GroupBox::FrameWidth, 2);
221  setWidgetLayoutProp(WT_GroupBox, GroupBox::TextAlignTop, false);
222  setWidgetLayoutProp(WT_GroupBox, GroupBox::TitleTextColor, ColorMode(QPalette::Text));
223 
224  setWidgetLayoutProp(WT_ToolBar, ToolBar::HandleExtent, 6);
225  setWidgetLayoutProp(WT_ToolBar, ToolBar::SeparatorExtent, 6);
226  setWidgetLayoutProp(WT_ToolBar, ToolBar::ExtensionExtent, 10);
227  setWidgetLayoutProp(WT_ToolBar, ToolBar::FrameWidth, 2);
228  setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemSpacing, 3);
229  setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemMargin, 1);
230 
231  setWidgetLayoutProp(WT_ToolButton, ToolButton::ContentsMargin, 5);
232  setWidgetLayoutProp(WT_ToolButton, ToolButton::FocusMargin, 3);
233  setWidgetLayoutProp(WT_ToolButton, ToolButton::MenuIndicatorSize, 11);
234 
235  setWidgetLayoutProp(WT_ToolBoxTab, ToolBoxTab::Margin, 0);
236 
237  setWidgetLayoutProp(WT_Window, Window::TitleTextColor, ColorMode(QPalette::HighlightedText));
238  setWidgetLayoutProp(WT_Window, Window::TitleHeight, 20);
239  setWidgetLayoutProp(WT_Window, Window::TitleMargin, 2);
240  setWidgetLayoutProp(WT_Window, Window::NoTitleFrame, 0);
241  setWidgetLayoutProp(WT_Window, Window::ButtonWidth, 16);
242  setWidgetLayoutProp(WT_Window, Window::ButtonSpace, 2);
243  setWidgetLayoutProp(WT_Window, Window::ButtonToTextSpace, 3);
244 }
245 
246 K4Style::~K4Style()
247 {
248  // this is just for stupid msvc compiler to force the creation of
249  // DoubleButtonOption::defaultOption() inside kstyle lib
250  // hope the optimizer won't throw it away
251  const DoubleButtonOption *bOpt = extractOption<const DoubleButtonOption *>(nullptr);
252  Q_UNUSED(bOpt)
253 #ifdef __GNUC__
254 #warning "mem leak: need to delete bOpt"
255 #endif
256  delete d;
257 }
258 
259 /*
260  Custom Style Element runtime extension:
261  We reserve one StyleHint to let the effective style inform widgets whether it supports certain
262  string based style elements.
263  As this could lead to number conflicts (i.e. an app utilizing one of the hints itself for other
264  purposes) there're various safety mechanisms to rule out such interference.
265 
266  1) It's most unlikely that a widget in some 3rd party app will accidentally call a general
267  QStyle/K4Style styleHint() or draw*() and (unconditionally) expect a valid return, however:
268  a. The StyleHint is not directly above Qt's custom base, assuming most 3rd party apps would
269  - in case - make use of such
270  b. In order to be accepted, the StyleHint query must pass a widget with a perfectly matching
271  name, containing the typical element prefix ("CE_", etc.) and being supported by the current style
272  c. Instead using Qt's fragile qstyleoption_cast on the QStyleOption provided to the StyleHint
273  query, try to dump out a string and hope for the best, we now manipulate the widgets objectName().
274  Plain Qt dependent widgets can do that themselves and if a widget uses K4Style's convenience access
275  functions, it won't notice this at all
276 
277  2) The key problem is that a common KDE widget will run into an apps custom style which will then
278  falsely respond to the styleHint() call with an invalid value.
279  To prevent this, supporting styles *must* set a Q_CLASSINFO "X-KDE-CustomElements".
280 
281  3) If any of the above traps snaps, the returned id is 0 - the QStyle default, indicating
282  that this element is not supported by the current style.
283 
284  Obviously, this contains the "diminished clean" action to (temporarily) manipulate the
285  objectName() of a const QWidget* - but this happens completely inside K4Style or the widget, if
286  it does not make use of K4Styles static convenience functions.
287  My biggest worry here would be, that in a multithreaded environment a thread (usually not being
288  owner of the widget) does something crucially relying on the widgets name property...
289  This however would also have to happen during the widget construction or stylechanges, when
290  the functions in doubt will typically be called.
291  So this is imho unlikely causing any trouble, ever.
292 */
293 
294 /*
295  The functions called by the real style implementation to add support for a certain element.
296  Checks for well-formed string (containing the element prefix) and returns 0 otherwise.
297  Checks whether the element is already supported or inserts it otherwise; Returns the proper id
298  NOTICE: We could check for "X-KDE-CustomElements", but this would bloat style start up times
299  (if they e.g. register 100 elements or so)
300 */
301 
302 static inline int newStyleElement(const QString &element, const char *check, int &counter, QHash<QString, int> *elements)
303 {
304  if (!element.contains(check)) {
305  return 0;
306  }
307  int id = elements->value(element, 0);
308  if (!id) {
309  ++counter;
310  id = counter;
311  elements->insert(element, id);
312  }
313  return id;
314 }
315 
317 {
318  return (StyleHint)newStyleElement(element, "SH_", d->hintCounter, &d->styleElements);
319 }
320 
321 QStyle::ControlElement K4Style::newControlElement(const QString &element)
322 {
323  return (ControlElement)newStyleElement(element, "CE_", d->controlCounter, &d->styleElements);
324 }
325 
326 K4Style::SubElement K4Style::newSubElement(const QString &element)
327 {
328  return (SubElement)newStyleElement(element, "SE_", d->subElementCounter, &d->styleElements);
329 }
330 
332 {
333 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
334  return QString("breeze");
335 #else
336  return QString(); // native style
337 #endif
338 }
339 
340 /*
341  The functions called by widgets that request custom element support, passed to the effective style.
342  Collected in a static inline function due to similarity.
343 */
344 
345 static inline int customStyleElement(QStyle::StyleHint type, const QString &element, QWidget *widget)
346 {
347  if (!widget || widget->style()->metaObject()->indexOfClassInfo("X-KDE-CustomElements") < 0) {
348  return 0;
349  }
350 
351  const QString originalName = widget->objectName();
352  widget->setObjectName(element);
353  const int id = widget->style()->styleHint(type, nullptr, widget);
354  widget->setObjectName(originalName);
355  return id;
356 }
357 
359 {
360  return (StyleHint) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
361 }
362 
363 QStyle::ControlElement K4Style::customControlElement(const QString &element, const QWidget *widget)
364 {
365  return (ControlElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
366 }
367 
368 QStyle::SubElement K4Style::customSubElement(const QString &element, const QWidget *widget)
369 {
370  return (SubElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
371 }
372 
373 void K4Style::polish(QWidget *w)
374 {
375  if (qobject_cast<QLabel *>(w)) {
376  w->installEventFilter(this);
377  }
378 
379  // Enable hover effects in all itemviews
380  if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(w)) {
381  itemView->viewport()->setAttribute(Qt::WA_Hover);
382  }
383 
385 }
386 void K4Style::unpolish(QWidget *w)
387 {
388  if (qobject_cast<QLabel *>(w)) {
389  w->removeEventFilter(this);
390  }
391 
393 }
394 void K4Style::polish(QApplication *a)
395 {
397 }
398 void K4Style::unpolish(QApplication *a)
399 {
401 }
402 void K4Style::polish(QPalette &pal)
403 {
405 }
406 QRect K4Style::itemTextRect(const QFontMetrics &fm, const QRect &r,
407  int flags, bool enabled,
408  const QString &text) const
409 {
410  return QCommonStyle::itemTextRect(fm, r, flags, enabled, text);
411 }
412 QRect K4Style::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
413 {
414  return QCommonStyle::itemPixmapRect(r, flags, pixmap);
415 }
416 void K4Style::drawItemText(QPainter *painter, const QRect &rect,
417  int flags, const QPalette &pal, bool enabled,
418  const QString &text, QPalette::ColorRole textRole) const
419 {
420  QCommonStyle::drawItemText(painter, rect, flags, pal, enabled,
421  text, textRole);
422 }
423 void K4Style::drawItemPixmap(QPainter *painter, const QRect &rect,
424  int alignment, const QPixmap &pixmap) const
425 {
426  QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap);
427 }
428 QPalette K4Style::standardPalette() const
429 {
431 }
432 
433 QIcon K4Style::standardIcon(StandardPixmap standardIcon, const QStyleOption */*option*/,
434  const QWidget */*widget*/) const
435 {
436  switch (standardIcon) {
438  return QIcon::fromTheme("user-desktop");
440  return QIcon::fromTheme("user-trash");
442  return QIcon::fromTheme("computer");
444  return QIcon::fromTheme("media-floppy");
446  return QIcon::fromTheme("drive-harddisk");
449  return QIcon::fromTheme("drive-optical");
451  return QIcon::fromTheme("folder-remote");
453  return QIcon::fromTheme("user-home");
455  return QIcon::fromTheme("document-open-folder");
457  return QIcon::fromTheme("folder");
458  case QStyle::SP_DirIcon:
459  return QIcon::fromTheme("folder");
461  return QIcon::fromTheme("folder"); //TODO: generate (!?) folder with link emblem
462  case QStyle::SP_FileIcon:
463  return QIcon::fromTheme("text-plain"); //TODO: look for a better icon
465  return QIcon::fromTheme("text-plain"); //TODO: generate (!?) file with link emblem
467  return QIcon::fromTheme("media-playback-start"); //TODO: find correct icon
469  return QIcon::fromTheme("media-playback-stop"); //TODO: find correct icon
471  return QIcon::fromTheme("go-up");
473  return QIcon::fromTheme("folder-new");
475  return QIcon::fromTheme("view-list-details");
477  return QIcon::fromTheme("document-properties");
479  return QIcon::fromTheme("view-list-icons");
481  return QIcon::fromTheme("view-list-text");
483  return QIcon::fromTheme("go-previous");
485  return QIcon::fromTheme("dialog-information");
487  return QIcon::fromTheme("dialog-warning");
489  return QIcon::fromTheme("dialog-error");
491  return QIcon::fromTheme("dialog-information");
493  return QIcon::fromTheme("dialog-ok");
495  return QIcon::fromTheme("dialog-cancel");
497  return QIcon::fromTheme("help-contents");
499  return QIcon::fromTheme("document-open");
501  return QIcon::fromTheme("document-save");
503  return QIcon::fromTheme("dialog-close");
505  return QIcon::fromTheme("dialog-ok-apply");
507  return QIcon::fromTheme("document-revert");
509  return QIcon::fromTheme("dialog-cancel");
511  return QIcon::fromTheme("dialog-ok-apply");
513  return QIcon::fromTheme("dialog-cancel");
514  case QStyle::SP_ArrowUp:
515  return QIcon::fromTheme("go-up");
517  return QIcon::fromTheme("go-down");
519  return QIcon::fromTheme("go-previous-view");
521  return QIcon::fromTheme("go-next-view");
523  return QIcon::fromTheme("go-previous");
525  return QIcon::fromTheme("go-next");
527  return QIcon::fromTheme("view-refresh");
529  return QIcon::fromTheme("process-stop");
531  return QIcon::fromTheme("media-playback-start");
533  return QIcon::fromTheme("media-playback-stop");
535  return QIcon::fromTheme("media-playback-pause");
537  return QIcon::fromTheme("media-skip-forward");
539  return QIcon::fromTheme("media-skip-backward");
541  return QIcon::fromTheme("media-seek-forward");
543  return QIcon::fromTheme("media-seek-backward");
545  return QIcon::fromTheme("audio-volume-medium");
547  return QIcon::fromTheme("audio-volume-muted");
548 
549  default:
550  return QIcon();
551  }
552 }
553 
554 QPixmap K4Style::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
555  const QWidget *widget) const
556 {
557  return QCommonStyle::standardPixmap(standardPixmap, opt, widget);
558 }
559 QPixmap K4Style::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
560  const QStyleOption *opt) const
561 {
562  return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt);
563 }
564 
565 void K4Style::drawInsideRect(QPainter *p, const QRect &r) const
566 {
567  p->drawRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
568 }
569 
570 QRect K4Style::centerRect(const QRect &in, int w, int h) const
571 {
572  return QRect(in.x() + (in.width() - w) / 2, in.y() + (in.height() - h) / 2, w, h);
573 }
574 
575 QRect K4Style::centerRect(const QRect &in, const QSize &size) const
576 {
577  return centerRect(in, size.width(), size.height());
578 }
579 
580 void K4Style::drawKStylePrimitive(WidgetType widgetType, int primitive,
581  const QStyleOption *opt,
582  const QRect &r, const QPalette &pal,
583  State flags, QPainter *p,
584  const QWidget *widget,
585  K4Style::Option *kOpt) const
586 {
587  switch (widgetType) {
588  case WT_Tree: {
589  switch (primitive) {
590  case Tree::VerticalBranch:
591  case Tree::HorizontalBranch:
592  //### FIXME: set sane color.
594  return;
595  case Tree::ExpanderOpen:
596  case Tree::ExpanderClosed: {
597  p->setPen(pal.text().color());
598  drawInsideRect(p, r); //the border.
599  int signLineSize = r.width() / 4;
600  p->drawLine(r.center().x() - signLineSize, r.center().y(),
601  r.center().x() + signLineSize, r.center().y()); //-
602  if (primitive == Tree::ExpanderClosed) //vertical line of +
603  p->drawLine(r.center().x(), r.center().y() - signLineSize,
604  r.center().x(), r.center().y() + signLineSize);
605  return;
606  }
607  default:
608  break;
609  }
610 
611  break;
612  }
613 
614  case WT_SpinBox: {
615  switch (primitive) {
616  case SpinBox::PlusSymbol:
617  case SpinBox::MinusSymbol: {
618  p->setPen(pal.buttonText().color());
619 
620  int l = qMin(r.width() - 2, r.height() - 2);
621  QPoint c = r.center();
622 
623  p->drawLine(c.x() - l / 2, c.y(), c.x() + l / 2, c.y());
624  if (primitive == SpinBox::PlusSymbol) {
625  p->drawLine(c.x(), c.y() - l / 2, c.x(), c.y() + l / 2);
626  }
627 
628  return;
629  }
630  default:
631  break;
632  }
633 
634  break;
635  }
636 
637  case WT_GroupBox: {
638  if (primitive == GroupBox::FlatFrame) {
639  QPen oldPen = p->pen();
641  p->drawLine(r.topLeft(), r.topRight());
642  p->setPen(oldPen);
643  }
644 
645  break;
646  }
647 
648  case WT_ToolBoxTab: {
649  if (primitive == ToolBoxTab::Panel) {
650  drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, flags, p, widget);
651  }
652 
653  break;
654  }
655 
656  case WT_DockWidget: {
657  switch (primitive) {
658  case DockWidget::TitlePanel:
659  p->fillRect(r, pal.color(QPalette::Highlight));
660  return;
661 
662  case DockWidget::SeparatorHandle:
663  return;
664 
665  default:
666  break;
667  }
668 
669  break;
670  }
671 
672  case WT_Window: {
673  switch (primitive) {
674  case Window::TitlePanel:
675  p->fillRect(r, pal.color(QPalette::Highlight));
676  return;
677 
678  case Window::ButtonMenu: {
679  K4Style::TitleButtonOption *tbkOpts =
680  extractOption<K4Style::TitleButtonOption *>(kOpt);
681  if (!tbkOpts->icon.isNull()) {
682  tbkOpts->icon.paint(p, r);
683  } else {
684  QStyleOption tool(0);
685  tool.palette = pal;
686  // TODO: give it a nice KDE logo.
687  QPixmap pm = standardPixmap(SP_TitleBarMenuButton, &tool, widget);
688  tool.rect = r;
689  p->save();
690  drawItemPixmap(p, r, Qt::AlignCenter, pm);
691  p->restore();
692  }
693  return;
694  }
695 
696  case Window::ButtonMin:
697  case Window::ButtonMax:
698  case Window::ButtonRestore:
699  case Window::ButtonClose:
700  case Window::ButtonShade:
701  case Window::ButtonUnshade:
702  case Window::ButtonHelp: {
703  K4Style::TitleButtonOption *tbkOpts =
704  extractOption<K4Style::TitleButtonOption *>(kOpt);
705  State bflags = flags;
706  bflags &= ~State_Sunken;
707  if (tbkOpts->active) {
708  bflags |= State_Sunken;
709  }
710  drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, bflags, p, widget);
711  return;
712  }
713  }
714 
715  break;
716  }
717 
718  case WT_TabBar: {
719  // For vertical text fallback, provide the generic text implementation
720  // a transformed rotated painter, with rect swizzled appropriately
721  if (primitive == TabBar::EastText || primitive == TabBar::WestText) {
722  QTransform tr;
723 
724  if (primitive == TabBar::WestText) {
725  tr.translate(r.x(), r.height() + r.y());
726  tr.rotate(-90);
727  } else {
728  tr.translate(r.width() + r.x(), r.y());
729  tr.rotate(90);
730  }
731 
732  p->save();
733  p->setTransform(tr, true);
734  drawKStylePrimitive(WT_TabBar, Generic::Text, opt,
735  QRect(0, 0, r.height(), r.width()), pal, flags, p, widget, kOpt);
736  p->restore();
737  }
738  break;
739  }
740 
741  default:
742  break;
743  }
744 
745  if (primitive == Generic::Text) {
746  K4Style::TextOption *textOpts = extractOption<K4Style::TextOption *>(kOpt);
747 
748  //### debug
749  //p->setPen(Qt::green);
750  //drawInsideRect(p, r);
751 
752  QColor col = textOpts->color.color(pal);
753  QPen old = p->pen();
754  p->setPen(col);
755  drawItemText(p, r, Qt::AlignVCenter | Qt::TextShowMnemonic | textOpts->hAlign, pal, flags & State_Enabled,
756  textOpts->text);
757  p->setPen(old);
758  } else if (primitive == Generic::Icon) {
759  K4Style::IconOption *iconOpts = extractOption<K4Style::IconOption *>(kOpt);
760  QIcon::Mode mode;
761  QIcon::State iconState;
762 
763  // Select the correct icon from the iconset
764  if (flags & State_Enabled)
765  if (iconOpts->active) {
766  mode = QIcon::Active;
767  } else {
768  mode = QIcon::Normal;
769  }
770  else {
771  mode = QIcon::Disabled;
772  }
773 
774  if ((flags & State_On) || (flags & State_Sunken)) {
775  iconState = QIcon::On;
776  } else {
777  iconState = QIcon::Off;
778  }
779 
780  QSize size = iconOpts->size;
781  if (!size.isValid()) {
782  size = QSize(pixelMetric(PM_SmallIconSize), pixelMetric(PM_SmallIconSize));
783  }
784  QPixmap icon = iconOpts->icon.pixmap(size, mode, iconState);
785  p->drawPixmap(centerRect(r, icon.size()), icon);
786  } else if (primitive == Generic::FocusIndicator) {
787  QPen pen;
788  pen.setWidth(0);
789  pen.setStyle(Qt::DotLine);
790  p->setPen(pen);
791  drawInsideRect(p, r);
792  } else if (primitive >= Generic::ArrowUp && primitive <= Generic::ArrowLeft) {
793  //### FIXME: Helper for these sorts of things, as Keramik has virtually
794  //identical code!
795  K4Style::ColorOption *colorOpt = extractOption<K4Style::ColorOption *>(kOpt);
796  QColor arrowColor = colorOpt->color.color(pal);
797 
798  QPolygon poly;
799 
800  switch (primitive) {
801  case Generic::ArrowUp:
802  poly.setPoints(QCOORDARRLEN(u_arrow), u_arrow);
803  break;
804 
805  case Generic::ArrowDown:
806  poly.setPoints(QCOORDARRLEN(d_arrow), d_arrow);
807  break;
808 
809  case Generic::ArrowLeft:
810  poly.setPoints(QCOORDARRLEN(l_arrow), l_arrow);
811  break;
812 
813  default:
814  poly.setPoints(QCOORDARRLEN(r_arrow), r_arrow);
815  }
816 
817  if (flags & State_Enabled) {
818  //CHECKME: Why is the -1 needed?
819  poly.translate(r.x() + r.width() / 2 - 1, r.y() + r.height() / 2);
820 
821  p->setPen(arrowColor);
822  p->drawPolygon(poly);
823  } else {
824  //Disabled ones ignore color parameter
825  poly.translate(r.x() + r.width() / 2, r.y() + r.height() / 2 + 1);
826  p->setPen(pal.color(QPalette::Light));
827  p->drawPolygon(poly);
828  poly.translate(-1, -1);
829  p->setPen(pal.mid().color());
830  p->drawPolygon(poly);
831  }
832 
833  }
834 #if 0 //Reenable if you need a debug aid
835  else {
836  p->setPen(Qt::red);
837  drawInsideRect(p, r);
838  }
839 #endif
840 }
841 
842 void K4Style::setWidgetLayoutProp(WidgetType widget, int metric, int value)
843 {
844  if (metrics.size() <= widget) {
845  metrics.resize(widget + 1);
846  }
847 
848  QVector<int> &widgetMetrics = metrics[widget];
849  if (widgetMetrics.size() <= metric) {
850  widgetMetrics.resize(metric + 1);
851  }
852 
853  widgetMetrics[metric] = value;
854 }
855 
856 int K4Style::widgetLayoutProp(WidgetType widget, int metric,
857  const QStyleOption *opt,
858  const QWidget *w) const
859 {
860  Q_UNUSED(opt)
861  Q_UNUSED(w)
862 
863  if (metrics.size() <= widget) {
864  return 0;
865  }
866 
867  const QVector<int> &widgetMetrics = metrics[widget];
868  if (widgetMetrics.size() <= metric) {
869  return 0;
870  }
871 
872  return widgetMetrics[metric];
873 }
874 
875 QSize K4Style::expandDim(const QSize &orig, WidgetType wt, int baseMarginMetric,
876  const QStyleOption *opt, const QWidget *w, bool rotated) const
877 {
878  int addWidth = 2 * widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) +
879  widgetLayoutProp(wt, baseMarginMetric + Left, opt, w) +
880  widgetLayoutProp(wt, baseMarginMetric + Right, opt, w);
881 
882  int addHeight = 2 * widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) +
883  widgetLayoutProp(wt, baseMarginMetric + Top, opt, w) +
884  widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w);
885 
886  return QSize(orig.width() + (rotated ? addHeight : addWidth),
887  orig.height() + (rotated ? addWidth : addHeight));
888 }
889 
890 QRect K4Style::insideMargin(const QRect &orig, WidgetType wt,
891  int baseMarginMetric,
892  const QStyleOption *opt, const QWidget *w) const
893 {
894  int x1 = orig.topLeft().x();
895  int y1 = orig.topLeft().y();
896  int x2 = orig.bottomRight().x();
897  int y2 = orig.bottomRight().y();
898 
899  x1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
900  x1 += widgetLayoutProp(wt, baseMarginMetric + Left, opt, w);
901 
902  y1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
903  y1 += widgetLayoutProp(wt, baseMarginMetric + Top, opt, w);
904 
905  x2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
906  x2 -= widgetLayoutProp(wt, baseMarginMetric + Right, opt, w);
907 
908  y2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
909  y2 -= widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w);
910 
911  return QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
912 }
913 
914 QRect K4Style::handleRTL(const QStyleOption *opt, const QRect &subRect) const
915 {
916  return visualRect(opt->direction, opt->rect, subRect);
917 }
918 
919 QPoint K4Style::handleRTL(const QStyleOption *opt, const QPoint &pos) const
920 {
921  return visualPos(opt->direction, opt->rect, pos);
922 }
923 
924 void K4Style::drawPrimitive(PrimitiveElement elem, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
925 {
926  //Extract the stuff we need out of the option
927  State flags = option->state;
928  QRect r = option->rect;
929  QPalette pal = option->palette;
930 
931  switch (elem) {
932  case PE_FrameFocusRect:
933  drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, option, r, pal, flags, painter, widget);
934  return;
935  case PE_IndicatorArrowUp:
936  drawKStylePrimitive(WT_Generic, Generic::ArrowUp, option, r, pal, flags, painter, widget);
937  return;
938  case PE_IndicatorArrowDown:
939  drawKStylePrimitive(WT_Generic, Generic::ArrowDown, option, r, pal, flags, painter, widget);
940  return;
941  case PE_IndicatorArrowLeft:
942  drawKStylePrimitive(WT_Generic, Generic::ArrowLeft, option, r, pal, flags, painter, widget);
943  return;
944  case PE_IndicatorArrowRight:
945  drawKStylePrimitive(WT_Generic, Generic::ArrowRight, option, r, pal, flags, painter, widget);
946  return;
947  case PE_IndicatorMenuCheckMark:
948  //### check flags
949  drawKStylePrimitive(WT_MenuItem, MenuItem::CheckOn, option, r, pal, flags, painter, widget);
950  return;
951  case PE_IndicatorCheckBox:
952  if (flags & State_NoChange) {
953  drawKStylePrimitive(WT_CheckBox, CheckBox::CheckTriState, option, r, pal, flags, painter, widget);
954  } else if (flags & State_On) {
955  drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOn, option, r, pal, flags, painter, widget);
956  } else {
957  drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOff, option, r, pal, flags, painter, widget);
958  }
959  return;
960  case PE_IndicatorRadioButton:
961  if (flags & State_On) {
962  drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOn, option, r, pal, flags, painter, widget);
963  } else {
964  drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOff, option, r, pal, flags, painter, widget);
965  }
966  return;
967  case PE_IndicatorBranch: {
968  int centerX = r.x() + r.width() / 2;
969  int centerY = r.y() + r.height() / 2;
970 
971  int expanderAdjust = 0;
972  //First, determine whether we need to draw an expander.
973  if (flags & State_Children) {
974  //How large should we make it?
975  int sizeLimit = qMin(qMin(r.width(), r.height()),
976  widgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, option, widget));
977  if ((sizeLimit & 1) == 0) {
978  --sizeLimit;
979  }
980 
981  expanderAdjust = sizeLimit / 2 + 1;
982 
983  QRect expanderRect = QRect(centerX - sizeLimit / 2, centerY - sizeLimit / 2,
984  sizeLimit, sizeLimit);
985 
986  drawKStylePrimitive(WT_Tree, flags & State_Open ? Tree::ExpanderOpen : Tree::ExpanderClosed,
987  option, expanderRect, pal, flags, painter, widget);
988  }
989 
990  //Now, draw the branches. The top line gets drawn unless we're completely
991  //w/o any indication of a neightbor
992  if (flags & (State_Item | State_Children | State_Sibling)) {
993  QRect topLine = QRect(QPoint(centerX, r.y()), QPoint(centerX, centerY - expanderAdjust));
994  drawKStylePrimitive(WT_Tree, Tree::VerticalBranch, option, topLine, pal, flags, painter, widget);
995  }
996 
997  //The right/left (depending on dir) line gets drawn if we have an item
998  if (flags & State_Item) {
999  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 
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);
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  }
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:
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:
2463 
2464  case SH_FormLayoutWrapPolicy:
2466 
2467  case SH_MessageBox_TextInteractionFlags:
2468  return true;
2469 
2470  case SH_DialogButtonBox_ButtonsHaveIcons: {
2471  // was KGlobalSettings::showIconsOnPushButtons() :
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:
2494  case PM_ToolBarIconSize:
2496  case PM_LargeIconSize:
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:
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:
2746  case QTabBar::RoundedSouth:
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:
2759  return East;
2760  case QTabBar::RoundedWest:
2762  return West;
2763  case QTabBar::RoundedNorth:
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:
2991  return pane.adjusted(left, top, -right, -bot);
2992  case QTabBar::RoundedEast:
2994  return pane.adjusted(bot, left, -top, -right);
2995  case QTabBar::RoundedSouth:
2997  return pane.adjusted(right, bot, -left, -top);
2998  case QTabBar::RoundedWest:
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:
3016  case QTabBar::RoundedSouth:
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:
3026  r.adjust(0, tov3.leftButtonSize.width(), 0, -tov3.rightButtonSize.width());
3027  break;
3028  case QTabBar::RoundedWest:
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) {
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 
4009  insideSize = QSize(10, widgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, option, widget));
4010  }
4011  break;
4012 
4013  //Double huh if we get those.
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:
4058  case QTabBar::RoundedWest:
4060  return contentsSize + QSize(hor, vert);
4061  case QTabBar::RoundedSouth:
4063  case QTabBar::RoundedEast:
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  }
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())) {
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(), nullptr, &p, lbl);
4154  }
4155  break;
4156 
4157  default:
4158  break;
4159  }
4160  }
4161  }
4162 
4163  return false;
4164 }
4165 
4167  mode(PaletteEntryMode),
4168  role(_role)
4169 {}
4170 
4172  mode(_mode),
4173  role(_role)
4174 {}
4175 
4176 K4Style::ColorMode::operator int() const
4177 {
4178  return int(role) | int(mode);
4179 }
4180 
4182 {
4183  mode = (encoded & BWAutoContrastMode) ? BWAutoContrastMode : PaletteEntryMode;
4184  role = QPalette::ColorRole(encoded & (~BWAutoContrastMode));
4185 }
4186 
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 
4213 {
4214  hAlign = Qt::AlignLeft; //NOTE: Check BIDI?
4215 }
4216 
bool active
whether the button is pressed
Definition: k4style.h:343
K4AboutData::LicenseKey key() const
Returns the license key.
void setTransform(const QTransform &transform, bool combine)
QString text() const
Returns the full license text.
QSize size() const const
bool isValid() const const
MouseButtonPress
void setHeight(int height)
void setStyle(Qt::PenStyle style)
QRect centerRect(const QRect &in, int w, int h) const
Returns a w x h QRect center inside the &#39;in&#39; rectangle.
Definition: k4style.cpp:570
QEvent::Type type() const const
QHash::iterator insert(const Key &key, const T &value)
int currentSize(KIconLoader::Group group) const
QPoint topRight() const const
StyleHint newStyleHint(const QString &element)
Runtime element extension, allows inheriting styles to add support custom elements merges supporting ...
Definition: k4style.cpp:316
int width() const const
const QBrush & text() const const
int width() const const
bool end()
Dense4Pattern
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setBottomRight(const QPoint &position)
QPixmap copy(int x, int y, int width, int height) const const
virtual void polish(QPalette &pal) override
void setRenderHint(QPainter::RenderHint hint, bool on)
Format_ARGB32_Premultiplied
void strokePath(const QPainterPath &path, const QPen &pen)
int right() const const
virtual QPixmap standardPixmap(QStyle::StandardPixmap sp, const QStyleOption *option, const QWidget *widget) const const override
virtual void drawKStylePrimitive(WidgetType widgetType, int primitive, const QStyleOption *opt, const QRect &r, const QPalette &pal, State flags, QPainter *p, const QWidget *widget=nullptr, Option *kOpt=nullptr) const
Draws primitives which are used inside K4Style.
Definition: k4style.cpp:580
virtual void unpolish(QWidget *widget) override
void setColorAt(qreal position, const QColor &color)
const QFont & font() const const
virtual void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const const override
QStyle * style() const const
virtual int widgetLayoutProp(WidgetType widgetType, int metric, const QStyleOption *opt=nullptr, const QWidget *w=nullptr) const
Used to obtain information about K4Style layout properties and metrics.
Definition: k4style.cpp:856
void setClipping(bool enable)
const QColor & color(QPalette::ColorGroup group, QPalette::ColorRole role) const const
int & rwidth()
void addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
QTextStream & right(QTextStream &stream)
QPoint bottomRight() const const
bool isNull() const const
void translate(int dx, int dy)
void save()
QPoint bottomLeft() const const
virtual const QMetaObject * metaObject() const const
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
void drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
int height() const const
int x() const const
int y() const const
virtual QRect itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const const
Base for our own option classes.
Definition: k4style.h:237
QString text
The text to draw.
Definition: k4style.h:363
ActiveButton
List of active button possibilities.
Definition: k4style.h:311
ShortcutFocusReason
void rotate(qreal angle)
void drawLine(const QLineF &line)
Option representing text drawing info. For Generic::Text.
Definition: k4style.h:361
Option for drawing double scrollbar buttons, indicating whether a button should be drawn active or no...
Definition: k4style.h:307
ColorMode(QPalette::ColorRole _role)
Constructor, using a the given palette role _role and a default mode.
Definition: k4style.cpp:4166
LeftToRight
QPalette::ColorRole foregroundRole() const const
void setBrushOrigin(int x, int y)
AlignCenter
int x() const const
int y() const const
virtual QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget) const const override
bool active
Is the icon active?
Definition: k4style.h:294
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) const const
int & rheight()
Mode
K4Style understands two kinds of colors:Palette entries.
Definition: k4style.h:201
QTextStream & left(QTextStream &stream)
const QColor & color() const const
static StyleHint customStyleHint(const QString &element, const QWidget *widget)
Runtime element extension This is just convenience and does /not/ require the using widgets style to ...
Definition: k4style.cpp:358
void drawRect(const QRectF &rectangle)
void setFont(const QFont &font)
QTransform & translate(qreal dx, qreal dy)
bool isEnabled() const const
virtual int pixelMetric(QStyle::PixelMetric m, const QStyleOption *opt, const QWidget *widget) const const override
void resize(int size)
void drawInsideRect(QPainter *p, const QRect &r) const
Draws inside the rectangle using a thinkness 0 pen.
Definition: k4style.cpp:565
void installEventFilter(QObject *filterObj)
void fill(uint pixelValue)
virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const const override
Option representing the color of the thing to draw.
Definition: k4style.h:281
int top() const const
QRgb rgb() const const
void setPen(const QColor &color)
void setFocus()
void setTop(int y)
int left() const const
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
void setWidth(int width)
void setWidth(int width)
virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const const =0
virtual QRect subElementRect(QStyle::SubElement sr, const QStyleOption *opt, const QWidget *widget) const const override
QTextStream & center(QTextStream &stream)
Qt::Alignment hAlign
The horizontal alignment, default is Qt::AlignLeft.
Definition: k4style.h:362
void setBrush(const QBrush &brush)
QPoint center() const const
virtual bool eventFilter(QObject *watched, QEvent *event)
virtual void drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const const
QPoint brushOrigin() const const
PrimitiveElement
int indexOfClassInfo(const char *name) const const
void init()
Called by the constructor to set the default value of hAlign.
Definition: k4style.cpp:4212
virtual QSize sizeFromContents(QStyle::ContentsType ct, const QStyleOption *opt, const QSize &csz, const QWidget *widget) const const override
void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment, QIcon::Mode mode, QIcon::State state) const const
static KIconLoader * global()
QIcon icon
window Icon
Definition: k4style.h:344
static QPalette createApplicationPalette(const KSharedConfigPtr &config)
bool isWindow() const const
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const const
const T value(const Key &key) const const
QColor color(const QPalette &palette)
Return the color corresponding to our role from the palette, automatically compensating for the contr...
Definition: k4style.cpp:4187
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
const QBrush & mid() const const
int height() const const
virtual void drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const const
QColor lighter(int factor) const const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
bool isValid() const const
QCA_EXPORT void init()
void restore()
A representation for colors for use as a widget layout property.
Definition: k4style.h:191
QTransform & rotate(qreal angle, Qt::Axis axis)
WA_Hover
QIcon icon
Icon drawn by this option.
Definition: k4style.h:295
void setRight(int x)
bool contains(const QRect &rectangle, bool proper) const const
int width() const const
void setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
void drawPath(const QPainterPath &path)
WidgetType
This enum is used to represent K4Style&#39;s concept of a widget, and to associate drawing requests and m...
Definition: k4style.h:392
const QBrush & buttonText() const const
void setWidth(int width)
void setX(int x)
void setRect(int x, int y, int width, int height)
bool isNull() const const
QFontMetrics fontMetrics() const const
void setHeight(int height)
void setWidgetLayoutProp(WidgetType widget, int metric, int value)
Interface for the style to configure various metrics that K4Style has customizable.
Definition: k4style.cpp:842
Option for drawing WT_Window titlebar buttons, indicating whether the button is pressed, and containing the window icon.
Definition: k4style.h:342
int height() const const
void translate(int dx, int dy)
TextShowMnemonic
void adjust(int dx1, int dy1, int dx2, int dy2)
int bottom() const const
QPoint topLeft() const const
void translate(const QPointF &offset)
virtual QStyle::SubControl hitTestComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget) const const override
void setAlphaF(qreal alpha)
Option for drawing icons: represents whether the icon should be active or not.
Definition: k4style.h:293
QIcon fromTheme(const QString &name)
QSize size(int flags, const QString &text, int tabStops, int *tabArray) const const
virtual QRect itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const const
Horizontal
virtual int styleHint(QStyle::StyleHint sh, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *hret) const const override
virtual void drawControl(QStyle::ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *widget) const const override
QPoint pos() const const
WindowMinimized
void setPoints(int nPoints, const int *points)
int size() const const
static QString defaultStyle()
Returns the default widget style.
Definition: k4style.cpp:331
const QPen & pen() const const
State
void setLeft(int x)
T readEntry(const QString &key, const T &aDefault) const
virtual void drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *widget) const const override
WindowSystemMenuHint
void getRect(int *x, int *y, int *width, int *height) const const
void removeEventFilter(QObject *obj)
ColorMode color
Color to use for the drawing.
Definition: k4style.h:283
QRgb rgba() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 7 2020 22:56:37 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.