00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "arthurstyle.h"
00025 #include "arthurwidgets.h"
00026 #include <QLayout>
00027 #include <QPainter>
00028 #include <QPainterPath>
00029 #include <QPixmapCache>
00030 #include <QRadioButton>
00031 #include <QString>
00032 #include <QStyleOption>
00033 #include <QtDebug>
00034
00035 QPixmap cached(const QString &img)
00036 {
00037 if (QPixmap *p = QPixmapCache::find(img))
00038 return *p;
00039
00040 QPixmap pm;
00041 pm = QPixmap::fromImage(QImage(img), Qt::OrderedDither | Qt::OrderedAlphaDither);
00042 if (pm.isNull())
00043 return QPixmap();
00044
00045 QPixmapCache::insert(img, pm);
00046 return pm;
00047 }
00048
00049
00050 ArthurStyle::ArthurStyle()
00051 : QWindowsStyle()
00052 {
00053 Q_INIT_RESOURCE(shared);
00054 }
00055
00056
00057 void ArthurStyle::drawHoverRect(QPainter *painter, const QRect &r) const
00058 {
00059 double h = r.height();
00060 double h2 = r.height() / 2.0;
00061 QPainterPath path;
00062 path.addRect(r.x() + h2, r.y() + 0, r.width() - h2 * 2, r.height());
00063 path.addEllipse(r.x(), r.y(), h, h);
00064 path.addEllipse(r.x() + r.width() - h, r.y(), h, h);
00065 path.setFillRule(Qt::WindingFill);
00066 painter->setPen(Qt::NoPen);
00067 painter->setBrush(QColor(191, 215, 191));
00068 painter->setRenderHint(QPainter::Antialiasing);
00069 painter->drawPath(path);
00070 }
00071
00072
00073 void ArthurStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
00074 QPainter *painter, const QWidget *widget) const
00075 {
00076
00077 Q_ASSERT(option);
00078 switch (element) {
00079 case PE_FrameFocusRect:
00080 break;
00081
00082 case PE_IndicatorRadioButton:
00083 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
00084 bool hover = (button->state & State_Enabled) && (button->state & State_MouseOver);
00085 painter->save();
00086 QPixmap radio;
00087 if (hover)
00088 drawHoverRect(painter, widget->rect());
00089
00090 if (button->state & State_Sunken)
00091 radio = cached(":res/images/radiobutton-on.png");
00092 else if (button->state & State_On)
00093 radio = cached(":res/images/radiobutton_on.png");
00094 else
00095 radio = cached(":res/images/radiobutton_off.png");
00096 painter->drawPixmap(button->rect.topLeft(), radio);
00097
00098 painter->restore();
00099 }
00100 break;
00101
00102 case PE_PanelButtonCommand:
00103 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
00104 bool hover = (button->state & State_Enabled) && (button->state & State_MouseOver);
00105
00106 painter->save();
00107 const QPushButton *pushButton = qobject_cast<const QPushButton *>(widget);
00108 Q_ASSERT(pushButton);
00109 QWidget *parent = pushButton->parentWidget();
00110 if (parent && qobject_cast<QGroupBox *>(parent)) {
00111 QLinearGradient lg(0, 0, 0, parent->height());
00112 lg.setColorAt(0, QColor(224,224,224));
00113 lg.setColorAt(1, QColor(255,255,255));
00114 painter->setPen(Qt::NoPen);
00115 painter->setBrush(lg);
00116 painter->setBrushOrigin(-widget->mapToParent(QPoint(0,0)));
00117 painter->drawRect(button->rect);
00118 painter->setBrushOrigin(0,0);
00119 }
00120
00121 bool down = (button->state & State_Sunken) || (button->state & State_On);
00122
00123 QPixmap left, right, mid;
00124 if (down) {
00125 left = cached(":res/images/button_pressed_cap_left.png");
00126 right = cached(":res/images/button_pressed_cap_right.png");
00127 mid = cached(":res/images/button_pressed_stretch.png");
00128 } else {
00129 left = cached(":res/images/button_normal_cap_left.png");
00130 right = cached(":res/images/button_normal_cap_right.png");
00131 mid = cached(":res/images/button_normal_stretch.png");
00132 }
00133 painter->drawPixmap(button->rect.topLeft(), left);
00134 painter->drawTiledPixmap(QRect(button->rect.x() + left.width(),
00135 button->rect.y(),
00136 button->rect.width() - left.width() - right.width(),
00137 left.height()),
00138 mid);
00139 painter->drawPixmap(button->rect.x() + button->rect.width() - right.width(),
00140 button->rect.y(),
00141 right);
00142 if (hover)
00143 painter->fillRect(widget->rect().adjusted(3,5,-3,-5), QColor(31,127,31,63));
00144 painter->restore();
00145 }
00146 break;
00147
00148 case PE_FrameGroupBox:
00149 if (const QStyleOptionFrameV2 *group
00150 = qstyleoption_cast<const QStyleOptionFrameV2 *>(option)) {
00151 const QRect &r = group->rect;
00152
00153 painter->save();
00154 int radius = 14;
00155 int radius2 = radius*2;
00156 QPainterPath clipPath;
00157 clipPath.moveTo(radius, 0);
00158 clipPath.arcTo(r.right() - radius2, 0, radius2, radius2, 90, -90);
00159 clipPath.arcTo(r.right() - radius2, r.bottom() - radius2, radius2, radius2, 0, -90);
00160 clipPath.arcTo(r.left(), r.bottom() - radius2, radius2, radius2, 270, -90);
00161 clipPath.arcTo(r.left(), r.top(), radius2, radius2, 180, -90);
00162 painter->setClipPath(clipPath);
00163 QPixmap titleStretch = cached(":res/images/title_stretch.png");
00164 QPixmap topLeft = cached(":res/images/groupframe_topleft.png");
00165 QPixmap topRight = cached(":res/images/groupframe_topright.png");
00166 QPixmap bottomLeft = cached(":res/images/groupframe_bottom_left.png");
00167 QPixmap bottomRight = cached(":res/images/groupframe_bottom_right.png");
00168 QPixmap leftStretch = cached(":res/images/groupframe_left_stretch.png");
00169 QPixmap topStretch = cached(":res/images/groupframe_top_stretch.png");
00170 QPixmap rightStretch = cached(":res/images/groupframe_right_stretch.png");
00171 QPixmap bottomStretch = cached(":res/images/groupframe_bottom_stretch.png");
00172 QLinearGradient lg(0, 0, 0, r.height());
00173 lg.setColorAt(0, QColor(224,224,224));
00174 lg.setColorAt(1, QColor(255,255,255));
00175 painter->setPen(Qt::NoPen);
00176 painter->setBrush(lg);
00177 painter->drawRect(r.adjusted(0, titleStretch.height()/2, 0, 0));
00178 painter->setClipping(false);
00179
00180 int topFrameOffset = titleStretch.height()/2 - 2;
00181 painter->drawPixmap(r.topLeft() + QPoint(0, topFrameOffset), topLeft);
00182 painter->drawPixmap(r.topRight() - QPoint(topRight.width()-1, 0)
00183 + QPoint(0, topFrameOffset), topRight);
00184 painter->drawPixmap(r.bottomLeft() - QPoint(0, bottomLeft.height()-1), bottomLeft);
00185 painter->drawPixmap(r.bottomRight() - QPoint(bottomRight.width()-1,
00186 bottomRight.height()-1), bottomRight);
00187
00188 QRect left = r;
00189 left.setY(r.y() + topLeft.height() + topFrameOffset);
00190 left.setWidth(leftStretch.width());
00191 left.setHeight(r.height() - topLeft.height() - bottomLeft.height() - topFrameOffset);
00192 painter->drawTiledPixmap(left, leftStretch);
00193
00194 QRect top = r;
00195 top.setX(r.x() + topLeft.width());
00196 top.setY(r.y() + topFrameOffset);
00197 top.setWidth(r.width() - topLeft.width() - topRight.width());
00198 top.setHeight(topLeft.height());
00199 painter->drawTiledPixmap(top, topStretch);
00200
00201 QRect right = r;
00202 right.setX(r.right() - rightStretch.width()+1);
00203 right.setY(r.y() + topRight.height() + topFrameOffset);
00204 right.setWidth(rightStretch.width());
00205 right.setHeight(r.height() - topRight.height()
00206 - bottomRight.height() - topFrameOffset);
00207 painter->drawTiledPixmap(right, rightStretch);
00208
00209 QRect bottom = r;
00210 bottom.setX(r.x() + bottomLeft.width());
00211 bottom.setY(r.bottom() - bottomStretch.height()+1);
00212 bottom.setWidth(r.width() - bottomLeft.width() - bottomRight.width());
00213 bottom.setHeight(bottomLeft.height());
00214 painter->drawTiledPixmap(bottom, bottomStretch);
00215 painter->restore();
00216 }
00217 break;
00218
00219 default:
00220 QWindowsStyle::drawPrimitive(element, option, painter, widget);
00221 break;
00222 }
00223 return;
00224 }
00225
00226
00227 void ArthurStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
00228 QPainter *painter, const QWidget *widget) const
00229 {
00230 switch (control) {
00231 case CC_Slider:
00232 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
00233 QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
00234 QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
00235
00236 painter->save();
00237
00238 bool hover = (slider->state & State_Enabled) && (slider->state & State_MouseOver);
00239 if (hover) {
00240 QRect moderated = widget->rect().adjusted(0, 4, 0, -4);
00241 drawHoverRect(painter, moderated);
00242 }
00243
00244 if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
00245 QPixmap grv = cached(":res/images/slider_bar.png");
00246 painter->drawPixmap(QRect(groove.x() + 5, groove.y(),
00247 groove.width() - 10, grv.height()),
00248 grv);
00249 }
00250 if ((option->subControls & SC_SliderHandle) && handle.isValid()) {
00251 QPixmap hndl = cached(":res/images/slider_thumb_on.png");
00252 painter->drawPixmap(handle.topLeft(), hndl);
00253 }
00254
00255 painter->restore();
00256 }
00257 break;
00258 case CC_GroupBox:
00259 if (const QStyleOptionGroupBox *groupBox
00260 = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
00261 QStyleOptionGroupBox groupBoxCopy(*groupBox);
00262 groupBoxCopy.subControls &= ~SC_GroupBoxLabel;
00263 QWindowsStyle::drawComplexControl(control, &groupBoxCopy, painter, widget);
00264
00265 if (groupBox->subControls & SC_GroupBoxLabel) {
00266 const QRect &r = groupBox->rect;
00267 QPixmap titleLeft = cached(":res/images/title_cap_left.png");
00268 QPixmap titleRight = cached(":res/images/title_cap_right.png");
00269 QPixmap titleStretch = cached(":res/images/title_stretch.png");
00270 int txt_width = groupBox->fontMetrics.width(groupBox->text) + 20;
00271 painter->drawPixmap(r.center().x() - txt_width/2, 0, titleLeft);
00272 QRect tileRect = subControlRect(control, groupBox, SC_GroupBoxLabel, widget);
00273 painter->drawTiledPixmap(tileRect, titleStretch);
00274 painter->drawPixmap(tileRect.x() + tileRect.width(), 0, titleRight);
00275 int opacity = 31;
00276 painter->setPen(QColor(0, 0, 0, opacity));
00277 painter->drawText(tileRect.translated(0, 1),
00278 Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
00279 painter->drawText(tileRect.translated(2, 1),
00280 Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
00281 painter->setPen(QColor(0, 0, 0, opacity * 2));
00282 painter->drawText(tileRect.translated(1, 1),
00283 Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
00284 painter->setPen(Qt::white);
00285 painter->drawText(tileRect, Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
00286 }
00287 }
00288 break;
00289 default:
00290 QWindowsStyle::drawComplexControl(control, option, painter, widget);
00291 break;
00292 }
00293 return;
00294 }
00295
00296 QRect ArthurStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
00297 SubControl subControl, const QWidget *widget) const
00298 {
00299 QRect rect;
00300
00301 switch (control) {
00302 default:
00303 rect = QWindowsStyle::subControlRect(control, option, subControl, widget);
00304 break;
00305 case CC_GroupBox:
00306 if (const QStyleOptionGroupBox *group
00307 = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
00308 switch (subControl) {
00309 default:
00310 rect = QWindowsStyle::subControlRect(control, option, subControl, widget);
00311 break;
00312 case SC_GroupBoxContents:
00313 rect = QWindowsStyle::subControlRect(control, option, subControl, widget);
00314 rect.adjust(0, -8, 0, 0);
00315 break;
00316 case SC_GroupBoxFrame:
00317 rect = group->rect;
00318 break;
00319 case SC_GroupBoxLabel:
00320 QPixmap titleLeft = cached(":res/images/title_cap_left.png");
00321 QPixmap titleRight = cached(":res/images/title_cap_right.png");
00322 QPixmap titleStretch = cached(":res/images/title_stretch.png");
00323 int txt_width = group->fontMetrics.width(group->text) + 20;
00324 rect = QRect(group->rect.center().x() - txt_width/2 + titleLeft.width(), 0,
00325 txt_width - titleLeft.width() - titleRight.width(),
00326 titleStretch.height());
00327 break;
00328 }
00329 }
00330 break;
00331 }
00332
00333 if (control == CC_Slider && subControl == SC_SliderHandle) {
00334 rect.setWidth(13);
00335 rect.setHeight(27);
00336 } else if (control == CC_Slider && subControl == SC_SliderGroove) {
00337 rect.setHeight(9);
00338 rect.moveTop(27/2 - 9/2);
00339 }
00340 return rect;
00341 }
00342
00343 QSize ArthurStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
00344 const QSize &size, const QWidget *widget) const
00345 {
00346 QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
00347
00348
00349 switch (type) {
00350 case CT_RadioButton:
00351 newSize += QSize(20, 0);
00352 break;
00353
00354 case CT_PushButton:
00355 newSize.setHeight(26);
00356 break;
00357
00358 case CT_Slider:
00359 newSize.setHeight(27);
00360 break;
00361
00362 default:
00363 break;
00364 }
00365
00366 return newSize;
00367 }
00368
00369 int ArthurStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const
00370 {
00371 if (pm == PM_SliderLength)
00372 return 13;
00373 return QWindowsStyle::pixelMetric(pm, opt, widget);
00374 }
00375
00376 void ArthurStyle::polish(QWidget *widget)
00377 {
00378 if (widget->layout() && qobject_cast<QGroupBox *>(widget)) {
00379 if (qFindChildren<QGroupBox *>(widget).size() == 0)
00380 widget->layout()->setSpacing(0);
00381 else
00382 widget->layout()->setMargin(10);
00383 }
00384
00385 if (qobject_cast<QPushButton *>(widget)
00386 || qobject_cast<QRadioButton *>(widget)
00387 || qobject_cast<QSlider *>(widget)) {
00388 widget->setAttribute(Qt::WA_Hover);
00389 }
00390
00391 QPalette pal = widget->palette();
00392 if (widget->isWindow()) {
00393 pal.setColor(QPalette::Background, QColor(241, 241, 241));
00394 widget->setPalette(pal);
00395 }
00396
00397 }
00398
00399 void ArthurStyle::unpolish(QWidget *widget)
00400 {
00401 if (qobject_cast<QPushButton *>(widget)
00402 || qobject_cast<QRadioButton *>(widget)
00403 || qobject_cast<QSlider *>(widget)) {
00404 widget->setAttribute(Qt::WA_Hover, false);
00405 }
00406 }
00407
00408 void ArthurStyle::polish(QPalette &palette)
00409 {
00410 palette.setColor(QPalette::Background, QColor(241, 241, 241));
00411 }
00412
00413 QRect ArthurStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
00414 {
00415 QRect r;
00416 switch(element) {
00417 case SE_RadioButtonClickRect:
00418 r = widget->rect();
00419 break;
00420 case SE_RadioButtonContents:
00421 r = widget->rect().adjusted(20, 0, 0, 0);
00422 break;
00423 default:
00424 r = QWindowsStyle::subElementRect(element, option, widget);
00425 break;
00426 }
00427
00428 if (qobject_cast<const QRadioButton*>(widget))
00429 r = r.adjusted(5, 0, -5, 0);
00430
00431 return r;
00432 }