void Style::drawSpinBox(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { ASSURE_OPTION(sb, SpinBox); OPT_ENABLED SAVE_PAINTER(Pen|Brush|Alias); QStyleOptionSpinBox copy = *sb; // this doesn't work (for the moment, i assume...) // isEnabled = isEnabled && !(option->state & State_ReadOnly); if (isEnabled) if (const QAbstractSpinBox *box = qobject_cast<const QAbstractSpinBox*>(widget)) { isEnabled = isEnabled && !box->isReadOnly(); if (!isEnabled) copy.state &= ~State_Enabled; } if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) drawLineEditFrame(©, painter, widget); if (!isEnabled) { RESTORE_PAINTER return; // why bother the user with elements he can't use... ;) }
void Style::drawTabWidget(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { ASSURE_OPTION(twf, TabWidgetFrame); SAVE_PAINTER(Pen); QStyleOptionTabBarBaseV2 tbb; if (widget) tbb.initFrom(widget); else tbb.QStyleOption::operator=(*twf); tbb.shape = twf->shape; tbb.rect = twf->rect; if HAVE_OPTION(twf2, TabWidgetFrameV2) { tbb.selectedTabRect = twf2->selectedTabRect; } #define SET_BASE_HEIGHT(_o_) \ baseHeight = twf->tabBarSize._o_(); \ if (!baseHeight) { \ RESTORE_PAINTER; return; \ } /* no base -> no tabbing -> no bottom border either. period.*/\ if (baseHeight < 0) \ baseHeight = pixelMetric( PM_TabBarBaseHeight, option, widget ) int baseHeight; painter->setPen(FRAME_PEN); switch (twf->shape) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: SET_BASE_HEIGHT(height); tbb.rect.setHeight(baseHeight); painter->drawLine(RECT.bottomLeft(), RECT.bottomRight()); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: SET_BASE_HEIGHT(height); tbb.rect.setTop(tbb.rect.bottom()-baseHeight); painter->drawLine(RECT.topLeft(), RECT.topRight()); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: SET_BASE_HEIGHT(width); tbb.rect.setLeft(tbb.rect.right()-baseHeight); painter->drawLine(RECT.topLeft(), RECT.bottomLeft()); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: SET_BASE_HEIGHT(width); tbb.rect.setWidth(baseHeight); painter->drawLine(RECT.topRight(), RECT.bottomRight()); break; } #undef SET_BASE_HEIGHT // the "frame" // the bar drawTabBar(&tbb, painter, widget); RESTORE_PAINTER }
void Style::drawSliderHandle(const QRect &handle, const QStyleOption *option, QPainter *painter, int step) const { OPT_FOCUS SAVE_PAINTER(Pen|Brush|Alias); painter->setPen(Qt::NoPen); painter->setRenderHint(QPainter::Antialiasing, true); painter->setBrush(FCOLOR(Window)); painter->drawEllipse(handle); const int dx = handle.width() / THERMOMETER_FACTOR; const int dy = handle.height() / THERMOMETER_FACTOR; const QColor t = hasFocus ? FCOLOR(Highlight) : FCOLOR(WindowText); QColor c = FX::blend(FCOLOR(Window), t,4,5); c = FX::blend(c, t, 6-step, step); painter->setBrush(c); painter->drawEllipse(handle.adjusted(dx,dy,-dx,-dy)); RESTORE_PAINTER }
void Style::drawDockTitle(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { ASSURE_OPTION(dock, DockWidget); SAVE_PAINTER(Pen|Brush|Alias|Font); const bool floating = widget && widget->isWindow(); QRect rect = RECT; if (!dock->title.isEmpty()) { OPT_ENABLED const int bo = 16 + F(6); bool verticalTitleBar = false; if HAVE_OPTION(dock2, DockWidgetV2) { verticalTitleBar = dock2->verticalTitleBar; } if (verticalTitleBar) { int y = rect.y() + rect.height(); rect.setRect(0, 0, rect.height(), rect.width()); QMatrix m; m.translate(0, y); m.rotate(-90); painter->setMatrix(m, true); rect.adjust(0, dock->closable ? bo : F(4), 0, dock->closable ? -bo : -F(4)); } else { rect.adjust(dock->closable ? bo : F(4), 0, dock->closable ? -bo : -F(4), 0); } // text const int itemtextopts = Qt::AlignCenter | Qt::TextSingleLine | Qt::TextHideMnemonic; QPalette::ColorRole bg = widget ? widget->backgroundRole() : QPalette::Window; QPalette::ColorRole fg = widget ? widget->foregroundRole() : QPalette::WindowText; setBold(painter, dock->title, rect.width()); if (floating && widget->isActiveWindow()) painter->setPen(COLOR(fg)); else painter->setPen(FX::blend(COLOR(bg), COLOR(fg), 2, 1+isEnabled)); drawItemText(painter, rect, itemtextopts, PAL, isEnabled, dock->title, QPalette::NoRole, &rect); if (option->direction == Qt::LeftToRight) rect.setRect(rect.x() - F(8), rect.y(), F(8), rect.height()); else rect.setRect(rect.right(), rect.y(), F(8), rect.height()); }
void Style::drawLineEditFrame(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { if (RECT.height() > qMax(32, F(4) + 2*painter->fontMetrics().height())) { // abuse for mass text, eg. by webkit drawFrame(option, painter, widget); return; } OPT_ENABLED OPT_FOCUS SAVE_PAINTER(Pen|Alias); QRectF r(RECT); r.adjust(F(1), F(1), -F(1), -F(1)); QRectF r2(r); r2.setWidth(r2.height()); r2.moveRight(r.right()); QPainterPath path; path.moveTo(r.x() + config.frame.roundness, r.bottom()); // + config.frame.roundness to match aligned fames path.lineTo(r2.bottomLeft()); path.arcTo(r2, -90, 180); path.lineTo(r.x() + 2*r.width()/3, r.y()); QColor c; bool goodBad = false; if (widget && widget->testAttribute(Qt::WA_SetPalette)) { int r,g,b; FCOLOR(Base).getRgb(&r,&g,&b); if (goodBad = (r > g+b && qAbs(g-b) < qMax(qMin(g,b)/10,1))) // that's red c = FX::blend(Qt::red, LEF_COLOR, 1, 16-15*hasFocus); else if (goodBad = (g > r+b && qAbs(r-b) < qMax(qMin(r,b)/10,1))) // that's green c = FX::blend(Qt::green, LEF_COLOR, 1, 16-15*hasFocus); if (goodBad) painter->setPen(QPen(c, F(2) & ~1)); } if (!goodBad) painter->setPen(hasFocus ? FOCUS_FRAME_PEN : FRAME_PEN); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawPath(path); RESTORE_PAINTER }
void Style::drawTabBar(const QStyleOption *option, QPainter *painter, const QWidget *widget) const { ASSURE_OPTION(tbb, TabBarBase); if (!config.invert.headers) { if (tbb->selectedTabRect.isEmpty()) return; // only paint tab shapes if HAVE_OPTION(tbb2, TabBarBaseV2) { if (tbb2->documentMode) { return; // useless and adds confliciting horizintal lines } } SAVE_PAINTER(Pen|Alias); painter->setRenderHint(QPainter::Antialiasing, false); painter->setPen(QPen(FRAME_COLOR, FRAME_STROKE_WIDTH)); switch (tbb->shape) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: painter->drawLine(RECT.x(), RECT.bottom(), tbb->selectedTabRect.x(), RECT.bottom()); painter->drawLine(tbb->selectedTabRect.right(), RECT.bottom(), RECT.right(), RECT.bottom()); break; case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: painter->drawLine(RECT.x(), RECT.top(), tbb->selectedTabRect.x(), RECT.top()); painter->drawLine(tbb->selectedTabRect.right(), RECT.top(), RECT.right(), RECT.top()); break; case QTabBar::RoundedEast: case QTabBar::TriangularEast: painter->drawLine(RECT.x(), RECT.y(), RECT.x(), tbb->selectedTabRect.y()); painter->drawLine(RECT.x(), tbb->selectedTabRect.bottom(), RECT.x(), RECT.bottom()); break; case QTabBar::RoundedWest: case QTabBar::TriangularWest: painter->drawLine(RECT.right(), RECT.y(), RECT.right(), tbb->selectedTabRect.y()); painter->drawLine(RECT.right(), tbb->selectedTabRect.bottom(), RECT.right(), RECT.bottom()); break; } RESTORE_PAINTER return; } QWidget *win = 0; if (widget) { if (widget->parentWidget() && qobject_cast<QTabWidget*>(widget->parentWidget())) { if (widget->parentWidget()->style() == this) { return; // otherwise it's a proxystyle like on konqueror / kdevelop... } } else if (qobject_cast<const QTabBar*>(widget) || (appType == KDevelop && widget->inherits("QLabel"))) { return; // usually we alter the paintevent by eventfiltering } win = widget->window(); } else { if (painter->device()->devType() == QInternal::Widget) widget = static_cast<QWidget*>(painter->device()); else { QPaintDevice *dev = QPainter::redirected(painter->device()); if (dev && dev->devType() == QInternal::Widget) widget = static_cast<QWidget*>(dev); } if ( widget ) win = widget->window(); } QRect winRect; if (win) { winRect = win->rect(); winRect.moveTopLeft(widget->mapFrom(win, winRect.topLeft())); } // else // winRect = tbb->tabBarRect; // we set this from the eventfilter QEvent::Paint SAVE_PAINTER(Pen|Brush|Alias); painter->setBrush(PAL.color(QPalette::Active, QPalette::WindowText)); painter->setPen(Qt::NoPen); // TODO: half rounded rect? if (RECT.x() == winRect.x() || RECT.y() == winRect.y() || RECT.right() == winRect.right() || RECT.bottom() == winRect.bottom()) { painter->setRenderHint(QPainter::Antialiasing, false); painter->drawRect(RECT); } else { painter->setRenderHint(QPainter::Antialiasing, true); const int rnd = qMin(config.frame.roundness, verticalTabs(tbb->shape) ? RECT.width()/2 : RECT.height()/2); painter->drawRoundedRect(RECT, rnd, rnd); } RESTORE_PAINTER }
void Style::drawSlider(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { ASSURE_OPTION(slider, Slider); SAVE_PAINTER(Pen|Brush|Alias); OPT_SUNKEN OPT_ENABLED OPT_HOVER OPT_FOCUS QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget); QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget); isEnabled = isEnabled && (slider->maximum > slider->minimum); hover = isEnabled && (appType == GTK || (hover && (slider->activeSubControls & SC_SliderHandle))); sunken = sunken && (slider->activeSubControls & SC_SliderHandle); int radius; // groove if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { painter->setPen(Qt::NoPen); painter->setRenderHint(QPainter::Antialiasing, true); // thermometer if (slider->minimum > -1 && slider->sliderPosition != slider->minimum) { painter->setBrush(THERMOMETER_COLOR); QRect thermometer = groove; if (slider->orientation == Qt::Horizontal) thermometer.adjust(0, thermometer.height()/THERMOMETER_FACTOR, 0, -thermometer.height()/THERMOMETER_FACTOR); else thermometer.adjust(thermometer.width()/THERMOMETER_FACTOR, 0, -thermometer.width()/THERMOMETER_FACTOR, 0); radius = qMin(thermometer.width(), thermometer.height())/2; const QPoint c = handle.center(); if ( slider->orientation == Qt::Horizontal ) { bool ltr = slider->direction == Qt::LeftToRight; if (slider->upsideDown) ltr = !ltr; if (ltr) { groove.setLeft(c.x()); thermometer.setRight(c.x()); } else { groove.setRight(c.x()); thermometer.setLeft(handle.left()); } } else { if (slider->upsideDown) { groove.setBottom(c.y()); thermometer.setTop(c.y()); } else { groove.setTop(c.y()); thermometer.setBottom(handle.bottom()); } } painter->drawRoundedRect(thermometer, radius, radius); } if (slider->sliderPosition != slider->maximum || slider->minimum < 0 ) { radius = qMin(groove.width(), groove.height())/2; painter->setBrush(GROOVE_COLOR); painter->drawRoundedRect(groove, radius, radius); } painter->setRenderHint(QPainter::Antialiasing, false); } // tickmarks - we paint a centered dotline, no stupid above/below/both nonsense if (isEnabled && (slider->subControls & SC_SliderTickmarks) && slider->tickPosition != QSlider::NoTicks) { int interval = slider->tickInterval; if (interval < 1) interval = slider->pageStep; if (interval > 0) { QPen oldPen = painter->pen(); const qreal pw = F(1); QPen pen(FCOLOR(Window), pw); interval = (slider->maximum - slider->minimum) / interval; const int s = (slider->orientation == Qt::Horizontal) ? RECT.width() - handle.width() : RECT.height() - handle.height(); qreal space = s/(pw*interval) - 1.0f; pen.setDashPattern(QVector<qreal>() << 1.0f << space); space /= 2.0f; pen.setDashOffset(space - 0.5f + handle.width()*0.5f); painter->setPen(pen); QPoint c = groove.center(); if (slider->orientation == Qt::Horizontal) painter->drawLine(RECT.x() + space, c.y(), RECT.right() - space, c.y()); else painter->drawLine(c.x(), RECT.y() + space, c.x(), RECT.bottom() - space); painter->setPen(oldPen); } } // handle ====================================== if (isEnabled && (slider->subControls & SC_SliderHandle)) { int step = 0; if (sunken) step = 6; else if (isEnabled) { const Animator::ComplexInfo *info = Animator::HoverComplex::info(widget, slider->activeSubControls & SC_SliderHandle); if (info && ( info->fades[Animator::In] & SC_SliderHandle || info->fades[Animator::Out] & SC_SliderHandle )) step = info->step(SC_SliderHandle); if (hover && !step) step = 6; } drawSliderHandle(handle, option, painter, step); } RESTORE_PAINTER }
void Style::drawDial(const QStyleOptionComplex *option, QPainter *painter, const QWidget *) const { ASSURE_OPTION(dial, Slider); OPT_ENABLED OPT_HOVER OPT_FOCUS SAVE_PAINTER(Pen|Brush|Alias|Font); QRect rect = RECT; if (rect.width() > rect.height()) { rect.setLeft(rect.x()+(rect.width()-rect.height())/2); rect.setWidth(rect.height()); } else { rect.setTop(rect.y()+(rect.height()-rect.width())/2); rect.setHeight(rect.width()); } int d = qMin(2*rect.width()/5, config.slider.thickness); int r = (rect.width()-d)/2; // angle calculation from qcommonstyle.cpp (c) Trolltech 1992-2007, ASA. float a; if (dial->maximum == dial->minimum) a = M_PI / 2; else if (dial->dialWrapping) a = M_PI * 3 / 2 - (dial->sliderValue - dial->minimum) * 2 * M_PI / (dial->maximum - dial->minimum); else a = (M_PI * 8 - (dial->sliderValue - dial->minimum) * 10 * M_PI / (dial->maximum - dial->minimum)) / 6; QPoint cp = rect.center() + QPoint(qRound(r * cos(a)), -qRound(r * sin(a))); // the huge ring ======================================= r = d/2+1; rect.adjust(r,r,-r,-r); painter->setBrush(Qt::NoBrush); painter->setRenderHint( QPainter::Antialiasing ); const int start = -(dial->dialWrapping ? 90 : 120)*16; const int span = -16*(dial->dialWrapping ? 360 : 300)*(dial->sliderValue - dial->minimum)/(dial->maximum - dial->minimum); QPen pen; if (dial->sliderValue != dial->maximum) { QPen pen(GROOVE_COLOR, d); pen.setCapStyle(Qt::RoundCap); painter->setPen(pen); painter->drawArc(rect, start + span, -((dial->dialWrapping ? 360 : 300)*16 + span)); } if (dial->sliderValue != dial->minimum) { QPen pen(THERMOMETER_COLOR, d - 2*(d/THERMOMETER_FACTOR)); pen.setCapStyle(Qt::RoundCap); painter->setPen(pen); painter->drawArc(rect, start, span); } // the value ============================================== QFont fnt = painter->font(); int h = rect.height()/2; h -= 2 * (h - qMin(h, painter->fontMetrics().xHeight())) / 3; fnt.setPixelSize( h ); painter->setFont(fnt); painter->setPen(FX::blend(PAL.background().color(), PAL.foreground().color(),!hasFocus,2)); drawItemText(painter, rect, Qt::AlignCenter, PAL, isEnabled, QString::number(dial->sliderValue)); // the drop =========================== if (isEnabled) { rect = QRect(0,0,d,d); rect.moveCenter(cp); drawSliderHandle(rect, option, painter, hover * 6); } RESTORE_PAINTER }
void Style::drawComboBox(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { ASSURE_OPTION(cmb, ComboBox); OPT_ENABLED OPT_HOVER OPT_FOCUS SAVE_PAINTER(Pen|Brush|Alias); if ( widget && widget->inherits("WebView") ) { // paints hardcoded black text bypassing the style?! grrr... const_cast<QStyleOptionComboBox*>(cmb)->palette.setColor(QPalette::Window, QColor(230,230,230,255)); widget = 0; } animStep = !widget ? MAX_STEPS*hover : Animator::Hover::step(widget); QRect ar; const QComboBox *combo = widget ? qobject_cast<const QComboBox*>(widget) : NULL; if ((cmb->subControls & SC_ComboBoxArrow) && (!combo || combo->count() > 0)) { // do we have an arrow? ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget); const int dx = (F(2) & ~1) / 2; ar.translate(cmb->direction == Qt::LeftToRight ? -dx : dx, 0); } const bool listShown = combo && combo->view() && ((QWidget*)(combo->view()))->isVisible(); if (listShown) { // this messes up hover hover = hover || QRect(widget->mapToGlobal(RECT.topLeft()), RECT.size()).contains(QCursor::pos()); // TODO Qt5, avoid asking for the cursor pos animStep = MAX_STEPS; } QColor c = hasFocus ? FCOLOR(Highlight) : (cmb->editable ? FCOLOR(Text) : FCOLOR(WindowText)); if (cmb->editable) { drawLineEditFrame(option, painter, widget); c = FX::blend(FCOLOR(Base), c, MAX_STEPS, 1 + 2*animStep); } else { const int icon = cmb->currentIcon.isNull() ? 0 : cmb->iconSize.width() + F(4); QFont fnt(painter->font()); fnt.setBold(true); int text = QFontMetrics(fnt).width(cmb->currentText); if (text) text += F(4); if (!(text+icon)) // webkit etc. text = ar.left() - (F(16) + RECT.x()); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(QPen(hasFocus ? FCOLOR(Highlight) : FX::blend(FCOLOR(Window), c, 4, 1), FRAME_STROKE)); painter->setBrush(Qt::NoBrush); const int y = ar.y() + ar.height()/2; const int da = animStep * 168 / MAX_STEPS; if (option->direction == Qt::LeftToRight) { DRAW_SEGMENT(ar, 16*(120 - da/2), 16*(192+da)); painter->drawLine(RECT.x() + icon + text + F(6), y, ar.left()-F(2), y); } else { DRAW_SEGMENT(ar, 16*(30 + da/2), -16*(192+da)); painter->drawLine(RECT.right() - (icon + text + F(6)), y, ar.right()+F(2), y); } c = FX::blend(FCOLOR(Window), FCOLOR(WindowText), MAX_STEPS - animStep, 1 + animStep); } if (!isEnabled) { RESTORE_PAINTER return; }