/**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmotifstyle.h" #include "qcdestyle.h" #if !defined(QT_NO_STYLE_MOTIF) || defined(QT_PLUGIN) #include "qmenu.h" #include "qapplication.h" #include "qpainter.h" #include "qdrawutil.h" #include "qpixmap.h" #include "qpalette.h" #include "qwidget.h" #include "qpushbutton.h" #include "qscrollbar.h" #include "qtabbar.h" #include "qtabwidget.h" #include "qlistview.h" #include "qsplitter.h" #include "qslider.h" #include "qcombobox.h" #include "qlineedit.h" #include "qprogressbar.h" #include "qimage.h" #include "qfocusframe.h" #include "qdebug.h" #include "qpainterpath.h" #include "qmotifstyle_p.h" #include "qdialogbuttonbox.h" #include "qformlayout.h" #include #include #include #ifdef Q_WS_X11 #include "qx11info_x11.h" #endif QT_BEGIN_NAMESPACE // old constants that might still be useful... static const int motifItemFrame = 2; // menu item frame width static const int motifSepHeight = 2; // separator item height static const int motifItemHMargin = 3; // menu item hor text margin static const int motifItemVMargin = 2; // menu item ver text margin static const int motifArrowHMargin = 6; // arrow horizontal margin static const int motifTabSpacing = 12; // space between text and tab static const int motifCheckMarkHMargin = 2; // horiz. margins of check mark static const int motifCheckMarkSpace = 16; /*! \class QMotifStyle \brief The QMotifStyle class provides Motif look and feel. \ingroup appearance This class implements the Motif look and feel. It closely resembles the original Motif look as defined by the Open Group, but with some minor improvements. The Motif style is Qt's default GUI style on Unix platforms. \img qmotifstyle.png \sa QWindowsXPStyle, QMacStyle, QWindowsStyle, QPlastiqueStyle, QCDEStyle */ /*! \variable QMotifStyle::focus \internal */ /*! Constructs a QMotifStyle. If \a useHighlightCols is false (the default), the style will polish the application's color palette to emulate the Motif way of highlighting, which is a simple inversion between the base and the text color. */ QMotifStyle::QMotifStyle(bool useHighlightCols) : QCommonStyle(*new QMotifStylePrivate) { focus = 0; highlightCols = useHighlightCols; } /*! \internal */ QMotifStyle::QMotifStyle(QMotifStylePrivate &dd, bool useHighlightColors) : QCommonStyle(dd) { focus = 0; highlightCols = useHighlightColors; } /*! \overload Destroys the style. */ QMotifStyle::~QMotifStyle() { delete focus; } /*! \internal Animate indeterminate progress bars only when visible */ bool QMotifStyle::eventFilter(QObject *o, QEvent *e) { #ifndef QT_NO_PROGRESSBAR Q_D(QMotifStyle); switch(e->type()) { case QEvent::StyleChange: case QEvent::Show: if (QProgressBar *bar = qobject_cast(o)) { d->bars << bar; if (d->bars.size() == 1) { Q_ASSERT(d->animationFps> 0); d->animateTimer = startTimer(1000 / d->animationFps); } } break; case QEvent::Destroy: case QEvent::Hide: // reinterpret_cast because there is no type info when getting // the destroy event. We know that it is a QProgressBar. if (QProgressBar *bar = reinterpret_cast(o)) { d->bars.removeAll(bar); if (d->bars.isEmpty() && d->animateTimer) { killTimer(d->animateTimer); d->animateTimer = 0; } } default: break; } #endif // QT_NO_PROGRESSBAR return QStyle::eventFilter(o, e); } /*! \internal */ QIcon QMotifStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const { return QCommonStyle::standardIconImplementation(standardIcon, opt, widget); } /*! \reimp */ void QMotifStyle::timerEvent(QTimerEvent *event) { #ifndef QT_NO_PROGRESSBAR Q_D(QMotifStyle); if (event->timerId() == d->animateTimer) { Q_ASSERT(d->animationFps > 0); d->animateStep = d->startTime.elapsed() / (1000 / d->animationFps); foreach (QProgressBar *bar, d->bars) { if ((bar->minimum() == 0 && bar->maximum() == 0)) bar->update(); } } #endif // QT_NO_PROGRESSBAR event->ignore(); } QMotifStylePrivate::QMotifStylePrivate() #ifndef QT_NO_PROGRESSBAR : animationFps(25), animateTimer(0), animateStep(0) #endif { } /*! If \a arg is false, the style will polish the application's color palette to emulate the Motif way of highlighting, which is a simple inversion between the base and the text color. The effect will show up the next time an application palette is set via QApplication::setPalette(). The current color palette of the application remains unchanged. \sa QStyle::polish() */ void QMotifStyle::setUseHighlightColors(bool arg) { highlightCols = arg; } /*! Returns true if the style treats the highlight colors of the palette in a Motif-like manner, which is a simple inversion between the base and the text color; otherwise returns false. The default is false. */ bool QMotifStyle::useHighlightColors() const { return highlightCols; } /*! \reimp */ void QMotifStyle::polish(QPalette& pal) { if (pal.brush(QPalette::Active, QPalette::Light) == pal.brush(QPalette::Active, QPalette::Base)) { QColor nlight = pal.color(QPalette::Active, QPalette::Light).darker(108); pal.setColor(QPalette::Active, QPalette::Light, nlight) ; pal.setColor(QPalette::Disabled, QPalette::Light, nlight) ; pal.setColor(QPalette::Inactive, QPalette::Light, nlight) ; } if (highlightCols) return; // force the ugly motif way of highlighting *sigh* pal.setColor(QPalette::Active, QPalette::Highlight, pal.color(QPalette::Active, QPalette::Text)); pal.setColor(QPalette::Active, QPalette::HighlightedText, pal.color(QPalette::Active, QPalette::Base)); pal.setColor(QPalette::Disabled, QPalette::Highlight, pal.color(QPalette::Disabled, QPalette::Text)); pal.setColor(QPalette::Disabled, QPalette::HighlightedText, pal.color(QPalette::Disabled, QPalette::Base)); pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Active, QPalette::Text)); pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Active, QPalette::Base)); } /*! \reimp \internal Keep QStyle::polish() visible. */ void QMotifStyle::polish(QWidget* widget) { QStyle::polish(widget); #ifndef QT_NO_PROGRESSBAR if (qobject_cast(widget)) widget->installEventFilter(this); #endif } /*! \reimp \internal Keep QStyle::polish() visible. */ void QMotifStyle::unpolish(QWidget* widget) { QCommonStyle::unpolish(widget); #ifndef QT_NO_PROGRESSBAR if (qobject_cast(widget)) { Q_D(QMotifStyle); widget->removeEventFilter(this); d->bars.removeAll(static_cast(widget)); } #endif } /*! \reimp \internal Keep QStyle::polish() visible. */ void QMotifStyle::polish(QApplication* a) { QCommonStyle::polish(a); } /*! \reimp \internal Keep QStyle::polish() visible. */ void QMotifStyle::unpolish(QApplication* a) { QCommonStyle::unpolish(a); } static void rot(QPolygon& a, int n) { QPolygon r(a.size()); for (int i = 0; i < (int)a.size(); i++) { switch (n) { case 1: r.setPoint(i,-a[i].y(),a[i].x()); break; case 2: r.setPoint(i,-a[i].x(),-a[i].y()); break; case 3: r.setPoint(i,a[i].y(),-a[i].x()); break; } } a = r; } /*! \reimp */ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const { switch(pe) { case PE_Q3CheckListExclusiveIndicator: if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { if (lv->items.isEmpty()) return; if (lv->state & State_Enabled) p->setPen(QPen(opt->palette.text().color())); else p->setPen(QPen(lv->palette.color(QPalette::Disabled, QPalette::Text))); QPolygon a; int cx = opt->rect.width()/2 - 1; int cy = opt->rect.height()/2; int e = opt->rect.width()/2 - 1; for (int i = 0; i < 3; i++) { //penWidth 2 doesn't quite work a.setPoints(4, cx-e, cy, cx, cy-e, cx+e, cy, cx, cy+e); p->drawPolygon(a); e--; } if (opt->state & State_On) { if (lv->state & State_Enabled) p->setPen(QPen(opt->palette.text().color())); else p->setPen(QPen(lv->palette.color(QPalette::Disabled, QPalette::Text))); QBrush saveBrush = p->brush(); p->setBrush(opt->palette.text()); e = e - 2; a.setPoints(4, cx-e, cy, cx, cy-e, cx+e, cy, cx, cy+e); p->drawPolygon(a); p->setBrush(saveBrush); } } break; case PE_FrameTabWidget: case PE_FrameWindow: qDrawShadePanel(p, opt->rect, opt->palette, QStyle::State_None, proxy()->pixelMetric(PM_DefaultFrameWidth)); break; case PE_FrameFocusRect: if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(opt)) { if ((fropt->state & State_HasFocus) && focus && focus->isVisible() && !(fropt->state & QStyle::State_Item)) break; QCommonStyle::drawPrimitive(pe, opt, p, w); } break; case PE_IndicatorToolBarHandle: { p->save(); p->translate(opt->rect.x(), opt->rect.y()); QColor dark(opt->palette.dark().color()); QColor light(opt->palette.light().color()); int i; if (opt->state & State_Horizontal) { int h = opt->rect.height(); if (h > 6) { if (opt->state & State_On) p->fillRect(1, 1, 8, h - 2, opt->palette.highlight()); QPolygon a(2 * ((h-6)/3)); int y = 3 + (h%3)/2; p->setPen(dark); p->drawLine(8, 1, 8, h-2); for (i=0; 2*i < a.size(); ++i) { a.setPoint(2*i, 5, y+1+3*i); a.setPoint(2*i+1, 2, y+2+3*i); } p->drawPoints(a); p->setPen(light); p->drawLine(9, 1, 9, h-2); for (i=0; 2*i < a.size(); i++) { a.setPoint(2*i, 4, y+3*i); a.setPoint(2*i+1, 1, y+1+3*i); } p->drawPoints(a); // if (drawBorder) { // p->setPen(QPen(Qt::darkGray)); // p->drawLine(0, opt->rect.height() - 1, // tbExtent, opt->rect.height() - 1); // } } } else { int w = opt->rect.width(); if (w > 6) { if (opt->state & State_On) p->fillRect(1, 1, w - 2, 9, opt->palette.highlight()); QPolygon a(2 * ((w-6)/3)); int x = 3 + (w%3)/2; p->setPen(dark); p->drawLine(1, 8, w-2, 8); for (i=0; 2*i < a.size(); ++i) { a.setPoint(2*i, x+1+3*i, 6); a.setPoint(2*i+1, x+2+3*i, 3); } p->drawPoints(a); p->setPen(light); p->drawLine(1, 9, w-2, 9); for (i=0; 2*i < a.size(); ++i) { a.setPoint(2*i, x+3*i, 5); a.setPoint(2*i+1, x+1+3*i, 2); } p->drawPoints(a); // if (drawBorder) { // p->setPen(QPen(Qt::darkGray)); // p->drawLine(opt->rect.width() - 1, 0, // opt->rect.width() - 1, tbExtent); // } } } p->restore(); break; } case PE_PanelButtonCommand: case PE_PanelButtonBevel: case PE_PanelButtonTool: { QBrush fill; if (opt->state & State_Sunken) fill = opt->palette.brush(QPalette::Mid); else if ((opt->state & State_On) && (opt->state & State_Enabled)) fill = QBrush(opt->palette.mid().color(), Qt::Dense4Pattern); else fill = opt->palette.brush(QPalette::Button); if ((opt->state & State_Enabled || opt->state & State_On) || !(opt->state & State_AutoRaise)) qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken | State_On)), proxy()->pixelMetric(PM_DefaultFrameWidth), &fill); break; } case PE_IndicatorCheckBox: { bool on = opt->state & State_On; bool down = opt->state & State_Sunken; bool showUp = !(down ^ on); QBrush fill = opt->palette.brush((showUp || opt->state & State_NoChange) ?QPalette::Button : QPalette::Mid); if (opt->state & State_NoChange) { qDrawPlainRect(p, opt->rect, opt->palette.text().color(), 1, &fill); p->drawLine(opt->rect.x() + opt->rect.width() - 1, opt->rect.y(), opt->rect.x(), opt->rect.y() + opt->rect.height() - 1); } else { qDrawShadePanel(p, opt->rect, opt->palette, !showUp, proxy()->pixelMetric(PM_DefaultFrameWidth), &fill); } if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); break; } case PE_IndicatorRadioButton: { #define INTARRLEN(x) sizeof(x)/(sizeof(int)*2) int inner_pts[] = { // used for filling diamond 2,opt->rect.height()/2, opt->rect.width()/2,2, opt->rect.width()-3,opt->rect.height()/2, opt->rect.width()/2,opt->rect.height()-3 }; int top_pts[] = { // top (^) of diamond 0,opt->rect.height()/2, opt->rect.width()/2,0, opt->rect.width()-2,opt->rect.height()/2-1, opt->rect.width()-3,opt->rect.height()/2-1, opt->rect.width()/2,1, 1,opt->rect.height()/2, 2,opt->rect.height()/2, opt->rect.width()/2,2, opt->rect.width()-4,opt->rect.height()/2-1 }; int bottom_pts[] = { // bottom (v) of diamond 1,opt->rect.height()/2+1, opt->rect.width()/2,opt->rect.height()-1, opt->rect.width()-1,opt->rect.height()/2, opt->rect.width()-2,opt->rect.height()/2, opt->rect.width()/2,opt->rect.height()-2, 2,opt->rect.height()/2+1, 3,opt->rect.height()/2+1, opt->rect.width()/2,opt->rect.height()-3, opt->rect.width()-3,opt->rect.height()/2 }; bool on = opt->state & State_On; bool down = opt->state & State_Sunken; bool showUp = !(down ^ on); QPen oldPen = p->pen(); QBrush oldBrush = p->brush(); QPolygon a(INTARRLEN(inner_pts), inner_pts); p->setPen(Qt::NoPen); p->setBrush(opt->palette.brush(showUp ? QPalette::Button : QPalette::Mid)); a.translate(opt->rect.x(), opt->rect.y()); p->drawPolygon(a); p->setPen(showUp ? opt->palette.light().color() : opt->palette.dark().color()); p->setBrush(Qt::NoBrush); a.setPoints(INTARRLEN(top_pts), top_pts); a.translate(opt->rect.x(), opt->rect.y()); p->drawPolyline(a); p->setPen(showUp ? opt->palette.dark().color() : opt->palette.light().color()); a.setPoints(INTARRLEN(bottom_pts), bottom_pts); a.translate(opt->rect.x(), opt->rect.y()); p->drawPolyline(a); if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); p->setPen(oldPen); p->setBrush(oldBrush); break; } case PE_IndicatorSpinUp: case PE_IndicatorSpinPlus: case PE_IndicatorSpinDown: case PE_IndicatorSpinMinus: case PE_IndicatorArrowUp: case PE_IndicatorArrowDown: case PE_IndicatorArrowRight: case PE_IndicatorArrowLeft: { QRect rect = opt->rect; QPolygon bFill; QPolygon bTop; QPolygon bBot; QPolygon bLeft; if (pe == PE_IndicatorSpinPlus || pe == PE_IndicatorSpinUp) pe = PE_IndicatorArrowUp; else if (pe == PE_IndicatorSpinMinus || pe == PE_IndicatorSpinDown) pe = PE_IndicatorArrowDown; bool vertical = pe == PE_IndicatorArrowUp || pe == PE_IndicatorArrowDown; bool horizontal = !vertical; int dim = rect.width() < rect.height() ? rect.width() : rect.height(); int colspec = 0x0000; if (!(opt->state & State_Enabled)) dim -= 2; if(dim < 2) break; // adjust size and center (to fix rotation below) if (rect.width() > dim) { rect.setX(rect.x() + ((rect.width() - dim) / 2)); rect.setWidth(dim); } if (rect.height() > dim) { rect.setY(rect.y() + ((rect.height() - dim) / 2)); rect.setHeight(dim); } if (dim > 3) { if (pixelMetric(PM_DefaultFrameWidth) < 2) { // thin style bFill.resize( dim & 1 ? 3 : 4 ); bTop.resize( 2 ); bBot.resize( 2 ); bLeft.resize( 2 ); bLeft.putPoints( 0, 2, 0, 0, 0, dim-1 ); bTop.putPoints( 0, 2, 1, 0, dim-1, dim/2 ); bBot.putPoints( 0, 2, 1, dim-1, dim-1, dim/2 ); if ( dim > 6 ) { // dim>6: must fill interior bFill.putPoints( 0, 2, 0, dim-1, 0, 0 ); if ( dim & 1 ) // if size is an odd number bFill.setPoint( 2, dim - 1, dim / 2 ); else bFill.putPoints( 2, 2, dim-1, dim/2-1, dim-1, dim/2 ); } } else { if (dim > 6) bFill.resize(dim & 1 ? 3 : 4); bTop.resize((dim/2)*2); bBot.resize(dim & 1 ? dim + 1 : dim); bLeft.resize(dim > 4 ? 4 : 2); bLeft.putPoints(0, 2, 0,0, 0,dim-1); if (dim > 4) bLeft.putPoints(2, 2, 1,2, 1,dim-3); bTop.putPoints(0, 4, 1,0, 1,1, 2,1, 3,1); bBot.putPoints(0, 4, 1,dim-1, 1,dim-2, 2,dim-2, 3,dim-2); for(int i=0; i 6) { // dim>6: must fill interior bFill.putPoints(0, 2, 1,dim-3, 1,2); if (dim & 1) // if size is an odd number bFill.setPoint(2, dim - 3, dim / 2); else bFill.putPoints(2, 2, dim-4,dim/2-1, dim-4,dim/2); } } } else { if (dim == 3) { // 3x3 arrow pattern bLeft.setPoints(4, 0,0, 0,2, 1,1, 1,1); bTop .setPoints(2, 1,0, 1,0); bBot .setPoints(2, 1,2, 2,1); } else { // 2x2 arrow pattern bLeft.setPoints(2, 0,0, 0,1); bTop .setPoints(2, 1,0, 1,0); bBot .setPoints(2, 1,1, 1,1); } } // We use rot() and translate() as it is more efficient that // matrix transformations on the painter, and because it still // works with QT_NO_TRANSFORMATIONS defined. if (pe == PE_IndicatorArrowUp || pe == PE_IndicatorArrowLeft) { if (vertical) { rot(bFill,3); rot(bLeft,3); rot(bTop,3); rot(bBot,3); bFill.translate(0, rect.height() - 1); bLeft.translate(0, rect.height() - 1); bTop.translate(0, rect.height() - 1); bBot.translate(0, rect.height() - 1); } else { rot(bFill,2); rot(bLeft,2); rot(bTop,2); rot(bBot,2); bFill.translate(rect.width() - 1, rect.height() - 1); bLeft.translate(rect.width() - 1, rect.height() - 1); bTop.translate(rect.width() - 1, rect.height() - 1); bBot.translate(rect.width() - 1, rect.height() - 1); } if (opt->state & State_Sunken) colspec = horizontal ? 0x2334 : 0x2343; else colspec = horizontal ? 0x1443 : 0x1434; } else { if (vertical) { rot(bFill,1); rot(bLeft,1); rot(bTop,1); rot(bBot,1); bFill.translate(rect.width() - 1, 0); bLeft.translate(rect.width() - 1, 0); bTop.translate(rect.width() - 1, 0); bBot.translate(rect.width() - 1, 0); } if (opt->state & State_Sunken) colspec = horizontal ? 0x2443 : 0x2434; else colspec = horizontal ? 0x1334 : 0x1343; } bFill.translate(rect.x(), rect.y()); bLeft.translate(rect.x(), rect.y()); bTop.translate(rect.x(), rect.y()); bBot.translate(rect.x(), rect.y()); const QColor *cols[5]; if (opt->state & State_Enabled) { cols[0] = 0; cols[1] = &opt->palette.button().color(); cols[2] = &opt->palette.mid().color(); cols[3] = &opt->palette.light().color(); cols[4] = &opt->palette.dark().color(); } else { cols[0] = 0; cols[1] = &opt->palette.mid().color(); cols[2] = &opt->palette.mid().color(); cols[3] = &opt->palette.mid().color(); cols[4] = &opt->palette.mid().color(); } #define CMID *cols[(colspec>>12) & 0xf] #define CLEFT *cols[(colspec>>8) & 0xf] #define CTOP *cols[(colspec>>4) & 0xf] #define CBOT *cols[colspec & 0xf] QPen savePen = p->pen(); QBrush saveBrush = p->brush(); QPen pen(Qt::NoPen); QBrush brush = opt->palette.brush((opt->state & State_Enabled) ? QPalette::Button : QPalette::Mid); p->setPen(pen); p->setBrush(brush); p->drawPolygon(bFill); p->setBrush(Qt::NoBrush); p->setPen(CLEFT); p->drawPolyline(bLeft); p->setPen(CTOP); p->drawPolyline(bTop); p->setPen(CBOT); p->drawPolyline(bBot); p->setBrush(saveBrush); p->setPen(savePen); #undef CMID #undef CLEFT #undef CTOP #undef CBOT if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); break; } case PE_IndicatorDockWidgetResizeHandle: { const int motifOffset = 10; int sw = proxy()->pixelMetric(PM_SplitterWidth); if (opt->state & State_Horizontal) { int yPos = opt->rect.y() + opt->rect.height() / 2; int kPos = opt->rect.right() - motifOffset - sw; int kSize = sw - 2; qDrawShadeLine(p, opt->rect.left(), yPos, kPos, yPos, opt->palette); qDrawShadePanel(p, kPos, yPos - sw / 2 + 1, kSize, kSize, opt->palette, false, 1, &opt->palette.brush(QPalette::Button)); qDrawShadeLine(p, kPos + kSize - 1, yPos, opt->rect.right(), yPos, opt->palette); } else { int xPos = opt->rect.x() + opt->rect.width() / 2; int kPos = motifOffset; int kSize = sw - 2; qDrawShadeLine(p, xPos, opt->rect.top() + kPos + kSize - 1, xPos, opt->rect.bottom(), opt->palette); qDrawShadePanel(p, xPos - sw / 2 + 1, opt->rect.top() + kPos, kSize, kSize, opt->palette, false, 1, &opt->palette.brush(QPalette::Button)); qDrawShadeLine(p, xPos, opt->rect.top(), xPos, opt->rect.top() + kPos, opt->palette); } break; } case PE_IndicatorMenuCheckMark: { const int markW = 6; const int markH = 6; int posX = opt->rect.x() + (opt->rect.width() - markW) / 2 - 1; int posY = opt->rect.y() + (opt->rect.height() - markH) / 2; int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth); if (dfw < 2) { // Could do with some optimizing/caching... QPolygon a(7*2); int i, xx, yy; xx = posX; yy = 3 + posY; for (i=0; i<3; i++) { a.setPoint(2*i, xx, yy); a.setPoint(2*i+1, xx, yy+2); xx++; yy++; } yy -= 2; for (i=3; i<7; i++) { a.setPoint(2*i, xx, yy); a.setPoint(2*i+1, xx, yy+2); xx++; yy--; } if (! (opt->state & State_Enabled) && ! (opt->state & State_On)) { int pnt; p->setPen(opt->palette.highlightedText().color()); QPoint offset(1,1); for (pnt = 0; pnt < (int)a.size(); pnt++) a[pnt] += offset; p->drawPolyline(a); for (pnt = 0; pnt < (int)a.size(); pnt++) a[pnt] -= offset; } p->setPen(opt->palette.text().color()); p->drawPolyline(a); qDrawShadePanel(p, posX-2, posY-2, markW+4, markH+6, opt->palette, true, dfw); } else qDrawShadePanel(p, posX, posY, markW, markH, opt->palette, true, dfw, &opt->palette.brush(QPalette::Mid)); break; } case PE_IndicatorProgressChunk: { bool vertical = false; if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) vertical = (pb2->orientation == Qt::Vertical); if (!vertical) { p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height(), opt->palette.brush(QPalette::Highlight)); } else { p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height(), opt->palette.brush(QPalette::Highlight)); } } break; default: QCommonStyle::drawPrimitive(pe, opt, p, w); break; } } /*! \reimp */ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *widget) const { switch(element) { case CE_Splitter: { QStyleOption handleOpt = *opt; if (handleOpt.state & State_Horizontal) handleOpt.state &= ~State_Horizontal; else handleOpt.state |= State_Horizontal; proxy()->drawPrimitive(PE_IndicatorDockWidgetResizeHandle, &handleOpt, p, widget); break; } case CE_ScrollBarSubLine: case CE_ScrollBarAddLine:{ PrimitiveElement pe; if (element == CE_ScrollBarAddLine) pe = (opt->state & State_Horizontal) ? (opt->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft) : PE_IndicatorArrowDown; else pe = (opt->state & State_Horizontal) ? (opt->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight) : PE_IndicatorArrowUp; QStyleOption arrowOpt = *opt; arrowOpt.state |= State_Enabled; proxy()->drawPrimitive(pe, &arrowOpt, p, widget); if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) { int fw = proxy()->pixelMetric(PM_DefaultFrameWidth); p->fillRect(opt->rect.adjusted(fw, fw, -fw, -fw), QBrush(p->background().color(), Qt::Dense5Pattern)); } }break; case CE_ScrollBarSubPage: case CE_ScrollBarAddPage: p->fillRect(opt->rect, opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window)); break; case CE_ScrollBarSlider: { QStyleOption bevelOpt = *opt; bevelOpt.state |= State_Raised; bevelOpt.state &= ~(State_Sunken | State_On); p->save(); p->setBrushOrigin(bevelOpt.rect.topLeft()); proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget); p->restore(); if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); break; } case CE_RadioButton: case CE_CheckBox: if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { bool isRadio = (element == CE_RadioButton); QStyleOptionButton subopt = *btn; subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator : SE_CheckBoxIndicator, btn, widget); proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, &subopt, p, widget); subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents : SE_CheckBoxContents, btn, widget); proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget); if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) { QStyleOptionFocusRect fropt; fropt.QStyleOption::operator=(*btn); fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect : SE_CheckBoxFocusRect, btn, widget); proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); } } break; case CE_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { proxy()->drawControl(CE_PushButtonBevel, btn, p, widget); QStyleOptionButton subopt = *btn; subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget); if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) { QStyleOptionFocusRect fropt; fropt.QStyleOption::operator=(*btn); fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget); proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); } } break; case CE_PushButtonBevel: if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { int diw, x1, y1, x2, y2; p->setPen(opt->palette.foreground().color()); p->setBrush(QBrush(opt->palette.button().color(), Qt::NoBrush)); diw = proxy()->pixelMetric(PM_ButtonDefaultIndicator); opt->rect.getCoords(&x1, &y1, &x2, &y2); if (btn->features & (QStyleOptionButton::AutoDefaultButton|QStyleOptionButton::DefaultButton)) { x1 += diw; y1 += diw; x2 -= diw; y2 -= diw; } if (btn->features & QStyleOptionButton::DefaultButton) { if (diw == 0) { QPolygon a; a.setPoints(9, x1, y1, x2, y1, x2, y2, x1, y2, x1, y1+1, x2-1, y1+1, x2-1, y2-1, x1+1, y2-1, x1+1, y1+1); p->setPen(opt->palette.shadow().color()); p->drawPolygon(a); x1 += 2; y1 += 2; x2 -= 2; y2 -= 2; } else { qDrawShadePanel(p, opt->rect.adjusted(1, 1, -1, -1), opt->palette, true); } } if (!(btn->features & QStyleOptionButton::Flat) || (btn->state & (State_Sunken | State_On))) { QStyleOptionButton newOpt = *btn; newOpt.rect = QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); p->setBrushOrigin(p->brushOrigin()); proxy()->drawPrimitive(PE_PanelButtonCommand, &newOpt, p, widget); } if (btn->features & QStyleOptionButton::HasMenu) { int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget); QRect ir = btn->rect; QStyleOptionButton newBtn = *btn; newBtn.rect = QRect(ir.right() - mbi - 3, ir.y() + 4, mbi, ir.height() - 8); proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); } break; } #ifndef QT_NO_TABBAR case CE_TabBarTabShape: if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { const int default_frame = proxy()->pixelMetric(PM_DefaultFrameWidth, tab, widget); const int frame_offset = (default_frame > 1) ? 1 : 0; if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedEast || tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::RoundedWest) { p->save(); QRect tabRect = opt->rect; QColor tabLight = opt->palette.light().color(); QColor tabDark = opt->palette.dark().color(); p->fillRect(opt->rect.adjusted(default_frame, default_frame, -default_frame, -default_frame), tab->palette.background()); if(tab->shape == QTabBar::RoundedWest) { tabDark = opt->palette.light().color(); tabLight = opt->palette.dark().color(); tabRect = QRect(0, 0, tabRect.height(), tabRect.width()); p->translate(opt->rect.left(), opt->rect.bottom()); p->rotate(-90); } else if(tab->shape == QTabBar::RoundedSouth) { tabDark = opt->palette.light().color(); tabLight = opt->palette.dark().color(); tabRect = QRect(0, 0, tabRect.width(), tabRect.height()); p->translate(opt->rect.right(), opt->rect.bottom()); p->rotate(180); } else if(tab->shape == QTabBar::RoundedEast) { tabRect = QRect(0, 0, tabRect.height(), tabRect.width()); p->translate(opt->rect.right(), opt->rect.top()); p->rotate(90); } if (default_frame > 1) { p->setPen(tabLight); p->drawLine(tabRect.left(), tabRect.bottom(), tabRect.right(), tabRect.bottom()); p->setPen(tabLight); p->drawLine(tabRect.left(), tabRect.bottom()-1, tabRect.right(), tabRect.bottom()-1); if (tabRect.left() == 0) p->drawPoint(tabRect.bottomLeft()); } else { p->setPen(tabLight); p->drawLine(tabRect.left(), tabRect.bottom(), tabRect.right(), tabRect.bottom()); } if (opt->state & State_Selected) { p->fillRect(QRect(tabRect.left()+1, tabRect.bottom()-frame_offset, tabRect.width()-3, 2), tab->palette.brush(QPalette::Active, QPalette::Background)); p->setPen(tab->palette.background().color()); p->drawLine(tabRect.left()+1, tabRect.bottom(), tabRect.left()+1, tabRect.top()+2); p->setPen(tabLight); } else { p->setPen(tabLight); } p->drawLine(tabRect.left(), tabRect.bottom()-1, tabRect.left(), tabRect.top() + 2); p->drawPoint(tabRect.left()+1, tabRect.top() + 1); p->drawLine(tabRect.left()+2, tabRect.top(), tabRect.right() - 2, tabRect.top()); p->drawPoint(tabRect.left(), tabRect.bottom()); if (default_frame > 1) { p->drawLine(tabRect.left()+1, tabRect.bottom(), tabRect.left()+1, tabRect.top() + 2); p->drawLine(tabRect.left()+2, tabRect.top()+1, tabRect.right() - 2, tabRect.top()+1); } p->setPen(tabDark); p->drawLine(tabRect.right() - 1, tabRect.top() + 2, tabRect.right() - 1, tabRect.bottom() - 1 + ((opt->state & State_Selected) ? frame_offset : -frame_offset)); if (default_frame > 1) { p->drawPoint(tabRect.right() - 1, tabRect.top() + 1); p->drawLine(tabRect.right(), tabRect.top() + 2, tabRect.right(), tabRect.bottom() - ((opt->state & State_Selected) ? ((tab->position == QStyleOptionTab::End) ? 0:1):1+frame_offset)); p->drawPoint(tabRect.right() - 1, tabRect.top() + 1); } p->restore(); } else { QCommonStyle::drawControl(element, opt, p, widget); } break; } #endif // QT_NO_TABBAR case CE_ProgressBarGroove: qDrawShadePanel(p, opt->rect, opt->palette, true, 2); break; case CE_ProgressBarLabel: if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { QTransform oldMatrix = p->transform(); QRect rect = pb->rect; bool vertical = false; bool invert = false; bool bottomToTop = false; if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) { vertical = (pb2->orientation == Qt::Vertical); invert = pb2->invertedAppearance; bottomToTop = pb2->bottomToTop; } if (vertical) { QTransform m; rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height if (bottomToTop) { m.translate(0.0, rect.width()); m.rotate(-90); } else { m.translate(rect.height(), 0.0); m.rotate(90); } p->setTransform(m, true); } const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, widget); int u = rect.width() / unit_width; int p_v = pb->progress - pb->minimum; int t_s = qMax(0, pb->maximum - pb->minimum); if (u > 0 && pb->progress >= INT_MAX / u && t_s >= u) { // scale down to something usable. p_v /= u; t_s /= u; } if (pb->textVisible && t_s) { int nu = (u * p_v + t_s/2) / t_s; int x = unit_width * nu; QRect left(rect.x(), rect.y(), x, rect.height()); QRect right(rect.x() + x, rect.y(), rect.width() - x, rect.height()); Qt::LayoutDirection dir; dir = vertical ? (bottomToTop ? Qt::LeftToRight : Qt::RightToLeft) : pb->direction; if (invert) dir = (dir == Qt::LeftToRight) ? Qt::RightToLeft : Qt::LeftToRight; const QRect highlighted = visualRect(dir, rect, left); const QRect background = visualRect(dir, rect, right); p->setPen(opt->palette.highlightedText().color()); p->setClipRect(highlighted); p->drawText(rect, Qt::AlignCenter | Qt::TextSingleLine, pb->text); if (pb->progress != pb->maximum) { p->setClipRect(background); p->setPen(opt->palette.highlight().color()); p->drawText(rect, Qt::AlignCenter | Qt::TextSingleLine, pb->text); } } p->setTransform(oldMatrix, false); break; } case CE_MenuTearoff: { if(opt->state & State_Selected) { if(pixelMetric(PM_MenuPanelWidth, opt, widget) > 1) qDrawShadePanel(p, opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height(), opt->palette, false, motifItemFrame, &opt->palette.brush(QPalette::Button)); else qDrawShadePanel(p, opt->rect.x()+1, opt->rect.y()+1, opt->rect.width()-2, opt->rect.height()-2, opt->palette, true, 1, &opt->palette.brush(QPalette::Button)); } else { p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); } p->setPen(QPen(opt->palette.dark().color(), 1, Qt::DashLine)); p->drawLine(opt->rect.x()+2, opt->rect.y()+opt->rect.height()/2-1, opt->rect.x()+opt->rect.width()-4, opt->rect.y()+opt->rect.height()/2-1); p->setPen(QPen(opt->palette.light().color(), 1, Qt::DashLine)); p->drawLine(opt->rect.x()+2, opt->rect.y()+opt->rect.height()/2, opt->rect.x()+opt->rect.width()-4, opt->rect.y()+opt->rect.height()/2); break; } case CE_MenuItem: if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(opt)) { int maxpmw = menuitem->maxIconWidth; if(menuitem->menuHasCheckableItems) maxpmw = qMax(maxpmw, motifCheckMarkSpace); int x, y, w, h; opt->rect.getRect(&x, &y, &w, &h); if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { // draw separator int textWidth = 0; if (!menuitem->text.isEmpty()) { QFont oldFont = p->font(); p->setFont(menuitem->font); p->fillRect(x, y, w, h, opt->palette.brush(QPalette::Button)); proxy()->drawItemText(p, menuitem->rect.adjusted(10, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter, menuitem->palette, menuitem->state & State_Enabled, menuitem->text, QPalette::Text); textWidth = menuitem->fontMetrics.width(menuitem->text) + 10; y += menuitem->fontMetrics.height() / 2; p->setFont(oldFont); } p->setPen(opt->palette.dark().color()); p->drawLine(x, y, x + 5, y); p->drawLine(x + 5 + textWidth, y, x+w, y); p->setPen(opt->palette.light().color()); p->drawLine(x, y + 1, x + 5, y + 1); p->drawLine(x + 5 + textWidth, y + 1, x+w, y + 1); return; } int pw = motifItemFrame; if((opt->state & State_Selected) && (opt->state & State_Enabled)) { // active item frame if(pixelMetric(PM_MenuPanelWidth, opt) > 1) qDrawShadePanel(p, x, y, w, h, opt->palette, false, pw, &opt->palette.brush(QPalette::Button)); else qDrawShadePanel(p, x+1, y+1, w-2, h-2, opt->palette, true, 1, &opt->palette.brush(QPalette::Button)); } else { // incognito frame p->fillRect(x, y, w, h, opt->palette.brush(QPalette::Button)); } QRect vrect = visualRect(opt->direction, opt->rect, QRect(x+motifItemFrame, y+motifItemFrame, maxpmw, h-2*motifItemFrame)); int xvis = vrect.x(); if (menuitem->checked) { if(!menuitem->icon.isNull()) qDrawShadePanel(p, xvis, y+motifItemFrame, maxpmw, h-2*motifItemFrame, opt->palette, true, 1, &opt->palette.brush(QPalette::Midlight)); } else if (!(opt->state & State_Selected)) { p->fillRect(xvis, y+motifItemFrame, maxpmw, h-2*motifItemFrame, opt->palette.brush(QPalette::Button)); } if(!menuitem->icon.isNull()) { // draw icon QIcon::Mode mode = QIcon::Normal; // no disabled icons in Motif if ((opt->state & State_Selected) && !!(opt->state & State_Enabled)) mode = QIcon::Active; QPixmap pixmap; if (menuitem->checkType != QStyleOptionMenuItem::NotCheckable && menuitem->checked) pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On); else pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode); int pixw = pixmap.width(); int pixh = pixmap.height(); QRect pmr(0, 0, pixw, pixh); pmr.moveCenter(vrect.center()); p->setPen(opt->palette.text().color()); p->drawPixmap(pmr.topLeft(), pixmap); } else if (menuitem->checkType != QStyleOptionMenuItem::NotCheckable) { // just "checking"... int mh = h - 2*motifItemFrame; QStyleOptionButton newMenuItem; newMenuItem.state = menuitem->checked ? State_On : State_None; if (opt->state & State_Enabled) { newMenuItem.state |= State_Enabled; if (menuitem->state & State_Sunken) newMenuItem.state |= State_Sunken; } if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) { newMenuItem.rect.setRect(xvis + 2, y + motifItemFrame + mh / 4, 11, 11); proxy()->drawPrimitive(PE_IndicatorRadioButton, &newMenuItem, p, widget); } else { newMenuItem.rect.setRect(xvis + 5, y + motifItemFrame + mh / 4, 9, 9); proxy()->drawPrimitive(PE_IndicatorCheckBox, &newMenuItem, p, widget); } } p->setPen(opt->palette.buttonText().color()); QColor discol; if (!(opt->state & State_Enabled)) { discol = opt->palette.text().color(); p->setPen(discol); } int xm = motifItemFrame + maxpmw + motifItemHMargin; vrect = visualRect(opt->direction, opt->rect, QRect(x+xm, y+motifItemVMargin, w-xm-menuitem->tabWidth, h-2*motifItemVMargin)); xvis = vrect.x(); QString s = menuitem->text; if (!s.isNull()) { // draw text int t = s.indexOf(QLatin1Char('\t')); int m = motifItemVMargin; int text_flags = Qt::AlignVCenter|Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; text_flags |= Qt::AlignLeft; QFont oldFont = p->font(); p->setFont(menuitem->font); if (t >= 0) { // draw tab text QRect vr = visualRect(opt->direction, opt->rect, QRect(x+w-menuitem->tabWidth-motifItemHMargin-motifItemFrame, y+motifItemVMargin, menuitem->tabWidth, h-2*motifItemVMargin)); int xv = vr.x(); QRect tr(xv, y+m, menuitem->tabWidth, h-2*m); p->drawText(tr, text_flags, s.mid(t+1)); if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern)); s = s.left(t); } QRect tr(xvis, y+m, w - xm - menuitem->tabWidth + 1, h-2*m); p->drawText(tr, text_flags, s.left(t)); p->setFont(oldFont); if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern)); } if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { // draw sub menu arrow int dim = (h-2*motifItemFrame) / 2; QStyle::PrimitiveElement arrow = (opt->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight); QStyleOption arrowOpt = *opt; arrowOpt.rect = visualRect(opt->direction, opt->rect, QRect(x+w - motifArrowHMargin - motifItemFrame - dim, y+h/2-dim/2, dim, dim)); if ((opt->state & State_Selected)) arrowOpt.state = (State_Sunken | ((opt->state & State_Enabled) ? State_Enabled : State_None)); else arrowOpt.state = ((opt->state & State_Enabled) ? State_Enabled : State_None); proxy()->drawPrimitive(arrow, &arrowOpt, p, widget); } break; } case CE_MenuBarItem: if (opt->state & State_Selected) // active item qDrawShadePanel(p, opt->rect, opt->palette, false, motifItemFrame, &opt->palette.brush(QPalette::Button)); else // other item p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); QCommonStyle::drawControl(element, opt, p, widget); break; case CE_HeaderSection: p->save(); p->setBrushOrigin(opt->rect.topLeft()); qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken|State_On)), proxy()->pixelMetric(PM_DefaultFrameWidth), &opt->palette.brush((opt->state & State_Sunken) ? QPalette::Mid : QPalette::Button)); p->restore(); break; case CE_RubberBand: { QPixmap tiledPixmap(16, 16); QPainter pixmapPainter(&tiledPixmap); pixmapPainter.setPen(Qt::NoPen); pixmapPainter.setBrush(Qt::Dense4Pattern); pixmapPainter.setBackground(QBrush(opt->palette.base())); pixmapPainter.setBackgroundMode(Qt::OpaqueMode); pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height()); pixmapPainter.end(); // ### workaround for borked XRENDER tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage()); p->save(); QRect r = opt->rect; QStyleHintReturnMask mask; if (styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask)) p->setClipRegion(mask.region); p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap); p->restore(); } break; #ifndef QT_NO_PROGRESSBAR case CE_ProgressBarContents: if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { QRect rect = pb->rect; bool vertical = false; bool inverted = false; // Get extra style options if version 2 const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt); if (pb2) { vertical = (pb2->orientation == Qt::Vertical); inverted = pb2->invertedAppearance; } QTransform m; if (vertical) { rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height m.rotate(90); m.translate(0, -(rect.height() + rect.y()*2)); } QPalette pal2 = pb->palette; // Correct the highlight color if it is the same as the background if (pal2.highlight() == pal2.background()) pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active, QPalette::Highlight)); bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical); if (inverted) reverse = !reverse; int w = rect.width(); if (pb->minimum == 0 && pb->maximum == 0) { QRect progressBar; Q_D(const QMotifStyle); // draw busy indicator int x = (d->animateStep*8)% (w * 2); if (x > w) x = 2 * w - x; x = reverse ? rect.right() - x : x + rect.x(); p->setTransform(m, true); p->setPen(QPen(pal2.highlight().color(), 4)); p->drawLine(x, rect.y(), x, rect.height()); } else QCommonStyle::drawControl(element, opt, p, widget); } break; #endif // QT_NO_PROGRESSBAR default: QCommonStyle::drawControl(element, opt, p, widget); break; } } static int get_combo_extra_width(int h, int w, int *return_awh=0) { int awh, tmp; if (h < 8) { awh = 6; } else if (h < 14) { awh = h - 2; } else { awh = h/2; } tmp = (awh * 3) / 2; if (tmp > w / 2) { awh = w / 2 - 3; tmp = w / 2 + 3; } if (return_awh) *return_awh = awh; return tmp; } static void get_combo_parameters(const QRect &r, int &ew, int &awh, int &ax, int &ay, int &sh, int &dh, int &sy) { ew = get_combo_extra_width(r.height(), r.width(), &awh); sh = (awh+3)/4; if (sh < 3) sh = 3; dh = sh/2 + 1; ay = r.y() + (r.height()-awh-sh-dh)/2; if (ay < 0) { //panic mode ay = 0; sy = r.height(); } else { sy = ay+awh+dh; } ax = r.x() + r.width() - ew; ax += (ew-awh)/2; } /*! \reimp */ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const { switch (cc) { case CC_ToolButton: if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(opt)) { QRect button, menuarea; button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); State bflags = toolbutton->state & ~State_Sunken; if (bflags & State_AutoRaise) { if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { bflags &= ~State_Raised; } } State mflags = bflags; if (toolbutton->state & State_Sunken) { if (toolbutton->activeSubControls & SC_ToolButton) bflags |= State_Sunken; mflags |= State_Sunken; } QStyleOption tool(0); tool.palette = toolbutton->palette; if (toolbutton->subControls & SC_ToolButton) { if (bflags & (State_Sunken | State_On | State_Raised)) { tool.rect = button; tool.state = bflags; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); } } if ((toolbutton->state & State_HasFocus) && (!focus || !focus->isVisible())) { QStyleOptionFocusRect fr; fr.QStyleOption::operator=(*toolbutton); fr.rect = toolbutton->rect.adjusted(3, 3, -3, -3); proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); } QStyleOptionToolButton label = *toolbutton; label.state = bflags; int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); label.rect = button.adjusted(fw, fw, -fw, -fw); proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); if (toolbutton->subControls & SC_ToolButtonMenu) { tool.rect = menuarea; tool.state = mflags; if (mflags & (State_Sunken | State_On | State_Raised)) proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); QRect ir = toolbutton->rect; QStyleOptionToolButton newBtn = *toolbutton; newBtn.rect = QRect(ir.right() + 5 - mbi, ir.height() - mbi + 4, mbi - 6, mbi - 6); proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); } } break; #ifndef QT_NO_SPINBOX case CC_SpinBox: if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(opt)) { QStyleOptionSpinBox copy = *spinbox; PrimitiveElement pe; if (spinbox->frame && (spinbox->subControls & SC_SpinBoxFrame)) { QRect r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxFrame, widget); qDrawShadePanel(p, r, opt->palette, false, proxy()->pixelMetric(PM_SpinBoxFrameWidth)); int fw = proxy()->pixelMetric(QStyle::PM_DefaultFrameWidth); r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxEditField, widget).adjusted(-fw,-fw,fw,fw); QStyleOptionFrame lineOpt; lineOpt.QStyleOption::operator=(*opt); lineOpt.rect = r; lineOpt.lineWidth = fw; lineOpt.midLineWidth = 0; lineOpt.state |= QStyle::State_Sunken; proxy()->drawPrimitive(QStyle::PE_FrameLineEdit, &lineOpt, p, widget); } if (spinbox->subControls & SC_SpinBoxUp) { copy.subControls = SC_SpinBoxUp; QPalette pal2 = spinbox->palette; if (!(spinbox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) { pal2.setCurrentColorGroup(QPalette::Disabled); copy.state &= ~State_Enabled; } copy.palette = pal2; if (spinbox->activeSubControls == SC_SpinBoxUp && (spinbox->state & State_Sunken)) { copy.state |= State_On; copy.state |= State_Sunken; } else { copy.state |= State_Raised; copy.state &= ~State_Sunken; } pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus : PE_IndicatorSpinUp); copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxUp, widget); proxy()->drawPrimitive(pe, ©, p, widget); } if (spinbox->subControls & SC_SpinBoxDown) { copy.subControls = SC_SpinBoxDown; copy.state = spinbox->state; QPalette pal2 = spinbox->palette; if (!(spinbox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { pal2.setCurrentColorGroup(QPalette::Disabled); copy.state &= ~State_Enabled; } copy.palette = pal2; if (spinbox->activeSubControls == SC_SpinBoxDown && (spinbox->state & State_Sunken)) { copy.state |= State_On; copy.state |= State_Sunken; } else { copy.state |= State_Raised; copy.state &= ~State_Sunken; } pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus : PE_IndicatorSpinDown); copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxDown, widget); proxy()->drawPrimitive(pe, ©, p, widget); } } break; #endif // QT_NO_SPINBOX #ifndef QT_NO_SLIDER case CC_Slider: if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { QRect groove = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, widget), handle = proxy()->subControlRect(CC_Slider, opt, SC_SliderHandle, widget); if ((opt->subControls & SC_SliderGroove) && groove.isValid()) { qDrawShadePanel(p, groove, opt->palette, true, proxy()->pixelMetric(PM_DefaultFrameWidth), &opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window)); if ((opt->state & State_HasFocus) && (!focus || !focus->isVisible())) { QStyleOption focusOpt = *opt; focusOpt.rect = subElementRect(SE_SliderFocusRect, opt, widget); proxy()->drawPrimitive(PE_FrameFocusRect, &focusOpt, p, widget); } } if ((opt->subControls & SC_SliderHandle) && handle.isValid()) { QStyleOption bevelOpt = *opt; bevelOpt.state = (opt->state | State_Raised) & ~State_Sunken; bevelOpt.rect = handle; p->save(); p->setBrushOrigin(bevelOpt.rect.topLeft()); proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget); p->restore(); if (slider->orientation == Qt::Horizontal) { int mid = handle.x() + handle.width() / 2; qDrawShadeLine(p, mid, handle.y(), mid, handle.y() + handle.height() - 2, opt->palette, true, 1); } else { int mid = handle.y() + handle.height() / 2; qDrawShadeLine(p, handle.x(), mid, handle.x() + handle.width() - 2, mid, opt->palette, true, 1); } if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) p->fillRect(handle, QBrush(p->background().color(), Qt::Dense5Pattern)); } if (slider->subControls & SC_SliderTickmarks) { QStyleOptionSlider tmpSlider = *slider; tmpSlider.subControls = SC_SliderTickmarks; int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth); tmpSlider.rect.translate(frameWidth - 1, 0); QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget); } } break; #endif // QT_NO_SLIDER case CC_ComboBox: if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { if (opt->subControls & SC_ComboBoxArrow) { int awh, ax, ay, sh, sy, dh, ew; int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0; if (cb->frame) { QStyleOptionButton btn; btn.QStyleOption::operator=(*cb); btn.state |= QStyle::State_Raised; proxy()->drawPrimitive(PE_PanelButtonCommand, &btn, p, widget); } else { p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); } QRect tr = opt->rect; tr.adjust(fw, fw, -fw, -fw); get_combo_parameters(tr, ew, awh, ax, ay, sh, dh, sy); QRect ar = QStyle::visualRect(opt->direction, opt->rect, QRect(ax,ay,awh,awh)); QStyleOption arrowOpt = *opt; arrowOpt.rect = ar; arrowOpt.state |= State_Enabled; proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); // draws the shaded line under the arrow p->setPen(opt->palette.light().color()); p->drawLine(ar.x(), sy, ar.x()+awh-1, sy); p->drawLine(ar.x(), sy, ar.x(), sy+sh-1); p->setPen(opt->palette.dark().color()); p->drawLine(ar.x()+1, sy+sh-1, ar.x()+awh-1, sy+sh-1); p->drawLine(ar.x()+awh-1, sy+1, ar.x()+awh-1, sy+sh-1); if ((cb->state & State_HasFocus) && (!focus || !focus->isVisible())) { QStyleOptionFocusRect focus; focus.QStyleOption::operator=(*opt); focus.rect = subElementRect(SE_ComboBoxFocusRect, opt, widget); focus.backgroundColor = opt->palette.button().color(); proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget); } } if (opt->subControls & SC_ComboBoxEditField) { if (cb->editable) { QRect er = proxy()->subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, widget); er.adjust(-1, -1, 1, 1); qDrawShadePanel(p, er, opt->palette, true, 1, &opt->palette.brush(QPalette::Base)); } } p->setPen(opt->palette.buttonText().color()); } break; #ifndef QT_NO_SCROLLBAR case CC_ScrollBar: { if (opt->subControls & SC_ScrollBarGroove) qDrawShadePanel(p, opt->rect, opt->palette, true, proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget), &opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window)); if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { QStyleOptionSlider newScrollbar = *scrollbar; if (scrollbar->minimum == scrollbar->maximum) newScrollbar.state |= State_Enabled; // make sure that the slider is drawn. QCommonStyle::drawComplexControl(cc, &newScrollbar, p, widget); } break; } #endif case CC_Q3ListView: if (opt->subControls & (SC_Q3ListViewBranch | SC_Q3ListViewExpand)) { int i; if (opt->subControls & SC_Q3ListView) QCommonStyle::drawComplexControl(cc, opt, p, widget); if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { QStyleOptionQ3ListViewItem item = lv->items.at(0); int y = opt->rect.y(); int c; QPolygon dotlines; if ((opt->activeSubControls & SC_All) && (opt->subControls & SC_Q3ListViewExpand)) { c = 2; dotlines.resize(2); dotlines[0] = QPoint(opt->rect.right(), opt->rect.top()); dotlines[1] = QPoint(opt->rect.right(), opt->rect.bottom()); } else { int linetop = 0, linebot = 0; // each branch needs at most two lines, ie. four end points dotlines.resize(item.childCount * 4); c = 0; // skip the stuff above the exposed rectangle for (i = 1; i < lv->items.size(); ++i) { QStyleOptionQ3ListViewItem child = lv->items.at(i); if (child.height + y > 0) break; y += child.totalHeight; } int bx = opt->rect.width() / 2; // paint stuff in the magical area while (i < lv->items.size() && y < lv->rect.height()) { QStyleOptionQ3ListViewItem child = lv->items.at(i); if (child.features & QStyleOptionQ3ListViewItem::Visible) { int lh; if (!(item.features & QStyleOptionQ3ListViewItem::MultiLine)) lh = child.height; else lh = p->fontMetrics().height() + 2 * lv->itemMargin; lh = qMax(lh, QApplication::globalStrut().height()); if (lh % 2 > 0) lh++; linebot = y + lh/2; if ((child.features & QStyleOptionQ3ListViewItem::Expandable || child.childCount > 0) && child.height > 0) { // needs a box p->setPen(opt->palette.text().color()); p->drawRect(bx-4, linebot-4, 9, 9); QPolygon a; if ((child.state & State_Open)) a.setPoints(3, bx-2, linebot-2, bx, linebot+2, bx+2, linebot-2); //Qt::RightArrow else a.setPoints(3, bx-2, linebot-2, bx+2, linebot, bx-2, linebot+2); //Qt::DownArrow p->setBrush(opt->palette.text()); p->drawPolygon(a); p->setBrush(Qt::NoBrush); // dotlinery dotlines[c++] = QPoint(bx, linetop); dotlines[c++] = QPoint(bx, linebot - 5); dotlines[c++] = QPoint(bx + 5, linebot); dotlines[c++] = QPoint(opt->rect.width(), linebot); linetop = linebot + 5; } else { // just dotlinery dotlines[c++] = QPoint(bx+1, linebot); dotlines[c++] = QPoint(opt->rect.width(), linebot); } y += child.totalHeight; } ++i; } // Expand line height to edge of rectangle if there's any // visible child below while (i < lv->items.size() && lv->items.at(i).height <= 0) ++i; if (i < lv->items.size()) linebot = opt->rect.height(); if (linetop < linebot) { dotlines[c++] = QPoint(bx, linetop); dotlines[c++] = QPoint(bx, linebot); } } int line; // index into dotlines p->setPen(opt->palette.text().color()); if (opt->subControls & SC_Q3ListViewBranch) for(line = 0; line < c; line += 2) { p->drawLine(dotlines[line].x(), dotlines[line].y(), dotlines[line+1].x(), dotlines[line+1].y()); } } break; } default: QCommonStyle::drawComplexControl(cc, opt, p, widget); break; } } /*! \reimp */ int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const { int ret = 0; switch(pm) { case PM_ButtonDefaultIndicator: ret = 5; break; case PM_CheckBoxLabelSpacing: case PM_RadioButtonLabelSpacing: ret = 10; break; case PM_ToolBarFrameWidth: ret = proxy()->pixelMetric(PM_DefaultFrameWidth); break; case PM_ToolBarItemMargin: ret = 1; break; case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: ret = 0; break; case PM_SplitterWidth: ret = qMax(10, QApplication::globalStrut().width()); break; case PM_SliderLength: ret = 30; break; case PM_SliderThickness: ret = 16 + 4 * proxy()->pixelMetric(PM_DefaultFrameWidth); break; #ifndef QT_NO_SLIDER case PM_SliderControlThickness: if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); int ticks = sl->tickPosition; int n = 0; if (ticks & QSlider::TicksAbove) n++; if (ticks & QSlider::TicksBelow) n++; if (!n) { ret = space; break; } int thick = 6; // Magic constant to get 5 + 16 + 5 space -= thick; //### the two sides may be unequal in size if (space > 0) thick += (space * 2) / (n + 2); ret = thick; } break; case PM_SliderSpaceAvailable: if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { if (sl->orientation == Qt::Horizontal) ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); else ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); } break; #endif // QT_NO_SLIDER case PM_DockWidgetFrameWidth: ret = 2; break; case PM_DockWidgetHandleExtent: ret = 9; break; case PM_ProgressBarChunkWidth: ret = 1; break; case PM_ExclusiveIndicatorWidth: case PM_ExclusiveIndicatorHeight: ret = 13; break; case PM_MenuBarHMargin: ret = 2; // really ugly, but Motif break; case PM_MenuButtonIndicator: if (!opt) ret = 12; else ret = qMax(12, (opt->rect.height() - 4) / 3); break; default: ret = QCommonStyle::pixelMetric(pm, opt, widget); break; } return ret; } /*! \reimp */ QRect QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const { switch (cc) { #ifndef QT_NO_SPINBOX case CC_SpinBox: if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(opt)) { int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; QSize bs; bs.setHeight(opt->rect.height()/2 - fw); bs.setWidth(qMin(bs.height() * 8 / 5, opt->rect.width() / 4)); // 1.6 -approximate golden mean bs = bs.expandedTo(QApplication::globalStrut()); int y = fw + spinbox->rect.y(); int x, lx, rx; x = spinbox->rect.x() + opt->rect.width() - fw - bs.width(); lx = fw; rx = x - fw * 2; const int margin = spinbox->frame ? 4 : 0; switch (sc) { case SC_SpinBoxUp: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) return QRect(); return visualRect(spinbox->direction, spinbox->rect, QRect(x, y, bs.width(), bs.height() - 1)); case SC_SpinBoxDown: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) return QRect(); return visualRect(spinbox->direction, spinbox->rect, QRect(x, y + bs.height() + 1, bs.width(), bs.height() - 1)); case SC_SpinBoxEditField: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) return visualRect(spinbox->direction, spinbox->rect, QRect(lx + margin, y + margin, spinbox->rect.width() - 2*fw - 2*margin, spinbox->rect.height() - 2*fw - 2*margin)); return visualRect(spinbox->direction, spinbox->rect, QRect(lx + margin, y + margin, rx - margin, spinbox->rect.height() - 2*fw - 2 * margin)); case SC_SpinBoxFrame: return visualRect(spinbox->direction, spinbox->rect, spinbox->rect); default: break; } break; } #endif // QT_NO_SPINBOX #ifndef QT_NO_SLIDER case CC_Slider: if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { if (sc == SC_SliderHandle) { int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, opt, widget); int thickness = proxy()->pixelMetric(PM_SliderControlThickness, opt, widget); bool horizontal = slider->orientation == Qt::Horizontal; int len = proxy()->pixelMetric(PM_SliderLength, opt, widget); int motifBorder = proxy()->pixelMetric(PM_DefaultFrameWidth); int sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, slider->sliderPosition, horizontal ? slider->rect.width() - len - 2 * motifBorder : slider->rect.height() - len - 2 * motifBorder, slider->upsideDown); if (horizontal) return visualRect(slider->direction, slider->rect, QRect(sliderPos + motifBorder, tickOffset + motifBorder, len, thickness - 2 * motifBorder)); return visualRect(slider->direction, slider->rect, QRect(tickOffset + motifBorder, sliderPos + motifBorder, thickness - 2 * motifBorder, len)); } } break; #endif // QT_NO_SLIDER #ifndef QT_NO_SCROLLBAR case CC_ScrollBar: if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth); QRect rect = visualRect(scrollbar->direction, scrollbar->rect, QCommonStyle::subControlRect(cc, scrollbar, sc, widget)); if (sc == SC_ScrollBarSlider) { if (scrollbar->orientation == Qt::Horizontal) rect.adjust(-dfw, dfw, dfw, -dfw); else rect.adjust(dfw, -dfw, -dfw, dfw); } else if (sc != SC_ScrollBarGroove) { if (scrollbar->orientation == Qt::Horizontal) rect.adjust(0, dfw, 0, -dfw); else rect.adjust(dfw, 0, -dfw, 0); } return visualRect(scrollbar->direction, scrollbar->rect, rect); } break; #endif // QT_NO_SCROLLBAR #ifndef QT_NO_COMBOBOX case CC_ComboBox: if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { switch (sc) { case SC_ComboBoxArrow: { int ew, awh, sh, dh, ax, ay, sy; int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0; QRect cr = opt->rect; cr.adjust(fw, fw, -fw, -fw); get_combo_parameters(cr, ew, awh, ax, ay, sh, dh, sy); return visualRect(cb->direction, cb->rect, QRect(QPoint(ax, ay), cr.bottomRight())); } case SC_ComboBoxEditField: { int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0; QRect rect = opt->rect; rect.adjust(fw, fw, -fw, -fw); int ew = get_combo_extra_width(rect.height(), rect.width()); rect.adjust(1, 1, -1-ew, -1); return visualRect(cb->direction, cb->rect, rect); } default: break; } } break; #endif // QT_NO_SCROLLBAR default: break; } return QCommonStyle::subControlRect(cc, opt, sc, widget); } /*! \reimp */ QSize QMotifStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *widget) const { QSize sz(contentsSize); switch(ct) { case CT_RadioButton: case CT_CheckBox: sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget); sz.rwidth() += motifItemFrame; break; case CT_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget); if (!btn->text.isEmpty() && (btn->features & (QStyleOptionButton::AutoDefaultButton|QStyleOptionButton::DefaultButton))) sz.setWidth(qMax(75, sz.width())); sz += QSize(0, 1); // magical extra pixel } break; case CT_MenuBarItem: { if(!sz.isEmpty()) sz += QSize(5*motifItemHMargin+1, 2*motifItemVMargin + motifItemFrame); break; } case CT_MenuItem: if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { sz = QCommonStyle::sizeFromContents(ct, opt, sz, widget); int w = sz.width(), h = sz.height(); if (mi->menuItemType == QStyleOptionMenuItem::Separator) { w = 10; h = (mi->text.isEmpty()) ? motifSepHeight : mi->fontMetrics.height(); } // a little bit of border can never harm w += 2*motifItemHMargin + 2*motifItemFrame; if (!mi->text.isNull() && mi->text.indexOf(QLatin1Char('\t')) >= 0) // string contains tab w += motifTabSpacing; else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) // submenu indicator needs some room if we don't have a tab column w += motifArrowHMargin + 4*motifItemFrame; int checkColumn = mi->maxIconWidth; if (mi->menuHasCheckableItems) checkColumn = qMax(checkColumn, motifCheckMarkSpace); if (checkColumn > 0) w += checkColumn + motifCheckMarkHMargin; sz = QSize(w, h); } break; default: sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget); break; } return sz; } /*! \reimp */ QRect QMotifStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *widget) const { QRect rect; switch (sr) { case SE_SliderFocusRect: rect = QCommonStyle::subElementRect(sr, opt, widget); rect.adjust(2, 2, -2, -2); break; case SE_CheckBoxIndicator: case SE_RadioButtonIndicator: { rect = visualRect(opt->direction, opt->rect, QCommonStyle::subElementRect(sr, opt, widget)); rect.adjust(motifItemFrame,0, motifItemFrame,0); rect = visualRect(opt->direction, opt->rect, rect); } break; case SE_ComboBoxFocusRect: { int awh, ax, ay, sh, sy, dh, ew; int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); QRect tr = opt->rect; tr.adjust(fw, fw, -fw, -fw); get_combo_parameters(tr, ew, awh, ax, ay, sh, dh, sy); rect.setRect(ax-2, ay-2, awh+4, awh+sh+dh+4); break; } case SE_Q3DockWindowHandleRect: if (const QStyleOptionQ3DockWindow *dw = qstyleoption_cast(opt)) { if (!dw->docked || !dw->closeEnabled) rect.setRect(0, 0, opt->rect.width(), opt->rect.height()); else { if (dw->state == State_Horizontal) rect.setRect(2, 15, opt->rect.width()-2, opt->rect.height() - 15); else rect.setRect(0, 2, opt->rect.width() - 15, opt->rect.height() - 2); } rect = visualRect(dw->direction, dw->rect, rect); } break; case SE_ProgressBarLabel: case SE_ProgressBarGroove: case SE_ProgressBarContents: if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { int textw = 0; if (pb->textVisible) textw = pb->fontMetrics.width(QLatin1String("100%")) + 6; if (pb->textAlignment == Qt::AlignLeft || pb->textAlignment == Qt::AlignCenter) { rect = opt->rect; } else { if(sr == SE_ProgressBarLabel) rect.setCoords(opt->rect.right() - textw, opt->rect.top(), opt->rect.right(), opt->rect.bottom()); else rect.setCoords(opt->rect.left(), opt->rect.top(), opt->rect.right() - textw, opt->rect.bottom()); } if (sr == SE_ProgressBarContents) rect.adjust(2, 2, -2, -2); rect = visualRect(pb->direction, pb->rect, rect); } break; case SE_CheckBoxClickRect: case SE_RadioButtonClickRect: rect = visualRect(opt->direction, opt->rect, opt->rect); break; default: rect = QCommonStyle::subElementRect(sr, opt, widget); } return rect; } #ifndef QT_NO_IMAGEFORMAT_XPM static const char * const qt_menu_xpm[] = { "16 16 11 1", " c #000000", ", c #336600", ". c #99CC00", "X c #666600", "o c #999933", "+ c #333300", "@ c #669900", "# c #999900", "$ c #336633", "% c #666633", "& c #99CC33", "................", "................", ".....#,++X#.....", "....X X....", "...X Xo#% X&..", "..# o..&@o o..", ".., X..#+ @X X..", "..+ o.o+ +o# +..", "..+ #o+ +## +..", ".., %@ ++ +, X..", "..# o@oo+ #..", "...X X##$ o..", "....X X..", "....&oX++X#oX...", "................", "................"}; static const char * const qt_close_xpm[] = { "12 12 2 1", " s None c None", ". c black", " ", " ", " . . ", " ... ... ", " ...... ", " .... ", " .... ", " ...... ", " ... ... ", " . . ", " ", " "}; static const char * const qt_maximize_xpm[] = { "12 12 2 1", " s None c None", ". c black", " ", " ", " ", " . ", " ... ", " ..... ", " ....... ", " ......... ", " ", " ", " ", " "}; static const char * const qt_minimize_xpm[] = { "12 12 2 1", " s None c None", ". c black", " ", " ", " ", " ", " ......... ", " ....... ", " ..... ", " ... ", " . ", " ", " ", " "}; #if 0 // ### not used??? static const char * const qt_normalize_xpm[] = { "12 12 2 1", " s None c None", ". c black", " ", " ", " . ", " .. ", " ... ", " .... ", " ..... ", " ...... ", " ....... ", " ", " ", " "}; #endif static const char * const qt_normalizeup_xpm[] = { "12 12 2 1", " s None c None", ". c black", " ", " ", " ", " ....... ", " ...... ", " ..... ", " .... ", " ... ", " .. ", " . ", " ", " "}; static const char * const qt_shade_xpm[] = { "12 12 2 1", "# c #000000", ". c None", "............", "............", ".#########..", ".#########..", "............", "............", "............", "............", "............", "............", "............", "............"}; static const char * const qt_unshade_xpm[] = { "12 12 2 1", "# c #000000", ". c None", "............", "............", ".#########..", ".#########..", ".#.......#..", ".#.......#..", ".#.......#..", ".#.......#..", ".#.......#..", ".#########..", "............", "............"}; static const char * dock_window_close_xpm[] = { "8 8 2 1", "# c #000000", ". c None", "##....##", ".##..##.", "..####..", "...##...", "..####..", ".##..##.", "##....##", "........"}; // Message box icons, from page 210 of the Windows style guide. // Hand-drawn to resemble Microsoft's icons, but in the Mac/Netscape palette. // Thanks to TrueColor displays, it is slightly more efficient to have // them duplicated. /* XPM */ static const char * const information_xpm[]={ "32 32 5 1", ". c None", "c c #000000", "* c #999999", "a c #ffffff", "b c #0000ff", "...........********.............", "........***aaaaaaaa***..........", "......**aaaaaaaaaaaaaa**........", ".....*aaaaaaaaaaaaaaaaaa*.......", "....*aaaaaaaabbbbaaaaaaaac......", "...*aaaaaaaabbbbbbaaaaaaaac.....", "..*aaaaaaaaabbbbbbaaaaaaaaac....", ".*aaaaaaaaaaabbbbaaaaaaaaaaac...", ".*aaaaaaaaaaaaaaaaaaaaaaaaaac*..", "*aaaaaaaaaaaaaaaaaaaaaaaaaaaac*.", "*aaaaaaaaaabbbbbbbaaaaaaaaaaac*.", "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", ".*aaaaaaaaaaabbbbbaaaaaaaaaac***", ".*aaaaaaaaaaabbbbbaaaaaaaaaac***", "..*aaaaaaaaaabbbbbaaaaaaaaac***.", "...caaaaaaabbbbbbbbbaaaaaac****.", "....caaaaaaaaaaaaaaaaaaaac****..", ".....caaaaaaaaaaaaaaaaaac****...", "......ccaaaaaaaaaaaaaacc****....", ".......*cccaaaaaaaaccc*****.....", "........***cccaaaac*******......", "..........****caaac*****........", ".............*caaac**...........", "...............caac**...........", "................cac**...........", ".................cc**...........", "..................***...........", "...................**..........."}; /* XPM */ static const char* const warning_xpm[]={ "32 32 4 1", ". c None", "a c #ffff00", "* c #000000", "b c #999999", ".............***................", "............*aaa*...............", "...........*aaaaa*b.............", "...........*aaaaa*bb............", "..........*aaaaaaa*bb...........", "..........*aaaaaaa*bb...........", ".........*aaaaaaaaa*bb..........", ".........*aaaaaaaaa*bb..........", "........*aaaaaaaaaaa*bb.........", "........*aaaa***aaaa*bb.........", ".......*aaaa*****aaaa*bb........", ".......*aaaa*****aaaa*bb........", "......*aaaaa*****aaaaa*bb.......", "......*aaaaa*****aaaaa*bb.......", ".....*aaaaaa*****aaaaaa*bb......", ".....*aaaaaa*****aaaaaa*bb......", "....*aaaaaaaa***aaaaaaaa*bb.....", "....*aaaaaaaa***aaaaaaaa*bb.....", "...*aaaaaaaaa***aaaaaaaaa*bb....", "...*aaaaaaaaaa*aaaaaaaaaa*bb....", "..*aaaaaaaaaaa*aaaaaaaaaaa*bb...", "..*aaaaaaaaaaaaaaaaaaaaaaa*bb...", ".*aaaaaaaaaaaa**aaaaaaaaaaa*bb..", ".*aaaaaaaaaaa****aaaaaaaaaa*bb..", "*aaaaaaaaaaaa****aaaaaaaaaaa*bb.", "*aaaaaaaaaaaaa**aaaaaaaaaaaa*bb.", "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", ".*aaaaaaaaaaaaaaaaaaaaaaaaa*bbbb", "..*************************bbbbb", "....bbbbbbbbbbbbbbbbbbbbbbbbbbb.", ".....bbbbbbbbbbbbbbbbbbbbbbbbb.."}; /* XPM */ static const char* const critical_xpm[]={ "32 32 4 1", ". c None", "a c #999999", "* c #ff0000", "b c #ffffff", "...........********.............", ".........************...........", ".......****************.........", "......******************........", ".....********************a......", "....**********************a.....", "...************************a....", "..*******b**********b*******a...", "..******bbb********bbb******a...", ".******bbbbb******bbbbb******a..", ".*******bbbbb****bbbbb*******a..", "*********bbbbb**bbbbb*********a.", "**********bbbbbbbbbb**********a.", "***********bbbbbbbb***********aa", "************bbbbbb************aa", "************bbbbbb************aa", "***********bbbbbbbb***********aa", "**********bbbbbbbbbb**********aa", "*********bbbbb**bbbbb*********aa", ".*******bbbbb****bbbbb*******aa.", ".******bbbbb******bbbbb******aa.", "..******bbb********bbb******aaa.", "..*******b**********b*******aa..", "...************************aaa..", "....**********************aaa...", "....a********************aaa....", ".....a******************aaa.....", "......a****************aaa......", ".......aa************aaaa.......", ".........aa********aaaaa........", "...........aaaaaaaaaaa..........", ".............aaaaaaa............"}; /* XPM */ static const char *const question_xpm[] = { "32 32 5 1", ". c None", "c c #000000", "* c #999999", "a c #ffffff", "b c #0000ff", "...........********.............", "........***aaaaaaaa***..........", "......**aaaaaaaaaaaaaa**........", ".....*aaaaaaaaaaaaaaaaaa*.......", "....*aaaaaaaaaaaaaaaaaaaac......", "...*aaaaaaaabbbbbbaaaaaaaac.....", "..*aaaaaaaabaaabbbbaaaaaaaac....", ".*aaaaaaaabbaaaabbbbaaaaaaaac...", ".*aaaaaaaabbbbaabbbbaaaaaaaac*..", "*aaaaaaaaabbbbaabbbbaaaaaaaaac*.", "*aaaaaaaaaabbaabbbbaaaaaaaaaac*.", "*aaaaaaaaaaaaabbbbaaaaaaaaaaac**", "*aaaaaaaaaaaaabbbaaaaaaaaaaaac**", "*aaaaaaaaaaaaabbaaaaaaaaaaaaac**", "*aaaaaaaaaaaaabbaaaaaaaaaaaaac**", "*aaaaaaaaaaaaaaaaaaaaaaaaaaaac**", ".*aaaaaaaaaaaabbaaaaaaaaaaaac***", ".*aaaaaaaaaaabbbbaaaaaaaaaaac***", "..*aaaaaaaaaabbbbaaaaaaaaaac***.", "...caaaaaaaaaabbaaaaaaaaaac****.", "....caaaaaaaaaaaaaaaaaaaac****..", ".....caaaaaaaaaaaaaaaaaac****...", "......ccaaaaaaaaaaaaaacc****....", ".......*cccaaaaaaaaccc*****.....", "........***cccaaaac*******......", "..........****caaac*****........", ".............*caaac**...........", "...............caac**...........", "................cac**...........", ".................cc**...........", "..................***...........", "...................**...........", }; #endif /*! \reimp */ QPixmap QMotifStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const { #ifndef QT_NO_IMAGEFORMAT_XPM switch (standardPixmap) { case SP_TitleBarMenuButton: return QPixmap(qt_menu_xpm); case SP_TitleBarShadeButton: return QPixmap(qt_shade_xpm); case SP_TitleBarUnshadeButton: return QPixmap(qt_unshade_xpm); case SP_TitleBarNormalButton: return QPixmap(qt_normalizeup_xpm); case SP_TitleBarMinButton: return QPixmap(qt_minimize_xpm); case SP_TitleBarMaxButton: return QPixmap(qt_maximize_xpm); case SP_TitleBarCloseButton: return QPixmap(qt_close_xpm); case SP_DockWidgetCloseButton: return QPixmap(dock_window_close_xpm); case SP_MessageBoxInformation: case SP_MessageBoxWarning: case SP_MessageBoxCritical: case SP_MessageBoxQuestion: { const char * const * xpm_data; switch (standardPixmap) { case SP_MessageBoxInformation: xpm_data = information_xpm; break; case SP_MessageBoxWarning: xpm_data = warning_xpm; break; case SP_MessageBoxCritical: xpm_data = critical_xpm; break; case SP_MessageBoxQuestion: xpm_data = question_xpm; break; default: xpm_data = 0; break; } QPixmap pm; if (xpm_data) { QImage image((const char **) xpm_data); // All that color looks ugly in Motif const QPalette &pal = QApplication::palette(); switch (standardPixmap) { case SP_MessageBoxInformation: case SP_MessageBoxQuestion: image.setColor(2, 0xff000000 | pal.color(QPalette::Active, QPalette::Dark).rgb()); image.setColor(3, 0xff000000 | pal.color(QPalette::Active, QPalette::Base).rgb()); image.setColor(4, 0xff000000 | pal.color(QPalette::Active, QPalette::Text).rgb()); break; case SP_MessageBoxWarning: image.setColor(1, 0xff000000 | pal.color(QPalette::Active, QPalette::Base).rgb()); image.setColor(2, 0xff000000 | pal.color(QPalette::Active, QPalette::Text).rgb()); image.setColor(3, 0xff000000 | pal.color(QPalette::Active, QPalette::Dark).rgb()); break; case SP_MessageBoxCritical: image.setColor(1, 0xff000000 | pal.color(QPalette::Active, QPalette::Dark).rgb()); image.setColor(2, 0xff000000 | pal.color(QPalette::Active, QPalette::Text).rgb()); image.setColor(3, 0xff000000 | pal.color(QPalette::Active, QPalette::Base).rgb()); break; default: break; } pm = QPixmap::fromImage(image); } return pm; } default: break; } #endif return QCommonStyle::standardPixmap(standardPixmap, opt, widget); } /*! \reimp */ bool QMotifStyle::event(QEvent *e) { if(e->type() == QEvent::FocusIn) { if (QWidget *focusWidget = QApplication::focusWidget()) { #ifndef QT_NO_GRAPHICSVIEW if (QGraphicsView *graphicsView = qobject_cast(focusWidget)) { QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { QGraphicsProxyWidget *proxy = static_cast(focusItem); if (proxy->widget()) focusWidget = proxy->widget()->focusWidget(); } } #endif if(!focus) focus = new QFocusFrame(focusWidget); focus->setWidget(focusWidget); } else { if(focus) focus->setWidget(0); } } else if(e->type() == QEvent::FocusOut) { if(focus) focus->setWidget(0); } return QCommonStyle::event(e); } /*! \reimp */ int QMotifStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const { int ret; switch (hint) { #ifdef QT3_SUPPORT case SH_GUIStyle: ret = Qt::MotifStyle; break; #endif case SH_DrawMenuBarSeparator: ret = true; break; case SH_ScrollBar_MiddleClickAbsolutePosition: case SH_Slider_SloppyKeyEvents: case SH_ProgressDialog_CenterCancelButton: case SH_Menu_SpaceActivatesItem: case SH_ScrollView_FrameOnlyAroundContents: case SH_DitherDisabledText: ret = 1; break; case SH_Menu_SubMenuPopupDelay: ret = 96; break; case SH_ProgressDialog_TextLabelAlignment: ret = Qt::AlignLeft | Qt::AlignVCenter; break; case SH_ItemView_ChangeHighlightOnFocus: ret = 0; break; case SH_MessageBox_UseBorderForButtonSpacing: ret = 1; break; case SH_Dial_BackgroundRole: ret = QPalette::Mid; break; case SH_DialogButtonLayout: ret = QDialogButtonBox::KdeLayout; break; case SH_LineEdit_PasswordCharacter: ret = '*'; break; case SH_DialogButtonBox_ButtonsHaveIcons: ret = 0; break; default: ret = QCommonStyle::styleHint(hint, opt, widget, returnData); break; } return ret; } /*! \reimp */ QPalette QMotifStyle::standardPalette() const { #ifdef Q_WS_X11 QColor background(0xcf, 0xcf, 0xcf); if (QX11Info::appDepth() <= 8) background = QColor(0xc0, 0xc0, 0xc0); #else QColor background = QColor(0xcf, 0xcf, 0xcf); #endif QColor light = background.lighter(); QColor mid = QColor(0xa6, 0xa6, 0xa6); QColor dark = QColor(0x79, 0x7d, 0x79); QPalette palette(Qt::black, background, light, dark, mid, Qt::black, Qt::white); palette.setBrush(QPalette::Disabled, QPalette::WindowText, dark); palette.setBrush(QPalette::Disabled, QPalette::Text, dark); palette.setBrush(QPalette::Disabled, QPalette::ButtonText, dark); palette.setBrush(QPalette::Disabled, QPalette::Base, background); return palette; } QT_END_NAMESPACE #endif // !defined(QT_NO_STYLE_MOTIF) || defined(QT_PLUGIN)