Back to index

kdeartwork  4.3.2
phasestyle.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00003 // phasestyle.cpp
00004 // -------------------
00005 // Qt widget style
00006 // -------------------
00007 // Copyright (c) 2004-2008 David Johnson <david@usermode.org>
00008 // Please see the header file for copyright and license information.
00010 //
00011 // Some miscellaneous notes
00012 //
00013 // Menu and toolbars are painted with the background color by default. This
00014 // differs from the Qt default of giving them PaletteButton backgrounds.
00015 // Menubars have normal gradients, toolbars have reverse.
00016 //
00017 // Some toolbars are not part of a QMainWindows, such as in a KDE file dialog.
00018 // In these cases we treat the toolbar as "floating" and paint it flat.
00019 //
00021 
00022 #include "phasestyle.h"
00023 
00024 #include <QApplication>
00025 #include <QBitmap>
00026 #include <QCheckBox>
00027 #include <QComboBox>
00028 #include <QDialogButtonBox>
00029 #include <QDockWidget>
00030 #include <QKeyEvent>
00031 #include <QLinearGradient>
00032 #include <QMenuBar>
00033 #include <QPainter>
00034 #include <QPixmapCache>
00035 #include <QProgressBar>
00036 #include <QStylePlugin>
00037 #include <QPushButton>
00038 #include <QRadioButton>
00039 #include <QSettings>
00040 #include <QSpinBox>
00041 #include <QSplitterHandle>
00042 #include <QToolBar>
00043 
00044 #include <limits.h>
00045 
00046 #include "bitmaps.h"
00047 
00048 // some convenient constants
00049 static const int ARROWMARGIN     = 6;
00050 static const int ITEMFRAME       = 1;
00051 static const int ITEMHMARGIN     = 3;
00052 static const int ITEMVMARGIN     = 0;
00053 static const int MAXGRADIENTSIZE = 128;
00054 
00056 // Construction, Destruction, Initialization                                //
00058 
00060 // PhaseStyle()
00061 // -----------
00062 // Constructor
00063 
00064 PhaseStyle::PhaseStyle()
00065     : QWindowsStyle(), gradients_(QPixmap::defaultDepth() > 8), timerid_(0)
00066 {
00067     // get phasestyle config
00068     QSettings settings("phasestyle");
00069     if (gradients_) { // don't bother setting if already false
00070         gradients_ = settings.value("/gradients", true).toBool();
00071     }
00072     highlights_ = settings.value("/highlights", true).toBool();
00073 
00074     // get contrast from KDE configs
00075     QSettings kdesettings("Trolltech");
00076     contrast_ = 100 + kdesettings.value("/Qt/KDE/contrast", 5).toInt();
00077 
00078     // create bitmaps
00079     const QSize arrowsz(6, 6);
00080     const QSize btnsz(10, 10);
00081     bitmaps_.insert(UArrow, QBitmap::fromData(arrowsz, uarrow_bits));
00082     bitmaps_.insert(DArrow, QBitmap::fromData(arrowsz, darrow_bits));
00083     bitmaps_.insert(LArrow, QBitmap::fromData(arrowsz, larrow_bits));
00084     bitmaps_.insert(RArrow, QBitmap::fromData(arrowsz, rarrow_bits));
00085     bitmaps_.insert(PlusSign, QBitmap::fromData(arrowsz, plussign_bits));
00086     bitmaps_.insert(MinusSign, QBitmap::fromData(arrowsz, minussign_bits));
00087     bitmaps_.insert(CheckMark, QBitmap::fromData(btnsz, checkmark_bits));
00088     bitmaps_.insert(TitleClose, QBitmap::fromData(btnsz, title_close_bits));
00089     bitmaps_.insert(TitleMin, QBitmap::fromData(btnsz, title_min_bits));
00090     bitmaps_.insert(TitleMax, QBitmap::fromData(btnsz, title_max_bits));
00091     bitmaps_.insert(TitleNormal, QBitmap::fromData(btnsz, title_normal_bits));
00092     bitmaps_.insert(TitleHelp, QBitmap::fromData(btnsz, title_help_bits));
00093 }
00094 
00095 PhaseStyle::~PhaseStyle() { ; }
00096 
00098 // Polishing                                                                //
00100 
00102 // polish()
00103 // --------
00104 // Initialize application specific
00105 
00106 void PhaseStyle::polish(QApplication* app)
00107 {
00108     QWindowsStyle::polish(app);
00109 }
00110 
00112 // polish()
00113 // --------
00114 // Initialize the appearance of widget
00115 
00116 void PhaseStyle::polish(QWidget *widget)
00117 {
00118     if (highlights_ &&
00119                (qobject_cast<QPushButton*>(widget) ||
00120                 qobject_cast<QComboBox*>(widget) ||
00121                 qobject_cast<QAbstractSpinBox*>(widget) ||
00122                 qobject_cast<QCheckBox*>(widget) ||
00123                 qobject_cast<QRadioButton*>(widget) ||
00124                 qobject_cast<QSplitterHandle*>(widget) ||
00125                 qobject_cast<QSlider*>(widget) ||
00126                 qobject_cast<QTabBar*>(widget))) {
00127         // mouseover highlighting
00128         widget->setAttribute(Qt::WA_Hover);
00129     }
00130     if (widget->inherits("QDockSeparator")
00131         || widget->inherits("QDockWidgetSeparator")) {
00132         widget->setAttribute(Qt::WA_Hover);
00133     }
00134     if (qobject_cast<QProgressBar*>(widget)) {
00135         // potentially animate progressbars
00136         widget->installEventFilter(this);
00137     }
00138 }
00139 
00141 // polish()
00142 // --------
00143 // Initialize the palette
00144 
00145 void PhaseStyle::polish(QPalette &pal)
00146 {
00147     // clear out gradients on a color change
00148     QPixmapCache::clear();
00149 
00150     // adjust bevel colors to have better contrast (KDE like)
00151     QColor background;
00152 
00153     int highlightval = 100 + (2*(contrast_-100)+4)*16/10;
00154     int lowlightval = 100 + (2*(contrast_-100)+4)*10;
00155 
00156     background = pal.color(QPalette::Active, QPalette::Window);
00157     pal.setColor(QPalette::Active, QPalette::Light,
00158                  background.lighter(highlightval));
00159     pal.setColor(QPalette::Active, QPalette::Dark,
00160                  background.darker(lowlightval));
00161     pal.setColor(QPalette::Active, QPalette::Mid,
00162                  background.darker(120));
00163     pal.setColor(QPalette::Active, QPalette::Midlight,
00164                  background.lighter(110));
00165 
00166     background = pal.color(QPalette::Inactive, QPalette::Window);
00167     pal.setColor(QPalette::Inactive, QPalette::Light,
00168                  background.lighter(highlightval));
00169     pal.setColor(QPalette::Inactive, QPalette::Dark,
00170                  background.darker(lowlightval));
00171     pal.setColor(QPalette::Inactive, QPalette::Mid,
00172                  background.darker(120));
00173     pal.setColor(QPalette::Inactive, QPalette::Midlight,
00174                  background.lighter(110));
00175 
00176     background = pal.color(QPalette::Disabled, QPalette::Window);
00177     pal.setColor(QPalette::Disabled, QPalette::Light,
00178                  background.lighter(highlightval));
00179     pal.setColor(QPalette::Disabled, QPalette::Dark,
00180                  background.darker(lowlightval));
00181     pal.setColor(QPalette::Disabled, QPalette::Mid,
00182                  background.darker(120));
00183     pal.setColor(QPalette::Disabled, QPalette::Midlight,
00184                  background.lighter(110));
00185 }
00186 
00188 // unPolish()
00189 // ----------
00190 // Undo the application polish
00191 
00192 void PhaseStyle::unpolish(QApplication *app)
00193 {
00194     QWindowsStyle::unpolish(app);
00195 }
00196 
00198 // unPolish()
00199 // ----------
00200 // Undo the initialization of a widget appearance
00201 
00202 void PhaseStyle::unpolish(QWidget *widget)
00203 {
00204     if (highlights_ &&
00205                (qobject_cast<QPushButton*>(widget) ||
00206                 qobject_cast<QComboBox*>(widget) ||
00207                 qobject_cast<QAbstractSpinBox*>(widget) ||
00208                 qobject_cast<QCheckBox*>(widget) ||
00209                 qobject_cast<QRadioButton*>(widget) ||
00210                 qobject_cast<QSplitterHandle*>(widget) ||
00211                 qobject_cast<QSlider*>(widget) ||
00212                 qobject_cast<QTabBar*>(widget))) {
00213         // turn off mouseover highlighting
00214         widget->setAttribute(Qt::WA_Hover, false);
00215     }
00216     if (widget->inherits("QDockSeparator")
00217         || widget->inherits("QDockWidgetSeparator")) {
00218         widget->setAttribute(Qt::WA_Hover, false);
00219     }
00220     if (qobject_cast<QProgressBar*>(widget)) {
00221         widget->removeEventFilter(this);
00222     }
00223 }
00224 
00226 // standardPalette()
00227 // -----------------
00228 // Return a standard palette
00229 
00230 QPalette PhaseStyle::standardPalette() const
00231 {
00232     QColor window(0xee, 0xee, 0xee);
00233     QColor button(0xdd, 0xdd, 0xe3);
00234     QColor highlight(0x60, 0x90, 0xc0);
00235     QPalette pal(window, window);
00236 
00237     pal.setBrush(QPalette::Button, button);
00238     pal.setBrush(QPalette::Highlight, highlight);
00239 
00240     pal.setBrush(QPalette::Disabled, QPalette::Button, window);
00241     pal.setBrush(QPalette::Disabled, QPalette::Foreground, window.darker());
00242     pal.setBrush(QPalette::Disabled, QPalette::Text, window.darker());
00243     pal.setBrush(QPalette::Disabled, QPalette::ButtonText, window.darker());
00244 
00245     return pal;
00246 }
00247 
00249 // Drawing                                                                  //
00251 
00253 // drawPhaseGradient()
00254 // ------------------
00255 // Draw a gradient
00256 
00257 void PhaseStyle::drawPhaseGradient(QPainter *painter,
00258                                    const QRect &rect,
00259                                    QColor color,
00260                                    bool horizontal,
00261                                    const QSize &gsize,
00262                                    bool reverse) const
00263 {
00264     if (!gradients_) {
00265         painter->fillRect(rect, color);
00266         return;
00267     }
00268 
00269     int size = (horizontal) ? gsize.width() :  gsize.height();
00270 
00271     if (size > MAXGRADIENTSIZE) { // keep it sensible
00272         painter->fillRect(rect, color);
00273         return;
00274     }
00275 
00276     GradientType type;
00277     QString name;
00278     QPixmap pixmap;
00279 
00280     if (horizontal) type = (reverse) ? HorizontalReverse : Horizontal;
00281     else            type = (reverse) ? VerticalReverse : Vertical;
00282 
00283     name = QString("%1.%2.%3").arg(color.name()).arg(size).arg(type);
00284     if (!QPixmapCache::find(name, pixmap)) {
00285         QPainter cachepainter;
00286 
00287         switch (type) {
00288           case Horizontal: {
00289               pixmap = QPixmap(size, 16);
00290               QLinearGradient gradient(0, 0, size, 0);
00291               gradient.setColorAt(0, color.lighter(contrast_));
00292               gradient.setColorAt(1, color.darker(contrast_));
00293               cachepainter.begin(&pixmap);
00294               cachepainter.fillRect(pixmap.rect(), gradient);
00295               cachepainter.end();
00296               break;
00297           }
00298           case HorizontalReverse: {
00299               pixmap = QPixmap(size, 16);
00300               QLinearGradient gradient(0, 0, size, 0);
00301               gradient.setColorAt(0, color.darker(contrast_));
00302               gradient.setColorAt(1, color.lighter(contrast_));
00303               cachepainter.begin(&pixmap);
00304               cachepainter.fillRect(pixmap.rect(), gradient);
00305               cachepainter.end();
00306               break;
00307           }
00308           case Vertical: {
00309               pixmap = QPixmap(16, size);
00310               QLinearGradient gradient(0, 0, 0, size);
00311               gradient.setColorAt(0, color.lighter(contrast_));
00312               gradient.setColorAt(1, color.darker(contrast_));
00313               cachepainter.begin(&pixmap);
00314               cachepainter.fillRect(pixmap.rect(), gradient);
00315               cachepainter.end();
00316               break;
00317           }
00318           case VerticalReverse: {
00319               pixmap = QPixmap(16, size);
00320               QLinearGradient gradient(0, 0, 0, size);
00321               gradient.setColorAt(0, color.darker(contrast_));
00322               gradient.setColorAt(1, color.lighter(contrast_));
00323               cachepainter.begin(&pixmap);
00324               cachepainter.fillRect(pixmap.rect(), gradient);
00325               cachepainter.end();
00326               break;
00327           }
00328           default:
00329               break;
00330         }
00331         QPixmapCache::insert(name, pixmap);
00332     }
00333 
00334     painter->drawTiledPixmap(rect, pixmap);
00335 }
00336 
00338 // drawPhaseBevel()
00339 // ----------------
00340 // Draw the basic Phase bevel
00341 
00342 void PhaseStyle::drawPhaseBevel(QPainter *painter,
00343                                 QRect rect,
00344                                 const QPalette &pal,
00345                                 const QBrush &fill,
00346                                 bool sunken,
00347                                 bool horizontal,
00348                                 bool reverse) const
00349 {
00350     int x, y, w, h;
00351     rect.getRect(&x, &y, &w, &h);
00352     int x2 = rect.right();
00353     int y2 = rect.bottom();
00354 
00355     QPen pen = painter->pen();
00356 
00357     painter->setPen(pal.dark().color());
00358     painter->drawRect(rect.adjusted(0, 0, -1, -1));
00359 
00360     painter->setPen(sunken ? pal.mid().color() : pal.midlight().color());
00361     painter->drawLine(x+1, y+1, x2-2, y+1);
00362     painter->drawLine(x+1, y+2, x+1, y2-2);
00363 
00364     painter->setPen(sunken ? pal.midlight().color() : pal.mid().color());
00365     painter->drawLine(x+2, y2-1, x2-1, y2-1);
00366     painter->drawLine(x2-1, y+2, x2-1, y2-2);
00367 
00368     painter->setPen(pal.button().color());
00369     painter->drawPoint(x+1, y2-1);
00370     painter->drawPoint(x2-1, y+1);
00371 
00372     if (sunken) {
00373         // sunken bevels don't get gradients
00374         painter->fillRect(rect.adjusted(2, 2, -2, -2), fill);
00375     } else {
00376         drawPhaseGradient(painter, rect.adjusted(2, 2, -2, -2), fill.color(),
00377                           horizontal, QSize(w-4, h-4), reverse);
00378     }
00379     painter->setPen(pen);
00380 }
00381 
00383 // drawPhaseButton()
00384 // ----------------
00385 // Draw the basic Phase button
00386 
00387 void PhaseStyle::drawPhaseButton(QPainter *painter,
00388                                  QRect rect,
00389                                  const QPalette &pal,
00390                                  const QBrush &fill,
00391                                  bool sunken) const
00392 {
00393     int x, y, w, h;
00394     rect.getRect(&x, &y, &w, &h);
00395     int x2 = rect.right();
00396     int y2 = rect.bottom();
00397 
00398     QPen pen = painter->pen();
00399 
00400     painter->setPen(pal.midlight().color());
00401     painter->drawLine(x+1, y2, x2, y2);
00402     painter->drawLine(x2, y+1, x2, y2-1);
00403 
00404     painter->setPen(pal.mid().color());
00405     painter->drawLine(x, y,  x2-1, y);
00406     painter->drawLine(x, y+1, x, y2-1);
00407 
00408     painter->setPen(pal.window().color());
00409     painter->drawPoint(x, y2);
00410     painter->drawPoint(x2, y);
00411 
00412     painter->setPen(pen);
00413     drawPhaseBevel(painter, rect.adjusted(1, 1, -1, -1), pal, fill,
00414                    sunken, false, false);
00415 }
00416 
00418 // drawPhasePanel()
00419 // ----------------
00420 // Draw the basic Phase panel
00421 
00422 void PhaseStyle::drawPhasePanel(QPainter *painter,
00423                                 const QRect &rect,
00424                                 const QPalette &pal,
00425                                 const QBrush &fill,
00426                                 bool sunken) const
00427 {
00428     int x, y, w, h;
00429     rect.getRect(&x, &y, &w, &h);
00430     int x2 = rect.right();
00431     int y2 = rect.bottom();
00432 
00433     QPen pen = painter->pen();
00434 
00435     if (sunken) {
00436         painter->setPen(pal.dark().color());
00437         painter->drawRect(rect.adjusted(1, 1, -2, -2));
00438         painter->setPen(pal.midlight().color());
00439         painter->drawLine(x+1, y2, x2, y2);
00440         painter->drawLine(x2, y+1, x2, y2-1);
00441         painter->setPen(pal.mid().color());
00442         painter->drawLine(x, y, x, y2-1);
00443         painter->drawLine(x+1, y, x2-1, y);
00444         painter->setPen(pal.window().color());
00445         painter->drawPoint(x, y2);
00446         painter->drawPoint(x2, y);
00447     } else {
00448         painter->setPen(pal.dark().color());
00449         painter->drawRect(rect.adjusted(0, 0, -1, -1));
00450         painter->setPen(pal.midlight().color());
00451         painter->drawLine(x+1, y+1, x2-2, y+1);
00452         painter->drawLine(x+1, y+2, x+1, y2-2);
00453         painter->setPen(pal.mid().color());
00454         painter->drawLine(x+2, y2-1, x2-1, y2-1);
00455         painter->drawLine(x2-1, y+2, x2-1, y2-2);
00456         painter->setPen(pal.window().color());
00457         painter->drawPoint(x+1, y2-1);
00458         painter->drawPoint(x2-1, y+1);
00459     }
00460 
00461     painter->fillRect(rect.adjusted(2, 2, -2, -2), fill);
00462     painter->setPen(pen);
00463 }
00464 
00466 // drawPhaseDoodads()
00467 // ------------------
00468 // Draw three doodads in rect
00469 
00470 void PhaseStyle::drawPhaseDoodads(QPainter *painter,
00471                                   const QRect& rect,
00472                                   const QPalette &pal,
00473                                   bool horizontal) const
00474 {
00475     int cx = rect.center().x();
00476     int cy = rect.center().y();
00477 
00478     QPen pen = painter->pen();
00479     if (horizontal && (rect.width() >= 20)) {
00480         for (int n = -5; n <= 5; n += 5) {
00481             painter->setPen(pal.mid().color());
00482             painter->drawLine(cx-1+n, cy+1, cx-1+n, cy-1);
00483             painter->drawLine(cx+n, cy-1, cx+1+n, cy-1);
00484             painter->setPen(pal.light().color());
00485             painter->drawLine(cx+2+n, cy, cx+2+n, cy+2);
00486             painter->drawLine(cx+1+n, cy+2, cx+n, cy+2);
00487         }
00488     } else if (!horizontal && (rect.height() >= 20)) {
00489         for (int n = -5; n <= 5; n += 5) {
00490             painter->setPen(pal.mid().color());
00491             painter->drawLine(cx-1, cy+1+n, cx-1, cy-1+n);
00492             painter->drawLine(cx, cy-1+n, cx+1, cy-1+n);
00493             painter->setPen(pal.light().color());
00494             painter->drawLine(cx+2, cy+n, cx+2, cy+2+n);
00495             painter->drawLine(cx+1, cy+2+n, cx, cy+2+n);
00496         }
00497     }
00498     painter->setPen(pen);
00499 }
00500 
00502 // drawPhaseTab()
00503 // -------------
00504 // Draw a Phase style tab
00505 
00506 void PhaseStyle::drawPhaseTab(QPainter *painter,
00507                               const QPalette &pal,
00508                               const QStyleOptionTab *tab) const
00509 {
00510     const State &flags = tab->state;
00511     const QStyleOptionTab::TabPosition &tabpos = tab->position;
00512     const QStyleOptionTab::SelectedPosition &selpos = tab->selectedPosition;
00513 
00514     bool selected = (flags & State_Selected);
00515     bool mouseover = (flags & State_MouseOver) && !selected;
00516     bool vertical = (tab->shape == QTabBar::RoundedEast) ||
00517                     (tab->shape == QTabBar::RoundedWest);
00518     bool reverse = (tab->direction == Qt::RightToLeft);
00519     bool corner = (tab->cornerWidgets & QStyleOptionTab::LeftCornerWidget);
00520     bool first = (tabpos == QStyleOptionTab::Beginning);
00521     bool rlast = (tabpos == QStyleOptionTab::End) && reverse;
00522     bool only = (tabpos == QStyleOptionTab::OnlyOneTab);
00523     bool edge = (first && !corner) || only;
00524     bool leftedge = vertical ? edge : (edge && !reverse);
00525     bool rightedge = vertical ? edge : (edge && reverse);
00526     bool prevselected = (selpos == QStyleOptionTab::PreviousIsSelected);
00527     bool nextselected = (selpos == QStyleOptionTab::NextIsSelected);
00528     if (reverse && !vertical) {
00529         qSwap(prevselected, nextselected);
00530     }
00531 
00532     // get rectangle
00533     QRect rect = tab->rect;
00534     if (!selected) {
00535         switch (tab->shape) {
00536           case QTabBar::RoundedNorth:
00537           default:
00538               rect.adjust(0, 2, 0, 0);
00539               break;
00540 
00541           case QTabBar::RoundedSouth:
00542               rect.adjust(0, 0, 0, -2);
00543               break;
00544 
00545           case QTabBar::RoundedWest:
00546               rect.adjust(2, 0, 0, 0);
00547               break;
00548 
00549           case QTabBar::RoundedEast:
00550               rect.adjust(0, 0, -2, 0);
00551               break;
00552         }
00553     }
00554 
00555     int x, y, w, h;
00556     rect.getRect(&x, &y, &w, &h);
00557     const int x2 = rect.right();
00558     const int y2 = rect.bottom();
00559 
00560     painter->save();
00561 
00562     // draw tab
00563     switch (tab->shape) {
00564       case QTabBar::RoundedNorth:
00565       default:
00566           // draw fill
00567           if (selected) {
00568               painter->fillRect(rect.adjusted(0, 1, 0, 0), pal.window());
00569           } else {
00570               drawPhaseGradient(painter, rect.adjusted(0, 1, 0, -2),
00571                                 mouseover ?
00572                                 pal.window().color() :
00573                                 pal.window().color().darker(contrast_),
00574                                 false, QSize(w, h), false);
00575           }
00576 
00577           // top frame
00578           painter->setPen(pal.dark().color());
00579           painter->drawLine(x, y, x2, y);
00580 
00581           painter->setPen(pal.midlight().color());
00582           if (nextselected)      painter->drawLine(x+1, y+1, x2,   y+1);
00583           else if (prevselected) painter->drawLine(x,   y+1, x2-2, y+1);
00584           else                   painter->drawLine(x+1, y+1, x2-2, y+1);
00585 
00586           // left frame
00587           painter->setPen(pal.dark().color());
00588           if (leftedge && selected)  painter->drawLine(x, y, x, y2);
00589           if (leftedge && !selected) painter->drawLine(x, y, x, y2-2);
00590           if (!leftedge && selected) painter->drawLine(x, y, x, y2-1);
00591           if (!selected && rlast)    painter->drawLine(x, y, x, y2-2);
00592           painter->setPen(pal.midlight().color());
00593           if (selected)           painter->drawLine(x+1, y+1, x+1, y2);
00594           else if (leftedge)      painter->drawLine(x+1, y+1, x+1, y2-2);
00595           else if (rlast)         painter->drawLine(x+1, y+1, x+1, y2-2);
00596           else if (!prevselected) painter->drawLine(x,   y+1, x,   y2-2);
00597           if (selected && !leftedge) painter->drawPoint(x, y2);
00598 
00599           // right frame
00600           if (!nextselected) {
00601               painter->setPen(pal.dark().color());
00602               if (rightedge && selected) painter->drawLine(x2, y+1, x2, y2);
00603               if (rightedge)             painter->drawLine(x2, y+1, x2, y2+1);
00604               else                       painter->drawLine(x2, y+1, x2, y2-1);
00605               painter->setPen(pal.mid().color());
00606               if (rightedge && selected) painter->drawLine(x2-1, y+2, x2-1, y2);
00607               else if (selected) painter->drawLine(x2-1, y+2, x2-1, y2-1);
00608               else               painter->drawLine(x2-1, y+2, x2-1, y2-2);
00609 
00610               if (selected && !rightedge) {
00611                   painter->setPen(pal.midlight().color());
00612                   painter->drawPoint(x2, y2);
00613               }
00614           }
00615 
00616           break;
00617 
00618       case QTabBar::RoundedSouth:
00619           // draw fill
00620           if (selected) {
00621               painter->fillRect(rect.adjusted(0, 0, 0, -1), pal.window());
00622           } else {
00623               drawPhaseGradient(painter, rect.adjusted(0, 2, 0, -1),
00624                                 mouseover ?
00625                                 pal.window().color() :
00626                                 pal.window().color().darker(contrast_),
00627                                 false, QSize(w, h), false);
00628           }
00629 
00630           // bottom frame
00631           painter->setPen(pal.dark().color());
00632           painter->drawLine(x, y2, x2, y2);
00633 
00634           painter->setPen(pal.mid().color());
00635           if (nextselected)      painter->drawLine(x, y2-1, x2,   y2-1);
00636           else                   painter->drawLine(x, y2-1, x2-1, y2-1);
00637 
00638           painter->setPen(pal.window().color());
00639           if (selected || first)  painter->drawPoint(x+1, y2-1);
00640           else if (!prevselected) painter->drawPoint(x,   y2-1);
00641 
00642           // left frame
00643           painter->setPen(pal.dark().color());
00644           if (selected && leftedge) painter->drawLine(x, y,   x, y2);
00645           else if (selected || leftedge || rlast) painter->drawLine(x, y+1, x, y2);
00646 
00647           painter->setPen(pal.midlight().color());
00648           if (!prevselected) {
00649               if (leftedge && selected)       painter->drawLine(x+1, y,   x+1, y2-2);
00650               else if (leftedge && !selected) painter->drawLine(x+1, y+2, x+1, y2-2);
00651               else if (selected)              painter->drawLine(x+1, y+1, x+1, y2-2);
00652               else if (rlast)                 painter->drawLine(x+1, y+2, x+1, y2-2);
00653               else                            painter->drawLine(x,   y+2, x,   y2-2);
00654           }
00655 
00656           if (selected && !leftedge) {
00657               painter->setPen(pal.mid().color());
00658               painter->drawPoint(x, y);
00659           }
00660 
00661           // right frame
00662           if (!nextselected) {
00663               painter->setPen(pal.dark().color());
00664               if (rightedge && selected) painter->drawLine(x2, y, x2, y2-1);
00665               else                       painter->drawLine(x2, y+1, x2, y2-1);
00666 
00667               painter->setPen(pal.mid().color());
00668               if (selected) {
00669                   painter->drawLine(x2-1, y,   x2-1, y2-2);
00670                   if (!rightedge) painter->drawPoint(x2, y);
00671               } else {
00672                   painter->drawLine(x2-1, y+2, x2-1, y2-2);
00673               }
00674           }
00675           break;
00676 
00677       case QTabBar::RoundedWest:
00678           // draw fill
00679           if (selected) {
00680               painter->fillRect(rect.adjusted(1, 0, 0, 0), pal.window());
00681           } else {
00682               drawPhaseGradient(painter, rect.adjusted(1, 0, -2, 0),
00683                                 mouseover ?
00684                                 pal.window().color() :
00685                                 pal.window().color().darker(contrast_),
00686                                 true, QSize(w, h), false);
00687           }
00688 
00689           // left frame
00690           painter->setPen(pal.dark().color());
00691           painter->drawLine(x, y, x, y2);
00692 
00693           painter->setPen(pal.midlight().color());
00694           if (nextselected)      painter->drawLine(x+1, y+1, x+1, y2);
00695           else if (prevselected) painter->drawLine(x+1, y,   x+1, y2-2);
00696           else                   painter->drawLine(x+1, y+1, x+1, y2-2);
00697 
00698           // top frame
00699           painter->setPen(pal.dark().color());
00700           if (leftedge || selected) painter->drawLine(x, y, x2-1, y);
00701           if (leftedge && selected) painter->drawPoint(x2, y);
00702 
00703           painter->setPen(pal.midlight().color());
00704           if (leftedge && selected)       painter->drawLine(x+1, y+1, x2,   y+1);
00705           else if (leftedge && !selected) painter->drawLine(x+1, y+1, x2-2, y+1);
00706           else if (selected)              painter->drawLine(x+1, y+1, x2,   y+1);
00707           else if (!prevselected)         painter->drawLine(x+1, y,   x2-2, y);
00708           if (!leftedge && selected)      painter->drawPoint(x2, y);
00709 
00710           // bottom frame
00711           if (!nextselected) {
00712               painter->setPen(pal.dark().color());
00713               if (rightedge && selected) painter->drawLine(x, y2, x2, y2);
00714               else if (selected)        painter->drawLine(x, y2, x2-1, y2);
00715               else                       painter->drawLine(x, y2, x2-2, y2);
00716 
00717               painter->setPen(pal.mid().color());
00718               if (selected) painter->drawLine(x+2, y2-1, x2-1, y2-1);
00719               else          painter->drawLine(x+2, y2-1, x2-2, y2-1);
00720 
00721               if (selected) {
00722                   painter->setPen(pal.midlight().color());
00723                   if (!rightedge) painter->drawPoint(x2, y2);
00724               }
00725           }
00726           break;
00727 
00728       case QTabBar::RoundedEast:
00729           // draw fill
00730           if (selected) {
00731               painter->fillRect(rect.adjusted(0, 0, -1, 0), pal.window());
00732           } else {
00733               drawPhaseGradient(painter, rect.adjusted(2, 0, -1, 0),
00734                                 mouseover ?
00735                                 pal.window().color() :
00736                                 pal.window().color().darker(contrast_),
00737                                 true, QSize(w, h), false);
00738           }
00739 
00740           // right frame
00741           painter->setPen(pal.dark().color());
00742           painter->drawLine(x2, y, x2, y2);
00743 
00744           painter->setPen(pal.mid().color());
00745           if (selected)          painter->drawLine(x2-1, y+2, x2-1, y2-1);
00746           else if (leftedge)     painter->drawLine(x2-1, y+2, x2-1, y2);
00747           else if (nextselected) painter->drawLine(x2-1, y+1, x2-1, y2);
00748           else if (prevselected) painter->drawLine(x2-1, y,   x2-1, y2-1);
00749           else                   painter->drawLine(x2-1, y+1, x2-1, y2-1);
00750 
00751           // top frame
00752           painter->setPen(pal.dark().color());
00753           if (leftedge || selected) painter->drawLine(x+1, y, x2, y);
00754           if (leftedge && selected) painter->drawPoint(x, y);
00755 
00756           painter->setPen(pal.midlight().color());
00757           if (leftedge && selected)       painter->drawLine(x,   y+1, x2-2, y+1);
00758           else if (leftedge && !selected) painter->drawLine(x+2, y+1, x2-2, y+1);
00759           else if (selected)              painter->drawLine(x+1, y+1, x2-2, y+1);
00760           else if (!prevselected)         painter->drawLine(x+2, y,   x2-2, y);
00761           if (!leftedge && selected)      painter->drawPoint(x+1, y+1);
00762 
00763           if (!leftedge && selected) {
00764               painter->setPen(pal.mid().color());
00765               painter->drawPoint(x, y);
00766           }
00767 
00768           // bottom frame
00769           if (!nextselected) {
00770               painter->setPen(pal.dark().color());
00771               if (rightedge && selected) painter->drawLine(x, y2, x2, y2);
00772               else if (selected)         painter->drawLine(x+1, y2, x2, y2);
00773               else                       painter->drawLine(x+1, y2, x2, y2);
00774 
00775               painter->setPen(pal.mid().color());
00776               if (selected) {
00777                   painter->drawLine(x,   y2-1, x2-2, y2-1);
00778                   if (!rightedge) painter->drawPoint(x, y2);
00779               } else {
00780                   painter->drawLine(x+2, y2-1, x2-2, y2-1);
00781               }
00782           }
00783           break;
00784     }
00785 
00786     painter->restore();
00787 }
00788 
00790 // drawPrimitive()
00791 // ---------------
00792 // Draw a primitive element
00793 
00794 void PhaseStyle::drawPrimitive(PrimitiveElement element,
00795                                const QStyleOption *option,
00796                                QPainter *painter,
00797                                const QWidget *widget) const
00798 {
00799     // shorthand
00800     const State &flags = option->state;
00801     const QPalette &pal = option->palette;
00802     const QRect &rect = option->rect;
00803 
00804     // common states
00805     bool sunken    = flags & State_Sunken;
00806     bool on        = flags & State_On;
00807     bool depress   = (sunken || on);
00808     bool enabled   = flags & State_Enabled;
00809     bool horiz     = flags & State_Horizontal;
00810     bool mouseover = highlights_ && (flags & State_MouseOver) && enabled;
00811 
00812     int x, y, w, h;
00813     rect.getRect(&x, &y, &w, &h);
00814     int x2 = rect.right();
00815     int y2 = rect.bottom();
00816     int cx = rect.center().x();
00817     int cy = rect.center().y();
00818 
00819     QPolygon polygon;
00820 
00821     painter->save();
00822 
00823     switch (element) {
00824       case PE_PanelButtonCommand:       // command button (QPushbutton)
00825           drawPhaseButton(painter, rect, pal, mouseover ?
00826                           pal.button().color().lighter(contrast_) :
00827                           pal.button(), depress);
00828           break;
00829 
00830       case PE_FrameButtonBevel:         // panel frame for a button bevel
00831       case PE_FrameButtonTool:          // panel frame for a tool button
00832           drawPhaseBevel(painter, rect, pal, Qt::NoBrush,
00833                          depress, false, false);
00834           break;
00835 
00836       case PE_PanelButtonBevel:         // generic panel with a button bevel
00837       case PE_IndicatorButtonDropDown:  // indicator for a drop down button
00838           drawPhaseBevel(painter, rect, pal, mouseover ?
00839                          pal.button().color().lighter(contrast_) :
00840                          pal.button(),
00841                          depress, false, false);
00842           break;
00843 
00844       case PE_PanelButtonTool:          // panel for a tool button
00845           if (widget && widget->inherits("QDockWidgetTitleButton")) {
00846               bool floating = (widget->parentWidget() && widget->parentWidget()->isWindow());
00847 
00848               if (mouseover || floating) {
00849                   drawPhasePanel(painter, rect, pal,
00850                                  pal.window().color(), depress);
00851               }
00852               break;
00853           }
00854 
00855           drawPhaseBevel(painter, rect, pal, mouseover ?
00856                          pal.button().color().lighter(contrast_) :
00857                          pal.button(),
00858                          depress, false, true);
00859           break;
00860 
00861       case PE_FrameDefaultButton:       // the frame around a default button
00862           drawPhasePanel(painter, rect, pal, pal.mid(), true);
00863           break;
00864 
00865       case PE_Frame:                    // generic styled frame
00866       case PE_FrameLineEdit:            // frame around line edit
00867       case PE_FrameMenu:                // frame for popup windows/menus
00868       case PE_FrameDockWidget:          // frame for dock windows and toolbars
00869       case PE_FrameTabWidget:           // frame around tab widgets
00870           drawPhasePanel(painter, rect, pal, Qt::NoBrush, sunken);
00871           break;
00872 
00873       case PE_FrameTabBarBase:          // frame for base of a tab bar
00874           // don't draw anything
00875           break;
00876 
00877       case PE_FrameWindow:              // frame for MDI or docking window
00878           drawPhasePanel(painter, rect, pal, Qt::NoBrush, sunken);
00879           // needs a black border
00880           painter->setPen(pal.shadow().color());
00881           painter->drawRect(rect.adjusted(0, 0, -1, -1));
00882           break;
00883 
00884       case PE_FrameGroupBox:            // frame around a group box
00885           painter->setPen(pal.dark().color());
00886           painter->drawRect(rect.adjusted(0, 0, -1, -1));
00887           break;
00888 
00889       case PE_FrameFocusRect: {         // generic focus indicator
00890           QColor focus(pal.highlight().color());
00891           focus.setAlphaF(0.66);
00892           painter->setPen(focus);
00893           painter->drawRect(rect.adjusted(0, 0, -1, -1));
00894           break;
00895       }
00896 
00897       case PE_IndicatorCheckBox:        // on/off indicator for check box
00898           drawPhasePanel(painter, rect.adjusted(1, 1, -1, -1),
00899                          pal, enabled ? pal.base() : pal.window(), true);
00900 
00901           if (mouseover) {
00902               painter->setPen(pal.highlight().color().darker(contrast_));
00903           } else if (on || (flags & State_NoChange)) {
00904               painter->setPen(pal.dark().color());
00905           } else {
00906               painter->setPen(Qt::NoPen);
00907           }
00908           if (on) {
00909               painter->setBrush(pal.highlight());
00910           } else if (flags & State_NoChange) {
00911               painter->setBrush(pal.mid());
00912           }
00913 
00914           painter->drawRect(rect.adjusted(4, 4, -5, -5));
00915           break;
00916 
00917       case PE_IndicatorRadioButton:     // on/off indicator for radio button
00918           painter->setBrush(enabled ? pal.base() : pal.window());
00919 
00920           painter->setPen(pal.dark().color());
00921           polygon.setPoints(8, x+1,cy+1, x+1,cy,    cx,y+1,    cx+1,y+1,
00922                                x2-1,cy,  x2-1,cy+1, cx+1,y2-1, cx,y2-1);
00923           painter->drawConvexPolygon(polygon);
00924 
00925           painter->setPen(pal.mid().color());
00926           polygon.setPoints(4, x,cy, cx,y, cx+1,y, x2,cy);
00927           painter->drawPolyline(polygon);
00928           painter->setPen(pal.midlight().color());
00929           polygon.setPoints(4, x2,cy+1, cx+1,y2, cx,y2, x,cy+1);
00930           painter->drawPolyline(polygon);
00931 
00932           if (on) {
00933               painter->setBrush(pal.highlight());
00934               painter->setPen(mouseover
00935                               ? pal.highlight().color().darker(contrast_)
00936                               : pal.dark().color());
00937               polygon.setPoints(8, x+4,cy+1, x+4,cy,    cx,y+4,    cx+1,y+4,
00938                                    x2-4,cy,  x2-4,cy+1, cx+1,y2-4, cx,y2-4);
00939               painter->drawConvexPolygon(polygon);
00940           } else if (mouseover) {
00941               painter->setPen(pal.highlight().color().darker(contrast_));
00942               polygon.setPoints(9, x+4,cy+1, x+4,cy,    cx,y+4,    cx+1,y+4,
00943                                    x2-4,cy,  x2-4,cy+1, cx+1,y2-4, cx,y2-4,
00944                                    x+4,cy+1);
00945               painter->drawPolyline(polygon);
00946           }
00947           break;
00948 
00949       case PE_IndicatorHeaderArrow: {   // sort arrow on view header
00950           const QStyleOptionHeader *header;
00951           header = qstyleoption_cast<const QStyleOptionHeader *>(option);
00952           if (header) {
00953               if (header->sortIndicator & QStyleOptionHeader::SortUp) {
00954                   drawPrimitive(PE_IndicatorArrowUp, option, painter, widget);
00955               } else {
00956                   drawPrimitive(PE_IndicatorArrowDown, option, painter, widget);
00957               }
00958           }
00959           break;
00960       }
00961 
00962       case PE_PanelMenuBar:             // panel for menu bars
00963       case PE_PanelToolBar:             // panel for a toolbar
00964           // adjust rect so we can use bevel
00965           drawPhaseBevel(painter, rect.adjusted(-1, -1, 0, 0),
00966                          pal, pal.window(), false, (w < h),
00967                          (element==PE_PanelToolBar) ? true : false);
00968           break;
00969 
00970       case PE_FrameStatusBar:           // frame for a section of a status bar
00971           painter->setPen(pal.mid().color());
00972           painter->drawLine(x, y,  x2-1, y);
00973           painter->drawLine(x, y+1, x, y2-1);
00974           painter->setPen(pal.midlight().color());
00975           painter->drawLine(x+1, y2, x2, y2);
00976           painter->drawLine(x2, y+1, x2, y2-1);
00977           break;
00978 
00979       case PE_IndicatorDockWidgetResizeHandle: // resize handle for docks
00980           painter->fillRect(rect,
00981                             (mouseover) ?
00982                             pal.window().color().lighter(contrast_) :
00983                             pal.window());
00984           drawPhaseDoodads(painter, rect, pal, horiz);
00985           break;
00986 
00987 
00988       case PE_IndicatorMenuCheckMark:   // check mark used in a menu
00989           if (on) {
00990               painter->setBrush(pal.highlightedText());
00991           } else {
00992               painter->setBrush(sunken ? pal.dark() : pal.text());
00993           }
00994           painter->setPen(painter->brush().color());
00995           painter->drawPixmap(cx-4, cy-4, bitmaps_[CheckMark]);
00996           break;
00997 
00998       case PE_IndicatorViewItemCheck:   // on/off indicator for a view item
00999       case PE_Q3CheckListIndicator: {   // Q3 checkbox of a list view item
01000           painter->setPen(pal.text().color());
01001           // draw box
01002           QRect box(0, 0, 13, 13);
01003           box.moveCenter(rect.center());
01004           painter->drawRect(box);
01005           painter->drawRect(box.adjusted(1,1,-1,-1));
01006           // draw check
01007           if (flags & State_On) {
01008               painter->setBrush(pal.text());
01009               painter->setPen(painter->brush().color());
01010               painter->drawPixmap(cx-4, cy-4, bitmaps_[CheckMark]);
01011           }
01012           break;
01013       }
01014 
01015       case PE_IndicatorBranch: {        // branch lines of a tree view
01016           if (pal.color(QPalette::Active, QPalette::Base).value() < 192) {
01017               painter->setPen(pal.text().color());
01018               painter->setBrush(pal.text());
01019           } else {
01020               painter->setPen(pal.mid().color());
01021               painter->setBrush(pal.mid());
01022           }
01023 
01024           int spacer = 0;
01025           // draw expander
01026           if (flags & State_Children) {
01027               QPolygon poly;
01028               if (flags & State_Open) {
01029                   poly.setPoints(3, -4,-2, 4,-2, 0,2);
01030               } else {
01031                   poly.setPoints(3, -2,-4, 2,0, -2,4);
01032               }
01033               poly.translate(cx, cy);
01034               painter->drawPolygon(poly);
01035 
01036               spacer = 6;
01037           }
01038 
01039           // draw lines
01040           if (flags & State_Item) {
01041               if (option->direction == Qt::RightToLeft)
01042                   painter->drawLine(x, cy, cx-spacer, cy);
01043               else
01044                   painter->drawLine(cx+spacer, cy, x2, cy);
01045           }
01046           if (flags & State_Sibling) {
01047               painter->drawLine(cx, cy+spacer, cx, y2);
01048           }
01049           if (flags & (State_Item|State_Sibling)) {
01050               painter->drawLine(cx, cy-spacer, cx, y);
01051           }
01052           break;
01053       }
01054 
01055       case PE_IndicatorToolBarHandle:   // toolbar handle
01056           drawPhaseGradient(painter, rect, pal.window().color(),
01057                             !horiz, rect.size(), true);
01058           drawPhaseDoodads(painter, rect, pal, !horiz);
01059           break;
01060 
01061       case PE_Q3DockWindowSeparator:     // Q3 dock/toolbar separator
01062       case PE_IndicatorToolBarSeparator: // toolbar separator
01063           // TODO: lines don't go to edge of bar, need to fix
01064           if (horiz) {
01065               painter->setPen(pal.mid().color());
01066               painter->drawLine(cx, 0, cx, y2);             
01067               painter->setPen(pal.midlight().color());
01068               painter->drawLine(cx+1, 0, cx+1, y2);
01069           } else {
01070               painter->setPen(pal.mid().color());
01071               painter->drawLine(0, cy, x2, cy);
01072               painter->setPen(pal.midlight().color());
01073               painter->drawLine(0, cy+1, x2, cy+1);
01074           }
01075           break;
01076 
01077       case PE_IndicatorArrowUp:         // generic up arrow
01078       case PE_IndicatorSpinUp:          // spin up arrow
01079           painter->setBrush(enabled ? pal.dark() : pal.mid());
01080           painter->setPen(painter->brush().color());
01081           if (sunken) painter->translate(pixelMetric(PM_ButtonShiftHorizontal),
01082                                          pixelMetric(PM_ButtonShiftVertical));
01083           painter->drawPixmap(cx-2, cy-2, bitmaps_[UArrow]);
01084           break;
01085 
01086       case PE_IndicatorArrowDown:       // generic down arrow
01087       case PE_IndicatorSpinDown:        // spin down arrow
01088           painter->setBrush(enabled ? pal.dark() : pal.mid());
01089           painter->setPen(painter->brush().color());
01090           if (sunken) painter->translate(pixelMetric(PM_ButtonShiftHorizontal),
01091                                          pixelMetric(PM_ButtonShiftVertical));
01092           painter->drawPixmap(cx-2, cy-2, bitmaps_[DArrow]);
01093           break;
01094 
01095       case PE_IndicatorArrowLeft:       // generic left arrow
01096           painter->setBrush(enabled ? pal.dark() : pal.mid());
01097           painter->setPen(painter->brush().color());
01098           if (sunken) painter->translate(pixelMetric(PM_ButtonShiftHorizontal),
01099                                          pixelMetric(PM_ButtonShiftVertical));
01100           painter->drawPixmap(cx-2, cy-2, bitmaps_[LArrow]);
01101           break;
01102 
01103       case PE_IndicatorArrowRight:      // generic right arrow
01104           painter->setBrush(enabled ? pal.dark() : pal.mid());
01105           painter->setPen(painter->brush().color());
01106           if (sunken) painter->translate(pixelMetric(PM_ButtonShiftHorizontal),
01107                                          pixelMetric(PM_ButtonShiftVertical));
01108           painter->drawPixmap(cx-2, cy-2, bitmaps_[RArrow]);
01109           break;
01110 
01111       case PE_IndicatorSpinPlus:        // spin plus sign
01112           painter->setBrush(enabled ? pal.dark() : pal.mid());
01113           painter->setPen(painter->brush().color());
01114           if (sunken) painter->translate(pixelMetric(PM_ButtonShiftHorizontal),
01115                                          pixelMetric(PM_ButtonShiftVertical));
01116           painter->drawPixmap(cx-2, cy-2, bitmaps_[PlusSign]);
01117           break;
01118 
01119       case PE_IndicatorSpinMinus:       // spin minus sign
01120           painter->setBrush(enabled ? pal.dark() : pal.mid());
01121           painter->setPen(painter->brush().color());
01122           if (sunken) painter->translate(pixelMetric(PM_ButtonShiftHorizontal),
01123                                          pixelMetric(PM_ButtonShiftVertical));
01124           painter->drawPixmap(cx-2, cy-2, bitmaps_[MinusSign]);
01125           break;
01126 
01127       // not drawing these elements, as default is sufficient
01128       // case PE_PanelLineEdit:            // panel for a line edit
01129       // case PE_Q3Separator:              // Q3 generic separator
01130       // case PE_IndicatorTabTear:         // jaggy torn tab indicator
01131       // case PE_IndicatorProgressChunk:   // section of progress bar
01132       // case PE_Q3CheckListController:    // Q3 controller of a list view item
01133       // case PE_Q3CheckListExclusiveIndicator: // Q3 radio of a list view item
01134       // case PE_PanelTipLabel:            // panel for a tip
01135 
01136       default:
01137           QWindowsStyle::drawPrimitive(element, option, painter, widget);
01138           break;
01139     }
01140 
01141     painter->restore();
01142 }
01143 
01145 // drawControl()
01146 // -------------
01147 // Draw a control
01148 
01149 void PhaseStyle::drawControl(ControlElement element,
01150                              const QStyleOption *option,
01151                              QPainter *painter,
01152                              const QWidget *widget) const
01153 {
01154     const QRect &rect = option->rect;
01155     const State &flags = option->state;
01156     const QPalette &pal = option->palette;
01157     bool depress = flags & (State_Sunken | State_On);
01158     bool enabled = flags & State_Enabled;
01159     bool horizontal = flags & State_Horizontal;
01160     bool mouseover = highlights_ && (flags & State_MouseOver) && enabled;
01161 
01162     int x, y, w, h;
01163     rect.getRect(&x, &y, &w, &h);
01164     int x2 = rect.right();
01165     int y2 = rect.bottom();
01166     //int cx = rect.center().x();
01167     int cy = rect.center().y();
01168 
01169     switch (element) {
01170       case CE_PushButtonBevel: { // QPushButton bevel and default indicator
01171           const QStyleOptionButton *button;
01172           button = qstyleoption_cast<const QStyleOptionButton *>(option);
01173           if (!button) break;
01174 
01175           if (!depress &&
01176               (button->features & QStyleOptionButton::DefaultButton)) {
01177               // draw default frame
01178               drawPrimitive(PE_FrameDefaultButton,
01179                             option, painter, widget);
01180               // adjust size for bevel
01181               int dbi = pixelMetric(PM_ButtonDefaultIndicator,
01182                                     button, widget);
01183               QStyleOptionButton tempopt = *button;
01184               tempopt.rect.adjust(dbi, dbi, -dbi, -dbi);
01185               // draw bevel
01186               drawPrimitive(PE_PanelButtonBevel,
01187                             &tempopt, painter, widget);
01188           } else if ((button->features & QStyleOptionButton::Flat)
01189                      && !depress) {
01190               // flat button, don't draw anything
01191           } else {
01192               // draw normal button
01193               drawPrimitive(PE_PanelButtonCommand,
01194                             button, painter, widget);
01195           }
01196 
01197           if (button->features & QStyleOptionButton::HasMenu) {
01198               // get arrow rect
01199               int mbi = pixelMetric(PM_MenuButtonIndicator,
01200                                     button, widget);
01201               QStyleOptionButton tempopt = *button;
01202               tempopt.rect = QRect(rect.right()- mbi, rect.height() - 20,
01203                                    mbi, rect.height() - 4);
01204               // draw arrow
01205               drawPrimitive(PE_IndicatorArrowDown,
01206                             &tempopt, painter, widget);
01207           }
01208           break;
01209       }
01210 
01211       case CE_DockWidgetTitle: {        // dock window title
01212           const QStyleOptionDockWidget *doption;
01213           doption = qstyleoption_cast<const QStyleOptionDockWidget*>(option);
01214           if (!doption) break;
01215 
01216           const QStyleOptionDockWidgetV2 *v2;
01217           v2 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(option);
01218           bool vertical = (v2 == 0) ? false : v2->verticalTitleBar;
01219 
01220           bool floating = false;
01221 
01222           if (doption->movable) {
01223               const QDockWidget *dwidget;
01224               dwidget = qobject_cast<const QDockWidget*>(widget);
01225               floating = (dwidget && dwidget->isFloating());
01226               if (floating) {
01227                   drawPhaseGradient(painter, rect,
01228                                     pal.highlight().color(),
01229                                     vertical, rect.size(), false);
01230               } else {
01231                   painter->setPen(pal.midlight().color());
01232                   painter->drawLine(x, y, x2-1, y);
01233                   painter->drawLine(x, y, x, y2-1);
01234                   painter->setPen(pal.mid().color());
01235                   painter->drawLine(x+1, y2, x2, y2);
01236                   painter->drawLine(x2, y+1, x2, y2);
01237                   drawPhaseGradient(painter, rect.adjusted(1, 1, -1, -1),
01238                                     pal.window().color(),
01239                                     vertical, QSize(w-2, h-2), false);
01240               }
01241           }
01242 
01243           if (!doption->title.isEmpty()) {
01244               painter->save();
01245 
01246               QRect trect = subElementRect(SE_DockWidgetTitleBarText,
01247                                            option, widget);
01248 
01249               if (vertical) {
01250                   painter->translate(trect.center().x(), trect.center().y());
01251                   painter->rotate(-90);
01252                   painter->translate(-trect.center().x(), -trect.center().y());
01253                   trect = painter->worldMatrix().inverted().mapRect(trect);
01254               }
01255 
01256               if (floating) {
01257                   QFont font = painter->font();
01258                   font.setBold(true);
01259                   painter->setFont(font);
01260               }
01261 
01262               drawItemText(painter,
01263                            trect.adjusted(4, 0, -4, -1),
01264                            Qt::AlignCenter | Qt::TextShowMnemonic,
01265                            pal, enabled, doption->title,
01266                            floating ? QPalette::HighlightedText : QPalette::WindowText);
01267 
01268               painter->restore();
01269           }
01270           break;
01271       }
01272 
01273       case CE_Splitter:              // splitter handle
01274           painter->fillRect(rect, mouseover ?
01275                             pal.window().color().lighter(contrast_) :
01276                             pal.window());
01277           drawPhaseDoodads(painter, rect, pal, !horizontal);
01278           break;
01279 
01280       case CE_TabBarTabShape: {      // tab shape within a tabbar
01281           const QStyleOptionTab *tab;
01282           tab = qstyleoption_cast<const QStyleOptionTab*>(option);
01283           if (!tab) break;
01284 
01285           // use default for triangular tabs
01286           if (tab->shape != QTabBar::RoundedNorth &&
01287               tab->shape != QTabBar::RoundedWest &&
01288               tab->shape != QTabBar::RoundedSouth &&
01289               tab->shape != QTabBar::RoundedEast) {
01290               QWindowsStyle::drawControl(element, option, painter, widget);
01291               break;
01292           }
01293           // this guy can get complicated, we we do it elsewhere
01294           drawPhaseTab(painter, pal, tab);
01295           break;
01296       }
01297 
01298       case CE_ProgressBarGroove:     // groove of progress bar
01299           drawPhasePanel(painter, rect, pal, pal.base(), true);
01300           break;
01301 
01302       case CE_ProgressBarContents: { // indicator of progress bar
01303           const QStyleOptionProgressBar *pbar;
01304           pbar = qstyleoption_cast<const QStyleOptionProgressBar*>(option);
01305           if (!pbar) break;
01306 
01307           bool vertical = false;
01308           bool inverted = false;
01309 
01310           // Get v2 options
01311           const QStyleOptionProgressBarV2 *pb2;
01312           pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2*>(option);
01313           if (pb2) {
01314               vertical = (pb2->orientation == Qt::Vertical);
01315               inverted = pb2->invertedAppearance;
01316           }
01317 
01318           if (vertical) {
01319               QMatrix matrix;
01320               qSwap(h, w); // flip width and height
01321               matrix.translate(h+5, 0.0);
01322               matrix.rotate(90.0);
01323               painter->setMatrix(matrix);
01324           }
01325 
01326           bool reverse = (vertical ||
01327                           (!vertical && (pbar->direction==Qt::RightToLeft)));
01328           if (inverted) reverse = !reverse;
01329 
01330           painter->save();
01331 
01332           painter->setBrush(pal.highlight());
01333           painter->setPen(pal.dark().color());
01334 
01335           if (pbar->minimum == 0 && pbar->maximum == 0) {
01336               // busy indicator
01337               int bar = pixelMetric(PM_ProgressBarChunkWidth, pbar, widget);
01338               int progress = pbar->progress % ((w-bar) * 2);
01339               if (progress > (w-bar)) progress = 2 * (w-bar) - progress;
01340               painter->drawRect(x+progress, y, bar-1, h-1);
01341           } else {
01342               double progress = (double)pbar->progress / (double)pbar->maximum;
01343               int dx = (int)(w * progress);
01344               if (dx > 2) {
01345                   if (reverse) x += w - dx;
01346                   painter->drawRect(x, y, dx-1, h-1);
01347               }
01348           }
01349           painter->restore();
01350           break;
01351       }
01352 
01353       case CE_ProgressBarLabel: {    // label of progress bar
01354           const QStyleOptionProgressBar *pbar;
01355           pbar = qstyleoption_cast<const QStyleOptionProgressBar*>(option);
01356           if (!pbar) break;
01357           if (pbar->minimum == 0 && pbar->maximum == 0) break;
01358 
01359           painter->save();
01360 
01361           bool vert = false;
01362           bool invert = false;
01363           bool btt = false; // bottom to top text orientation
01364           const QStyleOptionProgressBarV2 *pbar2;
01365           pbar2 = qstyleoption_cast<const QStyleOptionProgressBarV2*>(option);
01366           if (pbar2) {
01367               vert = (pbar2->orientation == Qt::Vertical);
01368               invert = pbar2->invertedAppearance;
01369               btt = pbar2->bottomToTop;
01370           }
01371 
01372           if (vert) {
01373               QMatrix matrix;
01374               qSwap(w, h); // flip width and height
01375               if (btt) {
01376                   matrix.translate(0.0, w);
01377                   matrix.rotate(-90.0);
01378               } else {
01379                   matrix.translate(h, 0.0);
01380                   matrix.rotate(90.0);
01381               }
01382               painter->setMatrix(matrix);
01383           }
01384 
01385           QRect left;
01386           int ipos = int(((pbar->progress - pbar->minimum) 
01387                           / double(pbar->maximum - pbar->minimum)) * w);
01388           bool rtl = (pbar->direction == Qt::RightToLeft);
01389           bool flip = ((!vert && ((rtl && !invert) || (!rtl && invert)))
01390                        || (vert && ((!invert && !btt) || (invert && btt))));
01391           if (flip) {
01392               ipos = w - ipos;
01393               if (ipos >= 0 && ipos <= w) {
01394                   left = QRect(x, y, ipos, h);
01395               }
01396           } else {
01397               if (ipos >= 0 && ipos <= w) {
01398                   left = QRect(x, y, ipos, h);
01399               }
01400           }
01401 
01402           // QFont font = painter->font();
01403           // font.setBold(true);
01404           // painter->setFont(font);
01405 
01406           painter->setPen(flip
01407                           ? pbar->palette.base().color()
01408                           : pbar->palette.text().color());
01409           painter->drawText(x, y, w, h, Qt::AlignCenter, pbar->text);
01410           if (!left.isNull()) {
01411               painter->setPen(flip
01412                               ? pbar->palette.text().color()
01413                               : pbar->palette.base().color());
01414               painter->setClipRect(left, Qt::IntersectClip);
01415               painter->drawText(x, y, w, h, Qt::AlignCenter, pbar->text);
01416           }
01417           painter->restore();
01418           break;
01419       }
01420 
01421       case CE_MenuBarItem: {            // menu item in a QMenuBar
01422           const QStyleOptionMenuItem *mbi;
01423           mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
01424           if (!mbi) break;
01425 
01426           if ((flags & State_Selected) && (flags & State_HasFocus)) {
01427               if (flags & State_Sunken) {
01428                   drawPhasePanel(painter, rect, pal,  pal.window(), true);
01429               } else {
01430                   drawPhaseBevel(painter, rect, pal, pal.window(),
01431                                  false, false, false);
01432               }
01433           } else {
01434               drawPhaseGradient(painter, rect, pal.window().color(), false,
01435                                 rect.size(), false);
01436           }
01437           QCommonStyle::drawControl(element, mbi, painter, widget);
01438           break;
01439       }
01440 
01441       case CE_MenuBarEmptyArea:         // empty area of a QMenuBar
01442           drawPhaseGradient(painter, rect, pal.window().color(), false,
01443                             rect.size(), false);
01444           break;
01445 
01446       case CE_MenuItem: {            // menu item in a QMenu
01447           const QStyleOptionMenuItem *mi;
01448           mi = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
01449           if (!mi) break;
01450 
01451           int checkwidth = qMax(mi->maxIconWidth, 20);
01452           bool active = (flags & State_Selected);
01453           int checked = (mi->checkType != QStyleOptionMenuItem::NotCheckable)
01454               ? mi->checked : false; 
01455           QRect vrect;
01456 
01457           // draw background
01458           if (active && enabled) {
01459               painter->fillRect(rect, pal.highlight());
01460           } else {
01461               painter->fillRect(rect, pal.window());
01462           }
01463 
01464           // draw separator
01465           if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
01466               painter->setPen(pal.mid().color());
01467               painter->drawLine(x+checkwidth, cy-1, x2-checkwidth-1, cy-1);
01468               painter->setPen(pal.dark().color());
01469               painter->drawLine(x+checkwidth+1, cy, x2-checkwidth-1, cy);
01470               painter->drawPoint(x+checkwidth, cy);
01471               painter->setPen(pal.midlight().color());
01472               painter->drawLine(x+checkwidth+1, cy+1, x2-checkwidth, cy+1);
01473               painter->drawPoint(x2-checkwidth, cy+1);
01474               break;
01475           }
01476 
01477           // set pen for text and icons
01478           if (enabled) {
01479               painter->setPen(active ? pal.highlightedText().color() :
01480                               pal.windowText().color());
01481           } else {
01482               painter->setPen(pal.mid().color());
01483           }
01484 
01485           // draw icon
01486           if (!mi->icon.isNull() && !checked) {
01487               QIcon::Mode mode;
01488               if (active)
01489                   mode = enabled ? QIcon::Active : QIcon::Disabled;
01490               else
01491                   mode = enabled ? QIcon::Normal : QIcon::Disabled;
01492 
01493               QPixmap pixmap = mi->icon.pixmap(pixelMetric(PM_SmallIconSize),
01494                                                mode);
01495               vrect = visualRect(mi->direction, rect,
01496                                  QRect(x, y, checkwidth, h));
01497               QRect pmrect(0, 0, pixmap.width(), pixmap.height());
01498               pmrect.moveCenter(vrect.center());
01499               painter->drawPixmap(pmrect.topLeft(), pixmap);
01500           }
01501 
01502           // draw check
01503           if (checked) {
01504               QStyleOptionMenuItem newmi = *mi;
01505               newmi.state = State_None;
01506               if (enabled) newmi.state |= State_Enabled;
01507               if (active) newmi.state |= State_On;
01508               newmi.rect = visualRect(mi->direction, rect,
01509                                       QRect(x, y, checkwidth, h));
01510               drawPrimitive(PE_IndicatorMenuCheckMark, &newmi, painter, widget);
01511           }
01512 
01513           // draw text
01514           int xm = ITEMFRAME + checkwidth + ITEMHMARGIN;
01515           int xp = x + xm;
01516           int tw = w - xm - mi->tabWidth - ARROWMARGIN - ITEMHMARGIN * 3
01517               - ITEMFRAME + 1;
01518           QString text = mi->text;
01519           QRect trect(xp, y+ITEMVMARGIN, tw, h - 2 * ITEMVMARGIN);
01520           vrect = visualRect(option->direction, rect, trect);
01521 
01522           if (!text.isEmpty()) { // draw label
01523               painter->save();
01524 
01525               if (mi->menuItemType == QStyleOptionMenuItem::DefaultItem) {
01526                   QFont font = mi->font;
01527                   font.setBold(true);
01528                   painter->setFont(font);
01529               }
01530 
01531               int t = text.indexOf('\t');
01532               int tflags = Qt::AlignVCenter | Qt::AlignLeft |
01533                            Qt::TextDontClip | Qt::TextSingleLine;
01534               if (styleHint(SH_UnderlineShortcut, mi, widget))
01535                   tflags |= Qt::TextShowMnemonic;
01536               else
01537                   tflags |= Qt::TextHideMnemonic;
01538 
01539               if (t >= 0) { // draw right label (accelerator)
01540                   QRect tabrect = visualRect(option->direction, rect, 
01541                                   QRect(trect.topRight(),
01542                                         QPoint(rect.right(), trect.bottom())));
01543                   painter->drawText(tabrect, tflags, text.mid(t+1));
01544                   text = text.left(t);
01545               }
01546 
01547               // draw left label
01548               painter->drawText(vrect, tflags, text.left(t));
01549               painter->restore();
01550           }
01551 
01552           // draw submenu arrow
01553           if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) {
01554               PrimitiveElement arrow = (option->direction == Qt::RightToLeft)
01555                   ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
01556               int dim = (h-2*ITEMFRAME) / 2;
01557               vrect = visualRect(option->direction, rect,
01558                                  QRect(x + w - ARROWMARGIN - ITEMFRAME - dim,
01559                                        y + h / 2 - dim / 2, dim, dim));
01560 
01561               QStyleOptionMenuItem newmi = *mi;
01562               newmi.rect = vrect;
01563               newmi.state = enabled ? State_Enabled : State_None;
01564               if (active) {
01565                     newmi.palette.setColor(QPalette::Dark,
01566                         newmi.palette.highlightedText().color());
01567               }
01568               drawPrimitive(arrow, &newmi, painter, widget);
01569           }
01570           break;
01571       }
01572 
01573       case CE_MenuTearoff:           // tearoff area in menu
01574           if (flags & State_Selected)
01575               painter->fillRect(rect, pal.brush(QPalette::Highlight));
01576           else
01577               painter->fillRect(rect, pal.brush(QPalette::Window));
01578           painter->setPen(QPen(pal.mid().color(), 1, Qt::DotLine));
01579           painter->drawLine(x+6, cy-1, x2-6, cy-1);
01580           painter->setPen(QPen(pal.dark().color(), 1, Qt::DotLine));
01581           painter->drawLine(x+6, cy, x2-6, cy);
01582           painter->setPen(QPen(pal.midlight().color(), 1, Qt::DotLine));
01583           painter->drawLine(x+6, cy+1, x2-6, cy+1);
01584           break;
01585 
01586       case CE_ToolBoxTab: {          // tab area of toolbox
01587           // TODO: account for reverse layout
01588           // TODO: Qt broken - palette isn't constant from tab to tab
01589           const QStyleOptionToolBox *box;
01590           box = qstyleoption_cast<const QStyleOptionToolBox*>(option);
01591           if (!box) break;
01592 
01593           const int rx = x2 - 20;
01594           const int cx = rx - h + 1;
01595 
01596           QPolygon polygon;
01597           polygon.setPoints(6,
01598                             x-1,y, cx,y, rx-2,y2-2, x2+1,y2-2,
01599                             x2+1,y2+1, x-1,y2+1);
01600 
01601           painter->save();
01602 
01603           if (flags & State_Selected) {
01604               painter->setPen(pal.dark().color());
01605               painter->setBrush(pal.window());
01606               painter->drawConvexPolygon(polygon);
01607           } else {
01608               painter->setClipRegion(polygon);
01609               drawPhaseGradient(painter, rect, pal.window().color(), false,
01610                                 QSize(w, h), false);
01611               painter->setClipping(false);
01612               painter->drawPolyline(polygon);
01613           }
01614 
01615           polygon.setPoints(4, x,y+1, cx,y+1, rx-2,y2-1, x2,y2-1);
01616           painter->setPen(pal.midlight().color());
01617           painter->drawPolyline(polygon);
01618 
01619           painter->restore();
01620           break;
01621       }
01622 
01623       case CE_SizeGrip: {            // window resize handle
01624           int sw = qMin(h, w) - 1;
01625           y = y2 - sw;
01626 
01627           QPen pen = painter->pen();
01628           if (option->direction == Qt::RightToLeft) {
01629               x2 = x + sw;
01630               for (int n = 0; n < 4; ++n) {
01631                   painter->setPen(pal.mid().color());
01632                   painter->drawLine(x, y, x2, y2);
01633                   painter->setPen(pal.midlight().color());
01634                   painter->drawLine(x, y+1, x2-1, y2);
01635                   y += 3;
01636                   x2 -= 3;
01637               }
01638           } else {
01639               x = x2 - sw;
01640               for (int n = 0; n < 4; ++n) {
01641                   painter->setPen(pal.mid().color());
01642                   painter->drawLine(x, y2, x2, y);
01643                   painter->setPen(pal.midlight().color());
01644                   painter->drawLine(x+1, y2, x2, y+1);
01645                   x += 3;
01646                   y += 3;
01647               }
01648           }
01649           painter->setPen(pen);
01650           break;
01651       }
01652 
01653       case CE_HeaderSection: {          // header bevel
01654           const QStyleOptionHeader *header;
01655           header = qstyleoption_cast<const QStyleOptionHeader *>(option);
01656           if (!header) break;
01657 
01658           horizontal = (header->orientation == Qt::Horizontal);
01659           // adjust rect so headers overlap by one pixel
01660           QRect arect = rect.adjusted(-1, -1, 0, 0);
01661           if (depress) {
01662               painter->save();
01663               painter->setPen(pal.dark().color());
01664               painter->setBrush(pal.mid());
01665               painter->drawRect(arect.adjusted(0, 0, -1, -1));
01666               painter->restore();
01667           }
01668           else {
01669               drawPhaseBevel(painter, arect, pal,
01670                              pal.window(), false, !horizontal, true);
01671           }
01672           break;
01673       }
01674 
01675       case CE_ScrollBarAddLine: {     // scrollbar scroll down
01676           PrimitiveElement arrow = (horizontal)
01677               ? PE_IndicatorArrowRight : PE_IndicatorArrowDown;
01678 
01679           drawPhaseBevel(painter, rect, pal, pal.button(),
01680                          depress, !horizontal, true);
01681           drawPrimitive(arrow, option, painter, widget);
01682           break;
01683       }
01684       case CE_ScrollBarSubLine: {    // scrollbar scroll up
01685           const QStyleOptionSlider *sb;
01686           sb = qstyleoption_cast<const QStyleOptionSlider *>(option);
01687           if (!sb) break;
01688 
01689           int extent = pixelMetric(PM_ScrollBarExtent, sb, widget);
01690 
01691           QRect button1, button2;
01692           PrimitiveElement arrow;
01693 
01694           if (horizontal) {
01695               button1.setRect(x, y, extent, extent);
01696               button2.setRect(x2 - extent + 1, y, extent, extent);
01697               arrow = PE_IndicatorArrowLeft;
01698           } else {
01699               button1.setRect(x, y, extent, extent);
01700               button2.setRect(x, y2 - extent + 1, extent, extent);
01701               arrow = PE_IndicatorArrowUp;
01702           }
01703 
01704           // draw buttons
01705           drawPhaseBevel(painter, button1, pal, pal.button(),
01706                          depress, !horizontal, true);
01707           drawPhaseBevel(painter, button2, pal, pal.button(),
01708                          depress, !horizontal, true);
01709 
01710           QStyleOptionSlider newoption = *sb;
01711           newoption.rect = button1;
01712           drawPrimitive(arrow, &newoption, painter, widget);
01713           newoption.rect = button2;
01714           drawPrimitive(arrow, &newoption, painter, widget);
01715 
01716           break;
01717       }
01718 
01719       case CE_ScrollBarAddPage:      // scrollbar page down
01720       case CE_ScrollBarSubPage:      // scrollbar page up
01721           if (h) { // has a height, thus visible
01722               QPen pen = painter->pen();
01723               painter->fillRect(rect, pal.mid());
01724               painter->setPen(pal.dark().color());
01725               if (horizontal) { // vertical
01726                   painter->drawLine(x, y, x2, y);
01727                   painter->drawLine(x, y2, x2, y2);
01728               } else { // horizontal
01729                   painter->drawLine(x, y, x, y2);
01730                   painter->drawLine(x2, y, x2, y2);
01731               }
01732               painter->setPen(pen);
01733           }
01734           break;
01735 
01736       case CE_ScrollBarSlider:       // scrollbar slider/thumb
01737           drawPhaseBevel(painter, rect, pal, mouseover ?
01738                          pal.button().color().lighter(contrast_) : pal.button(),
01739                          false, !horizontal, true);
01740           drawPhaseDoodads(painter, rect, pal, horizontal);
01741           break;
01742 
01743       case CE_RubberBand: {          // rubberband (such as for iconview)
01744           const QStyleOptionRubberBand *rb;
01745           rb = qstyleoption_cast<const QStyleOptionRubberBand*>(option);
01746           if (rb) {
01747               painter->save();
01748               QColor color = pal.highlight().color();
01749               if (!rb->opaque) color.setAlpha(127);
01750               painter->setPen(color);
01751               if (!rb->opaque) color.setAlpha(31);
01752               painter->setBrush(color);
01753               QStyleHintReturnMask mask;
01754               painter->drawRect(rect.adjusted(0, 0, -1, -1));
01755               painter->restore();
01756           }
01757           break;
01758       }
01759 
01760       case CE_ToolBar: {             // QToolBar
01761           drawPrimitive(PE_PanelToolBar, option, painter, widget);
01762           QRect grect = rect.adjusted(2, 2, -2, -2);
01763           drawPhaseGradient(painter, grect, pal.window().color(),
01764                             !horizontal, grect.size(), true);
01765           break;
01766       }
01767 
01768       // not drawing these controls, as default is sufficient
01769       // case CE_Q3DockWindowEmptyArea: // empty area of dock widget
01770       // case CE_PushButtonLabel:
01771       // case CE_FocusFrame:
01772       // case CE_CheckBox:
01773       // case CE_CheckBoxLabel:
01774       // case CE_ComboBoxLabel:
01775       // case CE_Header:
01776       // case CE_HeaderLabel:
01777       // case CE_MenuScroller:
01778       // case CE_RadioButton:
01779       // case CE_RadioButtonLabel:
01780       // case CE_ScrollBarFirst:
01781       // case CE_ScrollBarLast:
01782       // case CE_TabBarTab:
01783       // case CE_TabBarTabLabel:
01784       // case CE_ToolButtonLabel:
01785 
01786       default:
01787           QWindowsStyle::drawControl(element, option, painter, widget);
01788           break;
01789     }
01790 }
01791 
01793 // drawComplexControl()
01794 // --------------------
01795 // Draw complex control
01796 
01797 void PhaseStyle::drawComplexControl(ComplexControl control,
01798                                     const QStyleOptionComplex *option,
01799                                     QPainter *painter,
01800                                     const QWidget *widget) const
01801 {
01802     const QRect &rect = option->rect;
01803     const State &flags = option->state;
01804     const QPalette &pal = option->palette;
01805     bool enabled = flags & State_Enabled;
01806     bool sunken = flags & State_Sunken;
01807     bool mouseover = highlights_ && (flags & State_MouseOver) && enabled;
01808     int x, y, w, h;
01809     rect.getRect(&x, &y, &w, &h);
01810     QRect subrect;
01811 
01812     switch (control) {
01813       case CC_SpinBox: {                // QSpinBox
01814           const QStyleOptionSpinBox *box;
01815           box = qstyleoption_cast<const QStyleOptionSpinBox*>(option);
01816           if (!box) break;
01817 
01818           QStyleOptionSpinBox copybox = *box;
01819           PrimitiveElement element;
01820 
01821           // draw frame
01822           if (box->frame && (box->subControls & SC_SpinBoxFrame)) {
01823               subrect = subControlRect(CC_SpinBox, box,
01824                                        SC_SpinBoxFrame, widget);
01825               drawPhasePanel(painter, subrect, pal, Qt::NoBrush, true);
01826           }
01827 
01828           // draw button field
01829           subrect = subControlRect(CC_SpinBox, box,
01830                                    SC_SpinBoxFrame, widget);
01831           subrect.adjust(1, 1, -1, -1);
01832           int left = subControlRect(CC_SpinBox, box,
01833                                     SC_SpinBoxUp, widget).left();
01834           subrect.setLeft(left);
01835           drawPhaseBevel(painter, subrect, pal, mouseover ?
01836                          pal.button().color().lighter(contrast_) :
01837                          pal.button(),
01838                          false, false, false);
01839 
01840           // draw up arrow
01841           if (box->subControls & SC_SpinBoxUp) {
01842               subrect = subControlRect(CC_SpinBox, box, SC_SpinBoxUp, widget);
01843               copybox.subControls = SC_SpinBoxUp;
01844               copybox.rect = subControlRect(CC_SpinBox, box,
01845                                             SC_SpinBoxUp, widget);
01846 
01847               if (box->buttonSymbols == QAbstractSpinBox::PlusMinus)
01848                   element = PE_IndicatorSpinPlus;
01849               else
01850                   element = PE_IndicatorSpinUp;
01851 
01852               if (box->activeSubControls == SC_SpinBoxUp && sunken) {
01853                   copybox.state |= State_On;
01854                   copybox.state |= State_Sunken;
01855               } else {
01856                   copybox.state |= State_Raised;
01857                   copybox.state &= ~State_Sunken;
01858               }
01859               drawPrimitive(element, &copybox, painter, widget);
01860           }
01861 
01862           // draw down arrow
01863           if (box->subControls & SC_SpinBoxDown) {
01864               subrect = subControlRect(CC_SpinBox, box, SC_SpinBoxDown, widget);
01865               copybox.subControls = SC_SpinBoxDown;
01866               copybox.rect = subControlRect(CC_SpinBox, box,
01867                                             SC_SpinBoxDown, widget);
01868 
01869               if (box->buttonSymbols == QAbstractSpinBox::PlusMinus)
01870                   element = PE_IndicatorSpinMinus;
01871               else
01872                   element = PE_IndicatorSpinDown;
01873 
01874               if (box->activeSubControls == SC_SpinBoxDown && sunken) {
01875                   copybox.state |= State_On;
01876                   copybox.state |= State_Sunken;
01877               } else {
01878                   copybox.state |= State_Raised;
01879                   copybox.state &= ~State_Sunken;
01880               }
01881               drawPrimitive(element, &copybox, painter, widget);
01882           }
01883           break;
01884       }
01885 
01886       case CC_ComboBox: {               // QComboBox
01887           const QStyleOptionComboBox *combo;
01888           combo = qstyleoption_cast<const QStyleOptionComboBox*>(option);
01889           if (!combo) break;
01890 
01891           subrect = subControlRect(CC_ComboBox, combo,
01892                                    SC_ComboBoxArrow, widget);
01893 
01894           if (combo->editable) {
01895               // draw frame
01896               drawPhasePanel(painter, rect, pal, Qt::NoBrush, true);
01897               // draw arrow box
01898               drawPhaseBevel(painter, subrect.adjusted(-1, -1, 1, 1),
01899                              pal, mouseover
01900                              ? pal.button().color().lighter(contrast_)
01901                              : pal.button().color(), sunken, false);
01902           } else {
01903               // draw bevel
01904               drawPhaseButton(painter, rect, pal, mouseover
01905                               ? pal.button().color().lighter(contrast_)
01906                               : pal.button().color(), sunken);
01907           }
01908 
01909           if (combo->subControls & SC_ComboBoxArrow) {
01910               // draw slot
01911               int slot = qMax(h/4, 6);
01912               slot = qMin(slot, 12) + (h%2);
01913               subrect.adjust(3, 0, -3, 0);
01914               subrect.setTop(subrect.top() + subrect.height()/2 - slot/2);
01915               subrect.setHeight(slot);
01916               drawPhasePanel(painter, subrect,
01917                              pal, sunken ? pal.midlight() : pal.mid(),
01918                              true);
01919           }
01920    
01921           if ((flags & State_HasFocus) && !combo->editable) {
01922               QStyleOptionFocusRect focus;
01923               focus.QStyleOption::operator=(*combo);
01924               subrect = subElementRect(SE_ComboBoxFocusRect,
01925                                           combo, widget);
01926               focus.rect = visualRect(combo->direction, rect, subrect);
01927               drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
01928           }
01929           break;
01930       }
01931 
01932       case CC_Slider: {                 // QSlider
01933           const QStyleOptionSlider *slider;
01934           slider = qstyleoption_cast<const QStyleOptionSlider*>(option);
01935           if (!slider) break;
01936 
01937           if (slider->subControls & SC_SliderGroove) {
01938               subrect = subControlRect(CC_Slider, slider,
01939                                        SC_SliderGroove, widget);
01940               if (subrect.isValid()) {
01941                   if (slider->orientation == Qt::Horizontal) {
01942                       subrect.setTop(subrect.top()+subrect.height()/2-3);
01943                       subrect.setHeight(7);
01944                   } else {
01945                       subrect.setLeft(subrect.left()+subrect.width()/2-3);
01946                       subrect.setWidth(7);
01947                   }
01948                   drawPhasePanel(painter, subrect, pal, pal.mid(), true);
01949               }
01950           }
01951 
01952           if (slider->subControls & SC_SliderHandle) {
01953               subrect = subControlRect(CC_Slider, slider,
01954                                        SC_SliderHandle, widget);
01955               QColor color = mouseover
01956                   ? pal.button().color().lighter(contrast_)
01957                   : pal.button().color();
01958 
01959               if (slider->orientation == Qt::Horizontal) {
01960                   subrect.setWidth(6);
01961                   drawPhaseBevel(painter, subrect, pal, color,
01962                                  false, false, false);
01963                   subrect.moveLeft(subrect.left()+5);
01964                   drawPhaseBevel(painter, subrect, pal, color,
01965                                  false, false, false);
01966               } else {
01967                   subrect.setHeight(6);
01968                   drawPhaseBevel(painter, subrect, pal, color,
01969                                  false, true, false);
01970                   subrect.moveTop(subrect.top()+5);
01971                   drawPhaseBevel(painter, subrect, pal, color,
01972                                  false, true, false);
01973               }
01974           }
01975 
01976           if (slider->subControls & SC_SliderTickmarks) {
01977               bool ticksabove = slider->tickPosition & QSlider::TicksAbove;
01978               bool ticksbelow = slider->tickPosition & QSlider::TicksBelow;
01979               bool horizontal = (slider->orientation == Qt::Horizontal);
01980 
01981               int spaceavail = pixelMetric(PM_SliderSpaceAvailable,
01982                                            slider, widget);
01983               int interval = slider->tickInterval;
01984               if (interval==0) {
01985                   interval = slider->singleStep;
01986                   if (QStyle::sliderPositionFromValue(slider->minimum,
01987                                                       slider->maximum,
01988                                                       interval, spaceavail)
01989                       - QStyle::sliderPositionFromValue(slider->minimum,
01990                                                         slider->maximum,
01991                                                         0, spaceavail) < 3)
01992                       interval = slider->pageStep;
01993               }
01994               if (interval < 2) interval = 2;
01995 
01996               QRect handle = subControlRect(CC_Slider, slider,
01997                                             SC_SliderHandle, widget);
01998               int pos, offset, span, ticksize;
01999               if (horizontal) {
02000                   offset = handle.width() / 2;
02001                   span = w - handle.width();
02002                   ticksize = (h - handle.height()) / 2 - 1;
02003               } else {
02004                   offset = handle.height() / 2;
02005                   span = h - handle.height();
02006                   ticksize = (w - handle.width()) / 2 - 1;
02007               }
02008 
02009               QPen oldpen = painter->pen();
02010               painter->setPen(pal.dark().color());
02011 
02012               for (int n=slider->minimum; n<=slider->maximum; n+=interval) {
02013                   pos = sliderPositionFromValue(slider->minimum,
02014                                                 slider->maximum,
02015                                                 n,  span,
02016                                                 slider->upsideDown);
02017                   pos += offset;
02018 
02019                   if (horizontal) {
02020                       if (ticksabove) {
02021                           painter->drawLine(pos, y, pos, y + ticksize);
02022                       }
02023                       if (ticksbelow) {
02024                           painter->drawLine(pos, rect.bottom(),
02025                                             pos, rect.bottom() - ticksize);
02026                       }
02027                   } else {
02028                       if (ticksabove) {
02029                           painter->drawLine(x,  pos, x + ticksize, pos);
02030                       }
02031                       if (ticksbelow) {
02032                           painter->drawLine(rect.right(), pos,
02033                                             rect.right() - ticksize, pos);
02034                       }
02035                   }
02036 
02037                   painter->setPen(oldpen);
02038               }
02039           }
02040           break;
02041       }
02042 
02043       case CC_Dial: {                   // QDial
02044           const QStyleOptionSlider *dial;
02045           dial = qstyleoption_cast<const QStyleOptionSlider*>(option);
02046           if (!dial) break;
02047 
02048           // avoid aliasing
02049           QPainter::RenderHints oldhints = painter->renderHints();
02050           painter->setRenderHint(QPainter::Antialiasing, true);
02051 
02052           qreal cx = rect.center().x();
02053           qreal cy = rect.center().y();
02054           qreal radius = (qMin(w, h) / 2.0) - 2.0;
02055           qreal tick = qMax(radius / 6, static_cast<qreal>(4.0));
02056 
02057           if (dial->subControls & SC_DialGroove) {
02058               QRectF groove = QRectF(cx-radius+tick, cy-radius+tick,
02059                                      radius*2-tick*2, radius*2-tick*2);
02060 
02061               // Note: State_MouseOver doesn't work well with QDial
02062               QLinearGradient gradient(0, groove.top(), 0, groove.bottom());
02063               gradient.setColorAt(0, pal.button().color().darker(contrast_));
02064               gradient.setColorAt(1, pal.button().color().lighter(contrast_));
02065 
02066               painter->setPen(QPen(pal.dark().color(), 1.5));
02067               painter->setBrush(gradient);
02068               painter->drawEllipse(groove);
02069               painter->setBrush(Qt::NoBrush);
02070 
02071               groove.adjust(1.0, 1.0, -1.0, -1.0);
02072               painter->setPen(pal.midlight().color());
02073               painter->drawArc(groove, 60*16, 150*16);
02074               painter->setPen(pal.button().color());
02075               painter->drawArc(groove, 30*16, 30*16);
02076               painter->drawArc(groove, 210*16, 30*16);
02077               painter->setPen(pal.mid().color());
02078               painter->drawArc(groove, 240*16, 150*16);
02079           }
02080 
02081           if (dial->subControls & SC_DialHandle) {
02082               painter->save();
02083               qreal angle;
02084               qreal percent = (double)(dial->sliderValue - dial->minimum)
02085                             / (double)(dial->maximum - dial->minimum);
02086 
02087               if (dial->maximum == dial->minimum) {
02088                   angle = 0.0;
02089               } else if (dial->dialWrapping) {
02090                   angle = percent * 360.0;
02091               } else {
02092                   angle = percent * 315.0 + 22.5;
02093               }
02094 
02095               painter->translate(cx, cy);
02096               painter->rotate(angle);
02097 
02098               bool ul = (angle > 135.0 && angle < 315.0);
02099               painter->setPen(ul ? pal.midlight().color() : pal.mid().color());
02100               painter->drawLine(QLineF(-1, radius-tick-1, -1, radius-tick*4));
02101               painter->setPen(pal.dark().color());
02102               painter->drawLine(QLineF(0, radius-tick, 0, radius-tick*4));
02103               painter->setPen(ul ? pal.mid().color() : pal.midlight().color());
02104               painter->drawLine(QLineF(1, radius-tick-1, 1, radius-tick*4));
02105 
02106               painter->restore();
02107           }
02108 
02109           if (dial->subControls & QStyle::SC_DialTickmarks) {
02110               painter->save();
02111               painter->setPen(pal.dark().color());
02112 
02113               int ti = dial->tickInterval;
02114               int notches = (dial->maximum - dial->minimum + ti - 1) / ti;
02115 
02116               if (notches > 0) {
02117                   qreal start, increment;
02118                   if (dial->dialWrapping) {
02119                       start = 0.0;
02120                       increment = 360.0 / notches;
02121                   } else {
02122                       start = 22.5;
02123                       increment = 315.0 / notches;
02124                   }
02125 
02126                   painter->translate(cx, cy);
02127                   painter->rotate(start);
02128                   for (int n=0; n<=notches; ++n) {
02129                       painter->drawLine(QLineF(0.0, radius,
02130                                                0.0, radius - tick / 2.0));;
02131                       painter->rotate(increment);
02132                   }
02133               }
02134               painter->restore();
02135           }
02136 
02137           painter->setRenderHints(oldhints);
02138           break;
02139       }
02140 
02141       case CC_TitleBar:  {               // QWorkspace titlebar
02142           // TODO: sync this look up with dock window titles ?
02143           const QStyleOptionTitleBar *title;
02144           title = qstyleoption_cast<const QStyleOptionTitleBar*>(option);
02145           if (!title) break;
02146 
02147           bool shaded = (title->titleBarState & Qt::WindowMinimized);
02148 
02149           int x2 = rect.right();
02150           int y2 = rect.bottom();
02151 
02152           // draw titlebar frame
02153           drawPhaseGradient(painter, rect.adjusted(0,0,0,-3),
02154                             pal.highlight().color(),
02155                             false, rect.size(), false);
02156 
02157           painter->setPen(pal.shadow().color());
02158           painter->drawLine(x, y, x, y2);
02159           painter->drawLine(x, y, x2, y);
02160           painter->drawLine(x2, y, x2, y2);
02161           painter->setPen(pal.midlight().color());
02162           painter->drawLine(x+1, y+1, x2-2, y+1);
02163           painter->drawLine(x+1, y+2, x+1, y2);
02164           painter->setPen(pal.mid().color());
02165           painter->drawLine(x2-1, y+2, x2-1, y2);
02166           painter->setPen(pal.window().color());
02167           painter->drawLine(x+2, y+2, x2-2, y+2);
02168           painter->drawLine(x+2, y+2, x+2, y2);
02169           painter->drawLine(x2-2, y+2, x2-2, y2);
02170           painter->drawPoint(x2-1, y+1);
02171           if (shaded) {
02172               painter->setPen(pal.shadow().color());
02173               painter->drawLine(x, y2, x2, y2);
02174               painter->setPen(pal.mid().color());
02175               painter->drawLine(x+2, y2-1, x2-1, y2-1);
02176               painter->setPen(pal.window().color());
02177               painter->drawLine(x+2, y2-2, x2-2, y2-2);
02178               painter->drawPoint(x+1, y2-1);
02179           }
02180 
02181           // draw label
02182           if (title->subControls & SC_TitleBarLabel) {
02183               subrect = subControlRect(CC_TitleBar, title,
02184                                        SC_TitleBarLabel, widget);
02185 
02186               QFont font = painter->font();
02187               font.setBold(true);
02188               painter->setFont(font);
02189 
02190               drawItemText(painter, subrect,
02191                            Qt::AlignCenter |
02192                            Qt::TextShowMnemonic |
02193                            Qt::TextSingleLine,
02194                            pal, enabled, title->text,
02195                            QPalette::HighlightedText);
02196           }
02197 
02198           // draw buttons
02199           QPixmap pix;
02200           bool down;
02201           QStyleOption tool(*title);
02202 
02203           painter->setPen(pal.windowText().color());
02204 
02205           // menu/icon button
02206           if ((title->subControls & SC_TitleBarSysMenu) &&
02207               (title->titleBarFlags & Qt::WindowSystemMenuHint)) {
02208               subrect = subControlRect(CC_TitleBar, title,
02209                                        SC_TitleBarSysMenu, widget);
02210                 if (!title->icon.isNull()) {
02211                     title->icon.paint(painter, subrect);
02212                 } else {
02213                     down = ((title->activeSubControls & SC_TitleBarCloseButton)
02214                             && (flags & State_Sunken));
02215                     pix = standardPixmap(SP_TitleBarMenuButton, &tool, widget);
02216                     tool.rect = subrect;
02217                     tool.state = down ? State_Sunken : State_Raised;
02218                     drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
02219 
02220                     if (down) painter->translate(1, 1);
02221                     drawItemPixmap(painter, subrect, Qt::AlignCenter, pix);
02222                     if (down) painter->translate(-1, -1);
02223                 }
02224           }
02225 
02226           if (title->subControls & SC_TitleBarCloseButton) {
02227               subrect = subControlRect(CC_TitleBar, title,
02228                                        SC_TitleBarCloseButton, widget);
02229               if (!subrect.isNull()) {
02230                   down = ((title->activeSubControls & SC_TitleBarCloseButton)
02231                           && (flags & State_Sunken));
02232                   pix = standardPixmap(SP_TitleBarCloseButton, &tool, widget);
02233                   tool.rect = subrect;
02234                   tool.state = down ? State_Sunken : State_Raised;
02235                   drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
02236 
02237                   if (down) painter->translate(1, 1);
02238                   drawItemPixmap(painter, subrect, Qt::AlignCenter, pix);
02239                   if (down) painter->translate(-1, -1);
02240               }
02241           }
02242 
02243           if (title->subControls & SC_TitleBarMinButton) {
02244               subrect = subControlRect(CC_TitleBar, title,
02245                                        SC_TitleBarMinButton, widget);
02246               if (!subrect.isNull()) {
02247                   down = ((title->activeSubControls & SC_TitleBarMinButton)
02248                           && (flags & State_Sunken));
02249                   pix = standardPixmap(SP_TitleBarMinButton, &tool, widget);
02250                   tool.rect = subrect;
02251                   tool.state = down ? State_Sunken : State_Raised;
02252                   drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
02253 
02254                   if (down) painter->translate(1, 1);
02255                   drawItemPixmap(painter, subrect, Qt::AlignCenter, pix);
02256                   if (down) painter->translate(-1, -1);
02257               }
02258           }
02259 
02260           if ((title->subControls & SC_TitleBarMaxButton) &&
02261               (title->titleBarFlags & Qt::WindowMaximizeButtonHint)) {
02262               subrect = subControlRect(CC_TitleBar, title,
02263                                        SC_TitleBarMaxButton, widget);
02264               if (!subrect.isNull()) {
02265                   down = ((title->activeSubControls & SC_TitleBarMaxButton) &&
02266                           (flags & State_Sunken));
02267                   pix = standardPixmap(SP_TitleBarMaxButton, &tool, widget);
02268                   tool.rect = subrect;
02269                   tool.state = down ? State_Sunken : State_Raised;
02270                   drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
02271 
02272                   if (down) painter->translate(1, 1);
02273                   drawItemPixmap(painter, subrect, Qt::AlignCenter, pix);
02274                   if (down) painter->translate(-1, -1);
02275               }
02276           }
02277 
02278           if ((title->subControls & SC_TitleBarNormalButton) &&
02279               (((title->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
02280                 (title->titleBarState & Qt::WindowMinimized)) ||
02281                ((title->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
02282                 (title->titleBarState & Qt::WindowMaximized)))) {
02283               subrect = subControlRect(CC_TitleBar, title,
02284                                        SC_TitleBarNormalButton, widget);
02285               if (!subrect.isNull()) {
02286                   down = ((title->activeSubControls & SC_TitleBarNormalButton)
02287                           && (flags & State_Sunken));
02288                   pix = standardPixmap(SP_TitleBarNormalButton, &tool, widget);
02289                   tool.rect = subrect;
02290                   tool.state = down ? State_Sunken : State_Raised;
02291                   drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
02292 
02293                   if (down) painter->translate(1, 1);
02294                   drawItemPixmap(painter, subrect, Qt::AlignCenter, pix);
02295               }
02296           }
02297 
02298           if ((title->subControls & SC_TitleBarContextHelpButton) &&
02299               (title->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
02300               subrect = subControlRect(CC_TitleBar, title,
02301                                        SC_TitleBarContextHelpButton, widget);
02302               if (!subrect.isNull()) {
02303                   down = ((title->activeSubControls & SC_TitleBarContextHelpButton)
02304                           && (flags & State_Sunken));
02305                   pix = standardPixmap(SP_TitleBarContextHelpButton,
02306                                        &tool, widget);
02307                   tool.rect = subrect;
02308                   tool.state = down ? State_Sunken : State_Raised;
02309                   drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
02310 
02311                   if (down) painter->translate(1, 1);
02312                   drawItemPixmap(painter, subrect, Qt::AlignCenter, pix);
02313                   if (down) painter->translate(-1, -1);
02314               }
02315           }
02316 
02317           break;
02318       }
02319 
02320       // not drawing these controls, as default is sufficient
02321       // case CC_ScrollBar:
02322       // case CC_ToolButton:
02323       // case CC_GroupBox:
02324 
02325       default:
02326           QWindowsStyle::drawComplexControl(control, option, painter, widget);
02327           break;
02328     }
02329 }
02330 
02332 // standardPixmap()
02333 // ----------------
02334 // Get pixmap for style
02335 
02336 QPixmap PhaseStyle::standardPixmap(StandardPixmap pixmap,
02337                        const QStyleOption *option,
02338                        const QWidget *widget) const
02339 {
02340     switch (pixmap) {
02341       case SP_TitleBarMenuButton:
02342           return QPixmap(title_menu_xpm);
02343 
02344       case SP_DockWidgetCloseButton:
02345       case SP_TitleBarCloseButton:
02346           return bitmaps_[TitleClose];
02347 
02348       case SP_TitleBarMinButton:
02349           return bitmaps_[TitleMin];
02350 
02351       case SP_TitleBarMaxButton:
02352           return bitmaps_[TitleMax];
02353 
02354       case SP_TitleBarNormalButton:
02355           return bitmaps_[TitleNormal];
02356 
02357       case SP_TitleBarContextHelpButton:
02358           return bitmaps_[TitleHelp];
02359 
02360       default:
02361           return QWindowsStyle::standardPixmap(pixmap, option, widget);
02362           
02363     }
02364 }
02365 
02367 // Metrics and Rects                                                        //
02369 
02371 // pixelMetric()
02372 // -------------
02373 // Get the pixel metric for metric
02374 
02375 int PhaseStyle::pixelMetric(PixelMetric metric,
02376                             const QStyleOption *option,
02377                             const QWidget *widget) const
02378 {
02379     int ex = qMax(QApplication::fontMetrics().xHeight(), 17);
02380 
02381     switch (metric) {
02382       case PM_ButtonMargin:
02383          return 6;
02384 
02385       case PM_ButtonDefaultIndicator:   // size of default button frame
02386           return 3; // half button margin
02387 
02388       case PM_IndicatorWidth:
02389       case PM_IndicatorHeight:
02390       case PM_ExclusiveIndicatorWidth:
02391       case PM_ExclusiveIndicatorHeight:
02392       case PM_CheckListButtonSize:
02393           return ex & 0xfffe; // even size
02394 
02395       case PM_MenuBarPanelWidth:
02396           return 2;
02397 
02398       case PM_DockWidgetTitleMargin:
02399           return 2;
02400 
02401       case PM_DockWidgetFrameWidth:
02402           return 3;
02403 
02404       case PM_ScrollBarExtent:          // base width of a vertical scrollbar
02405           return ex & 0xfffe;
02406 
02407       case PM_ScrollBarSliderMin:       // minimum length of slider
02408           return  ex * 2;
02409 
02410       case PM_TabBarTabHSpace:          // extra tab spacing
02411           return 24;
02412 
02413       case PM_TabBarTabShiftVertical:
02414           return 2;
02415 
02416       case PM_TabBarTabVSpace: {
02417           const QStyleOptionTab *tab;
02418           tab = qstyleoption_cast<const QStyleOptionTab *>(option);
02419           if (tab) {
02420               if (tab->shape == QTabBar::RoundedNorth) {
02421                   return 10;
02422               } else {
02423                   return 6;
02424               }
02425           }
02426           return 0;
02427       }
02428 
02429       case PM_ProgressBarChunkWidth: {
02430           int breadth = qMax(option->rect.width(), option->rect.height());
02431           return qMax(breadth / 10, 10);
02432       }
02433 
02434       case PM_TitleBarHeight:
02435           return qMax(widget ? widget->fontMetrics().lineSpacing() :
02436                       (option ? option->fontMetrics.lineSpacing() : 0), 22);
02437 
02438       default:
02439           return QWindowsStyle::pixelMetric(metric, option, widget);
02440     }
02441 }
02442 
02444 // subElementRect()
02445 // ----------------
02446 // Return rect of subelement
02447 
02448 QRect PhaseStyle::subElementRect(SubElement element,
02449                                  const QStyleOption *option,
02450                                  const QWidget *widget) const
02451 {
02452     QRect rect;
02453     const int fw = 2;
02454     int x, y, w, h;
02455     option->rect.getRect(&x, &y, &w, &h);
02456 
02457     switch (element) {
02458       case SE_ComboBoxFocusRect: {
02459           int bw = qMin(h, 32); // position between edit and arrow
02460           rect.setRect(fw*2, fw*2, w-bw-fw-1, h-(fw*4));
02461           break;
02462       }
02463 
02464       case SE_ProgressBarContents:
02465           return option->rect.adjusted(3, 3, -3, -3);
02466 
02467       case SE_ProgressBarGroove:
02468       case SE_ProgressBarLabel:
02469           return option->rect;
02470 
02471       case SE_HeaderArrow: {
02472           int margin = pixelMetric(PM_HeaderMargin, option, widget);
02473           rect.setSize(QSize(h - margin*2, h - margin*2));
02474           if (option->state & State_Horizontal) {
02475               rect.moveTopLeft(QPoint(x + w - h, margin));
02476           } else {
02477               rect.moveTopLeft(QPoint(margin, margin));
02478           }
02479           rect = visualRect(option->direction, option->rect, rect);
02480           break;
02481       }
02482 
02483       case SE_ToolBoxTabContents:
02484           rect = visualRect(option->direction, option->rect, option->rect);
02485           break;
02486 
02487       case SE_DockWidgetTitleBarText: {
02488           rect = QWindowsStyle::subElementRect(element, option, widget);
02489 
02490           const QStyleOptionDockWidgetV2 *v2
02491               = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(option);
02492           bool vertical = (v2 == 0) ? false : v2->verticalTitleBar;
02493 
02494           if (vertical) {
02495               rect.adjust(0, -3, 0, -3);
02496           } else {
02497               rect.adjust(-3, 0, 3, 0);
02498           }
02499           break;
02500       }
02501 
02502       case SE_DockWidgetFloatButton:
02503       case SE_DockWidgetCloseButton: {
02504           rect = QWindowsStyle::subElementRect(element, option, widget);
02505 
02506           const QStyleOptionDockWidgetV2 *v2
02507               = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(option);
02508           bool vertical = (v2 == 0) ? false : v2->verticalTitleBar;
02509 
02510           if (vertical) {
02511               rect.moveTop(rect.top() + 3);
02512           } else {
02513               if (option->direction == Qt::LeftToRight) {
02514                   rect.moveLeft(rect.left() - 3);
02515               } else {
02516                   rect.moveLeft(rect.left() + 3);
02517               }
02518           }
02519           break;
02520       }
02521 
02522       default:
02523           rect = QWindowsStyle::subElementRect(element, option, widget);
02524     }
02525 
02526     return rect;
02527 }
02528 
02530 // subControlRect()
02531 // ----------------
02532 // Return rect of control
02533 
02534 QRect PhaseStyle::subControlRect(ComplexControl control,
02535                                  const QStyleOptionComplex *option,
02536                                  SubControl subcontrol,
02537                                  const QWidget *widget) const
02538 {
02539     QRect rect;
02540     QRect ctlrect = option->rect;
02541     int x, y, w, h, x2, y2;
02542     const int fw = 2;
02543     ctlrect.getRect(&x, &y, &w, &h);
02544     x2 = ctlrect.right(); y2 = ctlrect.bottom();
02545 
02546     switch (control) {
02547       case CC_SpinBox: {
02548           const QStyleOptionSpinBox *box;
02549           box = qstyleoption_cast<const QStyleOptionSpinBox*>(option);
02550           if (!box) break;
02551 
02552           bool odd = widget ? widget->height() % 2 : 0;
02553           int bw = (h*3/4) - odd + 1; // width of button box
02554           switch (subcontrol) {
02555             case SC_SpinBoxUp:
02556                 rect.setRect(w-bw, (h/2)-(odd ? 6 : 7), bw-1, 6);
02557                 break;
02558             case SC_SpinBoxDown:
02559                 rect.setRect(w-bw, (h/2)+1, bw-1, odd ? 7 : 6);
02560                 break;
02561             case SC_SpinBoxEditField:
02562                 rect.setRect(fw, fw, w-bw-fw, h-(fw*2));
02563                 break;
02564             case SC_SpinBoxFrame:
02565                 rect = ctlrect;
02566                 break;
02567             default:
02568                 break;
02569           }
02570           rect = visualRect(box->direction, ctlrect, rect);
02571           break;
02572       }
02573 
02574       case CC_ComboBox: {
02575           const QStyleOptionComboBox *combo;
02576           combo = qstyleoption_cast<const QStyleOptionComboBox*>(option);
02577           if (!combo) break;
02578 
02579           int bw = qMin(h, 32); // position between edit and arrow
02580           switch (subcontrol) {
02581             case SC_ComboBoxFrame: // total combobox area
02582                 rect = ctlrect;
02583                 break;
02584 
02585             case SC_ComboBoxArrow: // the right side
02586                 rect.setRect(w-bw, fw, bw-fw, h-(fw*2));
02587                 break;
02588 
02589             case SC_ComboBoxEditField: // the left side
02590                 rect.setRect(fw, fw, w-bw-fw-1, h-(fw*2));
02591                 if (!combo->editable) {
02592                     // give extra margin
02593                     rect.adjust(pixelMetric(PM_ButtonMargin),
02594                                 0, 0, 0);
02595                 }
02596                 break;
02597 
02598             case SC_ComboBoxListBoxPopup: // the list popup box
02599                 rect = ctlrect;
02600                 break;
02601 
02602             default:
02603                 break;
02604           }
02605           rect = visualRect(combo->direction, ctlrect, rect);
02606           break;
02607       }
02608 
02609       case CC_ScrollBar: {
02610           // three button scrollbar
02611           const QStyleOptionSlider *sb;
02612           sb = qstyleoption_cast<const QStyleOptionSlider *>(option);
02613           if (!sb) break;
02614 
02615           bool horizontal = (sb->orientation == Qt::Horizontal);
02616           int extent = pixelMetric(PM_ScrollBarExtent, sb, widget);
02617           int slidermax = ((horizontal) ?  ctlrect.width() : ctlrect.height())
02618               - (extent * 3);
02619           int slidermin = pixelMetric(PM_ScrollBarSliderMin, sb, widget);
02620           int sliderlen, sliderstart;
02621 
02622           // calculate slider length
02623           if (sb->maximum != sb->minimum) {
02624               int range = sb->maximum - sb->minimum;
02625               sliderlen = (sb->pageStep * slidermax) / (range + sb->pageStep);
02626               if ((sliderlen < slidermin) || (range > INT_MAX / 2))
02627                   sliderlen = slidermin;
02628               if (sliderlen > slidermax)
02629                   sliderlen = slidermax;
02630           } else {
02631               sliderlen = slidermax;
02632           }
02633 
02634           sliderstart = extent + sliderPositionFromValue(sb->minimum,
02635                                                          sb->maximum,
02636                                                          sb->sliderPosition,
02637                                                          slidermax - sliderlen,
02638                                                          sb->upsideDown);
02639 
02640           switch (subcontrol) {
02641             case SC_ScrollBarAddLine:
02642                 if (horizontal) {
02643                     rect.setRect(x2 - extent + 1, y, extent, extent);
02644                 } else {
02645                     rect.setRect(x, y2 - extent + 1, extent, extent);
02646                 }
02647                 break;
02648 
02649             case SC_ScrollBarSubLine:
02650                 // rect that covers *both* subline buttons
02651                 if (horizontal) {
02652                     rect.setRect(x, y, w - extent + 1, extent);
02653                 } else {
02654                     rect.setRect(x, y, extent, h - extent + 1);
02655                 }
02656                 break;
02657 
02658             case SC_ScrollBarAddPage:
02659                 if (horizontal)
02660                     rect.setRect(sliderstart + sliderlen, y,
02661                              slidermax - sliderstart - sliderlen + extent + 1,
02662                                  extent);
02663                 else
02664                     rect.setRect(x, sliderstart + sliderlen, extent,
02665                              slidermax - sliderstart - sliderlen + extent + 1);
02666                 break;
02667 
02668             case SC_ScrollBarSubPage:
02669                 if (horizontal) {
02670                     rect.setRect(x + extent, y,
02671                                  sliderstart - (x + extent), extent);
02672                 } else {
02673                     rect.setRect(x, y + extent, extent,
02674                                  sliderstart - (x + extent));
02675                 }
02676                 break;
02677 
02678             case SC_ScrollBarSlider:
02679                 if (horizontal) {
02680                     rect.setRect(sliderstart - 1, y, sliderlen + 2 + 1, extent);
02681                 } else {
02682                     rect.setRect(x, sliderstart - 1, extent, sliderlen + 2 + 1);
02683                 }
02684                 break;
02685 
02686             case SC_ScrollBarGroove:
02687                 if (horizontal) {
02688                     rect = ctlrect.adjusted(extent, 0, -(extent*2), 0);
02689                 } else {
02690                     rect = ctlrect.adjusted(0, extent, 0, -(extent*2));
02691                 }
02692                 break;
02693 
02694             default:
02695                 break;
02696           }
02697           rect = visualRect(sb->direction, ctlrect, rect);
02698           break;
02699       }
02700 
02701       case CC_TitleBar: {
02702           const QStyleOptionTitleBar *title;
02703           title = qstyleoption_cast<const QStyleOptionTitleBar*>(option);
02704           if (!title) break;
02705 
02706           const int wfw = 3; // window frame width
02707           const int button = h - 2*wfw;
02708           const int delta = button + fw;
02709           int offset = 0;
02710 
02711           bool minimized = title->titleBarState & Qt::WindowMinimized;
02712           bool maximized = title->titleBarState & Qt::WindowMaximized;
02713 
02714           switch (subcontrol) {
02715             case SC_TitleBarLabel:
02716                 rect = ctlrect;
02717                 if (title->titleBarFlags
02718                     & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
02719                     if (title->titleBarFlags & Qt::WindowSystemMenuHint)
02720                         rect.adjust(delta, 0, 0, 0);
02721                     if (title->titleBarFlags & Qt::WindowMinimizeButtonHint)
02722                         rect.adjust(0, 0, -delta, 0);
02723                     if (title->titleBarFlags & Qt::WindowMaximizeButtonHint)
02724                         rect.adjust(0, 0, -delta, 0);
02725                     if (title->titleBarFlags & Qt::WindowContextHelpButtonHint)
02726                       rect.adjust(0, 0, -delta, 0);
02727                     rect.adjust(wfw, wfw, -wfw, -wfw);
02728                 }
02729                 break;
02730 
02731             // right side buttons all fall through
02732             case SC_TitleBarContextHelpButton:
02733                 if (title->titleBarFlags & Qt::WindowContextHelpButtonHint)
02734                     offset += delta;
02735 
02736             case SC_TitleBarMinButton:
02737                 if (!minimized &&
02738                     (title->titleBarFlags & Qt::WindowMinimizeButtonHint))
02739                     offset += delta;
02740                 else if (subcontrol == SC_TitleBarMinButton)
02741                     break;
02742 
02743             case SC_TitleBarNormalButton:
02744                 if (minimized &&
02745                     (title->titleBarFlags & Qt::WindowMinimizeButtonHint))
02746                     offset += delta;
02747                 else if (maximized  &&
02748                          (title->titleBarFlags & Qt::WindowMaximizeButtonHint))
02749                     offset += delta;
02750                 else if (subcontrol == SC_TitleBarNormalButton)
02751                     break;
02752 
02753             case SC_TitleBarMaxButton:
02754                 if (!maximized &&
02755                     (title->titleBarFlags & Qt::WindowMaximizeButtonHint))
02756                     offset += delta;
02757                 else if (subcontrol == SC_TitleBarMaxButton)
02758                     break;
02759 
02760             case SC_TitleBarCloseButton:
02761                 if (title->titleBarFlags & Qt::WindowSystemMenuHint)
02762                     offset += delta;
02763                 else if (subcontrol == SC_TitleBarCloseButton)
02764                     break;
02765                 rect.setRect(x2 - offset, y + wfw, button, button);
02766                 break;
02767 
02768             // left side buttons
02769             case SC_TitleBarSysMenu:
02770                 if (title->titleBarFlags & Qt::WindowSystemMenuHint) {
02771                     rect.setRect(x + wfw, y + wfw, button, button);
02772                 }
02773                 break;
02774 
02775             default:
02776                 break;
02777           }
02778 
02779           rect = visualRect(title->direction, ctlrect, rect);
02780           break;
02781         }
02782 
02783       default:
02784           rect = QWindowsStyle::subControlRect(control, option,
02785                                               subcontrol, widget);
02786     }
02787 
02788     return rect;
02789 }
02790 
02791 
02793 // hitTestComplexControl()
02794 // -----------------------
02795 // Return subcontrol of position
02796 
02797 QStyle::SubControl PhaseStyle::hitTestComplexControl(ComplexControl control,
02798                                              const QStyleOptionComplex *option,
02799                                              const QPoint &position,
02800                                              const QWidget *widget) const
02801 {
02802     SubControl subcontrol = SC_None;
02803     QRect rect;
02804 
02805     switch (control) {
02806       case CC_ScrollBar: {
02807           const QStyleOptionSlider *sb;
02808           sb = qstyleoption_cast<const QStyleOptionSlider *>(option);
02809           if (!sb) break;
02810 
02811           // these cases are order dependent
02812           rect = subControlRect(control, sb, SC_ScrollBarSlider, widget);
02813           if (rect.contains(position)) {
02814               subcontrol = SC_ScrollBarSlider;
02815               break;
02816           }
02817 
02818           rect = subControlRect(control, sb, SC_ScrollBarAddPage, widget);
02819           if (rect.contains(position)) {
02820               subcontrol = SC_ScrollBarAddPage;
02821               break;
02822           }
02823 
02824           rect = subControlRect(control, sb, SC_ScrollBarSubPage, widget);
02825           if (rect.contains(position)) {
02826               subcontrol = SC_ScrollBarSubPage;
02827               break;
02828           }
02829 
02830           rect = subControlRect(control, sb, SC_ScrollBarAddLine, widget);
02831           if (rect.contains(position)) {
02832               subcontrol = SC_ScrollBarAddLine;
02833               break;
02834           }
02835 
02836           rect = subControlRect(control, sb, SC_ScrollBarSubLine, widget);
02837           if (rect.contains(position)) {
02838               subcontrol = SC_ScrollBarSubLine;
02839               break;
02840           }
02841 
02842           break;
02843       }
02844 
02845       default:
02846           subcontrol = QWindowsStyle::hitTestComplexControl(control, option,
02847                                                            position, widget);
02848           break;
02849     }
02850 
02851     return subcontrol;
02852 }
02853 
02855 // sizeFromContents()
02856 // ------------------
02857 // Return size of the element based on content
02858 
02859 QSize PhaseStyle::sizeFromContents(ContentsType contentstype,
02860                                    const QStyleOption *option,
02861                                    const QSize &contentssize,
02862                                    const QWidget *widget) const
02863 {
02864     switch (contentstype) {
02865       case CT_PushButton: {
02866           const QStyleOptionButton *button;
02867           button = qstyleoption_cast<const QStyleOptionButton *>(option);
02868           QSize size = contentssize;
02869           if (button) {
02870               int bm = pixelMetric(PM_ButtonMargin, button, widget);
02871               int fw = pixelMetric(PM_DefaultFrameWidth, button, widget) * 2;
02872               size.rwidth() += bm + fw;
02873               size.rheight() += bm + fw;
02874 
02875               if (button->text.isEmpty()) {
02876                   size = size.expandedTo(QSize(23, 23));
02877               } else {
02878                   size = size.expandedTo(QSize(75, 23));
02879               }
02880 
02881               if (button->features & QStyleOptionButton::AutoDefaultButton) {
02882                   int dbi = pixelMetric(PM_ButtonDefaultIndicator,
02883                                         button,
02884                                         widget);
02885                   size.rwidth() += dbi*2;
02886                   // Note: don't expand height
02887              }
02888 
02889           }
02890           return size;
02891       }
02892 
02893       default:
02894           return QWindowsStyle::sizeFromContents(contentstype,
02895                                                  option,
02896                                                  contentssize,
02897                                                  widget);
02898     }
02899 
02900     return QSize();
02901 }
02902 
02904 // Miscellaneous stuff                                                      //
02906 
02908 // styleHint()
02909 // -----------
02910 // "feel" hints for the GUI
02911 
02912 int PhaseStyle::styleHint(StyleHint hint,
02913                           const QStyleOption *option,
02914                           const QWidget *widget,
02915                           QStyleHintReturn *data) const
02916 {
02917     switch (hint) {
02918       case SH_Menu_SpaceActivatesItem:
02919       case SH_TitleBar_NoBorder:
02920       case SH_ToolTipLabel_Opacity:
02921         return 1;
02922 
02923       case SH_MainWindow_SpaceBelowMenuBar:
02924           return 0;
02925 
02926       case SH_UnderlineShortcut:
02927           if (QApplication::keyboardModifiers() & Qt::AltModifier) {
02928               return 1;
02929           }
02930           return 0;
02931 
02932     case SH_DialogButtonLayout:
02933         return QDialogButtonBox::KdeLayout;
02934 
02935 // TODO: investigate other hints, including:
02936 //    SH_ItemView_ShowDecorationSelected
02937 //    SH_ScrollBar_MiddleClickAbsolutePosition
02938 //    SH_ToolBox_SelectedPageTitleBold
02939 //    SH_ScrollView_FrameOnlyAroundContents
02940 
02941       default:
02942           return QWindowsStyle::styleHint(hint, option, widget, data);
02943     }
02944 }
02945 
02947 // eventFilter()
02948 // -------------
02949 // Handle events for animating progress bars
02950 
02951 bool PhaseStyle::eventFilter(QObject *object, QEvent *event)
02952 {
02953     if (!object->isWidgetType())
02954         return QObject::eventFilter(object, event);
02955 
02956     switch (event->type()) {
02957       case QEvent::KeyRelease:
02958       case QEvent::KeyPress:
02959           if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Alt) {
02960               // find top level window
02961               QWidget *widget = qobject_cast<QWidget*>(object);
02962               widget = widget->window();
02963               if (widget->parentWidget()) {
02964                   widget = widget->parentWidget()->window();
02965               }
02966 
02967               // update all visible enabled children widgets
02968               QList<QWidget*> wlist = qFindChildren<QWidget *>(widget);
02969               for (int n=0 ; n<wlist.size(); n++) {
02970                   if (wlist[n]->isEnabled() && wlist[n]->isVisible()) {
02971                       wlist[n]->update();
02972                   }
02973               }
02974           }
02975           break;
02976 
02977       case QEvent::StyleChange:
02978       case QEvent::Show:
02979           if (QProgressBar *bar = qobject_cast<QProgressBar*>(object)) {
02980             bars_ << bar;
02981             if (bars_.size() == 1) {
02982                 timerid_ = startTimer(25);
02983             }
02984           }
02985           break;
02986 
02987       case QEvent::Destroy:
02988           bars_.removeAll(reinterpret_cast<QProgressBar*>(object));
02989           break;
02990 
02991       case QEvent::Hide:
02992           if (QProgressBar *bar = qobject_cast<QProgressBar*>(object)) {
02993               bars_.removeAll(bar);
02994               if (bars_.isEmpty() && timerid_) {
02995                   killTimer(timerid_);
02996                   timerid_ = 0;
02997               }
02998           }
02999       default:
03000           break;
03001     }
03002 
03003     return QWindowsStyle::eventFilter(object, event);
03004 }
03005 
03007 // timerEvent()
03008 // ------------
03009 // Internal timer fired
03010 
03011 void PhaseStyle::timerEvent(QTimerEvent *event)
03012 {
03013     if (event->timerId() == timerid_) {
03014         foreach (QProgressBar *bar, bars_) {
03015             if ((bar->minimum() == 0 && bar->maximum() == 0)) {
03016                 bar->setValue(bar->value()+1);
03017                 bar->update();
03018             }
03019         }
03020     }
03021     event->ignore();
03022 }
03023 
03025 // Plugin stuff                                                            //
03027 
03028 class PhaseStylePlugin : public QStylePlugin
03029 {
03030 public:
03031     PhaseStylePlugin() { ; }
03032     QStringList keys() const {
03033         return QStringList() << "Phase";
03034     }
03035     QStyle *create(const QString &key) {
03036         if (key.toLower() == "phase") {
03037             return new PhaseStyle();
03038         }
03039         return 0;
03040     }
03041 };
03042 
03043 Q_EXPORT_PLUGIN(PhaseStylePlugin)